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 56 to Rev 57
- ↔ Reverse comparison
Rev 56 → Rev 57
/cpu_test/main.c
55,10 → 55,6
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4) |
//** external memory base address */ |
#define EXT_MEM_BASE (0xF0000000) |
//** exclusive access to this address will always succeed */ |
#define ATOMIC_SUCCESS_ADDR (EXT_MEM_BASE + 0) |
//** exclusive access to this address will always fail */ |
#define ATOMIC_FAILURE_ADDR (EXT_MEM_BASE + 4) |
/**@}*/ |
|
|
78,7 → 74,10
/// Global numbe rof available HPMs |
uint32_t num_hpm_cnts_global = 0; |
|
/// Variable to test atomic accessess |
uint32_t atomic_access_addr; |
|
|
/**********************************************************************//** |
* High-level CPU/processor test program. |
* |
837,12 → 836,20
if (neorv32_mtime_available()) { |
cnt_test++; |
|
// force MTIME IRQ |
neorv32_mtime_set_timecmp(0); |
// configure MTIME IRQ (and check overflow form low owrd to high word) |
neorv32_mtime_set_timecmp(-1); |
neorv32_mtime_set_time(0); |
|
// wait some time for the IRQ to arrive the CPU |
neorv32_cpu_csr_write(CSR_MIP, 0); // clear all pending IRQs |
|
neorv32_mtime_set_timecmp(0x0000000100000000ULL); |
neorv32_mtime_set_time( 0x00000000FFFFFFFEULL); |
|
// wait some time for the IRQ to trigger and arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
asm volatile("nop"); |
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MTI) { |
test_ok(); |
1458,7 → 1465,7
|
|
// ------ EXECUTE: should fail ------ |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] execute: ", cnt_test); |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] execute: ", cnt_test); |
cnt_test++; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
1483,7 → 1490,7
|
|
// ------ LOAD: should work ------ |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] read: ", cnt_test); |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] read: ", cnt_test); |
cnt_test++; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
1508,7 → 1515,7
|
|
// ------ STORE: should fail ------ |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] write: ", cnt_test); |
neorv32_uart_printf("[%i] PMP: U-mode [!X,!W,R] write: ", cnt_test); |
cnt_test++; |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
|
1563,34 → 1570,33
// Test atomic LR/SC operation - should succeed |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Atomic access (LR+SC) test (succeeding access): ", cnt_test); |
neorv32_uart_printf("[%i] Atomic access (LR+SC succeeding access): ", cnt_test); |
|
#ifdef __riscv_atomic |
if (is_simulation) { // check if this is a simulation |
// skip if A-mode is not implemented |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) { |
|
// skip if A-mode is not implemented |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) { |
cnt_test++; |
|
cnt_test++; |
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0x11223344); |
|
neorv32_cpu_store_unsigned_word(ATOMIC_SUCCESS_ADDR, 0x11223344); |
tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation |
asm volatile ("nop"); |
tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688); |
|
// atomic compare-and-swap |
if ((neorv32_cpu_atomic_cas((uint32_t)ATOMIC_SUCCESS_ADDR, 0x11223344, 0xAABBCCDD) == 0) && // status: success |
(neorv32_cpu_load_unsigned_word(ATOMIC_SUCCESS_ADDR) == 0xAABBCCDD) && // data written correctly |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception triggered |
test_ok(); |
} |
else { |
test_fail(); |
} |
// atomic access |
if ((tmp_b == 0) && // status: success |
(tmp_a == 0x11223344) && // correct data read |
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0x22446688) && // correct data write |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception triggered |
test_ok(); |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (on real HW)\n"); |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
#else |
neorv32_uart_printf("skipped (not implemented)\n"); |
1601,32 → 1607,67
// Test atomic LR/SC operation - should fail |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Atomic access (LR+SC) test (failing access): ", cnt_test); |
neorv32_uart_printf("[%i] Atomic access (LR+SC failing access 1): ", cnt_test); |
|
#ifdef __riscv_atomic |
if (is_simulation) { // check if this is a simulation |
// skip if A-mode is not implemented |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) { |
|
// skip if A-mode is not implemented |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) { |
cnt_test++; |
|
cnt_test++; |
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xAABBCCDD); |
|
neorv32_cpu_store_unsigned_word(ATOMIC_FAILURE_ADDR, 0x55667788); |
// atomic access |
tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation |
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0xDEADDEAD); // destroy reservation |
tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0x22446688); |
|
// atomic compare-and-swap |
if ((neorv32_cpu_atomic_cas((uint32_t)ATOMIC_FAILURE_ADDR, 0x55667788, 0xEEFFDDBB) != 0) && // staus: failed |
(neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) { // no exception triggered |
test_ok(); |
} |
else { |
test_fail(); |
} |
if ((tmp_b != 0) && // status: fail |
(tmp_a == 0xAABBCCDD) && // correct data read |
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0xDEADDEAD)) { // correct data write |
test_ok(); |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
#else |
neorv32_uart_printf("skipped (not implemented)\n"); |
#endif |
|
|
// ---------------------------------------------------------- |
// Test atomic LR/SC operation - should fail |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Atomic access (LR+SC failing access 2): ", cnt_test); |
|
#ifdef __riscv_atomic |
// skip if A-mode is not implemented |
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) { |
|
cnt_test++; |
|
neorv32_cpu_store_unsigned_word((uint32_t)&atomic_access_addr, 0x12341234); |
|
// atomic access |
tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&atomic_access_addr); // make reservation |
asm volatile ("ecall"); // destroy reservation via trap (simulate a context switch) |
tmp_b = neorv32_cpu_store_conditional((uint32_t)&atomic_access_addr, 0xDEADBEEF); |
|
if ((tmp_b != 0) && // status: fail |
(tmp_a == 0x12341234) && // correct data read |
(neorv32_cpu_load_unsigned_word((uint32_t)&atomic_access_addr) == 0x12341234)) { // correct data write |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (on real HW)\n"); |
} |
#else |
/hex_viewer/main.c
112,7 → 112,7
" 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" |
" atomic - perform atomic LR/SC access\n" |
" dump - dumpe several words from base address\n"); |
} |
|
208,7 → 208,7
void atomic_cas(void) { |
|
char terminal_buffer[16]; |
uint32_t mem_address, cas_expected, cas_desired; |
uint32_t mem_address, rdata, wdata, status; |
|
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_A_EXT)) != 0) { |
|
217,22 → 217,22
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_printf("\nEnter 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)); |
wdata = (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) == 0) { |
neorv32_uart_printf("\nAtomic-CAS: Successful!\n"); |
rdata = neorv32_cpu_load_reservate_word(mem_address); // make reservation |
status = neorv32_cpu_store_conditional(mem_address, wdata); |
|
// status |
neorv32_uart_printf("\nOld data: 0x%x\n", rdata); |
if (status == 0) { |
neorv32_uart_printf("Atomic access successful!\n"); |
neorv32_uart_printf("New data: 0x%x\n", neorv32_cpu_load_unsigned_word(mem_address)); |
} |
else { |
neorv32_uart_printf("\nAtomic-CAS: Failed!\n"); |
neorv32_uart_printf("Atomic access failed!\n"); |
} |
} |
else { |