feat: declarative cell metadata (Tier 1 + minimal Tier 2, issue #67)#68
Merged
Conversation
ADR captures the directional decision from issue #67's thread: - Tier 1 (--cell-library <PATH>.v at runtime, sverilogparse-backed pin tables for third-party IP without vendoring) + - Minimal Tier 2 (per-cell `kind` discriminator in TOML, no port-mapping schema yet) + - Opaque-RAM semantics for `kind = "ram"` in v1.0 (RAMBlock allocated, outputs routed to X-source slots, no port resolution — enough to unblock the downstream wafer.space tapeout currently blocked on gf180mcu_ocd_ip_sram_*). Built-in classifiers (sky130.rs, gf180mcu.rs, build.rs scanner) stay as fallback through the whole transition. Port-mapping schema gets its own ADR after real adoption. Plan doc breaks the work into P1-P5 phases. Each phase is its own commit; no squashing until the implementation feedback loop confirms shape. Co-developed-by: Claude Code v2.1.143 (claude-opus-4-7)
Introduce src/cell_library.rs: - `RuntimeCellLibrary::from_files(paths)` parses one or more user-supplied `.v` files via sverilogparse (already in tree) and populates a runtime pin-direction + bus-width table. - Sibling `<file>.cells.toml` manifests are autoloaded; each may carry per-cell `kind` annotations (Tier-2 minimal slice — kind discriminator only, port mapping deliberately deferred). - `ChainedPinProvider` wraps a built-in `LeafPinProvider` (SKY130LeafPins, GF180MCULeafPins, AIGPDKLeafPins) and consults the runtime library first. Built-in providers stay load-bearing for cells the runtime doesn't know about. - `CellKind` enum covers v1.0 vocabulary (`std` / `dff` / `latch` / `clock_gate` / `ram` / `filler` / `endcap` / `tap` / `io_pad_*` / `delay` / `multi_output` / `tie_*`). Unknown values fail the manifest parse — no silent degradation. - `schema_version = "1.0"` is mandatory; future schema versions upgrade in lockstep with semantic changes. No CLI wiring or AIG-construction integration yet — those land in P2/P3. Module is self-contained and tested in isolation (10 unit tests covering pin parsing, inout-as-Unknown, manifest kind, schema rejection, kind-vocabulary rejection, autoload, no-manifest case, chained provider precedence, and the autoload-extension helper). Adds `toml = "0.8"` as a new dep (one transitive: toml_edit). ADR 0010 § Tier 1 + Tier 2 minimal slice. Plan: docs/plans/declarative-cell-metadata.md P1. Co-developed-by: Claude Code v2.1.143 (claude-opus-4-7)
Add --cell-library <PATH> (repeatable) to `jacquard sim` and `jacquard cosim`. load_design parses each path via RuntimeCellLibrary::from_files and wraps the appropriate built-in LeafPinProvider (SKY130 / GF180MCU / AIGPDK) with ChainedPinProvider, making third-party IP modules visible to the netlist reader without vendoring. The AIG-construction-side consultation of the manifest (`kind = "ram"` → opaque RAMBlock allocation) is the next slice (P3b). Until that lands the cell library buys us pin-direction resolution for previously-unrecognised cells but the AIG still falls back to AIGPDK for unknown cell types — sufficient to make the CLI surface compile and to verify the parsing path, not yet sufficient to unblock third-party SRAM macros. Three DesignArgs construction sites updated (cmd_sim, cmd_cosim in the under-feature-flag path, cmd_dump_paths) — dump_paths defaults to an empty Vec since timing analysis doesn't currently need runtime cell libraries. Co-developed-by: Claude Code v2.1.143 (claude-opus-4-7)
When PdkVariant::classify returns None during AIG construction (i.e. the cell isn't a vendored sky130 / gf180mcu standard cell), consult the runtime cell-library manifest. For cells declared `kind = "ram"` (ADR 0010 § "kind = ram semantics in v1.0"), allocate a per-output SRAM driver and route through the existing `srams` map for X-source enumeration — the same mechanism `$__RAMGEM_SYNC_` and `CF_SRAM_*` use, just without the port_r/port_w resolution those paths require. Thread an `Option<&RuntimeCellLibrary>` through AIG::from_netlistdb_with_cells → from_netlistdb_impl → dfs_netlistdb_build_aig. The existing public `AIG::from_netlistdb` becomes a thin delegate passing `None`; all existing call sites and tests stay green. `compute_x_sources` previously asserted `rd_pin >= 1` for every slot in `port_r_rd_data`. Opaque RAMs are narrower than the fixed 32-bit array — unused slots stay default-zero. Relax the assert to skip rd_pin == 0 rather than panic. New unit test `test_x_sources_narrow_opaque_ram` covers an 8-bit opaque RAM through compute_x_sources and compute_x_capable_pins. setup.rs `load_design` now passes the runtime library to `AIG::from_netlistdb_with_cells` when non-empty, completing the end-to-end wiring from --cell-library on the CLI to opaque-RAM allocation in AIG construction. Co-developed-by: Claude Code v2.1.143 (claude-opus-4-7)
`test_opaque_ram_end_to_end` exercises the full ADR-0010 pipeline:
Verilog blackbox + TOML manifest
→ RuntimeCellLibrary::from_files
→ ChainedPinProvider
→ NetlistDB::from_sverilog_source
→ AIG::from_netlistdb_with_cells
→ opaque-RAM RAMBlock allocation
→ compute_x_sources
Fixture mirrors gf180mcu_ocd_ip_sram__sram1024x8m8wm1 — the cell
that drove issue #67. The 8-bit Q output ends up in
srams[cellid].port_r_rd_data[0..8] with the upper 24 slots
default-zero (the narrow-width case the P3b assert relaxation
made safe). compute_x_sources returns 8 X-sources for the 8
allocated read-data aigpins.
Without this PR's plumbing, the same fixture failed at netlist
load (no pin table for `gf180mcu_ocd_ip_sram_*`) and even with
pin tables would have fallen through to the AIGPDK AND2/INV/BUF
fallback (wrong output behaviour). The driving wafer.space
tapeout's `chip_top.pnl.v` is materially the same shape at a
larger scale — should clear once a `.cells.toml` manifest entry
for the OCD SRAM is added.
Co-developed-by: Claude Code v2.1.143 (claude-opus-4-7)
Two doc updates closing out the declarative-cell-metadata plan: 1. `adding-a-pdk.md`: new "Adding third-party IP via runtime manifest" section at the end. Points users at the `--cell-library` + `.cells.toml` pathway for non-Rust-PR enablement of memory macros, IO pads, fillers, and other behaviourally-opaque cells. The overview gains a "two pathways" note so readers pick the right route up front. 2. `gf180mcu-enablement.md` § Follow-on cleanup: items 1, 2, 4 are now subsumed by ADR 0010 (build.rs scanner removal, IO/PR-library enablement). Item 3 (CellLibrary enum relocation) and item 5 (Liberty install in CI) remain independent. Strikethrough notation makes the supersession explicit while keeping the historical record intact. Closes out the P5 (final phase) of the declarative-cell-metadata plan. PR is now feature-complete for the Tier 1 + minimal Tier 2 slice; port-mapping schema is documented as the next ADR. Co-developed-by: Claude Code v2.1.143 (claude-opus-4-7)
d0046c1 to
7f3a3ea
Compare
This was referenced May 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #67's Tier 1 + minimal Tier 2 slice.
Summary
Built-in classifiers (`sky130.rs`, `gf180mcu.rs`, `build.rs` scanner) stay as fallback through the whole transition.
Phases (all landed)
Test plan
What's deferred
Closes #67 (directional sign-off + spike) — the port-mapping schema work is a separate issue.