mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
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:
61 files changed
+2539
-433
No files matched your search
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
APP_SRCS += $(ROOT_PATH)/app/apps/benchmark/main.c
|
||||
APP_CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections
|
||||
@@ -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
@@ -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).
|
||||
@@ -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
@@ -7,4 +7,4 @@ HAVE_SVA := NO
|
||||
ISA := RV32IM
|
||||
HAVE_CSR := NO
|
||||
APP := bringup
|
||||
LINK_TYPE := ld2_psram
|
||||
LINK_TYPE := ld2_psram
|
||||
+246
-208
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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(®_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) {
|
||||
|
||||
@@ -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(®_sysctrl_perf_mgmt_wait_lo, ®_sysctrl_perf_mgmt_wait_hi);
|
||||
snapshot->user_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_user_wait_lo, ®_sysctrl_perf_user_wait_hi);
|
||||
snapshot->dma_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_dma_wait_lo, ®_sysctrl_perf_dma_wait_hi);
|
||||
snapshot->native_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_natv_wait_lo, ®_sysctrl_perf_natv_wait_hi);
|
||||
snapshot->apb_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_apb_wait_lo, ®_sysctrl_perf_apb_wait_hi);
|
||||
snapshot->sdram_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_sdram_wait_lo, ®_sysctrl_perf_sdram_wait_hi);
|
||||
snapshot->psram_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_psram_wait_lo, ®_sysctrl_perf_psram_wait_hi);
|
||||
snapshot->flash_wait =
|
||||
rs_perf_read_counter(®_sysctrl_perf_flash_wait_lo, ®_sysctrl_perf_flash_wait_hi);
|
||||
return RS_OK;
|
||||
}
|
||||
@@ -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}")
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
# ICS55 technology cells are supplied by the locked Liberty views in Yosys.
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
@@ -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)),)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
);
|
||||
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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).
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user