// ################################################################################################# // # << NEORV32 - RISC-V 'A' Extension - AMO Emulation Test Program >> # // # ********************************************************************************************* # // # BSD 3-Clause License # // # # // # Copyright (c) 2023, Stephan Nolting. All rights reserved. # // # # // # Redistribution and use in source and binary forms, with or without modification, are # // # permitted provided that the following conditions are met: # // # # // # 1. Redistributions of source code must retain the above copyright notice, this list of # // # conditions and the following disclaimer. # // # # // # 2. Redistributions in binary form must reproduce the above copyright notice, this list of # // # conditions and the following disclaimer in the documentation and/or other materials # // # provided with the distribution. # // # # // # 3. Neither the name of the copyright holder nor the names of its contributors may be used to # // # endorse or promote products derived from this software without specific prior written # // # permission. # // # # // # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS # // # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # // # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # // # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # // # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # // # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # // # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # // # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # // # OF THE POSSIBILITY OF SUCH DAMAGE. # // # ********************************************************************************************* # // # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting # // ################################################################################################# /**********************************************************************//** * @file atomic_test/main.c * @author Stephan Nolting * @brief Test program for the NEORV32 'A' ISA extension - check the emulation * of the AMO (read-modify-write) operations. **************************************************************************/ #include /**********************************************************************//** * @name User configuration **************************************************************************/ /**@{*/ /** UART BAUD rate */ #define BAUD_RATE (19200) //** Number of test cases for each instruction */ #define NUM_TEST_CASES (10000) //** Silent mode (only show actual errors when != 0) */ #define SILENT_MODE (1) // Prototypes uint32_t xorshift32(void); uint32_t check_result(uint32_t num, uint32_t amo_var_old, uint32_t amo_var_pre, uint32_t amo_var_new, uint32_t amo_var); void print_report(int num_err, int num_tests); // Global variable for atomic accesses volatile uint32_t amo_var; /**********************************************************************//** * MIN/MAX helpers. **************************************************************************/ /**@{*/ static inline int32_t MAX(int32_t a, int32_t b) { return((a) > (b) ? a : b); } static inline int32_t MIN(int32_t a, int32_t b) { return((a) < (b) ? a : b); } static inline int32_t MAXU(uint32_t a, uint32_t b) { return((a) > (b) ? a : b); } static inline int32_t MINU(uint32_t a, uint32_t b) { return((a) < (b) ? a : b); } /**@}*/ /**********************************************************************//** * Main function; test all provided AMO emulation functions. * * @note This program requires the RISC-V A CPU extension. * * @return Irrelevant. **************************************************************************/ int main() { const uint32_t num_tests = (uint32_t)NUM_TEST_CASES; // capture all exceptions and give debug info via UART neorv32_rte_setup(); // setup UART0 at default baud rate, no interrupts neorv32_uart0_setup(BAUD_RATE, 0); // intro neorv32_uart0_printf("<<< NEORV32 AMO Operations (atomic read-modify-write) Emulation Test >>>\n\n"); // check if A extension is implemented at all if ((neorv32_cpu_csr_read(CSR_MISA) & (1<> 17; x32 ^= x32 << 5; return x32; } /**********************************************************************//** * Check results (reference (SW) vs actual hardware). * * @param[in] num Test case number * @param[in] amo_var_old Initial value of atomic variable. * @param[in] amo_var_pre Value of atomic variable read from memory (before operation). * @param[in] amo_var_new Expected new value of atomic variable. * @param[in] amo_var Actual new value of atomic variable. * @return zero if results are correct. **************************************************************************/ uint32_t check_result(uint32_t num, uint32_t amo_var_old, uint32_t amo_var_pre, uint32_t amo_var_new, uint32_t amo_var) { #if (SILENT_MODE == 0) neorv32_uart0_printf("%u: MEM_INITIAL[addr] = 0x%x vs. MEM_PRE[addr] = 0x%x | MEM_NEW_ref[addr] = 0x%x vs. MEM_NEW[addr] = 0x%x, ", num, amo_var_old, amo_var_pre, amo_var_new, amo_var); #endif if ((amo_var_old != amo_var_pre) || (amo_var_new != amo_var)) { #if (SILENT_MODE != 0) neorv32_uart0_printf("%u: MEM_INITIAL[addr] = 0x%x vs. MEM_PRE[addr] = 0x%x | MEM_NEW_ref[addr] = 0x%x vs. MEM_NEW[addr] = 0x%x, ", num, amo_var_old, amo_var_pre, amo_var_new, amo_var); #endif neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27); return 1; } else { #if (SILENT_MODE == 0) neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27); #endif return 0; } } /**********************************************************************//** * Print test report. * * @param[in] num_err Number or errors in this test. * @param[in] num_tests Total number of conducted tests. **************************************************************************/ void print_report(int num_err, int num_tests) { neorv32_uart0_printf("Errors: %i/%i ", num_err, num_tests); if (num_err == 0) { neorv32_uart0_printf("%c[1m[ok]%c[0m\n", 27, 27); } else { neorv32_uart0_printf("%c[1m[FAILED]%c[0m\n", 27, 27); } }