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 39 to Rev 40
- ↔ Reverse comparison
Rev 39 → Rev 40
/neorv32_cpu.c
295,3 → 295,123
return 1; // A extension not implemented -Y always fail |
#endif |
} |
|
|
/**********************************************************************//** |
* Physical memory protection (PMP): Get minimal region size (granularity). |
* |
* @warning This function overrides PMPCFG0[0] and PMPADDR0 CSRs. |
* |
* @warning This function requires the PMP CPU extension. |
* |
* @return Returns minimal region size in bytes; Returns 0 on failure. |
**************************************************************************/ |
uint32_t neorv32_cpu_pmp_get_granularity(void) { |
|
if ((neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) == 0) { |
return 0; // PMP not implemented |
} |
|
// check min granulartiy |
uint32_t tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); |
tmp &= 0xffffff00; // disable entry 0 |
neorv32_cpu_csr_write(CSR_PMPCFG0, tmp); |
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff); |
uint32_t tmp_a = neorv32_cpu_csr_read(CSR_PMPADDR0); |
|
uint32_t i; |
|
// find least-significat set bit |
for (i=31; i!=0; i--) { |
if (((tmp_a >> i) & 1) == 0) { |
break; |
} |
} |
|
return (uint32_t)(1 << (i+1+2)); |
} |
|
|
/**********************************************************************//** |
* Physical memory protection (PMP): Configure region. |
* |
* @note Using NAPOT mode - page base address has to be naturally aligned. |
* |
* @warning This function requires the PMP CPU extension. |
* |
* @param[in] index Region number (index, 0..max_regions-1). |
* @param[in] base Region base address (has to be naturally aligned!). |
* @param[in] size Region size, has to be a power of 2 (min 8 bytes or according to HW's PMP.granularity configuration). |
* @param[in] config Region configuration (attributes) byte (for PMPCFGx). |
* @return Returns 0 on success, 1 on failure. |
**************************************************************************/ |
int neorv32_cpu_pmp_configure_region(uint32_t index, uint32_t base, uint32_t size, uint8_t config) { |
|
if ((neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) == 0) { |
return 1; // PMP not implemented |
} |
|
if (size < 8) { |
return 1; // minimal region size is 8 bytes |
} |
|
if ((size & (size - 1)) != 0) { |
return 1; // region size is not a power of two |
} |
|
// setup configuration |
uint32_t tmp; |
uint32_t config_int = ((uint32_t)config) << ((index%4)*8); |
uint32_t config_mask = ((uint32_t)0xFF) << ((index%4)*8); |
config_mask = ~config_mask; |
|
// clear old configuration |
if (index < 3) { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); |
tmp &= config_mask; // clear old config |
neorv32_cpu_csr_write(CSR_PMPCFG0, tmp); |
} |
else { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); |
tmp &= config_mask; // clear old config |
neorv32_cpu_csr_write(CSR_PMPCFG1, tmp); |
} |
|
// set base address and region size |
uint32_t addr_mask = ~((size - 1) >> 2); |
uint32_t size_mask = (size - 1) >> 3; |
|
tmp = base & addr_mask; |
tmp = tmp | size_mask; |
|
switch(index & 7) { |
case 0: neorv32_cpu_csr_write(CSR_PMPADDR0, tmp); break; |
case 1: neorv32_cpu_csr_write(CSR_PMPADDR1, tmp); break; |
case 2: neorv32_cpu_csr_write(CSR_PMPADDR2, tmp); break; |
case 3: neorv32_cpu_csr_write(CSR_PMPADDR3, tmp); break; |
case 4: neorv32_cpu_csr_write(CSR_PMPADDR4, tmp); break; |
case 5: neorv32_cpu_csr_write(CSR_PMPADDR5, tmp); break; |
case 6: neorv32_cpu_csr_write(CSR_PMPADDR6, tmp); break; |
case 7: neorv32_cpu_csr_write(CSR_PMPADDR7, tmp); break; |
default: break; |
} |
|
// wait for HW to computer PMP-internal stuff (address masks) |
for (tmp=0; tmp<16; tmp++) { |
asm volatile ("nop"); |
} |
|
// set new configuration |
if (index < 3) { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG0); |
tmp |= config_int; // set new config |
neorv32_cpu_csr_write(CSR_PMPCFG0, tmp); |
} |
else { |
tmp = neorv32_cpu_csr_read(CSR_PMPCFG1); |
tmp |= config_int; // set new config |
neorv32_cpu_csr_write(CSR_PMPCFG1, tmp); |
} |
|
return 0; |
} |
/neorv32_rte.c
45,7 → 45,7
/**********************************************************************//** |
* The >private< trap vector look-up table of the NEORV32 RTE. |
**************************************************************************/ |
static uint32_t __neorv32_rte_vector_lut[16] __attribute__((unused)); // trap handler vector table |
static uint32_t __neorv32_rte_vector_lut[17] __attribute__((unused)); // trap handler vector table |
|
// private functions |
static void __attribute__((__interrupt__)) __neorv32_rte_core(void) __attribute__((aligned(16))) __attribute__((unused)); |
94,8 → 94,8
|
// id valid? |
if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS) || (id == RTE_TRAP_I_ILLEGAL) || |
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) || |
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || |
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) || |
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) || |
(id == RTE_TRAP_MSI) || (id == RTE_TRAP_MTI) || (id == RTE_TRAP_MEI) || |
(id == RTE_TRAP_FIRQ_0) || (id == RTE_TRAP_FIRQ_1) || (id == RTE_TRAP_FIRQ_2) || (id == RTE_TRAP_FIRQ_3)) { |
|
121,8 → 121,8
|
// id valid? |
if ((id == RTE_TRAP_I_MISALIGNED) || (id == RTE_TRAP_I_ACCESS) || (id == RTE_TRAP_I_ILLEGAL) || |
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) || |
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || |
(id == RTE_TRAP_BREAKPOINT) || (id == RTE_TRAP_L_MISALIGNED) || (id == RTE_TRAP_L_ACCESS) || |
(id == RTE_TRAP_S_MISALIGNED) || (id == RTE_TRAP_S_ACCESS) || (id == RTE_TRAP_MENV_CALL) || (id == RTE_TRAP_UENV_CALL) || |
(id == RTE_TRAP_MSI) || (id == RTE_TRAP_MTI) || (id == RTE_TRAP_MEI) || |
(id == RTE_TRAP_FIRQ_0) || (id == RTE_TRAP_FIRQ_1) || (id == RTE_TRAP_FIRQ_2) || (id == RTE_TRAP_FIRQ_3)) { |
|
177,6 → 177,7
case TRAP_CODE_L_ACCESS: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_L_ACCESS]; break; |
case TRAP_CODE_S_MISALIGNED: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_MISALIGNED]; break; |
case TRAP_CODE_S_ACCESS: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_S_ACCESS]; break; |
case TRAP_CODE_UENV_CALL: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_UENV_CALL]; break; |
case TRAP_CODE_MENV_CALL: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MENV_CALL]; break; |
case TRAP_CODE_MSI: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MSI]; break; |
case TRAP_CODE_MTI: rte_handler = __neorv32_rte_vector_lut[RTE_TRAP_MTI]; break; |
215,7 → 216,8
case TRAP_CODE_L_ACCESS: neorv32_uart_print("Load access fault"); break; |
case TRAP_CODE_S_MISALIGNED: neorv32_uart_print("Store address misaligned"); break; |
case TRAP_CODE_S_ACCESS: neorv32_uart_print("Store access fault"); break; |
case TRAP_CODE_MENV_CALL: neorv32_uart_print("Environment call"); break; |
case TRAP_CODE_UENV_CALL: neorv32_uart_print("Environment call from U-mode"); break; |
case TRAP_CODE_MENV_CALL: neorv32_uart_print("Environment call from M-mode"); break; |
case TRAP_CODE_MSI: neorv32_uart_print("Machine software interrupt"); break; |
case TRAP_CODE_MTI: neorv32_uart_print("Machine timer interrupt"); break; |
case TRAP_CODE_MEI: neorv32_uart_print("Machine external interrupt"); break; |
249,7 → 251,7
neorv32_uart_printf("\n\n<< Hardware Configuration Overview >>\n"); |
|
// CPU configuration |
neorv32_uart_printf("\n-- Central Processing Unit --\n"); |
neorv32_uart_printf("\n---- Central Processing Unit ----\n"); |
|
// ID |
neorv32_uart_printf("Hart ID: 0x%x\n", neorv32_cpu_csr_read(CSR_MHARTID)); |
285,6 → 287,15
} |
|
// CPU extensions |
neorv32_uart_printf("\nEndianness: "); |
if (neorv32_cpu_csr_read(CSR_MSTATUSH) & (1<<CPU_MSTATUSH_MBE)) { |
neorv32_uart_printf("big\n"); |
} |
else { |
neorv32_uart_printf("little\n"); |
} |
|
// CPU extensions |
neorv32_uart_printf("\nExtensions: "); |
tmp = neorv32_cpu_csr_read(CSR_MISA); |
for (i=0; i<26; i++) { |
295,7 → 306,7
} |
} |
|
// Z* CPU extensions (from custom CSR "mzext") |
// Z* CPU extensions (from custom "mzext" CSR) |
tmp = neorv32_cpu_csr_read(CSR_MZEXT); |
if (tmp & (1<<CPU_MZEXT_ZICSR)) { |
neorv32_uart_printf("Zicsr "); |
306,6 → 317,9
if (tmp & (1<<CPU_MZEXT_PMP)) { |
neorv32_uart_printf("PMP "); |
} |
if (tmp & (1<<CPU_MZEXT_ZICNT)) { |
neorv32_uart_printf("Zicnt "); |
} |
|
|
// check physical memory protection |
312,27 → 326,9
neorv32_uart_printf("\n\nPhysical memory protection: "); |
if (neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) { |
|
// check granulartiy |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0); |
neorv32_cpu_csr_write(CSR_PMPADDR0, 0xffffffff); |
uint32_t pmp_test_g = neorv32_cpu_csr_read(0x3b0); |
// get minimal region siz (granulartiy) |
neorv32_uart_printf("\n- Minimal granularity: %u bytes per region\n", neorv32_cpu_pmp_get_granularity()); |
|
// find least-significat set bit |
for (i=31; i!=0; i--) { |
if (((pmp_test_g >> i) & 1) == 0) { |
break; |
} |
} |
|
neorv32_uart_printf("\n- Min granularity: "); |
if (i < 29) { |
neorv32_uart_printf("%u bytes per region\n", (uint32_t)(1 << (i+1+2))); |
} |
else { |
neorv32_uart_printf("2^%u bytes per region\n", i+1+2); |
} |
|
|
// test available modes |
neorv32_uart_printf("- Mode TOR: "); |
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x08); |
370,13 → 366,13
|
|
// Misc - system |
neorv32_uart_printf("\n\n-- Processor --\n"); |
neorv32_uart_printf("\n\n---- Processor - General ----\n"); |
neorv32_uart_printf("Clock: %u Hz\n", SYSINFO_CLK); |
neorv32_uart_printf("User ID: 0x%x\n", SYSINFO_USER_CODE); |
|
|
// Memory configuration |
neorv32_uart_printf("\n-- Processor Memory Configuration --\n"); |
neorv32_uart_printf("\n---- Processor - Memory Configuration ----\n"); |
|
neorv32_uart_printf("Instr. base address: 0x%x\n", SYSINFO_ISPACE_BASE); |
neorv32_uart_printf("Internal IMEM: "); |
385,7 → 381,7
neorv32_uart_printf("Internal IMEM as ROM: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM)); |
|
neorv32_uart_printf("Data base address: 0x%x\n", SYSINFO_DSPACE_BASE); |
neorv32_uart_printf("\nData 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); |
393,11 → 389,18
neorv32_uart_printf("Bootloader: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER)); |
|
neorv32_uart_printf("External M interface: "); |
neorv32_uart_printf("\nExternal memory bus interface: "); |
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT)); |
neorv32_uart_printf("External memory bus Endianness: "); |
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) { |
neorv32_uart_printf("big\n"); |
} |
else { |
neorv32_uart_printf("little\n"); |
} |
|
// peripherals |
neorv32_uart_printf("\n-- Available Processor Peripherals --\n"); |
neorv32_uart_printf("\n\n---- Processor - Peripherals ----\n"); |
|
tmp = SYSINFO_FEATURES; |
|
516,20 → 519,39
**************************************************************************/ |
void neorv32_rte_print_logo(void) { |
|
neorv32_uart_print( |
"\n" |
" ##\n" |
" ## ## ## ##\n" |
" ## ## ######### ######## ######## ## ## ######## ######## ## ###############\n" |
"#### ## ## ## ## ## ## ## ## ## ## ## ## ## #### ####\n" |
"## ## ## ## ## ## ## ## ## ## ## ## ## ## ##### ##\n" |
"## ## ## ######### ## ## ######### ## ## ##### ## ## #### ##### ####\n" |
"## ## ## ## ## ## ## ## ## ## ## ## ## ## ##### ##\n" |
"## #### ## ## ## ## ## ## ## ## ## ## ## #### ####\n" |
"## ## ######### ######## ## ## ## ######## ########## ## ###############\n" |
" ## ## ## ##\n" |
" ##\n" |
"\n"); |
const uint32_t logo_data_c[11][4] = |
{ |
{0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000}, |
{0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000}, |
{0b01100000110001111111110001111111,0b10000111111110001100000011000111,0b11111000011111111000000110000000,0b11111111111111110000000000000000}, |
{0b11110000110011000000000011000000,0b11001100000011001100000011001100,0b00001100110000001100000110000011,0b11000000000000111100000000000000}, |
{0b11011000110011000000000011000000,0b11001100000011001100000011000000,0b00001100000000011000000110000000,0b11000111111000110000000000000000}, |
{0b11001100110011111111100011000000,0b11001111111110001100000011000000,0b11111000000001100000000110000011,0b11000111111000111100000000000000}, |
{0b11000110110011000000000011000000,0b11001100001100000110000110000000,0b00001100000110000000000110000000,0b11000111111000110000000000000000}, |
{0b11000011110011000000000011000000,0b11001100000110000011001100001100,0b00001100011000000000000110000011,0b11000000000000111100000000000000}, |
{0b11000001100001111111110001111111,0b10001100000011000000110000000111,0b11111000111111111100000110000000,0b11111111111111110000000000000000}, |
{0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00110001100011000000000000000000}, |
{0b00000000000000000000000000000000,0b00000000000000000000000000000000,0b00000000000000000000000110000000,0b00000000000000000000000000000000} |
}; |
|
int u,v,w; |
uint32_t tmp; |
|
for (u=0; u<11; u++) { |
neorv32_uart_print("\n"); |
for (v=0; v<4; v++) { |
tmp = logo_data_c[u][v]; |
for (w=0; w<32; w++){ |
if (tmp & (1 << (31-w))) { |
neorv32_uart_putc('#'); |
} |
else { |
neorv32_uart_putc(' '); |
} |
} |
} |
} |
neorv32_uart_print("\n"); |
} |
|
|