diff --git a/STDCELL_ORIGIN_TRACKING_PLAN.md b/STDCELL_ORIGIN_TRACKING_PLAN.md new file mode 100644 index 0000000000..adf9550586 --- /dev/null +++ b/STDCELL_ORIGIN_TRACKING_PLAN.md @@ -0,0 +1,201 @@ +# Plan: Origin tracking through standard-cell mapping (`&nf`) + +Status: **draft / design** — follow-on to PR #487 (per-object origin tracking, `vOrigins`). +Branch: `origin-tracking-stdcell` (base: `origin-tracking-clean`). + +## Goal + +Make `\src` provenance survive **standard-cell** technology mapping so that an +ASIC flow (e.g. LibreLane → sky130/gf180) can label each mapped gate with the +RTL source location it came from. + +PR #487 + the yosys `src-retention-y-ext` branch already deliver this for the +**FPGA / LUT** path: yosys writes XAIGER, ABC propagates `vOrigins` through the +LUT mapper (`&if`) and optimization, ABC writes the `"y"` extension, and yosys +applies `\src` to `$lut` cells. Validated end-to-end by +`tests/techmap/abc9_src_retention_full.sh` (100% of LUTs tagged). + +The standard-cell path is **not** covered. This plan closes the ABC-side gap and +scopes the companion yosys work. + +## Maintainer guidance (authoritative) + +From direct correspondence with Alan Mishchenko (ABC maintainer) and Dan +Ravenslofty (YosysHQ, final say on abc-in-yosys), and the PR threads: + +- **The lightweight per-object `vOrigins` approach (PR #487) is endorsed.** Alan: + "your implementation is quite clean and has low resource usage … Glad this + method works for mapping RTL code into the resulting AIG nodes (as well gates + and LUTs after mapping)." So origins on **mapped std-cell gates** are an + accepted goal, not just LUTs. +- **Alan explicitly named the engines to cover**: `&dc2, &if, &nf, &mfs, &syn2, + &dch, &synch2, &sweep, &scorr`. **`&nf` is on that list** — this PR is exactly + the remaining item. +- **Acceptance criterion: zero change to default behavior.** Alan: "If the + resulting integration does not change the default behavior, I will be happy to + include it in the public version." The `&nf` change must be a no-op unless + `p->vOrigins` is set. +- **The heavyweight `Nr_Man_t` retention manager is rejected — do NOT revive it.** + Alan: "the idea of 'origin annotation' [hash-table manager] is hard to + implement, because it requires modifications to 10+ different packages … it + reminds me of [HAIG] which was one of the most complicated things I ever + implemented in ABC — and it did not work." This rules out the + `YosysHQ/abc#41` / `Silimate/abc#4` (`Nr_Man_t` on `Abc_Ntk_t`) lineage, + including its classic-`abc`/`write_blif` provenance path. The `vOrigins` + (GIA-only) line is the sanctioned successor. +- **Lofty originally suggested the XAIGER `"y"` extension** as the yosys↔abc + channel (`YosysHQ/abc#41` discussion); the abc internals are "up to Alan". + +### Current engine coverage (verified on `origin-tracking-clean`) + +| Engine (Alan's list) | File | `vOrigins` covered | +|---|---|---| +| `&if` (LUT map) | `giaIf.c` | yes | +| `&mfs` | `giaMfs.c` | yes | +| `&sweep` | `giaSweep.c` | yes | +| `&scorr` | `cecCorr.c` | yes | +| `&dc2` / `&dch` | `giaAig.c` (`…AfterRoundTrip`) | yes | +| `&syn2` / `&synch2` | `giaScript.c` | yes | +| `&b` (balance) | `giaBalAig.c` | yes | +| **`&nf` (std-cell map)** | **`giaNf.c`** | **yes — by construction (see spike)** | + +`grep -c Origin src/aig/gia/giaNf.c` = 0 — but this is **expected and fine**. + +### Spike result (verified): `&nf` preserves origins without code changes + +`&nf` maps **in place**: `Nf_ManDeriveMapping` attaches `vCellMapping` to +`p->pGia` and returns the *same* GIA (`giaNf.c:2409` → `return p->pGia`) — no +object renumbering. `Nf_StoCreate` only allocates side arrays; it does not dup +the GIA. The only renumbering operations in the `Nf_ManPerformMapping` wrapper +are `Gia_ManDupMuxes` (coarsen), `Gia_ManDupUnnormalize` and +`Gia_ManDupNormalize` (boxes path) — **all already origin-instrumented**. So +`vOrigins` on the AIG nodes survive `&nf` untouched. + +**Empirically confirmed** (standalone abc, PR #487 binary, sky130 liberty, on a +yosys-produced XAIGER carrying the `"y"` extension): + +``` +&read input.xaig; &origins -M 100; &origins -> Origins: 13 entries +&nf; &origins -> Origins: 13 entries (preserved) +``` + +Consequence: **no propagation code is needed in `giaNf.c`**, and a +`Gia_ManOriginsDupNf` helper is **not** required. Alan's "cover `&nf`" item is +satisfied by construction. + +> Open/inconclusive: a plain standalone `&write`→`&read` round-trip of the +> *mapped* GIA did not restore origins, but that test was not faithful (missing +> `read_box`; the real abc9 write-back path differs). Whether `&write` emits the +> `"y"` extension correctly for a cell-mapped GIA must be checked on the +> yosys-integration side — it belongs to the consumption work below, not to +> `&nf` itself. + +## Verified current state (why std-cell doesn't work today) + +1. **`&nf` (the std-cell mapper, `src/aig/gia/giaNf.c`) is not origin-instrumented.** + `grep -c Origin src/aig/gia/giaNf.c` = 0. PR #487 instrumented the LUT + mappers (`giaIf.c`, `giaJf.c`, `giaLf.c`) and the optimization passes + (`giaAig.c` dc2/dch, `giaMfs.c`, `giaBalAig.c`, `giaHash.c`, `giaDup.c` `&st`, + …) but never the `&nf` cell mapper. + +2. **The emission channel already exists.** `Gia_AigerWriteS` (`giaAiger.c:1876`) + writes `vOrigins` as the variable-length `"y"` extension. If a mapped GIA + carries `vOrigins`, `&write` emits them for free. + +3. **The LUT instrumentation template is small and local.** + `Gia_ManOriginsDupIf(pNew, p, pIfMan)` (`giaDup.c:458`) walks the `If_Man_t` + objects, and for each source object `i` with origins, unions them into the + mapped object `Abc_Lit2Var(pIfObj->iCopy)` of `pNew`. An `&nf` analogue needs + the equivalent source→mapped-node correspondence from `Nf_Man_t`. + +4. **LibreLane's std-cell flow uses the classic `abc` pass over BLIF, not XAIGER.** + yosys `passes/techmap/abc.cc:1017`: `read_blif input.blif;