mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
Add optional Tiny NSS1 PSRAM initialization, identity and geometry checks, mapped CPU/DMA workload coverage, and retained pin-level device verification. Harden shared XPI byte lanes, burst boundaries, response completion and timeout behavior while preserving NOR/SRAM-only boot and Mini compatibility.\n\nValidation: focused P8/XPI tests, ICS55 and IHP130 Verilator P8 replays, Tiny netlist boot, synthesis and observational STA completed. Full long-running Icarus firmware remains deferred to final Tiny qualification.
64 lines
2.6 KiB
Python
64 lines
2.6 KiB
Python
"""Reject incomplete P8 transport/optional-device evidence."""
|
|
import pytest
|
|
from pathlib import Path
|
|
|
|
from scripts.tiny_r2_p8 import measurements
|
|
|
|
CONFIG = {"PDK": "IHP130", "EXT_CLK_HZ": "24000000"}
|
|
|
|
|
|
@pytest.fixture
|
|
def valid_log():
|
|
return "\n".join([
|
|
"P8_TRANSPORT sys_hz=24000000 mem_hz=24000000 bytes=1024 burst=4 "
|
|
"isolated_cycles=24000 contended_cycles=48000 progress=10",
|
|
*[f"P8_XPI_WINDOW index={i} mem_cycles=24000 "
|
|
f"write_bytes={1024 if i % 2 == 0 else 0} read_bytes={0 if i % 2 == 0 else 1024} "
|
|
"aw_max=10 w_max=20 ar_max=30 b_max=40 r_max=50" for i in range(4)],
|
|
"P8_RESULT code=0 profiles=1", "SIM_TEST_PASS Tiny cycles=100000",
|
|
])
|
|
|
|
|
|
def test_p8_measurement_units(valid_log):
|
|
result = measurements(valid_log, CONFIG)
|
|
assert result["profiles"][0]["isolated_bytes_per_second"] == 1024000
|
|
assert result["profiles"][0]["contended_bytes_per_second"] == 512000
|
|
assert result["windows"][0]["b_max_ns"] == pytest.approx(40e9 / 24e6)
|
|
|
|
|
|
@pytest.mark.parametrize("old,new", [
|
|
("SIM_TEST_PASS Tiny cycles=100000", "Hello retroSoC!"),
|
|
("profiles=1", "profiles=0"), ("code=0", "code=3"),
|
|
("write_bytes=1024", "write_bytes=1020"), ("progress=10", "progress=0"),
|
|
("aw_max=10", "aw_max=25000"), ("isolated_cycles=24000", "isolated_cycles=0"),
|
|
])
|
|
def test_p8_rejects_incomplete_measurements(valid_log, old, new):
|
|
with pytest.raises(ValueError):
|
|
measurements(valid_log.replace(old, new), CONFIG)
|
|
|
|
|
|
def test_p8_does_not_promote_missing_profiles_or_errors(valid_log):
|
|
with pytest.raises(ValueError):
|
|
measurements(valid_log, {"PDK": "ICS55", "EXT_CLK_HZ": "24000000"})
|
|
with pytest.raises(ValueError):
|
|
measurements(valid_log + "\nSIM_TEST_FAIL", CONFIG)
|
|
with pytest.raises(ValueError):
|
|
measurements(valid_log, CONFIG, absent=True)
|
|
|
|
|
|
def test_p8_optional_absence_has_separate_verdict():
|
|
log = ("P8_ABSENT bounded optional-device rejection\nP8_RESULT code=0 profiles=0\n"
|
|
"SIM_TEST_PASS Tiny cycles=100000\n")
|
|
assert measurements(log, CONFIG, absent=True)["mode"] == "absent"
|
|
with pytest.raises(ValueError):
|
|
measurements(log, CONFIG)
|
|
|
|
|
|
def test_p8_observer_labels_match_axi_channels():
|
|
source = (Path(__file__).resolve().parents[1] /
|
|
"rtl/tiny/dv/tiny_p8_observers.svh").read_text()
|
|
order = source.split("wire [4:0] s_p8_stalls = {", 1)[1].split("};", 1)[0]
|
|
channels = [line.split("`_P8_AXI.", 1)[1].split("valid", 1)[0]
|
|
for line in order.splitlines() if "`_P8_AXI." in line]
|
|
assert channels == ["aw", "w", "ar", "b", "r"]
|