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

rework low-level hardware access #158

Merged
merged 9 commits into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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