3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-01-18 00:08:59 +00:00
This commit is contained in:
Emil J. Tywoniak 2026-01-07 21:38:13 +01:00
parent 1567526954
commit 340fec0a67

View file

@ -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 <deque>
#ifdef _MSC_VER
#include <stdlib.h>
#define __builtin_bswap32 _byteswap_ulong
@ -127,14 +129,20 @@ struct ConstEvalAig
void compute_deps(RTLIL::SigBit output, const pool<RTLIL::SigBit> &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<uint32_t> inputs;
void process(ConstEvalAig& ce, int aiger_autoidx, std::vector<bool>& lut_defined, std::deque<Lut>& 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<bool> lut_defined;
std::deque<Lut> 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);