OpenCores
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)) {

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.