Skip to content

Multi-origin vOrigins with per-node cap#7

Closed
robtaylor wants to merge 5 commits intomainfrom
origin-tracking-clean
Closed

Multi-origin vOrigins with per-node cap#7
robtaylor wants to merge 5 commits intomainfrom
origin-tracking-clean

Conversation

@robtaylor
Copy link
Copy Markdown
Owner

Summary

CI check for the multi-origin vOrigins implementation (upstream PR berkeley-abc#487).

  • Per-object origin tracking (vOrigins) on Gia_Man_t
  • Propagation through all ABC9 engines (~20 call sites)
  • Union-based small-buffer optimization (4 inline slots, geometric-doubling overflow)
  • AIGER "y" extension with sentinel-based format detection
  • &origins / &origins_id debugging commands
  • Per-node origin cap (nOriginsMax) to bound O(n²) accumulation in shared cones

Test plan

  • CI builds pass (Linux, macOS, Windows)
  • Smoke test: &r i10.aig; &origins_id; &sweep; &syn2; &dc2; &if -K 6; &mfs; &origins
  • Roundtrip: &w /tmp/test.aig; &r /tmp/test.aig; &origins preserves origins
  • Cap test: &origins_id -M 256 bounds pathological cases

Add lightweight origin tracking that propagates source-location
provenance through ABC's optimization passes. This enables the
Yosys abc9 flow to preserve \src attributes on LUT cells after
technology mapping, achieving ~100% coverage on tested designs
with negligible overhead (~0.6% time, ~3% memory on picorv32).

Changes:
- Add Vec_Int_t *vOrigins field to Gia_Man_t with inline accessors
- Read/write origins via AIGER "y" extension (sentinel -1 for unmapped)
- Propagate through all Gia_ManDup* variants via Gia_ManOriginsDup()
- Propagate through structural hashing (AND/XOR/MUX) in giaHash.c
- Recover origins after GIA→AIG→GIA round-trips (&dc2, &dch) via
  Gia_ManOriginsAfterRoundTrip() using CO driver + top-down propagation
- Propagate through IF mapper using iCopy correspondence
- Instrument giaEquiv, giaMuxes, giaTim, giaBalAig, dauGia

Co-developed-by: Claude Code v2.1.44 (claude-opus-4-6)
Extend origin tracking to cover the complete abc9 optimization
pipeline. Add Gia_ManOriginsDupVec for functions that use Vec_Int_t
copy vectors instead of the Value field.

Engines instrumented:
- &dc2, &dch: Round-trip recovery (giaAig.c)
- &if: iCopy-based propagation in SopBalance/DsdBalance (giaIf.c),
  plus DupHashMapping/DupUnhashMapping for timing paths
- &jf, &lf: OriginsDupVec in Jf_ManDeriveGia/Lf_ManDeriveMappingGia
- &syn2, &synch2: Sub-operations (Jf/Lf mappers) + round-trip
  recovery in Gia_ManAigSynch2Choices, DupFromBarBufs/DupToBarBufs
  for box designs (giaScript.c)
- &sweep: Gia_ManFraigReduceGia, Gia_ManDupWithBoxes (giaSweep.c)
- &scorr: Gia_ManCorrReduce (cecCorr.c)
- &mfs: Custom propagation via vMfs2Old/vMfs2Gia (giaMfs.c)
- Supporting: Gia_ManDupCollapse/DupNormalize/DupUnnormalize (giaTim.c),
  DupUnshuffleInputs/DupMoveLast (giaTim.c),
  EquivToChoices (giaEquiv.c), DupMuxes (giaMuxes.c),
  BalanceInt (giaBalAig.c), DauMergePart (dauGia.c),
  DupWithAttributes (giaDup.c)

Add bounds checks in Gia_ObjOrigin and Gia_ObjSetOrigin for GIAs
that grow after vOrigins is allocated (e.g., AreaBalance adding nodes).

Coverage verified by static analysis finding all Gia_Man_t* functions
that call Gia_ManStart without Gia_ManOriginsDup — 23 functions
covered, remaining 167 are outside the abc9 pipeline.

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
@robtaylor robtaylor force-pushed the origin-tracking-clean branch from dd225ea to bf2c7a3 Compare April 2, 2026 22:47
Replace single-origin-per-object vOrigins with a union-based scheme
that stores up to GIA_ORIGINS_INLINE (default 4) origins inline, with
overflow to a heap-allocated array for outliers. This captures merge
events from structural hashing and optimization that previously lost
origin information.

Data structure (Gia_OriginsEntry_t union, 16 bytes on 64-bit):
- Small mode: 4 inline int slots (-1 = unused)
- Large mode: sentinel (INT_MIN) + count + heap pointer
- Stride = sizeof(entry)/sizeof(int) = 4 ints per object

Key changes:
- gia.h: Union type, stride constants, inline accessors
  (Gia_ObjOriginsNum, Gia_ObjOriginsGet, Gia_ObjForEachOrigin),
  updated Gia_ObjOrigin/Gia_ObjSetOrigin for backward compat
- giaDup.c: Gia_ObjAddOrigin (dedup + promote), Gia_ObjUnionOrigins,
  Gia_ManOriginsFreeOverflows; updated OriginsDup/DupVec/AfterRoundTrip
  for strided multi-origin propagation
- giaHash.c: Union all input origins on hash miss AND hash hit (captures
  structural sharing from different source paths)
- giaAiger.c: Variable-length "y" extension format [count, lit0, lit1,...]
  with backward-compatible reader for old single-origin format
- giaIf.c, giaMfs.c: Mapper propagation via Gia_ObjUnionOrigins
- giaMan.c: Free overflow arrays before vOrigins cleanup

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)

Harden multi-origin vOrigins: leak guards, geometric growth, format sentinel

- Add free-before-alloc guards in all OriginsDup functions to prevent
  memory leaks when vOrigins is already populated (e.g. Gia_ManDup
  followed by Gia_ManDupWithAttributes)
- Replace O(n²) realloc-by-1 with geometric doubling in overflow
  arrays (8-slot initial capacity, double at powers of 2)
- Add sentinel int -2 to AIGER "y" extension writer/reader for
  unambiguous new-vs-old format detection (fixes edge case where
  nInts == nAigObjs with all-zero origins)
- Extract Gia_ManOriginsDupIf() helper to deduplicate 3 identical
  14-line IF mapper origin propagation blocks
- Replace Gia_ManOriginsGrow push-loop with Vec_IntFillExtra
- Add vNodes NULL guard in AIGER reader
- Remove orphaned duplicate comment block

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)

Simplify vOrigins: extract OriginsReset, fix free(), hoist iteration count

Code review cleanup:
- Extract Gia_ManOriginsReset() helper to replace 5 identical
  free-overflows + free-vec leak-guard blocks
- Use ABC_FREE() instead of bare free() in Gia_ObjSetOrigin
  for allocator consistency
- Hoist Gia_ObjOriginsNum() call out of Gia_ObjForEachOrigin
  macro loop condition (callers declare _nOrig)
- Add compile-time assertion that GIA_ORIGINS_INLINE is large
  enough to cover the overflow header on the target platform

Co-developed-by: Claude Code v2.1.83 (claude-opus-4-6)
- &origins: prints multi-origin statistics (entry count, total origins,
  average/max per node, overflow count, histogram). Origins are
  populated either from XAIGER "y" extension (normal abc9 flow) or
  by &origins_id (testing).
- &origins_id: sets identity origins (each AND node -> itself) for
  testing origin propagation in standalone ABC sessions. Not needed
  in the normal abc9 flow where origins come from Yosys via XAIGER.

Co-developed-by: Claude Code v2.1.58 (claude-opus-4-6)
Shared fanin cones can accumulate origins from all CO drivers,
causing O(n²) dedup cost in Gia_ObjAddOrigin. Add nOriginsMax
field to Gia_Man_t that short-circuits overflow-mode AddOrigin
when the node has reached the limit. Cap is set via &origins_id -M.

Pathological case (10K outputs, shared 50-deep cone):
  No cap:   5.70s, 1.01M total origins, max 10000/node
  -M 256:   0.79s, 45K total origins, max 256/node (7.2x faster)
Normal designs (i10.aig, max 165/node): identical results.

Co-developed-by: Claude Code v2.1.89 (claude-opus-4-6)
@robtaylor robtaylor force-pushed the origin-tracking-clean branch from bf2c7a3 to 1b3c537 Compare April 3, 2026 00:30
@robtaylor
Copy link
Copy Markdown
Owner Author

Closing - replaced by new PR based directly on upstream master.

@robtaylor robtaylor closed this Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant