Merge remote-tracking branch 'origin/master' into xaig_dff
authorEddie Hung <eddie@fpgeh.com>
Mon, 30 Dec 2019 22:31:42 +0000 (14:31 -0800)
committerEddie Hung <eddie@fpgeh.com>
Mon, 30 Dec 2019 22:31:42 +0000 (14:31 -0800)
1  2 
backends/aiger/xaiger.cc
techlibs/xilinx/cells_sim.v
techlibs/xilinx/synth_xilinx.cc

index d27e0cde5c5aa85f30cbd9b51f2bfd78f32bc2d9,4451037713b8c5b1e0323472252d4e924fef6057..bfdae7160887b674c2225182ffec0949308eea3b
@@@ -78,12 -78,10 +78,11 @@@ struct XAigerWrite
        Module *module;
        SigMap sigmap;
  
 -      pool<SigBit> input_bits, output_bits;
 +      pool<SigBit> input_bits, output_bits, external_bits;
        dict<SigBit, SigBit> not_map, alias_map;
        dict<SigBit, pair<SigBit, SigBit>> and_map;
-       vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int>> ci_bits;
-       vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int,int>> co_bits;
+       vector<SigBit> ci_bits, co_bits;
 +      dict<SigBit, std::pair<int,int>> ff_bits;
        dict<SigBit, float> arrival_times;
  
        vector<pair<int, int>> aig_gates;
                                                                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) {
                                                }
                                        }
                                }
-                                       int offset = 0;
 +
 +                              // Connect <cell>.$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));
 +
-                                               co_bits.emplace_back(b, cell, "\\$abc9_currQ", 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);
 +                                              unused_bits.erase(I);
 +                                      }
 +                              }
 +
                                box_list.emplace_back(cell);
                        }
  
                        aig_map[bit] = 2*aig_m;
                }
  
-               for (auto &c : ci_bits) {
-                       RTLIL::SigBit bit = std::get<0>(c);
 +              dict<SigBit, int> ff_aig_map;
-               for (auto &c : co_bits) {
-                       RTLIL::SigBit bit = std::get<0>(c);
-                       std::get<4>(c) = ordered_outputs[bit] = aig_o++;
++              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 bit : co_bits) {
+                       ordered_outputs[bit] = aig_o++;
                        aig_outputs.push_back(bit2aig(bit));
                }
  
                                //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<SigSig, SigSig> 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 <port> = DFF.Q;" with "assign <port> = 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 "<cell>.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 "<cell>.$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
Simple merge
index e7069f2865f5a4bf96db83999a2e13bce2c45493,d4095e449b238d442e96d147fb238130f19a79a5..f2a9ae9823c0d0cbc80f0297b0396dac148c0f7c
@@@ -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;