From 340fec0a675d18530e3868e52abc7ee6b4585414 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 7 Jan 2026 21:38:13 +0100 Subject: [PATCH] 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);