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/example
    from Rev 72 to Rev 73
    Reverse comparison

Rev 72 → Rev 73

/bitmanip_test/main.c
603,11 → 603,9
* "after-main" handler that is executed after the application's
* main function returns (called by crt0.S start-up code)
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
if (return_code) {
neorv32_uart0_printf("\n<RTE> main function returned with exit code (%i) </RTE>\n", return_code);
}
 
return 0;
}
/coremark/core_portme.c
81,8 → 81,8
void
start_time(void)
{
GETMYTIME(&start_time_val);
neorv32_cpu_csr_write(CSR_MCOUNTINHIBIT, 0); // start all counters
GETMYTIME(&start_time_val);
}
/* Function : stop_time
This function will be called right after ending the timed portion of the
103,8 → 103,8
 
Actual value returned may be cpu cycles, milliseconds or any other
value, as long as it can be converted to seconds by <time_in_secs>. This
methodology is taken to accomodate any hardware or simulated platform. The
sample implementation returns millisecs by default, and the resolution is
methodology is taken to accommodate any hardware or simulated platform. The
sample implementation returns milliseconds by default, and the resolution is
controlled by <TIMER_RES_DIVIDER>
*/
CORE_TICKS
233,24 → 233,24
 
neorv32_uart0_printf("\nNEORV32: All reported numbers only show the integer part.\n\n");
 
neorv32_uart0_printf("NEORV32: HPM results\n");
neorv32_uart0_printf("NEORV32: HPM results (low words only)\n");
if (num_hpm_cnts_global == 0) {neorv32_uart0_printf("no HPMs available\n"); }
if (num_hpm_cnts_global > 0) {neorv32_uart0_printf("# Retired compr. instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); }
if (num_hpm_cnts_global > 1) {neorv32_uart0_printf("# I-fetch wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); }
if (num_hpm_cnts_global > 2) {neorv32_uart0_printf("# I-issue wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); }
if (num_hpm_cnts_global > 3) {neorv32_uart0_printf("# Multi-cycle ALU wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); }
if (num_hpm_cnts_global > 4) {neorv32_uart0_printf("# Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); }
if (num_hpm_cnts_global > 5) {neorv32_uart0_printf("# Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); }
if (num_hpm_cnts_global > 6) {neorv32_uart0_printf("# Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); }
if (num_hpm_cnts_global > 7) {neorv32_uart0_printf("# Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); }
if (num_hpm_cnts_global > 8) {neorv32_uart0_printf("# Conditional branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); }
if (num_hpm_cnts_global > 9) {neorv32_uart0_printf("# Conditional branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); }
if (num_hpm_cnts_global > 10) {neorv32_uart0_printf("# Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); }
if (num_hpm_cnts_global > 11) {neorv32_uart0_printf("# Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); }
if (num_hpm_cnts_global > 0) {neorv32_uart0_printf(" > Retired compr. instructions: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER3)); }
if (num_hpm_cnts_global > 1) {neorv32_uart0_printf(" > Instr.-fetch wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER4)); }
if (num_hpm_cnts_global > 2) {neorv32_uart0_printf(" > Instr.-issue wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER5)); }
if (num_hpm_cnts_global > 3) {neorv32_uart0_printf(" > Multi-cycle ALU wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER6)); }
if (num_hpm_cnts_global > 4) {neorv32_uart0_printf(" > Load operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER7)); }
if (num_hpm_cnts_global > 5) {neorv32_uart0_printf(" > Store operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER8)); }
if (num_hpm_cnts_global > 6) {neorv32_uart0_printf(" > Load/store wait cycles: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER9)); }
if (num_hpm_cnts_global > 7) {neorv32_uart0_printf(" > Unconditional jumps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER10)); }
if (num_hpm_cnts_global > 8) {neorv32_uart0_printf(" > Conditional branches (all): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER11)); }
if (num_hpm_cnts_global > 9) {neorv32_uart0_printf(" > Conditional branches (taken): %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER12)); }
if (num_hpm_cnts_global > 10) {neorv32_uart0_printf(" > Entered traps: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER13)); }
if (num_hpm_cnts_global > 11) {neorv32_uart0_printf(" > Illegal operations: %u\n", (uint32_t)neorv32_cpu_csr_read(CSR_MHPMCOUNTER14)); }
neorv32_uart0_printf("\n");
 
neorv32_uart0_printf("NEORV32: Executed instructions 0x%x_%x\n", (uint32_t)exe_instructions.uint32[1], (uint32_t)exe_instructions.uint32[0]);
neorv32_uart0_printf("NEORV32: CoreMark core clock cycles 0x%x_%x\n", (uint32_t)exe_time.uint32[1], (uint32_t)exe_time.uint32[0]);
neorv32_uart0_printf("NEORV32: Executed instructions 0x%x%x\n", (uint32_t)exe_instructions.uint32[1], (uint32_t)exe_instructions.uint32[0]);
neorv32_uart0_printf("NEORV32: CoreMark core clock cycles 0x%x%x\n", (uint32_t)exe_time.uint32[1], (uint32_t)exe_time.uint32[0]);
 
uint64_t average_cpi_int = exe_time.uint64 / exe_instructions.uint64;
neorv32_uart0_printf("NEORV32: Average CPI (integer part only): %u cycles/instruction\n", (uint32_t)average_cpi_int);
/demo_gptmr/main.c
113,7 → 113,7
**************************************************************************/
void gptmr_firq_handler(void) {
 
neorv32_cpu_csr_write(CSR_MIP, 1<<GPTMR_FIRQ_PENDING); // clear/ack pending FIRQ
neorv32_cpu_csr_write(CSR_MIP, ~(1<<GPTMR_FIRQ_PENDING)); // clear/ack pending FIRQ
 
neorv32_uart0_putc('.'); // send tick symbol via UART0
neorv32_gpio_pin_toggle(0); // toggle output port bit 0
/demo_pmp/main.c
0,0 → 1,177
// #################################################################################################
// # << NEORV32 - Physical Memory Protection Example Program >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2022, 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: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file demo_pmp/main.c
* @author Stephan Nolting
* @brief Physical memory protection (PMP) example program.
**************************************************************************/
#include <neorv32.h>
 
 
/**********************************************************************//**
* @name User configuration
**************************************************************************/
/**@{*/
/** UART BAUD rate */
#define BAUD_RATE 19200
/**@}*/
 
 
/**********************************************************************//**
* Example variable that will be protected by the PMP
**************************************************************************/
uint32_t protected_var[4] = {
0x11223344,
0x55667788,
0x00CAFE00,
0xDEADC0DE
};
 
 
/**********************************************************************//**
* Main function
*
* @note This program requires the CPU PMP extension (with at least 2 regions) and UART0.
*
* @return 0 if execution was successful
**************************************************************************/
int main() {
 
// initialize NEORV32 run-time environment
neorv32_rte_setup();
 
// setup UART0 at default baud rate, no parity bits, no HW flow control
neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
 
// check if UART0 is implemented
if (neorv32_uart0_available() == 0) {
return 1; // UART0 not available, exit
}
 
// check if PMP is implemented at all
if ((neorv32_cpu_csr_read(CSR_MXISA) & (1 << CSR_MXISA_PMP)) == 0) {
neorv32_uart0_printf("ERROR! PMP CPU extension not implemented!\n");
return 1;
}
 
 
// intro
neorv32_uart0_printf("\n<<< NEORV32 Physical Memory Protection (PMP) Example Program >>>\n\n");
 
neorv32_uart0_printf("NOTE: This program requires at least 2 PMP regions (PMP_NUM_REGIONS >= 2)\n"
" and a minimal granularity of 4 bytes (PMP_MIN_GRANULARITY = 4).\n\n");
 
neorv32_uart0_printf("NOTE: A 4-word array 'protected_var[4]' is created, which will be probed from\n"
" **machine-mode**. It provides the following access rights:\n"
" - NO_EXECUTE\n"
" - NO_WRITE\n"
" - READ\n"
" - LOCKED - also enforce access rights for machine-mode software\n\n");
 
 
// show PMP configuration
neorv32_uart0_printf("PMP hardware configuration:\n");
neorv32_uart0_printf("> Number of regions: %u\n", neorv32_cpu_pmp_get_num_regions());
neorv32_uart0_printf("> Min. granularity: %u bytes (minimal region size)\n\n", neorv32_cpu_pmp_get_granularity());
 
 
// The "protected_var" variable will be protected: No execute and no write access, just allow read access
 
// create protected region
int pmp_status;
uint8_t permissions;
neorv32_uart0_printf("Creating protected regions (any access within [REGION_BEGIN <= address < REGION_END] will match the PMP rules)...\n");
 
// any access in "region_begin <= address < region_end" will match the PMP rule
uint32_t region_begin = (uint32_t)(&protected_var[0]);
uint32_t region_end = (uint32_t)(&protected_var[4]) + 4;
neorv32_uart0_printf("REGION_BEGIN = 0x%x\n", region_begin);
neorv32_uart0_printf("REGION_END = 0x%x\n", region_end);
 
// base (region begin)
permissions = PMP_OFF << PMPCFG_A_LSB; // mode = OFF
neorv32_uart0_printf("> Region begin (PMP entry 0): Base = 0x%x, Mode = OFF (base of region) ", region_begin);
pmp_status = neorv32_cpu_pmp_configure_region(0, region_begin, permissions);
if (pmp_status) {
neorv32_uart0_printf("[FAILED]\n");
}
else {
neorv32_uart0_printf("[ok]\n");
}
 
// bound (region end)
permissions = (PMP_TOR << PMPCFG_A_LSB) | // enable entry as TOR = top of region
(0 << PMPCFG_X) | // no "execute" permission
(0 << PMPCFG_W) | // no "write" permission
(1 << PMPCFG_R) | // set "read" permission
(1 << PMPCFG_L); // locked: also enforce PMP rule for machine-mode software
neorv32_uart0_printf("> Region end (PMP entry 1): Base = 0x%x, Mode = TOR (top of region) ", region_end);
pmp_status = neorv32_cpu_pmp_configure_region(1, region_end, permissions);
if (pmp_status) {
neorv32_uart0_printf("[FAILED]\n");
}
else {
neorv32_uart0_printf("[ok]\n");
}
 
// test access
neorv32_uart0_printf("\nTesting access to 'protected_var' - invalid accesses will raise an exception, which will be\n"
"captured by the NEORV32 runtime environment's dummy/debug handlers ('<RTE> ... </RTE>').\n\n");
 
neorv32_uart0_printf("Reading protected_var[0] = 0x%x\n", protected_var[0]);
neorv32_uart0_printf("Reading protected_var[1] = 0x%x\n", protected_var[1]);
neorv32_uart0_printf("Reading protected_var[2] = 0x%x\n", protected_var[2]);
neorv32_uart0_printf("Reading protected_var[3] = 0x%x\n\n", protected_var[3]);
 
neorv32_uart0_printf("Trying to write protected_var[0]... ");
protected_var[0] = 0; // should fail!
neorv32_uart0_printf("Trying to write protected_var[1]... ");
protected_var[1] = 0; // should fail!
neorv32_uart0_printf("Trying to write protected_var[2]... ");
protected_var[2] = 0; // should fail!
neorv32_uart0_printf("Trying to write protected_var[3]... ");
protected_var[3] = 0; // should fail!
 
neorv32_uart0_printf("\nReading again protected_var[0] = 0x%x\n", protected_var[0]);
neorv32_uart0_printf("Reading again protected_var[1] = 0x%x\n", protected_var[1]);
neorv32_uart0_printf("Reading again protected_var[2] = 0x%x\n", protected_var[2]);
neorv32_uart0_printf("Reading again protected_var[3] = 0x%x\n\n", protected_var[3]);
 
 
neorv32_uart0_printf("\nPMP demo program completed.\n");
 
return 0;
}
/demo_pmp/makefile
0,0 → 1,40
#################################################################################################
# << NEORV32 - Application Makefile >> #
# ********************************************************************************************* #
# Make sure to add the RISC-V GCC compiler's bin folder to your PATH environment variable. #
# ********************************************************************************************* #
# BSD 3-Clause License #
# #
# 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: #
# #
# 1. Redistributions of source code must retain the above copyright notice, this list of #
# conditions and the following disclaimer. #
# #
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
# conditions and the following disclaimer in the documentation and/or other materials #
# provided with the distribution. #
# #
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
# endorse or promote products derived from this software without specific prior written #
# permission. #
# #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
# OF THE POSSIBILITY OF SUCH DAMAGE. #
# ********************************************************************************************* #
# The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
#################################################################################################
 
# Modify this variable to fit your NEORV32 setup (neorv32 home folder)
NEORV32_HOME ?= ../../..
 
include $(NEORV32_HOME)/sw/common/common.mk
/demo_slink/main.c
3,7 → 3,7
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
// # Copyright (c) 2022, 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: #
475,7 → 475,7
**************************************************************************/
void slink_rx_firq_handler(void) {
 
neorv32_cpu_csr_write(CSR_MIP, 1 << SLINK_RX_FIRQ_PENDING); // ACK interrupt
neorv32_cpu_csr_write(CSR_MIP, ~(1 << SLINK_RX_FIRQ_PENDING)); // ACK interrupt
neorv32_uart0_printf("\n<SLINK_RX_IRQ>\n");
}
 
485,7 → 485,7
**************************************************************************/
void slink_tx_firq_handler(void) {
 
neorv32_cpu_csr_write(CSR_MIP, 1 << SLINK_TX_FIRQ_PENDING); // ACK interrupt
neorv32_cpu_csr_write(CSR_MIP, ~(1 << SLINK_TX_FIRQ_PENDING)); // ACK interrupt
neorv32_uart0_printf("\n<SLINK_TX_IRQ>\n");
}
 
/newlib_demo/main.c
55,7 → 55,7
/**********************************************************************//**
* Main function: Check some of newlib's core functions.
*
* @note This program requires UART.
* @note This program requires UART0.
*
* @return 0 if execution was successful
**************************************************************************/
87,7 → 87,12
 
neorv32_uart0_printf("newlib version %i.%i\n\n", (int32_t)__NEWLIB__, (int32_t)__NEWLIB_MINOR__);
 
neorv32_uart0_printf("<rand> test... ");
srand(neorv32_cpu_csr_read(CSR_CYCLE)); // set random seed
neorv32_uart0_printf("%i, %i, %i, %i ", rand() % 100, rand() % 100, rand() % 100, rand() % 100);
neorv32_uart0_printf("ok\n");
 
 
char *char_buffer; // pointer for dynamic memory allocation
 
neorv32_uart0_printf("<malloc> test... ");
131,9 → 136,7
* "after-main" handler that is executed after the application's
* main function returns (called by crt0.S start-up code)
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
neorv32_uart0_printf("\n<RTE> main function returned with exit code %i. </RTE>\n", return_code);
 
return 0;
neorv32_uart0_printf("\n<RTE> main function returned with exit code %i </RTE>\n", return_code);
}
/processor_check/main.c
82,6 → 82,7
 
 
// Prototypes
void __attribute__((naked)) goto_user_mode(void);
void sim_irq_trigger(uint32_t sel);
void global_trap_handler(void);
void xirq_trap_handler0(void);
101,10 → 102,16
/// XIRQ trap handler acknowledge
uint32_t xirq_trap_handler_ack = 0;
 
/// Variable to test store accesses
volatile uint32_t store_access_addr[2];
 
/// Variable to test atomic accesses
uint32_t atomic_access_addr;
volatile uint32_t atomic_access_addr;
 
/// Variable to test PMP
volatile uint32_t pmp_access_addr;
 
 
/**********************************************************************//**
* High-level CPU/processor test program.
*
162,7 → 169,7
}
 
 
// reset performance counter
// reset (performance) counters
// neorv32_cpu_csr_write(CSR_MCYCLEH, 0); -> done in crt0.S
// neorv32_cpu_csr_write(CSR_MCYCLE, 0); -> done in crt0.S
// neorv32_cpu_csr_write(CSR_MINSTRETH, 0); -> done in crt0.S
177,13 → 184,13
 
// fancy intro
// -----------------------------------------------
// logo
// show ASCII logo
neorv32_rte_print_logo();
 
// show project credits
neorv32_rte_print_credits();
 
// show full HW config report
// show full hardware configuration report
neorv32_rte_print_hw_config();
 
 
223,6 → 230,13
 
 
// ----------------------------------------------------------
// Test fence instructions (just make sure CPU does not crash)
// ----------------------------------------------------------
asm volatile ("fence");
asm volatile ("fence.i");
 
 
// ----------------------------------------------------------
// Test performance counter: setup as many events and counter as feasible
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
362,23 → 376,20
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
 
neorv32_cpu_csr_write(CSR_CYCLE, 1); // make sure CSR is != 0 for this test
neorv32_cpu_csr_write(CSR_CYCLEH, 1); // make sure CSR is != 0 for this test
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
// access to cycle CSR is no longer allowed
asm volatile (" mv %[result], zero \n" // initialize with zero
" rdcycle %[result] " // read CSR_CYCLE, is not allowed and should not alter [result]
asm volatile (" li %[result], 0xcc11aa22 \n" // initialize
" rdcycleh %[result] " // read CSR_CYCLE, is not allowed and should not alter [result]
: [result] "=r" (tmp_a) : );
}
 
if (tmp_a != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
// make sure there was an illegal instruction trap
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) && (tmp_a == 0)) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) &&
(tmp_a == 0xcc11aa22)) { // destination register not altered
test_ok();
}
else {
400,7 → 411,7
cnt_test++;
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
asm volatile ("mret");
}
417,7 → 428,7
// External memory interface test
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] External memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
PRINT_STANDARD("[%i] Ext. memory access (@ 0x%x): ", cnt_test, (uint32_t)EXT_MEM_BASE);
 
if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_MEM_EXT)) {
cnt_test++;
456,7 → 467,7
// Illegal CSR access (CSR not implemented)
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] Non-existent CSR access: ", cnt_test);
PRINT_STANDARD("[%i] Non-existent CSR: ", cnt_test);
 
cnt_test++;
 
474,7 → 485,7
// Write-access to read-only CSR
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] Read-only CSR write access: ", cnt_test);
PRINT_STANDARD("[%i] Read-only CSR write: ", cnt_test);
 
cnt_test++;
 
512,7 → 523,7
// Unaligned instruction address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] I_ALIGN (instr. alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] I_ALIGN (instr. align) EXC: ", cnt_test);
 
// skip if C-mode is implemented
if ((neorv32_cpu_csr_read(CSR_MISA) & (1<<CSR_MISA_C)) == 0) {
614,7 → 625,7
// Breakpoint instruction
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] BREAK (break instr.) EXC: ", cnt_test);
PRINT_STANDARD("[%i] BREAK EXC: ", cnt_test);
cnt_test++;
 
asm volatile("EBREAK");
631,14 → 642,17
// Unaligned load address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] L_ALIGN (load addr alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] L_ALIGN (load align) EXC: ", cnt_test);
cnt_test++;
 
// load from unaligned address
neorv32_cpu_load_unsigned_word(ADDR_UNALIGNED_1);
asm volatile ("li %[da], 0xcafe1230 \n" // initialize destination register with known value
"lw %[da], 0(%[ad]) " // must not update destination register to to exception
: [da] "=r" (tmp_b) : [ad] "r" (ADDR_UNALIGNED_1));
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_MISALIGNED) &&
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNALIGNED_1)) {
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNALIGNED_1) &&
(tmp_b == 0xcafe1230)) { // make sure dest. reg is not updated
test_ok();
}
else {
650,16 → 664,20
// Load access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] L_ACC (load bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] L_ACC (load access) EXC: ", cnt_test);
cnt_test++;
 
tmp_a = (1 << BUSKEEPER_ERR_FLAG) | (1 << BUSKEEPER_ERR_TYPE);
 
// load from unreachable aligned address
neorv32_cpu_load_unsigned_word(ADDR_UNREACHABLE);
asm volatile ("li %[da], 0xcafe1230 \n" // initialize destination register with known value
"lw %[da], 0(%[ad]) " // must not update destination register to to exception
: [da] "=r" (tmp_b) : [ad] "r" (ADDR_UNREACHABLE));
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) && // load bus access error exception
(NEORV32_BUSKEEPER.CTRL = tmp_a)) { // buskeeper: error flag + timeout error
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_UNREACHABLE) &&
(tmp_b == 0xcafe1230) && // make sure dest. reg is not updated
(NEORV32_BUSKEEPER.CTRL = tmp_a)) { // buskeeper: error flag + timeout error
test_ok();
}
else {
671,13 → 689,22
// Unaligned store address
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] S_ALIGN (store addr alignment) EXC: ", cnt_test);
PRINT_STANDARD("[%i] S_ALIGN (store align) EXC: ", cnt_test);
cnt_test++;
 
// initialize test variable
store_access_addr[0] = 0x11223344;
store_access_addr[1] = 0x55667788;
tmp_a = (uint32_t)(&store_access_addr[0]);
tmp_a += 2; // make word-unaligned
 
// store to unaligned address
neorv32_cpu_store_unsigned_word(ADDR_UNALIGNED_2, 0);
neorv32_cpu_store_unsigned_word(tmp_a, 0);
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_MISALIGNED) &&
(neorv32_cpu_csr_read(CSR_MTVAL) == tmp_a) &&
(store_access_addr[0] == 0x11223344) &&
(store_access_addr[1] == 0x55667788)) { // make sure memory was not altered
test_ok();
}
else {
689,7 → 716,7
// Store access fault
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] S_ACC (store bus access) EXC: ", cnt_test);
PRINT_STANDARD("[%i] S_ACC (store access) EXC: ", cnt_test);
cnt_test++;
 
tmp_a = (1 << BUSKEEPER_ERR_FLAG) | (0 << BUSKEEPER_ERR_TYPE);
698,6 → 725,7
neorv32_cpu_store_unsigned_word(ADDR_READONLY, 0);
 
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_S_ACCESS) && // store bus access error exception
(neorv32_cpu_csr_read(CSR_MTVAL) == ADDR_READONLY) &&
(NEORV32_BUSKEEPER.CTRL == tmp_a)) { // buskeeper: error flag + device error
test_ok();
}
710,10 → 738,10
// Environment call from M-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from M-mode EXC: ", cnt_test);
PRINT_STANDARD("[%i] ENVCALL M-mode EXC: ", cnt_test);
cnt_test++;
 
asm volatile("ECALL");
asm volatile("ecall");
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_MENV_CALL) {
test_ok();
727,14 → 755,14
// Environment call from U-mode
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] ENVCALL (ecall instr.) from U-mode EXC: ", cnt_test);
PRINT_STANDARD("[%i] ENVCALL U-mode EXC: ", cnt_test);
 
cnt_test++;
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
asm volatile("ECALL");
asm volatile("ecall");
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_UENV_CALL) {
1408,7 → 1436,7
 
 
// ----------------------------------------------------------
// Test WFI ("sleep") instructions, wakeup via MTIME
// Test WFI ("sleep") instruction (executed in user mode), wakeup via MTIME
// ----------------------------------------------------------
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
PRINT_STANDARD("[%i] WFI (sleep instruction, wake-up via MTIME): ", cnt_test);
1421,9 → 1449,15
// enable mtime interrupt
neorv32_cpu_irq_enable(CSR_MIE_MTIE);
 
// put CPU into sleep mode
asm volatile ("wfi");
// clear mstatus.TW to allow execution of WFI also in user-mode
neorv32_cpu_csr_write(CSR_MSTATUS, neorv32_cpu_csr_read(CSR_MSTATUS) & ~(1<<CSR_MSTATUS_TW));
 
// put CPU into sleep mode (from user mode)
goto_user_mode();
{
asm volatile ("wfi");
}
 
// no more mtime interrupts
neorv32_cpu_irq_disable(CSR_MIE_MTIE);
neorv32_mtime_set_timecmp(-1);
1445,7 → 1479,7
cnt_test++;
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
// access to misa not allowed for user-level programs
tmp_a = neorv32_cpu_csr_read(CSR_MISA);
1488,10 → 1522,10
// ----------------------------------------------------------
// Test physical memory protection
// ----------------------------------------------------------
PRINT_STANDARD("[%i] PMP - Physical memory protection: ", cnt_test);
PRINT_STANDARD("[%i] PMP:\n", cnt_test);
 
// check if PMP is implemented
if (neorv32_cpu_pmp_get_num_regions() != 0) {
// check if PMP is implemented (two regions are required for these tests)
if (neorv32_cpu_pmp_get_num_regions() > 1) {
 
// Create PMP protected region
// ---------------------------------------------
1498,22 → 1532,19
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
cnt_test++;
 
// find out minimal region size (granularity)
tmp_b = neorv32_cpu_pmp_get_granularity();
tmp_a = (uint32_t)(&pmp_access_addr); // base address of protected region
tmp_b = PMP_TOR << PMPCFG_A_LSB; // enable region, but absolutely no access rights
 
tmp_a = NEORV32_SYSINFO.DSPACE_BASE; // base address of protected region
PRINT_STANDARD("Creating protected page (NAPOT, [!X,!W,!R], %u bytes) @ 0x%x: ", tmp_b, tmp_a);
 
// configure
int pmp_return = neorv32_cpu_pmp_configure_region(0, tmp_a, tmp_b, PMPCFG_MODE_NAPOT << PMPCFG_A_LSB); // NAPOT, NO read/write/execute permissions
 
if ((pmp_return == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
int pmp_res = 0;
PRINT_STANDARD("Setup region 0 OFF [ -, -, -] @ 0x%x\n", tmp_a);
pmp_res += neorv32_cpu_pmp_configure_region(0, tmp_a, 0);
PRINT_STANDARD("Setup region 1 TOR [!X,!W,!R] @ 0x%x ", tmp_a+4);
pmp_res += neorv32_cpu_pmp_configure_region(1, tmp_a+4, tmp_b);
if ((pmp_res == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
test_ok();
}
else {
if (neorv32_cpu_csr_read(CSR_PMPCFG0) & 0x80) {
PRINT_CRITICAL("%c[1m<Entry LOCKED!> %c[0m\n", 27, 27);
}
test_fail();
}
 
1524,22 → 1555,18
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
asm volatile ("jalr ra, %[input_i]" : : [input_i] "r" (tmp_a)); // call address to execute -> should fail
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_fail();
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ACCESS) {
asm volatile ("ecall"); // switch back to machine mode (if not already)
test_ok();
}
else {
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
test_ok();
asm volatile ("ecall"); // switch back to machine mode (if not already)
test_fail();
}
 
 
1549,17 → 1576,15
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
tmp_b = 0;
goto_user_mode();
{
tmp_b = neorv32_cpu_load_unsigned_word(tmp_a); // load access -> should fail
asm volatile ("li %[da], 0xcafe0000 \n" // initialize destination register with known value
"lw %[da], 0(%[ad]) " // must not update destination register to to exception
: [da] "=r" (tmp_b) : [ad] "r" (tmp_a));
}
 
if (tmp_b != 0) {
PRINT_CRITICAL("%c[1m<SECURITY FAILURE> %c[0m\n", 27, 27);
}
 
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) {
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_L_ACCESS) &&
(tmp_b == 0xcafe0000)) { // destination register not altered
// switch back to machine mode (if not already)
asm volatile ("ecall");
 
1579,7 → 1604,7
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
 
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
neorv32_cpu_goto_user_mode();
goto_user_mode();
{
neorv32_cpu_store_unsigned_word(tmp_a, 0); // store access -> should fail
}
1774,9 → 1799,27
}
 
 
 
/**********************************************************************//**
* Simulation-based function to trigger CPU interrupts (MSI, MEI, FIRQ4..7).
* Switch from privilege mode MACHINE to privilege mode USER.
*
* @warning This function requires the U extension to be implemented.
**************************************************************************/
void __attribute__((naked)) goto_user_mode(void) {
 
// make sure to use NO registers in here! -> naked
 
asm volatile ("csrw mepc, ra \n" // move return address to mepc so we can return using "mret". also, we can now use ra as temp register
"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)));
}
 
 
/**********************************************************************//**
* Simulation-based function to trigger CPU interrupts (MSI, MEI).
*
* @param[in] sel IRQ select mask (bit positions according to #NEORV32_CSR_MIE_enum).
**************************************************************************/
void sim_irq_trigger(uint32_t sel) {
1793,7 → 1836,7
void global_trap_handler(void) {
 
// clear all pending FIRQs
neorv32_cpu_csr_write(CSR_MIP, -1);
neorv32_cpu_csr_write(CSR_MIP, 0);
 
// hack: always come back in MACHINE MODE
register uint32_t mask = (1<<CSR_MSTATUS_MPP_H) | (1<<CSR_MSTATUS_MPP_L);
1844,7 → 1887,7
* main function returns (called by crt0.S start-up code): Output minimal
* test report to physical UART
**************************************************************************/
int __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
 
// make sure sim mode is disabled and UARTs are actually enabled
NEORV32_UART0.CTRL |= (1 << UART_CTRL_EN);
1853,6 → 1896,4
 
// minimal result report
PRINT_CRITICAL("%u/%u\n", (uint32_t)return_code, (uint32_t)cnt_test);
 
return 0;
}

powered by: WebSVN 2.1.0

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