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/lib/source
- from Rev 55 to Rev 56
- ↔ Reverse comparison
Rev 55 → Rev 56
/neorv32_cpu.c
271,27 → 271,36
|
|
/**********************************************************************//** |
* Simple delay function using busy wait. |
* Simple delay function using busy wait (simple loop). |
* |
* @warning This function requires the cycle CSR(s). Hence, the Zicsr extension is mandatory. |
* @warning This function is not really precise (especially if there is no M extension available)! Use a timer-based approach (using cycle or time CSRs) for precise timings. |
* |
* @param[in] time_ms Time in ms to wait. |
* @param[in] time_ms Time in ms to wait (max 32767ms). |
**************************************************************************/ |
void neorv32_cpu_delay_ms(uint32_t time_ms) { |
void neorv32_cpu_delay_ms(int16_t time_ms) { |
|
uint64_t time_resume = neorv32_cpu_get_cycle(); |
const uint32_t loop_cycles_c = 16; // clock cycles per iteration of the ASM loop |
|
// check input |
if (time_ms < 0) { |
time_ms = -time_ms; |
} |
|
uint32_t clock = SYSINFO_CLK; // clock ticks per second |
clock = clock / 1000; // clock ticks per ms |
|
uint64_t wait_cycles = ((uint64_t)clock) * ((uint64_t)time_ms); |
time_resume += wait_cycles; |
uint32_t ticks = (uint32_t)(wait_cycles / loop_cycles_c); |
|
while(1) { |
if (neorv32_cpu_get_cycle() >= time_resume) { |
break; |
} |
} |
asm volatile (" .balign 4 \n" // make sure this is 32-bit aligned |
" __neorv32_cpu_delay_ms_start: \n" |
" beq %[cnt_r], zero, __neorv32_cpu_delay_ms_end \n" // 3 cycles (not taken) |
" beq %[cnt_r], zero, __neorv32_cpu_delay_ms_end \n" // 3 cycles (never taken) |
" addi %[cnt_w], %[cnt_r], -1 \n" // 2 cycles |
" nop \n" // 2 cycles |
" j __neorv32_cpu_delay_ms_start \n" // 6 cycles |
" __neorv32_cpu_delay_ms_end: " |
: [cnt_w] "=r" (ticks) : [cnt_r] "r" (ticks)); |
} |
|
|
304,10 → 313,10
|
// make sure to use NO registers in here! -> naked |
|
asm volatile ("csrw mepc, ra \n\t" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here |
"li ra, %[input_imm] \n\t" // bit mask to clear the two MPP bits |
"csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode |
"mret \n\t" // return and switch to user mode |
asm volatile ("csrw mepc, ra \n" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here |
"li ra, %[input_imm] \n" // bit mask to clear the two MPP bits |
"csrrc zero, mstatus, ra \n" // clear MPP bits -> MPP=u-mode |
"mret \n" // return and switch to user mode |
: : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L))); |
} |
|
621,6 → 630,11
**************************************************************************/ |
uint32_t neorv32_cpu_hpm_get_counters(void) { |
|
// inhibit all HPM counters |
uint32_t tmp = neorv32_cpu_csr_read(CSR_MCOUNTINHIBIT); |
tmp |= 0xfffffff8; |
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, tmp); |
|
// try setting all mhpmcounter* CSRs to 1 |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER4, 1); |
650,7 → 664,7
neorv32_cpu_csr_write(CSR_MHPMCOUNTER28, 1); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER29, 1); |
|
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0) |
// sum up all written ones (only available HPM counter CSRs will return =! 0) |
uint32_t num_hpm_cnts = 0; |
|
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3); |
686,6 → 700,42
|
|
/**********************************************************************//** |
* Hardware performance monitors (HPM): Get total counter width |
* |
* @warning This function overrides mhpmcounter3[h] CSRs. |
* |
* @return Size of HPM counter bits (1-64). |
**************************************************************************/ |
uint32_t neorv32_cpu_hpm_get_size(void) { |
|
// inhibt auto-update |
asm volatile ("csrwi %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTEREN_HPM3)); |
|
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 0xffffffff); |
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3H, 0xffffffff); |
|
uint32_t tmp, size, i; |
|
if (neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H) == 0) { |
size = 0; |
tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3); |
} |
else { |
size = 32; |
tmp = neorv32_cpu_csr_read(CSR_MHPMCOUNTER3H); |
} |
|
for (i=0; i<32; i++) { |
if (tmp & (1<<i)) { |
size++; |
} |
} |
|
return size; |
} |
|
|
/**********************************************************************//** |
* Check if certain Z* extension is available |
* |
* @param[in] flag Index of the Z-extension to check from #NEORV32_CSR_MZEXT_enum |
/neorv32_rte.c
282,7 → 282,6
|
// ID |
neorv32_uart_printf("Hart ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID)); |
|
neorv32_uart_printf("Vendor ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MVENDORID)); |
|
tmp = neorv32_cpu_csr_read(CSR_MARCHID); |
353,6 → 352,12
if (tmp & (1<<CSR_MZEXT_ZFINX)) { |
neorv32_uart_printf("Zfinx "); |
} |
if (tmp & (1<<CSR_MZEXT_ZXNOCNT)) { |
neorv32_uart_printf("Zxnocnt(!) "); |
} |
if (tmp & (1<<CSR_MZEXT_ZXSCNT)) { |
neorv32_uart_printf("Zxscnt(!) "); |
} |
|
// check physical memory protection |
neorv32_uart_printf("\nPMP: "); |
365,7 → 370,7
} |
|
// check hardware performance monitors |
neorv32_uart_printf("HPM Counters: %u\n", neorv32_cpu_hpm_get_counters()); |
neorv32_uart_printf("HPM Counters: %ux, %u-bit wide\n", neorv32_cpu_hpm_get_counters(), neorv32_cpu_hpm_get_size()); |
|
|
// Memory configuration |
372,17 → 377,27
neorv32_uart_printf("\n=== << Memory Configuration >> ===\n"); |
|
neorv32_uart_printf("Instr. base address: 0x%x\n", SYSINFO_ISPACE_BASE); |
|
// IMEM |
neorv32_uart_printf("Internal IMEM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)); |
neorv32_uart_printf("IMEM size: %u bytes\n", SYSINFO_IMEM_SIZE); |
neorv32_uart_printf("Internal IMEM as ROM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM)) { |
neorv32_uart_printf("yes, %u bytes", SYSINFO_IMEM_SIZE); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)) { |
neorv32_uart_printf(", read-only (ROM)"); |
} |
} |
else { |
neorv32_uart_printf("no"); |
} |
neorv32_uart_printf("\n"); |
|
// DMEM |
neorv32_uart_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE); |
neorv32_uart_printf("Internal DMEM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)); |
neorv32_uart_printf("DMEM size: %u bytes\n", SYSINFO_DMEM_SIZE); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_DMEM)) { neorv32_uart_printf("yes, %u bytes\n", SYSINFO_DMEM_SIZE); } |
else { neorv32_uart_printf("no\n"); } |
|
// i-cache |
neorv32_uart_printf("Internal i-cache: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_ICACHE)) { |