diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | frontends/aiger/aigerparse.cc | 2 | ||||
-rw-r--r-- | frontends/ilang/ilang_lexer.l | 13 | ||||
-rw-r--r-- | frontends/ilang/ilang_parser.y | 3 | ||||
-rw-r--r-- | passes/cmds/bugpoint.cc | 28 | ||||
-rw-r--r-- | passes/cmds/connect.cc | 26 | ||||
-rw-r--r-- | passes/cmds/connwrappers.cc | 22 | ||||
-rw-r--r-- | passes/cmds/copy.cc | 4 | ||||
-rw-r--r-- | passes/cmds/delete.cc | 43 | ||||
-rw-r--r-- | passes/cmds/design.cc | 15 | ||||
-rw-r--r-- | passes/cmds/setattr.cc | 36 | ||||
-rw-r--r-- | passes/cmds/show.cc | 94 | ||||
-rw-r--r-- | passes/cmds/splice.cc | 32 | ||||
-rw-r--r-- | passes/cmds/stat.cc | 46 | ||||
-rw-r--r-- | passes/hierarchy/submod.cc | 45 | ||||
-rw-r--r-- | passes/techmap/dfflibmap.cc | 54 | ||||
-rw-r--r-- | passes/techmap/extract.cc | 79 | ||||
-rw-r--r-- | passes/tests/test_autotb.cc | 20 | ||||
-rw-r--r-- | techlibs/common/Makefile.inc | 1 | ||||
-rw-r--r-- | techlibs/common/cmp2lcu.v | 116 | ||||
-rw-r--r-- | techlibs/common/cmp2lut.v | 8 | ||||
-rw-r--r-- | techlibs/common/synth.cc | 6 | ||||
-rw-r--r-- | techlibs/xilinx/synth_xilinx.cc | 3 | ||||
-rw-r--r-- | tests/techmap/cmp2lcu.ys | 52 |
24 files changed, 442 insertions, 311 deletions
@@ -51,6 +51,10 @@ ifneq ($(wildcard Makefile.conf),) include Makefile.conf endif +ifeq ($(ENABLE_PYOSYS),1) +ENABLE_LIBYOSYS := 1 +endif + BINDIR := $(PREFIX)/bin LIBDIR := $(PREFIX)/lib DATDIR := $(PREFIX)/share/yosys @@ -529,6 +533,7 @@ $(eval $(call add_include_file,kernel/register.h)) $(eval $(call add_include_file,kernel/celltypes.h)) $(eval $(call add_include_file,kernel/celledges.h)) $(eval $(call add_include_file,kernel/consteval.h)) +$(eval $(call add_include_file,kernel/constids.inc)) $(eval $(call add_include_file,kernel/sigtools.h)) $(eval $(call add_include_file,kernel/modtools.h)) $(eval $(call add_include_file,kernel/macc.h)) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index cbce0c990..92cf92fa8 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -30,7 +30,9 @@ #include <libkern/OSByteOrder.h> #define __builtin_bswap32 OSSwapInt32 #endif +#ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS +#endif #include <inttypes.h> #include "kernel/yosys.h" diff --git a/frontends/ilang/ilang_lexer.l b/frontends/ilang/ilang_lexer.l index 4fd0ae855..62f53d18e 100644 --- a/frontends/ilang/ilang_lexer.l +++ b/frontends/ilang/ilang_lexer.l @@ -29,6 +29,7 @@ #pragma clang diagnostic ignored "-Wdeprecated-register" #endif +#include <cstdlib> #include "frontends/ilang/ilang_frontend.h" #include "ilang_parser.tab.hh" @@ -88,7 +89,16 @@ USING_YOSYS_NAMESPACE "."[0-9]+ { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_ID; } [0-9]+'[01xzm-]* { rtlil_frontend_ilang_yylval.string = strdup(yytext); return TOK_VALUE; } --?[0-9]+ { rtlil_frontend_ilang_yylval.integer = atoi(yytext); return TOK_INT; } +-?[0-9]+ { + char *end = nullptr; + long value = strtol(yytext, &end, 10); + if (end != yytext + strlen(yytext)) + return TOK_INVALID; // literal out of range of long + if (value < INT_MIN || value > INT_MAX) + return TOK_INVALID; // literal out of range of int (relevant mostly for LP64 platforms) + rtlil_frontend_ilang_yylval.integer = value; + return TOK_INT; +} \" { BEGIN(STRING); } <STRING>\\. { yymore(); } @@ -136,4 +146,3 @@ USING_YOSYS_NAMESPACE void *rtlil_frontend_ilang_avoid_input_warnings() { return (void*)&yyinput; } - diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 4e0b62edd..91adc0cc9 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -179,6 +179,9 @@ wire_options: wire_options TOK_WIDTH TOK_INT { current_wire->width = $3; } | + wire_options TOK_WIDTH TOK_INVALID { + rtlil_frontend_ilang_yyerror("ilang error: invalid wire width"); + } | wire_options TOK_UPTO { current_wire->upto = true; } | diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index ed427693d..ad6a07fa0 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -114,8 +114,8 @@ struct BugpointPass : public Pass { return design; RTLIL::Design *design_copy = new RTLIL::Design; - for (auto &it : design->modules_) - design_copy->add(it.second->clone()); + for (auto module : design->modules()) + design_copy->add(module->clone()); Pass::call(design_copy, "proc_clean -quiet"); Pass::call(design_copy, "clean -purge"); @@ -127,21 +127,21 @@ struct BugpointPass : public Pass { RTLIL::Design *simplify_something(RTLIL::Design *design, int &seed, bool stage2, bool modules, bool ports, bool cells, bool connections, bool assigns, bool updates) { RTLIL::Design *design_copy = new RTLIL::Design; - for (auto &it : design->modules_) - design_copy->add(it.second->clone()); + for (auto module : design->modules()) + design_copy->add(module->clone()); int index = 0; if (modules) { - for (auto &it : design_copy->modules_) + for (auto module : design_copy->modules()) { - if (it.second->get_blackbox_attribute()) + if (module->get_blackbox_attribute()) continue; if (index++ == seed) { - log("Trying to remove module %s.\n", it.first.c_str()); - design_copy->remove(it.second); + log("Trying to remove module %s.\n", module->name.c_str()); + design_copy->remove(module); return design_copy; } } @@ -178,12 +178,12 @@ struct BugpointPass : public Pass { if (mod->get_blackbox_attribute()) continue; - for (auto &it : mod->cells_) + for (auto cell : mod->cells()) { if (index++ == seed) { - log("Trying to remove cell %s.%s.\n", mod->name.c_str(), it.first.c_str()); - mod->remove(it.second); + log("Trying to remove cell %s.%s.\n", mod->name.c_str(), cell->name.c_str()); + mod->remove(cell); return design_copy; } } @@ -285,7 +285,7 @@ struct BugpointPass : public Pass { } } } - return NULL; + return nullptr; } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE @@ -433,8 +433,8 @@ struct BugpointPass : public Pass { { Pass::call(design, "design -reset"); crashing_design = clean_design(crashing_design, clean, /*do_delete=*/true); - for (auto &it : crashing_design->modules_) - design->add(it.second->clone()); + for (auto module : crashing_design->modules()) + design->add(module->clone()); delete crashing_design; } } diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index f93bada27..0b0868dfb 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -32,9 +32,9 @@ static void unset_drivers(RTLIL::Design *design, RTLIL::Module *module, SigMap & RTLIL::Wire *dummy_wire = module->addWire(NEW_ID, sig.size()); - for (auto &it : module->cells_) - for (auto &port : it.second->connections_) - if (ct.cell_output(it.second->type, port.first)) + for (auto cell : module->cells()) + for (auto &port : cell->connections_) + if (ct.cell_output(cell->type, port.first)) sigmap(port.second).replace(sig, dummy_wire, &port.second); for (auto &conn : module->connections_) @@ -77,15 +77,13 @@ struct ConnectPass : public Pass { } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { - RTLIL::Module *module = NULL; - for (auto &it : design->modules_) { - if (!design->selected(it.second)) - continue; - if (module != NULL) - log_cmd_error("Multiple modules selected: %s, %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(it.first)); - module = it.second; + RTLIL::Module *module = nullptr; + for (auto mod : design->selected_modules()) { + if (module != nullptr) + log_cmd_error("Multiple modules selected: %s, %s\n", log_id(module->name), log_id(mod->name)); + module = mod; } - if (module == NULL) + if (module == nullptr) log_cmd_error("No modules selected.\n"); if (!module->processes.empty()) log_cmd_error("Found processes in selected module.\n"); @@ -130,7 +128,7 @@ struct ConnectPass : public Pass { std::vector<RTLIL::SigBit> lhs = it.first.to_sigbit_vector(); std::vector<RTLIL::SigBit> rhs = it.first.to_sigbit_vector(); for (size_t i = 0; i < lhs.size(); i++) - if (rhs[i].wire != NULL) + if (rhs[i].wire != nullptr) sigmap.add(lhs[i], rhs[i]); } @@ -172,14 +170,14 @@ struct ConnectPass : public Pass { if (flag_nounset) log_cmd_error("Can't use -port together with -nounset.\n"); - if (module->cells_.count(RTLIL::escape_id(port_cell)) == 0) + if (module->cell(RTLIL::escape_id(port_cell)) == nullptr) log_cmd_error("Can't find cell %s.\n", port_cell.c_str()); RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, port_expr)) log_cmd_error("Failed to parse port expression `%s'.\n", port_expr.c_str()); - module->cells_.at(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig)); + module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig)); } else log_cmd_error("Expected -set, -unset, or -port.\n"); diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index 5a15cbbaf..6ae7c9304 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -65,15 +65,13 @@ struct ConnwrappersWorker decls[key] = decl; } - void work(RTLIL::Design *design, RTLIL::Module *module) + void work(RTLIL::Module *module) { std::map<RTLIL::SigBit, std::pair<bool, RTLIL::SigSpec>> extend_map; SigMap sigmap(module); - for (auto &it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = it.second; - if (!decl_celltypes.count(cell->type)) continue; @@ -105,13 +103,8 @@ struct ConnwrappersWorker } } - for (auto &it : module->cells_) + for (auto cell : module->selected_cells()) { - RTLIL::Cell *cell = it.second; - - if (!design->selected(module, cell)) - continue; - for (auto &conn : cell->connections_) { std::vector<RTLIL::SigBit> sigbits = sigmap(conn.second).to_sigbit_vector(); @@ -141,8 +134,8 @@ struct ConnwrappersWorker } if (old_sig.size()) - log("Connected extended bits of %s.%s:%s: %s -> %s\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), - RTLIL::id2cstr(conn.first), log_signal(old_sig), log_signal(conn.second)); + log("Connected extended bits of %s.%s:%s: %s -> %s\n", log_id(module->name), log_id(cell->name), + log_id(conn.first), log_signal(old_sig), log_signal(conn.second)); } } } @@ -200,9 +193,8 @@ struct ConnwrappersPass : public Pass { log_header(design, "Executing CONNWRAPPERS pass (connect extended ports of wrapper cells).\n"); - for (auto &mod_it : design->modules_) - if (design->selected(mod_it.second)) - worker.work(design, mod_it.second); + for (auto module : design->selected_modules()) + worker.work(module); } } ConnwrappersPass; diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc index acd2dba52..99f1f69cf 100644 --- a/passes/cmds/copy.cc +++ b/passes/cmds/copy.cc @@ -44,10 +44,10 @@ struct CopyPass : public Pass { std::string src_name = RTLIL::escape_id(args[1]); std::string trg_name = RTLIL::escape_id(args[2]); - if (design->modules_.count(src_name) == 0) + if (design->module(src_name) == nullptr) log_cmd_error("Can't find source module %s.\n", src_name.c_str()); - if (design->modules_.count(trg_name) != 0) + if (design->module(trg_name) != nullptr) log_cmd_error("Target module name %s already exists.\n", trg_name.c_str()); RTLIL::Module *new_mod = design->module(src_name)->clone(); diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index 125bc96ca..b124e3b0f 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -65,27 +65,24 @@ struct DeletePass : public Pass { } extra_args(args, argidx, design); - std::vector<RTLIL::IdString> delete_mods; - - for (auto &mod_it : design->modules_) + std::vector<RTLIL::Module *> delete_mods; + for (auto module : design->modules()) { - if (design->selected_whole_module(mod_it.first) && !flag_input && !flag_output) { - delete_mods.push_back(mod_it.first); + if (design->selected_whole_module(module->name) && !flag_input && !flag_output) { + delete_mods.push_back(module); continue; } - if (!design->selected_module(mod_it.first)) + if (!design->selected_module(module->name)) continue; - RTLIL::Module *module = mod_it.second; - if (flag_input || flag_output) { - for (auto &it : module->wires_) - if (design->selected(module, it.second)) { + for (auto wire : module->wires()) + if (design->selected(module, wire)) { if (flag_input) - it.second->port_input = false; + wire->port_input = false; if (flag_output) - it.second->port_output = false; + wire->port_output = false; } module->fixup_ports(); continue; @@ -96,20 +93,19 @@ struct DeletePass : public Pass { pool<RTLIL::IdString> delete_procs; pool<RTLIL::IdString> delete_mems; - for (auto &it : module->wires_) - if (design->selected(module, it.second)) - delete_wires.insert(it.second); + for (auto wire : module->selected_wires()) + delete_wires.insert(wire); for (auto &it : module->memories) if (design->selected(module, it.second)) delete_mems.insert(it.first); - for (auto &it : module->cells_) { - if (design->selected(module, it.second)) - delete_cells.insert(it.second); - if (it.second->type.in(ID($memrd), ID($memwr)) && - delete_mems.count(it.second->parameters.at(ID::MEMID).decode_string()) != 0) - delete_cells.insert(it.second); + for (auto cell : module->cells()) { + if (design->selected(module, cell)) + delete_cells.insert(cell); + if (cell->type.in(ID($memrd), ID($memwr)) && + delete_mems.count(cell->parameters.at(ID::MEMID).decode_string()) != 0) + delete_cells.insert(cell); } for (auto &it : module->processes) @@ -134,9 +130,8 @@ struct DeletePass : public Pass { module->fixup_ports(); } - for (auto &it : delete_mods) { - delete design->modules_.at(it); - design->modules_.erase(it); + for (auto mod : delete_mods) { + design->remove(mod); } } } DeletePass; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 4fd43329f..4612760cc 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -60,6 +60,11 @@ struct DesignPass : public Pass { log("Push the current design to the stack and then clear the current design.\n"); log("\n"); log("\n"); + log(" design -push-copy\n"); + log("\n"); + log("Push the current design to the stack without clearing the current design.\n"); + log("\n"); + log("\n"); log(" design -pop\n"); log("\n"); log("Reset the current design and pop the last design from the stack.\n"); @@ -101,6 +106,7 @@ struct DesignPass : public Pass { bool reset_mode = false; bool reset_vlog_mode = false; bool push_mode = false; + bool push_copy_mode = false; bool pop_mode = false; bool import_mode = false; RTLIL::Design *copy_from_design = NULL, *copy_to_design = NULL; @@ -126,6 +132,11 @@ struct DesignPass : public Pass { push_mode = true; continue; } + if (!got_mode && args[argidx] == "-push-copy") { + got_mode = true; + push_copy_mode = true; + continue; + } if (!got_mode && args[argidx] == "-pop") { got_mode = true; pop_mode = true; @@ -307,7 +318,7 @@ struct DesignPass : public Pass { } } - if (!save_name.empty() || push_mode) + if (!save_name.empty() || push_mode || push_copy_mode) { RTLIL::Design *design_copy = new RTLIL::Design; @@ -321,7 +332,7 @@ struct DesignPass : public Pass { if (saved_designs.count(save_name)) delete saved_designs.at(save_name); - if (push_mode) + if (push_mode || push_copy_mode) pushed_designs.push_back(design_copy); else saved_designs[save_name] = design_copy; diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 08abb94cb..515f5a4ef 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -38,7 +38,7 @@ struct setunset_t value = RTLIL::Const(set_value.substr(1, GetSize(set_value)-2)); } else { RTLIL::SigSpec sig_value; - if (!RTLIL::SigSpec::parse(sig_value, NULL, set_value)) + if (!RTLIL::SigSpec::parse(sig_value, nullptr, set_value)) log_cmd_error("Can't decode value '%s'!\n", set_value.c_str()); value = sig_value.as_const(); } @@ -96,10 +96,8 @@ struct SetattrPass : public Pass { } extra_args(args, argidx, design); - for (auto &mod : design->modules_) + for (auto module : design->modules()) { - RTLIL::Module *module = mod.second; - if (flag_mod) { if (design->selected_whole_module(module->name)) do_setunset(module->attributes, setunset_list); @@ -109,17 +107,17 @@ struct SetattrPass : public Pass { if (!design->selected(module)) continue; - for (auto &it : module->wires_) - if (design->selected(module, it.second)) - do_setunset(it.second->attributes, setunset_list); + for (auto wire : module->wires()) + if (design->selected(module, wire)) + do_setunset(wire->attributes, setunset_list); for (auto &it : module->memories) if (design->selected(module, it.second)) do_setunset(it.second->attributes, setunset_list); - for (auto &it : module->cells_) - if (design->selected(module, it.second)) - do_setunset(it.second->attributes, setunset_list); + for (auto cell : module->cells()) + if (design->selected(module, cell)) + do_setunset(cell->attributes, setunset_list); for (auto &it : module->processes) if (design->selected(module, it.second)) @@ -208,19 +206,13 @@ struct SetparamPass : public Pass { } extra_args(args, argidx, design); - for (auto &mod : design->modules_) + for (auto module : design->selected_modules()) { - RTLIL::Module *module = mod.second; - - if (!design->selected(module)) - continue; - - for (auto &it : module->cells_) - if (design->selected(module, it.second)) { - if (!new_cell_type.empty()) - it.second->type = new_cell_type; - do_setunset(it.second->parameters, setunset_list); - } + for (auto cell : module->selected_cells()) { + if (!new_cell_type.empty()) + cell->type = new_cell_type; + do_setunset(cell->parameters, setunset_list); + } } } } SetparamPass; diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index c0e07b6e1..155ed0fcd 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -41,8 +41,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -using RTLIL::id2cstr; - #undef CLUSTER_CELLS_AND_PORTBOXES struct ShowWorker @@ -101,7 +99,7 @@ struct ShowWorker { sig.sort_and_unify(); for (auto &c : sig.chunks()) { - if (c.wire != NULL) + if (c.wire != nullptr) for (auto &s : color_selections) if (s.second.selected_members.count(module->name) > 0 && s.second.selected_members.at(module->name).count(c.wire->name) > 0) return stringf("color=\"%s\"", s.first.c_str()); @@ -218,7 +216,7 @@ struct ShowWorker if (sig.is_chunk()) { const RTLIL::SigChunk &c = sig.as_chunk(); - if (c.wire != NULL && design->selected_member(module->name, c.wire->name)) { + if (c.wire != nullptr && design->selected_member(module->name, c.wire->name)) { if (!range_check || c.wire->width == c.width) return stringf("n%d", id2num(c.wire->name)); } else { @@ -230,7 +228,7 @@ struct ShowWorker return std::string(); } - std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = NULL) + std::string gen_portbox(std::string port, RTLIL::SigSpec sig, bool driver, std::string *node = nullptr) { std::string code; std::string net = gen_signode_simple(sig); @@ -287,7 +285,7 @@ struct ShowWorker else code += stringf("x%d:e -> %s:w [arrowhead=odiamond, arrowtail=odiamond, dir=both, %s, %s];\n", idx, port.c_str(), nextColor(sig).c_str(), widthLabel(sig.size()).c_str()); } - if (node != NULL) + if (node != nullptr) *node = stringf("x%d", idx); } else @@ -300,7 +298,7 @@ struct ShowWorker net_conn_map[net].bits = sig.size(); net_conn_map[net].color = nextColor(sig, net_conn_map[net].color); } - if (node != NULL) + if (node != nullptr) *node = net; } return code; @@ -366,22 +364,20 @@ struct ShowWorker std::set<std::string> all_sources, all_sinks; std::map<std::string, std::string> wires_on_demand; - for (auto &it : module->wires_) { - if (!design->selected_member(module->name, it.first)) - continue; + for (auto wire : module->selected_wires()) { const char *shape = "diamond"; - if (it.second->port_input || it.second->port_output) + if (wire->port_input || wire->port_output) shape = "octagon"; - if (it.first[0] == '\\') { + if (wire->name[0] == '\\') { fprintf(f, "n%d [ shape=%s, label=\"%s\", %s, fontcolor=\"black\" ];\n", - id2num(it.first), shape, findLabel(it.first.str()), - nextColor(RTLIL::SigSpec(it.second), "color=\"black\"").c_str()); - if (it.second->port_input) - all_sources.insert(stringf("n%d", id2num(it.first))); - else if (it.second->port_output) - all_sinks.insert(stringf("n%d", id2num(it.first))); + id2num(wire->name), shape, findLabel(wire->name.str()), + nextColor(RTLIL::SigSpec(wire), "color=\"black\"").c_str()); + if (wire->port_input) + all_sources.insert(stringf("n%d", id2num(wire->name))); + else if (wire->port_output) + all_sinks.insert(stringf("n%d", id2num(wire->name))); } else { - wires_on_demand[stringf("n%d", id2num(it.first))] = it.first.str(); + wires_on_demand[stringf("n%d", id2num(wire->name))] = wire->name.str(); } } @@ -398,15 +394,12 @@ struct ShowWorker fprintf(f, "}\n"); } - for (auto &it : module->cells_) + for (auto cell : module->selected_cells()) { - if (!design->selected_member(module->name, it.first)) - continue; - std::vector<RTLIL::IdString> in_ports, out_ports; - for (auto &conn : it.second->connections()) { - if (!ct.cell_output(it.second->type, conn.first)) + for (auto &conn : cell->connections()) { + if (!ct.cell_output(cell->type, conn.first)) in_ports.push_back(conn.first); else out_ports.push_back(conn.first); @@ -419,12 +412,12 @@ struct ShowWorker for (auto &p : in_ports) label_string += stringf("<p%d> %s%s|", id2num(p), escape(p.str()), - genSignedLabels && it.second->hasParam(p.str() + "_SIGNED") && - it.second->getParam(p.str() + "_SIGNED").as_bool() ? "*" : ""); + genSignedLabels && cell->hasParam(p.str() + "_SIGNED") && + cell->getParam(p.str() + "_SIGNED").as_bool() ? "*" : ""); if (label_string[label_string.size()-1] == '|') label_string = label_string.substr(0, label_string.size()-1); - label_string += stringf("}|%s\\n%s|{", findLabel(it.first.str()), escape(it.second->type.str())); + label_string += stringf("}|%s\\n%s|{", findLabel(cell->name.str()), escape(cell->type.str())); for (auto &p : out_ports) label_string += stringf("<p%d> %s|", id2num(p), escape(p.str())); @@ -434,19 +427,19 @@ struct ShowWorker label_string += "}}"; std::string code; - for (auto &conn : it.second->connections()) { - code += gen_portbox(stringf("c%d:p%d", id2num(it.first), id2num(conn.first)), - conn.second, ct.cell_output(it.second->type, conn.first)); + for (auto &conn : cell->connections()) { + code += gen_portbox(stringf("c%d:p%d", id2num(cell->name), id2num(conn.first)), + conn.second, ct.cell_output(cell->type, conn.first)); } #ifdef CLUSTER_CELLS_AND_PORTBOXES if (!code.empty()) fprintf(f, "subgraph cluster_c%d {\nc%d [ shape=record, label=\"%s\"%s ];\n%s}\n", - id2num(it.first), id2num(it.first), label_string.c_str(), findColor(it.first), code.c_str()); + id2num(cell->name), id2num(cell->name), label_string.c_str(), findColor(cell->name), code.c_str()); else #endif fprintf(f, "c%d [ shape=record, label=\"%s\"%s ];\n%s", - id2num(it.first), label_string.c_str(), findColor(it.first.str()), code.c_str()); + id2num(cell->name), label_string.c_str(), findColor(cell->name.str()), code.c_str()); } for (auto &it : module->processes) @@ -491,12 +484,12 @@ struct ShowWorker { bool found_lhs_wire = false; for (auto &c : conn.first.chunks()) { - if (c.wire == NULL || design->selected_member(module->name, c.wire->name)) + if (c.wire == nullptr || design->selected_member(module->name, c.wire->name)) found_lhs_wire = true; } bool found_rhs_wire = false; for (auto &c : conn.second.chunks()) { - if (c.wire == NULL || design->selected_member(module->name, c.wire->name)) + if (c.wire == nullptr || design->selected_member(module->name, c.wire->name)) found_rhs_wire = true; } if (!found_lhs_wire || !found_rhs_wire) @@ -572,23 +565,21 @@ struct ShowWorker design->optimize(); page_counter = 0; - for (auto &mod_it : design->modules_) + for (auto mod : design->selected_modules()) { - module = mod_it.second; - if (!design->selected_module(module->name)) - continue; + module = mod; if (design->selected_whole_module(module->name)) { if (module->get_blackbox_attribute()) { - // log("Skipping blackbox module %s.\n", id2cstr(module->name)); + // log("Skipping blackbox module %s.\n", log_id(module->name)); continue; } else - if (module->cells_.empty() && module->connections().empty() && module->processes.empty()) { - log("Skipping empty module %s.\n", id2cstr(module->name)); + if (module->cells().size() == 0 && module->connections().empty() && module->processes.empty()) { + log("Skipping empty module %s.\n", log_id(module->name)); continue; } else - log("Dumping module %s to page %d.\n", id2cstr(module->name), ++page_counter); + log("Dumping module %s to page %d.\n", log_id(module->name), ++page_counter); } else - log("Dumping selected parts of module %s to page %d.\n", id2cstr(module->name), ++page_counter); + log("Dumping selected parts of module %s to page %d.\n", log_id(module->name), ++page_counter); handle_module(); } } @@ -802,13 +793,12 @@ struct ShowPass : public Pass { if (format != "ps" && format != "dot") { int modcount = 0; - for (auto &mod_it : design->modules_) { - if (mod_it.second->get_blackbox_attribute()) + for (auto module : design->selected_modules()) { + if (module->get_blackbox_attribute()) continue; - if (mod_it.second->cells_.empty() && mod_it.second->connections().empty()) + if (module->cells().size() == 0 && module->connections().empty()) continue; - if (design->selected_module(mod_it.first)) - modcount++; + modcount++; } if (modcount > 1) log_cmd_error("For formats different than 'ps' or 'dot' only one module must be selected.\n"); @@ -835,7 +825,7 @@ struct ShowPass : public Pass { FILE *f = fopen(dot_file.c_str(), "w"); if (custom_prefix) yosys_output_files.insert(dot_file); - if (f == NULL) { + if (f == nullptr) { for (auto lib : libs) delete lib; log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str()); @@ -889,8 +879,8 @@ struct ShowPass : public Pass { if (flag_pause) { #ifdef YOSYS_ENABLE_READLINE - char *input = NULL; - while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != NULL) { + char *input = nullptr; + while ((input = readline("Press ENTER to continue (or type 'shell' to open a shell)> ")) != nullptr) { if (input[strspn(input, " \t\r\n")] == 0) break; char *p = input + strspn(input, " \t\r\n"); diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc index f99090279..ea9e06979 100644 --- a/passes/cmds/splice.cc +++ b/passes/cmds/splice.cc @@ -102,7 +102,7 @@ struct SpliceWorker for (auto &bit : sig.to_sigbit_vector()) { - if (bit.wire == NULL) + if (bit.wire == nullptr) { if (last_bit == 0) chunks.back().append(bit); @@ -149,23 +149,23 @@ struct SpliceWorker void run() { - log("Splicing signals in module %s:\n", RTLIL::id2cstr(module->name)); + log("Splicing signals in module %s:\n", log_id(module->name)); driven_bits.push_back(RTLIL::State::Sm); driven_bits.push_back(RTLIL::State::Sm); - for (auto &it : module->wires_) - if (it.second->port_input) { - RTLIL::SigSpec sig = sigmap(it.second); + for (auto wire : module->wires()) + if (wire->port_input) { + RTLIL::SigSpec sig = sigmap(wire); driven_chunks.insert(sig); for (auto &bit : sig.to_sigbit_vector()) driven_bits.push_back(bit); driven_bits.push_back(RTLIL::State::Sm); } - for (auto &it : module->cells_) - for (auto &conn : it.second->connections()) - if (!ct.cell_known(it.second->type) || ct.cell_output(it.second->type, conn.first)) { + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) { RTLIL::SigSpec sig = sigmap(conn.second); driven_chunks.insert(sig); for (auto &bit : sig.to_sigbit_vector()) @@ -180,9 +180,8 @@ struct SpliceWorker SigPool selected_bits; if (!sel_by_cell) - for (auto &it : module->wires_) - if (design->selected(module, it.second)) - selected_bits.add(sigmap(it.second)); + for (auto wire : module->selected_wires()) + selected_bits.add(sigmap(wire)); std::vector<Cell*> mod_cells = module->cells(); @@ -343,17 +342,14 @@ struct SplicePass : public Pass { log_header(design, "Executing SPLICE pass (creating cells for signal splicing).\n"); - for (auto &mod_it : design->modules_) + for (auto module : design->selected_modules()) { - if (!design->selected(mod_it.second)) - continue; - - if (mod_it.second->processes.size()) { - log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str()); + if (module->processes.size()) { + log("Skipping module %s as it contains processes.\n", module->name.c_str()); continue; } - SpliceWorker worker(design, mod_it.second); + SpliceWorker worker(design, module); worker.sel_by_cell = sel_by_cell; worker.sel_by_wire = sel_by_wire; worker.sel_any_bit = sel_any_bit; diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 758a59661..6c4bc0e5b 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -79,18 +79,15 @@ struct statdata_t STAT_NUMERIC_MEMBERS #undef X - for (auto &it : mod->wires_) + for (auto wire : mod->selected_wires()) { - if (!design->selected(mod, it.second)) - continue; - - if (it.first[0] == '\\') { + if (wire->name[0] == '\\') { num_pub_wires++; - num_pub_wire_bits += it.second->width; + num_pub_wire_bits += wire->width; } num_wires++; - num_wire_bits += it.second->width; + num_wire_bits += wire->width; } for (auto &it : mod->memories) { @@ -100,12 +97,9 @@ struct statdata_t num_memory_bits += it.second->width * it.second->size; } - for (auto &it : mod->cells_) + for (auto cell : mod->selected_cells()) { - if (!design->selected(mod, it.second)) - continue; - - RTLIL::IdString cell_type = it.second->type; + RTLIL::IdString cell_type = cell->type; if (width_mode) { @@ -116,15 +110,15 @@ struct statdata_t ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow), ID($alu))) { - int width_a = it.second->hasPort(ID::A) ? GetSize(it.second->getPort(ID::A)) : 0; - int width_b = it.second->hasPort(ID::B) ? GetSize(it.second->getPort(ID::B)) : 0; - int width_y = it.second->hasPort(ID::Y) ? GetSize(it.second->getPort(ID::Y)) : 0; + int width_a = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : 0; + int width_b = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : 0; + int width_y = cell->hasPort(ID::Y) ? GetSize(cell->getPort(ID::Y)) : 0; cell_type = stringf("%s_%d", cell_type.c_str(), max<int>({width_a, width_b, width_y})); } else if (cell_type.in(ID($mux), ID($pmux))) - cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort(ID::Y))); + cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y))); else if (cell_type.in(ID($sr), ID($dff), ID($dffsr), ID($adff), ID($dlatch), ID($dlatchsr))) - cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(it.second->getPort(ID::Q))); + cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q))); } if (!cell_area.empty()) { @@ -157,7 +151,7 @@ struct statdata_t log(" Number of cells: %6d\n", num_cells); for (auto &it : num_cells_by_type) if (it.second) - log(" %-26s %6d\n", RTLIL::id2cstr(it.first), it.second); + log(" %-26s %6d\n", log_id(it.first), it.second); if (!unknown_cell_area.empty()) { log("\n"); @@ -255,7 +249,7 @@ statdata_t hierarchy_worker(std::map<RTLIL::IdString, statdata_t> &mod_stat, RTL for (auto &it : num_cells_by_type) if (mod_stat.count(it.first) > 0) { - log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, RTLIL::id2cstr(it.first), it.second); + log(" %*s%-*s %6d\n", 2*level, "", 26-2*level, log_id(it.first), it.second); mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1) * it.second; mod_data.num_cells -= it.second; } else { @@ -281,7 +275,7 @@ void read_liberty_cellarea(dict<IdString, double> &cell_area, string liberty_fil continue; LibertyAst *ar = cell->find("area"); - if (ar != NULL && !ar->value.empty()) + if (ar != nullptr && !ar->value.empty()) cell_area["\\" + cell->args[0]] = atof(ar->value.c_str()); } } @@ -319,7 +313,7 @@ struct StatPass : public Pass { log_header(design, "Printing statistics.\n"); bool width_mode = false; - RTLIL::Module *top_mod = NULL; + RTLIL::Module *top_mod = nullptr; std::map<RTLIL::IdString, statdata_t> mod_stat; dict<IdString, double> cell_area; string techname; @@ -342,9 +336,9 @@ struct StatPass : public Pass { continue; } if (args[argidx] == "-top" && argidx+1 < args.size()) { - if (design->modules_.count(RTLIL::escape_id(args[argidx+1])) == 0) + if (design->module(RTLIL::escape_id(args[argidx+1])) == nullptr) log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str()); - top_mod = design->modules_.at(RTLIL::escape_id(args[++argidx])); + top_mod = design->module(RTLIL::escape_id(args[++argidx])); continue; } break; @@ -364,18 +358,18 @@ struct StatPass : public Pass { mod_stat[mod->name] = data; log("\n"); - log("=== %s%s ===\n", RTLIL::id2cstr(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); + log("=== %s%s ===\n", log_id(mod->name), design->selected_whole_module(mod->name) ? "" : " (partially selected)"); log("\n"); data.log_data(mod->name, false); } - if (top_mod != NULL && GetSize(mod_stat) > 1) + if (top_mod != nullptr && GetSize(mod_stat) > 1) { log("\n"); log("=== design hierarchy ===\n"); log("\n"); - log(" %-28s %6d\n", RTLIL::id2cstr(top_mod->name), 1); + log(" %-28s %6d\n", log_id(top_mod->name), 1); statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0); log("\n"); diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index f5701acee..2db7cf26b 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -51,7 +51,7 @@ struct SubmodWorker RTLIL::Wire *new_wire; RTLIL::Const is_int_driven; bool is_int_used, is_ext_driven, is_ext_used; - wire_flags_t(RTLIL::Wire* wire) : new_wire(NULL), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } + wire_flags_t(RTLIL::Wire* wire) : new_wire(nullptr), is_int_driven(State::S0, GetSize(wire)), is_int_used(false), is_ext_driven(false), is_ext_used(false) { } }; std::map<RTLIL::Wire*, wire_flags_t> wire_flags; bool flag_found_something; @@ -75,7 +75,7 @@ struct SubmodWorker void flag_signal(const RTLIL::SigSpec &sig, bool create, bool set_int_driven, bool set_int_used, bool set_ext_driven, bool set_ext_used) { for (auto &c : sig.chunks()) - if (c.wire != NULL) { + if (c.wire != nullptr) { flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); if (set_int_driven) for (int i = c.offset; i < c.offset+c.width; i++) { @@ -100,8 +100,7 @@ struct SubmodWorker flag_signal(conn.second, true, true, true, false, false); } } - for (auto &it : module->cells_) { - RTLIL::Cell *cell = it.second; + for (auto cell : module->cells()) { if (submod.cells.count(cell) > 0) continue; if (ct.cell_known(cell->type)) { @@ -211,7 +210,7 @@ struct SubmodWorker RTLIL::Cell *new_cell = new_mod->addCell(cell->name, cell); for (auto &conn : new_cell->connections_) for (auto &bit : conn.second) - if (bit.wire != NULL) { + if (bit.wire != nullptr) { log_assert(wire_flags.count(bit.wire) > 0); bit.wire = wire_flags.at(bit.wire).new_wire; } @@ -274,12 +273,11 @@ struct SubmodWorker if (opt_name.empty()) { - for (auto &it : module->wires_) - it.second->attributes.erase(ID::submod); + for (auto wire : module->wires()) + wire->attributes.erase(ID::submod); - for (auto &it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = it.second; if (cell->attributes.count(ID::submod) == 0 || cell->attributes[ID::submod].bits.size() == 0) { cell->attributes.erase(ID::submod); continue; @@ -291,7 +289,7 @@ struct SubmodWorker if (submodules.count(submod_str) == 0) { submodules[submod_str].name = submod_str; submodules[submod_str].full_name = module->name.str() + "_" + submod_str; - while (design->modules_.count(submodules[submod_str].full_name) != 0 || + while (design->module(submodules[submod_str].full_name) != nullptr || module->count_id(submodules[submod_str].full_name) != 0) submodules[submod_str].full_name += "_"; } @@ -301,9 +299,8 @@ struct SubmodWorker } else { - for (auto &it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = it.second; if (!design->selected(module, cell)) continue; submodules[opt_name].name = opt_name; @@ -392,12 +389,12 @@ struct SubmodPass : public Pass { while (did_something) { did_something = false; std::vector<RTLIL::IdString> queued_modules; - for (auto &mod_it : design->modules_) - if (handled_modules.count(mod_it.first) == 0 && design->selected_whole_module(mod_it.first)) - queued_modules.push_back(mod_it.first); + for (auto mod : design->modules()) + if (handled_modules.count(mod->name) == 0 && design->selected_whole_module(mod->name)) + queued_modules.push_back(mod->name); for (auto &modname : queued_modules) - if (design->modules_.count(modname) != 0) { - SubmodWorker worker(design, design->modules_[modname], copy_mode, hidden_mode); + if (design->module(modname) != nullptr) { + SubmodWorker worker(design, design->module(modname), copy_mode, hidden_mode); handled_modules.insert(modname); did_something = true; } @@ -407,15 +404,13 @@ struct SubmodPass : public Pass { } else { - RTLIL::Module *module = NULL; - for (auto &mod_it : design->modules_) { - if (!design->selected_module(mod_it.first)) - continue; - if (module != NULL) - log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod_it.first.c_str()); - module = mod_it.second; + RTLIL::Module *module = nullptr; + for (auto mod : design->selected_modules()) { + if (module != nullptr) + log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod->name.c_str()); + module = mod; } - if (module == NULL) + if (module == nullptr) log("Nothing selected -> do nothing.\n"); else { Pass::call_on_module(design, module, "opt_clean"); diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index b15109cd3..aa344cf8a 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -78,7 +78,7 @@ static void logmap_all() static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, bool &pin_pol) { - if (cell == NULL || attr == NULL || attr->value.empty()) + if (cell == nullptr || attr == nullptr || attr->value.empty()) return false; std::string value = attr->value; @@ -117,7 +117,7 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name, static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode) { - LibertyAst *best_cell = NULL; + LibertyAst *best_cell = nullptr; std::map<std::string, char> best_cell_ports; int best_cell_pins = 0; bool best_cell_noninv = false; @@ -132,11 +132,11 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has continue; LibertyAst *dn = cell->find("dont_use"); - if (dn != NULL && dn->value == "true") + if (dn != nullptr && dn->value == "true") continue; LibertyAst *ff = cell->find("ff"); - if (ff == NULL) + if (ff == nullptr) continue; std::string cell_clk_pin, cell_rst_pin, cell_next_pin; @@ -163,7 +163,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has double area = 0; LibertyAst *ar = cell->find("area"); - if (ar != NULL && !ar->value.empty()) + if (ar != nullptr && !ar->value.empty()) area = atof(ar->value.c_str()); int num_pins = 0; @@ -175,7 +175,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has continue; LibertyAst *dir = pin->find("direction"); - if (dir == NULL || dir->value == "internal") + if (dir == nullptr || dir->value == "internal") continue; num_pins++; @@ -183,7 +183,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has goto continue_cell_loop; LibertyAst *func = pin->find("function"); - if (dir->value == "output" && func != NULL) { + if (dir->value == "output" && func != nullptr) { std::string value = func->value; for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) value.erase(pos, 1); @@ -205,10 +205,10 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has this_cell_ports[pin->args[0]] = 0; } - if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) + if (!found_output || (best_cell != nullptr && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) continue; - if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area) + if (best_cell != nullptr && num_pins == best_cell_pins && area > best_cell_area) continue; best_cell = cell; @@ -219,7 +219,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has continue_cell_loop:; } - if (best_cell != NULL) { + if (best_cell != nullptr) { log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str()); if (prepare_mode) { @@ -238,7 +238,7 @@ static void find_cell(LibertyAst *ast, IdString cell_type, bool clkpol, bool has static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode) { - LibertyAst *best_cell = NULL; + LibertyAst *best_cell = nullptr; std::map<std::string, char> best_cell_ports; int best_cell_pins = 0; bool best_cell_noninv = false; @@ -253,11 +253,11 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool continue; LibertyAst *dn = cell->find("dont_use"); - if (dn != NULL && dn->value == "true") + if (dn != nullptr && dn->value == "true") continue; LibertyAst *ff = cell->find("ff"); - if (ff == NULL) + if (ff == nullptr) continue; std::string cell_clk_pin, cell_set_pin, cell_clr_pin, cell_next_pin; @@ -280,7 +280,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool double area = 0; LibertyAst *ar = cell->find("area"); - if (ar != NULL && !ar->value.empty()) + if (ar != nullptr && !ar->value.empty()) area = atof(ar->value.c_str()); int num_pins = 0; @@ -292,7 +292,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool continue; LibertyAst *dir = pin->find("direction"); - if (dir == NULL || dir->value == "internal") + if (dir == nullptr || dir->value == "internal") continue; num_pins++; @@ -300,7 +300,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool goto continue_cell_loop; LibertyAst *func = pin->find("function"); - if (dir->value == "output" && func != NULL) { + if (dir->value == "output" && func != nullptr) { std::string value = func->value; for (size_t pos = value.find_first_of("\" \t"); pos != std::string::npos; pos = value.find_first_of("\" \t")) value.erase(pos, 1); @@ -322,10 +322,10 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool this_cell_ports[pin->args[0]] = 0; } - if (!found_output || (best_cell != NULL && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) + if (!found_output || (best_cell != nullptr && (num_pins > best_cell_pins || (best_cell_noninv && !found_noninv_output)))) continue; - if (best_cell != NULL && num_pins == best_cell_pins && area > best_cell_area) + if (best_cell != nullptr && num_pins == best_cell_pins && area > best_cell_area) continue; best_cell = cell; @@ -336,7 +336,7 @@ static void find_cell_sr(LibertyAst *ast, IdString cell_type, bool clkpol, bool continue_cell_loop:; } - if (best_cell != NULL) { + if (best_cell != nullptr) { log(" cell %s (%sinv, pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_noninv ? "non" : "", best_cell_pins, best_cell_area, cell_type.c_str()); if (prepare_mode) { @@ -481,11 +481,11 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare SigMap sigmap(module); std::vector<RTLIL::Cell*> cell_list; - for (auto &it : module->cells_) { - if (design->selected(module, it.second) && cell_mappings.count(it.second->type) > 0) - cell_list.push_back(it.second); - if (it.second->type == ID($_NOT_)) - notmap[sigmap(it.second->getPort(ID::A))].insert(it.second); + for (auto cell : module->cells()) { + if (design->selected(module, cell) && cell_mappings.count(cell->type) > 0) + cell_list.push_back(cell); + if (cell->type == ID($_NOT_)) + notmap[sigmap(cell->getPort(ID::A))].insert(cell); } std::map<std::string, int> stats; @@ -663,9 +663,9 @@ struct DfflibmapPass : public Pass { log(" final dff cell mappings:\n"); logmap_all(); - for (auto &it : design->modules_) - if (design->selected(it.second) && !it.second->get_blackbox_attribute()) - dfflibmap(design, it.second, prepare_mode); + for (auto module : design->selected_modules()) + if (!module->get_blackbox_attribute()) + dfflibmap(design, module, prepare_mode); cell_mappings.clear(); } diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index aea958f0f..f29044790 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -29,8 +29,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -using RTLIL::id2cstr; - class SubCircuitSolver : public SubCircuit::Solver { public: @@ -121,8 +119,8 @@ public: if (wire_attr.size() > 0) { - RTLIL::Wire *lastNeedleWire = NULL; - RTLIL::Wire *lastHaystackWire = NULL; + RTLIL::Wire *lastNeedleWire = nullptr; + RTLIL::Wire *lastHaystackWire = nullptr; dict<RTLIL::IdString, RTLIL::Const> emptyAttr; for (auto &conn : needleCell->connections()) @@ -149,27 +147,27 @@ struct bit_ref_t { int bit; }; -bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL, - int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL) +bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = nullptr, + int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = nullptr) { SigMap sigmap(mod); std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref; if (sel && !sel->selected(mod)) { - log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name)); + log(" Skipping module %s as it is not selected.\n", log_id(mod->name)); return false; } if (mod->processes.size() > 0) { - log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name)); + log(" Skipping module %s as it contains unprocessed processes.\n", log_id(mod->name)); return false; } if (constports) { - graph.createNode("$const$0", "$const$0", NULL, true); - graph.createNode("$const$1", "$const$1", NULL, true); - graph.createNode("$const$x", "$const$x", NULL, true); - graph.createNode("$const$z", "$const$z", NULL, true); + graph.createNode("$const$0", "$const$0", nullptr, true); + graph.createNode("$const$1", "$const$1", nullptr, true); + graph.createNode("$const$x", "$const$x", nullptr, true); + graph.createNode("$const$z", "$const$z", nullptr, true); graph.createPort("$const$0", "\\Y", 1); graph.createPort("$const$1", "\\Y", 1); graph.createPort("$const$x", "\\Y", 1); @@ -182,28 +180,26 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count; if (max_fanout > 0) - for (auto &cell_it : mod->cells_) + for (auto cell : mod->cells()) { - RTLIL::Cell *cell = cell_it.second; if (!sel || sel->selected(mod, cell)) for (auto &conn : cell->connections()) { RTLIL::SigSpec conn_sig = conn.second; sigmap.apply(conn_sig); for (auto &bit : conn_sig) - if (bit.wire != NULL) + if (bit.wire != nullptr) sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++; } } // create graph nodes from cells - for (auto &cell_it : mod->cells_) + for (auto cell : mod->cells()) { - RTLIL::Cell *cell = cell_it.second; if (sel && !sel->selected(mod, cell)) continue; std::string type = cell->type.str(); - if (sel == NULL && type.compare(0, 2, "\\$") == 0) + if (sel == nullptr && type.compare(0, 2, "\\$") == 0) type = type.substr(1); graph.createNode(cell->name.str(), type, (void*)cell); @@ -221,7 +217,7 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, { auto &bit = conn_sig[i]; - if (bit.wire == NULL) { + if (bit.wire == nullptr) { if (constports) { std::string node = "$const$x"; if (bit == RTLIL::State::S0) node = "$const$0"; @@ -253,9 +249,8 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, } // mark external signals (used in non-selected cells) - for (auto &cell_it : mod->cells_) + for (auto cell : mod->cells()) { - RTLIL::Cell *cell = cell_it.second; if (sel && !sel->selected(mod, cell)) for (auto &conn : cell->connections()) { @@ -271,9 +266,8 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, } // mark external signals (used in module ports) - for (auto &wire_it : mod->wires_) + for (auto wire : mod->wires()) { - RTLIL::Wire *wire = wire_it.second; if (wire->port_id > 0) { RTLIL::SigSpec conn_sig(wire); @@ -300,8 +294,7 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit: RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name); // create cell ports - for (auto &it : needle->wires_) { - RTLIL::Wire *wire = it.second; + for (auto wire : needle->wires()) { if (wire->port_id > 0) { for (int i = 0; i < wire->width; i++) sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i)); @@ -316,7 +309,7 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit: RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData; RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData; - if (needle_cell == NULL) + if (needle_cell == nullptr) continue; for (auto &conn : needle_cell->connections()) { @@ -587,7 +580,7 @@ struct ExtractPass : public Pass { if (map_filenames.empty() && mine_outfile.empty()) log_cmd_error("Missing option -map <verilog_or_ilang_file> or -mine <output_ilang_file>.\n"); - RTLIL::Design *map = NULL; + RTLIL::Design *map = nullptr; if (!mine_mode) { @@ -630,24 +623,24 @@ struct ExtractPass : public Pass { log_header(design, "Creating graphs for SubCircuit library.\n"); if (!mine_mode) - for (auto &mod_it : map->modules_) { + for (auto module : map->modules()) { SubCircuit::Graph mod_graph; - std::string graph_name = "needle_" + RTLIL::unescape_id(mod_it.first); + std::string graph_name = "needle_" + RTLIL::unescape_id(module->name); log("Creating needle graph %s.\n", graph_name.c_str()); - if (module2graph(mod_graph, mod_it.second, constports)) { + if (module2graph(mod_graph, module, constports)) { solver.addGraph(graph_name, mod_graph); - needle_map[graph_name] = mod_it.second; - needle_list.push_back(mod_it.second); + needle_map[graph_name] = module; + needle_list.push_back(module); } } - for (auto &mod_it : design->modules_) { + for (auto module : design->modules()) { SubCircuit::Graph mod_graph; - std::string graph_name = "haystack_" + RTLIL::unescape_id(mod_it.first); + std::string graph_name = "haystack_" + RTLIL::unescape_id(module->name); log("Creating haystack graph %s.\n", graph_name.c_str()); - if (module2graph(mod_graph, mod_it.second, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : NULL)) { + if (module2graph(mod_graph, module, constports, design, mine_mode ? mine_max_fanout : -1, mine_mode ? &mine_split : nullptr)) { solver.addGraph(graph_name, mod_graph); - haystack_map[graph_name] = mod_it.second; + haystack_map[graph_name] = module; } } @@ -680,7 +673,7 @@ struct ExtractPass : public Pass { } RTLIL::Cell *new_cell = replace(needle_map.at(result.needleGraphId), haystack_map.at(result.haystackGraphId), result); design->select(haystack_map.at(result.haystackGraphId), new_cell); - log(" new cell: %s\n", id2cstr(new_cell->name)); + log(" new cell: %s\n", log_id(new_cell->name)); } } } @@ -697,12 +690,12 @@ struct ExtractPass : public Pass { for (auto &result: results) { log("\nFrequent SubCircuit with %d nodes and %d matches:\n", int(result.nodes.size()), result.totalMatchesAfterLimits); - log(" primary match in %s:", id2cstr(haystack_map.at(result.graphId)->name)); + log(" primary match in %s:", log_id(haystack_map.at(result.graphId)->name)); for (auto &node : result.nodes) log(" %s", RTLIL::unescape_id(node.nodeId).c_str()); log("\n"); for (auto &it : result.matchesPerGraph) - log(" matches in %s: %d\n", id2cstr(haystack_map.at(it.first)->name), it.second); + log(" matches in %s: %d\n", log_id(haystack_map.at(it.first)->name), it.second); RTLIL::Module *mod = haystack_map.at(result.graphId); std::set<RTLIL::Cell*> cells; @@ -717,12 +710,12 @@ struct ExtractPass : public Pass { for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); for (auto &chunk : sig.chunks()) - if (chunk.wire != NULL) + if (chunk.wire != nullptr) wires.insert(chunk.wire); } RTLIL::Module *newMod = new RTLIL::Module; - newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, id2cstr(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits); + newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, log_id(haystack_map.at(result.graphId)->name), result.totalMatchesAfterLimits); map->add(newMod); for (auto wire : wires) { @@ -739,8 +732,8 @@ struct ExtractPass : public Pass { for (auto &conn : cell->connections()) { std::vector<SigChunk> chunks = sigmap(conn.second); for (auto &chunk : chunks) - if (chunk.wire != NULL) - chunk.wire = newMod->wires_.at(chunk.wire->name); + if (chunk.wire != nullptr) + chunk.wire = newMod->wire(chunk.wire->name); newCell->setPort(conn.first, chunks); } } diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 1f071bd69..42e8a61ea 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -85,7 +85,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s f << stringf("reg [31:0] xorshift128_x = 123456789;\n"); f << stringf("reg [31:0] xorshift128_y = 362436069;\n"); f << stringf("reg [31:0] xorshift128_z = 521288629;\n"); - f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(NULL))); + f << stringf("reg [31:0] xorshift128_w = %u; // <-- seed value\n", seed ? seed : int(time(nullptr))); f << stringf("reg [31:0] xorshift128_t;\n\n"); f << stringf("task xorshift128;\n"); f << stringf("begin\n"); @@ -97,22 +97,19 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s f << stringf("end\n"); f << stringf("endtask\n\n"); - for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) + for (auto mod : design->modules()) { std::map<std::string, int> signal_in; std::map<std::string, std::string> signal_const; std::map<std::string, int> signal_clk; std::map<std::string, int> signal_out; - RTLIL::Module *mod = it->second; - if (mod->get_bool_attribute(ID::gentb_skip)) continue; int count_ports = 0; - log("Generating test bench for module `%s'.\n", it->first.c_str()); - for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { - RTLIL::Wire *wire = it2->second; + log("Generating test bench for module `%s'.\n", mod->name.c_str()); + for (auto wire : mod->wires()) { if (wire->port_output) { count_ports++; signal_out[idy("sig", mod->name.str(), wire->name.str())] = wire->width; @@ -140,8 +137,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s } } f << stringf("%s %s(\n", id(mod->name.str()).c_str(), idy("uut", mod->name.str()).c_str()); - for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { - RTLIL::Wire *wire = it2->second; + for (auto wire : mod->wires()) { if (wire->port_output || wire->port_input) f << stringf("\t.%s(%s)%s\n", id(wire->name.str()).c_str(), idy("sig", mod->name.str(), wire->name.str()).c_str(), --count_ports ? "," : ""); @@ -312,9 +308,9 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter, int s f << stringf("\t// $dumpfile(\"testbench.vcd\");\n"); f << stringf("\t// $dumpvars(0, testbench);\n"); f << stringf("\tfile = $fopen(`outfile);\n"); - for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) - if (!it->second->get_bool_attribute(ID::gentb_skip)) - f << stringf("\t%s;\n", idy(it->first.str(), "test").c_str()); + for (auto module : design->modules()) + if (!module->get_bool_attribute(ID::gentb_skip)) + f << stringf("\t%s;\n", idy(module->name.str(), "test").c_str()); f << stringf("\t$fclose(file);\n"); f << stringf("\t$finish;\n"); f << stringf("end\n\n"); diff --git a/techlibs/common/Makefile.inc b/techlibs/common/Makefile.inc index d5e69a241..7b1e4b430 100644 --- a/techlibs/common/Makefile.inc +++ b/techlibs/common/Makefile.inc @@ -30,3 +30,4 @@ $(eval $(call add_share_file,share,techlibs/common/cmp2lut.v)) $(eval $(call add_share_file,share,techlibs/common/cells.lib)) $(eval $(call add_share_file,share,techlibs/common/mul2dsp.v)) $(eval $(call add_share_file,share,techlibs/common/abc9_model.v)) +$(eval $(call add_share_file,share,techlibs/common/cmp2lcu.v)) diff --git a/techlibs/common/cmp2lcu.v b/techlibs/common/cmp2lcu.v new file mode 100644 index 000000000..b6f4aeed6 --- /dev/null +++ b/techlibs/common/cmp2lcu.v @@ -0,0 +1,116 @@ +// This pass performs an optimisation that decomposes wide arithmetic +// comparisons into LUT-size chunks (as guided by the `LUT_WIDTH +// macro) connected to a single lookahead-carry-unit $lcu cell, +// which is typically mapped to dedicated (and fast) FPGA +// carry-chains. +(* techmap_celltype = "$lt $le $gt $ge" *) +module _80_lcu_cmp_ (A, B, Y); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 0; +parameter B_WIDTH = 0; +parameter Y_WIDTH = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +output [Y_WIDTH-1:0] Y; + +parameter _TECHMAP_CELLTYPE_ = ""; + +generate + if (_TECHMAP_CELLTYPE_ == "" || `LUT_WIDTH < 2) + wire _TECHMAP_FAIL_ = 1; + else if (_TECHMAP_CELLTYPE_ == "$lt") begin + // Transform $lt into $gt by swapping A and B + $gt #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); + end + else if (_TECHMAP_CELLTYPE_ == "$le") begin + // Transform $le into $ge by swapping A and B + $ge #(.A_SIGNED(B_SIGNED), .B_SIGNED(A_SIGNED), .A_WIDTH(B_WIDTH), .B_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(B), .B(A), .Y(Y)); + end + else begin + // Perform sign extension on A and B + localparam WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH; + wire [WIDTH-1:0] AA = {{(WIDTH-A_WIDTH){A_SIGNED ? A[A_WIDTH-1] : 1'b0}}, A}; + wire [WIDTH-1:0] BB = {{(WIDTH-B_WIDTH){B_SIGNED ? B[B_WIDTH-1] : 1'b0}}, B}; + // For $ge operation, start with the assumption that A and B are + // equal (propagating this equality if A and B turn out to be so) + if (_TECHMAP_CELLTYPE_ == "$ge") + localparam CI = 1'b1; + else + localparam CI = 1'b0; + $__CMP2LCU #(.AB_WIDTH(WIDTH), .AB_SIGNED(A_SIGNED && B_SIGNED), .LCU_WIDTH(1), .BUDGET(`LUT_WIDTH), .CI(CI)) + _TECHMAP_REPLACE_ (.A(AA), .B(BB), .P(1'b1), .G(1'b0), .Y(Y)); + end +endgenerate +endmodule + +module $__CMP2LCU (A, B, P, G, Y); + +parameter AB_WIDTH = 0; +parameter AB_SIGNED = 0; +parameter LCU_WIDTH = 1; +parameter BUDGET = 0; +parameter CI = 0; + +input [AB_WIDTH-1:0] A; // A from original $gt/$ge +input [AB_WIDTH-1:0] B; // B from original $gt/$ge +input [LCU_WIDTH-1:0] P; // P of $lcu +input [LCU_WIDTH-1:0] G; // G of $lcu +output Y; + +parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0; +parameter [AB_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0; +parameter [LCU_WIDTH-1:0] _TECHMAP_CONSTMSK_P_ = 0; + +generate + if (AB_WIDTH == 0) begin + wire [LCU_WIDTH-1:0] CO; + $lcu #(.WIDTH(LCU_WIDTH)) _TECHMAP_REPLACE_ (.P(P), .G(G), .CI(CI), .CO(CO)); + assign Y = CO[LCU_WIDTH-1]; + end + else begin + if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] && _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]) + localparam COST = 0; + else if (_TECHMAP_CONSTMSK_A_[AB_WIDTH-1:0] || _TECHMAP_CONSTMSK_B_[AB_WIDTH-1:0]) + localparam COST = 1; + else + localparam COST = 2; + + if (BUDGET < COST) + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH), .AB_SIGNED(AB_SIGNED), .LCU_WIDTH(LCU_WIDTH+1), .BUDGET(`LUT_WIDTH), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A), .B(B), .P({P, 1'b1}), .G({G, 1'b0}), .Y(Y)); + else begin + wire PP, GG; + // Bit-wise equality (xnor) of A and B + assign PP = A[AB_WIDTH-1] ^~ B[AB_WIDTH-1]; + if (AB_SIGNED) + assign GG = ~A[AB_WIDTH-1] & B[AB_WIDTH-1]; + else if (_TECHMAP_CONSTMSK_P_[LCU_WIDTH-1]) // First compare for LUT if P (and G) is constant + assign GG = A[AB_WIDTH-1] & ~B[AB_WIDTH-1]; + else + // Priority "encoder" that checks A[i] == 1'b1 && B[i] == 1'b0 + // from MSB down, deferring to less significant bits if the + // MSBs are equal + assign GG = P[0] & (A[AB_WIDTH-1] & ~B[AB_WIDTH-1]); + if (LCU_WIDTH == 1) begin + // Propagate only if all pairs are equal + // (inconclusive evidence to say A >= B) + wire P_ = P[0] & PP; + // Generate if any comparisons call for it + wire G_ = G[0] | GG; + end + else begin + // Propagate only if all pairs are equal + // (inconclusive evidence to say A >= B) + wire [LCU_WIDTH-1:0] P_ = {P[LCU_WIDTH-1:1], P[0] & PP}; + // Generate if any comparisons call for it + wire [LCU_WIDTH-1:0] G_ = {G[LCU_WIDTH-1:1], G[0] | GG}; + end + $__CMP2LCU #(.AB_WIDTH(AB_WIDTH-1), .AB_SIGNED(1'b0), .LCU_WIDTH(LCU_WIDTH), .BUDGET(BUDGET-COST), .CI(CI)) + _TECHMAP_REPLACE_ (.A(A[AB_WIDTH-2:0]), .B(B[AB_WIDTH-2:0]), .P(P_), .G(G_), .Y(Y)); + end + end +endgenerate +endmodule diff --git a/techlibs/common/cmp2lut.v b/techlibs/common/cmp2lut.v index 1c8192b85..8ecd356cc 100644 --- a/techlibs/common/cmp2lut.v +++ b/techlibs/common/cmp2lut.v @@ -57,10 +57,6 @@ function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut; o_bit = (lhs > rhs); if (operation == 3) o_bit = (lhs >= rhs); - if (operation == 4) - o_bit = (lhs == rhs); - if (operation == 5) - o_bit = (lhs != rhs); gen_lut = gen_lut | (o_bit << n); end end @@ -75,10 +71,6 @@ generate localparam operation = 2; if (_TECHMAP_CELLTYPE_ == "$ge") localparam operation = 3; - if (_TECHMAP_CELLTYPE_ == "$eq") - localparam operation = 4; - if (_TECHMAP_CELLTYPE_ == "$ne") - localparam operation = 5; if (A_WIDTH > `LUT_WIDTH || B_WIDTH > `LUT_WIDTH || Y_WIDTH != 1) wire _TECHMAP_FAIL_ = 1; diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index e7a192c07..d6dffdd7f 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -225,9 +225,9 @@ struct SynthPass : public ScriptPass run("peepopt"); run("opt_clean"); if (help_mode) - run("techmap -map +/cmp2lut.v", " (if -lut)"); - else - run(stringf("techmap -map +/cmp2lut.v -D LUT_WIDTH=%d", lut)); + run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v", " (if -lut)"); + else if (lut) + run(stringf("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=%d", lut)); if (!noalumacc) run("alumacc", " (unless -noalumacc)"); if (!noshare) diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 8553efd6b..ac4f5bcf4 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -393,8 +393,6 @@ struct SynthXilinxPass : public ScriptPass run("pmux2shiftx", "(skip if '-nosrl' and '-widemux=0')"); run("clean", " (skip if '-nosrl' and '-widemux=0')"); } - - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=" + lut_size_s); } if (check_label("map_dsp", "(skip if '-nodsp')")) { @@ -460,6 +458,7 @@ struct SynthXilinxPass : public ScriptPass } if (check_label("coarse")) { + run("techmap -map +/cmp2lut.v -map +/cmp2lcu.v -D LUT_WIDTH=" + lut_size_s); run("alumacc"); run("share"); run("opt"); diff --git a/tests/techmap/cmp2lcu.ys b/tests/techmap/cmp2lcu.ys new file mode 100644 index 000000000..7c8a63692 --- /dev/null +++ b/tests/techmap/cmp2lcu.ys @@ -0,0 +1,52 @@ +read_verilog <<EOT +module top(input [12:0] a, b, output gtu, gts, ltu, lts, geu, ges, leu, les); +assign gtu = a > b; +assign gts = $signed(a) > $signed(b); +assign ltu = a < b; +assign lts = $signed(a) < $signed(b); +assign geu = a >= b; +assign ges = $signed(a) >= $signed(b); +assign leu = a <= b; +assign les = $signed(a) <= $signed(b); +endmodule +EOT + +equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=6 +design -load postopt +select -assert-count 8 t:$lcu r:WIDTH=5 %i +select -assert-none t:$gt t:$ge t:$lt t:$le + +design -load preopt +equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=4 +design -load postopt +select -assert-count 8 t:$lcu r:WIDTH=7 %i +select -assert-none t:$gt t:$ge t:$lt t:$le + + +design -reset +read_verilog <<EOT +module top(input [8:0] a, b, output gtu, gts, ltu, lts, geu, ges, leu, les); +wire [13:0] c = {a[8:6], 3'b101, a[5:4], 2'b11, a[3:0]}; +wire [13:0] d = {b[8], 3'b101, b[7:4], 2'b01, b[3:0]}; +assign gtu = c > d; +assign gts = $signed(c) > $signed(d); +assign ltu = c < d; +assign lts = $signed(c) < $signed(d); +assign geu = c >= d; +assign ges = $signed(c) >= $signed(d); +assign leu = c <= d; +assign les = $signed(c) <= $signed(d); +endmodule +EOT +design -save gold + +equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=5 +design -load postopt +select -assert-count 8 t:$lcu r:WIDTH=2 %i +select -assert-none t:$gt t:$ge t:$lt t:$le + +design -load preopt +equiv_opt -assert techmap -map +/cmp2lcu.v -D LUT_WIDTH=3 +design -load postopt +select -assert-count 8 t:$lcu r:WIDTH=4 %i +select -assert-none t:$gt t:$ge t:$lt t:$le |