Merge remote-tracking branch 'origin/xc7mux' into xaig
authorEddie Hung <eddie@fpgeh.com>
Wed, 12 Jun 2019 15:52:46 +0000 (08:52 -0700)
committerEddie Hung <eddie@fpgeh.com>
Wed, 12 Jun 2019 15:52:46 +0000 (08:52 -0700)
34 files changed:
CHANGELOG
Makefile
backends/aiger/xaiger.cc
backends/json/json.cc
passes/cmds/stat.cc
passes/opt/Makefile.inc
passes/opt/muxpack.cc [new file with mode: 0644]
passes/sat/expose.cc
passes/techmap/abc9.cc
passes/techmap/shregmap.cc
techlibs/ice40/abc_hx.box
techlibs/ice40/abc_lp.box
techlibs/ice40/abc_u.box
techlibs/ice40/cells_map.v
techlibs/ice40/cells_sim.v
techlibs/ice40/synth_ice40.cc
techlibs/xilinx/Makefile.inc
techlibs/xilinx/abc.box [new file with mode: 0644]
techlibs/xilinx/abc.lut [new file with mode: 0644]
techlibs/xilinx/arith_map.v
techlibs/xilinx/brams_bb.v
techlibs/xilinx/cells_map.v
techlibs/xilinx/cells_sim.v
techlibs/xilinx/cells_xtra.sh
techlibs/xilinx/cells_xtra.v
techlibs/xilinx/mux_map.v [new file with mode: 0644]
tests/simple_abc9/abc.box [new file with mode: 0644]
tests/simple_abc9/abc9.v
tests/simple_abc9/run-test.sh
tests/tools/autotest.sh
tests/various/muxpack.v [new file with mode: 0644]
tests/various/muxpack.ys [new file with mode: 0644]
tests/various/shregmap.v [new file with mode: 0644]
tests/various/shregmap.ys [new file with mode: 0644]

index 839fefcf1d0b57888408eb5dc20bc8dae561733f..c1b548aebbcb4c416733b71fc922987876acfe55 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,7 +17,9 @@ Yosys 0.8 .. Yosys 0.8-dev
     - Added "rename -src"
     - Added "equiv_opt" pass
     - Added "read_aiger" frontend
+    - Added "muxpack" pass
     - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx"
+    - "synth_xilinx" to now infer wide multiplexers
 
 
 Yosys 0.7 .. Yosys 0.8
index 76dac48a586c2ae9dd8c8b9b73f5a5c14cc5e3d6..fb0eaf14dc7d3290801996d036eaa374d8ceabc5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -122,7 +122,7 @@ OBJS = kernel/version_$(GIT_REV).o
 # is just a symlink to your actual ABC working directory, as 'make mrproper'
 # will remove the 'abc' directory and you do not want to accidentally
 # delete your work on ABC..
-ABCREV = 3709744
+ABCREV = 62487de
 ABCPULL = 1
 ABCURL ?= https://github.com/berkeley-abc/abc
 ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
index 7126002f65bcf94b0e4dbfc491dd88cf6ece5b2b..bf2f9f1bc1d20746ec9494d0a480aca48b631e07 100644 (file)
@@ -49,7 +49,8 @@ struct XAigerWriter
        dict<SigBit, SigBit> not_map, ff_map, alias_map;
        dict<SigBit, pair<SigBit, SigBit>> and_map;
        //pool<SigBit> initstate_bits;
-       vector<std::pair<SigBit,int>> ci_bits, co_bits;
+       vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int>> ci_bits;
+       vector<std::tuple<SigBit,RTLIL::Cell*,RTLIL::IdString,int,int>> co_bits;
        vector<std::pair<SigBit,SigBit>> ff_bits;
 
        vector<pair<int, int>> aig_gates;
@@ -152,10 +153,11 @@ struct XAigerWriter
                                undriven_bits.insert(bit);
                                unused_bits.insert(bit);
 
-                               if (wire->port_input)
-                                       input_bits.insert(bit);
-                               else if (keep)
+                               if (wire->port_input || keep) {
+                                       if (bit != wirebit)
+                                               alias_map[bit] = wirebit;
                                        input_bits.insert(wirebit);
+                               }
 
                                if (wire->port_output || keep) {
                                        if (bit != wirebit)
@@ -166,7 +168,7 @@ struct XAigerWriter
                }
 
                for (auto bit : input_bits)
-                       undriven_bits.erase(bit);
+                       undriven_bits.erase(sigmap(bit));
 
                for (auto bit : output_bits)
                        if (!bit.wire->port_input)
@@ -179,15 +181,17 @@ struct XAigerWriter
                for (auto cell : module->cells())
                {
                        RTLIL::Module* inst_module = module->design->module(cell->type);
-                       bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false;
-                       bool known_type = yosys_celltypes.cell_known(cell->type);
+                       bool builtin_type = yosys_celltypes.cell_known(cell->type);
+                       bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id");
 
                        if (!holes_mode) {
                                toposort.node(cell->name);
-                               for (const auto &conn : cell->connections())
-                               {
+                               for (const auto &conn : cell->connections()) {
+                                       if (!builtin_type && !abc_type)
+                                               continue;
+
                                        if (!cell->type.in("$_NOT_", "$_AND_")) {
-                                               if (known_type) {
+                                               if (builtin_type) {
                                                        if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA"))
                                                                continue;
                                                        if (cell->type == "$memrd" && conn.first == "\\DATA")
@@ -198,8 +202,8 @@ struct XAigerWriter
                                                        RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
                                                        log_assert(inst_module_port);
 
-                                                       if (inst_module_port->attributes.count("\\abc_flop_q"))
-                                                               continue;
+                                                       if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q"))
+                                                                       continue;
                                                }
                                        }
 
@@ -256,22 +260,28 @@ struct XAigerWriter
                        //      continue;
                        //}
 
+                       bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false;
                        if (inst_flop) {
                                SigBit d, q;
                                for (const auto &c : cell->connections()) {
+                                       auto is_input = cell->input(c.first);
+                                       auto is_output = cell->output(c.first);
+                                       log_assert(is_input || is_output);
+                                       RTLIL::Wire* port = inst_module->wire(c.first);
                                        for (auto b : c.second.bits()) {
-                                               auto is_input = cell->input(c.first);
-                                               auto is_output = cell->output(c.first);
-                                               log_assert(is_input || is_output);
-                                               if (is_input && inst_module->wire(c.first)->attributes.count("\\abc_flop_d")) {
-                                                       SigBit I = sigmap(b);
-                                                       if (I != b)
-                                                               alias_map[b] = I;
+                                               if (is_input && port->attributes.count("\\abc_flop_d")) {
                                                        d = b;
+                                                       SigBit I = sigmap(d);
+                                                       if (I != d)
+                                                               alias_map[I] = d;
+                                                       unused_bits.erase(d);
                                                }
-                                               if (is_output && inst_module->wire(c.first)->attributes.count("\\abc_flop_q")) {
-                                                   SigBit O = sigmap(b);
-                                                       q = O;
+                                               if (is_output && port->attributes.count("\\abc_flop_q")) {
+                                                       q = b;
+                                                       SigBit O = sigmap(q);
+                                                       if (O != q)
+                                                               alias_map[O] = q;
+                                                       undriven_bits.erase(O);
                                                }
                                        }
                                }
@@ -279,7 +289,6 @@ struct XAigerWriter
                                        abc_box_seen = inst_module->attributes.count("\\abc_box_id");
 
                                ff_bits.emplace_back(d, q);
-                               undriven_bits.erase(q);
                        }
                        else if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
                                abc_box_seen = true;
@@ -303,8 +312,10 @@ struct XAigerWriter
                                                        }
                                                }
                                                if (is_output) {
+                                                       input_bits.insert(b);
                                                        SigBit O = sigmap(b);
-                                                       input_bits.insert(O);
+                                                       if (O != b)
+                                                               alias_map[O] = b;
                                                        undriven_bits.erase(O);
                                                }
                                        }
@@ -321,19 +332,22 @@ struct XAigerWriter
                                        for (auto user_cell : it.second)
                                                toposort.edge(driver_cell, user_cell);
 
-#ifndef NDEBUG
+                       pool<RTLIL::Module*> abc_carry_modules;
+
+#if 0
                        toposort.analyze_loops = true;
 #endif
-                       toposort.sort();
-#ifndef NDEBUG
+                       bool no_loops = toposort.sort();
+#if 0
+                       unsigned i = 0;
                        for (auto &it : toposort.loops) {
-                               log("  loop");
+                               log("  loop %d", i++);
                                for (auto cell : it)
                                        log(" %s", log_id(cell));
                                log("\n");
                        }
 #endif
-                       log_assert(!toposort.found_loops);
+                       log_assert(no_loops);
 
                        for (auto cell_name : toposort.sorted) {
                                RTLIL::Cell *cell = module->cell(cell_name);
@@ -341,26 +355,100 @@ struct XAigerWriter
                                if (!box_module || !box_module->attributes.count("\\abc_box_id"))
                                        continue;
 
-                               // Box ordering is alphabetical
-                               cell->connections_.sort(RTLIL::sort_by_id_str());
-                               for (const auto &c : cell->connections()) {
-                                       for (auto b : c.second.bits()) {
-                                               auto is_input = cell->input(c.first);
-                                               auto is_output = cell->output(c.first);
-                                               log_assert(is_input || is_output);
-                                               if (is_input) {
+                               if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) {
+                                       RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr;
+                                       RTLIL::Wire* last_in = nullptr, *last_out = nullptr;
+                                       for (const auto &port_name : box_module->ports) {
+                                               RTLIL::Wire* w = box_module->wire(port_name);
+                                               log_assert(w);
+                                               if (w->port_input) {
+                                                       if (w->attributes.count("\\abc_carry_in")) {
+                                                               log_assert(!carry_in);
+                                                               carry_in = w;
+                                                       }
+                                                       log_assert(!last_in || last_in->port_id < w->port_id);
+                                                       last_in = w;
+                                               }
+                                               if (w->port_output) {
+                                                       if (w->attributes.count("\\abc_carry_out")) {
+                                                               log_assert(!carry_out);
+                                                               carry_out = w;
+                                                       }
+                                                       log_assert(!last_out || last_out->port_id < w->port_id);
+                                                       last_out = w;
+                                               }
+                                       }
+
+                                       if (carry_in) {
+                                               log_assert(last_in);
+                                               std::swap(box_module->ports[carry_in->port_id-1], box_module->ports[last_in->port_id-1]);
+                                               std::swap(carry_in->port_id, last_in->port_id);
+                                       }
+                                       if (carry_out) {
+                                               log_assert(last_out);
+                                               std::swap(box_module->ports[carry_out->port_id-1], box_module->ports[last_out->port_id-1]);
+                                               std::swap(carry_out->port_id, last_out->port_id);
+                                       }
+                               }
+
+                               // Fully pad all unused input connections of this box cell with S0
+                               // Fully pad all undriven output connections of this box cell with anonymous wires
+                               // NB: Assume box_module->ports are sorted alphabetically
+                               //     (as RTLIL::Module::fixup_ports() would do)
+                               for (const auto &port_name : box_module->ports) {
+                                       RTLIL::Wire* w = box_module->wire(port_name);
+                                       log_assert(w);
+                                       auto it = cell->connections_.find(port_name);
+                                       if (w->port_input) {
+                                               RTLIL::SigSpec rhs;
+                                               if (it != cell->connections_.end()) {
+                                                       if (GetSize(it->second) < GetSize(w))
+                                                               it->second.append(RTLIL::SigSpec(RTLIL::S0, GetSize(w)-GetSize(it->second)));
+                                                       rhs = it->second;
+                                               }
+                                               else {
+                                                       rhs = RTLIL::SigSpec(RTLIL::S0, GetSize(w));
+                                                       cell->setPort(port_name, rhs);
+                                               }
+
+                                               int offset = 0;
+                                               for (const auto &b : rhs.bits()) {
                                                        SigBit I = sigmap(b);
                                                        if (I != b)
                                                                alias_map[b] = I;
-                                                       co_bits.emplace_back(b, 0);
+                                                       co_bits.emplace_back(b, cell, port_name, offset++, 0);
+                                                       unused_bits.erase(b);
                                                }
-                                               if (is_output) {
+                                       }
+                                       if (w->port_output) {
+                                               RTLIL::SigSpec rhs;
+                                               auto it = cell->connections_.find(w->name);
+                                               if (it != cell->connections_.end()) {
+                                                       if (GetSize(it->second) < GetSize(w))
+                                                               it->second.append(module->addWire(NEW_ID, GetSize(w)-GetSize(it->second)));
+                                                       rhs = it->second;
+                                               }
+                                               else {
+                                                       rhs = module->addWire(NEW_ID, GetSize(w));
+                                                       cell->setPort(port_name, rhs);
+                                               }
+
+                                               int offset = 0;
+                                               for (const auto &b : rhs.bits()) {
+                                                       ci_bits.emplace_back(b, cell, port_name, offset++);
                                                        SigBit O = sigmap(b);
-                                                       ci_bits.emplace_back(O, 0);
+                                                       if (O != b)
+                                                               alias_map[O] = b;
+                                                       undriven_bits.erase(O);
+
+                                                       auto jt = input_bits.find(b);
+                                                       if (jt != input_bits.end()) {
+                                                               log_assert(b.wire->attributes.count("\\keep"));
+                                                               input_bits.erase(b);
+                                                       }
                                                }
                                        }
                                }
-
                                box_list.emplace_back(cell);
                        }
 
@@ -375,9 +463,10 @@ struct XAigerWriter
                        if ((wire->port_input && wire->port_output && !undriven_bits.count(bit))
                                        || wire->attributes.count("\\keep")) {
                                log_assert(input_bits.count(bit) && output_bits.count(bit));
-                               RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out");
+                               RTLIL::IdString wire_name = wire->name.str() + "$inout.out";
+                               RTLIL::Wire *new_wire = module->wire(wire_name);
                                if (!new_wire)
-                                       new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire));
+                                       new_wire = module->addWire(wire_name, GetSize(wire));
                                SigBit new_bit(new_wire, bit.offset);
                                module->connect(new_bit, bit);
                                if (not_map.count(bit))
@@ -394,13 +483,10 @@ struct XAigerWriter
                        }
                }
 
-               // Do some CI/CO post-processing:
                // Erase all POs that are undriven
-               for (auto bit : undriven_bits)
-                       output_bits.erase(bit);
-               // CIs cannot be undriven
-               for (const auto &c : ci_bits)
-                       undriven_bits.erase(c.first);
+               if (!holes_mode)
+                       for (auto bit : undriven_bits)
+                               output_bits.erase(bit);
                for (auto bit : unused_bits)
                        undriven_bits.erase(bit);
 
@@ -414,8 +500,20 @@ struct XAigerWriter
                }
 
                init_map.sort();
-               input_bits.sort();
-               output_bits.sort();
+               if (holes_mode) {
+                       struct sort_by_port_id {
+                               bool operator()(const RTLIL::SigBit& a, const RTLIL::SigBit& b) const {
+                                       return a.wire->port_id < b.wire->port_id;
+                               }
+                       };
+                       input_bits.sort(sort_by_port_id());
+                       output_bits.sort(sort_by_port_id());
+               }
+               else {
+                       input_bits.sort();
+                       output_bits.sort();
+               }
+
                not_map.sort();
                ff_map.sort();
                and_map.sort();
@@ -425,23 +523,24 @@ struct XAigerWriter
 
                for (auto bit : input_bits) {
                        aig_m++, aig_i++;
+                       log_assert(!aig_map.count(bit));
                        aig_map[bit] = 2*aig_m;
                }
 
                for (auto &f : ff_bits) {
-                       auto bit = f.second;
+                       RTLIL::SigBit bit = f.second;
                        aig_m++, aig_i++;
+                       log_assert(!aig_map.count(bit));
                        aig_map[bit] = 2*aig_m;
                }
 
                dict<SigBit, int> ff_aig_map;
                for (auto &c : ci_bits) {
+                       RTLIL::SigBit bit = std::get<0>(c);
                        aig_m++, aig_i++;
-                       c.second = 2*aig_m;
-                       auto r = aig_map.insert(std::make_pair(c.first, c.second));
-                       if (!r.second) {
-                               ff_aig_map[c.first] = c.second;
-                       }
+                       auto r = aig_map.insert(std::make_pair(bit, 2*aig_m));
+                       if (!r.second)
+                               ff_aig_map[bit] = 2*aig_m;
                }
 
                if (imode && input_bits.empty()) {
@@ -505,9 +604,8 @@ struct XAigerWriter
                //      aig_latchin.push_back(1);
 
                for (auto &c : co_bits) {
-                       RTLIL::SigBit bit = c.first;
-                       c.second = aig_o++;
-                       ordered_outputs[bit] = c.second;
+                       RTLIL::SigBit bit = std::get<0>(c);
+                       std::get<4>(c) = ordered_outputs[bit] = aig_o++;
                        aig_outputs.push_back(bit2aig(bit));
                }
 
@@ -518,7 +616,8 @@ struct XAigerWriter
 
                for (auto &f : ff_bits) {
                        aig_o++;
-                       aig_outputs.push_back(ff_aig_map.at(f.second));
+                       RTLIL::SigBit bit = f.second;
+                       aig_outputs.push_back(ff_aig_map.at(bit));
                }
 
                if (omode && output_bits.empty()) {
@@ -693,49 +792,79 @@ struct XAigerWriter
                        if (omode && num_outputs == 0)
                                num_outputs = 1;
                        write_h_buffer(1);
+                       log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size());
                        write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size());
-                       write_h_buffer(num_outputs + ff_bits.size() + co_bits.size());
-                       write_h_buffer(input_bits.size() + ff_bits.size());
+                       log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size());
+                       write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size());
+                       log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size());
+                       write_h_buffer(input_bits.size()+ ff_bits.size());
+                       log_debug("poNum = %zu\n", num_outputs + ff_bits.size());
                        write_h_buffer(num_outputs + ff_bits.size());
+                       log_debug("boxNum = %zu\n", box_list.size());
                        write_h_buffer(box_list.size());
 
                        RTLIL::Module *holes_module = nullptr;
                        holes_module = module->design->addModule("\\__holes__");
+                       log_assert(holes_module);
 
+                       int port_id = 1;
+                       int box_count = 0;
                        for (auto cell : box_list) {
+                               RTLIL::Module* box_module = module->design->module(cell->type);
                                int box_inputs = 0, box_outputs = 0;
-                               int box_id = module->design->module(cell->type)->attributes.at("\\abc_box_id").as_int();
                                Cell *holes_cell = nullptr;
-                               if (holes_module && !holes_module->cell(stringf("\\u%d", box_id)))
-                                       holes_cell = holes_module->addCell(stringf("\\u%d", box_id), cell->type);
-                               RTLIL::Wire *holes_wire;
-                               // NB: cell->connections_ already sorted from before
-                               for (const auto &c : cell->connections()) {
-                                       log_assert(c.second.size() == 1);
-                                       if (cell->input(c.first)) {
-                                               box_inputs += c.second.size();
-                                               if (holes_cell) {
+                               if (box_module->get_bool_attribute("\\whitebox")) {
+                                       holes_cell = holes_module->addCell(cell->name, cell->type);
+                                       holes_cell->parameters = cell->parameters;
+                               }
+
+                               // NB: Assume box_module->ports are sorted alphabetically
+                               //     (as RTLIL::Module::fixup_ports() would do)
+                               for (const auto &port_name : box_module->ports) {
+                                       RTLIL::Wire *w = box_module->wire(port_name);
+                                       log_assert(w);
+                                       RTLIL::Wire *holes_wire;
+                                       RTLIL::SigSpec port_wire;
+                                       if (w->port_input) {
+                                               for (int i = 0; i < GetSize(w); i++) {
+                                                       box_inputs++;
                                                        holes_wire = holes_module->wire(stringf("\\i%d", box_inputs));
                                                        if (!holes_wire) {
                                                                holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs));
                                                                holes_wire->port_input = true;
+                                                               holes_wire->port_id = port_id++;
+                                                               holes_module->ports.push_back(holes_wire->name);
                                                        }
-                                                       holes_cell->setPort(c.first, holes_wire);
+                                                       if (holes_cell)
+                                                               port_wire.append(holes_wire);
                                                }
+                                               if (!port_wire.empty())
+                                                       holes_cell->setPort(w->name, port_wire);
                                        }
-                                       if (cell->output(c.first)) {
-                                               box_outputs += c.second.size();
-                                               if (holes_cell) {
-                                                       holes_wire = holes_module->addWire(stringf("\\%s.%s", cell->type.c_str(), c.first.c_str()));
+                                       if (w->port_output) {
+                                               box_outputs += GetSize(w);
+                                               for (int i = 0; i < GetSize(w); i++) {
+                                                       if (GetSize(w) == 1)
+                                                               holes_wire = holes_module->addWire(stringf("%s.%s", cell->name.c_str(), w->name.c_str()));
+                                                       else
+                                                               holes_wire = holes_module->addWire(stringf("%s.%s[%d]", cell->name.c_str(), w->name.c_str(), i));
                                                        holes_wire->port_output = true;
-                                                       holes_cell->setPort(c.first, holes_wire);
+                                                       holes_wire->port_id = port_id++;
+                                                       holes_module->ports.push_back(holes_wire->name);
+                                                       if (holes_cell)
+                                                               port_wire.append(holes_wire);
+                                                       else
+                                                               holes_module->connect(holes_wire, RTLIL::S0);
                                                }
+                                               if (!port_wire.empty())
+                                                       holes_cell->setPort(w->name, port_wire);
                                        }
                                }
+
                                write_h_buffer(box_inputs);
                                write_h_buffer(box_outputs);
-                               write_h_buffer(box_id);
-                               write_h_buffer(0 /* OldBoxNum */);
+                               write_h_buffer(box_module->attributes.at("\\abc_box_id").as_int());
+                               write_h_buffer(box_count++);
                        }
 
                        f << "h";
@@ -749,7 +878,7 @@ struct XAigerWriter
                        f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
                        f.write(buffer_str.data(), buffer_str.size());
 
-                       if (!ff_bits.empty()) {
+                       /*if (!ff_bits.empty())*/ {
                                std::stringstream r_buffer;
                                auto write_r_buffer = [&r_buffer](int i32) {
                                        // TODO: Don't assume we're on little endian
@@ -760,6 +889,7 @@ struct XAigerWriter
 #endif
                                        r_buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
                                };
+                               log_debug("flopNum = %zu\n", ff_bits.size());
                                write_r_buffer(ff_bits.size());
                                int mergeability_class = 1;
                                for (auto cell : ff_bits)
@@ -778,13 +908,25 @@ struct XAigerWriter
                        }
 
                        if (holes_module) {
-                               holes_module->fixup_ports();
+                               // NB: fixup_ports() will sort ports by name
+                               //holes_module->fixup_ports();
+                               holes_module->check();
 
                                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; aigmap; clean -purge");
+                               // TODO: Should not need to opt_merge if we only instantiate
+                               //       each box type once...
+                               Pass::call(holes_module->design, "opt_merge -share_all");
+
+                               Pass::call(holes_module->design, "flatten -wb");
+
+                               // TODO: Should techmap all lib_whitebox-es once
+                               //Pass::call(holes_module->design, "techmap");
+
+                               Pass::call(holes_module->design, "aigmap");
+                               Pass::call(holes_module->design, "clean -purge");
 
                                holes_module->design->selection_stack.pop_back();
 
@@ -835,7 +977,7 @@ struct XAigerWriter
 
                                if (output_bits.count(b)) {
                                        int o = ordered_outputs.at(b);
-                                       output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire));
+                                       output_lines[o] += stringf("output %lu %d %s\n", o - co_bits.size(), i, log_id(wire));
                                        continue;
                                }
 
@@ -865,38 +1007,23 @@ struct XAigerWriter
                        }
                }
 
-               for (const auto &c : ci_bits) {
-                       RTLIL::SigBit b = c.first;
-                       RTLIL::Wire *wire = b.wire;
-                       int i = b.offset;
-                       int a = bit2aig(b);
-                       log_assert((a & 1) == 0);
-                       input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
-               }
-
-               for (const auto &c : co_bits) {
-                       RTLIL::SigBit b = c.first;
-                       RTLIL::Wire *wire = b.wire;
-                       int o = c.second;
-                       if (wire)
-                               output_lines[o] += stringf("output %d %d %s\n", o, b.offset, log_id(wire));
-                       else
-                               output_lines[o] += stringf("output %d %d __const%d__\n", o, 0, b.data);
-               }
-
                input_lines.sort();
                for (auto &it : input_lines)
                        f << it.second;
-               log_assert(input_lines.size() == input_bits.size() + ci_bits.size());
+               log_assert(input_lines.size() == input_bits.size());
 
                init_lines.sort();
                for (auto &it : init_lines)
                        f << it.second;
 
+               int box_count = 0;
+               for (auto cell : box_list)
+                       f << stringf("box %d %d %s\n", box_count++, 0, log_id(cell->name));
+
                output_lines.sort();
                for (auto &it : output_lines)
                        f << it.second;
-               log_assert(output_lines.size() == output_bits.size() + co_bits.size());
+               log_assert(output_lines.size() == output_bits.size());
                if (omode && output_bits.empty())
                        f << "output " << output_lines.size() << " 0 __dummy_o__\n";
 
index b4f82a3feb33ee502c1b6cbae00fd2ad450e4c32..f5c687981311febd5e004ea0908ebcde3864fa4f 100644 (file)
@@ -130,75 +130,72 @@ struct JsonWriter
                        f << stringf("        }");
                        first = false;
                }
-               f << stringf("\n      }");
+               f << stringf("\n      },\n");
 
-               if (!module->get_blackbox_attribute()) {
-                       f << stringf(",\n      \"cells\": {");
-                       first = true;
-                       for (auto c : module->cells()) {
-                               if (use_selection && !module->selected(c))
-                                       continue;
-                               f << stringf("%s\n", first ? "" : ",");
-                               f << stringf("        %s: {\n", get_name(c->name).c_str());
-                               f << stringf("          \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
-                               f << stringf("          \"type\": %s,\n", get_name(c->type).c_str());
-                               if (aig_mode) {
-                                       Aig aig(c);
-                                       if (!aig.name.empty()) {
-                                               f << stringf("          \"model\": \"%s\",\n", aig.name.c_str());
-                                               aig_models.insert(aig);
-                                       }
-                               }
-                               f << stringf("          \"parameters\": {");
-                               write_parameters(c->parameters);
-                               f << stringf("\n          },\n");
-                               f << stringf("          \"attributes\": {");
-                               write_parameters(c->attributes);
-                               f << stringf("\n          },\n");
-                               if (c->known()) {
-                                       f << stringf("          \"port_directions\": {");
-                                       bool first2 = true;
-                                       for (auto &conn : c->connections()) {
-                                               string direction = "output";
-                                               if (c->input(conn.first))
-                                                       direction = c->output(conn.first) ? "inout" : "input";
-                                               f << stringf("%s\n", first2 ? "" : ",");
-                                               f << stringf("            %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
-                                               first2 = false;
-                                       }
-                                       f << stringf("\n          },\n");
+               f << stringf("      \"cells\": {");
+               first = true;
+               for (auto c : module->cells()) {
+                       if (use_selection && !module->selected(c))
+                               continue;
+                       f << stringf("%s\n", first ? "" : ",");
+                       f << stringf("        %s: {\n", get_name(c->name).c_str());
+                       f << stringf("          \"hide_name\": %s,\n", c->name[0] == '$' ? "1" : "0");
+                       f << stringf("          \"type\": %s,\n", get_name(c->type).c_str());
+                       if (aig_mode) {
+                               Aig aig(c);
+                               if (!aig.name.empty()) {
+                                       f << stringf("          \"model\": \"%s\",\n", aig.name.c_str());
+                                       aig_models.insert(aig);
                                }
-                               f << stringf("          \"connections\": {");
+                       }
+                       f << stringf("          \"parameters\": {");
+                       write_parameters(c->parameters);
+                       f << stringf("\n          },\n");
+                       f << stringf("          \"attributes\": {");
+                       write_parameters(c->attributes);
+                       f << stringf("\n          },\n");
+                       if (c->known()) {
+                               f << stringf("          \"port_directions\": {");
                                bool first2 = true;
                                for (auto &conn : c->connections()) {
+                                       string direction = "output";
+                                       if (c->input(conn.first))
+                                               direction = c->output(conn.first) ? "inout" : "input";
                                        f << stringf("%s\n", first2 ? "" : ",");
-                                       f << stringf("            %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
+                                       f << stringf("            %s: \"%s\"", get_name(conn.first).c_str(), direction.c_str());
                                        first2 = false;
                                }
-                               f << stringf("\n          }\n");
-                               f << stringf("        }");
-                               first = false;
+                               f << stringf("\n          },\n");
                        }
-                       f << stringf("\n      },\n");
-
-                       f << stringf("      \"netnames\": {");
-                       first = true;
-                       for (auto w : module->wires()) {
-                               if (use_selection && !module->selected(w))
-                                       continue;
-                               f << stringf("%s\n", first ? "" : ",");
-                               f << stringf("        %s: {\n", get_name(w->name).c_str());
-                               f << stringf("          \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
-                               f << stringf("          \"bits\": %s,\n", get_bits(w).c_str());
-                               f << stringf("          \"attributes\": {");
-                               write_parameters(w->attributes);
-                               f << stringf("\n          }\n");
-                               f << stringf("        }");
-                               first = false;
+                       f << stringf("          \"connections\": {");
+                       bool first2 = true;
+                       for (auto &conn : c->connections()) {
+                               f << stringf("%s\n", first2 ? "" : ",");
+                               f << stringf("            %s: %s", get_name(conn.first).c_str(), get_bits(conn.second).c_str());
+                               first2 = false;
                        }
-                       f << stringf("\n      }");
+                       f << stringf("\n          }\n");
+                       f << stringf("        }");
+                       first = false;
+               }
+               f << stringf("\n      },\n");
+
+               f << stringf("      \"netnames\": {");
+               first = true;
+               for (auto w : module->wires()) {
+                       if (use_selection && !module->selected(w))
+                               continue;
+                       f << stringf("%s\n", first ? "" : ",");
+                       f << stringf("        %s: {\n", get_name(w->name).c_str());
+                       f << stringf("          \"hide_name\": %s,\n", w->name[0] == '$' ? "1" : "0");
+                       f << stringf("          \"bits\": %s,\n", get_bits(w).c_str());
+                       f << stringf("          \"attributes\": {");
+                       write_parameters(w->attributes);
+                       f << stringf("\n          }\n");
+                       f << stringf("        }");
+                       first = false;
                }
-               f << stringf("\n");
+               f << stringf("\n      }\n");
 
                f << stringf("    }");
        }
index d22685b62954bfd9b17888618a220e6038c4e634..c42f7fcdd787a50707e415e6580559cbc6329e53 100644 (file)
@@ -339,6 +339,9 @@ struct StatPass : public Pass {
                                if (mod->get_bool_attribute("\\top"))
                                        top_mod = mod;
 
+                       if (mod->attributes.count("\\abc_box_id"))
+                               continue;
+
                        statdata_t data(design, mod, width_mode, cell_area, techname);
                        mod_stat[mod->name] = data;
 
index 337fee9e43f02d3f0f65f41f93347f565ed516ce..ea36463303935a7431f94c4d8d07c84c4ac0e8e0 100644 (file)
@@ -14,5 +14,6 @@ OBJS += passes/opt/opt_demorgan.o
 OBJS += passes/opt/rmports.o
 OBJS += passes/opt/opt_lut.o
 OBJS += passes/opt/pmux2shiftx.o
+OBJS += passes/opt/muxpack.o
 endif
 
diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc
new file mode 100644 (file)
index 0000000..8c4db4e
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *                2019  Eddie Hung    <eddie@fpgeh.com>
+ *
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct MuxpackWorker
+{
+       Module *module;
+       SigMap sigmap;
+
+       int mux_count, pmux_count;
+
+       pool<Cell*> remove_cells;
+
+       dict<SigSpec, Cell*> sig_chain_next;
+       dict<SigSpec, Cell*> sig_chain_prev;
+       pool<SigBit> sigbit_with_non_chain_users;
+       pool<Cell*> chain_start_cells;
+       pool<Cell*> candidate_cells;
+
+       void make_sig_chain_next_prev()
+       {
+               for (auto wire : module->wires())
+               {
+                       if (wire->port_output || wire->get_bool_attribute("\\keep")) {
+                               for (auto bit : sigmap(wire))
+                                       sigbit_with_non_chain_users.insert(bit);
+                       }
+               }
+
+               for (auto cell : module->cells())
+               {
+                       if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
+                       {
+                               SigSpec a_sig = sigmap(cell->getPort("\\A"));
+                               SigSpec b_sig;
+                               if (cell->type == "$mux")
+                                       b_sig = sigmap(cell->getPort("\\B"));
+                               SigSpec y_sig = sigmap(cell->getPort("\\Y"));
+   
+                               if (sig_chain_next.count(a_sig))
+                                       for (auto a_bit : a_sig.bits())
+                                               sigbit_with_non_chain_users.insert(a_bit);
+                               else {
+                                       sig_chain_next[a_sig] = cell;
+                                       candidate_cells.insert(cell);
+                               }
+
+                               if (!b_sig.empty()) {
+                                       if (sig_chain_next.count(b_sig))
+                                               for (auto b_bit : b_sig.bits())
+                                                       sigbit_with_non_chain_users.insert(b_bit);
+                                       else {
+                                               sig_chain_next[b_sig] = cell;
+                                               candidate_cells.insert(cell);
+                                       }
+                               }
+
+                               sig_chain_prev[y_sig] = cell;
+                               continue;
+                       }
+
+                       for (auto conn : cell->connections())
+                               if (cell->input(conn.first))
+                                       for (auto bit : sigmap(conn.second))
+                                               sigbit_with_non_chain_users.insert(bit);
+               }
+       }
+
+       void find_chain_start_cells()
+       {
+               for (auto cell : candidate_cells)
+               {
+                       log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
+
+                       SigSpec a_sig = cell->getPort("\\A");
+                       if (cell->type == "$mux") {
+                               SigSpec b_sig = cell->getPort("\\B");
+                               if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
+                                       goto start_cell;
+
+                               if (!sig_chain_prev.count(a_sig))
+                                       a_sig = b_sig;
+                       }
+                       else if (cell->type == "$pmux") {
+                               if (!sig_chain_prev.count(a_sig))
+                                       goto start_cell;
+                       }
+                       else log_abort();
+
+                       {
+                               for (auto bit : a_sig.bits())
+                                       if (sigbit_with_non_chain_users.count(bit))
+                                               goto start_cell;
+
+                               Cell *c1 = sig_chain_prev.at(a_sig);
+                               Cell *c2 = cell;
+
+                               if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH"))
+                                       goto start_cell;
+                       }
+
+                       continue;
+
+               start_cell:
+                       chain_start_cells.insert(cell);
+               }
+       }
+
+       vector<Cell*> create_chain(Cell *start_cell)
+       {
+               vector<Cell*> chain;
+
+               Cell *c = start_cell;
+               while (c != nullptr)
+               {
+                       chain.push_back(c);
+
+                       SigSpec y_sig = sigmap(c->getPort("\\Y"));
+
+                       if (sig_chain_next.count(y_sig) == 0)
+                               break;
+
+                       c = sig_chain_next.at(y_sig);
+                       if (chain_start_cells.count(c) != 0)
+                               break;
+               }
+
+               return chain;
+       }
+
+       void process_chain(vector<Cell*> &chain)
+       {
+               if (GetSize(chain) < 2)
+                       return;
+
+               int cursor = 0;
+               while (cursor < GetSize(chain))
+               {
+                       int cases = GetSize(chain) - cursor;
+
+                       Cell *first_cell = chain[cursor];
+                       dict<int, SigBit> taps_dict;
+
+                       if (cases < 2) {
+                               cursor++;
+                               continue;
+                       }
+
+                       Cell *last_cell = chain[cursor+cases-1];
+
+                       log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n",
+                               log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases);
+
+                       mux_count += cases;
+                       pmux_count += 1;
+
+                       first_cell->type = "$pmux";
+                       SigSpec b_sig = first_cell->getPort("\\B");
+                       SigSpec s_sig = first_cell->getPort("\\S");
+
+                       for (int i = 1; i < cases; i++) {
+                               Cell* prev_cell = chain[cursor+i-1];
+                               Cell* cursor_cell = chain[cursor+i];
+                               if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
+                                       b_sig.append(cursor_cell->getPort("\\B"));
+                                       s_sig.append(cursor_cell->getPort("\\S"));
+                               }
+                               else {
+                                       b_sig.append(cursor_cell->getPort("\\A"));
+                                       s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
+                               }
+                               remove_cells.insert(cursor_cell);
+                       }
+
+                       first_cell->setPort("\\B", b_sig);
+                       first_cell->setPort("\\S", s_sig);
+                       first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
+                       first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
+
+                       cursor += cases;
+               }
+       }
+
+       void cleanup()
+       {
+               for (auto cell : remove_cells)
+                       module->remove(cell);
+
+               remove_cells.clear();
+               sig_chain_next.clear();
+               sig_chain_prev.clear();
+               chain_start_cells.clear();
+               candidate_cells.clear();
+       }
+
+       MuxpackWorker(Module *module) :
+                       module(module), sigmap(module), mux_count(0), pmux_count(0)
+       {
+               make_sig_chain_next_prev();
+               find_chain_start_cells();
+
+               for (auto c : chain_start_cells) {
+                       vector<Cell*> chain = create_chain(c);
+                       process_chain(chain);
+               }
+
+               cleanup();
+       }
+};
+
+struct MuxpackPass : public Pass {
+       MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { }
+       void help() YS_OVERRIDE
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    muxpack [selection]\n");
+               log("\n");
+               log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n");
+               log("constructs) and $mux cells (e.g. those created by if-else constructs) into \n");
+               log("into $pmux cells.\n");
+               log("\n");
+       }
+       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+       {
+               log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n");
+
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++)
+               {
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               int mux_count = 0;
+               int pmux_count = 0;
+
+               for (auto module : design->selected_modules()) {
+                       MuxpackWorker worker(module);
+                       mux_count += worker.mux_count;
+                       pmux_count += worker.pmux_count;
+               }
+
+               log("Converted %d (p)mux cells into %d pmux cells.\n", mux_count, pmux_count);
+       }
+} MuxpackPass;
+
+PRIVATE_NAMESPACE_END
index 50ab38063ef5bc81da49b8fd19f9863c8ed075cd..71ce1683d95b9d9842147a4acf8dad07acc477f1 100644 (file)
@@ -42,7 +42,7 @@ struct dff_map_bit_info_t {
 
 bool consider_wire(RTLIL::Wire *wire, std::map<RTLIL::IdString, dff_map_info_t> &dff_dq_map)
 {
-       if (/*wire->name[0] == '$' ||*/ dff_dq_map.count(wire->name))
+       if (wire->name[0] == '$' || dff_dq_map.count(wire->name))
                return false;
        if (wire->port_input)
                return false;
index 2aa19b348fec78afd508e751642b0a3185215d13..19157adc60d647d7c3e4e5dc73d198efd2961d6c 100644 (file)
@@ -25,8 +25,7 @@
 #define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 #define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
 //#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
-//#define ABC_COMMAND_LUT "&st; &sweep; &scorr; &dc2; &retime; &dch -f; &if; &mfs; &ps"
-#define ABC_COMMAND_LUT "&st; &scorr; &dc2; &retime; &dch -f; &if; &ps -l -m"
+#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if {W} -v; &ps -l"
 #define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
 #define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 
@@ -273,7 +272,8 @@ failed:
 void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
                std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
                bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
-               const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file)
+               const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file,
+               std::string wire_delay)
 {
        module = current_module;
        map_autoidx = autoidx++;
@@ -388,6 +388,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
        for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
                abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
 
+       for (size_t pos = abc_script.find("{W}"); pos != std::string::npos; pos = abc_script.find("{W}", pos))
+               abc_script = abc_script.substr(0, pos) + wire_delay + abc_script.substr(pos+3);
+
        abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
        abc_script = add_echos_to_abc_cmd(abc_script);
 
@@ -424,6 +427,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 
        Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
 
+#if 0
+       std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
+       std::ifstream ifs;
+       ifs.open(buffer);
+       if (ifs.fail())
+               log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
+       buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
+       log_assert(!design->module("$__abc9__"));
+       AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
+       reader.parse_xaiger();
+       ifs.close();
+       Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
+       design->remove(design->module("$__abc9__"));
+#endif
+
        design->selection_stack.pop_back();
 
        // Now 'unexpose' those wires by undoing
@@ -453,48 +471,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
        {
                log_header(design, "Executing ABC9.\n");
 
-               std::string buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str());
-               f = fopen(buffer.c_str(), "wt");
-               if (f == NULL)
-                       log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
-               fprintf(f, "GATE ZERO    1 Y=CONST0;\n");
-               fprintf(f, "GATE ONE     1 Y=CONST1;\n");
-               fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", get_cell_cost("$_BUF_"));
-               fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_NOT_"));
-               if (enabled_gates.empty() || enabled_gates.count("AND"))
-                       fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", get_cell_cost("$_AND_"));
-               if (enabled_gates.empty() || enabled_gates.count("NAND"))
-                       fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_NAND_"));
-               if (enabled_gates.empty() || enabled_gates.count("OR"))
-                       fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", get_cell_cost("$_OR_"));
-               if (enabled_gates.empty() || enabled_gates.count("NOR"))
-                       fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_NOR_"));
-               if (enabled_gates.empty() || enabled_gates.count("XOR"))
-                       fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_"));
-               if (enabled_gates.empty() || enabled_gates.count("XNOR"))
-                       fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_"));
-               if (enabled_gates.empty() || enabled_gates.count("ANDNOT"))
-                       fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ANDNOT_"));
-               if (enabled_gates.empty() || enabled_gates.count("ORNOT"))
-                       fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_ORNOT_"));
-               if (enabled_gates.empty() || enabled_gates.count("AOI3"))
-                       fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_AOI3_"));
-               if (enabled_gates.empty() || enabled_gates.count("OAI3"))
-                       fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_OAI3_"));
-               if (enabled_gates.empty() || enabled_gates.count("AOI4"))
-                       fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_AOI4_"));
-               if (enabled_gates.empty() || enabled_gates.count("OAI4"))
-                       fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", get_cell_cost("$_OAI4_"));
-               if (enabled_gates.empty() || enabled_gates.count("MUX"))
-                       fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_MUX_"));
-               if (map_mux4)
-                       fprintf(f, "GATE MUX4   %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*get_cell_cost("$_MUX_"));
-               if (map_mux8)
-                       fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*get_cell_cost("$_MUX_"));
-               if (map_mux16)
-                       fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*get_cell_cost("$_MUX_"));
-               fclose(f);
-
+        std::string buffer;
                if (!lut_costs.empty()) {
                        buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
                        f = fopen(buffer.c_str(), "wt");
@@ -536,19 +513,21 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                        log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 
                bool builtin_lib = liberty_file.empty();
-               RTLIL::Design *mapped_design = new RTLIL::Design;
                //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
                buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
-               AigerReader reader(mapped_design, ifs, "\\netlist", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
+               log_assert(!design->module("$__abc9__"));
+               AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
                reader.parse_xaiger();
-
                ifs.close();
 
+#if 0
+               Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "output.v"));
+#endif
+
                log_header(design, "Re-integrating ABC9 results.\n");
-               RTLIL::Module *mapped_mod = mapped_design->modules_["\\netlist"];
+               RTLIL::Module *mapped_mod = design->module("$__abc9__");
                if (mapped_mod == NULL)
-                       log_error("ABC output file does not contain a module `netlist'.\n");
-               Pass::call(mapped_design, "clean");
+                       log_error("ABC output file does not contain a module `$__abc9__'.\n");
 
                pool<RTLIL::SigBit> output_bits;
                for (auto &it : mapped_mod->wires_) {
@@ -564,7 +543,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                else {
                                        // Attempt another wideports_split here because there
                                        // exists the possibility that different bits of a port
-                                       // could be an input and output, therefore parse_xiager()
+                                       // could be an input and output, therefore parse_xaiger()
                                        // could not combine it into a wideport
                                        auto r = wideports_split(w->name.str());
                                        wire = module->wire(r.first);
@@ -575,6 +554,33 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                        }
                }
 
+               // Remove all AND, NOT, and ABC box instances
+               // in preparation for stitching mapped_mod in
+               dict<IdString, decltype(RTLIL::Cell::parameters)> erased_boxes;
+               for (auto it = module->cells_.begin(); it != module->cells_.end(); ) {
+                       RTLIL::Cell* cell = it->second;
+                       if (cell->type.in("$_AND_", "$_NOT_")) {
+                               it = module->cells_.erase(it);
+                               continue;
+                       }
+                       RTLIL::Module* box_module = design->module(cell->type);
+                       if (box_module && box_module->attributes.count("\\abc_box_id")) {
+                               erased_boxes.insert(std::make_pair(it->first, std::move(cell->parameters)));
+                               it = module->cells_.erase(it);
+                               continue;
+                       }
+                       ++it;
+               }
+               // Do the same for module connections
+               for (auto &it : module->connections_) {
+                       auto &signal = it.first;
+                       auto bits = signal.bits();
+                       for (auto &b : bits)
+                               if (output_bits.count(b))
+                                       b = module->addWire(NEW_ID);
+                       signal = std::move(bits);
+               }
+
                std::map<std::string, int> cell_stats;
                for (auto c : mapped_mod->cells())
                {
@@ -584,31 +590,39 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                        RTLIL::Cell *cell;
                                        RTLIL::SigBit a_bit = c->getPort("\\A").as_bit();
                                        RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
-                                       if (!lut_costs.empty() || !lut_file.empty()) {
+                                       if (!a_bit.wire) {
+                                               c->setPort("\\Y", module->addWire(NEW_ID));
+                                               module->connect(module->wires_[remap_name(y_bit.wire->name)], RTLIL::S1);
+                                       }
+                                       else if (!lut_costs.empty() || !lut_file.empty()) {
+                                               RTLIL::Cell* driving_lut = nullptr;
                                                // ABC can return NOT gates that drive POs
-                                               if (a_bit.wire->port_input) {
-                                                       // If it's a NOT gate that comes from a primary input directly
-                                                       // then implement it using a LUT
-                                                       cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
-                                                                       RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset),
-                                                                       RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
-                                                                       1);
-                                               }
-                                               else {
-                                                       // Otherwise, clone the driving LUT to guarantee that we
-                                                       // won't increase the max logic depth
+                                               if (!a_bit.wire->port_input) {
+                                                       // If it's not a NOT gate that that comes from a PI directly,
+                                                       // find the driving LUT and clone that to guarantee that we won't
+                                                       // increase the max logic depth
                                                        // (TODO: Optimise by not cloning unless will increase depth)
                                                        RTLIL::IdString driver_name;
                                                        if (GetSize(a_bit.wire) == 1)
                                                                driver_name = stringf("%s$lut", a_bit.wire->name.c_str());
                                                        else
                                                                driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset);
-                                                       RTLIL::Cell* driver = mapped_mod->cell(driver_name);
-                                                       log_assert(driver);
-                                                       auto driver_a = driver->getPort("\\A").chunks();
+                                                       driving_lut = mapped_mod->cell(driver_name);
+                                               }
+
+                                               if (!driving_lut) {
+                                                       // If a driver couldn't be found (could be from PI,
+                                                       // or from a box) then implement using a LUT
+                                                       cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
+                                                                       RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset),
+                                                                       RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
+                                                                       1);
+                                               }
+                                               else {
+                                                       auto driver_a = driving_lut->getPort("\\A").chunks();
                                                        for (auto &chunk : driver_a)
                                                                chunk.wire = module->wires_[remap_name(chunk.wire->name)];
-                                                       RTLIL::Const driver_lut = driver->getParam("\\LUT");
+                                                       RTLIL::Const driver_lut = driving_lut->getParam("\\LUT");
                                                        for (auto &b : driver_lut.bits) {
                                                                if (b == RTLIL::State::S0) b = RTLIL::State::S1;
                                                                else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
@@ -618,7 +632,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                                                        RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
                                                                        driver_lut);
                                                }
-                                               cell_stats["$lut"]++;
                                        }
                                        else {
                                                cell = module->addCell(remap_name(c->name), "$_NOT_");
@@ -629,168 +642,24 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                        if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
                                        continue;
                                }
-
-                               cell_stats[RTLIL::unescape_id(c->type)]++;
-                               if (c->type == "\\ZERO" || c->type == "\\ONE") {
-                                       RTLIL::SigSig conn;
-                                       conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
-                                       conn.second = RTLIL::SigSpec(c->type == "\\ZERO" ? 0 : 1, 1);
-                                       module->connect(conn);
-                                       continue;
-                               }
-                               if (c->type == "\\BUF") {
-                                       RTLIL::SigSig conn;
-                                       conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]);
-                                       conn.second = RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]);
-                                       module->connect(conn);
-                                       continue;
-                               }
-
-                               if (c->type == "\\AND" || c->type == "\\OR" || c->type == "\\XOR" || c->type == "\\NAND" || c->type == "\\NOR" ||
-                                               c->type == "\\XNOR" || c->type == "\\ANDNOT" || c->type == "\\ORNOT") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\MUX") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\MUX4") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX4_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
-                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
-                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
-                                       cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\MUX8") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX8_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
-                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
-                                       cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
-                                       cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
-                                       cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
-                                       cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
-                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
-                                       cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
-                                       cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\MUX16") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_MUX16_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
-                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
-                                       cell->setPort("\\E", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\E").as_wire()->name)]));
-                                       cell->setPort("\\F", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\F").as_wire()->name)]));
-                                       cell->setPort("\\G", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\G").as_wire()->name)]));
-                                       cell->setPort("\\H", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\H").as_wire()->name)]));
-                                       cell->setPort("\\I", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\I").as_wire()->name)]));
-                                       cell->setPort("\\J", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\J").as_wire()->name)]));
-                                       cell->setPort("\\K", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\K").as_wire()->name)]));
-                                       cell->setPort("\\L", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\L").as_wire()->name)]));
-                                       cell->setPort("\\M", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\M").as_wire()->name)]));
-                                       cell->setPort("\\N", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\N").as_wire()->name)]));
-                                       cell->setPort("\\O", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\O").as_wire()->name)]));
-                                       cell->setPort("\\P", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\P").as_wire()->name)]));
-                                       cell->setPort("\\S", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\S").as_wire()->name)]));
-                                       cell->setPort("\\T", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\T").as_wire()->name)]));
-                                       cell->setPort("\\U", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\U").as_wire()->name)]));
-                                       cell->setPort("\\V", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\V").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\AOI3" || c->type == "\\OAI3") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\AOI4" || c->type == "\\OAI4") {
-                                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), "$_" + c->type.substr(1) + "_");
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\A", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]));
-                                       cell->setPort("\\B", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\B").as_wire()->name)]));
-                                       cell->setPort("\\C", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\C").as_wire()->name)]));
-                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
-                                       cell->setPort("\\Y", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]));
-                                       continue;
-                               }
-                               if (c->type == "\\DFF") {
-                                       log_assert(clk_sig.size() == 1);
-                                       RTLIL::Cell *cell;
-                                       if (en_sig.size() == 0) {
-                                               cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
-                                       } else {
-                                               log_assert(en_sig.size() == 1);
-                                               cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
-                                               cell->setPort("\\E", en_sig);
-                                       }
-                                       if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                                       cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
-                                       cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
-                                       cell->setPort("\\C", clk_sig);
-                                       continue;
-                               }
                        }
-                       else
-                               cell_stats[RTLIL::unescape_id(c->type)]++;
+            cell_stats[RTLIL::unescape_id(c->type)]++;
 
-                       if (c->type == "\\_const0_" || c->type == "\\_const1_") {
-                               RTLIL::SigSig conn;
-                               conn.first = RTLIL::SigSpec(module->wires_[remap_name(c->connections().begin()->second.as_wire()->name)]);
-                               conn.second = RTLIL::SigSpec(c->type == "\\_const0_" ? 0 : 1, 1);
-                               module->connect(conn);
-                               continue;
-                       }
-
-                       if (c->type == "\\_dff_") {
-                               log_assert(clk_sig.size() == 1);
-                               RTLIL::Cell *cell;
-                               if (en_sig.size() == 0) {
-                                       cell = module->addCell(remap_name(c->name), clk_polarity ? "$_DFF_P_" : "$_DFF_N_");
-                               } else {
-                                       log_assert(en_sig.size() == 1);
-                                       cell = module->addCell(remap_name(c->name), stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
-                                       cell->setPort("\\E", en_sig);
+                       if (c->type == "$lut") {
+                               if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
+                                       SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
+                                       SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
+                                       module->connect(my_y, my_a);
+                                       continue;
                                }
-                               if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
-                               cell->setPort("\\D", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\D").as_wire()->name)]));
-                               cell->setPort("\\Q", RTLIL::SigSpec(module->wires_[remap_name(c->getPort("\\Q").as_wire()->name)]));
-                               cell->setPort("\\C", clk_sig);
-                               continue;
-                       }
-
-                       if (c->type == "$lut" && GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
-                               SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
-                               SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
-                               module->connect(my_y, my_a);
-                               continue;
                        }
+                       else {
+                auto it = erased_boxes.find(c->name);
+                log_assert(it != erased_boxes.end());
+                c->parameters = std::move(it->second);
+            }
 
-                       RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
+                       RTLIL::Cellcell = module->addCell(remap_name(c->name), c->type);
                        if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
                        cell->parameters = c->parameters;
                        for (auto &conn : c->connections()) {
@@ -799,7 +668,8 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                        if (c.width == 0)
                                                continue;
                                        //log_assert(c.width == 1);
-                                       c.wire = module->wires_[remap_name(c.wire->name)];
+                                       if (c.wire)
+                                               c.wire = module->wires_[remap_name(c.wire->name)];
                                        newsig.append(c);
                                }
                                cell->setPort(conn.first, newsig);
@@ -836,49 +706,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                for (auto &it : cell_stats)
                        log("ABC RESULTS:   %15s cells: %8d\n", it.first.c_str(), it.second);
                int in_wires = 0, out_wires = 0;
-               //for (auto &si : signal_list)
-               //      if (si.is_port) {
-               //              char buffer[100];
-               //              snprintf(buffer, 100, "\\n%d", si.id);
-               //              RTLIL::SigSig conn;
-               //              if (si.type != G(NONE)) {
-               //                      conn.first = si.bit;
-               //                      conn.second = RTLIL::SigSpec(module->wires_[remap_name(buffer)]);
-               //                      out_wires++;
-               //              } else {
-               //                      conn.first = RTLIL::SigSpec(module->wires_[remap_name(buffer)]);
-               //                      conn.second = si.bit;
-               //                      in_wires++;
-               //              }
-               //              module->connect(conn);
-               //      }
-
-               // Go through all AND and NOT output connections,
-               // and for those output ports driving wires
-               // also driven by mapped_mod, disconnect them
-               for (auto cell : module->cells()) {
-                       if (!cell->type.in("$_AND_", "$_NOT_"))
-                               continue;
-                       for (auto &it : cell->connections_) {
-                               auto port_name = it.first;
-                               if (!cell->output(port_name)) continue;
-                               auto &signal = it.second;
-                               auto bits = signal.bits();
-                               for (auto &b : bits)
-                                       if (output_bits.count(b))
-                                               b = module->addWire(NEW_ID);
-                               signal = std::move(bits);
-                       }
-               }
-               // Do the same for module connections
-               for (auto &it : module->connections_) {
-                       auto &signal = it.first;
-                       auto bits = signal.bits();
-                       for (auto &b : bits)
-                               if (output_bits.count(b))
-                                       b = module->addWire(NEW_ID);
-                       signal = std::move(bits);
-               }
 
                // Stitch in mapped_mod's inputs/outputs into module
                for (auto &it : mapped_mod->wires_) {
@@ -894,7 +721,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                        else {
                                // Attempt another wideports_split here because there
                                // exists the possibility that different bits of a port
-                               // could be an input and output, therefore parse_xiager()
+                               // could be an input and output, therefore parse_xaiger()
                                // could not combine it into a wideport
                                auto r = wideports_split(w->name.str());
                                wire = module->wire(r.first);
@@ -924,7 +751,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                log("ABC RESULTS:           input signals: %8d\n", in_wires);
                log("ABC RESULTS:          output signals: %8d\n", out_wires);
 
-               delete mapped_design;
+               design->remove(mapped_mod);
        }
        //else
        //{
@@ -1137,12 +964,17 @@ struct Abc9Pass : public Pass {
                std::string exe_file = proc_self_dirname() + "yosys-abc";
 #endif
                std::string script_file, liberty_file, constr_file, clk_str, box_file, lut_file;
-               std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
+               std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1", wire_delay;
                bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
                bool show_tempdir = false, sop_mode = false;
                vector<int> lut_costs;
                markgroups = false;
 
+#if 0
+               cleanup = false;
+               show_tempdir = true;
+#endif
+
                map_mux4 = false;
                map_mux8 = false;
                map_mux16 = false;
@@ -1386,6 +1218,10 @@ struct Abc9Pass : public Pass {
                                        box_file = std::string(pwd) + "/" + box_file;
                                continue;
                        }
+                       if (arg == "-W" && argidx+1 < args.size()) {
+                               wire_delay = "-S " + args[++argidx];
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -1428,7 +1264,7 @@ struct Abc9Pass : public Pass {
                        if (!dff_mode || !clk_str.empty()) {
                                abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
                                                delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode,
-                                               box_file, lut_file);
+                                               box_file, lut_file, wire_delay);
                                continue;
                        }
 
@@ -1574,7 +1410,7 @@ struct Abc9Pass : public Pass {
                                en_sig = assign_map(std::get<3>(it.first));
                                abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
                                                keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode,
-                                               box_file, lut_file);
+                                               box_file, lut_file, wire_delay);
                                assign_map.set(mod);
                        }
                }
index 21dfe96198c43a252575bb6483c2fd062b241328..46f6a79fb47a7a7cb1276b280cd559ae81cf3680 100644 (file)
@@ -293,10 +293,13 @@ struct ShregmapWorker
 
                                if (opts.init || sigbit_init.count(q_bit) == 0)
                                {
-                                       if (sigbit_chain_next.count(d_bit)) {
+                                       auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell));
+                                       if (!r.second) {
                                                sigbit_with_non_chain_users.insert(d_bit);
-                                       } else
-                                               sigbit_chain_next[d_bit] = cell;
+                                               Wire *wire = module->addWire(NEW_ID);
+                                               module->connect(wire, d_bit);
+                                               sigbit_chain_next.insert(std::make_pair(wire, cell));
+                                       }
 
                                        sigbit_chain_prev[q_bit] = cell;
                                        continue;
index 994f3091da2453ac522c8f83d03994c857e60563..a0655643ddeada3c1dce31025ef2c25dde201045 100644 (file)
@@ -4,7 +4,7 @@
 
 # Inputs: C D
 # Outputs: Q
-SB_DFF 1 1 2 1
+SB_DFF 1 0 2 1
 - -
 
 # Inputs: C D E
@@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1
 
 # Inputs: I0 I1 I2 I3
 # Outputs: O
-SB_LUT4 22 0 4 1
+SB_LUT4 22 1 4 1
 449 400 379 316
index 002b7bba4b77186048c26e77bb456ea86fbb780e..dbc98d0c47ea45a3a51d028dc3ed337bdff9b95b 100644 (file)
@@ -4,7 +4,7 @@
 
 # Inputs: C D
 # Outputs: Q
-SB_DFF 1 1 2 1
+SB_DFF 1 0 2 1
 - -
 
 # Inputs: C D E
@@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1
 
 # Inputs: I0 I1 I2 I3
 # Outputs: O
-SB_LUT4 22 0 4 1
+SB_LUT4 22 1 4 1
 465 558 589 661
index cb336181c8ce3d275b02f22820ef43f9a138ee4e..3b5834e403b5e32eac34cfde0444eff0b7233049 100644 (file)
@@ -4,7 +4,7 @@
 
 # Inputs: C D
 # Outputs: Q
-SB_DFF 1 1 2 1
+SB_DFF 1 0 2 1
 - -
 
 # Inputs: C D E
@@ -109,5 +109,5 @@ SB_CARRY 21 1 3 1
 
 # Inputs: I0 I1 I2 I3
 # Outputs: O
-SB_LUT4 22 0 4 1
+SB_LUT4 22 1 4 1
 1285 1231 1205 874
index 287c48b11b867c0424bdb2ffbbd20f5a1e4574cf..759549e30cc183bb662c805fa86863f3e6fce1c3 100644 (file)
@@ -53,7 +53,7 @@ module \$lut (A, Y);
     end else
     if (WIDTH == 4) begin
       localparam [15:0] INIT = {LUT[15], LUT[7], LUT[11], LUT[3], LUT[13], LUT[5], LUT[9], LUT[1], LUT[14], LUT[6], LUT[10], LUT[2], LUT[12], LUT[4], LUT[8], LUT[0]};
-      SB_LUT4 #(.LUT_INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y),
+      SB_LUT4 #(.LUT_INIT(INIT)) _TECHMAP_REPLACE_ (.O(Y),
         .I0(A[3]), .I1(A[2]), .I2(A[1]), .I3(A[0]));
     end else begin
       wire _TECHMAP_FAIL_ = 1;
index 560008bc4021ddb20fec659843ad343f10f0bc38..523dd8cbeab4f7fee703a24609629a7f81854821 100644 (file)
@@ -127,7 +127,7 @@ endmodule
 
 // SiliconBlue Logic Cells
 
-(* abc_box_id = 22 *)
+(* abc_box_id = 22, lib_whitebox *)
 module SB_LUT4 (output O, input I0, I1, I2, I3);
        parameter [15:0] LUT_INIT = 0;
        wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
@@ -136,8 +136,8 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
        assign O = I0 ? s1[1] : s1[0];
 endmodule
 
-(* abc_box_id = 21, lib_whitebox *)
-module SB_CARRY (output CO, input I0, I1, CI);
+(* abc_box_id = 21, abc_carry, lib_whitebox *)
+module SB_CARRY ((* abc_carry_out *) output CO, input I0, I1, (* abc_carry_in *) input CI);
        assign CO = (I0 && I1) || ((I0 || I1) && CI);
 endmodule
 
@@ -145,7 +145,7 @@ endmodule
 
 (* abc_box_id = 1, abc_flop, lib_whitebox *)
 module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
-`ifndef ABC_MODEL
+`ifndef _ABC
        always @(posedge C)
                Q <= D;
 `else
index 168161a90c029b03948a12f57b2ba46a88807b55..5afa042b01d322720ae1c67fc75c98e83a988f18 100644 (file)
@@ -240,7 +240,7 @@ struct SynthIce40Pass : public ScriptPass
        {
                if (check_label("begin"))
                {
-                       run("read_verilog -lib -D ABC_MODEL +/ice40/cells_sim.v");
+                       run("read_verilog -lib -D_ABC +/ice40/cells_sim.v");
                        run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
                        run("proc");
                }
@@ -334,7 +334,7 @@ struct SynthIce40Pass : public ScriptPass
                                if (abc == "abc9")
                                        run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
                                else
-                                       run(abc + " -lut 4", "(skip if -noabc)");
+                                       run(abc + " -dress -lut 4", "(skip if -noabc)");
                        }
                        run("clean");
                        if (relut || help_mode) {
index d68f03bb44f3635209e3224be27e87562b2fd8aa..2f39451677eb2d80cbb9843b63e117b978b473f0 100644 (file)
@@ -30,6 +30,9 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
 $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.lut))
 
 $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
 $(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
diff --git a/techlibs/xilinx/abc.box b/techlibs/xilinx/abc.box
new file mode 100644 (file)
index 0000000..a4182ed
--- /dev/null
@@ -0,0 +1,62 @@
+# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
+
+# F7BMUX slower than F7AMUX
+# Inputs: I0 I1 S0
+# Outputs: O
+F7BMUX 1 1 3 1
+217 223 296
+
+# Inputs: I0 I1 S0
+# Outputs: O
+MUXF8 2 1 3 1
+104 94 273
+
+# CARRY4 + CARRY4_[ABCD]X
+# Inputs: S0 S1 S2 S3 CYINIT DI0 DI1 DI2 DI3 CI
+# Outputs:  O0 O1 O2 O3 CO0 CO1 CO2 CO3
+#   (NB: carry chain input/output must be last input/output,
+#        swapped with what normally would have been the last
+#        output, here: CI <-> S, CO <-> O
+CARRY4 3 1 10 8
+223 -   -   -   482 -   -   -   -   222
+400 205 -   -   598 407 -   -   -   334
+523 558 226 -   584 556 537 -   -   239
+582 618 330 227 642 615 596 438 -   313
+340 -   -   -   536 379 -   -   -   271
+433 469 -   -   494 465 445 -   -   157
+512 548 292 -   592 540 520 356 -   228
+508 528 378 380 580 526 507 398 385 114
+
+# SLICEM/A6LUT
+# Inputs: A0 A1 A2 A3 A4 A5 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 WCLK WE
+# Outputs: DPO SPO
+RAM64X1D 4 0 15 2
+-   -   -   -   -   -   - 124 124 124 124 124 124 - -
+124 124 124 124 124 124 - -   -   -   -   -   124 - -
+
+# SLICEM/A6LUT + F7[AB]MUX
+# Inputs: A0 A1 A2 A3 A4 A5 A6 D DPRA0 DPRA1 DPRA2 DPRA3 DPRA4 DPRA5 DPRA6 WCLK WE
+# Outputs: DPO SPO
+RAM128X1D 5 0 17 2
+-   -   -   -   -   -   -   - 314 314 314 314 314 314 292 - -
+347 347 347 347 347 347 296 - -   -   -   -   -   -   -   - -
+
+# Inputs: C CE D R
+# Outputs: Q
+FDRE 6 0 4 1
+- - - -
+
+# Inputs: C CE D S
+# Outputs: Q
+FDSE 7 0 4 1
+- - - -
+
+# Inputs: C CE CLR D
+# Outputs: Q
+FDCE 8 0 4 1
+- - 404 -
+
+# Inputs: C CE D PRE
+# Outputs: Q
+FDPE 9 0 4 1
+- - - 404
diff --git a/techlibs/xilinx/abc.lut b/techlibs/xilinx/abc.lut
new file mode 100644 (file)
index 0000000..3a7dc26
--- /dev/null
@@ -0,0 +1,14 @@
+# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
+
+# K    area    delay
+1      1       124
+2      2       124 235
+3      3       124 235 399
+4      3       124 235 399 490
+5      3       124 235 399 490 620
+6      5       124 235 399 490 620 632
+                # F7BMUX
+7      10      296 420 531 695 756 916 928
+                # F8MUX
+                    # F8MUX+F7BMUX
+8      20      273 569 693 804 968 1029 1189 1201
index 09a5f07e83d76b2d1b6bdfa3b450ddea750bc833..5c848d4e69913167cbad26b00baf7585ccca8bff 100644 (file)
@@ -180,7 +180,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
 
                        // First one
                        if (i == 0) begin
-                               CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_part
+                               CARRY4 carry4_1st_part
                                (
                                .CYINIT(CI),
                                .CI    (1'd0),
@@ -207,7 +207,7 @@ module _80_xilinx_alu (A, B, CI, BI, X, Y, CO);
 
                        // First one
                        if (i == 0) begin
-                               CARRY4 #(.IS_INITIALIZED(1'd1)) carry4_1st_full
+                               CARRY4 carry4_1st_full
                                (
                                .CYINIT(CI),
                                .CI    (1'd0),
index a682ba4a72926b7ae506673edcdd5874fa4a4bb6..f540d299d5e861e0eb47079d0587d2b70849b677 100644 (file)
@@ -19,10 +19,10 @@ module RAMB18E1 (
        input [1:0] WEA,
        input [3:0] WEBWE,
 
-       output [15:0] DOADO,
-       output [15:0] DOBDO,
-       output [1:0] DOPADOP,
-       output [1:0] DOPBDOP
+       (* abc_flop_q *) output [15:0] DOADO,
+       (* abc_flop_q *) output [15:0] DOBDO,
+       (* abc_flop_q *) output [1:0] DOPADOP,
+       (* abc_flop_q *) output [1:0] DOPBDOP
 );
        parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
        parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
@@ -143,10 +143,10 @@ module RAMB36E1 (
        input [3:0] WEA,
        input [7:0] WEBWE,
 
-       output [31:0] DOADO,
-       output [31:0] DOBDO,
-       output [3:0] DOPADOP,
-       output [3:0] DOPBDOP
+       (* abc_flop_q *) output [31:0] DOADO,
+       (* abc_flop_q *) output [31:0] DOBDO,
+       (* abc_flop_q *) output [3:0] DOPADOP,
+       (* abc_flop_q *) output [3:0] DOPBDOP
 );
        parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
        parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
index 40789ddbe1548c9e5041f55f24c0021cacd2ed92..f8f9356bc6c2db816dc68b56fe5a8954a0db30f8 100644 (file)
@@ -2,6 +2,7 @@
  *  yosys -- Yosys Open SYnthesis Suite
  *
  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *                2019  Eddie Hung    <eddie@fpgeh.com>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
  *
  */
 
-// Convert negative-polarity reset to positive-polarity
-(* techmap_celltype = "$_DFF_NN0_" *)
-module _90_dff_nn0_to_np0 (input D, C, R, output Q); \$_DFF_NP0_  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_DFF_PN0_" *)
-module _90_dff_pn0_to_pp0 (input D, C, R, output Q); \$_DFF_PP0_  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_DFF_NN1_" *)
-module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1   _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-(* techmap_celltype = "$_DFF_PN1_" *)
-module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1   _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
-
 module \$__SHREG_ (input C, input D, input E, output Q);
   parameter DEPTH = 0;
   parameter [DEPTH-1:0] INIT = 0;
@@ -88,7 +79,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
     end else
     if (DEPTH > 65 && DEPTH <= 96) begin
       wire T0, T1, T2, T3, T4, T5, T6;
-      SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
+      SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1));
       SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
       \$__XILINX_SHREG_ #(.DEPTH(DEPTH-64), .INIT(INIT[DEPTH-64-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_2 (.C(C), .D(T3), .L(L[4:0]), .E(E), .Q(T4));
       if (&_TECHMAP_CONSTMSK_L_)
@@ -101,7 +92,7 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
     end else
     if (DEPTH > 97 && DEPTH < 128) begin
       wire T0, T1, T2, T3, T4, T5, T6, T7, T8;
-      SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
+      SRLC32E #(.INIT(INIT_R[32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1));
       SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
       SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
       \$__XILINX_SHREG_ #(.DEPTH(DEPTH-96), .INIT(INIT[DEPTH-96-1:0]), .CLKPOL(CLKPOL), .ENPOL(ENPOL)) fpga_srl_3 (.C(C), .D(T5), .L(L[4:0]), .E(E), .Q(T6));
@@ -115,9 +106,9 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
     end
     else if (DEPTH == 128) begin
       wire T0, T1, T2, T3, T4, T5, T6;
-      SRLC32E #(.INIT(INIT_R[32-1:0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D(D), .Q(T0), .Q31(T1));
-      SRLC32E #(.INIT(INIT_R[64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
-      SRLC32E #(.INIT(INIT_R[96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
+      SRLC32E #(.INIT(INIT_R[ 32-1: 0]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_0 (.A(L[4:0]), .CE(CE), .CLK(C), .D( D), .Q(T0), .Q31(T1));
+      SRLC32E #(.INIT(INIT_R[ 64-1:32]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_1 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T1), .Q(T2), .Q31(T3));
+      SRLC32E #(.INIT(INIT_R[ 96-1:64]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_2 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T3), .Q(T4), .Q31(T5));
       SRLC32E #(.INIT(INIT_R[128-1:96]), .IS_CLK_INVERTED(~CLKPOL[0])) fpga_srl_3 (.A(L[4:0]), .CE(CE), .CLK(C), .D(T5), .Q(T6), .Q31(SO));
       if (&_TECHMAP_CONSTMSK_L_)
         assign Q = T6;
@@ -152,5 +143,122 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
   endgenerate
 endmodule
 
-`ifndef SRL_ONLY
-`endif
+module \$__XILINX_SHIFTX (A, B, Y);
+  parameter A_SIGNED = 0;
+  parameter B_SIGNED = 0;
+  parameter A_WIDTH = 1;
+  parameter B_WIDTH = 1;
+  parameter Y_WIDTH = 1;
+
+  input [A_WIDTH-1:0] A;
+  input [B_WIDTH-1:0] B;
+  output [Y_WIDTH-1:0] Y;
+
+  parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0;
+  parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0;
+  parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
+  parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
+
+  function integer compute_num_leading_X_in_A;
+    integer i, c;
+  begin
+    compute_num_leading_X_in_A = 0;
+    c = 1;
+    for (i = A_WIDTH-1; i >= 0; i=i-1) begin
+      if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx)
+        c = 0;
+      compute_num_leading_X_in_A = compute_num_leading_X_in_A + c;
+    end
+  end
+  endfunction
+  localparam num_leading_X_in_A = compute_num_leading_X_in_A();
+
+  generate
+    genvar i, j;
+    // Bit-blast
+    if (Y_WIDTH > 1) begin
+      for (i = 0; i < Y_WIDTH; i++)
+        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i]));
+    end
+    // If the LSB of B is constant zero (and Y_WIDTH is 1) then
+    //   we can optimise by removing every other entry from A
+    //   and popping the constant zero from B
+    else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin
+      wire [(A_WIDTH+1)/2-1:0] A_i;
+      for (i = 0; i < (A_WIDTH+1)/2; i++)
+        assign A_i[i] = A[i*2];
+      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y));
+    end
+    // Trim off any leading 1'bx -es in A, and resize B accordingly
+    else if (num_leading_X_in_A > 0) begin
+      localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A;
+      localparam B_WIDTH_new = $clog2(A_WIDTH_new);
+      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y));
+    end
+    else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
+      \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+    end
+    else if (B_WIDTH == 3) begin
+      localparam a_width0 = 2 ** 2;
+      localparam a_widthN = A_WIDTH - a_width0;
+      wire T0, T1;
+      \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2),                .Y_WIDTH(Y_WIDTH)) fpga_soft_mux      (.A(A[a_width0-1:0]),       .B(B[2-1:0]),                .Y(T0));
+      if (a_widthN > 1)
+        \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1));
+      else
+        assign T1 = A[A_WIDTH-1];
+      MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y));
+    end
+    else if (B_WIDTH == 4) begin
+      localparam a_width0 = 2 ** 2;
+      localparam num_mux8 = A_WIDTH / a_width0;
+      localparam a_widthN = A_WIDTH - num_mux8*a_width0;
+      wire [4-1:0] T;
+      wire T0, T1;
+      for (i = 0; i < 4; i++)
+        if (i < num_mux8)
+          \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2),                .Y_WIDTH(Y_WIDTH)) fpga_soft_mux      (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]),                .Y(T[i]));
+        else if (i == num_mux8 && a_widthN > 0) begin
+          if (a_widthN > 1)
+            \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
+          else
+            assign T[i] = A[A_WIDTH-1];
+        end
+        else
+          assign T[i] = 1'bx;
+      MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0));
+      MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1));
+      MUXF8 fpga_hard_mux_2 (.I0(T0),   .I1(T1),   .S(B[3]), .O(Y));
+    end
+    else begin
+      localparam a_width0 = 2 ** 4;
+      localparam num_mux16 = A_WIDTH / a_width0;
+      localparam a_widthN = A_WIDTH - num_mux16*a_width0;
+      wire [(2**(B_WIDTH-4))-1:0] T;
+      for (i = 0; i < 2 ** (B_WIDTH-4); i++)
+        if (i < num_mux16)
+          \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4),                .Y_WIDTH(Y_WIDTH)) fpga_soft_mux      (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]),                .Y(T[i]));
+        else if (i == num_mux16 && a_widthN > 0) begin
+          if (a_widthN > 1)
+            \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
+          else
+            assign T[i] = A[A_WIDTH-1];
+        end
+        else
+          assign T[i] = 1'bx;
+      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y));
+    end
+  endgenerate
+endmodule
+
+module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
+input A, B, C, D, E, F, G, H, S, T, U;
+output Y;
+  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y));
+endmodule
+
+module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y);
+input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V;
+output Y;
+  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y));
+endmodule
index 3a4540b83689be6a2c7d33692f62924cd7846711..d9aa366665f0a39d8e08e3275b087a619ee19a62 100644 (file)
@@ -159,10 +159,12 @@ module MUXCY(output O, input CI, DI, S);
   assign O = S ? CI : DI;
 endmodule
 
+(* abc_box_id = 1, lib_whitebox *)
 module MUXF7(output O, input I0, I1, S);
   assign O = S ? I1 : I0;
 endmodule
 
+(* abc_box_id = 2, lib_whitebox *)
 module MUXF8(output O, input I0, I1, S);
   assign O = S ? I1 : I0;
 endmodule
@@ -171,7 +173,8 @@ module XORCY(output O, input CI, LI);
   assign O = CI ^ LI;
 endmodule
 
-module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
+(* abc_box_id = 3, abc_carry, lib_whitebox *)
+module CARRY4((* abc_carry_out *) output [3:0] CO, output [3:0] O, (* abc_carry_in *) input CI, input CYINIT, input [3:0] DI, S);
   assign O = S ^ {CO[2:0], CI | CYINIT};
   assign CO[0] = S[0] ? CI | CYINIT : DI[0];
   assign CO[1] = S[1] ? CO[0] : DI[1];
@@ -202,7 +205,7 @@ endmodule
 
 `endif
 
-module FDRE (output reg Q, input C, CE, D, R);
+module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R);
   parameter [0:0] INIT = 1'b0;
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -214,7 +217,7 @@ module FDRE (output reg Q, input C, CE, D, R);
   endcase endgenerate
 endmodule
 
-module FDSE (output reg Q, input C, CE, D, S);
+module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S);
   parameter [0:0] INIT = 1'b0;
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -226,7 +229,7 @@ module FDSE (output reg Q, input C, CE, D, S);
   endcase endgenerate
 endmodule
 
-module FDCE (output reg Q, input C, CE, D, CLR);
+module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
   parameter [0:0] INIT = 1'b0;
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -240,7 +243,7 @@ module FDCE (output reg Q, input C, CE, D, CLR);
   endcase endgenerate
 endmodule
 
-module FDPE (output reg Q, input C, CE, D, PRE);
+module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
   parameter [0:0] INIT = 1'b0;
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
@@ -254,30 +257,31 @@ module FDPE (output reg Q, input C, CE, D, PRE);
   endcase endgenerate
 endmodule
 
-module FDRE_1 (output reg Q, input C, CE, D, R);
+module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R);
   parameter [0:0] INIT = 1'b0;
   initial Q <= INIT;
   always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
 endmodule
 
-module FDSE_1 (output reg Q, input C, CE, D, S);
+module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S);
   parameter [0:0] INIT = 1'b1;
   initial Q <= INIT;
   always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
 endmodule
 
-module FDCE_1 (output reg Q, input C, CE, D, CLR);
+module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
   parameter [0:0] INIT = 1'b0;
   initial Q <= INIT;
   always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
 endmodule
 
-module FDPE_1 (output reg Q, input C, CE, D, PRE);
+module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
   parameter [0:0] INIT = 1'b1;
   initial Q <= INIT;
   always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
 endmodule
 
+//(* abc_box_id = 4 /*, lib_whitebox*/ *)
 module RAM64X1D (
   output DPO, SPO,
   input  D, WCLK, WE,
@@ -295,6 +299,7 @@ module RAM64X1D (
   always @(posedge clk) if (WE) mem[a] <= D;
 endmodule
 
+//(* abc_box_id = 5 /*, lib_whitebox*/ *)
 module RAM128X1D (
   output       DPO, SPO,
   input        D, WCLK, WE,
@@ -310,7 +315,7 @@ module RAM128X1D (
 endmodule
 
 module SRL16E (
-  output Q,
+  (* abc_flop_q *) output Q,
   input A0, A1, A2, A3, CE, CLK, D
 );
   parameter [15:0] INIT = 16'h0000;
@@ -328,7 +333,7 @@ module SRL16E (
 endmodule
 
 module SRLC32E (
-  output Q,
+  (* abc_flop_q *) output Q,
   output Q31,
   input [4:0] A,
   input CE, CLK, D
index 8e39b440dfbd9a3e1def30b29c9bdd896e19627e..2b384f40589e096a2dc0176c1a18b34031bb0db7 100644 (file)
@@ -116,7 +116,7 @@ function xtract_cell_decl()
        xtract_cell_decl PS7 "(* keep *)"
        xtract_cell_decl PULLDOWN
        xtract_cell_decl PULLUP
-       xtract_cell_decl RAM128X1D
+       #xtract_cell_decl RAM128X1D
        xtract_cell_decl RAM128X1S
        xtract_cell_decl RAM256X1S
        xtract_cell_decl RAM32M
@@ -125,7 +125,7 @@ function xtract_cell_decl()
        xtract_cell_decl RAM32X1S_1
        xtract_cell_decl RAM32X2S
        xtract_cell_decl RAM64M
-       xtract_cell_decl RAM64X1D
+       #xtract_cell_decl RAM64X1D
        xtract_cell_decl RAM64X1S
        xtract_cell_decl RAM64X1S_1
        xtract_cell_decl RAM64X2S
index fbcc74682c49e20ecd2b35cf924b3684fd1bba69..0ec3d0df0302b5b8d261f501c089ad862c3f0f07 100644 (file)
@@ -3655,17 +3655,6 @@ module PULLUP (...);
     output O;
 endmodule
 
-module RAM128X1D (...);
-    parameter [127:0] INIT = 128'h00000000000000000000000000000000;
-    parameter [0:0] IS_WCLK_INVERTED = 1'b0;
-    output DPO, SPO;
-    input [6:0] A;
-    input [6:0] DPRA;
-    input D;
-    input WCLK;
-    input WE;
-endmodule
-
 module RAM128X1S (...);
     parameter [127:0] INIT = 128'h00000000000000000000000000000000;
     parameter [0:0] IS_WCLK_INVERTED = 1'b0;
@@ -3756,13 +3745,6 @@ module RAM64M (...);
     input WE;
 endmodule
 
-module RAM64X1D (...);
-    parameter [63:0] INIT = 64'h0000000000000000;
-    parameter [0:0] IS_WCLK_INVERTED = 1'b0;
-    output DPO, SPO;
-    input A0, A1, A2, A3, A4, A5, D, DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5, WCLK, WE;
-endmodule
-
 module RAM64X1S (...);
     parameter [63:0] INIT = 64'h0000000000000000;
     parameter [0:0] IS_WCLK_INVERTED = 1'b0;
diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v
new file mode 100644 (file)
index 0000000..0fa8db7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *                2019  Eddie Hung    <eddie@fpgeh.com>
+ *
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+module \$shiftx (A, B, Y);
+  parameter A_SIGNED = 0;
+  parameter B_SIGNED = 0;
+  parameter A_WIDTH = 1;
+  parameter B_WIDTH = 1;
+  parameter Y_WIDTH = 1;
+
+  input [A_WIDTH-1:0] A;
+  input [B_WIDTH-1:0] B;
+  output [Y_WIDTH-1:0] Y;
+
+  parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
+  parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
+
+  generate
+    genvar i, j;
+    // TODO: Check if this opt still necessary
+    if (B_SIGNED) begin
+      if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0)
+        // Optimisation to remove B_SIGNED if sign bit of B is constant-0
+        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y));
+      else
+        wire _TECHMAP_FAIL_ = 1;
+    end
+    else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
+      wire _TECHMAP_FAIL_ = 1;
+    end
+    else begin
+        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
+    end
+  endgenerate
+endmodule
diff --git a/tests/simple_abc9/abc.box b/tests/simple_abc9/abc.box
new file mode 100644 (file)
index 0000000..a8801d8
--- /dev/null
@@ -0,0 +1,2 @@
+MUXF8 1 0 3 1
+1 1 1
index f37d975ff74aa0101bfe17deb05c5f858f50f727..2752ff8ccce9fd487f8e76d825f913a00917f292 100644 (file)
@@ -142,3 +142,111 @@ assign b = ~a;
 (* keep *) reg d;
 always @* d <= &c;
 endmodule
+
+// Citation: https://github.com/alexforencich/verilog-ethernet
+module abc9_test021(clk, rst, s_eth_hdr_valid, s_eth_hdr_ready, s_eth_dest_mac, s_eth_src_mac, s_eth_type, s_eth_payload_axis_tdata, s_eth_payload_axis_tkeep, s_eth_payload_axis_tvalid, s_eth_payload_axis_tready, s_eth_payload_axis_tlast, s_eth_payload_axis_tid, s_eth_payload_axis_tdest, s_eth_payload_axis_tuser, m_eth_hdr_valid, m_eth_hdr_ready, m_eth_dest_mac, m_eth_src_mac, m_eth_type, m_eth_payload_axis_tdata, m_eth_payload_axis_tkeep, m_eth_payload_axis_tvalid, m_eth_payload_axis_tready, m_eth_payload_axis_tlast, m_eth_payload_axis_tid, m_eth_payload_axis_tdest, m_eth_payload_axis_tuser);
+  input clk;
+  output [47:0] m_eth_dest_mac;
+  input m_eth_hdr_ready;
+  output m_eth_hdr_valid;
+  output [7:0] m_eth_payload_axis_tdata;
+  output [7:0] m_eth_payload_axis_tdest;
+  output [7:0] m_eth_payload_axis_tid;
+  output m_eth_payload_axis_tkeep;
+  output m_eth_payload_axis_tlast;
+  input m_eth_payload_axis_tready;
+  output m_eth_payload_axis_tuser;
+  output m_eth_payload_axis_tvalid;
+  output [47:0] m_eth_src_mac;
+  output [15:0] m_eth_type;
+  input rst;
+  input [191:0] s_eth_dest_mac;
+  output [3:0] s_eth_hdr_ready;
+  input [3:0] s_eth_hdr_valid;
+  input [31:0] s_eth_payload_axis_tdata;
+  input [31:0] s_eth_payload_axis_tdest;
+  input [31:0] s_eth_payload_axis_tid;
+  input [3:0] s_eth_payload_axis_tkeep;
+  input [3:0] s_eth_payload_axis_tlast;
+  output [3:0] s_eth_payload_axis_tready;
+  input [3:0] s_eth_payload_axis_tuser;
+  input [3:0] s_eth_payload_axis_tvalid;
+  input [191:0] s_eth_src_mac;
+  input [63:0] s_eth_type;
+  (* keep *)
+  wire [0:0] grant, request;
+  wire a;
+  not u0 (
+    a,
+    grant[0]
+  );
+  and u1  (
+    request[0],
+    s_eth_hdr_valid[0],
+    a
+  );
+  (* keep *)
+  MUXF8 u2  (
+    .I0(1'bx),
+    .I1(1'bx),
+    .O(o),
+    .S(1'bx)
+  );
+  arbiter  arb_inst (
+    .acknowledge(acknowledge),
+    .clk(clk),
+    .grant(grant),
+    .grant_encoded(grant_encoded),
+    .grant_valid(grant_valid),
+    .request(request),
+    .rst(rst)
+  );
+endmodule
+
+module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encoded);
+  input [3:0] acknowledge;
+  input clk;
+  output [3:0] grant;
+  output [1:0] grant_encoded;
+  output grant_valid;
+  input [3:0] request;
+  input rst;
+endmodule
+
+(* abc_box_id=1 *)
+module MUXF8(input I0, I1, S, output O);
+endmodule
+
+// Citation: https://github.com/alexforencich/verilog-ethernet
+// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test022" abc9.v -q
+// returns before b4321a31
+//   Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [7] is used but has no
+//   driver.
+//   Warning: Wire abc9_test022.\m_eth_payload_axis_tkeep [3] is used but has no
+//   driver.
+module abc9_test022
+(
+    input  wire        clk,
+    input  wire        i,
+    output wire [7:0]  m_eth_payload_axis_tkeep
+);
+    reg [7:0]  m_eth_payload_axis_tkeep_reg = 8'd0;
+    assign m_eth_payload_axis_tkeep = m_eth_payload_axis_tkeep_reg;
+    always @(posedge clk)
+        m_eth_payload_axis_tkeep_reg <= i ? 8'hff : 8'h0f;
+endmodule
+
+// Citation: https://github.com/riscv/riscv-bitmanip
+// TODO: yosys -p "synth_xilinx -abc9 -top abc9_test023" abc9.v -q
+// returns before 14233843
+//   Warning: Wire abc9_test023.\dout [1] is used but has no driver.
+module abc9_test023 #(
+       parameter integer N = 2,
+       parameter integer M = 2
+) (
+       input [7:0] din,
+       output [M-1:0] dout
+);
+       wire [2*M-1:0] mask = {M{1'b1}};
+       assign dout = (mask << din[N-1:0]) >> M;
+endmodule
index 97f2843788f0ec06914a9ddf93e89e38b64178f7..4935d41ad6aba19616293eb0e8c9b3d7fd2a1ff7 100755 (executable)
@@ -19,4 +19,4 @@ fi
 
 cp ../simple/*.v .
 DOLLAR='?'
-exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; techmap; opt -full; abc9 -lut 4; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
+exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v EXTRA_FLAGS="-p 'hierarchy; synth -run coarse; opt -full; techmap; abc9 -lut 4 -box ../abc.box; stat; check -assert; select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%'"
index c394b9817d816451c76f7ffed8fcdd22115db5d4..23964a751fd66f61ceced03e35e42221c6f6f74a 100755 (executable)
@@ -143,6 +143,7 @@ do
                fn=$(basename $fn)
                bn=$(basename $bn)
 
+               rm -f ${bn}_ref.fir
                if [[ "$ext" == "v" ]]; then
                        egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}
                elif [[ "$ext" == "aig" ]] || [[ "$ext" == "aag" ]]; then
@@ -150,7 +151,6 @@ do
                else
                        cp ../${fn} ${bn}_ref.${ext}
                fi
-               rm -f ${bn}_ref.fir
 
                if [ ! -f ../${bn}_tb.v ]; then
                        "$toolsdir"/../../yosys -f "$frontend $include_opts" -b "test_autotb $autotb_opts" -o ${bn}_tb.v ${bn}_ref.v
diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v
new file mode 100644 (file)
index 0000000..f1bd5ea
--- /dev/null
@@ -0,0 +1,138 @@
+module mux_if_unbal_4_1 #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @*
+    if (s == 0) o <= i[0*W+:W];
+    else if (s == 1) o <= i[1*W+:W];
+    else if (s == 2) o <= i[2*W+:W];
+    else if (s == 3) o <= i[3*W+:W];
+    else o <= {W{1'bx}};
+endmodule
+
+module mux_if_unbal_5_3 #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @* begin
+    o <= {W{1'bx}};
+    if (s == 0) o <= i[0*W+:W];
+    if (s == 1) o <= i[1*W+:W];
+    if (s == 2) o <= i[2*W+:W];
+    if (s == 3) o <= i[3*W+:W];
+    if (s == 4) o <= i[4*W+:W];
+end
+endmodule
+
+module mux_if_unbal_5_3_invert #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @*
+    if (s != 0) 
+               if (s != 1) 
+                       if (s != 2)
+                               if (s != 3)
+                                       if (s != 4) o <= i[4*W+:W];
+                                       else o <= i[0*W+:W];
+                               else o <= i[3*W+:W];
+                       else o <= i[2*W+:W];
+               else o <= i[1*W+:W];
+    else o <= {W{1'bx}};
+endmodule
+
+module mux_if_unbal_5_3_width_mismatch #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @* begin
+    o <= {W{1'bx}};
+    if (s == 0) o <= i[0*W+:W];
+    if (s == 1) o <= i[1*W+:W];
+    if (s == 2) o[W-2:0] <= i[2*W+:W-1];
+    if (s == 3) o <= i[3*W+:W];
+    if (s == 4) o <= i[4*W+:W];
+end
+endmodule
+
+module mux_if_unbal_4_1_missing #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @* begin
+    if (s == 0) o <= i[0*W+:W];
+//    else if (s == 1) o <= i[1*W+:W];
+//    else if (s == 2) o <= i[2*W+:W];
+    else if (s == 3) o <= i[3*W+:W];
+    else o <= {W{1'bx}};
+end
+endmodule
+
+module mux_if_unbal_5_3_order #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @* begin
+    o <= {W{1'bx}};
+    if (s == 3) o <= i[3*W+:W];
+    if (s == 2) o <= i[2*W+:W];
+    if (s == 1) o <= i[1*W+:W];
+    if (s == 4) o <= i[4*W+:W];
+    if (s == 0) o <= i[0*W+:W];
+end
+endmodule
+
+module mux_if_unbal_4_1_nonexcl #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @*
+    if (s == 0) o <= i[0*W+:W];
+    else if (s == 1) o <= i[1*W+:W];
+    else if (s == 2) o <= i[2*W+:W];
+    else if (s == 3) o <= i[3*W+:W];
+       else if (s == 0) o <= {W{1'b0}};
+    else o <= {W{1'bx}};
+endmodule
+
+module mux_if_unbal_5_3_nonexcl #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @* begin
+    o <= {W{1'bx}};
+    if (s == 0) o <= i[0*W+:W];
+    if (s == 1) o <= i[1*W+:W];
+    if (s == 2) o <= i[2*W+:W];
+    if (s == 3) o <= i[3*W+:W];
+    if (s == 4) o <= i[4*W+:W];
+       if (s == 0) o <= i[2*W+:W];
+end
+endmodule
+
+module mux_case_unbal_8_7#(parameter N=8, parameter W=7) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @* begin
+    o <= {W{1'bx}};
+    case (s)
+    0: o <= i[0*W+:W];
+    default:
+        case (s)
+        1: o <= i[1*W+:W];
+        2: o <= i[2*W+:W];
+        default:
+            case (s)
+            3: o <= i[3*W+:W];
+            4: o <= i[4*W+:W];
+            5: o <= i[5*W+:W];
+            default:
+                case (s)
+                    6: o <= i[6*W+:W];
+                    default: o <= i[7*W+:W];
+                endcase
+            endcase
+        endcase
+    endcase
+end
+endmodule
+
+module mux_if_bal_8_2 #(parameter N=8, parameter W=2) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
+always @*
+    if (s[0] == 1'b0)
+     if (s[1] == 1'b0)
+      if (s[2] == 1'b0)
+       o <= i[0*W+:W];
+      else
+       o <= i[1*W+:W];
+     else
+      if (s[2] == 1'b0)
+       o <= i[2*W+:W];
+      else
+       o <= i[3*W+:W];
+    else
+     if (s[1] == 1'b0)
+      if (s[2] == 1'b0)
+       o <= i[4*W+:W];
+      else
+       o <= i[5*W+:W];
+     else
+      if (s[2] == 1'b0)
+       o <= i[6*W+:W];
+      else
+       o <= i[7*W+:W];
+endmodule
diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys
new file mode 100644 (file)
index 0000000..9ea743b
--- /dev/null
@@ -0,0 +1,150 @@
+read_verilog muxpack.v
+design -save read
+hierarchy -top mux_if_unbal_4_1
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_5_3
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_5_3_invert
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_5_3_width_mismatch
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 2 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_4_1_missing
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_5_3_order
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_4_1_nonexcl
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_unbal_5_3_nonexcl
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_case_unbal_8_7
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 0 t:$mux
+select -assert-count 1 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
+
+design -load read
+hierarchy -top mux_if_bal_8_2
+prep
+design -save gold
+muxpack
+opt
+stat
+select -assert-count 7 t:$mux
+select -assert-count 0 t:$pmux
+design -stash gate
+design -import gold -as gold
+design -import gate -as gate
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports miter
diff --git a/tests/various/shregmap.v b/tests/various/shregmap.v
new file mode 100644 (file)
index 0000000..56e05c2
--- /dev/null
@@ -0,0 +1,22 @@
+module shregmap_test(input i, clk, output [1:0] q);
+reg head = 1'b0;
+reg [3:0] shift1 = 4'b0000;
+reg [3:0] shift2 = 4'b0000;
+
+always @(posedge clk) begin
+    head <= i;
+    shift1 <= {shift1[2:0], head};
+    shift2 <= {shift2[2:0], head};
+end
+
+assign q = {shift2[3], shift1[3]};
+endmodule
+
+module $__SHREG_DFF_P_(input C, D, output Q);
+parameter DEPTH = 1;
+parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}};
+reg [DEPTH-1:0] r = INIT;
+always @(posedge C) 
+    r <= { r[DEPTH-2:0], D };
+assign Q = r[DEPTH-1];
+endmodule
diff --git a/tests/various/shregmap.ys b/tests/various/shregmap.ys
new file mode 100644 (file)
index 0000000..ca7f470
--- /dev/null
@@ -0,0 +1,31 @@
+read_verilog shregmap.v
+design -copy-to model $__SHREG_DFF_P_
+hierarchy -top shregmap_test
+prep
+design -save gold
+
+techmap
+shregmap -init
+
+opt
+
+stat
+# show -width
+select -assert-count 1 t:$_DFF_P_
+select -assert-count 2 t:$__SHREG_DFF_P_
+
+design -stash gate
+
+design -import gold -as gold
+design -import gate -as gate
+design -copy-from model -as $__SHREG_DFF_P_ \$__SHREG_DFF_P_
+prep
+
+miter -equiv -flatten -make_assert -make_outputs gold gate miter
+sat -verify -prove-asserts -show-ports -seq 5 miter
+
+design -load gold
+stat
+
+design -load gate
+stat