diff options
Diffstat (limited to 'passes/techmap')
-rw-r--r-- | passes/techmap/Makefile.inc | 2 | ||||
-rw-r--r-- | passes/techmap/abc.cc | 67 | ||||
-rw-r--r-- | passes/techmap/alumacc.cc | 16 | ||||
-rw-r--r-- | passes/techmap/dffinit.cc | 26 | ||||
-rw-r--r-- | passes/techmap/dfflibmap.cc | 1 | ||||
-rw-r--r-- | passes/techmap/extract.cc | 4 | ||||
-rw-r--r-- | passes/techmap/iopadmap.cc | 6 | ||||
-rw-r--r-- | passes/techmap/lut2mux.cc | 93 | ||||
-rw-r--r-- | passes/techmap/maccmap.cc | 2 | ||||
-rw-r--r-- | passes/techmap/muxcover.cc | 6 | ||||
-rw-r--r-- | passes/techmap/nlutmap.cc | 173 | ||||
-rw-r--r-- | passes/techmap/simplemap.cc | 4 | ||||
-rw-r--r-- | passes/techmap/techmap.cc | 4 |
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]); |