Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minor software framework cleanups and optimizations #940

Merged
merged 11 commits into from
Jul 5, 2024
2 changes: 1 addition & 1 deletion docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ To benchmark a certain processor configuration for its setup-specific CPI value
The `A` ISA extension adds instructions and mechanisms for atomic memory access operations. Note that the NEORV32 `A`
only includes the _load-reservate_ (`lr.w`) and _store-conditional_ (`sc.w`) instructions - the remaining read-modify-write
instructions (like `amoswap`) are **not supported**. However, these missing instructions can be emulated using the
LR and SC operations.
LR and SC operations (quote from the RISC-V spec.: "_Any AMO can be emulated by an LR/SC pair._").

.AMO Emulation
[NOTE]
Expand Down
10 changes: 5 additions & 5 deletions docs/datasheet/soc_gpio.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[cols="<3,<3,<4"]
[frame="topbot",grid="none"]
|=======================
| Hardware source files: | neorv32_gpio.vhd |
| Hardware source files: | neorv32_gpio.vhd |
| Software driver files: | neorv32_gpio.c |
| | neorv32_gpio.h |
| Top entity ports: | `gpio_o` | 64-bit parallel output port
Expand Down Expand Up @@ -37,8 +37,8 @@ be performed within a single clock cycle.
[options="header",grid="rows"]
|=======================
| Address | Name [C] | Bit(s) | R/W | Function
| `0xfffffc00` | `INPUT_LO` | 31:0 | r/- | parallel input port pins 31:0
| `0xfffffc04` | `INPUT_HI` | 31:0 | r/- | parallel input port pins 63:32
| `0xfffffc08` | `OUTPUT_LO` | 31:0 | r/w | parallel output port pins 31:0
| `0xfffffc0c` | `OUTPUT_HI` | 31:0 | r/w | parallel output port pins 63:32
| `0xfffffc00` | `INPUT[0]` | 31:0 | r/- | parallel input port pins 31:0
| `0xfffffc04` | `INPUT[1]` | 31:0 | r/- | parallel input port pins 63:32
| `0xfffffc08` | `OUTPUT[0]` | 31:0 | r/w | parallel output port pins 31:0
| `0xfffffc0c` | `OUTPUT[1]` | 31:0 | r/w | parallel output port pins 63:32
|=======================
1 change: 0 additions & 1 deletion sw/bootloader/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

/**
* @file bootloader.c
* @author Stephan Nolting
* @brief Default NEORV32 bootloader.
*/

Expand Down
11 changes: 7 additions & 4 deletions sw/common/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,23 @@ __crt0_call_constructors_loop_end:
__crt0_main_entry:
addi x10, zero, 0 // x10 = a0 = argc = 0
addi x11, zero, 0 // x11 = a1 = argv = 0
jal x1, main // call actual app's main function
jal x1, main // call actual main function

__crt0_main_exit: // main's "return" and "exit" will arrive here
csrw mie, zero // disable all interrupt sources
csrw mscratch, a0 // backup main's return code to mscratch (for debugger)
csrw mscratch, a0 // backup main's return code to mscratch (for debugger or destructors)



// ************************************************************************************************
// Call destructors
// ************************************************************************************************
#ifndef MAKE_BOOTLOADER // destructors are not supported for bootloader
__crt0_call_destructors:
la x8, __fini_array_start
la x9, __fini_array_end
la x8, __crt0_trap_handler // use the crt0 trap handler if there are exceptions in the destructors
csrw mtvec, x8
la x8, __fini_array_start
la x9, __fini_array_end

__crt0_call_destructors_loop:
bge x8, x9, __crt0_call_destructors_loop_end
Expand Down
4 changes: 2 additions & 2 deletions sw/example/atomic_test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ int main() {

#else

#warning Program HAS NOT BEEN COMPILED as RISC-V A ISA extensions is not enabled!
neorv32_uart0_printf("\nProgram HAS NOT BEEN COMPILED as RISC-V A ISA extensions is not enabled!\n");
#warning Program HAS NOT BEEN COMPILED since RISC-V 'A' ISA extension is not enabled!
neorv32_uart0_printf("\nProgram HAS NOT BEEN COMPILED since RISC-V 'A' ISA extension is not enabled!\n");

#endif

Expand Down
17 changes: 14 additions & 3 deletions sw/example/demo_newlib/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
/**@}*/


/**********************************************************************//**
* @name Print main's return code using a destructor
**************************************************************************/
void __attribute__((destructor)) main_destructor_test(void) {

int32_t main_ret = (int32_t)neorv32_cpu_csr_read(CSR_MSCRATCH);
neorv32_uart0_printf("\nDestructor: main terminated with return/exit code %i.\n", main_ret);
}


/**********************************************************************//**
* @name Max heap size (from linker script's "__neorv32_heap_size")
**************************************************************************/
Expand Down Expand Up @@ -111,10 +121,11 @@ int main() {
// NOTE: exit is highly over-sized as it also includes clean-up functions (destructors), which
// are not required for bare-metal or RTOS applications... better use the simple 'return' or even better
// make sure main never returns. Anyway, let's check if 'exit' works.
neorv32_uart0_printf("terminating via <exit> ");
exit(0);
int exit_code = 7;
neorv32_uart0_printf("<exit> terminating by exit(%i)...\n", exit_code);
exit(exit_code);

// should never be reached
neorv32_uart0_printf("failed!n");
neorv32_uart0_printf("exit failed!\n");
return 0;
}
16 changes: 8 additions & 8 deletions sw/example/processor_check/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1898,12 +1898,12 @@ int main() {
amo_var = 0x00cafe00; // initialize
asm volatile ("fence"); // flush/reload d-cache

tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&amo_var);
tmp_a = neorv32_cpu_amolr((uint32_t)&amo_var);
amo_var = 0x10cafe00; // break reservation
asm volatile ("fence"); // flush/reload d-cache
tmp_b = neorv32_cpu_store_conditional_word((uint32_t)&amo_var, 0xaaaaaaaa);
tmp_b = (tmp_b << 1) | neorv32_cpu_store_conditional_word((uint32_t)&amo_var, 0xcccccccc); // another SC: must fail
tmp_b = (tmp_b << 1) | neorv32_cpu_store_conditional_word((uint32_t)ADDR_UNREACHABLE, 0); // another SC: must fail; no bus exception!
tmp_b = neorv32_cpu_amosc((uint32_t)&amo_var, 0xaaaaaaaa);
tmp_b = (tmp_b << 1) | neorv32_cpu_amosc((uint32_t)&amo_var, 0xcccccccc); // another SC: must fail
tmp_b = (tmp_b << 1) | neorv32_cpu_amosc((uint32_t)ADDR_UNREACHABLE, 0); // another SC: must fail; no bus exception!
asm volatile ("fence"); // flush/reload d-cache

if ((tmp_a == 0x00cafe00) && // correct LR.W result
Expand Down Expand Up @@ -1939,12 +1939,12 @@ int main() {
amo_var = 0x00abba00; // initialize
asm volatile ("fence"); // flush/reload d-cache

tmp_a = neorv32_cpu_load_reservate_word((uint32_t)&amo_var);
tmp_a = neorv32_cpu_amolr((uint32_t)&amo_var);
asm volatile ("fence"); // flush/reload d-cache
neorv32_cpu_load_unsigned_word((uint32_t)&amo_var); // dummy read, must not alter reservation set state
tmp_b = neorv32_cpu_store_conditional_word((uint32_t)&amo_var, 0xcccccccc);
tmp_b = (tmp_b << 1) | neorv32_cpu_store_conditional_word((uint32_t)&amo_var, 0xcccccccc); // another SC: must fail
tmp_b = (tmp_b << 1) | neorv32_cpu_store_conditional_word((uint32_t)ADDR_UNREACHABLE, 0); // another SC: must fail; no bus exception!
tmp_b = neorv32_cpu_amosc((uint32_t)&amo_var, 0xcccccccc);
tmp_b = (tmp_b << 1) | neorv32_cpu_amosc((uint32_t)&amo_var, 0xcccccccc); // another SC: must fail
tmp_b = (tmp_b << 1) | neorv32_cpu_amosc((uint32_t)ADDR_UNREACHABLE, 0); // another SC: must fail; no bus exception!
asm volatile ("fence"); // flush/reload d-cache

if ((tmp_a == 0x00abba00) && // correct LR.W result
Expand Down
47 changes: 35 additions & 12 deletions sw/lib/include/neorv32_aux.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,50 @@


/**********************************************************************//**
* Processor clock prescaler select
* Processor clock prescaler select (relative to processor's main clock)
**************************************************************************/
/**@{*/
enum NEORV32_CLOCK_PRSC_enum {
CLK_PRSC_2 = 0, /**< CPU_CLK (from clk_i top signal) / 2 */
CLK_PRSC_4 = 1, /**< CPU_CLK (from clk_i top signal) / 4 */
CLK_PRSC_8 = 2, /**< CPU_CLK (from clk_i top signal) / 8 */
CLK_PRSC_64 = 3, /**< CPU_CLK (from clk_i top signal) / 64 */
CLK_PRSC_128 = 4, /**< CPU_CLK (from clk_i top signal) / 128 */
CLK_PRSC_1024 = 5, /**< CPU_CLK (from clk_i top signal) / 1024 */
CLK_PRSC_2048 = 6, /**< CPU_CLK (from clk_i top signal) / 2048 */
CLK_PRSC_4096 = 7 /**< CPU_CLK (from clk_i top signal) / 4096 */
CLK_PRSC_2 = 0, /**< CPU_CLK / 2 */
CLK_PRSC_4 = 1, /**< CPU_CLK / 4 */
CLK_PRSC_8 = 2, /**< CPU_CLK / 8 */
CLK_PRSC_64 = 3, /**< CPU_CLK / 64 */
CLK_PRSC_128 = 4, /**< CPU_CLK / 128 */
CLK_PRSC_1024 = 5, /**< CPU_CLK / 1024 */
CLK_PRSC_2048 = 6, /**< CPU_CLK / 2048 */
CLK_PRSC_4096 = 7 /**< CPU_CLK / 4096 */
};
/**@}*/


/**********************************************************************//**
* @name Date and time struct
* @name Subword-access helper
**************************************************************************/
/**@{*/
/** @name 64-bit */
typedef union {
uint64_t uint64;
uint32_t uint32[sizeof(uint64_t)/sizeof(uint32_t)];
uint16_t uint16[sizeof(uint64_t)/sizeof(uint16_t)];
uint8_t uint8[ sizeof(uint64_t)/sizeof(uint8_t)];
} subwords64_t;
/** @name 32-bit */
typedef union {
uint32_t uint32[sizeof(uint32_t)/sizeof(uint32_t)];
uint16_t uint16[sizeof(uint32_t)/sizeof(uint16_t)];
uint8_t uint8[ sizeof(uint32_t)/sizeof(uint8_t)];
} subwords32_t;
/** @name 16-bit */
typedef union {
uint16_t uint16[sizeof(uint16_t)/sizeof(uint16_t)];
uint8_t uint8[ sizeof(uint16_t)/sizeof(uint8_t)];
} subwords16_t;
/**@}*/


/**********************************************************************//**
* @name Date and time struct
**************************************************************************/
typedef struct {
uint16_t year; /**< current year (absolute) */
uint8_t month; /**< 1..12 */
Expand All @@ -57,11 +81,10 @@ typedef struct {
uint8_t minutes; /**< 0..59 */
uint8_t seconds; /**< 0..59 */
} date_t;
/**@}*/


/**********************************************************************//**
* @name Prototypes
* @name AUX prototypes
**************************************************************************/
/**@{*/
uint64_t neorv32_aux_date2unixtime(date_t* date);
Expand Down
Loading