<<<
:sectnums:
== Software Framework

The NEORV32 project comes with a complete software ecosystem called the "software framework" which
is based on the C-language RISC-V GCC port and consists of the following parts:

* <<_compiler_toolchain>>
* <<_core_libraries>>
* <<_system_view_description_file_svd>>
* <<_application_makefile>>
* <<_default_compiler_flags>>
* <<_linker_script>>
* <<_c_standard_library>>
* <<_start_up_code_crt0>>
* <<_executable_image_formats>>
* <<_neorv32_runtime_environment>>
* <<_bootloader>>

.Software Documentation
[TIP]
All core libraries and example programs are documented _in-code_ using **Doxygen**.
The API documentation is automatically built and deployed to GitHub pages:
https://stnolting.github.io/neorv32/sw/files.html.

.Example Programs
[TIP]
A collection of annotated example programs illustrating how to use certain NEORV32 functions
and peripheral/IO modules can be found in `sw/example`.


// ####################################################################################################################
:sectnums:
=== Compiler Toolchain

The toolchain for this project is based on the free and open RISC-V GCC-port. You can find the compiler sources and
build instructions in the official RISC-V GNU toolchain GitHub repository: https://github.com/riscv-collab/riscv-gnu-toolchain.

.Toolchain Installation
[TIP]
More information regarding the toolchain (building from scratch or downloading prebuilt ones) can be found in the
user guide section https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[Software Toolchain Setup].


<<<
// ####################################################################################################################
:sectnums:
=== Core Libraries

The NEORV32 project provides a set of pre-defined C libraries that allow an easy integration of the processor/CPU features
(also called "HAL" - _hardware abstraction layer_). All driver and runtime-related files are located in
`sw/lib`. These library files are automatically included and linked by adding the following include statement:

[source,c]
----
#include <neorv32.h> // NEORV32 HAL, core and runtime libraries
----

The NEORV32 HAL consists of the following files.

.NEORV32 Hardware Abstraction Layer File List
[cols="<3,<3,<6"]
[options="header",grid="rows"]
|=======================
| C source file       | C header file          | Description
| -                   | `neorv32.h`            | Main NEORV32 library file
| `neorv32_aux.c`     | `neorv32_aux.h`        | General auxiliary/helper function
| `neorv32_cfs.c`     | `neorv32_cfs.h`        | <<_custom_functions_subsystem_cfs>> HAL
| `neorv32_clint.c`   | `neorv32_clint.h`      | <<_core_local_interruptor_clint>> HAL
| `neorv32_cpu.c`     | `neorv32_cpu.h`        | <<_neorv32_central_processing_unit_cpu>> HAL
|                     | `neorv32_csr.h`        | <<_control_and_status_registers_csrs>> definitions
| `neorv32_cfu.c`     | `neorv32_cfu.h`        | <<_custom_functions_unit_cfu>> HAL
| `neorv32_dma.c`     | `neorv32_dma.h`        | <<_direct_memory_access_controller_dma>> HAL
| `neorv32_gpio.c`    | `neorv32_gpio.h`       | <<_general_purpose_input_and_output_port_gpio>> HAL
| `neorv32_gptmr.c`   | `neorv32_gptmr.h`      | <<_general_purpose_timer_gptmr>> HAL
| -                   | `neorv32_intrinsics.h` | Macros for intrinsics and custom instructions
| -                   | `neorv32_legacy.h`     | Legacy / backwards-compatibility wrappers (**do not use for new designs**)
| `neorv32_neoled.c`  | `neorv32_neoled.h`     | <<_smart_led_interface_neoled>> HAL
| `neorv32_onewire.c` | `neorv32_onewire.h`    | <<_one_wire_serial_interface_controller_onewire>> HAL
| `neorv32_pwm.c`     | `neorv32_pwm.h`        | <<_pulse_width_modulation_controller_pwm>> HAL
| `neorv32_rte.c`     | `neorv32_rte.h`        | <<_neorv32_runtime_environment>>
| `neorv32_sdi.c`     | `neorv32_sdi.h`        | <<_serial_data_interface_controller_sdi>> HAL
| `neorv32_slink.c`   | `neorv32_slink.h`      | <<_stream_link_interface_slink>> HAL
| `neorv32_smp.c`     | `neorv32_smp.h`        | HAL for the SMP <<_dual_core_configuration>>
| `neorv32_spi.c`     | `neorv32_spi.h`        | <<_serial_peripheral_interface_controller_spi>> HAL
|                     | `neorv32_sysinfo.h`    | <<_system_configuration_information_memory_sysinfo>> HAL
| `neorv32_tracer.c`  | `neorv32_tracer.h`     | <<_execution_trace_buffer_tracer>> HAL
| `neorv32_trng.c`    | `neorv32_trng.h`       | <<_true_random_number_generator_trng>> HAL
| `neorv32_twd.c`     | `neorv32_twd.h`        | <<_two_wire_serial_device_controller_twd>> HAL
| `neorv32_twi.c`     | `neorv32_twi.h`        | <<_two_wire_serial_interface_controller_twi>> HAL
| `neorv32_uart.c`    | `neorv32_uart.h`       | <<_primary_universal_asynchronous_receiver_and_transmitter_uart0>> and UART1 HAL
| `neorv32_wdt.c`     | `neorv32_wdt.h`        | <<_watchdog_timer_wdt>> HAL
| `neorv32_newlib.c`  | -                      | Platform-specific system calls for _newlib_
|=======================

.Doxygen API Documentation
[TIP]
The Doxygen-based documentation of all core libraries is available online at
https://stnolting.github.io/neorv32/sw/files.html.


<<<
// ####################################################################################################################
:sectnums:
=== System View Description File (SVD)

A CMSIS-SVD-compatible **System View Description (SVD)** file including all peripherals is available in `sw/svd`.


<<<
// ####################################################################################################################
:sectnums:
=== Application Makefile

Application compilation is based on a centralized GNU makefile (`sw/common/common.mk`). Each software project
(for example the ones in `sw/example` folder) should provide a local makefile that just includes the central makefile:

[source,makefile]
----
# Set path to NEORV32 root directory
NEORV32_HOME ?= ../../..
# Include the main NEORV32 makefile
include $(NEORV32_HOME)/sw/common/common.mk
----

Thus, the functionality of the central makefile (including all targets) becomes available for the project.
A project-local makefile should be used to define all setup-relevant configuration options instead of changing the
central makefile to keep the code base clean. Setting variables in the project-local makefile will override the default
configuration. Most example projects already provide a makefile that list all relevant configuration options.

The following example shows the configuration of a local Makefile:

[source,makefile]
----
# Override the default CPU ISA
MARCH = rv32imc_zicsr_zifencei

# Override the default RISC-V GCC prefix
RISCV_PREFIX ?= riscv-none-elf-

# Override default optimization goal
EFFORT = -Os

# Add extended debug symbols for Eclipse
USER_FLAGS += -ggdb -gdwarf-3

# Additional sources
APP_SRC += $(wildcard ./*.c)
APP_INC += -I .

# Adjust processor IMEM size and base address
USER_FLAGS += -Wl,--defsym,__neorv32_rom_size=16k
USER_FLAGS += -Wl,--defsym,__neorv32_rom_base=0x00000000

# Adjust processor DMEM size and base address
USER_FLAGS += -Wl,--defsym,__neorv32_ram_size=8k
USER_FLAGS += -Wl,--defsym,__neorv32_ram_base=0x80000000

# Adjust maximum heap size
USER_FLAGS += -Wl,--defsym,__neorv32_heap_size=2k

# Set path to NEORV32 root directory
NEORV32_HOME ?= ../../..

# Include the main NEORV32 makefile
include $(NEORV32_HOME)/sw/common/common.mk
----

.Setup of a New Project
[TIP]
When creating a new project, copy an existing project folder or at least the makefile to the new project folder.
It is recommended to create new projects also in `sw/example` to keep the file dependencies. However, these
dependencies can be manually configured via makefile variables if the new project is located somewhere else.
For more complex projects, it may be useful to use explicit `source` and `include` folders. See `sw/example/coremark` for an example.

:sectnums:
==== Makefile Targets

Invoking a project-local makefile (executing `make` or `make help`) will show the help menu that lists all
available targets as well as all variable including their _current_ setting.

[source,makefile]
----
neorv32/sw/example/hello_world$ make
NEORV32 Software Makefile
Find more information at https://github.com/stnolting/neorv32
Use make V=1 or set BUILD_VERBOSE to increase build verbosity

Targets:

  help          show this text
  check         check toolchain and list supported ISA extensions
  info          show project/makefile configuration
  gdb           start GNU debugging session
  asm           compile and generate <main.asm> assembly listing file for manual debugging
  elf           compile and generate <main.elf> ELF file
  exe           compile and generate <neorv32_exe.bin> executable image file for bootloader upload (includes a HEADER!)
  bin           compile and generate <neorv32_raw_exe.bin> executable memory image
  hex           compile and generate <neorv32_raw_exe.hex> executable memory image
  coe           compile and generate <neorv32_raw_exe.coe> executable memory image
  mem           compile and generate <neorv32_raw_exe.mem> executable memory image
  mif           compile and generate <neorv32_raw_exe.mif> executable memory image
  image         compile and generate VHDL IMEM application boot image <neorv32_application_image.vhd> in local folder
  install       compile, generate and install VHDL IMEM application boot image <neorv32_application_image.vhd>
  sim           in-console simulation using default/simple testbench and GHDL
  hdl_lists     regenerate HDL file-lists (*.f) in NEORV32_HOME/rtl
  all           exe + install + hex + bin + asm
  elf_info      show ELF layout info
  elf_sections  show ELF sections
  clean         clean up project home folder
  clean_all     clean up project home folder and image generator
  bl_image      compile and generate VHDL BOOTROM bootloader boot image <neorv32_bootloader_image.vhd> in local folder
  bootloader    compile, generate and install VHDL BOOTROM bootloader boot image <neorv32_bootloader_image.vhd>

Variables:

  BUILD_VERBOSE   Set to increase build verbosity: 0
  USER_FLAGS      Custom toolchain flags [append only]: "-ggdb -gdwarf-3 -Wl,--defsym,__neorv32_rom_size=16k -Wl,--defsym,__neorv32_ram_size=8k"
  USER_LIBS       Custom libraries [append only]: ""
  EFFORT          Optimization level: "-Os"
  MARCH           Machine architecture: "rv32i_zicsr_zifencei"
  MABI            Machine binary interface: "ilp32"
  APP_INC         C include folder(s) [append only]: "-I ."
  APP_SRC         C source folder(s) [append only]: "./main.c   "
  APP_OBJ         Object file(s) [append only]
  ASM_INC         ASM include folder(s) [append only]: "-I ."
  RISCV_PREFIX    Toolchain prefix: "riscv-none-elf-"
  NEORV32_HOME    NEORV32 home folder: "../../.."
  GDB_ARGS        GDB (connection) arguments: "-ex target extended-remote localhost:3333"
  GHDL_RUN_FLAGS  GHDL simulation run arguments: ""
----

.Build Artifacts
[NOTE]
All _intermediate_ build artifacts (like object files and binaries) will be places into a (new) project-local
folder named `build`. The _resulting_ build artifacts (like executable, the main ELF and all memory
initialization/image files) will be placed in the root project folder.

.Increse Verbosity
[TIP]
Use `make V=1` or set `BUILD_VERBOSE` in your environment to increase build verbosity.


:sectnums:
==== Default Compiler Flags

The central makefile uses specific compiler flags to tune the code to the NEORV32 hardware. Hence, these flags should not
be altered. However, experienced users can modify them to further tune compilation.

.Compiler Options (`CC_OPTS`)
[cols="<3,<9"]
[grid="none"]
|=======================
| `-Wall`               | Enable all compiler warnings.
| `-ffunction-sections` | Put functions in independent sections. This allows a code optimization as dead code can be easily removed.
| `-fdata-sections`     | Put data segment in independent sections. This allows a code optimization as unused data can be easily removed.
| `-nostartfiles`       | Do not use the default start code. Instead, the NEORV32-specific start-up code (`sw/common/crt0.S`) is used (pulled-in by the linker script).
| `-mno-fdiv`           | Use built-in software functions for floating-point divisions and square roots (since the according instructions are not supported yet).
| `-mstrict-align`      | Unaligned memory accesses cannot be resolved by the hardware and require emulation.
| `-mbranch-cost=10`    | Branching costs a lot of cycles.
| `-Wl,--gc-sections`   | Make the linker perform dead code elimination.
| `-ffp-contract=off`   | Disable floating-point expression contraction (fused multiply-add/sub; not supported by the NEORV32 FPU).
| `-g`                  | Add (simple) debug information.
|=======================

.Linker Libraries (`LD_LIBS`)
[cols="<2,<9"]
[grid="none"]
|=======================
| `-lm`   | Include/link with `math.h`.
| `-lc`   | Search for the standard C library when linking.
| `-lgcc` | Make sure we have no unresolved references to internal GCC library subroutines.
|=======================

.Advanced Debug Symbols
[IMPORTANT]
By default, only "simple" symbols are added to the ELF (`-g`). Extended debug flags (e.g. for Eclipse) can be added
using the `USER_FLAGS` variable (e.g. `USER_FLAGS += -ggdb -gdwarf-3`). Note that other debug flags may be required
depending of the GCC/GDB version


<<<
// ####################################################################################################################
:sectnums:
=== Linker Script

The NEORV32-specific linker script (`sw/common/neorv32.ld`) is used to link the compiled sources according to the
processor's <<_address_space>>). For the final executable, only two memory segments are required:

.Linker script - Memory Segments
[cols="<2,<8"]
[options="header",grid="rows"]
|=======================
| Memory section  | Description
| `rom`           | Instruction memory address space (processor-internal <<_instruction_memory_imem>> and/or external memory)
| `ram`           | Data memory address space (processor-internal <<_data_memory_dmem>> and/or external memory)
|=======================

These two sections are configured by several variables defined in the linker script and exposed to the build
framework (aka the makefile). Those variable allow to customized the RAM/ROM sizes and base addresses. Additionally,
a certain amount of the RAM can be reserved for the software-managed heap (see <<_ram_layout>>).

.Linker script - Configuration
[cols="<2,<7,^1"]
[options="header",grid="rows"]
|=======================
| Memory section        | Description                                    | Default
| `__neorv32_rom_size`  | "ROM" size (instruction memory / IMEM)         | 16kB
| `__neorv32_ram_size`  | "RAM" size (data memory / DMEM)                | 8kB
| `__neorv32_rom_base`  | "ROM" base address (instruction memory / IMEM) | `0x00000000`
| `__neorv32_ram_base`  | "RAM" base address (data memory / DMEM)        | `0x80000000`
| `__neorv32_heap_size` | Maximum heap size; part of the "RAM"           | 0kB
|=======================

Each variable provides a default value (e.g. "16K" for the instruction memory /ROM /IMEM size). These defaults can
be overridden by setup-specific values to take the user-defined processor configuration into account (e.g. a different IMEM
size). The `USER_FLAGS` variable provided by the <<_application_makefile>> can also be used to customize the memory
configuration. For example, the following line can be added to a project-specific local makefile to adjust the memory
sizes:

.Overriding Default Memory Sizes (configuring 64kB IMEM and 32kB DMEM)
[source, makefile]
----
USER_FLAGS += "-Wl,--defsym,__neorv32_rom_size=64k -Wl,--defsym,__neorv32_ram_size=32k"
----

.Memory Configuration Constraints
[IMPORTANT]
Memory sizes have to be a multiple of 4 bytes. Memory base addresses have to be 32-bit-aligned.


:sectnums:
==== RAM Layout

The default NEORV32 linker script uses the defined RAM (**DMEM**) size to map several sections.
Note that depending on the application some sections might have zero size.

.Default RAM Layout
[source]
----
End of RAM
+------------------------------+
|             Stack            |
+------------------------------+
.     stack grows downwards    .
.                              .
.                              .
.      heap grows upwards      .
+------------------------------+
|   Dynamic memory (".heap")   |
+------------------------------+
| Uninitialized data (".bss")  |
+------------------------------+
|  Initialized data (".data")  |
+------------------------------+
Start of RAM
----

[start=1]
. **Initialized data (`.data`)**: The data section is placed right at the beginning of the RAM. For example, this
contains _explicitly initialized_ global variables which are initialized by the <<_start_up_code_crt0>>.
. **Non-initialized data (`.bss`)**: This dynamic data section contains data like global variables
_without explicit initialization_. This memory section is cleared by the <<_start_up_code_crt0>>.
. **Heap (`.heap`)**: The heap is used for dynamic memory that is managed by functions like `malloc()` and `free()`.
The heap grows upwards. This section is not initialized at all.
. **Stack**: The stack starts at the end of the RAM at the last 16-byte aligned address. According to the RISC-V ABI / calling
convention the stack is 128-bit-aligned before procedure entry. The stack grows downwards.

.Heap Size
[IMPORTANT]
The maximum size of the heap is defined by the `__neorv32_heap_size` variable. This variable has to be
**explicitly defined** in order to define a heap size (and to use dynamic memory allocation at all).

.Heap-Stack Collision
[WARNING]
Take care when using dynamic memory to avoid collision of the heap and stack memory areas. There is no compile-time
protection mechanism available as the actual heap and stack size are defined by _runtime_ data.
The <<_smpmp_isa_extension,physical memory protection>> extension can be used to implement a guarding mechanism.


:sectnums:
==== ROM Layout

The default NEORV32 linker script uses the defined ROM (**IMEM**) size to map several sections.
Note that depending on the application some sections might have zero size.

.Default ROM Layout
[source]
----
End of ROM
+------------------------------+
|   Initial data for ".data"   |
+------------------------------+
|  Read-only data (".rodata")  |
+------------------------------+
|    Program code (".text")    |
+------------------------------+
Start of ROM
----

[start=1]
. **Program code (`.text`)**: This section contains the actual instructions of the program.
. **Read-only data (`.rodata`)**: Read-only data, for example for constants and strings.
. **Heap (`.heap`)**: Initialization data that is copied at runtime to the RAM's `data` section by by the <<_start_up_code_crt0>>.

.Binary Executable Image
[IMPORTANT]
The main <<_application_makefile>> extracts the `.text`, `.rodata`, and `.data` sections from the final ELF
and concatenates them in order to build the final binary executable image (`main.bin`). Once placed in memory,
this image can be executed right away. Furthermore, this image is used by the image generator auxiliary tool
to generate different <<_executable_image_formats>>.


<<<
// ####################################################################################################################
:sectnums:
=== C Standard Library

The default software framework relies on **newlib** as default C standard library. Newlib provides hooks for common
"system calls" (like file handling and standard input/output) that are used by other C libraries like `stdio`.
These hooks are available in `sw/lib/source/newlib.c` and were adapted for the NEORV32 processor.

.Standard Input/Output Streams / Consoles
[NOTE]
The <<_primary_universal_asynchronous_receiver_and_transmitter_uart0, UART0>>
is used to implement all the standard input, output and error consoles (`STDIN` = file number 0, `STDOUT` = file
number 1, `STDERR` = file number 2). All other input/output streams (other file number than 0,1,2) are redirected
to <<_secondary_universal_asynchronous_receiver_and_transmitter_uart1, UART1>>.

.Constructors and Destructors
[NOTE]
Constructors and destructors for plain C code or for C++ applications are supported by the software framework.
See `sw/example/hello_cpp` for a minimal example. Note that constructor and destructors are only executed
by core 0 (primary core) in the SMP <<_dual_core_configuration>>.

.Newlib Test/Demo Program
[TIP]
A simple test and demo program that uses some of newlib's system functions (like `malloc`/`free` and `read`/`write`)
is available in `sw/example/demo_newlib`.

.Executing System Functions on a Host Computer
[TIP]
The NEORV32 on-chip debugger supports <<_semihosting>> which allow to use the input/output facilities on a host computer.


<<<
// ####################################################################################################################
:sectnums:
=== Start-Up Code (crt0)

The CPU and also the processor require a minimal start-up and initialization code to bring the hardware into an
operational state. Furthermore, the C runtime requires an initialization before compiled code can be executed.
This setup is done by the start-up code (`sw/common/crt0.S`) which is automatically linked with _every_ application
program and gets mapped before the actual application code so it gets executed right after boot.

The `crt0.S` start-up performs the following operations:

[start=1]
. Setup the stack pointer and the global pointer according to the <<_ram_layout>> provided by the <<_linker_script>> symbols.
. Initialize <<_mstatus>> CSR disabling machine-level interrupts.
. Install an endless loop as trap handler to <<_mtvec>> CSR: the core will halt if any trap occurs.
. Clear <<_mie>> CSR disabling all interrupt sources.
. Initialize all integer register `x1` - `x31` (only `x1` - `x15` if the `E` CPU extension is enabled).
. If the executing CPU core is not core 0, an SMP-specific code is executed and the CPU is halted in sleep mode. See section <<_dual_core_boot>> for more information.
. Setup `.data` section to configure initialized variables.
. Clear the `.bss` section.
. Call constructors (if there are any).
. Call the application's `main()` function (with no arguments; `argc` = `argv` = 0).
. If `main()` returns:
** All interrupt sources are disabled by clearing <<_mie>> CSR.
** The return value of `main()` is copied to the <<_mscratch>> CSR to allow inspection by the debugger.
** The core will halt if any trap occurs.
** Call all _destructors_ (if there are any).
** Execute an `ebreak` instruction to enter debug mode if an external debugger is connected; the core will just halt if this fails.
** The CPU halts: enter sleep mode executing the `wfi` instruction in an endless loop.


<<<
// ####################################################################################################################
:sectnums:
=== Executable Image Formats

The binary executable image (see <<_rom_layout>>) is further processed by the NEORV32 image generator (`sw/image_gen`)
to generate a final executable file. The image generator can generate several types of executable file formats selected
by a flag when calling the generator. **Note that all these options are managed by the makefile (see <<_makefile_targets>>).**

[cols="<2,<8"]
[grid="none"]
|=======================
| `app_bin` | Generates an executable binary file (including a bootloader header) for upload via the bootloader.
| `app_vhd` | Generates an executable VHDL memory initialization image for the processor-internal IMEM.
| `bld_vhd` | Generates an executable VHDL memory initialization image for the processor-internal BOOT ROM.
| `raw_hex` | Generates a raw 8x ASCII hex-char file for custom purpose.
| `raw_bin` | Generates a raw binary file for custom purpose.
| `raw_coe` | Generates a raw COE file for FPGA memory initialization.
| `raw_mem` | Generates a raw MEM file for FPGA memory initialization.
| `raw_mif` | Generates a raw MIF file for FPGA memory initialization.
|=======================

.Image Generator Compilation
[NOTE]
The sources of the image generator are automatically compiled when invoking the makefile
(requiring a _native_ GCC installation).

.Executable Header
[NOTE]
For the `app_bin` option the image generator adds a small header to the executable. This header is required by the
<<_bootloader>> to identify and manage the executable. The header consists of three 32-bit words located right
at the beginning of the file. The first word of the executable is the signature word and is always `0xB007C0DE`.
Based on this word the bootloader can identify a valid image file. The next word represents the size in bytes of the
actual program image in bytes. A simple complement checksum of the actual program image is given by the third word.
This provides a simple protection against data transmission or storage errors.
**Note that this executable format cannot be used for _direct_ execution.**

.VHDL Memory Initialization Files
[NOTE]
The generated VHDL images are plain VHDL packages providing program data as constant array.
Note that this array is always extended to a power of 2. Unused elements are set to zero.

Optionally, the NEORV32 image generator can also be used stand-alone:

[source,bash]
----
neorv32/sw/image_gen$ ./image_gen
NEORV32 executable image generator

Usage:    image_gen [options]
Example:  image_gen -i main.bin -o main_exe.bin -t app_bin

Options:
  -h             Show this help text and exit
  -i file_name   Input binary file name; mandatory
  -o file_name   Output file name; mandatory
  -t type        Type of image to generate; default is 'app_bin'

Image type:
  app_bin   Application executable for bootloader upload (binary file with header)
  app_vhd   Application memory image (IMEM VHDL package file)
  bld_vhd   Bootloader memory image (BOOTROM VHDL package file)
  raw_hex   ASCII hex file (raw executable)
  raw_bin   Binary file (raw executable)
  raw_coe   COE file (raw executable)
  raw_mem   MEM file (raw executable)
  raw_mif   MIF file (raw executable)
----


<<<
// ####################################################################################################################

include::software_bootloader.adoc[]


<<<
// ####################################################################################################################

include::software_rte.adoc[]
