feat: refactor test scripts to update paths and improve organization

- Updated paths in test files to reflect new directory structure for RTL and script files.
- Changed references from rtl/mini to rtl/ip and scripts/rtl where applicable.
- Added a new test file for Tiny product isolation, ensuring independent ABI and bus acceptance.
- Enhanced tests for memory map generation and protocol contracts for Tiny architecture.
- Ensured that all tests are aligned with the latest directory structure and naming conventions.
This commit is contained in:
maksyuki committed 2026-09-25 15:44:02 +08:00
1 parent b72e14ea40
commit 9c706ba0ff
194 files changed
+5507 -422

No files matched your search

+4 -2
View File
@@ -22,7 +22,7 @@ truth wins.
records approved Required-rule deviations.
- [crt/README.md](crt/README.md) defines the freestanding RISC-V runtime and
SDK layout; [app/README.md](app/README.md) defines application composition.
- `Makefile`, `rtl/mini/mk/software.mk`, committed `configs/*.mk`, and the
- `Makefile`, `rtl/mk/software.mk`, committed `configs/*.mk`, and the
GitHub workflows define the active build and regression behavior.
- `quality/embedded_c_policy.json`, `quality/warnings/`, and
`quality/metrics/policy.json` define the active quality policy.
@@ -77,7 +77,9 @@ README that states its ownership, source of truth, and validation expectations.
`bringup`, `debug`, and `shell`; each profile is declared in
`app/apps/<name>/app.mk`. The `debug` application is an RTL debug-transport
acceptance image, not a user-facing firmware profile.
- Do not add new dependencies on `crt/inc`, retired `tiny` names, or legacy
- Tiny is a distinct wired MCU product under `rtl/tiny`; `SOC=TINY` selects its
IHP130 profile and AXI4/APB4 integration.
- Do not add new dependencies on `crt/inc`, retired SDK `tiny` names, or legacy
`rs_*.h`/`tiny*.h` include paths.
- Treat `app/coremark/coremark-main`, `app/fatfs/ff16`, `app/lvgl/lvgl-main`,
and managed ports as third-party or managed code. Update them through their
+34 -12
View File
@@ -29,7 +29,7 @@ $(error HAVE_DEBUG has been removed; the Hazard3 Debug Module is always enabled)
endif
SOC ?= MINI
MINI_MODE ?= PRODUCT
MINI_MODE ?= $(if $(filter MINI,$(SOC)),PRODUCT,NONE)
SIMU ?= VCS
SYNTH ?= NONE
SYNTH_RECIPE ?= balanced
@@ -44,7 +44,7 @@ SRAM_SIZE_KIB ?= $(if $(filter ICS55,$(PDK)),128,32)
PDK_BEHAV ?= NO
HAVE_SVA ?= NO
APU_ENABLE_P7 ?= NO
HAVE_HP ?= YES
HAVE_HP ?= $(if $(filter TINY,$(SOC)),NO,YES)
HP_CONFIG ?= rv32imafdc_zicbom_max
BUILD_RELEASE ?= NO
JTAG_IDCODE ?= DEADBEEF
@@ -65,7 +65,7 @@ RTL_SIM_TIMEOUT ?= -1
SIM_FIRMWARE_NAME ?= $(FIRMWARE_NAME)
SIM_SUCCESS_MARKER ?= SIM_TEST_PASS
RTL_PATH := $(ROOT_PATH)/rtl/mini
RTL_PATH := $(ROOT_PATH)/rtl/$(shell printf '%s' '$(SOC)' | tr '[:upper:]' '[:lower:]')
RTL_TOP ?= retrosoc_tb
@@ -212,8 +212,8 @@ else
FLOW_FILELIST_DIR := $(SIM_BUILD_ROOT)/filelists
endif
VALID_SOC := MINI
VALID_MINI_MODE := PRODUCT MPW
VALID_SOC := MINI TINY
VALID_MINI_MODE := PRODUCT MPW NONE
VALID_SIMU := VCS VERILATOR IVERILOG
VALID_SYNTH := NONE YOSYS
VALID_SYNTH_RECIPE := balanced area speed
@@ -276,11 +276,18 @@ $(error NPU_P5_ACCEPTANCE and NPU_P6_ACCEPTANCE are mutually exclusive)
endif
endif
ifeq ($(SOC),MINI)
ifeq ($(MINI_MODE),NONE)
$(error SOC=MINI requires MINI_MODE=PRODUCT or MPW)
endif
ifeq ($(MINI_MODE),PRODUCT)
ifneq ($(HAVE_HP),YES)
$(error MINI_MODE=PRODUCT requires HAVE_HP=YES)
endif
endif
else
include $(ROOT_PATH)/rtl/tiny/mk/config.mk
endif
MISSING_LOCAL_RTL_FILES := $(filter-out $(wildcard $(LOCAL_RTL_FILES)),$(LOCAL_RTL_FILES))
ifneq ($(strip $(MISSING_LOCAL_RTL_FILES)),)
@@ -389,7 +396,9 @@ ifeq ($(APU_ENABLE_P7), YES)
DEF_LIST += +define+APU_ENABLE_P7
endif
ifeq ($(MINI_MODE), PRODUCT)
ifeq ($(SOC), TINY)
DEF_LIST += +define+RETROSOC_SOC__TINY
else ifeq ($(MINI_MODE), PRODUCT)
DEF_LIST += +define+MINI_PRODUCT
else
DEF_LIST += +define+MINI_MPW
@@ -399,8 +408,10 @@ ifeq ($(SYNTH), YOSYS)
DEF_LIST += +define+SYNTHESIS
endif
include rtl/mini/Makefile
include $(RTL_PATH)/Makefile
ifeq ($(SOC),MINI)
include rtl/mini/mk/formal.mk
endif
ifeq ($(SIMU),IVERILOG)
PERF_LOG ?= $(IVERILOG_BEHV_DIR)/sim.log
@@ -410,9 +421,11 @@ endif
ifeq ($(SYNTH), YOSYS)
include physical/smoke/syn/yosys/yosys.mk
ifeq ($(SOC),MINI)
include physical/smoke/syn/yosys/ga2d_block.mk
include physical/smoke/syn/yosys/apu_block.mk
endif
endif
ifeq ($(STA), OPENSTA)
include physical/smoke/sta/opensta/opensta.mk
@@ -571,7 +584,7 @@ config:
doctor:
@python3 $(ROOT_PATH)/scripts/doctor.py \
--root $(ROOT_PATH) --simu $(SIMU) --synth $(SYNTH) --sta $(STA) \
--pdk $(PDK) --have-sram-macro $(HAVE_SRAM_MACRO) \
--pdk $(PDK) --soc $(SOC) --have-sram-macro $(HAVE_SRAM_MACRO) \
--formal $(FORMAL) --lock $(LOCK_FILE)
benchmark-report: firmware
@@ -593,7 +606,13 @@ hp-performance-check:
--lp $(LP_COREMARK_REPORT) --hp $(HP_COREMARK_REPORT) \
--minimum-ratio $(HP_PERF_MIN_RATIO) --output $(META_DIR)/lp-hp-performance.json
ifeq ($(SOC),TINY)
setup: setup-tiny
setup-tiny:
python3 $(ROOT_PATH)/scripts/setup_tiny.py
else
setup: setup-mpw setup-vexiiriscv setup-clusterip setup-ip setup-pdk setup-app
endif
setup-regression:
$(MAKE) CONFIG=configs/ci/ihp130.mk setup
@@ -1091,19 +1110,22 @@ commercial-package: $(MPW_VARIANT_DEP) $(FILELIST_STAMP) manifest
--variant-root $(VARIANT_ROOT) --output-dir $(VARIANT_ROOT)/commercial/input
regress-smoke:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite smoke --pdk IHP130
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite smoke --pdk IHP130 $(if $(filter TINY,$(SOC)),--soc TINY)
regress-rtl:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite rtl --pdk IHP130
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite rtl --pdk IHP130 $(if $(filter TINY,$(SOC)),--soc TINY)
regress-pr:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk IHP130 $(if $(filter YES,$(REGRESS_NETSIM_BOOT_ONLY)),--netsim-boot-only)
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk IHP130 $(if $(filter TINY,$(SOC)),--soc TINY) $(if $(filter YES,$(REGRESS_NETSIM_BOOT_ONLY)),--netsim-boot-only)
ifneq ($(SOC),TINY)
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk GF180 $(if $(filter YES,$(REGRESS_NETSIM_BOOT_ONLY)),--netsim-boot-only)
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk SKY130 $(if $(filter YES,$(REGRESS_NETSIM_BOOT_ONLY)),--netsim-boot-only)
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk ICS55 $(if $(filter YES,$(REGRESS_NETSIM_BOOT_ONLY)),--netsim-boot-only)
endif
regress-nightly:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite nightly
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite nightly $(if $(filter TINY,$(SOC)),--soc TINY)
sim-asm: asm
$(MAKE) SIM_FIRMWARE_NAME=$(ASM_FIRMWARE_NAME) sim
+22 -5
View File
@@ -20,11 +20,13 @@ An open-source RISC-V SoC platform, from SystemVerilog RTL and firmware to repro
## Platform overview
**Mini is the active implementation.** The product configuration combines a
low-power (LP) management hart and a high-performance (HP) application hart.
The separate Mini MPW profile retains the legacy selectable-core integration.
[Tiny, Std, and Pro](docs/soc-family-positioning.md) are product-roadmap targets,
not additional supported build profiles.
**Mini and Tiny have independent integration flows.** Mini combines a
low-power Hazard3 management hart and a VexiiRiscv application hart; its separate
MPW profile retains selectable-core compatibility. [Tiny](docs/ip/tiny-soc.md)
is a wired MCU with one Hazard3 RV32IMC hart, 128 KiB SRAM, AXI4/APB4 and no
wireless IP. Tiny first targets IHP130; [Std and Pro](docs/soc-family-positioning.md)
remain roadmap products. Qualification is determined by each profile's retained
verification and physical reports.
| Area | Mini platform |
| --- | --- |
@@ -96,6 +98,20 @@ Keep `firmware sim` in the same Make invocation so both use one build variant.
Outputs live under `build/<profile>-<YYYY-MM-DD-HH-MM>-<config-hash>/`.
Check the flow logs and result JSON; UART startup text alone is not a pass.
### Build and simulate Tiny
```sh
make CONFIG=configs/ci/ihp130-tiny.mk setup
make CONFIG=configs/ci/ihp130-tiny.mk doctor
make CONFIG=configs/ci/ihp130-tiny.mk firmware sim
make CONFIG=configs/ci/ihp130-tiny.mk SIMU=IVERILOG firmware sim
```
Tiny uses its own source lists and product maps under `rtl/tiny`. Its firmware
loads into on-chip SRAM without PSRAM/SDRAM initialization. The first release
uses a fixed 24 MHz clock and disables atomic instructions. Wireless, external
RAM, HP cores, accelerators and advanced low-power modes remain deferred.
## Configurations and common flows
Start from a [committed profile](configs/README.md). These are selected entry
@@ -103,6 +119,7 @@ points, not the complete profile or application inventory.
| Profile | Purpose |
| --- | --- |
| [IHP130 Tiny](configs/ci/ihp130-tiny.mk) | Single-hart wired MCU, 128 KiB SRAM, pin-level Flash boot and automated acceptance. |
| [IHP130 Mini](configs/ci/ihp130.mk) | Manual bring-up with 32 KiB macro-backed SRAM. |
| [GF180](configs/ci/gf180.mk) / [SKY130](configs/ci/sky130.mk) | Alternative PDK profiles with 32 KiB macro-backed SRAM. |
| [ICS55](configs/ci/ics55.mk) | Regression-compatible profile with SRAM and PLL disabled. |
+7
View File
@@ -162,3 +162,10 @@ make regress-nightly
See the [repository README](../README.md) for prerequisites, supported
configurations, and build artifact locations.
For `SOC=TINY`, `bringup` and `ci_smoke` use the MCU acceptance composition. It
boots through XPI into SRAM, checks CPU C/A behavior and bus exceptions, DMA
(including UART requests), interrupts, RTC, GPIO, UART1 and I2C error completion,
then verifies watchdog reset by completing after the next NOR boot. It uses
SYSCTRL terminal status. The small `asm/tiny_boot.S` image separately qualifies
the synthesized SRAM/pad path; it is not a replacement for the full RTL test.
+3
View File
@@ -0,0 +1,3 @@
APP_SRCS += $(ROOT_PATH)/app/apps/ci_smoke/tiny.c
APP_CFLAGS += -Os
APP_SRCS += $(ROOT_PATH)/app/apps/ci_smoke/mcu_acceptance.S
+31
View File
@@ -0,0 +1,31 @@
/* Copyright (c) 2026 Yuchi Miao; SPDX-License-Identifier: MulanPSL-2.0 */
.section .text
.balign 4
.global rs_mcu_compressed_probe
.type rs_mcu_compressed_probe,@function
rs_mcu_compressed_probe:
.option push
.option rvc
c.li a0, 21
c.slli a0, 1
c.jr ra
.option pop
.size rs_mcu_compressed_probe, .-rs_mcu_compressed_probe
.balign 4
.global rs_mcu_atomic_probe
.type rs_mcu_atomic_probe,@function
rs_mcu_atomic_probe:
/* lr.w a0,(a0): must trap because the Tiny A extension is disabled. */
.word 0x1005252f
ret
.size rs_mcu_atomic_probe, .-rs_mcu_atomic_probe
.balign 4
.global rs_mcu_unmapped_probe
.type rs_mcu_unmapped_probe,@function
rs_mcu_unmapped_probe:
li a0, 0x38000000
lw a0, 0(a0)
ret
.size rs_mcu_unmapped_probe, .-rs_mcu_unmapped_probe
+10
View File
@@ -0,0 +1,10 @@
#ifndef RETROSOC_MCU_ACCEPTANCE_H
#define RETROSOC_MCU_ACCEPTANCE_H
#include <stdint.h>
uint32_t rs_mcu_compressed_probe(void);
void rs_mcu_atomic_probe(uint32_t *address);
void rs_mcu_unmapped_probe(void);
#endif
+278
View File
@@ -0,0 +1,278 @@
#include <stddef.h>
#include <stdint.h>
#include <retrosoc/arch/riscv/system_base.h>
#include <retrosoc/core/archinfo.h>
#include <retrosoc/core/irq.h>
#include <retrosoc/core/soc.h>
#include <retrosoc/generated/irq_metadata.h>
#include <retrosoc/hal/clint.h>
#include <retrosoc/hal/dma.h>
#include <retrosoc/hal/gpio.h>
#include <retrosoc/hal/i2c.h>
#include <retrosoc/hal/onchip_sram.h>
#include <retrosoc/hal/pwm.h>
#include <retrosoc/hal/rtc.h>
#include <retrosoc/hal/sysctrl.h>
#include <retrosoc/hal/timer.h>
#include <retrosoc/hal/uart.h>
#include <retrosoc/hal/watchdog.h>
#include <retrosoc/lib/printf.h>
#include "mcu_acceptance.h"
static _Alignas(64) uint32_t rs_mcu_source[80];
static _Alignas(64) uint32_t rs_mcu_destination[80];
static volatile uint32_t rs_mcu_irq_count;
static volatile uint32_t rs_mcu_exception_count;
static volatile bool rs_mcu_handler_failed;
static void rs_mcu_finish(bool pass, uint8_t code) {
printf("Tiny acceptance %s code=%u\n", pass ? "passed" : "failed", code);
rs_sysctrl_write_test_status(pass, code);
/* The terminal status must retain the first accepted full-word write. */
rs_sysctrl_write_test_status(!pass, UINT8_C(255));
for (;;) {
}
}
static void rs_mcu_exception(uintptr_t mcause, uintptr_t stack_pointer) {
volatile uint32_t *const frame = (volatile uint32_t *)stack_pointer;
if ((mcause != UINT32_C(2)) && (mcause != UINT32_C(5))) {
rs_mcu_handler_failed = true;
}
++rs_mcu_exception_count;
/* system_irq.S saves MEPC in slot 11 of the RV32 trap frame. Both test
* instructions are explicitly 32 bits; normal exceptions do not use this handler. */
frame[11] += UINT32_C(4);
}
static void rs_mcu_timer_irq(uintptr_t mcause, uintptr_t stack_pointer) {
(void)mcause;
(void)stack_pointer;
++rs_mcu_irq_count;
if (rs_timer_interrupt_clear(RS_TIMER_0, RS_TIMER_INTERRUPT_ALL) != RS_OK) {
rs_mcu_handler_failed = true;
}
}
static bool rs_mcu_dma(void) {
rs_dma_config_t config = {
.kind = RS_DMA_KIND_MM_TO_MM,
.request = RS_DMA_REQUEST_SOFTWARE,
.source = (uintptr_t)rs_mcu_source,
.destination = (uintptr_t)rs_mcu_destination,
.byte_count = UINT32_C(259),
.width = RS_DMA_WIDTH_32,
.source_increment = true,
.destination_increment = true,
.priority = 0U,
.burst_beats = 16U,
};
for (uint32_t index = 0U; index < 80U; ++index) {
rs_mcu_source[index] = UINT32_C(0xa519c300) ^ index;
rs_mcu_destination[index] = UINT32_C(0xcccccccc);
}
if ((rs_dma_configure(4U, &config) != RS_EINVAL) ||
(rs_dma_configure(RS_DMA_CHANNEL_BULK, &config) != RS_OK) ||
(rs_dma_start(RS_DMA_CHANNEL_BULK) != RS_OK) ||
(rs_dma_wait(RS_DMA_CHANNEL_BULK, RS_TIMEOUT_DEFAULT) != RS_OK)) {
return false;
}
for (uint32_t index = 0U; index < 64U; ++index) {
if (rs_mcu_source[index] != rs_mcu_destination[index]) {
return false;
}
}
if (rs_mcu_destination[64] !=
((rs_mcu_source[64] & UINT32_C(0x00ffffff)) | UINT32_C(0xcc000000))) {
return false;
}
config.kind = RS_DMA_KIND_MM_TO_STREAM;
config.request = RS_DMA_REQUEST_I2S_TX;
return rs_dma_config_validate(0U, &config) != RS_OK;
}
static bool rs_mcu_interrupts(void) {
uint32_t timeout = UINT32_C(20000);
if ((rs_irq_enable_external(RS_SOC_EXT_IRQ_TIMER0, rs_mcu_timer_irq) != RS_OK) ||
(rs_timer_interrupt_enable(RS_TIMER_0, RS_TIMER_INTERRUPT_TIMEOUT) != RS_OK) ||
(rs_timer_interrupt_test(RS_TIMER_0, RS_TIMER_INTERRUPT_TIMEOUT) != RS_OK)) {
return false;
}
__RV_CSR_SET(CSR_MSTATUS, MSTATUS_MIE);
while ((rs_mcu_irq_count == 0U) && (timeout != 0U)) {
--timeout;
}
__RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_MIE);
return (rs_mcu_irq_count == 1U) && !rs_mcu_handler_failed &&
(rs_irq_disable_external(RS_SOC_EXT_IRQ_TIMER0) == RS_OK);
}
static bool rs_mcu_io(void) {
const rs_gpio_config_t output = {
.mode = RS_GPIO_MODE_OUTPUT,
.pull = RS_GPIO_PULL_NONE,
.trigger = RS_GPIO_TRIGGER_NONE,
.output_high = false,
};
const rs_uart_config_t loopback = {
.source_clock_hz = RS_CPU_CLOCK_HZ,
.baud_rate = UART_BPS,
.data_bits = 8U,
.stop_bits = 1U,
.parity = RS_UART_PARITY_NONE,
.rx_watermark = 1U,
.rx_timeout_bits = 16U,
.tx_enable = true,
.rx_enable = true,
.loopback_enable = true,
};
const uint32_t transmit[4] = {UINT32_C(0x54), UINT32_C(0x49), UINT32_C(0x4e), UINT32_C(0x59)};
uint32_t receive[4] = {0U};
rs_uart_timing_t timing;
bool high;
uint32_t timeout = UINT32_C(10000);
uint8_t payload = UINT8_C(0x55);
const rs_i2c_transfer_t transfer = {
.address = UINT16_C(0x50),
.tx_data = &payload,
.tx_length = 1U,
};
rs_i2c_status_t status;
if ((rs_gpio_configure(15U, &output) != RS_OK) || (rs_gpio_write(15U, true) != RS_OK) ||
(rs_gpio_read(15U, &high) != RS_OK) || !high || (rs_gpio_write(15U, false) != RS_OK) ||
(rs_gpio_read(15U, &high) != RS_OK) || high) {
return false;
}
if ((rs_uart_configure(&loopback, RS_TIMEOUT_DEFAULT) != RS_OK) ||
(rs_uart_write_dma(transmit, 4U, RS_TIMEOUT_DEFAULT) != RS_OK) ||
(rs_uart_read_dma(receive, 4U, RS_TIMEOUT_DEFAULT) != RS_OK)) {
return false;
}
for (uint32_t index = 0U; index < 4U; ++index) {
if (transmit[index] != receive[index]) {
return false;
}
}
if ((rs_uart_init(RS_CPU_CLOCK_HZ, UART_BPS) != RS_OK) ||
(rs_uart_timing_calculate(RS_CPU_CLOCK_HZ, UART_BPS, &timing) != RS_OK)) {
return false;
}
/* UART1 uses the same register ABI; the current shared high-level UART
* API selects UART0. Exercise UART1 PIO and its internal loopback here. */
RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x00)) = timing.baud_integer;
RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x04)) = timing.baud_fraction;
RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x08)) = UINT32_C(3);
RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x0c)) = UINT32_C(7);
RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x10)) = UINT32_C(0x5a);
while (((RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x18)) & UINT32_C(0x40)) != 0U) &&
(timeout != 0U)) {
--timeout;
}
if ((timeout == 0U) || ((RS_SOC_REG32(RS_SOC_APB4_UART1_BASE, UINT32_C(0x14)) &
UINT32_C(0xff)) != UINT32_C(0x5a))) {
return false;
}
/* There is no slave on the pulled-up acceptance board: a real address
* transaction must terminate as NACK rather than stick waiting on the bus. */
for (uint32_t bus = 0U; bus < 2U; ++bus) {
const rs_i2c_bus_t instance = (bus == 0U) ? RS_I2C_BUS_0 : RS_I2C_BUS_1;
if ((rs_i2c_init(instance, RS_CPU_CLOCK_HZ, UINT32_C(100000)) != RS_OK) ||
(rs_i2c_transfer(instance, &transfer, RS_TIMEOUT_DEFAULT) != RS_EIO) ||
(rs_i2c_get_status(instance, &status) != RS_OK) ||
((status.errors & RS_I2C_ERROR_ADDR_NACK) == 0U)) {
return false;
}
}
return true;
}
static bool rs_mcu_rtc(void) {
const rs_rtc_config_t config = {
.second_cycles = UINT32_C(4096),
.calibration_ppm = 0,
.interrupt_enable = 0U,
.wake_enable = 0U,
.enable = true,
};
const rs_rtc_time_t value = {.seconds = UINT64_C(1234), .subsecond = 0U};
rs_rtc_time_t observed;
return (rs_rtc_probe() == RS_OK) && (rs_rtc_configure(&config, RS_TIMEOUT_DEFAULT) == RS_OK) &&
(rs_rtc_set_time(&value, RS_TIMEOUT_DEFAULT) == RS_OK) &&
(rs_rtc_get_time(&observed, RS_TIMEOUT_DEFAULT) == RS_OK) &&
(observed.seconds >= value.seconds);
}
int main(void) {
rs_archinfo_t info;
rs_onchip_sram_info_t memory;
rs_sysctrl_fault_status_t fault;
rs_watchdog_status_t watchdog;
uint64_t before;
uint64_t after;
const rs_watchdog_config_t watchdog_config = {
.prescale_divider = 1U,
.timeout_ticks = UINT32_C(20000),
.window_min_ticks = 0U,
.early_warning_ticks = 0U,
.window_enable = false,
.early_warning_enable = false,
.debug_freeze_enable = true,
};
if (rs_uart_init(RS_CPU_CLOCK_HZ, UART_BPS) != RS_OK) {
rs_mcu_finish(false, 1U);
}
printf("Hello retroSoC! Tiny MCU\n");
if (rs_watchdog_get_status(&watchdog, RS_TIMEOUT_DEFAULT) != RS_OK) {
rs_mcu_finish(false, 2U);
}
if (watchdog.reset_count != 0U) {
rs_mcu_finish(true, 0U);
}
if ((rs_archinfo_read(&info) != RS_OK) || (rs_archinfo_validate_build(&info) != RS_OK) ||
(info.soc_id != RS_SOC_ID) || (info.topology != UINT32_C(0x20200001)) ||
(rs_onchip_sram_probe(&memory) != RS_OK) || (memory.memory_bytes != UINT32_C(131072)) ||
(memory.data_bytes != 4U) || (memory.bank_count != 32U)) {
rs_mcu_finish(false, 3U);
}
if ((rs_mcu_compressed_probe() != 42U) || ((__RV_CSR_READ(CSR_MISA) & UINT32_C(1)) != 0U) ||
(rs_irq_register_exception(2U, rs_mcu_exception) != RS_OK) ||
(rs_irq_register_exception(5U, rs_mcu_exception) != RS_OK)) {
rs_mcu_finish(false, 4U);
}
rs_mcu_atomic_probe(rs_mcu_source);
rs_mcu_unmapped_probe();
if ((rs_mcu_exception_count != 2U) || rs_mcu_handler_failed ||
(rs_sysctrl_get_fault_status(&fault) != RS_OK) || !fault.pending ||
(fault.address != UINT32_C(0x38000000)) || (rs_sysctrl_clear_fault() != RS_OK)) {
rs_mcu_finish(false, 5U);
}
if (!rs_mcu_dma()) {
rs_mcu_finish(false, 6U);
}
if ((rs_clint_get_time(&before) != RS_OK) || (rs_clint_get_time(&after) != RS_OK) ||
(after <= before) || !rs_mcu_interrupts()) {
rs_mcu_finish(false, 7U);
}
if (!rs_mcu_rtc() || (rs_pwm_probe() != RS_OK) ||
(rs_sysctrl_set_hp_release(true) != RS_ENOTSUP)) {
rs_mcu_finish(false, 8U);
}
if (!rs_mcu_io()) {
rs_mcu_finish(false, 10U);
}
printf("Tiny CPU/DMA/IRQ/RTC/I/O passed; exercising watchdog reset\n");
if ((rs_watchdog_configure(&watchdog_config) != RS_OK) ||
(rs_watchdog_start(RS_TIMEOUT_DEFAULT) != RS_OK)) {
rs_mcu_finish(false, 9U);
}
for (;;) {
}
}
+3
View File
@@ -0,0 +1,3 @@
APP_SRCS += $(ROOT_PATH)/app/apps/ci_smoke/tiny.c
APP_CFLAGS += -Os
APP_SRCS += $(ROOT_PATH)/app/apps/ci_smoke/mcu_acceptance.S
+58
View File
@@ -0,0 +1,58 @@
/* Copyright (c) 2026 Yuchi Miao; SPDX-License-Identifier: MulanPSL-2.0 */
#include "retrosoc/generated/memory_map.h"
/* Small gate-level acceptance image. Executes through the real XPI pins,
* checks both ends of SRAM and byte strobes, then checks APB/UART/SYSCTRL.
* The full SDK/application acceptance runs separately in both RTL simulators. */
.section .text
.global _start
_start:
li t0, RS_SOC_SRAM_BASE
li t1, 0x12345678
sw t1, 0(t0)
lw t2, 0(t0)
bne t1, t2, failed
li t0, RS_SOC_SRAM_END - 3
sw t1, 0(t0)
li t2, 0xab
sb t2, 1(t0)
lw t2, 0(t0)
li t1, 0x1234ab78
bne t1, t2, failed
li s0, RS_SOC_APB4_UART0_BASE
li t0, 26
sw t0, 0(s0)
li t0, 11
sw t0, 4(s0)
li t0, 3
sw t0, 8(s0)
sw t0, 12(s0)
la s1, message
print_loop:
lbu s2, 0(s1)
beqz s2, passed
wait_uart:
lw t0, 24(s0)
andi t0, t0, 32
bnez t0, wait_uart
sw s2, 16(s0)
addi s1, s1, 1
j print_loop
passed:
/* Let the serial output drain before setting the terminal verdict. */
lw t0, 24(s0)
andi t0, t0, 4
bnez t0, passed
li t0, RS_SOC_APB4_SYSCTRL_BASE
li t1, 0x80000001
sw t1, RS_SOC_SYSCTRL_TEST_STATUS_OFFSET(t0)
halt:
j halt
failed:
li t0, RS_SOC_APB4_SYSCTRL_BASE
li t1, 0x80000100
sw t1, RS_SOC_SYSCTRL_TEST_STATUS_OFFSET(t0)
j halt
message:
.asciz "Hello retroSoC! Tiny netlist boot\n"
+9
View File
@@ -52,3 +52,12 @@ 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).
## Tiny MCU
`ci/ihp130-tiny.mk` selects `SOC=TINY`, one RV32IMC Hazard3 (A disabled),
128 KiB SRAM, AXI32/APB4, four DMA channels and the wired peripheral subset.
The profile uses 24 MHz, `HAVE_HP=NO`, `MINI_MODE=NONE`, CSR-enabled RV32IM
firmware and `ld2_all_sram`. Both `bringup` and `ci_smoke` select Tiny acceptance
firmware. Icarus and Verilator use the same pin-level Flash model. Other PDKs,
wireless, external RAM and HP applications are rejected by the Tiny config gate.
+18
View File
@@ -0,0 +1,18 @@
SOC := TINY
MINI_MODE := NONE
PDK := IHP130
SIMU := VERILATOR
HAVE_PLL := NO
HAVE_SRAM_IF := YES
HAVE_SRAM_MACRO := YES
SRAM_SIZE_KIB := 128
HAVE_HP := NO
HAVE_SVA := NO
EXT_CLK_HZ := 24000000
AUD_CLK_HZ := 24000000
CLINT_TIMEBASE_HZ := 1000000
ISA := RV32IM
HAVE_CSR := YES
APP := bringup
LINK_TYPE := ld2_all_sram
RTL_TOP := retrosoc_tiny_tb
+15 -1
View File
@@ -160,7 +160,7 @@ on it.
## Build Integration
The central software build assembles the runtime sources in
[`../rtl/mini/mk/software.mk`](../rtl/mini/mk/software.mk). It selects the
[`../rtl/mk/software.mk`](../rtl/mk/software.mk). It selects the
RISC-V ISA, optional CSR interrupt support, linker layout, and the application
profile. Applications add their own sources after the common runtime is
selected.
@@ -219,3 +219,17 @@ hardware validation.
For the complete firmware, simulation, synthesis, and timing flow, see the
[repository README](../README.md).
## Product composition
Tiny uses the same `rs_` SDK and selects its generated memory, IRQ and capability
headers through the committed profile. The generated memory-map header includes
Tiny capability metadata, so public DMA headers report four channels without
requiring an application to reproduce private compiler flags. Unavailable IP
drivers are omitted; Tiny SYSCTRL rejects unsupported lifecycle/PLL operations
before MMIO. Startup skips external-RAM initialization and loads into SRAM.
`<retrosoc/hal/watchdog.h>` provides `rs_watchdog_configure`, `rs_watchdog_start`,
`rs_watchdog_service`, `rs_watchdog_get_status` and `rs_watchdog_clear_reset_cause`,
with SDK status values and bounded command waits. These wrappers preserve the
locked watchdog register ABI.
+6
View File
@@ -17,6 +17,7 @@ _start:
/* Direct Mode: All exceptions set pc to BASE */
csrc CSR_MTVEC, 0x3
#endif
#ifndef RS_SOC_TINY
# wait psram reset done
la a0, _flash_wait_start
la a1, 2000
@@ -25,6 +26,8 @@ wait_psram_reset:
addi a0, a0, 4
blt a0, a1, wait_psram_reset
#endif
# ===== Startup Stage 1 =====
# init the regfile
# zero-initialize register file
@@ -68,6 +71,7 @@ wait_psram_reset:
# when code LMA is different with VMA
# test: using psram before loading
#ifndef RS_SOC_TINY
# Define the addresses
.equ GPIO_ALT_ENABLE, RS_SOC_APB4_GPIO_ADMIN_BASE + 0x34
.equ GPIO_ALT_SELECT, RS_SOC_APB4_GPIO_ADMIN_BASE + 0x38
@@ -98,6 +102,8 @@ PSRAM_READY_WAIT:
andi t1, t1, PSRAM_READY
beqz t1, PSRAM_READY_WAIT
#endif
app_loader_start:
la a0, _ram_lma
la a1, _ram_vma
+4
View File
@@ -77,7 +77,11 @@
#define RS_DMA_ERROR_READ UINT32_C(0x00000040)
#define RS_DMA_ERROR_STREAM_LAST UINT32_C(0x00000100)
#ifdef RS_SOC_TINY
#define RS_DMA_CHANNEL_COUNT 4U
#else
#define RS_DMA_CHANNEL_COUNT 8U
#endif
#define RS_DMA_CHANNEL_HP 6U
#define RS_DMA_CHANNEL_RESERVED 7U
#define RS_DMA_MAX_BURST_BEATS 16U
+13
View File
@@ -1,5 +1,18 @@
#ifndef RETROSOC_WDG_H
#define RETROSOC_WDG_H
#include <wdg.h>
#include <retrosoc/core/status.h>
typedef wdg_config_t rs_watchdog_config_t;
typedef wdg_snapshot_t rs_watchdog_status_t;
rs_status_t rs_watchdog_configure(const rs_watchdog_config_t *config);
rs_status_t rs_watchdog_start(rs_timeout_t timeout);
rs_status_t rs_watchdog_service(rs_timeout_t timeout);
rs_status_t rs_watchdog_get_status(rs_watchdog_status_t *status, rs_timeout_t timeout);
rs_status_t rs_watchdog_clear_reset_cause(rs_timeout_t timeout);
void ip_wdg_test(int argc, char **argv);
#endif
+13
View File
@@ -39,7 +39,20 @@ rs_status_t rs_archinfo_validate_build(const rs_archinfo_t *info) {
.config_id = ARCHINFO_INTEGRATION_CONFIG_ID,
};
#ifdef RS_SOC_TINY
if ((info == NULL) || (info->soc_id != RS_SOC_ID) ||
(info->component_id != ARCHINFO_COMPONENT_ID_VALUE) ||
(info->ip_version != ARCHINFO_IP_VERSION_VALUE) ||
(((info->capability & ARCHINFO_CAPABILITY_ABI_MASK) >> ARCHINFO_CAPABILITY_ABI_SHIFT) !=
ARCHINFO_ABI_VERSION) ||
(expectation.check_build_id && (info->build_id != expectation.build_id)) ||
(info->config_id != expectation.config_id)) {
return RS_EFORMAT;
}
return RS_OK;
#else
return rs_archinfo_status(archinfo_validate(info, &expectation));
#endif
}
rs_status_t rs_archinfo_read_device_id(uint32_t device_id[4]) {
+10
View File
@@ -18,6 +18,11 @@ static bool rs_dma_address_valid(uintptr_t address, uint32_t byte_count, bool in
}
static bool rs_dma_request_valid(const rs_dma_config_t *config) {
#ifdef RS_SOC_TINY
if (config->kind != RS_DMA_KIND_MM_TO_MM) {
return false;
}
#endif
switch (config->kind) {
case RS_DMA_KIND_MM_TO_MM:
return (config->request == RS_DMA_REQUEST_SOFTWARE) ||
@@ -91,6 +96,11 @@ rs_status_t rs_dma_tcd_validate(uint32_t channel, const rs_dma_tcd_t *tcd) {
kind = (tcd->control >> RS_DMA_TCD_KIND_SHIFT) & UINT32_C(0x7);
request = (tcd->control >> RS_DMA_TCD_REQUEST_SHIFT) & UINT32_C(0xF);
burst = (tcd->control >> RS_DMA_TCD_BURST_SHIFT) & UINT32_C(0x1F);
#ifdef RS_SOC_TINY
if (kind != (uint32_t)RS_DMA_KIND_MM_TO_MM) {
return RS_ENOTSUP;
}
#endif
if ((kind > (uint32_t)RS_DMA_KIND_STREAM_TO_MM) ||
(request > (uint32_t)RS_DMA_REQUEST_CRYPTO_OUT) || (burst > RS_DMA_MAX_BURST_BEATS) ||
((tcd->source & UINT32_C(0x3)) != UINT32_C(0)) ||
+2 -2
View File
@@ -454,7 +454,7 @@ rs_status_t rs_i2c_write_dma(rs_i2c_bus_t bus, uint16_t address, bool ten_bit_ad
const uint32_t channel = (bus == RS_I2C_BUS_0) ? RS_DMA_CHANNEL_I2C0 : RS_DMA_CHANNEL_I2C1;
const rs_dma_request_t request =
(bus == RS_I2C_BUS_0) ? RS_DMA_REQUEST_I2C0_TX : RS_DMA_REQUEST_I2C1_TX;
rs_dma_config_t dma_config;
rs_dma_config_t dma_config = {0};
if (!rs_i2c_bus_valid(bus) || (data == NULL) || (workspace == NULL) || (length == 0U) ||
(length > RS_I2C_DMA_MAX_BYTES)) {
@@ -499,7 +499,7 @@ rs_status_t rs_i2c_read_dma(rs_i2c_bus_t bus, uint16_t address, bool ten_bit_add
const uint32_t channel = (bus == RS_I2C_BUS_0) ? RS_DMA_CHANNEL_I2C0 : RS_DMA_CHANNEL_I2C1;
const rs_dma_request_t request =
(bus == RS_I2C_BUS_0) ? RS_DMA_REQUEST_I2C0_RX : RS_DMA_REQUEST_I2C1_RX;
rs_dma_config_t dma_config;
rs_dma_config_t dma_config = {0};
if (!rs_i2c_bus_valid(bus) || (data == NULL) || (workspace == NULL) || (length == 0U) ||
(length > RS_I2C_DMA_MAX_BYTES)) {
+30
View File
@@ -86,6 +86,12 @@ static rs_status_t rs_sysctrl_perf_offsets(rs_sysctrl_perf_counter_t counter, ui
return RS_EINVAL;
}
#ifdef RS_SOC_TINY
if ((counter != RS_SYSCTRL_PERF_MGMT_WAIT) && (counter != RS_SYSCTRL_PERF_DMA_WAIT)) {
return RS_ENOTSUP;
}
#endif
switch (counter) {
case RS_SYSCTRL_PERF_MGMT_WAIT:
*low_offset = RS_SYSCTRL_PERF_MGMT_WAIT_LO_OFFSET;
@@ -215,6 +221,9 @@ rs_status_t rs_sysctrl_clear_user_core_config_error(void) {
}
rs_status_t rs_sysctrl_get_pll_config(uint8_t *selection) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
if (selection == NULL) {
return RS_EINVAL;
}
@@ -224,6 +233,9 @@ rs_status_t rs_sysctrl_get_pll_config(uint8_t *selection) {
}
rs_status_t rs_sysctrl_set_pll_config(uint8_t selection) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
if (((uint32_t)selection & ~RS_SYSCTRL_PLL_SELECTION_MASK) != 0U) {
return RS_EINVAL;
}
@@ -232,16 +244,25 @@ rs_status_t rs_sysctrl_set_pll_config(uint8_t selection) {
}
rs_status_t rs_sysctrl_apply_pll_config(void) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
*rs_sysctrl_register(RS_SYSCTRL_PLL_CMD_OFFSET) = RS_SYSCTRL_PLL_CMD_APPLY;
return RS_OK;
}
rs_status_t rs_sysctrl_clear_pll_error(void) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
*rs_sysctrl_register(RS_SYSCTRL_PLL_CMD_OFFSET) = RS_SYSCTRL_PLL_CMD_CLEAR_ERROR;
return RS_OK;
}
rs_status_t rs_sysctrl_get_pll_status(rs_sysctrl_pll_status_t *status) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
uint32_t value;
if (status == NULL) {
@@ -282,6 +303,9 @@ rs_status_t rs_sysctrl_clear_fault(void) {
}
rs_status_t rs_sysctrl_set_hp_release(bool release) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
rs_sysctrl_hp_status_t status;
if ((rs_sysctrl_get_hp_status(&status) != RS_OK) || !status.present) {
@@ -295,6 +319,9 @@ rs_status_t rs_sysctrl_set_hp_release(bool release) {
}
rs_status_t rs_sysctrl_get_hp_status(rs_sysctrl_hp_status_t *status) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
uint32_t value;
if (status == NULL) {
@@ -311,6 +338,9 @@ rs_status_t rs_sysctrl_get_hp_status(rs_sysctrl_hp_status_t *status) {
}
rs_status_t rs_sysctrl_select_hp_debug(bool select_hp) {
#ifdef RS_SOC_TINY
return RS_ENOTSUP;
#endif
rs_sysctrl_hp_status_t status;
uint32_t value;
+2 -2
View File
@@ -279,7 +279,7 @@ rs_status_t rs_uart_irq_test(uint32_t mask) {
}
rs_status_t rs_uart_write_dma(const uint32_t *words, size_t count, rs_timeout_t timeout) {
rs_dma_config_t config;
rs_dma_config_t config = {0};
size_t index;
rs_status_t status;
@@ -314,7 +314,7 @@ rs_status_t rs_uart_write_dma(const uint32_t *words, size_t count, rs_timeout_t
}
rs_status_t rs_uart_read_dma(uint32_t *words, size_t count, rs_timeout_t timeout) {
rs_dma_config_t config;
rs_dma_config_t config = {0};
rs_status_t status;
if ((words == NULL) || (count == 0U) || (count > (UINT32_MAX / sizeof(*words)))) {
+35
View File
@@ -7,6 +7,41 @@
#define RS_WDG_COMMAND_TIMEOUT UINT32_C(1024)
static rs_status_t rs_watchdog_status(wdg_status_t status) {
switch (status) {
case WDG_STATUS_OK:
return RS_OK;
case WDG_STATUS_INVALID_ARGUMENT:
return RS_EINVAL;
case WDG_STATUS_TIMEOUT:
return RS_ETIMEOUT;
case WDG_STATUS_INCOMPATIBLE:
return RS_EFORMAT;
default:
return RS_EIO;
}
}
rs_status_t rs_watchdog_configure(const rs_watchdog_config_t *config) {
return rs_watchdog_status(wdg_configure((uintptr_t)RS_SOC_APB4_WDG_BASE, config));
}
rs_status_t rs_watchdog_start(rs_timeout_t timeout) {
return rs_watchdog_status(wdg_start((uintptr_t)RS_SOC_APB4_WDG_BASE, timeout));
}
rs_status_t rs_watchdog_service(rs_timeout_t timeout) {
return rs_watchdog_status(wdg_service((uintptr_t)RS_SOC_APB4_WDG_BASE, timeout));
}
rs_status_t rs_watchdog_get_status(rs_watchdog_status_t *status, rs_timeout_t timeout) {
return rs_watchdog_status(wdg_snapshot((uintptr_t)RS_SOC_APB4_WDG_BASE, status, timeout));
}
rs_status_t rs_watchdog_clear_reset_cause(rs_timeout_t timeout) {
return rs_watchdog_status(wdg_clear_reset_cause((uintptr_t)RS_SOC_APB4_WDG_BASE, timeout));
}
void ip_wdg_test(int argc, char **argv) {
static const wdg_config_t config = {
.prescale_divider = 1U,
+2
View File
@@ -3,6 +3,8 @@
This directory contains repository-level engineering policy that supplements
the root README and subsystem guides.
- [Tiny MCU](ip/tiny-soc.md) defines the independent wired Tiny product, AXI4/APB4, SRAM-only startup and IHP130 acceptance.
- [Contributing](../CONTRIBUTING.md) describes community discussion, development,
review, validation evidence, and maintainer responsibilities.
- [git-workflow.md](git-workflow.md) defines branch and commit conventions,
+1
View File
@@ -4,6 +4,7 @@
| Tier | Profile | Automated coverage |
| --- | --- | --- |
| Pull request | `configs/ci/ihp130-tiny.mk` | Tiny firmware, Verilator/Icarus, lint; local Yosys, netlist and OpenSTA |
| Smoke | `configs/ci/ihp130.mk` | strict Verilator RTL lint, firmware, Verilator SVA compilation, Icarus assembly self-test |
| Pull request | `configs/ci/ihp130.mk` | strict Verilator RTL lint, firmware, Verilator, Icarus |
| Pull request | `configs/ci/ihp130-debug.mk` | Verilator remote-bitbang JTAG DTM, Debug Module, OpenOCD, and GDB acceptance |
+2
View File
@@ -4,6 +4,8 @@ This directory owns architecture, register ABI, software contract, and
verification documentation for self-owned retroSoC peripheral IP and platform
extension interfaces.
- [Tiny MCU](tiny-soc.md) defines the independent wired Tiny product, AXI4/APB4, SRAM-only startup and IHP130 acceptance.
- [timer.md](timer.md) defines the dual APB4 general timer.
- [sysctrl.md](sysctrl.md) defines the APB4 SystemCtrl register ABI, control-plane contracts, HAL, and verification.
- [resource-controller.md](resource-controller.md) defines root-managed resource ownership, IRQ routing, and cache-maintenance handoff.
+146
View File
@@ -0,0 +1,146 @@
# Tiny MCU Verification Record
This record accompanies the [frozen Tiny contract](tiny-soc.md). It describes
local implementation evidence from 2026-09-25, not a release or silicon signoff.
The working tree is uncommitted and the readiness status remains `prototype`.
## Configuration and artifact roots
The selected profile is `configs/ci/ihp130-tiny.mk`: IHP130, 128 KiB SRAM,
24 MHz, RV32IM firmware on an RV32IMC hart with A disabled. Runs below used
`BUILD_TIMESTAMP=2026-09-25-12-00`:
- Default `bringup`: `build/ihp130-tiny-2026-09-25-12-00-d6009644a134/`.
- `APP=ci_smoke`: `build/ihp130-tiny-2026-09-25-12-00-044d45791ef7/`.
- `APP=ci_smoke HAVE_SVA=YES`:
`build/ihp130-tiny-2026-09-25-12-00-6874f2ffdf11/`.
Configuration digests identify settings and the dependency lock, not a clean
source revision. A release requires rerunning from its reviewed commit.
## Functional and quality checks
| Check | Evidence/boundary |
| --- | --- |
| Tiny maps and source isolation | Generated address, IRQ, pad and clock/reset inputs validate; source closure excludes Mini product RTL, RIB/RIBP and HP generation. |
| AXI fabric, both simulators | Directed tests cover competing CPU/DMA requests, W-before-AW, delayed W, response backpressure, ID/RLAST, 16-beat bursts, 4 KiB crossing, alignment, reserved regions and continued operation after errors. |
| Tiny SYSCTRL, both simulators | APB tests cover unsupported controls, partial terminal writes, sticky first status, counter snapshots, first-fault retention, W1C, RTC wake and reset. |
| Verilator full firmware | `SIM_TEST_PASS`; the CI composition also passes with SVA enabled. Pin-level NOR, compressed instructions, disabled atomics, load faults, SRAM discovery, memory/UART DMA, external timer IRQ, CLINT time, RTC, GPIO, UART1 loopback, I2C NACK and watchdog reboot are exercised. |
| Icarus full firmware | Final expanded CI firmware passes at 3,705,751 cycles, matching the SVA-enabled Verilator run. |
| Icarus synthesized boot | `netsim-boot` passes at 29,362 cycles using the compact assembly image. Covers pin-level NOR, SRAM first/last words, byte writes, UART and terminal status; does not establish full C-firmware gate-level coverage. |
| SDK gates | C formatting, embedded-C policy and host tests pass, including Tiny channel/endpoint rejection compiled from the real DMA validator. No new Required-rule MISRA deviation is recorded; these partial checks do not certify MISRA conformance. |
| Focused Python tests | 112 tests passed across Tiny, address/pad generation and build/regression tooling. Shared debug-reset and SRAM/DMA register-parity checks also pass. After fixing parameterization/publication compatibility and preparing the existing MPW/device-model inputs, all 54 non-reference failures selected for rerun pass. |
| RTL policy | Changed RTL formatting, full owned RTL style audit and readiness metadata pass. Global formatting limitations are listed below. |
| Reproducibility | Dependency lock validation, Ruff, PR/nightly dry-runs and `git diff --check` pass. Tiny source packaging exports the Tiny top, actual filelist and its core timing SDC. |
The full-firmware verdict is authoritative only when both the tool result and
`result-sim-check.json` pass. UART text alone is not sufficient. Assembly netlist
acceptance uses the same strict terminal marker policy.
## Synthesis and timing
For the CI composition, Yosys completed with the IHP130 technology libraries
and 32 `tc_sram_1024x32` banks. The `balanced` report records 207,739 cells and
9,798,326.725198 square micrometers of library area. The area includes the
instantiated memory/pad hierarchy and is not a placed die-area estimate.
OpenSTA completed with the selected slow library corner and the 41.666666667 ns
system clock. Reported setup WNS is **-455.18 ns**, setup TNS is
**-13,049,600 ns**, and hold WNS/TNS are zero. The worst path starts at the
synchronized system-reset register and reaches peripheral FIFO storage through
the high-fanout reset distribution. This is an open physical/timing issue;
24 MHz is a functional target, not a timing-qualified operating point.
Reports reside under the CI variant's `syn/yosys/rpt/` and `sta/opensta/`.
The metric collector understands the Tiny top and timestamp-prefixed Yosys JSON
reports. Metrics remain in `observe` mode; no warning or metric baseline has
been edited to accept this feature.
## Commands and remaining coverage
The build/verification commands were run with the profile and timestamp above:
```sh
make CONFIG=configs/ci/ihp130-tiny.mk doctor firmware sim
make CONFIG=configs/ci/ihp130-tiny.mk APP=ci_smoke HAVE_SVA=YES firmware sim
make CONFIG=configs/ci/ihp130-tiny.mk APP=ci_smoke SIMU=IVERILOG firmware sim
make CONFIG=configs/ci/ihp130-tiny.mk APP=ci_smoke SYNTH=YOSYS synth
make CONFIG=configs/ci/ihp130-tiny.mk APP=ci_smoke SIMU=IVERILOG netsim-boot
make CONFIG=configs/ci/ihp130-tiny.mk APP=ci_smoke STA=OPENSTA sta
make CONFIG=configs/ci/ihp130-tiny.mk metrics package
make sw-format-check sw-policy-check sw-host-test rtl-style-check-all rtl-readiness-check
python3 -m pytest -q tests/test_tiny.py tests/test_memory_map.py tests/test_pin_map.py tests/test_script_tools.py
python3 scripts/regress.py --root . --suite pr --pdk IHP130 --netsim-boot-only
```
The combined IHP130 regression stops in its Mini phase because the locked
VexiiRiscv checkout is absent. Tiny can be selected independently with
`--soc TINY`, or `make CONFIG=configs/ci/ihp130-tiny.mk regress-pr`.
The initial full Pytest run completed with 1,234 passed, 26 failed, 19 skipped
and 71 errors. Parameterization/format-sensitive expectations and the Mini
publication's constant/cast parsing were corrected; the affected cases were
rerun successfully. MPW/device-model inputs and a writable test ccache resolved
additional environment failures. The remaining 16 cases require the absent
locked FLAC corpus, MLPerf Tiny models or TensorFlow oracle sources. These are
not Tiny setup dependencies. The full suite was not rerun after the focused
corrections; it is not reported as a clean full-suite pass.
The initial run, focused results, combined-regression failure and remaining
reference-input case list are retained under the CI variant's
`meta/validation/`.
Global RTL/Make formatting checks encounter existing APU/accelerator files
outside this change. Changed-file formatting is checked independently.
Remaining qualification includes reset-tree/timing closure, placement/routing,
PVT/MMMC, CDC/RDC signoff, silicon and power measurements, full C netlist
acceptance, a Tiny-specific external OpenOCD session, positive external I2C
slave transactions and comprehensive pad-level PWM/RTC coverage. Wireless,
retention, secure boot and other PDKs remain explicit deferred features.
## Shared-path migration follow-up
Mini now references the canonical shared RTL, `scripts/rtl` helpers and
`rtl/mk/software.mk` directly. The 21 Mini compatibility links and seven Tiny
helper links have been removed. Filelists, simulator/formal/synthesis rules,
Python imports, tests, publication tooling and ownership documents use the new
paths. No Git file-type changes remain. Historical warning baselines are
unchanged.
The resolved Mini `commonip.fl`, `ip.fl` and `top.fl` retain the same 299
unique sources in the same order. `netlist_support.fl` retains its two sources;
`inc.fl` adds `rtl/ip/core`. All relocated shared RTL content hashes match the
pre-migration snapshot. This follow-up changes paths, not RTL behavior or the
public hardware/software interface.
Validation after removing the links:
- 245 focused tests passed: 144 build/generator/topology/style/Tiny tests,
96 publication/LibreLane tests and five debug-reset/SRAM simulations.
Full-suite collection succeeds with 1,356 tests; the full suite was not
rerun because of the reference-input gaps documented above.
- Mini `configs/ci/ihp130.mk` address/pad/topology/clock-reset checks and firmware
build pass. Its Verilator compile reaches HP generation and stops because
the locked VexiiRiscv checkout is missing; full Mini simulation and the
combined regression remain unverified.
- Tiny `configs/ci/ihp130-tiny.mk`, `APP=ci_smoke HAVE_SVA=YES`, firmware and
Verilator simulation pass again at 3,705,751 cycles. Full Icarus, synthesis
and STA were not repeated for this path-only follow-up.
- Eleven Python CLI entrypoints work outside the repository directory.
Mini SRAM formal filelist generation, `sv2v` conversion, filelist combination
and dependency generation pass using the canonical shared paths, including
the relocated SRAM header. Formal proofs were not rerun.
- Ruff, owned RTL style, readiness metadata, 251 local Markdown links and
`git diff --check` pass. The Make formatter still reports existing EOF and
formal-command indentation differences in APU/GA2D/formal fragments; those
unrelated differences were preserved.
Run logs, exact commands and path snapshots are retained under
`build/ihp130-2026-09-25-12-00-9903b3d112b7/meta/validation/shared-path-migration/`.
No C register/API change or additional MISRA deviation belongs to this
follow-up; the SDK gates from the implementation record above were not rerun.
## Next review
```text
Use $retrosoc-mini-feature-review in review mode for feature tiny-soc. Review the current worktree diff against docs/ip/tiny-soc.md and docs/ip/tiny-soc-verification.md. Verify Tiny isolation, default Mini compatibility, AXI/APB/error/reset behavior and the SDK ABI. Treat the observed reset-fanout timing deficit and missing APU/NPU/VexiiRiscv inputs as explicit qualification gaps; do not claim timing closure or alter warning/metric baselines.
```
+193
View File
@@ -0,0 +1,193 @@
# retroSoC Tiny MCU Contract
## Purpose and research boundary
This contract freezes the approved Tiny wired-MCU first release. Tiny owns its
integration in `rtl/tiny`; Mini remains a separate product. The committed
`configs/ci/ihp130-tiny.mk` profile is the reproducible implementation boundary.
The design was approved on 2026-09-25. Source presence does not establish
verification, timing closure, silicon qualification, or low-power performance.
The [RP2350](https://www.raspberrypi.com/products/rp2350/) is a Hazard3-based MCU
reference for software, SRAM, and deterministic I/O. Its dual-core, security,
USB, and PIO features are not Tiny requirements. The
[CAST SRAM controller](https://www.cast-inc.com/peripherals/memory-controllers/sram-ctrl)
illustrates native AXI synchronous SRAM and documented verification delivery;
no commercial implementation or qualification is reused.
## Requirements and non-goals
- TINY-001: one Hazard3 hart, RV32IMC with A disabled, mandatory debug support;
existing RV32IM firmware remains the default compiler target.
- TINY-002: native 32-bit AXI4 data and APB4 control. The CPU's native AHB-Lite
terminates at a direct AXI adapter. No RIB/RIBP source or interface is part of
Tiny's compilation or elaboration closure.
- TINY-003: 128 KiB technology-backed SRAM, XPI NOR boot, no external RAM
dependency. Reset vector is `0x00000000`; SRAM begins at `0x30000000`.
- TINY-004: 32 GPIO, two UARTs, two I2C controllers, two general timers,
CLINT, four DMA channels, PWM, RTC, watchdog, SYSCTRL and architecture info.
- TINY-005: IHP130, 24 MHz system clock, no PLL, 1 MHz CLINT timebase. CPU,
AXI, APB, RTC and watchdog share the system clock.
- TINY-006: Tiny must build independently of MPW, HP CPU generation and
multimedia inputs. Shared SDK APIs retain the `rs_` namespace.
- TINY-007: no wireless IP, radio-specific host integration, or wireless stack.
Deferred: RV32 A atomics, RTOS ports, authenticated boot, retention/power gating,
independent sleep clock, 256–512 KiB SRAM, USB, SDIO, standalone general SPI,
I2S, CAN, ADC, multimedia accelerators and other PDK qualification. XPI retains
the existing four-chip-select interface; initial pin-level acceptance uses NOR
on NSS0. The unpopulated chip selects are not qualified device configurations.
## Selected architecture and interfaces
`retrosoc_tiny` integrates the CPU, two-master fabric, SRAM, XPI and one APB
island. `retrosoc_tiny_asic` owns technology pads; `retrosoc_tiny_tb` owns device
models and terminal verdicts. Product maps, filelists and bindings belong to
Tiny; reusable core/debug, memory and bus utilities belong to shared RTL IP.
AXI has 32-bit addresses/data and one-bit ID/USER. CPU and DMA share one
globally active read or write transaction. Round-robin ownership changes only
after B or RLAST handshake; accepted W traffic cannot change owners. Backpressure
must preserve VALID payloads. Memory accepts naturally aligned 1/2/4-byte INCR
transactions of 1–16 beats within a target and 4 KiB page. MMIO accepts one-beat
FIXED/INCR accesses. Unsupported size/burst/lock/alignment or crossing returns
SLVERR; absent regions return DECERR. Rejected reads return the advertised
number of response beats; rejected writes drain their accepted data before B.
APB uses full setup/access phases, PSTRB and PSLVERR. Registers retain their
existing IP offset, access and reset contracts. A missing peripheral has no
successful decode. GPIO alternate functions retain the selected Mini mappings;
unsupported alternate functions drive neither pads nor peripheral requests.
UART TX/RX and XPI have dedicated pins.
## DMA and interrupt contract
DMA retains the V2 manual register ABI, direct and TCD modes, 32-bit transfers,
up-to-16-beat memory bursts and existing completion/error/W1C/abort semantics.
Four channels are available: 0 UART0, 1 I2C0, 2 I2C1, 3 bulk/XPI. UART1 uses
PIO/IRQ. Stream endpoints and requests for omitted devices are unsupported and
must fail validation rather than wait indefinitely. Capability discovery and
SDK range checks must agree with hardware.
CLINT software/timer occupy core bits 0/1. Reused external sources keep Mini
core-bit numbering: UART0 2, timer0 3, timer1 4, I2C0 7, XPI 9, PWM 11,
RTC 13, watchdog 14, GPIO 18, I2C1 19, DMA 20, UART1 26. The vector has 32
bits (30 Hazard3 external inputs); all omitted sources are zero.
## Register and software ABI
Tiny maps reuse the addresses of implemented Mini peripherals, Flash alias and
XPI aperture. Generated outputs contain address/IRQ/capability metadata and
linker regions, not new generated IP register definitions. SVH/C register pairs
remain handwritten and checked for parity. Hardware identity must describe Tiny,
one MCU hart, 128 KiB SRAM and actual capabilities.
Tiny SYSCTRL preserves fault capture, performance enable/clear and TEST_STATUS
at the existing offsets. The first full-word TEST_STATUS write with bit 31 set
is sticky until system reset; bit 0 is pass and bits 15:8 are the result code.
Unsupported Mini lifecycle/clock controls fail safely; they do not enable HP or
user-core behavior. Unavailable IP drivers are omitted from the Tiny firmware composition.
Unsupported SYSCTRL lifecycle/PLL operations and DMA channel/endpoint requests
return an error before MMIO. GPIO alternate modes follow the Tiny pin map.
The `bringup` and `ci_smoke` applications select product-specific entrypoints.
Startup skips PSRAM setup on Tiny and uses `ld2_all_sram`: code/data copy from
Flash into SRAM, with SRAM BSS and stack. IRQ/CSR support is enabled. Public
headers remain under `<retrosoc/...>`; retired `tiny*.h` paths are not restored.
## Clock, reset and lifecycle
External reset is asynchronously asserted and synchronously released. Watchdog
reset restarts the system. Debug hart reset waits for the CPU AXI adapter to
be idle; it must not abandon an accepted transaction. JTAG and asynchronous
external inputs retain the approved Common synchronizer/handshake boundaries.
There is no cross-domain system bus or dynamic clock switching in this release.
RTC/WDG run at the configured system frequency and provide no independent
deep-sleep guarantee. SRAM contents are not initialized by reset.
## Errors, observability and security
Decode/protocol faults complete with AXI errors and feed sticky SYSCTRL fault
information. DMA records errors and supports bounded software waits and abort.
Counters and terminal-test status permit firmware and simulation diagnosis.
Watchdog provides whole-system recovery from a nonresponsive target; this
release makes no unrestricted AXI liveness, secure-boot, production-entropy,
isolation, or safety-certification claim.
## Development order and acceptance
### TINY-P0 — Freeze Tiny MCU Contract
Record the approved requirements here and update document indexes. Acceptance:
reviewable specification, valid links and `git diff --check`.
### TINY-P1 — Product Selection and Shared Infrastructure
Add SOC=TINY, the committed profile, dependency selection and shared build/IP
boundaries. Preserve Mini defaults. Acceptance: configuration/generator tests,
dependency lock validation, no implicit Tiny dependency on Mini product RTL.
### TINY-P2 — AXI4/APB4 Tiny RTL
Implement the hierarchy and contracts above. Acceptance: lint, standalone AXI,
APB, memory, reset and IRQ checks; no RIB/RIBP in the resolved source closure.
### TINY-P3 — SDK Boot and System Verification
Implement generated capabilities, SRAM-only startup, HAL selection and firmware.
Acceptance: both simulators boot through pin-level NOR and emit SIM_TEST_PASS;
test SRAM boundaries, DMA, peripherals, IRQ, disabled A, C instructions and debug.
### TINY-P4 — IHP130 Qualification and Documentation
Add Tiny to IHP130 regression without replacing Mini coverage. Run format/style,
lint, software policy/host tests, Ruff, Pytest, firmware and supported regressions.
Run Yosys, Icarus netlist and OpenSTA; archive macro mapping, area, cell count,
24 MHz timing and warnings under the configuration's build variant. Check docs
and example commands. Record unrun/failed gates explicitly; do not promote
warning baselines or metrics policy as part of this feature.
## Reproducible commands and current evidence
Use the committed profile, and preserve one `BUILD_TIMESTAMP` when commands
must share artifacts:
```sh
make CONFIG=configs/ci/ihp130-tiny.mk setup doctor
make CONFIG=configs/ci/ihp130-tiny.mk firmware sim
make CONFIG=configs/ci/ihp130-tiny.mk SIMU=IVERILOG firmware sim
make CONFIG=configs/ci/ihp130-tiny.mk SYNTH=YOSYS synth
make CONFIG=configs/ci/ihp130-tiny.mk SIMU=IVERILOG netsim-boot
make CONFIG=configs/ci/ihp130-tiny.mk STA=OPENSTA sta
make CONFIG=configs/ci/ihp130-tiny.mk metrics package
python3 scripts/regress.py --root . --suite pr --pdk IHP130 --soc TINY --dry-run
```
`netsim-boot` runs the dedicated `app/asm/tiny_boot.S` gate-level image. It checks
pin-level NOR boot, both ends of physical SRAM, a byte-lane write, UART and the
SYSCTRL terminal result. It requires `SIM_TEST_PASS`; this is separate from the
complete SDK/IRQ/DMA/watchdog acceptance in both RTL simulators. `netsim` retains
the full firmware option. The shared SRAM IP's capability register describes
the IP's native superset; end-to-end requests must obey Tiny's narrower fabric
contract above.
Tiny uses two-cycle AHB ERROR completion so Hazard3 can trap AXI failures. The
shared core/bridge parameters retain Mini's existing default behavior. Tiny
ArchInfo reports SOC_ID `0x54494e59`, topology `0x20200001`, and FEATURES0
`0x00007ffe`: bits 1/2 SRAM interface/macro, 3 AXI, 4 APB, 5 DMA, 6 UART,
7 I2C, 8 PWM, 9 RTC, 10 watchdog, 11 GPIO, 12 CLINT, 13 timers and 14 XPI.
Bit 0 (PLL) is zero. Tiny FAULT_DETAIL contains the raw AXI response (2/3),
FAULT_STATUS reason is 1 for decode and 2 for slave/protocol errors,
and FAULT_MASTER uses 0 for CPU and 1 for DMA; no RIB encoding is exported.
The public watchdog API is `rs_watchdog_*` with `rs_status_t` and bounded waits.
The [verification record](tiny-soc-verification.md) distinguishes successful
functional checks from missing reference inputs and physical closure. The
product remains `prototype`: negative pre-layout reset-fanout timing must not
be presented as a qualified 24 MHz implementation.
## Commercial delivery gaps
Current-revision verification and physical reports govern readiness. Reusable
VIP, coverage closure, full CDC/RDC, DFT/MBIST, PVT/MMMC, post-layout timing,
power characterization, regulatory and silicon qualification remain separate.
+3 -1
View File
@@ -32,8 +32,10 @@ and reviewed evidence for the applicable rules.
- Use `rs_status_t` for fallible operations. Prefer bounded string/format APIs
and timeout-based register waits. Dynamic allocation is not permitted in
self-owned embedded C.
- New `tiny` identifiers, legacy include paths, and prohibited library calls
- Retired `tiny`-prefixed SDK identifiers, legacy include paths, and prohibited library calls
are not allowed outside the compatibility files explicitly listed by policy.
The Tiny product name in prose/string literals and `RS_SOC_TINY` product
selection do not restore those retired SDK interfaces.
The standard is referenced by name and category only. Consult the licensed
MISRA publication for the complete rule text and applicability guidance; do
+1 -1
View File
@@ -10,7 +10,7 @@ validated without changing functional behavior.
The owned profile in
[`rtl/rtl_style_manifest.json`](../rtl/rtl_style_manifest.json) is the source
of truth for the reviewed source set. It includes `rtl/ip/**` and
`rtl/mini/top/**`, but excludes managed, generated, PDK, formal, device-model,
`rtl/mini/top/**` and `rtl/tiny/top/**`, but excludes managed, generated, PDK, formal, device-model,
and third-party sources.
[`rtl/rtl_style_audit.json`](../rtl/rtl_style_audit.json) records the exact
+1 -1
View File
@@ -10,7 +10,7 @@ differ: retroSoC uses `clk_i` and `rst_n_i`, not `rst_ni`.
## 1. Scope and rule levels
The owned profile applies to `rtl/ip/**` and `rtl/mini/top/**`. Formal,
The owned profile applies to `rtl/ip/**`, `rtl/mini/top/**`, and `rtl/tiny/top/**`. Formal,
device-model, PDK, generated, managed, and third-party sources use the profiles
declared in [`rtl/rtl_style_manifest.json`](../rtl/rtl_style_manifest.json).
+27 -36
View File
@@ -3,9 +3,9 @@
## Status and Scope
This document defines the intended Tiny, Mini, Std, and Pro product ladder.
It is a product roadmap, not a statement of implemented repository support.
The current build system accepts only `SOC=MINI`, and the committed Mini
profiles remain the executable source of truth.
Tiny and Mini have executable build profiles; Std and Pro remain roadmap
targets. Committed product profiles and retained validation evidence define
implemented support. Tiny first targets IHP130 as a wired MCU.
Mini is the family anchor. It establishes the common product model: an open
RISC-V SoC in which a small, always-available Hazard3 management core owns
@@ -14,8 +14,8 @@ add application processors and accelerators without transferring final
lifecycle control to Linux. Tiny reduces this model to an MCU-class device and
does not require a separate application processor.
All frequencies, memory sizes, bus widths, accelerator rates, and software
features below are product targets. They require separate RTL integration,
Except for the explicitly identified executable baselines, frequencies, memory
sizes, bus widths, accelerator rates, and software features below are product targets. They require separate RTL integration,
driver enablement, verification, and physical qualification before they can be
advertised for a device or PDK.
@@ -47,45 +47,36 @@ nodes, protocol bridges, and smart-home edge endpoints. It is MCU-first: boot
latency, sleep behavior, deterministic I/O, security, package cost, and usable
energy per event take precedence over Linux compatibility.
Tiny has two productization profiles:
The first executable product is **Tiny-MCU**, an independent wired MCU
integration in `rtl/tiny`, selected with `configs/ci/ihp130-tiny.mk`. It has no
wireless IP, wireless protocol stack, or radio-specific companion integration.
Tiny-Connect, BLE, IEEE 802.15.4 and Wi-Fi are deferred product research.
- **Tiny-MCU** contains no radio and targets wired control or products that do
not need connectivity on every unit.
- **Tiny-Connect** provides Bluetooth Low Energy and IEEE 802.15.4 capability.
The open digital-RTL baseline should expose a qualified SPI or SDIO host,
interrupt, reset, wake, and power-sequencing interface to a certified radio.
On-die or co-packaged RF becomes a product option only after suitable RF IP,
analog integration, PDK support, and regulatory qualification exist.
### First-release Architecture
Wi-Fi 6 is an optional upper Tiny-Connect SKU rather than a baseline
requirement. This avoids imposing its RF, memory, and active-power costs on
802.15.4 and Bluetooth endpoint products.
### Recommended Architecture
| Area | Product target |
| Area | Tiny MCU baseline |
| --- | --- |
| CPU | One Hazard3 RV32IMAC core at 64-160 MHz, subject to PDK qualification |
| On-chip memory | 256-512 KiB banked SRAM, boot ROM, and 8-32 KiB retention SRAM |
| Code storage | QSPI flash with execute-in-place and authenticated recovery boot |
| Memory model | No MMU and no external DRAM dependency |
| Interconnect | 32-bit RIB; bounded `INCR4` support for DMA and XIP, without a full AXI4 fabric |
| Software | Freestanding SDK, bare metal, and Zephyr- or FreeRTOS-class RTOS ports |
| Low power | Clock gating, switchable SRAM banks, RTC/event wake, retention, and a separately measured deep-sleep state |
| Security | Immutable boot root, signed boot, OTP key material, PMP, TRNG, and symmetric/hash acceleration |
| Edge I/O | UART, SPI, I2C, PWM, ADC, I2S/PDM, USB full speed, and CAN FD selected by package profile |
| CPU | One Hazard3 RV32IMC hart; A extension disabled until atomic bus semantics are qualified |
| On-chip memory | 128 KiB macro-backed SRAM; 256–512 KiB and retention SRAM deferred |
| Code storage | XPI NOR boot, loaded into SRAM; authenticated recovery boot deferred |
| Memory model | No MMU, HP hart, or external DRAM/PSRAM dependency |
| Interconnect | 32-bit AXI4 data plane and APB4 control; no RIB/RIBP |
| Software | Existing freestanding SDK, RV32IM compiler target, CSR/IRQ-enabled acceptance firmware |
| Clock/reset | 24 MHz system clock, no PLL, 1 MHz CLINT timebase, watchdog and JTAG reset |
| Edge I/O | 32 GPIO, two UARTs, two I2C controllers, two timers, four DMA channels, PWM, RTC, watchdog and XPI |
No power-current number should be published until it is measured on a
qualified physical implementation with the wake sources and retention state
specified. Tiny's acceptance criteria should include sleep-to-active latency,
energy per sensing/reporting cycle, and certified-radio interoperability, not
only CPU benchmarks.
The normative [Tiny MCU contract](ip/tiny-soc.md) defines the AXI subset,
address/interrupt ABI, startup, errors and phased acceptance. Independent
low-power clocks, clock/power gating, retention, secure boot, RTOS ports, USB,
SDIO, standalone general SPI, CAN and ADC remain future work. No measured
frequency ceiling, power-current, wake-latency or security claim follows from
this initial functional profile.
### Commercial Reference Points
| Commercial SoC | Relevant axis | Position relative to Tiny |
| --- | --- | --- |
| [Espressif ESP32-H2](https://www.espressif.com/en/products/socs/esp32-h2) | Low-power RV32 MCU with Bluetooth LE and IEEE 802.15.4 | Primary Tiny-Connect endpoint and Thread/Zigbee market reference |
| [Espressif ESP32-H2](https://www.espressif.com/en/products/socs/esp32-h2) | Low-power RV32 MCU with Bluetooth LE and IEEE 802.15.4 | Deferred Tiny-Connect research reference |
| [Espressif ESP32-C6](https://www.espressif.com/en/products/socs/esp32-c6) | RV32 high- and low-power cores with Wi-Fi 6, Bluetooth LE, and IEEE 802.15.4 | Upper connectivity reference; RF and protocol integration are well beyond a radio-companion Tiny baseline |
| [Raspberry Pi RP2350](https://www.raspberrypi.com/products/rp2350/) | Dual Hazard3 option, 520 KiB SRAM, security, USB, and programmable I/O | Closest open-core MCU and deterministic-I/O reference, without integrated radio |
| [ST STM32U5](https://www.st.com/en/microcontrollers-microprocessors/stm32u5-series.html) | Ultra-low-power secure MCU family with large embedded memory and graphics options | Energy-efficiency, security, and industrial MCU ecosystem reference rather than an ISA-equivalent peer |
@@ -414,7 +405,7 @@ software quality.
| Tier | Claim gate |
| --- | --- |
| Tiny | Measured active and sleep power, bounded wake latency, secure-boot validation, and qualified edge-connectivity operation |
| Tiny | First release: wired-MCU boot, AXI/APB/DMA/IRQ and IHP130 evidence; future low-power/security claims require separate measurements and qualification |
| Mini | Repeatable Linux boot, at least 64 MiB usable main memory, native memory bursts, and management-controlled start/stop recovery |
| Std | Full AXI4 ordering tests, coherent accelerator traffic, 1080p60 graphical desktop, audio playback, and NPU inference under concurrent DMA load |
| Pro | Four-hart coherent SMP stress, RV64 distribution boot, more-than-4-GiB memory validation, and concurrent GPU/NPU/video operation |
@@ -12,7 +12,7 @@ from typing import Any
ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(ROOT))
from rtl.mini.pin_map.generate_pin_map import read_map # noqa: E402
from scripts.rtl.generate_pin_map import read_map # noqa: E402
from scripts.check_clock_reset_domains import validate # noqa: E402
from scripts.setup_helpers import atomic_write # noqa: E402
+1 -1
View File
@@ -14,7 +14,7 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(ROOT))
from librelane.flows import Flow # noqa: E402
from rtl.mini.pin_map.generate_pin_map import IHP130_POWER_PAD_COUNTS # noqa: E402
from scripts.rtl.generate_pin_map import IHP130_POWER_PAD_COUNTS # noqa: E402
from scripts.setup_helpers import atomic_write # noqa: E402
@@ -13,7 +13,7 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(ROOT))
from rtl.mini.pin_map.generate_pin_map import ( # noqa: E402
from scripts.rtl.generate_pin_map import ( # noqa: E402
IHP130_POWER_PAD_COUNTS,
Pad,
ihp130_pad_instance,
+1 -1
View File
@@ -11,7 +11,7 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(ROOT))
from rtl.mini.pin_map.generate_pin_map import Pad, ihp130_pad_instance, read_map # noqa: E402
from scripts.rtl.generate_pin_map import Pad, ihp130_pad_instance, read_map # noqa: E402
from scripts.check_clock_reset_domains import validate # noqa: E402
from scripts.setup_helpers import atomic_write # noqa: E402
+1 -1
View File
@@ -12,7 +12,7 @@ from typing import Any
ROOT = Path(__file__).resolve().parents[4]
sys.path.insert(0, str(ROOT))
from rtl.mini.pin_map.generate_pin_map import read_map # noqa: E402
from scripts.rtl.generate_pin_map import read_map # noqa: E402
from scripts.check_clock_reset_domains import validate # noqa: E402
from scripts.setup_helpers import atomic_write # noqa: E402
+4 -3
View File
@@ -1,5 +1,6 @@
OPENSTA ?= sta
OPENSTA_TOP ?= $(if $(filter TINY,$(SOC)),retrosoc_tiny_asic,retrosoc_asic)
OPENSTA_THREADS ?= $(JOBS)
OPENSTA_NETLIST ?= $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
OPENSTA_REPORT ?= $(STA_BUILD_ROOT)/retrosoc_sta.log
@@ -8,8 +9,8 @@ OPENSTA_METRICS ?= $(STA_BUILD_ROOT)/timing_metrics.rpt
OPENSTA_CONFIG ?= $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.config
OPENSTA_SDC ?= $(STA_BUILD_ROOT)/retrosoc_core.sdc
OPENSTA_SDC_GEN := $(ROOT_PATH)/physical/smoke/sta/opensta/generate_sdc.py
OPENSTA_DOMAIN_MAP := $(ROOT_PATH)/rtl/mini/integration/clock_reset_domains.json
OPENSTA_PIN_MAP := $(ROOT_PATH)/rtl/mini/pin_map/pin_map.json
OPENSTA_DOMAIN_MAP := $(RTL_PATH)/integration/clock_reset_domains.json
OPENSTA_PIN_MAP := $(RTL_PATH)/pin_map/pin_map.json
include $(ROOT_PATH)/physical/smoke/sta/opensta/pdk_timing.mk
@@ -36,7 +37,7 @@ sta: $(OPENSTA_SDC) | manifest
}
python3 $(ROOT_PATH)/scripts/run_flow.py --tool opensta --log $(OPENSTA_LOG) \
--result $(STA_BUILD_ROOT)/result-sta.json \
--env OPENSTA_NETLIST=$(OPENSTA_NETLIST) --env OPENSTA_LIBERTY=$(OPENSTA_LIBERTY) \
--env OPENSTA_TOP=$(OPENSTA_TOP) --env OPENSTA_NETLIST=$(OPENSTA_NETLIST) --env OPENSTA_LIBERTY=$(OPENSTA_LIBERTY) \
--env 'OPENSTA_LINK_LIBS=$(OPENSTA_LINK_LIBS)' --env 'OPENSTA_SRAM_LIBS=$(OPENSTA_SRAM_LIBS)' \
--env OPENSTA_SDC=$(OPENSTA_SDC) --env OPENSTA_REPORT=$(OPENSTA_REPORT) \
--env OPENSTA_METRICS=$(OPENSTA_METRICS) -- \
+5 -1
View File
@@ -14,7 +14,11 @@ if {[info exists ::env(OPENSTA_SRAM_LIBS)] && $::env(OPENSTA_SRAM_LIBS) ne ""} {
}
}
read_verilog $::env(OPENSTA_NETLIST)
link_design retrosoc_asic
set top_design retrosoc_asic
if {[info exists ::env(OPENSTA_TOP)] && $::env(OPENSTA_TOP) ne ""} {
set top_design $::env(OPENSTA_TOP)
}
link_design $top_design
read_sdc $::env(OPENSTA_SDC)
report_checks -path_delay min_max -sort_by_slack -slack_max 0.0 -group_path_count 1000 -endpoint_path_count 1000 > $::env(OPENSTA_REPORT)
@@ -18,10 +18,9 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[4]
SCRIPT_DIR = REPO_ROOT / "rtl/mini/script"
sys.path.insert(0, str(SCRIPT_DIR))
from filelist import FileList, parse_filelists, write_filelist # noqa: E402
from generate_filelist import generate_all # noqa: E402
sys.path.insert(0, str(REPO_ROOT))
from scripts.rtl.filelist import FileList, parse_filelists, write_filelist # noqa: E402
from rtl.mini.script.generate_filelist import generate_all # noqa: E402
APU_SOURCE_MARKERS = ("/ip/multimedia/apu_", "/ip/multimedia/apb4_apu.sv")
+25 -12
View File
@@ -13,13 +13,10 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[4]
SCRIPT_DIR = REPO_ROOT / "rtl/mini/script"
INTEGRATION_DIR = REPO_ROOT / "rtl/mini/integration"
sys.path.insert(0, str(SCRIPT_DIR))
sys.path.insert(0, str(INTEGRATION_DIR))
from filelist import FileList, atomic_write, parse_filelists # noqa: E402
from generate_filelist import generate_all # noqa: E402
from generate_user_extensions import generate as generate_user_extensions # noqa: E402
sys.path.insert(0, str(REPO_ROOT))
from scripts.rtl.filelist import FileList, atomic_write, parse_filelists # noqa: E402
from rtl.mini.script.generate_filelist import generate_all # noqa: E402
from rtl.mini.integration.generate_user_extensions import generate as generate_user_extensions # noqa: E402
INCLUDE_RE = re.compile(r'^\s*`include\s+"([^"]+)"')
@@ -69,6 +66,20 @@ def configured_filelist(
*,
require_files: bool = True,
) -> FileList:
if getattr(args, "soc", "MINI") == "TINY":
directory = getattr(args, "source_filelist_dir", None)
if directory is None:
raise ValueError("Tiny export requires --source-filelist-dir")
names = ("def.fl", "inc.fl", "commonip.fl", "clusterip.fl", "ip.fl",
"tech.fl", "core_hazard3.fl", "top.fl")
filelist = parse_filelists((directory / name for name in names), require_files=require_files)
if "+define+RETROSOC_SOC__TINY" not in filelist.defines:
raise ValueError("Tiny export requires Tiny source lists")
if "+define+SYNTHESIS" not in filelist.defines:
filelist.defines.append("+define+SYNTHESIS")
return filelist
if args.dynamic_core_filelist is None or args.dynamic_ip_filelist is None:
raise ValueError("Mini export requires dynamic core and IP filelists")
names: list[str | Path] = []
for name in (
"memory_map_filelist",
@@ -271,7 +282,7 @@ def metadata_file(value: str) -> tuple[Path, Path]:
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Export configured retroSoC RTL sources")
parser.add_argument("mode", choices=("tar", "sv"))
parser.add_argument("--soc", default="MINI", choices=("MINI",))
parser.add_argument("--soc", default="MINI", choices=("MINI", "TINY"))
parser.add_argument("--pdk", default="IHP130", choices=("IHP130", "ICS55", "SKY130", "GF180"))
parser.add_argument("--simu", default="VCS", choices=("VCS", "VERILATOR", "IVERILOG"))
parser.add_argument("--have-pll", action="store_true")
@@ -285,18 +296,19 @@ def parse_args() -> argparse.Namespace:
parser.add_argument(
"--dynamic-core-filelist",
type=Path,
required=True,
required=False,
)
parser.add_argument(
"--dynamic-ip-filelist",
type=Path,
required=True,
required=False,
)
parser.add_argument("--memory-map-filelist", type=Path)
parser.add_argument("--soc-topology-filelist", type=Path)
parser.add_argument("--user-extensions-filelist", type=Path)
parser.add_argument("--pin-map-filelist", type=Path)
parser.add_argument("--archinfo-incdir", type=Path)
parser.add_argument("--source-filelist-dir", type=Path)
parser.add_argument("--librelane-safe", action="store_true")
parser.add_argument("--metadata-file", type=metadata_file, action="append", default=[])
parser.add_argument("--output-dir", type=Path, default=REPO_ROOT / "export")
@@ -312,15 +324,16 @@ def main() -> int:
with tempfile.TemporaryDirectory(prefix="retrosoc-filelists-") as temporary:
generated_dir = Path(temporary)
user_extensions_dir = generated_dir / "user_extensions"
if args.soc == "MINI":
generate_all(generated_dir, build_defines(args))
if args.user_extensions_filelist is None:
if args.soc == "MINI" and args.user_extensions_filelist is None:
generate_user_extensions(
REPO_ROOT / "rtl/mini/integration/user_extensions.json",
user_extensions_dir,
)
filelist = configured_filelist(args, generated_dir, user_extensions_dir)
if args.mode == "sv":
output = export_dir / "retrosoc_asic_sources.sv"
output = export_dir / ("retrosoc_tiny_asic_sources.sv" if args.soc == "TINY" else "retrosoc_asic_sources.sv")
write_single_sv(filelist, output, librelane_safe=args.librelane_safe)
else:
output = write_tar(filelist, export_dir, args.soc, dict(args.metadata_file))
+1 -1
View File
@@ -98,7 +98,7 @@ APU_BLOCK_STA_RESULT := $(APU_BLOCK_STA)/result-sta.json
APU_BLOCK_SYN_RESULT := $(APU_BLOCK_SYN)/result-synth.json
$(APU_BLOCK_FL): $(APU_BLOCK_EXPORTER) $(FILELIST_TEMPLATES) \
$(RTL_PATH)/script/generate_filelist.py $(RTL_PATH)/script/filelist.py
$(RTL_PATH)/script/generate_filelist.py $(ROOT_PATH)/scripts/rtl/filelist.py
@mkdir -p $(APU_BLOCK_FL_DIR)
python3 $(APU_BLOCK_EXPORTER) --output-dir $(APU_BLOCK_FL_DIR) \
$(foreach define,$(DEF_LIST),--define $(define))
+3 -3
View File
@@ -48,7 +48,7 @@ endif
# active DEF_LIST but without the SoC generated-include chain, so the block
# flow does not depend on the HP/pin-map generation stamps.
$(GA2D_BLOCK_FL_DIR)/.stamp: $(RTL_PATH)/script/generate_filelist.py \
$(RTL_PATH)/script/filelist.py \
$(ROOT_PATH)/scripts/rtl/filelist.py \
$(sort $(wildcard $(ROOT_PATH)/rtl/filelist/pdk_*.fl) \
$(wildcard $(RTL_PATH)/filelist/*.fl) $(RTL_PATH)/lint.msg)
$(FLOW_PYTHON) $(RTL_PATH)/script/generate_filelist.py \
@@ -57,11 +57,11 @@ $(GA2D_BLOCK_FL_DIR)/.stamp: $(RTL_PATH)/script/generate_filelist.py \
@touch $@
$(GA2D_BLOCK_FLIST): $(GA2D_BLOCK_FL_DIR)/.stamp $(MEMORY_MAP_STAMP)
@python3 $(RTL_PATH)/script/comb.py \
@python3 $(ROOT_PATH)/scripts/rtl/comb.py \
-f $(GA2D_BLOCK_FL_DIR)/def.fl \
-f $(MEMORY_MAP_FILELIST) \
-f $(GA2D_BLOCK_FL_DIR)/ga2d_block.fl --output $@
@python3 $(RTL_PATH)/script/filelist_deps.py -f $@ \
@python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py -f $@ \
--extra $(MEMORY_MAP_FILELIST) \
--target $(GA2D_BLOCK_NETLIST) --output $(GA2D_BLOCK_DEPFILE)
+4 -3
View File
@@ -30,7 +30,8 @@ include $(YOSYS_DIR)/synth_config.mk
ifeq ($(origin YOSYS_TARGET_PERIOD_PS),undefined)
YOSYS_TARGET_PERIOD_PS := $(shell python3 $(ROOT_PATH)/scripts/yosys_period.py \
--domains $(ROOT_PATH)/rtl/mini/integration/clock_reset_domains.json)
--domains $(RTL_PATH)/integration/clock_reset_domains.json \
--domain $(if $(filter TINY,$(SOC)),system,hp))
ifeq ($(strip $(YOSYS_TARGET_PERIOD_PS)),)
$(error Failed to derive YOSYS_TARGET_PERIOD_PS from the clock/reset inventory)
endif
@@ -49,8 +50,8 @@ YOSYS_SCRIPTS := $(wildcard $(YOSYS_DIR)/script/*) $(YOSYS_DIR)/synth_config.mk
-include $(YOSYS_DEPFILE)
$(SV_FLIST): $(MPW_VARIANT_STAMP) $(FILELIST_STAMP)
@python3 $(RTL_PATH)/script/comb.py $(RTL_FLIST) --output $(SV_FLIST)
@python3 $(RTL_PATH)/script/filelist_deps.py $(RTL_FLIST) --target $(NETLIST) \
@python3 $(ROOT_PATH)/scripts/rtl/comb.py $(RTL_FLIST) --output $(SV_FLIST)
@python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(RTL_FLIST) --target $(NETLIST) \
--output $(YOSYS_DEPFILE)
gen_synth_filelist: $(SV_FLIST)
+2 -2
View File
@@ -146,9 +146,9 @@ def collect_data(config: dict[str, Any], *, check_snapshot: bool = True) -> dict
product = profiles["profile"]
if product.get("MINI_MODE") != "PRODUCT" or product.get("HAVE_HP") != "YES":
raise ValueError("datasheet requires the reviewed dual-hart PRODUCT profile")
address = load_generator("datasheet_memory", "rtl/mini/address_map/generate_memory_map.py")
address = load_generator("datasheet_memory", "scripts/rtl/generate_memory_map.py")
topology = load_generator("datasheet_topology", "rtl/mini/integration/generate_soc_topology.py")
pinmap = load_generator("datasheet_pins", "rtl/mini/pin_map/generate_pin_map.py")
pinmap = load_generator("datasheet_pins", "scripts/rtl/generate_pin_map.py")
reset, regions, _ = address.read_map(ROOT / MAP, int(product["SRAM_SIZE_KIB"]))
_, _, _, gpio, _, _, irqs, policies = topology.read_topology(ROOT / TOPOLOGY, ROOT / MAP)
pads, _ = pinmap.read_map(ROOT / PINS)
+1 -1
View File
@@ -20,7 +20,7 @@ def check_examples(compiler: str) -> int:
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/address_map/generate_memory_map.py"),
str(ROOT / "scripts/rtl/generate_memory_map.py"),
"--map",
str(ROOT / "rtl/mini/address_map/memory_map.json"),
"--output-dir",
@@ -8451,13 +8451,13 @@
],
"sources": [
"rtl/mini/top/retrosoc.sv",
"rtl/mini/top/onchip_ram.sv"
"rtl/ip/memory/onchip_ram.sv"
],
"instance_source": {
"file": "rtl/mini/top/retrosoc.sv",
"name": "u_onchip_ram",
"module": "onchip_ram",
"declaration_file": "rtl/mini/top/onchip_ram.sv"
"declaration_file": "rtl/ip/memory/onchip_ram.sv"
}
},
{
@@ -8495,7 +8495,7 @@
}
],
"sources": [
"rtl/mini/top/onchip_ram.sv"
"rtl/ip/memory/onchip_ram.sv"
]
}
],
@@ -8562,11 +8562,11 @@
"style": "direct",
"bindings": [
{
"file": "rtl/mini/top/onchip_ram.sv",
"file": "rtl/ip/memory/onchip_ram.sv",
"text": ".data_i(s_mem_wdata[31:0])"
},
{
"file": "rtl/mini/top/onchip_ram.sv",
"file": "rtl/ip/memory/onchip_ram.sv",
"text": ".data_i(s_mem_wdata[63:32])"
}
],
@@ -10929,13 +10929,13 @@
],
"sources": [
"rtl/mini/top/retrosoc.sv",
"rtl/mini/top/onchip_ram.sv"
"rtl/ip/memory/onchip_ram.sv"
],
"instance_source": {
"file": "rtl/mini/top/retrosoc.sv",
"name": "u_onchip_ram",
"module": "onchip_ram",
"declaration_file": "rtl/mini/top/onchip_ram.sv"
"declaration_file": "rtl/ip/memory/onchip_ram.sv"
}
},
{
@@ -1430,10 +1430,10 @@
"sram": {
"document": "docs/ip/onchip-sram.md",
"defines": [
"rtl/mini/top/onchip_ram_define.svh"
"rtl/ip/memory/onchip_ram_define.svh"
],
"rtl": [
"rtl/mini/top/onchip_ram_reg.sv"
"rtl/ip/memory/onchip_ram_reg.sv"
],
"parameters": {
"Present": 1,
@@ -58,7 +58,7 @@ the existing non-coherent buffer protocol. LP and HP configuration differences d
two harts into a symmetric cache-coherent SMP platform.
#block(above:rhythm.metadata-before,below:rhythm.metadata-after,breakable:false)[
#set text(size:9pt)
#source("rtl/mini/top/mgmt_core_wrapper.sv",title:"LP instance") ·
#source("rtl/ip/core/mgmt_core_wrapper.sv",title:"LP instance") ·
#source("scripts/vexiiriscv/GenerateRetroSocHp.scala",title:"HP configuration/PMA") ·
#source("scripts/generate_vexiiriscv.py",title:"Artifact manifest") ·
#source("app/ports/linux/linux/retrosoc_hp.dts",title:"HP platform properties")
@@ -41,7 +41,7 @@ The debug replacement sets the stack and calls main, without the generic PSRAM i
relocation or BSS loop. The XPI flash-loader replacement sets the stack, clears BSS and calls
main; if main returns it executes EBREAK and loops. Those compact entries are tied to their
application/linker assumptions and do not establish a universal alternative startup sequence.
#source-note("rtl/mini/mk/software.mk",title:"Generic CRT, conditional IRQ objects and application CRT replacement")
#source-note("rtl/mk/software.mk",title:"Generic CRT, conditional IRQ objects and application CRT replacement")
#source-note("crt/arch/riscv/startup.S",title:"Actual generic LP entry and PSRAM-ready loop")
#source-note("app/apps/debug/startup.S",title:"Dedicated debug entry")
#source-note("app/apps/xpi_flash_loader/startup.S",title:"Dedicated SRAM flash-loader entry")
@@ -13,7 +13,7 @@
"rtl/mini/top/apb4_periph.sv",
"rtl/mini/top/apb4_system.sv",
"rtl/mini/top/memory_pad_mux.sv",
"rtl/mini/top/mgmt_debug_wrapper.sv",
"rtl/ip/core/mgmt_debug_wrapper.sv",
"rtl/mini/top/retrosoc.sv",
"rtl/mini/top/soc_clock_reset_subsystem.sv",
"rtl/mini/top/soc_data_plane.sv"
@@ -168,7 +168,7 @@
"ips": [],
"rotate": false,
"clock": {
"file": "rtl/mini/top/mgmt_debug_wrapper.sv",
"file": "rtl/ip/core/mgmt_debug_wrapper.sv",
"name": "u_jtag_rst_sync",
"module": "rst_sync",
"port": "clk_i",
@@ -167,7 +167,7 @@
"crt/include/retrosoc/hal/onchip_sram.h",
"docs/ip/onchip-sram.md",
"publications/examples/sram.c",
"rtl/mini/top/onchip_ram_reg.sv"
"rtl/ip/memory/onchip_ram_reg.sv"
],
"tests": [
"tests/test_onchip_sram_register_parity.py"
@@ -1159,7 +1159,7 @@
"applies_to": "Reviewed generic LP CRT; dedicated debug and XPI-loader startups have separate initialization contracts.",
"sources": [
"crt/arch/riscv/startup.S",
"rtl/mini/mk/software.mk"
"rtl/mk/software.mk"
]
},
{
@@ -3385,7 +3385,7 @@
"rtl/managed/clusterip/common/rtl/utils/register.sv",
"rtl/mini/top/clock_config_controller.sv",
"rtl/mini/top/hp_lifecycle_controller.sv",
"rtl/mini/top/mgmt_core_wrapper.sv",
"rtl/ip/core/mgmt_core_wrapper.sv",
"rtl/mini/top/resource_controller.sv",
"rtl/mini/top/soc_clock_reset_subsystem.sv",
"scripts/generate_vexiiriscv.py",
@@ -5213,7 +5213,7 @@
"crt/src/service/test.c",
"publications/datasheets/mini.json",
"rtl/mini/integration/soc_topology.json",
"rtl/mini/mk/software.mk",
"rtl/mk/software.mk",
"scripts/build_hp_linux.py",
"scripts/regress.py",
"crt/src/hal/hp_mailbox.c",
@@ -5225,17 +5225,17 @@
"bindings": [
{
"id": "csr-selection",
"file": "rtl/mini/mk/software.mk",
"file": "rtl/mk/software.mk",
"text": "ifeq ($(HAVE_CSR),YES)\nDEF_VAL += -DCSR_ENABLE\nendif"
},
{
"id": "irq-objects",
"file": "rtl/mini/mk/software.mk",
"file": "rtl/mk/software.mk",
"text": "ifeq ($(HAVE_CSR),YES)\nCRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/system_irq.S\nCRT_SRCS += $(ROOT_PATH)/crt/src/core/system_irq_handler.c\nCRT_SRCS += $(ROOT_PATH)/crt/src/core/irq.c"
},
{
"id": "app-override",
"file": "rtl/mini/mk/software.mk",
"file": "rtl/mk/software.mk",
"text": "ifneq ($(strip $(APP_CRT_SRCS)),)\nCRT_SRCS := $(APP_CRT_SRCS)\nendif"
},
{
@@ -6151,8 +6151,8 @@
"rtl/mini/top/fabric_monitor.sv",
"rtl/mini/top/hp_subsystem.sv",
"rtl/mini/top/memory_pad_mux.sv",
"rtl/mini/top/mgmt_debug_wrapper.sv",
"rtl/mini/top/onchip_ram.sv",
"rtl/ip/core/mgmt_debug_wrapper.sv",
"rtl/ip/memory/onchip_ram.sv",
"rtl/mini/top/rcu.sv",
"rtl/mini/top/resource_controller.sv",
"rtl/mini/top/retrosoc.sv",
+7 -2
View File
@@ -34,7 +34,12 @@ def lp_parameters(text: str) -> dict[str, str]:
matches = re.findall(r"\bhazard3_cpu_1port\s*#\s*\((.*?)\)\s+u_hazard3_cpu_1port\s*\(", without_comments(text), re.S)
if len(matches) != 1:
raise ValueError("LP instance missing or ambiguous")
return unique_pairs(re.findall(r"\.([A-Z][A-Z0-9_]*)\s*\(([^()]*)\)", matches[0]), "LP")
parameters = unique_pairs(re.findall(r"\.([A-Z][A-Z0-9_]*)\s*\(([^()]*)\)", matches[0]), "LP")
# The fixed Mini integration uses the shared wrapper's Boolean feature
# defaults. Keep configurable integer expressions (notably IRQ count) intact.
defaults = dict(re.findall(r"parameter\s+bit\s+(\w+)\s*=\s*1'b([01])", without_comments(text)))
return {name: defaults.get(value, value) if name.startswith("EXTENSION_") else value
for name, value in parameters.items()}
def hp_parameters(text: str) -> tuple[dict[str, str], list[str]]:
@@ -109,7 +114,7 @@ def validate_details(spec: dict, ids: set[str], root: Path, active_limits: set[s
def collect_details(root: Path, spec: dict, ids: set[str], active_limits: set[str]) -> dict:
validate_details(spec, ids, root, active_limits)
lp = lp_parameters((root / "rtl/mini/top/mgmt_core_wrapper.sv").read_text(encoding="utf-8"))
lp = lp_parameters((root / "rtl/ip/core/mgmt_core_wrapper.sv").read_text(encoding="utf-8"))
hp_source = (root / "scripts/vexiiriscv/GenerateRetroSocHp.scala").read_text(encoding="utf-8")
hp, hp_isa = hp_parameters(hp_source)
for required, actual, name in ((spec["cpu"]["lp_fields"], lp, "LP"), (spec["cpu"]["hp_fields"], hp, "HP")):
+6 -4
View File
@@ -111,11 +111,11 @@ def buffer_budget(kind: str, *, width=0, height=0, rate=0, bits=0, milliseconds=
"total_bytes": stride * count, "dma_supported": supported}
def constants(text: str, prefix: str, rtl=False) -> dict[str, int]:
def constants(text: str, prefix: str, rtl=False, *, exclude: frozenset[str] = frozenset()) -> dict[str, int]:
text = re.sub(r"/\*.*?\*/|//[^\n]*", "", text, flags=re.S)
pattern = (rf"\b({prefix}\w+)\s*=\s*\d+'d(\d+)\s*;" if rtl else
rf"\b({prefix}\w+)\s*(?:=\s*|\s+)(\d+)(?:U)?(?=\s*[,;\n])")
pairs = re.findall(pattern, text)
pairs = [(name, value) for name, value in re.findall(pattern, text) if name not in exclude]
if len({name for name, _ in pairs}) != len(pairs):
raise ValueError(f"duplicate constant: {prefix}")
return {name: int(value) for name, value in pairs}
@@ -194,8 +194,10 @@ def collect_programming(root: Path, spec: dict, ids: set[str], revision: str) ->
sdk_text = (root / "crt/include/retrosoc/hal/dma.h").read_text()
sdk = constants(sdk_text, "RS_DMA_REQUEST_")
channels = constants(sdk_text, "RS_DMA_CHANNEL_")
channels.update(constants((root / "crt/include/retrosoc/hal/dma_regs.h").read_text(), "RS_DMA_CHANNEL_"))
channels.pop("RS_DMA_CHANNEL_COUNT")
# Capacity is selected by product; it is not a named channel allocation.
# Keep the Mini publication's role inventory independent of Tiny's count.
channels.update(constants((root / "crt/include/retrosoc/hal/dma_regs.h").read_text(),
"RS_DMA_CHANNEL_", exclude=frozenset({"RS_DMA_CHANNEL_COUNT"})))
if {r["symbol"] for r in spec["channels"]} != set(channels):
raise ValueError("DMA channel allocation coverage mismatch")
for row in result["dma_routes"]:
+18 -2
View File
@@ -21,6 +21,22 @@ LITERAL = re.compile(r"(?P<w>\d+)?'[sS]?(?P<base>[hHbBdDoO])(?P<digits>[0-9a-fA-
def number(expression: str, constants: dict[str, int] | None = None) -> int:
constants = constants or {}
expression = " ".join(expression.split()).replace("`", "")
# Preserve sized-cast truncation and unwrap a complete parenthesized
# expression before looking for an SV conditional at its top level.
while expression.startswith("(") and expression.endswith(")"):
depth = 0
enclosed = True
for index, character in enumerate(expression):
depth += (character == "(") - (character == ")")
if depth == 0 and index != len(expression) - 1:
enclosed = False
break
if not enclosed or depth != 0:
break
expression = expression[1:-1].strip()
sized_cast = re.fullmatch(r"(\d+)'\(([^()]*)\)", expression)
if sized_cast:
return number(sized_cast[2], constants) & ((1 << int(sized_cast[1])) - 1)
expression = LITERAL.sub(
lambda m: str(
int(m["digits"].replace("_", ""), {"h": 16, "b": 2, "d": 10, "o": 8}[m["base"].lower()])
@@ -151,7 +167,7 @@ def parse_definitions(paths: list[str], extra: dict[str, int]) -> tuple[dict, di
"line": text.count("\n", 0, match.start()) + 1,
}
for match in re.finditer(
r"\b(?:localparam|parameter)\s+(?:(?:int(?:\s+unsigned)?|logic(?:\s*\[[^]]+\])?|\w+_t)\s+)?"
r"\b(?:localparam|parameter)\s+(?:(?:int(?:\s+unsigned)?|bit|logic(?:\s*\[[^]]+\])?|\w+_t)\s+)?"
r"(\w+)\s*=\s*([^;\n]+)",
text,
):
@@ -165,7 +181,7 @@ def parse_definitions(paths: list[str], extra: dict[str, int]) -> tuple[dict, di
},
)
for match in re.finditer(
r"\blocalparam\s+(?:int(?:\s+unsigned)?|logic(?:\s*\[[^]]+\])?|\w+_t)\s+(\w+)\s*=\s*([^;]+);",
r"\blocalparam\s+(?:int(?:\s+unsigned)?|bit|logic(?:\s*\[[^]]+\])?|\w+_t)\s+(\w+)\s*=\s*([^;]+);",
text,
):
definitions[match[1]] = {
+3 -2
View File
@@ -1,10 +1,11 @@
# RTL Design and Simulation
This directory contains retroSoC SystemVerilog RTL, CPU/IP integration,
peripheral and technology wrappers, filelists, testbench support, and the Mini
peripheral and technology wrappers, filelists, testbench support, and the Mini/Tiny
SoC build entry points.
`mini/` is the active SoC integration flow. `managed/` contains locked or
`mini/` and `tiny/` own independent product integrations. Tiny is the single-hart
AXI32/APB4 wired MCU described in [its contract](../docs/ip/tiny-soc.md). `managed/` contains locked or
vendored integration inputs, `ip/` contains self-owned IP and experiments, and
`model/` contains committed device simulation models with preserved upstream
notices. `filelist/` selects PDK-specific RTL sources; `tech/` contains
+7 -4
View File
@@ -1,11 +1,14 @@
# RIB and Experimental IP
# Shared RTL IP
This directory owns project RTL IP.
Self-owned IP is grouped by function: interconnect, util, memory, storage,
serial, USB, multimedia, and peripheral. The Mini SoC selects active sources
explicitly in rtl/mini/filelist/ip.fl, whose source order is part of
the build contract.
serial, USB, multimedia, and peripheral. Mini and Tiny select active sources
explicitly in their product filelists.
Source order is part of the build contract. Shared Hazard3/debug wrappers are
in `core`, AXI adapters in `interconnect`, and native AXI SRAM in `memory`.
Both products reference these shared files directly in their own filelists.
Tiny does not select any RIB/RIBP module.
experimental contains retained inactive RTL. It is not included by any active
filelist and must not become a build dependency without an explicit integration
@@ -11,7 +11,9 @@
`include "mmap_define.svh"
module mgmt_core_wrapper #(
parameter int ExternalIrqCount = 30
parameter int ExternalIrqCount = 30,
parameter bit EnableAtomics = 1'b1,
parameter bit TwoCycleBusErrors = 1'b0
) (
// verilog_format: off -- preserve reviewed column alignment
input logic clk_i,
@@ -58,7 +60,7 @@ module mgmt_core_wrapper #(
.hclk(clk_i),
.hresetn(s_core_rst_n)
);
ahbl2axi4 u_ahbl2axi4 (
ahbl2axi4 #(.TwoCycleErrors(TwoCycleBusErrors)) u_ahbl2axi4 (
.ahbl (u_ahbl_if),
.axi4 (axi4),
.idle_o(s_ahbl_idle)
@@ -103,7 +105,7 @@ module mgmt_core_wrapper #(
hazard3_cpu_1port #(
.RESET_VECTOR (`SOC_CPU_RESET_ADDR),
.MTVEC_INIT (32'h0000_0000),
.EXTENSION_A (1),
.EXTENSION_A (EnableAtomics),
.EXTENSION_C (1),
.EXTENSION_E (0),
.EXTENSION_M (1),
File renamed without changes.
File renamed without changes.
@@ -11,7 +11,9 @@
`include "axi4_define.svh"
module ahbl2axi4 (
module ahbl2axi4 #(
parameter bit TwoCycleErrors = 1'b0
) (
ahbl_if.slave ahbl,
axi4_if.master axi4,
output logic idle_o
@@ -27,6 +29,7 @@ module ahbl2axi4 (
localparam logic [2:0] FSM_WRITE_RESP = 3'd2;
localparam logic [2:0] FSM_READ = 3'd3;
localparam logic [2:0] FSM_READ_RESP = 3'd4;
localparam logic [2:0] FSM_ERROR_RESP = 3'd5;
logic [2:0] s_fsm_d, s_fsm_q;
logic [31:0] s_addr_d, s_addr_q;
@@ -37,15 +40,22 @@ module ahbl2axi4 (
logic [ 3:0] s_wstrb;
logic [31:0] s_wdata;
logic s_terminal;
logic s_axi_err;
logic s_resp_valid;
assign idle_o = s_fsm_q == FSM_IDLE;
assign s_terminal = ((s_fsm_q == FSM_WRITE_RESP) && axi4.bvalid) ||
assign s_resp_valid = ((s_fsm_q == FSM_WRITE_RESP) && axi4.bvalid) ||
((s_fsm_q == FSM_READ_RESP) && axi4.rvalid);
assign ahbl.hready = (s_fsm_q == FSM_IDLE) || s_terminal;
assign ahbl.hresp = s_terminal &&
assign s_axi_err = s_resp_valid &&
(((s_fsm_q == FSM_WRITE_RESP) && (axi4.bresp != `AXI4_RESP_OKAY)) ||
((s_fsm_q == FSM_READ_RESP) && (axi4.rresp != `AXI4_RESP_OKAY))) ?
AHBL_RESP_ERROR : AHBL_RESP_OKAY;
((s_fsm_q == FSM_READ_RESP) && (axi4.rresp != `AXI4_RESP_OKAY)));
// In compliant mode, the AXI terminal error is consumed during the first
// AHB ERROR cycle (HREADY=0). The saved state supplies the final ERROR cycle
// (HREADY=1), allowing Hazard3 to squash a following pipelined access.
assign s_terminal = (s_resp_valid && !(TwoCycleErrors && s_axi_err)) ||
(s_fsm_q == FSM_ERROR_RESP);
assign ahbl.hready = (s_fsm_q == FSM_IDLE) || s_terminal;
assign ahbl.hresp = (s_axi_err || (s_fsm_q == FSM_ERROR_RESP)) ? AHBL_RESP_ERROR : AHBL_RESP_OKAY;
assign ahbl.hrdata = axi4.rdata;
always_comb begin
@@ -155,6 +165,9 @@ module ahbl2axi4 (
FSM_READ: begin
if (axi4.arvalid && axi4.arready) s_fsm_d = FSM_READ_RESP;
end
FSM_WRITE_RESP, FSM_READ_RESP: begin
if (TwoCycleErrors && s_axi_err) s_fsm_d = FSM_ERROR_RESP;
end
default: begin
end
endcase
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+7 -2
View File
@@ -13,7 +13,9 @@ module apb4_dma #(
parameter int DataWidth = 32,
parameter int NumChannels = 4,
parameter int MaxBurstBeats = 16,
parameter int FifoDepth = 16
parameter int FifoDepth = 16,
parameter logic [15:0] RequestMask = 16'h3fff,
parameter bit EnableStreams = 1'b1
) (
// verilog_format: off -- integration ports retain established peripheral endpoint names.
input logic clk_i,
@@ -72,7 +74,8 @@ module apb4_dma #(
dma_reg #(
.NumChannels (NumChannels),
.DataWidth (DataWidth),
.MaxBurstBeats(MaxBurstBeats)
.MaxBurstBeats(MaxBurstBeats),
.EnableStreams(EnableStreams)
) u_dma_reg (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
@@ -119,6 +122,8 @@ module apb4_dma #(
);
dma_core #(
.RequestMask (RequestMask),
.EnableStreams(EnableStreams),
.AddrWidth (AddrWidth),
.DataWidth (DataWidth),
.NumChannels (NumChannels),
+9 -3
View File
@@ -18,7 +18,9 @@ module dma_core #(
parameter int ChannelIndexWidth = (NumChannels > 1) ? $clog2(NumChannels) : 1,
parameter int MaxBurstBeats = 16,
parameter int FifoDepth = 16,
parameter bit EnableCrc = 1'b1
parameter bit EnableCrc = 1'b1,
parameter logic [15:0] RequestMask = 16'h3fff,
parameter bit EnableStreams = 1'b1
) (
// verilog_format: off -- channel vectors are kept aligned with the register-bank ABI.
input logic clk_i,
@@ -447,7 +449,9 @@ module dma_core #(
s_start_valid[channel] = 1'b1;
s_start_err_code[channel] = DMA_ERROR_CONFIG;
if ((s_cfg_width[channel] != DMA_WIDTH_32) || (s_cfg_byte_count[channel] == 32'd0) ||
if (!RequestMask[s_cfg_request[channel]] ||
(!EnableStreams && (s_cfg_kind[channel] != DMA_KIND_MM_TO_MM)) ||
(s_cfg_width[channel] != DMA_WIDTH_32) || (s_cfg_byte_count[channel] == 32'd0) ||
(s_cfg_burst[channel] == 5'd0) ||
(s_cfg_burst[channel] > 5'(MaxBurstBeats))) begin
s_start_valid[channel] = 1'b0;
@@ -1268,7 +1272,9 @@ module dma_core #(
if (s_tcd_parse_q) begin
s_tcd_parse_q <= 1'b0;
if (s_err_q[s_tcd_read_owner_q] ||
if (!RequestMask[s_tcd_word7_q[s_tcd_read_owner_q][15:12]] ||
(!EnableStreams && (s_tcd_word7_q[s_tcd_read_owner_q][10:8] != DMA_KIND_MM_TO_MM)) ||
s_err_q[s_tcd_read_owner_q] ||
(s_tcd_word7_q[s_tcd_read_owner_q][0] == 1'b0) ||
(s_tcd_word3_q[s_tcd_read_owner_q] == 32'd0) ||
(s_tcd_word1_q[s_tcd_read_owner_q][1:0] != 2'b00) ||
+10 -1
View File
@@ -12,6 +12,7 @@
module dma_reg #(
parameter int NumChannels = 4,
parameter bit EnableStreams = 1'b1,
parameter int ChannelIndexWidth = (NumChannels > 1) ? $clog2(NumChannels) : 1,
parameter int DataWidth = 32,
parameter int MaxBurstBeats = 16
@@ -350,7 +351,15 @@ module dma_reg #(
`APB4_DMA__IP_ID: s_read_data = IpId;
`APB4_DMA__IP_VERSION: s_read_data = IpVersion;
`APB4_DMA__CAPABILITY:
s_read_data = {1'b0, 3'd3, 4'(MaxBurstBeats), 8'(DataWidth), 8'(NumChannels), 7'd0, 1'b1};
s_read_data = {
1'b0,
(EnableStreams ? 3'd3 : 3'd0),
4'(MaxBurstBeats),
8'(DataWidth),
8'(NumChannels),
7'd0,
1'b1
};
`APB4_DMA__GLOBAL_CTRL: s_read_data = 32'd0;
`APB4_DMA__GLOBAL_STATUS: s_read_data = {31'd0, |busy_i};
`APB4_DMA__IRQ_STATE: s_read_data = {{(32 - NumChannels) {1'b0}}, s_irq_state};
File renamed without changes.
+3 -1
View File
@@ -10,7 +10,9 @@
`include "xpi_define.svh"
`ifdef SIMU_VERILATOR
`ifdef RETROSOC_SOC__TINY
`define APB4_XPI_CORE_MODULE xpi_core
`elsif SIMU_VERILATOR
`define APB4_XPI_CORE_MODULE xpi_core_verilator
`else
`define APB4_XPI_CORE_MODULE xpi_core
File renamed without changes.
File renamed without changes.
+4 -4
View File
@@ -1,6 +1,6 @@
GENERATED_FL_DIR := $(FLOW_FILELIST_DIR)
MEMORY_MAP_SOURCE := $(RTL_PATH)/address_map/memory_map.json
MEMORY_MAP_SCRIPT := $(RTL_PATH)/address_map/generate_memory_map.py
MEMORY_MAP_SCRIPT := $(ROOT_PATH)/scripts/rtl/generate_memory_map.py
MEMORY_MAP_DIR := $(VARIANT_ROOT)/generated/memory_map
MEMORY_MAP_STAMP := $(MEMORY_MAP_DIR)/.stamp
MEMORY_MAP_RTL_DIR := $(MEMORY_MAP_DIR)/rtl
@@ -8,7 +8,7 @@ MEMORY_MAP_C_DIR := $(MEMORY_MAP_DIR)/include
MEMORY_MAP_LINKER_DIR := $(MEMORY_MAP_DIR)/linker
MEMORY_MAP_FILELIST := $(MEMORY_MAP_DIR)/memory_map.fl
PIN_MAP_SOURCE := $(RTL_PATH)/pin_map/pin_map.json
PIN_MAP_SCRIPT := $(RTL_PATH)/pin_map/generate_pin_map.py
PIN_MAP_SCRIPT := $(ROOT_PATH)/scripts/rtl/generate_pin_map.py
PIN_MAP_DIR := $(VARIANT_ROOT)/generated/pin_map
PIN_MAP_STAMP := $(PIN_MAP_DIR)/.stamp
PIN_MAP_FILELIST := $(PIN_MAP_DIR)/pin_map.fl
@@ -132,7 +132,7 @@ check-clock-reset-domains:
$(FLOW_PYTHON) $(CLOCK_RESET_DOMAINS_SCRIPT) --map $(CLOCK_RESET_DOMAINS_SOURCE) --root $(ROOT_PATH)
$(FILELIST_STAMP): $(FILELIST_TEMPLATES) $(RTL_PATH)/script/generate_filelist.py $(LOCAL_RTL_FILES) \
$(RTL_PATH)/script/filelist.py $(MEMORY_MAP_STAMP) $(PIN_MAP_STAMP) $(SOC_TOPOLOGY_STAMP) \
$(ROOT_PATH)/scripts/rtl/filelist.py $(MEMORY_MAP_STAMP) $(PIN_MAP_STAMP) $(SOC_TOPOLOGY_STAMP) \
$(USER_EXTENSIONS_STAMP) $(ARCHINFO_METADATA_STAMP) \
$(if $(filter MPW,$(MINI_MODE)),$(MPW_VARIANT_STAMP)) \
$(if $(filter YES,$(HAVE_HP)),$(HP_GENERATED_STAMP))
@@ -146,7 +146,7 @@ $(FILELIST_STAMP): $(FILELIST_TEMPLATES) $(RTL_PATH)/script/generate_filelist.py
generate_filelist: $(FILELIST_STAMP)
# software
include $(RTL_PATH)/mk/software.mk
include $(ROOT_PATH)/rtl/mk/software.mk
#====================== filelist ======================
ifeq ($(PDK), IHP130)
+10 -4
View File
@@ -1,8 +1,12 @@
# Mini SoC Integration
This directory is the active Mini SoC integration boundary.
This directory is the Mini SoC integration boundary. Tiny owns a separate
[MCU integration](../tiny/README.md). Shared CPU/debug, memory, bus helpers and
software build logic are owned outside Mini. Filelists, build rules and tests
reference their canonical shared paths directly.
- address_map contains the canonical address-map input and generator.
- address_map contains the canonical Mini address-map input. Its generator
lives in `scripts/rtl/generate_memory_map.py`.
- core contains self-owned Mini core wrappers.
- dv contains behavioural testbench, device models, and Verilator harness
sources.
@@ -10,8 +14,10 @@ This directory is the active Mini SoC integration boundary.
behavioral/synthesis Common source set; `netlist_support.fl` is the explicit
allowlist of testbench dependencies not already present in a synthesized
netlist.
- mk contains simulator and software make fragments.
- script contains filelist, address-map, conversion, and setup helpers.
- mk contains Mini simulator and formal make fragments; shared firmware rules
live in `rtl/mk/software.mk`.
- script contains Mini filelist generation and simulator-binding helpers.
Shared parsing/conversion helpers live in `scripts/rtl`.
- top contains SoC integration RTL, including `apb4_system` for the APB4
platform block and `apb4_periph` for the APB4 peripheral container.
+2 -1
View File
@@ -1,6 +1,7 @@
# Canonical Address Map
memory_map.json is the sole source for Mini SoC address ranges. Its generator
`memory_map.json` is the sole source for Mini SoC address ranges. The shared
[generator](../../../scripts/rtl/generate_memory_map.py)
emits RTL include definitions, SDK headers, linker memory regions, and the
filelist include path into the selected build variant.
+2 -2
View File
@@ -9,7 +9,7 @@
/clusterip/common/rtl/interface/ram_if.sv
/top/rib_if.sv
/clusterip/common/rtl/utils/register.sv
/top/soc_common_fifo.sv
/ip/util/soc_common_fifo.sv
/clusterip/common/rtl/utils/spill_register.sv
/clusterip/common/rtl/stream/round_robin_arbiter.sv
/clusterip/common/rtl/utils/lfsr.sv
@@ -20,7 +20,7 @@
/clusterip/common/rtl/cdc/cdc_sync.sv
/clusterip/common/rtl/cdc/cdc_rst_ctrlr.sv
/clusterip/common/rtl/cdc/cdc_2phase.sv
/top/soc_common_cdc.sv
/ip/util/soc_common_cdc.sv
/clusterip/common/rtl/clkrst/clk_int_div.sv
/clusterip/common/rtl/clock/safe_clock_mux.sv
/clusterip/common/rtl/clkrst/rst_sync.sv
+1
View File
@@ -13,6 +13,7 @@
+incdir+/clusterip/rtc/rtl
+incdir+/clusterip/wdg/rtl
+incdir+/clusterip/crc/rtl
+incdir+/ip/core
+incdir+/ip/interconnect
+incdir+/ip/util
+incdir+/ip/memory
+10 -10
View File
@@ -1,11 +1,11 @@
/top/apb4_if_bridge.sv
/ip/interconnect/apb4_if_bridge.sv
/top/apb4_async_bridge.sv
/top/gpio_pad_bridge.sv
/ip/peripheral/gpio_pad_bridge.sv
/top/memory_pad_mux.sv
/top/ribp2rib.sv
/top/rib2ribp.sv
/top/rib2apb.sv
/top/axi4_connector.sv
/ip/interconnect/axi4_connector.sv
/top/axi4_master_idle.sv
/top/axi4_mgmt_router.sv
/top/axi4_async_bridge.sv
@@ -18,9 +18,9 @@
/top/fabric_monitor.sv
/top/soc_data_plane.sv
/top/data_plane_fault_cdc.sv
/top/axi4_error_slave.sv
/ip/interconnect/axi4_error_slave.sv
/top/rib2axi4.sv
/top/ahbl2axi4.sv
/ip/interconnect/ahbl2axi4.sv
/top/axi42apb4_system.sv
/top/axi42apb4_periph.sv
/top/axi4_word_bridge.sv
@@ -33,8 +33,8 @@
/top/retrosoc.sv
/top/retrosoc_asic.sv
/top/retrosoc_core.sv
/top/onchip_ram_reg.sv
/top/onchip_ram.sv
/ip/memory/onchip_ram_reg.sv
/ip/memory/onchip_ram.sv
/top/resource_controller.sv
/top/apb4_periph.sv
/top/apb4_system.sv
@@ -46,10 +46,10 @@
/top/clock_frequency_monitor.sv
/top/soc_clock_gate.sv
/top/soc_clock_reset_subsystem.sv
/top/mgmt_debug_reset.sv
/ip/core/mgmt_debug_reset.sv
/top/hp_lifecycle_controller.sv
/top/mgmt_debug_wrapper.sv
/top/mgmt_core_wrapper.sv
/ip/core/mgmt_debug_wrapper.sv
/ip/core/mgmt_core_wrapper.sv
/top/hp_core_wrapper.sv
/top/hp_subsystem.sv
/top/user_core_design.sv
+4 -5
View File
@@ -10,10 +10,9 @@ from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
ROOT = SCRIPT_DIR.parents[2]
FILELIST_DIR = ROOT / "rtl/mini/script"
sys.path.insert(0, str(FILELIST_DIR))
sys.path.insert(0, str(ROOT))
from filelist import FileList, write_filelist # noqa: E402
from scripts.rtl.filelist import FileList, write_filelist # noqa: E402
COMMON_RTL = ROOT / "rtl/managed/clusterip/common/rtl"
@@ -249,8 +248,8 @@ def source_files(target: str) -> list[Path]:
COMMON_RTL / "utils/register.sv",
COMMON_RTL / "utils/xchecker.sv",
ROOT / "rtl/tech/tc_sram.sv",
TOP / "onchip_ram_reg.sv",
TOP / "onchip_ram.sv",
ROOT / "rtl/ip/memory/onchip_ram_reg.sv",
ROOT / "rtl/ip/memory/onchip_ram.sv",
SCRIPT_DIR / "onchip_ram_formal.sv",
]
if target == "opipsram":
@@ -68,7 +68,7 @@
"reset": "s_jtag_trst_n_sync",
"reset_source": "jtag_trst_n_i",
"reset_primitive": "rst_sync",
"path": "rtl/mini/top/mgmt_debug_wrapper.sv",
"path": "rtl/ip/core/mgmt_debug_wrapper.sv",
"instance": "u_jtag_rst_sync",
"sta": {"source_port": "jtag_tck_i_pad", "object_type": "port", "period_ns": 100.0, "async_group": "jtag"}
},
+5 -5
View File
@@ -178,8 +178,8 @@ FORMAL_SOURCE_FILES := $(RTL_PATH)/formal/bus_formal.sv \
$(ROOT_PATH)/rtl/ip/memory/psram_pkg.sv \
$(ROOT_PATH)/rtl/ip/memory/psram_axi4.sv \
$(ROOT_PATH)/rtl/ip/memory/psram_phy.sv \
$(RTL_PATH)/top/onchip_ram_reg.sv \
$(RTL_PATH)/top/onchip_ram.sv \
$(ROOT_PATH)/rtl/ip/memory/onchip_ram_reg.sv \
$(ROOT_PATH)/rtl/ip/memory/onchip_ram.sv \
$(ROOT_PATH)/rtl/tech/tc_sram.sv \
$(ROOT_PATH)/rtl/managed/clusterip/common/rtl/utils/register.sv \
$(ROOT_PATH)/rtl/managed/clusterip/common/rtl/utils/xchecker.sv \
@@ -242,11 +242,11 @@ $(FORMAL_DIR)/%/formal.fl: $(FORMAL_FILELIST_GENERATOR) $(FORMAL_SOURCE_FILES) \
--memory-map-dir $(MEMORY_MAP_DIR) --soc-topology-dir $(SOC_TOPOLOGY_DIR) \
--user-extensions-dir $(USER_EXTENSIONS_DIR)
$(FORMAL_DIR)/%/design.v: $(FORMAL_DIR)/%/formal.fl $(RTL_PATH)/script/convt_sv2v.py \
$(RTL_PATH)/script/filelist.py $(FORMAL_SOURCE_FILES)
$(FORMAL_DIR)/%/design.v: $(FORMAL_DIR)/%/formal.fl $(ROOT_PATH)/scripts/rtl/convt_sv2v.py \
$(ROOT_PATH)/scripts/rtl/filelist.py $(FORMAL_SOURCE_FILES)
python3 $(ROOT_PATH)/scripts/run_flow.py --tool formal-sv2v \
--log $(@D)/sv2v.log --result $(@D)/result-sv2v.json \
-- python3 $(RTL_PATH)/script/convt_sv2v.py -f $< --output $@
-- python3 $(ROOT_PATH)/scripts/rtl/convt_sv2v.py -f $< --output $@
$(FORMAL_DIR)/%/prove.sby: $(FORMAL_DIR)/%/design.v \
$(FORMAL_SBY_GENERATOR)
+9 -9
View File
@@ -36,8 +36,8 @@ IVERILOG_SIM_OPTS := +sim_timeout=$(RTL_SIM_TIMEOUT) +wave_$(WAVE)
$(CONVERTED_SOC): $(if $(filter MPW,$(MINI_MODE)),$(MPW_VARIANT_STAMP)) $(FILELIST_STAMP)
@mkdir -p $(@D)
python3 $(RTL_PATH)/script/convt_sv2v.py $(RTL_FLIST) --output $@
python3 $(RTL_PATH)/script/filelist_deps.py $(RTL_FLIST) --target $@ \
python3 $(ROOT_PATH)/scripts/rtl/convt_sv2v.py $(RTL_FLIST) --output $@
python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(RTL_FLIST) --target $@ \
--output $(CONVERTED_DEPFILE)
$(IVERILOG_BEHV_FLIST): $(FILELIST_STAMP) $(CONVERTED_SOC) $(IVERILOG_FILELIST_GEN)
@@ -88,7 +88,7 @@ $(IVERILOG_BEHV_SIMV): $(IVERILOG_BEHV_FLIST)
--log $(IVERILOG_BEHV_DIR)/compile.log --result $(IVERILOG_BEHV_DIR)/result-compile.json \
--cwd $(IVERILOG_BEHV_DIR) -- $(IVERILOG) $(IVERILOG_COMMON_OPTS) \
$(IVERILOG_TIME_OPTS) -f $< -o simv -s $(RTL_TOP)
python3 $(RTL_PATH)/script/filelist_deps.py -f $(IVERILOG_BEHV_FLIST) \
python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py -f $(IVERILOG_BEHV_FLIST) \
--target $@ --output $(IVERILOG_BEHV_DEPFILE)
$(IVERILOG_NETL_SIMV): $(IVERILOG_NETL_FLIST)
@@ -97,7 +97,7 @@ $(IVERILOG_NETL_SIMV): $(IVERILOG_NETL_FLIST)
--log $(IVERILOG_NETL_DIR)/compile.log --result $(IVERILOG_NETL_DIR)/result-compile.json \
--cwd $(IVERILOG_NETL_DIR) -- $(IVERILOG) $(IVERILOG_COMMON_OPTS) \
$(IVERILOG_TIME_OPTS) -f $< -o simv -s $(RTL_TOP)
python3 $(RTL_PATH)/script/filelist_deps.py -f $(IVERILOG_NETL_FLIST) \
python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py -f $(IVERILOG_NETL_FLIST) \
--target $@ --output $(IVERILOG_NETL_DEPFILE)
$(IVERILOG_POST_SIMV): $(IVERILOG_POST_FLIST)
@@ -106,7 +106,7 @@ $(IVERILOG_POST_SIMV): $(IVERILOG_POST_FLIST)
--log $(IVERILOG_POST_DIR)/compile.log --result $(IVERILOG_POST_DIR)/result-compile.json \
--cwd $(IVERILOG_POST_DIR) -- $(IVERILOG) $(IVERILOG_COMMON_OPTS) \
$(IVERILOG_POST_OPTS) -f $< -o simv -s $(RTL_TOP) -s retrosoc_sdf_annotator
python3 $(RTL_PATH)/script/filelist_deps.py -f $(IVERILOG_POST_FLIST) \
python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py -f $(IVERILOG_POST_FLIST) \
--target $@ --output $(IVERILOG_POST_DEPFILE)
comp: $(IVERILOG_BEHV_SIMV)
@@ -114,7 +114,7 @@ netcomp: $(IVERILOG_NETL_SIMV)
postcomp: $(IVERILOG_POST_SIMV)
sim: comp
python3 $(RTL_PATH)/script/prepare_norflash.py --sim-dir $(IVERILOG_BEHV_DIR) \
python3 $(ROOT_PATH)/scripts/rtl/prepare_norflash.py --sim-dir $(IVERILOG_BEHV_DIR) \
--firmware $(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex
python3 $(ROOT_PATH)/scripts/run_flow.py --tool iverilog-sim \
--log $(IVERILOG_BEHV_DIR)/sim.log --result $(IVERILOG_BEHV_DIR)/result-sim.json \
@@ -123,7 +123,7 @@ sim: comp
--result $(IVERILOG_BEHV_DIR)/result-sim-check.json --require '$(SIM_SUCCESS_MARKER)'
netsim: netcomp
python3 $(RTL_PATH)/script/prepare_norflash.py --sim-dir $(IVERILOG_NETL_DIR) \
python3 $(ROOT_PATH)/scripts/rtl/prepare_norflash.py --sim-dir $(IVERILOG_NETL_DIR) \
--firmware $(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex
python3 $(ROOT_PATH)/scripts/run_flow.py --tool iverilog-sim \
--log $(IVERILOG_NETL_DIR)/sim.log --result $(IVERILOG_NETL_DIR)/result-sim.json \
@@ -132,7 +132,7 @@ netsim: netcomp
--result $(IVERILOG_NETL_DIR)/result-sim-check.json --require '$(SIM_SUCCESS_MARKER)'
netsim-boot: netcomp
python3 $(RTL_PATH)/script/prepare_norflash.py --sim-dir $(IVERILOG_NETL_DIR) \
python3 $(ROOT_PATH)/scripts/rtl/prepare_norflash.py --sim-dir $(IVERILOG_NETL_DIR) \
--firmware $(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex
python3 $(ROOT_PATH)/scripts/run_flow.py --tool iverilog-sim \
--log $(IVERILOG_NETL_DIR)/sim.log --result $(IVERILOG_NETL_DIR)/result-sim.json \
@@ -142,7 +142,7 @@ netsim-boot: netcomp
--result $(IVERILOG_NETL_DIR)/result-sim-check.json --require 'Hello retroSoC!'
postsim: postcomp
python3 $(RTL_PATH)/script/prepare_norflash.py --sim-dir $(IVERILOG_POST_DIR) \
python3 $(ROOT_PATH)/scripts/rtl/prepare_norflash.py --sim-dir $(IVERILOG_POST_DIR) \
--firmware $(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex
python3 $(ROOT_PATH)/scripts/run_flow.py --tool iverilog-sim \
--log $(IVERILOG_POST_DIR)/sim.log --result $(IVERILOG_POST_DIR)/result-sim.json \
+2 -2
View File
@@ -99,13 +99,13 @@ $(VCS_BEHV_SIMV) $(VCS_NETL_SIMV) $(VCS_POST_SIMV): $(MPW_VARIANT_DEP) $(FILELIS
$(FLOW_PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool vcs --log $(DIR)/driver-compile.log \
--result $(DIR)/result-compile.json --cwd $(DIR) -- \
$(SIM_TOOL) $(COMMON_OPTS) $(OPTS) $(FLIST) -top $(RTL_TOP) $(COMP_LOG)
$(FLOW_PYTHON) $(RTL_PATH)/script/filelist_deps.py $(DEPS_ARGS) --target $@ --output $(DEPFILE)
$(FLOW_PYTHON) $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(DEPS_ARGS) --target $@ --output $(DEPFILE)
$(VCS_NETL_SIMV): $(SYN_BUILD_ROOT)/out/retrosoc_asic_yosys.v
$(VCS_POST_SIMV): $(ROOT_PATH)/physical/sdf/retrosoc_asic.v $(ROOT_PATH)/physical/sdf/retrosoc_asic_CTS_MIN.sdf.gz
sim netsim postsim:
$(FLOW_PYTHON) $(RTL_PATH)/script/prepare_norflash.py --sim-dir $(DIR) \
$(FLOW_PYTHON) $(ROOT_PATH)/scripts/rtl/prepare_norflash.py --sim-dir $(DIR) \
--firmware $(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex
$(FLOW_PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool vcs-sim --stream-bytes \
--log $(DIR)/driver-sim.log \
+2 -2
View File
@@ -74,7 +74,7 @@ $(VERILATOR_STAMP): $(MPW_VARIANT_DEP) $(FILELIST_STAMP) $(VERILATOR_EXTRA_SOURC
python3 $(ROOT_PATH)/scripts/run_flow.py --tool verilator \
--log $(BUILD_DIR)/verilating.log --result $(BUILD_DIR)/result-verilate.json \
-- $(VERILATOR) $(VERILATOR_FLAGS)
python3 $(RTL_PATH)/script/filelist_deps.py $(RTL_FLIST) \
python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(RTL_FLIST) \
$(foreach source,$(VERILATOR_EXTRA_SOURCES),--extra $(source)) \
--target $@ --output $(VERILATOR_DEPFILE)
@touch $@
@@ -90,7 +90,7 @@ $(RTL_LINT_STAMP): $(MPW_VARIANT_DEP) $(FILELIST_STAMP) $(VERILATOR_EXTRA_SOURCE
python3 $(ROOT_PATH)/scripts/run_flow.py --tool rtl-lint \
--log $(RTL_LINT_DIR)/lint.log --result $(RTL_LINT_DIR)/result-rtl-lint.json \
-- $(VERILATOR) $(RTL_LINT_FLAGS)
python3 $(RTL_PATH)/script/filelist_deps.py $(RTL_FLIST) \
python3 $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(RTL_FLIST) \
$(foreach source,$(VERILATOR_EXTRA_SOURCES),--extra $(source)) \
--target $@ --output $(RTL_LINT_DEPFILE)
@touch $@
+2 -1
View File
@@ -1,7 +1,8 @@
# Canonical SoC Pin Map
`pin_map.json` is the single source for the Mini SoC logical pad ABI and its
ASIC, FPGA, Verilator, and RTL-testbench bindings. The generator emits
ASIC, FPGA, Verilator, and RTL-testbench bindings. The shared
[generator](../../../scripts/rtl/generate_pin_map.py) emits
temporary SystemVerilog include files below the selected build variant; do not
edit generated files.
+4 -1
View File
@@ -5,9 +5,12 @@ from __future__ import annotations
import argparse
import gzip
import re
import sys
from pathlib import Path
from filelist import atomic_write, parse_filelists, write_filelist
REPO_ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(REPO_ROOT))
from scripts.rtl.filelist import atomic_write, parse_filelists, write_filelist # noqa: E402
SCRIPT_DIR = Path(__file__).resolve().parent
+4 -1
View File
@@ -4,9 +4,12 @@ from __future__ import annotations
import argparse
import re
import sys
from pathlib import Path
from filelist import atomic_write
REPO_ROOT = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(REPO_ROOT))
from scripts.rtl.filelist import atomic_write # noqa: E402
SCRIPT_DIR = Path(__file__).resolve().parent
+6
View File
@@ -0,0 +1,6 @@
# Shared RTL/SDK Build Rules
`software.mk` owns common compiler, linker and firmware artifact rules for Mini
and Tiny. Product configuration and application source selection remain explicit.
Both products include this canonical file directly. Changes require both
product configuration tests, affected firmware builds, and SDK gates.
+20 -2
View File
@@ -142,6 +142,17 @@ CRT_SRCS := $(ROOT_PATH)/crt/arch/riscv/startup.S \
$(ROOT_PATH)/crt/src/hal/user_ip.c \
$(ROOT_PATH)/crt/src/hal/user_core.c
ifeq ($(SOC),TINY)
DEF_VAL += -DRS_SOC_TINY
CFLAGS += -DRS_SOC_TINY
TINY_CRT_NAMES := startup.S clzsi2.c divdi3.c ffssi2.c udivdi3.c umoddi3.c \
stdlib.c string.c console.c printf.c archinfo.c clint.c uart_math.c uart.c \
gpio_math.c gpio.c timer_math.c timer.c pwm.c rtc.c wdg.c watchdog.c i2c_math.c i2c.c \
dma_math.c dma.c onchip_sram.c xpi.c
CRT_SRCS := $(foreach source,$(CRT_SRCS),$(if $(filter $(notdir $(source)),$(TINY_CRT_NAMES)),$(source)))
CRT_SRCS += $(ROOT_PATH)/crt/src/hal/sysctrl.c
endif
ifeq ($(HAVE_CSR),YES)
CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/system_irq.S
CRT_SRCS += $(ROOT_PATH)/crt/src/core/system_irq_handler.c
@@ -154,7 +165,7 @@ APP_SRCS :=
APP_INC_DIRS :=
APP_CFLAGS :=
APP_CRT_SRCS :=
APP_MK := $(ROOT_PATH)/app/apps/$(APP)/app.mk
APP_MK := $(ROOT_PATH)/app/apps/$(APP)/$(if $(filter TINY,$(SOC)),tiny.mk,app.mk)
ifeq ($(wildcard $(APP_MK)),)
$(error Application profile not found: $(APP_MK))
@@ -219,6 +230,11 @@ FORCE_VERSION:
upd_ver_info: $(VERSION_HEADER)
ifeq ($(SOC),TINY)
asm: tiny-boot-image
cp $(SW_BUILD_DIR)/tiny_boot.hex $(SW_BUILD_DIR)/$(ASM_FIRMWARE_NAME).hex
cp $(SW_BUILD_DIR)/tiny_boot.bin $(SW_BUILD_DIR)/$(ASM_FIRMWARE_NAME).bin
else
asm: $(MPW_VARIANT_DEP) $(MEMORY_MAP_STAMP)
@mkdir -p $(SW_BUILD_DIR)/asm
$(MAKE) -C $(ROOT_PATH)/app/asm OUT_DIR=$(SW_BUILD_DIR)/asm \
@@ -227,8 +243,10 @@ asm: $(MPW_VARIANT_DEP) $(MEMORY_MAP_STAMP)
cp $(SW_BUILD_DIR)/asm/hello-asm.bin $(SW_BUILD_DIR)/$(ASM_FIRMWARE_NAME).bin
cp $(SW_BUILD_DIR)/asm/hello-asm.txt $(SW_BUILD_DIR)/$(ASM_FIRMWARE_NAME)_all.txt
endif
$(FIRMWARE_ELF): $(MPW_VARIANT_DEP) $(MEMORY_MAP_STAMP) $(SOC_TOPOLOGY_STAMP) $(SOC_IRQ_METADATA) $(USER_EXTENSIONS_STAMP) $(ARCHINFO_METADATA_STAMP) $(VERSION_HEADER) $(SRC_PATH) $(SW_HEADERS) $(LDS_PATH) \
$(ROOT_PATH)/rtl/mini/mk/software.mk
$(ROOT_PATH)/rtl/mk/software.mk $(APP_MK)
@mkdir -p $(SW_BUILD_DIR)
cd $(SW_BUILD_DIR) && $(CP) -P -o $(LINK_TYPE).lds $(LDS_PATH)
cp $(MEMORY_REGIONS_LD) $(SW_BUILD_DIR)/memory_regions.ld
+2 -1
View File
@@ -5,7 +5,8 @@
"name": "owned-rtl",
"paths": [
"rtl/ip",
"rtl/mini/top"
"rtl/mini/top",
"rtl/tiny/top"
],
"status": "prototype",
"baseline_revision": null,
+55 -45
View File
@@ -96,12 +96,21 @@
}
],
"inventory": {
"rtl/ip/core": [
"mgmt_core_wrapper.sv",
"mgmt_debug_reset.sv",
"mgmt_debug_wrapper.sv"
],
"rtl/ip/experimental": [
"apb4_gpu.sv",
"axi4f2ribp.sv",
"wb2ribp.sv"
],
"rtl/ip/interconnect": [
"ahbl2axi4.sv",
"apb4_if_bridge.sv",
"axi4_connector.sv",
"axi4_error_slave.sv",
"axi4l2ribp.sv",
"ribp2ribp.sv",
"ribp_regslice.sv"
@@ -110,6 +119,9 @@
"apb4_opipsram.sv",
"apb4_psram.sv",
"axi4_sdram.sv",
"onchip_ram.sv",
"onchip_ram_define.svh",
"onchip_ram_reg.sv",
"opipsram_axi4.sv",
"opipsram_core.sv",
"opipsram_define.svh",
@@ -125,11 +137,11 @@
"psram_phy.sv",
"psram_pkg.sv",
"psram_reg.sv",
"sdram_axi4.sv",
"sdram_clkgen.sv",
"sdram_core.sv",
"sdram_define.svh",
"sdram_pkg.sv",
"sdram_axi4.sv",
"sdram_reg.sv"
],
"rtl/ip/multimedia": [
@@ -142,8 +154,8 @@
"apu_codec_sequencer.sv",
"apu_codec_transport.sv",
"apu_control_store.sv",
"apu_dma.sv",
"apu_define.svh",
"apu_dma.sv",
"apu_entropy_engine.sv",
"apu_kernel_engine.sv",
"apu_kws_apum_profile.svh",
@@ -159,9 +171,9 @@
"apu_primitive_dispatcher.sv",
"apu_proof_memo.sv",
"apu_reconstruction_engine.sv",
"apu_reg.sv",
"apu_resampler.sv",
"apu_ring_scheduler.sv",
"apu_reg.sv",
"apu_stream_router.sv",
"apu_transform_engine.sv",
"axi4s_dvp.sv",
@@ -171,8 +183,8 @@
"ga2d_addr_gen.sv",
"ga2d_axi4_master.sv",
"ga2d_core.sv",
"ga2d_dma.sv",
"ga2d_define.svh",
"ga2d_dma.sv",
"ga2d_pixel.sv",
"ga2d_pkg.sv",
"ga2d_reg.sv",
@@ -217,7 +229,6 @@
],
"rtl/ip/peripheral": [
"apb4_clint.sv",
"clock_ctrl_if.sv",
"apb4_dma.sv",
"apb4_gpio.sv",
"apb4_hp_mailbox.sv",
@@ -229,6 +240,7 @@
"clint_if.sv",
"clint_reg.sv",
"clint_timebase.sv",
"clock_ctrl_if.sv",
"dma_axi4_master.sv",
"dma_core.sv",
"dma_define.svh",
@@ -238,6 +250,7 @@
"gpio_core.sv",
"gpio_define.svh",
"gpio_if.sv",
"gpio_pad_bridge.sv",
"gpio_reg.sv",
"hp_mailbox_define.svh",
"pll_ctrl_if.sv",
@@ -250,6 +263,17 @@
"timer_reg.sv",
"user_gpio_if.sv"
],
"rtl/ip/security": [
"apb4_crypto.sv",
"crypto_aes_core.sv",
"crypto_aes_engine.sv",
"crypto_define.svh",
"crypto_montgomery.sv",
"crypto_pkg.sv",
"crypto_rsa_core.sv",
"crypto_sha2_core.sv",
"crypto_sha2_engine.sv"
],
"rtl/ip/serial": [
"apb4_i2c.sv",
"apb4_i2c_define.svh",
@@ -280,17 +304,6 @@
"ws2812_if.sv",
"ws2812_reg.sv"
],
"rtl/ip/security": [
"apb4_crypto.sv",
"crypto_aes_core.sv",
"crypto_aes_engine.sv",
"crypto_define.svh",
"crypto_montgomery.sv",
"crypto_pkg.sv",
"crypto_rsa_core.sv",
"crypto_sha2_core.sv",
"crypto_sha2_engine.sv"
],
"rtl/ip/storage": [
"apb4_sdio.sv",
"apb4_spisd.sv",
@@ -324,9 +337,6 @@
"xpi_pkg.sv",
"xpi_reg.sv"
],
"rtl/ip/util": [
"async_fifo.sv"
],
"rtl/ip/usb": [
"apb4_usb2.sv",
"usb2_define.svh",
@@ -345,53 +355,49 @@
"usb2_ulpi_if.sv",
"usb2_ulpi_link.sv"
],
"rtl/ip/util": [
"async_fifo.sv",
"soc_common_cdc.sv",
"soc_common_fifo.sv"
],
"rtl/mini/top": [
"ahbl2axi4.sv",
"ahbl2ribp.sv",
"apb4_if_bridge.sv",
"apb4_async_bridge.sv",
"apb4_periph.sv",
"apb4_system.sv",
"axi42apb4_system.sv",
"axi42apb4.svh",
"axi42apb4_periph.sv",
"axi42apb4_state.svh",
"axi42apb4_system.sv",
"axi42ram.sv",
"axi42ribp.sv",
"axi42ribp_burst.sv",
"axi4_bus.sv",
"axi4_address_gate.sv",
"axi4_async_bridge.sv",
"axi4_connector.sv",
"axi4_bus.sv",
"axi4_data_crossbar.sv",
"axi4_target_guard.sv",
"axi4_downsizer_64to32.sv",
"axi4_error_slave.sv",
"axi4_id_prefix.sv",
"axi4_interconnect.sv",
"axi4_master_idle.sv",
"axi4_mgmt_router.sv",
"axi4_target_guard.sv",
"axi4_upsizer_32to64.sv",
"axi4_word_bridge.sv",
"core_wrapper.sv",
"clock_config_controller.sv",
"clock_frequency_monitor.sv",
"core_wrapper.sv",
"data_plane_fault_cdc.sv",
"extension_compat.sv",
"extension_dma_master.sv",
"extension_slot.sv",
"extension_subsystem.sv",
"fabric_monitor.sv",
"gpio_pad_bridge.sv",
"hp_axi4_mux3.sv",
"hp_core_wrapper.sv",
"hp_subsystem.sv",
"hp_lifecycle_controller.sv",
"mgmt_core_wrapper.sv",
"mgmt_debug_reset.sv",
"mgmt_debug_wrapper.sv",
"hp_subsystem.sv",
"memory_pad_mux.sv",
"onchip_ram_define.svh",
"onchip_ram_reg.sv",
"onchip_ram.sv",
"pll_rcu_controller.sv",
"rcu.sv",
"resource_controller.sv",
@@ -412,24 +418,28 @@
"soc_clock_config.svh",
"soc_clock_gate.sv",
"soc_clock_reset_subsystem.sv",
"soc_common_cdc.sv",
"soc_common_fifo.sv",
"soc_data_plane.sv",
"user_core_design.sv",
"user_core_top.sv",
"user_extensions.svh",
"user_ip_design_template.sv",
"user_ip_top.sv",
"user_ip_wrapper.sv",
"axi42apb4.svh",
"axi42apb4_state.svh"
"user_ip_wrapper.sv"
],
"rtl/tiny/top": [
"retrosoc_tiny.sv",
"retrosoc_tiny_asic.sv",
"tiny_archinfo.sv",
"tiny_axi42apb4.sv",
"tiny_axi4_fabric.sv",
"tiny_sysctrl.sv"
]
},
"reviewed_boundaries": [
{
"paths": [
"rtl/ip/experimental/axi4f2ribp.sv",
"rtl/ip/experimental/apb4_gpu.sv",
"rtl/ip/experimental/axi4f2ribp.sv",
"rtl/ip/experimental/wb2ribp.sv"
],
"result": "inactive experimental source",
@@ -471,16 +481,16 @@
},
{
"paths": [
"rtl/mini/top/onchip_ram.sv",
"rtl/mini/top/onchip_ram_reg.sv"
"rtl/ip/memory/onchip_ram.sv",
"rtl/ip/memory/onchip_ram_reg.sv"
],
"result": "reviewed AXI and technology-memory boundary",
"rationale": "AXI and APB state uses Common registers; the synchronous bank array retains the stable technology wrapper and PDK SRAM pin boundary."
},
{
"paths": [
"rtl/mini/top/soc_common_cdc.sv",
"rtl/mini/top/soc_common_fifo.sv"
"rtl/ip/util/soc_common_cdc.sv",
"rtl/ip/util/soc_common_fifo.sv"
],
"result": "managed compatibility wrapper retained",
"rationale": "The narrow self-owned wrappers preserve required Verilator filename behavior while including managed Common source."
+4 -2
View File
@@ -4,7 +4,8 @@
"owned": {
"roots": [
"rtl/ip",
"rtl/mini/top"
"rtl/mini/top",
"rtl/tiny/top"
],
"suffixes": [
".sv",
@@ -18,7 +19,8 @@
"verification": {
"roots": [
"rtl/mini/formal",
"rtl/mini/dv"
"rtl/mini/dv",
"rtl/tiny/dv"
],
"suffixes": [
".sv",
+151
View File
@@ -0,0 +1,151 @@
export CCACHE_DIR := $(CACHE_ROOT)/ccache/verilator
export CCACHE_TEMPDIR := $(CACHE_ROOT)/ccache/verilator/tmp
TINY_GENERATED_DIR := $(VARIANT_ROOT)/generated/tiny
GENERATED_FL_DIR := $(FLOW_FILELIST_DIR)
FILELIST_STAMP := $(GENERATED_FL_DIR)/.stamp
MEMORY_MAP_DIR := $(TINY_GENERATED_DIR)/memory_map
MEMORY_MAP_C_DIR := $(MEMORY_MAP_DIR)/include
MEMORY_MAP_LINKER_DIR := $(MEMORY_MAP_DIR)/linker
MEMORY_MAP_STAMP := $(FILELIST_STAMP)
PIN_MAP_DIR := $(TINY_GENERATED_DIR)/pin_map
SOC_TOPOLOGY_INCLUDE_DIR := $(TINY_GENERATED_DIR)/include
SOC_TOPOLOGY_STAMP := $(FILELIST_STAMP)
SOC_IRQ_METADATA := $(SOC_TOPOLOGY_INCLUDE_DIR)/retrosoc/generated/irq_metadata.h
USER_EXTENSIONS_DIR := $(TINY_GENERATED_DIR)
USER_EXTENSIONS_STAMP := $(FILELIST_STAMP)
ARCHINFO_METADATA_DIR := $(TINY_GENERATED_DIR)/archinfo
ARCHINFO_METADATA_SCRIPT := $(ROOT_PATH)/rtl/managed/clusterip/archinfo/scripts/generate_metadata.py
ARCHINFO_METADATA_STAMP := $(ARCHINFO_METADATA_DIR)/.stamp
TINY_MAPS := $(wildcard $(RTL_PATH)/address_map/*.json $(RTL_PATH)/pin_map/*.json $(RTL_PATH)/integration/*.json)
TINY_TEMPLATES := $(wildcard $(RTL_PATH)/filelist/*.fl)
TINY_TOOLS := $(ROOT_PATH)/scripts/generate_tiny.py $(wildcard $(ROOT_PATH)/scripts/rtl/*.py)
$(ARCHINFO_METADATA_STAMP): $(LOCK_FILE) $(wildcard $(ARCHINFO_METADATA_SCRIPT))
@test -f $(ARCHINFO_METADATA_SCRIPT) || { echo "Run Tiny setup first" >&2; exit 1; }
$(PYTHON) $(ARCHINFO_METADATA_SCRIPT) --repo-root $(ROOT_PATH) --lock $(LOCK_FILE) \
--config-digest $(CONFIG_DIGEST) $(if $(filter YES,$(BUILD_RELEASE)),--release) \
--output-sv $(ARCHINFO_METADATA_DIR)/archinfo_integration_metadata.svh \
--output-c $(ARCHINFO_METADATA_DIR)/archinfo_integration_metadata.h
@touch $@
$(FILELIST_STAMP): $(ROOT_PATH)/Makefile $(RTL_PATH)/Makefile $(TINY_MAPS) $(TINY_TEMPLATES) $(TINY_TOOLS) $(ARCHINFO_METADATA_STAMP)
$(PYTHON) $(ROOT_PATH)/scripts/generate_tiny.py --output $(TINY_GENERATED_DIR) \
--filelists $(GENERATED_FL_DIR) $(foreach define,$(DEF_LIST),--define $(define))
@touch $@
$(SOC_IRQ_METADATA): $(FILELIST_STAMP)
@test -f $@
generate_filelist memory-map pin-map soc-topology user-extensions: $(FILELIST_STAMP)
archinfo-metadata: $(ARCHINFO_METADATA_STAMP)
check-memory-map:
$(PYTHON) $(ROOT_PATH)/scripts/rtl/generate_memory_map.py --map $(RTL_PATH)/address_map/memory_map.json --check
check-pin-map:
$(PYTHON) $(ROOT_PATH)/scripts/rtl/generate_pin_map.py --map $(RTL_PATH)/pin_map/pin_map.json --check
check-soc-topology:
$(PYTHON) $(ROOT_PATH)/scripts/generate_tiny.py --check
check-clock-reset-domains:
$(PYTHON) $(ROOT_PATH)/scripts/check_clock_reset_domains.py --map $(RTL_PATH)/integration/clock_reset_domains.json --root $(ROOT_PATH)
RTL_FILELISTS := $(addprefix $(GENERATED_FL_DIR)/,def.fl inc.fl commonip.fl clusterip.fl ip.fl tech.fl core_hazard3.fl top.fl)
RTL_FLIST := $(foreach filelist,$(RTL_FILELISTS),-f $(filelist))
PDK_FILELIST := $(GENERATED_FL_DIR)/pdk_ihp130.fl
TINY_TB_FLIST := -f $(GENERATED_FL_DIR)/tb.fl
TOP_DESIGN := retrosoc_tiny_asic
RTL_NAME := retrosoc_tiny_asic
OPENSTA_NETLIST := $(SYN_BUILD_ROOT)/out/$(RTL_NAME)_yosys.v
OPENSTA_CONFIG := $(SYN_BUILD_ROOT)/out/$(RTL_NAME)_yosys.config
NETLIST_PATH := $(OPENSTA_NETLIST)
TINY_CONVERTED := $(SIM_BUILD_ROOT)/converted_soc.v
TINY_DEPFILE := $(SIM_BUILD_ROOT)/sources.d
TINY_LINT_LOG := $(VARIANT_ROOT)/lint/verilator/lint.log
SOC_SIM_TIME ?= 1800
TINY_SIM_TIMEOUT ?= 20000000
VERILATOR ?= verilator
IVERILOG ?= iverilog
VVP ?= vvp
include $(ROOT_PATH)/rtl/mk/software.mk
-include $(TINY_DEPFILE)
$(TINY_CONVERTED): $(FILELIST_STAMP)
@mkdir -p $(@D)
$(PYTHON) $(ROOT_PATH)/scripts/rtl/convt_sv2v.py $(RTL_FLIST) --output $@
$(PYTHON) $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(RTL_FLIST) \
--target $@ --output $(TINY_DEPFILE)
ifeq ($(SIMU),VERILATOR)
$(SIM_BUILD_ROOT)/emu: $(FILELIST_STAMP) $(wildcard $(RTL_PATH)/dv/*.sv)
@mkdir -p $(SIM_BUILD_ROOT) $(CCACHE_TEMPDIR)
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool verilator \
--log $(SIM_BUILD_ROOT)/compile.log --result $(SIM_BUILD_ROOT)/result-compile.json -- \
$(VERILATOR) --binary --timing --assert -j $(JOBS) --top-module $(RTL_TOP) \
-Wno-fatal --timescale 1ns/1ps --Mdir $(SIM_BUILD_ROOT)/obj_dir -o $(SIM_BUILD_ROOT)/emu \
$(RTL_FLIST) -f $(PDK_FILELIST) $(TINY_TB_FLIST)
$(PYTHON) $(ROOT_PATH)/scripts/rtl/filelist_deps.py $(RTL_FLIST) $(TINY_TB_FLIST) \
--target $@ --output $(TINY_DEPFILE)
comp: $(SIM_BUILD_ROOT)/emu
TINY_RUN := timeout --foreground $(SOC_SIM_TIME)s $(SIM_BUILD_ROOT)/emu
else
$(SIM_BUILD_ROOT)/simv: $(TINY_CONVERTED) $(wildcard $(RTL_PATH)/dv/*.sv)
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool iverilog \
--log $(SIM_BUILD_ROOT)/compile.log --result $(SIM_BUILD_ROOT)/result-compile.json -- \
$(IVERILOG) -g2012 -gno-specify -s $(RTL_TOP) -o $@ -f $(GENERATED_FL_DIR)/def.fl \
-f $(GENERATED_FL_DIR)/inc.fl -f $(PDK_FILELIST) $(TINY_TB_FLIST) $(TINY_CONVERTED)
comp: $(SIM_BUILD_ROOT)/simv
TINY_RUN := $(VVP) $(SIM_BUILD_ROOT)/simv
endif
rtl-lint: $(FILELIST_STAMP) | manifest
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool rtl-lint \
--log $(TINY_LINT_LOG) --result $(VARIANT_ROOT)/lint/verilator/result-rtl-lint.json -- \
$(VERILATOR) --lint-only --timing --assert --timescale 1ns/1ps --Wall -Wno-fatal \
--top-module retrosoc_tiny_asic $(RTL_FLIST) -f $(PDK_FILELIST)
check-rtl-lint: rtl-lint
$(PYTHON) $(ROOT_PATH)/scripts/analyze_warnings.py check --root $(ROOT_PATH) \
--profile $(PROFILE_NAME) --variant-root $(VARIANT_ROOT) --tool rtl-lint \
--output $(META_DIR)/rtl-lint-warnings.json
sim: comp firmware | manifest
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool $(SIM_TOOL_NAME)-sim \
--log $(SIM_BUILD_ROOT)/sim.log --result $(SIM_BUILD_ROOT)/result-sim.json -- \
$(TINY_RUN) +firmware=$(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex +max_cycles=$(TINY_SIM_TIMEOUT)
$(PYTHON) $(ROOT_PATH)/scripts/check_simulation.py --log $(SIM_BUILD_ROOT)/sim.log \
--result $(SIM_BUILD_ROOT)/result-sim-check.json --require '$(SIM_SUCCESS_MARKER)'
netcomp: $(FILELIST_STAMP)
@mkdir -p $(NETLIST_SIM_ROOT)
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool iverilog \
--log $(NETLIST_SIM_ROOT)/compile.log --result $(NETLIST_SIM_ROOT)/result-compile.json -- \
$(IVERILOG) -g2012 -gno-specify -DRETROSOC_SOC__TINY_NETLIST -s $(RTL_TOP) -o $(NETLIST_SIM_ROOT)/simv \
-f $(GENERATED_FL_DIR)/def.fl -f $(GENERATED_FL_DIR)/inc.fl -f $(PDK_FILELIST) \
$(TINY_TB_FLIST) $(NETLIST_PATH)
netsim: netcomp firmware | manifest
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool iverilog-sim \
--log $(NETLIST_SIM_ROOT)/sim.log --result $(NETLIST_SIM_ROOT)/result-sim.json -- \
$(VVP) $(NETLIST_SIM_ROOT)/simv +firmware=$(SW_BUILD_DIR)/$(SIM_FIRMWARE_NAME).hex +max_cycles=$(TINY_SIM_TIMEOUT)
$(PYTHON) $(ROOT_PATH)/scripts/check_simulation.py --log $(NETLIST_SIM_ROOT)/sim.log \
--result $(NETLIST_SIM_ROOT)/result-sim-check.json --require '$(SIM_SUCCESS_MARKER)'
.PHONY: generate_filelist memory-map pin-map soc-topology user-extensions archinfo-metadata \
check-memory-map check-pin-map check-soc-topology check-clock-reset-domains comp sim \
rtl-lint check-rtl-lint netcomp netsim netsim-boot
TINY_BOOT_ELF := $(SW_BUILD_DIR)/tiny_boot.elf
$(TINY_BOOT_ELF): $(ROOT_PATH)/app/asm/tiny_boot.S $(FILELIST_STAMP)
@mkdir -p $(SW_BUILD_DIR)
$(CC) -march=rv32im_zicsr -mabi=ilp32 -nostdlib -I$(MEMORY_MAP_C_DIR) -I$(SOC_TOPOLOGY_INCLUDE_DIR) \
-Wl,-Ttext=0x0,--entry=_start,--build-id=none -o $@ $<
$(OBJC) -O verilog $@ $(SW_BUILD_DIR)/tiny_boot.hex
$(OBJC) -O binary $@ $(SW_BUILD_DIR)/tiny_boot.bin
tiny-boot-image: $(TINY_BOOT_ELF)
netsim-boot: netcomp tiny-boot-image | manifest
$(PYTHON) $(ROOT_PATH)/scripts/run_flow.py --tool iverilog-sim \
--log $(NETLIST_SIM_ROOT)/sim.log --result $(NETLIST_SIM_ROOT)/result-sim.json -- \
$(VVP) $(NETLIST_SIM_ROOT)/simv +firmware=$(SW_BUILD_DIR)/tiny_boot.hex +max_cycles=100000
$(PYTHON) $(ROOT_PATH)/scripts/check_simulation.py --log $(NETLIST_SIM_ROOT)/sim.log \
--result $(NETLIST_SIM_ROOT)/result-sim-check.json --require 'SIM_TEST_PASS'
.PHONY: tiny-boot-image
+27
View File
@@ -0,0 +1,27 @@
# Tiny MCU Integration
Tiny is the independent single-Hazard3 wired MCU product. Its frozen contract
is [Tiny MCU](../../docs/ip/tiny-soc.md). Use
`make CONFIG=configs/ci/ihp130-tiny.mk setup` followed by
`make CONFIG=configs/ci/ihp130-tiny.mk firmware sim`.
`top` owns product integration, `address_map`, `pin_map` and `integration` own
canonical address, pad, IRQ and clock/reset inputs, `filelist` selects sources,
`dv` owns product verification, and `mk` owns product configuration. Reusable
RTL lives in `rtl/ip`; Common and Hazard3 remain locked managed inputs.
No Tiny source list includes RIB/RIBP or Mini product RTL. Build rules invoke
shared helpers in `scripts/rtl` directly; generated files belong only under
the selected build variant.
The initial IHP130 profile has 128 KiB SRAM, 24 MHz AXI32/APB4, four DMA channels,
and RV32IMC without atomics. Wireless, external RAM, HP cores and accelerators
are outside this release. Run both Icarus and Verilator, the Tiny directed
tests, and the IHP130 regression before claiming qualification. Synthesis and
STA use the Tiny top and clock inventory, not Mini constraints.
`make CONFIG=configs/ci/ihp130-tiny.mk regress-pr` runs only Tiny's IHP130
matrix. The regression runner also accepts `--soc TINY`; leaving it unset
retains the combined Mini/Tiny IHP130 matrix. `netsim-boot` uses the compact
assembly SRAM/pad test, while `netsim` uses the full SDK acceptance image.
See the [verification record](../../docs/ip/tiny-soc-verification.md) for
qualification boundaries and the observed reset-distribution timing deficit.
+406
View File
@@ -0,0 +1,406 @@
{
"schema_version": 2,
"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_APB4_PERIPH_WAIT_LO",
"offset": "0x5C"
},
{
"symbol": "PERF_APB4_PERIPH_WAIT_HI",
"offset": "0x60"
},
{
"symbol": "PERF_APB4_SYSTEM_WAIT_LO",
"offset": "0x64"
},
{
"symbol": "PERF_APB4_SYSTEM_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"
},
{
"symbol": "TEST_STATUS",
"offset": "0x84"
},
{
"symbol": "RTC_WAKE_STATUS",
"offset": "0x88"
},
{
"symbol": "PERF_SDIO0_WAIT_LO",
"offset": "0x8C"
},
{
"symbol": "PERF_SDIO0_WAIT_HI",
"offset": "0x90"
},
{
"symbol": "PERF_SDIO1_WAIT_LO",
"offset": "0x94"
},
{
"symbol": "PERF_SDIO1_WAIT_HI",
"offset": "0x98"
},
{
"symbol": "PERF_USB2_WAIT_LO",
"offset": "0x9C"
},
{
"symbol": "PERF_USB2_WAIT_HI",
"offset": "0xA0"
},
{
"symbol": "HP_CTRL",
"offset": "0xA4"
},
{
"symbol": "HP_STATUS",
"offset": "0xA8"
},
{
"symbol": "DEBUG_SELECT",
"offset": "0xAC"
},
{
"symbol": "CLK_HP_REQ",
"offset": "0xB0"
},
{
"symbol": "CLK_HP_CURRENT",
"offset": "0xB4"
},
{
"symbol": "CLK_LP_CFG",
"offset": "0xB8"
},
{
"symbol": "CLK_PCLK_CFG",
"offset": "0xBC"
},
{
"symbol": "CLK_STATUS",
"offset": "0xC0"
},
{
"symbol": "CLK_FAULT",
"offset": "0xC4"
},
{
"symbol": "CLK_TIMEOUT",
"offset": "0xC8"
},
{
"symbol": "CLK_GATE",
"offset": "0xCC"
},
{
"symbol": "MEM_PAD_CTRL",
"offset": "0xD0"
},
{
"symbol": "MEM_PAD_STATUS",
"offset": "0xD4"
},
{
"symbol": "MEM_PAD_FAULT",
"offset": "0xD8"
}
],
"regions": [
{
"symbol": "FLASH",
"base": "0x00000000",
"size": "0x01000000",
"route": "axi4",
"kind": "active",
"public": true,
"linker": "FLASH",
"user_access": "ro",
"burst": "incr16"
},
{
"symbol": "APB4_GPIO",
"base": "0x10000000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_UART0",
"base": "0x10001000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_TIM0",
"base": "0x10002000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_TIM1",
"base": "0x10003000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_I2C0",
"base": "0x10006000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_XPI",
"base": "0x10009000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "APB4_DMA",
"base": "0x1000A000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "APB4_SYSCTRL",
"base": "0x1000B000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "APB4_CLINT",
"base": "0x10020000",
"size": "0x00010000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "APB4_I2C1",
"base": "0x10011000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_GPIO_ADMIN",
"base": "0x10014000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "APB4_SRAM",
"base": "0x10017000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "APB4_UART1",
"base": "0x10018000",
"size": "0x00001000",
"route": "apb4_periph",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_ARCHINFO",
"base": "0x20000000",
"size": "0x00001000",
"route": "apb4_system",
"kind": "active",
"public": true,
"user_access": "ro"
},
{
"symbol": "APB4_PWM",
"base": "0x20002000",
"size": "0x00001000",
"route": "apb4_system",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_RTC",
"base": "0x20004000",
"size": "0x00001000",
"route": "apb4_system",
"kind": "active",
"public": true,
"user_access": "rw"
},
{
"symbol": "APB4_WDG",
"base": "0x20005000",
"size": "0x00001000",
"route": "apb4_system",
"kind": "active",
"public": true,
"user_access": "none"
},
{
"symbol": "SRAM",
"base": "0x30000000",
"size": "0x00020000",
"size_options": [
"0x00001000",
"0x00004000",
"0x00008000",
"0x00010000",
"0x00020000"
],
"route": "ram",
"kind": "active",
"public": true,
"linker": "SRAM",
"user_access": "rw",
"burst": "incr16"
},
{
"symbol": "XPI",
"base": "0x50000000",
"size": "0x10000000",
"route": "axi4",
"kind": "active",
"public": true,
"user_access": "rw",
"burst": "incr16"
}
],
"legacy_rib": false,
"capability_header": "retrosoc/generated/soc_features.h"
}
+86
View File
@@ -0,0 +1,86 @@
// Copyright (c) 2026 Yuchi Miao
// SPDX-License-Identifier: MulanPSL-2.0
`timescale 1ns / 1ps
module retrosoc_tiny_tb;
logic s_clk_driver = 1'b0;
wire s_clk = s_clk_driver;
logic s_reset_driver = 1'b0;
wire s_rst_n = s_reset_driver;
wire s_uart0_tx, s_uart1_tx;
wire s_uart0_rx = 1'b1;
wire s_uart1_rx = 1'b1;
wire s_jtag_tck = 1'b0;
wire s_jtag_tms = 1'b1;
wire s_jtag_tdi = 1'b0;
wire s_jtag_trst_n = s_rst_n;
wire s_jtag_tdo;
tri1 [31:0] s_gpio;
wire s_xpi_sck;
wire [ 3:0] s_xpi_nss;
tri [ 3:0] s_xpi_data;
integer s_cycles;
integer s_max_cycles = 20000000;
integer s_done_cycles = 0;
logic [ 7:0] s_uart_byte;
`ifdef RETROSOC_SOC__TINY_NETLIST
wire [7:0] s_test_code = {
u_dut.s_test_code_7_,
u_dut.s_test_code_6_,
u_dut.s_test_code_5_,
u_dut.s_test_code_4_,
u_dut.s_test_code_3_,
u_dut.s_test_code_2_,
u_dut.s_test_code_1_,
u_dut.s_test_code_0_
};
`else
wire [7:0] s_test_code = u_dut.s_test_code;
`endif
always #20.833333 s_clk_driver = !s_clk_driver;
initial begin
if ($value$plusargs("max_cycles=%d", s_max_cycles)) begin
end
repeat (20) @(posedge s_clk);
@(negedge s_clk);
s_reset_driver = 1'b1;
for (s_cycles = 0; s_cycles < s_max_cycles; s_cycles = s_cycles + 1) begin
@(posedge s_clk);
if (u_dut.s_test_done) begin
if (!u_dut.s_test_pass) $fatal(1, "SIM_TEST_FAIL code=%0d", s_test_code);
s_done_cycles = s_done_cycles + 1;
if (s_done_cycles == 128) begin
$display("SIM_TEST_PASS Tiny cycles=%0d", s_cycles);
$finish;
end
end
end
if (s_done_cycles != 128) $fatal(1, "SIM_TEST_TIMEOUT Tiny cycles=%0d", s_cycles);
end
`ifdef RETROSOC_SOC__TINY_NETLIST
// UART0 diagnostic output; SYSCTRL remains the authoritative test verdict.
initial
forever begin
@(negedge s_uart0_tx);
#1627.604;
for (int bit_index = 0; bit_index < 8; bit_index++) begin
s_uart_byte[bit_index] = s_uart0_tx;
#1085.069;
end
$write("%c", s_uart_byte);
end
`endif
retrosoc_tiny_asic u_dut (
`include "retrosoc_asic_tb_bindings.svh"
);
tiny_qspi_nor u_flash (
.sck_i (s_xpi_sck),
.cs_n_i (s_xpi_nss[0]),
.data_io(s_xpi_data)
);
endmodule
+91
View File
@@ -0,0 +1,91 @@
// Copyright (c) 2026 Yuchi Miao
// SPDX-License-Identifier: MulanPSL-2.0
`timescale 1ns / 1ps
// Pin-level 0xEB NOR model: 8 command bits, 24 quad address bits, 8 mode
// bits and four dummy clocks. Unsupported commands fail closed. This model
// verifies reset-read transport; program/erase and analog NOR timing are not
// represented. Both simulators use exactly this same serial model.
module tiny_qspi_nor (
input logic sck_i,
input logic cs_n_i,
inout wire [3:0] data_io
);
typedef enum logic [2:0] {
Command,
Address,
Mode,
Dummy,
Data
} state_e;
state_e s_state;
logic [ 7:0] s_memory [0:16777215];
logic [ 7:0] s_command;
logic [23:0] s_address;
logic [ 3:0] s_output;
integer s_count;
integer s_nibble;
string s_firmware;
assign data_io = (!cs_n_i && (s_state == Data)) ? s_output : 4'bzzzz;
initial begin
s_state = Command;
s_count = 0;
s_command = '0;
s_address = '0;
if (!$value$plusargs("firmware=%s", s_firmware)) $fatal(1, "Missing +firmware hex image");
$readmemh(s_firmware, s_memory);
end
always @(posedge sck_i or posedge cs_n_i) begin
if (cs_n_i) begin
s_state = Command;
s_count = 0;
s_command = '0;
s_address = '0;
end else begin
case (s_state)
Command: begin
s_command = {s_command[6:0], data_io[0]};
if (s_count == 7) begin
if (s_command != 8'heb) $fatal(1, "Unsupported NOR command %02x", s_command);
s_state = Address;
s_count = 0;
end else s_count = s_count + 1;
end
Address: begin
s_address = {s_address[19:0], data_io};
if (s_count == 5) begin
s_state = Mode;
s_count = 0;
end else s_count = s_count + 1;
end
Mode: begin
if (s_count == 1) begin
s_state = Dummy;
s_count = 0;
end else s_count = s_count + 1;
end
Dummy: begin
if (s_count == 3) s_state = Data;
else s_count = s_count + 1;
end
Data: begin
end
default: $fatal(1, "Invalid NOR state");
endcase
end
end
always @(negedge sck_i or posedge cs_n_i) begin
if (cs_n_i) begin
s_nibble = 0;
s_output = '0;
end else if (s_state == Data) begin
if ((s_nibble & 1) == 0) s_output = s_memory[s_address+(s_nibble/2)][7:4];
else s_output = s_memory[s_address+(s_nibble/2)][3:0];
s_nibble = s_nibble + 1;
end else begin
s_nibble = 0;
s_output = '0;
end
end
endmodule
+24
View File
@@ -0,0 +1,24 @@
/clusterip/archinfo/rtl/archinfo_reg.sv
/clusterip/archinfo/rtl/apb4_archinfo.sv
/clusterip/pwm/rtl/pwm_pkg.sv
/clusterip/pwm/rtl/pwm_tickgen.sv
/clusterip/pwm/rtl/pwm_timer.sv
/clusterip/pwm/rtl/pwm_channel.sv
/clusterip/pwm/rtl/pwm_deadtime.sv
/clusterip/pwm/rtl/pwm_carrier.sv
/clusterip/pwm/rtl/pwm_capture.sv
/clusterip/pwm/rtl/pwm_core.sv
/clusterip/pwm/rtl/pwm_reg.sv
/clusterip/pwm/rtl/pwm_if.sv
/clusterip/pwm/rtl/apb4_pwm.sv
/clusterip/rtc/rtl/rtc_pkg.sv
/clusterip/rtc/rtl/rtc_if.sv
/clusterip/rtc/rtl/rtc_tickgen.sv
/clusterip/rtc/rtl/rtc_core.sv
/clusterip/rtc/rtl/rtc_reg.sv
/clusterip/rtc/rtl/apb4_rtc.sv
/clusterip/wdg/rtl/wdg_pkg.sv
/clusterip/wdg/rtl/wdg_if.sv
/clusterip/wdg/rtl/wdg_core.sv
/clusterip/wdg/rtl/wdg_reg.sv
/clusterip/wdg/rtl/apb4_wdg.sv
+22
View File
@@ -0,0 +1,22 @@
/clusterip/common/rtl/interface/apb4_if.sv
/clusterip/common/rtl/interface/apb4_pure_if.sv
/clusterip/common/rtl/interface/ahbl_if.sv
/clusterip/common/rtl/interface/axi4_if.sv
/clusterip/common/rtl/interface/axi4_addr_gen.sv
/clusterip/common/rtl/interface/axi4_stream_if.sv
/clusterip/common/rtl/interface/ram_if.sv
/clusterip/common/rtl/utils/register.sv
/clusterip/common/rtl/utils/spill_register.sv
/clusterip/common/rtl/stream/round_robin_arbiter.sv
/clusterip/common/rtl/utils/lfsr.sv
/clusterip/common/rtl/utils/bin2gray.sv
/clusterip/common/rtl/utils/gray2bin.sv
/clusterip/common/rtl/base/ecc_secded.sv
/clusterip/common/rtl/utils/edge_det.sv
/clusterip/common/rtl/cdc/cdc_sync.sv
/clusterip/common/rtl/cdc/cdc_rst_ctrlr.sv
/clusterip/common/rtl/cdc/cdc_2phase.sv
/clusterip/common/rtl/clkrst/rst_sync.sv
/clusterip/common/rtl/clkrst/counter.sv
/ip/util/soc_common_fifo.sv
/ip/util/soc_common_cdc.sv
Loaded 100 of 194 files, more files were not shown because too many files have changed in this diff. Show more