From: Clifford Wolf Date: Wed, 30 Jul 2014 20:04:30 +0000 (+0200) Subject: Added techmap CONSTMAP feature X-Git-Tag: yosys-0.4~354 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=254148910556d057ec296e4f8c44e92bdb8c09a3;p=yosys.git Added techmap CONSTMAP feature --- diff --git a/kernel/rtlil.h b/kernel/rtlil.h index d6acb5bcc..7bd75bd1d 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -278,6 +278,9 @@ namespace RTLIL result.push_back(it.second); return result; } + + std::set to_set() const { return *this; } + std::vector to_vector() const { return *this; } }; }; diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 0ae5220e0..75b9dee9b 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -17,11 +17,11 @@ * */ -#include "kernel/compatibility.h" -#include "kernel/register.h" -#include "kernel/sigtools.h" +#include "kernel/yosys.h" #include "kernel/toposort.h" -#include "kernel/log.h" +#include "kernel/sigtools.h" +#include "libs/sha1/sha1.h" + #include #include #include @@ -66,6 +66,36 @@ struct TechmapWorker typedef std::map> TechmapWires; + std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) + { + std::string constmap_info; + std::map> connbits_map; + + for (auto conn : cell->connections()) + for (int i = 0; i < SIZE(conn.second); i++) { + RTLIL::SigBit bit = sigmap(conn.second[i]); + if (bit.wire == nullptr) { + if (verbose) + log(" Constant input on bit %d of port %s: %s\n", i, log_id(conn.first), log_signal(bit)); + constmap_info += stringf("|%s %d %d", log_id(conn.first), i, bit.data); + } else if (connbits_map.count(bit)) { + if (verbose) + log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, log_id(conn.first), + connbits_map.at(bit).second, log_id(connbits_map.at(bit).first)); + constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i, + log_id(connbits_map.at(bit).first), connbits_map.at(bit).second); + } else + connbits_map[bit] = std::pair(conn.first, i);stringf("%s %d", log_id(conn.first), i, bit.data); + } + + unsigned char hash[20]; + char hash_hex_string[41]; + sha1::calc(constmap_info.c_str(), constmap_info.size(), hash); + sha1::toHexString(hash, hash_hex_string); + + return stringf("$paramod$constmap$%s%s", hash_hex_string, tpl->name.c_str()); + } + TechmapWires techmap_find_special_wires(RTLIL::Module *module) { TechmapWires result; @@ -374,14 +404,19 @@ struct TechmapWorker } else { if (cell->parameters.size() != 0) { derived_name = tpl->derive(map, parameters); - tpl = map->modules_[derived_name]; + tpl = map->module(derived_name); log_continue = true; } techmap_cache[key] = tpl; } - if (flatten_mode) + if (flatten_mode) { techmap_do_cache[tpl] = true; + } else { + RTLIL::Module *constmapped_tpl = map->module(constmap_tpl_name(sigmap, tpl, cell, false)); + if (constmapped_tpl != nullptr) + tpl = constmapped_tpl; + } if (techmap_do_cache.count(tpl) == 0) { @@ -426,14 +461,80 @@ struct TechmapWorker const char *q = strrchr(p+1, '.'); q = q ? q : p+1; + std::string cmd_string = data.value.as_const().decode_string(); + + if (cmd_string.rfind("CONSTMAP; ", 0) == 0) + { + cmd_string = cmd_string.substr(strlen("CONSTMAP; ")); + + log("Analyzing pattern of constant bits for this cell:\n"); + std::string new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); + log("Creating constmapped module `%s'.\n", log_id(new_tpl_name)); + log_assert(map->module(new_tpl_name) == nullptr); + + RTLIL::Module *new_tpl = map->addModule(new_tpl_name); + tpl->cloneInto(new_tpl); + + techmap_do_cache.erase(tpl); + techmap_do_cache[new_tpl] = true; + tpl = new_tpl; + + std::map port_new2old_map; + std::map port_connmap; + std::map cellbits_to_tplbits; + + for (auto wire : tpl->wires().to_vector()) + { + if (!wire->port_input || wire->port_output) + continue; + + std::string port_name = wire->name; + tpl->rename(wire, NEW_ID); + + RTLIL::Wire *new_wire = tpl->addWire(port_name, wire); + wire->port_input = false; + + for (int i = 0; i < wire->width; i++) { + port_new2old_map[RTLIL::SigBit(new_wire, i)] = RTLIL::SigBit(wire, i); + port_connmap[RTLIL::SigBit(wire, i)] = RTLIL::SigBit(new_wire, i); + } + } + + for (auto conn : cell->connections()) + for (int i = 0; i < SIZE(conn.second); i++) + { + RTLIL::SigBit bit = sigmap(conn.second[i]); + RTLIL::SigBit tplbit(tpl->wire(conn.first), i); + + if (bit.wire == nullptr) + { + RTLIL::SigBit oldbit = port_new2old_map.at(tplbit); + port_connmap.at(oldbit) = bit; + } + else if (cellbits_to_tplbits.count(bit)) + { + RTLIL::SigBit oldbit = port_new2old_map.at(tplbit); + port_connmap.at(oldbit) = cellbits_to_tplbits[bit]; + } + else + cellbits_to_tplbits[bit] = tplbit; + } + + RTLIL::SigSig port_conn; + for (auto &it : port_connmap) { + port_conn.first.append_bit(it.first); + port_conn.second.append_bit(it.second); + } + tpl->connect(port_conn); + } + + Pass::call_on_module(map, tpl, cmd_string); + log_assert(!strncmp(q, "_TECHMAP_DO_", 12)); std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12); while (tpl->wires_.count(new_name)) new_name += "_"; - tpl->rename(data.wire, new_name); - - std::string cmd_string = data.value.as_const().decode_string(); - Pass::call_on_module(map, tpl, cmd_string); + tpl->rename(data.wire->name, new_name); keep_running = true; break; @@ -571,6 +672,14 @@ struct TechmapPass : public Pass { log(" wire to start out as non-constant and evaluate to a constant value\n"); log(" during processing of other _TECHMAP_DO_* commands.\n"); log("\n"); + log(" A _TECHMAP_DO_* command may start with the special token 'CONSTMAP; '.\n"); + log(" in this case techmap will create a copy for each distinct configuration\n"); + log(" of constant inputs and shorted inputs at this point and import the\n"); + log(" constant and connected bits into the map module. All further commands\n"); + log(" are executed in this copy. This is a very convenient way of creating\n"); + log(" optimizied specializations of techmap modules without using the special\n"); + log(" parameters described below.\n"); + log("\n"); log("In addition to this special wires, techmap also supports special parameters in\n"); log("modules in the map file:\n"); log("\n"); diff --git a/techlibs/common/stdcells.v b/techlibs/common/stdcells.v index a2fce1313..7ee2771e6 100644 --- a/techlibs/common/stdcells.v +++ b/techlibs/common/stdcells.v @@ -152,7 +152,8 @@ output [Y_WIDTH-1:0] Y; localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH); localparam BB_WIDTH = `MIN($clog2(shift_left ? Y_WIDTH : A_SIGNED ? WIDTH : A_WIDTH) + 1, B_WIDTH); -wire [1023:0] _TECHMAP_DO_ = "proc; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; +wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; +wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; integer i; reg [WIDTH-1:0] buffer; @@ -198,7 +199,8 @@ localparam WIDTH = `MAX(A_WIDTH, Y_WIDTH) + (B_SIGNED ? 2**(BB_WIDTH-1) : 0); parameter _TECHMAP_CELLTYPE_ = ""; localparam extbit = _TECHMAP_CELLTYPE_ == "$shift" ? 1'b0 : 1'bx; -wire [1023:0] _TECHMAP_DO_ = "proc; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; +wire [1023:0] _TECHMAP_DO_00_ = "proc;;"; +wire [1023:0] _TECHMAP_DO_01_ = "CONSTMAP; opt_muxtree; opt_const -mux_undef -mux_bool -fine;;;"; integer i; reg [WIDTH-1:0] buffer;