From: Eddie Hung Date: Mon, 30 Dec 2019 22:31:42 +0000 (-0800) Subject: Merge remote-tracking branch 'origin/master' into xaig_dff X-Git-Tag: working-ls180~881^2^2~52 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=405e974fe51f4ede0b374ddddc398a26e04b0265;p=yosys.git Merge remote-tracking branch 'origin/master' into xaig_dff --- 405e974fe51f4ede0b374ddddc398a26e04b0265 diff --cc backends/aiger/xaiger.cc index d27e0cde5,445103771..bfdae7160 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@@ -78,12 -78,10 +78,11 @@@ struct XAigerWrite Module *module; SigMap sigmap; - pool input_bits, output_bits; + pool input_bits, output_bits, external_bits; dict not_map, alias_map; dict> and_map; - vector> ci_bits; - vector> co_bits; + vector ci_bits, co_bits; + dict> ff_bits; dict arrival_times; vector> aig_gates; @@@ -440,8 -376,8 +438,8 @@@ else alias_map[b] = I; } - co_bits.emplace_back(b, cell, port_name, offset++, 0); + co_bits.emplace_back(b); - unused_bits.erase(b); + unused_bits.erase(I); } } if (w->port_output) { @@@ -471,29 -405,7 +468,28 @@@ } } } + + // Connect .$abc9_currQ (inserted by abc9_map.v) as an input to the flop box + if (box_module->get_bool_attribute("\\abc9_flop")) { + SigSpec rhs = module->wire(stringf("%s.$abc9_currQ", cell->name.c_str())); + if (rhs.empty()) + log_error("'%s.$abc9_currQ' is not a wire present in module '%s'.\n", log_id(cell), log_id(module)); + - int offset = 0; + for (auto b : rhs) { + SigBit I = sigmap(b); + if (b == RTLIL::Sx) + b = State::S0; + else if (I != b) { + if (I == RTLIL::Sx) + alias_map[b] = State::S0; + else + alias_map[b] = I; + } - co_bits.emplace_back(b, cell, "\\$abc9_currQ", offset++, 0); ++ co_bits.emplace_back(b); + unused_bits.erase(I); + } + } + box_list.emplace_back(cell); } @@@ -570,18 -489,8 +566,16 @@@ aig_map[bit] = 2*aig_m; } + dict ff_aig_map; - for (auto &c : ci_bits) { - RTLIL::SigBit bit = std::get<0>(c); ++ for (auto &bit : ci_bits) { + aig_m++, aig_i++; + auto r = aig_map.insert(std::make_pair(bit, 2*aig_m)); + if (!r.second) + ff_aig_map[bit] = 2*aig_m; + } + - for (auto &c : co_bits) { - RTLIL::SigBit bit = std::get<0>(c); - std::get<4>(c) = ordered_outputs[bit] = aig_o++; + for (auto bit : co_bits) { + ordered_outputs[bit] = aig_o++; aig_outputs.push_back(bit2aig(bit)); } @@@ -829,52 -697,22 +834,53 @@@ //holes_module->fixup_ports(); holes_module->check(); - // TODO: Should techmap/aigmap/check all lib_whitebox-es just once, - // instead of per write_xaiger call - holes_module->design->selection_stack.emplace_back(false); - RTLIL::Selection& sel = holes_module->design->selection_stack.back(); - sel.select(holes_module); - - Pass::call(holes_module->design, "flatten -wb"); - + // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger + // since boxes may contain parameters in which case `flatten` would have + // created a new $paramod ... - Pass::call(holes_module->design, "techmap"); - Pass::call(holes_module->design, "aigmap"); - for (auto cell : holes_module->cells()) - if (!cell->type.in("$_NOT_", "$_AND_")) + Pass::call_on_module(holes_module->design, holes_module, "flatten -wb; techmap; aigmap"); + + dict replace; + for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) { + auto cell = it->second; + if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", + "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) { + SigBit D = cell->getPort("\\D"); + SigBit Q = cell->getPort("\\Q"); + // Remove the DFF cell from what needs to be a combinatorial box + it = holes_module->cells_.erase(it); + Wire *port; + if (GetSize(Q.wire) == 1) + port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str())); + else + port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset)); + log_assert(port); + // Prepare to replace "assign = DFF.Q;" with "assign = DFF.D;" + // in order to extract the combinatorial control logic that feeds the box + // (i.e. clock enable, synchronous reset, etc.) + replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,D))); + // Since `flatten` above would have created wires named ".Q", + // extract the pre-techmap cell name + auto pos = Q.wire->name.str().rfind("."); + log_assert(pos != std::string::npos); + IdString driver = Q.wire->name.substr(0, pos); + // And drive the signal that was previously driven by "DFF.Q" (typically + // used to implement clock-enable functionality) with the ".$abc9_currQ" + // wire (which itself is driven an input port) we inserted above + Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str())); + log_assert(currQ); + holes_module->connect(Q, currQ); + continue; + } + else if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); + ++it; + } - holes_module->design->selection_stack.pop_back(); + for (auto &conn : holes_module->connections_) { + auto it = replace.find(conn); + if (it != replace.end()) + conn = it->second; + } // Move into a new (temporary) design so that "clean" will only // operate (and run checks on) this one module diff --cc techlibs/xilinx/synth_xilinx.cc index e7069f286,d4095e449..f2a9ae982 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@@ -125,8 -120,7 +123,8 @@@ struct SynthXilinxPass : public ScriptP } std::string top_opt, edif_file, blif_file, family; - bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; - bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram, abc9; ++ bool flatten, retime, vpr, ise, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, uram; + bool abc9, dff_mode; bool flatten_before_abc; int widemux;