From: Eddie Hung Date: Thu, 14 Feb 2019 01:00:00 +0000 (-0800) Subject: Use ConstEval to compute LUT masks X-Git-Tag: working-ls180~1237^2~339 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=13bf036bd6f78f57d6431171aca49984898a2bdd;p=yosys.git Use ConstEval to compute LUT masks --- diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 56bffcf38..62354498c 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -24,6 +24,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" +#include "kernel/consteval.h" #include "aigerparse.h" #include @@ -71,9 +72,9 @@ void AigerReader::parse_aiger() line_count = 1; if (header == "aag") - parse_aiger_ascii(true /* create_and */); + parse_aiger_ascii(); else if (header == "aig") - parse_aiger_binary(true /* create_and */); + parse_aiger_binary(); else log_abort(); @@ -123,6 +124,32 @@ static uint32_t parse_xaiger_literal(std::istream &f) return l.value(); } +static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) +{ + const unsigned variable = literal >> 1; + const bool invert = literal & 1; + RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? + RTLIL::Wire *wire = module->wire(wire_name); + if (wire) return wire; + log_debug("Creating %s\n", wire_name.c_str()); + wire = module->addWire(wire_name); + if (!invert) return wire; + RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); + RTLIL::Wire *wire_inv = module->wire(wire_inv_name); + if (wire_inv) { + if (module->cell(wire_inv_name)) return wire; + } + else { + log_debug("Creating %s\n", wire_inv_name.c_str()); + wire_inv = module->addWire(wire_inv_name); + } + + log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); + module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? + + return wire; +} + void AigerReader::parse_xaiger() { std::string header; @@ -147,9 +174,9 @@ void AigerReader::parse_xaiger() line_count = 1; if (header == "aag") - parse_aiger_ascii(false /* create_and */); + parse_aiger_ascii(); else if (header == "aig") - parse_aiger_binary(false /* create_and */); + parse_aiger_binary(); else log_abort(); @@ -162,11 +189,11 @@ void AigerReader::parse_xaiger() if (!comment_seen) { f.ignore(1); c = f.peek(); - if (c == '\n') - break; - f.ignore(1); comment_seen = true; } + if (c == '\n') + break; + f.ignore(1); // XAIGER extensions if (c == 'm') { uint32_t dataSize = parse_xaiger_literal(f); @@ -178,7 +205,6 @@ void AigerReader::parse_xaiger() uint32_t cutLeavesM = parse_xaiger_literal(f); log_debug("rootNodeID=%d cutLeavesM=%d\n", rootNodeID, cutLeavesM); RTLIL::Wire *output_sig = module->wire(stringf("\\n%d", rootNodeID)); - log_assert(output_sig); uint32_t nodeID; RTLIL::SigSpec input_sig; for (unsigned j = 0; j < cutLeavesM; ++j) { @@ -188,17 +214,30 @@ void AigerReader::parse_xaiger() log_assert(wire); input_sig.append(wire); } + RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size()); + ConstEval ce(module); + for (int j = 0; j < (1 << cutLeavesM); ++j) { + ce.push(); + ce.set(input_sig, RTLIL::Const{j, static_cast(cutLeavesM)}); + RTLIL::SigSpec o(output_sig); + ce.eval(o); + lut_mask[j] = o.as_const()[0]; + ce.pop(); + } + RTLIL::Cell *output_cell = module->cell(stringf("\\n%d_and", rootNodeID)); + log_assert(output_cell); + module->remove(output_cell); RTLIL::Cell *cell = module->addCell(NEW_ID, "$lut"); cell->parameters["\\WIDTH"] = RTLIL::Const(input_sig.size()); - cell->parameters["\\LUT"] = RTLIL::Const(RTLIL::State::Sx, 1 << input_sig.size()); + cell->parameters["\\LUT"] = std::move(lut_mask); cell->setPort("\\A", input_sig); cell->setPort("\\Y", output_sig); } } else if (c == 'n') { - // TODO: What is this? - uint32_t n = parse_xaiger_literal(f); - f.seekg(n); + parse_xaiger_literal(f); + f >> s; + log_debug("n: '%s'\n", s.c_str()); } } else if (c == 'i' || c == 'l' || c == 'o') { @@ -265,8 +304,7 @@ void AigerReader::parse_xaiger() } } - for (auto &wp : wideports_cache) - { + for (auto &wp : wideports_cache) { auto name = wp.first; int width = wp.second + 1; @@ -283,8 +321,10 @@ void AigerReader::parse_xaiger() wire->port_output = other_wire->port_output; other_wire->port_input = false; other_wire->port_output = false; - if (wire->port_output) + if (wire->port_input) { + log_debug("assign %s = %s [%d];\n", other_wire->name.c_str(), wire->name.c_str(), i); module->connect(other_wire, SigSpec(wire, i)); + } else module->connect(SigSpec(wire, i), other_wire); } @@ -295,33 +335,7 @@ void AigerReader::parse_xaiger() design->add(module); } -static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal) -{ - const unsigned variable = literal >> 1; - const bool invert = literal & 1; - RTLIL::IdString wire_name(stringf("\\n%d%s", variable, invert ? "_inv" : "")); // FIXME: is "_inv" the right suffix? - RTLIL::Wire *wire = module->wire(wire_name); - if (wire) return wire; - log_debug("Creating %s\n", wire_name.c_str()); - wire = module->addWire(wire_name); - if (!invert) return wire; - RTLIL::IdString wire_inv_name(stringf("\\n%d", variable)); - RTLIL::Wire *wire_inv = module->wire(wire_inv_name); - if (wire_inv) { - if (module->cell(wire_inv_name)) return wire; - } - else { - log_debug("Creating %s\n", wire_inv_name.c_str()); - wire_inv = module->addWire(wire_inv_name); - } - - log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str()); - module->addNotGate(stringf("\\n%d_not", variable), wire_inv, wire); // FIXME: is "_not" the right suffix? - - return wire; -} - -void AigerReader::parse_aiger_ascii(bool create_and) +void AigerReader::parse_aiger_ascii() { std::string line; std::stringstream ss; @@ -412,13 +426,11 @@ void AigerReader::parse_aiger_ascii(bool create_and) log_error("Line %u cannot be interpreted as an AND!\n", line_count); log_debug("%d %d %d is an AND\n", l1, l2, l3); - if (create_and) { - log_assert(!(l1 & 1)); - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - module->addAndGate(NEW_ID, i1_wire, i2_wire, o_wire); - } + log_assert(!(l1 & 1)); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); } } @@ -431,7 +443,7 @@ static unsigned parse_next_delta_literal(std::istream &f, unsigned ref) return ref - (x | (ch << (7 * i))); } -void AigerReader::parse_aiger_binary(bool create_and) +void AigerReader::parse_aiger_binary() { unsigned l1, l2, l3; std::string line; @@ -518,17 +530,11 @@ void AigerReader::parse_aiger_binary(bool create_and) l3 = parse_next_delta_literal(f, l2); log_debug("%d %d %d is an AND\n", l1, l2, l3); - if (create_and) { - log_assert(!(l1 & 1)); // TODO: Output of ANDs can't be inverted? - RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); - RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); - RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); - - RTLIL::Cell *and_cell = module->addCell(NEW_ID, "$_AND_"); - and_cell->setPort("\\A", i1_wire); - and_cell->setPort("\\B", i2_wire); - and_cell->setPort("\\Y", o_wire); - } + log_assert(!(l1 & 1)); + RTLIL::Wire *o_wire = createWireIfNotExists(module, l1); + RTLIL::Wire *i1_wire = createWireIfNotExists(module, l2); + RTLIL::Wire *i2_wire = createWireIfNotExists(module, l3); + module->addAndGate(o_wire->name.str() + "_and", i1_wire, i2_wire, o_wire); } } diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h index a1d2af9c9..42c87a298 100644 --- a/frontends/aiger/aigerparse.h +++ b/frontends/aiger/aigerparse.h @@ -44,8 +44,8 @@ struct AigerReader AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports); void parse_aiger(); void parse_xaiger(); - void parse_aiger_ascii(bool create_and); - void parse_aiger_binary(bool create_and); + void parse_aiger_ascii(); + void parse_aiger_binary(); }; YOSYS_NAMESPACE_END