feat: refactor tests for mailbox and environment validation

- Updated mailbox purpose tests to reflect new write order and sequence handling.
- Added tests to ensure Linux-ready values match LP contract and constants match Linux helper.
- Introduced tests to verify that offset changes do not hide stale Linux helpers.
- Enhanced environment tests to report current locked launcher and runtime versions.
- Added checks for SBT launcher presence in environment labels.
- Improved full diagram tests to validate storage geometry and RSA vector configurations.
- Expanded register tests to ensure crypto interrupt registers publish all events and lifecycle annotations preserve security boundaries.
- Modified script tools tests to include Vexii generation validation and updated workflow assertions.
This commit is contained in:
maksyuki committed 2026-09-30 10:51:04 +08:00
1 parent 9a634a9dc3
commit 3ac9e73ab9
48 files changed
+1937 -1359

No files matched your search

+1 -1
View File
@@ -28,7 +28,7 @@ on:
toolset:
description: Space-separated locked tools required by this suite
required: false
default: verilator sv2v iverilog yosys opensta openocd riscv_gnu
default: verilator sv2v iverilog yosys opensta openocd sbt riscv_gnu
type: string
full_flow_checks:
description: Check Yosys and OpenSTA environments before running the suite
+1 -1
View File
@@ -23,6 +23,6 @@ jobs:
profile: configs/ci/ihp130.mk
retention_days: 14
timeout_minutes: 60
toolset: verilator sv2v iverilog yosys sby bitwuzla riscv_gnu
toolset: verilator sv2v iverilog yosys sby bitwuzla sbt riscv_gnu
full_flow_checks: false
formal_checks: true
+4 -4
View File
@@ -474,9 +474,9 @@ crypto-p1-report: manifest
$(PYTHON) $(ROOT_PATH)/scripts/crypto_p1.py report --variant-root $(VARIANT_ROOT) \
--baseline-root $(CRYPTO_P0_BASELINE_ROOT) --lp-variant-root $(CRYPTO_P1_LP_ROOT) \
$(if $(CRYPTO_P1_CI_ROOT),--ci-variant-root $(CRYPTO_P1_CI_ROOT),)
CRYPTO_P1_ROOT ?= $(VARIANT_ROOT)
CRYPTO_P2_NETLIST_ROOT ?= $(VARIANT_ROOT)
CRYPTO_P2_STA_ROOT ?= $(VARIANT_ROOT)
CRYPTO_P1_ROOT ?= $(VARIANT_ROOT)
CRYPTO_P2_NETLIST_ROOT ?= $(VARIANT_ROOT)
CRYPTO_P2_STA_ROOT ?= $(VARIANT_ROOT)
CRYPTO_P2_PHYSICAL_ROOT ?= $(VARIANT_ROOT)
crypto-p2-synth: manifest
$(MAKE) CONFIG=$(ROOT_PATH)/configs/ci/ihp130.mk BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) \
@@ -1199,4 +1199,4 @@ regress-nightly:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite nightly $(if $(filter TINY,$(SOC)),--soc TINY)
sim-asm: asm
$(MAKE) SIM_FIRMWARE_NAME=$(ASM_FIRMWARE_NAME) sim
$(MAKE) SIM_FIRMWARE_NAME=$(ASM_FIRMWARE_NAME) sim
+1 -1
View File
@@ -14,4 +14,4 @@ $(APU_RELEASE_ASSETS_H): $(APU_P5_BUNDLE) $(APU_P7_MODEL) $(APU_P9_APUC) \
--kws-corpus $(CACHE_ROOT)/sources/apu-kws-pcm \
--output $@
$(SW_BUILD_DIR)/firmware: $(APU_RELEASE_ASSETS_H)
$(SW_BUILD_DIR)/firmware: $(APU_RELEASE_ASSETS_H)
+1 -1
View File
@@ -1,3 +1,3 @@
APP_SRCS += $(ROOT_PATH)/app/apps/hp_boot/main.c
APP_SRCS += $(ROOT_PATH)/app/apps/hp_boot/hp_boot_bundle.c
APP_INC_DIRS += $(ROOT_PATH)/app/apps/hp_boot
APP_INC_DIRS += $(ROOT_PATH)/app/apps/hp_boot
+1 -1
View File
@@ -19,4 +19,4 @@ LINK_TYPE := ld2_all_sram
SIM_SUCCESS_MARKER := SIM_TEST_PASS
RTL_SIM_TIMEOUT := 20000000
FIRMWARE_NAME := retrosoc_hp_boot
SIM_FIRMWARE_NAME := retrosoc_hp_boot
SIM_FIRMWARE_NAME := retrosoc_hp_boot
+4 -4
View File
@@ -384,10 +384,10 @@
"path": "xpack-openocd-0.12.0-1/bin"
},
"sbt": {
"version": "1.10.0",
"url": "https://github.com/sbt/sbt/releases/download/v1.10.0/sbt-1.10.0.tgz",
"sha256": "154b7de6c19207c73d0a304f901c8c4b6ead9a9c3a99a98a9d72ac19419d2640",
"archive": "sbt-1.10.0.tgz",
"version": "2.0.5",
"url": "https://github.com/sbt/sbt/releases/download/v2.0.5/sbt-2.0.5.tgz",
"sha256": "2a53c95403cb7fccd5da05d48cfe03ff4be573a3f3d0295a41963b109e756a18",
"archive": "sbt-2.0.5.tgz",
"path": "sbt/bin",
"download_timeout_seconds": 600,
"resume": true
+6 -6
View File
@@ -18,12 +18,12 @@ Regression Verilator firmware simulations override the profiles' manual
`bringup` default with `APP=ci_smoke`. The IHP130 PR simulation also uses the
32 KiB `ld2_all_sram` layout, the explicit Verilator `--fast-flash` backend,
and an 1800-second wall-clock budget. GF180, ICS55, and SKY130 use the common
`ld2_sdram` execution layout, the same fast-flash backend, and an 1800-second
budget for the GA2D acceptance workload while LP instruction traffic shares
the SDRAM target. The broad smoke therefore does not execute from the serial
PSRAM model. The full serial XPI and PSRAM path remains covered by the Icarus
assembly self-test and directed memory-model tests. This application verifies
UART output,
`ld2_sdram` execution layout, the same fast-flash backend, and a 3600-second
budget for the peripheral acceptance workload while LP instruction traffic
shares the SDRAM target. The broad smoke therefore does not execute from the
serial PSRAM model. The full serial XPI and PSRAM path remains covered by the
Icarus assembly self-test and directed memory-model tests. This application
verifies UART output,
archinfo APB readback, on-chip SRAM first/last-word and 8/16/32-bit access,
Fabric Monitor collection through the PCLK-to-HP APB path, truthful extension
capabilities, RNG integration, SDRAM 8/16/32-bit access in a reserved tail
+1 -1
View File
@@ -130,4 +130,4 @@ librelane-klayout: librelane-doctor
librelane-package: librelane-chip
$(FLOW_PYTHON) $(LIBRELANE_FLOW_ROOT)/scripts/package.py \
--root $(ROOT_PATH) --variant-root $(VARIANT_ROOT) \
--run-root $(LIBRELANE_RUN_ROOT) --output $(LIBRELANE_ARCHIVE)
--run-root $(LIBRELANE_RUN_ROOT) --output $(LIBRELANE_ARCHIVE)
+1 -1
View File
@@ -171,4 +171,4 @@ apu-block-clean:
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(APU_BLOCK_REPORT_DIR)
.PHONY: apu-block-filelist apu-block-synth apu-block-sta apu-block-report \
apu-block-evidence apu-block-clean
apu-block-evidence apu-block-clean
+1 -1
View File
@@ -176,4 +176,4 @@ sta-ga2d-block-clean:
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(GA2D_BLOCK_STA_DIR)
.PHONY: synth-ga2d-block synth-ga2d-block-clean netsim-ga2d-block netsim-ga2d-block-clean \
sta-ga2d-block sta-ga2d-block-clean
sta-ga2d-block sta-ga2d-block-clean
+100 -22
View File
@@ -10,13 +10,25 @@ from publications.implementation_reference import without_comments
BOOT_SOURCE = "app/apps/hp_boot/main.c"
READY_SOURCE = "app/ports/linux/rootfs-overlay/etc/init.d/S99retrosoc-hp"
BUNDLE_SOURCE = "app/apps/hp_boot/hp_boot_bundle.c"
INIT_SOURCE = "app/ports/linux/init"
READY_SOURCE = "app/ports/linux/hp_ready.c"
HAL_SOURCE = "crt/src/hal/hp_mailbox.c"
STATUS_SOURCE = "crt/include/retrosoc/core/status.h"
REGISTER_SOURCE = "rtl/ip/peripheral/hp_mailbox_define.svh"
MAILBOX_SOURCE = "rtl/ip/peripheral/apb4_hp_mailbox.sv"
MAP_SOURCE = "rtl/mini/address_map/memory_map.json"
SOURCES = {BOOT_SOURCE, READY_SOURCE, HAL_SOURCE, STATUS_SOURCE, REGISTER_SOURCE, MAILBOX_SOURCE, MAP_SOURCE}
SOURCES = {
BOOT_SOURCE,
BUNDLE_SOURCE,
INIT_SOURCE,
READY_SOURCE,
HAL_SOURCE,
STATUS_SOURCE,
REGISTER_SOURCE,
MAILBOX_SOURCE,
MAP_SOURCE,
}
NPU_DEFINES = ("RS_NPU_P5_ACCEPTANCE", "RS_NPU_P6_ACCEPTANCE")
@@ -29,8 +41,18 @@ def uint_constants(source: str) -> dict[str, int]:
r"^#define\s+(\w+)\s+UINT32_C\((0x[\da-fA-F]+|\d+)\)\s*$", source, re.M)}
def c_uint_literal(expression: str) -> int:
wrapper = re.fullmatch(r"UINT32_C\((0x[\da-fA-F]+|\d+)\)", expression.strip())
if wrapper:
return int(wrapper[1], 0)
literal = re.fullmatch(r"(0x[\da-fA-F]+|\d+)[uUlL]*", expression.strip())
if literal:
return int(literal[1], 0)
raise ValueError("Linux ready mailbox value expression changed")
def ready_mailbox(root: Path) -> list[dict]:
"""Resolve rootfs writes to register purposes, rather than positional labels."""
"""Resolve the Linux helper writes to register purposes and source order."""
hal = (root / HAL_SOURCE).read_text(encoding="utf-8")
rtl = (root / REGISTER_SOURCE).read_text(encoding="utf-8")
offsets = {name: int(value, 16) for name, value in re.findall(
@@ -63,27 +85,59 @@ def ready_mailbox(root: Path) -> list[dict]:
expected_values = [boot_constants[key] for key in (
"RS_HP_BOOT_READY_EVENT", "RS_HP_BOOT_READY_ARG", "RS_HP_BOOT_MAILBOX_READY_SEQUENCE")] + [1]
ready = (root / READY_SOURCE).read_text(encoding="utf-8")
writes = [(int(address, 0), int(value, 0)) for address, value in re.findall(
r"^\s*devmem\s+(0x[\da-fA-F]+)\s+32\s+(0x[\da-fA-F]+)\s*$", ready, re.M)]
expected = [(base + offsets[register], value)
for register, value in zip(registers, expected_values, strict=True)]
if writes != expected or sum(line.lstrip().startswith("devmem ") for line in ready.splitlines()) != len(writes):
mappings = re.findall(r"\bmmap\([^;]*,\s*(0x[\da-fA-F]+)\s*\);", ready)
if len(mappings) != 1 or int(mappings[0], 0) != base:
raise ValueError("Linux ready mailbox mapping changed")
writes = list(re.finditer(r"mailbox\[(\d+)\]\s*=\s*([^;]+);", ready))
if [match[1] for match in writes] != ["8", "9", "10", "11"]:
raise ValueError("Linux ready mailbox sequence changed")
message = 'echo "retroSoC HP Linux ready"'
if message not in ready or ready.index(message) > ready.index("devmem"):
raise ValueError("Linux ready message/publication order changed")
# A newly added responder invalidates the documented ready-only service gap.
shell_lines = [line.strip() for line in ready.splitlines()
if line.strip() and not line.lstrip().startswith("#")]
scaffold = ['case "$1" in', "start)", message, ";;", "esac"]
if [line for line in shell_lines if not line.startswith("devmem ")] != scaffold:
literal = r"(?:UINT32_C\((?:0x[\da-fA-F]+|\d+)\)|(?:0x[\da-fA-F]+|\d+)[uUlL]*)"
expressions = [match[2].strip() for match in writes]
event = re.fullmatch(
rf"\(\s*error\s*==\s*0U\s*\)\s*\?\s*({literal})\s*:\s*3U", expressions[0]
)
argument = re.fullmatch(
rf"\(\s*error\s*==\s*0U\s*\)\s*\?\s*({literal})\s*:\s*error", expressions[1]
)
direct = [re.fullmatch(literal, expression) for expression in expressions[2:]]
if event is None or argument is None or any(match is None for match in direct):
raise ValueError("Linux ready mailbox value expression changed")
actual_values = [
c_uint_literal(event[1]),
c_uint_literal(argument[1]),
*(c_uint_literal(match[0]) for match in direct if match is not None),
]
if actual_values != expected_values:
raise ValueError("Linux ready mailbox values differ from LP acceptance contract")
expected_addresses = [base + offsets[register] for register in registers]
actual_addresses = [base + (int(match[1]) * 4) for match in writes]
if actual_addresses != expected_addresses:
raise ValueError("Linux ready mailbox addresses differ from RTL register offsets")
message = '(void)puts("retroSoC HP Linux ready");'
fence = '__asm__ volatile("fence iorw, iorw" ::: "memory");'
if message not in ready or fence not in ready:
raise ValueError("Linux ready message/publication sequence changed")
ordered_positions = [
ready.index(message),
*(match.start() for match in writes[:3]),
ready.index(fence),
writes[3].start(),
]
if ordered_positions != sorted(ordered_positions):
raise ValueError("Linux ready message/publication sequence changed")
init = (root / INIT_SOURCE).read_text(encoding="utf-8")
init_lines = [line.strip() for line in init.splitlines() if line.strip()]
if not init_lines or init_lines[-1] != "exec /bin/hp-ready":
raise ValueError("Linux minimal init no longer terminates in the ready helper")
if not compact(ready).endswith("mailbox[11]=1U;for(;;){(void)pause();}}"):
raise ValueError("Linux ready-only service changed; review its acceptance coverage")
actual = list(zip(actual_addresses, actual_values, strict=True))
purposes = {"HP_EVENT": "Linux-ready event", "HP_ARG0": "Ready-state argument",
"HP_SEQUENCE": "Publication sequence", "HP_DOORBELL": "LP interrupt request"}
register_by_address = {base + offsets[register]: register for register in registers}
register_by_address = dict(zip(actual_addresses, registers, strict=True))
return [{"address": f"0x{address:08X}", "value": f"0x{value:08X}",
"register": register_by_address[address], "purpose": purposes[register_by_address[address]]}
for address, value in writes]
for address, value in actual]
def split_npu_conditions(body: str) -> tuple[str, list[tuple[str, str]]]:
@@ -222,10 +276,27 @@ def collect_boot_acceptance(root: Path, function_body: Callable[[str, str], str]
raise ValueError(f"HP boot {name} wait is no longer the reviewed bounded poll")
if not body.endswith("returnfalse;") or "while(" in body or "do{" in body:
raise ValueError(f"HP boot {name} wait termination changed")
wait_body = compact(function_body(source, "rs_hp_boot_wait_message"))
if ("if(message.sequence==sequence){return(message.code==code)&&(message.argument==argument);}" not in wait_body
or "if(rs_hp_mailbox_receive_from_hp(&message)!=RS_OK){returnfalse;}" not in wait_body):
bundle = (root / BUNDLE_SOURCE).read_text(encoding="utf-8")
expected_status = compact("""
if ((sequence > expected_sequence) || ((sequence != 0U) && (code == 3U))) {
return 2U;
}
if (sequence == expected_sequence) {
return ((code == expected_code) && (argument == expected_argument)) ? 1U : 2U;
}
return 0U;
""")
if compact(function_body(bundle, "rs_hp_boot_message_status")) != expected_status:
raise ValueError("HP boot mailbox token/error matching changed")
wait_body = compact(function_body(source, "rs_hp_boot_wait_message"))
for binding in (
"if(rs_hp_mailbox_receive_from_hp(&message)!=RS_OK){returnfalse;}",
"status=rs_hp_boot_message_status(message.code,message.argument,message.sequence,code,argument,sequence);",
"if(status==2U){printf(\"HP_PAYLOAD_FAILED:%u\\n\",(unsignedint)message.argument);returnfalse;}",
"if(status==1U){returntrue;}",
):
if binding not in wait_body:
raise ValueError("HP boot mailbox token/error matching changed")
main, gated = split_npu_conditions(function_body(source, "main"))
main = compact(main)
phases = (
@@ -257,7 +328,14 @@ def collect_boot_acceptance(root: Path, function_body: Callable[[str, str], str]
if position < 0:
raise ValueError(f"HP boot required phase or ordering changed: {phase}")
cursor = position + len(phase)
if (main.count("rs_test_finish(RS_TEST_PASSED,") != 1 or not main.endswith(phases[-1])
workload_branches = (
"if(header.workload==RS_HP_BOOT_WORKLOAD_SMOKE){",
"if(header.workload==RS_HP_BOOT_WORKLOAD_RTTHREAD){",
"if(header.workload==RS_HP_BOOT_WORKLOAD_LINUX){",
)
if any(main.count(branch) != 1 for branch in workload_branches):
raise ValueError("HP boot workload selection changed")
if (main.count("rs_test_finish(RS_TEST_PASSED,") != 3 or not main.endswith(phases[-1])
or re.findall(r"cache_clean_completed=(true|false);", main) != ["false", "true"]
or re.findall(r"s_hp_boot_ga2d_owned_by_hp=(true|false);", main) != ["true", "false"]):
raise ValueError("HP boot terminal pass or cache completion changed")
+102 -150
View File
@@ -5342,7 +5342,7 @@
},
{
"id": "aes",
"title": "AES engine\nkey schedule / modes",
"title": "AES SRAM engine\nkey schedule / modes",
"x": 0.0,
"y": 3.5,
"w": 4.0,
@@ -5369,18 +5369,18 @@
],
"sources": [
"rtl/ip/security/apb4_crypto.sv",
"rtl/ip/security/crypto_aes_engine.sv"
"rtl/ip/security/crypto_aes_sram_engine.sv"
],
"instance_source": {
"file": "rtl/ip/security/apb4_crypto.sv",
"name": "u_crypto_aes_engine",
"module": "crypto_aes_engine",
"declaration_file": "rtl/ip/security/crypto_aes_engine.sv"
}
"instance_source": {
"file": "rtl/ip/security/apb4_crypto.sv",
"name": "u_aes",
"module": "crypto_aes_sram_engine",
"declaration_file": "rtl/ip/security/crypto_aes_sram_engine.sv"
}
},
{
"id": "sha",
"title": "SHA-224 / SHA-256\nschedule / compression",
"title": "SHA SRAM engine\nschedule / compression",
"x": 6.3,
"y": 3.5,
"w": 4.0,
@@ -5401,18 +5401,18 @@
],
"sources": [
"rtl/ip/security/apb4_crypto.sv",
"rtl/ip/security/crypto_sha2_engine.sv"
"rtl/ip/security/crypto_sha2_sram_engine.sv"
],
"instance_source": {
"file": "rtl/ip/security/apb4_crypto.sv",
"name": "u_crypto_sha2_engine",
"module": "crypto_sha2_engine",
"declaration_file": "rtl/ip/security/crypto_sha2_engine.sv"
}
"instance_source": {
"file": "rtl/ip/security/apb4_crypto.sv",
"name": "u_sha",
"module": "crypto_sha2_sram_engine",
"declaration_file": "rtl/ip/security/crypto_sha2_sram_engine.sv"
}
},
{
"id": "rsa",
"title": "RSA Montgomery core\nprepare / exponentiation",
"title": "RSA SRAM core\nprepare / exponentiation",
"x": 12.6,
"y": 3.5,
"w": 4.0,
@@ -5425,22 +5425,22 @@
"side": "north"
},
{
"id": "p6",
"direction": "out",
"width": 2048,
"id": "p6",
"direction": "out",
"width": 32,
"side": "south"
}
],
"sources": [
"rtl/ip/security/apb4_crypto.sv",
"rtl/ip/security/crypto_rsa_core.sv"
"rtl/ip/security/crypto_rsa_sram_core.sv"
],
"instance_source": {
"file": "rtl/ip/security/apb4_crypto.sv",
"name": "u_crypto_rsa_core",
"module": "crypto_rsa_core",
"declaration_file": "rtl/ip/security/crypto_rsa_core.sv"
}
"instance_source": {
"file": "rtl/ip/security/apb4_crypto.sv",
"name": "u_rsa",
"module": "crypto_rsa_sram_core",
"declaration_file": "rtl/ip/security/crypto_rsa_sram_core.sv"
}
},
{
"id": "stream",
@@ -5488,16 +5488,16 @@
},
{
"id": "rsa_words",
"title": "APB operand / result\n2048-bit vectors",
"title": "APB storage portals\nresult / progress status",
"x": 12.6,
"y": 0.0,
"w": 4.0,
"h": 1.8,
"ports": [
{
"id": "p6",
"direction": "in",
"width": 2048,
"id": "p6",
"direction": "in",
"width": 32,
"side": "north"
}
],
@@ -5513,27 +5513,19 @@
"kind": "control",
"label": "START",
"style": "zigzag",
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".start_i(s_aes_start)"
}
],
"signals": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"scope": "apb4_crypto",
"symbol": "s_aes_start",
"bits": 1
}
],
"instance_ports": [
{
"node": "aes",
"port": "start_i",
"expression": "s_aes_start"
}
],
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".start_i(s_start[0])"
}
],
"instance_ports": [
{
"node": "aes",
"port": "start_i",
"expression": "s_start[0]"
}
],
"zigzag-dir": "horizontal"
},
{
@@ -5542,27 +5534,19 @@
"kind": "control",
"label": "START",
"style": "direct",
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".start_i(s_sha_start)"
}
],
"signals": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"scope": "apb4_crypto",
"symbol": "s_sha_start",
"bits": 1
}
],
"instance_ports": [
{
"node": "sha",
"port": "start_i",
"expression": "s_sha_start"
}
],
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".start_i(s_start[1])"
}
],
"instance_ports": [
{
"node": "sha",
"port": "start_i",
"expression": "s_start[1]"
}
],
"zigzag-dir": "horizontal"
},
{
@@ -5571,27 +5555,19 @@
"kind": "control",
"label": "START",
"style": "zigzag",
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".start_i(s_rsa_start)"
}
],
"signals": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"scope": "apb4_crypto",
"symbol": "s_rsa_start",
"bits": 1
}
],
"instance_ports": [
{
"node": "rsa",
"port": "start_i",
"expression": "s_rsa_start"
}
],
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".start_i(s_start[2])"
}
],
"instance_ports": [
{
"node": "rsa",
"port": "start_i",
"expression": "s_start[2]"
}
],
"zigzag-dir": "horizontal"
},
{
@@ -5600,27 +5576,19 @@
"kind": "data",
"label": "INPUT / 32",
"style": "direct",
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".input_data_i(s_aes_input_data)"
}
],
"signals": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"scope": "apb4_crypto",
"symbol": "s_aes_input_data",
"bits": 32
}
],
"instance_ports": [
{
"node": "aes",
"port": "input_data_i",
"expression": "s_aes_input_data"
}
],
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".input_data_i(s_aes_dma_active ? crypto_in_axis.tdata : s_wdata)"
}
],
"instance_ports": [
{
"node": "aes",
"port": "input_data_i",
"expression": "s_aes_dma_active ? crypto_in_axis.tdata : s_wdata"
}
],
"zigzag-dir": "horizontal"
},
{
@@ -5658,60 +5626,44 @@
"kind": "data",
"label": "INPUT / 32",
"style": "direct",
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".input_data_i(s_sha_input_data)"
}
],
"signals": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"scope": "apb4_crypto",
"symbol": "s_sha_input_data",
"bits": 32
}
],
"instance_ports": [
{
"node": "sha",
"port": "input_data_i",
"expression": "s_sha_input_data"
}
],
"zigzag-dir": "horizontal"
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".input_data_i(s_sha_dma_active ? crypto_in_axis.tdata : s_wdata)"
}
],
"instance_ports": [
{
"node": "sha",
"port": "input_data_i",
"expression": "s_sha_dma_active ? crypto_in_axis.tdata : s_wdata"
}
],
"zigzag-dir": "horizontal"
},
{
"from": "rsa.p6",
"to": "rsa_words.p6",
"kind": "data",
"label": "RESULT / 2048",
"label": "PROGRESS / 32",
"style": "direct",
"bindings": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"text": ".result_o(s_rsa_result)"
}
],
"signals": [
{
"file": "rtl/ip/security/apb4_crypto.sv",
"scope": "apb4_crypto",
"symbol": "s_rsa_result",
"bits": 2048
"text": ".progress_o(s_rsa_progress)"
}
],
"instance_ports": [
{
"node": "rsa",
"port": "result_o",
"expression": "s_rsa_result"
"port": "progress_o",
"expression": "s_rsa_progress"
}
],
"zigzag-dir": "horizontal"
}
],
"note": "AES and SHA consume PIO or selected stream words; RSA uses operand windows. Keys and operands reside in ordinary state and follow zeroize/abort rules. These are independent engines, not an invented descriptor queue or secure key store."
"note": "AES and SHA consume PIO or selected stream words. AES/SHA constants and work state plus RSA operands/results reside in the six private SRAM banks behind the wrapper's storage controller. The engines remain independently sequenced; no descriptor queue or readable secret-key aperture is implied."
},
"i2s": {
"nodes": [
+2 -2
View File
@@ -1969,7 +1969,7 @@
"section": "protocol",
"sources": [
"docs/ip/crypto.md",
"rtl/ip/security/crypto_sha2_engine.sv"
"rtl/ip/security/crypto_sha2_sram_engine.sv"
],
"note": "Digest word 0 is the most significant digest word. SHA-256 uses eight words; SHA-224 uses seven meaningful words and returns zero in word 7. This word significance differs from RSA limb significance.",
"bindings": [
@@ -2049,7 +2049,7 @@
"section": "protocol",
"sources": [
"docs/ip/crypto.md",
"rtl/ip/security/crypto_rsa_core.sv"
"rtl/ip/security/crypto_rsa_sram_core.sv"
],
"note": "64 little-endian 32-bit limbs; word 0 is least significant and word 63 is most significant. The middle 60 words are collapsed in this schematic. Public/private exponent rules and operand validity remain those of the RSA contract.",
"bindings": [
+25 -30
View File
@@ -421,30 +421,34 @@
"section": "functional",
"stores": [
{
"file": "rtl/ip/security/crypto_aes_engine.sv",
"instance": "u_input_fifo",
"file": "rtl/ip/security/crypto_clearable_fifo.sv",
"instance": "u_payload",
"parameters": {"Depth": 8},
"title": "AES input FIFO",
"depth": 8,
"bits": 37
},
{
"file": "rtl/ip/security/crypto_aes_engine.sv",
"instance": "u_output_fifo",
"file": "rtl/ip/security/crypto_clearable_fifo.sv",
"instance": "u_payload",
"parameters": {"Depth": 8},
"title": "AES output FIFO",
"depth": 8,
"bits": 37
},
{
"file": "rtl/ip/security/crypto_sha2_engine.sv",
"instance": "u_input_fifo",
"file": "rtl/ip/security/crypto_clearable_fifo.sv",
"instance": "u_payload",
"parameters": {"Depth": 16},
"title": "SHA input FIFO",
"depth": 16,
"bits": 37
}
],
"sources": [
"rtl/ip/security/crypto_aes_engine.sv",
"rtl/ip/security/crypto_sha2_engine.sv"
"rtl/ip/security/crypto_aes_sram_engine.sv",
"rtl/ip/security/crypto_clearable_fifo.sv",
"rtl/ip/security/crypto_sha2_sram_engine.sv"
],
"bindings": [],
"note": "Entries carry data and valid-byte/LAST metadata. AES has independent input/output FIFOs; SHA has an input FIFO and separate digest state. Zeroize/abort and ownership rules remain mandatory."
@@ -645,51 +649,42 @@
"section": "functional",
"stores": [
{
"file": "rtl/ip/security/crypto_rsa_core.sv",
"symbols": [
"modulus_i"
],
"word_view": 32,
"depth_ref": {"file": "crt/include/retrosoc/hal/crypto_regs.h", "constant": "RS_CRYPTO_RSA_WORDS"},
"bits_ref": {"file": "rtl/ip/security/apb4_crypto.sv", "symbol": "s_wdata"},
"title": "Modulus",
"depth": 64,
"bits": 32
},
{
"file": "rtl/ip/security/crypto_rsa_core.sv",
"symbols": [
"exponent_i"
],
"word_view": 32,
"depth_ref": {"file": "crt/include/retrosoc/hal/crypto_regs.h", "constant": "RS_CRYPTO_RSA_WORDS"},
"bits_ref": {"file": "rtl/ip/security/apb4_crypto.sv", "symbol": "s_wdata"},
"title": "Exponent",
"depth": 64,
"bits": 32
},
{
"file": "rtl/ip/security/crypto_rsa_core.sv",
"symbols": [
"base_i"
],
"word_view": 32,
"depth_ref": {"file": "crt/include/retrosoc/hal/crypto_regs.h", "constant": "RS_CRYPTO_RSA_WORDS"},
"bits_ref": {"file": "rtl/ip/security/apb4_crypto.sv", "symbol": "s_wdata"},
"title": "Base",
"depth": 64,
"bits": 32
},
{
"file": "rtl/ip/security/crypto_rsa_core.sv",
"symbols": [
"result_o"
],
"word_view": 32,
"depth_ref": {"file": "crt/include/retrosoc/hal/crypto_regs.h", "constant": "RS_CRYPTO_RSA_WORDS"},
"bits_ref": {"file": "rtl/ip/security/apb4_crypto.sv", "symbol": "s_wdata"},
"title": "Result",
"depth": 64,
"bits": 32
}
],
"sources": [
"rtl/ip/security/crypto_rsa_core.sv"
"crt/include/retrosoc/hal/crypto_regs.h",
"rtl/ip/security/apb4_crypto.sv",
"rtl/ip/security/crypto_rsa_sram_core.sv",
"rtl/ip/security/crypto_sram_store.sv"
],
"bindings": [],
"note": "Each 2,048-bit vector is shown as 64 little-endian 32-bit limb positions. These interfaces represent logical operand state, not secure SRAM, persistent keys or a key-slot service."
"note": "Each logical 2,048-bit APB aperture is shown as 64 little-endian 32-bit limb positions. P1 stores the live values in the shared private SRAM banks; the diagram does not imply separate arrays, persistent keys or a key-slot service."
},
{
"id": "xpi-windows",
@@ -4198,6 +4198,135 @@
}
},
"crypto": {
"main.MEM_STATUS": {
"access": "RO",
"description": "Storage initialization, verification, scrub, lock and fault state.",
"reset": "0x00000004",
"fields": [
{"lsb": 0, "msb": 0, "name": "READY", "description": "Constants are valid and locked, erasure is complete, and no memory fault is active.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_STATUS_READY"},
{"lsb": 1, "msb": 1, "name": "TABLE_VALID", "description": "The committed constants image passed validation.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_STATUS_TABLE_VALID"},
{"lsb": 2, "msb": 2, "name": "SCRUB_BUSY", "description": "Reset or zeroize scrubbing is active.", "reset": "1", "expression": "`APB4_CRYPTO__MEM_STATUS_SCRUB_BUSY"},
{"lsb": 3, "msb": 3, "name": "LOAD_ACTIVE", "description": "A TABLE_DATA loading transaction is active.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_STATUS_LOAD_ACTIVE"},
{"lsb": 4, "msb": 4, "name": "VERIFY_BUSY", "description": "Full storage readback and CRC verification is active.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_STATUS_VERIFY_BUSY"},
{"lsb": 5, "msb": 5, "name": "TABLE_LOCKED", "description": "The verified constants banks remain locked until hard/PCLK reset; zeroize does not unlock them.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_STATUS_TABLE_LOCKED"},
{"lsb": 6, "msb": 6, "name": "FAULT", "description": "A sticky storage lifecycle fault is active.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_STATUS_FAULT"},
{"lsb": 7, "msb": 31, "name": "Reserved", "description": "Reserved; reads zero.", "reset": "0", "expression": "25'd0"}
]
},
"main.MEM_CONTROL": {
"access": "WO",
"description": "One-hot storage lifecycle command; zero is a no-op.",
"reset": "Not retained (command/data port)",
"fields": [
{"lsb": 0, "msb": 0, "name": "BEGIN", "description": "Begin a new ordered constants load.", "reset": "Not retained", "expression": "`APB4_CRYPTO__MEM_CONTROL_BEGIN"},
{"lsb": 1, "msb": 1, "name": "COMMIT", "description": "Commit the complete image and start readback verification.", "reset": "Not retained", "expression": "`APB4_CRYPTO__MEM_CONTROL_COMMIT"},
{"lsb": 2, "msb": 2, "name": "CANCEL", "description": "Cancel an unlocked load attempt and start cleanup.", "reset": "Not retained", "expression": "`APB4_CRYPTO__MEM_CONTROL_CANCEL"},
{"lsb": 3, "msb": 31, "name": "Reserved", "description": "Reserved; write zero.", "reset": "Not retained", "expression": "29'd0"}
]
},
"main.TABLE_ID": {
"access": "RO",
"description": "Frozen CRYC1 constants-image identity.",
"reset": "0x43525901",
"fields": [
{"lsb": 0, "msb": 31, "name": "ID", "description": "CRYC1 image identifier.", "reset": "0x43525901", "expression": "`APB4_CRYPTO__TABLE_ID_VALUE"}
]
},
"main.TABLE_WORDS": {
"access": "RO",
"description": "Accepted ordered payload word count; BEGIN, CANCEL and reset clear it.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 11, "name": "WORDS", "description": "Accepted word count from 0 through 2048.", "reset": "0", "expression": "s_table_words"},
{"lsb": 12, "msb": 31, "name": "Reserved", "description": "Reserved; reads zero.", "reset": "0", "expression": "20'd0"}
]
},
"main.TABLE_DATA": {
"access": "WO",
"description": "Auto-incrementing full-word constants loader input.",
"reset": "Not retained (command/data port)",
"fields": [
{"lsb": 0, "msb": 31, "name": "DATA", "description": "Next constants-image word; full PSTRB is required.", "reset": "Not retained", "expression": "write data"}
]
},
"main.TABLE_CRC": {
"access": "RO",
"description": "CRC from the last complete full-storage readback.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "CRC", "description": "Readback CRC; zero until verification completes.", "reset": "0", "expression": "s_table_crc"}
]
},
"main.MEM_ERROR": {
"access": "RO",
"description": "First storage lifecycle error with physical bank and row context.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 7, "name": "CODE", "description": "First lifecycle error code; values 1 through 6 are defined.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_ERROR_CODE_MASK"},
{"lsb": 8, "msb": 10, "name": "BANK", "description": "Physical bank index; non-addressed errors report zero.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_ERROR_BANK_MASK"},
{"lsb": 11, "msb": 20, "name": "ROW", "description": "Physical row index; non-addressed errors report zero.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_ERROR_ROW_MASK"},
{"lsb": 21, "msb": 30, "name": "Reserved", "description": "Reserved; reads zero.", "reset": "0", "expression": "10'd0"},
{"lsb": 31, "msb": 31, "name": "VALID", "description": "The first-error record is valid.", "reset": "0", "expression": "`APB4_CRYPTO__MEM_ERROR_VALID"}
]
},
"main.MEM_CYCLES": {
"access": "RO",
"description": "Active PCLK cycles in the current or last verify/scrub operation.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "CYCLES", "description": "Maintenance cycle count, excluding loader inter-write gaps.", "reset": "0", "expression": "s_mem_cycles"}
]
},
"main.AES_BYTES_IN": {
"access": "RO",
"description": "Accepted AES input byte count.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "COUNT", "description": "Bytes accepted for the current or last AES operation.", "reset": "0", "expression": "s_aes_bytes_in"}
]
},
"main.AES_BYTES_OUT": {
"access": "RO",
"description": "Consumed AES output byte count.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "COUNT", "description": "Bytes consumed from the current or last AES operation.", "reset": "0", "expression": "s_aes_bytes_out"}
]
},
"main.AES_CYCLES": {
"access": "RO",
"description": "AES operation cycle count.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "CYCLES", "description": "Cycles in the current or last AES operation.", "reset": "0", "expression": "s_aes_cycles"}
]
},
"main.SHA_CYCLES": {
"access": "RO",
"description": "SHA operation cycle count.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "CYCLES", "description": "Cycles in the current or last SHA operation.", "reset": "0", "expression": "s_sha_cycles"}
]
},
"main.RSA_CYCLES": {
"access": "RO",
"description": "RSA operation cycle count.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 31, "name": "CYCLES", "description": "Cycles in the current or last RSA operation.", "reset": "0", "expression": "s_rsa_cycles"}
]
},
"main.RSA_PROGRESS": {
"access": "RO",
"description": "RSA private-operation flag and exponent position.",
"reset": "0",
"fields": [
{"lsb": 0, "msb": 0, "name": "PRIVATE", "description": "The active operation uses the private exponent path.", "reset": "0", "expression": "s_regs_q.private_operation"},
{"lsb": 1, "msb": 11, "name": "EXPONENT_INDEX", "description": "Current exponent bit position.", "reset": "0", "expression": "s_regs_q.exponent_index"},
{"lsb": 12, "msb": 31, "name": "Reserved", "description": "Reserved; reads zero.", "reset": "0", "expression": "20'd0"}
]
},
"main.COMMAND": {
"fields": [
{
@@ -4287,11 +4416,19 @@
},
{
"lsb": 5,
"msb": 5,
"name": "MEMORY_READY",
"description": "Writing one injects MEMORY_READY into sticky IRQ state for interrupt-path testing; it is not initialization or physical-erasure completion evidence.",
"reset": "Register reset applies",
"expression": "`APB4_CRYPTO__IRQ_MEMORY_READY"
},
{
"lsb": 6,
"msb": 31,
"name": "Reserved",
"description": "Reserved; write zero.",
"reset": "Not retained",
"expression": "32'd0"
"expression": "26'd0"
}
],
"reset": "Not retained (command/data port)"
@@ -1397,12 +1397,13 @@
}
],
"support": [
"rtl/ip/security/crypto_aes_core.sv",
"rtl/ip/security/crypto_aes_engine.sv",
"rtl/ip/security/crypto_montgomery.sv",
"rtl/ip/security/crypto_rsa_core.sv",
"rtl/ip/security/crypto_sha2_core.sv",
"rtl/ip/security/crypto_sha2_engine.sv"
"rtl/ip/security/crypto_aes_sram_core.sv",
"rtl/ip/security/crypto_aes_sram_engine.sv",
"rtl/ip/security/crypto_mem_ctrl.sv",
"rtl/ip/security/crypto_montgomery_sram.sv",
"rtl/ip/security/crypto_rsa_sram_core.sv",
"rtl/ip/security/crypto_sha2_sram_engine.sv",
"rtl/ip/security/crypto_sram_store.sv"
]
},
"mailbox": {
@@ -7,8 +7,10 @@
The supported open-source tool environment targets #environment.platform. The Docker image,
Nix application and manual Ubuntu #environment.ubuntu bootstrap share the repository's locked
installer. Docker and Nix use Python #environment.python to match the pinned requirement sets;
both provide Java #environment.java for the locked SBT #environment.sbt toolchain. These are
development prerequisites, *not additional SoC functions* or a statement of target performance.
both provide Java #environment.java for the locked SBT launcher #environment.sbt_launcher.
Each project selects its SBT engine through its own pinned build properties; the launcher
version is not an engine-version claim. These are development prerequisites,
*not additional SoC functions* or a statement of target performance.
#ds-table("development-entrypoints",[Development entrypoints and their boundaries],
([Entrypoint],[Reproducible input],[Use and evidence boundary]),
+344 -93
View File
@@ -1,22 +1,30 @@
{
"schema_version": 1,
"source_revision": "2a497ecef0b084c02f77ddfb1e94fb0197e14b02",
"source_revision": "c3de7c602a7ca0f0f9ade9d3ffb59339bc34fb8b",
"sources": [
"Makefile",
"app/README.md",
"app/apps/apu_release/main.c",
"app/apps/hp_boot/hp_boot_bundle.h",
"app/apps/hp_boot/main.c",
"app/ports/hp-apu/main.c",
"app/ports/linux/README.md",
"app/ports/linux/linux/retrosoc_hp.dts",
"app/ports/linux/opensbi/retrosoc_hp/platform.c",
"configs/benchmark/ihp130-hazard3-coremark.mk",
"configs/ci/ihp130-apu.mk",
"configs/ci/ihp130-hp.mk",
"configs/ci/ihp130.mk",
"configs/cluster/mini-mpw.mk",
"crt/README.md",
"crt/include/retrosoc/hal/apu_regs.h",
"crt/include/retrosoc/hal/ga2d.h",
"crt/include/retrosoc/hal/npu.h",
"crt/include/retrosoc/hal/npu_regs.h",
"crt/include/retrosoc/hal/resource.h",
"crt/include/retrosoc/hal/sysctrl.h",
"crt/src/hal/ga2d.c",
"crt/src/hal/npu.c",
"crt/src/hal/resource.c",
"crt/src/hal/sysctrl.c",
"docs/axi4-interconnect.md",
@@ -26,6 +34,7 @@
"docs/hazard3-debug.md",
"docs/ip/fabric-monitor.md",
"docs/ip/ga2d.md",
"docs/ip/npu-verification.md",
"docs/ip/resource-controller.md",
"docs/lp-hp-architecture.md",
"docs/mini-high-performance-traceability.md",
@@ -34,17 +43,28 @@
"physical/README.md",
"publications/datasheets/mini.json",
"publications/datasheets/register-profiles.json",
"publications/examples/npu.c",
"rtl/ip/multimedia/apb4_apu.sv",
"rtl/ip/multimedia/apb4_ga2d.sv",
"rtl/ip/multimedia/apb4_npu.sv",
"rtl/ip/multimedia/apu_define.svh",
"rtl/ip/multimedia/apu_kws_engine.sv",
"rtl/ip/multimedia/apu_kws_model_loader.sv",
"rtl/ip/multimedia/apu_kws_sram_client.sv",
"rtl/ip/multimedia/apu_local_sram.sv",
"rtl/ip/multimedia/apu_p5_codecs.apus",
"rtl/ip/multimedia/apu_reg.sv",
"rtl/ip/multimedia/ga2d_core.sv",
"rtl/ip/multimedia/ga2d_dma.sv",
"rtl/ip/multimedia/npu_accumulator.sv",
"rtl/ip/multimedia/npu_define.svh",
"rtl/ip/multimedia/npu_job_decoder.sv",
"rtl/ip/multimedia/npu_local_sram.sv",
"rtl/ip/multimedia/npu_pkg.sv",
"rtl/ip/multimedia/npu_reg.sv",
"rtl/ip/multimedia/npu_scheduler.sv",
"rtl/mini/integration/soc_topology.json",
"scripts/apu_abi_digest.py",
"scripts/apu_isa.py",
"scripts/apu_kws.py",
"scripts/apu_mcasm.py",
@@ -52,8 +72,23 @@
"scripts/build_apu_p5_bundle.py",
"scripts/build_hp_linux.py",
"scripts/check_lp_hp_performance.py",
"scripts/npu_compiler.py",
"scripts/npu_compiler_p0.py",
"scripts/npu_descriptors.py",
"scripts/package_hp_boot.py",
"tests/test_lp_irq.py"
"scripts/parse_performance_log.py",
"tests/test_lp_irq.py",
"rtl/mini/top/retrosoc.sv",
"rtl/mini/top/apb4_periph.sv",
"docs/development-environment.md",
"scripts/development_environment.py",
"dependencies/dependencies.lock.json",
"docker/Dockerfile",
"flake.nix",
".github/workflows/development-environment.yml",
".github/workflows/quality.yml",
"CONTRIBUTING.md",
"docs/git-workflow.md"
],
"support": [
{
@@ -609,7 +644,7 @@
"id": "resource",
"title": "Resource Controller",
"implementation": "Partial",
"scope": "Nine independently managed shared resources; resource 8 owns the active P5 GA2D direct 2D engine and IRQ route.",
"scope": "Ten independently managed shared resources; resource 8 owns GA2D and resource 9 owns NPU execution, including lifecycle and LP/HP IRQ routing.",
"dependencies": "No additional off-chip component implied; use the selected clock/reset and access policy.",
"hal": "Published API and syntax example; see the IP chapter.",
"linux": "Native driver support not established in this publication.",
@@ -629,7 +664,7 @@
"id": "monitor",
"title": "Fabric Monitor",
"implementation": "Integrated",
"scope": "Nine master and six target observation banks; bank 8 observes active P5 GA2D direct 2D traffic.",
"scope": "Ten master and six target observation banks; master bank 8 observes GA2D traffic and master bank 9 observes NPU descriptor and data DMA traffic.",
"dependencies": "No additional off-chip component implied; use the selected clock/reset and access policy.",
"hal": "Published API and syntax example; see the IP chapter.",
"linux": "Native driver support not established in this publication.",
@@ -739,23 +774,80 @@
"id": "apu",
"title": "Audio Processing Unit",
"implementation": "Partial",
"scope": "Microcode-controlled WAV/FLAC decoding with private DMA, direct/ring submission, I2S TX and local storage.",
"dependencies": "Load the compatible checked-in P5 APUMC V2 image. MP3 is unsupported and KWS is gated off by default; corpus, real-time and physical qualification remain separate.",
"scope": "WAV/FLAC image and job/stream execution; APUC-backed KWS is enabled only in the P9 acceptance configuration. MP3 remains unsupported.",
"dependencies": "Load compatible APUMC V2, APUC and APUM images in order. MP3 is unsupported and KWS is gated off by default; corpus, real-time and physical qualification remain separate.",
"hal": "Published API and syntax example; see the IP chapter.",
"linux": "Native driver support not established in this publication.",
"linux": "No delivered Linux ASoC integration. The LP/HP APU release image is bare-metal acceptance firmware, not a kernel driver.",
"verification": "Tests available",
"sources": [
"Makefile",
"app/apps/apu_release/main.c",
"app/ports/hp-apu/main.c",
"configs/ci/ihp130-apu.mk",
"crt/include/retrosoc/hal/apu.h",
"crt/include/retrosoc/hal/apu_regs.h",
"crt/src/hal/apu.c",
"docs/ip/apu.md",
"publications/examples/apu.c",
"rtl/ip/multimedia/apb4_apu.sv",
"rtl/ip/multimedia/apu_define.svh",
"rtl/ip/multimedia/apu_kws_coeff_loader.sv",
"rtl/ip/multimedia/apu_kws_coeff_store.sv",
"rtl/ip/multimedia/apu_kws_sram_client.sv",
"rtl/ip/multimedia/apu_local_sram.sv",
"rtl/ip/multimedia/apu_p5_codecs.apus",
"rtl/ip/multimedia/apu_reg.sv",
"rtl/ip/multimedia/apu_proof_memo.sv",
"scripts/apu_abi_digest.py",
"scripts/apu_isa.py",
"scripts/apu_kws.py",
"scripts/apu_kws_coeff.py",
"scripts/apu_mcasm.py",
"scripts/apu_p5_coefficients.py",
"scripts/build_apu_p5_bundle.py"
],
"tests": [
"tests/test_apu.py"
"tests/test_apu.py",
"tests/test_apu_p7_concurrent.py",
"tests/test_apu_p7_qualification.py",
"tests/test_apu_p8_contention.py",
"tests/test_apu_p8_quiesce_load.py"
],
"reports": []
},
{
"id": "npu",
"title": "Neural Processing Unit",
"implementation": "Integrated",
"scope": "Eight INT8 operators with native HP descriptor/DMA execution and private local SRAM.",
"dependencies": "Static compiler-supported graphs, exclusive resource/buffer ownership and explicit cache maintenance; locked KWS/VWW references for qualification.",
"hal": "Eleven public NPU HAL operations and a bounded submission example.",
"linux": "No native Linux NPU driver ABI is established. The HP smoke payload is freestanding acceptance firmware.",
"verification": "Tests available",
"sources": [
"crt/include/retrosoc/hal/npu.h",
"crt/include/retrosoc/hal/npu_regs.h",
"crt/src/hal/npu.c",
"docs/ip/npu-verification.md",
"docs/ip/npu.md",
"publications/examples/npu.c",
"rtl/ip/multimedia/apb4_npu.sv",
"rtl/ip/multimedia/npu_accumulator.sv",
"rtl/ip/multimedia/npu_define.svh",
"rtl/ip/multimedia/npu_job_decoder.sv",
"rtl/ip/multimedia/npu_local_sram.sv",
"rtl/ip/multimedia/npu_pkg.sv",
"rtl/ip/multimedia/npu_reg.sv",
"rtl/ip/multimedia/npu_scheduler.sv",
"scripts/npu_compiler.py",
"scripts/npu_compiler_p0.py",
"scripts/npu_descriptors.py"
],
"tests": [
"tests/test_npu_register_parity.py",
"tests/test_npu_rtl_p4.py",
"tests/test_npu_compiler.py",
"tests/test_npu_p6.py"
],
"reports": []
},
@@ -896,7 +988,7 @@
"impact": "Stale reads or loss of dirty data across CPU/DMA ownership changes.",
"trigger": "Concurrent cached CPU access and non-snooping DMA/LP access.",
"workaround": "Use exclusive ownership, whole cache-block ranges, directional cache maintenance and fences.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"docs/lp-hp-architecture.md",
"docs/ip/resource-controller.md"
@@ -904,14 +996,16 @@
},
{
"id": "hp-ready-wait",
"title": "HP loader has no firmware-local ready timeout",
"impact": "LP can wait indefinitely for the expected Linux mailbox event.",
"trigger": "No mailbox message after HP release.",
"workaround": "Use the simulator deadline during acceptance. A board supervisor/watchdog policy is integration work; no automatic retry is implemented here.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"title": "Linux ready service does not complete loader acceptance",
"impact": "The supplied rootfs publishes the initial ready checkpoint but does not provide the later GA2D result and cache-clean service required by the current hp_boot acceptance sequence.",
"trigger": "Using the ready-only Linux service where the loader expects the full acceptance mailbox protocol.",
"workaround": "Pair the loader with a matching acceptance payload or service. Current polling is bounded by iteration budgets and missing handshakes fail their stage; an initial ready message is not a terminal pass.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"app/apps/hp_boot/main.c",
"configs/ci/ihp130-hp.mk"
"configs/ci/ihp130-hp.mk",
"app/ports/linux/hp_ready.c",
"crt/src/hal/hp_mailbox.c"
]
},
{
@@ -920,7 +1014,7 @@
"impact": "A CRC-valid image is not proven to come from a trusted signer.",
"trigger": "Untrusted image or writable external boot storage.",
"workaround": "Treat signing, key storage, rollback prevention and secure recovery as separate unimplemented system requirements.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"app/apps/hp_boot/main.c",
"app/apps/hp_boot/hp_boot_bundle.h"
@@ -932,7 +1026,7 @@
"impact": "A HAL or DT node does not provide a native Linux driver.",
"trigger": "Applications attempt direct Linux use of a custom peripheral.",
"workaround": "Use the published support matrix, retain LP ownership where needed, and validate a platform driver before handoff.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"app/ports/linux/README.md",
"app/ports/linux/linux/retrosoc_hp.dts"
@@ -944,7 +1038,7 @@
"impact": "Some downstream peripheral engines are not reset by the central lifecycle request.",
"trigger": "Using Resource CONTROL.RESET as independent engine reset containment.",
"workaround": "Drain and use each IP reset/recovery contract. APU P1 has a local reset connection; do not generalize it to all engines.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"docs/ip/resource-controller.md"
]
@@ -955,7 +1049,7 @@
"impact": "Missing cache-clean acknowledgement prevents preservation of modified shared data.",
"trigger": "HP shutdown times out before acknowledgement.",
"workaround": "Keep a recoverable authoritative copy outside dirty HP cache; treat timed-out work as failed and reinitialize dependent queues.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"docs/lp-hp-architecture.md",
"docs/ip/resource-controller.md"
@@ -967,7 +1061,7 @@
"impact": "The inactive memory window returns an error and its pads are disconnected.",
"trigger": "Accessing the inactive memory mode or attempting a live protocol change.",
"workaround": "Select the mode at boot before use; respect the sticky lock. A live handover is not supported.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"docs/lp-hp-architecture.md"
]
@@ -978,7 +1072,7 @@
"impact": "Dedicated USB2 ULPI and SDIO1 pads need board assignment and electrical/timing review.",
"trigger": "Assuming logical pads are FPGA ball or package-pin assignments.",
"workaround": "Supply board constraints, bank voltages, external devices and validated timing before enabling a physical route.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"fpga/README.md",
"publications/datasheets/sections/pins.typ"
@@ -987,10 +1081,10 @@
{
"id": "apu-production",
"title": "APU MP3/KWS availability and qualification limits",
"impact": "WAV/FLAC code and image are implemented; this does not establish complete corpus, sustained real-time or physical qualification. MP3 remains a reserved trap entry; KWS RTL exists but PRODUCT defaults to EnableP7=0 and does not advertise KWS.",
"impact": "WAV/FLAC code and image are implemented. MP3 remains a reserved trap; default PRODUCT disables KWS, while the dedicated P7 configuration enables its fixed APUM model. These facts do not establish full-corpus, sustained real-time or physical qualification.",
"trigger": "Submitting MP3, assuming default KWS availability, or inferring full qualification from capability bits.",
"workaround": "Use advertised WAV/FLAC paths with a validated APUMC image and supported formats/rates. Treat KWS as gated development functionality until its complete qualification evidence is supplied.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"workaround": "Read the configuration-specific capability/digest. Use the supported image/model and explicit loader, cache and ownership protocol. Obtain complete revision-matched accuracy/concurrency/physical reports before wider qualification.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"publications/datasheets/ips/apu.typ",
"rtl/ip/multimedia/apu_reg.sv"
@@ -1002,7 +1096,7 @@
"impact": "Deterministic test data cannot supply production cryptographic entropy.",
"trigger": "Using the current entropy stream to generate secret keys or nonces.",
"workaround": "Keep diagnostic use separate; production entropy requires a reviewed physical source and qualification.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"publications/datasheets/ips/rng.typ",
"rtl/mini/top/apb4_system.sv"
@@ -1014,7 +1108,7 @@
"impact": "Configuration clocks and behavioral models are not electrical or silicon ratings.",
"trigger": "Selecting board voltage, frequency, thermal or timing limits from RTL defaults.",
"workaround": "Use approved technology, macro, package and board reports; leave absent specifications TBD.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"physical/README.md",
"docs/pll-clock-control.md"
@@ -1026,7 +1120,7 @@
"impact": "Legacy selection writes are rejected in PRODUCT.",
"trigger": "Calling selectable user-core/IP mutators on a fixed PRODUCT configuration.",
"workaround": "Detect mode/capabilities first and use fixed EXT-L/EXT-H APIs in PRODUCT.",
"applies_to": "Reviewed v0.4 PRODUCT snapshot; MPW differences are stated separately.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; MPW differences are stated separately.",
"sources": [
"docs/lp-hp-architecture.md",
"docs/ip/user-ip.md"
@@ -1050,7 +1144,7 @@
"impact": "READ_BASE and WRITE_BASE next-state assignments are not gated by the KindExtH write-legal result; an EXT-L write can change those readbacks while returning PSLVERR.",
"trigger": "Writing READ_BASE or WRITE_BASE through the EXT-L register window.",
"workaround": "Treat these writes as invalid and avoid them. Preserve the slot fault/address when diagnosing an error; do not assume a rejected write rolls back state. EXT-L has no connected data master, so these local outputs do not grant an EXT-L DMA path.",
"applies_to": "Reviewed v0.4 PRODUCT source snapshot; static RTL observation, no new simulation or hardware test.",
"applies_to": "Reviewed v0.5 PRODUCT source snapshot; static RTL observation, no new simulation or hardware test.",
"sources": [
"rtl/mini/top/extension_slot.sv",
"rtl/mini/top/extension_subsystem.sv"
@@ -1067,6 +1161,20 @@
"crt/arch/riscv/startup.S",
"rtl/mk/software.mk"
]
},
{
"id": "npu-deployment-scope",
"title": "NPU execution does not imply arbitrary model or qualified performance support",
"impact": "Unsupported graphs, unsafe buffer reuse or an assumed Linux driver can prevent correct deployment.",
"trigger": "Dynamic/arbitrary TFLite graphs, unadvertised operators, timeout without drain, or missing cache/ownership handoff.",
"workaround": "Use the static compiler subset and explicit CPU preprocessing/Softmax. Check capability and numeric profile, retain buffers until terminal/drained state, and require exact-revision reports for accuracy/performance claims.",
"applies_to": "Reviewed v0.5 PRODUCT snapshot; no MLPerf, timing-closure or silicon qualification claim.",
"sources": [
"rtl/ip/multimedia/npu_reg.sv",
"rtl/ip/multimedia/apb4_npu.sv",
"scripts/npu_compiler.py",
"crt/src/hal/npu.c"
]
}
],
"programming": {
@@ -2548,7 +2656,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"64-byte TX and RX FIFOs; fractional baud-rate generator.\""
"text": "\"**64-byte TX and RX FIFOs**; fractional baud-rate generator.\""
}
]
},
@@ -2572,7 +2680,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Two controller instances with 7-bit and 10-bit addressing.\""
"text": "\"Two controller instances with **7-bit and 10-bit addressing**.\""
}
]
},
@@ -2597,7 +2705,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Stereo master TX/RX with independent audio clock.\""
"text": "\"**Stereo master TX/RX** with independent audio clock.\""
}
]
},
@@ -2621,7 +2729,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Bidirectional open-drain host interface.\""
"text": "\"Bidirectional **open-drain** host interface.\""
}
]
},
@@ -2645,7 +2753,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"24-bit GRB transmission on one GPIO alternate function.\""
"text": "\"**24-bit GRB** transmission on one GPIO alternate function.\""
}
]
},
@@ -2670,7 +2778,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"SD card SPI-mode command/data host.\""
"text": "\"SD card **SPI-mode** command/data host.\""
}
]
},
@@ -2696,7 +2804,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Native one-bit/four-bit SDR operation.\""
"text": "\"Native **one-bit/four-bit SDR** operation.\""
}
]
},
@@ -2721,7 +2829,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Dual-role digital controller with external 8-bit ULPI PHY.\""
"text": "\"Dual-role digital controller with **external 8-bit ULPI PHY**.\""
}
]
},
@@ -2746,7 +2854,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Four chip-select slots and 16 programmable LUT sequences.\""
"text": "\"Four chip-select slots and **16 programmable LUT sequences**.\""
}
]
},
@@ -2771,7 +2879,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Four ESP-PSRAM64H devices addressable through a 32 MiB window.\""
"text": "\"Four ESP-PSRAM64H devices addressable through a **32 MiB window**.\""
}
]
},
@@ -2796,7 +2904,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"One octal DDR memory interface and one selected protocol profile.\""
"text": "\"One octal DDR memory interface and **one selected protocol profile**.\""
}
]
},
@@ -2821,7 +2929,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Fixed 64 MiB, x16 SDR geometry with bank/row tracking.\""
"text": "\"Fixed **64 MiB, x16 SDR** geometry with bank/row tracking.\""
}
]
},
@@ -2845,7 +2953,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"8-bit parallel RGB565/YUV422 capture.\""
"text": "\"**8-bit parallel RGB565/YUV422** capture.\""
}
]
},
@@ -2857,7 +2965,7 @@
"title": "JPEG",
"role": "Baseline sequential codec",
"modes": "8-bit SOF0 encode/decode and the indexed raster formats; modes are mutually exclusive.",
"excluded": "No progressive/lossless/arithmetic/10-12-bit modes. Native SoC DMA admission is currently blocked at slot 6.",
"excluded": "No progressive/lossless/arithmetic/10-12-bit modes. DMA permits one normal read and one normal write at a time.",
"software": "Standalone codec/register behavior is distinct from end-to-end SoC payload availability.",
"evidence": "Source-level subset; no compliance report attached",
"sources": [
@@ -2870,7 +2978,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"8-bit Baseline Sequential JPEG encode or decode.\""
"text": "\"8-bit **Baseline Sequential JPEG** encode or decode.\""
}
]
},
@@ -2882,7 +2990,7 @@
"title": "APU",
"role": "Coreless control/transport subsystem",
"modes": "Register/transport and bounded development codec paths described in the IP chapter.",
"excluded": "MP3 is not supported. KWS is implemented as a gated development path and remains disabled/unadvertised by default. No generic codec or full corpus qualification is implied.",
"excluded": "MP3 unsupported; KWS requires the P7-enabled configuration. No generic codec, arbitrary TFLite, Linux ASoC or complete corpus qualification is implied.",
"software": "A HAL, microcode format or test source does not establish an enabled production audio service.",
"evidence": "Source-level subset; no compliance report attached",
"sources": [
@@ -2894,7 +3002,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Coreless microcode sequencer with private DMA and local storage.\""
"text": "\"**Coreless microcode sequencer** with private DMA and local storage.\""
}
]
},
@@ -2921,6 +3029,30 @@
"text": "`define APB4_GA2D__CAPABILITY_P5 32'h0000_07ff"
}
]
},
{
"id": "npu",
"ips": [
"npu"
],
"title": "NPU",
"role": "Static INT8 tensor processing",
"modes": "Eight operator classes, checked INT32 accumulation, double-rounding requantization and native HP descriptor DMA.",
"software": "Static compiler-generated C, NPU HAL and freestanding LP/HP acceptance; preprocessing and terminal Softmax run on CPU.",
"excluded": "No arbitrary/dynamic TFLite graphs, implicit fallback, APUM binary compatibility, dedicated camera/audio stream or native Linux driver ABI.",
"evidence": "Source-level subset; no compliance report attached",
"sources": [
"rtl/ip/multimedia/npu_define.svh",
"rtl/ip/multimedia/apb4_npu.sv",
"scripts/npu_compiler.py"
],
"bindings": [
{
"file": "rtl/ip/multimedia/npu_define.svh",
"kind": "snippet",
"text": "`define APB4_NPU__CAPABILITY_P4 32'h0000_007f"
}
]
}
],
"formats": [
@@ -3194,7 +3326,7 @@
{
"file": "publications/datasheets/features.json",
"kind": "snippet",
"text": "\"Coreless microcode sequencer with private DMA and local storage.\""
"text": "\"**Coreless microcode sequencer** with private DMA and local storage.\""
}
]
}
@@ -3728,6 +3860,22 @@
"rtl/ip/multimedia/ga2d_core.sv"
]
},
{
"id": "apb4_npu",
"chapter": "npu",
"family": "npu",
"mode": "PRODUCT",
"region": "APB4_NPU",
"catalog": "npu",
"qualification": "Integrated native-HP NPU execution with eight operator classes, descriptor DMA and private SRAM; CAPABILITY=0x7F and OP_CAPABILITY=0x1FE. Resource 9 routes LP vector 33 / HP PLIC source 12. Use configured lifecycle, cache and descriptor admission rules; no native Linux driver, arbitrary model or current corpus/physical qualification is implied.",
"sources": [
"docs/ip/npu.md",
"rtl/ip/multimedia/npu_reg.sv",
"rtl/ip/multimedia/apb4_npu.sv",
"rtl/ip/multimedia/npu_control_cdc.sv",
"rtl/ip/multimedia/npu_core.sv"
]
},
{
"id": "apb4_crypto",
"chapter": "crypto",
@@ -4993,6 +5141,8 @@
9,
9,
9,
18,
18,
10,
18,
19,
@@ -5003,7 +5153,8 @@
15,
16,
17,
17
17,
19
],
"expected_entries": 4,
"meanings": {
@@ -5025,8 +5176,8 @@
"15": "The request to hold HP after P5 GA2D completion returned an unexpected error.",
"16": "Cache-clean request, P5 GA2D cache mailbox event, clean acknowledgement, or HP-held confirmation failed.",
"17": "GA2D handoff back to LP or LP-owned safe-idle confirmation failed.",
"18": "RT-Thread ready message failed validation or HP reported a test failure.",
"19": "LP-to-HP IRQ command failed or RT-Thread final verdict failed validation."
"18": "NPU handoff to HP failed, or the RT-Thread ready message reported failure or mismatched identity.",
"19": "NPU handoff back to LP failed, or the RT-Thread IRQ command/final verdict failed."
}
}
},
@@ -5068,6 +5219,11 @@
"rtl/mk/software.mk",
"scripts/build_hp_linux.py",
"scripts/regress.py",
"crt/src/hal/hp_mailbox.c",
"crt/include/retrosoc/core/status.h",
"rtl/ip/peripheral/hp_mailbox_define.svh",
"rtl/mini/address_map/memory_map.json",
"rtl/ip/peripheral/apb4_hp_mailbox.sv",
"app/ports/linux/init"
],
"bindings": [
@@ -5455,6 +5611,33 @@
"coverage": "Discover P5 capability, submit direct single-job FILL/COPY/CONVERT/BLEND work through master 8, including A8 fixed-color foreground masks and exact equal background/destination in-place composition, verify the resource-owned LP external completion route, and inspect destinations.",
"boundary": "Exercises the direct private-AXI64 P5 functional subset only; it does not cover transparent-background/premultiplied-alpha modes, scaling, rendering, descriptor/ring/queue submission, cache coherency, a Linux graphics driver, HP P5 composition acceptance, or physical performance."
},
{
"id": "ga2d-bounded-wait",
"title": "GA2D bounded wait and timeout ownership",
"kind": "test-fail",
"code": 15,
"trigger": "rs_ci_smoke_ga2d_bounded_wait(",
"coverage": "Force a deliberately small rs_ga2d_wait budget to expire with RS_ETIMEOUT while a real SDRAM job keeps running, prove timeout expiry does not imply safe idle or buffer reclaim, then complete the job under a normal bounded wait with exact destination and counter checks, and confirm rs_ga2d_abort_wait on the idle engine.",
"boundary": "Covers LP polling-budget semantics only; it does not exercise HP-side timeout handling, watchdog TIMEOUT error recovery, or abort of an in-flight job."
},
{
"id": "ga2d-dma-contention",
"title": "GA2D and central DMA concurrent progress",
"kind": "test-fail",
"code": 16,
"trigger": "rs_ci_smoke_ga2d_dma_contention(",
"coverage": "Run a central-DMA memory-to-memory transfer and a GA2D copy concurrently in disjoint SDRAM regions, verify both payloads byte-exactly, and confirm fabric-monitor request counters advance for both master 2 and master 8 during the shared window.",
"boundary": "Covers LP CPU, central DMA, and GA2D competition with SDRAM refresh in the behavioral product; wider peripheral-master contention is evidenced in the GA2D platform testbench, and no starvation bound is proven here."
},
{
"id": "npu-p2-shell-irq",
"title": "NPU P2 shell ownership and IRQ route",
"kind": "test-fail",
"code": 17,
"trigger": "rs_ci_smoke_npu_irq(",
"coverage": "Hand resource 9 to LP through the Resource Controller quiesce/acknowledge round trip, read back the shell identity/capability, and verify the IRQ_TEST-injected event reaches external ordinal 31 and clears by W1C.",
"boundary": "Covers the P2 register shell and interrupt route only; EXECUTION_READY stays clear, the private master is tied idle, and no job, DMA, or operator behavior is exercised."
},
{
"id": "apu",
"title": "APU discovery",
@@ -5830,6 +6013,7 @@
"rtl/ip/multimedia/apb4_apu.sv",
"rtl/ip/multimedia/apb4_ga2d.sv",
"rtl/ip/multimedia/apb4_jpeg.sv",
"rtl/ip/multimedia/apb4_npu.sv",
"rtl/ip/multimedia/apu_control_store.sv",
"rtl/ip/multimedia/apu_define.svh",
"rtl/ip/multimedia/apu_local_sram.sv",
@@ -5850,6 +6034,15 @@
"rtl/ip/multimedia/jpeg_encode_core.sv",
"rtl/ip/multimedia/jpeg_reg.sv",
"rtl/ip/multimedia/jpeg_table_store.sv",
"rtl/ip/multimedia/npu_accumulator.sv",
"rtl/ip/multimedia/npu_control_cdc.sv",
"rtl/ip/multimedia/npu_core.sv",
"rtl/ip/multimedia/npu_define.svh",
"rtl/ip/multimedia/npu_dma.sv",
"rtl/ip/multimedia/npu_local_sram.sv",
"rtl/ip/multimedia/npu_pkg.sv",
"rtl/ip/multimedia/npu_reg.sv",
"rtl/ip/multimedia/npu_scheduler.sv",
"rtl/ip/peripheral/apb4_clint.sv",
"rtl/ip/peripheral/apb4_dma.sv",
"rtl/ip/peripheral/apb4_gpio.sv",
@@ -5866,10 +6059,12 @@
"rtl/ip/peripheral/sysctrl_reg.sv",
"rtl/ip/peripheral/timer_core.sv",
"rtl/ip/peripheral/timer_reg.sv",
"crt/include/retrosoc/hal/crypto_regs.h",
"rtl/ip/security/apb4_crypto.sv",
"rtl/ip/security/crypto_aes_engine.sv",
"rtl/ip/security/crypto_rsa_core.sv",
"rtl/ip/security/crypto_sha2_engine.sv",
"rtl/ip/security/crypto_aes_sram_engine.sv",
"rtl/ip/security/crypto_clearable_fifo.sv",
"rtl/ip/security/crypto_rsa_sram_core.sv",
"rtl/ip/security/crypto_sha2_sram_engine.sv",
"rtl/ip/serial/apb4_i2c.sv",
"rtl/ip/serial/apb4_i2c_define.svh",
"rtl/ip/serial/apb4_i2s.sv",
@@ -5965,6 +6160,9 @@
"rtl/mini/top/user_ip_top.sv",
"rtl/mini/top/user_ip_wrapper.sv",
"scripts/apu_isa.py",
"scripts/npu_compiler_p0.py",
"scripts/npu_descriptors.py",
"scripts/npu_executor.py",
"scripts/package_hp_boot.py"
],
"bindings": [
@@ -7151,57 +7349,110 @@
"soc_architecture_catalog": "publications/datasheets/soc-architecture.json"
},
"ci_snapshot": {
"revision": "2a497ecef0b084c02f77ddfb1e94fb0197e14b02",
"checked_date": "2026-09-17",
"boundary": "Public GitHub workflow/job outcomes for this exact commit. Behavioral regression success is not synthesis, netlist, STA, formal, FPGA or silicon qualification. A failed prerequisite can leave later tests unexecuted.",
"revision": "c3de7c602a7ca0f0f9ade9d3ffb59339bc34fb8b",
"checked_date": "2026-09-23",
"checked_at": "2026-09-23T08:26:42Z",
"boundary": "Observed public GitHub workflow status for this exact commit. Unfinished runs have no conclusion. Installation, environment checking and runtime regression are separate evidence; workflow outcomes do not qualify unexecuted physical or silicon stages.",
"runs": [
{
"name": "regression-ihp130",
"run_id": 35035899124,
"result": "success",
"scope": "IHP130 PR behavioral-only regression",
"note": "Run pr regression passed; formal environment step skipped. Synthesis/timing environment checks are setup checks, not physical results.",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35035899124"
},
{
"name": "regression-gf180",
"run_id": 35035899130,
"result": "success",
"scope": "GF180 workflow",
"note": "Workflow outcome only; detailed stages require their own artifacts.",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35035899130"
},
{
"name": "regression-ics55",
"run_id": 35035899146,
"result": "success",
"scope": "ICS55 workflow",
"note": "Workflow outcome only; detailed stages require their own artifacts.",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35035899146"
"name": "quality",
"run_id": 35833990836,
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990836",
"scope": "Repository quality checks and script/RTL fixture tests",
"note": "No terminal conclusion has been observed. No per-IP corpus or physical qualification is inferred."
},
{
"name": "regression-smoke",
"run_id": 35035899140,
"result": "success",
"scope": "Smoke workflow",
"note": "Does not qualify all peripheral use cases.",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35035899140"
"run_id": 35833991124,
"status": "completed",
"conclusion": "success",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833991124",
"scope": "Bounded IHP130 smoke regression",
"note": "Selected workflow stages completed successfully. No per-IP corpus or physical qualification is inferred."
},
{
"name": "quality",
"run_id": 35035898949,
"result": "failure",
"scope": "Quality workflow",
"note": "Check source formatting failed. Later host tests, script tests and APU P5 acceptance were skipped.",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35035898949"
"name": "regression-ihp130",
"run_id": 35833991071,
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833991071",
"scope": "IHP130 hosted behavioral regression",
"note": "No terminal conclusion has been observed. No per-IP corpus or physical qualification is inferred."
},
{
"name": "regression-sky130",
"run_id": 35035899137,
"result": "failure",
"scope": "SKY130 PR workflow",
"note": "Run pr regression failed. Do not present this platform as passing.",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35035899137"
"run_id": 35833991199,
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833991199",
"scope": "SKY130 hosted behavioral regression",
"note": "No terminal conclusion has been observed. No per-IP corpus or physical qualification is inferred."
},
{
"name": "regression-gf180",
"run_id": 35833991194,
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833991194",
"scope": "GF180 hosted behavioral regression",
"note": "No terminal conclusion has been observed. No per-IP corpus or physical qualification is inferred."
},
{
"name": "regression-ics55",
"run_id": 35833991306,
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833991306",
"scope": "ICS55 hosted behavioral regression",
"note": "No terminal conclusion has been observed. No per-IP corpus or physical qualification is inferred."
},
{
"name": "development-environment",
"run_id": 35833990893,
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990893",
"scope": "Docker/Nix installation, environment checks and hosted IHP130 behavioral regression",
"note": "No terminal conclusion has been observed. No per-IP corpus or physical qualification is inferred.",
"observations": [
{
"name": "docker: Build Docker development environment",
"scope": "installation",
"status": "completed",
"conclusion": "success",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990893/job/107092965761"
},
{
"name": "docker: Run IHP130 regression in development environment",
"scope": "runtime-regression",
"status": "in_progress",
"conclusion": null,
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990893/job/107092965761"
},
{
"name": "nix: Install Nix",
"scope": "installation",
"status": "completed",
"conclusion": "success",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990893/job/107092965933"
},
{
"name": "nix: Check Nix flake",
"scope": "environment-check",
"status": "completed",
"conclusion": "success",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990893/job/107092965933"
},
{
"name": "nix: Run IHP130 regression in development environment",
"scope": "runtime-regression",
"status": "completed",
"conclusion": "success",
"url": "https://github.com/retroSoC/retroSoC/actions/runs/35833990893/job/107092965933"
}
]
}
]
}
+14 -14
View File
@@ -2505,54 +2505,54 @@
"skin": "lowkey"
}
},
"note": "Scope: crypto_aes_engine. Clock: clk_i; AES processing intervals omitted. AES engine example with key expansion complete and valid parameters. The final output waits for output_ready_i; internal block processing and earlier words are omitted. SHA/RSA have separate engine sequencing.",
"note": "Scope: crypto_aes_sram_engine. Clock: clk_i; AES processing intervals omitted. AES engine example with key expansion complete and valid parameters. The final output waits for output_ready_i; internal block processing and earlier words are omitted. SHA/RSA have separate engine sequencing.",
"clock_domain": "clk_i; AES processing intervals omitted",
"signals": {
"key_valid_o": {
"file": "rtl/ip/security/crypto_aes_engine.sv",
"scope": "crypto_aes_engine",
"file": "rtl/ip/security/crypto_aes_sram_engine.sv",
"scope": "crypto_aes_sram_engine",
"symbol": "key_valid_o",
"meaning": "A committed expanded key is valid before start.",
"polarity": "active-high"
},
"start_i": {
"file": "rtl/ip/security/crypto_aes_engine.sv",
"scope": "crypto_aes_engine",
"file": "rtl/ip/security/crypto_aes_sram_engine.sv",
"scope": "crypto_aes_sram_engine",
"symbol": "start_i",
"meaning": "Start a configured AES job.",
"polarity": "active-high"
},
"busy_o": {
"file": "rtl/ip/security/crypto_aes_engine.sv",
"scope": "crypto_aes_engine",
"file": "rtl/ip/security/crypto_aes_sram_engine.sv",
"scope": "crypto_aes_sram_engine",
"symbol": "busy_o",
"meaning": "AES engine active.",
"polarity": "active-high"
},
"output_valid_o": {
"file": "rtl/ip/security/crypto_aes_engine.sv",
"scope": "crypto_aes_engine",
"file": "rtl/ip/security/crypto_aes_sram_engine.sv",
"scope": "crypto_aes_sram_engine",
"symbol": "output_valid_o",
"meaning": "Final output word offered and retained until accepted.",
"polarity": "active-high"
},
"output_ready_i": {
"file": "rtl/ip/security/crypto_aes_engine.sv",
"scope": "crypto_aes_engine",
"file": "rtl/ip/security/crypto_aes_sram_engine.sv",
"scope": "crypto_aes_sram_engine",
"symbol": "output_ready_i",
"meaning": "Output consumer readiness.",
"polarity": "active-high"
},
"done_o": {
"file": "rtl/ip/security/crypto_aes_engine.sv",
"scope": "crypto_aes_engine",
"file": "rtl/ip/security/crypto_aes_sram_engine.sv",
"scope": "crypto_aes_sram_engine",
"symbol": "done_o",
"meaning": "Job completion after the final accepted output.",
"polarity": "active-high"
}
},
"review_sources": [
"rtl/ip/security/crypto_aes_engine.sv"
"rtl/ip/security/crypto_aes_sram_engine.sv"
],
"review_note": "Replaced generic accelerator lanes with the AES engine ready/valid and completion contract; no cipher throughput claim."
},
+1 -1
View File
@@ -32,6 +32,6 @@ def development_environment(root: Path) -> dict:
return {
"platform": "Linux x86_64", "ubuntu": ubuntu[0],
"python": ".".join(python[0]), "java": java_nix[0],
"sbt": lock["toolchains"]["ubuntu-22.04"]["sbt"]["version"],
"sbt_launcher": lock["toolchains"]["ubuntu-22.04"]["sbt"]["version"],
"sources": list(ENVIRONMENT_SOURCES),
}
+10 -1
View File
@@ -183,11 +183,20 @@ def linux_platform(root: Path) -> dict:
writes = [(0x10019020, 1), (0x10019024, 0x4C4E5801), (0x10019028, 1), (0x1001902C, 1)]
if "descriptor, 0x10019000)" not in ready:
raise ValueError("Linux mailbox mapping changed")
registers = ("HP_EVENT", "HP_ARG0", "HP_SEQUENCE", "HP_DOORBELL")
purposes = ("Linux-ready event", "Ready-state argument", "Publication sequence",
"LP interrupt request")
return {"hart_id": 1, "timebase_hz": timebase, "clock_hz": int(clocks[0]),
"cbom_bytes": dt_value("riscv,cbom-block-size"), "memory_base": memory[0][0],
"memory_bytes": int(memory[0][1], 0), "initrd_start": dt_value("linux,initrd-start"),
"initrd_template_end": dt_value("linux,initrd-end"), "bootargs": bootargs[0],
"ready_writes": [{"address": f"0x{a:08X}", "value": f"0x{v:08X}"} for a, v in writes]}
"ready_writes": [
{"address": f"0x{address:08X}", "value": f"0x{value:08X}",
"register": register, "purpose": purpose}
for (address, value), register, purpose in zip(
writes, registers, purposes, strict=True
)
]}
def collect_software(root: Path, spec: dict) -> dict:
+136 -136
View File
@@ -100,17 +100,17 @@ module apb4_apu #(
logic [13:0] s_kws_coeff_front_index;
logic s_kws_coeff_front_resp_valid, s_kws_coeff_front_resp_ready;
logic [63:0] s_kws_coeff_front_resp_data;
logic s_kws_coeff_front_resp_fault;
logic s_kws_coeff_front_resp_fault;
logic s_kws_coeff_infer_req, s_kws_coeff_infer_ready;
logic [6:0] s_kws_coeff_infer_index;
logic s_kws_coeff_infer_resp_valid, s_kws_coeff_infer_resp_ready;
logic [31:0] s_kws_coeff_infer_resp_data;
logic s_kws_coeff_infer_resp_fault;
logic s_kws_coeff_infer_resp_fault;
logic s_kws_coeff_profile_req, s_kws_coeff_profile_ready;
logic [10:0] s_kws_coeff_profile_index;
logic s_kws_coeff_profile_resp_valid, s_kws_coeff_profile_resp_ready;
logic [31:0] s_kws_coeff_profile_resp_data;
logic s_kws_coeff_profile_resp_fault;
logic s_kws_coeff_profile_resp_fault;
logic s_kws_engine_model_v_unused, s_kws_engine_model_lock_unused;
logic [31:0] s_kws_engine_model_stat_unused, s_kws_engine_model_crc_unused;
logic s_direct_start_allowed;
@@ -840,146 +840,146 @@ module apb4_apu #(
);
apu_kws_engine u_kws_engine (
.clk_i(clk_i),
.rst_n_i(rst_n_i),
.soft_reset_i(s_soft_reset),
.resource_reset_i(s_resource_reset_apply_q),
.counter_clear_i(s_cnt_clear),
.xrun_clear_i(s_xrun_clear),
.abort_i(s_abort),
.quiesce_i(quiesce_i),
.disable_i(s_kws_disable_request),
.flush_busy_i(i2s_rx_flush_busy_i),
.enable_i(s_kws_control[0]),
.memory_window_i(s_kws_control[1]),
.clear_history_i(s_kws_clear_history),
.model_valid_i(s_kws_model_valid),
.model_lock_i(s_kws_model_lock),
.sequencer_timeout_i(s_sequencer_timeout),
.memory_start_i(s_kws_memory_start),
.memory_start_ready_o(s_kws_mem_start_ready),
.memory_address_i(s_codec_descriptor[(2*32)+:32]),
.memory_dma_request_valid_o(s_kws_mem_dma_req),
.memory_dma_request_ready_i(s_kws_mem_dma_rdy),
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.soft_reset_i (s_soft_reset),
.resource_reset_i (s_resource_reset_apply_q),
.counter_clear_i (s_cnt_clear),
.xrun_clear_i (s_xrun_clear),
.abort_i (s_abort),
.quiesce_i (quiesce_i),
.disable_i (s_kws_disable_request),
.flush_busy_i (i2s_rx_flush_busy_i),
.enable_i (s_kws_control[0]),
.memory_window_i (s_kws_control[1]),
.clear_history_i (s_kws_clear_history),
.model_valid_i (s_kws_model_valid),
.model_lock_i (s_kws_model_lock),
.sequencer_timeout_i (s_sequencer_timeout),
.memory_start_i (s_kws_memory_start),
.memory_start_ready_o (s_kws_mem_start_ready),
.memory_address_i (s_codec_descriptor[(2*32)+:32]),
.memory_dma_request_valid_o (s_kws_mem_dma_req),
.memory_dma_request_ready_i (s_kws_mem_dma_rdy),
.memory_dma_request_address_o(s_kws_mem_dma_addr),
.memory_dma_request_bytes_o(s_kws_mem_dma_bytes),
.memory_dma_data_i(u_dma_read_axis.tdata),
.memory_dma_keep_i(u_dma_read_axis.tkeep),
.memory_dma_last_i(u_dma_read_axis.tlast),
.memory_dma_valid_i(s_kws_mem_data_v),
.memory_dma_ready_o(s_kws_mem_dma_data_rdy),
.memory_dma_done_i(s_kws_mem_dma_done),
.memory_dma_error_i(s_kws_mem_dma_error),
.memory_dma_error_code_i(s_dma_err_code),
.memory_dma_error_stage_i(s_dma_err_stage),
.memory_dma_error_resp_i(s_dma_err_resp),
.memory_dma_error_address_i(s_dma_err_addr),
.memory_done_o(s_kws_mem_done),
.memory_error_o(s_kws_mem_err),
.memory_error_code_o(s_kws_mem_err_code),
.memory_error_stage_o(s_kws_mem_err_stage),
.memory_error_resp_o(s_kws_mem_err_resp),
.memory_error_address_o(s_kws_mem_err_addr),
.memory_error_detail_o(s_kws_mem_err_detail),
.memory_input_used_o(s_kws_mem_input_used),
.kws_config_i(s_codec_kws_config_valid ? s_codec_kws_config : s_kws_config),
.input_config_i(s_kws_input_config),
.storage_req_o(s_kws_storage_req),
.storage_ready_i(s_kws_storage_ready),
.storage_done_i(s_kws_storage_done),
.storage_progress_i(s_kws_storage_progress),
.storage_write_o(s_kws_storage_write),
.model_read_valid_o(s_kws_model_read_valid),
.model_addr_o(s_kws_model_read_addr),
.model_data_i(s_kws_model_read_data),
.scratch_clear_o(s_kws_scratch_clear),
.scratch_read_valid_o(s_kws_scratch_read_valid),
.scratch_read_addr_o(s_kws_scratch_read_addr),
.scratch_read_data_i(s_kws_scratch_read_data),
.scratch_write_valid_o(s_kws_scratch_write_valid),
.scratch_write_addr_o(s_kws_scratch_write_addr),
.scratch_write_data_o(s_kws_scratch_write_data),
.scratch_write_strb_o(s_kws_scratch_write_strb),
.scratch_access_err_i(s_kws_scratch_err),
.coeff_frontend_req_valid_o(s_kws_coeff_front_req),
.coeff_frontend_req_ready_i(s_kws_coeff_front_ready),
.coeff_frontend_kind_o(s_kws_coeff_front_kind),
.coeff_frontend_index_o(s_kws_coeff_front_index),
.coeff_frontend_resp_valid_i(s_kws_coeff_front_resp_valid),
.coeff_frontend_resp_ready_o(s_kws_coeff_front_resp_ready),
.coeff_frontend_data_i(s_kws_coeff_front_resp_data),
.coeff_frontend_fault_i(s_kws_coeff_front_resp_fault),
.coeff_inference_req_valid_o(s_kws_coeff_infer_req),
.coeff_inference_req_ready_i(s_kws_coeff_infer_ready),
.coeff_inference_index_o(s_kws_coeff_infer_index),
.memory_dma_request_bytes_o (s_kws_mem_dma_bytes),
.memory_dma_data_i (u_dma_read_axis.tdata),
.memory_dma_keep_i (u_dma_read_axis.tkeep),
.memory_dma_last_i (u_dma_read_axis.tlast),
.memory_dma_valid_i (s_kws_mem_data_v),
.memory_dma_ready_o (s_kws_mem_dma_data_rdy),
.memory_dma_done_i (s_kws_mem_dma_done),
.memory_dma_error_i (s_kws_mem_dma_error),
.memory_dma_error_code_i (s_dma_err_code),
.memory_dma_error_stage_i (s_dma_err_stage),
.memory_dma_error_resp_i (s_dma_err_resp),
.memory_dma_error_address_i (s_dma_err_addr),
.memory_done_o (s_kws_mem_done),
.memory_error_o (s_kws_mem_err),
.memory_error_code_o (s_kws_mem_err_code),
.memory_error_stage_o (s_kws_mem_err_stage),
.memory_error_resp_o (s_kws_mem_err_resp),
.memory_error_address_o (s_kws_mem_err_addr),
.memory_error_detail_o (s_kws_mem_err_detail),
.memory_input_used_o (s_kws_mem_input_used),
.kws_config_i (s_codec_kws_config_valid ? s_codec_kws_config : s_kws_config),
.input_config_i (s_kws_input_config),
.storage_req_o (s_kws_storage_req),
.storage_ready_i (s_kws_storage_ready),
.storage_done_i (s_kws_storage_done),
.storage_progress_i (s_kws_storage_progress),
.storage_write_o (s_kws_storage_write),
.model_read_valid_o (s_kws_model_read_valid),
.model_addr_o (s_kws_model_read_addr),
.model_data_i (s_kws_model_read_data),
.scratch_clear_o (s_kws_scratch_clear),
.scratch_read_valid_o (s_kws_scratch_read_valid),
.scratch_read_addr_o (s_kws_scratch_read_addr),
.scratch_read_data_i (s_kws_scratch_read_data),
.scratch_write_valid_o (s_kws_scratch_write_valid),
.scratch_write_addr_o (s_kws_scratch_write_addr),
.scratch_write_data_o (s_kws_scratch_write_data),
.scratch_write_strb_o (s_kws_scratch_write_strb),
.scratch_access_err_i (s_kws_scratch_err),
.coeff_frontend_req_valid_o (s_kws_coeff_front_req),
.coeff_frontend_req_ready_i (s_kws_coeff_front_ready),
.coeff_frontend_kind_o (s_kws_coeff_front_kind),
.coeff_frontend_index_o (s_kws_coeff_front_index),
.coeff_frontend_resp_valid_i (s_kws_coeff_front_resp_valid),
.coeff_frontend_resp_ready_o (s_kws_coeff_front_resp_ready),
.coeff_frontend_data_i (s_kws_coeff_front_resp_data),
.coeff_frontend_fault_i (s_kws_coeff_front_resp_fault),
.coeff_inference_req_valid_o (s_kws_coeff_infer_req),
.coeff_inference_req_ready_i (s_kws_coeff_infer_ready),
.coeff_inference_index_o (s_kws_coeff_infer_index),
.coeff_inference_resp_valid_i(s_kws_coeff_infer_resp_valid),
.coeff_inference_resp_ready_o(s_kws_coeff_infer_resp_ready),
.coeff_inference_data_i(s_kws_coeff_infer_resp_data),
.coeff_inference_fault_i(s_kws_coeff_infer_resp_fault),
.stream_i(u_apu_rx_axis),
.rx_ready_o(s_kws_rx_ready),
.status_o(s_kws_status),
.result_o(s_kws_result),
.timestamp_lo_o(s_kws_timestamp_lo),
.timestamp_hi_o(s_kws_timestamp_hi),
.frame_count_o(s_kws_frame_count),
.inference_count_o(s_kws_inference_count),
.hit_count_o(s_kws_hit_count),
.overrun_count_o(s_kws_overrun_count),
.model_status_o(s_kws_engine_model_stat_unused),
.model_actual_crc_o(s_kws_engine_model_crc_unused),
.irq_set_o(s_kws_irq_set),
.fault_valid_o(s_kws_fault_valid),
.fault_code_o(s_kws_fault_code),
.fault_stage_o(s_kws_fault_stage),
.fault_resp_o(s_kws_fault_resp),
.fault_index_o(s_kws_fault_index),
.fault_addr_o(s_kws_fault_addr),
.fault_detail_o(s_kws_fault_detail),
.model_valid_o(s_kws_engine_model_v_unused),
.model_lock_o(s_kws_engine_model_lock_unused),
.busy_o(s_kws_busy),
.idle_o(s_kws_idle)
.coeff_inference_data_i (s_kws_coeff_infer_resp_data),
.coeff_inference_fault_i (s_kws_coeff_infer_resp_fault),
.stream_i (u_apu_rx_axis),
.rx_ready_o (s_kws_rx_ready),
.status_o (s_kws_status),
.result_o (s_kws_result),
.timestamp_lo_o (s_kws_timestamp_lo),
.timestamp_hi_o (s_kws_timestamp_hi),
.frame_count_o (s_kws_frame_count),
.inference_count_o (s_kws_inference_count),
.hit_count_o (s_kws_hit_count),
.overrun_count_o (s_kws_overrun_count),
.model_status_o (s_kws_engine_model_stat_unused),
.model_actual_crc_o (s_kws_engine_model_crc_unused),
.irq_set_o (s_kws_irq_set),
.fault_valid_o (s_kws_fault_valid),
.fault_code_o (s_kws_fault_code),
.fault_stage_o (s_kws_fault_stage),
.fault_resp_o (s_kws_fault_resp),
.fault_index_o (s_kws_fault_index),
.fault_addr_o (s_kws_fault_addr),
.fault_detail_o (s_kws_fault_detail),
.model_valid_o (s_kws_engine_model_v_unused),
.model_lock_o (s_kws_engine_model_lock_unused),
.busy_o (s_kws_busy),
.idle_o (s_kws_idle)
);
apu_dma u_apu_dma (
.clk_i(clk_i),
.rst_n_i(rst_n_i),
.abort_i(s_dma_abort),
.quiesce_i(s_dma_quiesce),
.bridge_epoch_i(bridge_epoch_i),
.perf_enable_i(s_perf_enable),
.counter_clear_i(s_cnt_clear),
.request_valid_i(s_dma_req_valid),
.request_ready_o(s_dma_req_ready),
.request_write_i(s_dma_req_write),
.request_addr_i(s_dma_req_addr),
.request_bytes_i(s_dma_req_bytes),
.read_base_i(s_read_base),
.read_limit_i(s_read_limit),
.write_base_i(s_write_base),
.write_limit_i(s_write_limit),
.timeout_i(s_dma_timeout),
.read_axis(u_dma_read_axis),
.write_axis(u_dma_write_axis),
.busy_o(s_dma_busy),
.done_o(s_dma_done),
.error_o(s_dma_err),
.aborted_o(s_dma_aborted),
.aborting_o(s_dma_aborting),
.error_code_o(s_dma_err_code),
.error_stage_o(s_dma_err_stage),
.error_resp_o(s_dma_err_resp),
.error_addr_o(s_dma_err_addr),
.input_pending_o(s_dma_input_pending),
.output_pending_o(s_dma_output_pending),
.read_bytes_o(s_dma_read_bytes),
.write_bytes_o(s_dma_write_bytes),
.write_burst_done_o(s_dma_write_burst_done),
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.abort_i (s_dma_abort),
.quiesce_i (s_dma_quiesce),
.bridge_epoch_i (bridge_epoch_i),
.perf_enable_i (s_perf_enable),
.counter_clear_i (s_cnt_clear),
.request_valid_i (s_dma_req_valid),
.request_ready_o (s_dma_req_ready),
.request_write_i (s_dma_req_write),
.request_addr_i (s_dma_req_addr),
.request_bytes_i (s_dma_req_bytes),
.read_base_i (s_read_base),
.read_limit_i (s_read_limit),
.write_base_i (s_write_base),
.write_limit_i (s_write_limit),
.timeout_i (s_dma_timeout),
.read_axis (u_dma_read_axis),
.write_axis (u_dma_write_axis),
.busy_o (s_dma_busy),
.done_o (s_dma_done),
.error_o (s_dma_err),
.aborted_o (s_dma_aborted),
.aborting_o (s_dma_aborting),
.error_code_o (s_dma_err_code),
.error_stage_o (s_dma_err_stage),
.error_resp_o (s_dma_err_resp),
.error_addr_o (s_dma_err_addr),
.input_pending_o (s_dma_input_pending),
.output_pending_o (s_dma_output_pending),
.read_bytes_o (s_dma_read_bytes),
.write_bytes_o (s_dma_write_bytes),
.write_burst_done_o (s_dma_write_burst_done),
.write_burst_bytes_o(s_dma_write_burst_bytes),
.read_stalls_o(s_dma_read_stalls),
.write_stalls_o(s_dma_write_stalls),
.axi4(axi4)
.read_stalls_o (s_dma_read_stalls),
.write_stalls_o (s_dma_write_stalls),
.axi4 (axi4)
);
apu_microcode_loader #(
+7 -7
View File
@@ -78,8 +78,8 @@ module apu_kws_coeff_loader (
CancelWait
} loader_state_e;
loader_state_e s_state_q;
logic [15:0][31:0] s_header_q;
loader_state_e s_state_q;
logic [15:0][31:0] s_header_q;
logic [31:0] s_addr_q, s_size_q, s_expected_crc_q, s_acl_base_q, s_acl_limit_q;
logic [31:0] s_received_q;
logic [31:0] s_crc_q, s_readback_crc_q;
@@ -129,10 +129,10 @@ module apu_kws_coeff_loader (
s_bank = word_i[13:10];
s_row = word_i[9:0];
unique case (s_bank)
4'd0: payload_word_is_padding = s_row >= 10'd1006;
4'd1: payload_word_is_padding = s_row >= 10'd769;
4'd2: payload_word_is_padding = s_row >= 10'd768;
4'd14: payload_word_is_padding = s_row >= 10'd637;
4'd0: payload_word_is_padding = s_row >= 10'd1006;
4'd1: payload_word_is_padding = s_row >= 10'd769;
4'd2: payload_word_is_padding = s_row >= 10'd768;
4'd14: payload_word_is_padding = s_row >= 10'd637;
default: payload_word_is_padding = 1'b0;
endcase
end
@@ -152,7 +152,7 @@ module apu_kws_coeff_loader (
always_comb begin
s_header_size_err = 1'b0;
s_header_err = 1'b0;
s_header_err = 1'b0;
s_header_err_addr = s_addr_q;
if (s_header_q[2] != ImageBytes) begin
s_header_size_err = 1'b1;
+2 -2
View File
@@ -303,8 +303,8 @@ module apu_kws_coeff_store (
end
if (s_loader_accept) begin
s_loader_fault_q <= loader_addr_i >= 14'd15360;
s_loader_bank_q <= loader_addr_i[13:10];
s_loader_fault_q <= loader_addr_i >= 14'd15360;
s_loader_bank_q <= loader_addr_i[13:10];
s_loader_pending_q <= !loader_write_i;
end else begin
s_loader_pending_q <= 1'b0;
+6 -6
View File
@@ -483,8 +483,8 @@ module apu_kws_engine (
log_lookup_t s_lookup;
logic [95:0] fraction_scaled, fraction_quotient, fraction_remainder;
begin
numerator = 96'd1000000 * mel_i + 96'd16 * peak_i;
denominator = 96'd16000000 * peak_i;
numerator = 96'd1000000 * mel_i + 96'd16 * peak_i;
denominator = 96'd16000000 * peak_i;
s_lookup.exponent = 0;
if (numerator >= denominator) begin
normalized_denominator = denominator;
@@ -498,7 +498,7 @@ module apu_kws_engine (
normalized_denominator = denominator;
for (int iteration = 0; iteration < 95; iteration++) begin
if (numerator < normalized_denominator) begin
numerator = numerator << 1;
numerator = numerator << 1;
s_lookup.exponent = s_lookup.exponent - 1'b1;
end
end
@@ -1049,13 +1049,13 @@ module apu_kws_engine (
end
endcase
s_infer_coeff_needed = 1'b0;
s_infer_coeff_needed = 1'b0;
coeff_inference_index_o = 7'd0;
if (s_infer_state_q == InferSoftmaxSum) begin
s_infer_coeff_needed = !s_coeff_operand_ready || (s_softmax_sum_diff >= -9'sd124);
s_infer_coeff_needed = !s_coeff_operand_ready || (s_softmax_sum_diff >= -9'sd124);
coeff_inference_index_o = 7'(-s_softmax_sum_diff);
end else if ((s_infer_state_q == InferSoftmaxScale) && (s_softmax_index_q != 4'd0)) begin
s_infer_coeff_needed = !s_coeff_operand_ready || (s_softmax_scale_diff >= -9'sd124);
s_infer_coeff_needed = !s_coeff_operand_ready || (s_softmax_scale_diff >= -9'sd124);
coeff_inference_index_o = 7'(-s_softmax_scale_diff);
end
end
+5 -5
View File
@@ -71,10 +71,10 @@ module apu_proof_memo #(
s_bitmap_cs = 1'b1;
s_bitmap_addr = {2'd0, addr_i[12:5]};
end else if ((s_state_q == Idle) && insert_i) begin
s_key_cs[addr_i[12:10]] = 1'b1;
s_key_cs[addr_i[12:10]] = 1'b1;
s_key_wren[addr_i[12:10]] = 1'b1;
s_bitmap_cs = 1'b1;
s_bitmap_addr = {2'd0, addr_i[12:5]};
s_bitmap_cs = 1'b1;
s_bitmap_addr = {2'd0, addr_i[12:5]};
end else if (s_state_q == InsertBitmapWrite) begin
s_bitmap_cs = 1'b1;
s_bitmap_wren = 1'b1;
@@ -119,8 +119,8 @@ module apu_proof_memo #(
.data_o(s_bitmap_rdata)
);
`else
logic [63:0] s_key_mem [0:Depth-1];
logic [31:0] s_bitmap_mem[0:BitmapRows-1];
logic [63:0] s_key_mem [ 0:Depth-1];
logic [31:0] s_bitmap_mem [0:BitmapRows-1];
logic [12:0] s_key_access_addr;
logic [63:0] s_key_access_data;
+288 -274
View File
@@ -131,26 +131,26 @@ module npu_core #(
logic s_epoch_restart;
logic s_unused;
assign launch_ready_o = 1'b1;
assign result_valid_o = 1'b0;
assign result_data_o = '0;
assign busy_o = 1'b0;
assign draining_o = 1'b0;
assign flush_busy_o = 1'b0;
assign snapshot_resp_data_o = '0;
assign launch_ready_o = 1'b1;
assign result_valid_o = 1'b0;
assign result_data_o = '0;
assign busy_o = 1'b0;
assign draining_o = 1'b0;
assign flush_busy_o = 1'b0;
assign snapshot_resp_data_o = '0;
// With zero accepted AXI obligations and no internal work, the
// clock-pause acknowledge is immediate and the HP idle contribution
// follows the platform formula !block_new_i || clock_pause_ack_o.
assign clock_pause_ack_o = block_new_i;
assign pause_active_o = block_new_i && clock_pause_ack_o;
assign idle_o = !block_new_i || clock_pause_ack_o;
assign clock_pause_ack_o = block_new_i;
assign pause_active_o = block_new_i && clock_pause_ack_o;
assign idle_o = !block_new_i || clock_pause_ack_o;
assign epoch_ack_o = s_epoch_ack_q;
assign quiesce_ack_o = s_quiesce_ack_q;
assign epoch_ack_o = s_epoch_ack_q;
assign quiesce_ack_o = s_quiesce_ack_q;
assign s_epoch_restart = (epoch_req_i != s_epoch_ack_q);
assign s_unused = ^{launch_data_i, result_ready_i, flush_i, 1'b0};
assign s_epoch_restart = (epoch_req_i != s_epoch_ack_q);
assign s_unused = ^{launch_data_i, result_ready_i, flush_i, 1'b0};
assign dma_clear_o = 1'b0;
assign dma_read_req_valid_o = 1'b0;
@@ -259,7 +259,7 @@ module npu_core #(
snap_state_e s_snap_state_d, s_snap_state_q;
logic [EpochWidth-1:0] s_epoch_ack_d, s_epoch_ack_q;
logic s_quiesce_ack_d, s_quiesce_ack_q;
logic s_epoch_restart;
logic s_epoch_restart;
// job context
logic [31:0] s_job_base_q;
logic [31:0] s_job_id_q;
@@ -267,26 +267,26 @@ module npu_core #(
logic [15:0] s_job_count_q;
logic [31:0] s_term_job_id_q;
// first-fault record
logic s_fault_seen_d, s_fault_seen_q;
logic [ 3:0] s_fault_code_d, s_fault_code_q;
logic s_fault_seen_d, s_fault_seen_q;
logic [3:0] s_fault_code_d, s_fault_code_q;
logic [31:0] s_fault_addr_d, s_fault_addr_q;
logic [31:0] s_fault_info_d, s_fault_info_q;
logic [31:0] s_fault_desc_d, s_fault_desc_q;
// terminal record
logic [ 2:0] s_res_code_d, s_res_code_q;
logic [ 2:0] s_res_irq_d, s_res_irq_q;
logic [2:0] s_res_code_d, s_res_code_q;
logic [2:0] s_res_irq_d, s_res_irq_q;
logic [31:0] s_res_completed_d, s_res_completed_q;
// snapshot capture
logic [SnapshotPayloadWidth-1:0] s_snap_payload_d, s_snap_payload_q;
logic s_launch_accept;
logic s_job_busy;
logic s_dec_busy;
logic s_sch_busy;
logic s_sch_drained;
logic s_drained;
logic s_compose_terminal;
logic s_stop;
logic s_clear;
logic s_launch_accept;
logic s_job_busy;
logic s_dec_busy;
logic s_sch_busy;
logic s_sch_drained;
logic s_drained;
logic s_compose_terminal;
logic s_stop;
logic s_clear;
// decoder wires
logic s_dec_job_start;
logic s_dec_read_req_valid;
@@ -314,51 +314,52 @@ module npu_core #(
logic [31:0] s_rec_input0_base, s_rec_output_base;
logic [31:0] s_rec_weight_base, s_rec_param_base;
logic [31:0] s_rec_irow, s_rec_orow;
logic [ 7:0] s_rec_kh, s_rec_kw, s_rec_sh, s_rec_sw;
logic [ 7:0] s_rec_pad_top, s_rec_pad_left, s_rec_in0_zero;
logic [ 7:0] s_rec_tile_h, s_rec_tile_w;
logic [7:0] s_rec_kh, s_rec_kw, s_rec_sh, s_rec_sw;
logic [7:0] s_rec_pad_top, s_rec_pad_left, s_rec_in0_zero;
logic [7:0] s_rec_tile_h, s_rec_tile_w;
logic [15:0] s_rec_k_slice;
logic [31:0] s_rec_input1_base, s_rec_input1_row_bytes;
logic [ 7:0] s_rec_in1_zero, s_rec_out_zero, s_rec_act_min, s_rec_act_max;
logic [7:0] s_rec_in1_zero, s_rec_out_zero, s_rec_act_min, s_rec_act_max;
logic [31:0] s_rec_weight_bytes, s_rec_param_bytes;
logic [15:0] s_rec_desc_index;
logic [ 15:0] s_rec_desc_index;
// scheduler wires
logic s_sch_launch;
logic s_sch_retired;
logic [31:0] s_sch_completed;
logic s_sch_read_req_valid;
logic s_sch_read_req_ready;
logic [31:0] s_sch_read_addr;
logic [31:0] s_sch_read_bytes;
logic s_sch_read_data_valid;
logic s_sch_read_data_ready;
logic s_sch_write_req_valid;
logic [31:0] s_sch_write_addr;
logic [31:0] s_sch_write_bytes;
logic s_sch_write_data_valid;
logic [63:0] s_sch_write_data;
logic [ 7:0] s_sch_write_keep;
logic s_sch_write_last;
logic s_sch_pause_ok;
logic s_sch_terminal;
logic s_sch_launch;
logic s_sch_retired;
logic [ 31:0] s_sch_completed;
logic s_sch_read_req_valid;
logic s_sch_read_req_ready;
logic [ 31:0] s_sch_read_addr;
logic [ 31:0] s_sch_read_bytes;
logic s_sch_read_data_valid;
logic s_sch_read_data_ready;
logic s_sch_write_req_valid;
logic [ 31:0] s_sch_write_addr;
logic [ 31:0] s_sch_write_bytes;
logic s_sch_write_data_valid;
logic [ 63:0] s_sch_write_data;
logic [ 7:0] s_sch_write_keep;
logic s_sch_write_last;
logic s_sch_pause_ok;
logic s_sch_terminal;
logic [639:0] s_sch_counters;
logic [639:0] s_sch_term_counters;
logic s_sch_fault_req;
logic [ 3:0] s_sch_fault_code;
logic [31:0] s_sch_fault_addr;
logic [31:0] s_sch_fault_info;
logic [31:0] s_sch_fault_desc;
logic s_sch_fault_req;
logic [ 3:0] s_sch_fault_code;
logic [ 31:0] s_sch_fault_addr;
logic [ 31:0] s_sch_fault_info;
logic [ 31:0] s_sch_fault_desc;
// fault arbitration
logic s_evt_dec;
logic s_evt_sch;
logic s_evt_cmd_err;
logic [ 3:0] s_evt_code;
logic [31:0] s_evt_addr;
logic [31:0] s_evt_info;
logic [31:0] s_evt_desc;
logic s_evt_any;
logic s_evt_dec;
logic s_evt_sch;
logic s_evt_cmd_err;
logic [ 3:0] s_evt_code;
logic [ 31:0] s_evt_addr;
logic [ 31:0] s_evt_info;
logic [ 31:0] s_evt_desc;
logic s_evt_any;
// Deterministic same-cycle first-fault priority: lower rank wins.
// verilog_format: off -- preserve macro case labels that Verible misclassifies as item tokens
function automatic logic [3:0] fault_rank(input logic [3:0] code_i);
logic [3:0] rank;
begin
@@ -377,6 +378,7 @@ module npu_core #(
return rank;
end
endfunction
// verilog_format: on
assign s_evt_dec = s_dec_fault_req;
assign s_evt_sch = s_sch_fault_req;
@@ -396,8 +398,11 @@ module npu_core #(
s_evt_info = s_dec_fault_info;
s_evt_desc = s_dec_fault_desc;
end
if (s_evt_sch && (!s_evt_dec ||
(fault_rank(s_sch_fault_code) <= fault_rank(s_dec_fault_code)))) begin
if (s_evt_sch && (!s_evt_dec || (fault_rank(
s_sch_fault_code
) <= fault_rank(
s_dec_fault_code
)))) begin
s_evt_code = s_sch_fault_code;
s_evt_addr = s_sch_fault_addr;
s_evt_info = s_sch_fault_info;
@@ -405,6 +410,7 @@ module npu_core #(
// phase) belongs to the descriptor the decoder holds.
s_evt_desc = s_dec_busy ? {16'd0, s_dec_cur_index} : s_sch_fault_desc;
end
// verilog_format: off -- preserve macro argument tokens that Verible misclassifies
if (s_evt_cmd_err && (!s_evt_dec && !s_evt_sch ||
(fault_rank(`APB4_NPU__FAULT_CODE_LOCAL_STATE) <=
fault_rank(s_evt_code)))) begin
@@ -413,6 +419,7 @@ module npu_core #(
s_evt_info = {16'd0, 8'd255, 4'd0, 2'd0, 2'd0};
s_evt_desc = s_dec_busy ? {16'd0, s_dec_cur_index} : s_sch_fault_desc;
end
// verilog_format: on
end
assign s_job_busy = (s_state_q != CoreIdle);
@@ -439,8 +446,7 @@ module npu_core #(
(s_state_q == CoreDrainReset);
assign flush_busy_o = 1'b0;
assign idle_o = !block_new_i || clock_pause_ack_o;
assign clock_pause_ack_o = block_new_i && dma_pause_ack_i && s_dec_pause_ok &&
s_sch_pause_ok;
assign clock_pause_ack_o = block_new_i && dma_pause_ack_i && s_dec_pause_ok && s_sch_pause_ok;
assign pause_active_o = block_new_i && clock_pause_ack_o;
assign epoch_ack_o = s_epoch_ack_q;
assign quiesce_ack_o = s_quiesce_ack_q;
@@ -475,20 +481,20 @@ module npu_core #(
// Core FSM
// -------------------------------------------------------------
always_comb begin
s_state_d = s_state_q;
s_epoch_ack_d = s_epoch_ack_q;
s_quiesce_ack_d = s_quiesce_ack_q;
s_snap_state_d = s_snap_state_q;
s_snap_payload_d = s_snap_payload_q;
s_fault_seen_d = s_fault_seen_q;
s_fault_code_d = s_fault_code_q;
s_fault_addr_d = s_fault_addr_q;
s_fault_info_d = s_fault_info_q;
s_fault_desc_d = s_fault_desc_q;
s_res_code_d = s_res_code_q;
s_res_irq_d = s_res_irq_q;
s_res_completed_d = s_res_completed_q;
snapshot_req_ready_o = 1'b0;
s_state_d = s_state_q;
s_epoch_ack_d = s_epoch_ack_q;
s_quiesce_ack_d = s_quiesce_ack_q;
s_snap_state_d = s_snap_state_q;
s_snap_payload_d = s_snap_payload_q;
s_fault_seen_d = s_fault_seen_q;
s_fault_code_d = s_fault_code_q;
s_fault_addr_d = s_fault_addr_q;
s_fault_info_d = s_fault_info_q;
s_fault_desc_d = s_fault_desc_q;
s_res_code_d = s_res_code_q;
s_res_irq_d = s_res_irq_q;
s_res_completed_d = s_res_completed_q;
snapshot_req_ready_o = 1'b0;
snapshot_resp_valid_o = 1'b0;
// snapshot endpoint: atomic capture of the live or retained bank
@@ -532,14 +538,14 @@ module npu_core #(
if (s_evt_any && !s_fault_seen_q) begin
s_state_d = CoreDrainFault;
end else if (s_all_done_q) begin
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_DONE);
s_res_irq_d = 3'b001;
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_DONE);
s_res_irq_d = 3'b001;
s_res_completed_d = {16'd0, s_job_count_q};
s_fault_code_d = 4'(`APB4_NPU__FAULT_CODE_NONE);
s_fault_desc_d = 32'hffff_ffff;
s_fault_addr_d = 32'd0;
s_fault_info_d = 32'd0;
s_state_d = CorePublish;
s_fault_code_d = 4'(`APB4_NPU__FAULT_CODE_NONE);
s_fault_desc_d = 32'hffff_ffff;
s_fault_addr_d = 32'd0;
s_fault_info_d = 32'd0;
s_state_d = CorePublish;
end else if (abort_i) begin
s_state_d = CoreDrainAbort;
end else if (quiesce_req_i) begin
@@ -550,17 +556,17 @@ module npu_core #(
if (s_drained) begin
if (s_fault_seen_q) begin
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_ERROR);
s_res_irq_d = 3'b010;
s_res_irq_d = 3'b010;
end else begin
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_ABORTED);
s_res_irq_d = 3'b100;
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_ABORTED);
s_res_irq_d = 3'b100;
s_fault_code_d = 4'(`APB4_NPU__FAULT_CODE_NONE);
s_fault_desc_d = 32'hffff_ffff;
s_fault_addr_d = 32'd0;
s_fault_info_d = 32'd0;
end
s_res_completed_d = s_sch_completed;
s_state_d = CorePublish;
s_state_d = CorePublish;
end
end
CoreDrainReset: begin
@@ -570,17 +576,17 @@ module npu_core #(
s_epoch_ack_d = epoch_req_i;
if (s_fault_seen_q) begin
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_ERROR);
s_res_irq_d = 3'b010;
s_res_irq_d = 3'b010;
end else begin
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_RESET_CANCELLED);
s_res_irq_d = 3'b010;
s_res_code_d = 3'(`APB4_NPU__RESULT_CODE_RESET_CANCELLED);
s_res_irq_d = 3'b010;
s_fault_code_d = 4'(`APB4_NPU__FAULT_CODE_RESET_CANCELLED);
s_fault_desc_d = 32'hffff_ffff;
s_fault_addr_d = 32'd0;
s_fault_info_d = 32'd0;
end
s_res_completed_d = s_sch_completed;
s_state_d = CorePublish;
s_state_d = CorePublish;
end
end
CorePublish: begin
@@ -618,46 +624,54 @@ module npu_core #(
end
assign result_valid_o = (s_state_q == CorePublish);
assign result_data_o = {s_res_irq_q, s_fault_code_q, s_res_code_q, s_fault_info_q,
s_fault_addr_q, s_fault_desc_q, s_res_completed_q, s_job_id_q};
assign result_data_o = {
s_res_irq_q,
s_fault_code_q,
s_res_code_q,
s_fault_info_q,
s_fault_addr_q,
s_fault_desc_q,
s_res_completed_q,
s_job_id_q
};
assign snapshot_resp_data_o = s_snap_payload_q;
always_ff @(posedge clk_hp_i or negedge rst_hp_n_i) begin
if (!rst_hp_n_i) begin
s_state_q <= CoreIdle;
s_snap_state_q <= SnapIdle;
s_job_base_q <= '0;
s_job_id_q <= '0;
s_timeout_q <= '0;
s_job_count_q <= '0;
s_term_job_id_q <= '0;
s_fault_seen_q <= 1'b0;
s_fault_code_q <= '0;
s_fault_addr_q <= '0;
s_fault_info_q <= '0;
s_fault_desc_q <= `APB4_NPU__FAULT_DESCRIPTOR_RESET;
s_res_code_q <= '0;
s_res_irq_q <= '0;
s_state_q <= CoreIdle;
s_snap_state_q <= SnapIdle;
s_job_base_q <= '0;
s_job_id_q <= '0;
s_timeout_q <= '0;
s_job_count_q <= '0;
s_term_job_id_q <= '0;
s_fault_seen_q <= 1'b0;
s_fault_code_q <= '0;
s_fault_addr_q <= '0;
s_fault_info_q <= '0;
s_fault_desc_q <= `APB4_NPU__FAULT_DESCRIPTOR_RESET;
s_res_code_q <= '0;
s_res_irq_q <= '0;
s_res_completed_q <= '0;
s_snap_payload_q <= '0;
s_all_done_q <= 1'b0;
s_snap_payload_q <= '0;
s_all_done_q <= 1'b0;
end else begin
s_state_q <= s_state_d;
s_snap_state_q <= s_snap_state_d;
s_snap_payload_q <= s_snap_payload_d;
s_fault_seen_q <= s_fault_seen_d;
s_fault_code_q <= s_fault_code_d;
s_fault_addr_q <= s_fault_addr_d;
s_fault_info_q <= s_fault_info_d;
s_fault_desc_q <= s_fault_desc_d;
s_res_code_q <= s_res_code_d;
s_res_irq_q <= s_res_irq_d;
s_state_q <= s_state_d;
s_snap_state_q <= s_snap_state_d;
s_snap_payload_q <= s_snap_payload_d;
s_fault_seen_q <= s_fault_seen_d;
s_fault_code_q <= s_fault_code_d;
s_fault_addr_q <= s_fault_addr_d;
s_fault_info_q <= s_fault_info_d;
s_fault_desc_q <= s_fault_desc_d;
s_res_code_q <= s_res_code_d;
s_res_irq_q <= s_res_irq_d;
s_res_completed_q <= s_res_completed_d;
if (s_launch_accept) begin
s_job_base_q <= launch_data_i[`APB4_NPU__LAUNCH_JOB_BASE+:32];
s_job_id_q <= launch_data_i[`APB4_NPU__LAUNCH_JOB_ID+:32];
s_timeout_q <= launch_data_i[`APB4_NPU__LAUNCH_TIMEOUT_CYCLES+:32];
s_job_count_q <= launch_data_i[`APB4_NPU__LAUNCH_JOB_COUNT+:16];
s_job_base_q <= launch_data_i[`APB4_NPU__LAUNCH_JOB_BASE+:32];
s_job_id_q <= launch_data_i[`APB4_NPU__LAUNCH_JOB_ID+:32];
s_timeout_q <= launch_data_i[`APB4_NPU__LAUNCH_TIMEOUT_CYCLES+:32];
s_job_count_q <= launch_data_i[`APB4_NPU__LAUNCH_JOB_COUNT+:16];
s_fault_seen_q <= 1'b0;
s_fault_desc_q <= `APB4_NPU__FAULT_DESCRIPTOR_RESET;
end
@@ -693,160 +707,160 @@ module npu_core #(
);
npu_job_decoder u_job_decoder (
.clk_hp_i (clk_hp_i),
.rst_hp_n_i (rst_hp_n_i),
.clear_i (s_stop),
.block_new_i (block_new_i),
.pause_ok_o (s_dec_pause_ok),
.job_start_i (s_dec_job_start),
.job_base_i (launch_data_i[`APB4_NPU__LAUNCH_JOB_BASE+:32]),
.job_count_i (launch_data_i[`APB4_NPU__LAUNCH_JOB_COUNT+:16]),
.read_req_valid_o (s_dec_read_req_valid),
.read_req_ready_i (s_dec_read_req_ready),
.read_addr_o (s_dec_read_addr),
.read_bytes_o (s_dec_read_bytes),
.read_data_valid_i (s_dec_read_data_valid),
.read_data_ready_o (s_dec_read_data_ready),
.read_data_i (dma_read_data_i),
.read_last_i (dma_read_last_i),
.dma_read_busy_i (dma_read_busy_i),
.dma_fault_i (dma_fault_i),
.dma_fault_code_i (dma_fault_code_i),
.dma_fault_addr_i (dma_fault_addr_i),
.dma_fault_resp_i (dma_fault_resp_i),
.rec_valid_o (s_rec_valid),
.rec_ready_i (s_rec_ready),
.rec_opcode_o (s_rec_opcode),
.rec_h_o (s_rec_h),
.rec_w_o (s_rec_w),
.rec_cin_o (s_rec_cin),
.rec_cout_o (s_rec_cout),
.rec_oh_o (s_rec_oh),
.rec_ow_o (s_rec_ow),
.rec_input0_base_o (s_rec_input0_base),
.rec_output_base_o (s_rec_output_base),
.rec_weight_base_o (s_rec_weight_base),
.rec_param_base_o (s_rec_param_base),
.clk_hp_i (clk_hp_i),
.rst_hp_n_i (rst_hp_n_i),
.clear_i (s_stop),
.block_new_i (block_new_i),
.pause_ok_o (s_dec_pause_ok),
.job_start_i (s_dec_job_start),
.job_base_i (launch_data_i[`APB4_NPU__LAUNCH_JOB_BASE+:32]),
.job_count_i (launch_data_i[`APB4_NPU__LAUNCH_JOB_COUNT+:16]),
.read_req_valid_o (s_dec_read_req_valid),
.read_req_ready_i (s_dec_read_req_ready),
.read_addr_o (s_dec_read_addr),
.read_bytes_o (s_dec_read_bytes),
.read_data_valid_i (s_dec_read_data_valid),
.read_data_ready_o (s_dec_read_data_ready),
.read_data_i (dma_read_data_i),
.read_last_i (dma_read_last_i),
.dma_read_busy_i (dma_read_busy_i),
.dma_fault_i (dma_fault_i),
.dma_fault_code_i (dma_fault_code_i),
.dma_fault_addr_i (dma_fault_addr_i),
.dma_fault_resp_i (dma_fault_resp_i),
.rec_valid_o (s_rec_valid),
.rec_ready_i (s_rec_ready),
.rec_opcode_o (s_rec_opcode),
.rec_h_o (s_rec_h),
.rec_w_o (s_rec_w),
.rec_cin_o (s_rec_cin),
.rec_cout_o (s_rec_cout),
.rec_oh_o (s_rec_oh),
.rec_ow_o (s_rec_ow),
.rec_input0_base_o (s_rec_input0_base),
.rec_output_base_o (s_rec_output_base),
.rec_weight_base_o (s_rec_weight_base),
.rec_param_base_o (s_rec_param_base),
.rec_input0_row_bytes_o(s_rec_irow),
.rec_output_row_bytes_o(s_rec_orow),
.rec_kh_o (s_rec_kh),
.rec_kw_o (s_rec_kw),
.rec_sh_o (s_rec_sh),
.rec_sw_o (s_rec_sw),
.rec_pad_top_o (s_rec_pad_top),
.rec_pad_left_o (s_rec_pad_left),
.rec_input0_zero_o (s_rec_in0_zero),
.rec_tile_h_o (s_rec_tile_h),
.rec_tile_w_o (s_rec_tile_w),
.rec_k_slice_o (s_rec_k_slice),
.rec_input1_base_o (s_rec_input1_base),
.rec_kh_o (s_rec_kh),
.rec_kw_o (s_rec_kw),
.rec_sh_o (s_rec_sh),
.rec_sw_o (s_rec_sw),
.rec_pad_top_o (s_rec_pad_top),
.rec_pad_left_o (s_rec_pad_left),
.rec_input0_zero_o (s_rec_in0_zero),
.rec_tile_h_o (s_rec_tile_h),
.rec_tile_w_o (s_rec_tile_w),
.rec_k_slice_o (s_rec_k_slice),
.rec_input1_base_o (s_rec_input1_base),
.rec_input1_row_bytes_o(s_rec_input1_row_bytes),
.rec_input1_zero_o (s_rec_in1_zero),
.rec_output_zero_o (s_rec_out_zero),
.rec_act_min_o (s_rec_act_min),
.rec_act_max_o (s_rec_act_max),
.rec_weight_bytes_o(s_rec_weight_bytes),
.rec_param_bytes_o (s_rec_param_bytes),
.rec_desc_index_o (s_rec_desc_index),
.retired_i (s_dec_retired),
.all_done_o (s_dec_all_done),
.busy_o (s_dec_busy),
.cur_desc_index_o (s_dec_cur_index),
.progress_o (s_dec_progress),
.fault_req_o (s_dec_fault_req),
.fault_code_o (s_dec_fault_code),
.fault_addr_o (s_dec_fault_addr),
.fault_info_o (s_dec_fault_info),
.fault_desc_o (s_dec_fault_desc)
.rec_input1_zero_o (s_rec_in1_zero),
.rec_output_zero_o (s_rec_out_zero),
.rec_act_min_o (s_rec_act_min),
.rec_act_max_o (s_rec_act_max),
.rec_weight_bytes_o (s_rec_weight_bytes),
.rec_param_bytes_o (s_rec_param_bytes),
.rec_desc_index_o (s_rec_desc_index),
.retired_i (s_dec_retired),
.all_done_o (s_dec_all_done),
.busy_o (s_dec_busy),
.cur_desc_index_o (s_dec_cur_index),
.progress_o (s_dec_progress),
.fault_req_o (s_dec_fault_req),
.fault_code_o (s_dec_fault_code),
.fault_addr_o (s_dec_fault_addr),
.fault_info_o (s_dec_fault_info),
.fault_desc_o (s_dec_fault_desc)
);
npu_scheduler u_scheduler (
.clk_hp_i (clk_hp_i),
.rst_hp_n_i (rst_hp_n_i),
.clear_i (s_clear),
.stop_i (s_stop),
.block_new_i (block_new_i),
.pause_ok_o (s_sch_pause_ok),
.launch_i (s_sch_launch),
.timeout_cycles_i (launch_data_i[`APB4_NPU__LAUNCH_TIMEOUT_CYCLES+:32]),
.job_active_i (s_state_q == CoreRun),
.pause_active_i (pause_active_o),
.rec_valid_i (s_rec_valid),
.rec_ready_o (s_rec_ready),
.rec_opcode_i (s_rec_opcode),
.rec_h_i (s_rec_h),
.rec_w_i (s_rec_w),
.rec_cin_i (s_rec_cin),
.rec_cout_i (s_rec_cout),
.rec_oh_i (s_rec_oh),
.rec_ow_i (s_rec_ow),
.rec_input0_base_i (s_rec_input0_base),
.rec_output_base_i (s_rec_output_base),
.rec_weight_base_i (s_rec_weight_base),
.rec_param_base_i (s_rec_param_base),
.clk_hp_i (clk_hp_i),
.rst_hp_n_i (rst_hp_n_i),
.clear_i (s_clear),
.stop_i (s_stop),
.block_new_i (block_new_i),
.pause_ok_o (s_sch_pause_ok),
.launch_i (s_sch_launch),
.timeout_cycles_i (launch_data_i[`APB4_NPU__LAUNCH_TIMEOUT_CYCLES+:32]),
.job_active_i (s_state_q == CoreRun),
.pause_active_i (pause_active_o),
.rec_valid_i (s_rec_valid),
.rec_ready_o (s_rec_ready),
.rec_opcode_i (s_rec_opcode),
.rec_h_i (s_rec_h),
.rec_w_i (s_rec_w),
.rec_cin_i (s_rec_cin),
.rec_cout_i (s_rec_cout),
.rec_oh_i (s_rec_oh),
.rec_ow_i (s_rec_ow),
.rec_input0_base_i (s_rec_input0_base),
.rec_output_base_i (s_rec_output_base),
.rec_weight_base_i (s_rec_weight_base),
.rec_param_base_i (s_rec_param_base),
.rec_input0_row_bytes_i(s_rec_irow),
.rec_output_row_bytes_i(s_rec_orow),
.rec_kh_i (s_rec_kh),
.rec_kw_i (s_rec_kw),
.rec_sh_i (s_rec_sh),
.rec_sw_i (s_rec_sw),
.rec_pad_top_i (s_rec_pad_top),
.rec_pad_left_i (s_rec_pad_left),
.rec_input0_zero_i (s_rec_in0_zero),
.rec_tile_h_i (s_rec_tile_h),
.rec_tile_w_i (s_rec_tile_w),
.rec_k_slice_i (s_rec_k_slice),
.rec_input1_base_i (s_rec_input1_base),
.rec_kh_i (s_rec_kh),
.rec_kw_i (s_rec_kw),
.rec_sh_i (s_rec_sh),
.rec_sw_i (s_rec_sw),
.rec_pad_top_i (s_rec_pad_top),
.rec_pad_left_i (s_rec_pad_left),
.rec_input0_zero_i (s_rec_in0_zero),
.rec_tile_h_i (s_rec_tile_h),
.rec_tile_w_i (s_rec_tile_w),
.rec_k_slice_i (s_rec_k_slice),
.rec_input1_base_i (s_rec_input1_base),
.rec_input1_row_bytes_i(s_rec_input1_row_bytes),
.rec_input1_zero_i (s_rec_in1_zero),
.rec_output_zero_i (s_rec_out_zero),
.rec_act_min_i (s_rec_act_min),
.rec_act_max_i (s_rec_act_max),
.rec_weight_bytes_i (s_rec_weight_bytes),
.rec_param_bytes_i (s_rec_param_bytes),
.rec_desc_index_i (s_rec_desc_index),
.retired_o (s_sch_retired),
.completed_o (s_sch_completed),
.read_req_valid_o (s_sch_read_req_valid),
.read_req_ready_i (s_sch_read_req_ready),
.read_addr_o (s_sch_read_addr),
.read_bytes_o (s_sch_read_bytes),
.read_data_valid_i (s_sch_read_data_valid),
.read_data_ready_o (s_sch_read_data_ready),
.read_data_i (dma_read_data_i),
.read_keep_i (dma_read_keep_i),
.read_last_i (dma_read_last_i),
.write_req_valid_o (s_sch_write_req_valid),
.write_req_ready_i (dma_write_req_ready_i),
.write_addr_o (s_sch_write_addr),
.write_bytes_o (s_sch_write_bytes),
.write_data_valid_o (s_sch_write_data_valid),
.write_data_ready_i (dma_write_data_ready_i),
.write_data_o (s_sch_write_data),
.write_keep_o (s_sch_write_keep),
.write_last_o (s_sch_write_last),
.write_done_i (dma_write_done_i),
.dma_read_busy_i (dma_read_busy_i),
.dma_write_busy_i (dma_write_busy_i),
.dma_pause_ack_i (dma_pause_ack_i),
.dma_fault_i (dma_fault_i),
.dma_fault_code_i (dma_fault_code_i),
.dma_fault_addr_i (dma_fault_addr_i),
.dma_fault_resp_i (dma_fault_resp_i),
.dma_read_bytes_i (dma_read_bytes_i),
.dma_write_bytes_i (dma_write_bytes_i),
.dma_stall_cycles_i (dma_stall_cycles_i),
.progress_i (s_dec_progress),
.terminal_i (s_sch_terminal),
.counters_o (s_sch_counters),
.term_counters_o (s_sch_term_counters),
.fault_req_o (s_sch_fault_req),
.fault_code_o (s_sch_fault_code),
.fault_addr_o (s_sch_fault_addr),
.fault_info_o (s_sch_fault_info),
.fault_desc_o (s_sch_fault_desc),
.busy_o (s_sch_busy),
.drained_o (s_sch_drained)
.rec_input1_zero_i (s_rec_in1_zero),
.rec_output_zero_i (s_rec_out_zero),
.rec_act_min_i (s_rec_act_min),
.rec_act_max_i (s_rec_act_max),
.rec_weight_bytes_i (s_rec_weight_bytes),
.rec_param_bytes_i (s_rec_param_bytes),
.rec_desc_index_i (s_rec_desc_index),
.retired_o (s_sch_retired),
.completed_o (s_sch_completed),
.read_req_valid_o (s_sch_read_req_valid),
.read_req_ready_i (s_sch_read_req_ready),
.read_addr_o (s_sch_read_addr),
.read_bytes_o (s_sch_read_bytes),
.read_data_valid_i (s_sch_read_data_valid),
.read_data_ready_o (s_sch_read_data_ready),
.read_data_i (dma_read_data_i),
.read_keep_i (dma_read_keep_i),
.read_last_i (dma_read_last_i),
.write_req_valid_o (s_sch_write_req_valid),
.write_req_ready_i (dma_write_req_ready_i),
.write_addr_o (s_sch_write_addr),
.write_bytes_o (s_sch_write_bytes),
.write_data_valid_o (s_sch_write_data_valid),
.write_data_ready_i (dma_write_data_ready_i),
.write_data_o (s_sch_write_data),
.write_keep_o (s_sch_write_keep),
.write_last_o (s_sch_write_last),
.write_done_i (dma_write_done_i),
.dma_read_busy_i (dma_read_busy_i),
.dma_write_busy_i (dma_write_busy_i),
.dma_pause_ack_i (dma_pause_ack_i),
.dma_fault_i (dma_fault_i),
.dma_fault_code_i (dma_fault_code_i),
.dma_fault_addr_i (dma_fault_addr_i),
.dma_fault_resp_i (dma_fault_resp_i),
.dma_read_bytes_i (dma_read_bytes_i),
.dma_write_bytes_i (dma_write_bytes_i),
.dma_stall_cycles_i (dma_stall_cycles_i),
.progress_i (s_dec_progress),
.terminal_i (s_sch_terminal),
.counters_o (s_sch_counters),
.term_counters_o (s_sch_term_counters),
.fault_req_o (s_sch_fault_req),
.fault_code_o (s_sch_fault_code),
.fault_addr_o (s_sch_fault_addr),
.fault_info_o (s_sch_fault_info),
.fault_desc_o (s_sch_fault_desc),
.busy_o (s_sch_busy),
.drained_o (s_sch_drained)
);
end
endmodule
+1 -1
View File
@@ -27,7 +27,7 @@ module crypto_aes_sram_engine (
output logic [ 3:0] output_keep_o,
output logic output_last_o,
output logic busy_o,
done_o,
output logic done_o,
error_o,
output logic [31:0] bytes_in_o,
bytes_out_o,
+11 -11
View File
@@ -22,17 +22,17 @@ module apu_p9_formal_design (
output logic store_write,
output logic [13:0] store_addr
);
logic s_start_q;
(* anyseq *) logic s_abort;
(* anyseq *) logic s_dma_request_ready;
(* anyseq *) logic s_dma_valid;
(* anyseq *) logic s_dma_done;
(* anyseq *) logic s_dma_error;
(* anyseq *) logic [31:0] s_dma_data;
(* anyseq *) logic s_store_ready;
(* anyseq *) logic s_store_valid;
(* anyseq *) logic [31:0] s_store_data;
(* anyseq *) logic s_store_fault;
logic s_start_q;
(* anyseq *)logic s_abort;
(* anyseq *)logic s_dma_request_ready;
(* anyseq *)logic s_dma_valid;
(* anyseq *)logic s_dma_done;
(* anyseq *)logic s_dma_error;
(* anyseq *)logic [31:0] s_dma_data;
(* anyseq *)logic s_store_ready;
(* anyseq *)logic s_store_valid;
(* anyseq *)logic [31:0] s_store_data;
(* anyseq *)logic s_store_fault;
apu_kws_coeff_loader u_dut (
.clk_i (clk_i),
+13 -13
View File
@@ -2,24 +2,24 @@
// SPDX-License-Identifier: MulanPSL-2.0
module apu_p9_formal;
(* anyseq *) (* gclk *) reg clk_i;
wire rst_n_i;
wire f_past_valid;
wire busy;
wire valid;
wire lock;
(* anyseq *) (* gclk *)reg clk_i;
wire rst_n_i;
wire f_past_valid;
wire busy;
wire valid;
wire lock;
wire [31:0] actual_crc;
wire [63:0] coefficient_id;
wire [31:0] status;
wire [5:0] error_code;
wire done;
wire abort_done;
wire dma_request_valid;
wire [ 5:0] error_code;
wire done;
wire abort_done;
wire dma_request_valid;
wire [31:0] dma_request_address;
wire [31:0] dma_request_bytes;
wire store_active;
wire store_req;
wire store_write;
wire store_active;
wire store_req;
wire store_write;
wire [13:0] store_addr;
apu_p9_formal_design u_design (.*);
+3 -3
View File
@@ -252,14 +252,14 @@ $(FORMAL_DIR)/%/prove.sby: $(FORMAL_DIR)/%/design.v \
$(FORMAL_SBY_GENERATOR)
python3 $(FORMAL_SBY_GENERATOR) --top $(FORMAL_TARGET_TOP)_formal --input $< \
--properties $(FORMAL_PROPERTIES_SOURCE) $(FORMAL_PROPERTIES_DEFINE) --solver $(FORMAL_SOLVER) \
--mode $(if $(filter ga2d,$*),bmc,$(if $(filter dma npu_dma npu_context npu_control apu apu_codec apu_kws apu_p9 apu_primitives apu_sequencer $(FORMAL_APU_LOADER_TARGETS) $(FORMAL_APU_PRIMITIVE_TARGETS) gateway_a sdio onchip_ram,$*),bmc,prove)) --depth $(if $(filter ga2d,$*),$(FORMAL_GA2D_DEPTH),$(if $(filter pll_rcu,$*),$(FORMAL_PLL_RCU_DEPTH),$(if $(filter npu_dma,$*),$(FORMAL_NPU_DMA_DEPTH),$(if $(filter npu_context,$*),$(FORMAL_NPU_CONTEXT_DEPTH),$(if $(filter npu_control,$*),$(FORMAL_NPU_CONTROL_DEPTH),$(if $(filter dma,$*),$(FORMAL_DMA_DEPTH),$(if $(filter apu apu_codec apu_kws apu_p9 apu_primitives apu_sequencer $(FORMAL_APU_LOADER_TARGETS) $(FORMAL_APU_PRIMITIVE_TARGETS),$*),$(FORMAL_APU_TARGET_DEPTH),$(if $(filter gateway_a,$*),$(FORMAL_GATEWAY_A_DEPTH),$(if $(filter sdio,$*),$(FORMAL_SDIO_DEPTH),$(if $(filter opipsram,$*),$(FORMAL_OPIPSRAM_DEPTH),$(if $(filter ws2812,$*),$(FORMAL_WS2812_DEPTH),$(if $(filter i2c,$*),$(FORMAL_I2C_DEPTH),$(if $(filter clint,$*),$(FORMAL_CLINT_DEPTH),$(if $(filter psram,$*),$(FORMAL_PSRAM_DEPTH),$(FORMAL_DEPTH))))))))))))))) --output $@
--mode $(if $(filter ga2d,$*),bmc,$(if $(filter dma npu_dma npu_context npu_control apu apu_codec apu_kws apu_p9 apu_primitives apu_sequencer $(FORMAL_APU_LOADER_TARGETS) $(FORMAL_APU_PRIMITIVE_TARGETS) gateway_a sdio onchip_ram,$*),bmc,prove)) --depth $(if $(filter ga2d,$*),$(FORMAL_GA2D_DEPTH),$(if $(filter pll_rcu,$*),$(FORMAL_PLL_RCU_DEPTH),$(if $(filter npu_dma,$*),$(FORMAL_NPU_DMA_DEPTH),$(if $(filter npu_context,$*),$(FORMAL_NPU_CONTEXT_DEPTH),$(if $(filter npu_control,$*),$(FORMAL_NPU_CONTROL_DEPTH),$(if $(filter dma,$*),$(FORMAL_DMA_DEPTH),$(if $(filter apu apu_codec apu_kws apu_p9 apu_primitives apu_sequencer $(FORMAL_APU_LOADER_TARGETS) $(FORMAL_APU_PRIMITIVE_TARGETS),$*),$(FORMAL_APU_TARGET_DEPTH),$(if $(filter gateway_a,$*),$(FORMAL_GATEWAY_A_DEPTH),$(if $(filter sdio,$*),$(FORMAL_SDIO_DEPTH),$(if $(filter opipsram,$*),$(FORMAL_OPIPSRAM_DEPTH),$(if $(filter ws2812,$*),$(FORMAL_WS2812_DEPTH),$(if $(filter i2c,$*),$(FORMAL_I2C_DEPTH),$(if $(filter clint,$*),$(FORMAL_CLINT_DEPTH),$(if $(filter psram,$*),$(FORMAL_PSRAM_DEPTH),$(FORMAL_DEPTH))))))))))))))) --output $@
@if [ "$*" = opipsram ]; then sed -i '/^async2sync/i clk2fflogic' $@; fi
$(FORMAL_DIR)/%/cover.sby: $(FORMAL_DIR)/%/design.v \
$(FORMAL_SBY_GENERATOR)
python3 $(FORMAL_SBY_GENERATOR) --top $(FORMAL_TARGET_TOP)_formal --input $< \
--properties $(FORMAL_PROPERTIES_SOURCE) $(FORMAL_PROPERTIES_DEFINE) --solver $(FORMAL_SOLVER) \
--mode cover --depth $(if $(filter ga2d,$*),$(FORMAL_GA2D_COVER_DEPTH),$(if $(filter pll_rcu,$*),$(FORMAL_PLL_RCU_DEPTH),$(if $(filter npu_dma,$*),$(FORMAL_NPU_DMA_COVER_DEPTH),$(if $(filter npu_context,$*),$(FORMAL_NPU_CONTEXT_DEPTH),$(if $(filter npu_control,$*),$(FORMAL_NPU_CONTROL_DEPTH),$(if $(filter dma,$*),$(FORMAL_DMA_COVER_DEPTH),$(if $(filter apu apu_codec apu_kws apu_p9 apu_primitives apu_sequencer $(FORMAL_APU_LOADER_TARGETS) $(FORMAL_APU_PRIMITIVE_TARGETS),$*),$(FORMAL_APU_TARGET_COVER_DEPTH),$(if $(filter gateway_a,$*),$(FORMAL_GATEWAY_A_DEPTH),$(if $(filter sdio,$*),$(FORMAL_SDIO_COVER_DEPTH),$(if $(filter opipsram,$*),$(FORMAL_OPIPSRAM_DEPTH),$(if $(filter ws2812,$*),$(FORMAL_WS2812_DEPTH),$(if $(filter i2c,$*),$(FORMAL_I2C_DEPTH),$(if $(filter clint,$*),$(FORMAL_CLINT_DEPTH),$(if $(filter psram,$*),$(FORMAL_PSRAM_DEPTH),$(FORMAL_DEPTH))))))))))))))) \
--mode cover --depth $(if $(filter ga2d,$*),$(FORMAL_GA2D_COVER_DEPTH),$(if $(filter pll_rcu,$*),$(FORMAL_PLL_RCU_DEPTH),$(if $(filter npu_dma,$*),$(FORMAL_NPU_DMA_COVER_DEPTH),$(if $(filter npu_context,$*),$(FORMAL_NPU_CONTEXT_DEPTH),$(if $(filter npu_control,$*),$(FORMAL_NPU_CONTROL_DEPTH),$(if $(filter dma,$*),$(FORMAL_DMA_COVER_DEPTH),$(if $(filter apu apu_codec apu_kws apu_p9 apu_primitives apu_sequencer $(FORMAL_APU_LOADER_TARGETS) $(FORMAL_APU_PRIMITIVE_TARGETS),$*),$(FORMAL_APU_TARGET_COVER_DEPTH),$(if $(filter gateway_a,$*),$(FORMAL_GATEWAY_A_DEPTH),$(if $(filter sdio,$*),$(FORMAL_SDIO_COVER_DEPTH),$(if $(filter opipsram,$*),$(FORMAL_OPIPSRAM_DEPTH),$(if $(filter ws2812,$*),$(FORMAL_WS2812_DEPTH),$(if $(filter i2c,$*),$(FORMAL_I2C_DEPTH),$(if $(filter clint,$*),$(FORMAL_CLINT_DEPTH),$(if $(filter psram,$*),$(FORMAL_PSRAM_DEPTH),$(FORMAL_DEPTH))))))))))))))) \
$(if $(filter $(FORMAL_APU_P5_LOADER_TARGETS),$*),--skip $(FORMAL_APU_P5_LOADER_COVER_SKIP)) \
$(if $(filter $(FORMAL_COMPACT_COVER_TARGETS),$*),--no-vcd) --output $@
@if [ "$*" = opipsram ]; then sed -i '/^async2sync/i clk2fflogic' $@; fi
@@ -390,4 +390,4 @@ formal-doctor:
formal-clean:
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(FORMAL_DIR)
.PHONY: formal formal-bus formal-rib-adapter formal-rib2apb formal-sysctrl formal-pll-rcu formal-gpio formal-ws2812 formal-uart formal-i2c formal-timer formal-clint formal-dvp formal-i2s formal-psram formal-onchip-ram formal-opipsram formal-dma formal-ga2d formal-apu formal-apu-kws formal-apu-p9 formal-apu-loader formal-apu-loader-p5 formal-apu-sequencer formal-gateway-a formal-sdio formal-npu_dma formal-npu-context formal-npu-control formal-npu-p6 formal-doctor formal-clean
.PHONY: formal formal-bus formal-rib-adapter formal-rib2apb formal-sysctrl formal-pll-rcu formal-gpio formal-ws2812 formal-uart formal-i2c formal-timer formal-clint formal-dvp formal-i2s formal-psram formal-onchip-ram formal-opipsram formal-dma formal-ga2d formal-apu formal-apu-kws formal-apu-p9 formal-apu-loader formal-apu-loader-p5 formal-apu-sequencer formal-gateway-a formal-sdio formal-npu_dma formal-npu-context formal-npu-control formal-npu-p6 formal-doctor formal-clean
+16 -16
View File
@@ -186,7 +186,7 @@ CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/libgcc/muldi3.S
CRT_SRCS += $(ROOT_PATH)/crt/arch/riscv/libgcc/mulsi3.c
endif
INC_PATH := -I$(SW_BUILD_DIR)/include \
INC_PATH := -I$(SW_BUILD_DIR)/include \
-I$(MEMORY_MAP_C_DIR) \
-I$(SOC_TOPOLOGY_INCLUDE_DIR) \
-I$(USER_EXTENSIONS_DIR)/include \
@@ -200,28 +200,28 @@ INC_PATH := -I$(SW_BUILD_DIR)/include \
-I$(ROOT_PATH)/rtl/managed/clusterip/ps2/sw/include \
-I$(ROOT_PATH)/crt/include \
$(addprefix -I,$(APP_INC_DIRS))
SRC_PATH := $(CRT_SRCS) $(APP_SRCS)
LDS_PATH := $(ROOT_PATH)/crt/linker/$(LINK_TYPE).lds
MEMORY_REGIONS_LD := $(MEMORY_MAP_LINKER_DIR)/memory_regions.ld
VERSION_HEADER := $(SW_BUILD_DIR)/include/socver.h
SRC_PATH := $(CRT_SRCS) $(APP_SRCS)
LDS_PATH := $(ROOT_PATH)/crt/linker/$(LINK_TYPE).lds
MEMORY_REGIONS_LD := $(MEMORY_MAP_LINKER_DIR)/memory_regions.ld
VERSION_HEADER := $(SW_BUILD_DIR)/include/socver.h
CRYPTO_CONSTANTS_HEADER := $(SW_BUILD_DIR)/include/crypto_constants.h
FIRMWARE_ELF := $(SW_BUILD_DIR)/firmware
ASM_FIRMWARE_NAME ?= retrosoc_asm
SW_HEADERS := $(shell find $(ROOT_PATH)/crt/include $(ROOT_PATH)/app -type f \
FIRMWARE_ELF := $(SW_BUILD_DIR)/firmware
ASM_FIRMWARE_NAME ?= retrosoc_asm
SW_HEADERS := $(shell find $(ROOT_PATH)/crt/include $(ROOT_PATH)/app -type f \
\( -name '*.h' -o -name '*.hpp' \) 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/archinfo/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/archinfo/sw/include \
-type f -name '*.h' 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/crc/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/crc/sw/include \
-type f -name '*.h' 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/rng/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/rng/sw/include \
-type f -name '*.h' 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/rtc/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/rtc/sw/include \
-type f -name '*.h' 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/wdg/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/wdg/sw/include \
-type f -name '*.h' 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/pwm/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/pwm/sw/include \
-type f -name '*.h' 2>/dev/null)
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/ps2/sw/include \
SW_HEADERS += $(shell find $(ROOT_PATH)/rtl/managed/clusterip/ps2/sw/include \
-type f -name '*.h' 2>/dev/null)
$(VERSION_HEADER): FORCE_VERSION $(ROOT_PATH)/crt/ver.py $(ROOT_PATH)/crt/ver.tmpl
@@ -266,4 +266,4 @@ firmware: $(FIRMWARE_ELF)
firmware asm: | manifest
.PHONY: FORCE_VERSION
.PHONY: FORCE_VERSION
+3 -2
View File
@@ -123,8 +123,9 @@ SRAM CoreMark quick report into `meta/coremark.json`; it requires one valid
`COREMARK_RESULT` record and `COREMARK_PASS`. Both reports complement, rather
than replace, the common `SIM_TEST_PASS` simulation verdict.
`generate_vexiiriscv.py` verifies the locked VexiiRiscv revision and generates
the fixed HP core below `build/`; generated RTL is never tracked.
`generate_vexiiriscv.py` verifies the locked VexiiRiscv revision, rejects local
source changes before and after generation, and generates the fixed HP core
below `build/`; generated RTL is never tracked.
`setup_hp_linux.py` installs the locked OpenSBI, Linux, and Buildroot revisions
and can resume a checkout left without `HEAD` by an interrupted fetch.
`build_hp_linux.py` builds the RV64 `lp64d` userspace/OpenSBI image set with the repo-owned
+13 -4
View File
@@ -46,14 +46,22 @@ def locked_revision(lock_path: Path) -> str:
return source["revision"]
def validate_locked_source(source: Path, expected: str) -> str:
actual = git_revision(source)
if actual != expected:
raise ValueError(f"VexiiRiscv revision mismatch: expected {expected}, found {actual}")
status = git_status(source)
if status:
raise ValueError("VexiiRiscv source has local changes:\n" + "\n".join(status))
return actual
def generate(args: argparse.Namespace) -> None:
root = args.root.resolve()
source = args.source.resolve()
output = args.output.resolve()
expected = locked_revision(args.lock.resolve())
actual = git_revision(source)
if actual != expected:
raise ValueError(f"VexiiRiscv revision mismatch: expected {expected}, found {actual}")
actual = validate_locked_source(source, expected)
scala_dir = root / "scripts" / "vexiiriscv"
output.mkdir(parents=True, exist_ok=True)
@@ -81,6 +89,7 @@ def generate(args: argparse.Namespace) -> None:
generated = output / "vexii_riscv_hp_generated.v"
if not generated.is_file():
raise FileNotFoundError(f"VexiiRiscv generator did not create {generated}")
validate_locked_source(source, expected)
submodules = run(["git", "submodule", "status", "--recursive"], source).splitlines()
manifest = {
@@ -91,7 +100,7 @@ def generate(args: argparse.Namespace) -> None:
"physical_address_width": 32,
"mmu": "sv39",
"vexiiriscv_revision": actual,
"source_status": git_status(source),
"source_status": [],
"submodules": submodules,
"generator": str((scala_dir / "GenerateRetroSocHp.scala").relative_to(root)),
"files": {generated.name: sha256(generated)},
+2 -2
View File
@@ -33,9 +33,9 @@ CI_SMOKE_SIM_VALUES = (
CI_SMOKE_SDRAM_SIM_VALUES = (
CI_SMOKE_APP_VALUE,
"LINK_TYPE=ld2_sdram",
# Hosted Verilator executes the expanded GA2D acceptance workload more
# Hosted Verilator executes the expanded peripheral acceptance workload
# slowly when LP code and accelerator traffic share the SDRAM target.
"SOC_SIM_TIME=1800",
"SOC_SIM_TIME=3600",
*CI_SMOKE_VERILATOR_VALUES,
)
RTL_LINT_VALUES = ("SIMU=VERILATOR", "HAVE_SVA=YES", "rtl-lint")
+1 -1
View File
@@ -68,7 +68,7 @@ module apu_kws_coeff_fixture (
);
initial begin
initialized_o = 1'b0;
initialized_o = 1'b0;
s_loader_active = 1'b0;
s_loader_req = 1'b0;
s_loader_addr = 14'd0;
+2 -2
View File
@@ -52,10 +52,10 @@ module apu_kws_engine_tb;
logic [ 5:0][ 3:0] scratch_write_strb;
logic scratch_access_err;
logic coeff_front_req, coeff_front_ready, coeff_front_resp_valid, coeff_front_resp_ready;
logic [3:0] coeff_front_kind;
logic [ 3:0] coeff_front_kind;
logic [13:0] coeff_front_index;
logic [63:0] coeff_front_data;
logic coeff_front_fault;
logic coeff_front_fault;
logic coeff_infer_req, coeff_infer_ready, coeff_infer_resp_valid, coeff_infer_resp_ready;
logic [ 6:0] coeff_infer_index;
logic [31:0] coeff_infer_data;
+2 -2
View File
@@ -58,10 +58,10 @@ module apu_p7_accuracy_tb;
logic [ 5:0][ 3:0] scratch_write_strb;
logic scratch_access_err;
logic coeff_front_req, coeff_front_ready, coeff_front_resp_valid, coeff_front_resp_ready;
logic [3:0] coeff_front_kind;
logic [ 3:0] coeff_front_kind;
logic [13:0] coeff_front_index;
logic [63:0] coeff_front_data;
logic coeff_front_fault;
logic coeff_front_fault;
logic coeff_infer_req, coeff_infer_ready, coeff_infer_resp_valid, coeff_infer_resp_ready;
logic [ 6:0] coeff_infer_index;
logic [31:0] coeff_infer_data;
+4 -4
View File
@@ -61,16 +61,16 @@ module apu_p7_frontend_dump_tb;
logic [ 5:0][ 3:0] scratch_write_strb;
logic scratch_access_err;
logic coeff_front_req, coeff_front_ready, coeff_front_resp_valid, coeff_front_resp_ready;
logic [3:0] coeff_front_kind;
logic [ 3:0] coeff_front_kind;
logic [13:0] coeff_front_index;
logic [63:0] coeff_front_data;
logic coeff_front_fault;
logic coeff_front_fault;
logic coeff_infer_req, coeff_infer_ready, coeff_infer_resp_valid, coeff_infer_resp_ready;
logic [ 6:0] coeff_infer_index;
logic [31:0] coeff_infer_data;
logic coeff_infer_fault, coeff_initialized;
int unsigned debug_commit_count;
logic [31:0] pcm_mem[0:PcmWords-1];
int unsigned debug_commit_count;
logic [31:0] pcm_mem [0:PcmWords-1];
always #5 clk_i = ~clk_i;
+18 -18
View File
@@ -109,24 +109,24 @@ module apu_p9_storage_tb;
initial begin
loader_active = 1'b0;
loader_req = 1'b0;
loader_write = 1'b1;
loader_addr = 14'd0;
loader_data = 32'd0;
front_req = 1'b0;
front_kind = 4'd0;
front_index = 14'd0;
loader_req = 1'b0;
loader_write = 1'b1;
loader_addr = 14'd0;
loader_data = 32'd0;
front_req = 1'b0;
front_kind = 4'd0;
front_index = 14'd0;
front_consume = 1'b0;
infer_req = 1'b0;
infer_index = 7'd0;
infer_req = 1'b0;
infer_index = 7'd0;
infer_consume = 1'b0;
memo_clear = 1'b0;
memo_lookup = 1'b0;
memo_insert = 1'b0;
memo_addr = 13'd0;
memo_key = 64'd0;
memo_clear = 1'b0;
memo_lookup = 1'b0;
memo_insert = 1'b0;
memo_addr = 13'd0;
memo_key = 64'd0;
repeat (3) @(negedge clk_i);
rst_n_i = 1'b1;
rst_n_i = 1'b1;
loader_active = 1'b1;
write_coefficient(14'(1024 + 5), 32'h1111_1111);
@@ -159,9 +159,9 @@ module apu_p9_storage_tb;
front_consume = 1'b0;
infer_consume = 1'b0;
front_kind = 4'd9;
front_index = 14'd0;
front_req = 1'b1;
front_kind = 4'd9;
front_index = 14'd0;
front_req = 1'b1;
@(negedge clk_i);
front_req = 1'b0;
wait (front_valid);
File diff suppressed because it is too large. Load diff
+49 -5
View File
@@ -58,9 +58,8 @@ def test_mailbox_purposes_follow_registers_in_the_actual_write_order():
"message->code = *rs_hp_mailbox_register(RS_HP_MAILBOX_HP_ARG0_OFFSET);", "field semantics"),
(br.MAILBOX_SOURCE, "`APB4_HP_MAILBOX__HP_DOORBELL: s_lp_intr_state_d = 1'b1;",
"`APB4_HP_MAILBOX__HP_DOORBELL: s_hp_intr_state_d = 1'b1;", "LP interrupt"),
(br.READY_SOURCE, "0x10019024 32 0x4C4E5801", "0x10019024 32 0x4C4E5802", "sequence"),
(br.READY_SOURCE, " ;;", " start_ga2d_responder\n ;;", "ready-only"),
(br.READY_SOURCE, " ;;", " devmem 0x10019020 32 2\n ;;", "sequence"),
(br.READY_SOURCE, "for (;;) {", "return 0;\n for (;;) {", "ready-only"),
(br.READY_SOURCE, "mailbox[11] = 1U;", "mailbox[8] = 2U;\n mailbox[11] = 1U;", "sequence"),
])
def test_mailbox_or_service_drift_requires_new_review(source_tree, relative, old, new, match):
replace(source_tree, relative, old, new)
@@ -68,9 +67,54 @@ def test_mailbox_or_service_drift_requires_new_review(source_tree, relative, old
br.ready_mailbox(source_tree)
@pytest.mark.parametrize("old,new", [
("mailbox[8] = (error == 0U) ? 1U : 3U;", "mailbox[8] = (error == 0U) ? 2U : 3U;"),
("UINT32_C(0x4C4E5801) : error", "UINT32_C(0x4C4E5802) : error"),
("mailbox[10] = 1U;", "mailbox[10] = 2U;"),
("mailbox[11] = 1U;", "mailbox[11] = 2U;"),
])
def test_each_linux_ready_value_must_match_the_lp_contract(source_tree, old, new):
replace(source_tree, br.READY_SOURCE, old, new)
with pytest.raises(ValueError, match="values differ"):
br.ready_mailbox(source_tree)
@pytest.mark.parametrize("old,new", [
("RS_HP_BOOT_READY_EVENT UINT32_C(1)",
"RS_HP_BOOT_READY_EVENT UINT32_C(2)"),
("RS_HP_BOOT_READY_ARG UINT32_C(0x4C4E5801)",
"RS_HP_BOOT_READY_ARG UINT32_C(0x4C4E5802)"),
("RS_HP_BOOT_MAILBOX_READY_SEQUENCE UINT32_C(1)",
"RS_HP_BOOT_MAILBOX_READY_SEQUENCE UINT32_C(2)"),
])
def test_each_lp_ready_constant_must_match_the_linux_helper(source_tree, old, new):
replace(source_tree, br.BOOT_SOURCE, old, new)
with pytest.raises(ValueError, match="values differ"):
br.ready_mailbox(source_tree)
def test_coordinated_hal_rtl_offset_change_cannot_hide_a_stale_linux_helper(source_tree):
replace(source_tree, br.HAL_SOURCE,
"RS_HP_MAILBOX_HP_EVENT_OFFSET UINT32_C(0x020)",
"RS_HP_MAILBOX_HP_EVENT_OFFSET UINT32_C(0x024)")
replace(source_tree, br.REGISTER_SOURCE,
"`define APB4_HP_MAILBOX__HP_EVENT 12'h020",
"`define APB4_HP_MAILBOX__HP_EVENT 12'h024")
with pytest.raises(ValueError, match="addresses differ"):
br.ready_mailbox(source_tree)
def test_rtl_doorbell_offset_change_cannot_hide_a_stale_linux_helper(source_tree):
replace(source_tree, br.REGISTER_SOURCE,
"`define APB4_HP_MAILBOX__HP_DOORBELL 12'h02C",
"`define APB4_HP_MAILBOX__HP_DOORBELL 12'h050")
with pytest.raises(ValueError, match="addresses differ"):
br.ready_mailbox(source_tree)
@pytest.mark.parametrize("old,new,match", [
("timeout < RS_HP_BOOT_EVENT_TIMEOUT; ++timeout", "; ++timeout", "bounded poll"),
("if (message.sequence == sequence)", "if (message.sequence != sequence)", "token/error"),
("if (status == 1U)", "if (status != 1U)", "token/error"),
("if (!s_hp_boot_ga2d_owned_by_hp)", "if (s_hp_boot_ga2d_owned_by_hp)", "reset ownership"),
("rs_hp_boot_fail(UINT8_C(13));", "rs_hp_boot_fail(UINT8_C(11));", "completion condition"),
("cache_clean_completed = true;", "cache_clean_completed = false;", "phase or ordering"),
@@ -144,7 +188,7 @@ def test_mailbox_address_is_derived_from_the_memory_map(source_tree):
mailbox = next(row for row in source["regions"] if row["symbol"] == "APB4_HP_MAILBOX")
mailbox["base"] = "0x1001A000"
path.write_text(json.dumps(source), encoding="utf-8")
replace(source_tree, br.READY_SOURCE, "0x100190", "0x1001A0")
replace(source_tree, br.READY_SOURCE, "0x10019000", "0x1001A000")
rows = br.ready_mailbox(source_tree)
assert rows[0]["address"] == "0x1001A020"
assert rows[0]["purpose"] == "Linux-ready event"
+10
View File
@@ -83,6 +83,7 @@ def test_protocol_field_order_is_checked_even_with_complete_coverage(data):
("scripts/apu_isa.py", "(self.dst, 4, 48)", "(self.dst, 4, 47)"),
("scripts/apu_isa.py", "APUMC_MAX_INSTRUCTIONS = APUMC_MAX_INSTRUCTIONS_V1", "APUMC_MAX_INSTRUCTIONS = 4096"),
("app/ports/linux/linux/retrosoc_hp.dts", "riscv,cbom-block-size = <64>", "riscv,cbom-block-size = <128>"),
("rtl/ip/security/apb4_crypto.sv", "logic [31:0] s_wdata;", "logic [63:0] s_wdata;"),
])
def test_source_drift_requires_diagram_review(source_tree, data, relative, old, new):
replace(source_tree, relative, old, new)
@@ -90,6 +91,15 @@ def test_source_drift_requires_diagram_review(source_tree, data, relative, old,
dr.collect_diagrams(source_tree, SPEC, data["regions"], data["system_reference"])
def test_rsa_limb_width_is_independent_of_dma_alignment(source_tree, data):
replace(source_tree, "crt/include/retrosoc/hal/crypto_regs.h",
"RS_CRYPTO_DMA_ALIGNMENT 4U", "RS_CRYPTO_DMA_ALIGNMENT 8U")
diagrams = dr.collect_diagrams(source_tree, SPEC, data["regions"], data["system_reference"])
assert [(row["depth"], row["bits"]) for row in diagrams["storage"]["rsa-vectors"]["stores"]] == [
(64, 32), (64, 32), (64, 32), (64, 32)
]
@pytest.mark.parametrize("mutation", ["node", "port", "endpoint", "direction", "width", "binding", "duplicate-edge"])
def test_circuit_records_reject_invented_or_inconsistent_connections(mutation):
circuit = copy.deepcopy(SPEC["circuits"]["uart0"])
+13 -3
View File
@@ -9,13 +9,23 @@ from publications.environment_reference import ENVIRONMENT_SOURCES, development_
ROOT = Path(__file__).resolve().parents[1]
def test_environment_reports_current_locked_runtime_versions():
def test_environment_reports_current_locked_launcher_and_runtime_versions():
result = development_environment(ROOT)
assert (result["platform"], result["ubuntu"], result["python"], result["java"], result["sbt"]) == (
"Linux x86_64", "22.04", "3.10", "17", "1.10.0")
assert (result["platform"], result["ubuntu"], result["python"], result["java"],
result["sbt_launcher"]) == (
"Linux x86_64", "22.04", "3.10", "17", "2.0.5")
assert not {"passed", "qualified", "performance"} & result.keys()
def test_environment_labels_sbt_as_a_launcher():
section = (ROOT / "publications/datasheets/sections/development-environment.typ").read_text(
encoding="utf-8"
)
assert "SBT launcher #environment.sbt_launcher" in section
assert "version is not an engine-version claim" in section
assert "#environment.sbt toolchain" not in section
@pytest.mark.parametrize("path,old,new,reason", [
("docker/Dockerfile", "openjdk-17-jre-headless", "openjdk-21-jre-headless", "runtime/platform"),
("flake.nix", "python310Full", "python3Full", "runtime/platform"),
+1
View File
@@ -116,6 +116,7 @@ def test_storage_geometry_preserves_product_overrides_and_sidebands(diagrams):
assert [(s["depth"], s["bits"]) for s in stores["dma-channel-fifos"]["stores"]] == [(32, 32)]
assert [(s["depth"], s["bits"]) for s in stores["sdio-pio"]["stores"]] == [(4, 36), (1, 32)]
assert [(s["depth"], s["bits"]) for s in stores["apu-fifos"]["stores"]] == [(64, 41), (64, 41)]
assert [(s["depth"], s["bits"]) for s in stores["rsa-vectors"]["stores"]] == [(64, 32)] * 4
assert [(s["depth"], s["bits"]) for s in stores["opi-lines"]["stores"]] == [(4, 256)]
assert sum(row["bytes"] for row in stores["apu-local"]["ranges"]) == 114688
assert stores["linker-ld2_psram"]["stack_region"] == "PSRAM"
+33 -3
View File
@@ -114,9 +114,12 @@ def test_composite_fields_and_multiline_capability_keep_the_real_layout(referenc
assert next(f for f in apu["fields"] if f["name"] == "CODE")["msb"] == 6
for item in reference.values():
for register in item["registers"]:
assert all(
"BEGIN" not in f["name"] and ";" not in f["name"] for f in register["fields"]
)
for field in register["fields"]:
assert ";" not in field["name"]
if "BEGIN" in field["name"]:
assert (item["id"], register["key"], field["name"]) == (
"crypto", "main.MEM_CONTROL", "BEGIN"
)
def test_read_predicate_is_not_mistaken_for_a_field_assignment():
@@ -133,6 +136,33 @@ def test_secret_apertures_do_not_claim_readback(reference):
assert "PSLVERR" in entry["description"]
def test_crypto_interrupt_registers_publish_all_six_events(reference):
registers = {entry["key"]: entry for entry in reference["crypto"]["registers"]}
expected = ["AES_DONE", "SHA_DONE", "RSA_DONE", "ERROR", "ZEROIZED", "MEMORY_READY"]
for key in ("main.IRQ_STATE", "main.IRQ_ENABLE", "main.IRQ_TEST"):
fields = registers[key]["fields"]
assert [field["name"] for field in fields[:6]] == expected
assert [(field["lsb"], field["msb"]) for field in fields[:6]] == [
(bit, bit) for bit in range(6)
]
assert (fields[6]["name"], fields[6]["lsb"], fields[6]["msb"]) == (
"Reserved", 6, 31
)
def test_crypto_lifecycle_annotations_preserve_security_boundaries(reference):
registers = {entry["key"]: entry for entry in reference["crypto"]["registers"]}
mem_status = {field["name"]: field for field in registers["main.MEM_STATUS"]["fields"]}
lock_description = mem_status["TABLE_LOCKED"]["description"]
assert "hard/PCLK reset" in lock_description
assert "zeroize does not unlock" in lock_description
irq_test = {field["name"]: field for field in registers["main.IRQ_TEST"]["fields"]}
test_description = irq_test["MEMORY_READY"]["description"]
assert "interrupt-path testing" in test_description
assert "not initialization or physical-erasure completion evidence" in test_description
def test_exact_register_description_wins_over_grouped_name_fragments(reference):
status = next(r for r in reference["xpi"]["registers"] if r["key"] == "main.STATUS")
assert "enable/busy/FIFO" in status["description"]
+25 -6
View File
@@ -37,6 +37,7 @@ from scripts.development_environment import ( # noqa: E402
write_stamp,
)
from scripts.generate_mpw import render_active_manifest, validate_extension_bindings # noqa: E402
from scripts import generate_vexiiriscv # noqa: E402
from scripts.install_toolchain import make_tree_world_readable, safe_extract # noqa: E402
from scripts.package import make_sbom # noqa: E402
from scripts.prepare_mpw import patch_serv # noqa: E402
@@ -1097,10 +1098,10 @@ def test_dependency_lock_and_config_key_include_a_fixed_timestamp(tmp_path: Path
assert lock["container_images"]["ubuntu_22_04"]["image"] == "ubuntu"
assert lock["nix_inputs"]["nixpkgs"]["revision"] == "50ab793786d9de88ee30ec4e4c24fb4236fc2674"
assert lock["toolchains"]["ubuntu-22.04"]["sbt"] == {
"version": "1.10.0",
"url": "https://github.com/sbt/sbt/releases/download/v1.10.0/sbt-1.10.0.tgz",
"sha256": "154b7de6c19207c73d0a304f901c8c4b6ead9a9c3a99a98a9d72ac19419d2640",
"archive": "sbt-1.10.0.tgz",
"version": "2.0.5",
"url": "https://github.com/sbt/sbt/releases/download/v2.0.5/sbt-2.0.5.tgz",
"sha256": "2a53c95403cb7fccd5da05d48cfe03ff4be573a3f3d0295a41963b109e756a18",
"archive": "sbt-2.0.5.tgz",
"path": "sbt/bin",
"download_timeout_seconds": 600,
"resume": True,
@@ -1527,7 +1528,7 @@ def test_behavioral_only_excludes_synthesis_and_netlist_consumers() -> None:
def test_hosted_regression_keeps_tools_but_skips_synthesis_execution() -> None:
workflow = (ROOT / ".github/workflows/_regression.yml").read_text(encoding="utf-8")
assert "default: verilator sv2v iverilog yosys opensta openocd riscv_gnu" in workflow
assert "default: verilator sv2v iverilog yosys opensta openocd sbt riscv_gnu" in workflow
assert "SIMU=IVERILOG SYNTH=YOSYS STA=NONE doctor" in workflow
assert "--behavioral-only" in workflow
@@ -1538,6 +1539,7 @@ def test_hosted_smoke_formal_check_is_doctor_only() -> None:
software_makefile = (ROOT / "rtl/mk/software.mk").read_text(encoding="utf-8")
assert "timeout_minutes: 60" in smoke
assert "toolset: verilator sv2v iverilog yosys sby bitwuzla sbt riscv_gnu" in smoke
assert "formal_checks: true" in smoke
assert "make CONFIG=${{ inputs.profile }} formal-doctor" in workflow
assert "make CONFIG=${{ inputs.profile }} formal\n" not in workflow
@@ -1545,6 +1547,23 @@ def test_hosted_smoke_formal_check_is_doctor_only() -> None:
assert "$(DUMP) -D" not in software_makefile
@pytest.mark.parametrize("revision,status,match", [
("different", [], "revision mismatch"),
("expected", [" M tracked.scala", "?? local/"], "local changes"),
])
def test_vexii_generation_rejects_unlocked_or_dirty_sources(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
revision: str,
status: list[str],
match: str,
) -> None:
monkeypatch.setattr(generate_vexiiriscv, "git_revision", lambda _source: revision)
monkeypatch.setattr(generate_vexiiriscv, "git_status", lambda _source: status)
with pytest.raises(ValueError, match=match):
generate_vexiiriscv.validate_locked_source(tmp_path, "expected")
def test_pdk_pr_regressions_cover_firmware_rtl_and_selected_netlist_target() -> None:
assert set(PDK_PR_PROFILES) == {"GF180", "IHP130", "ICS55", "SKY130"}
for pdk, profile in PDK_PR_PROFILES.items():
@@ -1564,7 +1583,7 @@ def test_pdk_pr_regressions_cover_firmware_rtl_and_selected_netlist_target() ->
else:
assert "LINK_TYPE=ld2_sdram" in verilator_values
assert "VERILATOR_SIM_ARGS=--fast-flash" in verilator_values
assert "SOC_SIM_TIME=1800" in verilator_values
assert "SOC_SIM_TIME=3600" in verilator_values
assert "HAVE_CSR=YES" in verilator_values
assert any("SIMU=IVERILOG" in values and "sim-asm" in values for values in command_values)
assert any("SYNTH=YOSYS" in values and "synth" in values for values in command_values)