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 41 to Rev 42
    Reverse comparison

Rev 41 → Rev 42

/neorv32_cpu.c
3,7 → 3,7
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
48,13 → 48,13
*
* @note Interrupts have to be globally enabled via neorv32_cpu_eint(void), too.
*
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CPU_MIE_enum.
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum.
* @return 0 if success, 1 if error (invalid irq_sel).
**************************************************************************/
int neorv32_cpu_irq_enable(uint8_t irq_sel) {
 
if ((irq_sel != CPU_MIE_MSIE) && (irq_sel != CPU_MIE_MTIE) && (irq_sel != CPU_MIE_MEIE) &&
(irq_sel != CPU_MIE_FIRQ0E) && (irq_sel != CPU_MIE_FIRQ1E) && (irq_sel != CPU_MIE_FIRQ2E) && (irq_sel != CPU_MIE_FIRQ3E)) {
if ((irq_sel != CSR_MIE_MSIE) && (irq_sel != CSR_MIE_MTIE) && (irq_sel != CSR_MIE_MEIE) &&
(irq_sel != CSR_MIE_FIRQ0E) && (irq_sel != CSR_MIE_FIRQ1E) && (irq_sel != CSR_MIE_FIRQ2E) && (irq_sel != CSR_MIE_FIRQ3E)) {
return 1;
}
 
67,13 → 67,13
/**********************************************************************//**
* Disable specific CPU interrupt.
*
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CPU_MIE_enum.
* @param[in] irq_sel CPU interrupt select. See #NEORV32_CSR_MIE_enum.
* @return 0 if success, 1 if error (invalid irq_sel).
**************************************************************************/
int neorv32_cpu_irq_disable(uint8_t irq_sel) {
 
if ((irq_sel != CPU_MIE_MSIE) && (irq_sel != CPU_MIE_MTIE) && (irq_sel != CPU_MIE_MEIE) &&
(irq_sel != CPU_MIE_FIRQ0E) && (irq_sel != CPU_MIE_FIRQ1E) && (irq_sel != CPU_MIE_FIRQ2E) && (irq_sel != CPU_MIE_FIRQ3E)) {
if ((irq_sel != CSR_MIE_MSIE) && (irq_sel != CSR_MIE_MTIE) && (irq_sel != CSR_MIE_MEIE) &&
(irq_sel != CSR_MIE_FIRQ0E) && (irq_sel != CSR_MIE_FIRQ1E) && (irq_sel != CSR_MIE_FIRQ2E) && (irq_sel != CSR_MIE_FIRQ3E)) {
return 1;
}
 
254,7 → 254,7
"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
: : [input_imm] "i" ((1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L)));
: : [input_imm] "i" ((1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L)));
}
 
 
298,20 → 298,78
 
 
/**********************************************************************//**
* Physical memory protection (PMP): Get number of available regions.
*
* @warning This function overrides all available PMPCFG* CSRs.
* @warning This function requires the PMP CPU extension.
*
* @return Returns number of available PMP regions.
**************************************************************************/
uint32_t neorv32_cpu_pmp_get_num_regions(void) {
 
// try setting R bit in all PMPCFG CSRs
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG1, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG2, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG3, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG4, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG5, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG6, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG7, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG8, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG9, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG10, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG11, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG12, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG13, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG14, 0x01010101);
neorv32_cpu_csr_write(CSR_PMPCFG15, 0x01010101);
 
// sum up all written ones (only available PMPCFG* CSRs/entries will return =! 0)
union {
uint32_t uint32;
uint8_t uint8[sizeof(uint32_t)/sizeof(uint8_t)];
} cnt;
 
cnt.uint32 = 0;
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG0);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG1);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG2);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG3);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG4);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG5);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG6);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG7);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG8);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG9);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG10);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG11);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG12);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG13);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG14);
cnt.uint32 += neorv32_cpu_csr_read(CSR_PMPCFG15);
 
// sum up bytes
uint32_t num_regions = 0;
num_regions += (uint32_t)cnt.uint8[0];
num_regions += (uint32_t)cnt.uint8[1];
num_regions += (uint32_t)cnt.uint8[2];
num_regions += (uint32_t)cnt.uint8[3];
 
return num_regions;
}
 
 
/**********************************************************************//**
* 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.
* @return Returns minimal region size in bytes.
**************************************************************************/
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
338,8 → 396,9
* @note Using NAPOT mode - page base address has to be naturally aligned.
*
* @warning This function requires the PMP CPU extension.
* @warning Only use available PMP regions. Check before using neorv32_cpu_pmp_get_regions(void).
*
* @param[in] index Region number (index, 0..max_regions-1).
* @param[in] index Region number (index, 0..PMP_NUM_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).
347,10 → 406,6
**************************************************************************/
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
}
366,16 → 421,25
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);
switch(index & 15) {
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) & config_mask); break;
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, neorv32_cpu_csr_read(CSR_PMPCFG1) & config_mask); break;
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, neorv32_cpu_csr_read(CSR_PMPCFG2) & config_mask); break;
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, neorv32_cpu_csr_read(CSR_PMPCFG3) & config_mask); break;
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, neorv32_cpu_csr_read(CSR_PMPCFG4) & config_mask); break;
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, neorv32_cpu_csr_read(CSR_PMPCFG5) & config_mask); break;
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, neorv32_cpu_csr_read(CSR_PMPCFG6) & config_mask); break;
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, neorv32_cpu_csr_read(CSR_PMPCFG7) & config_mask); break;
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, neorv32_cpu_csr_read(CSR_PMPCFG8) & config_mask); break;
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, neorv32_cpu_csr_read(CSR_PMPCFG9) & config_mask); break;
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, neorv32_cpu_csr_read(CSR_PMPCFG10) & config_mask); break;
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, neorv32_cpu_csr_read(CSR_PMPCFG11) & config_mask); break;
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, neorv32_cpu_csr_read(CSR_PMPCFG12) & config_mask); break;
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, neorv32_cpu_csr_read(CSR_PMPCFG13) & config_mask); break;
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, neorv32_cpu_csr_read(CSR_PMPCFG14) & config_mask); break;
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, neorv32_cpu_csr_read(CSR_PMPCFG15) & config_mask); break;
default: break;
}
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);
384,34 → 448,172
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;
switch(index & 63) {
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;
case 8: neorv32_cpu_csr_write(CSR_PMPADDR8, tmp); break;
case 9: neorv32_cpu_csr_write(CSR_PMPADDR9, tmp); break;
case 10: neorv32_cpu_csr_write(CSR_PMPADDR10, tmp); break;
case 11: neorv32_cpu_csr_write(CSR_PMPADDR11, tmp); break;
case 12: neorv32_cpu_csr_write(CSR_PMPADDR12, tmp); break;
case 13: neorv32_cpu_csr_write(CSR_PMPADDR13, tmp); break;
case 14: neorv32_cpu_csr_write(CSR_PMPADDR14, tmp); break;
case 15: neorv32_cpu_csr_write(CSR_PMPADDR15, tmp); break;
case 16: neorv32_cpu_csr_write(CSR_PMPADDR16, tmp); break;
case 17: neorv32_cpu_csr_write(CSR_PMPADDR17, tmp); break;
case 18: neorv32_cpu_csr_write(CSR_PMPADDR18, tmp); break;
case 19: neorv32_cpu_csr_write(CSR_PMPADDR19, tmp); break;
case 20: neorv32_cpu_csr_write(CSR_PMPADDR20, tmp); break;
case 21: neorv32_cpu_csr_write(CSR_PMPADDR21, tmp); break;
case 22: neorv32_cpu_csr_write(CSR_PMPADDR22, tmp); break;
case 23: neorv32_cpu_csr_write(CSR_PMPADDR23, tmp); break;
case 24: neorv32_cpu_csr_write(CSR_PMPADDR24, tmp); break;
case 25: neorv32_cpu_csr_write(CSR_PMPADDR25, tmp); break;
case 26: neorv32_cpu_csr_write(CSR_PMPADDR26, tmp); break;
case 27: neorv32_cpu_csr_write(CSR_PMPADDR27, tmp); break;
case 28: neorv32_cpu_csr_write(CSR_PMPADDR28, tmp); break;
case 29: neorv32_cpu_csr_write(CSR_PMPADDR29, tmp); break;
case 30: neorv32_cpu_csr_write(CSR_PMPADDR30, tmp); break;
case 31: neorv32_cpu_csr_write(CSR_PMPADDR31, tmp); break;
case 32: neorv32_cpu_csr_write(CSR_PMPADDR32, tmp); break;
case 33: neorv32_cpu_csr_write(CSR_PMPADDR33, tmp); break;
case 34: neorv32_cpu_csr_write(CSR_PMPADDR34, tmp); break;
case 35: neorv32_cpu_csr_write(CSR_PMPADDR35, tmp); break;
case 36: neorv32_cpu_csr_write(CSR_PMPADDR36, tmp); break;
case 37: neorv32_cpu_csr_write(CSR_PMPADDR37, tmp); break;
case 38: neorv32_cpu_csr_write(CSR_PMPADDR38, tmp); break;
case 39: neorv32_cpu_csr_write(CSR_PMPADDR39, tmp); break;
case 40: neorv32_cpu_csr_write(CSR_PMPADDR40, tmp); break;
case 41: neorv32_cpu_csr_write(CSR_PMPADDR41, tmp); break;
case 42: neorv32_cpu_csr_write(CSR_PMPADDR42, tmp); break;
case 43: neorv32_cpu_csr_write(CSR_PMPADDR43, tmp); break;
case 44: neorv32_cpu_csr_write(CSR_PMPADDR44, tmp); break;
case 45: neorv32_cpu_csr_write(CSR_PMPADDR45, tmp); break;
case 46: neorv32_cpu_csr_write(CSR_PMPADDR46, tmp); break;
case 47: neorv32_cpu_csr_write(CSR_PMPADDR47, tmp); break;
case 48: neorv32_cpu_csr_write(CSR_PMPADDR48, tmp); break;
case 49: neorv32_cpu_csr_write(CSR_PMPADDR49, tmp); break;
case 50: neorv32_cpu_csr_write(CSR_PMPADDR50, tmp); break;
case 51: neorv32_cpu_csr_write(CSR_PMPADDR51, tmp); break;
case 52: neorv32_cpu_csr_write(CSR_PMPADDR52, tmp); break;
case 53: neorv32_cpu_csr_write(CSR_PMPADDR53, tmp); break;
case 54: neorv32_cpu_csr_write(CSR_PMPADDR54, tmp); break;
case 55: neorv32_cpu_csr_write(CSR_PMPADDR55, tmp); break;
case 56: neorv32_cpu_csr_write(CSR_PMPADDR56, tmp); break;
case 57: neorv32_cpu_csr_write(CSR_PMPADDR57, tmp); break;
case 58: neorv32_cpu_csr_write(CSR_PMPADDR58, tmp); break;
case 59: neorv32_cpu_csr_write(CSR_PMPADDR59, tmp); break;
case 60: neorv32_cpu_csr_write(CSR_PMPADDR60, tmp); break;
case 61: neorv32_cpu_csr_write(CSR_PMPADDR61, tmp); break;
case 62: neorv32_cpu_csr_write(CSR_PMPADDR62, tmp); break;
case 63: neorv32_cpu_csr_write(CSR_PMPADDR63, tmp); break;
default: break;
}
 
// wait for HW to computer PMP-internal stuff (address masks)
// wait for HW to compute 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);
switch(index & 15) {
case 0: neorv32_cpu_csr_write(CSR_PMPCFG0, neorv32_cpu_csr_read(CSR_PMPCFG0) | config_int); break;
case 1: neorv32_cpu_csr_write(CSR_PMPCFG1, neorv32_cpu_csr_read(CSR_PMPCFG1) | config_int); break;
case 2: neorv32_cpu_csr_write(CSR_PMPCFG2, neorv32_cpu_csr_read(CSR_PMPCFG2) | config_int); break;
case 3: neorv32_cpu_csr_write(CSR_PMPCFG3, neorv32_cpu_csr_read(CSR_PMPCFG3) | config_int); break;
case 4: neorv32_cpu_csr_write(CSR_PMPCFG4, neorv32_cpu_csr_read(CSR_PMPCFG4) | config_int); break;
case 5: neorv32_cpu_csr_write(CSR_PMPCFG5, neorv32_cpu_csr_read(CSR_PMPCFG5) | config_int); break;
case 6: neorv32_cpu_csr_write(CSR_PMPCFG6, neorv32_cpu_csr_read(CSR_PMPCFG6) | config_int); break;
case 7: neorv32_cpu_csr_write(CSR_PMPCFG7, neorv32_cpu_csr_read(CSR_PMPCFG7) | config_int); break;
case 8: neorv32_cpu_csr_write(CSR_PMPCFG8, neorv32_cpu_csr_read(CSR_PMPCFG8) | config_int); break;
case 9: neorv32_cpu_csr_write(CSR_PMPCFG9, neorv32_cpu_csr_read(CSR_PMPCFG9) | config_int); break;
case 10: neorv32_cpu_csr_write(CSR_PMPCFG10, neorv32_cpu_csr_read(CSR_PMPCFG10) | config_int); break;
case 11: neorv32_cpu_csr_write(CSR_PMPCFG11, neorv32_cpu_csr_read(CSR_PMPCFG11) | config_int); break;
case 12: neorv32_cpu_csr_write(CSR_PMPCFG12, neorv32_cpu_csr_read(CSR_PMPCFG12) | config_int); break;
case 13: neorv32_cpu_csr_write(CSR_PMPCFG13, neorv32_cpu_csr_read(CSR_PMPCFG13) | config_int); break;
case 14: neorv32_cpu_csr_write(CSR_PMPCFG14, neorv32_cpu_csr_read(CSR_PMPCFG14) | config_int); break;
case 15: neorv32_cpu_csr_write(CSR_PMPCFG15, neorv32_cpu_csr_read(CSR_PMPCFG15) | config_int); break;
default: break;
}
else {
tmp = neorv32_cpu_csr_read(CSR_PMPCFG1);
tmp |= config_int; // set new config
neorv32_cpu_csr_write(CSR_PMPCFG1, tmp);
}
 
return 0;
}
 
 
/**********************************************************************//**
* Hardware performance monitors (HPM): Get number of available HPM counters.
*
* @warning This function overrides all available mhpmcounter* CSRs.
*
* @return Returns number of available HPM counters (..29).
**************************************************************************/
uint32_t neorv32_cpu_hpm_get_counters(void) {
 
// try setting all mhpmcounter* CSRs to 1
neorv32_cpu_csr_write(CSR_MHPMCOUNTER3, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER4, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER5, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER6, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER7, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER8, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER9, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER10, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER11, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER12, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER13, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER14, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER15, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER16, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER17, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER18, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER19, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER20, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER21, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER22, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER23, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER24, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER25, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER26, 1);
neorv32_cpu_csr_write(CSR_MHPMCOUNTER27, 1);
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)
uint32_t num_hpm_cnts = 0;
 
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER3);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER4);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER5);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER6);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER7);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER8);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER9);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER10);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER11);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER12);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER13);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER14);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER15);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER16);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER17);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER18);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER19);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER20);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER21);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER22);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER23);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER24);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER25);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER26);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER27);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER28);
num_hpm_cnts += neorv32_cpu_csr_read(CSR_MHPMCOUNTER29);
 
return num_hpm_cnts;
}
/neorv32_rte.c
3,7 → 3,7
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
288,7 → 288,7
// CPU extensions
neorv32_uart_printf("\nEndianness: ");
if (neorv32_cpu_csr_read(CSR_MSTATUSH) & (1<<CPU_MSTATUSH_MBE)) {
if (neorv32_cpu_csr_read(CSR_MSTATUSH) & (1<<CSR_MSTATUSH_MBE)) {
neorv32_uart_printf("big\n");
}
else {
296,7 → 296,7
}
// CPU extensions
neorv32_uart_printf("\nExtensions: ");
neorv32_uart_printf("Extensions: ");
tmp = neorv32_cpu_csr_read(CSR_MISA);
for (i=0; i<26; i++) {
if (tmp & (1 << i)) {
308,60 → 308,31
// Z* CPU extensions (from custom "mzext" CSR)
tmp = neorv32_cpu_csr_read(CSR_MZEXT);
if (tmp & (1<<CPU_MZEXT_ZICSR)) {
if (tmp & (1<<CSR_MZEXT_ZICSR)) {
neorv32_uart_printf("Zicsr ");
}
if (tmp & (1<<CPU_MZEXT_ZIFENCEI)) {
if (tmp & (1<<CSR_MZEXT_ZIFENCEI)) {
neorv32_uart_printf("Zifencei ");
}
if (tmp & (1<<CPU_MZEXT_PMP)) {
neorv32_uart_printf("PMP ");
}
 
 
// check physical memory protection
neorv32_uart_printf("\n\nPhysical memory protection: ");
if (neorv32_cpu_csr_read(CSR_MZEXT) & (1<<CPU_MZEXT_PMP)) {
neorv32_uart_printf("\nPMP: ");
uint32_t pmp_num_regions = neorv32_cpu_pmp_get_num_regions();
if (pmp_num_regions != 0) {
// get number of available regions
neorv32_uart_printf("\n- Available regions: %u\n", pmp_num_regions);
 
// get minimal region siz (granulartiy)
neorv32_uart_printf("\n- Minimal granularity: %u bytes per region\n", neorv32_cpu_pmp_get_granularity());
 
// test available modes
neorv32_uart_printf("- Mode TOR: ");
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x08);
if ((neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xFF) == 0x08) {
neorv32_uart_printf("available\n");
}
else {
neorv32_uart_printf("not implemented\n");
}
 
neorv32_uart_printf("- Mode NA4: ");
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x10);
if ((neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xFF) == 0x10) {
neorv32_uart_printf("available\n");
}
else {
neorv32_uart_printf("not implemented\n");
}
 
neorv32_uart_printf("- Mode NAPOT: ");
neorv32_cpu_csr_write(CSR_PMPCFG0, 0x18);
if ((neorv32_cpu_csr_read(CSR_PMPCFG0) & 0xFF) == 0x18) {
neorv32_uart_printf("available\n");
}
else {
neorv32_uart_printf("not implemented\n");
}
 
// deactivate entry
neorv32_cpu_csr_write(CSR_PMPCFG0, 0);
// get minimal region size (granulartiy)
neorv32_uart_printf("- Minimal granularity: %u bytes per region\n", neorv32_cpu_pmp_get_granularity());
}
else {
neorv32_uart_printf("not implemented\n");
}
 
// check physical memory protection
neorv32_uart_printf("HPM Counters: %u\n", neorv32_cpu_hpm_get_counters());
 
 
// Misc - system
neorv32_uart_printf("\n\n---- Processor - General ----\n");
neorv32_uart_printf("Clock: %u Hz\n", SYSINFO_CLK);
378,12 → 349,12
neorv32_uart_printf("Internal IMEM as ROM: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_INT_IMEM_ROM));
 
neorv32_uart_printf("\nData base address: 0x%x\n", SYSINFO_DSPACE_BASE);
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);
 
neorv32_uart_printf("\nInternal 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)) {
neorv32_uart_printf("- ");
419,12 → 390,12
}
}
 
neorv32_uart_printf("\nBootloader: ");
neorv32_uart_printf("Bootloader: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_BOOTLOADER));
 
neorv32_uart_printf("\nExternal memory bus interface: ");
neorv32_uart_printf("Ext. bus interface: ");
__neorv32_rte_print_true_false(SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT));
neorv32_uart_printf("External memory bus Endianness: ");
neorv32_uart_printf("Ext. bus Endianness: ");
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_MEM_EXT_ENDIAN)) {
neorv32_uart_printf("big\n");
}
542,7 → 513,9
**************************************************************************/
void neorv32_rte_print_credits(void) {
 
neorv32_uart_print("The NEORV32 Processor Project by Stephan Nolting\n"
neorv32_uart_print("The NEORV32 Processor Project\n"
"Copyright 2021, Stephan Nolting\n"
"BSD 3-Clause License\n"
"https://github.com/stnolting/neorv32\n\n");
}
 
597,7 → 570,7
"\n"
"BSD 3-Clause License\n"
"\n"
"Copyright (c) 2020, Stephan Nolting. All rights reserved.\n"
"Copyright (c) 2021, Stephan Nolting. All rights reserved.\n"
"\n"
"Redistribution and use in source and binary forms, with or without modification, are\n"
"permitted provided that the following conditions are met:\n"
/neorv32_uart.c
75,10 → 75,11
* @warning To enable simulation mode add <USER_FLAGS+=-DUART_SIM_MODE> when compiling.
*
* @param[in] baudrate Targeted BAUD rate (e.g. 9600).
* @param[in] parity PArity configuration (00=off, 10=even, 11=odd).
* @param[in] rx_irq Enable RX interrupt (data received) when 1.
* @param[in] tx_irq Enable TX interrupt (transmission done) when 1.
**************************************************************************/
void neorv32_uart_setup(uint32_t baudrate, uint8_t rx_irq, uint8_t tx_irq) {
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity, uint8_t rx_irq, uint8_t tx_irq) {
 
UART_CT = 0; // reset
 
116,6 → 117,9
uint32_t uart_en = 1;
uart_en = uart_en << UART_CT_EN;
 
uint32_t parity_config = (uint32_t)(parity & 3);
parity_config = parity_config << UART_CT_PMODE0;
 
uint32_t rx_irq_en = (uint32_t)(rx_irq & 1);
rx_irq_en = rx_irq_en << UART_CT_RX_IRQ;
 
123,7 → 127,7
tx_irq_en = tx_irq_en << UART_CT_TX_IRQ;
 
/* Enable the UART for SIM mode. */
/* Only use this for simulation! */
/* USE THIS ONLY FOR SIMULATION! */
#ifdef UART_SIM_MODE
#warning UART_SIM_MODE enabled! Sending all UART.TX data to text.io simulation output instead of real UART transmitter. Use this for simulations only!
uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
131,7 → 135,7
uint32_t sim_mode = 0;
#endif
 
UART_CT = prsc | baud | uart_en | rx_irq_en | tx_irq_en | sim_mode;
UART_CT = prsc | baud | uart_en | parity_config | rx_irq_en | tx_irq_en | sim_mode;
}
 
 
182,7 → 186,7
/**********************************************************************//**
* Get char from UART.
*
* @note This function is blocking.
* @note This function is blocking and does not check for UART frame/parity errors.
*
* @return Received char.
**************************************************************************/
199,8 → 203,48
 
 
/**********************************************************************//**
* Check if UARt has received a char.
* Get char from UART (and check errors).
*
* @note This function is non-blocking and checks for frame and parity errors.
*
* @param[in,out] data Received char.
* @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
**************************************************************************/
int neorv32_uart_getc_secure(char *data) {
 
uint32_t uart_rx = UART_DATA;
if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
 
int status = 0;
 
// check for frame error
if (uart_rx & (1<<UART_DATA_FERR)) {
status -= 1;
}
 
// check for parity error
if (uart_rx & (1<<UART_DATA_PERR)) {
status -= 2;
}
 
if (status == 0) {
status = 1;
}
 
// get received byte
*data = (char)uart_rx;
 
return status;
}
else {
return 0;
}
}
 
 
/**********************************************************************//**
* Check if UART has received a char.
*
* @note This function is non-blocking.
* @note Use neorv32_uart_char_received_get(void) to get the char.
*

powered by: WebSVN 2.1.0

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