aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc67
-rw-r--r--passes/techmap/alumacc.cc16
-rw-r--r--passes/techmap/dffinit.cc26
-rw-r--r--passes/techmap/dfflibmap.cc1
-rw-r--r--passes/techmap/extract.cc4
-rw-r--r--passes/techmap/iopadmap.cc6
-rw-r--r--passes/techmap/lut2mux.cc93
-rw-r--r--passes/techmap/maccmap.cc2
-rw-r--r--passes/techmap/muxcover.cc6
-rw-r--r--passes/techmap/nlutmap.cc173
-rw-r--r--passes/techmap/simplemap.cc4
-rw-r--r--passes/techmap/techmap.cc4
13 files changed, 365 insertions, 39 deletions
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index af4816a72..674cb77cb 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -20,6 +20,8 @@ OBJS += passes/techmap/pmuxtree.o
OBJS += passes/techmap/muxcover.o
OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
+OBJS += passes/techmap/lut2mux.o
+OBJS += passes/techmap/nlutmap.o
endif
GENFILES += passes/techmap/techmap.inc
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index d1e629b5a..5c5148590 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -100,6 +100,7 @@ SigMap assign_map;
RTLIL::Module *module;
std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map;
+pool<std::string> enabled_gates;
bool clk_polarity, en_polarity;
RTLIL::SigSpec clk_sig, en_sig;
@@ -837,17 +838,28 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
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_"));
- fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_AND_"));
- fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NAND_"));
- fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", get_cell_cost("$_OR_"));
- fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_NOR_"));
- fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XOR_"));
- fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", get_cell_cost("$_XNOR_"));
- fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI3_"));
- fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI3_"));
- fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_AOI4_"));
- fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", get_cell_cost("$_OAI4_"));
- 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 (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("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)
@@ -1075,6 +1087,12 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
design->select(module, cell);
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;
+ }
RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type);
if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
cell->parameters = c->parameters;
@@ -1224,6 +1242,11 @@ struct AbcPass : public Pass {
// log(" try to extract 4-input, 8-input, and/or 16-input muxes\n");
// log(" (ignored when used with -liberty or -lut)\n");
// log("\n");
+ log(" -g type1,type2,...\n");
+ log(" Map the the specified list of gate types. Supported gates types are:\n");
+ log(" AND, NAND, OR, NOR, XOR, XNOR, MUX, AOI3, OAI3, AOI4, OAI4.\n");
+ log(" (The NOT gate is always added to this list automatically.)\n");
+ log("\n");
log(" -dff\n");
log(" also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
log(" clock domains are automatically partitioned in clock domains and each\n");
@@ -1274,6 +1297,7 @@ struct AbcPass : public Pass {
map_mux4 = false;
map_mux8 = false;
map_mux16 = false;
+ enabled_gates.clear();
#ifdef _WIN32
if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
@@ -1338,6 +1362,25 @@ struct AbcPass : public Pass {
map_mux16 = true;
continue;
}
+ if (arg == "-g" && argidx+1 < args.size()) {
+ for (auto g : split_tokens(args[++argidx], ",")) {
+ if (g == "AND") goto ok_gate;
+ if (g == "NAND") goto ok_gate;
+ if (g == "OR") goto ok_gate;
+ if (g == "NOR") goto ok_gate;
+ if (g == "XOR") goto ok_gate;
+ if (g == "XNOR") goto ok_gate;
+ if (g == "MUX") goto ok_gate;
+ if (g == "AOI3") goto ok_gate;
+ if (g == "OAI3") goto ok_gate;
+ if (g == "AOI4") goto ok_gate;
+ if (g == "OAI4") goto ok_gate;
+ cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));
+ ok_gate:
+ enabled_gates.insert(g);
+ }
+ continue;
+ }
if (arg == "-fast") {
fast_mode = true;
continue;
@@ -1393,7 +1436,7 @@ struct AbcPass : public Pass {
std::set<RTLIL::Cell*> expand_queue_up, next_expand_queue_up;
std::set<RTLIL::Cell*> expand_queue_down, next_expand_queue_down;
- typedef std::tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
+ typedef tuple<bool, RTLIL::SigSpec, bool, RTLIL::SigSpec> clkdomain_t;
std::map<clkdomain_t, std::vector<RTLIL::Cell*>> assigned_cells;
std::map<RTLIL::Cell*, clkdomain_t> assigned_cells_reverse;
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index 54c9bc1aa..3c7ff4b92 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -40,7 +40,7 @@ struct AlumaccWorker
{
std::vector<RTLIL::Cell*> cells;
RTLIL::SigSpec a, b, c, y;
- std::vector<std::tuple<bool, bool, bool, bool, RTLIL::SigSpec>> cmp;
+ std::vector<tuple<bool, bool, bool, bool, RTLIL::SigSpec>> cmp;
bool is_signed, invert_b;
RTLIL::Cell *alu_cell;
@@ -98,9 +98,9 @@ struct AlumaccWorker
}
};
- std::map<RTLIL::SigBit, int> bit_users;
- std::map<RTLIL::SigSpec, maccnode_t*> sig_macc;
- std::map<RTLIL::SigSig, std::set<alunode_t*>> sig_alu;
+ dict<RTLIL::SigBit, int> bit_users;
+ dict<RTLIL::SigSpec, maccnode_t*> sig_macc;
+ dict<RTLIL::SigSig, pool<alunode_t*, hash_ptr_ops>> sig_alu;
int macc_counter, alu_counter;
AlumaccWorker(RTLIL::Module *module) : module(module), sigmap(module)
@@ -138,7 +138,7 @@ struct AlumaccWorker
n->users = 0;
for (auto bit : n->y)
- n->users = std::max(n->users, bit_users.at(bit) - 1);
+ n->users = max(n->users, bit_users.at(bit) - 1);
if (cell->type.in("$pos", "$neg"))
{
@@ -215,7 +215,7 @@ struct AlumaccWorker
{
while (1)
{
- std::set<maccnode_t*> delete_nodes;
+ pool<maccnode_t*, hash_ptr_ops> delete_nodes;
for (auto &it : sig_macc)
{
@@ -267,7 +267,7 @@ struct AlumaccWorker
void macc_to_alu()
{
- std::set<maccnode_t*> delete_nodes;
+ pool<maccnode_t*, hash_ptr_ops> delete_nodes;
for (auto &it : sig_macc)
{
@@ -409,7 +409,7 @@ struct AlumaccWorker
n->a = A;
n->b = B;
n->c = RTLIL::S1;
- n->y = module->addWire(NEW_ID, std::max(GetSize(A), GetSize(B)));
+ n->y = module->addWire(NEW_ID, max(GetSize(A), GetSize(B)));
n->is_signed = is_signed;
n->invert_b = true;
sig_alu[RTLIL::SigSig(A, B)].insert(n);
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index 2215c18e5..e0273f439 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -63,16 +63,26 @@ struct DffinitPass : public Pass {
SigMap sigmap(module);
dict<SigBit, State> init_bits;
pool<SigBit> cleanup_bits;
+ pool<SigBit> used_bits;
- for (auto wire : module->selected_wires())
+ for (auto wire : module->selected_wires()) {
if (wire->attributes.count("\\init")) {
Const value = wire->attributes.at("\\init");
- for (int i = 0; i < std::min(GetSize(value), GetSize(wire)); i++)
+ for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
init_bits[sigmap(SigBit(wire, i))] = value[i];
}
+ if (wire->port_output)
+ for (auto bit : sigmap(wire))
+ used_bits.insert(bit);
+ }
for (auto cell : module->selected_cells())
{
+ for (auto it : cell->connections())
+ if (!cell->known() || cell->input(it.first))
+ for (auto bit : sigmap(it.second))
+ used_bits.insert(bit);
+
if (ff_types.count(cell->type) == 0)
continue;
@@ -90,7 +100,7 @@ struct DffinitPass : public Pass {
for (int i = 0; i < GetSize(sig); i++) {
if (init_bits.count(sig[i]) == 0)
continue;
- while (GetSize(value.bits) < i)
+ while (GetSize(value.bits) <= i)
value.bits.push_back(State::S0);
value.bits[i] = init_bits.at(sig[i]);
cleanup_bits.insert(sig[i]);
@@ -104,11 +114,15 @@ struct DffinitPass : public Pass {
for (auto wire : module->selected_wires())
if (wire->attributes.count("\\init")) {
- Const value = wire->attributes.at("\\init");
+ Const &value = wire->attributes.at("\\init");
bool do_cleanup = true;
- for (int i = 0; i < std::min(GetSize(value), GetSize(wire)); i++)
- if (cleanup_bits.count(sigmap(SigBit(wire, i))) == 0)
+ for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
+ SigBit bit = sigmap(SigBit(wire, i));
+ if (cleanup_bits.count(bit) || !used_bits.count(bit))
+ value[i] = State::Sx;
+ else if (value[i] != State::Sx)
do_cleanup = false;
+ }
if (do_cleanup) {
log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
wire->attributes.erase("\\init");
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 64131c1a8..693651bfd 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -491,6 +491,7 @@ struct DfflibmapPass : public Pass {
std::string arg = args[argidx];
if (arg == "-liberty" && argidx+1 < args.size()) {
liberty_file = args[++argidx];
+ rewrite_filename(liberty_file);
continue;
}
if (arg == "-prepare") {
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index 68a7fc1f6..fc73177ce 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -130,7 +130,7 @@ public:
RTLIL::SigSpec needleSig = conn.second;
RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str()));
- for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) {
+ for (int i = 0; i < min(needleSig.size(), haystackSig.size()); i++) {
RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire;
if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire)
if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr))
@@ -737,7 +737,7 @@ struct ExtractPass : public Pass {
RTLIL::Cell *newCell = newMod->addCell(cell->name, cell->type);
newCell->parameters = cell->parameters;
for (auto &conn : cell->connections()) {
- std::vector<RTLIL::SigChunk> chunks = sigmap(conn.second);
+ std::vector<SigChunk> chunks = sigmap(conn.second);
for (auto &chunk : chunks)
if (chunk.wire != NULL)
chunk.wire = newMod->wires_.at(chunk.wire->name);
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 0e0a2adc9..9dab40ca8 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -45,10 +45,10 @@ struct IopadmapPass : public Pass {
log("the resulting cells to more sophisticated PAD cells.\n");
log("\n");
log(" -inpad <celltype> <portname>[:<portname>]\n");
- log(" Map module input ports to the given cell type with\n");
- log(" the given port name. if a 2nd portname is given, the\n");
+ log(" Map module input ports to the given cell type with the\n");
+ log(" given output port name. if a 2nd portname is given, the\n");
log(" signal is passed through the pad call, using the 2nd\n");
- log(" portname as output.\n");
+ log(" portname as input.\n");
log("\n");
log(" -outpad <celltype> <portname>[:<portname>]\n");
log(" -inoutpad <celltype> <portname>[:<portname>]\n");
diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc
new file mode 100644
index 000000000..fe55e499a
--- /dev/null
+++ b/passes/techmap/lut2mux.cc
@@ -0,0 +1,93 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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
+
+int lut2mux(Cell *cell)
+{
+ SigSpec sig_a = cell->getPort("\\A");
+ SigSpec sig_y = cell->getPort("\\Y");
+ Const lut = cell->getParam("\\LUT");
+ int count = 1;
+
+ if (GetSize(sig_a) == 1)
+ {
+ cell->module->addMuxGate(NEW_ID, lut[0], lut[1], sig_a, sig_y);
+ }
+ else
+ {
+ SigSpec sig_a_hi = sig_a[GetSize(sig_a)-1];
+ SigSpec sig_a_lo = sig_a.extract(0, GetSize(sig_a)-1);
+ SigSpec sig_y1 = cell->module->addWire(NEW_ID);
+ SigSpec sig_y2 = cell->module->addWire(NEW_ID);
+
+ Const lut1 = lut.extract(0, GetSize(lut)/2);
+ Const lut2 = lut.extract(GetSize(lut)/2, GetSize(lut)/2);
+
+ count += lut2mux(cell->module->addLut(NEW_ID, sig_a_lo, sig_y1, lut1));
+ count += lut2mux(cell->module->addLut(NEW_ID, sig_a_lo, sig_y2, lut2));
+
+ cell->module->addMuxGate(NEW_ID, sig_y1, sig_y2, sig_a_hi, sig_y);
+ }
+
+ cell->module->remove(cell);
+ return count;
+}
+
+struct Lut2muxPass : public Pass {
+ Lut2muxPass() : Pass("lut2mux", "convert $lut to $_MUX_") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" lut2mux [options] [selection]\n");
+ log("\n");
+ log("This pass converts $lut cells to $_MUX_ gates.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header("Executing LUT2MUX pass (mapping to constant drivers).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-v") {
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->selected_cells()) {
+ if (cell->type == "$lut") {
+ IdString cell_name = cell->name;
+ int count = lut2mux(cell);
+ log("Converted %s.%s to %d MUX cells.\n", log_id(module), log_id(cell_name), count);
+ }
+ }
+ }
+} Lut2muxPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc
index dad1c06ac..d5b8fe804 100644
--- a/passes/techmap/maccmap.cc
+++ b/passes/techmap/maccmap.cc
@@ -134,7 +134,7 @@ struct MaccmapWorker
}
return retval;
#else
- return std::max(n - 1, 0);
+ return max(n - 1, 0);
#endif
}
diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc
index b250c5680..514c3365f 100644
--- a/passes/techmap/muxcover.cc
+++ b/passes/techmap/muxcover.cc
@@ -49,8 +49,8 @@ struct MuxcoverWorker
vector<tree_t> tree_list;
- dict<std::tuple<SigBit, SigBit, SigBit>, std::tuple<SigBit, pool<SigBit>, bool>> decode_mux_cache;
- dict<SigBit, std::tuple<SigBit, SigBit, SigBit>> decode_mux_reverse_cache;
+ dict<tuple<SigBit, SigBit, SigBit>, tuple<SigBit, pool<SigBit>, bool>> decode_mux_cache;
+ dict<SigBit, tuple<SigBit, SigBit, SigBit>> decode_mux_reverse_cache;
int decode_mux_counter;
bool use_mux4;
@@ -142,7 +142,7 @@ struct MuxcoverWorker
if (A == B)
return 0;
- std::tuple<SigBit, SigBit, SigBit> key(A, B, sel);
+ tuple<SigBit, SigBit, SigBit> key(A, B, sel);
if (decode_mux_cache.count(key) == 0) {
auto &entry = decode_mux_cache[key];
std::get<0>(entry) = module->addWire(NEW_ID);
diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc
new file mode 100644
index 000000000..7ece40059
--- /dev/null
+++ b/passes/techmap/nlutmap.cc
@@ -0,0 +1,173 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * 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 NlutmapConfig
+{
+ vector<int> luts;
+};
+
+struct NlutmapWorker
+{
+ const NlutmapConfig &config;
+ pool<Cell*> mapped_cells;
+ Module *module;
+
+ NlutmapWorker(const NlutmapConfig &config, Module *module) :
+ config(config), module(module)
+ {
+ }
+
+ RTLIL::Selection get_selection()
+ {
+ RTLIL::Selection sel(false);
+ for (auto cell : module->cells())
+ if (!mapped_cells.count(cell))
+ sel.select(module, cell);
+ return sel;
+ }
+
+ void run_abc(int lut_size)
+ {
+ Pass::call_on_selection(module->design, get_selection(), "lut2mux");
+
+ if (lut_size > 0)
+ Pass::call_on_selection(module->design, get_selection(), stringf("abc -lut 1:%d", lut_size));
+ else
+ Pass::call_on_selection(module->design, get_selection(), "abc");
+
+ Pass::call_on_module(module->design, module, "opt_clean");
+ }
+
+ void run()
+ {
+ vector<int> available_luts = config.luts;
+
+ while (!available_luts.empty())
+ {
+ int n_luts = available_luts.back();
+ int lut_size = GetSize(available_luts);
+ available_luts.pop_back();
+
+ if (n_luts == 0)
+ continue;
+
+ run_abc(lut_size);
+
+ SigMap sigmap(module);
+ dict<Cell*, int> candidate_ratings;
+ dict<SigBit, int> bit_lut_count;
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type != "$lut" || mapped_cells.count(cell))
+ continue;
+
+ if (GetSize(cell->getPort("\\A")) == lut_size)
+ candidate_ratings[cell] = 0;
+
+ for (auto &conn : cell->connections())
+ for (auto bit : sigmap(conn.second))
+ bit_lut_count[bit]++;
+ }
+
+ for (auto &cand : candidate_ratings)
+ {
+ for (auto &conn : cand.first->connections())
+ for (auto bit : sigmap(conn.second))
+ cand.second -= bit_lut_count[bit];
+ }
+
+ vector<pair<int, IdString>> rated_candidates;
+
+ for (auto &cand : candidate_ratings)
+ rated_candidates.push_back(pair<int, IdString>(cand.second, cand.first->name));
+
+ std::sort(rated_candidates.begin(), rated_candidates.end());
+
+ while (n_luts > 0 && !rated_candidates.empty()) {
+ mapped_cells.insert(module->cell(rated_candidates.back().second));
+ rated_candidates.pop_back();
+ n_luts--;
+ }
+
+ if (!available_luts.empty())
+ available_luts.back() += n_luts;
+ }
+
+ run_abc(0);
+ }
+};
+
+struct NlutmapPass : public Pass {
+ NlutmapPass() : Pass("nlutmap", "map to LUTs of different sizes") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" nlutmap [options] [selection]\n");
+ log("\n");
+ log("This pass uses successive calls to 'abc' to map to an architecture. That\n");
+ log("provides a small number of differently sized LUTs.\n");
+ log("\n");
+ log(" -luts N_1,N_2,N_3,...\n");
+ log(" The number of LUTs with 1, 2, 3, ... inputs that are\n");
+ log(" available in the target architecture.\n");
+ log("\n");
+ log("Excess logic that does not fit into the specified LUTs is mapped back\n");
+ log("to generic logic gates ($_AND_, etc.).\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ NlutmapConfig config;
+
+ log_header("Executing NLUTMAP pass (mapping to constant drivers).\n");
+ log_push();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-luts" && argidx+1 < args.size()) {
+ vector<string> tokens = split_tokens(args[++argidx], ",");
+ config.luts.clear();
+ for (auto &token : tokens)
+ config.luts.push_back(atoi(token.c_str()));
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_whole_modules_warn())
+ {
+ NlutmapWorker worker(config, module);
+ worker.run();
+ }
+
+ log_pop();
+ }
+} NlutmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index 0fb5b3741..f6ac3964b 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -247,7 +247,7 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
bool is_ne = cell->type == "$ne" || cell->type == "$nex";
- RTLIL::SigSpec xor_out = module->addWire(NEW_ID, std::max(GetSize(sig_a), GetSize(sig_b)));
+ RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b)));
RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed);
xor_cell->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
simplemap_bitop(module, xor_cell);
@@ -293,7 +293,7 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_TBUF_");
gate->add_strpool_attribute("\\src", cell->get_strpool_attribute("\\src"));
gate->setPort("\\A", sig_a[i]);
- gate->setPort("\\E", sig_e[i]);
+ gate->setPort("\\E", sig_e);
gate->setPort("\\Y", sig_y[i]);
}
}
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 30a6d784f..19b2bda9c 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -49,7 +49,7 @@ void apply_prefix(std::string prefix, std::string &id)
void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
{
- std::vector<RTLIL::SigChunk> chunks = sig;
+ vector<SigChunk> chunks = sig;
for (auto &chunk : chunks)
if (chunk.wire != NULL) {
std::string wire_name = chunk.wire->name.str();
@@ -257,7 +257,7 @@ struct TechmapWorker
} else {
SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second;
apply_prefix(cell->name.str(), sig_tpl_pf, module);
- for (int i = 0; i < GetSize(sig_tpl); i++) {
+ for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) {
if (tpl_written_bits.count(tpl_sigmap(sig_tpl[i]))) {
c.first.append(sig_mod[i]);
c.second.append(sig_tpl_pf[i]);