<<<
:sectnums:
== General Software Framework Setup

To allow executables to be _actually executed_ on the NEORV32 Processor the configuration of the software framework
has to be aware to the hardware configuration. This guide focuses on the **memory configuration**. To enable
certain CPU ISA features refer to the <<_enabling_risc_v_cpu_extensions>> section.

This guide shows how to configure the linker script for a given hardware memory configuration. More information regarding the
linker script itself can be found in the according section of the data sheet: https://stnolting.github.io/neorv32/#_linker_script

[TIP]
If you have **not** changed the _default_ memory configuration in section <<_general_hardware_setup>>
you are already done and you can skip the rest of this section.

[NOTE]
Always keep the processor's https://stnolting.github.io/neorv32/#_address_space[Address Space] layout in mind
when modifying the linker script

There are two options to modify the default memory configuration of the linker script:

[start=1]
. <<_modifying_the_linker_script>>
. <<_overriding_the_default_configuration>> (recommended!)


:sectnums:
=== Modifying the Linker Script

This will modify the linker script _itself_.

[start=1]
. Open the NEORV32 linker script `sw/common/neorv32.ld` with a text editor. Right at the
beginning of this script you will find the `+++ NEORV32 memory configuration +++` configuration section:

.Cut-out of the linker script `neorv32.ld`
[source]
----
/* Default rom/ram (IMEM/DMEM) sizes */
__neorv32_rom_size = DEFINED(__neorv32_rom_size) ? __neorv32_rom_size : 2048M; <1>
__neorv32_ram_size = DEFINED(__neorv32_ram_size) ? __neorv32_ram_size : 8K; <2>

/* Default HEAP size (= 0; no heap at all) */
__neorv32_heap_size = DEFINED(__neorv32_heap_size) ? __neorv32_heap_size : 0; <3>

/* Default section base addresses - do not change this unless the hardware-defined address space layout is changed! */
__neorv32_rom_base = DEFINED(__neorv32_rom_base) ? __neorv32_rom_base : 0x00000000; /* = VHDL package's "ispace_base_c" */ <4>
__neorv32_ram_base = DEFINED(__neorv32_ram_base) ? __neorv32_ram_base : 0x80000000; /* = VHDL package's "dspace_base_c" */ <5>
----
<1> Default (max) size of the instruction memory address space (right-most value) (internal/external IMEM): 2048MB
<2> Default size of the data memory address space (right-most value) (internal/external DMEM): 8kB
<3> Default size of the HEAP (right-most value): 0kB
<4> Default base address of the instruction memory address space (right-most value): `0x00000000`
<5> Default base address of the data memory address space (right-most value): `0x80000000`

[start=2]
. Only the the `neorv32_ram_size` variable needs to modified! If you have changed the default DMEM (_MEM_INT_DMEM_SIZE_ generic)
size then change the right-most parameter (here: `8kB`) so it is equal to your DMEM hardware configuration. The `neorv32_rom_size`
does not need to be modified even if you have changed the default IMEM size.
For more information see https://stnolting.github.io/neorv32/#_linker_script

[start=3]
. Done! Save your changes and close the linker script.


:sectnums:
=== Overriding the Default Configuration

This will not change the default linker script at all. Hence, **this approach is recommended** as it allows to make
per-project memory configuration without changing the code base.

The RAM and ROM sizes from <<_modifying_the_linker_script>> (as well as the base addresses) can also be modified
by overriding the default values when invoking `make`. Therefore, the command needs to pass the according
values to the linker using the makefile's `USER_FLAGS` variable.

[TIP]
See section "Application Makefile" of the data sheet for more information regarding the default makefile variables:
https://stnolting.github.io/neorv32/#_application_makefile

.Example: override default RAM size while invoking make
[source, bash]
----
$ make USER_FLAGS+="-Wl,--defsym,__neorv32_rom_size=16k" clean_all exe
----

The `-Wl` will pass the following commands/flags to the linker. `--defsym` will define a symbol for the linker.
`neorv32_rom_size` is the variable that will be defined and `16k` is the value assigned to it (= 16*1024 bytes). As a result, this
command will set the RAM region to a size of 16kB.

[NOTE]
When using this approach the customized attributes have to be specified every time the makefile is invoked!
You can put the RAM/ROM override commands into the project's local makefile or define a simple shell script that defines
all the setup-related parameters (memory sizes, RISC-V ISA extensions, optimization goal, further tuning flags, etc.).
