feat: add test status handling to sysctrl and integrate with simulation framework

- Introduced test status signals (test_done_o, test_pass_o, test_code_o) in sysctrl interface and module.
- Updated memory map to include TEST_STATUS offset.
- Enhanced retrosoc_tb to monitor test completion and report results.
- Modified Emulator to handle test status and return appropriate exit codes.
- Updated formal verification to include assertions for test status.
- Added CoreMark log parsing script and integrated it into the regression tests.
- Implemented tests for test status handling in sysctrl_fault_tb.
- Adjusted simulation success and failure markers in various scripts and tests.
- Ensured compatibility with existing performance logging and regression testing frameworks.
This commit is contained in:
maksyuki committed 2026-08-06 13:23:16 +08:00
1 parent be2f351927
commit 99d4618cc2
45 files changed
+1209 -81

No files matched your search

+20
View File
@@ -143,6 +143,26 @@ module sysctrl_fault_tb;
$fatal(1, "user core stop state was not recorded");
end
read_register(32'h1000_B084, read_data);
if (read_data !== 32'h0000_0000) begin
$fatal(1, "test status did not reset");
end
write_register(32'h1000_B084, 32'h0000_5A01);
read_register(32'h1000_B084, read_data);
if (read_data !== 32'h0000_0000) begin
$fatal(1, "invalid test status write was accepted");
end
write_register(32'h1000_B084, 32'h8000_5A01);
read_register(32'h1000_B084, read_data);
if (read_data !== 32'h8000_5A01) begin
$fatal(1, "test pass status was not recorded");
end
write_register(32'h1000_B084, 32'h8000_0B00);
read_register(32'h1000_B084, read_data);
if (read_data !== 32'h8000_5A01) begin
$fatal(1, "terminal test status was overwritten");
end
$display("sysctrl fault and user core control test passed");
$finish;
end
+2
View File
@@ -64,10 +64,12 @@ def test_generated_artifacts_share_the_capacity_baseline(tmp_path: Path) -> None
assert "RS_SOC_HAS_SRAM 1U" in header
assert "SOC_SYSCTRL_PLL_CFG_OFFSET 32'h00000008" in rtl
assert "SOC_SYSCTRL_PLL_STATUS_OFFSET 32'h0000001C" in rtl
assert "SOC_SYSCTRL_TEST_STATUS_OFFSET 32'h00000084" in rtl
assert "SOC_ADDR_IS_RIBP(addr)" in rtl
assert "SOC_ADDR_IS_NMI" not in rtl
assert "RS_SOC_SYSCTRL_PLL_CFG_OFFSET UINT32_C(0x00000008)" in header
assert "RS_SOC_SYSCTRL_PLL_STATUS_OFFSET UINT32_C(0x0000001C)" in header
assert "RS_SOC_SYSCTRL_TEST_STATUS_OFFSET UINT32_C(0x00000084)" in header
assert "PSRAM (wxa!ri) : ORIGIN = 0x40000000, LENGTH = 0x00800000" in linker
+40
View File
@@ -2,6 +2,7 @@
from __future__ import annotations
from scripts.parse_coremark_log import parse_log as parse_coremark_log
from scripts.parse_performance_log import parse_log
@@ -51,3 +52,42 @@ def test_parse_log_rejects_report_with_performance_failure() -> None:
assert report["status"] == "failed"
assert report["failure_marker"] is True
def test_parse_coremark_quick_report() -> None:
report = parse_coremark_log(
"COREMARK_RESULT mode=quick qualified=0 memory=sram iterations=4 cycles=2000 "
"cpu_hz=72000000\nCOREMARK_PASS\n"
)
assert report["status"] == "passed"
assert report["results"] == [
{
"coremark_per_mhz": "2000.000",
"cpu_hz": 72000000,
"cycles": 2000,
"iterations": 4,
"memory": "sram",
"mode": "quick",
"qualified": False,
}
]
def test_parse_coremark_rejects_failure_or_non_sram_result() -> None:
report = parse_coremark_log(
"COREMARK_RESULT mode=quick qualified=0 memory=sram iterations=36 cycles=1800 "
"cpu_hz=72000000\nCOREMARK_FAIL result=1\n"
)
assert report["status"] == "failed"
assert report["failure_marker"] is True
try:
parse_coremark_log(
"COREMARK_RESULT mode=quick qualified=0 memory=psram iterations=36 cycles=1800 "
"cpu_hz=72000000\nCOREMARK_PASS\n"
)
except ValueError as error:
assert "SRAM" in str(error)
else:
raise AssertionError("non-SRAM CoreMark result was accepted")
+37 -2
View File
@@ -256,6 +256,8 @@ def test_sysctrl_formal_properties_use_exported_user_core_shape() -> None:
assert "`USER_CORE_COUNT" not in properties
assert "rib_wdata[4:0] < user_core_count" in properties
assert "user_reset == user_reset_mask" in properties
assert "SYSCTRL_TEST_STATUS_OFFSET" in properties
assert "test_done" in design
def test_sby_config_uses_prove_and_cover_with_bitwuzla(tmp_path: Path) -> None:
@@ -1143,7 +1145,7 @@ def test_simulation_success_marker_and_failure_detection(tmp_path: Path) -> None
log = tmp_path / "sim.log"
result = tmp_path / "result.json"
log.write_text(
"retroSoC: A Customized ASIC for Retro Stuff\nSimulation complete\n",
"SIM_TEST_PASS code=0\nSimulation complete\n",
encoding="utf-8",
)
run(
@@ -1157,7 +1159,7 @@ def test_simulation_success_marker_and_failure_detection(tmp_path: Path) -> None
assert json.loads(result.read_text(encoding="utf-8"))["status"] == "passed"
log.write_text(
"retroSoC: A Customized ASIC for Retro Stuff\nTEST FAILED\n",
"SIM_TEST_PASS code=0\nSIM_TEST_FAIL code=1\n",
encoding="utf-8",
)
failed = subprocess.run(
@@ -1375,6 +1377,39 @@ def test_fatfs_update_reextracts_downloaded_archive(tmp_path: Path) -> None:
assert (source / "ff.c").read_text(encoding="utf-8") == "new archive contents\n"
def test_coremark_setup_patch_is_idempotent(tmp_path: Path) -> None:
module_path = ROOT / "app/setup.py"
spec = importlib.util.spec_from_file_location("retrosoc_app_setup", module_path)
assert spec is not None and spec.loader is not None
app_setup = importlib.util.module_from_spec(spec)
spec.loader.exec_module(app_setup)
coremark = tmp_path / "coremark"
coremark.mkdir()
(coremark / "coremark.h").write_text('#include "core_portme.h"\n', encoding="utf-8")
(coremark / "core_main.c").write_text(
"/* Function: main */\nmain(void) {\n"
" if (time_in_secs(total_time) < 10) {\n }\n"
" return MAIN_RETURN_VAL;\n}\n",
encoding="utf-8",
)
previous_coremark_dir = app_setup.COREMARK_DIR
try:
app_setup.COREMARK_DIR = coremark
app_setup.patch_coremark()
first = (coremark / "core_main.c").read_text(encoding="utf-8")
app_setup.patch_coremark()
second = (coremark / "core_main.c").read_text(encoding="utf-8")
finally:
app_setup.COREMARK_DIR = previous_coremark_dir
assert first == second
assert "core_main(void)" in first
assert "COREMARK_MIN_RUN_SECS" in first
assert "#if COREMARK_MIN_RUN_SECS > 0" in first
assert "return total_errors == 0 ? 0 : 1;" in first
def test_ci_actions_are_pinned_to_commits() -> None:
action_files = [
*sorted((ROOT / ".github/workflows").glob("*.yml")),