diff options
-rw-r--r-- | backends/blif/blif.cc | 26 | ||||
-rw-r--r-- | backends/edif/edif.cc | 41 | ||||
-rw-r--r-- | backends/ilang/ilang_backend.cc | 12 | ||||
-rw-r--r-- | backends/intersynth/intersynth.cc | 41 | ||||
-rw-r--r-- | backends/smt2/smt2.cc | 4 | ||||
-rw-r--r-- | backends/spice/spice.cc | 22 | ||||
-rw-r--r-- | backends/verilog/verilog_backend.cc | 41 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 2 | ||||
-rw-r--r-- | kernel/yosys.cc | 27 | ||||
-rw-r--r-- | passes/opt/opt_merge.cc | 234 | ||||
-rw-r--r-- | tests/opt/opt_merge_init.ys | 28 | ||||
-rw-r--r-- | tests/opt/opt_merge_keep.ys | 64 | ||||
-rw-r--r-- | tests/simple/dynslice.v | 12 |
13 files changed, 304 insertions, 250 deletions
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index b6e38c16c..4bdaf7a7f 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -138,9 +138,9 @@ struct BlifDumper { if (!config->gates_mode) return "subckt"; - if (!design->modules_.count(RTLIL::escape_id(cell_type))) + if (design->module(RTLIL::escape_id(cell_type)) == nullptr) return "gate"; - if (design->modules_.at(RTLIL::escape_id(cell_type))->get_blackbox_attribute()) + if (design->module(RTLIL::escape_id(cell_type))->get_blackbox_attribute()) return "gate"; return "subckt"; } @@ -148,7 +148,7 @@ struct BlifDumper void dump_params(const char *command, dict<IdString, Const> ¶ms) { for (auto ¶m : params) { - f << stringf("%s %s ", command, RTLIL::id2cstr(param.first)); + f << stringf("%s %s ", command, log_id(param.first)); if (param.second.flags & RTLIL::CONST_FLAG_STRING) { std::string str = param.second.decode_string(); f << stringf("\""); @@ -172,8 +172,7 @@ struct BlifDumper std::map<int, RTLIL::Wire*> inputs, outputs; - for (auto &wire_it : module->wires_) { - RTLIL::Wire *wire = wire_it.second; + for (auto wire : module->wires()) { if (wire->port_input) inputs[wire->port_id] = wire; if (wire->port_output) @@ -229,10 +228,8 @@ struct BlifDumper f << stringf(".names $undef\n"); } - for (auto &cell_it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = cell_it.second; - if (config->unbuf_types.count(cell->type)) { auto portnames = config->unbuf_types.at(cell->type); f << stringf(".names %s %s\n1 1\n", @@ -649,25 +646,24 @@ struct BlifBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules_) - if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first.str(); + for (auto module : design->modules()) + if (module->get_bool_attribute("\\top")) + top_module_name = module->name.str(); *f << stringf("# Generated by %s\n", yosys_version_str); std::vector<RTLIL::Module*> mod_list; design->sort(); - for (auto module_it : design->modules_) + for (auto module : design->modules()) { - RTLIL::Module *module = module_it.second; if (module->get_blackbox_attribute() && !config.blackbox_mode) continue; if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in BLIF backend!\n", log_id(module->name)); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in BLIF backend!\n", log_id(module->name)); if (module->name == RTLIL::escape_id(top_module_name)) { BlifDumper::dump(*f, module, design, config); diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 199560ad0..cb1b4c284 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -171,13 +171,12 @@ struct EdifBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules_) - if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first.str(); + for (auto module : design->modules()) + if (module->get_bool_attribute("\\top")) + top_module_name = module->name.str(); - for (auto module_it : design->modules_) + for (auto module : design->modules()) { - RTLIL::Module *module = module_it.second; if (module->get_blackbox_attribute()) continue; @@ -185,14 +184,13 @@ struct EdifBackend : public Backend { top_module_name = module->name.str(); if (module->processes.size() != 0) - log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); + log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", log_id(module->name)); if (module->memories.size() != 0) - log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); + log_error("Found unmapped memories in module %s: unmapped memories are not supported in EDIF backend!\n", log_id(module->name)); - for (auto cell_it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = cell_it.second; - if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_blackbox_attribute()) { + if (design->module(cell->type) == nullptr || design->module(cell->type)->get_blackbox_attribute()) { lib_cell_ports[cell->type]; for (auto p : cell->connections()) lib_cell_ports[cell->type][p.first] = GetSize(p.second); @@ -277,11 +275,11 @@ struct EdifBackend : public Backend { // extract module dependencies std::map<RTLIL::Module*, std::set<RTLIL::Module*>> module_deps; - for (auto &mod_it : design->modules_) { - module_deps[mod_it.second] = std::set<RTLIL::Module*>(); - for (auto &cell_it : mod_it.second->cells_) - if (design->modules_.count(cell_it.second->type) > 0) - module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type)); + for (auto module : design->modules()) { + module_deps[module] = std::set<RTLIL::Module*>(); + for (auto cell : module->cells()) + if (design->module(cell->type) != nullptr) + module_deps[module].insert(design->module(cell->type)); } // simple good-enough topological sort @@ -292,12 +290,12 @@ struct EdifBackend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", RTLIL::id2cstr(it.first->name)); + // log("Next in topological sort: %s\n", log_id(it.first->name)); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", RTLIL::id2cstr(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } @@ -339,8 +337,7 @@ struct EdifBackend : public Backend { *f << stringf(" (view VIEW_NETLIST\n"); *f << stringf(" (viewType NETLIST)\n"); *f << stringf(" (interface\n"); - for (auto &wire_it : module->wires_) { - RTLIL::Wire *wire = wire_it.second; + for (auto wire : module->wires()) { if (wire->port_id == 0) continue; const char *dir = "INOUT"; @@ -378,8 +375,7 @@ struct EdifBackend : public Backend { *f << stringf(" (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n"); *f << stringf(" (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n"); } - for (auto &cell_it : module->cells_) { - RTLIL::Cell *cell = cell_it.second; + for (auto cell : module->cells()) { *f << stringf(" (instance %s\n", EDIF_DEF(cell->name)); *f << stringf(" (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); @@ -459,8 +455,7 @@ struct EdifBackend : public Backend { add_prop(p.first, p.second); *f << stringf("\n )\n"); } - for (auto &wire_it : module->wires_) { - RTLIL::Wire *wire = wire_it.second; + for (auto wire : module->wires()) { if (!wire->get_bool_attribute(ID::keep)) continue; for(int i = 0; i < wire->width; i++) { diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index e06786220..5445fad90 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -358,10 +358,10 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl if (!flag_m) { int count_selected_mods = 0; - for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { - if (design->selected_whole_module(it->first)) + for (auto module : design->modules()) { + if (design->selected_whole_module(module->name)) flag_m = true; - if (design->selected(it->second)) + if (design->selected(module)) count_selected_mods++; } if (count_selected_mods > 1) @@ -374,11 +374,11 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl f << stringf("autoidx %d\n", autoidx); } - for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { - if (!only_selected || design->selected(it->second)) { + for (auto module : design->modules()) { + if (!only_selected || design->selected(module)) { if (only_selected) f << stringf("\n"); - dump_module(f, "", it->second, design, only_selected, flag_m, flag_n); + dump_module(f, "", module, design, only_selected, flag_m, flag_n); } } diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc index 809a0fa09..31dce1cca 100644 --- a/backends/intersynth/intersynth.cc +++ b/backends/intersynth/intersynth.cc @@ -122,70 +122,67 @@ struct IntersynthBackend : public Backend { for (auto lib : libs) ct.setup_design(lib); - for (auto module_it : design->modules_) + for (auto module : design->modules()) { - RTLIL::Module *module = module_it.second; SigMap sigmap(module); if (module->get_blackbox_attribute()) continue; - if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0) + if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells().size() == 0) continue; if (selected && !design->selected_whole_module(module->name)) { if (design->selected_module(module->name)) - log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(module->name)); + log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); continue; } - log("Generating netlist %s.\n", RTLIL::id2cstr(module->name)); + log("Generating netlist %s.\n", log_id(module->name)); if (module->memories.size() != 0 || module->processes.size() != 0) log_error("Can't generate a netlist for a module with unprocessed memories or processes!\n"); std::set<std::string> constcells_code; - netlists_code += stringf("# Netlist of module %s\n", RTLIL::id2cstr(module->name)); - netlists_code += stringf("netlist %s\n", RTLIL::id2cstr(module->name)); + netlists_code += stringf("# Netlist of module %s\n", log_id(module->name)); + netlists_code += stringf("netlist %s\n", log_id(module->name)); // Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports - for (auto wire_it : module->wires_) { - RTLIL::Wire *wire = wire_it.second; + for (auto wire : module->wires()) { if (wire->port_input || wire->port_output) { celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n", - RTLIL::id2cstr(wire->name), wire->width, wire->port_input ? "*" : "", - wire->port_input ? "input" : "output", RTLIL::id2cstr(wire->name), wire->width, RTLIL::id2cstr(wire->name))); - netlists_code += stringf("node %s %s PORT %s\n", RTLIL::id2cstr(wire->name), RTLIL::id2cstr(wire->name), + log_id(wire->name), wire->width, wire->port_input ? "*" : "", + wire->port_input ? "input" : "output", log_id(wire->name), wire->width, log_id(wire->name))); + netlists_code += stringf("node %s %s PORT %s\n", log_id(wire->name), log_id(wire->name), netname(conntypes_code, celltypes_code, constcells_code, sigmap(wire)).c_str()); } } // Submodules: "std::set<string> celltypes_code" prevents duplicate cell types - for (auto cell_it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = cell_it.second; std::string celltype_code, node_code; if (!ct.cell_known(cell->type)) - log_error("Found unknown cell type %s in module!\n", RTLIL::id2cstr(cell->type)); + log_error("Found unknown cell type %s in module!\n", log_id(cell->type)); - celltype_code = stringf("celltype %s", RTLIL::id2cstr(cell->type)); - node_code = stringf("node %s %s", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); + celltype_code = stringf("celltype %s", log_id(cell->type)); + node_code = stringf("node %s %s", log_id(cell->name), log_id(cell->type)); for (auto &port : cell->connections()) { RTLIL::SigSpec sig = sigmap(port.second); if (sig.size() != 0) { conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); - celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first)); - node_code += stringf(" %s %s", RTLIL::id2cstr(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str()); + celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", log_id(port.first)); + node_code += stringf(" %s %s", log_id(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str()); } } for (auto ¶m : cell->parameters) { - celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), RTLIL::id2cstr(param.first)); + celltype_code += stringf(" cfg:%d %s", int(param.second.bits.size()), log_id(param.first)); if (param.second.bits.size() != 32) { - node_code += stringf(" %s '", RTLIL::id2cstr(param.first)); + node_code += stringf(" %s '", log_id(param.first)); for (int i = param.second.bits.size()-1; i >= 0; i--) node_code += param.second.bits[i] == State::S1 ? "1" : "0"; } else - node_code += stringf(" %s 0x%x", RTLIL::id2cstr(param.first), param.second.as_int()); + node_code += stringf(" %s 0x%x", log_id(param.first), param.second.as_int()); } celltypes_code.insert(celltype_code + "\n"); diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 628765831..eb4826051 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1523,12 +1523,12 @@ struct Smt2Backend : public Backend { for (auto &dep : it.second) if (module_deps.count(dep) > 0) goto not_ready_yet; - // log("Next in topological sort: %s\n", RTLIL::id2cstr(it.first->name)); + // log("Next in topological sort: %s\n", log_id(it.first->name)); sorted_modules.push_back(it.first); not_ready_yet:; } if (sorted_modules_idx == sorted_modules.size()) - log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", RTLIL::id2cstr(module_deps.begin()->first->name)); + log_error("Cyclic dependency between modules found! Cycle includes module %s.\n", log_id(module_deps.begin()->first->name)); while (sorted_modules_idx < sorted_modules.size()) module_deps.erase(sorted_modules.at(sorted_modules_idx++)); } diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 6738a4bbd..9b603a8c5 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -70,14 +70,13 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De idict<IdString, 1> inums; int cell_counter = 0, conn_counter = 0, nc_counter = 0; - for (auto &cell_it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = cell_it.second; f << stringf("X%d", cell_counter++); std::vector<RTLIL::SigSpec> port_sigs; - if (design->modules_.count(cell->type) == 0) + if (design->module(cell->type) == nullptr) { log_warning("no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", log_id(cell->type), log_id(module), log_id(cell)); @@ -88,11 +87,10 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De } else { - RTLIL::Module *mod = design->modules_.at(cell->type); + RTLIL::Module *mod = design->module(cell->type); std::vector<RTLIL::Wire*> ports; - for (auto wire_it : mod->wires_) { - RTLIL::Wire *wire = wire_it.second; + for (auto wire : mod->wires()) { if (wire->port_id == 0) continue; while (int(ports.size()) < wire->port_id) @@ -202,16 +200,15 @@ struct SpiceBackend : public Backend { extra_args(f, filename, args, argidx); if (top_module_name.empty()) - for (auto & mod_it:design->modules_) - if (mod_it.second->get_bool_attribute("\\top")) - top_module_name = mod_it.first.str(); + for (auto module : design->modules()) + if (module->get_bool_attribute("\\top")) + top_module_name = module->name.str(); *f << stringf("* SPICE netlist generated by %s\n", yosys_version_str); *f << stringf("\n"); - for (auto module_it : design->modules_) + for (auto module : design->modules()) { - RTLIL::Module *module = module_it.second; if (module->get_blackbox_attribute()) continue; @@ -226,8 +223,7 @@ struct SpiceBackend : public Backend { } std::vector<RTLIL::Wire*> ports; - for (auto wire_it : module->wires_) { - RTLIL::Wire *wire = wire_it.second; + for (auto wire : module->wires()) { if (wire->port_id == 0) continue; while (int(ports.size()) < wire->port_id) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 19541f1c4..e0fd201e1 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -73,12 +73,12 @@ void reset_auto_counter(RTLIL::Module *module) reset_auto_counter_id(module->name, false); - for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) - reset_auto_counter_id(it->second->name, true); + for (auto w : module->wires()) + reset_auto_counter_id(w->name, true); - for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { - reset_auto_counter_id(it->second->name, true); - reset_auto_counter_id(it->second->type, false); + for (auto cell : module->cells()) { + reset_auto_counter_id(cell->name, true); + reset_auto_counter_id(cell->type, false); } for (auto it = module->processes.begin(); it != module->processes.end(); ++it) @@ -1719,9 +1719,8 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) if (!noexpr) { std::set<std::pair<RTLIL::Wire*,int>> reg_bits; - for (auto &it : module->cells_) + for (auto cell : module->cells()) { - RTLIL::Cell *cell = it.second; if (!reg_ct.count(cell->type) || !cell->hasPort("\\Q")) continue; @@ -1734,9 +1733,8 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) reg_bits.insert(std::pair<RTLIL::Wire*,int>(chunk.wire, chunk.offset+i)); } } - for (auto &it : module->wires_) + for (auto wire : module->wires()) { - RTLIL::Wire *wire = it.second; for (int i = 0; i < wire->width; i++) if (reg_bits.count(std::pair<RTLIL::Wire*,int>(wire, i)) == 0) goto this_wire_aint_reg; @@ -1751,8 +1749,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { keep_running = false; - for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) { - RTLIL::Wire *wire = it->second; + for (auto wire : module->wires()) { if (wire->port_id == port_id) { if (port_id != 1) f << stringf(", "); @@ -1764,14 +1761,14 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } f << stringf(");\n"); - for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) - dump_wire(f, indent + " ", it->second); + for (auto w : module->wires()) + dump_wire(f, indent + " ", w); for (auto it = module->memories.begin(); it != module->memories.end(); ++it) dump_memory(f, indent + " ", it->second); - for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) - dump_cell(f, indent + " ", it->second); + for (auto cell : module->cells()) + dump_cell(f, indent + " ", cell); for (auto it = module->processes.begin(); it != module->processes.end(); ++it) dump_process(f, indent + " ", it->second); @@ -1995,16 +1992,16 @@ struct VerilogBackend : public Backend { design->sort(); *f << stringf("/* Generated by %s */\n", yosys_version_str); - for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { - if (it->second->get_blackbox_attribute() != blackboxes) + for (auto module : design->modules()) { + if (module->get_blackbox_attribute() != blackboxes) continue; - if (selected && !design->selected_whole_module(it->first)) { - if (design->selected_module(it->first)) - log_cmd_error("Can't handle partially selected module %s!\n", RTLIL::id2cstr(it->first)); + if (selected && !design->selected_whole_module(module->name)) { + if (design->selected_module(module->name)) + log_cmd_error("Can't handle partially selected module %s!\n", log_id(module->name)); continue; } - log("Dumping module `%s'.\n", it->first.c_str()); - dump_module(*f, "", it->second); + log("Dumping module `%s'.\n", module->name.c_str()); + dump_module(*f, "", module); } auto_name_map.clear(); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 10e9f2683..f801a17e0 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1727,7 +1727,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, } did_something = true; newNode = new AstNode(AST_CASE, shift_expr); - for (int i = 0; i <= source_width-result_width; i++) { + for (int i = 0; i < source_width; i++) { int start_bit = children[0]->id2ast->range_right + i; AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); AstNode *lvalue = children[0]->clone(); diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 4cb53f05d..6d64e2e90 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -1098,30 +1098,29 @@ static char *readline_obj_generator(const char *text, int state) if (design->selected_active_module.empty()) { - for (auto &it : design->modules_) - if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); + for (auto mod : design->modules()) + if (RTLIL::unescape_id(mod->name).compare(0, len, text) == 0) + obj_names.push_back(strdup(log_id(mod->name))); } - else - if (design->modules_.count(design->selected_active_module) > 0) + else if (design->module(design->selected_active_module) != nullptr) { - RTLIL::Module *module = design->modules_.at(design->selected_active_module); + RTLIL::Module *module = design->module(design->selected_active_module); - for (auto &it : module->wires_) - if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); + for (auto w : module->wires()) + if (RTLIL::unescape_id(w->name).compare(0, len, text) == 0) + obj_names.push_back(strdup(log_id(w->name))); for (auto &it : module->memories) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); + obj_names.push_back(strdup(log_id(it.first))); - for (auto &it : module->cells_) - if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); + for (auto cell : module->cells()) + if (RTLIL::unescape_id(cell->name).compare(0, len, text) == 0) + obj_names.push_back(strdup(log_id(cell->name))); for (auto &it : module->processes) if (RTLIL::unescape_id(it.first).compare(0, len, text) == 0) - obj_names.push_back(strdup(RTLIL::id2cstr(it.first))); + obj_names.push_back(strdup(log_id(it.first))); } std::sort(obj_names.begin(), obj_names.end()); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 8823a9061..4aa78ff39 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -26,7 +26,6 @@ #include <stdio.h> #include <set> -#define USE_CELL_HASH_CACHE USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -41,9 +40,7 @@ struct OptMergeWorker CellTypes ct; int total_count; -#ifdef USE_CELL_HASH_CACHE - dict<const RTLIL::Cell*, std::string> cell_hash_cache; -#endif + SHA1 checksum; static void sort_pmux_conn(dict<RTLIL::IdString, RTLIL::SigSpec> &conn) { @@ -68,7 +65,6 @@ struct OptMergeWorker } } -#ifdef USE_CELL_HASH_CACHE std::string int_to_hash_string(unsigned int v) { if (v == 0) @@ -83,14 +79,9 @@ struct OptMergeWorker std::string hash_cell_parameters_and_connections(const RTLIL::Cell *cell) { - if (cell_hash_cache.count(cell) > 0) - return cell_hash_cache[cell]; - + vector<string> hash_conn_strings; std::string hash_string = cell->type.str() + "\n"; - for (auto &it : cell->parameters) - hash_string += "P " + it.first.str() + "=" + it.second.as_string() + "\n"; - const dict<RTLIL::IdString, RTLIL::SigSpec> *conn = &cell->connections(); dict<RTLIL::IdString, RTLIL::SigSpec> alt_conn; @@ -124,13 +115,22 @@ struct OptMergeWorker conn = &alt_conn; } - vector<string> hash_conn_strings; - for (auto &it : *conn) { - if (cell->output(it.first)) - continue; - RTLIL::SigSpec sig = it.second; - assign_map.apply(sig); + RTLIL::SigSpec sig; + if (cell->output(it.first)) { + if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || + cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") || + cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) { + // For the 'Q' output of state elements, + // use its (* init *) attribute value + for (const auto &b : dff_init_map(it.second)) + sig.append(b.wire ? State::Sx : b); + } + else + continue; + } + else + sig = assign_map(it.second); string s = "C " + it.first.str() + "="; for (auto &chunk : sig.chunks()) { if (chunk.wire) @@ -143,50 +143,59 @@ struct OptMergeWorker hash_conn_strings.push_back(s + "\n"); } + for (auto &it : cell->parameters) + hash_conn_strings.push_back("P " + it.first.str() + "=" + it.second.as_string() + "\n"); + std::sort(hash_conn_strings.begin(), hash_conn_strings.end()); for (auto it : hash_conn_strings) hash_string += it; - cell_hash_cache[cell] = sha1(hash_string); - return cell_hash_cache[cell]; + checksum.update(hash_string); + return checksum.final(); } -#endif - bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2, bool <) + bool compare_cell_parameters_and_connections(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) { -#ifdef USE_CELL_HASH_CACHE - std::string hash1 = hash_cell_parameters_and_connections(cell1); - std::string hash2 = hash_cell_parameters_and_connections(cell2); - - if (hash1 != hash2) { - lt = hash1 < hash2; - return true; - } -#endif - - if (cell1->parameters != cell2->parameters) { - std::map<RTLIL::IdString, RTLIL::Const> p1(cell1->parameters.begin(), cell1->parameters.end()); - std::map<RTLIL::IdString, RTLIL::Const> p2(cell2->parameters.begin(), cell2->parameters.end()); - lt = p1 < p2; - return true; - } - - dict<RTLIL::IdString, RTLIL::SigSpec> conn1 = cell1->connections(); - dict<RTLIL::IdString, RTLIL::SigSpec> conn2 = cell2->connections(); - - for (auto &it : conn1) { - if (cell1->output(it.first)) - it.second = RTLIL::SigSpec(); - else - assign_map.apply(it.second); - } - - for (auto &it : conn2) { - if (cell2->output(it.first)) - it.second = RTLIL::SigSpec(); - else - assign_map.apply(it.second); + log_assert(cell1 != cell2); + if (cell1->type != cell2->type) return false; + + if (cell1->parameters != cell2->parameters) + return false; + + if (cell1->connections_.size() != cell2->connections_.size()) + return false; + for (const auto &it : cell1->connections_) + if (!cell2->connections_.count(it.first)) + return false; + + decltype(Cell::connections_) conn1, conn2; + conn1.reserve(cell1->connections_.size()); + conn2.reserve(cell1->connections_.size()); + + for (const auto &it : cell1->connections_) { + if (cell1->output(it.first)) { + if (it.first == ID(Q) && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || + cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") || + cell1->type.in("$adff", "$sr", "$ff", "$_FF_"))) { + // For the 'Q' output of state elements, + // use the (* init *) attribute value + auto &sig1 = conn1[it.first]; + for (const auto &b : dff_init_map(it.second)) + sig1.append(b.wire ? State::Sx : b); + auto &sig2 = conn2[it.first]; + for (const auto &b : dff_init_map(cell2->getPort(it.first))) + sig2.append(b.wire ? State::Sx : b); + } + else { + conn1[it.first] = RTLIL::SigSpec(); + conn2[it.first] = RTLIL::SigSpec(); + } + } + else { + conn1[it.first] = assign_map(it.second); + conn2[it.first] = assign_map(cell2->getPort(it.first)); + } } if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) || @@ -215,54 +224,9 @@ struct OptMergeWorker sort_pmux_conn(conn2); } - if (conn1 != conn2) { - std::map<RTLIL::IdString, RTLIL::SigSpec> c1(conn1.begin(), conn1.end()); - std::map<RTLIL::IdString, RTLIL::SigSpec> c2(conn2.begin(), conn2.end()); - lt = c1 < c2; - return true; - } - - if (conn1.count(ID(Q)) != 0 && (cell1->type.begins_with("$dff") || cell1->type.begins_with("$dlatch") || - cell1->type.begins_with("$_DFF") || cell1->type.begins_with("$_DLATCH") || cell1->type.begins_with("$_SR_") || - cell1->type.in("$adff", "$sr", "$ff", "$_FF_"))) { - std::vector<RTLIL::SigBit> q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector(); - std::vector<RTLIL::SigBit> q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector(); - for (size_t i = 0; i < q1.size(); i++) - if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) { - lt = q1.at(i) < q2.at(i); - return true; - } - } - - return false; + return conn1 == conn2; } - bool compare_cells(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) - { - if (cell1->type != cell2->type) - return cell1->type < cell2->type; - - if ((!mode_share_all && !ct.cell_known(cell1->type)) || !cell1->known()) - return cell1 < cell2; - - if (cell1->has_keep_attr() || cell2->has_keep_attr()) - return cell1 < cell2; - - bool lt; - if (compare_cell_parameters_and_connections(cell1, cell2, lt)) - return lt; - - return false; - } - - struct CompareCells { - OptMergeWorker *that; - CompareCells(OptMergeWorker *that) : that(that) {} - bool operator()(const RTLIL::Cell *cell1, const RTLIL::Cell *cell2) const { - return that->compare_cells(cell1, cell2); - } - }; - OptMergeWorker(RTLIL::Design *design, RTLIL::Module *module, bool mode_nomux, bool mode_share_all) : design(design), module(module), assign_map(module), mode_share_all(mode_share_all) { @@ -299,9 +263,6 @@ struct OptMergeWorker bool did_something = true; while (did_something) { -#ifdef USE_CELL_HASH_CACHE - cell_hash_cache.clear(); -#endif std::vector<RTLIL::Cell*> cells; cells.reserve(module->cells_.size()); for (auto &it : module->cells_) { @@ -312,42 +273,51 @@ struct OptMergeWorker } did_something = false; - std::map<RTLIL::Cell*, RTLIL::Cell*, CompareCells> sharemap(CompareCells(this)); + dict<std::string, RTLIL::Cell*> sharemap; for (auto cell : cells) { - if (sharemap.count(cell) > 0) { - did_something = true; - log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str()); - for (auto &it : cell->connections()) { - if (cell->output(it.first)) { - RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first); - log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), - log_signal(it.second), log_signal(other_sig)); - module->connect(RTLIL::SigSig(it.second, other_sig)); - assign_map.add(it.second, other_sig); - - if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || - cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") || - cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) { - for (auto c : it.second.chunks()) { - auto jt = c.wire->attributes.find(ID(init)); - if (jt == c.wire->attributes.end()) - continue; - for (int i = c.offset; i < c.offset + c.width; i++) - jt->second[i] = State::Sx; + if ((!mode_share_all && !ct.cell_known(cell->type)) || !cell->known()) + continue; + + auto hash = hash_cell_parameters_and_connections(cell); + auto r = sharemap.insert(std::make_pair(hash, cell)); + if (!r.second) { + if (compare_cell_parameters_and_connections(cell, r.first->second)) { + if (cell->has_keep_attr()) { + if (r.first->second->has_keep_attr()) + continue; + std::swap(r.first->second, cell); + } + + + did_something = true; + log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), r.first->second->name.c_str()); + for (auto &it : cell->connections()) { + if (cell->output(it.first)) { + RTLIL::SigSpec other_sig = r.first->second->getPort(it.first); + log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), + log_signal(it.second), log_signal(other_sig)); + module->connect(RTLIL::SigSig(it.second, other_sig)); + assign_map.add(it.second, other_sig); + + if (it.first == ID(Q) && (cell->type.begins_with("$dff") || cell->type.begins_with("$dlatch") || + cell->type.begins_with("$_DFF") || cell->type.begins_with("$_DLATCH") || cell->type.begins_with("$_SR_") || + cell->type.in("$adff", "$sr", "$ff", "$_FF_"))) { + for (auto c : it.second.chunks()) { + auto jt = c.wire->attributes.find(ID(init)); + if (jt == c.wire->attributes.end()) + continue; + for (int i = c.offset; i < c.offset + c.width; i++) + jt->second[i] = State::Sx; + } + dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second))); } - dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second))); } } + log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); + module->remove(cell); + total_count++; } - log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); -#ifdef USE_CELL_HASH_CACHE - cell_hash_cache.erase(cell); -#endif - module->remove(cell); - total_count++; - } else { - sharemap[cell] = cell; } } } diff --git a/tests/opt/opt_merge_init.ys b/tests/opt/opt_merge_init.ys index a29c29df6..0176f09c7 100644 --- a/tests/opt/opt_merge_init.ys +++ b/tests/opt/opt_merge_init.ys @@ -20,6 +20,7 @@ endmodule EOT opt_merge +select -assert-count 1 t:$dff select -assert-count 1 a:init=1'0 @@ -46,4 +47,31 @@ endmodule EOT opt_merge +select -assert-count 1 t:$dff select -assert-count 1 a:init=2'bx1 + + +design -reset +read_verilog -icells <<EOT +module top(input clk, i, (* init = 1'b0 *) output o, /* NB: no init here! */ output p); + \$dff #( + .CLK_POLARITY(1'h1), + .WIDTH(32'd1) + ) ffo ( + .CLK(clk), + .D(i), + .Q(o) + ); + \$dff #( + .CLK_POLARITY(1'h1), + .WIDTH(32'd1) + ) ffp ( + .CLK(clk), + .D(i), + .Q(p) + ); +endmodule +EOT + +opt_merge +select -assert-count 2 t:$dff diff --git a/tests/opt/opt_merge_keep.ys b/tests/opt/opt_merge_keep.ys new file mode 100644 index 000000000..2a9202901 --- /dev/null +++ b/tests/opt/opt_merge_keep.ys @@ -0,0 +1,64 @@ +read_verilog -icells <<EOT +module top(input clk, i, output o, p); + (* keep *) + \$_DFF_P_ ffo ( + .C(clk), + .D(i), + .Q(o) + ); + \$_DFF_P_ ffp ( + .C(clk), + .D(i), + .Q(p) + ); +endmodule +EOT + +opt_merge +select -assert-count 1 t:$_DFF_P_ +select -assert-count 1 a:keep + + +design -reset +read_verilog -icells <<EOT +module top(input clk, i, output o, p); + \$_DFF_P_ ffo ( + .C(clk), + .D(i), + .Q(o) + ); + (* keep *) + \$_DFF_P_ ffp ( + .C(clk), + .D(i), + .Q(p) + ); +endmodule +EOT + +opt_merge +select -assert-count 1 t:$_DFF_P_ +select -assert-count 1 a:keep + + +design -reset +read_verilog -icells <<EOT +module top(input clk, i, output o, p); + (* keep *) + \$_DFF_P_ ffo ( + .C(clk), + .D(i), + .Q(o) + ); + (* keep *) + \$_DFF_P_ ffp ( + .C(clk), + .D(i), + .Q(p) + ); +endmodule +EOT + +opt_merge +select -assert-count 2 t:$_DFF_P_ +select -assert-count 2 a:keep diff --git a/tests/simple/dynslice.v b/tests/simple/dynslice.v new file mode 100644 index 000000000..7236ac3a5 --- /dev/null +++ b/tests/simple/dynslice.v @@ -0,0 +1,12 @@ +module dynslice ( + input clk , + input [9:0] ctrl , + input [15:0] din , + input [3:0] sel , + output reg [127:0] dout +); +always @(posedge clk) +begin + dout[ctrl*sel+:16] <= din ; +end +endmodule |