From 340fec0a675d18530e3868e52abc7ee6b4585414 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 7 Jan 2026 21:38:13 +0100 Subject: [PATCH 1/5] WIP --- frontends/aiger/aigerparse.cc | 148 ++++++++++++++++++++++------------ 1 file changed, 98 insertions(+), 50 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4df37c0cd..4b0f50a38 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -23,6 +23,8 @@ // http://fmv.jku.at/papers/Biere-FMV-TR-07-1.pdf // https://stackoverflow.com/a/46137633 +#include "kernel/rtlil.h" +#include #ifdef _MSC_VER #include #define __builtin_bswap32 _byteswap_ulong @@ -127,14 +129,20 @@ struct ConstEvalAig void compute_deps(RTLIL::SigBit output, const pool &inputs) { + log_debug("insert self to sig2deps at %s\n", log_signal(output)); sig2deps[output].insert(output); - + log_debug("yea\n"); + RTLIL::Cell *cell = sig2driver.at(output); + log_debug("yeaaa\n"); + if (cell->type == ID($lut)) + return; RTLIL::SigBit sig_a = cell->getPort(ID::A); sig2deps[sig_a].reserve(sig2deps[sig_a].size() + sig2deps[output].size()); // Reserve so that any invalidation // that may occur does so here, and // not mid insertion (below) sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); + log_debug("weh\n"); if (!inputs.count(sig_a)) compute_deps(sig_a, inputs); @@ -343,7 +351,7 @@ RTLIL::Wire* AigerReader::createWireIfNotExists(RTLIL::Module *module, unsigned RTLIL::IdString wire_name(stringf("$aiger%d$%d%s", aiger_autoidx, variable, invert ? "b" : "")); RTLIL::Wire *wire = module->wire(wire_name); if (wire) return wire; - log_debug2("Creating %s\n", wire_name.c_str()); + log_debug("Creating %s\n", wire_name.c_str()); wire = module->addWire(wire_name); wire->port_input = wire->port_output = false; if (!invert) return wire; @@ -353,12 +361,12 @@ RTLIL::Wire* AigerReader::createWireIfNotExists(RTLIL::Module *module, unsigned if (module->cell(wire_inv_name)) return wire; } else { - log_debug2("Creating %s\n", wire_inv_name.c_str()); + log_debug("Creating %s\n", wire_inv_name.c_str()); wire_inv = module->addWire(wire_inv_name); wire_inv->port_input = wire_inv->port_output = false; } - log_debug2("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); module->addNotGate(stringf("$not$aiger%d$%d", aiger_autoidx, variable), wire_inv, wire); return wire; @@ -416,45 +424,85 @@ void AigerReader::parse_xaiger() uint32_t lutSize = parse_xaiger_literal(f); log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize); ConstEvalAig ce(module); - for (unsigned i = 0; i < lutNum; ++i) { - uint32_t rootNodeID = parse_xaiger_literal(f); - uint32_t cutLeavesM = parse_xaiger_literal(f); - log_debug2("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); - RTLIL::Wire *output_sig = module->wire(stringf("$aiger%d$%d", aiger_autoidx, rootNodeID)); - log_assert(output_sig); - uint32_t nodeID; - RTLIL::SigSpec input_sig; - for (unsigned j = 0; j < cutLeavesM; ++j) { - nodeID = parse_xaiger_literal(f); - log_debug2("\t%u\n", nodeID); - if (nodeID == 0) { - log_debug("\tLUT '$lut$aiger%d$%d' input %d is constant!\n", aiger_autoidx, rootNodeID, cutLeavesM); - continue; + struct Lut { + std::string name; + uint32_t output; + std::vector inputs; + void process(ConstEvalAig& ce, int aiger_autoidx, std::vector& lut_defined, std::deque& deferred, Module* module) { + SigSpec input_sig; + for (auto input : inputs) { + log_debug("\t%u\n", input); + if (input == 0) { + log_debug("\tLUT '$lut%s' input %d is constant!\n", name, input); + continue; + } + if (lut_defined.size() >= input + 1 && lut_defined[input]) { + deferred.push_back(*this); + return; + } + RTLIL::Wire *wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, input)); + log_assert(wire); + input_sig.append(wire); } - RTLIL::Wire *wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, nodeID)); - log_assert(wire); - input_sig.append(wire); + // Reverse input order as fastest input is returned first + input_sig.reverse(); + log_debug("looking for wire named %s\n", name); + RTLIL::Wire *output_wire = module->wire(name); + log_assert(output_wire); + log_assert(output_wire->width == 1); + log_debug("wehasdasd\n"); + // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) + ce.clear(); + ce.compute_deps(output_wire, input_sig.to_sigbit_pool()); + log_debug("weh\n"); + RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << GetSize(input_sig)); + for (int j = 0; j < GetSize(lut_mask); ++j) { + int gray = j ^ (j >> 1); + ce.set_incremental(input_sig, RTLIL::Const{gray, GetSize(input_sig)}); + RTLIL::SigBit o(output_wire); + bool success = ce.eval(o); + log_assert(success); + log_assert(o.wire == nullptr); + lut_mask.set(gray, o.data); + } + RTLIL::Cell *output_cell = module->cell(stringf("$and%s", name)); + log_assert(output_cell); + module->remove(output_cell); + module->addLut(stringf("$lut%s", name), input_sig, output_wire, std::move(lut_mask)); } - // Reverse input order as fastest input is returned first - input_sig.reverse(); - // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) - ce.clear(); - ce.compute_deps(output_sig, input_sig.to_sigbit_pool()); - RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << GetSize(input_sig)); - for (int j = 0; j < GetSize(lut_mask); ++j) { - int gray = j ^ (j >> 1); - ce.set_incremental(input_sig, RTLIL::Const{gray, GetSize(input_sig)}); - RTLIL::SigBit o(output_sig); - bool success = ce.eval(o); - log_assert(success); - log_assert(o.wire == nullptr); - lut_mask.set(gray, o.data); + }; + std::vector lut_defined; + std::deque deferred; + for (unsigned i = 0; i < lutNum; ++i) { + Lut lut; + lut.name = stringf("$aiger%d$%d", aiger_autoidx, lut.output); + lut.output = parse_xaiger_literal(f); + while (lut_defined.size() < lut.output + 1) + lut_defined.push_back(false); + lut_defined[lut.output] = true; + uint32_t cutLeavesM = parse_xaiger_literal(f); + log_debug("output=%d cutLeavesM=%d\n", lut.output, cutLeavesM); + RTLIL::Wire *output_wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, lut.output)); + log_assert(output_wire); + bool do_defer = false; + for (unsigned j = 0; j < cutLeavesM; ++j) { + uint32_t nodeID = parse_xaiger_literal(f); + lut.inputs.push_back(nodeID); + if (lut_defined.size() >= nodeID + 1 && lut_defined[nodeID]) + do_defer = true; } - RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)); - log_assert(output_cell); - module->remove(output_cell); - module->addLut(stringf("$lut$aiger%d$%d", aiger_autoidx, rootNodeID), input_sig, output_sig, std::move(lut_mask)); + if (do_defer) { + deferred.push_back(lut); + continue; + } + lut.process(ce, aiger_autoidx, lut_defined, deferred, module); } + while (!deferred.empty()) { + auto lut = deferred.front(); + lut.process(ce, aiger_autoidx, lut_defined, deferred, module); + deferred.pop_front(); + } + } else if (c == 'r') { uint32_t dataSize = parse_xaiger_literal(f); @@ -530,7 +578,7 @@ void AigerReader::parse_aiger_ascii() for (unsigned i = 1; i <= I; ++i, ++line_count) { if (!(f >> l1)) log_error("Line %u cannot be interpreted as an input!\n", line_count); - log_debug2("%d is an input\n", l1); + log_debug("%d is an input\n", l1); log_assert(!(l1 & 1)); // Inputs can't be inverted RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, l1 >> 1)); wire->port_input = true; @@ -543,7 +591,7 @@ void AigerReader::parse_aiger_ascii() if (L > 0 && !clk_name.empty()) { clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug2("Creating %s\n", clk_name.c_str()); + log_debug("Creating %s\n", clk_name.c_str()); clk_wire = module->addWire(clk_name); clk_wire->port_input = true; clk_wire->port_output = false; @@ -552,7 +600,7 @@ void AigerReader::parse_aiger_ascii() for (unsigned i = 0; i < L; ++i, ++line_count) { if (!(f >> l1 >> l2)) log_error("Line %u cannot be interpreted as a latch!\n", line_count); - log_debug2("%d %d is a latch\n", l1, l2); + log_debug("%d %d is a latch\n", l1, l2); log_assert(!(l1 & 1)); RTLIL::Wire *q_wire = module->addWire(stringf("$l%0*d", digits, l1 >> 1)); module->connect(createWireIfNotExists(module, l1), q_wire); @@ -592,7 +640,7 @@ void AigerReader::parse_aiger_ascii() log_error("Line %u cannot be interpreted as an output!\n", line_count); std::getline(f, line); // Ignore up to start of next line - log_debug2("%d is an output\n", l1); + log_debug("%d is an output\n", l1); RTLIL::Wire *wire = module->addWire(stringf("$o%0*d", digits, i)); wire->port_output = true; module->connect(wire, createWireIfNotExists(module, l1)); @@ -605,7 +653,7 @@ void AigerReader::parse_aiger_ascii() log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); std::getline(f, line); // Ignore up to start of next line - log_debug2("%d is a bad state property\n", l1); + log_debug("%d is a bad state property\n", l1); RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; bad_properties.push_back(wire); @@ -629,7 +677,7 @@ void AigerReader::parse_aiger_ascii() log_error("Line %u cannot be interpreted as an AND!\n", line_count); std::getline(f, line); // Ignore up to start of next line - log_debug2("%d %d %d is an AND\n", l1, l2, l3); + log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); @@ -655,7 +703,7 @@ void AigerReader::parse_aiger_binary() // Parse inputs int digits = decimal_digits(I); for (unsigned i = 1; i <= I; ++i) { - log_debug2("%d is an input\n", i); + log_debug("%d is an input\n", i); RTLIL::Wire *wire = module->addWire(stringf("$i%0*d", digits, i)); wire->port_input = true; module->connect(createWireIfNotExists(module, i << 1), wire); @@ -667,7 +715,7 @@ void AigerReader::parse_aiger_binary() if (L > 0 && !clk_name.empty()) { clk_wire = module->wire(clk_name); log_assert(!clk_wire); - log_debug2("Creating %s\n", clk_name.c_str()); + log_debug("Creating %s\n", clk_name.c_str()); clk_wire = module->addWire(clk_name); clk_wire->port_input = true; clk_wire->port_output = false; @@ -716,7 +764,7 @@ void AigerReader::parse_aiger_binary() log_error("Line %u cannot be interpreted as an output!\n", line_count); std::getline(f, line); // Ignore up to start of next line - log_debug2("%d is an output\n", l1); + log_debug("%d is an output\n", l1); RTLIL::Wire *wire = module->addWire(stringf("$o%0*d", digits, i)); wire->port_output = true; module->connect(wire, createWireIfNotExists(module, l1)); @@ -729,7 +777,7 @@ void AigerReader::parse_aiger_binary() log_error("Line %u cannot be interpreted as a bad state property!\n", line_count); std::getline(f, line); // Ignore up to start of next line - log_debug2("%d is a bad state property\n", l1); + log_debug("%d is a bad state property\n", l1); RTLIL::Wire *wire = createWireIfNotExists(module, l1); wire->port_output = true; bad_properties.push_back(wire); @@ -753,7 +801,7 @@ void AigerReader::parse_aiger_binary() l2 = parse_next_delta_literal(f, l1); l3 = parse_next_delta_literal(f, l2); - log_debug2("%d %d %d is an AND\n", l1, l2, l3); + log_debug("%d %d %d is an AND\n", l1, l2, l3); log_assert(!(l1 & 1)); RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); From 2633485c8fb8b8c9164f7bd0f75b11882b76b5a2 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 7 Jan 2026 21:50:34 +0100 Subject: [PATCH 2/5] fix --- frontends/aiger/aigerparse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 4b0f50a38..b02f5bdc2 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -475,8 +475,8 @@ void AigerReader::parse_xaiger() std::deque deferred; for (unsigned i = 0; i < lutNum; ++i) { Lut lut; - lut.name = stringf("$aiger%d$%d", aiger_autoidx, lut.output); lut.output = parse_xaiger_literal(f); + lut.name = stringf("$aiger%d$%d", aiger_autoidx, lut.output); while (lut_defined.size() < lut.output + 1) lut_defined.push_back(false); lut_defined[lut.output] = true; From 99212e6851f04c31d558abb870ca18f9a959c3d9 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 7 Jan 2026 22:28:04 +0100 Subject: [PATCH 3/5] just refactored --- frontends/aiger/aigerparse.cc | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index b02f5bdc2..1301822ac 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -428,7 +428,8 @@ void AigerReader::parse_xaiger() std::string name; uint32_t output; std::vector inputs; - void process(ConstEvalAig& ce, int aiger_autoidx, std::vector& lut_defined, std::deque& deferred, Module* module) { + + void process(ConstEvalAig& ce, int aiger_autoidx, Module* module) { SigSpec input_sig; for (auto input : inputs) { log_debug("\t%u\n", input); @@ -436,10 +437,6 @@ void AigerReader::parse_xaiger() log_debug("\tLUT '$lut%s' input %d is constant!\n", name, input); continue; } - if (lut_defined.size() >= input + 1 && lut_defined[input]) { - deferred.push_back(*this); - return; - } RTLIL::Wire *wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, input)); log_assert(wire); input_sig.append(wire); @@ -471,38 +468,20 @@ void AigerReader::parse_xaiger() module->addLut(stringf("$lut%s", name), input_sig, output_wire, std::move(lut_mask)); } }; - std::vector lut_defined; - std::deque deferred; for (unsigned i = 0; i < lutNum; ++i) { Lut lut; lut.output = parse_xaiger_literal(f); lut.name = stringf("$aiger%d$%d", aiger_autoidx, lut.output); - while (lut_defined.size() < lut.output + 1) - lut_defined.push_back(false); - lut_defined[lut.output] = true; uint32_t cutLeavesM = parse_xaiger_literal(f); log_debug("output=%d cutLeavesM=%d\n", lut.output, cutLeavesM); RTLIL::Wire *output_wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, lut.output)); log_assert(output_wire); - bool do_defer = false; for (unsigned j = 0; j < cutLeavesM; ++j) { uint32_t nodeID = parse_xaiger_literal(f); lut.inputs.push_back(nodeID); - if (lut_defined.size() >= nodeID + 1 && lut_defined[nodeID]) - do_defer = true; } - if (do_defer) { - deferred.push_back(lut); - continue; - } - lut.process(ce, aiger_autoidx, lut_defined, deferred, module); + lut.process(ce, aiger_autoidx, module); } - while (!deferred.empty()) { - auto lut = deferred.front(); - lut.process(ce, aiger_autoidx, lut_defined, deferred, module); - deferred.pop_front(); - } - } else if (c == 'r') { uint32_t dataSize = parse_xaiger_literal(f); From 1bd628d4ee556b78f274a477a4ff347e9ebc689d Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 7 Jan 2026 22:56:00 +0100 Subject: [PATCH 4/5] process parents first --- frontends/aiger/aigerparse.cc | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 1301822ac..ee1fdd8db 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -428,8 +428,20 @@ void AigerReader::parse_xaiger() std::string name; uint32_t output; std::vector inputs; + bool processed = false; + + void process(ConstEvalAig& ce, std::vector& luts, const std::vector>& parents, size_t i, int aiger_autoidx, Module* module) { + if (processed) { + log_debug("...already processed %d\n", i); + return; + } + for (auto parent : parents[i]) { + log_debug("process parent %d\n", parent); + luts[parent].process(ce, luts, parents, parent, aiger_autoidx, module); + } + processed = true; + log_debug("truly processing %d\n", i); - void process(ConstEvalAig& ce, int aiger_autoidx, Module* module) { SigSpec input_sig; for (auto input : inputs) { log_debug("\t%u\n", input); @@ -468,19 +480,29 @@ void AigerReader::parse_xaiger() module->addLut(stringf("$lut%s", name), input_sig, output_wire, std::move(lut_mask)); } }; + std::vector luts; + std::vector> parents; for (unsigned i = 0; i < lutNum; ++i) { - Lut lut; + Lut lut {}; lut.output = parse_xaiger_literal(f); lut.name = stringf("$aiger%d$%d", aiger_autoidx, lut.output); uint32_t cutLeavesM = parse_xaiger_literal(f); log_debug("output=%d cutLeavesM=%d\n", lut.output, cutLeavesM); RTLIL::Wire *output_wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, lut.output)); log_assert(output_wire); + size_t lut_idx = luts.size(); for (unsigned j = 0; j < cutLeavesM; ++j) { uint32_t nodeID = parse_xaiger_literal(f); lut.inputs.push_back(nodeID); + while (parents.size() < nodeID + 1) + parents.push_back(pool()); + log_debug("%d is parent of %d\n", lut_idx, nodeID); + parents[nodeID].insert(lut_idx); } - lut.process(ce, aiger_autoidx, module); + luts.push_back(lut); + } + for (size_t i = 0; i < luts.size(); i++) { + luts[i].process(ce, luts, parents, i, aiger_autoidx, module); } } else if (c == 'r') { From 39ff623ff79af1de97f88fdeef5d195db0823194 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 8 Jan 2026 00:24:00 +0100 Subject: [PATCH 5/5] smells good --- frontends/aiger/aigerparse.cc | 48 ++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index ee1fdd8db..eb004e05d 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -129,12 +129,8 @@ struct ConstEvalAig void compute_deps(RTLIL::SigBit output, const pool &inputs) { - log_debug("insert self to sig2deps at %s\n", log_signal(output)); sig2deps[output].insert(output); - log_debug("yea\n"); - RTLIL::Cell *cell = sig2driver.at(output); - log_debug("yeaaa\n"); if (cell->type == ID($lut)) return; RTLIL::SigBit sig_a = cell->getPort(ID::A); @@ -142,7 +138,6 @@ struct ConstEvalAig // that may occur does so here, and // not mid insertion (below) sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end()); - log_debug("weh\n"); if (!inputs.count(sig_a)) compute_deps(sig_a, inputs); @@ -430,17 +425,19 @@ void AigerReader::parse_xaiger() std::vector inputs; bool processed = false; - void process(ConstEvalAig& ce, std::vector& luts, const std::vector>& parents, size_t i, int aiger_autoidx, Module* module) { + void process(ConstEvalAig& ce, std::vector& luts, const std::vector>& parents, int aiger_autoidx, Module* module) { if (processed) { - log_debug("...already processed %d\n", i); return; } - for (auto parent : parents[i]) { - log_debug("process parent %d\n", parent); - luts[parent].process(ce, luts, parents, parent, aiger_autoidx, module); + if (output < parents.size()) { + for (auto parent : parents[output]) { + if (!parent) + continue; + luts[parent].process(ce, luts, parents, aiger_autoidx, module); + } } processed = true; - log_debug("truly processing %d\n", i); + log_debug("Processing %d\n", output); SigSpec input_sig; for (auto input : inputs) { @@ -455,15 +452,12 @@ void AigerReader::parse_xaiger() } // Reverse input order as fastest input is returned first input_sig.reverse(); - log_debug("looking for wire named %s\n", name); RTLIL::Wire *output_wire = module->wire(name); log_assert(output_wire); log_assert(output_wire->width == 1); - log_debug("wehasdasd\n"); // TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size()) ce.clear(); ce.compute_deps(output_wire, input_sig.to_sigbit_pool()); - log_debug("weh\n"); RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << GetSize(input_sig)); for (int j = 0; j < GetSize(lut_mask); ++j) { int gray = j ^ (j >> 1); @@ -481,7 +475,8 @@ void AigerReader::parse_xaiger() } }; std::vector luts; - std::vector> parents; + std::vector> parents; + std::unordered_map> remap; for (unsigned i = 0; i < lutNum; ++i) { Lut lut {}; lut.output = parse_xaiger_literal(f); @@ -491,18 +486,35 @@ void AigerReader::parse_xaiger() RTLIL::Wire *output_wire = module->wire(stringf("$aiger%d$%d", aiger_autoidx, lut.output)); log_assert(output_wire); size_t lut_idx = luts.size(); + remap[lut_idx] = lut.output; for (unsigned j = 0; j < cutLeavesM; ++j) { uint32_t nodeID = parse_xaiger_literal(f); + log_debug("\t%d\n", nodeID); lut.inputs.push_back(nodeID); while (parents.size() < nodeID + 1) - parents.push_back(pool()); - log_debug("%d is parent of %d\n", lut_idx, nodeID); + parents.push_back({}); parents[nodeID].insert(lut_idx); } luts.push_back(lut); } for (size_t i = 0; i < luts.size(); i++) { - luts[i].process(ce, luts, parents, i, aiger_autoidx, module); + auto output = luts[i].output; + std::unordered_set old_parents; + if (output < parents.size()) { + for (size_t parent : parents[output]) { + old_parents.insert(parent); + } + + } + parents[i].clear(); + for (auto parent : old_parents) { + if (remap[parent]) { + parents[i].insert(*remap[parent]); + } + } + } + for (auto lut : luts) { + lut.process(ce, luts, parents, aiger_autoidx, module); } } else if (c == 'r') {