Skip to content

Commit

Permalink
Merge pull request #158 from stnolting/rework_low_level_hw_access
Browse files Browse the repository at this point in the history
⚠️ rework of low-level hardware access
  • Loading branch information
stnolting authored Sep 18, 2021
2 parents e5952d5 + ad07638 commit 9d3fc2e
Show file tree
Hide file tree
Showing 49 changed files with 2,507 additions and 2,188 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ defined by the `hw_version_c` constant in the main VHDL package file [`rtl/core/

| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 18.09.2021 | 1.6.0.4 | :warning: :warning: **major change** modified low-level hardware access (memory-mapped registers) [PR #158](https://github.com/stnolting/neorv32/pull/158): now using `struct`-based access concept (IO module = `struct`, interface registers = members of struct) instead of `#define` single-pointers (inspired by https://blog.feabhas.com/2019/01/peripheral-register-access-using-c-structs-part-1/), format: `NEORV32_<module_name>.<register_name>`; renamed all control registers and bits from `*CT*` to `*CTRL*`; added `sw/lib/include/neorv32_legacy.h` compatibility layer (maps deprecated "defines" to according struct registers, provides old control register/bit names, _do not use for new designs!_) |
| 16.09.2021 | 1.6.0.3 | :bug: fixed another missing IRQ signal connection (NMI) in `system_integration` wrappers |
| 15.09.2021 | 1.6.0.2 | :warning: **split** processor-internal memory VHDL sources (IMEM and DMEM) into separated files ([#151](https://github.com/stnolting/neorv32/pull/151)): entity-only (`rtl/core/neorv32_*mem.entity.vhd`) and _default_ architecture-only (`rtl/core/mem/neorv32_*mem.default.vhd`); allows easy replacement by optimized platform-specific architectures |
| 13.09.2021 | 1.6.0.1 | :bug: fixed missing IRQ signal assignments (MSW and XIRQ) in AXI4-lite top wrapper |
Expand Down
2 changes: 1 addition & 1 deletion docs/datasheet/cpu.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ Volume II: Privileged Architecture_, which are available in the projects `docs/r

[TIP]
The CPU can discover available ISA extensions via the <<_misa>> CSR and the
_SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register
`CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register
or by executing an instruction and checking for an _illegal instruction exception_.

[NOTE]
Expand Down
8 changes: 4 additions & 4 deletions docs/datasheet/cpu_csr.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ CSR is simply ignored and will NOT cause an illegal instruction exception.

[TIP]
Information regarding the implemented RISC-V `Z*` _sub-extensions_ (like `Zicsr` or `Zfinx`) can be found
in the _SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
in the `CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.


:sectnums!:
Expand Down Expand Up @@ -508,16 +508,16 @@ configuration with <<_cpu_cnt_width>> less than 64 is not RISC-V compliant.
[IMPORTANT]
If _CPU_CNT_WIDTH_ is less than 64 (the default value) and greater than or equal 32, the according
MSBs of `[m]cycleh` and `[m]instreth` are read-only and always read as zero. This configuration
will also set the _SYSINFO_CPU_ZXSCNT_ flag in the _SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register. +
will also set the _SYSINFO_CPU_ZXSCNT_ flag in the `CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register. +
+
If _CPU_CNT_WIDTH_ is less than 32 and greater than 0, the `[m]cycleh` and `[m]instreth` do not
exist and any access will raise an illegal instruction exception. Furthermore, the according MSBs of
`[m]cycle` and `[m]instret` are read-only and always read as zero. This configuration will also
set the _SYSINFO_CPU_ZXSCNT_ flag in the _SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register. +
set the _SYSINFO_CPU_ZXSCNT_ flag in the `CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register. +
+
If _CPU_CNT_WIDTH_ is 0, <<_cycleh>> and <<_instreth>> / <<_mcycleh>> and <<_minstreth>> do not
exist and any access will raise an illegal instruction exception. This configuration will also set the
_SYSINFO_CPU_ZXNOCNT_ flag in the _SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
_SYSINFO_CPU_ZXNOCNT_ flag in the `CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.


:sectnums!:
Expand Down
29 changes: 22 additions & 7 deletions docs/datasheet/soc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ https://stnolting.github.io/neorv32/ug/#_application_specific_processor_configur

[TIP]
Privileged software can determine the actual CPU and processor configuration via the `misa` and the
i_SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
<<_system_configuration_information_memory_sysinfo, SYSINFO>> registers.

[NOTE]
If optional modules (like CPU extensions or peripheral devices) are *not enabled* the according circuitry
Expand Down Expand Up @@ -432,7 +432,7 @@ See section <<_pmp_physical_memory_protection>> for more information.
| **PMP_NUM_REGIONS** | _natural_ | 0
3+| Total number of implemented protections regions (0..64). If this generics is zero no physical memory
protection logic will be implemented at all. Setting <<_pmp_num_regions>>_ > 0 will set the _SYSINFO_CPU_PMP_ flag
in the _SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
in the `CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
|======


Expand Down Expand Up @@ -463,7 +463,7 @@ See section <<_hpm_hardware_performance_monitors>> for more information.
| **HPM_NUM_CNTS** | _natural_ | 0
3+| Total number of implemented hardware performance monitor counters (0..29). If this generics is zero, no
hardware performance monitor logic will be implemented at all. Setting <<_hpm_num_cnts>> > 0 will set the _SYSINFO_CPU_HPM_ flag
in the _SYSINFO_CPU_ <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
in the `CPU` <<_system_configuration_information_memory_sysinfo, SYSINFO>> register.
|======


Expand Down Expand Up @@ -1312,6 +1312,11 @@ address _0xFFFFFE00_. A region of 512 bytes is reserved for this devices. Hence,
accessed using a memory-mapped scheme. A special linker script as well as the NEORV32 core software
library abstract the specific memory layout for the user.

[IMPORTANT]
The base address of each component/module has to be aligned to the
total size of the module's occupied address space! The occupied address space
has to be a power of two (minimum 4 bytes)! Address spaces must not overlap!

[IMPORTANT]
When accessing an IO device that hast not been implemented (via the according _IO_x_EN_ generic), a
load/store access fault exception is triggered.
Expand All @@ -1335,11 +1340,21 @@ application start-up code `crt0.S`.
**Nomenclature for the Peripheral / IO Devices Listing**

Each peripheral device chapter features a register map showing accessible control and data registers of the
according device including the implemented control and status bits. You can directly interact with these
registers/bits via the provided _C-code defines_. These defines are set in the main processor core library
include file `sw/lib/include/neorv32.h`. The registers and/or register bits, which can be accessed
directly using plain C-code, are marked with a "[C]".
according device including the implemented control and status bits. C-language code can directly interact with these
registers via pre-defined `struct`. Each IO/peripheral module provides a unique `struct`. All accessible
interface registers of this module are defined as members of this `struct`. The pre-defined `struct` are defined int the
main processor core library include file `sw/lib/include/neorv32.h`.

The naming scheme of these low-level hardware access structs is `NEORV32_<module_name>.<register_name>`.

.Low-level hardware access example in C using the pre-defined `struct`
[source,c]
----
// Read from SYSINFO "CLK" register
uint32_t temp = NEORV32_SYSINFO.CLK;
----

The registers and/or register bits, which can be accessed directly using plain C-code, are marked with a "[C]".
Not all registers or register bits can be arbitrarily read/written. The following read/write access types are
available:

Expand Down
18 changes: 9 additions & 9 deletions docs/datasheet/soc_cfs.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The custom functions subsystem can be used to implement application-specific use
custom hardware accelerators via the external memory interface, the CFS provide a convenient and low-latency
extension and customization option.

The CFS provides up to 32x 32-bit memory-mapped registers (see register map table below). The actual
The CFS provides up to 32x 32-bit memory-mapped registers `REG` (see register map table below). The actual
functionality of these register has to be defined by the hardware designer.

[INFO]
Expand All @@ -39,8 +39,8 @@ register map table below). Note that all interface registers provide 32-bit acce
[source,c]
----
// C-code CFS usage example
CFS_REG_0 = (uint32_t)some_data_array(i); // write to CFS register 0
uint32_t temp = CFS_REG_20; // read from CFS register 20
NEORV32_CFS.REG[0] = (uint32_t)some_data_array(i); // write to CFS register 0
uint32_t temp = NEORV32_CFS.REG[20]; // read from CFS register 20
----

**CFS Interrupt**
Expand All @@ -63,14 +63,14 @@ generic (default = 32-bit). The size of the output signal conduit `cfs_out_o` is
_IO_CFS_OUT_SIZE_ configuration generic (default = 32-bit). If the custom function subsystem is not implemented
(_IO_CFS_EN_ = false) the `cfs_out_o` signal is tied to all-zero.

.CFS register map
.CFS register map (`struct NEORV32_CFS`)
[cols="^4,<5,^2,^3,<14"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bit(s) | R/W | Function
| `0xfffffe00` | _CFS_REG_0_ |`31:0` | (r)/(w) | custom CFS interface register 0
| `0xfffffe04` | _CFS_REG_1_ |`31:0` | (r)/(w) | custom CFS interface register 1
| ... | ... |`31:0` | (r)/(w) | ...
| `0xfffffe78` | _CFS_REG_30_ |`31:0` | (r)/(w) | custom CFS interface register 30
| `0xfffffe7c` | _CFS_REG_31_ |`31:0` | (r)/(w) | custom CFS interface register 31
| `0xfffffe00` | `NEORV32_CFS.REG[0]` |`31:0` | (r)/(w) | custom CFS interface register 0
| `0xfffffe04` | `NEORV32_CFS.REG[1]` |`31:0` | (r)/(w) | custom CFS interface register 1
| ... | ... |`31:0` | (r)/(w) | ...
| `0xfffffe78` | `NEORV32_CFS.REG[30]` |`31:0` | (r)/(w) | custom CFS interface register 30
| `0xfffffe7c` | `NEORV32_CFS.REG[31]` |`31:0` | (r)/(w) | custom CFS interface register 31
|=======================
10 changes: 5 additions & 5 deletions docs/datasheet/soc_gpio.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ The GPIO modules uses two memory-mapped registers (each 32-bit) each for accessi
output signals. Since the CPU can only process 32-bit "at once" updating the entire output cannot
be performed within a single clock cycle.

.GPIO unit register map
.GPIO unit register map (`struct NEORV32_GPIO`)
[cols="<2,<2,^1,^1,<6"]
[options="header",grid="rows"]
|=======================
| Address | Name [C] | Bit(s) | R/W | Function
| `0xffffffc0` | _GPIO_INPUT_LO_ | 31:0 | r/- | parallel input port pins 31:0 (write accesses are ignored)
| `0xffffffc4` | _GPIO_INPUT_HI_ | 31:0 | r/- | parallel input port pins 63:32 (write accesses are ignored)
| `0xffffffc8` | _GPIO_OUTPUT_LO_ | 31:0 | r/w | parallel output port pins 31:0
| `0xffffffcc` | _GPIO_OUTPUT_HI_ | 31:0 | r/w | parallel output port pins 63:32
| `0xffffffc0` | `NEORV32_GPIO.INPUT_LO` | 31:0 | r/- | parallel input port pins 31:0 (write accesses are ignored)
| `0xffffffc4` | `NEORV32_GPIO.INPUT_HI` | 31:0 | r/- | parallel input port pins 63:32 (write accesses are ignored)
| `0xffffffc8` | `NEORV32_GPIO.OUTPUT_LO` | 31:0 | r/w | parallel output port pins 31:0
| `0xffffffcc` | `NEORV32_GPIO.OUTPUT_HI` | 31:0 | r/w | parallel output port pins 63:32
|=======================
18 changes: 9 additions & 9 deletions docs/datasheet/soc_mtime.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,26 @@ use via the top's `mtime_o` signal.
If the processor-internal **MTIME unit is NOT implemented**, the top's `mtime_i` input signal is used to update the `time[h]` CSRs
and the `MTI` machine timer interrupt) CPU interrupt is directly connected to the top's `mtime_irq_i` input.

The 64-bit system time can be accessed via the `MTIME_LO` and `MTIME_HI` memory-mapped registers (read/write) and also via
the CPU's `time[h]` CSRs (read-only). A 64-bit time compare register – accessible via memory-mapped `MTIMECMP_LO` and `MTIMECMP_HI`
The 64-bit system time can be accessed via the `TIME_LO` and `TIME_HI` memory-mapped registers (read/write) and also via
the CPU's `time[h]` CSRs (read-only). A 64-bit time compare register – accessible via memory-mapped `TIMECMP_LO` and `TIMECMP_HI`
registers – are used to configure an interrupt to the CPU. The interrupt is triggered
whenever `MTIME` (high & low part) >= `MTIMECMP` (high & low part) and is directly forwarded to the CPU's `MTI` interrupt.
whenever `TIME` (high & low part) >= `TIMECMP` (high & low part) and is directly forwarded to the CPU's `MTI` interrupt.

[TIP]
The interrupt request is a single-shot signal,
so the CPU is triggered once if the system time is greater than or equal to the compare time. Hence,
another MTIME IRQ is only possible when updating `MTIMECMP`.
another MTIME IRQ is only possible when updating `TIMECMP`.

The 64-bit counter and the 64-bit comparator are implemented as 2×32-bit counters and comparators with a
registered carry to prevent a 64-bit carry chain and thus, to simplify timing closure.

.MTIME register map
.MTIME register map (`struct NEORV32_MTIME`)
[cols="<3,<3,^1,^1,<6"]
[options="header",grid="all"]
|=======================
| Address | Name [C] | Bits | R/W | Function
| `0xffffff90` | _MTIME_LO_ | 31:0 | r/w | machine system time, low word
| `0xffffff94` | _MTIME_HI_ | 31:0 | r/w | machine system time, high word
| `0xffffff98` | _MTIMECMP_LO_ | 31:0 | r/w | time compare, low word
| `0xffffff9c` | _MTIMECMP_HI_ | 31:0 | r/w | time compare, high word
| `0xffffff90` | `NEORV32_MTIME.TIME_LO` | 31:0 | r/w | machine system time, low word
| `0xffffff94` | `NEORV32_MTIME.TIME_HI` | 31:0 | r/w | machine system time, high word
| `0xffffff98` | `NEORV32_MTIME.TIMECMP_LO` | 31:0 | r/w | time compare, low word
| `0xffffff9c` | `NEORV32_MTIME.TIMECMP_HI` | 31:0 | r/w | time compare, high word
|=======================
Loading

0 comments on commit 9d3fc2e

Please sign in to comment.