URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/sw/example
- from Rev 39 to Rev 40
- ↔ Reverse comparison
Rev 39 → Rev 40
/cpu_test/main.c
59,6 → 59,8
|
|
// Prototypes |
void sim_trigger_msi(void); |
void sim_trigger_mei(void); |
void global_trap_handler(void); |
void test_ok(void); |
void test_fail(void); |
90,6 → 92,24
|
|
/**********************************************************************//** |
* Simulation-based function to trigger CPU MSI (machine software interrupt). |
**************************************************************************/ |
void sim_trigger_msi(void) { |
|
*(IO_REG32 (0xFF000000)) = 1; |
} |
|
|
/**********************************************************************//** |
* Simulation-based function to trigger CPU MEI (machine external interrupt). |
**************************************************************************/ |
void sim_trigger_mei(void) { |
|
*(IO_REG32 (0xFF000004)) = 1; |
} |
|
|
/**********************************************************************//** |
* This program uses mostly synthetic case to trigger all implemented exceptions. |
* Each exception is captured and evaluated for correct detection. |
* |
99,6 → 119,19
**************************************************************************/ |
int main() { |
|
register uint32_t tmp_a, tmp_b; |
int i; |
volatile uint32_t dummy_dst __attribute__((unused)); |
|
union { |
uint64_t uint64; |
uint32_t uint32[sizeof(uint64_t)/2]; |
} cpu_systime; |
|
|
// init UART at default baud rate, no rx interrupt, no tx interrupt |
neorv32_uart_setup(BAUD_RATE, 0, 0); |
|
// Disable cpu_test compilation by default |
#ifndef RUN_CPUTEST |
#warning cpu_test HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_CPUTEST clean_all exe<< to compile it. |
109,23 → 142,24
return 0; |
#endif |
|
neorv32_uart_printf("\n--- PROCESSOR/CPU TEST ---\n"); |
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n"); |
neorv32_uart_printf("This test suite is intended to verify the default NEORV32 processor setup using the default testbench.\n\n"); |
|
register uint32_t tmp_a, tmp_b, tmp_c; |
uint32_t i, j; |
volatile uint32_t dummy_dst __attribute__((unused)); |
// check if we came from hardware reset |
neorv32_uart_printf("Coming from hardware reset? "); |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_RESET) { |
neorv32_uart_printf("true\n"); |
} |
else { |
neorv32_uart_printf("unknown (mcause != TRAP_CODE_RESET)\n"); |
} |
|
union { |
uint64_t uint64; |
uint32_t uint32[sizeof(uint64_t)/2]; |
} cpu_systime; |
|
// reset performance counter |
neorv32_cpu_set_minstret(0); |
neorv32_cpu_set_mcycle(0); |
|
// init UART at default baud rate, no rx interrupt, no tx interrupt |
neorv32_uart_setup(BAUD_RATE, 0, 0); |
|
neorv32_mtime_set_time(0); |
// set CMP of machine system timer MTIME to max to prevent an IRQ |
uint64_t mtime_cmp_max = 0xFFFFFFFFFFFFFFFFUL; |
148,6 → 182,8
neorv32_rte_print_hw_config(); |
|
// configure RTE |
neorv32_uart_printf("\n\nInitializing NEORV32 run-time environment (RTE)... "); |
|
neorv32_rte_setup(); // this will install a full-detailed debug handler for all traps |
|
int install_err = 0; |
160,10 → 196,11
install_err += neorv32_rte_exception_install(RTE_TRAP_L_ACCESS, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_S_MISALIGNED, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_S_ACCESS, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_UENV_CALL, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_MENV_CALL, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_MTI, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_MSI, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_MTI, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_MEI, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_0, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_1, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_2, global_trap_handler); |
189,20 → 226,16
} |
|
// test intro |
neorv32_uart_printf("\n--- PROCESSOR/CPU TEST ---\n"); |
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n"); |
neorv32_uart_printf("This test suite is intended to verify the default NEORV32 processor setup using the default testbench.\n\n"); |
neorv32_uart_printf("Starting tests...\n\n"); |
neorv32_uart_printf("\nStarting tests...\n\n"); |
|
// enable global interrupts |
neorv32_cpu_eint(); |
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
|
// ---------------------------------------------------------- |
// List all accessible CSRs |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] List all accessible CSRs: ", cnt_test); |
|
if ((UART_CT & (1 << UART_CT_SIM_MODE)) == 0) { // check if this is a simulation |
257,24 → 290,26
|
|
// ---------------------------------------------------------- |
// CFU0 test (default HW) |
// Test standard RISC-V performance counter [m]cycle[h] |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Default CFU0 access test: ", cnt_test); |
neorv32_uart_printf("[%i] Testing [m]instret[h] counters: ", cnt_test); |
|
// cfu0 implemented? |
if (neorv32_cfu0_available()) { |
// check if counters are implemented |
if (neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_ZICNT)) { |
cnt_test++; |
|
// write test data |
CFU0_REG_0 = 0x01234567; |
CFU0_REG_1 = 0x76543210; |
CFU0_REG_2 = 0xABCDABCD; |
CFU0_REG_3 = 0xFFAAFFAA; |
// get current cycle counter |
volatile uint64_t cycle_csr_test = neorv32_cpu_get_cycle(); |
|
if ((CFU0_REG_0 == 0x01234567) && (CFU0_REG_1 == 0x76543210) && |
(CFU0_REG_2 == 0xABCDABCD) && (CFU0_REG_3 == 0xFFAAFFAA) && // correct read-back |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception |
// wait some time to have a nice increment |
asm volatile ("nop"); |
asm volatile ("nop"); |
asm volatile ("nop"); |
|
// make sure cycle counter has incremented and there was no exception during access |
if ((neorv32_cpu_get_cycle() > cycle_csr_test) && |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
} |
else { |
282,29 → 317,31
} |
} |
else { |
neorv32_uart_printf("skipped (CFU0 not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// CFU1 test (default HW) |
// Test standard RISC-V performance counter [m]instret[h] |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Default CFU1 access test: ", cnt_test); |
neorv32_uart_printf("[%i] Testing [m]cycle[h] counters: ", cnt_test); |
|
// cfu0 implemented? |
if (neorv32_cfu1_available()) { |
// check if counters are implemented |
if (neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_ZICNT)) { |
cnt_test++; |
|
// write test data |
CFU1_REG_0 = 0x22334455; |
CFU1_REG_1 = 0x44782931; |
CFU1_REG_2 = 0xDDAABBFF; |
CFU1_REG_3 = 0xA0B0D0C0; |
// get current instruction counter |
volatile uint64_t instret_csr_test = neorv32_cpu_get_instret(); |
|
if ((CFU1_REG_0 == 0x22334455) && (CFU1_REG_1 == 0x44782931) && |
(CFU1_REG_2 == 0xDDAABBFF) && (CFU1_REG_3 == 0xA0B0D0C0) && // correct read-back |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception |
// wait some time to have a nice increment |
asm volatile ("nop"); |
asm volatile ("nop"); |
asm volatile ("nop"); |
|
// make sure instruction counter has incremented and there was no exception during access |
if ((neorv32_cpu_get_instret() > instret_csr_test) && |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
} |
else { |
312,12 → 349,12
} |
} |
else { |
neorv32_uart_printf("skipped (CFU1 not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Bus timeout latency estimation |
// Bus timeout latency estimation (very unprecise!) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Estimating bus time-out latency: ", cnt_test); |
324,12 → 361,12
cnt_test++; |
|
// start timing |
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE); |
neorv32_cpu_csr_write(CSR_MCYCLE, 0); |
|
// this store access will timeout |
MMR_UNREACHABLE = 0; |
|
tmp_a = neorv32_cpu_csr_read(CSR_CYCLE) - tmp_a; |
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLE); |
|
// make sure there was a time-out |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) { |
381,7 → 418,7
} |
} |
else { |
neorv32_uart_printf("skipped (external memory interface not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
} |
else { |
506,6 → 543,94
|
|
// ---------------------------------------------------------- |
// Test pending interrupt |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Pending IRQ test (from MTIME): ", cnt_test); |
|
if (neorv32_mtime_available()) { |
cnt_test++; |
|
// disable global interrupts |
neorv32_cpu_dint(); |
|
// force MTIME IRQ |
neorv32_mtime_set_timecmp(0); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
// no more mtime interrupts |
neorv32_mtime_set_timecmp(-1); |
|
// re-enable global interrupts |
neorv32_cpu_eint(); |
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Test clearing pending interrupt (via mip CSR) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Clear pending IRQ (via mip CSR) test (from MTIME): ", cnt_test); |
|
if (neorv32_mtime_available()) { |
cnt_test++; |
|
// disable global interrupts |
neorv32_cpu_dint(); |
|
// force MTIME IRQ |
neorv32_mtime_set_timecmp(0); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
// no more mtime interrupts |
neorv32_mtime_set_timecmp(-1); |
|
|
if (neorv32_cpu_csr_read(CSR_MIP) & (1 << CPU_MIP_MTIP)) { // make sure MTIP is pending |
|
neorv32_cpu_csr_write(CSR_MIP, 0); // just clear all pending IRQs |
neorv32_cpu_eint(); // re-enable global interrupts |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) { |
test_ok(); |
} |
else { |
neorv32_uart_printf("IRQ triggered! "); |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("MTIP not pending! "); |
test_fail(); |
} |
|
// re-enable global interrupts |
neorv32_cpu_eint(); |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Unaligned instruction address |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
699,10 → 824,10
|
|
// ---------------------------------------------------------- |
// Environment call |
// Environment call from M-mode |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] ENVCALL (ecall instruction) exception test: ", cnt_test); |
neorv32_uart_printf("[%i] ENVCALL (ecall instruction) from M-mode exception test: ", cnt_test); |
cnt_test++; |
|
asm volatile("ECALL"); |
716,6 → 841,37
|
|
// ---------------------------------------------------------- |
// Environment call from U-mode |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] ENVCALL (ecall instruction) from U-mode exception test: ", cnt_test); |
|
// skip if U-mode is not implemented |
if (neorv32_cpu_csr_read(CSR_MISA) & (1<<CPU_MISA_U_EXT)) { |
|
cnt_test++; |
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to misa not allowed for user-level programs |
asm volatile("ECALL"); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_UENV_CALL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
|
} |
else { |
neorv32_uart_printf("skipped (not possible when U-EXT disabled)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Machine timer interrupt (MTIME) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
746,11 → 902,75
neorv32_mtime_set_timecmp(-1); |
} |
else { |
neorv32_uart_printf("skipped (WDT not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Machine software interrupt (MSI) via testbench |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] MSI (via testbench) interrupt test: ", cnt_test); |
|
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation |
cnt_test++; |
|
// trigger IRQ |
sim_trigger_msi(); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MSI) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (on real hardware)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Machine external interrupt (MEI) via testbench |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] MEI (via testbench) interrupt test: ", cnt_test); |
|
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation |
cnt_test++; |
|
// trigger IRQ |
sim_trigger_mei(); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MEI) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (on real hardware)\n"); |
} |
|
|
// ---------------------------------------------------------- |
// Fast interrupt channel 0 (WDT) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
783,7 → 1003,7
neorv32_wdt_disable(); |
} |
else { |
neorv32_uart_printf("skipped (WDT not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
829,7 → 1049,7
neorv32_gpio_port_set(0); |
} |
else { |
neorv32_uart_printf("skipped (GPIO not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
} |
else { |
887,7 → 1107,7
|
} |
else { |
neorv32_uart_printf("skipped (UART not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
926,7 → 1146,7
neorv32_spi_disable(); |
} |
else { |
neorv32_uart_printf("skipped (SPI not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
966,7 → 1186,7
neorv32_twi_disable(); |
} |
else { |
neorv32_uart_printf("skipped (TWI not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
996,7 → 1216,7
neorv32_mtime_set_timecmp(-1); |
} |
else { |
neorv32_uart_printf("skipped (MTIME not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
1014,12 → 1234,18
// switch to user mode (hart will be back in MACHINE mode when trap handler returns) |
neorv32_cpu_goto_user_mode(); |
{ |
// access to mstatus not allowed for user mode programs |
neorv32_cpu_csr_read(CSR_MSTATUS); |
// access to misa not allowed for user-level programs |
tmp_a = neorv32_cpu_csr_read(CSR_MISA); |
} |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
if (tmp_a == 0) { // make sure user-level code CANNOT read machine-level CSR content! |
test_ok(); |
} |
else { |
neorv32_uart_printf("SECURITY VIOLATION! "); |
test_fail(); |
} |
} |
else { |
test_fail(); |
1032,7 → 1258,7
|
|
// ---------------------------------------------------------- |
// Test RTE debug handler |
// Test RTE debug trap handler |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] RTE (runtime environment) debug trap handler test: ", cnt_test); |
1071,34 → 1297,16
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
cnt_test++; |
|
// check min granulartiy |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0); |
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff); |
tmp_a = neorv32_cpu_csr_read(0x3b0); |
// find out mininmal region size (granulartiy) |
tmp_b = neorv32_cpu_pmp_get_granularity(); |
|
// find least-significat set bit |
for (i=31; i!=0; i--) { |
if (((tmp_a >> i) & 1) == 0) { |
break; |
} |
} |
|
tmp_a = SYSINFO_DSPACE_BASE; // base address of protected region |
neorv32_uart_printf("Creating protected page (NAPOT, [!X,!W,R], %u bytes) @ 0x%x: ", tmp_b, tmp_a); |
|
tmp_b = 0; |
for (j=i; j!=0; j--) { |
tmp_b = tmp_b << 1; |
tmp_b = tmp_b | 1; |
} |
tmp_c = tmp_a & (~tmp_b); // clear LSBs in base address |
tmp_c = tmp_c | tmp_b; // set region size config |
// configure |
int pmp_return = neorv32_cpu_pmp_configure_region(0, tmp_a, tmp_b, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions |
|
neorv32_uart_printf("Creating protected page (NAPOT, [!X,!W,R], %u bytes) @ 0x%x (PMPADDR = 0x%x): ", (uint32_t)(1 << (i+1+2)), tmp_a, tmp_c); |
|
neorv32_cpu_csr_write(CSR_PMPADDR0, tmp_c); // 64k area @ 0xFFFFA000 |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0b00011001); // NAPOT, read permission, NO write and NO execute permissions |
|
if ((neorv32_cpu_csr_read(CSR_PMPADDR0) == tmp_c) && (neorv32_cpu_csr_read(CSR_PMPCFG0) == 0b00011001) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
if ((pmp_return == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { |
test_ok(); |
} |
else { |
1220,7 → 1428,7
|
} |
else { |
neorv32_uart_printf("not implemented\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
|
|
1249,7 → 1457,7
} |
} |
else { |
neorv32_uart_printf("skipped (A extension not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
} |
else { |
1281,7 → 1489,7
} |
} |
else { |
neorv32_uart_printf("skipped (A extension not implemented)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
} |
else { |
1289,7 → 1497,6
} |
|
|
|
// ---------------------------------------------------------- |
// Final test reports |
// ---------------------------------------------------------- |
/hex_viewer/main.c
55,6 → 55,7
// Prototypes |
void read_memory(void); |
void write_memory(void); |
void atomic_cas(void); |
void dump_memory(void); |
uint32_t hexstr_to_uint(char *buffer, uint8_t length); |
|
103,10 → 104,11
// decode input and execute command |
if (!strcmp(buffer, "help")) { |
neorv32_uart_printf("Available commands:\n" |
" help - show this text\n" |
" read - read single word from address\n" |
" write - write single word to address\n" |
" dump - dumpe several words from base address\n\n"); |
" help - show this text\n" |
" read - read single word from address\n" |
" write - write single word to address\n" |
" atomic - perform atomic compare-and-swap operation\n" |
" dump - dumpe several words from base address\n"); |
} |
|
else if (!strcmp(buffer, "read")) { |
113,6 → 115,10
read_memory(); |
} |
|
else if (!strcmp(buffer, "atomic")) { |
atomic_cas(); |
} |
|
else if (!strcmp(buffer, "write")) { |
write_memory(); |
} |
138,10 → 144,9
char terminal_buffer[16]; |
|
// enter address |
neorv32_uart_printf("Enter address (8 hex chars): "); |
neorv32_uart_printf("Enter address (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary |
|
// perform read access |
neorv32_uart_printf("\n[0x%x] = ", mem_address); |
169,13 → 174,12
char terminal_buffer[16]; |
|
// enter address |
neorv32_uart_printf("Enter address (8 hex chars): "); |
neorv32_uart_printf("Enter address (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary |
|
// enter data |
neorv32_uart_printf("\nEnter data (8 hex chars): "); |
neorv32_uart_printf("\nEnter data (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
197,6 → 201,45
|
|
/**********************************************************************//** |
* Perform atomic compare-and-swap operation |
**************************************************************************/ |
void atomic_cas(void) { |
|
char terminal_buffer[16]; |
uint32_t mem_address, cas_expected, cas_desired; |
|
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CPU_MISA_A_EXT)) != 0) { |
|
// enter memory address |
neorv32_uart_printf("Enter memory address (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
// enter expected value |
neorv32_uart_printf("\nEnter expected value @0x%x (8 hex chars): 0x", mem_address); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
cas_expected = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
// enter desired value |
neorv32_uart_printf("\nEnter desired (new) value @0x%x (8 hex chars): 0x", mem_address); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
cas_desired = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
|
// try to execute atomic compare-and-swap |
if (neorv32_cpu_atomic_cas(mem_address, cas_expected, cas_desired)) { |
neorv32_uart_printf("\nAtomic-CAS: Failed!\n"); |
} |
else { |
neorv32_uart_printf("\nAtomic-CAS: Successful!\n"); |
} |
} |
else { |
neorv32_uart_printf("Atomic operations not implemented/enabled!\n"); |
} |
} |
|
|
/**********************************************************************//** |
* Read several words from memory base address |
**************************************************************************/ |
void dump_memory(void) { |
204,10 → 247,9
char terminal_buffer[16]; |
|
// enter base address |
neorv32_uart_printf("Enter base address (8 hex chars): "); |
neorv32_uart_printf("Enter base address (8 hex chars): 0x"); |
neorv32_uart_scan(terminal_buffer, 8+1, 1); // 8 hex chars for address plus '\0' |
register uint32_t mem_address = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer)); |
mem_address = mem_address & 0xFFFFFFFCUL; // align to 32-bit boundary |
|
neorv32_uart_printf("\nPress key to start dumping. Press any key to abort.\n"); |
|