mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
fix(publications): align DVP and PSRAM source bindings
Follow the shared PSRAM model path and bind the DVP DMA selector together with its Tiny/Mini definition, preserving Mini bulk-channel semantics. Describe the 129-bit configuration/epoch CDC packet, 128-bit payload extraction and applied register using the existing RTL. Complete isolated fixture dependencies and add negative checks for channel, width, slice and register-bypass drift without relaxing source validation. The final publication selection passes 163 tests with one optional skip; the full final worktree passes 2031 tests with the same pypdf skip. Retain publication identity and strict source-drift checks. No RTL, PDF generation, source-baseline refresh or physical qualification is included.
This commit is contained in:
4 files changed
+261
-59
No files matched your search
@@ -8899,7 +8899,7 @@
|
||||
"id": "reg",
|
||||
"title": "APB4 registers\ncapture / stream control",
|
||||
"x": 0.0,
|
||||
"y": 7.0,
|
||||
"y": 10.5,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
"ports": [
|
||||
@@ -8922,24 +8922,49 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cfg",
|
||||
"title": "Configuration CDC\nsystem to pixel",
|
||||
"id": "cfg_packet",
|
||||
"title": "Packet assembly\n128-bit CFG + epoch",
|
||||
"x": 6.3,
|
||||
"y": 7.0,
|
||||
"y": 10.5,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
"ports": [
|
||||
{
|
||||
"id": "in",
|
||||
"direction": "in",
|
||||
"width": 128,
|
||||
"side": "west"
|
||||
},
|
||||
{
|
||||
"id": "out",
|
||||
"direction": "out",
|
||||
"width": 129,
|
||||
"side": "east"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
"rtl/ip/multimedia/axi4s_dvp.sv"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cfg",
|
||||
"title": "Configuration CDC\n129-bit epoch packet",
|
||||
"x": 12.6,
|
||||
"y": 10.5,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
"ports": [
|
||||
{
|
||||
"id": "p0",
|
||||
"direction": "in",
|
||||
"width": 128,
|
||||
"width": 129,
|
||||
"side": "west"
|
||||
},
|
||||
{
|
||||
"id": "p1",
|
||||
"direction": "out",
|
||||
"width": 128,
|
||||
"side": "east"
|
||||
"width": 129,
|
||||
"side": "south"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
@@ -8953,10 +8978,67 @@
|
||||
"declaration_file": "rtl/managed/clusterip/common/rtl/cdc/cdc_2phase.sv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "cfg_split",
|
||||
"title": "Epoch / payload split\npacket[127:0]",
|
||||
"x": 12.6,
|
||||
"y": 7.0,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
"ports": [
|
||||
{
|
||||
"id": "in",
|
||||
"direction": "in",
|
||||
"width": 129,
|
||||
"side": "north"
|
||||
},
|
||||
{
|
||||
"id": "out",
|
||||
"direction": "out",
|
||||
"width": 128,
|
||||
"side": "west"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
"rtl/ip/multimedia/axi4s_dvp.sv"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "applied",
|
||||
"title": "Applied configuration\npixel-domain register",
|
||||
"x": 6.3,
|
||||
"y": 7.0,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
"ports": [
|
||||
{
|
||||
"id": "in",
|
||||
"direction": "in",
|
||||
"width": 128,
|
||||
"side": "east"
|
||||
},
|
||||
{
|
||||
"id": "out",
|
||||
"direction": "out",
|
||||
"width": 128,
|
||||
"side": "west"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
"rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"rtl/managed/clusterip/common/rtl/utils/register.sv"
|
||||
],
|
||||
"instance_source": {
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"name": "u_applied_config",
|
||||
"module": "dffer",
|
||||
"declaration_file": "rtl/managed/clusterip/common/rtl/utils/register.sv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "core",
|
||||
"title": "Pixel-domain core\nRGB / YUV packing",
|
||||
"x": 12.6,
|
||||
"x": 0.0,
|
||||
"y": 7.0,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
@@ -8965,7 +9047,7 @@
|
||||
"id": "p1",
|
||||
"direction": "in",
|
||||
"width": 128,
|
||||
"side": "west"
|
||||
"side": "east"
|
||||
},
|
||||
{
|
||||
"id": "p2",
|
||||
@@ -8994,7 +9076,7 @@
|
||||
{
|
||||
"id": "pads",
|
||||
"title": "Camera inputs\nPCLK / VSYNC / HREF / D8",
|
||||
"x": 12.6,
|
||||
"x": 0.0,
|
||||
"y": 3.5,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
@@ -9028,7 +9110,7 @@
|
||||
"id": "p4",
|
||||
"direction": "out",
|
||||
"width": 42,
|
||||
"side": "west"
|
||||
"side": "east"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
@@ -9043,7 +9125,7 @@
|
||||
{
|
||||
"id": "sink",
|
||||
"title": "PIO / stream sink\ncentral DMA endpoint",
|
||||
"x": 0.0,
|
||||
"x": 12.6,
|
||||
"y": 3.5,
|
||||
"w": 4.0,
|
||||
"h": 1.8,
|
||||
@@ -9052,7 +9134,7 @@
|
||||
"id": "p4",
|
||||
"direction": "in",
|
||||
"width": 42,
|
||||
"side": "east"
|
||||
"side": "west"
|
||||
}
|
||||
],
|
||||
"sources": [
|
||||
@@ -9063,7 +9145,7 @@
|
||||
"edges": [
|
||||
{
|
||||
"from": "reg.p0",
|
||||
"to": "cfg.p0",
|
||||
"to": "cfg_packet.in",
|
||||
"kind": "control",
|
||||
"label": "CFG / 128",
|
||||
"style": "direct",
|
||||
@@ -9074,21 +9156,7 @@
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".src_data_i(s_cfg_sys)"
|
||||
}
|
||||
],
|
||||
"signals": [
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"scope": "axi4s_dvp",
|
||||
"symbol": "s_cfg_sys",
|
||||
"bits": 128
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"scope": "axi4s_dvp",
|
||||
"symbol": "s_cfg_sys",
|
||||
"bits": 128
|
||||
"text": ".src_data_i({!s_cfg_epoch_q, s_cfg_sys})"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
@@ -9096,28 +9164,129 @@
|
||||
"node": "reg",
|
||||
"port": "cfg_o",
|
||||
"expression": "s_cfg_sys"
|
||||
},
|
||||
}
|
||||
],
|
||||
"signals": [
|
||||
{
|
||||
"node": "cfg",
|
||||
"port": "src_data_i",
|
||||
"expression": "s_cfg_sys"
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"scope": "axi4s_dvp",
|
||||
"symbol": "s_cfg_sys",
|
||||
"bits": 128
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": "cfg.p1",
|
||||
"to": "core.p1",
|
||||
"from": "cfg_packet.out",
|
||||
"to": "cfg.p0",
|
||||
"kind": "control",
|
||||
"label": "CFG / 128",
|
||||
"label": "CFG + EPOCH / 129",
|
||||
"style": "direct",
|
||||
"bindings": [
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".dst_data_o(s_cfg_pclk_q)"
|
||||
"text": "cdc_2phase #(.DATA_WIDTH(129)) u_dvp_config_cdc"
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".src_data_i({!s_cfg_epoch_q, s_cfg_sys})"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
{
|
||||
"node": "cfg",
|
||||
"port": "src_data_i",
|
||||
"expression": "{!s_cfg_epoch_q, s_cfg_sys}"
|
||||
}
|
||||
],
|
||||
"signals": []
|
||||
},
|
||||
{
|
||||
"from": "cfg.p1",
|
||||
"to": "cfg_split.in",
|
||||
"kind": "control",
|
||||
"label": "PACKET / 129",
|
||||
"style": "direct",
|
||||
"bindings": [
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".dst_data_o(s_cfg_packet_pclk)"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
{
|
||||
"node": "cfg",
|
||||
"port": "dst_data_o",
|
||||
"expression": "s_cfg_packet_pclk"
|
||||
}
|
||||
],
|
||||
"signals": [
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"scope": "axi4s_dvp",
|
||||
"symbol": "s_cfg_packet_pclk",
|
||||
"bits": 129
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": "cfg_split.out",
|
||||
"to": "applied.in",
|
||||
"kind": "control",
|
||||
"label": "PAYLOAD / 128",
|
||||
"style": "direct",
|
||||
"bindings": [
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": "dffer #(.DATA_WIDTH(128)) u_applied_config"
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".dat_i(s_cfg_packet_pclk[127:0])"
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".en_i(s_cfg_v_pclk && s_cfg_rdy_pclk && !s_cfg_apply_pclk_q)"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
{
|
||||
"node": "applied",
|
||||
"port": "dat_i",
|
||||
"expression": "s_cfg_packet_pclk[127:0]"
|
||||
}
|
||||
],
|
||||
"signals": []
|
||||
},
|
||||
{
|
||||
"from": "applied.out",
|
||||
"to": "core.p1",
|
||||
"kind": "control",
|
||||
"label": "APPLIED CFG / 128",
|
||||
"style": "direct",
|
||||
"bindings": [
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".dat_o(s_cfg_pclk_q)"
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".cfg_i(s_cfg_pclk_q)"
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"text": ".cfg_valid_i(s_cfg_apply_pclk_q)"
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
{
|
||||
"node": "applied",
|
||||
"port": "dat_o",
|
||||
"expression": "s_cfg_pclk_q"
|
||||
},
|
||||
{
|
||||
"node": "core",
|
||||
"port": "cfg_i",
|
||||
"expression": "s_cfg_pclk_q"
|
||||
}
|
||||
],
|
||||
"signals": [
|
||||
@@ -9126,24 +9295,6 @@
|
||||
"scope": "axi4s_dvp",
|
||||
"symbol": "s_cfg_pclk_q",
|
||||
"bits": 128
|
||||
},
|
||||
{
|
||||
"file": "rtl/ip/multimedia/axi4s_dvp.sv",
|
||||
"scope": "axi4s_dvp",
|
||||
"symbol": "s_cfg_pclk_q",
|
||||
"bits": 128
|
||||
}
|
||||
],
|
||||
"instance_ports": [
|
||||
{
|
||||
"node": "cfg",
|
||||
"port": "dst_data_o",
|
||||
"expression": "s_cfg_pclk_q"
|
||||
},
|
||||
{
|
||||
"node": "core",
|
||||
"port": "cfg_i",
|
||||
"expression": "s_cfg_pclk_q"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -9241,7 +9392,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"note": "Configuration crosses into the pixel domain; 42-bit pixel/event payloads return through a warm-flush CDC FIFO. PIO or AXI4-Stream consumes the same captured payload. No direct DVP-to-JPEG connection is implied."
|
||||
"note": "The configuration CDC carries 128 configuration bits plus an epoch. Its payload is latched in the pixel domain before application to the core; command, cancellation and acknowledgement control is not expanded here. 42-bit pixel/event payloads return through a warm-flush CDC FIFO. PIO or AXI4-Stream consumes the same captured payload. No direct DVP-to-JPEG connection is implied."
|
||||
},
|
||||
"jpeg": {
|
||||
"nodes": [
|
||||
|
||||
@@ -1640,7 +1640,11 @@
|
||||
"bindings": [
|
||||
{
|
||||
"file": "crt/src/hal/dvp.c",
|
||||
"text": "rs_dma_configure(RS_DMA_CHANNEL_BULK"
|
||||
"text": "rs_dma_configure(RS_DVP_DMA_CHANNEL"
|
||||
},
|
||||
{
|
||||
"file": "crt/src/hal/dvp.c",
|
||||
"text": "#ifdef RS_SOC_TINY\n#define RS_DVP_DMA_CHANNEL RS_DMA_CHANNEL_DVP\n#else\n#define RS_DVP_DMA_CHANNEL RS_DMA_CHANNEL_BULK\n#endif"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2043,7 +2047,7 @@
|
||||
"silicon": "Not established",
|
||||
"reports": [],
|
||||
"sources": [
|
||||
"rtl/mini/dv/model/ESP_PSRAM64H.sv",
|
||||
"rtl/model/ESP_PSRAM64H.sv",
|
||||
"tests/test_psram.py",
|
||||
"docs/ip/psram.md"
|
||||
]
|
||||
|
||||
@@ -26,7 +26,8 @@ def data():
|
||||
|
||||
@pytest.fixture
|
||||
def source_tree(tmp_path):
|
||||
for relative in dr.dependencies(SPEC):
|
||||
circuits = {**SPEC["circuits"], **read_json(ROOT / SPEC["circuit_catalog"])}
|
||||
for relative in dr.dependencies({**SPEC, "circuits": circuits}):
|
||||
target = tmp_path / relative
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copyfile(ROOT / relative, target)
|
||||
@@ -40,6 +41,30 @@ def replace(root: Path, relative: str, old: str, new: str) -> None:
|
||||
path.write_text(source.replace(old, new), encoding="utf-8")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("before", "after"), [
|
||||
(".DATA_WIDTH(129)", ".DATA_WIDTH(128)"),
|
||||
("s_cfg_packet_pclk[127:0]", "s_cfg_packet_pclk[128:1]"),
|
||||
(".cfg_i (s_cfg_pclk_q)",
|
||||
".cfg_i (s_cfg_packet_pclk[127:0])"),
|
||||
])
|
||||
def test_dvp_configuration_diagram_rejects_packet_or_latch_drift(monkeypatch, before, after):
|
||||
circuit = read_json(ROOT / "publications/datasheets/diagram-circuits.json")["dvp"]
|
||||
dr.validate_circuit(ROOT, circuit)
|
||||
read_text = Path.read_text
|
||||
wrapper = ROOT / "rtl/ip/multimedia/axi4s_dvp.sv"
|
||||
|
||||
def drift(path, *args, **kwargs):
|
||||
text = read_text(path, *args, **kwargs)
|
||||
if path.resolve() == wrapper:
|
||||
assert text.count(before) == 1
|
||||
return text.replace(before, after)
|
||||
return text
|
||||
|
||||
monkeypatch.setattr(Path, "read_text", drift)
|
||||
with pytest.raises(ValueError, match="binding changed"):
|
||||
dr.validate_circuit(ROOT, circuit)
|
||||
|
||||
|
||||
def test_representative_inventory_uses_actual_widths_and_addresses(data):
|
||||
value = data["system_reference"]["illustrations"]
|
||||
assert sum(f["bits"] for f in value["dma_tcd"]) == 512
|
||||
|
||||
@@ -96,6 +96,28 @@ def test_channel_coverage_cannot_drop_the_boot_channel(spec):
|
||||
pr.collect_programming(ROOT, spec, IDS, REFERENCE["source_revision"])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("before", "after"), [
|
||||
("rs_dma_configure(RS_DVP_DMA_CHANNEL,", "rs_dma_configure(RS_DMA_CHANNEL_CRYPTO_IN,"),
|
||||
("#else\n#define RS_DVP_DMA_CHANNEL RS_DMA_CHANNEL_BULK",
|
||||
"#else\n#define RS_DVP_DMA_CHANNEL RS_DMA_CHANNEL_CRYPTO_IN"),
|
||||
])
|
||||
def test_dvp_bulk_binding_rejects_channel_drift(spec, monkeypatch, before, after):
|
||||
"""A real HAL call or Mini selector change must invalidate its published role."""
|
||||
read_text = Path.read_text
|
||||
dvp = ROOT / "crt/src/hal/dvp.c"
|
||||
|
||||
def drift(path, *args, **kwargs):
|
||||
text = read_text(path, *args, **kwargs)
|
||||
if path.resolve() == dvp:
|
||||
assert text.count(before) == 1
|
||||
return text.replace(before, after)
|
||||
return text
|
||||
|
||||
monkeypatch.setattr(Path, "read_text", drift)
|
||||
with pytest.raises(ValueError, match="programming binding changed: bulk"):
|
||||
check(spec)
|
||||
|
||||
|
||||
def test_mini_channel_selection_excludes_inactive_tiny_roles():
|
||||
header = (ROOT / "crt/include/retrosoc/hal/dma.h").read_text()
|
||||
selected = pr.mini_channel_enum(header)
|
||||
|
||||
Reference in new issue
Block a user