feat: refactor NMI interface and enhance performance logging

- Updated NMI interface references from  to  in multiple files for consistency.
- Added a new script  to convert UART performance records into structured JSON format.
- Enhanced the README documentation to include details about the new performance log parser.
- Implemented tests for the new performance log parser to ensure correct functionality.
- Added new test cases for DMA error handling and SDRAM data integrity to improve coverage.
- Updated existing test cases to accommodate changes in the NMI interface and added performance metrics.
- Refactored bus fault testbench to include fault code checks and improved error handling.
- Adjusted memory map generation and pin mapping tests to reflect recent changes in RTL structure.
This commit is contained in:
maksyuki committed 2026-08-02 10:21:09 +08:00
1 parent ed19891bf5
commit 0a6055134e
61 files changed
+2539 -433

No files matched your search

+2
View File
@@ -62,6 +62,8 @@ hazard3
def.fl
*yosys*.fl
*verilator*.fl
!rtl/filelist/pdk_ics55_yosys.fl
!rtl/filelist/pdk_ics55_verilator.fl
minirv.sv
user_design
*.zip
+35 -3
View File
@@ -33,6 +33,7 @@ PDK ?= IHP130
HAVE_PLL ?= NO
HAVE_SRAM_IF ?= NO
HAVE_SRAM_MACRO ?= NO
PDK_BEHAV ?= NO
HAVE_SVA ?= NO
WAVE ?= NO
FORMAL ?= NO
@@ -70,7 +71,7 @@ VCS_SHELL_PYTHON := $(if $(filter VCS,$(SIMU)),$(if $(filter $(VCS_SHELL_GOALS
JOBS ?= $(shell count=$$(nproc 2>/dev/null || printf '1'); \
if [ "$$count" -gt "$(MAX_JOBS)" ]; then printf '%s' '$(MAX_JOBS)'; \
else printf '%s' "$$count"; fi)
CONFIG_KEY_VARS := SOC CORE PDK HAVE_PLL HAVE_SRAM_IF HAVE_SRAM_MACRO HAVE_SVA \
CONFIG_KEY_VARS := SOC CORE PDK HAVE_PLL HAVE_SRAM_IF HAVE_SRAM_MACRO PDK_BEHAV HAVE_SVA \
ISA HAVE_CSR APP LINK_TYPE RTL_TOP FIRMWARE_NAME
VARIANT_ID := $(strip $(shell $(VCS_SHELL_PYTHON) $(ROOT_PATH)/scripts/config_key.py \
--lock $(LOCK_FILE) --profile $(PROFILE_NAME) --timestamp $(BUILD_TIMESTAMP) \
@@ -102,7 +103,7 @@ VALID_STA := NONE OPENSTA
VALID_PDK := ICS55 IHP130 SKY130 GF180
VALID_BOOL := YES NO
VALID_ISA := RV32E RV32I RV32IM
VALID_APP := bringup shell
VALID_APP := benchmark bringup shell
VALID_LINK_TYPE := xip ld2_sram ld2_psram ld2_sdram
define validate_value
@@ -118,6 +119,7 @@ $(call validate_value,PDK,$(VALID_PDK))
$(call validate_value,HAVE_PLL,$(VALID_BOOL))
$(call validate_value,HAVE_SRAM_IF,$(VALID_BOOL))
$(call validate_value,HAVE_SRAM_MACRO,$(VALID_BOOL))
$(call validate_value,PDK_BEHAV,$(VALID_BOOL))
$(call validate_value,HAVE_SVA,$(VALID_BOOL))
$(call validate_value,WAVE,$(VALID_BOOL))
$(call validate_value,FORMAL,$(VALID_BOOL))
@@ -127,6 +129,15 @@ $(call validate_value,HAVE_CSR,$(VALID_BOOL))
$(call validate_value,APP,$(VALID_APP))
$(call validate_value,LINK_TYPE,$(VALID_LINK_TYPE))
ifneq ($(filter benchmark-report,$(MAKECMDGOALS)),)
ifneq ($(APP),benchmark)
$(error benchmark-report requires APP=benchmark)
endif
ifeq ($(RTL_SIM_TIMEOUT),-1)
RTL_SIM_TIMEOUT := 20000000
endif
endif
ifeq ($(SYNTH),YOSYS)
ifeq ($(filter $(PDK),IHP130 ICS55 GF180 SKY130),)
$(error Yosys synthesis does not support PDK=$(PDK))
@@ -158,6 +169,13 @@ ifeq ($(HAVE_SRAM_MACRO), YES)
DEF_LIST += +define+HAVE_SRAM_MACRO
endif
ifeq ($(PDK_BEHAV), YES)
ifeq ($(SYNTH), YOSYS)
$(error PDK_BEHAV=YES is for functional simulation and cannot be synthesized)
endif
DEF_LIST += +define+PDK_BEHAV
endif
ifeq ($(HAVE_SVA), NO)
DEF_LIST += +define+SV_ASSRT_DISABLE
endif
@@ -169,6 +187,12 @@ endif
include rtl/mini/Makefile
include rtl/mini/mk/formal.mk
ifeq ($(SIMU),IVERILOG)
PERF_LOG ?= $(IVERILOG_BEHV_DIR)/sim.log
else
PERF_LOG ?= $(SIM_BUILD_ROOT)/sim.log
endif
ifeq ($(SYNTH), YOSYS)
include syn/yosys/yosys.mk
endif
@@ -181,6 +205,7 @@ endif
clean-all purge-cache manifest check-warnings metrics check-metrics package \
regress-smoke regress-pr regress-nightly sim-asm format format-check sw-format sw-format-check mk-format \
mk-format-check rtl-format rtl-format-check sw-policy-check sw-host-test \
benchmark-report \
pin-map check-pin-map soc-topology check-soc-topology user-extensions check-user-extensions \
check-clock-reset-domains tech-cell-test rtl-lint check-rtl-lint \
formal formal-bus formal-nmi2apb formal-clean formal-doctor
@@ -210,6 +235,7 @@ help:
' rtl-lint | check-rtl-lint run/check strict Verilator RTL lint warnings' \
' formal | formal-bus | formal-nmi2apb | formal-sysctrl | formal-pll-rcu | formal-gpio-user run SBY protocol proofs' \
' formal-doctor check the SBY, Yosys, sv2v, and Bitwuzla formal toolchain' \
' benchmark-report run the benchmark profile and write meta/performance.json' \
' tech-cell-test test GF180/SKY130 technology IO and clock wrappers' \
' check-warnings | metrics analyze flow logs and reports' \
' check-metrics apply the committed metrics policy' \
@@ -238,7 +264,7 @@ config:
SIMU '$(SIMU)' SYNTH '$(SYNTH)' STA '$(STA)' FORMAL '$(FORMAL)' \
VCS_USE_LSF '$(VCS_USE_LSF)' PDK '$(PDK)' \
HAVE_PLL '$(HAVE_PLL)' HAVE_SRAM_IF '$(HAVE_SRAM_IF)' \
HAVE_SRAM_MACRO '$(HAVE_SRAM_MACRO)' HAVE_SVA '$(HAVE_SVA)' \
HAVE_SRAM_MACRO '$(HAVE_SRAM_MACRO)' PDK_BEHAV '$(PDK_BEHAV)' HAVE_SVA '$(HAVE_SVA)' \
ISA '$(ISA)' HAVE_CSR '$(HAVE_CSR)' APP '$(APP)' \
LINK_TYPE '$(LINK_TYPE)'
@@ -247,6 +273,12 @@ doctor:
--root $(ROOT_PATH) --simu $(SIMU) --synth $(SYNTH) --sta $(STA) \
--pdk $(PDK) --formal $(FORMAL) --lock $(LOCK_FILE)
benchmark-report: firmware
$(MAKE) RTL_SIM_TIMEOUT=$(RTL_SIM_TIMEOUT) sim
$(FLOW_PYTHON) $(ROOT_PATH)/scripts/parse_performance_log.py --log $(PERF_LOG) \
--output $(META_DIR)/performance.json
setup: setup-mpw setup-core setup-clusterip setup-ip setup-pdk setup-app
setup-mpw:
+8
View File
@@ -27,6 +27,7 @@ The build selects an application with `APP=<name>`. The supported profiles are:
| Profile | Description |
| --- | --- |
| `benchmark` | Fixed-workload memory and DMA baseline with machine-readable wait counters and readback checksums. |
| `bringup` | Minimal firmware used for startup and basic SoC regression. |
| `shell` | Interactive application that adds shell services, board drivers, media, FatFs, CoreMark, and UserIP integration. |
@@ -42,10 +43,17 @@ make CONFIG=configs/ci/ihp130.mk SIMU=VERILATOR firmware sim
# Shell firmware and Verilator simulation
make CONFIG=configs/ci/ihp130-shell.mk SIMU=VERILATOR firmware sim
# IHP130/Hazard3 Verilator baseline; result is written below build/*/meta/
make CONFIG=configs/benchmark/ihp130-hazard3.mk SIMU=VERILATOR benchmark-report
```
For a firmware-only build, omit `SIMU=VERILATOR sim`.
The Verilator harness uses a zero-delay SDRAM protocol model so that memory
and DMA readback are checked in the fast emulator. The Icarus testbench keeps
the Micron SDRAM timing model and remains the timing-oriented behavioral flow.
## Adding an Application
1. Create `app/apps/<name>/main.c` and `app/apps/<name>/app.mk`.
+2
View File
@@ -0,0 +1,2 @@
APP_SRCS += $(ROOT_PATH)/app/apps/benchmark/main.c
APP_CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections
+218
View File
@@ -0,0 +1,218 @@
#include <stdint.h>
#include <stdbool.h>
#include <retrosoc/core/soc.h>
#include <retrosoc/hal/dma.h>
#include <retrosoc/hal/perf.h>
#include <retrosoc/hal/uart.h>
#define RS_BENCHMARK_WORDS UINT32_C(64)
#define RS_BENCHMARK_SRAM_OFFSET UINT32_C(0x10000)
#define RS_BENCHMARK_SRAM_SEED UINT32_C(0x13579BDF)
#define RS_BENCHMARK_SDRAM_SEED UINT32_C(0x2468ACE0)
#define RS_BENCHMARK_PSRAM_SEED UINT32_C(0x5A5A5A5A)
static void rs_benchmark_puts(const char *text) {
while (*text != '\0') {
putch(*text);
++text;
}
}
static void rs_benchmark_put_dec(uint32_t value) {
char digits[10];
uint32_t digit_count = 0U;
do {
digits[digit_count] = (char)('0' + (value % 10U));
value /= 10U;
++digit_count;
} while (value != 0U);
do {
--digit_count;
putch(digits[digit_count]);
} while (digit_count != 0U);
}
static void rs_benchmark_put_hex(uint32_t value) {
static const char digits[] = "0123456789abcdef";
uint32_t nibble_index;
for (nibble_index = 8U; nibble_index > 0U; --nibble_index) {
const uint32_t shift = (nibble_index - 1U) * 4U;
putch(digits[(value >> shift) & 0xFU]);
}
}
static void rs_benchmark_put_counter(const char *name, uint64_t value) {
rs_benchmark_puts(name);
rs_benchmark_put_dec((uint32_t)value);
}
static uint32_t rs_benchmark_write(volatile uint32_t *memory, uint32_t seed) {
uint32_t index;
uint32_t value = seed;
uint32_t checksum = 0U;
for (index = 0U; index < RS_BENCHMARK_WORDS; ++index) {
value = (value << 5) ^ (value >> 3) ^ index;
memory[index] = value;
checksum ^= value + index;
}
return checksum;
}
static uint32_t rs_benchmark_read(volatile const uint32_t *memory) {
uint32_t index;
uint32_t checksum = 0U;
for (index = 0U; index < RS_BENCHMARK_WORDS; ++index) {
checksum ^= memory[index] + index;
}
return checksum;
}
static void rs_benchmark_report(const char *region, const char *operation, uint32_t checksum,
const rs_perf_snapshot_t *snapshot) {
rs_benchmark_puts("PERF region=");
rs_benchmark_puts(region);
rs_benchmark_puts(" op=");
rs_benchmark_puts(operation);
rs_benchmark_puts(" words=");
rs_benchmark_put_dec(RS_BENCHMARK_WORDS);
rs_benchmark_puts(" checksum=");
rs_benchmark_put_hex(checksum);
rs_benchmark_put_counter(" mgmt_wait=", snapshot->mgmt_wait);
rs_benchmark_put_counter(" native_wait=", snapshot->native_wait);
rs_benchmark_put_counter(" sdram_wait=", snapshot->sdram_wait);
rs_benchmark_put_counter(" psram_wait=", snapshot->psram_wait);
rs_benchmark_put_counter(" flash_wait=", snapshot->flash_wait);
rs_benchmark_put_counter(" dma_wait=", snapshot->dma_wait);
putch('\n');
}
static void rs_benchmark_report_snapshot_failure(const char *region, const char *operation) {
rs_benchmark_puts("PERF_FAIL region=");
rs_benchmark_puts(region);
rs_benchmark_puts(" op=");
rs_benchmark_puts(operation);
rs_benchmark_puts(" reason=snapshot\n");
}
static void rs_benchmark_report_data_failure(const char *region, uint32_t expected,
uint32_t actual) {
rs_benchmark_puts("PERF_FAIL region=");
rs_benchmark_puts(region);
rs_benchmark_puts(" op=read reason=data expected=");
rs_benchmark_put_hex(expected);
rs_benchmark_puts(" actual=");
rs_benchmark_put_hex(actual);
putch('\n');
}
static bool rs_benchmark_memory(const char *region, volatile uint32_t *memory, uint32_t seed) {
rs_perf_snapshot_t snapshot;
uint32_t expected_checksum;
uint32_t actual_checksum;
(void)rs_perf_start();
expected_checksum = rs_benchmark_write(memory, seed);
if (rs_perf_snapshot(&snapshot) != RS_OK) {
rs_benchmark_report_snapshot_failure(region, "write");
return false;
}
rs_benchmark_report(region, "write", expected_checksum, &snapshot);
(void)rs_perf_start();
actual_checksum = rs_benchmark_read(memory);
if (rs_perf_snapshot(&snapshot) != RS_OK) {
rs_benchmark_report_snapshot_failure(region, "read");
return false;
}
rs_benchmark_report(region, "read", actual_checksum, &snapshot);
if (actual_checksum != expected_checksum) {
rs_benchmark_report_data_failure(region, expected_checksum, actual_checksum);
return false;
}
return true;
}
static bool rs_benchmark_dma(volatile uint32_t *source, volatile uint32_t *destination,
uint32_t expected_checksum) {
rs_dma_error_t error;
rs_perf_snapshot_t snapshot;
rs_status_t status;
uint32_t checksum;
error.response_code = 0U;
error.address = 0U;
(void)rs_perf_start();
status =
rs_dma_config(0U, (uintptr_t)source, 1U, (uintptr_t)destination, 1U, RS_BENCHMARK_WORDS);
if (status == RS_OK) {
status = rs_dma_start();
}
if (status == RS_OK) {
status = rs_dma_wait(RS_TIMEOUT_DEFAULT);
}
if (status != RS_OK) {
(void)rs_dma_get_error(&error);
rs_benchmark_puts("PERF_FAIL region=dma op=copy\n");
return false;
}
if (rs_perf_snapshot(&snapshot) != RS_OK) {
rs_benchmark_report_snapshot_failure("dma", "copy");
return false;
}
checksum = rs_benchmark_read(destination);
rs_benchmark_report("dma", "copy", checksum, &snapshot);
if (checksum != expected_checksum) {
rs_benchmark_report_data_failure("dma", expected_checksum, checksum);
return false;
}
return true;
}
int main(void) {
volatile uint32_t *const sram =
(volatile uint32_t *)(uintptr_t)(RS_SOC_SRAM_BASE + RS_BENCHMARK_SRAM_OFFSET);
volatile uint32_t *const sdram = (volatile uint32_t *)(uintptr_t)RS_SOC_SDRAM_BASE;
volatile uint32_t *const psram = (volatile uint32_t *)(uintptr_t)RS_SOC_PSRAM_BASE;
volatile uint32_t *const flash = (volatile uint32_t *)(uintptr_t)(RS_SOC_FLASH_BASE + 0x10000U);
uint32_t checksum;
uart0_init(CPU_FREQ, UART_BPS);
rs_benchmark_puts("retroSoC: A Customized ASIC for Retro Stuff\n");
if (!rs_benchmark_memory("sram", sram, RS_BENCHMARK_SRAM_SEED)) {
return 1;
}
if (!rs_benchmark_memory("sdram", sdram, RS_BENCHMARK_SDRAM_SEED)) {
return 1;
}
if (!rs_benchmark_memory("psram", psram, RS_BENCHMARK_PSRAM_SEED)) {
return 1;
}
(void)rs_perf_start();
checksum = rs_benchmark_read(flash);
{
rs_perf_snapshot_t snapshot;
if (rs_perf_snapshot(&snapshot) != RS_OK) {
rs_benchmark_report_snapshot_failure("flash", "read");
return 1;
}
rs_benchmark_report("flash", "read", checksum, &snapshot);
}
if (!rs_benchmark_dma(psram, sdram + RS_BENCHMARK_WORDS, rs_benchmark_read(psram))) {
return 1;
}
(void)rs_perf_stop();
rs_benchmark_puts("PERF_BENCHMARK_PASS\n");
return 0;
}
+8 -2
View File
@@ -5,10 +5,16 @@ selects SoC, PDK, ISA, CSR support, application, linker layout, and the
supported validation tier. The user-extension fabric is fixed; the management
core defaults to `HAZARD3` and may be set to `PICORV32` with `CORE`.
`ci/` contains pull-request profiles and `cluster/` contains configurations
requiring site tools or PDKs. The nightly workflow reuses the IHP130 CI profile.
`ci/` contains pull-request profiles, `cluster/` contains configurations
requiring site tools or PDKs, and `benchmark/` contains fixed-workload baseline
profiles. The nightly workflow reuses the IHP130 CI profile.
Start builds from a committed profile rather than setting an unreviewed mix of
variables on the command line.
`PDK_BEHAV=YES` selects technology-wrapper functional models for behavioral
simulation. It is a simulation-only setting, participates in the build variant
key, and is invalid with Yosys synthesis. Profiles that execute from an SRAM
macro must select either this mode or a qualified macro timing model.
For supported profiles and commands, see the root [README](../README.md) and
[agent contract](../AGENTS.md).
+12
View File
@@ -0,0 +1,12 @@
SOC := MINI
CORE := HAZARD3
PDK := IHP130
HAVE_PLL := NO
HAVE_SRAM_IF := YES
HAVE_SRAM_MACRO := YES
PDK_BEHAV := YES
HAVE_SVA := NO
ISA := RV32IM
HAVE_CSR := NO
APP := benchmark
LINK_TYPE := ld2_sram
+1 -1
View File
@@ -7,4 +7,4 @@ HAVE_SVA := NO
ISA := RV32IM
HAVE_CSR := NO
APP := bringup
LINK_TYPE := ld2_psram
LINK_TYPE := ld2_psram
+246 -208
View File
@@ -15,241 +15,279 @@
#error "Management core selection is missing"
#endif
#define CPU_FREQ 72 // unit: MHz
#define UART_BPS 921600 // unit: bps
#define PSRAM_NUM 4
#define PSRAM_SCLK_MIN_FREQ 12 // unit: MHz
#define PSRAM_SCLK_MAX_FREQ 133 // unit: MHz
#define PSRAM_SCLK_FREQ (CPU_FREQ / 2)
#define CPU_FREQ 72 // unit: MHz
#define UART_BPS 921600 // unit: bps
#define PSRAM_NUM 4
#define PSRAM_SCLK_MIN_FREQ 12 // unit: MHz
#define PSRAM_SCLK_MAX_FREQ 133 // unit: MHz
#define PSRAM_SCLK_FREQ (CPU_FREQ / 2)
#define SPFS_MEM_START RS_SOC_FLASH_BASE
#define SPFS_MEM_OFFST RS_SOC_FLASH_SIZE
#define SRAM_MEM_START RS_SOC_SRAM_BASE
#define SRAM_MEM_OFFST RS_SOC_SRAM_SIZE
#define SDRAM_MEM_START RS_SOC_SDRAM_BASE
#define SDRAM_MEM_OFFST RS_SOC_SDRAM_SIZE
#define PSRAM_MEM_START RS_SOC_PSRAM_BASE
#define PSRAM_MEM_OFFST RS_SOC_PSRAM_SIZE
#define XPI_MEM_START RS_SOC_XPI_BASE
#define XPI_MEM_OFFST RS_SOC_XPI_SIZE
#define TF_CARD_START RS_SOC_SPISD_BASE
#define TF_CARD_OFFST RS_SOC_SPISD_SIZE
#define SPFS_MEM_START RS_SOC_FLASH_BASE
#define SPFS_MEM_OFFST RS_SOC_FLASH_SIZE
#define SRAM_MEM_START RS_SOC_SRAM_BASE
#define SRAM_MEM_OFFST RS_SOC_SRAM_SIZE
#define SDRAM_MEM_START RS_SOC_SDRAM_BASE
#define SDRAM_MEM_OFFST RS_SOC_SDRAM_SIZE
#define PSRAM_MEM_START RS_SOC_PSRAM_BASE
#define PSRAM_MEM_OFFST RS_SOC_PSRAM_SIZE
#define XPI_MEM_START RS_SOC_XPI_BASE
#define XPI_MEM_OFFST RS_SOC_XPI_SIZE
#define TF_CARD_START RS_SOC_SPISD_BASE
#define TF_CARD_OFFST RS_SOC_SPISD_SIZE
#define RS_SOC_REG32(base, offset) (*(volatile uint32_t *)(uintptr_t)((base) + (offset)))
#define RS_SOC_REG32(base, offset) (*(volatile uint32_t *)(uintptr_t)((base) + (offset)))
// gpio
#define reg_gpio_oe RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x00))
#define reg_gpio_cs RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x04))
#define reg_gpio_pu RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x08))
#define reg_gpio_pd RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x0C))
#define reg_gpio_do RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x10))
#define reg_gpio_di RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x14))
#define reg_gpio_ien RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x18))
#define reg_gpio_itype0 RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x1C))
#define reg_gpio_itype1 RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x20))
#define reg_gpio_istat RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x24))
#define reg_gpio_iofcfg RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x28))
#define reg_gpio_pinmux RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x2C))
#define reg_gpio_user_sel RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x30))
#define reg_gpio_user_lock RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x34))
#define reg_gpio_user_status RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x38))
#define reg_gpio_oe RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x00))
#define reg_gpio_cs RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x04))
#define reg_gpio_pu RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x08))
#define reg_gpio_pd RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x0C))
#define reg_gpio_do RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x10))
#define reg_gpio_di RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x14))
#define reg_gpio_ien RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x18))
#define reg_gpio_itype0 RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x1C))
#define reg_gpio_itype1 RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x20))
#define reg_gpio_istat RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x24))
#define reg_gpio_iofcfg RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x28))
#define reg_gpio_pinmux RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x2C))
#define reg_gpio_user_sel RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x30))
#define reg_gpio_user_lock RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x34))
#define reg_gpio_user_status RS_SOC_REG32(RS_SOC_NMI_GPIO_BASE, UINT32_C(0x38))
// uart0
#define reg_uart0_clkdiv RS_SOC_REG32(RS_SOC_NMI_UART0_BASE, UINT32_C(0x00))
#define reg_uart0_data RS_SOC_REG32(RS_SOC_NMI_UART0_BASE, UINT32_C(0x04))
#define reg_uart0_clkdiv RS_SOC_REG32(RS_SOC_NMI_UART0_BASE, UINT32_C(0x00))
#define reg_uart0_data RS_SOC_REG32(RS_SOC_NMI_UART0_BASE, UINT32_C(0x04))
// tim0
#define reg_tim0_cfg RS_SOC_REG32(RS_SOC_NMI_TIM0_BASE, UINT32_C(0x00))
#define reg_tim0_rld RS_SOC_REG32(RS_SOC_NMI_TIM0_BASE, UINT32_C(0x04))
#define reg_tim0_val RS_SOC_REG32(RS_SOC_NMI_TIM0_BASE, UINT32_C(0x08))
#define reg_tim0_cfg RS_SOC_REG32(RS_SOC_NMI_TIM0_BASE, UINT32_C(0x00))
#define reg_tim0_rld RS_SOC_REG32(RS_SOC_NMI_TIM0_BASE, UINT32_C(0x04))
#define reg_tim0_val RS_SOC_REG32(RS_SOC_NMI_TIM0_BASE, UINT32_C(0x08))
// tim1
#define reg_tim1_cfg RS_SOC_REG32(RS_SOC_NMI_TIM1_BASE, UINT32_C(0x00))
#define reg_tim1_rld RS_SOC_REG32(RS_SOC_NMI_TIM1_BASE, UINT32_C(0x04))
#define reg_tim1_val RS_SOC_REG32(RS_SOC_NMI_TIM1_BASE, UINT32_C(0x08))
#define reg_tim1_cfg RS_SOC_REG32(RS_SOC_NMI_TIM1_BASE, UINT32_C(0x00))
#define reg_tim1_rld RS_SOC_REG32(RS_SOC_NMI_TIM1_BASE, UINT32_C(0x04))
#define reg_tim1_val RS_SOC_REG32(RS_SOC_NMI_TIM1_BASE, UINT32_C(0x08))
// psram
#define reg_psram_wait RS_SOC_REG32(RS_SOC_NMI_PSRAM_BASE, UINT32_C(0x00))
#define reg_psram_chd RS_SOC_REG32(RS_SOC_NMI_PSRAM_BASE, UINT32_C(0x04))
#define reg_psram_init RS_SOC_REG32(RS_SOC_NMI_PSRAM_BASE, UINT32_C(0x08))
#define reg_psram_wait RS_SOC_REG32(RS_SOC_NMI_PSRAM_BASE, UINT32_C(0x00))
#define reg_psram_chd RS_SOC_REG32(RS_SOC_NMI_PSRAM_BASE, UINT32_C(0x04))
#define reg_psram_init RS_SOC_REG32(RS_SOC_NMI_PSRAM_BASE, UINT32_C(0x08))
// spisd
#define reg_spisd_mode RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x00))
#define reg_spisd_clkdiv RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x04))
#define reg_spisd_addr RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x08))
#define reg_spisd_txdata RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x0C))
#define reg_spisd_rxdata RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x10))
#define reg_spisd_status RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x14))
#define reg_spisd_sync RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x18))
#define reg_spisd_mode RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x00))
#define reg_spisd_clkdiv RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x04))
#define reg_spisd_addr RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x08))
#define reg_spisd_txdata RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x0C))
#define reg_spisd_rxdata RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x10))
#define reg_spisd_status RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x14))
#define reg_spisd_sync RS_SOC_REG32(RS_SOC_NMI_SPISD_BASE, UINT32_C(0x18))
// i2c0
#define reg_i2c0_clkdiv RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x00))
#define reg_i2c0_devaddr RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x04))
#define reg_i2c0_regaddr RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x08))
#define reg_i2c0_txdata RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x0C))
#define reg_i2c0_rxdata RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x10))
#define reg_i2c0_xfer RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x14))
#define reg_i2c0_cfg RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x18))
#define reg_i2c0_status RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x1C))
#define reg_i2c0_clkdiv RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x00))
#define reg_i2c0_devaddr RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x04))
#define reg_i2c0_regaddr RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x08))
#define reg_i2c0_txdata RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x0C))
#define reg_i2c0_rxdata RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x10))
#define reg_i2c0_xfer RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x14))
#define reg_i2c0_cfg RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x18))
#define reg_i2c0_status RS_SOC_REG32(RS_SOC_NMI_I2C0_BASE, UINT32_C(0x1C))
// i2s
#define reg_i2s_mode RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x00))
#define reg_i2s_format RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x04))
#define reg_i2s_upbound RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x08))
#define reg_i2s_lowbound RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x0C))
#define reg_i2s_recven RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x10))
#define reg_i2s_txdata RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x14))
#define reg_i2s_rxdata RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x18))
#define reg_i2s_status RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x1C))
#define reg_i2s_mode RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x00))
#define reg_i2s_format RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x04))
#define reg_i2s_upbound RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x08))
#define reg_i2s_lowbound RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x0C))
#define reg_i2s_recven RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x10))
#define reg_i2s_txdata RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x14))
#define reg_i2s_rxdata RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x18))
#define reg_i2s_status RS_SOC_REG32(RS_SOC_NMI_I2S_BASE, UINT32_C(0x1C))
// onewire
#define reg_onewire_clkdiv RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x00))
#define reg_onewire_zerocnt RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x04))
#define reg_onewire_onecnt RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x08))
#define reg_onewire_rstcnt RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x0C))
#define reg_onewire_txdata RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x10))
#define reg_onewire_ctrl RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x14))
#define reg_onewire_status RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x18))
#define reg_onewire_clkdiv RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x00))
#define reg_onewire_zerocnt RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x04))
#define reg_onewire_onecnt RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x08))
#define reg_onewire_rstcnt RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x0C))
#define reg_onewire_txdata RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x10))
#define reg_onewire_ctrl RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x14))
#define reg_onewire_status RS_SOC_REG32(RS_SOC_NMI_ONEWIRE_BASE, UINT32_C(0x18))
// xpi
#define reg_xpi_cfgidx RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x00))
#define reg_xpi_accmd RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x04))
#define reg_xpi_mmstad RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x08))
#define reg_xpi_mmoffst RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x0C))
#define reg_xpi_mode RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x10))
#define reg_xpi_nss RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x14))
#define reg_xpi_clkdiv RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x18))
#define reg_xpi_rdwr RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x1C))
#define reg_xpi_revdat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x20))
#define reg_xpi_txupb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x24))
#define reg_xpi_txlowb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x28))
#define reg_xpi_rxupb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x2C))
#define reg_xpi_rxlowb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x30))
#define reg_xpi_flush RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x34))
#define reg_xpi_cmdtyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x38))
#define reg_xpi_cmdlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x3C))
#define reg_xpi_cmddat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x40))
#define reg_xpi_adrtyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x44))
#define reg_xpi_adrlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x48))
#define reg_xpi_adrdat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x4C))
#define reg_xpi_alttyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x50))
#define reg_xpi_altlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x54))
#define reg_xpi_altdat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x58))
#define reg_xpi_tdulen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x5C))
#define reg_xpi_rdulen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x60))
#define reg_xpi_dattyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x64))
#define reg_xpi_datlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x68))
#define reg_xpi_datbit RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x6C))
#define reg_xpi_hlvlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x70))
#define reg_xpi_txdata RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x74))
#define reg_xpi_rxdata RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x78))
#define reg_xpi_start RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x7C))
#define reg_xpi_status RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x80))
#define reg_xpi_cfgidx RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x00))
#define reg_xpi_accmd RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x04))
#define reg_xpi_mmstad RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x08))
#define reg_xpi_mmoffst RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x0C))
#define reg_xpi_mode RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x10))
#define reg_xpi_nss RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x14))
#define reg_xpi_clkdiv RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x18))
#define reg_xpi_rdwr RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x1C))
#define reg_xpi_revdat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x20))
#define reg_xpi_txupb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x24))
#define reg_xpi_txlowb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x28))
#define reg_xpi_rxupb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x2C))
#define reg_xpi_rxlowb RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x30))
#define reg_xpi_flush RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x34))
#define reg_xpi_cmdtyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x38))
#define reg_xpi_cmdlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x3C))
#define reg_xpi_cmddat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x40))
#define reg_xpi_adrtyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x44))
#define reg_xpi_adrlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x48))
#define reg_xpi_adrdat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x4C))
#define reg_xpi_alttyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x50))
#define reg_xpi_altlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x54))
#define reg_xpi_altdat RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x58))
#define reg_xpi_tdulen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x5C))
#define reg_xpi_rdulen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x60))
#define reg_xpi_dattyp RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x64))
#define reg_xpi_datlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x68))
#define reg_xpi_datbit RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x6C))
#define reg_xpi_hlvlen RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x70))
#define reg_xpi_txdata RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x74))
#define reg_xpi_rxdata RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x78))
#define reg_xpi_start RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x7C))
#define reg_xpi_status RS_SOC_REG32(RS_SOC_NMI_XPI_BASE, UINT32_C(0x80))
// dma(32b xfer, hardware trigger by I2S fifo, QSPI fifo)
#define reg_dma_mode RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x00))
#define reg_dma_srcaddr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x04))
#define reg_dma_srcincr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x08))
#define reg_dma_dstaddr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x0C))
#define reg_dma_dstincr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x10))
#define reg_dma_xferlen RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x14))
#define reg_dma_start RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x18))
#define reg_dma_stop RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x1C))
#define reg_dma_reset RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x20))
#define reg_dma_status RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x24))
#define reg_dma_fsm RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x28))
#define reg_dma_mode RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x00))
#define reg_dma_srcaddr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x04))
#define reg_dma_srcincr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x08))
#define reg_dma_dstaddr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x0C))
#define reg_dma_dstincr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x10))
#define reg_dma_xferlen RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x14))
#define reg_dma_start RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x18))
#define reg_dma_stop RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x1C))
#define reg_dma_reset RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x20))
#define reg_dma_status RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x24))
#define reg_dma_fsm RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x28))
#define reg_dma_error_status RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x2C))
#define reg_dma_error_addr RS_SOC_REG32(RS_SOC_NMI_DMA_BASE, UINT32_C(0x30))
#define RS_SOC_DMA_ERROR_PENDING UINT32_C(0x00000001)
#define RS_SOC_DMA_ERROR_RESPONSE_SHIFT 1U
#define RS_SOC_DMA_ERROR_RESPONSE_MASK UINT32_C(0x0000000E)
// sys ctrl
#define RS_SOC_SYSCTRL_REG32(offset) RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, (offset))
#define reg_sysctrl_coresel RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, UINT32_C(0x00))
#define reg_sysctrl_ipsel RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, UINT32_C(0x04))
#define reg_sysctrl_pll_cfg RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_CFG_OFFSET)
#define reg_sysctrl_pll_cmd RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_CMD_OFFSET)
#define RS_SOC_SYSCTRL_REG32(offset) RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, (offset))
#define reg_sysctrl_coresel RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, UINT32_C(0x00))
#define reg_sysctrl_ipsel RS_SOC_REG32(RS_SOC_NMI_SYSCTRL_BASE, UINT32_C(0x04))
#define reg_sysctrl_pll_cfg RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_CFG_OFFSET)
#define reg_sysctrl_pll_cmd RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_CMD_OFFSET)
/* Status: bit 0 pending (W1C), bit 1 write, bits 3:2 reason (1 unmapped, 2 reserved). */
#define reg_sysctrl_bus_fault_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_STATUS_OFFSET)
#define reg_sysctrl_bus_fault_addr RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_ADDR_OFFSET)
#define reg_sysctrl_bus_fault_count RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_COUNT_OFFSET)
#define reg_sysctrl_pll_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_STATUS_OFFSET)
#define reg_sysctrl_user_core_reset RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_USER_CORE_RESET_OFFSET)
#define reg_sysctrl_user_core_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_USER_CORE_STATUS_OFFSET)
#define reg_sysctrl_bus_fault_master RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_MASTER_OFFSET)
#define RS_SOC_BUS_FAULT_PENDING UINT32_C(0x00000001)
#define RS_SOC_BUS_FAULT_WRITE UINT32_C(0x00000002)
#define RS_SOC_BUS_FAULT_REASON_MASK UINT32_C(0x0000000C)
#define RS_SOC_BUS_FAULT_REASON_UNMAPPED UINT32_C(0x00000004)
#define RS_SOC_BUS_FAULT_REASON_RESERVED UINT32_C(0x00000008)
#define reg_sysctrl_bus_fault_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_STATUS_OFFSET)
#define reg_sysctrl_bus_fault_addr RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_ADDR_OFFSET)
#define reg_sysctrl_bus_fault_count RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_COUNT_OFFSET)
#define reg_sysctrl_pll_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PLL_STATUS_OFFSET)
#define reg_sysctrl_user_core_reset RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_USER_CORE_RESET_OFFSET)
#define reg_sysctrl_user_core_status RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_USER_CORE_STATUS_OFFSET)
#define reg_sysctrl_bus_fault_master RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_MASTER_OFFSET)
#define reg_sysctrl_bus_fault_detail RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_FAULT_DETAIL_OFFSET)
#define reg_sysctrl_perf_ctrl RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_CTRL_OFFSET)
#define reg_sysctrl_perf_mgmt_wait_lo RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_mgmt_wait_hi RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_MGMT_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_user_wait_lo RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_USER_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_user_wait_hi RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_USER_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_dma_wait_lo RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_DMA_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_dma_wait_hi RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_DMA_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_natv_wait_lo RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_NATV_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_natv_wait_hi RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_NATV_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_apb_wait_lo RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_APB_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_apb_wait_hi RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_APB_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_sdram_wait_lo \
RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_SDRAM_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_sdram_wait_hi \
RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_SDRAM_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_psram_wait_lo \
RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_PSRAM_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_psram_wait_hi \
RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_PSRAM_WAIT_HI_OFFSET)
#define reg_sysctrl_perf_flash_wait_lo \
RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_FLASH_WAIT_LO_OFFSET)
#define reg_sysctrl_perf_flash_wait_hi \
RS_SOC_SYSCTRL_REG32(RS_SOC_SYSCTRL_PERF_FLASH_WAIT_HI_OFFSET)
#define RS_SOC_BUS_FAULT_PENDING UINT32_C(0x00000001)
#define RS_SOC_BUS_FAULT_WRITE UINT32_C(0x00000002)
#define RS_SOC_BUS_FAULT_REASON_MASK UINT32_C(0x0000000C)
#define RS_SOC_BUS_FAULT_REASON_UNMAPPED UINT32_C(0x00000004)
#define RS_SOC_BUS_FAULT_REASON_RESERVED UINT32_C(0x00000008)
#define RS_SOC_BUS_FAULT_RESPONSE_OK UINT32_C(0x00000000)
#define RS_SOC_BUS_FAULT_RESPONSE_DECERR UINT32_C(0x00000001)
#define RS_SOC_BUS_FAULT_RESPONSE_PROTERR UINT32_C(0x00000002)
#define RS_SOC_BUS_FAULT_RESPONSE_SLVERR UINT32_C(0x00000003)
#define RS_SOC_BUS_FAULT_RESPONSE_TIMEOUT UINT32_C(0x00000004)
#define RS_SOC_BUS_FAULT_RESPONSE_RESERVED UINT32_C(0x00000005)
#define RS_SOC_PERF_CTRL_ENABLE UINT32_C(0x00000001)
#define RS_SOC_PERF_CTRL_CLEAR UINT32_C(0x00000002)
#define RS_SOC_PERF_CTRL_SNAPSHOT UINT32_C(0x00000004)
// clint
#define reg_clint_mtimel RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x00))
#define reg_clint_mtimeh RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x04))
#define reg_clint_mtimecmpl RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x08))
#define reg_clint_mtimecmph RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x0C))
#define reg_clint_msip RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x10))
#define reg_clint_clkdiv RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x14))
#define reg_clint_mtimel RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x00))
#define reg_clint_mtimeh RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x04))
#define reg_clint_mtimecmpl RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x08))
#define reg_clint_mtimecmph RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x0C))
#define reg_clint_msip RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x10))
#define reg_clint_clkdiv RS_SOC_REG32(RS_SOC_NMI_CLINT_BASE, UINT32_C(0x14))
// sdram
#define reg_sdram_clkdiv RS_SOC_REG32(RS_SOC_NMI_SDRAM_BASE, UINT32_C(0x00))
#define reg_sdram_cfg RS_SOC_REG32(RS_SOC_NMI_SDRAM_BASE, UINT32_C(0x04))
#define reg_sdram_clkdiv RS_SOC_REG32(RS_SOC_NMI_SDRAM_BASE, UINT32_C(0x00))
#define reg_sdram_cfg RS_SOC_REG32(RS_SOC_NMI_SDRAM_BASE, UINT32_C(0x04))
// dvp
#define reg_dvp_recven RS_SOC_REG32(RS_SOC_NMI_DVP_BASE, UINT32_C(0x00))
#define reg_dvp_rxdata RS_SOC_REG32(RS_SOC_NMI_DVP_BASE, UINT32_C(0x04))
#define reg_dvp_status RS_SOC_REG32(RS_SOC_NMI_DVP_BASE, UINT32_C(0x08))
#define reg_dvp_recven RS_SOC_REG32(RS_SOC_NMI_DVP_BASE, UINT32_C(0x00))
#define reg_dvp_rxdata RS_SOC_REG32(RS_SOC_NMI_DVP_BASE, UINT32_C(0x04))
#define reg_dvp_status RS_SOC_REG32(RS_SOC_NMI_DVP_BASE, UINT32_C(0x08))
// i2c1
#define reg_i2c1_clkdiv RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x00))
#define reg_i2c1_devaddr RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x04))
#define reg_i2c1_regaddr RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x08))
#define reg_i2c1_txdata RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x0C))
#define reg_i2c1_rxdata RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x10))
#define reg_i2c1_xfer RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x14))
#define reg_i2c1_cfg RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x18))
#define reg_i2c1_status RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x1C))
#define reg_i2c1_clkdiv RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x00))
#define reg_i2c1_devaddr RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x04))
#define reg_i2c1_regaddr RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x08))
#define reg_i2c1_txdata RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x0C))
#define reg_i2c1_rxdata RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x10))
#define reg_i2c1_xfer RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x14))
#define reg_i2c1_cfg RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x18))
#define reg_i2c1_status RS_SOC_REG32(RS_SOC_NMI_I2C1_BASE, UINT32_C(0x1C))
// archinfo
#define reg_archinfo_sys RS_SOC_REG32(RS_SOC_APB_ARCHINFO_BASE, UINT32_C(0x00))
#define reg_archinfo_idl RS_SOC_REG32(RS_SOC_APB_ARCHINFO_BASE, UINT32_C(0x04))
#define reg_archinfo_idh RS_SOC_REG32(RS_SOC_APB_ARCHINFO_BASE, UINT32_C(0x08))
#define reg_archinfo_sys RS_SOC_REG32(RS_SOC_APB_ARCHINFO_BASE, UINT32_C(0x00))
#define reg_archinfo_idl RS_SOC_REG32(RS_SOC_APB_ARCHINFO_BASE, UINT32_C(0x04))
#define reg_archinfo_idh RS_SOC_REG32(RS_SOC_APB_ARCHINFO_BASE, UINT32_C(0x08))
// rng
#define reg_rng_ctrl RS_SOC_REG32(RS_SOC_APB_RNG_BASE, UINT32_C(0x00))
#define reg_rng_seed RS_SOC_REG32(RS_SOC_APB_RNG_BASE, UINT32_C(0x04))
#define reg_rng_val RS_SOC_REG32(RS_SOC_APB_RNG_BASE, UINT32_C(0x08))
#define reg_rng_ctrl RS_SOC_REG32(RS_SOC_APB_RNG_BASE, UINT32_C(0x00))
#define reg_rng_seed RS_SOC_REG32(RS_SOC_APB_RNG_BASE, UINT32_C(0x04))
#define reg_rng_val RS_SOC_REG32(RS_SOC_APB_RNG_BASE, UINT32_C(0x08))
// uart
#define reg_uart1_lcr RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x00))
#define reg_uart1_div RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x04))
#define reg_uart1_trx RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x08))
#define reg_uart1_fcr RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x0C))
#define reg_uart1_lsr RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x10))
#define reg_uart1_lcr RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x00))
#define reg_uart1_div RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x04))
#define reg_uart1_trx RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x08))
#define reg_uart1_fcr RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x0C))
#define reg_uart1_lsr RS_SOC_REG32(RS_SOC_APB_UART1_BASE, UINT32_C(0x10))
// pwm
#define reg_pwm_ctrl RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x00))
#define reg_pwm_pscr RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x04))
#define reg_pwm_cnt RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x08))
#define reg_pwm_cmp RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x0C))
#define reg_pwm_cr0 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x10))
#define reg_pwm_cr1 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x14))
#define reg_pwm_cr2 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x18))
#define reg_pwm_cr3 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x1C))
#define reg_pwm_stat RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x20))
#define reg_pwm_ctrl RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x00))
#define reg_pwm_pscr RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x04))
#define reg_pwm_cnt RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x08))
#define reg_pwm_cmp RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x0C))
#define reg_pwm_cr0 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x10))
#define reg_pwm_cr1 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x14))
#define reg_pwm_cr2 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x18))
#define reg_pwm_cr3 RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x1C))
#define reg_pwm_stat RS_SOC_REG32(RS_SOC_APB_PWM_BASE, UINT32_C(0x20))
// ps2
#define reg_ps2_ctrl RS_SOC_REG32(RS_SOC_APB_PS2_BASE, UINT32_C(0x00))
#define reg_ps2_data RS_SOC_REG32(RS_SOC_APB_PS2_BASE, UINT32_C(0x04))
#define reg_ps2_stat RS_SOC_REG32(RS_SOC_APB_PS2_BASE, UINT32_C(0x08))
#define reg_ps2_ctrl RS_SOC_REG32(RS_SOC_APB_PS2_BASE, UINT32_C(0x00))
#define reg_ps2_data RS_SOC_REG32(RS_SOC_APB_PS2_BASE, UINT32_C(0x04))
#define reg_ps2_stat RS_SOC_REG32(RS_SOC_APB_PS2_BASE, UINT32_C(0x08))
// rtc
#define reg_rtc_ctrl RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x00))
#define reg_rtc_pscr RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x04))
#define reg_rtc_cnt RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x08))
#define reg_rtc_alrm RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x0C))
#define reg_rtc_ista RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x10))
#define reg_rtc_ssta RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x14))
#define reg_rtc_ctrl RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x00))
#define reg_rtc_pscr RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x04))
#define reg_rtc_cnt RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x08))
#define reg_rtc_alrm RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x0C))
#define reg_rtc_ista RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x10))
#define reg_rtc_ssta RS_SOC_REG32(RS_SOC_APB_RTC_BASE, UINT32_C(0x14))
// wdg
#define reg_wdg_ctrl RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x00))
#define reg_wdg_pscr RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x04))
#define reg_wdg_cnt RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x08))
#define reg_wdg_cmp RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x0C))
#define reg_wdg_stat RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x10))
#define reg_wdg_key RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x14))
#define reg_wdg_feed RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x18))
#define reg_wdg_ctrl RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x00))
#define reg_wdg_pscr RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x04))
#define reg_wdg_cnt RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x08))
#define reg_wdg_cmp RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x0C))
#define reg_wdg_stat RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x10))
#define reg_wdg_key RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x14))
#define reg_wdg_feed RS_SOC_REG32(RS_SOC_APB_WDG_BASE, UINT32_C(0x18))
// crc
#define reg_crc_ctrl RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x00))
#define reg_crc_init RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x04))
#define reg_crc_xorv RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x08))
#define reg_crc_data RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x0C))
#define reg_crc_stat RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x10))
#define reg_crc_ctrl RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x00))
#define reg_crc_init RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x04))
#define reg_crc_xorv RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x08))
#define reg_crc_data RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x0C))
#define reg_crc_stat RS_SOC_REG32(RS_SOC_APB_CRC_BASE, UINT32_C(0x10))
// tim3
#define reg_tim3_ctrl RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x00))
#define reg_tim3_pscr RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x04))
#define reg_tim3_cnt RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x08))
#define reg_tim3_cmp RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x0C))
#define reg_tim3_stat RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x10))
#define reg_user_ip_reg0 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x00))
#define reg_user_ip_reg1 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x04))
#define reg_user_ip_reg2 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x08))
#define reg_user_ip_reg3 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x0C))
#define reg_user_ip_reg4 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x10))
#define reg_user_ip_reg5 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x14))
#define reg_user_ip_reg6 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x18))
#define reg_tim3_ctrl RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x00))
#define reg_tim3_pscr RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x04))
#define reg_tim3_cnt RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x08))
#define reg_tim3_cmp RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x0C))
#define reg_tim3_stat RS_SOC_REG32(RS_SOC_APB_TMR_BASE, UINT32_C(0x10))
#define reg_user_ip_reg0 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x00))
#define reg_user_ip_reg1 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x04))
#define reg_user_ip_reg2 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x08))
#define reg_user_ip_reg3 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x0C))
#define reg_user_ip_reg4 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x10))
#define reg_user_ip_reg5 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x14))
#define reg_user_ip_reg6 RS_SOC_REG32(RS_SOC_APB_USER_IP_BASE, UINT32_C(0x18))
#endif
+6
View File
@@ -5,6 +5,11 @@
#include <retrosoc/core/status.h>
typedef struct {
uint32_t response_code;
uintptr_t address;
} rs_dma_error_t;
rs_status_t rs_dma_config(uint32_t mode, uintptr_t source, uint32_t source_increment,
uintptr_t destination, uint32_t destination_increment,
uint32_t transfer_words);
@@ -12,6 +17,7 @@ rs_status_t rs_dma_start(void);
rs_status_t rs_dma_stop(void);
rs_status_t rs_dma_reset(void);
rs_status_t rs_dma_wait(rs_timeout_t timeout);
rs_status_t rs_dma_get_error(rs_dma_error_t *error);
void ip_dma_test(void);
#endif
+23
View File
@@ -0,0 +1,23 @@
#ifndef RETROSOC_HAL_PERF_H
#define RETROSOC_HAL_PERF_H
#include <stdint.h>
#include <retrosoc/core/status.h>
typedef struct {
uint64_t mgmt_wait;
uint64_t user_wait;
uint64_t dma_wait;
uint64_t native_wait;
uint64_t apb_wait;
uint64_t sdram_wait;
uint64_t psram_wait;
uint64_t flash_wait;
} rs_perf_snapshot_t;
rs_status_t rs_perf_start(void);
rs_status_t rs_perf_stop(void);
rs_status_t rs_perf_snapshot(rs_perf_snapshot_t *snapshot);
#endif
+30 -2
View File
@@ -6,7 +6,8 @@
rs_status_t rs_dma_config(uint32_t mode, uintptr_t source, uint32_t source_increment,
uintptr_t destination, uint32_t destination_increment,
uint32_t transfer_words) {
if ((source == 0U) || (destination == 0U) || (transfer_words == 0U)) {
if ((mode > 4U) || (source == 0U) || (destination == 0U) || (transfer_words == 0U) ||
(source_increment > 1U) || (destination_increment > 1U)) {
return RS_EINVAL;
}
@@ -20,6 +21,7 @@ rs_status_t rs_dma_config(uint32_t mode, uintptr_t source, uint32_t source_incre
}
rs_status_t rs_dma_start(void) {
reg_dma_error_status = RS_SOC_DMA_ERROR_PENDING;
reg_dma_start = 1U;
return RS_OK;
}
@@ -37,7 +39,33 @@ rs_status_t rs_dma_reset(void) {
}
rs_status_t rs_dma_wait(rs_timeout_t timeout) {
return rs_wait_mask(&reg_dma_status, UINT32_MAX, 1U, timeout);
while (timeout-- != 0U) {
if ((reg_dma_error_status & RS_SOC_DMA_ERROR_PENDING) != 0U) {
return RS_EIO;
}
if (reg_dma_status == 1U) {
return RS_OK;
}
}
return RS_ETIMEOUT;
}
rs_status_t rs_dma_get_error(rs_dma_error_t *error) {
uint32_t status;
if (error == NULL) {
return RS_EINVAL;
}
status = reg_dma_error_status;
error->response_code =
(status & RS_SOC_DMA_ERROR_RESPONSE_MASK) >> RS_SOC_DMA_ERROR_RESPONSE_SHIFT;
error->address = (uintptr_t)reg_dma_error_addr;
if ((status & RS_SOC_DMA_ERROR_PENDING) != 0U) {
reg_dma_error_status = RS_SOC_DMA_ERROR_PENDING;
return RS_EIO;
}
return RS_OK;
}
void ip_dma_test(void) {
+44
View File
@@ -0,0 +1,44 @@
#include <stddef.h>
#include <retrosoc/core/soc.h>
#include <retrosoc/hal/perf.h>
static uint64_t rs_perf_read_counter(volatile const uint32_t *low, volatile const uint32_t *high) {
return ((uint64_t)*high << 32) | (uint64_t)*low;
}
rs_status_t rs_perf_start(void) {
reg_sysctrl_perf_ctrl = RS_SOC_PERF_CTRL_CLEAR;
reg_sysctrl_perf_ctrl = RS_SOC_PERF_CTRL_ENABLE;
return RS_OK;
}
rs_status_t rs_perf_stop(void) {
reg_sysctrl_perf_ctrl = 0U;
return RS_OK;
}
rs_status_t rs_perf_snapshot(rs_perf_snapshot_t *snapshot) {
if (snapshot == NULL) {
return RS_EINVAL;
}
reg_sysctrl_perf_ctrl = RS_SOC_PERF_CTRL_ENABLE | RS_SOC_PERF_CTRL_SNAPSHOT;
snapshot->mgmt_wait =
rs_perf_read_counter(&reg_sysctrl_perf_mgmt_wait_lo, &reg_sysctrl_perf_mgmt_wait_hi);
snapshot->user_wait =
rs_perf_read_counter(&reg_sysctrl_perf_user_wait_lo, &reg_sysctrl_perf_user_wait_hi);
snapshot->dma_wait =
rs_perf_read_counter(&reg_sysctrl_perf_dma_wait_lo, &reg_sysctrl_perf_dma_wait_hi);
snapshot->native_wait =
rs_perf_read_counter(&reg_sysctrl_perf_natv_wait_lo, &reg_sysctrl_perf_natv_wait_hi);
snapshot->apb_wait =
rs_perf_read_counter(&reg_sysctrl_perf_apb_wait_lo, &reg_sysctrl_perf_apb_wait_hi);
snapshot->sdram_wait =
rs_perf_read_counter(&reg_sysctrl_perf_sdram_wait_lo, &reg_sysctrl_perf_sdram_wait_hi);
snapshot->psram_wait =
rs_perf_read_counter(&reg_sysctrl_perf_psram_wait_lo, &reg_sysctrl_perf_psram_wait_hi);
snapshot->flash_wait =
rs_perf_read_counter(&reg_sysctrl_perf_flash_wait_lo, &reg_sysctrl_perf_flash_wait_hi);
return RS_OK;
}
+5 -4
View File
@@ -25,10 +25,10 @@ EXPECTED_MUXI2_CELLS = {
}
BROKEN_IMPLEMENTATION = " udp_mux2 u0(Y, A, B, S0);\n not u1(Y, Y);"
FIXED_IMPLEMENTATION = (
" wire muxi2_y;\n\n"
" udp_mux2 u0(muxi2_y, A, B, S0);\n"
" not u1(Y, muxi2_y);"
" wire muxi2_y;\n\n udp_mux2 u0(muxi2_y, A, B, S0);\n not u1(Y, muxi2_y);"
)
VERILATOR_LINT_OFF = "/* verilator lint_off DECLFILENAME */\n/* verilator lint_off SPECIFYIGN */\n"
VERILATOR_LINT_ON = "/* verilator lint_on SPECIFYIGN */\n/* verilator lint_on DECLFILENAME */\n"
MUXI2_MODULE = re.compile(
r"(?P<header>\bmodule\s+(?P<name>MUXI2X[A-Za-z0-9]+H7R)"
r"\s*\(Y,\s*A,\s*B,\s*S0\);)"
@@ -75,9 +75,10 @@ def prepare(source: Path, output: Path, revision: str) -> None:
raise FileNotFoundError(f"ICS55 H7CR Verilog model not found: {source}")
patched, cells = patch_muxi2_models(source.read_text(encoding="utf-8"))
verilator_model = VERILATOR_LINT_OFF + patched.rstrip() + "\n" + VERILATOR_LINT_ON
output = output.resolve()
metadata = f"{revision}\n{sha256(source)}\n{','.join(cells)}\n"
changed = atomic_write(output, patched)
changed = atomic_write(output, verilator_model)
atomic_write(output.with_suffix(output.suffix + ".revision"), metadata)
state = "prepared" if changed else "ready"
print(f"ICS55 H7CR functional model {state}: {output}")
+5
View File
@@ -13,3 +13,8 @@ rather than editing generated MPW output.
RTL changes require an affected firmware build and simulation. Use
`make regress-pr` or `make regress-nightly` for supported regression coverage;
see [Engineering Workflow](../docs/engineering.md) for results and artifacts.
The Verilator harness uses a zero-delay SDRAM protocol model because Verilator
does not elaborate the tri-state delays in the Micron model. The Icarus
testbench retains that Micron timing model, so it is the reference for SDRAM
command timing while Verilator provides fast functional coverage.
+4
View File
@@ -0,0 +1,4 @@
# Verilator uses functional standard-cell and IO models for ICS55.
+define+functional
/cache/retrosoc/pdk/ics55/ics55_h7cr_functional.v
/tech/ics55_io_sim_cells.sv
+1
View File
@@ -0,0 +1 @@
# ICS55 technology cells are supplied by the locked Liberty views in Yosys.
+5 -3
View File
@@ -15,6 +15,7 @@ module nmi2apb (
input logic clk_i,
input logic rst_n_i,
nmi_if.slave nmi,
output logic resp_err_o,
`include "soc_apb_ports.svh"
// verilog_format: on
);
@@ -24,7 +25,7 @@ module nmi2apb (
localparam FSM_ENAB = 2'd2;
logic [31:0] s_rd_data;
logic s_xfer_valid, s_xfer_ready;
logic s_xfer_valid, s_xfer_ready, s_xfer_error;
logic s_mem_valid_re;
logic [1:0] s_fsm_d, s_fsm_q;
@@ -63,8 +64,9 @@ module nmi2apb (
s_fsm_q
);
assign nmi.ready = nmi.valid && (s_fsm_q == FSM_ENAB) && s_xfer_ready;
assign nmi.rdata = {32{nmi.ready}} & s_rd_data;
assign nmi.ready = nmi.valid && (s_fsm_q == FSM_ENAB) && s_xfer_ready;
assign nmi.rdata = {32{nmi.ready}} & s_rd_data;
assign resp_err_o = nmi.ready && s_xfer_error;
// Capture slave-select one-hot at FSM_SETP for cleaner response mux.
`include "soc_apb_select_routes.svh"
+71 -26
View File
@@ -23,6 +23,8 @@
`define NATV_DMA_RESET 8'h20
`define NATV_DMA_STATUS 8'h24
`define NATV_DMA_FSM 8'h28
`define NATV_DMA_ERROR_STATUS 8'h2C
`define NATV_DMA_ERROR_ADDR 8'h30
// verilog_format: on
interface dma_hw_trg_if ();
@@ -43,7 +45,7 @@ module nmi_dma (
output logic dma_xfer_done_o,
dma_hw_trg_if.dut hw_trg,
nmi_if.slave nmi,
nmi_if.master nmi_dma
soc_nmi_if.master nmi_dma
// verilog_format: on
);
@@ -65,9 +67,15 @@ module nmi_dma (
logic s_dma_xferlen_en;
logic [31:0] s_dma_xferlen_d, s_dma_xferlen_q;
logic s_dma_status_d, s_dma_status_q;
logic s_dma_error_status_d, s_dma_error_status_q;
logic [2:0] s_dma_error_code_d, s_dma_error_code_q;
logic [31:0] s_dma_error_addr_d, s_dma_error_addr_q;
// common
logic s_xfer_start, s_xfer_stop, s_xfer_reset, s_xfer_done;
logic [1:0] s_xfer_fsm;
logic [ 1:0] s_xfer_fsm;
logic s_xfer_error;
logic [ 2:0] s_xfer_error_code;
logic [31:0] s_xfer_error_addr;
assign s_nmi_wr_hdshk = nmi.valid && (~s_nmi_ready_q) && (|nmi.wstrb);
@@ -180,6 +188,38 @@ module nmi_dma (
s_dma_status_q
);
always_comb begin
s_dma_error_status_d = s_dma_error_status_q;
if (s_nmi_wr_hdshk && nmi.addr[7:0] == `NATV_DMA_ERROR_STATUS && nmi.wstrb[0] &&
nmi.wdata[0]) begin
s_dma_error_status_d = 1'b0;
end else if (s_xfer_error) begin
s_dma_error_status_d = 1'b1;
end
end
dffr #(1) u_dma_error_status_dffr (
clk_i,
rst_n_i,
s_dma_error_status_d,
s_dma_error_status_q
);
assign s_dma_error_code_d = s_xfer_error_code;
dffer #(3) u_dma_error_code_dffer (
clk_i,
rst_n_i,
s_xfer_error,
s_dma_error_code_d,
s_dma_error_code_q
);
assign s_dma_error_addr_d = s_xfer_error_addr;
dffer #(32) u_dma_error_addr_dffer (
clk_i,
rst_n_i,
s_xfer_error,
s_dma_error_addr_d,
s_dma_error_addr_q
);
assign s_nmi_ready_d = nmi.valid && (~s_nmi_ready_q);
dffr #(1) u_nmi_ready_dffr (
@@ -193,15 +233,17 @@ module nmi_dma (
always_comb begin
s_nmi_rdata_d = s_nmi_rdata_q;
unique case (nmi.addr[7:0])
`NATV_DMA_MODE: s_nmi_rdata_d = {29'd0, s_dma_mode_q};
`NATV_DMA_SRCADDR: s_nmi_rdata_d = s_dma_srcaddr_q;
`NATV_DMA_SRCINCR: s_nmi_rdata_d = {31'd0, s_dma_srcincr_q};
`NATV_DMA_DSTADDR: s_nmi_rdata_d = s_dma_dstaddr_q;
`NATV_DMA_DSTINCR: s_nmi_rdata_d = {31'd0, s_dma_dstincr_q};
`NATV_DMA_XFERLEN: s_nmi_rdata_d = s_dma_xferlen_q;
`NATV_DMA_STATUS: s_nmi_rdata_d = {31'd0, s_dma_status_q};
`NATV_DMA_FSM: s_nmi_rdata_d = {30'd0, s_xfer_fsm};
default: s_nmi_rdata_d = s_nmi_rdata_q;
`NATV_DMA_MODE: s_nmi_rdata_d = {29'd0, s_dma_mode_q};
`NATV_DMA_SRCADDR: s_nmi_rdata_d = s_dma_srcaddr_q;
`NATV_DMA_SRCINCR: s_nmi_rdata_d = {31'd0, s_dma_srcincr_q};
`NATV_DMA_DSTADDR: s_nmi_rdata_d = s_dma_dstaddr_q;
`NATV_DMA_DSTINCR: s_nmi_rdata_d = {31'd0, s_dma_dstincr_q};
`NATV_DMA_XFERLEN: s_nmi_rdata_d = s_dma_xferlen_q;
`NATV_DMA_STATUS: s_nmi_rdata_d = {31'd0, s_dma_status_q};
`NATV_DMA_FSM: s_nmi_rdata_d = {30'd0, s_xfer_fsm};
`NATV_DMA_ERROR_STATUS: s_nmi_rdata_d = {28'd0, s_dma_error_code_q, s_dma_error_status_q};
`NATV_DMA_ERROR_ADDR: s_nmi_rdata_d = s_dma_error_addr_q;
default: s_nmi_rdata_d = s_nmi_rdata_q;
endcase
end
dffer #(32) u_nmi_rdata_dffer (
@@ -214,21 +256,24 @@ module nmi_dma (
dma_core u_dma_core (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mode_i (s_dma_mode_q),
.srcaddr_i(s_dma_srcaddr_q),
.srcincr_i(s_dma_srcincr_q),
.dstaddr_i(s_dma_dstaddr_q),
.dstincr_i(s_dma_dstincr_q),
.xferlen_i(s_dma_xferlen_q),
.start_i (s_xfer_start),
.stop_i (s_xfer_stop),
.reset_i (s_xfer_reset),
.done_o (s_xfer_done),
.fsm_o (s_xfer_fsm),
.hw_trg (hw_trg),
.nmi (nmi_dma)
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mode_i (s_dma_mode_q),
.srcaddr_i (s_dma_srcaddr_q),
.srcincr_i (s_dma_srcincr_q),
.dstaddr_i (s_dma_dstaddr_q),
.dstincr_i (s_dma_dstincr_q),
.xferlen_i (s_dma_xferlen_q),
.start_i (s_xfer_start),
.stop_i (s_xfer_stop),
.reset_i (s_xfer_reset),
.done_o (s_xfer_done),
.error_o (s_xfer_error),
.error_code_o(s_xfer_error_code),
.error_addr_o(s_xfer_error_addr),
.fsm_o (s_xfer_fsm),
.hw_trg (hw_trg),
.nmi (nmi_dma)
);
endmodule
+40 -15
View File
@@ -8,6 +8,8 @@
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`include "soc_nmi_defs.svh"
module dma_core (
// verilog_format: off
input logic clk_i,
@@ -22,9 +24,12 @@ module dma_core (
input logic stop_i,
input logic reset_i,
output logic done_o,
output logic error_o,
output logic [2:0] error_code_o,
output logic [31:0] error_addr_o,
output logic [1:0] fsm_o,
dma_hw_trg_if.dut hw_trg,
nmi_if.master nmi
soc_nmi_if.master nmi
// verilog_format: on
);
@@ -79,6 +84,9 @@ module dma_core (
s_nmi_wstrb_d = '0;
// common
done_o = '0;
error_o = 1'b0;
error_code_o = `SOC_NMI_RESP_OK;
error_addr_o = s_nmi_addr_q;
unique case (s_fsm_q)
FSM_IDLE: begin
if (start_i) begin
@@ -105,10 +113,17 @@ module dma_core (
default: s_nmi_valid_d = 1'b1;
endcase
s_nmi_addr_d = s_src_addr_q;
if (nmi.ready) begin
s_xfer_type_d = 1'b1;
s_xfer_done_d = 1'b1;
s_rd_data_d = nmi.rdata;
if (nmi.valid && nmi.ready) begin
s_nmi_valid_d = 1'b0;
if (nmi.resp_err) begin
s_fsm_d = FSM_IDLE;
error_o = 1'b1;
error_code_o = nmi.resp_code;
end else begin
s_xfer_type_d = 1'b1;
s_xfer_done_d = 1'b1;
s_rd_data_d = nmi.rdata;
end
end else if (nmi.valid) begin
s_xfer_done_d = 1'b0;
end
@@ -127,17 +142,24 @@ module dma_core (
s_nmi_addr_d = s_dst_addr_q;
s_nmi_wdata_d = s_rd_data_q;
s_nmi_wstrb_d = '1;
if (nmi.ready) begin
s_xfer_type_d = 1'b0;
s_xfer_done_d = 1'b1;
// when src rd+wr xfer done
if (s_xfer_cnt_q == xferlen_i) begin
s_xfer_cnt_d = '0;
s_fsm_d = FSM_DONE;
if (nmi.valid && nmi.ready) begin
s_nmi_valid_d = 1'b0;
if (nmi.resp_err) begin
s_fsm_d = FSM_IDLE;
error_o = 1'b1;
error_code_o = nmi.resp_code;
end else begin
s_xfer_cnt_d = s_xfer_cnt_q + 1'b1;
if (srcincr_i) s_src_addr_d = s_src_addr_q + 32'd4;
if (dstincr_i) s_dst_addr_d = s_dst_addr_q + 32'd4;
s_xfer_type_d = 1'b0;
s_xfer_done_d = 1'b1;
// when src rd+wr xfer done
if ((s_xfer_cnt_q + 32'd1) == xferlen_i) begin
s_xfer_cnt_d = '0;
s_fsm_d = FSM_DONE;
end else begin
s_xfer_cnt_d = s_xfer_cnt_q + 1'b1;
if (srcincr_i) s_src_addr_d = s_src_addr_q + 32'd4;
if (dstincr_i) s_dst_addr_d = s_dst_addr_q + 32'd4;
end
end
end else if (nmi.valid) s_xfer_done_d = 1'b0;
end
@@ -164,6 +186,9 @@ module dma_core (
s_nmi_wstrb_d = '0;
// common
done_o = '0;
error_o = 1'b0;
error_code_o = `SOC_NMI_RESP_OK;
error_addr_o = s_nmi_addr_q;
end
endcase
end
+189 -9
View File
@@ -10,6 +10,7 @@
`include "user_extensions.svh"
`include "mmap_define.svh"
`include "soc_nmi_defs.svh"
interface sysctrl_if ();
logic [`USER_CORESEL_WIDTH-1:0] core_sel_o;
@@ -18,16 +19,38 @@ interface sysctrl_if ();
logic user_bus_idle_i;
logic fault_access_i;
logic [ 1:0] fault_master_i;
logic [ 2:0] fault_code_i;
logic perf_enable_o;
logic perf_clear_o;
logic [ 63:0] perf_mgmt_wait_i;
logic [ 63:0] perf_user_wait_i;
logic [ 63:0] perf_dma_wait_i;
logic [ 63:0] perf_natv_wait_i;
logic [ 63:0] perf_apb_wait_i;
logic [ 63:0] perf_sdram_wait_i;
logic [ 63:0] perf_psram_wait_i;
logic [ 63:0] perf_flash_wait_i;
logic [ `USER_IPSEL_WIDTH-1:0] ip_sel_o;
modport dut(
input user_bus_idle_i,
input fault_access_i,
input fault_master_i,
input fault_code_i,
input perf_mgmt_wait_i,
input perf_user_wait_i,
input perf_dma_wait_i,
input perf_natv_wait_i,
input perf_apb_wait_i,
input perf_sdram_wait_i,
input perf_psram_wait_i,
input perf_flash_wait_i,
output core_sel_o,
output core_reset_o,
output user_bus_enable_o,
output ip_sel_o
output ip_sel_o,
output perf_enable_o,
output perf_clear_o
);
endinterface
@@ -47,8 +70,8 @@ module nmi_sysctrl (
typedef logic [7:0] sysctrl_offset_t;
localparam sysctrl_offset_t SYSCTRL_CORESEL_OFFSET = 8'h00;
localparam sysctrl_offset_t SYSCTRL_IPSEL_OFFSET = 8'h04;
localparam sysctrl_offset_t SYSCTRL_CORESEL_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_CORESEL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_IPSEL_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_IPSEL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_CFG_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PLL_CFG_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PLL_CMD_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PLL_CMD_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_STATUS_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_STATUS_OFFSET);
@@ -61,6 +84,41 @@ module nmi_sysctrl (
sysctrl_offset_t'(`SOC_SYSCTRL_USER_CORE_STATUS_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_MASTER_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_MASTER_OFFSET);
localparam sysctrl_offset_t SYSCTRL_FAULT_DETAIL_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_FAULT_DETAIL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_CTRL_OFFSET = sysctrl_offset_t'(`SOC_SYSCTRL_PERF_CTRL_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_MGMT_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_MGMT_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_USER_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_USER_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_USER_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_USER_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_DMA_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_DMA_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_DMA_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_DMA_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_NATV_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_NATV_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_NATV_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_NATV_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_APB_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_APB_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_APB_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_APB_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_SDRAM_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_SDRAM_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_SDRAM_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_SDRAM_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_PSRAM_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_PSRAM_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_PSRAM_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_PSRAM_WAIT_HI_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_FLASH_WAIT_LO_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_FLASH_WAIT_LO_OFFSET);
localparam sysctrl_offset_t SYSCTRL_PERF_FLASH_WAIT_HI_OFFSET =
sysctrl_offset_t'(`SOC_SYSCTRL_PERF_FLASH_WAIT_HI_OFFSET);
logic s_nmi_wr_hdshk, s_nmi_rd_hdshk;
logic s_nmi_ready_d, s_nmi_ready_q;
@@ -96,9 +154,20 @@ module nmi_sysctrl (
logic s_fault_pending_d, s_fault_pending_q;
logic s_fault_write_d, s_fault_write_q;
logic [2:0] s_fault_reason_d, s_fault_reason_q;
logic [2:0] s_fault_detail_d, s_fault_detail_q;
logic [31:0] s_fault_addr_d, s_fault_addr_q;
logic [31:0] s_fault_count_d, s_fault_count_q;
logic [1:0] s_fault_master_d, s_fault_master_q;
logic s_perf_enable_d, s_perf_enable_q;
logic s_perf_enable_en, s_perf_clear, s_perf_snapshot;
logic [63:0] s_perf_mgmt_wait_q;
logic [63:0] s_perf_user_wait_q;
logic [63:0] s_perf_dma_wait_q;
logic [63:0] s_perf_natv_wait_q;
logic [63:0] s_perf_apb_wait_q;
logic [63:0] s_perf_sdram_wait_q;
logic [63:0] s_perf_psram_wait_q;
logic [63:0] s_perf_flash_wait_q;
assign s_nmi_wr_hdshk = nmi.valid && (~s_nmi_ready_q) && (|nmi.wstrb);
assign s_nmi_rd_hdshk = nmi.valid && (~s_nmi_ready_q) && (~(|nmi.wstrb));
@@ -109,6 +178,8 @@ module nmi_sysctrl (
assign sysctrl.core_sel_o = s_sysctrl_coresel_q;
assign sysctrl.core_reset_o = s_user_reset_q;
assign sysctrl.user_bus_enable_o = s_user_running_q;
assign sysctrl.perf_enable_o = s_perf_enable_q;
assign sysctrl.perf_clear_o = s_perf_clear;
assign pll_ctrl.req_sel_o = s_pll_cfg_q;
assign pll_ctrl.req_valid_o = s_pll_req_valid_q;
assign pll_ctrl.rsp_ready_o = 1'b1;
@@ -311,6 +382,75 @@ module nmi_sysctrl (
s_pll_lock_q
);
assign s_perf_enable_en = s_nmi_wr_hdshk && nmi.addr[7:0] == SYSCTRL_PERF_CTRL_OFFSET &&
nmi.wstrb[0];
assign s_perf_enable_d = nmi.wdata[0];
assign s_perf_clear = s_perf_enable_en && nmi.wdata[1];
assign s_perf_snapshot = s_perf_enable_en && nmi.wdata[2];
dffer #(1) u_perf_enable_dffer (
clk_i,
rst_n_i,
s_perf_enable_en,
s_perf_enable_d,
s_perf_enable_q
);
dffer #(64) u_perf_mgmt_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_mgmt_wait_i,
s_perf_mgmt_wait_q
);
dffer #(64) u_perf_user_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_user_wait_i,
s_perf_user_wait_q
);
dffer #(64) u_perf_dma_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_dma_wait_i,
s_perf_dma_wait_q
);
dffer #(64) u_perf_natv_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_natv_wait_i,
s_perf_natv_wait_q
);
dffer #(64) u_perf_apb_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_apb_wait_i,
s_perf_apb_wait_q
);
dffer #(64) u_perf_sdram_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_sdram_wait_i,
s_perf_sdram_wait_q
);
dffer #(64) u_perf_psram_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_psram_wait_i,
s_perf_psram_wait_q
);
dffer #(64) u_perf_flash_wait_dffer (
clk_i,
rst_n_i,
s_perf_snapshot,
sysctrl.perf_flash_wait_i,
s_perf_flash_wait_q
);
assign s_fault_status_clear = s_nmi_wr_hdshk &&
nmi.addr[7:0] == SYSCTRL_FAULT_STATUS_OFFSET &&
nmi.wstrb[0] && nmi.wdata[0];
@@ -318,6 +458,7 @@ module nmi_sysctrl (
s_fault_pending_d = s_fault_pending_q;
s_fault_write_d = s_fault_write_q;
s_fault_reason_d = s_fault_reason_q;
s_fault_detail_d = s_fault_detail_q;
s_fault_addr_d = s_fault_addr_q;
s_fault_count_d = s_fault_count_q;
if (s_fault_status_clear) begin
@@ -325,9 +466,20 @@ module nmi_sysctrl (
end
if (fault_valid_i) begin
s_fault_pending_d = 1'b1;
s_fault_write_d = |fault_wstrb_i;
s_fault_reason_d = sysctrl.fault_access_i ? 3'd3 : (fault_reserved_i ? 3'd2 : 3'd1);
s_fault_addr_d = fault_addr_i;
if (~s_fault_pending_q || s_fault_status_clear) begin
s_fault_write_d = |fault_wstrb_i;
s_fault_detail_d = |sysctrl.fault_code_i ? sysctrl.fault_code_i :
sysctrl.fault_access_i ? `SOC_NMI_RESP_PROTERR :
fault_reserved_i ? `SOC_NMI_RESP_RESERVED : `SOC_NMI_RESP_DECERR;
unique case (s_fault_detail_d)
`SOC_NMI_RESP_RESERVED: s_fault_reason_d = 3'd2;
`SOC_NMI_RESP_PROTERR: s_fault_reason_d = 3'd3;
`SOC_NMI_RESP_SLVERR: s_fault_reason_d = 3'd4;
`SOC_NMI_RESP_TIMEOUT: s_fault_reason_d = 3'd5;
default: s_fault_reason_d = 3'd1;
endcase
s_fault_addr_d = fault_addr_i;
end
if (~(&s_fault_count_q)) begin
s_fault_count_d = s_fault_count_q + 32'd1;
end
@@ -351,6 +503,12 @@ module nmi_sysctrl (
s_fault_reason_d,
s_fault_reason_q
);
dffr #(3) u_fault_detail_dffr (
clk_i,
rst_n_i,
s_fault_detail_d,
s_fault_detail_q
);
dffr #(32) u_fault_addr_dffr (
clk_i,
rst_n_i,
@@ -363,11 +521,15 @@ module nmi_sysctrl (
s_fault_count_d,
s_fault_count_q
);
assign s_fault_master_d = sysctrl.fault_master_i;
dffer #(2) u_fault_master_dffer (
always_comb begin
s_fault_master_d = s_fault_master_q;
if (fault_valid_i && (~s_fault_pending_q || s_fault_status_clear)) begin
s_fault_master_d = sysctrl.fault_master_i;
end
end
dffr #(2) u_fault_master_dffr (
clk_i,
rst_n_i,
fault_valid_i,
s_fault_master_d,
s_fault_master_q
);
@@ -413,6 +575,24 @@ module nmi_sysctrl (
s_sysctrl_coresel_q
};
SYSCTRL_FAULT_MASTER_OFFSET: s_nmi_rdata_d = {30'd0, s_fault_master_q};
SYSCTRL_FAULT_DETAIL_OFFSET: s_nmi_rdata_d = {29'd0, s_fault_detail_q};
SYSCTRL_PERF_CTRL_OFFSET: s_nmi_rdata_d = {31'd0, s_perf_enable_q};
SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_mgmt_wait_q[31:0];
SYSCTRL_PERF_MGMT_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_mgmt_wait_q[63:32];
SYSCTRL_PERF_USER_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_user_wait_q[31:0];
SYSCTRL_PERF_USER_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_user_wait_q[63:32];
SYSCTRL_PERF_DMA_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_dma_wait_q[31:0];
SYSCTRL_PERF_DMA_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_dma_wait_q[63:32];
SYSCTRL_PERF_NATV_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_natv_wait_q[31:0];
SYSCTRL_PERF_NATV_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_natv_wait_q[63:32];
SYSCTRL_PERF_APB_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_apb_wait_q[31:0];
SYSCTRL_PERF_APB_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_apb_wait_q[63:32];
SYSCTRL_PERF_SDRAM_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_sdram_wait_q[31:0];
SYSCTRL_PERF_SDRAM_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_sdram_wait_q[63:32];
SYSCTRL_PERF_PSRAM_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_psram_wait_q[31:0];
SYSCTRL_PERF_PSRAM_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_psram_wait_q[63:32];
SYSCTRL_PERF_FLASH_WAIT_LO_OFFSET: s_nmi_rdata_d = s_perf_flash_wait_q[31:0];
SYSCTRL_PERF_FLASH_WAIT_HI_OFFSET: s_nmi_rdata_d = s_perf_flash_wait_q[63:32];
default: s_nmi_rdata_d = s_nmi_rdata_q;
endcase
// verilog_format: on
+48 -37
View File
@@ -28,12 +28,32 @@ def parse_integer(value: Any, field: str) -> int:
raise ValueError(f"{field} must be an integer")
def read_map(path: Path) -> tuple[int, list[dict[str, Any]]]:
def read_map(path: Path) -> tuple[int, list[dict[str, Any]], list[dict[str, Any]]]:
with path.open(encoding="utf-8") as source:
document = json.load(source)
if document.get("schema_version") != 1:
raise ValueError("schema_version must be 1")
cpu_reset = parse_integer(document.get("cpu_reset"), "cpu_reset")
registers = document.get("sysctrl_registers")
if not isinstance(registers, list) or not registers:
raise ValueError("sysctrl_registers must be a non-empty list")
normalized_registers: list[dict[str, Any]] = []
register_symbols: set[str] = set()
register_offsets: set[int] = set()
for index, register in enumerate(registers):
if not isinstance(register, dict):
raise ValueError(f"sysctrl_registers[{index}] must be an object")
symbol = register.get("symbol")
if not isinstance(symbol, str) or not symbol or not symbol.replace("_", "").isalnum():
raise ValueError(f"sysctrl_registers[{index}].symbol must be an uppercase identifier")
if symbol != symbol.upper() or symbol in register_symbols:
raise ValueError(f"sysctrl_registers[{index}].symbol must be unique and uppercase")
offset = parse_integer(register.get("offset"), f"sysctrl_registers[{index}].offset")
if offset < 0 or offset > 0xFFC or offset % 4 != 0 or offset in register_offsets:
raise ValueError(f"sysctrl_registers[{index}].offset must be unique and 32-bit aligned")
register_symbols.add(symbol)
register_offsets.add(offset)
normalized_registers.append({"symbol": symbol, "offset": offset})
regions = document.get("regions")
if not isinstance(regions, list) or not regions:
raise ValueError("regions must be a non-empty list")
@@ -85,7 +105,7 @@ def read_map(path: Path) -> tuple[int, list[dict[str, Any]]]:
if previous is not None and region["base"] <= previous["end"]:
raise ValueError(f"address-map overlap: {previous['symbol']} and {region['symbol']}")
previous = region
return cpu_reset, normalized
return cpu_reset, normalized, normalized_registers
def hex32(value: int) -> str:
@@ -109,7 +129,9 @@ def join_or(expressions: list[str]) -> str:
return " || \\\n ".join(expressions) if expressions else "1'b0"
def render_rtl(cpu_reset: int, regions: list[dict[str, Any]]) -> str:
def render_rtl(
cpu_reset: int, regions: list[dict[str, Any]], sysctrl_registers: list[dict[str, Any]]
) -> str:
lines = [
"// Generated by rtl/mini/address_map/generate_memory_map.py; do not edit.",
"`ifndef RETROSOC_GENERATED_MMAP_DEFINE_SVH",
@@ -153,25 +175,20 @@ def render_rtl(cpu_reset: int, regions: list[dict[str, Any]]) -> str:
f"`define SOC_USER_ADDR_READABLE(addr) ({join_or(user_readable)})",
f"`define SOC_USER_ADDR_WRITABLE(addr) ({join_or(user_writable)})",
]
lines += [
"",
"`define SOC_SYSCTRL_PLL_CFG_OFFSET 32'h00000008",
"`define SOC_SYSCTRL_PLL_CMD_OFFSET 32'h0000000C",
"`define SOC_SYSCTRL_FAULT_STATUS_OFFSET 32'h00000010",
"`define SOC_SYSCTRL_FAULT_ADDR_OFFSET 32'h00000014",
"`define SOC_SYSCTRL_FAULT_COUNT_OFFSET 32'h00000018",
"`define SOC_SYSCTRL_PLL_STATUS_OFFSET 32'h0000001C",
"`define SOC_SYSCTRL_USER_CORE_RESET_OFFSET 32'h00000020",
"`define SOC_SYSCTRL_USER_CORE_STATUS_OFFSET 32'h00000024",
"`define SOC_SYSCTRL_FAULT_MASTER_OFFSET 32'h00000028",
"",
"`endif",
"",
]
lines.append("")
for register in sysctrl_registers:
macro = f"SOC_SYSCTRL_{register['symbol']}_OFFSET"
lines.append(f"`define {macro:<31} {hex32(register['offset'])}")
lines += ["", "`endif", ""]
return "\n".join(lines)
def render_c(cpu_reset: int, regions: list[dict[str, Any]], have_sram_if: str) -> str:
def render_c(
cpu_reset: int,
regions: list[dict[str, Any]],
sysctrl_registers: list[dict[str, Any]],
have_sram_if: str,
) -> str:
lines = [
"/* Generated by rtl/mini/address_map/generate_memory_map.py; do not edit. */",
"#ifndef RETROSOC_GENERATED_MEMORY_MAP_H",
@@ -192,21 +209,12 @@ def render_c(cpu_reset: int, regions: list[dict[str, Any]], have_sram_if: str) -
f"#define RS_SOC_{symbol}_SIZE {c_hex32(region['size'])}",
f"#define RS_SOC_{symbol}_END {c_hex32(region['end'])}",
]
lines += [
"",
"#define RS_SOC_SYSCTRL_PLL_CFG_OFFSET UINT32_C(0x00000008)",
"#define RS_SOC_SYSCTRL_PLL_CMD_OFFSET UINT32_C(0x0000000C)",
"#define RS_SOC_SYSCTRL_FAULT_STATUS_OFFSET UINT32_C(0x00000010)",
"#define RS_SOC_SYSCTRL_FAULT_ADDR_OFFSET UINT32_C(0x00000014)",
"#define RS_SOC_SYSCTRL_FAULT_COUNT_OFFSET UINT32_C(0x00000018)",
"#define RS_SOC_SYSCTRL_PLL_STATUS_OFFSET UINT32_C(0x0000001C)",
"#define RS_SOC_SYSCTRL_USER_CORE_RESET_OFFSET UINT32_C(0x00000020)",
"#define RS_SOC_SYSCTRL_USER_CORE_STATUS_OFFSET UINT32_C(0x00000024)",
"#define RS_SOC_SYSCTRL_FAULT_MASTER_OFFSET UINT32_C(0x00000028)",
"",
"#endif",
"",
]
lines.append("")
lines.extend(
f"#define RS_SOC_SYSCTRL_{register['symbol']}_OFFSET {c_hex32(register['offset'])}"
for register in sysctrl_registers
)
lines += ["", "#endif", ""]
return "\n".join(lines)
@@ -244,12 +252,15 @@ def atomic_write(path: Path, content: str) -> None:
def generate(map_path: Path, output_dir: Path, have_sram_if: str) -> None:
cpu_reset, regions = read_map(map_path)
atomic_write(output_dir / "rtl" / "mmap_define.svh", render_rtl(cpu_reset, regions))
cpu_reset, regions, sysctrl_registers = read_map(map_path)
atomic_write(
output_dir / "rtl" / "mmap_define.svh",
render_rtl(cpu_reset, regions, sysctrl_registers),
)
atomic_write(output_dir / "memory_map.fl", f"+incdir+{output_dir / 'rtl'}\n")
atomic_write(
output_dir / "include" / "retrosoc" / "generated" / "memory_map.h",
render_c(cpu_reset, regions, have_sram_if),
render_c(cpu_reset, regions, sysctrl_registers, have_sram_if),
)
atomic_write(output_dir / "linker" / "memory_regions.ld", render_linker(regions))
+31
View File
@@ -1,6 +1,37 @@
{
"schema_version": 1,
"cpu_reset": "0x00000000",
"sysctrl_registers": [
{"symbol": "CORESEL", "offset": "0x00"},
{"symbol": "IPSEL", "offset": "0x04"},
{"symbol": "PLL_CFG", "offset": "0x08"},
{"symbol": "PLL_CMD", "offset": "0x0C"},
{"symbol": "FAULT_STATUS", "offset": "0x10"},
{"symbol": "FAULT_ADDR", "offset": "0x14"},
{"symbol": "FAULT_COUNT", "offset": "0x18"},
{"symbol": "PLL_STATUS", "offset": "0x1C"},
{"symbol": "USER_CORE_RESET", "offset": "0x20"},
{"symbol": "USER_CORE_STATUS", "offset": "0x24"},
{"symbol": "FAULT_MASTER", "offset": "0x28"},
{"symbol": "FAULT_DETAIL", "offset": "0x2C"},
{"symbol": "PERF_CTRL", "offset": "0x40"},
{"symbol": "PERF_MGMT_WAIT_LO", "offset": "0x44"},
{"symbol": "PERF_MGMT_WAIT_HI", "offset": "0x48"},
{"symbol": "PERF_USER_WAIT_LO", "offset": "0x4C"},
{"symbol": "PERF_USER_WAIT_HI", "offset": "0x50"},
{"symbol": "PERF_DMA_WAIT_LO", "offset": "0x54"},
{"symbol": "PERF_DMA_WAIT_HI", "offset": "0x58"},
{"symbol": "PERF_NATV_WAIT_LO", "offset": "0x5C"},
{"symbol": "PERF_NATV_WAIT_HI", "offset": "0x60"},
{"symbol": "PERF_APB_WAIT_LO", "offset": "0x64"},
{"symbol": "PERF_APB_WAIT_HI", "offset": "0x68"},
{"symbol": "PERF_SDRAM_WAIT_LO", "offset": "0x6C"},
{"symbol": "PERF_SDRAM_WAIT_HI", "offset": "0x70"},
{"symbol": "PERF_PSRAM_WAIT_LO", "offset": "0x74"},
{"symbol": "PERF_PSRAM_WAIT_HI", "offset": "0x78"},
{"symbol": "PERF_FLASH_WAIT_LO", "offset": "0x7C"},
{"symbol": "PERF_FLASH_WAIT_HI", "offset": "0x80"}
],
"regions": [
{"symbol": "FLASH", "base": "0x00000000", "size": "0x01000000", "route": "native", "kind": "active", "public": true, "linker": "FLASH", "user_access": "ro"},
{"symbol": "NMI_GPIO", "base": "0x10000000", "size": "0x00001000", "route": "native", "kind": "active", "public": true, "user_access": "rw"},
+37 -14
View File
@@ -25,20 +25,30 @@ module retrosoc_top (
input wire rst_n_i
);
wire s_clk;
wire s_rst_n;
wire s_psram_sck;
wire s_psram_nss0;
wire s_psram_dat0;
wire s_psram_dat1;
wire s_psram_dat2;
wire s_psram_dat3;
wire s_xpi_nss0_o;
wire s_xpi_sck_o;
wire s_xpi_dat0_io;
wire s_xpi_dat1_io;
wire s_xpi_dat2_io;
wire s_xpi_dat3_io;
wire s_clk;
wire s_rst_n;
wire s_psram_sck;
wire s_psram_nss0;
wire s_psram_dat0;
wire s_psram_dat1;
wire s_psram_dat2;
wire s_psram_dat3;
wire s_xpi_nss0_o;
wire s_xpi_sck_o;
wire s_xpi_dat0_io;
wire s_xpi_dat1_io;
wire s_xpi_dat2_io;
wire s_xpi_dat3_io;
wire s_sdram_clk;
wire s_sdram_cke;
wire s_sdram_cs_n;
wire s_sdram_ras_n;
wire s_sdram_cas_n;
wire s_sdram_we_n;
wire [ 1:0] s_sdram_ba;
wire [12:0] s_sdram_addr;
wire [ 1:0] s_sdram_dqm;
wire [15:0] s_sdram_dq;
assign s_clk = ext_clk_i;
assign s_rst_n = rst_n_i;
@@ -61,4 +71,17 @@ module retrosoc_top (
.sio ({s_psram_dat3, s_psram_dat2, s_psram_dat1, s_psram_dat0})
);
sdram_verilator_model u_sdram_verilator_model (
.clk_i (s_sdram_clk),
.cke_i (s_sdram_cke),
.cs_n_i (s_sdram_cs_n),
.ras_n_i(s_sdram_ras_n),
.cas_n_i(s_sdram_cas_n),
.we_n_i (s_sdram_we_n),
.ba_i (s_sdram_ba),
.addr_i (s_sdram_addr),
.dqm_i (s_sdram_dqm),
.dq_io (s_sdram_dq)
);
endmodule
@@ -0,0 +1,117 @@
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
// Zero-delay SDRAM model for the Verilator performance harness.
//
// The production Icarus testbench uses the Micron timing model. Verilator's
// no-timing mode cannot elaborate that tri-state timing model, so this model
// implements the controller-visible ACT/READ/WRITE burst protocol instead.
module sdram_verilator_model (
input logic clk_i,
input logic cke_i,
input logic cs_n_i,
input logic ras_n_i,
input logic cas_n_i,
input logic we_n_i,
input logic [ 1:0] ba_i,
// The Micron x16 model used by Icarus exposes a 12-bit row address.
// verilator lint_off UNUSEDSIGNAL
input logic [12:0] addr_i,
// verilator lint_on UNUSEDSIGNAL
input logic [ 1:0] dqm_i,
inout wire [15:0] dq_io
);
localparam int unsigned MEMORY_WORDS = 1 << 24;
localparam logic [3:0] CMD_ACTIVE = 4'b0011;
localparam logic [3:0] CMD_READ = 4'b0101;
localparam logic [3:0] CMD_WRITE = 4'b0100;
logic [11:0] s_row_q [ 0:3];
logic [15:0] s_memory [0:MEMORY_WORDS-1];
logic s_write_pending_q;
logic [23:0] s_write_addr_q;
logic s_read_pending_q;
logic s_read_drive_q;
logic s_read_second_q;
logic [23:0] s_read_addr_q;
logic [15:0] s_read_data_q;
logic [ 3:0] s_command;
assign s_command = {cs_n_i, ras_n_i, cas_n_i, we_n_i};
assign dq_io = s_read_drive_q ? s_read_data_q : 'z;
initial begin
s_write_pending_q = 1'b0;
s_read_pending_q = 1'b0;
s_read_drive_q = 1'b0;
s_read_second_q = 1'b0;
s_write_addr_q = '0;
s_read_addr_q = '0;
s_read_data_q = '0;
for (int unsigned bank = 0; bank < 4; ++bank) begin
s_row_q[bank] = '0;
end
end
function automatic logic [23:0] sdram_address(input logic [1:0] bank, input logic [11:0] row,
input logic [9:0] column);
sdram_address = {bank, row, column};
endfunction
task automatic write_beat(input logic [23:0] address);
begin
if (!dqm_i[0]) s_memory[address][7:0] <= dq_io[7:0];
if (!dqm_i[1]) s_memory[address][15:8] <= dq_io[15:8];
end
endtask
always_ff @(posedge clk_i) begin
if (cke_i) begin
if (s_read_drive_q) begin
if (!s_read_second_q) begin
s_read_data_q <= s_memory[s_read_addr_q+1'b1];
s_read_second_q <= 1'b1;
end else begin
s_read_drive_q <= 1'b0;
end
end else if (s_read_pending_q) begin
s_read_data_q <= s_memory[s_read_addr_q];
s_read_pending_q <= 1'b0;
s_read_drive_q <= 1'b1;
s_read_second_q <= 1'b0;
end
if (s_write_pending_q) begin
write_beat(s_write_addr_q);
s_write_pending_q <= 1'b0;
end
unique case (s_command)
CMD_ACTIVE: begin
s_row_q[ba_i] <= addr_i[11:0];
end
CMD_READ: begin
s_read_addr_q <= sdram_address(ba_i, s_row_q[ba_i], addr_i[9:0]);
s_read_pending_q <= 1'b1;
end
CMD_WRITE: begin
write_beat(sdram_address(ba_i, s_row_q[ba_i], addr_i[9:0]));
s_write_addr_q <= sdram_address(ba_i, s_row_q[ba_i], addr_i[9:0]) + 1'b1;
s_write_pending_q <= 1'b1;
end
default: begin
end
endcase
end
end
endmodule
+1
View File
@@ -3,6 +3,7 @@
/clusterip/common/rtl/interface/ahbl_if.sv
/clusterip/common/rtl/interface/nmi_if.sv
/clusterip/common/rtl/interface/ram_if.sv
/top/soc_nmi_if.sv
/clusterip/common/rtl/utils/register.sv
/clusterip/common/rtl/utils/lfsr.sv
/clusterip/common/rtl/utils/gray2bin.sv
+1
View File
@@ -42,6 +42,7 @@
/ip/native/peripheral/gpio.sv
/ip/native/interconnect/nmi2apb.sv
/ip/native/interconnect/ahbl2nmi.sv
/top/ahbl2soc_nmi.sv
/ip/native/interconnect/axi4l2nmi.sv
/ip/native/util/async_fifo.sv
/ip/native/util/fifo.sv
+1
View File
@@ -1,5 +1,6 @@
/top/apb4_if_bridge.sv
/top/gpio_pad_bridge.sv
/top/soc_nmi_regslice.sv
/top/core_wrapper.sv
/top/retrosoc.sv
/top/retrosoc_asic.sv
+6 -3
View File
@@ -23,9 +23,9 @@ module bus_formal_design (
output logic [ 1:0] arb_owner
);
nmi_if mgmt_nmi ();
nmi_if user_nmi ();
nmi_if dma_nmi ();
soc_nmi_if mgmt_nmi ();
soc_nmi_if user_nmi ();
soc_nmi_if dma_nmi ();
nmi_if natv_nmi ();
nmi_if apb_nmi ();
@@ -91,6 +91,9 @@ module bus_formal_design (
.user_bus_idle_o (user_idle),
.natv_nmi (natv_nmi),
.apb_nmi (apb_nmi),
.apb_resp_err_i (1'b0),
.perf_enable_i (1'b0),
.perf_clear_i (1'b0),
.fault_valid_o (fault_valid),
.fault_addr_o (fault_addr),
.fault_wstrb_o (fault_wstrb),
+2 -1
View File
@@ -30,11 +30,12 @@ def source_files(target: str) -> list[Path]:
common = [
COMMON_RTL / "interface/nmi_if.sv",
COMMON_RTL / "utils/register.sv",
TOP / "soc_nmi_if.sv",
]
if target == "bus":
return [
*common,
INTERCONNECT / "nmi_regslice.sv",
TOP / "soc_nmi_regslice.sv",
TOP / "bus.sv",
SCRIPT_DIR / "bus_formal.sv",
]
+49 -40
View File
@@ -54,48 +54,57 @@ module sysctrl_formal_design (
(* anyseq *)logic [ 3:0] f_fault_wstrb;
(* anyseq *)logic f_fault_reserved;
assign nmi.valid = f_nmi_valid;
assign nmi.addr = f_nmi_addr;
assign nmi.wdata = f_nmi_wdata;
assign nmi.wstrb = f_nmi_wstrb;
assign sysctrl.user_bus_idle_i = 1'b1;
assign sysctrl.fault_access_i = 1'b0;
assign sysctrl.fault_master_i = '0;
assign pll_ctrl.req_ready_i = f_pll_req_ready;
assign pll_ctrl.rsp_active_sel_i = f_pll_active_sel;
assign nmi.valid = f_nmi_valid;
assign nmi.addr = f_nmi_addr;
assign nmi.wdata = f_nmi_wdata;
assign nmi.wstrb = f_nmi_wstrb;
assign sysctrl.user_bus_idle_i = 1'b1;
assign sysctrl.fault_access_i = 1'b0;
assign sysctrl.fault_master_i = '0;
assign sysctrl.fault_code_i = f_fault_reserved ? `SOC_NMI_RESP_RESERVED : `SOC_NMI_RESP_DECERR;
assign sysctrl.perf_mgmt_wait_i = '0;
assign sysctrl.perf_user_wait_i = '0;
assign sysctrl.perf_dma_wait_i = '0;
assign sysctrl.perf_natv_wait_i = '0;
assign sysctrl.perf_apb_wait_i = '0;
assign sysctrl.perf_sdram_wait_i = '0;
assign sysctrl.perf_psram_wait_i = '0;
assign sysctrl.perf_flash_wait_i = '0;
assign pll_ctrl.req_ready_i = f_pll_req_ready;
assign pll_ctrl.rsp_active_sel_i = f_pll_active_sel;
assign pll_ctrl.rsp_active_valid_i = f_pll_active_valid;
assign pll_ctrl.rsp_safe_clk_i = f_pll_safe_clk;
assign pll_ctrl.rsp_pll_lock_i = f_pll_lock;
assign pll_ctrl.rsp_error_i = f_pll_rsp_error;
assign pll_ctrl.rsp_valid_i = f_pll_rsp_valid;
assign pll_ctrl.capable_i = f_pll_capable;
assign pll_ctrl.rsp_safe_clk_i = f_pll_safe_clk;
assign pll_ctrl.rsp_pll_lock_i = f_pll_lock;
assign pll_ctrl.rsp_error_i = f_pll_rsp_error;
assign pll_ctrl.rsp_valid_i = f_pll_rsp_valid;
assign pll_ctrl.capable_i = f_pll_capable;
assign nmi_valid = nmi.valid;
assign nmi_addr = nmi.addr;
assign nmi_wdata = nmi.wdata;
assign nmi_wstrb = nmi.wstrb;
assign nmi_ready = nmi.ready;
assign ip_sel = sysctrl.ip_sel_o;
assign core_sel = u_dut.s_sysctrl_coresel_q;
assign user_reset = u_dut.s_user_reset_q;
assign user_bus_enable = u_dut.s_user_running_q;
assign user_config_error = u_dut.s_user_config_error_q;
assign pll_cfg = u_dut.s_pll_cfg_q;
assign pll_req_valid = pll_ctrl.req_valid_o;
assign pll_req_ready = pll_ctrl.req_ready_i;
assign pll_busy = u_dut.s_pll_busy_q;
assign pll_error = u_dut.s_pll_error_q;
assign pll_error_reason = u_dut.s_pll_error_reason_q;
assign pll_rsp_valid = pll_ctrl.rsp_valid_i;
assign fault_valid = f_fault_valid;
assign fault_addr = f_fault_addr;
assign fault_wstrb = f_fault_wstrb;
assign fault_reserved = f_fault_reserved;
assign fault_pending = u_dut.s_fault_pending_q;
assign fault_write = u_dut.s_fault_write_q;
assign fault_reason = u_dut.s_fault_reason_q;
assign fault_addr_q = u_dut.s_fault_addr_q;
assign fault_count = u_dut.s_fault_count_q;
assign nmi_valid = nmi.valid;
assign nmi_addr = nmi.addr;
assign nmi_wdata = nmi.wdata;
assign nmi_wstrb = nmi.wstrb;
assign nmi_ready = nmi.ready;
assign ip_sel = sysctrl.ip_sel_o;
assign core_sel = u_dut.s_sysctrl_coresel_q;
assign user_reset = u_dut.s_user_reset_q;
assign user_bus_enable = u_dut.s_user_running_q;
assign user_config_error = u_dut.s_user_config_error_q;
assign pll_cfg = u_dut.s_pll_cfg_q;
assign pll_req_valid = pll_ctrl.req_valid_o;
assign pll_req_ready = pll_ctrl.req_ready_i;
assign pll_busy = u_dut.s_pll_busy_q;
assign pll_error = u_dut.s_pll_error_q;
assign pll_error_reason = u_dut.s_pll_error_reason_q;
assign pll_rsp_valid = pll_ctrl.rsp_valid_i;
assign fault_valid = f_fault_valid;
assign fault_addr = f_fault_addr;
assign fault_wstrb = f_fault_wstrb;
assign fault_reserved = f_fault_reserved;
assign fault_pending = u_dut.s_fault_pending_q;
assign fault_write = u_dut.s_fault_write_q;
assign fault_reason = u_dut.s_fault_reason_q;
assign fault_addr_q = u_dut.s_fault_addr_q;
assign fault_count = u_dut.s_fault_count_q;
nmi_sysctrl u_dut (
.clk_i (clk_i),
+5 -3
View File
@@ -133,9 +133,11 @@ module sysctrl_formal;
end
if ($past(rst_n_i && fault_valid)) begin
assert (fault_pending);
assert (fault_write == (|$past(fault_wstrb)));
assert (fault_reason == ($past(fault_reserved) ? 3'd2 : 3'd1));
assert (fault_addr_q == $past(fault_addr));
if (!$past(fault_pending)) begin
assert (fault_write == (|$past(fault_wstrb)));
assert (fault_reason == ($past(fault_reserved) ? 3'd2 : 3'd1));
assert (fault_addr_q == $past(fault_addr));
end
if (!$past(&fault_count)) begin
assert (fault_count == $past(fault_count) + 32'd1);
end
+12 -3
View File
@@ -17,6 +17,7 @@ SV_IDENTIFIER_RE = re.compile(r"[A-Za-z_][A-Za-z0-9_]*$")
SV_REFERENCE_RE = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*(?:\[[0-9]+\])?$")
SV_CONSTANT_RE = re.compile(r"(?:1'[bB][01]|'[01])$")
FABRIC_LINK_NAMES = ("mgmt", "user", "dma", "native", "apb")
SOC_NMI_FABRIC_LINK_NAMES = ("mgmt", "user", "dma")
IRQ_GROUP_NAMES = ("nmi", "apb")
IRQ_VECTOR_WIDTH = 32
COMPATIBILITY_IRQ_BINDINGS = (
@@ -676,9 +677,13 @@ def render_apb_select_routes(targets: list[ApbTarget]) -> str:
def render_apb_response_mux(targets: list[ApbTarget]) -> str:
lines = ["// Generated by rtl/mini/integration/generate_soc_topology.py; do not edit."]
for signal, expression in (("s_rd_data", "prdata"), ("s_xfer_ready", "pready")):
for signal, expression, width in (
("s_rd_data", "prdata", "32"),
("s_xfer_ready", "pready", "1"),
("s_xfer_error", "pslverr", "1"),
):
terms = [
f"({{{'32' if signal == 's_rd_data' else '1'}{{s_psel_q[{target.slot}]}}}} & "
f"({{{width}{{s_psel_q[{target.slot}]}}}} & "
f"{target.name}.{expression})"
for target in targets
]
@@ -688,7 +693,11 @@ def render_apb_response_mux(targets: list[ApbTarget]) -> str:
def render_fabric_interfaces(links: list[FabricLink]) -> str:
lines = ["// Generated by rtl/mini/integration/generate_soc_topology.py; do not edit."]
lines.extend(f" nmi_if {link.interface} ();" for link in links)
lines.extend(
f" {'soc_nmi_if' if link.name in SOC_NMI_FABRIC_LINK_NAMES else 'nmi_if'} "
f"{link.interface} ();"
for link in links
)
return "\n".join(lines) + "\n"
+3
View File
@@ -79,6 +79,7 @@ CRT_SRCS := $(ROOT_PATH)/crt/arch/riscv/startup.S \
$(ROOT_PATH)/crt/src/hal/i2c.c \
$(ROOT_PATH)/crt/src/hal/onewire.c \
$(ROOT_PATH)/crt/src/hal/dma.c \
$(ROOT_PATH)/crt/src/hal/perf.c \
$(ROOT_PATH)/crt/src/hal/lcd.c \
$(ROOT_PATH)/crt/src/hal/psram.c \
$(ROOT_PATH)/crt/src/hal/spisd.c \
@@ -93,6 +94,7 @@ endif
APP_SRCS :=
APP_INC_DIRS :=
APP_CFLAGS :=
APP_MK := $(ROOT_PATH)/app/apps/$(APP)/app.mk
ifeq ($(wildcard $(APP_MK)),)
@@ -100,6 +102,7 @@ $(error Application profile not found: $(APP_MK))
endif
include $(APP_MK)
CFLAGS += $(APP_CFLAGS)
APP_INC_DIRS += $(MPW_OUTPUT_DIR)
ifneq ($(filter RV32E RV32I,$(ISA)),)
+2
View File
@@ -15,6 +15,7 @@ SOC_VXXFILES += $(RTL_PATH)/dv/model/ESP_PSRAM64H.sv
SOC_VXXFILES += $(RTL_PATH)/dv/verilator/rtl/flash_read_binder.sv
SOC_VXXFILES += $(RTL_PATH)/dv/verilator/rtl/QSPIFlash.sv
SOC_VXXFILES += $(RTL_PATH)/dv/verilator/rtl/retrosoc_top.sv
SOC_VXXFILES += $(RTL_PATH)/dv/verilator/rtl/sdram_verilator_model.sv
SOC_VSRC_INCLPATH += -I$(SOC_VSRC_HOME)
VERILATOR ?= verilator
@@ -42,6 +43,7 @@ VERILATOR_EXTRA_SOURCES := $(RTL_PATH)/dv/model/ESP_PSRAM64H.sv \
$(RTL_PATH)/dv/verilator/rtl/flash_read_binder.sv \
$(RTL_PATH)/dv/verilator/rtl/QSPIFlash.sv \
$(RTL_PATH)/dv/verilator/rtl/retrosoc_top.sv \
$(RTL_PATH)/dv/verilator/rtl/sdram_verilator_model.sv \
$(SOC_CXXFILES) $(wildcard $(SOC_CSRC_HOME)/*.h) \
$(wildcard $(SOC_CSRC_HOME)/*.hpp)
+40 -1
View File
@@ -205,7 +205,46 @@
"xpi_dat0_io_pad": "s_xpi_dat0_io",
"xpi_dat1_io_pad": "s_xpi_dat1_io",
"xpi_dat2_io_pad": "s_xpi_dat2_io",
"xpi_dat3_io_pad": "s_xpi_dat3_io"
"xpi_dat3_io_pad": "s_xpi_dat3_io",
"sdram_clk_o_pad": "s_sdram_clk",
"sdram_cke_o_pad": "s_sdram_cke",
"sdram_cs_n_o_pad": "s_sdram_cs_n",
"sdram_ras_n_o_pad": "s_sdram_ras_n",
"sdram_cas_n_o_pad": "s_sdram_cas_n",
"sdram_we_n_o_pad": "s_sdram_we_n",
"sdram_ba0_o_pad": "s_sdram_ba[0]",
"sdram_ba1_o_pad": "s_sdram_ba[1]",
"sdram_addr0_o_pad": "s_sdram_addr[0]",
"sdram_addr1_o_pad": "s_sdram_addr[1]",
"sdram_addr2_o_pad": "s_sdram_addr[2]",
"sdram_addr3_o_pad": "s_sdram_addr[3]",
"sdram_addr4_o_pad": "s_sdram_addr[4]",
"sdram_addr5_o_pad": "s_sdram_addr[5]",
"sdram_addr6_o_pad": "s_sdram_addr[6]",
"sdram_addr7_o_pad": "s_sdram_addr[7]",
"sdram_addr8_o_pad": "s_sdram_addr[8]",
"sdram_addr9_o_pad": "s_sdram_addr[9]",
"sdram_addr10_o_pad": "s_sdram_addr[10]",
"sdram_addr11_o_pad": "s_sdram_addr[11]",
"sdram_addr12_o_pad": "s_sdram_addr[12]",
"sdram_dqm0_o_pad": "s_sdram_dqm[0]",
"sdram_dqm1_o_pad": "s_sdram_dqm[1]",
"sdram_dq0_io_pad": "s_sdram_dq[0]",
"sdram_dq1_io_pad": "s_sdram_dq[1]",
"sdram_dq2_io_pad": "s_sdram_dq[2]",
"sdram_dq3_io_pad": "s_sdram_dq[3]",
"sdram_dq4_io_pad": "s_sdram_dq[4]",
"sdram_dq5_io_pad": "s_sdram_dq[5]",
"sdram_dq6_io_pad": "s_sdram_dq[6]",
"sdram_dq7_io_pad": "s_sdram_dq[7]",
"sdram_dq8_io_pad": "s_sdram_dq[8]",
"sdram_dq9_io_pad": "s_sdram_dq[9]",
"sdram_dq10_io_pad": "s_sdram_dq[10]",
"sdram_dq11_io_pad": "s_sdram_dq[11]",
"sdram_dq12_io_pad": "s_sdram_dq[12]",
"sdram_dq13_io_pad": "s_sdram_dq[13]",
"sdram_dq14_io_pad": "s_sdram_dq[14]",
"sdram_dq15_io_pad": "s_sdram_dq[15]"
}
},
"tb": {
+148
View File
@@ -0,0 +1,148 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`include "soc_nmi_defs.svh"
// Management-core AHB-Lite to SoC NMI bridge. It is intentionally separate
// from the managed-compatible ahbl2nmi used by externally supplied user cores.
module ahbl2soc_nmi (
ahbl_if.slave ahbl,
soc_nmi_if.master nmi
);
localparam logic [1:0] AHBL_TRANS_NSEQ = 2'b10;
localparam logic [2:0] AHBL_SIZE_BYTE = 3'b000;
localparam logic [2:0] AHBL_SIZE_HWRD = 3'b001;
localparam logic AHBL_RESP_OKAY = 1'b0;
localparam logic AHBL_RESP_ERROR = 1'b1;
localparam logic [1:0] STATE_IDLE = 2'd0;
localparam logic [1:0] STATE_DATA = 2'd1;
localparam logic [1:0] STATE_WAIT = 2'd2;
logic [1:0] s_fsm_d, s_fsm_q;
logic [31:0] s_haddr_d, s_haddr_q;
logic s_hwrite_d, s_hwrite_q;
logic [2:0] s_hsize_d, s_hsize_q;
assign ahbl.hready = s_fsm_q == STATE_IDLE || nmi.ready;
assign ahbl.hresp = nmi.ready && nmi.resp_err ? AHBL_RESP_ERROR : AHBL_RESP_OKAY;
assign ahbl.hrdata = nmi.rdata;
assign nmi.valid = s_fsm_q != STATE_IDLE;
assign nmi.addr = {s_haddr_q[31:2], 2'b00};
always_comb begin
nmi.wstrb = '0;
nmi.wdata = '0;
if (s_hwrite_q) begin
unique case (s_hsize_q)
AHBL_SIZE_BYTE: begin
unique case (s_haddr_q[1:0])
2'd0: begin
nmi.wstrb = 4'b0001;
nmi.wdata = {24'd0, ahbl.hwdata[7:0]};
end
2'd1: begin
nmi.wstrb = 4'b0010;
nmi.wdata = {16'd0, ahbl.hwdata[7:0], 8'd0};
end
2'd2: begin
nmi.wstrb = 4'b0100;
nmi.wdata = {8'd0, ahbl.hwdata[7:0], 16'd0};
end
default: begin
nmi.wstrb = 4'b1000;
nmi.wdata = {ahbl.hwdata[7:0], 24'd0};
end
endcase
end
AHBL_SIZE_HWRD: begin
if (s_haddr_q[1]) begin
nmi.wstrb = 4'b1100;
nmi.wdata = {ahbl.hwdata[15:0], 16'd0};
end else begin
nmi.wstrb = 4'b0011;
nmi.wdata = {16'd0, ahbl.hwdata[15:0]};
end
end
default: begin
nmi.wstrb = 4'b1111;
nmi.wdata = ahbl.hwdata;
end
endcase
end
end
always_comb begin
s_fsm_d = s_fsm_q;
s_haddr_d = s_haddr_q;
s_hwrite_d = s_hwrite_q;
s_hsize_d = s_hsize_q;
unique case (s_fsm_q)
STATE_IDLE: begin
if (ahbl.htrans == AHBL_TRANS_NSEQ && ahbl.hready) begin
s_fsm_d = STATE_DATA;
s_haddr_d = ahbl.haddr;
s_hwrite_d = ahbl.hwrite;
s_hsize_d = ahbl.hsize;
end
end
STATE_DATA: begin
if (!nmi.ready) begin
s_fsm_d = STATE_WAIT;
end else if (ahbl.htrans == AHBL_TRANS_NSEQ) begin
s_haddr_d = ahbl.haddr;
s_hwrite_d = ahbl.hwrite;
s_hsize_d = ahbl.hsize;
end else begin
s_fsm_d = STATE_IDLE;
end
end
STATE_WAIT: begin
if (nmi.ready) begin
if (ahbl.htrans == AHBL_TRANS_NSEQ) begin
s_fsm_d = STATE_DATA;
s_haddr_d = ahbl.haddr;
s_hwrite_d = ahbl.hwrite;
s_hsize_d = ahbl.hsize;
end else begin
s_fsm_d = STATE_IDLE;
end
end
end
default: s_fsm_d = STATE_IDLE;
endcase
end
dffr #(2) u_fsm_dffr (
ahbl.hclk,
ahbl.hresetn,
s_fsm_d,
s_fsm_q
);
dffr #(32) u_haddr_dffr (
ahbl.hclk,
ahbl.hresetn,
s_haddr_d,
s_haddr_q
);
dffr #(1) u_hwrite_dffr (
ahbl.hclk,
ahbl.hresetn,
s_hwrite_d,
s_hwrite_q
);
dffr #(3) u_hsize_dffr (
ahbl.hclk,
ahbl.hresetn,
s_hsize_d,
s_hsize_q
);
endmodule
+168 -21
View File
@@ -9,6 +9,7 @@
// See the Mulan PSL v2 for more details.
`include "mmap_define.svh"
`include "soc_nmi_defs.svh"
module bus (
// verilog_format: off
@@ -17,19 +18,31 @@ module bus (
`ifdef HAVE_SRAM_IF
ram_if.master ram,
`endif
nmi_if.slave mgmt_nmi,
nmi_if.slave user_nmi,
nmi_if.slave dma_nmi,
soc_nmi_if.slave mgmt_nmi,
soc_nmi_if.slave user_nmi,
soc_nmi_if.slave dma_nmi,
input logic user_bus_enable_i,
output logic user_bus_idle_o,
nmi_if.master natv_nmi,
nmi_if.master apb_nmi,
input logic apb_resp_err_i,
input logic perf_enable_i,
input logic perf_clear_i,
output logic fault_valid_o,
output logic [31:0] fault_addr_o,
output logic [3:0] fault_wstrb_o,
output logic fault_reserved_o,
output logic fault_access_o,
output logic [1:0] fault_master_o
output logic [1:0] fault_master_o,
output logic [2:0] fault_code_o,
output logic [63:0] perf_mgmt_wait_o,
output logic [63:0] perf_user_wait_o,
output logic [63:0] perf_dma_wait_o,
output logic [63:0] perf_natv_wait_o,
output logic [63:0] perf_apb_wait_o,
output logic [63:0] perf_sdram_wait_o,
output logic [63:0] perf_psram_wait_o,
output logic [63:0] perf_flash_wait_o
// verilog_format: on
);
@@ -38,14 +51,25 @@ module bus (
localparam logic [1:0] MSTR_DMA = 2'd2;
logic s_natv_sel, s_apb_sel, s_ram_sel, s_fault_sel, s_access_denied;
logic s_target_resp_err, s_rsp_err, s_rsp_ready, s_fault_event;
logic [2:0] s_rsp_code;
logic s_ram_valid, s_ram_ready;
logic s_mstr_lock_d, s_mstr_lock_q;
logic [1:0] s_mstr_id_d, s_mstr_id_q;
logic [1:0] s_mstr_rr_d, s_mstr_rr_q;
logic s_user_request;
logic s_user_access_allowed;
nmi_if u_mstr_nmi_if ();
nmi_if u_mstr_rgsl_nmi_if ();
soc_nmi_if u_mstr_nmi_if ();
soc_nmi_if u_mstr_rgsl_nmi_if ();
logic [63:0] s_perf_mgmt_wait_d, s_perf_mgmt_wait_q;
logic [63:0] s_perf_user_wait_d, s_perf_user_wait_q;
logic [63:0] s_perf_dma_wait_d, s_perf_dma_wait_q;
logic [63:0] s_perf_natv_wait_d, s_perf_natv_wait_q;
logic [63:0] s_perf_apb_wait_d, s_perf_apb_wait_q;
logic [63:0] s_perf_sdram_wait_d, s_perf_sdram_wait_q;
logic [63:0] s_perf_psram_wait_d, s_perf_psram_wait_q;
logic [63:0] s_perf_flash_wait_d, s_perf_flash_wait_q;
assign s_user_request = user_bus_enable_i && user_nmi.valid;
assign user_bus_idle_o = ~s_mstr_lock_q || s_mstr_id_q != MSTR_USER;
@@ -135,13 +159,19 @@ module bus (
assign mgmt_nmi.ready = s_mstr_lock_q && s_mstr_id_q == MSTR_MGMT ? u_mstr_nmi_if.ready : '0;
assign mgmt_nmi.rdata = s_mstr_lock_q && s_mstr_id_q == MSTR_MGMT ? u_mstr_nmi_if.rdata : '0;
assign mgmt_nmi.resp_err = s_mstr_lock_q && s_mstr_id_q == MSTR_MGMT ? u_mstr_nmi_if.resp_err : 1'b0;
assign mgmt_nmi.resp_code = s_mstr_lock_q && s_mstr_id_q == MSTR_MGMT ? u_mstr_nmi_if.resp_code : `SOC_NMI_RESP_OK;
assign user_nmi.ready = s_mstr_lock_q && s_mstr_id_q == MSTR_USER ? u_mstr_nmi_if.ready : '0;
assign user_nmi.rdata = s_mstr_lock_q && s_mstr_id_q == MSTR_USER ? u_mstr_nmi_if.rdata : '0;
assign user_nmi.resp_err = s_mstr_lock_q && s_mstr_id_q == MSTR_USER ? u_mstr_nmi_if.resp_err : 1'b0;
assign user_nmi.resp_code = s_mstr_lock_q && s_mstr_id_q == MSTR_USER ? u_mstr_nmi_if.resp_code : `SOC_NMI_RESP_OK;
assign dma_nmi.ready = s_mstr_lock_q && s_mstr_id_q == MSTR_DMA ? u_mstr_nmi_if.ready : '0;
assign dma_nmi.rdata = s_mstr_lock_q && s_mstr_id_q == MSTR_DMA ? u_mstr_nmi_if.rdata : '0;
assign dma_nmi.resp_err = s_mstr_lock_q && s_mstr_id_q == MSTR_DMA ? u_mstr_nmi_if.resp_err : 1'b0;
assign dma_nmi.resp_code = s_mstr_lock_q && s_mstr_id_q == MSTR_DMA ? u_mstr_nmi_if.resp_code : `SOC_NMI_RESP_OK;
// verilog_format: on
nmi_regslice u_nmi_regslice (
soc_nmi_regslice u_soc_nmi_regslice (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.nmi_slv(u_mstr_nmi_if),
@@ -177,16 +207,37 @@ module bus (
assign ram.wstrb = s_ram_valid ? u_mstr_rgsl_nmi_if.wstrb : '0;
`else
assign s_ram_sel = 1'b0;
assign s_ram_valid = 1'b0;
assign s_ram_ready = 1'b0;
`endif
assign s_fault_sel = u_mstr_rgsl_nmi_if.valid &&
(s_access_denied || ~(s_natv_sel || s_apb_sel || s_ram_sel));
assign fault_valid_o = s_fault_sel;
assign fault_addr_o = u_mstr_rgsl_nmi_if.addr;
assign fault_wstrb_o = u_mstr_rgsl_nmi_if.wstrb;
assign fault_reserved_o = `SOC_ADDR_IS_RESERVED(u_mstr_rgsl_nmi_if.addr);
assign fault_access_o = s_access_denied;
assign fault_master_o = s_mstr_id_q;
assign s_fault_sel = u_mstr_rgsl_nmi_if.valid &&
(s_access_denied || ~(s_natv_sel || s_apb_sel || s_ram_sel));
assign s_target_resp_err = apb_nmi.valid && apb_nmi.ready && apb_resp_err_i;
assign s_rsp_ready = s_fault_sel || (natv_nmi.valid && natv_nmi.ready) ||
(apb_nmi.valid && apb_nmi.ready) || s_ram_ready;
always_comb begin
s_rsp_err = s_target_resp_err;
s_rsp_code = s_target_resp_err ? `SOC_NMI_RESP_SLVERR : `SOC_NMI_RESP_OK;
if (s_fault_sel) begin
s_rsp_err = 1'b1;
if (s_access_denied) begin
s_rsp_code = `SOC_NMI_RESP_PROTERR;
end else if (`SOC_ADDR_IS_RESERVED(u_mstr_rgsl_nmi_if.addr)) begin
s_rsp_code = `SOC_NMI_RESP_RESERVED;
end else begin
s_rsp_code = `SOC_NMI_RESP_DECERR;
end
end
end
assign s_fault_event = u_mstr_rgsl_nmi_if.valid && s_rsp_ready && s_rsp_err;
assign fault_valid_o = s_fault_event;
assign fault_addr_o = u_mstr_rgsl_nmi_if.addr;
assign fault_wstrb_o = u_mstr_rgsl_nmi_if.wstrb;
assign fault_reserved_o = s_rsp_code == `SOC_NMI_RESP_RESERVED;
assign fault_access_o = s_rsp_code == `SOC_NMI_RESP_PROTERR;
assign fault_master_o = s_mstr_id_q;
assign fault_code_o = s_rsp_code;
// verilog_format: on
`ifdef HAVE_SRAM_MACRO
@@ -196,27 +247,123 @@ module bus (
s_ram_valid,
s_ram_ready
);
`else
assign s_ram_ready = s_ram_valid;
`endif
// verilog_format: off
`ifdef HAVE_SRAM_IF
assign u_mstr_rgsl_nmi_if.ready = s_access_denied || (natv_nmi.valid && natv_nmi.ready) ||
(apb_nmi.valid && apb_nmi.ready) || s_ram_ready || s_fault_sel;
assign u_mstr_rgsl_nmi_if.ready = s_rsp_ready;
`else
assign u_mstr_rgsl_nmi_if.ready = s_access_denied || (natv_nmi.valid && natv_nmi.ready) ||
(apb_nmi.valid && apb_nmi.ready) || s_fault_sel;
assign u_mstr_rgsl_nmi_if.ready = s_rsp_ready;
`endif
`ifdef HAVE_SRAM_IF
assign u_mstr_rgsl_nmi_if.rdata = s_access_denied ? '0 :
assign u_mstr_rgsl_nmi_if.rdata = s_rsp_err ? '0 :
(natv_nmi.valid && natv_nmi.ready) ? natv_nmi.rdata :
(apb_nmi.valid && apb_nmi.ready) ? apb_nmi.rdata :
s_ram_ready ? ram.rdata : '0;
`else
assign u_mstr_rgsl_nmi_if.rdata = s_access_denied ? '0 :
assign u_mstr_rgsl_nmi_if.rdata = s_rsp_err ? '0 :
(natv_nmi.valid && natv_nmi.ready) ? natv_nmi.rdata :
(apb_nmi.valid && apb_nmi.ready) ? apb_nmi.rdata : '0;
`endif
assign u_mstr_rgsl_nmi_if.resp_err = s_rsp_ready && s_rsp_err;
assign u_mstr_rgsl_nmi_if.resp_code = s_rsp_ready ? s_rsp_code : `SOC_NMI_RESP_OK;
// verilog_format: on
always_comb begin
s_perf_mgmt_wait_d = s_perf_mgmt_wait_q;
s_perf_user_wait_d = s_perf_user_wait_q;
s_perf_dma_wait_d = s_perf_dma_wait_q;
s_perf_natv_wait_d = s_perf_natv_wait_q;
s_perf_apb_wait_d = s_perf_apb_wait_q;
s_perf_sdram_wait_d = s_perf_sdram_wait_q;
s_perf_psram_wait_d = s_perf_psram_wait_q;
s_perf_flash_wait_d = s_perf_flash_wait_q;
if (perf_clear_i) begin
s_perf_mgmt_wait_d = '0;
s_perf_user_wait_d = '0;
s_perf_dma_wait_d = '0;
s_perf_natv_wait_d = '0;
s_perf_apb_wait_d = '0;
s_perf_sdram_wait_d = '0;
s_perf_psram_wait_d = '0;
s_perf_flash_wait_d = '0;
end else if (perf_enable_i && u_mstr_rgsl_nmi_if.valid && !s_rsp_ready) begin
unique case (s_mstr_id_q)
MSTR_MGMT: s_perf_mgmt_wait_d = s_perf_mgmt_wait_q + 1'b1;
MSTR_USER: s_perf_user_wait_d = s_perf_user_wait_q + 1'b1;
default: s_perf_dma_wait_d = s_perf_dma_wait_q + 1'b1;
endcase
if (s_natv_sel) s_perf_natv_wait_d = s_perf_natv_wait_q + 1'b1;
if (s_apb_sel) s_perf_apb_wait_d = s_perf_apb_wait_q + 1'b1;
if (`SOC_ADDR_IS_SDRAM(u_mstr_rgsl_nmi_if.addr)) begin
s_perf_sdram_wait_d = s_perf_sdram_wait_q + 1'b1;
end
if (`SOC_ADDR_IS_PSRAM(u_mstr_rgsl_nmi_if.addr)) begin
s_perf_psram_wait_d = s_perf_psram_wait_q + 1'b1;
end
if (`SOC_ADDR_IS_FLASH(u_mstr_rgsl_nmi_if.addr)) begin
s_perf_flash_wait_d = s_perf_flash_wait_q + 1'b1;
end
end
end
dffr #(64) u_perf_mgmt_wait_dffr (
clk_i,
rst_n_i,
s_perf_mgmt_wait_d,
s_perf_mgmt_wait_q
);
dffr #(64) u_perf_user_wait_dffr (
clk_i,
rst_n_i,
s_perf_user_wait_d,
s_perf_user_wait_q
);
dffr #(64) u_perf_dma_wait_dffr (
clk_i,
rst_n_i,
s_perf_dma_wait_d,
s_perf_dma_wait_q
);
dffr #(64) u_perf_natv_wait_dffr (
clk_i,
rst_n_i,
s_perf_natv_wait_d,
s_perf_natv_wait_q
);
dffr #(64) u_perf_apb_wait_dffr (
clk_i,
rst_n_i,
s_perf_apb_wait_d,
s_perf_apb_wait_q
);
dffr #(64) u_perf_sdram_wait_dffr (
clk_i,
rst_n_i,
s_perf_sdram_wait_d,
s_perf_sdram_wait_q
);
dffr #(64) u_perf_psram_wait_dffr (
clk_i,
rst_n_i,
s_perf_psram_wait_d,
s_perf_psram_wait_q
);
dffr #(64) u_perf_flash_wait_dffr (
clk_i,
rst_n_i,
s_perf_flash_wait_d,
s_perf_flash_wait_q
);
assign perf_mgmt_wait_o = s_perf_mgmt_wait_q;
assign perf_user_wait_o = s_perf_user_wait_q;
assign perf_dma_wait_o = s_perf_dma_wait_q;
assign perf_natv_wait_o = s_perf_natv_wait_q;
assign perf_apb_wait_o = s_perf_apb_wait_q;
assign perf_sdram_wait_o = s_perf_sdram_wait_q;
assign perf_psram_wait_o = s_perf_psram_wait_q;
assign perf_flash_wait_o = s_perf_flash_wait_q;
endmodule
+1 -1
View File
@@ -13,7 +13,7 @@ module core_wrapper (
input logic clk_i,
input logic rst_n_i,
input logic [31:0] irq_i,
nmi_if.master nmi
soc_nmi_if.master nmi
// verilog_format: on
);
+5 -3
View File
@@ -28,6 +28,7 @@ module ip_apb_wrapper (
ps2_if.dut ps2,
input logic [`USER_IPSEL_WIDTH-1:0] ip_sel_i,
user_gpio_if.user_ip user_gpio,
output logic nmi_resp_err_o,
output logic [`SOC_IRQ_APB_WIDTH-1:0] irq_o
// verilog_format: on
);
@@ -63,9 +64,10 @@ module ip_apb_wrapper (
`include "soc_apb_irq_bindings.svh"
nmi2apb u_nmi2apb (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.nmi (nmi),
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.nmi (nmi),
.resp_err_o(nmi_resp_err_o),
`include "soc_apb_connections.svh"
);
+1 -1
View File
@@ -27,7 +27,7 @@ module ip_nmi_wrapper (
i2s_if.dut i2s,
onewire_if.dut onewire,
xpi_if.dut xpi,
nmi_if.master dma_nmi,
soc_nmi_if.master dma_nmi,
sysctrl_if.dut sysctrl,
pll_ctrl_if.sysctrl pll_ctrl,
sdram_if.dut sdram,
+2 -2
View File
@@ -15,7 +15,7 @@ module mgmt_core_wrapper (
input logic clk_i,
input logic rst_n_i,
input logic [31:0] irq_i,
nmi_if.master nmi
soc_nmi_if.master nmi
// verilog_format: on
);
@@ -62,7 +62,7 @@ module mgmt_core_wrapper (
logic s_pwrup_req;
// verilog_format: off
ahbl_if u_ahbl_if (clk_i, rst_n_i);
ahbl2nmi u_ahbl2nmi (u_ahbl_if, nmi);
ahbl2soc_nmi u_ahbl2soc_nmi (u_ahbl_if, nmi);
// verilog_format: on
hazard3_cpu_1port #(
+50 -14
View File
@@ -61,10 +61,33 @@ module retrosoc (
logic s_bus_fault_reserved;
logic s_bus_fault_access;
logic [ 1:0] s_bus_fault_master;
logic [ 2:0] s_bus_fault_code;
logic s_apb_resp_err;
logic s_perf_enable;
logic s_perf_clear;
logic [ 63:0] s_perf_mgmt_wait;
logic [ 63:0] s_perf_user_wait;
logic [ 63:0] s_perf_dma_wait;
logic [ 63:0] s_perf_natv_wait;
logic [ 63:0] s_perf_apb_wait;
logic [ 63:0] s_perf_sdram_wait;
logic [ 63:0] s_perf_psram_wait;
logic [ 63:0] s_perf_flash_wait;
logic [`SOC_IRQ_VECTOR_WIDTH-1:0] s_user_irq;
assign u_sysctrl_if.fault_access_i = s_bus_fault_access;
assign u_sysctrl_if.fault_master_i = s_bus_fault_master;
assign u_sysctrl_if.fault_access_i = s_bus_fault_access;
assign u_sysctrl_if.fault_master_i = s_bus_fault_master;
assign u_sysctrl_if.fault_code_i = s_bus_fault_code;
assign s_perf_enable = u_sysctrl_if.perf_enable_o;
assign s_perf_clear = u_sysctrl_if.perf_clear_o;
assign u_sysctrl_if.perf_mgmt_wait_i = s_perf_mgmt_wait;
assign u_sysctrl_if.perf_user_wait_i = s_perf_user_wait;
assign u_sysctrl_if.perf_dma_wait_i = s_perf_dma_wait;
assign u_sysctrl_if.perf_natv_wait_i = s_perf_natv_wait;
assign u_sysctrl_if.perf_apb_wait_i = s_perf_apb_wait;
assign u_sysctrl_if.perf_sdram_wait_i = s_perf_sdram_wait;
assign u_sysctrl_if.perf_psram_wait_i = s_perf_psram_wait;
assign u_sysctrl_if.perf_flash_wait_i = s_perf_flash_wait;
gpio_pad_bridge u_gpio_pad_bridge (
.inner(u_gpio_if),
@@ -103,12 +126,24 @@ core_wrapper u_core_wrapper (
.user_bus_enable_i(u_sysctrl_if.user_bus_enable_o),
.user_bus_idle_o (u_sysctrl_if.user_bus_idle_i),
`include "soc_bus_fabric.svh"
.apb_resp_err_i (s_apb_resp_err),
.perf_enable_i (s_perf_enable),
.perf_clear_i (s_perf_clear),
.fault_valid_o (s_bus_fault_valid),
.fault_addr_o (s_bus_fault_addr),
.fault_wstrb_o (s_bus_fault_wstrb),
.fault_reserved_o (s_bus_fault_reserved),
.fault_access_o (s_bus_fault_access),
.fault_master_o (s_bus_fault_master)
.fault_master_o (s_bus_fault_master),
.fault_code_o (s_bus_fault_code),
.perf_mgmt_wait_o (s_perf_mgmt_wait),
.perf_user_wait_o (s_perf_user_wait),
.perf_dma_wait_o (s_perf_dma_wait),
.perf_natv_wait_o (s_perf_natv_wait),
.perf_apb_wait_o (s_perf_apb_wait),
.perf_sdram_wait_o(s_perf_sdram_wait),
.perf_psram_wait_o(s_perf_psram_wait),
.perf_flash_wait_o(s_perf_flash_wait)
);
ip_nmi_wrapper u_ip_nmi_wrapper (
@@ -141,18 +176,19 @@ core_wrapper u_core_wrapper (
);
ip_apb_wrapper u_ip_apb_wrapper (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.clk_aud_i (clk_aud_i),
.rst_aud_n_i(rst_aud_n_i),
.tmr_capch_i(s_tmr_capch),
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.clk_aud_i (clk_aud_i),
.rst_aud_n_i (rst_aud_n_i),
.tmr_capch_i (s_tmr_capch),
`include "soc_ip_apb_wrapper_fabric.svh"
.uart (u_uart1_if),
.pwm (u_pwm_if),
.ps2 (u_ps2_if),
.ip_sel_i (u_sysctrl_if.ip_sel_o),
.user_gpio (u_user_gpio_if),
.irq_o (s_apb_irq)
.uart (u_uart1_if),
.pwm (u_pwm_if),
.ps2 (u_ps2_if),
.ip_sel_i (u_sysctrl_if.ip_sel_o),
.user_gpio (u_user_gpio_if),
.nmi_resp_err_o(s_apb_resp_err),
.irq_o (s_apb_irq)
);
endmodule
+21
View File
@@ -0,0 +1,21 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`ifndef RETROSOC_SOC_NMI_DEFS_SVH
`define RETROSOC_SOC_NMI_DEFS_SVH
`define SOC_NMI_RESP_OK 3'd0
`define SOC_NMI_RESP_DECERR 3'd1
`define SOC_NMI_RESP_PROTERR 3'd2
`define SOC_NMI_RESP_SLVERR 3'd3
`define SOC_NMI_RESP_TIMEOUT 3'd4
`define SOC_NMI_RESP_RESERVED 3'd5
`endif
+52
View File
@@ -0,0 +1,52 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`ifndef RETROSOC_SOC_NMI_IF_SV
`define RETROSOC_SOC_NMI_IF_SV
`include "soc_nmi_defs.svh"
// SoC-owned NMI fabric contract. Native IP remains on ClusterIP's nmi_if;
// this interface adds a response status only on the SoC master side.
interface soc_nmi_if ();
logic valid;
logic [31:0] addr;
logic [31:0] wdata;
logic [ 3:0] wstrb;
logic [31:0] rdata;
logic ready;
logic resp_err;
logic [ 2:0] resp_code;
modport slave(
input valid,
input addr,
input wdata,
input wstrb,
output rdata,
output ready,
output resp_err,
output resp_code
);
modport master(
output valid,
output addr,
output wdata,
output wstrb,
input rdata,
input ready,
input resp_err,
input resp_code
);
endinterface
`endif
+141
View File
@@ -0,0 +1,141 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`include "soc_nmi_defs.svh"
module soc_nmi_regslice (
// verilog_format: off
input logic clk_i,
input logic rst_n_i,
soc_nmi_if.slave nmi_slv,
soc_nmi_if.master nmi_mst
// verilog_format: on
);
localparam logic [1:0] FSM_IDLE = 2'd0;
localparam logic [1:0] FSM_REQ = 2'd1;
localparam logic [1:0] FSM_RESP = 2'd2;
logic [1:0] s_fsm_d, s_fsm_q;
logic s_nmi_mst_valid_d, s_nmi_mst_valid_q;
logic [31:0] s_nmi_mst_addr_d, s_nmi_mst_addr_q;
logic [31:0] s_nmi_mst_wdata_d, s_nmi_mst_wdata_q;
logic [3:0] s_nmi_mst_wstrb_d, s_nmi_mst_wstrb_q;
logic [31:0] s_nmi_mst_rdata_d, s_nmi_mst_rdata_q;
logic s_nmi_mst_ready_d, s_nmi_mst_ready_q;
logic s_nmi_mst_resp_err_d, s_nmi_mst_resp_err_q;
logic [2:0] s_nmi_mst_resp_code_d, s_nmi_mst_resp_code_q;
assign nmi_mst.valid = s_nmi_mst_valid_q;
assign nmi_mst.addr = s_nmi_mst_addr_q;
assign nmi_mst.wdata = s_nmi_mst_wdata_q;
assign nmi_mst.wstrb = s_nmi_mst_wstrb_q;
always_comb begin
s_fsm_d = s_fsm_q;
s_nmi_mst_valid_d = s_nmi_mst_valid_q;
s_nmi_mst_addr_d = s_nmi_mst_addr_q;
s_nmi_mst_wdata_d = s_nmi_mst_wdata_q;
s_nmi_mst_wstrb_d = s_nmi_mst_wstrb_q;
s_nmi_mst_ready_d = s_nmi_mst_ready_q;
s_nmi_mst_rdata_d = s_nmi_mst_rdata_q;
s_nmi_mst_resp_err_d = s_nmi_mst_resp_err_q;
s_nmi_mst_resp_code_d = s_nmi_mst_resp_code_q;
nmi_slv.ready = 1'b0;
nmi_slv.rdata = '0;
nmi_slv.resp_err = 1'b0;
nmi_slv.resp_code = `SOC_NMI_RESP_OK;
unique case (s_fsm_q)
FSM_IDLE: begin
if (nmi_slv.valid) begin
s_fsm_d = FSM_REQ;
s_nmi_mst_valid_d = 1'b1;
s_nmi_mst_addr_d = nmi_slv.addr;
s_nmi_mst_wdata_d = nmi_slv.wdata;
s_nmi_mst_wstrb_d = nmi_slv.wstrb;
end
end
FSM_REQ: begin
if (nmi_mst.ready) begin
s_fsm_d = FSM_RESP;
s_nmi_mst_valid_d = 1'b0;
s_nmi_mst_ready_d = 1'b1;
s_nmi_mst_rdata_d = nmi_mst.rdata;
s_nmi_mst_resp_err_d = nmi_mst.resp_err;
s_nmi_mst_resp_code_d = nmi_mst.resp_code;
end
end
FSM_RESP: begin
s_fsm_d = FSM_IDLE;
nmi_slv.ready = s_nmi_mst_ready_q;
nmi_slv.rdata = s_nmi_mst_rdata_q;
nmi_slv.resp_err = s_nmi_mst_resp_err_q;
nmi_slv.resp_code = s_nmi_mst_resp_code_q;
end
default: s_fsm_d = FSM_IDLE;
endcase
end
dffr #(2) u_fsm_dffr (
clk_i,
rst_n_i,
s_fsm_d,
s_fsm_q
);
dffr #(1) u_nmi_mstr_valid_dffr (
clk_i,
rst_n_i,
s_nmi_mst_valid_d,
s_nmi_mst_valid_q
);
dffr #(32) u_nmi_mst_addr_dffr (
clk_i,
rst_n_i,
s_nmi_mst_addr_d,
s_nmi_mst_addr_q
);
dffr #(32) u_nmi_mst_wdata_dffr (
clk_i,
rst_n_i,
s_nmi_mst_wdata_d,
s_nmi_mst_wdata_q
);
dffr #(4) u_nmi_mst_wstrb_dffr (
clk_i,
rst_n_i,
s_nmi_mst_wstrb_d,
s_nmi_mst_wstrb_q
);
dffr #(32) u_nmi_mst_rdata_dffr (
clk_i,
rst_n_i,
s_nmi_mst_rdata_d,
s_nmi_mst_rdata_q
);
dffr #(1) u_nmi_mst_ready_dffr (
clk_i,
rst_n_i,
s_nmi_mst_ready_d,
s_nmi_mst_ready_q
);
dffr #(1) u_nmi_mst_resp_err_dffr (
clk_i,
rst_n_i,
s_nmi_mst_resp_err_d,
s_nmi_mst_resp_err_q
);
dffr #(3) u_nmi_mst_resp_code_dffr (
clk_i,
rst_n_i,
s_nmi_mst_resp_code_d,
s_nmi_mst_resp_code_q
);
endmodule
+1 -1
View File
@@ -17,7 +17,7 @@ module user_core_top (
input logic [ 31:0] irq_i,
input logic [`USER_CORESEL_WIDTH-1:0] sel_i,
input logic [`USER_CORE_COUNT-1:0] core_reset_i,
nmi_if.master nmi
soc_nmi_if.master nmi
// verilog_format: on
);
+2 -2
View File
@@ -195,14 +195,14 @@ module tc_io_in_pad (
.A (),
.PAD(pad),
.IE (1'b1),
.CS (1'b1), // 1: CMOS 0: SCHMI
.CS (1'b1), // 1: CMOS 0: SCHMI
.I (1'b0),
.OE (1'b0),
.OD (1'b0),
.PU (1'b0),
.PD (1'b0),
.DS0(1'b0),
.DS1(1'b1) // 8mA
.DS1(1'b1) // 8mA
);
`endif
+5
View File
@@ -13,6 +13,11 @@ FatFs R0.16 archive. It verifies the archive, GitHub authentication, release
absence, and the published asset checksum before reporting the checksum-pinned
URL.
`parse_performance_log.py` converts the `APP=benchmark` UART `PERF` records
into `meta/performance.json`. The parser requires the terminal
`PERF_BENCHMARK_PASS` marker and deliberately does not alter the common
simulation success-marker policy.
Update or add tests in [`../tests`](../tests) for script behavior. Run
`ruff check .` and `python3 -m pytest -q`; build-flow changes also require the
relevant dry-run or regression profile from [`AGENTS.md`](../AGENTS.md).
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""Parse reproducible SoC performance benchmark output into structured JSON."""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
PERF_PREFIX = "PERF "
PASS_MARKER = "PERF_BENCHMARK_PASS"
FAIL_PREFIX = "PERF_FAIL"
REQUIRED_FIELDS = {
"region",
"op",
"words",
"checksum",
"mgmt_wait",
"native_wait",
"sdram_wait",
"psram_wait",
"flash_wait",
"dma_wait",
}
TOKEN = re.compile(r"([a-z_]+)=([^\s]+)")
def parse_number(value: str) -> int:
return int(value, 0)
def parse_log(content: str) -> dict[str, object]:
samples: list[dict[str, object]] = []
for line in content.splitlines():
if not line.startswith(PERF_PREFIX):
continue
fields = {name: value for name, value in TOKEN.findall(line)}
missing = REQUIRED_FIELDS.difference(fields)
if missing:
raise ValueError(f"performance sample is missing fields: {sorted(missing)}")
sample: dict[str, object] = {
"region": fields["region"],
"operation": fields["op"],
"words": parse_number(fields["words"]),
"checksum": int(fields["checksum"], 16),
}
for counter in sorted(REQUIRED_FIELDS - {"region", "op", "words", "checksum"}):
sample[counter] = parse_number(fields[counter])
samples.append(sample)
passed = PASS_MARKER in content
failure_marker = any(line.startswith(FAIL_PREFIX) for line in content.splitlines())
return {
"schema_version": 1,
"status": "passed" if passed and samples and not failure_marker else "failed",
"failure_marker": failure_marker,
"pass_marker": passed,
"samples": samples,
}
def atomic_write(path: Path, content: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_suffix(path.suffix + ".tmp")
temporary.write_text(content, encoding="utf-8")
temporary.replace(path)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--log", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
return parser.parse_args()
def main() -> int:
args = parse_args()
report = parse_log(args.log.read_text(encoding="utf-8", errors="replace"))
atomic_write(args.output, json.dumps(report, indent=2, sort_keys=True) + "\n")
if report["status"] != "passed":
print("performance benchmark did not emit a complete passing report", file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())
+18 -10
View File
@@ -9,10 +9,11 @@ module bus_fault_tb;
logic fault_reserved_o;
logic fault_access_o;
logic [ 1:0] fault_master_o;
logic [ 2:0] fault_code_o;
logic user_bus_idle_o;
nmi_if mgmt_nmi ();
nmi_if user_nmi ();
nmi_if dma_nmi ();
soc_nmi_if mgmt_nmi ();
soc_nmi_if user_nmi ();
soc_nmi_if dma_nmi ();
nmi_if natv_nmi ();
nmi_if apb_nmi ();
@@ -33,16 +34,20 @@ module bus_fault_tb;
.user_bus_idle_o (user_bus_idle_o),
.natv_nmi (natv_nmi),
.apb_nmi (apb_nmi),
.apb_resp_err_i (1'b0),
.perf_enable_i (1'b0),
.perf_clear_i (1'b0),
.fault_valid_o (fault_valid_o),
.fault_addr_o (fault_addr_o),
.fault_wstrb_o (fault_wstrb_o),
.fault_reserved_o (fault_reserved_o),
.fault_access_o (fault_access_o),
.fault_master_o (fault_master_o)
.fault_master_o (fault_master_o),
.fault_code_o (fault_code_o)
);
task automatic expect_fault(input logic [31:0] address, input logic [3:0] write_strobes,
input logic reserved);
input logic reserved, input logic [2:0] expected_code);
begin
@(negedge clk_i);
mgmt_nmi.addr = address;
@@ -51,11 +56,13 @@ module bus_fault_tb;
mgmt_nmi.valid = 1'b1;
while (!fault_valid_o) @(posedge clk_i);
if (fault_addr_o !== address || fault_wstrb_o !== write_strobes ||
fault_reserved_o !== reserved || fault_access_o || natv_nmi.valid || apb_nmi.valid) begin
fault_reserved_o !== reserved || fault_access_o || fault_code_o !== expected_code ||
natv_nmi.valid || apb_nmi.valid) begin
$fatal(1, "unexpected fault response for address %h", address);
end
while (!mgmt_nmi.ready) @(posedge clk_i);
if (mgmt_nmi.rdata !== 32'd0) begin
if (mgmt_nmi.rdata !== 32'd0 || !mgmt_nmi.resp_err ||
mgmt_nmi.resp_code !== expected_code) begin
$fatal(1, "fault response data must be zero");
end
@(negedge clk_i);
@@ -76,7 +83,8 @@ module bus_fault_tb;
$fatal(1, "user access was not denied locally");
end
while (!user_nmi.ready) @(posedge clk_i);
if (user_nmi.rdata !== 32'd0) begin
if (user_nmi.rdata !== 32'd0 || !user_nmi.resp_err ||
user_nmi.resp_code !== `SOC_NMI_RESP_PROTERR) begin
$fatal(1, "denied user response data must be zero");
end
@(negedge clk_i);
@@ -102,8 +110,8 @@ module bus_fault_tb;
repeat (2) @(posedge clk_i);
rst_n_i = 1'b1;
expect_fault(32'h1000_F000, 4'hF, 1'b1);
expect_fault(32'hA000_0000, 4'h0, 1'b0);
expect_fault(32'h1000_F000, 4'hF, 1'b1, `SOC_NMI_RESP_RESERVED);
expect_fault(32'hA000_0000, 4'h0, 1'b0, `SOC_NMI_RESP_DECERR);
expect_user_denied(32'h1000_B000, 4'hF);
$display("bus fault responder test passed");
$finish;
+97
View File
@@ -0,0 +1,97 @@
`timescale 1ns / 1ps
module dma_error_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic [ 2:0] mode_i = 3'd0;
logic [31:0] srcaddr_i = 32'h3800_1000;
logic srcincr_i = 1'b1;
logic [31:0] dstaddr_i = 32'h4000_1000;
logic dstincr_i = 1'b1;
logic [31:0] xferlen_i = 32'd1;
logic start_i = 1'b0;
logic stop_i = 1'b0;
logic reset_i = 1'b0;
logic done_o;
logic error_o;
logic [ 2:0] error_code_o;
logic [31:0] error_addr_o;
logic [ 1:0] fsm_o;
logic error_mode = 1'b0;
integer write_count = 0;
dma_hw_trg_if hw_trg ();
soc_nmi_if nmi ();
always #5 clk_i = ~clk_i;
assign nmi.ready = nmi.valid;
assign nmi.rdata = 32'hA5A5_5A5A;
assign nmi.resp_err = error_mode && nmi.valid;
assign nmi.resp_code = error_mode ? `SOC_NMI_RESP_DECERR : `SOC_NMI_RESP_OK;
always @(posedge clk_i) begin
if (nmi.valid && nmi.ready && (|nmi.wstrb)) begin
write_count <= write_count + 1;
end
end
dma_core u_dma_core (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.mode_i (mode_i),
.srcaddr_i (srcaddr_i),
.srcincr_i (srcincr_i),
.dstaddr_i (dstaddr_i),
.dstincr_i (dstincr_i),
.xferlen_i (xferlen_i),
.start_i (start_i),
.stop_i (stop_i),
.reset_i (reset_i),
.done_o (done_o),
.error_o (error_o),
.error_code_o(error_code_o),
.error_addr_o(error_addr_o),
.fsm_o (fsm_o),
.hw_trg (hw_trg),
.nmi (nmi)
);
task automatic start_transfer;
begin
@(negedge clk_i);
start_i = 1'b1;
@(negedge clk_i);
start_i = 1'b0;
end
endtask
initial begin
hw_trg.i2s_tx_proc = 1'b0;
hw_trg.i2s_rx_proc = 1'b0;
hw_trg.qspi_tx_proc = 1'b0;
hw_trg.qspi_rx_proc = 1'b0;
repeat (2) @(posedge clk_i);
rst_n_i = 1'b1;
start_transfer();
wait (done_o);
@(negedge clk_i);
if (write_count != 1) begin
$fatal(1, "one-word DMA transfer issued %0d writes", write_count);
end
error_mode = 1'b1;
start_transfer();
wait (error_o);
@(negedge clk_i);
if (error_code_o !== `SOC_NMI_RESP_DECERR || error_addr_o !== srcaddr_i) begin
$fatal(1, "DMA error response was not propagated");
end
if (write_count != 1) begin
$fatal(1, "DMA issued a write after a read error");
end
$display("dma error responder test passed");
$finish;
end
endmodule
+110
View File
@@ -0,0 +1,110 @@
`timescale 1ns / 1ps
module sdram_data_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
wire [15:0] s_dq;
logic [31:0] s_read_data;
nmi_if nmi ();
sdram_if sdram ();
always #5 clk_i = ~clk_i;
assign s_dq = sdram.oe_o ? sdram.dq_o : 'z;
assign sdram.dq_i = s_dq;
nmi_sdram u_nmi_sdram (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.nmi (nmi),
.sdram (sdram)
);
`ifdef SDRAM_TIMING_MODEL
sdr u_sdr (
.Clk (sdram.clk_o),
.Cke (sdram.cke_o),
.Cs_n (sdram.cs_n_o),
.Ras_n(sdram.ras_n_o),
.Cas_n(sdram.cas_n_o),
.We_n (sdram.we_n_o),
.Addr (sdram.addr_o),
.Ba (sdram.ba_o),
.Dq (s_dq),
.Dqm (sdram.dqm_o)
);
`else
sdram_verilator_model u_sdram_verilator_model (
.clk_i (sdram.clk_o),
.cke_i (sdram.cke_o),
.cs_n_i (sdram.cs_n_o),
.ras_n_i(sdram.ras_n_o),
.cas_n_i(sdram.cas_n_o),
.we_n_i (sdram.we_n_o),
.ba_i (sdram.ba_o),
.addr_i (sdram.addr_o),
.dqm_i (sdram.dqm_o),
.dq_io (s_dq)
);
`endif
task automatic write_word(input logic [31:0] address, input logic [31:0] data,
input logic [3:0] strobe);
begin
@(negedge clk_i);
nmi.addr = address;
nmi.wdata = data;
nmi.wstrb = strobe;
nmi.valid = 1'b1;
do begin
@(posedge clk_i);
end while (!nmi.ready);
@(negedge clk_i);
nmi.valid = 1'b0;
nmi.wstrb = '0;
end
endtask
task automatic read_word(input logic [31:0] address);
begin
@(negedge clk_i);
nmi.addr = address;
nmi.wdata = '0;
nmi.wstrb = '0;
nmi.valid = 1'b1;
do begin
@(posedge clk_i);
end while (!nmi.ready);
s_read_data = nmi.rdata;
@(negedge clk_i);
nmi.valid = 1'b0;
end
endtask
initial begin
nmi.addr = '0;
nmi.valid = 1'b0;
nmi.wdata = '0;
nmi.wstrb = '0;
repeat (4) @(posedge clk_i);
rst_n_i = 1'b1;
// The controller waits 100 us after reset before accepting a request.
repeat (8000) @(posedge clk_i);
write_word(`SOC_ADDR_SDRAM_BASE, 32'h1234_5678, 4'b1111);
read_word(`SOC_ADDR_SDRAM_BASE);
if (s_read_data !== 32'h1234_5678) begin
$fatal(1, "full-word SDRAM readback was %08x", s_read_data);
end
write_word(`SOC_ADDR_SDRAM_BASE, 32'hA5A5_0000, 4'b1100);
read_word(`SOC_ADDR_SDRAM_BASE);
if (s_read_data !== 32'hA5A5_5678) begin
$fatal(1, "masked SDRAM readback was %08x", s_read_data);
end
$display("sdram data integrity test passed");
$finish;
end
endmodule
+31
View File
@@ -63,6 +63,15 @@ module sysctrl_fault_tb;
sysctrl.user_bus_idle_i = 1'b1;
sysctrl.fault_access_i = 1'b0;
sysctrl.fault_master_i = '0;
sysctrl.fault_code_i = `SOC_NMI_RESP_RESERVED;
sysctrl.perf_mgmt_wait_i = 64'd11;
sysctrl.perf_user_wait_i = 64'd12;
sysctrl.perf_dma_wait_i = 64'd13;
sysctrl.perf_natv_wait_i = 64'd14;
sysctrl.perf_apb_wait_i = 64'd15;
sysctrl.perf_sdram_wait_i = 64'd16;
sysctrl.perf_psram_wait_i = 64'd17;
sysctrl.perf_flash_wait_i = 64'd18;
pll_ctrl.req_ready_i = 1'b1;
pll_ctrl.rsp_active_sel_i = '0;
pll_ctrl.rsp_active_valid_i = 1'b0;
@@ -88,10 +97,32 @@ module sysctrl_fault_tb;
if (read_data !== 32'h1000_F000) $fatal(1, "fault address was not recorded");
read_register(32'h1000_B018, read_data);
if (read_data !== 32'h0000_0001) $fatal(1, "fault count was not incremented");
read_register(32'h1000_B02C, read_data);
if (read_data !== `SOC_NMI_RESP_RESERVED) $fatal(1, "fault detail was not recorded");
@(negedge clk_i);
sysctrl.fault_code_i = `SOC_NMI_RESP_DECERR;
fault_valid_i = 1'b1;
fault_addr_i = 32'hA000_0000;
fault_wstrb_i = 4'h0;
fault_reserved_i = 1'b0;
@(negedge clk_i);
fault_valid_i = 1'b0;
read_register(32'h1000_B014, read_data);
if (read_data !== 32'h1000_F000) $fatal(1, "later fault overwrote first fault address");
read_register(32'h1000_B018, read_data);
if (read_data !== 32'h0000_0002) $fatal(1, "later fault did not increment count");
read_register(32'h1000_B02C, read_data);
if (read_data !== `SOC_NMI_RESP_RESERVED) $fatal(1, "later fault overwrote first fault detail");
write_register(32'h1000_B010, 32'h0000_0001);
read_register(32'h1000_B010, read_data);
if (read_data !== 32'h0000_000A) $fatal(1, "fault W1C did not clear pending");
write_register(32'h1000_B040, 32'h0000_0005);
read_register(32'h1000_B044, read_data);
if (read_data !== 32'd11) $fatal(1, "performance snapshot was not recorded");
read_register(32'h1000_B020, read_data);
if (read_data !== 32'h0000_003F) $fatal(1, "user cores were not held in reset");
write_register(32'h1000_B000, 32'h0000_0006);
+56
View File
@@ -0,0 +1,56 @@
"""DMA protocol regression tests."""
from __future__ import annotations
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_dma_reports_bus_errors_and_transfers_exact_word_count(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
source_list = tmp_path / "dma_error.fl"
source_list.write_text(
"\n".join(
[
"+define+SV_ASSRT_DISABLE",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
f"+incdir+{ROOT / 'rtl/mini/top'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
str(ROOT / "rtl/mini/top/soc_nmi_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/native/peripheral/dma.sv"),
str(ROOT / "rtl/ip/native/peripheral/dma_core.sv"),
str(ROOT / "tests/rtl/dma_error_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "dma_error_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "dma_error_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "dma_error_tb", "-o", str(simulation), str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "dma error responder test passed" in result.stdout
+4 -1
View File
@@ -110,8 +110,9 @@ def test_bus_fault_responder_handles_reserved_and_unmapped_addresses(tmp_path: P
f"+incdir+{tmp_path / 'user_extensions' / 'rtl'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
str(ROOT / "rtl/mini/top/soc_nmi_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/native/interconnect/nmi_regslice.sv"),
str(ROOT / "rtl/mini/top/soc_nmi_regslice.sv"),
str(ROOT / "rtl/mini/top/bus.sv"),
str(ROOT / "tests/rtl/bus_fault_tb.sv"),
"",
@@ -163,6 +164,7 @@ def test_sysctrl_fault_registers_record_and_clear_pending(tmp_path: Path) -> Non
f"+incdir+{ROOT / 'rtl/mini/top'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
str(ROOT / "rtl/mini/top/soc_nmi_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/native/peripheral/pll_ctrl_if.sv"),
str(ROOT / "rtl/ip/native/peripheral/sysctrl.sv"),
@@ -211,6 +213,7 @@ def test_pll_controller_reconfigures_and_falls_back_to_the_safe_clock(tmp_path:
f"+incdir+{ROOT / 'rtl/mini/top'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
str(ROOT / "rtl/mini/top/soc_nmi_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/cdc/cdc_sync.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/cdc/cdc_2phase.sv"),
+52
View File
@@ -0,0 +1,52 @@
"""Tests for the machine-readable benchmark log parser."""
from __future__ import annotations
from scripts.parse_performance_log import parse_log
def test_parse_log_requires_terminal_marker_and_complete_samples() -> None:
report = parse_log(
"PERF region=sdram op=read words=1024 checksum=0x1234 mgmt_wait=10 "
"native_wait=9 sdram_wait=8 psram_wait=0 flash_wait=0 dma_wait=0\n"
"PERF_BENCHMARK_PASS\n"
)
assert report["status"] == "passed"
assert report["failure_marker"] is False
assert report["pass_marker"] is True
assert report["samples"] == [
{
"checksum": 0x1234,
"dma_wait": 0,
"flash_wait": 0,
"mgmt_wait": 10,
"native_wait": 9,
"operation": "read",
"psram_wait": 0,
"region": "sdram",
"sdram_wait": 8,
"words": 1024,
}
]
def test_parse_log_rejects_missing_benchmark_marker() -> None:
report = parse_log(
"PERF region=flash op=read words=1024 checksum=0 mgmt_wait=1 native_wait=1 "
"sdram_wait=0 psram_wait=0 flash_wait=1 dma_wait=0\n"
)
assert report["status"] == "failed"
def test_parse_log_rejects_report_with_performance_failure() -> None:
report = parse_log(
"PERF region=sdram op=read words=1024 checksum=0x1234 mgmt_wait=10 "
"native_wait=9 sdram_wait=8 psram_wait=0 flash_wait=0 dma_wait=0\n"
"PERF_FAIL region=sdram op=read reason=data expected=1234 actual=0\n"
"PERF_BENCHMARK_PASS\n"
)
assert report["status"] == "failed"
assert report["failure_marker"] is True
+5
View File
@@ -50,6 +50,9 @@ def test_pin_map_generates_asic_and_platform_bindings(tmp_path: Path) -> None:
testbench = (tmp_path / "rtl/retrosoc_asic_tb_bindings.svh").read_text(
encoding="utf-8"
)
verilator = (tmp_path / "rtl/retrosoc_asic_verilator_bindings.svh").read_text(
encoding="utf-8"
)
assert "inout extclk_i_pad," in ports
assert "input xi_i_pad," in ports
@@ -60,6 +63,8 @@ def test_pin_map_generates_asic_and_platform_bindings(tmp_path: Path) -> None:
assert ".gpio_15_io_pad()" in fpga
assert ".gpio_24_io_pad(s_psram_dat1)" in testbench
assert testbench.count(".gpio_24_io_pad(") == 1
assert ".sdram_clk_o_pad(s_sdram_clk)" in verilator
assert ".sdram_dq15_io_pad(s_sdram_dq[15])" in verilator
assert "user_gpio_" not in ports
assert "user_gpio_" not in pads
assert "user_gpio_" not in testbench
+23 -2
View File
@@ -112,6 +112,14 @@ def test_generate_all_is_stable_and_expands_paths(tmp_path: Path) -> None:
assert str(ROOT / "rtl/managed/clusterip") in cluster
assert (tmp_path / "core_hazard3.fl").is_file()
assert (tmp_path / "core_picorv32.fl").is_file()
assert {
"pdk_gf180.fl",
"pdk_ics55.fl",
"pdk_ics55_verilator.fl",
"pdk_ics55_yosys.fl",
"pdk_ihp130.fl",
"pdk_sky130.fl",
}.issubset({path.name for path in generated})
def test_source_export_selects_the_requested_management_core(tmp_path: Path) -> None:
@@ -196,7 +204,7 @@ def test_formal_filelists_are_scoped_to_the_protocol_duts(tmp_path: Path) -> Non
gpio_user = parse_filelists([gpio_user_filelist], require_files=False)
assert "+define+SV_ASSRT_DISABLE" in bus.defines
assert ROOT / "rtl/mini/top/bus.sv" in bus.files
assert ROOT / "rtl/ip/native/interconnect/nmi_regslice.sv" in bus.files
assert ROOT / "rtl/mini/top/soc_nmi_regslice.sv" in bus.files
assert ROOT / "rtl/mini/formal/bus_formal.sv" in bus.files
assert ROOT / "rtl/ip/native/interconnect/nmi2apb.sv" in nmi2apb.files
assert ROOT / "rtl/mini/formal/nmi2apb_formal.sv" in nmi2apb.files
@@ -612,10 +620,23 @@ def test_management_core_selection_is_limited_to_hazard3_and_picorv32() -> None:
assert "DEF_LIST += +define+CORE_$(CORE)" in makefile
assert "`ifdef CORE_PICORV32" in wrapper
assert "`elsif CORE_HAZARD3" in wrapper
assert "ahbl2nmi u_ahbl2nmi" in wrapper
assert "ahbl2soc_nmi u_ahbl2soc_nmi" in wrapper
assert ".RESET_VECTOR (`SOC_CPU_RESET_ADDR)" in wrapper
def test_benchmark_profile_uses_functional_sram_and_reserved_data() -> None:
makefile = (ROOT / "Makefile").read_text(encoding="utf-8")
profile = (ROOT / "configs/benchmark/ihp130-hazard3.mk").read_text(encoding="utf-8")
benchmark = (ROOT / "app/apps/benchmark/main.c").read_text(encoding="utf-8")
assert "PDK_BEHAV ?= NO" in makefile
assert "PDK_BEHAV HAVE_SVA" in makefile
assert "PDK_BEHAV=YES is for functional simulation" in makefile
assert "HAVE_SRAM_MACRO := YES" in profile
assert "PDK_BEHAV := YES" in profile
assert "RS_BENCHMARK_SRAM_OFFSET UINT32_C(0x10000)" in benchmark
def test_smoke_regression_uses_ihp130_behavioral_coverage_only() -> None:
commands, profiles = select_regression("smoke", "IHP130")
+141
View File
@@ -0,0 +1,141 @@
"""SDRAM controller data-integrity regression."""
from __future__ import annotations
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_sdram_controller_preserves_full_and_masked_writes(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
generated = tmp_path / "generated"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/address_map/generate_memory_map.py"),
"--map",
str(ROOT / "rtl/mini/address_map/memory_map.json"),
"--output-dir",
str(generated),
],
check=True,
)
source_list = tmp_path / "sdram_data.fl"
source_list.write_text(
"\n".join(
[
"+define+SV_ASSRT_DISABLE",
f"+incdir+{generated / 'rtl'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/native/memory/sdram.sv"),
str(ROOT / "rtl/ip/native/memory/sdram_clkgen.sv"),
str(ROOT / "rtl/ip/native/memory/sdram_reg.sv"),
str(ROOT / "rtl/ip/native/memory/sdram_core.sv"),
str(ROOT / "rtl/mini/dv/verilator/rtl/sdram_verilator_model.sv"),
str(ROOT / "tests/rtl/sdram_data_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "sdram_data_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "sdram_data_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "sdram_data_tb", "-o", str(simulation), str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "sdram data integrity test passed" in result.stdout
def test_sdram_controller_preserves_data_with_micron_timing_model(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
vvp = shutil.which("vvp")
if iverilog is None or vvp is None:
return
generated = tmp_path / "generated"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/address_map/generate_memory_map.py"),
"--map",
str(ROOT / "rtl/mini/address_map/memory_map.json"),
"--output-dir",
str(generated),
],
check=True,
)
source_list = tmp_path / "sdram_timing.fl"
source_list.write_text(
"\n".join(
[
"+define+SV_ASSRT_DISABLE",
"+define+SDRAM_TIMING_MODEL",
f"+incdir+{generated / 'rtl'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
f"+incdir+{ROOT / 'rtl/managed/third_party/model/sdram'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/nmi_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/ip/native/memory/sdram.sv"),
str(ROOT / "rtl/ip/native/memory/sdram_clkgen.sv"),
str(ROOT / "rtl/ip/native/memory/sdram_reg.sv"),
str(ROOT / "rtl/ip/native/memory/sdram_core.sv"),
str(ROOT / "tests/rtl/sdram_data_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "sdram_timing_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "sdram_timing_tb"
subprocess.run(
[
iverilog,
"-g2012",
"-s",
"sdram_data_tb",
"-I",
str(ROOT / "rtl/managed/third_party/model/sdram"),
"-o",
str(simulation),
str(converted),
str(ROOT / "rtl/managed/third_party/model/sdram/sdr.v"),
],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "sdram data integrity test passed" in result.stdout
+6
View File
@@ -202,6 +202,12 @@ def test_ics55_sim_model_preparer_patches_every_h7cr_muxi2_variant(tmp_path: Pat
assert first.returncode == 0, first.stderr
prepared = output.read_text(encoding="utf-8")
assert prepared.startswith(
"/* verilator lint_off DECLFILENAME */\n/* verilator lint_off SPECIFYIGN */\n"
)
assert prepared.endswith(
"/* verilator lint_on SPECIFYIGN */\n/* verilator lint_on DECLFILENAME */\n"
)
assert prepared.count("wire muxi2_y;") == len(cells)
assert prepared.count("udp_mux2 u0(muxi2_y, A, B, S0);") == len(cells)
assert "not u1(Y, Y);" not in prepared