Skip to content

✨ Support sequential networks in write_aiger - #699

Open
marcelwa wants to merge 1 commit into
lsils:masterfrom
marcelwa:upstream-seq-write-aiger
Open

✨ Support sequential networks in write_aiger#699
marcelwa wants to merge 1 commit into
lsils:masterfrom
marcelwa:upstream-seq-write-aiger

Conversation

@marcelwa

Copy link
Copy Markdown
Contributor

Description

write_aiger hardcoded a latch count of 0 and asserted the network was combinational,
so a sequential<aig_network> could be passed in but silently lost its registers — they
degrade into extra PI/PO pairs, and the assertion is a no-op in release builds.

This adds real latch support, gated on num_registers / foreach_ri / foreach_ro via
if constexpr. The combinational path is untouched and still produces byte-identical
output — the two pre-existing byte-exact tests pass unchanged.

Reset values

Reset values are now always written explicitly, which matters more than it first looks:

  • An omitted reset field means 0 in the AIGER format, so omitting it for an
    uninitialized register would silently convert it into a zero-initialized one.
  • An undefined reset is therefore encoded the way the format prescribes: by
    repeating the latch's own current-state literal.

Verified in both directions — ABC reports the expected Init0 = 1. Init1 = 1. InitDC = 1.
for a network carrying one register of each kind, and the output round-trips through
aiger_reader preserving register count, reset values, and names.

CI ordering

The binary format encodes CIs implicitly, requiring variables 1..I to be the primary
inputs and I+1..I+L the register outputs. That invariant was previously assumed
silently; it is now documented and checked by a debug assertion.

Drive-by

Added the missing <cassert> include. The header uses assert but only ever compiled
because its includers happened to provide it — a TU that includes write_aiger.hpp
first currently fails to build.

Testing

Five new test cases in test/io/write_aiger.cpp (26 assertions total), passing in both
debug and NDEBUG builds:

  • byte-exact output for a sequential AIG with an undefined reset
  • byte-exact output for reset values 0 and 1
  • write → aiger_reader round trip preserving PI/PO/register counts and reset values
  • latch names emitted as l<n> and surviving a round trip
  • undefined reset encoded as the self-literal and read back as undefined

Context: this came out of building a Python-side ABC bridge in
aigverse, where sequential designs could not be
handed to ABC at all because there was no way to write them. Offering it upstream since
it seems generally useful.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GbUqcnZayPooFgekEXVSjz

`write_aiger` hardcoded a latch count of 0 and asserted that the network was
combinational, so `sequential<aig_network>` could be passed in but silently
lost its registers: they degraded into extra PI/PO pairs.

Emit registers as AIGER latches when the network type provides `num_registers`,
`foreach_ri`, and `foreach_ro`. The combinational path is unchanged and still
produces byte-identical output.

Reset values are always written explicitly. An omitted reset field means 0 in
the AIGER format, so omitting it would silently turn an uninitialized register
into a zero-initialized one; an undefined reset is instead encoded by repeating
the latch's own current-state literal, as the format prescribes. Latch names are
emitted as `l<n>` symbol table entries, mirroring `on_latch_name`.

Because the binary format encodes CIs implicitly, PIs must be variables 1..I and
register outputs I+1..I+L. That invariant is now checked by a debug assertion
rather than being silently assumed.

Also add the missing `<cassert>` include; the header used `assert` but only
compiled because its includers happened to provide it.

Verified against both readers: the output round-trips through `aiger_reader`
preserving register count, reset values, and names, and ABC reads it back with
the expected `Init0`/`Init1`/`InitDC` counts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GbUqcnZayPooFgekEXVSjz
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.65217% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 84.07%. Comparing base (25beb0e) to head (ac6759d).

Files with missing lines Patch % Lines
include/mockturtle/io/write_aiger.hpp 95.65% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master     #699   +/-   ##
=======================================
  Coverage   84.06%   84.07%           
=======================================
  Files         190      190           
  Lines       29468    29500   +32     
=======================================
+ Hits        24773    24802   +29     
- Misses       4695     4698    +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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