mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
feat(tiny): add scripts for SDC generation and packaging
- Introduced to create pad-aware timing constraints for the Tiny IHP130 chip flow. - Added to create a checksummed delivery archive for the Tiny LibreLane implementation. - Created for synthesis-only header of the locked IHP SRAM macro physical views. - Implemented to limit OpenSTA report enumeration for path counts. - Updated to include power pad definitions. - Enhanced to handle power pad counts and validation. - Added tests for Tiny flow and pin map validation, including power pad overrides and constraints.
This commit is contained in:
29 files changed
+1520
-63
No files matched your search
@@ -29,6 +29,7 @@ REQUIRED_PROFILES = {"fpga_mini", "tb", "verilator"}
|
||||
CONNECTION_RE = re.compile(r"(?:[A-Za-z_][A-Za-z0-9_]*)(?:\[[0-9]+\])?$")
|
||||
CONSTANT_RE = re.compile(r"[0-9]+'[bBdDhHoO][0-9a-fA-F_xXzZ]+$")
|
||||
IHP130_POWER_PAD_COUNTS = {"vdd": 24, "vss": 24, "iovdd": 16, "iovss": 16}
|
||||
POWER_PAD_KINDS = tuple(IHP130_POWER_PAD_COUNTS)
|
||||
POWER_CONNECTIONS = "`RETROSOC_PAD_POWER_CONNECTIONS"
|
||||
|
||||
|
||||
@@ -173,9 +174,33 @@ def validate_connection(value: Any, field: str) -> str | None:
|
||||
raise ValueError(f"{field} must be a signal, bit-select, constant, or null")
|
||||
|
||||
|
||||
def read_map(path: Path) -> tuple[list[Pad], dict[str, dict[str, str | None]]]:
|
||||
def read_document(path: Path) -> dict[str, Any]:
|
||||
with path.open(encoding="utf-8") as source:
|
||||
document = json.load(source)
|
||||
return json.load(source)
|
||||
|
||||
|
||||
def parse_power_pads(document: dict[str, Any]) -> dict[str, int]:
|
||||
counts = document.get("power_pads")
|
||||
if counts is None:
|
||||
return dict(IHP130_POWER_PAD_COUNTS)
|
||||
if not isinstance(counts, dict) or set(counts) != set(POWER_PAD_KINDS):
|
||||
raise ValueError(f"power_pads must contain exactly {list(POWER_PAD_KINDS)}")
|
||||
parsed: dict[str, int] = {}
|
||||
for kind in POWER_PAD_KINDS:
|
||||
value = counts[kind]
|
||||
if not isinstance(value, int) or isinstance(value, bool) or value <= 0:
|
||||
raise ValueError(f"power_pads.{kind} must be a positive integer")
|
||||
parsed[kind] = value
|
||||
return parsed
|
||||
|
||||
|
||||
def read_power_pad_counts(path: Path) -> dict[str, int]:
|
||||
return parse_power_pads(read_document(path))
|
||||
|
||||
|
||||
def read_map(path: Path) -> tuple[list[Pad], dict[str, dict[str, str | None]]]:
|
||||
document = read_document(path)
|
||||
parse_power_pads(document)
|
||||
if document.get("schema_version") != 1:
|
||||
raise ValueError("schema_version must be 1")
|
||||
groups = document.get("pads")
|
||||
@@ -299,7 +324,10 @@ def render_pad_instance(pad: Pad) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def render_pad_bindings(pads: list[Pad]) -> str:
|
||||
def render_pad_bindings(
|
||||
pads: list[Pad], power_counts: dict[str, int] | None = None
|
||||
) -> str:
|
||||
counts = IHP130_POWER_PAD_COUNTS if power_counts is None else power_counts
|
||||
lines = [
|
||||
"// Generated by scripts/rtl/generate_pin_map.py; do not edit.",
|
||||
"`ifdef PDK_IHP130",
|
||||
@@ -311,7 +339,7 @@ def render_pad_bindings(pads: list[Pad]) -> str:
|
||||
" generate",
|
||||
]
|
||||
cell_suffixes = {"vdd": "Vdd", "vss": "Vss", "iovdd": "IOVdd", "iovss": "IOVss"}
|
||||
for kind, count in IHP130_POWER_PAD_COUNTS.items():
|
||||
for kind, count in counts.items():
|
||||
lines.extend(
|
||||
[
|
||||
f" for (genvar i = 0; i < {count}; i++) begin : {kind}_pads",
|
||||
@@ -435,9 +463,12 @@ def render_profile_bindings(pads: list[Pad], bindings: dict[str, str | None]) ->
|
||||
|
||||
def generate(map_path: Path, output_dir: Path) -> None:
|
||||
pads, profiles = read_map(map_path)
|
||||
power_counts = read_power_pad_counts(map_path)
|
||||
rtl_dir = output_dir / "rtl"
|
||||
atomic_write(rtl_dir / "retrosoc_asic_ports.svh", render_ports(pads))
|
||||
atomic_write(rtl_dir / "retrosoc_asic_pad_bindings.svh", render_pad_bindings(pads))
|
||||
atomic_write(
|
||||
rtl_dir / "retrosoc_asic_pad_bindings.svh", render_pad_bindings(pads, power_counts)
|
||||
)
|
||||
atomic_write(rtl_dir / "retrosoc_core_ports.svh", render_core_ports(pads))
|
||||
atomic_write(rtl_dir / "retrosoc_core_bindings.svh", render_core_bindings(pads))
|
||||
for profile, bindings in profiles.items():
|
||||
|
||||
Reference in new issue
Block a user