mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
feat: enhance build variant ID generation and regression environment setup
- Added timestamp normalization to function in , allowing for optional timestamp input. - Updated command-line interface to accept a timestamp argument for generating deterministic build variant IDs. - Modified in to include a build timestamp in the environment variables. - Introduced a new test suite in to validate the pin-map generator, including tests for duplicate pads and invalid entries. - Added a test for ensuring the regression runner uses a consistent build timestamp. - Created a new SystemVerilog testbench for the APB4 interface bridge to verify correct signal crossing.
This commit is contained in:
28 files changed
+1075
-747
No files matched your search
@@ -98,7 +98,7 @@ README that states its ownership, source of truth, and validation expectations.
|
||||
## Build and Repository Safety
|
||||
|
||||
- Start from a committed configuration profile. Build products belong below
|
||||
`build/<profile>-<config-hash>/`; caches belong below `.cache/`. Do not
|
||||
`build/<profile>-<YYYY-MM-DD-HH-MM>-<config-hash>/`; caches belong below `.cache/`. Do not
|
||||
commit generated outputs.
|
||||
- Preserve unrelated worktree changes. Do not reset, discard, or reformat files
|
||||
outside the requested scope.
|
||||
|
||||
@@ -51,6 +51,7 @@ LINK_TYPE ?= ld2_sram
|
||||
|
||||
BUILD_ROOT ?= $(ROOT_PATH)/build
|
||||
CACHE_ROOT ?= $(ROOT_PATH)/.cache/retrosoc
|
||||
BUILD_TIMESTAMP ?= $(shell date '+%Y-%m-%d-%H-%M')
|
||||
MAX_JOBS ?= 16
|
||||
HOST_CC ?= cc
|
||||
CLANG_FORMAT ?= clang-format-14
|
||||
@@ -60,12 +61,13 @@ JOBS ?= $(shell count=$$(nproc 2>/dev/null || printf '1'); \
|
||||
CONFIG_KEY_VARS := SOC CORE IP PDK HAVE_PLL HAVE_SRAM_IF HAVE_SRAM_MACRO HAVE_SVA \
|
||||
ISA HAVE_CSR APP LINK_TYPE RTL_TOP FIRMWARE_NAME
|
||||
VARIANT_ID := $(strip $(shell python3 $(ROOT_PATH)/scripts/config_key.py \
|
||||
--lock $(LOCK_FILE) --profile $(PROFILE_NAME) \
|
||||
--lock $(LOCK_FILE) --profile $(PROFILE_NAME) --timestamp $(BUILD_TIMESTAMP) \
|
||||
$(foreach var,$(CONFIG_KEY_VARS),--value $(var)=$($(var)))))
|
||||
ifeq ($(VARIANT_ID),)
|
||||
$(error Failed to calculate build variant ID)
|
||||
endif
|
||||
LOCK_DIGEST := $(strip $(shell python3 $(ROOT_PATH)/scripts/dependency_lock.py --lock $(LOCK_FILE) --digest))
|
||||
export BUILD_TIMESTAMP
|
||||
VARIANT_ROOT := $(abspath $(BUILD_ROOT))/$(VARIANT_ID)
|
||||
SW_BUILD_DIR := $(VARIANT_ROOT)/sw
|
||||
SIM_TOOL_NAME := $(shell printf '%s' '$(SIMU)' | tr '[:upper:]' '[:lower:]')
|
||||
@@ -161,7 +163,8 @@ endif
|
||||
|
||||
.PHONY: help config doctor setup setup-mpw setup-core setup-clusterip setup-ip setup-pdk setup-app \
|
||||
clean-all purge-cache manifest check-warnings metrics check-metrics package \
|
||||
regress-pr regress-nightly sim-asm sw-format sw-format-check sw-policy-check sw-host-test
|
||||
regress-pr regress-nightly sim-asm sw-format sw-format-check sw-policy-check sw-host-test \
|
||||
pin-map check-pin-map
|
||||
.NOTPARALLEL: setup
|
||||
|
||||
help:
|
||||
@@ -178,6 +181,8 @@ help:
|
||||
' config | manifest print/write the effective configuration' \
|
||||
' memory-map generate the selected address-map artifacts' \
|
||||
' check-memory-map validate the canonical address map' \
|
||||
' pin-map generate the selected pin-map artifacts' \
|
||||
' check-pin-map validate the canonical SoC pin map' \
|
||||
' check-warnings | metrics analyze flow logs and reports' \
|
||||
' check-metrics apply the committed metrics policy' \
|
||||
' sw-format apply clang-format to self-owned embedded C code' \
|
||||
@@ -194,7 +199,7 @@ help:
|
||||
config:
|
||||
@printf '%-18s %s\n' \
|
||||
ROOT_PATH '$(ROOT_PATH)' CONFIG '$(or $(CONFIG_PATH),<defaults>)' \
|
||||
VARIANT_ID '$(VARIANT_ID)' VARIANT_ROOT '$(VARIANT_ROOT)' \
|
||||
BUILD_TIMESTAMP '$(BUILD_TIMESTAMP)' VARIANT_ID '$(VARIANT_ID)' VARIANT_ROOT '$(VARIANT_ROOT)' \
|
||||
JOBS '$(JOBS)' \
|
||||
SOC '$(SOC)' CORE '$(CORE)' IP '$(IP)' \
|
||||
SIMU '$(SIMU)' SYNTH '$(SYNTH)' STA '$(STA)' PDK '$(PDK)' \
|
||||
|
||||
@@ -116,12 +116,21 @@ make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk SIMU=IVERILOG \
|
||||
| Nightly regression suite | `make regress-nightly` |
|
||||
| Script and policy checks | `make sw-format-check sw-policy-check sw-host-test` |
|
||||
|
||||
Build outputs are isolated below `build/<profile>-<config-hash>/`. Each variant keeps its
|
||||
Build outputs are isolated below `build/<profile>-<YYYY-MM-DD-HH-MM>-<config-hash>/`. Each variant keeps its
|
||||
firmware, generated sources, simulator output, synthesis and timing reports, manifest, warning
|
||||
analysis, and metrics separate from other configurations. Use `make clean` to remove the
|
||||
selected backend, `make clean-all` to remove all build output, and `make purge-cache` to remove
|
||||
download and compiler caches.
|
||||
|
||||
`BUILD_TIMESTAMP` defaults to the local build-start time. Set it explicitly when separate Make
|
||||
commands must reuse one variant:
|
||||
|
||||
```sh
|
||||
export BUILD_TIMESTAMP=2026-07-21-10-39
|
||||
make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk firmware
|
||||
make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk SIMU=IVERILOG sim
|
||||
```
|
||||
|
||||
## Reproducibility And CI
|
||||
|
||||
[`config/dependencies.lock.json`](config/dependencies.lock.json) is the source of truth for
|
||||
|
||||
@@ -9,6 +9,8 @@ the root README and subsystem guides.
|
||||
baseline, scope, partial automation, and deviation process.
|
||||
- [pll-clock-control.md](pll-clock-control.md) describes the SYSCTRL PLL
|
||||
register protocol and software quiesce contract.
|
||||
- [soc-integration-wiring.md](soc-integration-wiring.md) defines the generated
|
||||
pin-map workflow and SoC integration boundary.
|
||||
|
||||
Keep policy descriptions here concise and link to executable configuration as
|
||||
the source of truth. Changes that alter process requirements must also update
|
||||
|
||||
+7
-3
@@ -60,13 +60,17 @@ affected implementation change.
|
||||
|
||||
## Build Layout
|
||||
|
||||
The variant identifier is the profile name plus a hash over effective hardware/software build
|
||||
settings and the dependency lock. Runtime-only settings such as wave capture and timeout do not
|
||||
create a new variant.
|
||||
The variant identifier is the profile name, the local creation timestamp, and a hash over effective
|
||||
hardware/software build settings and the dependency lock. The timestamp has the
|
||||
`YYYY-MM-DD-HH-MM` format and does not alter the hash. Runtime-only settings such as wave capture
|
||||
and timeout do not alter the hash either. `BUILD_TIMESTAMP` defaults to the current local minute;
|
||||
set it explicitly when separate Make commands must share one variant. The regression runner exports
|
||||
one timestamp to all of its child Make commands.
|
||||
|
||||
```text
|
||||
build/<variant>/
|
||||
generated/mpw/<simulator>/
|
||||
generated/pin_map/
|
||||
sw/
|
||||
sim/<simulator>/
|
||||
syn/yosys/
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# SoC Integration Wiring
|
||||
|
||||
`rtl/mini/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. It does not
|
||||
contain board package locations; FPGA package constraints remain in the board
|
||||
`.xdc` file.
|
||||
|
||||
The generator emits temporary SystemVerilog include files below
|
||||
`build/<variant>/generated/pin_map/`. The ASIC top includes the generated port
|
||||
and pad bindings, while each platform wrapper includes its own generated
|
||||
named-port binding. Do not edit generated files.
|
||||
|
||||
Use the following commands after editing the map:
|
||||
|
||||
```sh
|
||||
make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk check-pin-map
|
||||
make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk pin-map
|
||||
```
|
||||
|
||||
When adding a pad, define its whitelisted pad template, direction, conditional
|
||||
feature, and every profile binding in the JSON map. Use `null` for an open
|
||||
binding. The generator rejects duplicate pad names, unknown profile bindings,
|
||||
unsupported features, and unapproved connection syntax.
|
||||
|
||||
SoC wrappers use the existing clusterIP interfaces for protocol boundaries.
|
||||
`apb4_if_bridge` only adapts `apb4_pure_if` to `apb4_if`, and `gpio_pad_bridge`
|
||||
only exposes the pad-side subset of `gpio_if`; neither module contains state.
|
||||
@@ -4,6 +4,13 @@ This directory contains FPGA-facing top-level integration for the Mini SoC.
|
||||
`mini/retrosoc_top.sv` is the FPGA top wrapper and
|
||||
`mini/starrysky_v2.xdc` contains board timing and pin constraints.
|
||||
|
||||
The wrapper consumes the generated `retrosoc_asic_fpga_mini_bindings.svh`
|
||||
include. Before invoking an FPGA tool, generate the selected profile with
|
||||
`make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk pin-map` and add
|
||||
`build/<variant>/generated/pin_map/rtl` to the tool include path. Logical pad
|
||||
names and wrapper bindings are owned by `rtl/mini/pin_map/pin_map.json`;
|
||||
package locations remain in the board `.xdc` file.
|
||||
|
||||
FPGA constraints are board-specific implementation inputs, not generic ASIC
|
||||
RTL. Validate changes with the relevant FPGA tool flow and hardware target; do
|
||||
not reuse them as ASIC timing constraints. Follow the RTL and hardware-facing
|
||||
|
||||
+2
-116
@@ -3,7 +3,6 @@
|
||||
module retrosoc_top (
|
||||
input clk_i,
|
||||
inout rst_n_i,
|
||||
// gpio
|
||||
inout ps2_clk_i,
|
||||
inout ps2_dat_i,
|
||||
output onewire_dat_o,
|
||||
@@ -75,7 +74,6 @@ module retrosoc_top (
|
||||
inout sdram_dq15_io
|
||||
);
|
||||
|
||||
|
||||
wire s_sys_clk;
|
||||
wire s_aud_clk;
|
||||
clk_wiz_0 u_clk_wiz_0 (
|
||||
@@ -85,119 +83,7 @@ module retrosoc_top (
|
||||
);
|
||||
|
||||
retrosoc_asic u_retrosoc (
|
||||
.extclk_i_pad (s_sys_clk),
|
||||
.audclk_i_pad (s_aud_clk),
|
||||
.ext_rst_n_i_pad (rst_n_i),
|
||||
`ifdef HAVE_PLL
|
||||
.xi_i_pad (s_sys_clk),
|
||||
.xo_o_pad (),
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_0_i_pad (1'b0),
|
||||
.core_sel_1_i_pad (1'b0),
|
||||
.core_sel_2_i_pad (1'b0),
|
||||
.core_sel_3_i_pad (1'b0),
|
||||
.core_sel_4_i_pad (1'b0),
|
||||
`endif
|
||||
`ifdef IP_MDD
|
||||
.user_gpio_0_io_pad (),
|
||||
.user_gpio_1_io_pad (),
|
||||
.user_gpio_2_io_pad (),
|
||||
.user_gpio_3_io_pad (),
|
||||
.user_gpio_4_io_pad (),
|
||||
.user_gpio_5_io_pad (),
|
||||
.user_gpio_6_io_pad (),
|
||||
.user_gpio_7_io_pad (),
|
||||
.user_gpio_8_io_pad (),
|
||||
.user_gpio_9_io_pad (),
|
||||
.user_gpio_10_io_pad(),
|
||||
.user_gpio_11_io_pad(),
|
||||
.user_gpio_12_io_pad(),
|
||||
.user_gpio_13_io_pad(),
|
||||
.user_gpio_14_io_pad(),
|
||||
.user_gpio_15_io_pad(),
|
||||
`endif
|
||||
.gpio_0_io_pad (ps2_clk_i),
|
||||
.gpio_1_io_pad (ps2_dat_i),
|
||||
.gpio_2_io_pad (onewire_dat_o),
|
||||
.gpio_3_io_pad (i2c_scl_io),
|
||||
.gpio_4_io_pad (i2c_sda_io),
|
||||
.gpio_5_io_pad (pwm_2_o),
|
||||
.gpio_6_io_pad (spisd_sck_o),
|
||||
.gpio_7_io_pad (spisd_nss_o),
|
||||
.gpio_8_io_pad (spisd_mosi_o),
|
||||
.gpio_9_io_pad (spisd_miso_i),
|
||||
.gpio_10_io_pad (i2s_mclk_o),
|
||||
.gpio_11_io_pad (i2s_sclk_o),
|
||||
.gpio_12_io_pad (i2s_lrck_o),
|
||||
.gpio_13_io_pad (i2s_dacdat_o),
|
||||
.gpio_14_io_pad (i2s_adcdat_i),
|
||||
.gpio_15_io_pad (),
|
||||
.gpio_16_io_pad (),
|
||||
.gpio_17_io_pad (),
|
||||
.gpio_18_io_pad (),
|
||||
.gpio_19_io_pad (),
|
||||
.gpio_20_io_pad (),
|
||||
.gpio_21_io_pad (psram_sck_o),
|
||||
.gpio_22_io_pad (psram_nss0_o),
|
||||
.gpio_23_io_pad (psram_dat0_io),
|
||||
.gpio_24_io_pad (psram_dat1_io),
|
||||
.gpio_25_io_pad (psram_dat2_io),
|
||||
.gpio_26_io_pad (psram_dat3_io),
|
||||
.gpio_27_io_pad (),
|
||||
.gpio_28_io_pad (),
|
||||
.gpio_29_io_pad (),
|
||||
.gpio_30_io_pad (gpio_io30),
|
||||
.gpio_31_io_pad (),
|
||||
.uart0_tx_o_pad (uart0_tx_o),
|
||||
.uart0_rx_i_pad (uart0_rx_i),
|
||||
.xpi_sck_o_pad (xpi_sck_o),
|
||||
.xpi_nss0_o_pad (xpi_nss0_o),
|
||||
.xpi_nss1_o_pad (),
|
||||
.xpi_nss2_o_pad (),
|
||||
.xpi_nss3_o_pad (),
|
||||
.xpi_dat0_io_pad (xpi_dat0_io),
|
||||
.xpi_dat1_io_pad (xpi_dat1_io),
|
||||
.xpi_dat2_io_pad (xpi_dat2_io),
|
||||
.xpi_dat3_io_pad (xpi_dat3_io),
|
||||
.sdram_clk_o_pad (sdram_clk_o),
|
||||
.sdram_cke_o_pad (sdram_cke_o),
|
||||
.sdram_cs_n_o_pad (sdram_cs_n_o),
|
||||
.sdram_ras_n_o_pad (sdram_ras_n_o),
|
||||
.sdram_cas_n_o_pad (sdram_cas_n_o),
|
||||
.sdram_we_n_o_pad (sdram_we_n_o),
|
||||
.sdram_ba0_o_pad (sdram_ba0_o),
|
||||
.sdram_ba1_o_pad (sdram_ba1_o),
|
||||
.sdram_addr0_o_pad (sdram_addr0_o),
|
||||
.sdram_addr1_o_pad (sdram_addr1_o),
|
||||
.sdram_addr2_o_pad (sdram_addr2_o),
|
||||
.sdram_addr3_o_pad (sdram_addr3_o),
|
||||
.sdram_addr4_o_pad (sdram_addr4_o),
|
||||
.sdram_addr5_o_pad (sdram_addr5_o),
|
||||
.sdram_addr6_o_pad (sdram_addr6_o),
|
||||
.sdram_addr7_o_pad (sdram_addr7_o),
|
||||
.sdram_addr8_o_pad (sdram_addr8_o),
|
||||
.sdram_addr9_o_pad (sdram_addr9_o),
|
||||
.sdram_addr10_o_pad (sdram_addr10_o),
|
||||
.sdram_addr11_o_pad (sdram_addr11_o),
|
||||
.sdram_addr12_o_pad (sdram_addr12_o),
|
||||
.sdram_dqm0_o_pad (sdram_dqm0_o),
|
||||
.sdram_dqm1_o_pad (sdram_dqm1_o),
|
||||
.sdram_dq0_io_pad (sdram_dq0_io),
|
||||
.sdram_dq1_io_pad (sdram_dq1_io),
|
||||
.sdram_dq2_io_pad (sdram_dq2_io),
|
||||
.sdram_dq3_io_pad (sdram_dq3_io),
|
||||
.sdram_dq4_io_pad (sdram_dq4_io),
|
||||
.sdram_dq5_io_pad (sdram_dq5_io),
|
||||
.sdram_dq6_io_pad (sdram_dq6_io),
|
||||
.sdram_dq7_io_pad (sdram_dq7_io),
|
||||
.sdram_dq8_io_pad (sdram_dq8_io),
|
||||
.sdram_dq9_io_pad (sdram_dq9_io),
|
||||
.sdram_dq10_io_pad (sdram_dq10_io),
|
||||
.sdram_dq11_io_pad (sdram_dq11_io),
|
||||
.sdram_dq12_io_pad (sdram_dq12_io),
|
||||
.sdram_dq13_io_pad (sdram_dq13_io),
|
||||
.sdram_dq14_io_pad (sdram_dq14_io),
|
||||
.sdram_dq15_io_pad (sdram_dq15_io)
|
||||
`include "retrosoc_asic_fpga_mini_bindings.svh"
|
||||
);
|
||||
|
||||
endmodule
|
||||
@@ -57,6 +57,10 @@ interface gpio_if ();
|
||||
input alt1_oe_i,
|
||||
output irq_o
|
||||
);
|
||||
|
||||
modport pad(input oe_o, input cs_o, input pu_o, input pd_o, input do_o, output di_i);
|
||||
|
||||
modport soc_pad(output oe_o, output cs_o, output pu_o, output pd_o, output do_o, input di_i);
|
||||
endinterface
|
||||
|
||||
module nmi_gpio (
|
||||
|
||||
+17
-3
@@ -7,6 +7,11 @@ MEMORY_MAP_RTL_DIR := $(MEMORY_MAP_DIR)/rtl
|
||||
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_DIR := $(VARIANT_ROOT)/generated/pin_map
|
||||
PIN_MAP_STAMP := $(PIN_MAP_DIR)/.stamp
|
||||
PIN_MAP_FILELIST := $(PIN_MAP_DIR)/pin_map.fl
|
||||
MPW_STAMP := $(CACHE_ROOT)/stamps/mpw-$(LOCK_DIGEST).prepared
|
||||
MPW_OUTPUT_DIR := $(VARIANT_ROOT)/generated/mpw/$(SIM_TOOL_NAME)
|
||||
MPW_VARIANT_STAMP := $(MPW_OUTPUT_DIR)/.stamp
|
||||
@@ -43,8 +48,17 @@ memory-map: $(MEMORY_MAP_STAMP)
|
||||
check-memory-map:
|
||||
python3 $(MEMORY_MAP_SCRIPT) --map $(MEMORY_MAP_SOURCE) --check
|
||||
|
||||
$(PIN_MAP_STAMP): $(PIN_MAP_SOURCE) $(PIN_MAP_SCRIPT)
|
||||
python3 $(PIN_MAP_SCRIPT) --map $(PIN_MAP_SOURCE) --output-dir $(PIN_MAP_DIR)
|
||||
@touch $@
|
||||
|
||||
pin-map: $(PIN_MAP_STAMP)
|
||||
|
||||
check-pin-map:
|
||||
python3 $(PIN_MAP_SCRIPT) --map $(PIN_MAP_SOURCE) --check
|
||||
|
||||
$(FILELIST_STAMP): $(FILELIST_TEMPLATES) $(RTL_PATH)/script/generate_filelist.py \
|
||||
$(RTL_PATH)/script/filelist.py $(MEMORY_MAP_STAMP)
|
||||
$(RTL_PATH)/script/filelist.py $(MEMORY_MAP_STAMP) $(PIN_MAP_STAMP)
|
||||
python3 $(RTL_PATH)/script/generate_filelist.py \
|
||||
--output-dir $(GENERATED_FL_DIR) \
|
||||
$(foreach define,$(DEF_LIST),--define $(define))
|
||||
@@ -71,7 +85,7 @@ NET_FLIST += -f $(GENERATED_FL_DIR)/sys_def.fl
|
||||
NET_FLIST += -f $(GENERATED_FL_DIR)/commonip.fl
|
||||
NET_FLIST += -f $(GENERATED_FL_DIR)/inc.fl
|
||||
|
||||
RTL_FLIST := -f $(MEMORY_MAP_FILELIST) $(NET_FLIST)
|
||||
RTL_FLIST := -f $(MEMORY_MAP_FILELIST) -f $(PIN_MAP_FILELIST) $(NET_FLIST)
|
||||
RTL_FLIST += -f $(GENERATED_FL_DIR)/clusterip.fl
|
||||
RTL_FLIST += -f $(GENERATED_FL_DIR)/ip.fl
|
||||
RTL_FLIST += -f $(GENERATED_FL_DIR)/tech.fl
|
||||
@@ -99,4 +113,4 @@ else ifeq ($(SIMU), IVERILOG)
|
||||
include $(RTL_PATH)/mk/iverilog.mk
|
||||
endif
|
||||
|
||||
.PHONY: gen_mpw_code generate_filelist memory-map check-memory-map firmware
|
||||
.PHONY: gen_mpw_code generate_filelist memory-map check-memory-map pin-map check-pin-map firmware
|
||||
@@ -91,120 +91,7 @@ module retrosoc_tb;
|
||||
assign s_user_gpio_0_io = r_user_gpio_0_io;
|
||||
|
||||
retrosoc_asic u_retrosoc_asic (
|
||||
.extclk_i_pad (s_ext_clk),
|
||||
.audclk_i_pad (s_aud_clk),
|
||||
.ext_rst_n_i_pad (s_rst_n),
|
||||
`ifdef HAVE_PLL
|
||||
.xi_i_pad (r_xtal_clk),
|
||||
.xo_o_pad (),
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_0_i_pad (s_core_sel[0]),
|
||||
.core_sel_1_i_pad (s_core_sel[1]),
|
||||
.core_sel_2_i_pad (s_core_sel[2]),
|
||||
.core_sel_3_i_pad (s_core_sel[3]),
|
||||
.core_sel_4_i_pad (s_core_sel[4]),
|
||||
`endif
|
||||
`ifdef IP_MDD
|
||||
.user_gpio_0_io_pad (s_user_gpio_0_io),
|
||||
.user_gpio_1_io_pad (),
|
||||
.user_gpio_2_io_pad (),
|
||||
.user_gpio_3_io_pad (),
|
||||
.user_gpio_4_io_pad (),
|
||||
.user_gpio_5_io_pad (),
|
||||
.user_gpio_6_io_pad (),
|
||||
.user_gpio_7_io_pad (),
|
||||
.user_gpio_8_io_pad (),
|
||||
.user_gpio_9_io_pad (),
|
||||
.user_gpio_10_io_pad(),
|
||||
.user_gpio_11_io_pad(),
|
||||
.user_gpio_12_io_pad(),
|
||||
.user_gpio_13_io_pad(),
|
||||
.user_gpio_14_io_pad(),
|
||||
.user_gpio_15_io_pad(),
|
||||
`endif
|
||||
.gpio_0_io_pad (s_gpio_0_io),
|
||||
.gpio_1_io_pad (s_gpio_1_io),
|
||||
.gpio_2_io_pad (),
|
||||
.gpio_3_io_pad (),
|
||||
.gpio_4_io_pad (),
|
||||
.gpio_5_io_pad (),
|
||||
.gpio_6_io_pad (),
|
||||
.gpio_7_io_pad (s_i2c0_scl_io),
|
||||
.gpio_8_io_pad (s_i2c0_sda_io),
|
||||
.gpio_9_io_pad (),
|
||||
.gpio_10_io_pad (),
|
||||
.gpio_11_io_pad (),
|
||||
.gpio_12_io_pad (),
|
||||
.gpio_13_io_pad (),
|
||||
.gpio_14_io_pad (),
|
||||
.gpio_15_io_pad (),
|
||||
.gpio_16_io_pad (),
|
||||
.gpio_17_io_pad (),
|
||||
.gpio_18_io_pad (),
|
||||
.gpio_19_io_pad (),
|
||||
.gpio_20_io_pad (),
|
||||
.gpio_21_io_pad (s_psram_sck),
|
||||
.gpio_22_io_pad (s_psram_nss0),
|
||||
.gpio_23_io_pad (s_psram_dat0),
|
||||
.gpio_24_io_pad (s_psram_dat1),
|
||||
.gpio_25_io_pad (s_psram_dat2),
|
||||
.gpio_26_io_pad (s_psram_dat3),
|
||||
.gpio_27_io_pad (s_psram_nss1),
|
||||
.gpio_28_io_pad (),
|
||||
.gpio_29_io_pad (),
|
||||
.gpio_30_io_pad (),
|
||||
.gpio_31_io_pad (),
|
||||
.uart0_tx_o_pad (s_uart0_tx),
|
||||
.uart0_rx_i_pad (s_uart0_rx),
|
||||
.xpi_sck_o_pad (s_xpi_sck_o),
|
||||
.xpi_nss0_o_pad (s_xpi_nss0_o), // xpi flash
|
||||
.xpi_nss1_o_pad (s_xpi_nss1_o), // qpi flash
|
||||
.xpi_nss2_o_pad (s_xpi_nss2_o),
|
||||
.xpi_nss3_o_pad (), // tft test
|
||||
.xpi_dat0_io_pad (s_xpi_dat0_io),
|
||||
.xpi_dat1_io_pad (s_xpi_dat1_io),
|
||||
.xpi_dat2_io_pad (s_xpi_dat2_io),
|
||||
.xpi_dat3_io_pad (s_xpi_dat3_io),
|
||||
.sdram_clk_o_pad (s_sdram_clk),
|
||||
.sdram_cke_o_pad (s_sdram_cke),
|
||||
.sdram_cs_n_o_pad (s_sdram_cs_n),
|
||||
.sdram_ras_n_o_pad (s_sdram_ras_n),
|
||||
.sdram_cas_n_o_pad (s_sdram_cas_n),
|
||||
.sdram_we_n_o_pad (s_sdram_we_n),
|
||||
.sdram_ba0_o_pad (s_sdram_ba[0]),
|
||||
.sdram_ba1_o_pad (s_sdram_ba[1]),
|
||||
.sdram_addr0_o_pad (s_sdram_addr[0]),
|
||||
.sdram_addr1_o_pad (s_sdram_addr[1]),
|
||||
.sdram_addr2_o_pad (s_sdram_addr[2]),
|
||||
.sdram_addr3_o_pad (s_sdram_addr[3]),
|
||||
.sdram_addr4_o_pad (s_sdram_addr[4]),
|
||||
.sdram_addr5_o_pad (s_sdram_addr[5]),
|
||||
.sdram_addr6_o_pad (s_sdram_addr[6]),
|
||||
.sdram_addr7_o_pad (s_sdram_addr[7]),
|
||||
.sdram_addr8_o_pad (s_sdram_addr[8]),
|
||||
.sdram_addr9_o_pad (s_sdram_addr[9]),
|
||||
.sdram_addr10_o_pad (s_sdram_addr[10]),
|
||||
.sdram_addr11_o_pad (s_sdram_addr[11]),
|
||||
.sdram_addr12_o_pad (s_sdram_addr[12]),
|
||||
.sdram_dqm0_o_pad (s_sdram_dqm[0]),
|
||||
.sdram_dqm1_o_pad (s_sdram_dqm[1]),
|
||||
.sdram_dq0_io_pad (s_sdram_dq[0]),
|
||||
.sdram_dq1_io_pad (s_sdram_dq[1]),
|
||||
.sdram_dq2_io_pad (s_sdram_dq[2]),
|
||||
.sdram_dq3_io_pad (s_sdram_dq[3]),
|
||||
.sdram_dq4_io_pad (s_sdram_dq[4]),
|
||||
.sdram_dq5_io_pad (s_sdram_dq[5]),
|
||||
.sdram_dq6_io_pad (s_sdram_dq[6]),
|
||||
.sdram_dq7_io_pad (s_sdram_dq[7]),
|
||||
.sdram_dq8_io_pad (s_sdram_dq[8]),
|
||||
.sdram_dq9_io_pad (s_sdram_dq[9]),
|
||||
.sdram_dq10_io_pad (s_sdram_dq[10]),
|
||||
.sdram_dq11_io_pad (s_sdram_dq[11]),
|
||||
.sdram_dq12_io_pad (s_sdram_dq[12]),
|
||||
.sdram_dq13_io_pad (s_sdram_dq[13]),
|
||||
.sdram_dq14_io_pad (s_sdram_dq[14]),
|
||||
.sdram_dq15_io_pad (s_sdram_dq[15])
|
||||
`include "retrosoc_asic_tb_bindings.svh"
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -45,121 +45,9 @@ module retrosoc_top (
|
||||
assign s_clk = ext_clk_i;
|
||||
assign s_rst_n = rst_n_i;
|
||||
assign s_core_sel = core_sel_i;
|
||||
|
||||
retrosoc_asic u_retrosoc_asic (
|
||||
.extclk_i_pad (s_clk),
|
||||
.audclk_i_pad (),
|
||||
.ext_rst_n_i_pad (s_rst_n),
|
||||
`ifdef HAVE_PLL
|
||||
.xi_i_pad (),
|
||||
.xo_o_pad (),
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
.core_sel_0_i_pad (s_core_sel[0]),
|
||||
.core_sel_1_i_pad (s_core_sel[1]),
|
||||
.core_sel_2_i_pad (s_core_sel[2]),
|
||||
.core_sel_3_i_pad (s_core_sel[3]),
|
||||
.core_sel_4_i_pad (s_core_sel[4]),
|
||||
`endif
|
||||
`ifdef IP_MDD
|
||||
.user_gpio_0_io_pad (),
|
||||
.user_gpio_1_io_pad (),
|
||||
.user_gpio_2_io_pad (),
|
||||
.user_gpio_3_io_pad (),
|
||||
.user_gpio_4_io_pad (),
|
||||
.user_gpio_5_io_pad (),
|
||||
.user_gpio_6_io_pad (),
|
||||
.user_gpio_7_io_pad (),
|
||||
.user_gpio_8_io_pad (),
|
||||
.user_gpio_9_io_pad (),
|
||||
.user_gpio_10_io_pad(),
|
||||
.user_gpio_11_io_pad(),
|
||||
.user_gpio_12_io_pad(),
|
||||
.user_gpio_13_io_pad(),
|
||||
.user_gpio_14_io_pad(),
|
||||
.user_gpio_15_io_pad(),
|
||||
`endif
|
||||
.gpio_0_io_pad (),
|
||||
.gpio_1_io_pad (),
|
||||
.gpio_2_io_pad (),
|
||||
.gpio_3_io_pad (),
|
||||
.gpio_4_io_pad (),
|
||||
.gpio_5_io_pad (),
|
||||
.gpio_6_io_pad (),
|
||||
.gpio_7_io_pad (),
|
||||
.gpio_8_io_pad (),
|
||||
.gpio_9_io_pad (),
|
||||
.gpio_10_io_pad (),
|
||||
.gpio_11_io_pad (),
|
||||
.gpio_12_io_pad (),
|
||||
.gpio_13_io_pad (),
|
||||
.gpio_14_io_pad (),
|
||||
.gpio_15_io_pad (),
|
||||
.gpio_16_io_pad (),
|
||||
.gpio_17_io_pad (),
|
||||
.gpio_18_io_pad (),
|
||||
.gpio_19_io_pad (),
|
||||
.gpio_20_io_pad (),
|
||||
.gpio_21_io_pad (s_psram_sck),
|
||||
.gpio_22_io_pad (s_psram_nss0),
|
||||
.gpio_23_io_pad (s_psram_dat0),
|
||||
.gpio_24_io_pad (s_psram_dat1),
|
||||
.gpio_25_io_pad (s_psram_dat2),
|
||||
.gpio_26_io_pad (s_psram_dat3),
|
||||
.gpio_27_io_pad (),
|
||||
.gpio_28_io_pad (),
|
||||
.gpio_29_io_pad (),
|
||||
.gpio_30_io_pad (),
|
||||
.gpio_31_io_pad (),
|
||||
.uart0_tx_o_pad (),
|
||||
.uart0_rx_i_pad (),
|
||||
.xpi_sck_o_pad (s_xpi_sck_o),
|
||||
.xpi_nss0_o_pad (s_xpi_nss0_o),
|
||||
.xpi_nss1_o_pad (),
|
||||
.xpi_nss2_o_pad (),
|
||||
.xpi_nss3_o_pad (),
|
||||
.xpi_dat0_io_pad (s_xpi_dat0_io),
|
||||
.xpi_dat1_io_pad (s_xpi_dat1_io),
|
||||
.xpi_dat2_io_pad (s_xpi_dat2_io),
|
||||
.xpi_dat3_io_pad (s_xpi_dat3_io),
|
||||
.sdram_clk_o_pad (),
|
||||
.sdram_cke_o_pad (),
|
||||
.sdram_cs_n_o_pad (),
|
||||
.sdram_ras_n_o_pad (),
|
||||
.sdram_cas_n_o_pad (),
|
||||
.sdram_we_n_o_pad (),
|
||||
.sdram_ba0_o_pad (),
|
||||
.sdram_ba1_o_pad (),
|
||||
.sdram_addr0_o_pad (),
|
||||
.sdram_addr1_o_pad (),
|
||||
.sdram_addr2_o_pad (),
|
||||
.sdram_addr3_o_pad (),
|
||||
.sdram_addr4_o_pad (),
|
||||
.sdram_addr5_o_pad (),
|
||||
.sdram_addr6_o_pad (),
|
||||
.sdram_addr7_o_pad (),
|
||||
.sdram_addr8_o_pad (),
|
||||
.sdram_addr9_o_pad (),
|
||||
.sdram_addr10_o_pad (),
|
||||
.sdram_addr11_o_pad (),
|
||||
.sdram_addr12_o_pad (),
|
||||
.sdram_dqm0_o_pad (),
|
||||
.sdram_dqm1_o_pad (),
|
||||
.sdram_dq0_io_pad (),
|
||||
.sdram_dq1_io_pad (),
|
||||
.sdram_dq2_io_pad (),
|
||||
.sdram_dq3_io_pad (),
|
||||
.sdram_dq4_io_pad (),
|
||||
.sdram_dq5_io_pad (),
|
||||
.sdram_dq6_io_pad (),
|
||||
.sdram_dq7_io_pad (),
|
||||
.sdram_dq8_io_pad (),
|
||||
.sdram_dq9_io_pad (),
|
||||
.sdram_dq10_io_pad (),
|
||||
.sdram_dq11_io_pad (),
|
||||
.sdram_dq12_io_pad (),
|
||||
.sdram_dq13_io_pad (),
|
||||
.sdram_dq14_io_pad (),
|
||||
.sdram_dq15_io_pad ()
|
||||
`include "retrosoc_asic_verilator_bindings.svh"
|
||||
);
|
||||
|
||||
QSPIFlash u_QSPIFlash (
|
||||
@@ -177,5 +65,4 @@ module retrosoc_top (
|
||||
.sio ({s_psram_dat3, s_psram_dat2, s_psram_dat1, s_psram_dat0})
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
@@ -1,3 +1,5 @@
|
||||
/top/apb4_if_bridge.sv
|
||||
/top/gpio_pad_bridge.sv
|
||||
/top/core_wrapper.sv
|
||||
/top/retrosoc.sv
|
||||
/top/retrosoc_asic.sv
|
||||
|
||||
@@ -40,19 +40,19 @@ $(IVERILOG_BEHV_FLIST): $(FILELIST_STAMP) $(CONVERTED_SOC)
|
||||
@mkdir -p $(@D)
|
||||
python3 $(RTL_PATH)/script/gen_iverilog_filelist.py \
|
||||
--mode behv --pdk $(PDK) --generated-dir $(GENERATED_FL_DIR) \
|
||||
--output $@ --converted $(CONVERTED_SOC)
|
||||
--pin-map-rtl-dir $(PIN_MAP_DIR)/rtl --output $@ --converted $(CONVERTED_SOC)
|
||||
|
||||
$(IVERILOG_NETL_FLIST): $(FILELIST_STAMP) $(NETLIST_PATH)
|
||||
@mkdir -p $(@D)
|
||||
python3 $(RTL_PATH)/script/gen_iverilog_filelist.py \
|
||||
--mode netl --pdk $(PDK) --generated-dir $(GENERATED_FL_DIR) \
|
||||
--output $@ --netlist $(NETLIST_PATH)
|
||||
--pin-map-rtl-dir $(PIN_MAP_DIR)/rtl --output $@ --netlist $(NETLIST_PATH)
|
||||
|
||||
$(IVERILOG_POST_FLIST): $(FILELIST_STAMP) $(POST_PATH) $(SDF_PATH)
|
||||
@mkdir -p $(@D)
|
||||
python3 $(RTL_PATH)/script/gen_iverilog_filelist.py \
|
||||
--mode post --pdk $(PDK) --generated-dir $(GENERATED_FL_DIR) \
|
||||
--output $@ --netlist $(POST_PATH) --sdf $(SDF_PATH) \
|
||||
--pin-map-rtl-dir $(PIN_MAP_DIR)/rtl --output $@ --netlist $(POST_PATH) --sdf $(SDF_PATH) \
|
||||
--sdf-scope $(SDF_SCOPE)
|
||||
|
||||
convt_sv2v: $(CONVERTED_SOC)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# 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
|
||||
temporary SystemVerilog include files below the selected build variant; do not
|
||||
edit generated files.
|
||||
|
||||
The map intentionally does not contain FPGA package locations. Board-level
|
||||
locations remain owned by the FPGA constraint file. Validate changes with
|
||||
`make check-pin-map` and the pin-map tests before running a regression.
|
||||
@@ -0,0 +1,290 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate SoC pad declarations and platform bindings from one JSON map."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
VALID_FEATURES = {"HAVE_PLL", "CORE_MDD", "IP_MDD"}
|
||||
VALID_KINDS = {
|
||||
"full",
|
||||
"schmitt_input",
|
||||
"sdram_dq",
|
||||
"tri_input",
|
||||
"tri_output",
|
||||
"xpi_data",
|
||||
"xtal",
|
||||
}
|
||||
REQUIRED_PROFILES = {"fpga_mini", "tb", "verilator"}
|
||||
CONNECTION_RE = re.compile(r"(?:[A-Za-z_][A-Za-z0-9_]*)(?:\[[0-9]+\])?$")
|
||||
CONSTANT_RE = re.compile(r"[0-9]+'[bBdDhHoO][0-9a-fA-F_xXzZ]+$")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Pad:
|
||||
name: str
|
||||
direction: str
|
||||
feature: str | None
|
||||
kind: str
|
||||
index: int | None
|
||||
signal: str | None
|
||||
interface: str | None
|
||||
peer: str | None
|
||||
bind: bool
|
||||
|
||||
|
||||
def atomic_write(path: Path, content: str) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if path.exists() and path.read_text(encoding="utf-8") == content:
|
||||
return
|
||||
descriptor, temporary_name = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent)
|
||||
try:
|
||||
with os.fdopen(descriptor, "w", encoding="utf-8", newline="\n") as output:
|
||||
output.write(content)
|
||||
os.replace(temporary_name, path)
|
||||
except BaseException:
|
||||
Path(temporary_name).unlink(missing_ok=True)
|
||||
raise
|
||||
|
||||
|
||||
def require_string(value: Any, field: str) -> str:
|
||||
if not isinstance(value, str) or not value:
|
||||
raise ValueError(f"{field} must be a non-empty string")
|
||||
return value
|
||||
|
||||
|
||||
def parse_feature(value: Any, field: str) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
feature = require_string(value, field)
|
||||
if feature not in VALID_FEATURES:
|
||||
raise ValueError(f"{field} must be one of {sorted(VALID_FEATURES)}")
|
||||
return feature
|
||||
|
||||
|
||||
def format_template(value: str | None, index: int | None, field: str) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(f"{field} must be a string")
|
||||
if "{index}" in value:
|
||||
if index is None:
|
||||
raise ValueError(f"{field} uses {{index}} without an indexed pad")
|
||||
return value.format(index=index)
|
||||
return value
|
||||
|
||||
|
||||
def parse_pad(entry: dict[str, Any], defaults: dict[str, Any], index: int | None) -> Pad:
|
||||
data = {**defaults, **entry}
|
||||
name = require_string(format_template(data.get("name"), index, "pad.name"), "pad.name")
|
||||
direction = require_string(data.get("direction"), f"{name}.direction")
|
||||
if direction not in {"input", "output", "inout"}:
|
||||
raise ValueError(f"{name}.direction must be input, output, or inout")
|
||||
kind = require_string(data.get("kind"), f"{name}.kind")
|
||||
if kind not in VALID_KINDS:
|
||||
raise ValueError(f"{name}.kind is not supported")
|
||||
feature = parse_feature(data.get("feature"), f"{name}.feature")
|
||||
signal = format_template(data.get("signal"), index, f"{name}.signal")
|
||||
interface = format_template(data.get("interface"), index, f"{name}.interface")
|
||||
peer = format_template(data.get("peer"), index, f"{name}.peer")
|
||||
bind = data.get("bind", True)
|
||||
if not isinstance(bind, bool):
|
||||
raise ValueError(f"{name}.bind must be boolean")
|
||||
if kind in {"tri_input", "schmitt_input", "tri_output"} and signal is None:
|
||||
raise ValueError(f"{name}.signal is required for {kind}")
|
||||
if kind == "full" and (interface is None or index is None):
|
||||
raise ValueError(f"{name} requires an interface and index")
|
||||
if kind in {"xpi_data", "sdram_dq"} and index is None:
|
||||
raise ValueError(f"{name} requires an index")
|
||||
if kind == "xtal" and bind and (signal is None or peer is None):
|
||||
raise ValueError(f"{name} requires signal and peer")
|
||||
return Pad(name, direction, feature, kind, index, signal, interface, peer, bind)
|
||||
|
||||
|
||||
def expand_group(group: Any, index: int) -> list[Pad]:
|
||||
if not isinstance(group, dict):
|
||||
raise ValueError(f"pads[{index}] must be an object")
|
||||
defaults = {key: value for key, value in group.items() if key not in {"ports", "count", "prefix", "suffix"}}
|
||||
ports = group.get("ports")
|
||||
if ports is not None:
|
||||
if not isinstance(ports, list) or not ports:
|
||||
raise ValueError(f"pads[{index}].ports must be a non-empty list")
|
||||
if not all(isinstance(port, dict) for port in ports):
|
||||
raise ValueError(f"pads[{index}].ports entries must be objects")
|
||||
return [parse_pad(port, defaults, None) for port in ports]
|
||||
count = group.get("count")
|
||||
if not isinstance(count, int) or count <= 0:
|
||||
raise ValueError(f"pads[{index}].count must be a positive integer")
|
||||
prefix = require_string(group.get("prefix"), f"pads[{index}].prefix")
|
||||
suffix = require_string(group.get("suffix"), f"pads[{index}].suffix")
|
||||
return [
|
||||
parse_pad({"name": f"{prefix}{pad_index}{suffix}"}, defaults, pad_index)
|
||||
for pad_index in range(count)
|
||||
]
|
||||
|
||||
|
||||
def validate_connection(value: Any, field: str) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
connection = require_string(value, field)
|
||||
if CONNECTION_RE.fullmatch(connection) or CONSTANT_RE.fullmatch(connection):
|
||||
return connection
|
||||
raise ValueError(f"{field} must be a signal, bit-select, constant, or null")
|
||||
|
||||
|
||||
def read_map(path: Path) -> tuple[list[Pad], dict[str, dict[str, str | None]]]:
|
||||
with path.open(encoding="utf-8") as source:
|
||||
document = json.load(source)
|
||||
if document.get("schema_version") != 1:
|
||||
raise ValueError("schema_version must be 1")
|
||||
groups = document.get("pads")
|
||||
if not isinstance(groups, list) or not groups:
|
||||
raise ValueError("pads must be a non-empty list")
|
||||
pads: list[Pad] = []
|
||||
for index, group in enumerate(groups):
|
||||
expanded = expand_group(group, index)
|
||||
if len(expanded) == 0:
|
||||
raise ValueError(f"pads[{index}] does not expand to any pads")
|
||||
pads.extend(expanded)
|
||||
names = [pad.name for pad in pads]
|
||||
if len(names) != len(set(names)):
|
||||
raise ValueError("pad names must be unique")
|
||||
known_names = set(names)
|
||||
for pad in pads:
|
||||
if pad.peer is not None and pad.peer not in known_names:
|
||||
raise ValueError(f"{pad.name}.peer is not a known pad")
|
||||
profiles = document.get("profiles")
|
||||
if not isinstance(profiles, dict) or set(profiles) != REQUIRED_PROFILES:
|
||||
raise ValueError(f"profiles must contain exactly {sorted(REQUIRED_PROFILES)}")
|
||||
normalized_profiles: dict[str, dict[str, str | None]] = {}
|
||||
for profile, profile_data in profiles.items():
|
||||
if not isinstance(profile_data, dict):
|
||||
raise ValueError(f"profiles.{profile} must be an object")
|
||||
bindings = profile_data.get("bindings", {})
|
||||
if not isinstance(bindings, dict):
|
||||
raise ValueError(f"profiles.{profile}.bindings must be an object")
|
||||
if any(name not in known_names for name in bindings):
|
||||
raise ValueError(f"profiles.{profile} contains an unknown pad")
|
||||
normalized_profiles[profile] = {
|
||||
name: validate_connection(value, f"profiles.{profile}.bindings.{name}")
|
||||
for name, value in bindings.items()
|
||||
}
|
||||
return pads, normalized_profiles
|
||||
|
||||
|
||||
def wrap_feature(pad: Pad, line: str) -> list[str]:
|
||||
if pad.feature is None:
|
||||
return [line]
|
||||
return [f"`ifdef {pad.feature}", line, "`endif"]
|
||||
|
||||
|
||||
def render_ports(pads: list[Pad]) -> str:
|
||||
lines = ["// Generated by rtl/mini/pin_map/generate_pin_map.py; do not edit."]
|
||||
for index, pad in enumerate(pads):
|
||||
suffix = "," if index != len(pads) - 1 else ""
|
||||
lines.extend(wrap_feature(pad, f" {pad.direction} {pad.name}{suffix}"))
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def render_pad_instance(pad: Pad) -> str | None:
|
||||
instance = f"u_{pad.name}"
|
||||
if pad.kind == "tri_input":
|
||||
return (
|
||||
f" tc_io_tri_pad {instance} (.pad({pad.name}), .c2p(1'b0), .c2p_en(1'b0), "
|
||||
f".p2c({pad.signal}));"
|
||||
)
|
||||
if pad.kind == "schmitt_input":
|
||||
return (
|
||||
f" tc_io_tri_schmitt_pad {instance} (.pad({pad.name}), .c2p(1'b0), "
|
||||
f".c2p_en(1'b0), .p2c({pad.signal}));"
|
||||
)
|
||||
if pad.kind == "tri_output":
|
||||
return (
|
||||
f" tc_io_tri_pad {instance} (.pad({pad.name}), .c2p({pad.signal}), .c2p_en(1'b1), "
|
||||
".p2c());"
|
||||
)
|
||||
if pad.kind == "full":
|
||||
return (
|
||||
f" tc_io_tri_full_pad {instance} (.pad({pad.name}), .c2p({pad.interface}.do_o[{pad.index}]), "
|
||||
f".c2p_en({pad.interface}.oe_o[{pad.index}]), .p2c({pad.interface}.di_i[{pad.index}]), "
|
||||
f".cs({pad.interface}.cs_o[{pad.index}]), .pu({pad.interface}.pu_o[{pad.index}]), "
|
||||
f".pd({pad.interface}.pd_o[{pad.index}]));"
|
||||
)
|
||||
if pad.kind == "xpi_data":
|
||||
return (
|
||||
f" tc_io_tri_pad {instance} (.pad({pad.name}), .c2p(u_xpi_if.io_do_o[{pad.index}]), "
|
||||
f".c2p_en(u_xpi_if.io_oe_o[{pad.index}]), .p2c(u_xpi_if.io_di_i[{pad.index}]));"
|
||||
)
|
||||
if pad.kind == "sdram_dq":
|
||||
return (
|
||||
f" tc_io_tri_pad {instance} (.pad({pad.name}), .c2p(u_sdram_if.dq_o[{pad.index}]), "
|
||||
f".c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[{pad.index}]));"
|
||||
)
|
||||
if pad.kind == "xtal" and pad.bind:
|
||||
return (
|
||||
f" tc_io_xtl_pad u_xtal_io_pad (.xi_pad({pad.name}), .xo_pad({pad.peer}), "
|
||||
f".en(1'b1), .clk({pad.signal}));"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def render_pad_bindings(pads: list[Pad]) -> str:
|
||||
lines = ["// Generated by rtl/mini/pin_map/generate_pin_map.py; do not edit."]
|
||||
for pad in pads:
|
||||
line = render_pad_instance(pad)
|
||||
if line is not None:
|
||||
lines.extend(wrap_feature(pad, line))
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def render_profile_bindings(pads: list[Pad], bindings: dict[str, str | None]) -> str:
|
||||
lines = ["// Generated by rtl/mini/pin_map/generate_pin_map.py; do not edit."]
|
||||
for index, pad in enumerate(pads):
|
||||
connection = bindings.get(pad.name)
|
||||
suffix = "," if index != len(pads) - 1 else ""
|
||||
value = "" if connection is None else connection
|
||||
lines.extend(wrap_feature(pad, f" .{pad.name}({value}){suffix}"))
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def generate(map_path: Path, output_dir: Path) -> None:
|
||||
pads, profiles = read_map(map_path)
|
||||
rtl_dir = output_dir / "rtl"
|
||||
atomic_write(rtl_dir / "retrosoc_asic_ports.svh", render_ports(pads))
|
||||
atomic_write(rtl_dir / "retrosoc_asic_pad_bindings.svh", render_pad_bindings(pads))
|
||||
for profile, bindings in profiles.items():
|
||||
atomic_write(
|
||||
rtl_dir / f"retrosoc_asic_{profile}_bindings.svh",
|
||||
render_profile_bindings(pads, bindings),
|
||||
)
|
||||
atomic_write(output_dir / "pin_map.fl", f"+incdir+{rtl_dir}\n")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--map", required=True, type=Path)
|
||||
parser.add_argument("--output-dir", type=Path)
|
||||
parser.add_argument("--check", action="store_true", help="validate only; write nothing")
|
||||
arguments = parser.parse_args()
|
||||
try:
|
||||
if arguments.check:
|
||||
read_map(arguments.map)
|
||||
else:
|
||||
if arguments.output_dir is None:
|
||||
parser.error("--output-dir is required unless --check is used")
|
||||
generate(arguments.map, arguments.output_dir)
|
||||
except (OSError, ValueError, json.JSONDecodeError) as error:
|
||||
parser.error(str(error))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,314 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"pads": [
|
||||
{
|
||||
"kind": "tri_input",
|
||||
"direction": "inout",
|
||||
"ports": [
|
||||
{"name": "extclk_i_pad", "signal": "s_ext_clk"},
|
||||
{"name": "audclk_i_pad", "signal": "s_aud_clk"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "schmitt_input",
|
||||
"direction": "inout",
|
||||
"ports": [
|
||||
{"name": "ext_rst_n_i_pad", "signal": "s_ext_rst_n"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "xtal",
|
||||
"feature": "HAVE_PLL",
|
||||
"ports": [
|
||||
{"name": "xi_i_pad", "direction": "input", "signal": "s_xtal_io", "peer": "xo_o_pad"},
|
||||
{"name": "xo_o_pad", "direction": "output", "bind": false}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "tri_input",
|
||||
"direction": "inout",
|
||||
"feature": "CORE_MDD",
|
||||
"prefix": "core_sel_",
|
||||
"suffix": "_i_pad",
|
||||
"count": 5,
|
||||
"signal": "s_core_sel[{index}]"
|
||||
},
|
||||
{
|
||||
"kind": "full",
|
||||
"direction": "inout",
|
||||
"feature": "IP_MDD",
|
||||
"prefix": "user_gpio_",
|
||||
"suffix": "_io_pad",
|
||||
"count": 16,
|
||||
"interface": "u_user_gpio_if"
|
||||
},
|
||||
{
|
||||
"kind": "full",
|
||||
"direction": "inout",
|
||||
"prefix": "gpio_",
|
||||
"suffix": "_io_pad",
|
||||
"count": 32,
|
||||
"interface": "u_gpio_if"
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"ports": [
|
||||
{"name": "uart0_tx_o_pad", "signal": "u_uart0_if.tx_o"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "tri_input",
|
||||
"direction": "inout",
|
||||
"ports": [
|
||||
{"name": "uart0_rx_i_pad", "signal": "u_uart0_if.rx_i"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"ports": [
|
||||
{"name": "xpi_sck_o_pad", "signal": "u_xpi_if.sck_o"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"prefix": "xpi_nss",
|
||||
"suffix": "_o_pad",
|
||||
"count": 4,
|
||||
"signal": "u_xpi_if.nss_o[{index}]"
|
||||
},
|
||||
{
|
||||
"kind": "xpi_data",
|
||||
"direction": "inout",
|
||||
"prefix": "xpi_dat",
|
||||
"suffix": "_io_pad",
|
||||
"count": 4
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"ports": [
|
||||
{"name": "sdram_clk_o_pad", "signal": "u_sdram_if.clk_o"},
|
||||
{"name": "sdram_cke_o_pad", "signal": "u_sdram_if.cke_o"},
|
||||
{"name": "sdram_cs_n_o_pad", "signal": "u_sdram_if.cs_n_o"},
|
||||
{"name": "sdram_ras_n_o_pad", "signal": "u_sdram_if.ras_n_o"},
|
||||
{"name": "sdram_cas_n_o_pad", "signal": "u_sdram_if.cas_n_o"},
|
||||
{"name": "sdram_we_n_o_pad", "signal": "u_sdram_if.we_n_o"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"prefix": "sdram_ba",
|
||||
"suffix": "_o_pad",
|
||||
"count": 2,
|
||||
"signal": "u_sdram_if.ba_o[{index}]"
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"prefix": "sdram_addr",
|
||||
"suffix": "_o_pad",
|
||||
"count": 13,
|
||||
"signal": "u_sdram_if.addr_o[{index}]"
|
||||
},
|
||||
{
|
||||
"kind": "tri_output",
|
||||
"direction": "output",
|
||||
"prefix": "sdram_dqm",
|
||||
"suffix": "_o_pad",
|
||||
"count": 2,
|
||||
"signal": "u_sdram_if.dqm_o[{index}]"
|
||||
},
|
||||
{
|
||||
"kind": "sdram_dq",
|
||||
"direction": "inout",
|
||||
"prefix": "sdram_dq",
|
||||
"suffix": "_io_pad",
|
||||
"count": 16
|
||||
}
|
||||
],
|
||||
"profiles": {
|
||||
"fpga_mini": {
|
||||
"bindings": {
|
||||
"extclk_i_pad": "s_sys_clk",
|
||||
"audclk_i_pad": "s_aud_clk",
|
||||
"ext_rst_n_i_pad": "rst_n_i",
|
||||
"xi_i_pad": "s_sys_clk",
|
||||
"core_sel_0_i_pad": "1'b0",
|
||||
"core_sel_1_i_pad": "1'b0",
|
||||
"core_sel_2_i_pad": "1'b0",
|
||||
"core_sel_3_i_pad": "1'b0",
|
||||
"core_sel_4_i_pad": "1'b0",
|
||||
"gpio_0_io_pad": "ps2_clk_i",
|
||||
"gpio_1_io_pad": "ps2_dat_i",
|
||||
"gpio_2_io_pad": "onewire_dat_o",
|
||||
"gpio_3_io_pad": "i2c_scl_io",
|
||||
"gpio_4_io_pad": "i2c_sda_io",
|
||||
"gpio_5_io_pad": "pwm_2_o",
|
||||
"gpio_6_io_pad": "spisd_sck_o",
|
||||
"gpio_7_io_pad": "spisd_nss_o",
|
||||
"gpio_8_io_pad": "spisd_mosi_o",
|
||||
"gpio_9_io_pad": "spisd_miso_i",
|
||||
"gpio_10_io_pad": "i2s_mclk_o",
|
||||
"gpio_11_io_pad": "i2s_sclk_o",
|
||||
"gpio_12_io_pad": "i2s_lrck_o",
|
||||
"gpio_13_io_pad": "i2s_dacdat_o",
|
||||
"gpio_14_io_pad": "i2s_adcdat_i",
|
||||
"gpio_21_io_pad": "psram_sck_o",
|
||||
"gpio_22_io_pad": "psram_nss0_o",
|
||||
"gpio_23_io_pad": "psram_dat0_io",
|
||||
"gpio_24_io_pad": "psram_dat1_io",
|
||||
"gpio_25_io_pad": "psram_dat2_io",
|
||||
"gpio_26_io_pad": "psram_dat3_io",
|
||||
"gpio_30_io_pad": "gpio_io30",
|
||||
"uart0_tx_o_pad": "uart0_tx_o",
|
||||
"uart0_rx_i_pad": "uart0_rx_i",
|
||||
"xpi_sck_o_pad": "xpi_sck_o",
|
||||
"xpi_nss0_o_pad": "xpi_nss0_o",
|
||||
"xpi_dat0_io_pad": "xpi_dat0_io",
|
||||
"xpi_dat1_io_pad": "xpi_dat1_io",
|
||||
"xpi_dat2_io_pad": "xpi_dat2_io",
|
||||
"xpi_dat3_io_pad": "xpi_dat3_io",
|
||||
"sdram_clk_o_pad": "sdram_clk_o",
|
||||
"sdram_cke_o_pad": "sdram_cke_o",
|
||||
"sdram_cs_n_o_pad": "sdram_cs_n_o",
|
||||
"sdram_ras_n_o_pad": "sdram_ras_n_o",
|
||||
"sdram_cas_n_o_pad": "sdram_cas_n_o",
|
||||
"sdram_we_n_o_pad": "sdram_we_n_o",
|
||||
"sdram_ba0_o_pad": "sdram_ba0_o",
|
||||
"sdram_ba1_o_pad": "sdram_ba1_o",
|
||||
"sdram_addr0_o_pad": "sdram_addr0_o",
|
||||
"sdram_addr1_o_pad": "sdram_addr1_o",
|
||||
"sdram_addr2_o_pad": "sdram_addr2_o",
|
||||
"sdram_addr3_o_pad": "sdram_addr3_o",
|
||||
"sdram_addr4_o_pad": "sdram_addr4_o",
|
||||
"sdram_addr5_o_pad": "sdram_addr5_o",
|
||||
"sdram_addr6_o_pad": "sdram_addr6_o",
|
||||
"sdram_addr7_o_pad": "sdram_addr7_o",
|
||||
"sdram_addr8_o_pad": "sdram_addr8_o",
|
||||
"sdram_addr9_o_pad": "sdram_addr9_o",
|
||||
"sdram_addr10_o_pad": "sdram_addr10_o",
|
||||
"sdram_addr11_o_pad": "sdram_addr11_o",
|
||||
"sdram_addr12_o_pad": "sdram_addr12_o",
|
||||
"sdram_dqm0_o_pad": "sdram_dqm0_o",
|
||||
"sdram_dqm1_o_pad": "sdram_dqm1_o",
|
||||
"sdram_dq0_io_pad": "sdram_dq0_io",
|
||||
"sdram_dq1_io_pad": "sdram_dq1_io",
|
||||
"sdram_dq2_io_pad": "sdram_dq2_io",
|
||||
"sdram_dq3_io_pad": "sdram_dq3_io",
|
||||
"sdram_dq4_io_pad": "sdram_dq4_io",
|
||||
"sdram_dq5_io_pad": "sdram_dq5_io",
|
||||
"sdram_dq6_io_pad": "sdram_dq6_io",
|
||||
"sdram_dq7_io_pad": "sdram_dq7_io",
|
||||
"sdram_dq8_io_pad": "sdram_dq8_io",
|
||||
"sdram_dq9_io_pad": "sdram_dq9_io",
|
||||
"sdram_dq10_io_pad": "sdram_dq10_io",
|
||||
"sdram_dq11_io_pad": "sdram_dq11_io",
|
||||
"sdram_dq12_io_pad": "sdram_dq12_io",
|
||||
"sdram_dq13_io_pad": "sdram_dq13_io",
|
||||
"sdram_dq14_io_pad": "sdram_dq14_io",
|
||||
"sdram_dq15_io_pad": "sdram_dq15_io"
|
||||
}
|
||||
},
|
||||
"verilator": {
|
||||
"bindings": {
|
||||
"extclk_i_pad": "s_clk",
|
||||
"ext_rst_n_i_pad": "s_rst_n",
|
||||
"core_sel_0_i_pad": "s_core_sel[0]",
|
||||
"core_sel_1_i_pad": "s_core_sel[1]",
|
||||
"core_sel_2_i_pad": "s_core_sel[2]",
|
||||
"core_sel_3_i_pad": "s_core_sel[3]",
|
||||
"core_sel_4_i_pad": "s_core_sel[4]",
|
||||
"gpio_21_io_pad": "s_psram_sck",
|
||||
"gpio_22_io_pad": "s_psram_nss0",
|
||||
"gpio_23_io_pad": "s_psram_dat0",
|
||||
"gpio_24_io_pad": "s_psram_dat1",
|
||||
"gpio_25_io_pad": "s_psram_dat2",
|
||||
"gpio_26_io_pad": "s_psram_dat3",
|
||||
"xpi_sck_o_pad": "s_xpi_sck_o",
|
||||
"xpi_nss0_o_pad": "s_xpi_nss0_o",
|
||||
"xpi_dat0_io_pad": "s_xpi_dat0_io",
|
||||
"xpi_dat1_io_pad": "s_xpi_dat1_io",
|
||||
"xpi_dat2_io_pad": "s_xpi_dat2_io",
|
||||
"xpi_dat3_io_pad": "s_xpi_dat3_io"
|
||||
}
|
||||
},
|
||||
"tb": {
|
||||
"bindings": {
|
||||
"extclk_i_pad": "s_ext_clk",
|
||||
"audclk_i_pad": "s_aud_clk",
|
||||
"ext_rst_n_i_pad": "s_rst_n",
|
||||
"xi_i_pad": "r_xtal_clk",
|
||||
"core_sel_0_i_pad": "s_core_sel[0]",
|
||||
"core_sel_1_i_pad": "s_core_sel[1]",
|
||||
"core_sel_2_i_pad": "s_core_sel[2]",
|
||||
"core_sel_3_i_pad": "s_core_sel[3]",
|
||||
"core_sel_4_i_pad": "s_core_sel[4]",
|
||||
"user_gpio_0_io_pad": "s_user_gpio_0_io",
|
||||
"gpio_0_io_pad": "s_gpio_0_io",
|
||||
"gpio_1_io_pad": "s_gpio_1_io",
|
||||
"gpio_7_io_pad": "s_i2c0_scl_io",
|
||||
"gpio_8_io_pad": "s_i2c0_sda_io",
|
||||
"gpio_21_io_pad": "s_psram_sck",
|
||||
"gpio_22_io_pad": "s_psram_nss0",
|
||||
"gpio_23_io_pad": "s_psram_dat0",
|
||||
"gpio_24_io_pad": "s_psram_dat1",
|
||||
"gpio_25_io_pad": "s_psram_dat2",
|
||||
"gpio_26_io_pad": "s_psram_dat3",
|
||||
"gpio_27_io_pad": "s_psram_nss1",
|
||||
"uart0_tx_o_pad": "s_uart0_tx",
|
||||
"uart0_rx_i_pad": "s_uart0_rx",
|
||||
"xpi_sck_o_pad": "s_xpi_sck_o",
|
||||
"xpi_nss0_o_pad": "s_xpi_nss0_o",
|
||||
"xpi_nss1_o_pad": "s_xpi_nss1_o",
|
||||
"xpi_nss2_o_pad": "s_xpi_nss2_o",
|
||||
"xpi_dat0_io_pad": "s_xpi_dat0_io",
|
||||
"xpi_dat1_io_pad": "s_xpi_dat1_io",
|
||||
"xpi_dat2_io_pad": "s_xpi_dat2_io",
|
||||
"xpi_dat3_io_pad": "s_xpi_dat3_io",
|
||||
"sdram_clk_o_pad": "s_sdram_clk",
|
||||
"sdram_cke_o_pad": "s_sdram_cke",
|
||||
"sdram_cs_n_o_pad": "s_sdram_cs_n",
|
||||
"sdram_ras_n_o_pad": "s_sdram_ras_n",
|
||||
"sdram_cas_n_o_pad": "s_sdram_cas_n",
|
||||
"sdram_we_n_o_pad": "s_sdram_we_n",
|
||||
"sdram_ba0_o_pad": "s_sdram_ba[0]",
|
||||
"sdram_ba1_o_pad": "s_sdram_ba[1]",
|
||||
"sdram_addr0_o_pad": "s_sdram_addr[0]",
|
||||
"sdram_addr1_o_pad": "s_sdram_addr[1]",
|
||||
"sdram_addr2_o_pad": "s_sdram_addr[2]",
|
||||
"sdram_addr3_o_pad": "s_sdram_addr[3]",
|
||||
"sdram_addr4_o_pad": "s_sdram_addr[4]",
|
||||
"sdram_addr5_o_pad": "s_sdram_addr[5]",
|
||||
"sdram_addr6_o_pad": "s_sdram_addr[6]",
|
||||
"sdram_addr7_o_pad": "s_sdram_addr[7]",
|
||||
"sdram_addr8_o_pad": "s_sdram_addr[8]",
|
||||
"sdram_addr9_o_pad": "s_sdram_addr[9]",
|
||||
"sdram_addr10_o_pad": "s_sdram_addr[10]",
|
||||
"sdram_addr11_o_pad": "s_sdram_addr[11]",
|
||||
"sdram_addr12_o_pad": "s_sdram_addr[12]",
|
||||
"sdram_dqm0_o_pad": "s_sdram_dqm[0]",
|
||||
"sdram_dqm1_o_pad": "s_sdram_dqm[1]",
|
||||
"sdram_dq0_io_pad": "s_sdram_dq[0]",
|
||||
"sdram_dq1_io_pad": "s_sdram_dq[1]",
|
||||
"sdram_dq2_io_pad": "s_sdram_dq[2]",
|
||||
"sdram_dq3_io_pad": "s_sdram_dq[3]",
|
||||
"sdram_dq4_io_pad": "s_sdram_dq[4]",
|
||||
"sdram_dq5_io_pad": "s_sdram_dq[5]",
|
||||
"sdram_dq6_io_pad": "s_sdram_dq[6]",
|
||||
"sdram_dq7_io_pad": "s_sdram_dq[7]",
|
||||
"sdram_dq8_io_pad": "s_sdram_dq[8]",
|
||||
"sdram_dq9_io_pad": "s_sdram_dq[9]",
|
||||
"sdram_dq10_io_pad": "s_sdram_dq[10]",
|
||||
"sdram_dq11_io_pad": "s_sdram_dq[11]",
|
||||
"sdram_dq12_io_pad": "s_sdram_dq[12]",
|
||||
"sdram_dq13_io_pad": "s_sdram_dq[13]",
|
||||
"sdram_dq14_io_pad": "s_sdram_dq[14]",
|
||||
"sdram_dq15_io_pad": "s_sdram_dq[15]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ def parse_args() -> argparse.Namespace:
|
||||
parser.add_argument("--mode", required=True, choices=("behv", "netl", "post"))
|
||||
parser.add_argument("--pdk", required=True)
|
||||
parser.add_argument("--generated-dir", type=Path, default=DEFAULT_GENERATED_DIR)
|
||||
parser.add_argument("--pin-map-rtl-dir", type=Path, required=True)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
parser.add_argument("--converted", type=Path)
|
||||
parser.add_argument("--netlist", type=Path)
|
||||
@@ -60,6 +61,10 @@ def main() -> int:
|
||||
base_names = ["def.fl", "sys_def.fl", "inc.fl", "tb.fl"]
|
||||
base = parse_filelists(generated_dir / name for name in base_names)
|
||||
base.options.insert(0, "+timescale+1ns/1ps")
|
||||
pin_map_rtl_dir = args.pin_map_rtl_dir.resolve()
|
||||
if not pin_map_rtl_dir.is_dir():
|
||||
raise FileNotFoundError(f"pin-map RTL directory not found: {pin_map_rtl_dir}")
|
||||
base.incdirs.append(pin_map_rtl_dir)
|
||||
|
||||
if args.mode == "behv":
|
||||
base.files.append(_require(args.converted, "converted behavioral RTL"))
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// retroSoC is licensed under Mulan PSL v2.
|
||||
// You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
// You may obtain a copy of Mulan PSL v2 at:
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
module apb4_if_bridge (
|
||||
apb4_pure_if.slave apb_pure,
|
||||
apb4_if.master timed
|
||||
);
|
||||
|
||||
assign timed.paddr = apb_pure.paddr;
|
||||
assign timed.pprot = apb_pure.pprot;
|
||||
assign timed.psel = apb_pure.psel;
|
||||
assign timed.penable = apb_pure.penable;
|
||||
assign timed.pwrite = apb_pure.pwrite;
|
||||
assign timed.pwdata = apb_pure.pwdata;
|
||||
assign timed.pstrb = apb_pure.pstrb;
|
||||
|
||||
assign apb_pure.pready = timed.pready;
|
||||
assign apb_pure.prdata = timed.prdata;
|
||||
assign apb_pure.pslverr = timed.pslverr;
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
|
||||
// retroSoC is licensed under Mulan PSL v2.
|
||||
// You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
// You may obtain a copy of Mulan PSL v2 at:
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
module gpio_pad_bridge (
|
||||
gpio_if.pad inner,
|
||||
gpio_if.soc_pad outer
|
||||
);
|
||||
|
||||
assign outer.oe_o = inner.oe_o;
|
||||
assign outer.cs_o = inner.cs_o;
|
||||
assign outer.pu_o = inner.pu_o;
|
||||
assign outer.pd_o = inner.pd_o;
|
||||
assign outer.do_o = inner.do_o;
|
||||
assign inner.di_i = outer.di_i;
|
||||
|
||||
endmodule
|
||||
+40
-109
@@ -70,116 +70,47 @@ module ip_apb_wrapper (
|
||||
`endif
|
||||
// verilog_format: on
|
||||
|
||||
// archinfo
|
||||
assign u_archinfo_apb_if.paddr = u_archinfo_apb_pure_if.paddr;
|
||||
assign u_archinfo_apb_if.pprot = u_archinfo_apb_pure_if.pprot;
|
||||
assign u_archinfo_apb_if.psel = u_archinfo_apb_pure_if.psel;
|
||||
assign u_archinfo_apb_if.penable = u_archinfo_apb_pure_if.penable;
|
||||
assign u_archinfo_apb_if.pwrite = u_archinfo_apb_pure_if.pwrite;
|
||||
assign u_archinfo_apb_if.pwdata = u_archinfo_apb_pure_if.pwdata;
|
||||
assign u_archinfo_apb_if.pstrb = u_archinfo_apb_pure_if.pstrb;
|
||||
assign u_archinfo_apb_pure_if.pready = u_archinfo_apb_if.pready;
|
||||
assign u_archinfo_apb_pure_if.prdata = u_archinfo_apb_if.prdata;
|
||||
assign u_archinfo_apb_pure_if.pslverr = u_archinfo_apb_if.pslverr;
|
||||
// rng
|
||||
assign u_rng_apb_if.paddr = u_rng_apb_pure_if.paddr;
|
||||
assign u_rng_apb_if.pprot = u_rng_apb_pure_if.pprot;
|
||||
assign u_rng_apb_if.psel = u_rng_apb_pure_if.psel;
|
||||
assign u_rng_apb_if.penable = u_rng_apb_pure_if.penable;
|
||||
assign u_rng_apb_if.pwrite = u_rng_apb_pure_if.pwrite;
|
||||
assign u_rng_apb_if.pwdata = u_rng_apb_pure_if.pwdata;
|
||||
assign u_rng_apb_if.pstrb = u_rng_apb_pure_if.pstrb;
|
||||
assign u_rng_apb_pure_if.pready = u_rng_apb_if.pready;
|
||||
assign u_rng_apb_pure_if.prdata = u_rng_apb_if.prdata;
|
||||
assign u_rng_apb_pure_if.pslverr = u_rng_apb_if.pslverr;
|
||||
// uart1
|
||||
assign u_uart1_apb_if.paddr = u_uart1_apb_pure_if.paddr;
|
||||
assign u_uart1_apb_if.pprot = u_uart1_apb_pure_if.pprot;
|
||||
assign u_uart1_apb_if.psel = u_uart1_apb_pure_if.psel;
|
||||
assign u_uart1_apb_if.penable = u_uart1_apb_pure_if.penable;
|
||||
assign u_uart1_apb_if.pwrite = u_uart1_apb_pure_if.pwrite;
|
||||
assign u_uart1_apb_if.pwdata = u_uart1_apb_pure_if.pwdata;
|
||||
assign u_uart1_apb_if.pstrb = u_uart1_apb_pure_if.pstrb;
|
||||
assign u_uart1_apb_pure_if.pready = u_uart1_apb_if.pready;
|
||||
assign u_uart1_apb_pure_if.prdata = u_uart1_apb_if.prdata;
|
||||
assign u_uart1_apb_pure_if.pslverr = u_uart1_apb_if.pslverr;
|
||||
// pwm
|
||||
assign u_pwm_apb_if.paddr = u_pwm_apb_pure_if.paddr;
|
||||
assign u_pwm_apb_if.pprot = u_pwm_apb_pure_if.pprot;
|
||||
assign u_pwm_apb_if.psel = u_pwm_apb_pure_if.psel;
|
||||
assign u_pwm_apb_if.penable = u_pwm_apb_pure_if.penable;
|
||||
assign u_pwm_apb_if.pwrite = u_pwm_apb_pure_if.pwrite;
|
||||
assign u_pwm_apb_if.pwdata = u_pwm_apb_pure_if.pwdata;
|
||||
assign u_pwm_apb_if.pstrb = u_pwm_apb_pure_if.pstrb;
|
||||
assign u_pwm_apb_pure_if.pready = u_pwm_apb_if.pready;
|
||||
assign u_pwm_apb_pure_if.prdata = u_pwm_apb_if.prdata;
|
||||
assign u_pwm_apb_pure_if.pslverr = u_pwm_apb_if.pslverr;
|
||||
// ps2
|
||||
assign u_ps2_apb_if.paddr = u_ps2_apb_pure_if.paddr;
|
||||
assign u_ps2_apb_if.pprot = u_ps2_apb_pure_if.pprot;
|
||||
assign u_ps2_apb_if.psel = u_ps2_apb_pure_if.psel;
|
||||
assign u_ps2_apb_if.penable = u_ps2_apb_pure_if.penable;
|
||||
assign u_ps2_apb_if.pwrite = u_ps2_apb_pure_if.pwrite;
|
||||
assign u_ps2_apb_if.pwdata = u_ps2_apb_pure_if.pwdata;
|
||||
assign u_ps2_apb_if.pstrb = u_ps2_apb_pure_if.pstrb;
|
||||
assign u_ps2_apb_pure_if.pready = u_ps2_apb_if.pready;
|
||||
assign u_ps2_apb_pure_if.prdata = u_ps2_apb_if.prdata;
|
||||
assign u_ps2_apb_pure_if.pslverr = u_ps2_apb_if.pslverr;
|
||||
// rtc
|
||||
assign u_rtc_apb_if.paddr = u_rtc_apb_pure_if.paddr;
|
||||
assign u_rtc_apb_if.pprot = u_rtc_apb_pure_if.pprot;
|
||||
assign u_rtc_apb_if.psel = u_rtc_apb_pure_if.psel;
|
||||
assign u_rtc_apb_if.penable = u_rtc_apb_pure_if.penable;
|
||||
assign u_rtc_apb_if.pwrite = u_rtc_apb_pure_if.pwrite;
|
||||
assign u_rtc_apb_if.pwdata = u_rtc_apb_pure_if.pwdata;
|
||||
assign u_rtc_apb_if.pstrb = u_rtc_apb_pure_if.pstrb;
|
||||
assign u_rtc_apb_pure_if.pready = u_rtc_apb_if.pready;
|
||||
assign u_rtc_apb_pure_if.prdata = u_rtc_apb_if.prdata;
|
||||
assign u_rtc_apb_pure_if.pslverr = u_rtc_apb_if.pslverr;
|
||||
// wdg
|
||||
assign u_wdg_apb_if.paddr = u_wdg_apb_pure_if.paddr;
|
||||
assign u_wdg_apb_if.pprot = u_wdg_apb_pure_if.pprot;
|
||||
assign u_wdg_apb_if.psel = u_wdg_apb_pure_if.psel;
|
||||
assign u_wdg_apb_if.penable = u_wdg_apb_pure_if.penable;
|
||||
assign u_wdg_apb_if.pwrite = u_wdg_apb_pure_if.pwrite;
|
||||
assign u_wdg_apb_if.pwdata = u_wdg_apb_pure_if.pwdata;
|
||||
assign u_wdg_apb_if.pstrb = u_wdg_apb_pure_if.pstrb;
|
||||
assign u_wdg_apb_pure_if.pready = u_wdg_apb_if.pready;
|
||||
assign u_wdg_apb_pure_if.prdata = u_wdg_apb_if.prdata;
|
||||
assign u_wdg_apb_pure_if.pslverr = u_wdg_apb_if.pslverr;
|
||||
// crc
|
||||
assign u_crc_apb_if.paddr = u_crc_apb_pure_if.paddr;
|
||||
assign u_crc_apb_if.pprot = u_crc_apb_pure_if.pprot;
|
||||
assign u_crc_apb_if.psel = u_crc_apb_pure_if.psel;
|
||||
assign u_crc_apb_if.penable = u_crc_apb_pure_if.penable;
|
||||
assign u_crc_apb_if.pwrite = u_crc_apb_pure_if.pwrite;
|
||||
assign u_crc_apb_if.pwdata = u_crc_apb_pure_if.pwdata;
|
||||
assign u_crc_apb_if.pstrb = u_crc_apb_pure_if.pstrb;
|
||||
assign u_crc_apb_pure_if.pready = u_crc_apb_if.pready;
|
||||
assign u_crc_apb_pure_if.prdata = u_crc_apb_if.prdata;
|
||||
assign u_crc_apb_pure_if.pslverr = u_crc_apb_if.pslverr;
|
||||
// tmr
|
||||
assign u_tmr_apb_if.paddr = u_tmr_apb_pure_if.paddr;
|
||||
assign u_tmr_apb_if.pprot = u_tmr_apb_pure_if.pprot;
|
||||
assign u_tmr_apb_if.psel = u_tmr_apb_pure_if.psel;
|
||||
assign u_tmr_apb_if.penable = u_tmr_apb_pure_if.penable;
|
||||
assign u_tmr_apb_if.pwrite = u_tmr_apb_pure_if.pwrite;
|
||||
assign u_tmr_apb_if.pwdata = u_tmr_apb_pure_if.pwdata;
|
||||
assign u_tmr_apb_if.pstrb = u_tmr_apb_pure_if.pstrb;
|
||||
assign u_tmr_apb_pure_if.pready = u_tmr_apb_if.pready;
|
||||
assign u_tmr_apb_pure_if.prdata = u_tmr_apb_if.prdata;
|
||||
assign u_tmr_apb_pure_if.pslverr = u_tmr_apb_if.pslverr;
|
||||
apb4_if_bridge u_archinfo_apb_bridge (
|
||||
.apb_pure(u_archinfo_apb_pure_if),
|
||||
.timed (u_archinfo_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_rng_apb_bridge (
|
||||
.apb_pure(u_rng_apb_pure_if),
|
||||
.timed (u_rng_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_uart1_apb_bridge (
|
||||
.apb_pure(u_uart1_apb_pure_if),
|
||||
.timed (u_uart1_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_pwm_apb_bridge (
|
||||
.apb_pure(u_pwm_apb_pure_if),
|
||||
.timed (u_pwm_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_ps2_apb_bridge (
|
||||
.apb_pure(u_ps2_apb_pure_if),
|
||||
.timed (u_ps2_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_rtc_apb_bridge (
|
||||
.apb_pure(u_rtc_apb_pure_if),
|
||||
.timed (u_rtc_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_wdg_apb_bridge (
|
||||
.apb_pure(u_wdg_apb_pure_if),
|
||||
.timed (u_wdg_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_crc_apb_bridge (
|
||||
.apb_pure(u_crc_apb_pure_if),
|
||||
.timed (u_crc_apb_if)
|
||||
);
|
||||
apb4_if_bridge u_tmr_apb_bridge (
|
||||
.apb_pure(u_tmr_apb_pure_if),
|
||||
.timed (u_tmr_apb_if)
|
||||
);
|
||||
`ifdef IP_MDD
|
||||
assign u_user_ip_apb_if.paddr = u_user_ip_apb_pure_if.paddr;
|
||||
assign u_user_ip_apb_if.pprot = u_user_ip_apb_pure_if.pprot;
|
||||
assign u_user_ip_apb_if.psel = u_user_ip_apb_pure_if.psel;
|
||||
assign u_user_ip_apb_if.penable = u_user_ip_apb_pure_if.penable;
|
||||
assign u_user_ip_apb_if.pwrite = u_user_ip_apb_pure_if.pwrite;
|
||||
assign u_user_ip_apb_if.pwdata = u_user_ip_apb_pure_if.pwdata;
|
||||
assign u_user_ip_apb_if.pstrb = u_user_ip_apb_pure_if.pstrb;
|
||||
assign u_user_ip_apb_pure_if.pready = u_user_ip_apb_if.pready;
|
||||
assign u_user_ip_apb_pure_if.prdata = u_user_ip_apb_if.prdata;
|
||||
assign u_user_ip_apb_pure_if.pslverr = u_user_ip_apb_if.pslverr;
|
||||
apb4_if_bridge u_user_ip_apb_bridge (
|
||||
.apb_pure(u_user_ip_apb_pure_if),
|
||||
.timed (u_user_ip_apb_if)
|
||||
);
|
||||
`endif
|
||||
|
||||
// verilog_format: off
|
||||
|
||||
@@ -28,12 +28,7 @@ module retrosoc (
|
||||
`ifdef HAVE_SRAM_IF
|
||||
ram_if.master ram,
|
||||
`endif
|
||||
output logic [31:0] gpio_oe_o,
|
||||
output logic [31:0] gpio_cs_o,
|
||||
output logic [31:0] gpio_pu_o,
|
||||
output logic [31:0] gpio_pd_o,
|
||||
output logic [31:0] gpio_do_o,
|
||||
input logic [31:0] gpio_di_i,
|
||||
gpio_if.soc_pad gpio,
|
||||
uart_if.dut uart0,
|
||||
xpi_if.dut xpi,
|
||||
sdram_if.dut sdram
|
||||
@@ -73,6 +68,11 @@ module retrosoc (
|
||||
logic [ 3:0] s_bus_fault_wstrb;
|
||||
logic s_bus_fault_reserved;
|
||||
|
||||
gpio_pad_bridge u_gpio_pad_bridge (
|
||||
.inner(u_gpio_if),
|
||||
.outer(gpio)
|
||||
);
|
||||
|
||||
`ifdef CORE_MDD
|
||||
assign u_sysctrl_if.core_sel_i = core_sel_i;
|
||||
`else
|
||||
@@ -122,12 +122,6 @@ module retrosoc (
|
||||
// | 30 | opipsram_dat7_io_pad | __NONE_FUNC__ |
|
||||
// | 31 | opipsram_dqs_o_pad | __NONE_FUNC__ |
|
||||
// =====================================================
|
||||
assign gpio_oe_o = u_gpio_if.oe_o;
|
||||
assign gpio_cs_o = u_gpio_if.cs_o;
|
||||
assign gpio_pu_o = u_gpio_if.pu_o;
|
||||
assign gpio_pd_o = u_gpio_if.pd_o;
|
||||
assign gpio_do_o = u_gpio_if.do_o;
|
||||
assign u_gpio_if.di_i = gpio_di_i;
|
||||
// GPIO0 FUNC0
|
||||
// pad0
|
||||
assign u_uart1_if.rx_i = u_gpio_if.di_i[0];
|
||||
|
||||
@@ -5,135 +5,15 @@
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
// NOTE: need to focus on the port dir
|
||||
|
||||
`include "gpio_define.svh"
|
||||
`include "mdd_config.svh"
|
||||
|
||||
module retrosoc_asic (
|
||||
inout extclk_i_pad,
|
||||
inout audclk_i_pad,
|
||||
inout ext_rst_n_i_pad,
|
||||
`ifdef HAVE_PLL
|
||||
input xi_i_pad,
|
||||
output xo_o_pad,
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
inout core_sel_0_i_pad,
|
||||
inout core_sel_1_i_pad,
|
||||
inout core_sel_2_i_pad,
|
||||
inout core_sel_3_i_pad,
|
||||
inout core_sel_4_i_pad,
|
||||
`endif
|
||||
`ifdef IP_MDD
|
||||
inout user_gpio_0_io_pad,
|
||||
inout user_gpio_1_io_pad,
|
||||
inout user_gpio_2_io_pad,
|
||||
inout user_gpio_3_io_pad,
|
||||
inout user_gpio_4_io_pad,
|
||||
inout user_gpio_5_io_pad,
|
||||
inout user_gpio_6_io_pad,
|
||||
inout user_gpio_7_io_pad,
|
||||
inout user_gpio_8_io_pad,
|
||||
inout user_gpio_9_io_pad,
|
||||
inout user_gpio_10_io_pad,
|
||||
inout user_gpio_11_io_pad,
|
||||
inout user_gpio_12_io_pad,
|
||||
inout user_gpio_13_io_pad,
|
||||
inout user_gpio_14_io_pad,
|
||||
inout user_gpio_15_io_pad,
|
||||
`endif
|
||||
// gpio
|
||||
inout gpio_0_io_pad,
|
||||
inout gpio_1_io_pad,
|
||||
inout gpio_2_io_pad,
|
||||
inout gpio_3_io_pad,
|
||||
inout gpio_4_io_pad,
|
||||
inout gpio_5_io_pad,
|
||||
inout gpio_6_io_pad,
|
||||
inout gpio_7_io_pad,
|
||||
inout gpio_8_io_pad,
|
||||
inout gpio_9_io_pad,
|
||||
inout gpio_10_io_pad,
|
||||
inout gpio_11_io_pad,
|
||||
inout gpio_12_io_pad,
|
||||
inout gpio_13_io_pad,
|
||||
inout gpio_14_io_pad,
|
||||
inout gpio_15_io_pad,
|
||||
inout gpio_16_io_pad,
|
||||
inout gpio_17_io_pad,
|
||||
inout gpio_18_io_pad,
|
||||
inout gpio_19_io_pad,
|
||||
inout gpio_20_io_pad,
|
||||
inout gpio_21_io_pad,
|
||||
inout gpio_22_io_pad,
|
||||
inout gpio_23_io_pad,
|
||||
inout gpio_24_io_pad,
|
||||
inout gpio_25_io_pad,
|
||||
inout gpio_26_io_pad,
|
||||
inout gpio_27_io_pad,
|
||||
inout gpio_28_io_pad,
|
||||
inout gpio_29_io_pad,
|
||||
inout gpio_30_io_pad,
|
||||
inout gpio_31_io_pad,
|
||||
// uart
|
||||
output uart0_tx_o_pad,
|
||||
inout uart0_rx_i_pad,
|
||||
// xpi
|
||||
output xpi_sck_o_pad,
|
||||
output xpi_nss0_o_pad,
|
||||
output xpi_nss1_o_pad,
|
||||
output xpi_nss2_o_pad,
|
||||
output xpi_nss3_o_pad,
|
||||
inout xpi_dat0_io_pad,
|
||||
inout xpi_dat1_io_pad,
|
||||
inout xpi_dat2_io_pad,
|
||||
inout xpi_dat3_io_pad,
|
||||
// sdram
|
||||
output sdram_clk_o_pad,
|
||||
output sdram_cke_o_pad,
|
||||
output sdram_cs_n_o_pad,
|
||||
output sdram_ras_n_o_pad,
|
||||
output sdram_cas_n_o_pad,
|
||||
output sdram_we_n_o_pad,
|
||||
output sdram_ba0_o_pad,
|
||||
output sdram_ba1_o_pad,
|
||||
output sdram_addr0_o_pad,
|
||||
output sdram_addr1_o_pad,
|
||||
output sdram_addr2_o_pad,
|
||||
output sdram_addr3_o_pad,
|
||||
output sdram_addr4_o_pad,
|
||||
output sdram_addr5_o_pad,
|
||||
output sdram_addr6_o_pad,
|
||||
output sdram_addr7_o_pad,
|
||||
output sdram_addr8_o_pad,
|
||||
output sdram_addr9_o_pad,
|
||||
output sdram_addr10_o_pad,
|
||||
output sdram_addr11_o_pad,
|
||||
output sdram_addr12_o_pad,
|
||||
output sdram_dqm0_o_pad,
|
||||
output sdram_dqm1_o_pad,
|
||||
inout sdram_dq0_io_pad,
|
||||
inout sdram_dq1_io_pad,
|
||||
inout sdram_dq2_io_pad,
|
||||
inout sdram_dq3_io_pad,
|
||||
inout sdram_dq4_io_pad,
|
||||
inout sdram_dq5_io_pad,
|
||||
inout sdram_dq6_io_pad,
|
||||
inout sdram_dq7_io_pad,
|
||||
inout sdram_dq8_io_pad,
|
||||
inout sdram_dq9_io_pad,
|
||||
inout sdram_dq10_io_pad,
|
||||
inout sdram_dq11_io_pad,
|
||||
inout sdram_dq12_io_pad,
|
||||
inout sdram_dq13_io_pad,
|
||||
inout sdram_dq14_io_pad,
|
||||
inout sdram_dq15_io_pad
|
||||
`include "retrosoc_asic_ports.svh"
|
||||
);
|
||||
// clk&rst
|
||||
logic s_ext_clk;
|
||||
logic s_aud_clk;
|
||||
logic s_sys_clkdiv4;
|
||||
@@ -144,7 +24,6 @@ module retrosoc_asic (
|
||||
logic s_ext_rst_n;
|
||||
logic s_sys_rst_n;
|
||||
logic s_aud_rst_n;
|
||||
logic s_tmr_capch;
|
||||
|
||||
`ifdef CORE_MDD
|
||||
logic [`USER_CORESEL_WIDTH-1:0] s_core_sel;
|
||||
@@ -158,140 +37,14 @@ module retrosoc_asic (
|
||||
ram_if u_ram_if ();
|
||||
`endif
|
||||
|
||||
// verilog_format: off
|
||||
logic [31:0] s_gpio_oe;
|
||||
logic [31:0] s_gpio_cs;
|
||||
logic [31:0] s_gpio_pu;
|
||||
logic [31:0] s_gpio_pd;
|
||||
logic [31:0] s_gpio_do;
|
||||
logic [31:0] s_gpio_di;
|
||||
gpio_if u_gpio_if ();
|
||||
uart_if u_uart0_if ();
|
||||
xpi_if u_xpi_if ();
|
||||
sdram_if u_sdram_if ();
|
||||
pll_ctrl_if u_pll_ctrl_if ();
|
||||
|
||||
`include "retrosoc_asic_pad_bindings.svh"
|
||||
|
||||
tc_io_tri_pad u_extclk_i_pad (.pad(extclk_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_ext_clk));
|
||||
tc_io_tri_pad u_audclk_i_pad (.pad(audclk_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_aud_clk));
|
||||
tc_io_tri_schmitt_pad u_ext_rst_n_i_pad (.pad(ext_rst_n_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_ext_rst_n));
|
||||
`ifdef HAVE_PLL
|
||||
tc_io_xtl_pad u_xtal_io_pad (.xi_pad(xi_i_pad), .xo_pad(xo_o_pad), .en(1'b1), .clk(s_xtal_io));
|
||||
`endif
|
||||
`ifdef CORE_MDD
|
||||
tc_io_tri_pad u_core_sel_0_i_pad (.pad(core_sel_0_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_core_sel[0]));
|
||||
tc_io_tri_pad u_core_sel_1_i_pad (.pad(core_sel_1_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_core_sel[1]));
|
||||
tc_io_tri_pad u_core_sel_2_i_pad (.pad(core_sel_2_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_core_sel[2]));
|
||||
tc_io_tri_pad u_core_sel_3_i_pad (.pad(core_sel_3_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_core_sel[3]));
|
||||
tc_io_tri_pad u_core_sel_4_i_pad (.pad(core_sel_4_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(s_core_sel[4]));
|
||||
`endif
|
||||
`ifdef IP_MDD
|
||||
tc_io_tri_full_pad u_user_gpio_0_io_pad (.pad(user_gpio_0_io_pad), .c2p(u_user_gpio_if.do_o[0]), .c2p_en(u_user_gpio_if.oe_o[0]), .p2c(u_user_gpio_if.di_i[0]), .cs(u_user_gpio_if.cs_o[0]), .pu(u_user_gpio_if.pu_o[0]), .pd(u_user_gpio_if.pd_o[0]));
|
||||
tc_io_tri_full_pad u_user_gpio_1_io_pad (.pad(user_gpio_1_io_pad), .c2p(u_user_gpio_if.do_o[1]), .c2p_en(u_user_gpio_if.oe_o[1]), .p2c(u_user_gpio_if.di_i[1]), .cs(u_user_gpio_if.cs_o[1]), .pu(u_user_gpio_if.pu_o[1]), .pd(u_user_gpio_if.pd_o[1]));
|
||||
tc_io_tri_full_pad u_user_gpio_2_io_pad (.pad(user_gpio_2_io_pad), .c2p(u_user_gpio_if.do_o[2]), .c2p_en(u_user_gpio_if.oe_o[2]), .p2c(u_user_gpio_if.di_i[2]), .cs(u_user_gpio_if.cs_o[2]), .pu(u_user_gpio_if.pu_o[2]), .pd(u_user_gpio_if.pd_o[2]));
|
||||
tc_io_tri_full_pad u_user_gpio_3_io_pad (.pad(user_gpio_3_io_pad), .c2p(u_user_gpio_if.do_o[3]), .c2p_en(u_user_gpio_if.oe_o[3]), .p2c(u_user_gpio_if.di_i[3]), .cs(u_user_gpio_if.cs_o[3]), .pu(u_user_gpio_if.pu_o[3]), .pd(u_user_gpio_if.pd_o[3]));
|
||||
tc_io_tri_full_pad u_user_gpio_4_io_pad (.pad(user_gpio_4_io_pad), .c2p(u_user_gpio_if.do_o[4]), .c2p_en(u_user_gpio_if.oe_o[4]), .p2c(u_user_gpio_if.di_i[4]), .cs(u_user_gpio_if.cs_o[4]), .pu(u_user_gpio_if.pu_o[4]), .pd(u_user_gpio_if.pd_o[4]));
|
||||
tc_io_tri_full_pad u_user_gpio_5_io_pad (.pad(user_gpio_5_io_pad), .c2p(u_user_gpio_if.do_o[5]), .c2p_en(u_user_gpio_if.oe_o[5]), .p2c(u_user_gpio_if.di_i[5]), .cs(u_user_gpio_if.cs_o[5]), .pu(u_user_gpio_if.pu_o[5]), .pd(u_user_gpio_if.pd_o[5]));
|
||||
tc_io_tri_full_pad u_user_gpio_6_io_pad (.pad(user_gpio_6_io_pad), .c2p(u_user_gpio_if.do_o[6]), .c2p_en(u_user_gpio_if.oe_o[6]), .p2c(u_user_gpio_if.di_i[6]), .cs(u_user_gpio_if.cs_o[6]), .pu(u_user_gpio_if.pu_o[6]), .pd(u_user_gpio_if.pd_o[6]));
|
||||
tc_io_tri_full_pad u_user_gpio_7_io_pad (.pad(user_gpio_7_io_pad), .c2p(u_user_gpio_if.do_o[7]), .c2p_en(u_user_gpio_if.oe_o[7]), .p2c(u_user_gpio_if.di_i[7]), .cs(u_user_gpio_if.cs_o[7]), .pu(u_user_gpio_if.pu_o[7]), .pd(u_user_gpio_if.pd_o[7]));
|
||||
tc_io_tri_full_pad u_user_gpio_8_io_pad (.pad(user_gpio_8_io_pad), .c2p(u_user_gpio_if.do_o[8]), .c2p_en(u_user_gpio_if.oe_o[8]), .p2c(u_user_gpio_if.di_i[8]), .cs(u_user_gpio_if.cs_o[8]), .pu(u_user_gpio_if.pu_o[8]), .pd(u_user_gpio_if.pd_o[8]));
|
||||
tc_io_tri_full_pad u_user_gpio_9_io_pad (.pad(user_gpio_9_io_pad), .c2p(u_user_gpio_if.do_o[9]), .c2p_en(u_user_gpio_if.oe_o[9]), .p2c(u_user_gpio_if.di_i[9]), .cs(u_user_gpio_if.cs_o[9]), .pu(u_user_gpio_if.pu_o[9]), .pd(u_user_gpio_if.pd_o[9]));
|
||||
tc_io_tri_full_pad u_user_gpio_10_io_pad (.pad(user_gpio_10_io_pad), .c2p(u_user_gpio_if.do_o[10]), .c2p_en(u_user_gpio_if.oe_o[10]), .p2c(u_user_gpio_if.di_i[10]), .cs(u_user_gpio_if.cs_o[10]), .pu(u_user_gpio_if.pu_o[10]), .pd(u_user_gpio_if.pd_o[10]));
|
||||
tc_io_tri_full_pad u_user_gpio_11_io_pad (.pad(user_gpio_11_io_pad), .c2p(u_user_gpio_if.do_o[11]), .c2p_en(u_user_gpio_if.oe_o[11]), .p2c(u_user_gpio_if.di_i[11]), .cs(u_user_gpio_if.cs_o[11]), .pu(u_user_gpio_if.pu_o[11]), .pd(u_user_gpio_if.pd_o[11]));
|
||||
tc_io_tri_full_pad u_user_gpio_12_io_pad (.pad(user_gpio_12_io_pad), .c2p(u_user_gpio_if.do_o[12]), .c2p_en(u_user_gpio_if.oe_o[12]), .p2c(u_user_gpio_if.di_i[12]), .cs(u_user_gpio_if.cs_o[12]), .pu(u_user_gpio_if.pu_o[12]), .pd(u_user_gpio_if.pd_o[12]));
|
||||
tc_io_tri_full_pad u_user_gpio_13_io_pad (.pad(user_gpio_13_io_pad), .c2p(u_user_gpio_if.do_o[13]), .c2p_en(u_user_gpio_if.oe_o[13]), .p2c(u_user_gpio_if.di_i[13]), .cs(u_user_gpio_if.cs_o[13]), .pu(u_user_gpio_if.pu_o[13]), .pd(u_user_gpio_if.pd_o[13]));
|
||||
tc_io_tri_full_pad u_user_gpio_14_io_pad (.pad(user_gpio_14_io_pad), .c2p(u_user_gpio_if.do_o[14]), .c2p_en(u_user_gpio_if.oe_o[14]), .p2c(u_user_gpio_if.di_i[14]), .cs(u_user_gpio_if.cs_o[14]), .pu(u_user_gpio_if.pu_o[14]), .pd(u_user_gpio_if.pd_o[14]));
|
||||
tc_io_tri_full_pad u_user_gpio_15_io_pad (.pad(user_gpio_15_io_pad), .c2p(u_user_gpio_if.do_o[15]), .c2p_en(u_user_gpio_if.oe_o[15]), .p2c(u_user_gpio_if.di_i[15]), .cs(u_user_gpio_if.cs_o[15]), .pu(u_user_gpio_if.pu_o[15]), .pd(u_user_gpio_if.pd_o[15]));
|
||||
`endif
|
||||
// gpio
|
||||
tc_io_tri_full_pad u_gpio_0_io_pad (.pad(gpio_0_io_pad), .c2p(s_gpio_do[0]), .c2p_en(s_gpio_oe[0]), .p2c(s_gpio_di[0]), .cs(s_gpio_cs[0]), .pu(s_gpio_pu[0]), .pd(s_gpio_pd[0]));
|
||||
tc_io_tri_full_pad u_gpio_1_io_pad (.pad(gpio_1_io_pad), .c2p(s_gpio_do[1]), .c2p_en(s_gpio_oe[1]), .p2c(s_gpio_di[1]), .cs(s_gpio_cs[1]), .pu(s_gpio_pu[1]), .pd(s_gpio_pd[1]));
|
||||
tc_io_tri_full_pad u_gpio_2_io_pad (.pad(gpio_2_io_pad), .c2p(s_gpio_do[2]), .c2p_en(s_gpio_oe[2]), .p2c(s_gpio_di[2]), .cs(s_gpio_cs[2]), .pu(s_gpio_pu[2]), .pd(s_gpio_pd[2]));
|
||||
tc_io_tri_full_pad u_gpio_3_io_pad (.pad(gpio_3_io_pad), .c2p(s_gpio_do[3]), .c2p_en(s_gpio_oe[3]), .p2c(s_gpio_di[3]), .cs(s_gpio_cs[3]), .pu(s_gpio_pu[3]), .pd(s_gpio_pd[3]));
|
||||
tc_io_tri_full_pad u_gpio_4_io_pad (.pad(gpio_4_io_pad), .c2p(s_gpio_do[4]), .c2p_en(s_gpio_oe[4]), .p2c(s_gpio_di[4]), .cs(s_gpio_cs[4]), .pu(s_gpio_pu[4]), .pd(s_gpio_pd[4]));
|
||||
tc_io_tri_full_pad u_gpio_5_io_pad (.pad(gpio_5_io_pad), .c2p(s_gpio_do[5]), .c2p_en(s_gpio_oe[5]), .p2c(s_gpio_di[5]), .cs(s_gpio_cs[5]), .pu(s_gpio_pu[5]), .pd(s_gpio_pd[5]));
|
||||
tc_io_tri_full_pad u_gpio_6_io_pad (.pad(gpio_6_io_pad), .c2p(s_gpio_do[6]), .c2p_en(s_gpio_oe[6]), .p2c(s_gpio_di[6]), .cs(s_gpio_cs[6]), .pu(s_gpio_pu[6]), .pd(s_gpio_pd[6]));
|
||||
tc_io_tri_full_pad u_gpio_7_io_pad (.pad(gpio_7_io_pad), .c2p(s_gpio_do[7]), .c2p_en(s_gpio_oe[7]), .p2c(s_gpio_di[7]), .cs(s_gpio_cs[7]), .pu(s_gpio_pu[7]), .pd(s_gpio_pd[7]));
|
||||
tc_io_tri_full_pad u_gpio_8_io_pad (.pad(gpio_8_io_pad), .c2p(s_gpio_do[8]), .c2p_en(s_gpio_oe[8]), .p2c(s_gpio_di[8]), .cs(s_gpio_cs[8]), .pu(s_gpio_pu[8]), .pd(s_gpio_pd[8]));
|
||||
tc_io_tri_full_pad u_gpio_9_io_pad (.pad(gpio_9_io_pad), .c2p(s_gpio_do[9]), .c2p_en(s_gpio_oe[9]), .p2c(s_gpio_di[9]), .cs(s_gpio_cs[9]), .pu(s_gpio_pu[9]), .pd(s_gpio_pd[9]));
|
||||
tc_io_tri_full_pad u_gpio_10_io_pad (.pad(gpio_10_io_pad), .c2p(s_gpio_do[10]), .c2p_en(s_gpio_oe[10]), .p2c(s_gpio_di[10]), .cs(s_gpio_cs[10]), .pu(s_gpio_pu[10]), .pd(s_gpio_pd[10]));
|
||||
tc_io_tri_full_pad u_gpio_11_io_pad (.pad(gpio_11_io_pad), .c2p(s_gpio_do[11]), .c2p_en(s_gpio_oe[11]), .p2c(s_gpio_di[11]), .cs(s_gpio_cs[11]), .pu(s_gpio_pu[11]), .pd(s_gpio_pd[11]));
|
||||
tc_io_tri_full_pad u_gpio_12_io_pad (.pad(gpio_12_io_pad), .c2p(s_gpio_do[12]), .c2p_en(s_gpio_oe[12]), .p2c(s_gpio_di[12]), .cs(s_gpio_cs[12]), .pu(s_gpio_pu[12]), .pd(s_gpio_pd[12]));
|
||||
tc_io_tri_full_pad u_gpio_13_io_pad (.pad(gpio_13_io_pad), .c2p(s_gpio_do[13]), .c2p_en(s_gpio_oe[13]), .p2c(s_gpio_di[13]), .cs(s_gpio_cs[13]), .pu(s_gpio_pu[13]), .pd(s_gpio_pd[13]));
|
||||
tc_io_tri_full_pad u_gpio_14_io_pad (.pad(gpio_14_io_pad), .c2p(s_gpio_do[14]), .c2p_en(s_gpio_oe[14]), .p2c(s_gpio_di[14]), .cs(s_gpio_cs[14]), .pu(s_gpio_pu[14]), .pd(s_gpio_pd[14]));
|
||||
tc_io_tri_full_pad u_gpio_15_io_pad (.pad(gpio_15_io_pad), .c2p(s_gpio_do[15]), .c2p_en(s_gpio_oe[15]), .p2c(s_gpio_di[15]), .cs(s_gpio_cs[15]), .pu(s_gpio_pu[15]), .pd(s_gpio_pd[15]));
|
||||
tc_io_tri_full_pad u_gpio_16_io_pad (.pad(gpio_16_io_pad), .c2p(s_gpio_do[16]), .c2p_en(s_gpio_oe[16]), .p2c(s_gpio_di[16]), .cs(s_gpio_cs[16]), .pu(s_gpio_pu[16]), .pd(s_gpio_pd[16]));
|
||||
tc_io_tri_full_pad u_gpio_17_io_pad (.pad(gpio_17_io_pad), .c2p(s_gpio_do[17]), .c2p_en(s_gpio_oe[17]), .p2c(s_gpio_di[17]), .cs(s_gpio_cs[17]), .pu(s_gpio_pu[17]), .pd(s_gpio_pd[17]));
|
||||
tc_io_tri_full_pad u_gpio_18_io_pad (.pad(gpio_18_io_pad), .c2p(s_gpio_do[18]), .c2p_en(s_gpio_oe[18]), .p2c(s_gpio_di[18]), .cs(s_gpio_cs[18]), .pu(s_gpio_pu[18]), .pd(s_gpio_pd[18]));
|
||||
tc_io_tri_full_pad u_gpio_19_io_pad (.pad(gpio_19_io_pad), .c2p(s_gpio_do[19]), .c2p_en(s_gpio_oe[19]), .p2c(s_gpio_di[19]), .cs(s_gpio_cs[19]), .pu(s_gpio_pu[19]), .pd(s_gpio_pd[19]));
|
||||
tc_io_tri_full_pad u_gpio_20_io_pad (.pad(gpio_20_io_pad), .c2p(s_gpio_do[20]), .c2p_en(s_gpio_oe[20]), .p2c(s_gpio_di[20]), .cs(s_gpio_cs[20]), .pu(s_gpio_pu[20]), .pd(s_gpio_pd[20]));
|
||||
tc_io_tri_full_pad u_gpio_21_io_pad (.pad(gpio_21_io_pad), .c2p(s_gpio_do[21]), .c2p_en(s_gpio_oe[21]), .p2c(s_gpio_di[21]), .cs(s_gpio_cs[21]), .pu(s_gpio_pu[21]), .pd(s_gpio_pd[21]));
|
||||
tc_io_tri_full_pad u_gpio_22_io_pad (.pad(gpio_22_io_pad), .c2p(s_gpio_do[22]), .c2p_en(s_gpio_oe[22]), .p2c(s_gpio_di[22]), .cs(s_gpio_cs[22]), .pu(s_gpio_pu[22]), .pd(s_gpio_pd[22]));
|
||||
tc_io_tri_full_pad u_gpio_23_io_pad (.pad(gpio_23_io_pad), .c2p(s_gpio_do[23]), .c2p_en(s_gpio_oe[23]), .p2c(s_gpio_di[23]), .cs(s_gpio_cs[23]), .pu(s_gpio_pu[23]), .pd(s_gpio_pd[23]));
|
||||
tc_io_tri_full_pad u_gpio_24_io_pad (.pad(gpio_24_io_pad), .c2p(s_gpio_do[24]), .c2p_en(s_gpio_oe[24]), .p2c(s_gpio_di[24]), .cs(s_gpio_cs[24]), .pu(s_gpio_pu[24]), .pd(s_gpio_pd[24]));
|
||||
tc_io_tri_full_pad u_gpio_25_io_pad (.pad(gpio_25_io_pad), .c2p(s_gpio_do[25]), .c2p_en(s_gpio_oe[25]), .p2c(s_gpio_di[25]), .cs(s_gpio_cs[25]), .pu(s_gpio_pu[25]), .pd(s_gpio_pd[25]));
|
||||
tc_io_tri_full_pad u_gpio_26_io_pad (.pad(gpio_26_io_pad), .c2p(s_gpio_do[26]), .c2p_en(s_gpio_oe[26]), .p2c(s_gpio_di[26]), .cs(s_gpio_cs[26]), .pu(s_gpio_pu[26]), .pd(s_gpio_pd[26]));
|
||||
tc_io_tri_full_pad u_gpio_27_io_pad (.pad(gpio_27_io_pad), .c2p(s_gpio_do[27]), .c2p_en(s_gpio_oe[27]), .p2c(s_gpio_di[27]), .cs(s_gpio_cs[27]), .pu(s_gpio_pu[27]), .pd(s_gpio_pd[27]));
|
||||
tc_io_tri_full_pad u_gpio_28_io_pad (.pad(gpio_28_io_pad), .c2p(s_gpio_do[28]), .c2p_en(s_gpio_oe[28]), .p2c(s_gpio_di[28]), .cs(s_gpio_cs[28]), .pu(s_gpio_pu[28]), .pd(s_gpio_pd[28]));
|
||||
tc_io_tri_full_pad u_gpio_29_io_pad (.pad(gpio_29_io_pad), .c2p(s_gpio_do[29]), .c2p_en(s_gpio_oe[29]), .p2c(s_gpio_di[29]), .cs(s_gpio_cs[29]), .pu(s_gpio_pu[29]), .pd(s_gpio_pd[29]));
|
||||
tc_io_tri_full_pad u_gpio_30_io_pad (.pad(gpio_30_io_pad), .c2p(s_gpio_do[30]), .c2p_en(s_gpio_oe[30]), .p2c(s_gpio_di[30]), .cs(s_gpio_cs[30]), .pu(s_gpio_pu[30]), .pd(s_gpio_pd[30]));
|
||||
tc_io_tri_full_pad u_gpio_31_io_pad (.pad(gpio_31_io_pad), .c2p(s_gpio_do[31]), .c2p_en(s_gpio_oe[31]), .p2c(s_gpio_di[31]), .cs(s_gpio_cs[31]), .pu(s_gpio_pu[31]), .pd(s_gpio_pd[31]));
|
||||
// uart0
|
||||
tc_io_tri_pad u_uart0_tx_o_pad (.pad(uart0_tx_o_pad), .c2p(u_uart0_if.tx_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_uart0_rx_i_pad (.pad(uart0_rx_i_pad), .c2p(1'b0), .c2p_en(1'b0), .p2c(u_uart0_if.rx_i));
|
||||
// xpi
|
||||
tc_io_tri_pad u_xpi_sck_o_pad (.pad(xpi_sck_o_pad), .c2p(u_xpi_if.sck_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_xpi_nss0_o_pad (.pad(xpi_nss0_o_pad), .c2p(u_xpi_if.nss_o[0]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_xpi_nss1_o_pad (.pad(xpi_nss1_o_pad), .c2p(u_xpi_if.nss_o[1]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_xpi_nss2_o_pad (.pad(xpi_nss2_o_pad), .c2p(u_xpi_if.nss_o[2]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_xpi_nss3_o_pad (.pad(xpi_nss3_o_pad), .c2p(u_xpi_if.nss_o[3]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_xpi_dat0_io_pad (.pad(xpi_dat0_io_pad), .c2p(u_xpi_if.io_do_o[0]), .c2p_en(u_xpi_if.io_oe_o[0]), .p2c(u_xpi_if.io_di_i[0]));
|
||||
tc_io_tri_pad u_xpi_dat1_io_pad (.pad(xpi_dat1_io_pad), .c2p(u_xpi_if.io_do_o[1]), .c2p_en(u_xpi_if.io_oe_o[1]), .p2c(u_xpi_if.io_di_i[1]));
|
||||
tc_io_tri_pad u_xpi_dat2_io_pad (.pad(xpi_dat2_io_pad), .c2p(u_xpi_if.io_do_o[2]), .c2p_en(u_xpi_if.io_oe_o[2]), .p2c(u_xpi_if.io_di_i[2]));
|
||||
tc_io_tri_pad u_xpi_dat3_io_pad (.pad(xpi_dat3_io_pad), .c2p(u_xpi_if.io_do_o[3]), .c2p_en(u_xpi_if.io_oe_o[3]), .p2c(u_xpi_if.io_di_i[3]));
|
||||
// sdram
|
||||
tc_io_tri_pad u_sdram_clk_o_pad (.pad(sdram_clk_o_pad), .c2p(u_sdram_if.clk_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_cke_o_pad (.pad(sdram_cke_o_pad), .c2p(u_sdram_if.cke_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_cs_n_o_pad (.pad(sdram_cs_n_o_pad), .c2p(u_sdram_if.cs_n_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_ras_n_o_pad (.pad(sdram_ras_n_o_pad), .c2p(u_sdram_if.ras_n_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_cas_n_o_pad (.pad(sdram_cas_n_o_pad), .c2p(u_sdram_if.cas_n_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_we_n_o_pad (.pad(sdram_we_n_o_pad), .c2p(u_sdram_if.we_n_o), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_ba0_o_pad (.pad(sdram_ba0_o_pad), .c2p(u_sdram_if.ba_o[0]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_ba1_o_pad (.pad(sdram_ba1_o_pad), .c2p(u_sdram_if.ba_o[1]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr0_o_pad (.pad(sdram_addr0_o_pad), .c2p(u_sdram_if.addr_o[0]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr1_o_pad (.pad(sdram_addr1_o_pad), .c2p(u_sdram_if.addr_o[1]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr2_o_pad (.pad(sdram_addr2_o_pad), .c2p(u_sdram_if.addr_o[2]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr3_o_pad (.pad(sdram_addr3_o_pad), .c2p(u_sdram_if.addr_o[3]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr4_o_pad (.pad(sdram_addr4_o_pad), .c2p(u_sdram_if.addr_o[4]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr5_o_pad (.pad(sdram_addr5_o_pad), .c2p(u_sdram_if.addr_o[5]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr6_o_pad (.pad(sdram_addr6_o_pad), .c2p(u_sdram_if.addr_o[6]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr7_o_pad (.pad(sdram_addr7_o_pad), .c2p(u_sdram_if.addr_o[7]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr8_o_pad (.pad(sdram_addr8_o_pad), .c2p(u_sdram_if.addr_o[8]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr9_o_pad (.pad(sdram_addr9_o_pad), .c2p(u_sdram_if.addr_o[9]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr10_o_pad (.pad(sdram_addr10_o_pad), .c2p(u_sdram_if.addr_o[10]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr11_o_pad (.pad(sdram_addr11_o_pad), .c2p(u_sdram_if.addr_o[11]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_addr12_o_pad (.pad(sdram_addr12_o_pad), .c2p(u_sdram_if.addr_o[12]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_dqm0_o_pad (.pad(sdram_dqm0_o_pad), .c2p(u_sdram_if.dqm_o[0]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_dqm1_o_pad (.pad(sdram_dqm1_o_pad), .c2p(u_sdram_if.dqm_o[1]), .c2p_en(1'b1), .p2c());
|
||||
tc_io_tri_pad u_sdram_dq0_io_pad (.pad(sdram_dq0_io_pad), .c2p(u_sdram_if.dq_o[0]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[0]));
|
||||
tc_io_tri_pad u_sdram_dq1_io_pad (.pad(sdram_dq1_io_pad), .c2p(u_sdram_if.dq_o[1]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[1]));
|
||||
tc_io_tri_pad u_sdram_dq2_io_pad (.pad(sdram_dq2_io_pad), .c2p(u_sdram_if.dq_o[2]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[2]));
|
||||
tc_io_tri_pad u_sdram_dq3_io_pad (.pad(sdram_dq3_io_pad), .c2p(u_sdram_if.dq_o[3]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[3]));
|
||||
tc_io_tri_pad u_sdram_dq4_io_pad (.pad(sdram_dq4_io_pad), .c2p(u_sdram_if.dq_o[4]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[4]));
|
||||
tc_io_tri_pad u_sdram_dq5_io_pad (.pad(sdram_dq5_io_pad), .c2p(u_sdram_if.dq_o[5]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[5]));
|
||||
tc_io_tri_pad u_sdram_dq6_io_pad (.pad(sdram_dq6_io_pad), .c2p(u_sdram_if.dq_o[6]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[6]));
|
||||
tc_io_tri_pad u_sdram_dq7_io_pad (.pad(sdram_dq7_io_pad), .c2p(u_sdram_if.dq_o[7]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[7]));
|
||||
tc_io_tri_pad u_sdram_dq8_io_pad (.pad(sdram_dq8_io_pad), .c2p(u_sdram_if.dq_o[8]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[8]));
|
||||
tc_io_tri_pad u_sdram_dq9_io_pad (.pad(sdram_dq9_io_pad), .c2p(u_sdram_if.dq_o[9]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[9]));
|
||||
tc_io_tri_pad u_sdram_dq10_io_pad (.pad(sdram_dq10_io_pad), .c2p(u_sdram_if.dq_o[10]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[10]));
|
||||
tc_io_tri_pad u_sdram_dq11_io_pad (.pad(sdram_dq11_io_pad), .c2p(u_sdram_if.dq_o[11]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[11]));
|
||||
tc_io_tri_pad u_sdram_dq12_io_pad (.pad(sdram_dq12_io_pad), .c2p(u_sdram_if.dq_o[12]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[12]));
|
||||
tc_io_tri_pad u_sdram_dq13_io_pad (.pad(sdram_dq13_io_pad), .c2p(u_sdram_if.dq_o[13]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[13]));
|
||||
tc_io_tri_pad u_sdram_dq14_io_pad (.pad(sdram_dq14_io_pad), .c2p(u_sdram_if.dq_o[14]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[14]));
|
||||
tc_io_tri_pad u_sdram_dq15_io_pad (.pad(sdram_dq15_io_pad), .c2p(u_sdram_if.dq_o[15]), .c2p_en(u_sdram_if.oe_o), .p2c(u_sdram_if.dq_i[15]));
|
||||
// verilog_format: on
|
||||
|
||||
|
||||
// clk buffer & mux
|
||||
rcu u_rcu (
|
||||
.ext_clk_i (s_ext_clk),
|
||||
.aud_clk_i (s_aud_clk),
|
||||
@@ -329,12 +82,7 @@ module retrosoc_asic (
|
||||
`ifdef HAVE_SRAM_IF
|
||||
.ram (u_ram_if),
|
||||
`endif
|
||||
.gpio_oe_o (s_gpio_oe),
|
||||
.gpio_cs_o (s_gpio_cs),
|
||||
.gpio_pu_o (s_gpio_pu),
|
||||
.gpio_pd_o (s_gpio_pd),
|
||||
.gpio_do_o (s_gpio_do),
|
||||
.gpio_di_i (s_gpio_di),
|
||||
.gpio (u_gpio_if),
|
||||
.uart0 (u_uart0_if),
|
||||
.xpi (u_xpi_if),
|
||||
.sdram (u_sdram_if)
|
||||
|
||||
+26
-4
@@ -7,19 +7,40 @@ import hashlib
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
from scripts.dependency_lock import DEFAULT_LOCK, lock_digest, load_lock # noqa: E402
|
||||
|
||||
TIMESTAMP_FORMAT = "%Y-%m-%d-%H-%M"
|
||||
TIMESTAMP_RE = re.compile(r"[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}")
|
||||
|
||||
|
||||
def slug(value: str) -> str:
|
||||
normalized = re.sub(r"[^a-z0-9]+", "-", value.lower()).strip("-")
|
||||
return normalized or "manual"
|
||||
|
||||
|
||||
def variant_id(profile: str, values: list[str], lock: Path) -> str:
|
||||
def normalize_timestamp(value: str | None) -> str:
|
||||
if value is None:
|
||||
return datetime.now().astimezone().strftime(TIMESTAMP_FORMAT)
|
||||
if TIMESTAMP_RE.fullmatch(value) is None:
|
||||
raise ValueError(f"timestamp must use {TIMESTAMP_FORMAT}")
|
||||
try:
|
||||
datetime.strptime(value, TIMESTAMP_FORMAT)
|
||||
except ValueError as error:
|
||||
raise ValueError(f"timestamp must use {TIMESTAMP_FORMAT}") from error
|
||||
return value
|
||||
|
||||
|
||||
def variant_id(
|
||||
profile: str,
|
||||
values: list[str],
|
||||
lock: Path,
|
||||
timestamp: str | None = None,
|
||||
) -> str:
|
||||
parsed: dict[str, str] = {}
|
||||
for item in values:
|
||||
name, separator, value = item.partition("=")
|
||||
@@ -34,18 +55,19 @@ def variant_id(profile: str, values: list[str], lock: Path) -> str:
|
||||
digest = hashlib.sha256(
|
||||
json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
||||
).hexdigest()[:12]
|
||||
return f"{slug(profile)}-{digest}"
|
||||
return f"{slug(profile)}-{normalize_timestamp(timestamp)}-{digest}"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Generate a deterministic build variant ID")
|
||||
parser = argparse.ArgumentParser(description="Generate a timestamped build variant ID")
|
||||
parser.add_argument("--lock", type=Path, default=DEFAULT_LOCK)
|
||||
parser.add_argument("--profile", default="manual")
|
||||
parser.add_argument("--value", action="append", default=[])
|
||||
parser.add_argument("--timestamp", help=f"creation time in {TIMESTAMP_FORMAT} format")
|
||||
args = parser.parse_args()
|
||||
load_lock(args.lock)
|
||||
try:
|
||||
print(variant_id(args.profile, args.value, args.lock))
|
||||
print(variant_id(args.profile, args.value, args.lock, args.timestamp))
|
||||
except ValueError as error:
|
||||
parser.error(str(error))
|
||||
return 0
|
||||
|
||||
+18
-4
@@ -3,8 +3,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -37,14 +39,25 @@ PR_PROFILES = (
|
||||
NIGHTLY_PROFILES = PR_PROFILES + ("configs/nightly/picorv32-rv32im-ihp130.mk",)
|
||||
|
||||
|
||||
def run_command(command: list[str], root: Path, capture_output: bool) -> str:
|
||||
def regression_environment() -> dict[str, str]:
|
||||
environment = os.environ.copy()
|
||||
environment.setdefault(
|
||||
"BUILD_TIMESTAMP", datetime.now().astimezone().strftime("%Y-%m-%d-%H-%M")
|
||||
)
|
||||
return environment
|
||||
|
||||
|
||||
def run_command(
|
||||
command: list[str], root: Path, capture_output: bool, environment: dict[str, str]
|
||||
) -> str:
|
||||
if not capture_output:
|
||||
subprocess.run(command, cwd=root, check=True)
|
||||
subprocess.run(command, cwd=root, env=environment, check=True)
|
||||
return ""
|
||||
|
||||
result = subprocess.run(
|
||||
command,
|
||||
cwd=root,
|
||||
env=environment,
|
||||
check=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
@@ -63,11 +76,12 @@ def main() -> int:
|
||||
args = parser.parse_args()
|
||||
commands = PR_COMMANDS if args.suite == "pr" else NIGHTLY_COMMANDS
|
||||
profiles = PR_PROFILES if args.suite == "pr" else NIGHTLY_PROFILES
|
||||
environment = regression_environment()
|
||||
for profile, values in commands:
|
||||
command = ["make", f"CONFIG={profile}", *values]
|
||||
print("+ " + " ".join(command), flush=True)
|
||||
if not args.dry_run:
|
||||
output = run_command(command, args.root, "firmware" in values)
|
||||
output = run_command(command, args.root, "firmware" in values, environment)
|
||||
warnings = self_owned_warnings(args.root, output)
|
||||
if warnings:
|
||||
print("self-owned C compiler warnings:", flush=True)
|
||||
@@ -82,7 +96,7 @@ def main() -> int:
|
||||
]
|
||||
print("+ " + " ".join(command), flush=True)
|
||||
if not args.dry_run:
|
||||
subprocess.run(command, cwd=args.root, check=True)
|
||||
subprocess.run(command, cwd=args.root, env=environment, check=True)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module apb4_if_bridge_tb;
|
||||
logic pclk = 1'b0;
|
||||
logic presetn = 1'b0;
|
||||
apb4_pure_if apb_pure ();
|
||||
apb4_if apb_timed (
|
||||
.pclk (pclk),
|
||||
.presetn(presetn)
|
||||
);
|
||||
|
||||
apb4_if_bridge u_apb4_if_bridge (
|
||||
.apb_pure(apb_pure),
|
||||
.timed (apb_timed)
|
||||
);
|
||||
|
||||
initial begin
|
||||
apb_pure.paddr = 32'h1234_5678;
|
||||
apb_pure.pprot = 3'b101;
|
||||
apb_pure.psel = 1'b1;
|
||||
apb_pure.penable = 1'b1;
|
||||
apb_pure.pwrite = 1'b1;
|
||||
apb_pure.pwdata = 32'hCAFE_BABE;
|
||||
apb_pure.pstrb = 4'b1101;
|
||||
apb_timed.pready = 1'b1;
|
||||
apb_timed.prdata = 32'hDEAD_BEEF;
|
||||
apb_timed.pslverr = 1'b0;
|
||||
#1;
|
||||
|
||||
if ({apb_timed.paddr, apb_timed.pprot, apb_timed.psel, apb_timed.penable,
|
||||
apb_timed.pwrite, apb_timed.pwdata, apb_timed.pstrb} !==
|
||||
{apb_pure.paddr, apb_pure.pprot, apb_pure.psel, apb_pure.penable,
|
||||
apb_pure.pwrite, apb_pure.pwdata, apb_pure.pstrb}) begin
|
||||
$fatal(1, "APB request fields did not cross the bridge");
|
||||
end
|
||||
if ({apb_pure.pready, apb_pure.prdata, apb_pure.pslverr} !==
|
||||
{apb_timed.pready, apb_timed.prdata, apb_timed.pslverr}) begin
|
||||
$fatal(1, "APB response fields did not cross the bridge");
|
||||
end
|
||||
|
||||
$display("apb4 interface bridge test passed");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,149 @@
|
||||
"""Tests for the canonical Mini SoC pin-map generator."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
GENERATOR = ROOT / "rtl/mini/pin_map/generate_pin_map.py"
|
||||
PIN_MAP = ROOT / "rtl/mini/pin_map/pin_map.json"
|
||||
FPGA_TOP = ROOT / "fpga/mini/retrosoc_top.sv"
|
||||
FPGA_XDC = ROOT / "fpga/mini/starrysky_v2.xdc"
|
||||
|
||||
|
||||
def generate(output_dir: Path) -> None:
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(GENERATOR),
|
||||
"--map",
|
||||
str(PIN_MAP),
|
||||
"--output-dir",
|
||||
str(output_dir),
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
def validate(map_path: Path) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
[sys.executable, str(GENERATOR), "--map", str(map_path), "--check"],
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
|
||||
def test_pin_map_generates_asic_and_platform_bindings(tmp_path: Path) -> None:
|
||||
generate(tmp_path)
|
||||
|
||||
ports = (tmp_path / "rtl/retrosoc_asic_ports.svh").read_text(encoding="utf-8")
|
||||
pads = (tmp_path / "rtl/retrosoc_asic_pad_bindings.svh").read_text(encoding="utf-8")
|
||||
fpga = (tmp_path / "rtl/retrosoc_asic_fpga_mini_bindings.svh").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
testbench = (tmp_path / "rtl/retrosoc_asic_tb_bindings.svh").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
assert "inout extclk_i_pad," in ports
|
||||
assert "input xi_i_pad," in ports
|
||||
assert "inout sdram_dq15_io_pad" in ports
|
||||
assert "u_gpio_31_io_pad" in pads
|
||||
assert "u_sdram_dq15_io_pad" in pads
|
||||
assert ".gpio_30_io_pad(gpio_io30)" in fpga
|
||||
assert ".gpio_15_io_pad()" in fpga
|
||||
assert ".gpio_24_io_pad(s_psram_dat1)" in testbench
|
||||
assert testbench.count(".gpio_24_io_pad(") == 1
|
||||
|
||||
|
||||
def test_pin_map_rejects_duplicate_pads(tmp_path: Path) -> None:
|
||||
document = json.loads(PIN_MAP.read_text(encoding="utf-8"))
|
||||
document["pads"][0]["ports"].append(
|
||||
{"name": "extclk_i_pad", "signal": "s_duplicate_clock"}
|
||||
)
|
||||
invalid_map = tmp_path / "duplicate.json"
|
||||
invalid_map.write_text(json.dumps(document), encoding="utf-8")
|
||||
|
||||
result = validate(invalid_map)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "pad names must be unique" in result.stderr
|
||||
|
||||
|
||||
def test_pin_map_rejects_non_object_port_entry(tmp_path: Path) -> None:
|
||||
document = json.loads(PIN_MAP.read_text(encoding="utf-8"))
|
||||
document["pads"][0]["ports"].append("extclk_i_pad")
|
||||
invalid_map = tmp_path / "invalid-port.json"
|
||||
invalid_map.write_text(json.dumps(document), encoding="utf-8")
|
||||
|
||||
result = validate(invalid_map)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "ports entries must be objects" in result.stderr
|
||||
|
||||
|
||||
def test_pin_map_rejects_unknown_profile_pad(tmp_path: Path) -> None:
|
||||
document = json.loads(PIN_MAP.read_text(encoding="utf-8"))
|
||||
document["profiles"]["tb"]["bindings"]["unknown_pad"] = "s_unknown"
|
||||
invalid_map = tmp_path / "unknown.json"
|
||||
invalid_map.write_text(json.dumps(document), encoding="utf-8")
|
||||
|
||||
result = validate(invalid_map)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "unknown pad" in result.stderr
|
||||
|
||||
|
||||
def test_fpga_constraints_reference_declared_top_ports() -> None:
|
||||
top_ports = set(re.findall(r"^\s*(?:input|output|inout)\s+([A-Za-z_][A-Za-z0-9_]*)", FPGA_TOP.read_text(encoding="utf-8"), re.MULTILINE))
|
||||
xdc_ports = set(re.findall(r"\[get_ports\s+([A-Za-z_][A-Za-z0-9_]*)\]", FPGA_XDC.read_text(encoding="utf-8")))
|
||||
|
||||
assert xdc_ports
|
||||
assert xdc_ports <= top_ports
|
||||
|
||||
|
||||
def test_apb4_interface_bridge(tmp_path: Path) -> None:
|
||||
iverilog = shutil.which("iverilog")
|
||||
sv2v = shutil.which("sv2v")
|
||||
vvp = shutil.which("vvp")
|
||||
if iverilog is None or sv2v is None or vvp is None:
|
||||
return
|
||||
source_list = tmp_path / "apb4_if_bridge.fl"
|
||||
source_list.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_pure_if.sv"),
|
||||
str(ROOT / "rtl/mini/top/apb4_if_bridge.sv"),
|
||||
str(ROOT / "tests/rtl/apb4_if_bridge_tb.sv"),
|
||||
"",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
converted = tmp_path / "apb4_if_bridge_tb.v"
|
||||
subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
|
||||
"-f",
|
||||
str(source_list),
|
||||
"--output",
|
||||
str(converted),
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
simulation = tmp_path / "apb4_if_bridge_tb"
|
||||
subprocess.run(
|
||||
[iverilog, "-g2012", "-s", "apb4_if_bridge_tb", "-o", str(simulation), str(converted)],
|
||||
check=True,
|
||||
)
|
||||
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
|
||||
|
||||
assert "apb4 interface bridge test passed" in result.stdout
|
||||
@@ -25,6 +25,7 @@ from scripts.analyze_warnings import normalize # noqa: E402
|
||||
from scripts.check_c_warnings import self_owned_warnings # noqa: E402
|
||||
from scripts.dependency_lock import LockError, load_lock # noqa: E402
|
||||
from scripts.install_toolchain import safe_extract # noqa: E402
|
||||
from scripts.regress import regression_environment # noqa: E402
|
||||
from scripts.setup_helpers import download_file, ensure_git_repo # noqa: E402
|
||||
|
||||
|
||||
@@ -190,7 +191,7 @@ def test_make_dry_run_and_validation_do_not_write_filelists() -> None:
|
||||
assert "Invalid SIMU='UNKNOWN'" in invalid.stderr
|
||||
|
||||
|
||||
def test_dependency_lock_and_config_key_are_deterministic(tmp_path: Path) -> None:
|
||||
def test_dependency_lock_and_config_key_include_a_fixed_timestamp(tmp_path: Path) -> None:
|
||||
lock = load_lock(ROOT / "config/dependencies.lock.json")
|
||||
assert lock["schema_version"] == 1
|
||||
assert len(lock["sources"]["mpw"]["revision"]) == 40
|
||||
@@ -202,6 +203,8 @@ def test_dependency_lock_and_config_key_are_deterministic(tmp_path: Path) -> Non
|
||||
str(ROOT / "config/dependencies.lock.json"),
|
||||
"--profile",
|
||||
"unit",
|
||||
"--timestamp",
|
||||
"2026-07-21-10-39",
|
||||
"--value",
|
||||
"CORE=HAZARD3",
|
||||
"--value",
|
||||
@@ -210,7 +213,15 @@ def test_dependency_lock_and_config_key_are_deterministic(tmp_path: Path) -> Non
|
||||
first = run(*command).stdout.strip()
|
||||
second = run(*command).stdout.strip()
|
||||
assert first == second
|
||||
assert first.startswith("unit-")
|
||||
assert re.fullmatch(r"unit-2026-07-21-10-39-[0-9a-f]{12}", first)
|
||||
|
||||
invalid_timestamp = subprocess.run(
|
||||
[*command, "--timestamp", "2026-07-21-10-99"],
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
assert invalid_timestamp.returncode != 0
|
||||
assert "timestamp must use %Y-%m-%d-%H-%M" in invalid_timestamp.stderr
|
||||
|
||||
broken = tmp_path / "broken.json"
|
||||
broken.write_text('{"schema_version": 1}\n', encoding="utf-8")
|
||||
@@ -222,6 +233,17 @@ def test_dependency_lock_and_config_key_are_deterministic(tmp_path: Path) -> Non
|
||||
raise AssertionError("invalid dependency lock was accepted")
|
||||
|
||||
|
||||
def test_regression_runner_uses_one_build_timestamp(monkeypatch) -> None:
|
||||
monkeypatch.setenv("BUILD_TIMESTAMP", "2026-07-21-10-39")
|
||||
assert regression_environment()["BUILD_TIMESTAMP"] == "2026-07-21-10-39"
|
||||
|
||||
monkeypatch.delenv("BUILD_TIMESTAMP")
|
||||
assert re.fullmatch(
|
||||
r"[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}",
|
||||
regression_environment()["BUILD_TIMESTAMP"],
|
||||
)
|
||||
|
||||
|
||||
def test_run_flow_writes_structured_result(tmp_path: Path) -> None:
|
||||
log = tmp_path / "flow.log"
|
||||
result = tmp_path / "result.json"
|
||||
|
||||
Reference in new issue
Block a user