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 45 to Rev 47
- ↔ Reverse comparison
Rev 45 → Rev 47
/bit_manipulation/main.c
1,5 → 1,5
// ################################################################################################# |
// # << NEORV32 - Bit manipulation 'B.Zbb' test program >> # |
// # << NEORV32 - RISC-V Bit Manipulation 'B.Zbb' Extension Test Program >> # |
// # ********************************************************************************************* # |
// # BSD 3-Clause License # |
// # # |
55,7 → 55,7
|
// Prototypes |
uint32_t xorshift32(void); |
uint32_t check_result(uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res); |
uint32_t check_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res); |
void print_report(int num_err, int num_tests); |
|
|
69,8 → 69,8
int main() { |
|
uint32_t opa = 0, opb = 0, res_hw = 0, res_sw = 0; |
int i = 0, err_cnt = 0; |
const int num_tests = (int)NUM_TEST_CASES; |
uint32_t i = 0, err_cnt = 0; |
const uint32_t num_tests = (int)NUM_TEST_CASES; |
|
// capture all exceptions and give debug info via UART |
neorv32_rte_setup(); |
94,7 → 94,7
opa = xorshift32(); |
res_sw = riscv_emulate_clz(opa); |
res_hw = riscv_intrinsic_clz(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
105,7 → 105,7
opa = xorshift32(); |
res_sw = riscv_emulate_ctz(opa); |
res_hw = riscv_intrinsic_ctz(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
116,7 → 116,7
opa = xorshift32(); |
res_sw = riscv_emulate_cpop(opa); |
res_hw = riscv_intrinsic_cpop(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
127,7 → 127,7
opa = xorshift32(); |
res_sw = riscv_emulate_sextb(opa); |
res_hw = riscv_intrinsic_sextb(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
138,7 → 138,7
opa = xorshift32(); |
res_sw = riscv_emulate_sexth(opa); |
res_hw = riscv_intrinsic_sexth(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
150,7 → 150,7
opb = xorshift32(); |
res_sw = riscv_emulate_min(opa, opb); |
res_hw = riscv_intrinsic_min(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
162,7 → 162,7
opb = xorshift32(); |
res_sw = riscv_emulate_minu(opa, opb); |
res_hw = riscv_intrinsic_minu(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
174,7 → 174,7
opb = xorshift32(); |
res_sw = riscv_emulate_max(opa, opb); |
res_hw = riscv_intrinsic_max(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
186,7 → 186,7
opb = xorshift32(); |
res_sw = riscv_emulate_maxu(opa, opb); |
res_hw = riscv_intrinsic_maxu(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
198,7 → 198,7
opb = xorshift32(); |
res_sw = riscv_emulate_pack(opa, opb); |
res_hw = riscv_intrinsic_pack(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
210,7 → 210,7
opb = xorshift32(); |
res_sw = riscv_emulate_andn(opa, opb); |
res_hw = riscv_intrinsic_andn(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
222,7 → 222,7
opb = xorshift32(); |
res_sw = riscv_emulate_orn(opa, opb); |
res_hw = riscv_intrinsic_orn(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
234,7 → 234,7
opb = xorshift32(); |
res_sw = riscv_emulate_xnor(opa, opb); |
res_hw = riscv_intrinsic_xnor(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
246,7 → 246,7
opb = xorshift32(); |
res_sw = riscv_emulate_rol(opa, opb); |
res_hw = riscv_intrinsic_rol(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
258,7 → 258,7
opb = xorshift32(); |
res_sw = riscv_emulate_ror(opa, opb); |
res_hw = riscv_intrinsic_ror(opa, opb); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
269,7 → 269,7
opa = xorshift32(); |
res_sw = riscv_emulate_ror(opa, 20); |
res_hw = riscv_intrinsic_rori20(opa); |
err_cnt += check_result(opa, opb, res_sw, res_hw); |
err_cnt += check_result(i, opa, opb, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
280,7 → 280,7
opa = xorshift32(); |
res_sw = riscv_emulate_orcb(opa); |
res_hw = riscv_intrinsic_orcb(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
291,7 → 291,7
opa = xorshift32(); |
res_sw = riscv_emulate_rev8(opa); |
res_hw = riscv_intrinsic_rev8(opa); |
err_cnt += check_result(opa, 0, res_sw, res_hw); |
err_cnt += check_result(i, opa, 0, res_sw, res_hw); |
} |
print_report(err_cnt, num_tests); |
|
322,6 → 322,7
/**********************************************************************//** |
* Check results (reference (SW) vs actual hardware). |
* |
* @param[in] num Test case number |
* @param[in] opa Operand 1 |
* @param[in] opb Operand 2 |
* @param[in] ref Software reference |
328,10 → 329,10
* @param[in] res Actual results |
* @return zero if results are equal. |
**************************************************************************/ |
uint32_t check_result(uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res) { |
uint32_t check_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res) { |
|
if (ref != res) { |
neorv32_uart_printf("opa = 0x%x, opb = 0x%x : ref = 0x%x vs res = 0x%x ", opa, opb, ref, res); |
neorv32_uart_printf("%u: opa = 0x%x, opb = 0x%x : ref = 0x%x vs res = 0x%x ", num, opa, opb, ref, res); |
neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27); |
return 1; |
} |
/cpu_test/main.c
36,7 → 36,7
/**********************************************************************//** |
* @file cpu_test/main.c |
* @author Stephan Nolting |
* @brief Simple CPU test program. |
* @brief CPU/Processor test program. |
**************************************************************************/ |
|
#include <neorv32.h> |
51,8 → 51,8
#define BAUD_RATE 19200 |
//** Reachable unaligned address */ |
#define ADDR_UNALIGNED 0x00000002 |
//** Unreachable aligned address */ |
#define ADDR_UNREACHABLE 0xFFFFFF00 |
//** Unreachable word-aligned address */ |
#define ADDR_UNREACHABLE (IO_BASE_ADDRESS-4) |
//* external memory base address */ |
#define EXT_MEM_BASE 0xF0000000 |
/**@}*/ |
59,8 → 59,7
|
|
// Prototypes |
void sim_trigger_msi(void); |
void sim_trigger_mei(void); |
void sim_irq_trigger(uint32_t sel); |
void global_trap_handler(void); |
void test_ok(void); |
void test_fail(void); |
96,24 → 95,6
|
|
/**********************************************************************//** |
* 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. |
* |
140,7 → 121,7
return 0; |
#endif |
|
neorv32_uart_printf("\n<< PROCESSOR/CPU TEST >>\n"); |
neorv32_uart_printf("\n<< CPU/PROCESSOR TEST >>\n"); |
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n"); |
|
// check if we came from hardware reset |
149,7 → 130,7
neorv32_uart_printf("yes\n"); |
} |
else { |
neorv32_uart_printf("unknown (mcause != TRAP_CODE_RESET)\n"); |
neorv32_uart_printf("unknown\n"); |
} |
|
// check available hardware extensions and compare with compiler flags |
208,20 → 189,28
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); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_3, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_4, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_5, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_6, global_trap_handler); |
install_err += neorv32_rte_exception_install(RTE_TRAP_FIRQ_7, global_trap_handler); |
|
if (install_err) { |
neorv32_uart_printf("RTE error (%i)!\n", install_err); |
neorv32_uart_printf("RTE install error (%i)!\n", install_err); |
return 0; |
} |
|
// enable interrupt sources |
install_err = neorv32_cpu_irq_enable(CSR_MIE_MSIE); // activate software interrupt |
install_err += neorv32_cpu_irq_enable(CSR_MIE_MTIE); // activate timer interrupt |
install_err += neorv32_cpu_irq_enable(CSR_MIE_MEIE); // activate external interrupt |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E); // activate fast interrupt channel 0 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ1E); // activate fast interrupt channel 1 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E); // activate fast interrupt channel 2 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E); // activate fast interrupt channel 3 |
install_err = neorv32_cpu_irq_enable(CSR_MIE_MSIE); // machine software interrupt |
install_err += neorv32_cpu_irq_enable(CSR_MIE_MTIE); // machine timer interrupt |
install_err += neorv32_cpu_irq_enable(CSR_MIE_MEIE); // machine external interrupt |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ0E); // fast interrupt channel 0 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ1E); // fast interrupt channel 1 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ2E); // fast interrupt channel 2 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ3E); // fast interrupt channel 3 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ4E); // fast interrupt channel 4 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ5E); // fast interrupt channel 5 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ6E); // fast interrupt channel 6 |
install_err += neorv32_cpu_irq_enable(CSR_MIE_FIRQ7E); // fast interrupt channel 7 |
|
if (install_err) { |
neorv32_uart_printf("IRQ enable error (%i)!\n", install_err); |
472,7 → 461,7
|
|
// ---------------------------------------------------------- |
// Test FENCE.I instruction (clear & reload i-cache) |
// Test FENCE.I instruction (instruction buffer / i-cache clear & reload) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Testing FENCE.I operation: ", cnt_test); |
662,7 → 651,7
} |
} |
else { |
neorv32_uart_printf("skipped (not possible when C extension is enabled)\n"); |
neorv32_uart_printf("skipped (n.a. with C-ext)\n"); |
} |
|
|
738,7 → 727,7
} |
} |
else { |
neorv32_uart_printf("skipped (not possible when C-EXT disabled)\n"); |
neorv32_uart_printf("skipped (n.a. with C-ext)\n"); |
} |
|
|
874,7 → 863,7
|
} |
else { |
neorv32_uart_printf("skipped (not possible when U-EXT disabled)\n"); |
neorv32_uart_printf("skipped (n.a. without U-ext)\n"); |
} |
|
|
919,7 → 908,7
cnt_test++; |
|
// trigger IRQ |
sim_trigger_msi(); |
sim_irq_trigger(1 << CSR_MIE_MSIE); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
947,7 → 936,7
cnt_test++; |
|
// trigger IRQ |
sim_trigger_mei(); |
sim_irq_trigger(1 << CSR_MIE_MEIE); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
969,14 → 958,14
// Fast interrupt channel 0 (WDT) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ0 (fast IRQ0) interrupt test (via WDT): ", cnt_test); |
neorv32_uart_printf("[%i] FIRQ0 (fast interrupt 0) test (via WDT): ", cnt_test); |
|
if (neorv32_wdt_available()) { |
cnt_test++; |
|
// configure WDT |
neorv32_wdt_setup(CLK_PRSC_2, 0); // lowest clock prescaler, trigger IRQ on timeout |
neorv32_wdt_reset(); // reset watchdog |
neorv32_wdt_setup(CLK_PRSC_4096, 0, 1); // highest clock prescaler, trigger IRQ on timeout, lock access |
WDT_CT = 0; // try to deactivate WDT (should fail as access is loced) |
neorv32_wdt_force(); // force watchdog into action |
|
// wait some time for the IRQ to arrive the CPU |
1002,7 → 991,7
// Fast interrupt channel 1 (GPIO) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ1 (fast IRQ1) interrupt test (via GPIO): ", cnt_test); |
neorv32_uart_printf("[%i] FIRQ1 (fast interrupt 1) test (via GPIO): ", cnt_test); |
|
if (UART_CT & (1 << UART_CT_SIM_MODE)) { // check if this is a simulation |
if (neorv32_gpio_available()) { |
1048,7 → 1037,7
// Fast interrupt channel 2 (UART) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ2 (fast IRQ2) interrupt test (via UART): ", cnt_test); |
neorv32_uart_printf("[%i] FIRQ2 (fast interrupt 2) test (via UART): ", cnt_test); |
|
if (neorv32_uart_available()) { |
cnt_test++; |
1098,7 → 1087,7
// Fast interrupt channel 3 (SPI) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ3 (fast IRQ3) interrupt test (via SPI): ", cnt_test); |
neorv32_uart_printf("[%i] FIRQ3 (fast interrupt 3) test (via SPI): ", cnt_test); |
|
if (neorv32_spi_available()) { |
cnt_test++; |
1133,7 → 1122,7
// Fast interrupt channel 3 (TWI) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ3 (fast IRQ3) interrupt test (via TWI): ", cnt_test); |
neorv32_uart_printf("[%i] FIRQ3 (fast interrupt 3) test (via TWI): ", cnt_test); |
|
if (neorv32_twi_available()) { |
cnt_test++; |
1166,6 → 1155,42
|
|
// ---------------------------------------------------------- |
// Fast interrupt channel 4..7 (SoC fast IRQ) |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] FIRQ4..7 (SoC fast interrupt 0..3, via testbench) test: ", cnt_test); |
|
cnt_test++; |
|
// trigger all SoC Fast interrupts at once |
neorv32_cpu_dint(); // do not fire yet! |
sim_irq_trigger((1 << CSR_MIE_FIRQ4E) | (1 << CSR_MIE_FIRQ5E) | (1 << CSR_MIE_FIRQ6E) | (1 << CSR_MIE_FIRQ7E)); |
|
// wait some time for the IRQ to arrive the CPU |
asm volatile("nop"); |
asm volatile("nop"); |
|
// make sure all SoC FIRQs have been triggered |
tmp_a = (1 << CSR_MIP_FIRQ4P) | (1 << CSR_MIP_FIRQ5P) | (1 << CSR_MIP_FIRQ6P) | (1 << CSR_MIP_FIRQ7P); |
if (neorv32_cpu_csr_read(CSR_MIP) == tmp_a) { |
neorv32_cpu_eint(); // allow IRQs to fire again |
asm volatile ("nop"); |
asm volatile ("nop"); // irq should kick in HERE |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_FIRQ_7) { // make sure FIRQ7 was last IRQ to be handled |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
test_fail(); |
} |
|
neorv32_cpu_eint(); // re-enable IRQs globally |
|
|
// ---------------------------------------------------------- |
// Test WFI ("sleep") instructions, wakeup via MTIME |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
1227,7 → 1252,7
|
} |
else { |
neorv32_uart_printf("skipped (not possible when U-EXT disabled)\n"); |
neorv32_uart_printf("skipped (n.a. without U-ext)\n"); |
} |
|
|
1480,56 → 1505,25
|
|
// ---------------------------------------------------------- |
// Test AMO atomic operation - should raise illegal instruction exception |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCAUSE, 0); |
neorv32_uart_printf("[%i] Atomic AMOSWAP test (should raise illegal CMD exception): ", 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++; |
|
// AMO operations are not implemented! |
// this should cause an illegal instruction exception |
asm volatile ("amoswap.w x0, x0, (x0)"); |
|
// atomic compare-and-swap |
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) { |
test_ok(); |
} |
else { |
test_fail(); |
} |
} |
else { |
neorv32_uart_printf("skipped (not implemented)\n"); |
} |
#else |
neorv32_uart_printf("skipped (not implemented)\n"); |
#endif |
|
|
// ---------------------------------------------------------- |
// HPM reports |
// ---------------------------------------------------------- |
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, -1); // stop all counters |
neorv32_uart_printf("\n\n-- HPM reports (%u HPMs available) --\n", num_hpm_cnts_global); |
neorv32_uart_printf("#IR - Total number of instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); // = HPM_0 |
neorv32_uart_printf("#CY - Total number of clock cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE)); // = HPM_2 |
neorv32_uart_printf("#03 - Retired compr. instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); |
neorv32_uart_printf("#04 - I-fetch wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); |
neorv32_uart_printf("#05 - I-issue wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); |
neorv32_uart_printf("#06 - Multi-cycle ALU wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); |
neorv32_uart_printf("#07 - Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); |
neorv32_uart_printf("#08 - Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); |
neorv32_uart_printf("#09 - Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); |
neorv32_uart_printf("#10 - Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); |
neorv32_uart_printf("#11 - Conditional branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); |
neorv32_uart_printf("#12 - Conditional branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); |
neorv32_uart_printf("#13 - Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); |
neorv32_uart_printf("#14 - Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); |
neorv32_uart_printf("#IR - Total number of instr.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_INSTRET)); // = HPM_0 |
//neorv32_uart_printf("#TM - Current system time: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_TIME)); // = HPM_1 |
neorv32_uart_printf("#CY - Total number of clk cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_CYCLE)); // = HPM_2 |
neorv32_uart_printf("#03 - Retired compr. instr.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); |
neorv32_uart_printf("#04 - I-fetch wait cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); |
neorv32_uart_printf("#05 - I-issue wait cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); |
neorv32_uart_printf("#06 - Multi-cyc. ALU wait cyc.: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); |
neorv32_uart_printf("#07 - Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); |
neorv32_uart_printf("#08 - Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); |
neorv32_uart_printf("#09 - Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); |
neorv32_uart_printf("#10 - Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); |
neorv32_uart_printf("#11 - Cond. branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); |
neorv32_uart_printf("#12 - Cond. branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); |
neorv32_uart_printf("#13 - Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); |
neorv32_uart_printf("#14 - Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); |
|
|
// ---------------------------------------------------------- |
1550,6 → 1544,17
|
|
/**********************************************************************//** |
* Simulation-based function to trigger CPU interrupts (MSI, MEI, FIRQ4..7). |
* |
* @param[in] sel IRQ select mask (bit positions according to #NEORV32_CSR_MIE_enum). |
**************************************************************************/ |
void sim_irq_trigger(uint32_t sel) { |
|
*(IO_REG32 (0xFF000000)) = sel; |
} |
|
|
/**********************************************************************//** |
* Trap handler for ALL exceptions/interrupts. |
**************************************************************************/ |
void global_trap_handler(void) { |
/demo_trng/main.c
36,7 → 36,7
/**********************************************************************//** |
* @file demo_trng/main.c |
* @author Stephan Nolting |
* @brief TRNG demo program. |
* @brief True random number generator demo program. |
**************************************************************************/ |
|
#include <neorv32.h> |
51,9 → 51,13
/**@}*/ |
|
|
// prototypes |
void print_random_data(void); |
void generate_histogram(void); |
|
|
/**********************************************************************//** |
* This program generates a simple dimming sequence for PWM channel 0,1,2. |
* Simple true random number test/demo program. |
* |
* @note This program requires the UART and the TRNG to be synthesized. |
* |
61,14 → 65,6
**************************************************************************/ |
int main(void) { |
|
uint8_t lucky_numbers_5of50[5]; |
uint8_t lucky_numbers_2of10[2]; |
|
int err; |
uint8_t i, j, probe; |
uint8_t trng_data; |
unsigned int num_samples; |
|
// check if UART unit is implemented at all |
if (neorv32_uart_available() == 0) { |
return 0; |
102,7 → 98,7
// main menu |
neorv32_uart_printf("\nCommands:\n" |
" n: Print 8-bit random numbers (abort by pressing any key)\n" |
" l: Print your lucky numbers\n"); |
" h: Generate and print histogram\n"); |
|
neorv32_uart_printf("CMD:> "); |
char cmd = neorv32_uart_getc(); |
109,104 → 105,101
neorv32_uart_putc(cmd); // echo |
neorv32_uart_printf("\n"); |
|
// output RND data |
if (cmd == 'n') { |
num_samples = 0; |
while(1) { |
err = neorv32_trng_get(&trng_data); |
if (err) { |
neorv32_uart_printf("\nTRNG error (%i)!\n", err); |
break; |
} |
neorv32_uart_printf("%u ", (uint32_t)(trng_data)); |
num_samples++; |
if (neorv32_uart_char_received()) { // abort when key pressed |
neorv32_uart_printf("\nPrinted samples: %u", num_samples); |
break; |
} |
} |
print_random_data(); |
} |
else if (cmd == 'h') { |
generate_histogram(); |
} |
else { |
neorv32_uart_printf("Invalid command.\n"); |
} |
} |
|
// print lucky numbers |
if (cmd == 'l') { |
// reset arrays |
for (i=0; i<5; i++) { |
lucky_numbers_5of50[i] = 0; |
} |
lucky_numbers_2of10[0] = 0; |
lucky_numbers_2of10[1] = 0; |
return 0; |
} |
|
// get numbers |
i = 0; |
while (i<5) { |
err = neorv32_trng_get(&trng_data); |
if (err) { |
neorv32_uart_printf("\nTRNG error (%i)!\n", err); |
break; |
} |
// valid range? |
if ((trng_data == 0) || (trng_data > 50)) { |
continue; |
} |
// already sampled? |
probe = 0; |
for (j=0; j<5; j++) { |
if (lucky_numbers_5of50[j] == trng_data) { |
probe++; |
} |
} |
if (probe) { |
continue; |
} |
else { |
lucky_numbers_5of50[i] = trng_data; |
i++; |
} |
} |
|
// get numbers part 2 |
i = 0; |
while (i<2) { |
err = neorv32_trng_get(&trng_data); |
if (err) { |
neorv32_uart_printf("\nTRNG error (%i)!\n", err); |
break; |
} |
// valid range? |
if ((trng_data == 0) || (trng_data > 10)) { |
continue; |
} |
// already sampled? |
probe = 0; |
for (j=0; j<2; j++) { |
if (lucky_numbers_2of10[j] == trng_data) { |
probe++; |
} |
} |
if (probe) { |
continue; |
} |
else { |
lucky_numbers_2of10[i] = trng_data; |
i++; |
} |
} |
/**********************************************************************//** |
* Print random numbers until a key is pressed. |
**************************************************************************/ |
void print_random_data(void) { |
|
// output |
neorv32_uart_printf("\n"); |
for (j=0; j<5; j++) { |
if (i==4) { |
neorv32_uart_printf("%u", (uint32_t)lucky_numbers_5of50[j]); |
} |
else { |
neorv32_uart_printf("%u, ", (uint32_t)lucky_numbers_5of50[j]); |
} |
} |
neorv32_uart_printf("\nLucky numbers: %u, %u\n", (uint32_t)lucky_numbers_2of10[0], (uint32_t)lucky_numbers_2of10[1]); |
|
uint32_t num_samples = 0; |
int err = 0; |
uint8_t trng_data; |
|
while(1) { |
err = neorv32_trng_get(&trng_data); |
if (err) { |
neorv32_uart_printf("\nTRNG error!\n"); |
break; |
} |
neorv32_uart_printf("%u ", (uint32_t)(trng_data)); |
num_samples++; |
if (neorv32_uart_char_received()) { // abort when key pressed |
break; |
} |
} |
neorv32_uart_printf("\nPrinted samples: %u\n", num_samples); |
} |
|
return 0; |
|
/**********************************************************************//** |
* Generate and print histogram. Samples random data until a key is pressed. |
**************************************************************************/ |
void generate_histogram(void) { |
|
uint32_t hist[256]; |
uint32_t i; |
uint32_t cnt = 0; |
int err = 0; |
uint8_t trng_data; |
|
neorv32_uart_printf("Press any key to start.\n"); |
|
while(neorv32_uart_char_received() == 0); |
neorv32_uart_printf("Sampling... Press any key to stop.\n"); |
|
// clear histogram |
for (i=0; i<256; i++) { |
hist[i] = 0; |
} |
|
// sample random data |
while(1) { |
|
err = neorv32_trng_get(&trng_data); |
hist[trng_data & 0xff]++; |
cnt++; |
|
if (err) { |
neorv32_uart_printf("\nTRNG error!\n"); |
break; |
} |
|
if (neorv32_uart_char_received()) { // abort when key pressed |
break; |
} |
|
if (cnt & 0x80000000UL) { // to prevent overflow |
break; |
} |
} |
|
// print histogram |
neorv32_uart_printf("Histogram [random data value] : [# occurences]\n"); |
for (i=0; i<256; i++) { |
neorv32_uart_printf("%u: %u\n", (uint32_t)i, hist[i]); |
} |
|
neorv32_uart_printf("\nSamples: %u\n", cnt); |
|
// average |
uint64_t average = 0; |
for (i=0; i<256; i++) { |
average += (uint64_t)hist[i] * i; |
} |
average = average / ((uint64_t)cnt); |
neorv32_uart_printf("Average value: %u\n", (uint32_t)average); |
} |
|
/demo_wdt/main.c
75,7 → 75,6
// this is not required, but keeps us safe |
neorv32_rte_setup(); |
|
|
// init UART at default baud rate, no parity bits, no rx interrupt, no tx interrupt |
neorv32_uart_setup(BAUD_RATE, 0b00, 0, 0); |
|
90,25 → 89,23
neorv32_uart_print("Cause of last processor reset: "); |
uint8_t wdt_cause = neorv32_wdt_get_cause(); |
|
if (wdt_cause == 1) { |
if (wdt_cause == 0) { |
neorv32_uart_print("External reset\n"); |
} |
else if (wdt_cause == 2) { |
neorv32_uart_print("Watchdog timeout\n"); |
else if (wdt_cause == 1) { |
neorv32_uart_print("Watchdog\n"); |
} |
else if (wdt_cause == 3) { |
neorv32_uart_print("Watchdog access fault\n"); |
} |
else { |
neorv32_uart_print("Undefined\n"); |
} |
|
|
// the watchod has a 20-bit counter, which trigger either an interrupt or a system reset |
// the watchod has a 20-bit counter, which triggers either an interrupt or a system reset |
// when overflowing |
|
// init watchdog (watchdog timer increment = cpu_clock/64, trigger reset on overflow) |
neorv32_wdt_setup(CLK_PRSC_64, 1); |
// init watchdog (watchdog timer increment = cpu_clock/64, trigger reset on overflow, lock |
// access so nobody can alter the configuration until next reset) |
neorv32_wdt_setup(CLK_PRSC_64, 1, 1); |
|
|
|