[docs] link dual-core section

This commit is contained in:
stnolting 2025-01-02 14:39:56 +01:00
parent b30b517234
commit e5b9218a82
4 changed files with 43 additions and 8 deletions

View file

@ -1,6 +1,10 @@
:sectnums:
=== Dual-Core Configuration
.Hardware Requirements
[IMPORTANT]
The SMP dual-core configuration requires the <<_core_local_interruptor_clint>> to be implemented.
Optionally, the CPU core can be implemented as **symmetric multiprocessing (SMP) dual-core** system.
This dual-core configuration is enabled by the `DUAL_CORE_EN` <<_processor_top_entity_generics, top generic>>.
When enabled, two _core complexes_ are implemented. Each core complex consists of a CPU core and optional
@ -41,6 +45,10 @@ cores share the same heap, `.data` and `.bss` sections.
| **Booting** | See next section <<_dual_core_boot>>.
|=======================
.Dual-Core Example
[TIP]
A simple dual-core example setup / test program can be found in `sw/example/demo_dual_core`.
==== Dual-Core Boot
@ -70,5 +78,5 @@ boundary.´
After that, the primary core triggers the _machine software interrupt_ of core 1 using the
<<_core_local_interruptor_clint>>. Core 1 wakes up from sleep mode, consumes the configuration structure and
finally starts executing at the provided entry point. When `neorv32_rte_smp_launch()` returns (with no error)
code the secondary core is online and running.
finally starts executing at the provided entry point. When `neorv32_rte_smp_launch()` returns (with no error
code) the secondary core is online and running.

View file

@ -3,7 +3,7 @@
:sectnums:
== NEORV32 Processor (SoC)
The NEORV32 Processor is based on the NEORV32 CPU. Together with common peripheral
The NEORV32 Processor is build around the <<_neorv32_central_processing_unit_cpu>>. Together with common peripheral
interfaces and embedded memories it provides a RISC-V-based full-scale microcontroller-like SoC platform.
.The NEORV32 Processor (Block Diagram)
@ -19,6 +19,7 @@ image::neorv32_processor.png[align=center]
**Key Features**
* _optional_ SMP <<_dual_core_configuration>>
* _optional_ processor-internal data and instruction memories (<<_data_memory_dmem,**DMEM**>>/<<_instruction_memory_imem,**IMEM**>>)
* _optional_ caches (<<_processor_internal_instruction_cache_icache,**I-CACHE**>>, <<_processor_internal_data_cache_dcache,**D-CACHE**>>,
<<_execute_in_place_module_xip,**XIP-CACHE**>>, <<_processor_external_bus_interface_xbus,**XBUS-CACHE**>>)
@ -162,7 +163,7 @@ to all inputs and output so the synthesis tool can insert an explicit IO (bounda
| `cfs_out_o` | 32 | out | - | custom CFS output signal conduit
5+^| **<<_smart_led_interface_neoled>>**
| `neoled_o` | 1 | out | - | asynchronous serial data output
5+^| **<<_core_local_interruptor_clint>**
5+^| **<<_core_local_interruptor_clint>>**
| `mtime_time_o` | 64 | out | - | CLINT.MTIMER system time output
5+^| **<<_external_interrupt_controller_xirq>>**
| `xirq_i` | 32 | in | `'L'` | external interrupt requests
@ -210,6 +211,8 @@ The generic type "`suv(x:y)`" is an abbreviation for "`std_ulogic_vector(x downt
| Name | Type | Default | Description
4+^| **<<_processor_clocking>>**
| `CLOCK_FREQUENCY` | natural | 0 | The clock frequency of the processor's `clk_i` input port in Hertz (Hz).
4+^| **<<_dual_core_configuration>>**
| `DUAL_CORE_EN` | boolean | false | Enable the SMP dual-core configuration.
4+^| **Core Identification**
| `JEDEC_ID` | suv(10:0) | "00000000000" | JEDEC ID; continuation codes plus vendor ID (passed to <<_mvendorid>> CSR and to the <<_debug_transport_module_dtm>>).
4+^| **<<_boot_configuration>>**
@ -520,6 +523,11 @@ The components of the processor's bus system infrastructure are located in `rtl/
[TIP]
See sections CPU <<_architecture>> and <<_bus_interface>> for more information regarding the CPU bus accesses.
.SMP Dual-Core Configuration
[TIP]
The dual-core configuration adds a second CPU core complex in parallel to the first one.
See section <<_dual_core_configuration>> for more information.
:sectnums:
==== Bus Gateway
@ -669,6 +677,10 @@ generic (see <<_processor_top_entity_generics>>).
| 2 | IMEM Image | Base of internal IMEM | Implement the processor-internal <<_instruction_memory_imem>> as pre-initialized ROM and boot from there.
|=======================
.Dual-Core Boot
[TIP]
For the SMPA dual-core CPU configuration boot procedure see section <<_dual_core_boot>>.
:sectnums:
==== Booting via Bootloader

View file

@ -15,6 +15,11 @@ RAM size of at least 256 bytes. Both constraints ensure that the bootloader can
configuration. However, the bootloader can recompiled with different capabilities. See the User Guide
https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader for more information.
.SMP Dual-Core Configuration
[NOTE]
For the SMP <<_dual_core_configuration>> only the primary core (core 0) will boot and execute the bootloader
while the secondary core (core 1) will be halted in sleep mode.
The NEORV32 bootloader (`sw/bootloader/bootloader.c`) provides an optional built-in firmware that
allows to upload new application executables at _any time_ without the need to re-synthesize the FPGA's bitstream.
A UART connection is used to provide a simple text-based user interface that allows to upload executables.

View file

@ -3,7 +3,8 @@
The NEORV32 software framework provides a minimal **runtime environment** (abbreviated "RTE") that takes care of a stable
and _safe_ execution environment by handling _all_ traps (exceptions & interrupts). The RTE simplifies trap handling
by wrapping the CPU's privileged architecture (i.e. trap-related CSRs) into a unified software API.
by wrapping the CPU's privileged architecture (i.e. trap-related CSRs and the actual execution of trap handlers)
into a unified software API.
Once initialized, the RTE provides <<_default_rte_trap_handlers>> that catch all possible traps. These
default handlers just output a message via UART to inform the user when a certain trap has been triggered. The
@ -33,9 +34,14 @@ just output a message via the *primary UART (UART0)* to inform the user that a t
handled by the actual application. After sending this message, the RTE tries to continue executing the actual program
by resolving the trap cause.
.Dual-Core Configuration
[NOTE]
The RTE also supports the SMP <<_dual_core_configuration>> as it provides core-individual internal trap management.
==== Using the RTE
.Machine-Mode Only
[IMPORTANT]
All provided RTE functions can be called only from machine-mode code.
@ -48,8 +54,10 @@ the RTE's setup function:
void neorv32_rte_setup(void);
----
.RTE Setup
[NOTE]
The RTE should be enabled right at the beginning of the application's `main` function.
The RTE should be enabled right at the beginning of the application's `main` function. For the SMP
<<_dual_core_configuration>> the RTE setup functions has to be called on each core individually.
[IMPORTANT]
It is recommended to not use the <<_mscratch>> CSR when using the RTE as this register is used to provide services
@ -149,8 +157,10 @@ RISC-V CLINT timer interrupt:
neorv32_rte_handler_uninstall(RTE_TRAP_MTI);
----
[TIP]
The current RTE configuration can be printed via UART0 via the `neorv32_rte_info` function.
.Dual-Core Configuration
[NOTE]
The RTE handler install/uninstall functions can be called on any core in the SMP <<_dual_core_configuration>>.
Internally, the functions will only access the core-specific management entries.
==== Default RTE Trap Handlers