diff --git a/passes/cmds/abstract.cc b/passes/cmds/abstract.cc index 698907eb9..88c234f71 100644 --- a/passes/cmds/abstract.cc +++ b/passes/cmds/abstract.cc @@ -271,7 +271,7 @@ unsigned int abstract_value(Module* mod, EnableLogic enable, const std::vectormodule, conn.first).unescape(), i, mod); explain_selections(selected_reps.at(sigmap(conn.second[i]))); offsets_to_abstract.insert(i); } @@ -484,6 +484,10 @@ struct AbstractPass : public Pass { unsigned int changed = 0; if ((mode == State) || (mode == Value)) { + std::optional enable_search; + if (enable == Enable::ActiveLow || enable == Enable::ActiveHigh) + enable_search.emplace(&design->twines); + for (auto mod : design->selected_modules()) { EnableLogic enable_logic; @@ -493,12 +497,12 @@ struct AbstractPass : public Pass { } break; case Enable::ActiveLow: case Enable::ActiveHigh: { - Wire *enable_wire = mod->wire("\\" + enable_name); + Wire *enable_wire = mod->wire(enable_search->find("\\" + enable_name)); if (!enable_wire) log_cmd_error("Enable wire %s not found in module %s\n", enable_name, mod->name); if (GetSize(enable_wire) != 1) log_cmd_error("Enable wire %s must have width 1 but has width %d in module %s\n", - enable_name.c_str(), GetSize(enable_wire), mod->name.c_str()); + enable_name.c_str(), GetSize(enable_wire), mod->name); enable_logic = { enable_wire, enable == Enable::ActiveHigh }; } break; case Enable::Initstates: { diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index 1011a093c..8434f1390 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -34,7 +34,8 @@ static void add_formal(RTLIL::Module *module, const std::string &celltype, const { std::string escaped_name = RTLIL::escape_id(name); std::string escaped_enable_name = (enable_name != "") ? RTLIL::escape_id(enable_name) : ""; - RTLIL::Wire *wire = module->wire(escaped_name); + TwineSearch search(&module->design->twines); + RTLIL::Wire *wire = module->wire(search.find(escaped_name)); log_assert(is_formal_celltype(celltype)); if (wire == nullptr) { @@ -48,7 +49,7 @@ static void add_formal(RTLIL::Module *module, const std::string &celltype, const log("Added $%s cell for wire \"%s.%s\"\n", celltype, module->name.str(), name); } else { - RTLIL::Wire *enable_wire = module->wire(escaped_enable_name); + RTLIL::Wire *enable_wire = module->wire(search.find(escaped_enable_name)); if(enable_wire == nullptr) log_error("Could not find enable wire with name \"%s\".\n", enable_name); @@ -62,10 +63,12 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n { RTLIL::Wire *wire = nullptr; name = RTLIL::escape_id(name); + TwineSearch search(&design->twines); + IdString name_ref = search.find(name); - if (module->count_id(name) != 0) + if (module->count_id(name_ref) != 0) { - wire = module->wire(name); + wire = module->wire(name_ref); if (wire != nullptr && wire->width != width) wire = nullptr; @@ -97,6 +100,8 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n if (!flag_global) return; + IdString port_id = design->twines.add(name); + for (auto cell : module->cells()) { RTLIL::Module *mod = design->module(cell->type); @@ -106,10 +111,10 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n continue; if (mod->get_blackbox_attribute()) continue; - if (cell->hasPort(name)) + if (cell->hasPort(port_id)) continue; - cell->setPort(name, wire); + cell->setPort(port_id, wire); log("Added connection %s to cell %s.%s (%s).\n", name, module->name, cell->name, cell->type); } } diff --git a/passes/cmds/box_derive.cc b/passes/cmds/box_derive.cc index 2d5ee2440..99b4926a1 100644 --- a/passes/cmds/box_derive.cc +++ b/passes/cmds/box_derive.cc @@ -60,8 +60,8 @@ struct BoxDerivePass : Pass { log_header(d, "Executing BOX_DERIVE pass. (derive modules for boxes)\n"); size_t argidx; - IdString naming_attr; - IdString base_name; + std::string naming_attr; + std::string base_name; bool apply_mode = false; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-naming_attr" && argidx + 1 < args.size()) @@ -75,11 +75,14 @@ struct BoxDerivePass : Pass { } extra_args(args, argidx, d); + IdString naming_attr_ref = naming_attr.empty() ? IdString::Null : d->twines.find(naming_attr); + Module *base_override = nullptr; if (!base_name.empty()) { - base_override = d->module(base_name); + IdString base_ref = d->twines.find(base_name); + base_override = base_ref == IdString::Null ? nullptr : d->module(base_ref); if (!base_override) - log_cmd_error("Base module %s not found.\n", base_name.unescape()); + log_cmd_error("Base module %s not found.\n", RTLIL::unescape_id(base_name)); } dict>, Module*> done; @@ -94,7 +97,7 @@ struct BoxDerivePass : Pass { if (base_override) base = base_override; - auto index = std::make_pair(base->name, cell->parameters); + auto index = std::make_pair(IdString(base->name), cell->parameters); if (cell->parameters.empty()) continue; @@ -103,22 +106,22 @@ struct BoxDerivePass : Pass { IdString derived_type = base->derive(d, cell->parameters); Module *derived = d->module(derived_type); log_assert(derived && "Failed to derive module\n"); - log("derived %s\n", derived_type); + log("derived %s\n", d->twines.str(derived_type).c_str()); - if (!naming_attr.empty() && derived->has_attribute(naming_attr)) { - IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr)); - if (!new_name.isPublic()) + if (naming_attr_ref != IdString::Null && derived->has_attribute(naming_attr_ref)) { + std::string new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr_ref)); + if (new_name.empty() || new_name[0] != '\\') log_error("Derived module %s cannot be renamed to private name %s.\n", - derived, new_name.unescape()); - derived->attributes.erase(naming_attr); - d->rename(derived, new_name); + derived, RTLIL::unescape_id(new_name)); + derived->attributes.erase(naming_attr_ref); + d->rename(derived, std::move(new_name)); } done[index] = derived; } if (apply_mode) - cell->type = done[index]->name; + cell->type = cell->module->design->twines.copy_from(done[index]->design->twines, done[index]->name); } } } diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc index eb194f3e3..649758383 100644 --- a/passes/cmds/chtype.cc +++ b/passes/cmds/chtype.cc @@ -22,23 +22,25 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static void publish(RTLIL::IdString& id) { - if (id.begins_with("$")) { - log_debug("publishing %s\n", id.c_str()); - id = "\\" + id.str(); - log_debug("published %s\n", id.c_str()); - } +static IdString publish(TwinePool &twines, IdString id) { + std::string name = twines.str(id); + if (!name.starts_with("$")) + return id; + log_debug("publishing %s\n", name.c_str()); + IdString published = twines.add("\\" + name); + log_debug("published %s\n", twines.str(published).c_str()); + return published; } static void publish_design(RTLIL::Design* design) { auto saved_modules = design->modules_; design->modules_.clear(); - for (auto& [name, mod] : saved_modules) { - publish(mod->name); - design->modules_[mod->name] = mod; - for (auto* cell : mod->cells()) { - publish(cell->type); - } + for (auto& [_, mod] : saved_modules) { + IdString new_name = publish(design->twines, mod->name); + mod->name = new_name; + design->modules_[new_name] = mod; + for (auto* cell : mod->cells()) + cell->type = publish(design->twines, cell->type); } } @@ -74,12 +76,12 @@ struct ChtypePass : public Pass { for (argidx = 1; argidx < args.size(); argidx++) { if (set_type == IdString() && args[argidx] == "-set" && argidx+1 < args.size()) { - set_type = RTLIL::escape_id(args[++argidx]); + set_type = design->twines.add(RTLIL::escape_id(args[++argidx])); continue; } if (args[argidx] == "-map" && argidx+2 < args.size()) { - IdString old_type = RTLIL::escape_id(args[++argidx]); - IdString new_type = RTLIL::escape_id(args[++argidx]); + IdString old_type = design->twines.add(RTLIL::escape_id(args[++argidx])); + IdString new_type = design->twines.add(RTLIL::escape_id(args[++argidx])); map_types[old_type] = new_type; continue; } diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index b8a61d532..06f227f86 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -122,7 +122,7 @@ struct ConnectPass : public Pass { RTLIL::Module *module = nullptr; for (auto mod : design->selected_modules()) { if (module != nullptr) - log_cmd_error("Multiple modules selected: %s, %s\n", module->name.unescape(), mod->name.unescape()); + log_cmd_error("Multiple modules selected: %s, %s\n", module, mod); module = mod; } if (module == nullptr) @@ -184,17 +184,20 @@ struct ConnectPass : public Pass { if (flag_nounset) log_cmd_error("Can't use -port together with -nounset.\n"); - if (module->cell(RTLIL::escape_id(port_cell)) == nullptr) + TwineSearch search(&module->design->twines); + RTLIL::Cell *port_cell_obj = module->cell(search.find(RTLIL::escape_id(port_cell))); + if (port_cell_obj == nullptr) log_cmd_error("Can't find cell %s.\n", port_cell); 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); + IdString port_port_ref = module->design->twines.add(RTLIL::escape_id(port_port)); if (!flag_assert) { - module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig)); + port_cell_obj->setPort(port_port_ref, sigmap(sig)); } else { - SigSpec cur = module->cell(RTLIL::escape_id(port_cell))->getPort(RTLIL::escape_id(port_port)); + SigSpec cur = port_cell_obj->getPort(port_port_ref); if (sigmap(sig) != sigmap(cur)) { log_cmd_error("Expected connection not present: expected %s, found %s.\n", log_signal(sig), log_signal(cur)); } diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index dcc6f0004..c735f403c 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -33,8 +33,8 @@ struct ConnwrappersWorker bool is_signed; }; - std::set decl_celltypes; - std::map, portdecl_t> decls; + std::set decl_celltypes; + std::map, portdecl_t> decls; void add_port(std::string celltype, std::string portname, std::string widthparam, std::string signparam) { @@ -77,22 +77,24 @@ struct ConnwrappersWorker for (auto &conn : cell->connections()) { - std::pair key(cell->type, conn.first); + std::pair key(cell->type, module->design->twines.str(conn.first)); if (!decls.count(key)) continue; portdecl_t &decl = decls.at(key); - if (!cell->parameters.count(decl.widthparam)) + IdString widthparam = module->design->twines.find(decl.widthparam); + if (widthparam == IdString::Null || !cell->parameters.count(widthparam)) continue; - if (!decl.signparam.empty() && !cell->parameters.count(decl.signparam)) + IdString signparam = decl.signparam.empty() ? IdString::Null : module->design->twines.find(decl.signparam); + if (!decl.signparam.empty() && (signparam == IdString::Null || !cell->parameters.count(signparam))) continue; - int inner_width = cell->parameters.at(decl.widthparam).as_int(); + int inner_width = cell->parameters.at(widthparam).as_int(); int outer_width = conn.second.size(); - bool is_signed = decl.signparam.empty() ? decl.is_signed : cell->parameters.at(decl.signparam).as_bool(); + bool is_signed = decl.signparam.empty() ? decl.is_signed : cell->parameters.at(signparam).as_bool(); if (inner_width >= outer_width) continue; @@ -135,7 +137,7 @@ struct ConnwrappersWorker if (old_sig.size()) log("Connected extended bits of %s.%s:%s: %s -> %s\n", module->name.unescape(), cell->name.unescape(), - conn.first.unescape(), log_signal(old_sig), log_signal(conn.second)); + PooledName(module, conn.first).unescape(), log_signal(old_sig), log_signal(conn.second)); } } } diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc index 5a5835a43..9fcf33722 100644 --- a/passes/cmds/copy.cc +++ b/passes/cmds/copy.cc @@ -44,15 +44,15 @@ struct CopyPass : public Pass { std::string src_name = RTLIL::escape_id(args[1]); std::string trg_name = RTLIL::escape_id(args[2]); - if (design->module(src_name) == nullptr) - log_cmd_error("Can't find source module %s.\n", src_name); + TwineSearch search(&design->twines); + IdString src_ref = search.find(src_name); + if (design->module(src_ref) == nullptr) + log_cmd_error("Can't find source module %s.\n", src_name.c_str()); - if (design->module(trg_name) != nullptr) + if (design->module(search.find(trg_name)) != nullptr) log_cmd_error("Target module name %s already exists.\n", trg_name); - RTLIL::Module *new_mod = design->module(src_name)->clone(); - new_mod->name = trg_name; - design->add(new_mod); + design->module(src_ref)->clone(design, design->twines.add(std::string{trg_name})); } } CopyPass; diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index e341f29d6..628a7d699 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -91,14 +91,14 @@ struct DeletePass : public Pass { pool delete_wires; pool delete_cells; pool delete_procs; - pool delete_mems; + dict delete_mems; 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); + delete_mems[design->twines.str(it.first)] = it.first; for (auto cell : module->cells()) { if (design->selected(module, cell)) @@ -113,8 +113,8 @@ struct DeletePass : public Pass { delete_procs.insert(it.second); for (auto &it : delete_mems) { - delete module->memories.at(it); - module->memories.erase(it); + delete module->memories.at(it.second); + module->memories.erase(it.second); } for (auto &it : delete_cells) diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 9dff6fa45..de90cbd4e 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -254,30 +254,32 @@ struct DesignPass : public Pass { if (import_mode) { std::string prefix = RTLIL::escape_id(as_name); + IdString as_name_ref = copy_to_design->twines.add(std::string{prefix}); pool queue; dict done; - if (copy_to_design->module(prefix) != nullptr) - copy_to_design->remove(copy_to_design->module(prefix)); + if (copy_to_design->module(as_name_ref) != nullptr) + copy_to_design->remove(copy_to_design->module(as_name_ref)); if (GetSize(copy_src_modules) != 1) log_cmd_error("No top module found in source design.\n"); for (auto mod : copy_src_modules) { - log("Importing %s as %s.\n", mod, RTLIL::unescape_id(prefix)); + log("Importing %s as %s.\n", mod, PooledName(design, as_name_ref).unescape()); - RTLIL::Module *t = mod->clone(); - t->name = prefix; - t->design = copy_to_design; + RTLIL::Module *t = mod->clone(copy_to_design, as_name_ref); t->attributes.erase(ID::top); - copy_to_design->add(t); queue.insert(t); - done[mod->name] = prefix; + done[mod->name] = as_name_ref; } + std::optional src_search; + if (copy_from_design) + src_search.emplace(©_from_design->twines); + while (!queue.empty() && copy_from_design) { pool old_queue; @@ -286,28 +288,27 @@ struct DesignPass : public Pass { for (auto mod : old_queue) for (auto cell : mod->cells()) { - Module *fmod = copy_from_design->module(cell->type); + Module *fmod = copy_from_design->module( + src_search->find(copy_to_design->twines.str(cell->type))); if (fmod == nullptr) continue; if (done.count(cell->type) == 0) { - std::string trg_name = prefix + "." + (cell->type.c_str() + (*cell->type.c_str() == '\\')); + IdString trg_ref = copy_to_design->twines.add( + Twine::Suffix{as_name_ref, "." + cell->type.unescape()}); - log("Importing %s as %s.\n", fmod, RTLIL::unescape_id(trg_name)); + log("Importing %s as %s.\n", fmod, PooledName(copy_to_design, trg_ref).unescape()); - if (copy_to_design->module(trg_name) != nullptr) - copy_to_design->remove(copy_to_design->module(trg_name)); + if (copy_to_design->module(trg_ref) != nullptr) + copy_to_design->remove(copy_to_design->module(trg_ref)); - RTLIL::Module *t = fmod->clone(); - t->name = trg_name; - t->design = copy_to_design; + RTLIL::Module *t = fmod->clone(copy_to_design, trg_ref); t->attributes.erase(ID::top); - copy_to_design->add(t); queue.insert(t); - done[cell->type] = trg_name; + done[cell->type] = trg_ref; } cell->type = done.at(cell->type); @@ -323,14 +324,12 @@ struct DesignPass : public Pass { for (auto mod : copy_src_modules) { std::string trg_name = as_name.empty() ? mod->name.str() : RTLIL::escape_id(as_name); + IdString trg_ref = copy_to_design->twines.add(std::string{trg_name}); - if (copy_to_design->module(trg_name) != nullptr) - copy_to_design->remove(copy_to_design->module(trg_name)); + if (copy_to_design->module(trg_ref) != nullptr) + copy_to_design->remove(copy_to_design->module(trg_ref)); - RTLIL::Module *t = mod->clone(); - t->name = trg_name; - t->design = copy_to_design; - copy_to_design->add(t); + mod->clone(copy_to_design, trg_ref); } } @@ -338,8 +337,7 @@ struct DesignPass : public Pass { { RTLIL::Design *design_copy = new RTLIL::Design; - for (auto mod : design->modules()) - design_copy->add(mod->clone()); + design->clone_into(design_copy); design_copy->selection_stack = design->selection_stack; design_copy->selection_vars = design->selection_vars; @@ -361,7 +359,7 @@ struct DesignPass : public Pass { design->selection_stack.clear(); design->selection_vars.clear(); - design->selected_active_module.clear(); + design->selected_active_module = IdString::Null; design->push_full_selection(); } @@ -377,8 +375,7 @@ struct DesignPass : public Pass { { RTLIL::Design *saved_design = pop_mode ? pushed_designs.back() : saved_designs.at(load_name); - for (auto mod : saved_design->modules()) - design->add(mod->clone()); + saved_design->clone_into(design); design->selection_stack = saved_design->selection_stack; design->selection_vars = saved_design->selection_vars; diff --git a/passes/cmds/design_equal.cc b/passes/cmds/design_equal.cc index 1912a823e..ed7ead1df 100644 --- a/passes/cmds/design_equal.cc +++ b/passes/cmds/design_equal.cc @@ -22,13 +22,33 @@ YOSYS_NAMESPACE_BEGIN +class PoolBridge +{ + const TwinePool *pool_a; + const TwinePool *pool_b; + TwineSearch search_a; + TwineSearch search_b; + +public: + PoolBridge(RTLIL::Design *design_a, RTLIL::Design *design_b) : + pool_a(&design_a->twines), pool_b(&design_b->twines), + search_a(&design_a->twines), search_b(&design_b->twines) {} + + IdString a_to_b(IdString ref) const { return search_b.find(pool_a->str(ref)); } + IdString b_to_a(IdString ref) const { return search_a.find(pool_b->str(ref)); } + + bool same(IdString a, IdString b) const { return pool_a->str(a) == pool_b->str(b); } +}; + class ModuleComparator { RTLIL::Module *mod_a; RTLIL::Module *mod_b; + const PoolBridge &bridge; public: - ModuleComparator(RTLIL::Module *mod_a, RTLIL::Module *mod_b) : mod_a(mod_a), mod_b(mod_b) {} + ModuleComparator(RTLIL::Module *mod_a, RTLIL::Module *mod_b, const PoolBridge &bridge) : + mod_a(mod_a), mod_b(mod_b), bridge(bridge) {} template [[noreturn]] void error(FmtString...> fmt, const Args &... args) @@ -38,9 +58,9 @@ public: [[noreturn]] void formatted_error(std::string err) { - log("Module A: %s\n", mod_a->name.unescape()); + log("Module A: %s\n", mod_a); log_module(mod_a, " "); - log("Module B: %s\n", mod_b->name.unescape()); + log("Module B: %s\n", mod_b); log_module(mod_b, " "); log_cmd_error("Designs are different: %s\n", err); } @@ -50,7 +70,7 @@ public: if (a.wire == nullptr && b.wire == nullptr) return a.data == b.data; if (a.wire != nullptr && b.wire != nullptr) - return a.wire->name == b.wire->name && a.offset == b.offset; + return bridge.same(a.wire->name, b.wire->name) && a.offset == b.offset; return false; } @@ -67,20 +87,21 @@ public: std::string compare_attributes(const RTLIL::AttrObject *a, const RTLIL::AttrObject *b) { for (const auto &it : a->attributes) { - if (b->attributes.count(it.first) == 0) - return "missing attribute " + std::string(it.first.unescape()) + " in second design"; - if (it.second != b->attributes.at(it.first)) - return "attribute " + std::string(it.first.unescape()) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(it.first)); + IdString in_b = bridge.a_to_b(it.first); + if (b->attributes.count(in_b) == 0) + return "missing attribute " + std::string(mod_a->design->twines.unescaped_str(it.first)) + " in second design"; + if (it.second != b->attributes.at(in_b)) + return "attribute " + std::string(mod_a->design->twines.unescaped_str(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->attributes.at(in_b)); } for (const auto &it : b->attributes) - if (a->attributes.count(it.first) == 0) - return "missing attribute " + std::string(it.first.unescape()) + " in first design"; + if (a->attributes.count(bridge.b_to_a(it.first)) == 0) + return "missing attribute " + std::string(mod_b->design->twines.unescaped_str(it.first)) + " in first design"; return ""; } std::string compare_wires(const RTLIL::Wire *a, const RTLIL::Wire *b) { - if (a->name != b->name) + if (!bridge.same(a->name, b->name)) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->width != b->width) return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width); @@ -104,19 +125,21 @@ public: void check_wires() { for (const auto &it : mod_a->wires_) { - if (mod_b->wires_.count(it.first) == 0) - error("Module %s missing wire %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); - if (std::string mismatch = compare_wires(it.second, mod_b->wires_.at(it.first)); !mismatch.empty()) - error("Module %s wire %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); + RTLIL::Wire *wb = mod_b->wire(bridge.a_to_b(it.first)); + if (!wb) + error("Module %s missing wire %s in second design.\n", mod_a, it.second); + else if (std::string mismatch = compare_wires(it.second, wb); !mismatch.empty()) + error("Module %s wire %s %s.\n", mod_a, it.second, mismatch); + } + for (const auto &it : mod_b->wires_) { + if (!mod_a->wire(bridge.b_to_a(it.first))) + error("Module %s missing wire %s in first design.\n", mod_b, it.second); } - for (const auto &it : mod_b->wires_) - if (mod_a->wires_.count(it.first) == 0) - error("Module %s missing wire %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } std::string compare_memories(const RTLIL::Memory *a, const RTLIL::Memory *b) { - if (a->name != b->name) + if (!bridge.same(a->name, b->name)) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (a->width != b->width) return "width mismatch: " + std::to_string(a->width) + " != " + std::to_string(b->width); @@ -131,32 +154,34 @@ public: std::string compare_cells(const RTLIL::Cell *a, const RTLIL::Cell *b) { - if (a->name != b->name) + if (!bridge.same(a->name, b->name)) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); - if (a->type != b->type) + if (!bridge.same(a->type, b->type)) return "type mismatch: " + std::string(a->type.unescape()) + " != " + b->type.unescape(); if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch; for (const auto &it : a->parameters) { - if (b->parameters.count(it.first) == 0) - return "parameter mismatch: missing parameter " + std::string(it.first.unescape()) + " in second design"; - if (it.second != b->parameters.at(it.first)) - return "parameter mismatch: " + std::string(it.first.unescape()) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(it.first)); + IdString in_b = bridge.a_to_b(it.first); + if (b->parameters.count(in_b) == 0) + return "parameter mismatch: missing parameter " + std::string(mod_a->design->twines.unescaped_str(it.first)) + " in second design"; + if (it.second != b->parameters.at(in_b)) + return "parameter mismatch: " + std::string(mod_a->design->twines.unescaped_str(it.first)) + " mismatch: " + log_const(it.second) + " != " + log_const(b->parameters.at(in_b)); } for (const auto &it : b->parameters) - if (a->parameters.count(it.first) == 0) - return "parameter mismatch: missing parameter " + std::string(it.first.unescape()) + " in first design"; + if (a->parameters.count(bridge.b_to_a(it.first)) == 0) + return "parameter mismatch: missing parameter " + std::string(mod_b->design->twines.unescaped_str(it.first)) + " in first design"; for (const auto &it : a->connections()) { - if (b->connections().count(it.first) == 0) - return "connection mismatch: missing connection " + std::string(it.first.unescape()) + " in second design"; - if (!compare_sigspec(it.second, b->connections().at(it.first))) - return "connection " + std::string(it.first.unescape()) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(it.first)); + IdString in_b = bridge.a_to_b(it.first); + if (b->connections().count(in_b) == 0) + return "connection mismatch: missing connection " + a->module->design->twines.unescaped_str(it.first) + " in second design"; + if (!compare_sigspec(it.second, b->connections().at(in_b))) + return "connection " + a->module->design->twines.unescaped_str(it.first) + " mismatch: " + log_signal(it.second) + " != " + log_signal(b->connections().at(in_b)); } for (const auto &it : b->connections()) - if (a->connections().count(it.first) == 0) - return "connection mismatch: missing connection " + std::string(it.first.unescape()) + " in first design"; + if (a->connections().count(bridge.b_to_a(it.first)) == 0) + return "connection mismatch: missing connection " + a->module->design->twines.unescaped_str(it.first) + " in first design"; return ""; } @@ -164,27 +189,30 @@ public: void check_cells() { for (const auto &it : mod_a->cells_) { - if (mod_b->cells_.count(it.first) == 0) - error("Module %s missing cell %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); - if (std::string mismatch = compare_cells(it.second, mod_b->cells_.at(it.first)); !mismatch.empty()) - error("Module %s cell %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); + RTLIL::Cell *cb = mod_b->cell(bridge.a_to_b(it.first)); + if (!cb) + error("Module %s missing cell %s in second design.\n", mod_a, it.second); + else if (std::string mismatch = compare_cells(it.second, cb); !mismatch.empty()) + error("Module %s cell %s %s.\n", mod_a, it.second, mismatch); + } + for (const auto &it : mod_b->cells_) { + if (!mod_a->cell(bridge.b_to_a(it.first))) + error("Module %s missing cell %s in first design.\n", mod_b, it.second); } - for (const auto &it : mod_b->cells_) - if (mod_a->cells_.count(it.first) == 0) - error("Module %s missing cell %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); } void check_memories() { for (const auto &it : mod_a->memories) { - if (mod_b->memories.count(it.first) == 0) - error("Module %s missing memory %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); - if (std::string mismatch = compare_memories(it.second, mod_b->memories.at(it.first)); !mismatch.empty()) - error("Module %s memory %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch); + IdString in_b = bridge.a_to_b(it.first); + if (mod_b->memories.count(in_b) == 0) + error("Module %s missing memory %s in second design.\n", mod_a, it.second); + if (std::string mismatch = compare_memories(it.second, mod_b->memories.at(in_b)); !mismatch.empty()) + error("Module %s memory %s %s.\n", mod_a, it.second, mismatch); } for (const auto &it : mod_b->memories) - if (mod_a->memories.count(it.first) == 0) - error("Module %s missing memory %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); + if (mod_a->memories.count(bridge.b_to_a(it.first)) == 0) + error("Module %s missing memory %s in first design.\n", mod_b, it.second); } std::string compare_case_rules(const RTLIL::CaseRule *a, const RTLIL::CaseRule *b) @@ -201,9 +229,9 @@ public: return "actions size mismatch: " + std::to_string(a->actions.size()) + " != " + std::to_string(b->actions.size()); for (size_t i = 0; i < a->actions.size(); i++) { if (!compare_sigspec(a->actions[i].first, b->actions[i].first)) - return "action " + std::to_string(i) + " first mismatch: " + log_signal(a->actions[i].first) + " != " + log_signal(b->actions[i].first); + return "action " + std::to_string(i) + " lhs mismatch: " + log_signal(a->actions[i].first) + " != " + log_signal(b->actions[i].first); if (!compare_sigspec(a->actions[i].second, b->actions[i].second)) - return "action " + std::to_string(i) + " second mismatch: " + log_signal(a->actions[i].second) + " != " + log_signal(b->actions[i].second); + return "action " + std::to_string(i) + " rhs mismatch: " + log_signal(a->actions[i].second) + " != " + log_signal(b->actions[i].second); } if (a->switches.size() != b->switches.size()) @@ -241,17 +269,17 @@ public: return "actions size mismatch: " + std::to_string(a->actions.size()) + " != " + std::to_string(b->actions.size()); for (size_t i = 0; i < a->actions.size(); i++) { if (!compare_sigspec(a->actions[i].first, b->actions[i].first)) - return "action " + std::to_string(i) + " first mismatch: " + log_signal(a->actions[i].first) + " != " + log_signal(b->actions[i].first); + return "action " + std::to_string(i) + " lhs mismatch: " + log_signal(a->actions[i].first) + " != " + log_signal(b->actions[i].first); if (!compare_sigspec(a->actions[i].second, b->actions[i].second)) - return "action " + std::to_string(i) + " second mismatch: " + log_signal(a->actions[i].second) + " != " + log_signal(b->actions[i].second); + return "action " + std::to_string(i) + " rhs mismatch: " + log_signal(a->actions[i].second) + " != " + log_signal(b->actions[i].second); } if (a->mem_write_actions.size() != b->mem_write_actions.size()) return "mem_write_actions size mismatch: " + std::to_string(a->mem_write_actions.size()) + " != " + std::to_string(b->mem_write_actions.size()); for (size_t i = 0; i < a->mem_write_actions.size(); i++) { const auto &ma = a->mem_write_actions[i]; const auto &mb = b->mem_write_actions[i]; - if (ma.memid != mb.memid) - return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + ma.memid.unescape() + " != " + mb.memid.unescape(); + if (!bridge.same(ma.memid, mb.memid)) + return "mem_write_actions " + std::to_string(i) + " memid mismatch: " + mod_a->design->twines.unescaped_str(ma.memid) + " != " + mod_b->design->twines.unescaped_str(mb.memid); if (!compare_sigspec(ma.address, mb.address)) return "mem_write_actions " + std::to_string(i) + " address mismatch: " + log_signal(ma.address) + " != " + log_signal(mb.address); if (!compare_sigspec(ma.data, mb.data)) @@ -268,7 +296,7 @@ public: std::string compare_processes(const RTLIL::Process *a, const RTLIL::Process *b) { - if (a->name != b->name) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); + if (!bridge.same(a->name, b->name)) return "name mismatch: " + std::string(a->name.unescape()) + " != " + b->name.unescape(); if (std::string mismatch = compare_attributes(a, b); !mismatch.empty()) return mismatch; if (std::string mismatch = compare_case_rules(&a->root_case, &b->root_case); !mismatch.empty()) @@ -284,14 +312,15 @@ public: void check_processes() { for (auto &it : mod_a->processes) { - if (mod_b->processes.count(it.first) == 0) - error("Module %s missing process %s in second design.\n", mod_a->name.unescape(), it.first.unescape()); - if (std::string mismatch = compare_processes(it.second, mod_b->processes.at(it.first)); !mismatch.empty()) - error("Module %s process %s %s.\n", mod_a->name.unescape(), it.first.unescape(), mismatch.c_str()); + IdString in_b = bridge.a_to_b(it.first); + if (mod_b->processes.count(in_b) == 0) + error("Module %s missing process %s in second design.\n", mod_a, it.second); + if (std::string mismatch = compare_processes(it.second, mod_b->processes.at(in_b)); !mismatch.empty()) + error("Module %s process %s %s.\n", mod_a, it.second, mismatch.c_str()); } for (auto &it : mod_b->processes) - if (mod_a->processes.count(it.first) == 0) - error("Module %s missing process %s in first design.\n", mod_b->name.unescape(), it.first.unescape()); + if (mod_a->processes.count(bridge.b_to_a(it.first)) == 0) + error("Module %s missing process %s in first design.\n", mod_b, it.second); } void check_connections() @@ -299,23 +328,23 @@ public: const auto &conns_a = mod_a->connections(); const auto &conns_b = mod_b->connections(); if (conns_a.size() != conns_b.size()) { - error("Module %s connection count differs: %zu != %zu\n", mod_a->name.unescape(), conns_a.size(), conns_b.size()); + error("Module %s connection count differs: %zu != %zu\n", mod_a, conns_a.size(), conns_b.size()); } else { for (size_t i = 0; i < conns_a.size(); i++) { if (!compare_sigspec(conns_a[i].first, conns_b[i].first)) - error("Module %s connection %zu LHS %s != %s.\n", mod_a->name.unescape(), i, log_signal(conns_a[i].first), log_signal(conns_b[i].first)); + error("Module %s connection %zu LHS %s != %s.\n", mod_a, i, log_signal(conns_a[i].first), log_signal(conns_b[i].first)); if (!compare_sigspec(conns_a[i].second, conns_b[i].second)) - error("Module %s connection %zu RHS %s != %s.\n", mod_a->name.unescape(), i, log_signal(conns_a[i].second), log_signal(conns_b[i].second)); + error("Module %s connection %zu RHS %s != %s.\n", mod_a, i, log_signal(conns_a[i].second), log_signal(conns_b[i].second)); } } } void check() { - if (mod_a->name != mod_b->name) - error("Modules have different names: %s != %s\n", mod_a->name.unescape(), mod_b->name.unescape()); + if (!bridge.same(mod_a->name, mod_b->name)) + error("Modules have different names: %s != %s\n", mod_a, mod_b); if (std::string mismatch = compare_attributes(mod_a, mod_b); !mismatch.empty()) - error("Module %s %s.\n", mod_a->name.unescape(), mismatch); + error("Module %s %s.\n", mod_a, mismatch); check_wires(); check_cells(); check_memories(); @@ -346,18 +375,21 @@ struct DesignEqualPass : public Pass { RTLIL::Design *other = saved_designs.at(check_name); + PoolBridge bridge(design, other); + for (auto &it : design->modules_) { RTLIL::Module *mod = it.second; - if (!other->has(mod->name)) - log_error("Second design missing module %s.\n", mod->name.unescape()); + RTLIL::Module *other_mod = other->module(bridge.a_to_b(it.first)); + if (!other_mod) + log_error("Second design missing module %s.\n", mod); - ModuleComparator cmp(mod, other->module(mod->name)); + ModuleComparator cmp(mod, other_mod, bridge); cmp.check(); } for (auto &it : other->modules_) { RTLIL::Module *mod = it.second; - if (!design->has(mod->name)) - log_error("First design missing module %s.\n", mod->name.unescape()); + if (!design->has(bridge.b_to_a(it.first))) + log_error("First design missing module %s.\n", mod); } log("Designs are identical.\n"); diff --git a/passes/cmds/dft_tag.cc b/passes/cmds/dft_tag.cc index 216f66b2c..d7bbae349 100644 --- a/passes/cmds/dft_tag.cc +++ b/passes/cmds/dft_tag.cc @@ -369,13 +369,20 @@ struct DftTagWorker { pending_cells.erase(cell); } + IdString tag_id(const Cell *cell) + { + return module->design->twines.add(RTLIL::escape_id(cell->getParam(ID::TAG).decode_string())); + } + void propagate_tags(Cell *cell) { if (cell->type == ID($set_tag)) { - IdString tag = stringf("\\%s", cell->getParam(ID::TAG).decode_string()); + IdString tag = tag_id(cell); if (all_tags.insert(tag).second) { - auto group_sep = tag.str().find(':'); - IdString tag_group = group_sep != std::string::npos ? tag.str().substr(0, group_sep) : tag; + std::string tag_str = module->design->twines.str(tag); + auto group_sep = tag_str.find(':'); + IdString tag_group = group_sep != std::string::npos + ? module->design->twines.add(tag_str.substr(0, group_sep)) : tag; tag_groups[tag_group].insert(tag); group_of_tag[tag] = tag_group; } @@ -478,7 +485,7 @@ struct DftTagWorker { void process_cell(IdString tag, Cell *cell) { if (cell->type == ID($set_tag)) { - IdString cell_tag = stringf("\\%s", cell->getParam(ID::TAG).decode_string()); + IdString cell_tag = tag_id(cell); auto tag_sig_a = tag_signal(tag, cell->getPort(ID::A)); auto &sig_y = cell->getPort(ID::Y); @@ -628,7 +635,7 @@ struct DftTagWorker { auto prop = autoEq(NEW_ID, masked_a, masked_b); - auto tag_sig = autoAnd(NEW_ID, prop, autoReduceOr(NEW_ID, {tag_sig_a, tag_sig_b})); + auto tag_sig = autoAnd(NEW_ID, prop, autoReduceOr(NEW_ID, SigSpec{tag_sig_a, tag_sig_b})); tag_sig.extend_u0(GetSize(sig_y), false); emit_tag_signal(tag, sig_y, tag_sig); return; @@ -660,7 +667,7 @@ struct DftTagWorker { auto prop = autoGe(NEW_ID, masked_a, masked_b); - auto tag_sig = autoAnd(NEW_ID, prop, autoReduceOr(NEW_ID, {tag_sig_a, tag_sig_b})); + auto tag_sig = autoAnd(NEW_ID, prop, autoReduceOr(NEW_ID, SigSpec{tag_sig_a, tag_sig_b})); tag_sig.extend_u0(GetSize(sig_y), false); emit_tag_signal(tag, sig_y, tag_sig); return; @@ -698,7 +705,7 @@ struct DftTagWorker { auto sig_q = ff.sig_q; auto sig_d = ff.sig_d; - ff.name = NEW_ID; + ff.name = module->design->twines.add(NEW_ID); ff.cell = nullptr; ff.sig_d = tag_signal(tag, ff.sig_d); ff.sig_q = module->addWire(NEW_ID, width); @@ -752,7 +759,7 @@ struct DftTagWorker { for (auto cell : get_tag_cells) { auto &sig_a = cell->getPort(ID::A); - IdString tag = stringf("\\%s", cell->getParam(ID::TAG).decode_string()); + IdString tag = tag_id(cell); tag_signal(tag, sig_a); } @@ -772,13 +779,14 @@ struct DftTagWorker { continue; int index = 0; - auto name = module->uniquify(stringf("%s:%s", wire->name, tag.c_str() + 1), index); + std::string tag_str = module->design->twines.unescaped_str(tag); + auto name = module->uniquify(stringf("%s:%s", wire->name, tag_str), index); auto hdlname = wire->get_hdlname_attribute(); if (!hdlname.empty()) hdlname.back() += index ? - stringf(":%s_%d", tag.c_str() + 1, index) : - stringf(":%s", tag.c_str() + 1); + stringf(":%s_%d", tag_str, index) : + stringf(":%s", tag_str); auto tag_wire = module->addWire(name, wire->width); @@ -817,7 +825,7 @@ struct DftTagWorker { for (auto cell : get_tag_cells) { auto &sig_a = cell->getPort(ID::A); auto &sig_y = cell->getPort(ID::Y); - IdString tag = stringf("\\%s", cell->getParam(ID::TAG).decode_string()); + IdString tag = tag_id(cell); auto tag_sig = tag_signal(tag, sig_a); module->connect(sig_y, tag_sig); @@ -826,7 +834,7 @@ struct DftTagWorker { } - SigSpec autoAnd(IdString name, const SigSpec &sig_a, const SigSpec &sig_b) + SigSpec autoAnd(Twine &&name, const SigSpec &sig_a, const SigSpec &sig_b) { log_assert(GetSize(sig_a) == GetSize(sig_b)); if (sig_a.is_fully_zero() || sig_b.is_fully_ones() || sig_a == sig_b) @@ -834,10 +842,10 @@ struct DftTagWorker { if (sig_a.is_fully_ones() || sig_b.is_fully_zero()) return sig_b; - return module->And(name, sig_a, sig_b); + return module->And(std::move(name), sig_a, sig_b); } - SigSpec autoOr(IdString name, const SigSpec &sig_a, const SigSpec &sig_b) + SigSpec autoOr(Twine &&name, const SigSpec &sig_a, const SigSpec &sig_b) { log_assert(GetSize(sig_a) == GetSize(sig_b)); if (sig_a.is_fully_ones() || sig_b.is_fully_zero() || sig_a == sig_b) @@ -845,10 +853,10 @@ struct DftTagWorker { if (sig_a.is_fully_zero() || sig_b.is_fully_ones()) return sig_b; - return module->Or(name, sig_a, sig_b); + return module->Or(std::move(name), sig_a, sig_b); } - SigSpec autoXor(IdString name, const SigSpec &sig_a, const SigSpec &sig_b) + SigSpec autoXor(Twine &&name, const SigSpec &sig_a, const SigSpec &sig_b) { log_assert(GetSize(sig_a) == GetSize(sig_b)); if (sig_a == sig_b) @@ -858,13 +866,13 @@ struct DftTagWorker { if (sig_b.is_fully_zero()) return sig_a; if (sig_a.is_fully_ones()) - return autoNot(name, sig_b); + return autoNot(std::move(name), sig_b); if (sig_b.is_fully_ones()) - return autoNot(name, sig_a); - return module->Xor(name, sig_a, sig_b); + return autoNot(std::move(name), sig_a); + return module->Xor(std::move(name), sig_a, sig_b); } - SigSpec autoXnor(IdString name, const SigSpec &sig_a, const SigSpec &sig_b) + SigSpec autoXnor(Twine &&name, const SigSpec &sig_a, const SigSpec &sig_b) { log_assert(GetSize(sig_a) == GetSize(sig_b)); if (sig_a == sig_b) @@ -874,13 +882,13 @@ struct DftTagWorker { if (sig_b.is_fully_ones()) return sig_a; if (sig_a.is_fully_zero()) - return autoNot(name, sig_b); + return autoNot(std::move(name), sig_b); if (sig_b.is_fully_zero()) - return autoNot(name, sig_a); - return module->Xnor(name, sig_a, sig_b); + return autoNot(std::move(name), sig_a); + return module->Xnor(std::move(name), sig_a, sig_b); } - SigSpec autoNot(IdString name, const SigSpec &sig_a) + SigSpec autoNot(Twine &&name, const SigSpec &sig_a) { if (sig_a.is_fully_const()) { auto const_val = sig_a.as_const(); @@ -890,10 +898,10 @@ struct DftTagWorker { } return const_val; } - return module->Not(name, sig_a); + return module->Not(std::move(name), sig_a); } - SigSpec autoEq(IdString name, const SigSpec &sig_a, const SigSpec &sig_b) + SigSpec autoEq(Twine &&name, const SigSpec &sig_a, const SigSpec &sig_b) { log_assert(GetSize(sig_a) == GetSize(sig_b)); if (sig_a == sig_b) @@ -908,10 +916,10 @@ struct DftTagWorker { return State::S0; } - return module->Eq(name, sig_a, sig_b); + return module->Eq(std::move(name), sig_a, sig_b); } - SigSpec autoGe(IdString name, const SigSpec &sig_a, const SigSpec &sig_b) + SigSpec autoGe(Twine &&name, const SigSpec &sig_a, const SigSpec &sig_b) { log_assert(GetSize(sig_a) == GetSize(sig_b)); if (sig_a == sig_b || sig_a.is_fully_ones()) @@ -919,10 +927,10 @@ struct DftTagWorker { if (sig_b.is_fully_zero()) return State::S1; - return module->Ge(name, sig_a, sig_b); + return module->Ge(std::move(name), sig_a, sig_b); } - SigSpec autoReduceAnd(IdString name, const SigSpec &sig_a) + SigSpec autoReduceAnd(Twine &&name, const SigSpec &sig_a) { if (GetSize(sig_a) == 0) return State::S1; @@ -934,10 +942,10 @@ struct DftTagWorker { return State::S0; if (sig_a.is_fully_ones()) return State::S1; - return module->ReduceAnd(name, sig_a); + return module->ReduceAnd(std::move(name), sig_a); } - SigSpec autoReduceOr(IdString name, const SigSpec &sig_a) + SigSpec autoReduceOr(Twine &&name, const SigSpec &sig_a) { if (GetSize(sig_a) == 0) return State::S0; @@ -949,7 +957,7 @@ struct DftTagWorker { return State::S1; if (sig_a.is_fully_zero()) return State::S0; - return module->ReduceOr(name, sig_a); + return module->ReduceOr(std::move(name), sig_a); } }; diff --git a/passes/cmds/glift.cc b/passes/cmds/glift.cc index d906c241d..886e7c54d 100644 --- a/passes/cmds/glift.cc +++ b/passes/cmds/glift.cc @@ -34,8 +34,8 @@ private: std::vector> meta_mux_selects; RTLIL::Module *module = nullptr; - const RTLIL::IdString cost_model_wire_name = ID(__glift_weight); - const RTLIL::IdString glift_attribute_name = ID(glift); + const IdString cost_model_wire_name = ID::__glift_weight; + const IdString glift_attribute_name = ID::glift; RTLIL::SigSpec get_corresponding_taint_signal(RTLIL::SigSpec sig) { @@ -47,7 +47,8 @@ private: //Get a SigSpec for the corresponding taint signal for the cell port, creating one if necessary: if (sig.is_wire()) { - RTLIL::Wire *w = module->wire(sig.as_wire()->name.str() + "_t"); + IdString taint_name_ref = module->design->twines.add(sig.as_wire()->name.str() + "_t"); + RTLIL::Wire *w = module->wire(taint_name_ref); if (w == nullptr) w = module->addWire(sig.as_wire()->name.str() + "_t", 1); ret = w; } @@ -385,8 +386,8 @@ private: meta_mux_select_sums.swap(meta_mux_select_sums_buf); } if (meta_mux_select_sums.size() > 0) { - meta_mux_select_sums[0].as_wire()->set_bool_attribute("\\minimize"); - meta_mux_select_sums[0].as_wire()->set_bool_attribute("\\keep"); + meta_mux_select_sums[0].as_wire()->set_bool_attribute(ID::minimize); + meta_mux_select_sums[0].as_wire()->set_bool_attribute(ID::keep); module->rename(meta_mux_select_sums[0].as_wire(), cost_model_wire_name); } } @@ -600,7 +601,7 @@ struct GliftPass : public Pass { for (auto i = 0; i < GetSize(topo_modules.sorted); ++i) { RTLIL::Module *module = topo_modules.sorted[i]; - GliftWorker(module, !non_top_modules[module->name], opt_create_precise_model, opt_create_imprecise_model, opt_create_instrumented_model, opt_taintconstants, opt_keepoutputs, opt_simplecostmodel, opt_nocostmodel, opt_instrumentmore); + GliftWorker(module, !non_top_modules.count(module->name), opt_create_precise_model, opt_create_imprecise_model, opt_create_instrumented_model, opt_taintconstants, opt_keepoutputs, opt_simplecostmodel, opt_nocostmodel, opt_instrumentmore); } } } GliftPass; diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index 0da132521..31e1faf69 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -21,6 +21,7 @@ #include "kernel/rtlil.h" #include "kernel/log.h" #include "backends/verilog/verilog_backend.h" +#include "kernel/twine.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -30,11 +31,14 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: from_name = RTLIL::escape_id(from_name); to_name = RTLIL::escape_id(to_name); - if (module->count_id(to_name)) - log_cmd_error("There is already an object `%s' in module `%s'.\n", RTLIL::unescape_id(to_name), module->name); + TwineSearch search(&module->design->twines); + IdString to_ref = search.find(to_name); + if (module->count_id(to_ref)) + log_cmd_error("There is already an object `%s' in module `%s'.\n", RTLIL::unescape_id(to_name), module); - RTLIL::Wire *wire_to_rename = module->wire(from_name); - RTLIL::Cell *cell_to_rename = module->cell(from_name); + IdString from_ref = search.find(from_name); + RTLIL::Wire *wire_to_rename = module->wire(from_ref); + RTLIL::Cell *cell_to_rename = module->cell(from_ref); if (wire_to_rename != nullptr) { log("Renaming wire %s to %s in module %s.\n", wire_to_rename, RTLIL::unescape_id(to_name), module); @@ -105,13 +109,16 @@ static IdString derive_name_from_cell_output_wire(const RTLIL::Cell *cell, strin RTLIL::Wire *wire; - if (move_to_cell && (!(wire = cell->module->wire(name)) || !(wire->port_input || wire->port_output))) - return name; + if (move_to_cell) { + IdString name_ref = cell->module->design->twines.find(name); + if (!(wire = cell->module->wire(name_ref)) || !(wire->port_input || wire->port_output)) + return cell->module->design->twines.add(std::move(name)); + } if (suffix.empty()) { suffix = cell->type.str(); } - return name + suffix; + return cell->module->design->twines.add(name + suffix); } static bool rename_witness(RTLIL::Design *design, dict &cache, RTLIL::Module *module) @@ -134,12 +141,12 @@ static bool rename_witness(RTLIL::Design *design, dict &ca bool witness_in_cell = rename_witness(design, cache, impl); has_witness_signals |= witness_in_cell; if (witness_in_cell && !cell->name.isPublic()) { - std::string name = cell->name.c_str() + 1; + std::string name = cell->name.str().substr(1); for (auto &c : name) if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_') c = '_'; auto new_id = module->uniquify("\\_witness_." + name); - cell->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 }); + cell->set_hdlname_attribute({ "_witness_", strstr(module->design->twines.str(new_id).c_str(), ".") + 1 }); renames.emplace_back(cell, new_id); } } @@ -156,13 +163,13 @@ static bool rename_witness(RTLIL::Design *design, dict &ca for (auto chunk : sig_out.chunks()) { if (chunk.is_wire() && !chunk.wire->name.isPublic()) { - std::string name = stringf("%s_%s", cell->type.c_str() + 1, cell->name.c_str() + 1); + std::string name = stringf("%s_%s", cell->type.str().substr(1), cell->name.str().substr(1)); for (auto &c : name) if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_') c = '_'; auto new_id = module->uniquify("\\_witness_." + name); auto new_wire = module->addWire(new_id, GetSize(sig_out)); - new_wire->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 }); + new_wire->set_hdlname_attribute({ "_witness_", strstr(module->design->twines.str(new_id).c_str(), ".") + 1 }); if (clk2fflogic) module->connect({new_wire, sig_out}); else @@ -178,13 +185,13 @@ static bool rename_witness(RTLIL::Design *design, dict &ca has_witness_signals = true; if (cell->name.isPublic()) continue; - std::string name = stringf("%s_%s", cell->type.c_str() + 1, cell->name.c_str() + 1); + std::string name = stringf("%s_%s", cell->type.str().substr(1), cell->name.str().substr(1)); for (auto &c : name) if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_') c = '_'; auto new_id = module->uniquify("\\_witness_." + name); renames.emplace_back(cell, new_id); - cell->set_hdlname_attribute({ "_witness_", strstr(new_id.c_str(), ".") + 1 }); + cell->set_hdlname_attribute({ "_witness_", strstr(module->design->twines.str(new_id).c_str(), ".") + 1 }); } } for (auto rename : renames) { @@ -389,12 +396,12 @@ struct RenamePass : public Pass { dict new_cell_names; for (auto wire : module->selected_wires()) - if (wire->name[0] == '$') - new_wire_names.emplace(wire, derive_name_from_src(wire->get_src_attribute(), counter++)); + if (!wire->name.isPublic()) + new_wire_names.emplace(wire, module->design->twines.add(derive_name_from_src(wire->get_src_attribute(), counter++))); for (auto cell : module->selected_cells()) - if (cell->name[0] == '$') - new_cell_names.emplace(cell, derive_name_from_src(cell->get_src_attribute(), counter++)); + if (!cell->name.isPublic()) + new_cell_names.emplace(cell, module->design->twines.add(derive_name_from_src(cell->get_src_attribute(), counter++))); for (auto &it : new_wire_names) module->rename(it.first, it.second); @@ -411,7 +418,7 @@ struct RenamePass : public Pass { for (auto module : design->selected_modules()) { dict new_cell_names; for (auto cell : module->selected_cells()) - if (cell->name[0] == '$') + if (!cell->name.isPublic()) new_cell_names[cell] = derive_name_from_cell_output_wire(cell, cell_suffix, flag_move_to_cell); for (auto &[cell, new_name] : new_cell_names) { if (flag_move_to_cell) { @@ -421,13 +428,12 @@ struct RenamePass : public Pass { if (wire_suffix.empty()) { for (auto const &[port, _] : cell->connections()) { if (cell->output(port)) { - wire_suffix += stringf("%s.%s", cell->type, port.c_str() + 1); + wire_suffix += stringf("%s.%s", cell->type, module->design->twines.str(port).c_str() + 1); break; } } } - IdString new_wire_name = found_wire->name.str() + wire_suffix; - module->rename(found_wire, new_wire_name); + module->rename(found_wire, found_wire->name.unescape() + wire_suffix); } } module->rename(cell, new_name); @@ -446,19 +452,19 @@ struct RenamePass : public Pass { dict new_cell_names; for (auto wire : module->selected_wires()) - if (wire->name[0] == '$') { - RTLIL::IdString buf; + if (!wire->name.isPublic()) { + std::string buf; do buf = stringf("\\%s%d%s", pattern_prefix, counter++, pattern_suffix); - while (module->wire(buf) != nullptr); - new_wire_names[wire] = buf; + while (module->wire(design->twines.find(buf)) != nullptr); + new_wire_names[wire] = design->twines.add(std::move(buf)); } for (auto cell : module->selected_cells()) - if (cell->name[0] == '$') { - RTLIL::IdString buf; + if (!cell->name.isPublic()) { + std::string buf; do buf = stringf("\\%s%d%s", pattern_prefix, counter++, pattern_suffix); - while (module->cell(buf) != nullptr); - new_cell_names[cell] = buf; + while (module->cell(design->twines.find(buf)) != nullptr); + new_cell_names[cell] = design->twines.add(std::move(buf)); } for (auto &it : new_wire_names) @@ -493,11 +499,11 @@ struct RenamePass : public Pass { for (auto wire : module->selected_wires()) if (wire->name.isPublic() && wire->port_id == 0) - new_wire_names[wire] = NEW_ID; + new_wire_names[wire] = module->design->twines.add(NEW_ID); for (auto cell : module->selected_cells()) if (cell->name.isPublic()) - new_cell_names[cell] = NEW_ID; + new_cell_names[cell] = module->design->twines.add(NEW_ID); for (auto &it : new_wire_names) module->rename(it.first, it.second); @@ -512,13 +518,13 @@ struct RenamePass : public Pass { if (argidx+1 != args.size()) log_cmd_error("Invalid number of arguments!\n"); - IdString new_name = RTLIL::escape_id(args[argidx]); + IdString new_name = design->twines.add(std::string{RTLIL::escape_id(args[argidx])}); RTLIL::Module *module = design->top_module(); if (module == nullptr) log_cmd_error("No top module found!\n"); - log("Renaming module %s to %s.\n", module, new_name.unescape()); + log("Renaming module %s to %s.\n", module, PooledName(design, new_name).unescape()); design->rename(module, new_name); } else @@ -542,12 +548,12 @@ struct RenamePass : public Pass { for (auto wire : module->selected_wires()) if (wire->port_id == 0) { seed = mkhash_xorshift(seed); - new_wire_names[wire] = stringf("$_%u_", seed); + new_wire_names[wire] = module->design->twines.add(stringf("$_%u_", seed)); } for (auto cell : module->selected_cells()) { seed = mkhash_xorshift(seed); - new_cell_names[cell] = stringf("$_%u_", seed); + new_cell_names[cell] = module->design->twines.add(stringf("$_%u_", seed)); } for (auto &it : new_wire_names) @@ -574,7 +580,7 @@ struct RenamePass : public Pass { if (!VERILOG_BACKEND::id_is_verilog_escaped(name)) continue; new_wire_names[wire] = module->uniquify("\\" + renamed_unescaped(name)); - auto new_name = new_wire_names[wire].str().substr(1); + auto new_name = module->design->twines.str(new_wire_names[wire]).substr(1); if (VERILOG_BACKEND::id_is_verilog_escaped(new_name)) log_error("Failed to rename wire %s -> %s\n", name, new_name); } @@ -587,7 +593,7 @@ struct RenamePass : public Pass { if (!VERILOG_BACKEND::id_is_verilog_escaped(name)) continue; new_cell_names[cell] = module->uniquify("\\" + renamed_unescaped(name)); - auto new_name = new_cell_names[cell].str().substr(1); + auto new_name = module->design->twines.str(new_cell_names[cell]).substr(1); if (VERILOG_BACKEND::id_is_verilog_escaped(new_name)) log_error("Failed to rename cell %s -> %s\n", name, new_name); } @@ -609,7 +615,7 @@ struct RenamePass : public Pass { std::string from_name = args[argidx++]; std::string to_name = args[argidx++]; - if (!design->selected_active_module.empty()) + if (design->selected_active_module != IdString::Null) { if (design->module(design->selected_active_module) != nullptr) rename_in_module(design->module(design->selected_active_module), from_name, to_name, flag_output); @@ -620,11 +626,13 @@ struct RenamePass : public Pass { log_cmd_error("Mode -output requires that there is an active module selected.\n"); RTLIL::Module *module_to_rename = nullptr; - for (auto module : design->modules()) - if (module->name == from_name || module->name.unescape() == from_name) { + for (auto module : design->modules()) { + std::string module_name_str = module->name.str(); + if (module_name_str == from_name || RTLIL::unescape_id(module_name_str) == from_name) { module_to_rename = module; break; } + } if (module_to_rename != nullptr) { to_name = RTLIL::escape_id(to_name); diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 76b323338..1e3badce9 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -17,6 +17,8 @@ * */ +#include "kernel/rtlil.h" +#include "kernel/twine.h" #include "kernel/yosys.h" #include "kernel/newcelltypes.h" #include "kernel/sigtools.h" @@ -27,14 +29,14 @@ PRIVATE_NAMESPACE_BEGIN static std::vector work_stack; -static bool match_ids(RTLIL::IdString id, const std::string &pattern) +static bool match_ids(const std::string &id, const std::string &pattern) { if (id == pattern) return true; const char *id_c = id.c_str(); const char *pat_c = pattern.c_str(); - size_t id_size = strlen(id_c); + size_t id_size = id.size(); size_t pat_size = pattern.size(); if (*id_c == '\\' && id_size == 1 + pat_size && memcmp(id_c + 1, pat_c, pat_size) == 0) @@ -103,39 +105,44 @@ static bool match_attr_val(const RTLIL::Const &value, const std::string &pattern log_abort(); } -static bool match_attr(const dict &attributes, const std::string &name_pat, const std::string &value_pat, char match_op) +static bool match_attr(const TwinePool &pool, const dict &attributes, const std::string &name_pat, const std::string &value_pat, char match_op) { if (name_pat.find('*') != std::string::npos || name_pat.find('?') != std::string::npos || name_pat.find('[') != std::string::npos) { for (auto &it : attributes) { - if (patmatch(name_pat.c_str(), it.first.c_str()) && match_attr_val(it.second, value_pat, match_op)) + std::string name = pool.str(it.first); + if (patmatch(name_pat.c_str(), name.c_str()) && match_attr_val(it.second, value_pat, match_op)) return true; - if (it.first.size() > 0 && it.first[0] == '\\' && patmatch(name_pat.c_str(), it.first.substr(1).c_str()) && match_attr_val(it.second, value_pat, match_op)) + if (name.size() > 0 && name[0] == '\\' && patmatch(name_pat.c_str(), name.c_str() + 1) && match_attr_val(it.second, value_pat, match_op)) return true; } } else { - if (name_pat.size() > 0 && (name_pat[0] == '\\' || name_pat[0] == '$') && attributes.count(name_pat) && match_attr_val(attributes.at(name_pat), value_pat, match_op)) - return true; - if (attributes.count("\\" + name_pat) && match_attr_val(attributes.at("\\" + name_pat), value_pat, match_op)) + if (name_pat.size() > 0 && (name_pat[0] == '\\' || name_pat[0] == '$')) { + IdString key = pool.find(name_pat); + if (key != IdString::Null && attributes.count(key) && match_attr_val(attributes.at(key), value_pat, match_op)) + return true; + } + IdString key = pool.find("\\" + name_pat); + if (key != IdString::Null && attributes.count(key) && match_attr_val(attributes.at(key), value_pat, match_op)) return true; } return false; } -static bool match_attr(const dict &attributes, const std::string &match_expr) +static bool match_attr(const TwinePool &pool, const dict &attributes, const std::string &match_expr) { size_t pos = match_expr.find_first_of(""); if (pos != std::string::npos) { if (match_expr.compare(pos, 2, "!=") == 0) - return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '!'); + return match_attr(pool, attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '!'); if (match_expr.compare(pos, 2, "<=") == 0) - return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '['); + return match_attr(pool, attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), '['); if (match_expr.compare(pos, 2, ">=") == 0) - return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), ']'); - return match_attr(attributes, match_expr.substr(0, pos), match_expr.substr(pos+1), match_expr[pos]); + return match_attr(pool, attributes, match_expr.substr(0, pos), match_expr.substr(pos+2), ']'); + return match_attr(pool, attributes, match_expr.substr(0, pos), match_expr.substr(pos+1), match_expr[pos]); } - return match_attr(attributes, match_expr, std::string(), 0); + return match_attr(pool, attributes, match_expr, std::string(), 0); } static void select_all(RTLIL::Design *design, RTLIL::Selection &lhs) @@ -466,11 +473,11 @@ static void select_op_intersect(RTLIL::Design *design, RTLIL::Selection &lhs, co namespace { struct expand_rule_t { char mode; - std::set cell_types, port_names; + std::set cell_types, port_names; }; } -static int parse_comma_list(std::set &tokens, const std::string &str, size_t pos, std::string stopchar) +static int parse_comma_list(std::set &tokens, const std::string &str, size_t pos, std::string stopchar) { stopchar += ','; while (1) { @@ -517,6 +524,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v } } + auto &twines = design->twines; for (auto cell : mod->cells()) for (auto &conn : cell->connections()) { @@ -527,7 +535,7 @@ static int select_op_expand(RTLIL::Design *design, RTLIL::Selection &lhs, std::v last_mode = rule.mode; if (rule.cell_types.size() > 0 && rule.cell_types.count(cell->type) == 0) continue; - if (rule.port_names.size() > 0 && rule.port_names.count(conn.first) == 0) + if (rule.port_names.size() > 0 && rule.port_names.count(twines.str(conn.first)) == 0) continue; if (rule.mode == '+') goto include_match; @@ -610,14 +618,15 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char std::string str = arg.substr(pos, endpos-pos); if (str[0] == '@') { str = RTLIL::escape_id(str.substr(1)); - if (design->selection_vars.count(str) > 0) { - for (auto i1 : design->selection_vars.at(str).selected_members) + IdString sel_name = design->twines.find(str); + if (sel_name != IdString::Null && design->selection_vars.count(sel_name) > 0) { + for (auto i1 : design->selection_vars.at(sel_name).selected_members) for (auto i2 : i1.second) limits.insert(i2); } else log_cmd_error("Selection %s is not defined!\n", RTLIL::unescape_id(str)); } else - limits.insert(RTLIL::escape_id(str)); + limits.insert(design->twines.add(RTLIL::escape_id(str))); } pos = endpos; } @@ -661,7 +670,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &sel) { - if (design->selected_active_module.empty()) + if (design->selected_active_module == IdString::Null) return; if (sel.full_selection) { @@ -810,8 +819,9 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (arg[0] == '@') { std::string set_name = RTLIL::escape_id(arg.substr(1)); - if (design->selection_vars.count(set_name) > 0) - work_stack.push_back(design->selection_vars[set_name]); + IdString set_twine = design->twines.find(set_name); + if (set_twine != IdString::Null && design->selection_vars.count(set_twine) > 0) + work_stack.push_back(design->selection_vars[set_twine]); else log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name)); select_filter_active_mod(design, work_stack.back()); @@ -824,8 +834,8 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp select_blackboxes = true; } - if (!design->selected_active_module.empty()) { - arg_mod = design->selected_active_module; + if (design->selected_active_module != IdString::Null) { + arg_mod = design->twines.str(design->selected_active_module); arg_memb = arg; if (!isprefixed(arg_memb)) arg_memb_found[arg_memb] = false; @@ -864,7 +874,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp continue; if (arg_mod.compare(0, 2, "A:") == 0) { - if (!match_attr(mod->attributes, arg_mod.substr(2))) + if (!match_attr(design->twines, mod->attributes, arg_mod.substr(2))) continue; } else if (arg_mod.compare(0, 2, "N:") == 0) { @@ -920,7 +930,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp } else if (arg_memb.compare(0, 2, "m:") == 0) { for (auto &it : mod->memories) - if (match_ids(it.first, arg_memb.substr(2))) + if (match_ids(design->twines.str(it.first), arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "c:") == 0) { @@ -931,10 +941,11 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (arg_memb.compare(0, 2, "t:") == 0) { if (arg_memb.compare(2, 1, "@") == 0) { std::string set_name = RTLIL::escape_id(arg_memb.substr(3)); - if (!design->selection_vars.count(set_name)) + IdString set_twine = design->twines.find(set_name); + if (set_twine == IdString::Null || !design->selection_vars.count(set_twine)) log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name)); - auto &muster = design->selection_vars[set_name]; + auto &muster = design->selection_vars[set_twine]; for (auto cell : mod->cells()) if (muster.selected_modules.count(cell->type)) sel.selected_members[mod->name].insert(cell->name); @@ -946,26 +957,26 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp } else if (arg_memb.compare(0, 2, "p:") == 0) { for (auto &it : mod->processes) - if (match_ids(it.first, arg_memb.substr(2))) + if (match_ids(design->twines.str(it.first), arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "a:") == 0) { for (auto wire : mod->wires()) - if (match_attr(wire->attributes, arg_memb.substr(2))) + if (match_attr(design->twines, wire->attributes, arg_memb.substr(2))) sel.selected_members[mod->name].insert(wire->name); for (auto &it : mod->memories) - if (match_attr(it.second->attributes, arg_memb.substr(2))) + if (match_attr(design->twines, it.second->attributes, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); for (auto cell : mod->cells()) - if (match_attr(cell->attributes, arg_memb.substr(2))) + if (match_attr(design->twines, cell->attributes, arg_memb.substr(2))) sel.selected_members[mod->name].insert(cell->name); for (auto &it : mod->processes) - if (match_attr(it.second->attributes, arg_memb.substr(2))) + if (match_attr(design->twines, it.second->attributes, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "r:") == 0) { for (auto cell : mod->cells()) - if (match_attr(cell->parameters, arg_memb.substr(2))) + if (match_attr(design->twines, cell->parameters, arg_memb.substr(2))) sel.selected_members[mod->name].insert(cell->name); } else { std::string orig_arg_memb = arg_memb; @@ -977,7 +988,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp arg_memb_found[orig_arg_memb] = true; } for (auto &it : mod->memories) - if (match_ids(it.first, arg_memb)) { + if (match_ids(design->twines.str(it.first), arg_memb)) { sel.selected_members[mod->name].insert(it.first); arg_memb_found[orig_arg_memb] = true; } @@ -987,7 +998,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp arg_memb_found[orig_arg_memb] = true; } for (auto &it : mod->processes) - if (match_ids(it.first, arg_memb)) { + if (match_ids(design->twines.str(it.first), arg_memb)) { sel.selected_members[mod->name].insert(it.first); arg_memb_found[orig_arg_memb] = true; } @@ -1022,7 +1033,7 @@ static std::string describe_selection_for_assert(RTLIL::Design *design, RTLIL::S if (whole_modules && sel->selected_whole_module(mod->name)) desc += stringf("%s\n", mod); for (auto it : mod->selected_members()) - desc += stringf("%s/%s\n", mod, it); + desc += stringf("%s/%s\n", mod, design->obj_name(it).c_str()); } if (push_selection) design->pop_selection(); return desc; @@ -1344,6 +1355,7 @@ struct SelectPass : public Pass { work_stack.clear(); + std::optional search; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -1410,10 +1422,13 @@ struct SelectPass : public Pass { continue; } if (arg == "-module" && argidx+1 < args.size()) { - RTLIL::IdString mod_name = RTLIL::escape_id(args[++argidx]); - if (design->module(mod_name) == nullptr) - log_cmd_error("No such module: %s\n", mod_name.unescape()); - design->selected_active_module = mod_name.str(); + std::string mod_name = RTLIL::escape_id(args[++argidx]); + if (!search) + search.emplace(&design->twines); + IdString t = search->find(mod_name); + if (t == IdString::Null || design->module(t) == nullptr) + log_cmd_error("No such module: %s\n", RTLIL::unescape_id(mod_name)); + design->selected_active_module = t; got_module = true; continue; } @@ -1452,9 +1467,15 @@ struct SelectPass : public Pass { log_warning("Ignoring line without slash in 'select -read': %s\n", line); continue; } - IdString mod_name = RTLIL::escape_id(line.substr(0, slash_pos)); - IdString obj_name = RTLIL::escape_id(line.substr(slash_pos+1)); - sel.selected_members[mod_name].insert(obj_name); + std::string mod_name = RTLIL::escape_id(line.substr(0, slash_pos)); + std::string obj_name = RTLIL::escape_id(line.substr(slash_pos+1)); + if (!search) + search.emplace(&design->twines); + IdString mod_ref = search->find(mod_name); + IdString obj_ref = search->find(obj_name); + if (mod_ref == IdString::Null || obj_ref == IdString::Null) + continue; + sel.selected_members[mod_ref].insert(obj_ref); } select_filter_active_mod(design, sel); @@ -1498,7 +1519,7 @@ struct SelectPass : public Pass { if (clear_mode) { design->selection() = RTLIL::Selection::FullSelection(design); - design->selected_active_module = std::string(); + design->selected_active_module = IdString::Null; return; } @@ -1528,7 +1549,7 @@ struct SelectPass : public Pass { log("%s\n", mod); if (!list_mod_mode) for (auto it : mod->selected_members()) - LOG_OBJECT("%s/%s\n", mod->name.unescape().c_str(), it->name.unescape().c_str()) + LOG_OBJECT("%s/%s\n", mod->name.unescape().c_str(), mod->design->twines.unescaped_str(it->name_).c_str()) } if (count_mode) { @@ -1633,16 +1654,18 @@ struct SelectPass : public Pass { if (!set_name.empty()) { + IdString set_twine = design->twines.add(std::string(set_name)); if (work_stack.size() == 0) - design->selection_vars[set_name] = RTLIL::Selection::EmptySelection(design); + design->selection_vars[set_twine] = RTLIL::Selection::EmptySelection(design); else - design->selection_vars[set_name] = work_stack.back(); + design->selection_vars[set_twine] = work_stack.back(); return; } if (!unset_name.empty()) { - if (!design->selection_vars.erase(unset_name)) + IdString unset_twine = design->twines.find(unset_name); + if (unset_twine == IdString::Null || !design->selection_vars.erase(unset_twine)) log_error("Selection '%s' does not exist!\n", unset_name); return; } @@ -1652,10 +1675,10 @@ struct SelectPass : public Pass { if (sel.full_selection) log("*\n"); for (auto &it : sel.selected_modules) - log("%s\n", it.unescape()); + log("%s\n", PooledName(design, it).unescape()); for (auto &it : sel.selected_members) for (auto &it2 : it.second) - log("%s/%s\n", it.first.unescape(), it2.unescape()); + log("%s/%s\n", PooledName(design, it.first).unescape(), PooledName(design, it2).unescape()); return; } @@ -1707,18 +1730,19 @@ struct CdPass : public Pass { if (args.size() == 1 || args[1] == "/") { design->pop_selection(); design->push_full_selection(); - design->selected_active_module = std::string(); + design->selected_active_module = IdString::Null; return; } if (args[1] == "..") { - string modname = design->selected_active_module; + string modname = design->twines.str(design->selected_active_module); design->pop_selection(); design->push_full_selection(); - design->selected_active_module = std::string(); + design->selected_active_module = IdString::Null; + TwineSearch search(&design->twines); while (1) { size_t pos = modname.rfind('.'); @@ -1727,12 +1751,13 @@ struct CdPass : public Pass { break; modname = modname.substr(0, pos); - Module *mod = design->module(modname); + IdString mod_ref = search.find(modname); + Module *mod = design->module(mod_ref); if (mod == nullptr) continue; - design->selected_active_module = modname; + design->selected_active_module = mod_ref; design->pop_selection(); design->push_full_selection(); select_filter_active_mod(design, design->selection()); @@ -1743,12 +1768,14 @@ struct CdPass : public Pass { return; } - std::string modname = RTLIL::escape_id(args[1]); + TwineSearch search(&design->twines); + IdString modname = search.find(RTLIL::escape_id(args[1])); - if (design->module(modname) == nullptr && !design->selected_active_module.empty()) { + if (design->module(modname) == nullptr && design->selected_active_module != IdString::Null) { RTLIL::Module *module = design->module(design->selected_active_module); - if (module != nullptr && module->cell(modname) != nullptr) - modname = module->cell(modname)->type.str(); + IdString cell_ref = modname; + if (module != nullptr && cell_ref != IdString::Null && module->cell(cell_ref) != nullptr) + modname = module->cell(cell_ref)->type; } if (design->module(modname) != nullptr) { @@ -1760,7 +1787,7 @@ struct CdPass : public Pass { return; } - log_cmd_error("No such module `%s' found!\n", RTLIL::unescape_id(modname)); + log_cmd_error("No such module `%s' found!\n", PooledName(design, modname).unescape()); } } CdPass; @@ -1775,9 +1802,12 @@ static void log_matches(const char *title, Module *module, const T &list) if (!matches.empty()) { log("\n%d %s:\n", int(matches.size()), title); - std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str()); - for (auto id : matches) - log(" %s\n", id.unescape()); + auto &twines = module->design->twines; + std::sort(matches.begin(), matches.end(), [&](IdString a, IdString b) { + return twines.str(a) < twines.str(b); + }); + for (auto ref : matches) + log(" %s\n", twines.unescaped_str(ref).c_str()); } } @@ -1804,7 +1834,7 @@ struct LsPass : public Pass { size_t argidx = 1; extra_args(args, argidx, design); - if (design->selected_active_module.empty()) + if (design->selected_active_module == IdString::Null) { std::vector matches; @@ -1813,9 +1843,9 @@ struct LsPass : public Pass { if (!matches.empty()) { log("\n%d %s:\n", int(matches.size()), "modules"); - std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str()); + std::sort(matches.begin(), matches.end(), RTLIL::sort_by_id_str(design->twines)); for (auto id : matches) - log(" %s%s\n", id.unescape(), design->selected_whole_module(design->module(id)) ? "" : "*"); + log(" %s%s\n", PooledName(design, id).unescape(), design->selected_whole_module(design->module(id)) ? "" : "*"); } } else diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index aae6983e2..8d8442007 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -26,7 +26,7 @@ PRIVATE_NAMESPACE_BEGIN struct setunset_t { - RTLIL::IdString name; + std::string name; RTLIL::Const value; bool unset; @@ -46,13 +46,15 @@ struct setunset_t } }; -static void do_setunset(dict &attrs, const std::vector &list) +static void do_setunset(RTLIL::Design *design, dict &attrs, const std::vector &list) { for (auto &item : list) - if (item.unset) - attrs.erase(item.name); - else - attrs[item.name] = item.value; + if (item.unset) { + IdString name = design->twines.find(item.name); + if (name != IdString::Null) + attrs.erase(name); + } else + attrs[design->twines.add(std::string(item.name))] = item.value; } struct SetattrPass : public Pass { @@ -101,12 +103,12 @@ struct SetattrPass : public Pass { { if (flag_mod) { if (module->is_selected_whole()) - do_setunset(module->attributes, setunset_list); + do_setunset(design, module->attributes, setunset_list); continue; } for (auto memb : module->selected_members()) - do_setunset(memb->attributes, setunset_list); + do_setunset(design, memb->attributes, setunset_list); } } } SetattrPass; @@ -187,8 +189,8 @@ struct SetparamPass : public Pass { { for (auto cell : module->selected_cells()) { if (!new_cell_type.empty()) - cell->type = new_cell_type; - do_setunset(cell->parameters, setunset_list); + cell->type = cell->module->design->twines.add(new_cell_type); + do_setunset(design, cell->parameters, setunset_list); } } } @@ -234,14 +236,15 @@ struct ChparamPass : public Pass { break; } + TwineSearch search(&design->twines); for (int i = argidx; i < GetSize(args); i++) - if (design->module("$abstract\\" + args[i]) != nullptr && - design->module(RTLIL::escape_id(args[i])) == nullptr) + if (design->module(search.find("$abstract\\" + args[i])) != nullptr && + design->module(search.find(RTLIL::escape_id(args[i]))) == nullptr) args[i] = "$abstract\\" + args[i]; extra_args(args, argidx, design); - do_setunset(new_parameters, setunset_list); + do_setunset(design, new_parameters, setunset_list); if (list_mode) { if (!new_parameters.empty()) @@ -249,7 +252,7 @@ struct ChparamPass : public Pass { for (auto module : design->selected_modules()) { log("%s:\n", module); for (auto param : module->avail_parameters) - log(" %s\n", param.unescape()); + log(" %s\n", PooledName(design, param).unescape()); } return; } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index aa0add992..802ba5fbe 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -17,6 +17,7 @@ * */ +#include "kernel/rtlil.h" #include "kernel/yosys.h" #include "kernel/celltypes.h" #include "kernel/log_help.h" @@ -48,7 +49,7 @@ struct ShowWorker vector dot_escape_store; std::map dot_id2num_store; - std::map autonames; + std::map autonames; int single_idx_count; struct net_conn { std::set> in, out; std::string color; }; @@ -56,6 +57,7 @@ struct ShowWorker FILE *f; RTLIL::Design *design; + TwineSearch search; RTLIL::Module *module; uint32_t currentColor; bool genWidthLabels; @@ -146,16 +148,16 @@ struct ShowWorker return ""; } - std::string findColor(IdString member_name) + std::string findColor(IdString member_ref) { for (auto &s : color_selections) - if (s.second.selected_member(module->name, member_name)) { + if (member_ref != IdString::Null && s.second.selected_member(module->name, member_ref)) { return stringf("color=\"%s\", fontcolor=\"%s\"", s.first, s.first); } RTLIL::Const colorattr_value; - RTLIL::Cell *cell = module->cell(member_name); - RTLIL::Wire *wire = module->wire(member_name); + RTLIL::Cell *cell = member_ref != IdString::Null ? module->cell(member_ref) : nullptr; + RTLIL::Wire *wire = member_ref != IdString::Null ? module->wire(member_ref) : nullptr; if (cell && cell->attributes.count(colorattr)) colorattr_value = cell->attributes.at(colorattr); @@ -174,8 +176,9 @@ struct ShowWorker const char *findLabel(std::string member_name) { + IdString member_ref = search.find(member_name); for (auto &s : label_selections) - if (s.second.selected_member(module->name, member_name)) + if (member_ref != IdString::Null && s.second.selected_member(module->name, member_ref)) return escape(s.first); return escape(member_name, true); } @@ -478,19 +481,22 @@ struct ShowWorker out_ports.push_back(conn.first); } - std::sort(in_ports.begin(), in_ports.end(), RTLIL::sort_by_id_str()); - std::sort(out_ports.begin(), out_ports.end(), RTLIL::sort_by_id_str()); + std::sort(in_ports.begin(), in_ports.end(), RTLIL::sort_by_id_str(design->twines)); + std::sort(out_ports.begin(), out_ports.end(), RTLIL::sort_by_id_str(design->twines)); for (auto &p : in_ports) { - bool signed_suffix = genSignedLabels && cell->hasParam(p.str() + "_SIGNED") - && cell->getParam(p.str() + "_SIGNED").as_bool(); + std::string p_str = design->twines.str(p); + IdString signed_param = design->twines.find(p_str + "_SIGNED"); + bool signed_suffix = genSignedLabels && signed_param != IdString::Null + && cell->hasParam(signed_param) + && cell->getParam(signed_param).as_bool(); - in_label_pieces.push_back(stringf(" %s%s", id2num(p), escape(p.str()), + in_label_pieces.push_back(stringf(" %s%s", id2num(p), escape(p_str), signed_suffix ? "*" : "")); } for (auto &p : out_ports) - out_label_pieces.push_back(stringf(" %s", id2num(p), escape(p.str()))); + out_label_pieces.push_back(stringf(" %s", id2num(p), escape(design->twines.str(p)))); std::string in_label = join_label_pieces(in_label_pieces); std::string out_label = join_label_pieces(out_label_pieces); @@ -523,7 +529,7 @@ struct ShowWorker { RTLIL::Process *proc = it.second; - if (!design->selected_member(module->name, proc->name)) + if (!design->selected_member(module->name, it.first)) continue; std::set input_signals, output_signals; @@ -624,7 +630,7 @@ struct ShowWorker const std::string wireshape, bool genSignedLabels, bool stretchIO, bool enumerateIds, bool abbreviateIds, bool notitle, bool href, const std::vector> &color_selections, const std::vector> &label_selections, RTLIL::IdString colorattr) : - f(f), design(design), currentColor(colorSeed), genWidthLabels(genWidthLabels), wireshape(wireshape), + f(f), design(design), search(&design->twines), currentColor(colorSeed), genWidthLabels(genWidthLabels), wireshape(wireshape), genSignedLabels(genSignedLabels), stretchIO(stretchIO), enumerateIds(enumerateIds), abbreviateIds(abbreviateIds), notitle(notitle), href(href), color_selections(color_selections), label_selections(label_selections), colorattr(colorattr) { @@ -836,7 +842,7 @@ struct ShowPass : public Pass { continue; } if (arg == "-colorattr" && argidx+1 < args.size()) { - colorattr = RTLIL::escape_id(args[++argidx]); + colorattr = design->twines.add(RTLIL::escape_id(args[++argidx])); continue; } if (arg == "-format" && argidx+1 < args.size()) { diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 4526bc1f6..68b0a1f45 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -23,10 +23,10 @@ #include "kernel/cost.h" #include "kernel/gzip.h" #include "kernel/log_help.h" +#include "kernel/rtlil.h" #include "kernel/yosys.h" #include "libs/json11/json11.hpp" #include "passes/techmap/libparse.h" -#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -59,18 +59,19 @@ struct statdata_t { double local_sequential_area = 0; double submodule_area = 0; int num_submodules = 0; - std::map num_submodules_by_type; - std::map submodules_area_by_type; + std::map num_submodules_by_type; + std::map submodules_area_by_type; - std::map local_num_cells_by_type; - std::map local_area_cells_by_type; - std::map local_seq_area_cells_by_type; + std::map local_num_cells_by_type; + std::map local_area_cells_by_type; + std::map local_seq_area_cells_by_type; string tech; - std::map num_cells_by_type; - std::map area_cells_by_type; - std::map seq_area_cells_by_type; - std::set unknown_cell_area; + std::map num_cells_by_type_raw; + std::map num_cells_by_type; + std::map area_cells_by_type; + std::map seq_area_cells_by_type; + std::set unknown_cell_area; statdata_t operator+(const statdata_t &other) const { @@ -80,6 +81,8 @@ struct statdata_t { #undef X for (auto &it : num_cells_by_type) sum.num_cells_by_type[it.first] += it.second; + for (auto &it : num_cells_by_type_raw) + sum.num_cells_by_type_raw[it.first] += it.second; return sum; } statdata_t operator*(unsigned int other) const @@ -88,6 +91,8 @@ struct statdata_t { #define X(_name) sum._name *= other; STAT_NUMERIC_MEMBERS #undef X + for (auto &it : sum.num_cells_by_type_raw) + it.second *= other; for (auto &it : sum.num_cells_by_type) it.second *= other; return sum; @@ -103,6 +108,12 @@ struct statdata_t { else num_cells_by_type[it.first] = it.second; } + for (auto &it : other.num_cells_by_type_raw) { + if (num_cells_by_type_raw.count(it.first)) + num_cells_by_type_raw[it.first] += it.second; + else + num_cells_by_type_raw[it.first] = it.second; + } for (auto &it : other.submodules_area_by_type) { if (submodules_area_by_type.count(it.first)) submodules_area_by_type[it.first] += it.second; @@ -141,7 +152,7 @@ struct statdata_t { } } - statdata_t(const RTLIL::Design *design, const RTLIL::Module *mod, bool width_mode, dict &cell_area, string techname) + statdata_t(RTLIL::Design *design, const RTLIL::Module *mod, bool width_mode, dict &cell_area, string techname) { tech = techname; @@ -183,9 +194,9 @@ struct statdata_t { local_num_memory_bits += it.second->width * it.second->size; } for (auto cell : mod->selected_cells()) { - RTLIL::IdString cell_type = cell->type; + std::string cell_type = cell->type.str(); if (width_mode) { - if (cell_type.in(ID($not), ID($pos), ID($neg), ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_and), + if (cell->type.in(ID($not), ID($pos), ID($neg), ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($lut), ID($and), ID($or), ID($xor), ID($xnor), 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), @@ -194,15 +205,15 @@ struct statdata_t { 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, max({width_a, width_b, width_y})); - } else if (cell_type.in(ID($mux))) + } else if (cell->type.in(ID($mux))) cell_type = stringf("%s_%d", cell_type, GetSize(cell->getPort(ID::Y))); - else if (cell_type.in(ID($bmux), ID($pmux))) + else if (cell->type.in(ID($bmux), ID($pmux))) cell_type = stringf("%s_%d_%d", cell_type, GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S))); - else if (cell_type == ID($demux)) + else if (cell->type == ID($demux)) cell_type = stringf("%s_%d_%d", cell_type, GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S))); - else if (cell_type.in(ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), + else if (cell->type.in(ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($aldff), ID($aldffe), ID($dlatch), ID($adlatch), ID($dlatchsr))) cell_type = stringf("%s_%d", cell_type, GetSize(cell->getPort(ID::Q))); @@ -249,7 +260,7 @@ struct statdata_t { } else if (it == "S") { port_name = ID::S; } else { - port_name = ID(it); + port_name = design->twines.add(std::string{it}); } if (cell->hasPort(port_name)) { int width = GetSize(cell->getPort(port_name)); @@ -311,6 +322,7 @@ struct statdata_t { } else { unknown_cell_area.insert(cell_type); num_cells++; + num_cells_by_type_raw[cell->type]++; num_cells_by_type[cell_type]++; local_num_cells++; local_num_cells_by_type[cell_type]++; @@ -321,6 +333,7 @@ struct statdata_t { } } else { num_cells++; + num_cells_by_type_raw[cell->type]++; num_cells_by_type[cell_type]++; area_cells_by_type[cell_type] = 0; seq_area_cells_by_type[cell_type] = 0; @@ -337,18 +350,16 @@ struct statdata_t { num_processes++; local_num_processes++; } - RTLIL::IdString cell_name = mod->name; - auto s = cell_name.str(); } unsigned int estimate_xilinx_lc() { - unsigned int lut6_cnt = num_cells_by_type[ID(LUT6)]; - unsigned int lut5_cnt = num_cells_by_type[ID(LUT5)]; - unsigned int lut4_cnt = num_cells_by_type[ID(LUT4)]; - unsigned int lut3_cnt = num_cells_by_type[ID(LUT3)]; - unsigned int lut2_cnt = num_cells_by_type[ID(LUT2)]; - unsigned int lut1_cnt = num_cells_by_type[ID(LUT1)]; + unsigned int lut6_cnt = num_cells_by_type[ID::str(ID::LUT6)]; + unsigned int lut5_cnt = num_cells_by_type[ID::str(ID::LUT5)]; + unsigned int lut4_cnt = num_cells_by_type[ID::str(ID::LUT4)]; + unsigned int lut3_cnt = num_cells_by_type[ID::str(ID::LUT3)]; + unsigned int lut2_cnt = num_cells_by_type[ID::str(ID::LUT2)]; + unsigned int lut1_cnt = num_cells_by_type[ID::str(ID::LUT1)]; unsigned int lc_cnt = 0; lc_cnt += lut6_cnt; @@ -398,7 +409,7 @@ struct statdata_t { unsigned int tran_cnt = 0; auto &gate_costs = CellCosts::cmos_gate_cost(); - for (auto it : num_cells_by_type) { + for (auto it : num_cells_by_type_raw) { auto ctype = it.first; auto cnum = it.second; @@ -505,7 +516,7 @@ struct statdata_t { } } - void log_data(RTLIL::IdString mod_name, bool top_mod, bool print_area = true, bool print_hierarchical = true, bool print_global_only = false) + void log_data(const std::string &mod_name, bool top_mod, bool print_area = true, bool print_hierarchical = true, bool print_global_only = false) { print_log_header(print_area, print_hierarchical, print_global_only); @@ -523,7 +534,7 @@ struct statdata_t { print_log_line("cells", local_num_cells, local_area, num_cells, area, 0, print_area, print_hierarchical, print_global_only); for (auto &it : num_cells_by_type) if (it.second) { - auto name = string(it.first.unescape()); + auto name = RTLIL::unescape_id(it.first); print_log_line(name, local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, area_cells_by_type.at(it.first), 1, print_area, print_hierarchical, print_global_only); @@ -533,7 +544,7 @@ struct statdata_t { print_global_only); for (auto &it : num_submodules_by_type) if (it.second) - print_log_line(string(it.first.unescape()), it.second, 0, it.second, + print_log_line(RTLIL::unescape_id(it.first), it.second, 0, it.second, submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0, 1, print_area, print_hierarchical, print_global_only); } @@ -607,7 +618,7 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %s", json11::Json(it.first.unescape()).dump(), + log(" %s: %s", json11::Json(RTLIL::unescape_id(it.first)).dump(), json_line(local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, area_cells_by_type.at(it.first)) @@ -621,7 +632,7 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %s", json11::Json(it.first.unescape()).dump(), + log(" %s: %s", json11::Json(RTLIL::unescape_id(it.first)).dump(), json_line(0, 0, it.second, submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0) .c_str()); @@ -662,14 +673,14 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); + log(" %s: %u", json11::Json(RTLIL::unescape_id(it.first)).dump(), it.second); first_line = false; } for (auto &it : num_submodules_by_type) if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); + log(" %s: %u", json11::Json(RTLIL::unescape_id(it.first)).dump(), it.second); first_line = false; } log("\n"); @@ -697,14 +708,14 @@ struct statdata_t { if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); + log(" %s: %u", json11::Json(RTLIL::unescape_id(it.first)).dump(), it.second); first_line = false; } for (auto &it : num_submodules_by_type) if (it.second) { if (!first_line) log(",\n"); - log(" %s: %u", json11::Json(it.first.unescape()).dump(), it.second); + log(" %s: %u", json11::Json(RTLIL::unescape_id(it.first)).dump(), it.second); first_line = false; } log("\n"); @@ -726,26 +737,27 @@ struct statdata_t { } }; -statdata_t hierarchy_worker(std::map &mod_stat, RTLIL::IdString mod, int level, bool quiet = false, bool has_area = true, +statdata_t hierarchy_worker(const TwineSearch &search, std::map &mod_stat, IdString mod, int level, bool quiet = false, bool has_area = true, bool hierarchy_mode = true) { statdata_t mod_data = mod_stat.at(mod); for (auto &it : mod_data.num_submodules_by_type) { - if (mod_stat.count(it.first) > 0) { + IdString sub = search.find(it.first); + if (sub != IdString::Null && mod_stat.count(sub) > 0) { if (!quiet) - mod_data.print_log_line(string(it.first.unescape()), mod_stat.at(it.first).local_num_cells, - mod_stat.at(it.first).local_area, mod_stat.at(it.first).num_cells, mod_stat.at(it.first).area, + mod_data.print_log_line(RTLIL::unescape_id(it.first), mod_stat.at(sub).local_num_cells, + mod_stat.at(sub).local_area, mod_stat.at(sub).num_cells, mod_stat.at(sub).area, level, has_area, hierarchy_mode); - hierarchy_worker(mod_stat, it.first, level + 1, quiet, has_area, hierarchy_mode) * it.second; + hierarchy_worker(search, mod_stat, sub, level + 1, quiet, has_area, hierarchy_mode) * it.second; } } return mod_data; } -statdata_t hierarchy_builder(const RTLIL::Design *design, const RTLIL::Module *top_mod, std::map &mod_stat, - bool width_mode, dict &cell_area, string techname) +statdata_t hierarchy_builder(RTLIL::Design *design, const RTLIL::Module *top_mod, std::map &mod_stat, + bool width_mode, dict &cell_area, string techname) { if (top_mod == nullptr) top_mod = design->top_module(); @@ -797,7 +809,7 @@ statdata_t hierarchy_builder(const RTLIL::Design *design, const RTLIL::Module *t return mod_data; } -void read_liberty_cellarea(dict &cell_area, string liberty_file) +void read_liberty_cellarea(dict &cell_area, string liberty_file) { std::istream *f = uncompressed(liberty_file.c_str()); yosys_input_files.insert(liberty_file); @@ -928,7 +940,7 @@ struct StatPass : public Pass { bool width_mode = false, json_mode = false, hierarchy_mode = false; RTLIL::Module *top_mod = nullptr; std::map mod_stat; - dict cell_area; + dict cell_area; string techname; size_t argidx; @@ -948,9 +960,12 @@ struct StatPass : public Pass { continue; } if (args[argidx] == "-top" && argidx + 1 < args.size()) { - if (design->module(RTLIL::escape_id(args[argidx + 1])) == nullptr) + TwineSearch search(&design->twines); + IdString top_ref = search.find(RTLIL::escape_id(args[argidx + 1])); + if (design->module(top_ref) == nullptr) log_cmd_error("Can't find module %s.\n", args[argidx + 1]); - top_mod = design->module(RTLIL::escape_id(args[++argidx])); + top_mod = design->module(top_ref); + argidx++; continue; } if (args[argidx] == "-json") { @@ -1005,7 +1020,7 @@ struct StatPass : public Pass { top_mod = mod; statdata_t data = mod_stat.at(mod->name); if (json_mode) { - data.log_data_json(mod->name.c_str(), first_module, hierarchy_mode); + data.log_data_json(mod->name.str().c_str(), first_module, hierarchy_mode); first_module = false; } else { log("\n"); @@ -1031,7 +1046,8 @@ struct StatPass : public Pass { mod_stat[top_mod->name].area, 0, has_area, hierarchy_mode, true); } - statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0, /*quiet=*/json_mode, has_area, hierarchy_mode); + TwineSearch search(&design->twines); + statdata_t data = hierarchy_worker(search, mod_stat, top_mod->name, 0, /*quiet=*/json_mode, has_area, hierarchy_mode); if (json_mode) data.log_data_json("design", true, hierarchy_mode, true); diff --git a/passes/cmds/timeest.cc b/passes/cmds/timeest.cc index 80843aaee..dbffce5e9 100644 --- a/passes/cmds/timeest.cc +++ b/passes/cmds/timeest.cc @@ -116,7 +116,7 @@ struct EstimateSta { continue; } else { // find or build AIG model of combinational cell - auto fingerprint = std::make_pair(cell->type, cell->parameters); + auto fingerprint = std::make_pair(IdString(cell->type), cell->parameters); if (!aigs.count(fingerprint)) { aigs.emplace(fingerprint, Aig(cell)); if (aigs.at(fingerprint).name.empty()) { @@ -133,7 +133,7 @@ struct EstimateSta { // since we're now taking reference into `aigs`, we can no longer modify it // and thus have to fill `cell_aigs` in a separate loop for (auto cell : combinational) { - auto fingerprint = std::make_pair(cell->type, cell->parameters); + auto fingerprint = std::make_pair(IdString(cell->type), cell->parameters); cell_aigs.emplace(cell, &aigs.at(fingerprint)); } @@ -188,7 +188,7 @@ struct EstimateSta { assert(cell_aigs.count(cell)); Aig &aig = *cell_aigs.at(cell); for (auto &node : aig.nodes) { - if (!node.portname.empty()) { + if (node.portname != IdString{}) { topo.edge( desc_sig(cell->getPort(node.portname)[node.portbit]), desc_aig(cell, node) @@ -235,7 +235,7 @@ struct EstimateSta { if (aig_node) { Cell *cell = std::get<1>(node); Aig &aig = *cell_aigs.at(cell); - if (!aig_node->portname.empty()) { + if (aig_node->portname != IdString{}) { // for a cell port, copy `levels` value from port bit SigBit bit = cell->getPort(aig_node->portname)[aig_node->portbit]; levels[node] = levels[desc_sig(bit)]; @@ -294,7 +294,7 @@ struct EstimateSta { critical[node] = true; } - if (!aig_node->portname.empty()) { + if (aig_node->portname != IdString{}) { SigBit bit = cell->getPort(aig_node->portname)[aig_node->portbit]; if (critical.count(node)) critical[desc_sig(bit)] = true; @@ -359,7 +359,7 @@ struct EstimateSta { for (auto wire : m->wires()) { if (bits_to_select.check_any(sigmap(wire))) - to_select.insert(wire->name); + { IdString wn = wire->name; to_select.insert(wn); } } if (select) { @@ -420,16 +420,18 @@ struct TimeestPass : Pass { if (select && d->selected_modules().size() > 1) log_cmd_error("The -select option operates on a single selected module\n"); + TwineSearch search(&d->twines); for (auto m : d->selected_modules()) { std::optional clk; if (clk_domain_specified) { - if (!m->wire(RTLIL::escape_id(clk_name))) { + IdString clk_ref = search.find(RTLIL::escape_id(clk_name)); + if (!m->wire(clk_ref)) { log_warning("No domain '%s' in module %s\n", clk_name.c_str(), m); continue; } - clk = SigBit(m->wire(RTLIL::escape_id(clk_name)), 0); + clk = SigBit(m->wire(clk_ref), 0); } EstimateSta sta(m, clk, /*top_port_endpoints=*/ !clk_domain_specified); diff --git a/passes/cmds/wrapcell.cc b/passes/cmds/wrapcell.cc index d31710984..4d13f2dac 100644 --- a/passes/cmds/wrapcell.cc +++ b/passes/cmds/wrapcell.cc @@ -48,7 +48,7 @@ struct ContextData { std::string unused_outputs; }; -std::optional format_with_params(std::string fmt, const dict ¶meters, +std::optional format_with_params(const TwinePool &twines, std::string fmt, const dict ¶meters, const ContextData &context) { std::stringstream result; @@ -69,9 +69,10 @@ std::optional format_with_params(std::string fmt, const dictgetPort(port).size()) return port; - else if (len == 1) - return stringf("%s[%d]", port, base); - else - return stringf("%s[%d:%d]", port, base + len - 1, base); + auto &pool = cell->module->design->twines; + if (len == 1) + return pool.add(stringf("%s[%d]", pool.str(port).c_str(), base)); + return pool.add(stringf("%s[%d:%d]", pool.str(port).c_str(), base + len - 1, base)); } SigSpec sample(Cell *cell) @@ -113,7 +114,9 @@ struct Chunk { std::vector collect_chunks(std::vector> bits) { std::vector ret; - std::sort(bits.begin(), bits.end()); + std::sort(bits.begin(), bits.end(), [](const auto &a, const auto &b) { + return a.first.raw() < b.first.raw() || (a.first.raw() == b.first.raw() && a.second < b.second); + }); for (auto it = bits.begin(); it != bits.end();) { auto sep = it + 1; for (; sep != bits.end() && @@ -171,9 +174,9 @@ struct WrapcellPass : Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-setattr" && argidx+1 < args.size()) { - attributes.emplace_back(RTLIL::escape_id(args[++argidx]), ""); + attributes.emplace_back(d->twines.add(RTLIL::escape_id(args[++argidx])), ""); } else if (args[argidx] == "-formatattr" && argidx+2 < args.size()) { - IdString id = RTLIL::escape_id(args[++argidx]); + IdString id = d->twines.add(RTLIL::escape_id(args[++argidx])); attributes.emplace_back(id, args[++argidx]); } else if (args[argidx] == "-name" && argidx+1 < args.size()) { name_fmt = args[++argidx]; @@ -199,6 +202,7 @@ struct WrapcellPass : Pass { for (auto cell : module->selected_cells()) { Module *subm; Cell *subcell; + IdString name_ref; if (!ct.cell_known(cell->type)) log_error("Non-internal cell type '%s' on cell '%s' in module '%s' unsupported\n", @@ -219,20 +223,20 @@ struct WrapcellPass : Pass { if (!unused_outputs.empty()) { context.unused_outputs += "_unused"; for (auto chunk : collect_chunks(unused_outputs)) - context.unused_outputs += "_" + chunk.format(cell).unescape(); + context.unused_outputs += "_" + module->design->twines.unescaped_str(chunk.format(cell)); } - std::optional unescaped_name = format_with_params(name_fmt, cell->parameters, context); + std::optional unescaped_name = format_with_params(d->twines, name_fmt, cell->parameters, context); if (!unescaped_name) log_error("Formatting error when processing cell '%s' in module '%s'\n", cell, module); - IdString name = RTLIL::escape_id(unescaped_name.value()); - if (d->module(name)) + name_ref = d->twines.add(RTLIL::escape_id(unescaped_name.value())); + if (d->module(name_ref)) goto replace_cell; - subm = d->addModule(name); - subcell = subm->addCell("$1", cell->type); + subm = d->addModule(name_ref); + subcell = subm->addCell("$1", IdString(cell->type)); for (auto conn : cell->connections()) { if (ct.cell_output(cell->type, conn.first)) { // Insert marker bits as placehodlers which need to be replaced @@ -262,7 +266,7 @@ struct WrapcellPass : Pass { if (rule.value_fmt.empty()) { subm->set_bool_attribute(rule.name); } else { - std::optional value = format_with_params(rule.value_fmt, cell->parameters, context); + std::optional value = format_with_params(d->twines, rule.value_fmt, cell->parameters, context); if (!value) log_error("Formatting error when processing cell '%s' in module '%s'\n", @@ -284,7 +288,7 @@ struct WrapcellPass : Pass { for (auto chunk : collect_chunks(used_outputs)) new_connections[chunk.format(cell)] = chunk.sample(cell); - cell->type = name; + cell->type = name_ref; cell->connections_ = new_connections; } } diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index 602ad776d..44a5cda95 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -41,7 +41,7 @@ struct EquivMakeWorker pool undriven_bits; SigMap assign_map; - void read_blacklists() + void read_blacklists(const TwineSearch &search) { for (auto fn : blacklists) { @@ -55,13 +55,15 @@ struct EquivMakeWorker token = next_token(line); if (token.empty()) break; - blacklist_names.insert(RTLIL::escape_id(token)); + IdString name = search.find(RTLIL::escape_id(token)); + if (name != IdString::Null) + blacklist_names.insert(name); } } } } - void read_encfiles() + void read_encfiles(const TwineSearch &search) { for (auto fn : encfiles) { @@ -78,11 +80,11 @@ struct EquivMakeWorker continue; if (token == ".fsm") { - IdString modname = RTLIL::escape_id(next_token(line)); + IdString modname = search.find(RTLIL::escape_id(next_token(line))); (void)modname; - IdString signame = RTLIL::escape_id(next_token(line)); + IdString signame = search.find(RTLIL::escape_id(next_token(line))); if (encdata.count(signame)) - log_cmd_error("Re-definition of signal '%s' in encfile '%s'!\n", signame, fn); + log_cmd_error("Re-definition of signal '%s' in encfile '%s'!\n", PooledName(gold_mod->design, signame).unescape(), fn); encdata[signame] = dict(); ed = &encdata[signame]; continue; @@ -141,7 +143,7 @@ struct EquivMakeWorker equiv_mod->addAssert(NEW_ID_SUFFIX("assert"), eq_wire, State::S1); } - void find_same_wires() + void find_same_wires(const TwineSearch &search) { SigMap assign_map(equiv_mod); SigMap rd_signal_map; @@ -152,18 +154,18 @@ struct EquivMakeWorker for (auto id : wire_names) { - IdString gold_id = id.str() + "_gold"; - IdString gate_id = id.str() + "_gate"; + IdString gold_id = search.find(equiv_mod->design->twines.str(id) + "_gold"); + IdString gate_id = search.find(equiv_mod->design->twines.str(id) + "_gate"); Wire *gold_wire = equiv_mod->wire(gold_id); Wire *gate_wire = equiv_mod->wire(gate_id); if (encdata.count(id)) { - log("Creating encoder/decoder for signal %s.\n", id.unescape()); + log("Creating encoder/decoder for signal %s.\n", PooledName(equiv_mod->design, id).unescape()); - Wire *dec_wire = equiv_mod->addWire(id.str() + "_decoded", gold_wire->width); - Wire *enc_wire = equiv_mod->addWire(id.str() + "_encoded", gate_wire->width); + Wire *dec_wire = equiv_mod->addWire(equiv_mod->design->twines.str(id) + "_decoded", gold_wire->width); + Wire *enc_wire = equiv_mod->addWire(equiv_mod->design->twines.str(id) + "_encoded", gate_wire->width); SigSpec dec_a, dec_b, dec_s; SigSpec enc_a, enc_b, enc_s; @@ -235,7 +237,7 @@ struct EquivMakeWorker log("Presumably equivalent wires: %s (%s), %s (%s) -> %s\n", gold_wire, log_signal(assign_map(gold_wire)), - gate_wire, log_signal(assign_map(gate_wire)), id.unescape()); + gate_wire, log_signal(assign_map(gate_wire)), PooledName(equiv_mod->design, id).unescape()); if (gold_wire->port_output || gate_wire->port_output) { @@ -314,7 +316,7 @@ struct EquivMakeWorker new_sig[i] = old_sig[i]; if (old_sig != new_sig) { log("Changing input %s of cell %s (%s): %s -> %s\n", - conn.first.unescape(), c, c->type.unescape(), + PooledName(equiv_mod, conn.first).unescape(), c, c->type.unescape(), log_signal(old_sig), log_signal(new_sig)); c->setPort(conn.first, new_sig); } @@ -323,14 +325,14 @@ struct EquivMakeWorker equiv_mod->fixup_ports(); } - void find_same_cells() + void find_same_cells(const TwineSearch &search) { SigMap assign_map(equiv_mod); for (auto id : cell_names) { - IdString gold_id = id.str() + "_gold"; - IdString gate_id = id.str() + "_gate"; + IdString gold_id = search.find(equiv_mod->design->twines.str(id) + "_gold"); + IdString gate_id = search.find(equiv_mod->design->twines.str(id) + "_gate"); Cell *gold_cell = equiv_mod->cell(gold_id); Cell *gate_cell = equiv_mod->cell(gate_id); @@ -345,7 +347,7 @@ struct EquivMakeWorker goto try_next_cell_name; log("Presumably equivalent cells: %s %s (%s) -> %s\n", - gold_cell, gate_cell, gold_cell->type.unescape(), id.unescape()); + gold_cell, gate_cell, gold_cell->type.unescape(), PooledName(equiv_mod->design, id).unescape()); for (auto gold_conn : gold_cell->connections()) { @@ -419,8 +421,9 @@ struct EquivMakeWorker { copy_to_equiv(); find_undriven_nets(false); - find_same_wires(); - find_same_cells(); + TwineSearch search(&equiv_mod->design->twines); + find_same_wires(search); + find_same_cells(search); find_undriven_nets(true); } }; @@ -488,9 +491,10 @@ struct EquivMakePass : public Pass { if (argidx+3 != args.size()) log_cmd_error("Invalid number of arguments.\n"); - worker.gold_mod = design->module(RTLIL::escape_id(args[argidx])); - worker.gate_mod = design->module(RTLIL::escape_id(args[argidx+1])); - worker.equiv_mod = design->module(RTLIL::escape_id(args[argidx+2])); + TwineSearch search(&design->twines); + worker.gold_mod = design->module(search.find(RTLIL::escape_id(args[argidx]))); + worker.gate_mod = design->module(search.find(RTLIL::escape_id(args[argidx+1]))); + worker.equiv_mod = design->module(search.find(RTLIL::escape_id(args[argidx+2]))); if (worker.gold_mod == nullptr) log_cmd_error("Can't find gold module %s.\n", args[argidx]); @@ -507,8 +511,8 @@ struct EquivMakePass : public Pass { if (worker.gate_mod->has_memories() || worker.gate_mod->has_processes()) log_cmd_error("Gate module contains memories or processes. Run 'memory' or 'proc' respectively.\n"); - worker.read_blacklists(); - worker.read_encfiles(); + worker.read_blacklists(search); + worker.read_encfiles(search); log_header(design, "Executing EQUIV_MAKE pass (creating equiv checking module).\n"); diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc index 7f8d8d282..2aa2db3ad 100644 --- a/passes/equiv/equiv_struct.cc +++ b/passes/equiv/equiv_struct.cc @@ -78,8 +78,8 @@ struct EquivStructWorker if (bits_a[i] != bits_b[i]) { inputs_a.append(bits_a[i]); inputs_b.append(bits_b[i]); - input_names.push_back(GetSize(bits_a) == 1 ? port_a.first.str() : - stringf("%s[%d]", port_a.first.unescape(), i)); + input_names.push_back(GetSize(bits_a) == 1 ? module->design->twines.str(port_a.first) : + stringf("%s[%d]", module->design->twines.unescaped_str(port_a.first).c_str(), i)); } } @@ -110,9 +110,7 @@ struct EquivStructWorker module->connect(sig_b, sig_a); } - auto merged_attr = cell_b->get_strpool_attribute(ID::equiv_merged); - merged_attr.insert(cell_b->name.unescape()); - cell_a->add_strpool_attribute(ID::equiv_merged, merged_attr); + cell_a->set_bool_attribute(ID::equiv_merged); module->remove(cell_b); } @@ -175,14 +173,14 @@ struct EquivStructWorker if (cell->input(conn.first)) { SigSpec sig = sigmap(conn.second); for (int i = 0; i < GetSize(sig); i++) - fwd_connections.push_back(make_tuple(conn.first, i, sig[i])); + fwd_connections.push_back(std::make_tuple(conn.first, i, sig[i])); } if (cell->output(conn.first)) { SigSpec sig = equiv_bits(conn.second); for (int i = 0; i < GetSize(sig); i++) { key.connections.clear(); - key.connections.push_back(make_tuple(conn.first, i, sig[i])); + key.connections.push_back(std::make_tuple(conn.first, i, sig[i])); if (merge_cache.count(key)) bwd_merge_cache.insert(key); @@ -213,7 +211,7 @@ struct EquivStructWorker for (auto cell_name : merge_cache[key]) { Cell *c = module->cell(cell_name); if (c != nullptr) { - string n = cell_name.str(); + string n = module->design->twines.str(cell_name); cells_type = c->type; if (GetSize(n) > 5 && n.compare(GetSize(n)-5, std::string::npos, "_gold") == 0) gold_cells.push_back(c); @@ -266,7 +264,7 @@ struct EquivStructWorker run_strategy: int total_group_size = GetSize(gold_cells) + GetSize(gate_cells) + GetSize(other_cells); log(" %s merging %d %s cells (from group of %d) using strategy %s:\n", phase ? "Bwd" : "Fwd", - 2*GetSize(cell_pairs), cells_type.unescape(), total_group_size, strategy); + 2*GetSize(cell_pairs), PooledName(module->design, cells_type).unescape(), total_group_size, strategy); for (auto it : cell_pairs) { log(" Merging cells %s and %s.\n", it.first, it.second); merge_cell_pair(it.first, it.second); @@ -334,7 +332,7 @@ struct EquivStructPass : public Pass { continue; } if (args[argidx] == "-fwonly" && argidx+1 < args.size()) { - fwonly_cells.insert(RTLIL::escape_id(args[++argidx])); + fwonly_cells.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-maxiter" && argidx+1 < args.size()) { diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index 43a797ff4..f5361838e 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -69,7 +69,7 @@ static bool find_states(RTLIL::SigSpec sig, const RTLIL::SigSpec &dff_out, RTLIL for (auto &cellport : cellport_list) { - RTLIL::Cell *cell = module->cells_.at(cellport.first); + RTLIL::Cell *cell = module->cell(cellport.first); if ((cell->type != ID($mux) && cell->type != ID($pmux)) || cellport.second != ID::Y) { log(" unexpected cell type %s (%s) found in state selection tree.\n", cell->type, cell->name); return false; @@ -271,7 +271,7 @@ static void extract_fsm(RTLIL::Wire *wire) std::set cellport_list; sig2driver.find(dff_out, cellport_list); for (auto &cellport : cellport_list) { - RTLIL::Cell *cell = module->cells_.at(cellport.first); + RTLIL::Cell *cell = module->cell(cellport.first); if ((cell->type != ID($dff) && cell->type != ID($adff)) || cellport.second != ID::Q) continue; log(" found %s cell for state register: %s\n", cell->type, cell->name); @@ -319,7 +319,7 @@ static void extract_fsm(RTLIL::Wire *wire) cellport_list.clear(); sig2trigger.find(dff_out, cellport_list); for (auto &cellport : cellport_list) { - RTLIL::Cell *cell = module->cells_.at(cellport.first); + RTLIL::Cell *cell = module->cell(cellport.first); RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec sig_b; if (cell->hasPort(ID::B)) @@ -388,10 +388,8 @@ static void extract_fsm(RTLIL::Wire *wire) // rename original state wire - module->wires_.erase(wire->name); wire->attributes.erase(ID::fsm_encoding); - wire->name = stringf("$fsm$oldstate%s", wire->name); - module->wires_[wire->name] = wire; + module->rename(wire, stringf("$fsm$oldstate%s", wire->name)); if(wire->attributes.count(ID::hdlname)) { auto hdlname = wire->get_hdlname_attribute(); hdlname.pop_back(); @@ -405,7 +403,7 @@ static void extract_fsm(RTLIL::Wire *wire) cellport_list.clear(); sig2driver.find(ctrl_out, cellport_list); for (auto &cellport : cellport_list) { - RTLIL::Cell *cell = module->cells_.at(cellport.first); + RTLIL::Cell *cell = module->cell(cellport.first); RTLIL::SigSpec port_sig = assign_map(cell->getPort(cellport.second)); RTLIL::SigSpec unconn_sig = port_sig.extract(ctrl_out); RTLIL::Wire *unconn_wire = module->addWire(stringf("$fsm_unconnect$%d", autoidx++), unconn_sig.size()); diff --git a/passes/hierarchy/flatten.cc b/passes/hierarchy/flatten.cc index 29e7205ee..324e014c5 100644 --- a/passes/hierarchy/flatten.cc +++ b/passes/hierarchy/flatten.cc @@ -42,24 +42,55 @@ template return result; } -IdString concat_name(RTLIL::Cell *cell, IdString const &object_name, const std::string &separator = ".") -{ - std::string_view object_name_view(object_name.c_str()); - if (object_name_view[0] == '\\'){ - return concat_views(cell->name.c_str(), separator, object_name_view.substr(1)); +struct module_ptr_compare { + bool operator()(RTLIL::Module *a, RTLIL::Module *b) const { + return a < b; } +}; + +std::pair hier_name_parts(RTLIL::Cell *cell, std::string_view object_name_view, const std::string &separator) +{ + if (!object_name_view.empty() && object_name_view[0] == '\\') + return {cell->name.str() + separator, std::string(object_name_view.substr(1))}; constexpr std::string_view prefix = "$flatten"; - if (object_name_view.substr(0, prefix.size()) == prefix){ + if (object_name_view.substr(0, prefix.size()) == prefix) object_name_view.remove_prefix(prefix.size()); - } - return concat_views(prefix, cell->name.c_str(), separator, object_name_view); + return {"$flatten" + cell->name.str() + separator, std::string(object_name_view)}; } -template -IdString map_name(RTLIL::Cell *cell, T *object, const std::string &separator = ".") +std::string concat_name(RTLIL::Cell *cell, std::string_view object_name_view, const std::string &separator = ".") { - return cell->module->uniquify(concat_name(cell, object->name, separator)); + auto [prefix, tail] = hier_name_parts(cell, object_name_view, separator); + return prefix + tail; +} + +IdString remap_flattened_name(RTLIL::Design *design, IdString obj_ref, + IdString pub_prefix_ref, IdString priv_prefix_ref, const std::string &separator, dict &memo) +{ + if (auto it = memo.find(obj_ref); it != memo.end()) + return it->second; + + const TwineNode &node = design->twines[obj_ref]; + IdString result; + if (node.is_suffix()) { + const Twine::Suffix &sfx = node.suffix(); + IdString prefix = remap_flattened_name(design, sfx.prefix.tag(obj_ref.isPublic()), + pub_prefix_ref, priv_prefix_ref, separator, memo); + result = design->twines.add(Twine::Suffix{prefix, sfx.tail}); + } else { + std::string_view obj = node.leaf(); + if (obj_ref.isPublic()) { + result = design->twines.add(Twine::Suffix{pub_prefix_ref, separator + std::string(obj)}); + } else { + constexpr std::string_view flatten_prefix = "$flatten"; + if (obj.substr(0, flatten_prefix.size()) == flatten_prefix) + obj.remove_prefix(flatten_prefix.size()); + result = design->twines.add(Twine::Suffix{priv_prefix_ref, std::string(obj)}); + } + } + memo[obj_ref] = result; + return result; } void map_sigspec(const dict &map, RTLIL::SigSpec &sig, RTLIL::Module *into = nullptr) @@ -78,6 +109,9 @@ struct FlattenWorker bool create_scopename = false; std::string separator = "."; + std::string cell_hdlname; + std::string cell_scopename; + template void map_attributes(RTLIL::Cell *cell, T *object, IdString orig_object_name) { @@ -86,53 +120,50 @@ struct FlattenWorker // Preserve original names via the hdlname attribute, but only for objects with a fully public name. // If the '-scopename' option is used, also preserve the containing scope of private objects if their scope is fully public. - if (cell->name[0] == '\\') { - if (object->has_attribute(ID::hdlname) || orig_object_name[0] == '\\') { - std::string new_hdlname; - - if (cell->has_attribute(ID::hdlname)) { - new_hdlname = cell->get_string_attribute(ID(hdlname)); - } else { - log_assert(!cell->name.empty()); - new_hdlname = cell->name.c_str() + 1; - } + if (cell->name.isPublic()) { + if (object->has_attribute(ID::hdlname) || orig_object_name.isPublic()) { + std::string new_hdlname = cell_hdlname; new_hdlname += ' '; if (object->has_attribute(ID::hdlname)) { new_hdlname += object->get_string_attribute(ID(hdlname)); } else { - log_assert(!orig_object_name.empty()); - new_hdlname += orig_object_name.c_str() + 1; + new_hdlname += cell->module->design->twines.unescaped_str(orig_object_name); } object->set_string_attribute(ID(hdlname), new_hdlname); } else if (object->has_attribute(ID(scopename))) { - std::string new_scopename; - - if (cell->has_attribute(ID::hdlname)) { - new_scopename = cell->get_string_attribute(ID(hdlname)); - } else { - log_assert(!cell->name.empty()); - new_scopename = cell->name.c_str() + 1; - } + std::string new_scopename = cell_hdlname; new_scopename += ' '; new_scopename += object->get_string_attribute(ID(scopename)); object->set_string_attribute(ID(scopename), new_scopename); } else if (create_scopename) { - log_assert(!cell->name.empty()); - object->set_string_attribute(ID(scopename), cell->name.c_str() + 1); + object->set_string_attribute(ID::scopename, cell_scopename); } } } - void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector &new_cells, const std::string &separator) + void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector &new_cells, const std::string &separator, const dict &hier_wires) { // Copy the contents of the flattened cell - dict memory_map; + if (cell->name.isPublic()) { + log_assert(!cell->name.empty()); + cell_hdlname = cell->has_attribute(ID::hdlname) ? cell->get_string_attribute(ID(hdlname)) : cell->name.unescape(); + cell_scopename = create_scopename ? cell->name.unescape() : std::string(); + } + + IdString pub_prefix_ref = cell->name; + IdString priv_prefix_ref = design->twines.add("$flatten" + cell->name.str() + separator); + dict remap_memo; + auto make_name = [&](IdString obj_ref) -> IdString { + return module->uniquify(remap_flattened_name(design, obj_ref, pub_prefix_ref, priv_prefix_ref, separator, remap_memo)); + }; + + dict memory_map; for (auto &tpl_memory_it : tpl->memories) { - RTLIL::Memory *new_memory = module->addMemory(map_name(cell, tpl_memory_it.second, separator), tpl_memory_it.second); + RTLIL::Memory *new_memory = module->addMemory(make_name(tpl_memory_it.second->name), tpl_memory_it.second); map_attributes(cell, new_memory, tpl_memory_it.second->name); - memory_map[tpl_memory_it.first] = new_memory->name; + memory_map[design->twines.str(tpl_memory_it.first)] = new_memory->name; design->select(module, new_memory); } @@ -140,11 +171,13 @@ struct FlattenWorker dict positional_ports; for (auto tpl_wire : tpl->wires()) { if (tpl_wire->port_id > 0) - positional_ports.emplace(stringf("$%d", tpl_wire->port_id), tpl_wire->name); + positional_ports.emplace(design->twines.add(stringf("$%d", tpl_wire->port_id)), tpl_wire->name); RTLIL::Wire *new_wire = nullptr; - if (tpl_wire->name[0] == '\\') { - RTLIL::Wire *hier_wire = module->wire(concat_name(cell, tpl_wire->name, separator)); + if (tpl_wire->name.isPublic() && !hier_wires.empty()) { + std::string wire_name = concat_name(cell, tpl_wire->name.str(), separator); + auto hwit = hier_wires.find(wire_name); + RTLIL::Wire *hier_wire = (hwit != hier_wires.end()) ? hwit->second : nullptr; if (hier_wire != nullptr && hier_wire->get_bool_attribute(ID::hierconn)) { hier_wire->attributes.erase(ID::hierconn); if (GetSize(hier_wire) < GetSize(tpl_wire)) { @@ -156,7 +189,7 @@ struct FlattenWorker } } if (new_wire == nullptr) { - new_wire = module->addWire(map_name(cell, tpl_wire, separator), tpl_wire); + new_wire = module->addWire(make_name(tpl_wire->name), tpl_wire); new_wire->port_input = new_wire->port_output = false; new_wire->port_id = false; } @@ -167,25 +200,26 @@ struct FlattenWorker } for (auto &tpl_proc_it : tpl->processes) { - RTLIL::Process *new_proc = module->addProcess(map_name(cell, tpl_proc_it.second, separator), tpl_proc_it.second); + RTLIL::Process *new_proc = module->addProcess(make_name(tpl_proc_it.second->name), tpl_proc_it.second); map_attributes(cell, new_proc, tpl_proc_it.second->name); for (auto new_proc_sync : new_proc->syncs) - for (auto &memwr_action : new_proc_sync->mem_write_actions) - memwr_action.memid = memory_map.at(memwr_action.memid).str(); + for (auto &memwr_action : new_proc_sync->mem_write_actions) { + memwr_action.memid = memory_map.at(design->twines.str(memwr_action.memid)); + } auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); }; new_proc->rewrite_sigspecs(rewriter); design->select(module, new_proc); } for (auto tpl_cell : tpl->cells()) { - RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell, separator), tpl_cell); + RTLIL::Cell *new_cell = module->addCell(make_name(tpl_cell->name), tpl_cell); map_attributes(cell, new_cell, tpl_cell->name); if (new_cell->has_memid()) { - IdString memid = new_cell->getParam(ID::MEMID).decode_string(); - new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str())); + std::string memid = new_cell->getParam(ID::MEMID).decode_string(); + new_cell->setParam(ID::MEMID, Const(design->twines.str(memory_map.at(memid)))); } else if (new_cell->is_mem_cell()) { - IdString memid = new_cell->getParam(ID::MEMID).decode_string(); - new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid, separator).str())); + std::string memid = new_cell->getParam(ID::MEMID).decode_string(); + new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid, separator))); } auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); }; new_cell->rewrite_sigspecs(rewriter); @@ -218,9 +252,10 @@ struct FlattenWorker if (positional_ports.count(port_name) > 0) port_name = positional_ports.at(port_name); if (tpl->wire(port_name) == nullptr || tpl->wire(port_name)->port_id == 0) { - if (port_name.begins_with("$")) + std::string port_name_str = design->twines.str(port_name); + if (!port_name_str.empty() && port_name_str[0] == '$') log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", - port_name.c_str(), cell->name.c_str(), tpl->name.c_str()); + port_name_str, cell->name, tpl->name); continue; } @@ -261,7 +296,7 @@ struct FlattenWorker if (sigmap(new_conn.first).has_const()) log_error("Cell port %s.%s.%s is driving constant bits: %s <= %s\n", - module, cell, port_it.first.unescape(), log_signal(new_conn.first), log_signal(new_conn.second)); + module, cell, PooledName(design, port_it.first).unescape(), log_signal(new_conn.first), log_signal(new_conn.second)); module->connect(new_conn); sigmap.add(new_conn.first, new_conn.second); @@ -281,13 +316,13 @@ struct FlattenWorker if (attr.first == ID::hdlname) scopeinfo->attributes.insert(attr); else - scopeinfo->attributes.emplace(stringf("\\cell_%s", attr.first.unescape()), attr.second); + scopeinfo->attributes.emplace(design->twines.add(stringf("\\cell_%s", design->twines.unescaped_str(attr.first))), attr.second); } for (auto const &attr : tpl->attributes) - scopeinfo->attributes.emplace(stringf("\\module_%s", attr.first.unescape()), attr.second); + scopeinfo->attributes.emplace(design->twines.add(stringf("\\module_%s", design->twines.unescaped_str(attr.first))), attr.second); - scopeinfo->attributes.emplace(ID(module), tpl->name.unescape()); + scopeinfo->attributes.emplace(ID::module, RTLIL::Const(tpl->name.unescape())); } module->remove(cell); @@ -298,20 +333,27 @@ struct FlattenWorker void flatten_module(RTLIL::Design *design, RTLIL::Module *module, pool &used_modules, const std::string &separator) { - if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb)) + if (!design->selected_module(module) || module->get_blackbox_attribute(ignore_wb)) return; SigMap sigmap(module); + + dict hier_wires; + for (auto wire : module->wires()) + if (wire->get_bool_attribute(ID::hierconn)) + hier_wires[wire->name.str()] = wire; + std::vector worklist = module->selected_cells(); while (!worklist.empty()) { RTLIL::Cell *cell = worklist.back(); worklist.pop_back(); - if (!design->has(cell->type)) + IdString cell_type_ref = cell->type; + if (!design->has(cell_type_ref)) continue; - RTLIL::Module *tpl = design->module(cell->type); + RTLIL::Module *tpl = design->module(cell_type_ref); if (tpl->get_blackbox_attribute(ignore_wb)) continue; @@ -325,7 +367,7 @@ struct FlattenWorker // If a design is fully selected and has a top module defined, topological sorting ensures that all cells // added during flattening are black boxes, and flattening is finished in one pass. However, when flattening // individual modules, this isn't the case, and the newly added cells might have to be flattened further. - flatten_cell(design, module, cell, tpl, sigmap, worklist, separator); + flatten_cell(design, module, cell, tpl, sigmap, worklist, separator, hier_wires); } } }; @@ -420,7 +462,7 @@ struct FlattenPass : public Pass { else used_modules.insert(top); - TopoSort> topo_modules; + TopoSort topo_modules; pool worklist = used_modules; while (!worklist.empty()) { RTLIL::Module *module = worklist.pop(); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 1cbfb1693..973799af1 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -21,6 +21,7 @@ #include "kernel/yosys.h" #include "kernel/celltypes.h" #include "frontends/verific/verific.h" +#include "frontends/ast/ast.h" #include #include #include @@ -57,18 +58,19 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, for (auto &celltype : found_celltypes) { - std::set portnames; + std::set portnames; std::set parameters; - std::map portwidths; - log("Generate module for cell type %s:\n", celltype); + std::map portwidths; + log("Generate module for cell type %s:\n", design->twines.str(celltype)); for (auto mod : design->modules()) for (auto cell : mod->cells()) if (cell->type == celltype) { for (auto &conn : cell->connections()) { - if (conn.first[0] != '$') - portnames.insert(conn.first); - portwidths[conn.first] = max(portwidths[conn.first], conn.second.size()); + std::string port_name = design->twines.str(conn.first); + if (!port_name.empty() && port_name[0] != '$') + portnames.insert(std::string(port_name)); + portwidths[std::string(port_name)] = max(portwidths[std::string(port_name)], conn.second.size()); } for (auto ¶ : cell->parameters) parameters.insert(para.first); @@ -99,11 +101,11 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, } while (portnames.size() > 0) { - RTLIL::IdString portname = *portnames.begin(); + std::string portname = *portnames.begin(); for (auto &decl : portdecls) - if (decl.index == 0 && patmatch(decl.portname.c_str(), portname.unescape().c_str())) { + if (decl.index == 0 && patmatch(decl.portname.c_str(), RTLIL::unescape_id(portname).c_str())) { generate_port_decl_t d = decl; - d.portname = portname.str(); + d.portname = portname; d.index = *indices.begin(); log_assert(!indices.empty()); indices.erase(d.index); @@ -112,17 +114,15 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, log(" port %d: %s [%d:0] %s\n", d.index, d.input ? d.output ? "inout" : "input" : "output", portwidths[d.portname]-1, RTLIL::unescape_id(d.portname)); goto found_matching_decl; } - log_error("Can't match port %s.\n", portname.unescape()); + log_error("Can't match port %s.\n", RTLIL::unescape_id(portname).c_str()); found_matching_decl:; portnames.erase(portname); } log_assert(indices.empty()); - RTLIL::Module *mod = new RTLIL::Module; - mod->name = celltype; + RTLIL::Module *mod = design->addModule(celltype); mod->attributes[ID::blackbox] = RTLIL::Const(1); - design->add(mod); for (auto &decl : ports) { RTLIL::Wire *wire = mod->addWire(decl.portname, portwidths.at(decl.portname)); @@ -134,7 +134,7 @@ void generate(RTLIL::Design *design, const std::vector &celltypes, mod->fixup_ports(); for (auto ¶ : parameters) - log(" ignoring parameter %s.\n", para.unescape()); + log(" ignoring parameter %s.\n", PooledName(design, para).unescape()); log(" module %s created.\n", mod); } @@ -157,18 +157,18 @@ std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) { return basicType; } -// Try to read an IdString as a numbered connection name ("$123" or similar), +// Try to read a IdString as a numbered connection name ("$123" or similar), // writing the result to dst. If the string isn't of the right format, ignore // dst and return false. -bool read_id_num(RTLIL::IdString str, int *dst) +bool read_id_num(RTLIL::Design &design, IdString ref, int *dst) { log_assert(dst); - const char *c_str = str.c_str(); - if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9')) + std::string sv = design.twines.str(ref); + if (sv.empty() || sv[0] != '$' || !('0' <= sv[1] && sv[1] <= '9')) return false; - *dst = atoi(c_str + 1); + *dst = atoi(std::string(sv).c_str() + 1); return true; } @@ -176,7 +176,7 @@ bool read_id_num(RTLIL::IdString str, int *dst) struct IFExpander { IFExpander (RTLIL::Design &design, RTLIL::Module &m) - : module(m), has_interfaces_not_found(false) + : design(design), module(m), has_interfaces_not_found(false) { // Keep track of all derived interfaces available in the current // module in 'interfaces_in_module': @@ -188,12 +188,13 @@ struct IFExpander } } + RTLIL::Design &design; RTLIL::Module &module; dict interfaces_in_module; bool has_interfaces_not_found; std::vector connections_to_remove; - std::vector connections_to_add_name; + std::vector connections_to_add; std::vector connections_to_add_signal; dict interfaces_to_add_to_submodule; dict modports_used_in_submodule; @@ -203,7 +204,7 @@ struct IFExpander { has_interfaces_not_found = false; connections_to_remove.clear(); - connections_to_add_name.clear(); + connections_to_add.clear(); connections_to_add_signal.clear(); interfaces_to_add_to_submodule.clear(); modports_used_in_submodule.clear(); @@ -226,7 +227,7 @@ struct IFExpander // about it and don't set has_interfaces_not_found (to avoid a // loop). log_warning("Could not find interface instance for `%s' in `%s'\n", - interface_name.unescape(), &module); + PooledName(module.design, interface_name).unescape(), &module); } // Handle an interface connection from the module @@ -239,7 +240,7 @@ struct IFExpander // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name interface_name_str.replace(0,23,""); interface_name_str = "\\" + interface_name_str; - RTLIL::IdString interface_name = interface_name_str; + IdString interface_name = design.twines.add(std::string(interface_name_str)); // If 'interfaces' in the cell have not be been handled yet, we aren't // ready to derive the sub-module either @@ -253,7 +254,7 @@ struct IFExpander // '_inst_from_top_dummy'. Check for both of them here int nexactmatch = interfaces_in_module.count(interface_name) > 0; std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy"; - RTLIL::IdString interface_name2 = interface_name_str2; + IdString interface_name2 = design.twines.add(std::string(interface_name_str2)); int nmatch2 = interfaces_in_module.count(interface_name2) > 0; // If we can't find either name, this is a missing interface. @@ -268,16 +269,19 @@ struct IFExpander RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2); // Go over all wires in interface, and add replacements to lists. + std::string conn_name_str(design.twines.str(conn_name)); for (auto mod_wire : mod_replace_ports->wires()) { - std::string signal_name1 = conn_name.str() + "." + mod_wire->name.unescape(); - std::string signal_name2 = interface_name.str() + "." + mod_wire->name.unescape(); - connections_to_add_name.push_back(RTLIL::IdString(signal_name1)); - if(module.wire(signal_name2) == nullptr) { + std::string member = mod_wire->name.unescape(); + std::string signal_name1 = conn_name_str + "." + member; + std::string signal_name2 = interface_name_str + "." + member; + connections_to_add.push_back(AST::intern_hier_name(&design, signal_name1)); + IdString signal_name2_ref = AST::intern_hier_name(&design, signal_name2); + if(module.wire(signal_name2_ref) == nullptr) { log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), module.name.unescape()); } else { - RTLIL::Wire *wire_in_parent = module.wire(signal_name2); + RTLIL::Wire *wire_in_parent = module.wire(signal_name2_ref); connections_to_add_signal.push_back(wire_in_parent); } } @@ -289,7 +293,7 @@ struct IFExpander // AstModule::derive string modport_name = submodule.wire(conn_name)->get_string_attribute(ID::interface_modport); if (!modport_name.empty()) { - modports_used_in_submodule[conn_name] = "\\" + modport_name; + modports_used_in_submodule[conn_name] = design.twines.add("\\" + modport_name); } } @@ -310,7 +314,7 @@ struct IFExpander // Check if the connection is present as an interface in the sub-module's port list int id; - if (read_id_num(conn_name, &id)) { + if (read_id_num(design, conn_name, &id)) { /* Interface expansion is incompatible with positional arguments * during expansion, the port list gets each interface signal * inserted after the interface itself which means that the argument @@ -351,8 +355,8 @@ struct IFExpander // interface port connection with the individual signal connections. void rewrite_interface_connections(RTLIL::Cell &cell) const { - for(unsigned int i=0;i &libdirs) { std::string cell_type = cell.type.str(); - RTLIL::Module *abs_mod = design.module("$abstract" + cell_type); + RTLIL::Module *abs_mod = design.module(design.twines.find("$abstract" + cell_type)); if (abs_mod) { cell.type = abs_mod->derive(&design, cell.parameters); cell.parameters.clear(); @@ -418,7 +422,7 @@ RTLIL::Module *get_module(RTLIL::Design &design, // We couldn't find the module anywhere. Complain if check is set. if (check) log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n", - cell_type.c_str(), parent.name.c_str(), cell.name.c_str()); + cell_type.c_str(), parent.name.str().data(), cell.name); return nullptr; } @@ -433,7 +437,7 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI { int id; for (auto &conn : cell.connections()) { - if (read_id_num(conn.first, &id)) { + if (read_id_num(*module.design, conn.first, &id)) { if (id <= 0 || id > GetSize(mod.ports)) log_error("Module `%s' referenced in module `%s' in cell `%s' " "has only %d ports, requested port %d.\n", @@ -447,11 +451,11 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI log_error("Module `%s' referenced in module `%s' in cell `%s' " "does not have a port named '%s'.\n", cell.type.unescape(), &module, &cell, - conn.first.unescape()); + PooledName(module.design, conn.first).unescape()); } } for (auto ¶m : cell.parameters) { - if (read_id_num(param.first, &id)) { + if (read_id_num(*module.design, param.first, &id)) { if (id <= 0 || id > GetSize(mod.avail_parameters)) log_error("Module `%s' referenced in module `%s' in cell `%s' " "has only %d parameters, requested parameter %d.\n", @@ -460,13 +464,14 @@ void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLI continue; } + std::string param_name = module.design->twines.str(param.first); if (mod.avail_parameters.count(param.first) == 0 && - param.first[0] != '$' && - strchr(param.first.c_str(), '.') == NULL) { + param_name[0] != '$' && + param_name.find('.') == std::string::npos) { log_error("Module `%s' referenced in module `%s' in cell `%s' " "does not have a parameter named '%s'.\n", cell.type.unescape(), &module, &cell, - param.first.unescape()); + RTLIL::unescape_id(param_name)); } } } @@ -504,9 +509,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check int idx = atoi(cell->type.substr(pos_idx + 1, pos_num).c_str()); int num = atoi(cell->type.substr(pos_num + 1, pos_type).c_str()); array_cells[cell] = std::pair(idx, num); - cell->type = cell->type.substr(pos_type + 1); + cell->type = cell->module->design->twines.add(std::string{cell->type.str().substr(pos_type + 1)}); } + dict interfaces_by_name; + dict modports_by_name; + RTLIL::Module *mod = design->module(cell->type); if (!mod) { @@ -534,7 +542,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check if (mod->get_blackbox_attribute()) { if (flag_simcheck || (flag_smtcheck && !mod->get_bool_attribute(ID::smtlib2_module))) log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n", - cell->type.c_str(), module->name.c_str(), cell->name.c_str()); + cell->type, module->name.str().data(), cell->name); continue; } @@ -559,10 +567,14 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check continue; } + for (auto &p : if_expander.interfaces_to_add_to_submodule) + interfaces_by_name[p.first] = p.second; + for (auto &p : if_expander.modports_used_in_submodule) + modports_by_name[p.first] = p.second; cell->type = mod->derive(design, cell->parameters, - if_expander.interfaces_to_add_to_submodule, - if_expander.modports_used_in_submodule); + interfaces_by_name, + modports_by_name); cell->parameters.clear(); did_something = true; @@ -608,9 +620,11 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check for (auto &conn : cell->connections_) { int conn_size = conn.second.size(); - RTLIL::IdString portname = conn.first; - if (portname.begins_with("$")) { - int port_id = atoi(portname.substr(1).c_str()); + IdString portname = conn.first; + std::string portname_str = module->design->twines.str(conn.first); + if (portname_str.empty() || portname_str[0] != '$') { + } else { + int port_id = atoi(portname_str.substr(1).data()); for (auto wire : mod->wires()) if (wire->port_id == port_id) { portname = wire->name; @@ -618,12 +632,12 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check } } if (mod->wire(portname) == nullptr) - log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", module, cell, conn.first.unescape()); + log_error("Array cell `%s.%s' connects to unknown port `%s'.\n", module, cell, PooledName(module, conn.first).unescape()); int port_size = mod->wire(portname)->width; if (conn_size == port_size || conn_size == 0) continue; if (conn_size != port_size*num) - log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", module, cell, conn.first.unescape()); + log_error("Array cell `%s.%s' has invalid port vs. signal size for port `%s'.\n", module, cell, PooledName(module, conn.first).unescape()); conn.second = conn.second.extract(port_size*idx, port_size); } } @@ -631,7 +645,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check return did_something; } -void hierarchy_worker(RTLIL::Design *design, std::set> &used, RTLIL::Module *mod, int indent) +void hierarchy_worker(RTLIL::Design *design, std::set &used, RTLIL::Module *mod, int indent) { if (used.count(mod) > 0) return; @@ -643,17 +657,19 @@ void hierarchy_worker(RTLIL::Design *design, std::setcells()) { - std::string celltype = cell->type.str(); - if (celltype.compare(0, strlen("$array:"), "$array:") == 0) - celltype = basic_cell_type(celltype); - if (design->module(celltype)) - hierarchy_worker(design, used, design->module(celltype), indent+4); + RTLIL::Module *cm; + if (cell->type.begins_with("$array:")) + cm = design->module(design->twines.find(basic_cell_type(cell->type.str()))); + else + cm = design->module(cell->type); + if (cm) + hierarchy_worker(design, used, cm, indent+4); } } void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib) { - std::set> used; + std::set used; hierarchy_worker(design, used, top, 0); std::vector del_modules; @@ -692,6 +708,8 @@ bool set_keep_print(std::map &cache, RTLIL::Module *mod) if (cache.count(mod) == 0) { cache[mod] = false; for (auto c : mod->cells()) { + if (mod->name == c->type) + continue; RTLIL::Module *m = mod->design->module(c->type); if ((m != nullptr && set_keep_print(cache, m)) || c->type == ID($print)) { cache[mod] = true; @@ -707,6 +725,8 @@ bool set_keep_assert(std::map &cache, RTLIL::Module *mod) if (cache.count(mod) == 0) { cache[mod] = false; for (auto c : mod->cells()) { + if (mod->name == c->type) + continue; RTLIL::Module *m = mod->design->module(c->type); if ((m != nullptr && set_keep_assert(cache, m)) || c->type.in(ID($check), ID($assert), ID($assume), ID($live), ID($fair), ID($cover))) { cache[mod] = true; @@ -722,13 +742,21 @@ int find_top_mod_score(Design *design, Module *module, dict &db) if (db.count(module) == 0) { int score = 0; db[module] = 0; + std::optional search; for (auto cell : module->cells()) { - std::string celltype = cell->type.str(); - // Is this an array instance - if (celltype.compare(0, strlen("$array:"), "$array:") == 0) - celltype = basic_cell_type(celltype); // Is this cell a module instance? - auto instModule = design->module(celltype); + RTLIL::Module *instModule; + if (cell->type.begins_with("$array:")) { + std::string type = basic_cell_type(cell->type.str()); + instModule = design->module(design->twines.find(type)); + if (instModule == nullptr) { + if (!search) + search.emplace(&design->twines); + instModule = design->module(search->find(type)); + } + } + else + instModule = design->module(cell->type); // If there is no instance for this, issue a warning. if (instModule != nullptr) { score = max(score, find_top_mod_score(design, instModule, db) + 1); @@ -754,16 +782,26 @@ RTLIL::Module *check_if_top_has_changed(Design *design, Module *top_mod) } // Find a matching wire for an implicit port connection; traversing generate block scope -RTLIL::Wire *find_implicit_port_wire(Module *module, Cell *cell, const std::string& port) +RTLIL::Wire *find_implicit_port_wire(Module *module, Cell *cell, const std::string& port, + std::optional &search) { + if (!search) + search.emplace(&module->design->twines); const std::string &cellname = cell->name.str(); size_t idx = cellname.size(); while ((idx = cellname.find_last_of('.', idx-1)) != std::string::npos) { - Wire *found = module->wire(cellname.substr(0, idx+1) + port.substr(1)); - if (found != nullptr) - return found; + std::string wire_name = cellname.substr(0, idx+1) + port.substr(1); + IdString ref = search->find(wire_name); + if (ref != IdString::Null) { + Wire *found = module->wire(ref); + if (found != nullptr) + return found; + } } - return module->wire(port); + IdString ref = search->find(port); + if (ref != IdString::Null) + return module->wire(ref); + return nullptr; } struct HierarchyPass : public Pass { @@ -988,31 +1026,33 @@ struct HierarchyPass : public Pass { if (!load_top_mod.empty()) { - IdString top_name = RTLIL::escape_id(load_top_mod); - IdString abstract_id = "$abstract" + RTLIL::escape_id(load_top_mod); + IdString top_name = design->twines.add(RTLIL::escape_id(load_top_mod)); + IdString abstract_id = design->twines.add("$abstract" + RTLIL::escape_id(load_top_mod)); top_mod = design->module(top_name); + RTLIL::Module *abstract_mod = design->module(abstract_id); dict top_parameters; - if ((top_mod == nullptr && design->module(abstract_id)) || top_mod != nullptr) { + if ((top_mod == nullptr && abstract_mod) || top_mod != nullptr) { for (auto ¶ : parameters) { SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) log_cmd_error("Can't decode value '%s'!\n", para.second); RTLIL::Const c = sig_value.as_const(); c.tag_bare_integer_const(para.second); - top_parameters[RTLIL::escape_id(para.first)] = c; + top_parameters[design->twines.add(RTLIL::escape_id(para.first))] = c; } } - if (top_mod == nullptr && design->module(abstract_id)) - top_mod = design->module(design->module(abstract_id)->derive(design, top_parameters)); + if (top_mod == nullptr && abstract_mod) + top_mod = design->module(abstract_mod->derive(design, top_parameters)); else if (top_mod != nullptr && !top_parameters.empty()) top_mod = design->module(top_mod->derive(design, top_parameters)); - if (top_mod != nullptr && top_mod->name != top_name) { + IdString top_name_ref = top_name; + if (top_mod != nullptr && top_mod->name != top_name_ref) { Module *m = top_mod->clone(); - m->name = top_name; - Module *old_mod = design->module(top_name); + m->name = top_name_ref; + Module *old_mod = design->module(top_name_ref); if (old_mod) design->remove(old_mod); design->add(m); @@ -1081,7 +1121,7 @@ struct HierarchyPass : public Pass { } if (top_mod != nullptr && top_mod->name.begins_with("$abstract")) { - IdString top_name = top_mod->name.substr(strlen("$abstract")); + IdString top_name = design->twines.add(top_mod->name.str().substr(strlen("$abstract"))); dict top_parameters; for (auto ¶ : parameters) { @@ -1090,15 +1130,16 @@ struct HierarchyPass : public Pass { log_cmd_error("Can't decode value '%s'!\n", para.second); RTLIL::Const c = sig_value.as_const(); c.tag_bare_integer_const(para.second); - top_parameters[RTLIL::escape_id(para.first)] = c; + top_parameters[design->twines.add(RTLIL::escape_id(para.first))] = c; } top_mod = design->module(top_mod->derive(design, top_parameters)); - if (top_mod != nullptr && top_mod->name != top_name) { + IdString top_name_ref = top_name; + if (top_mod != nullptr && top_mod->name != top_name_ref) { Module *m = top_mod->clone(); - m->name = top_name; - Module *old_mod = design->module(top_name); + m->name = top_name_ref; + Module *old_mod = design->module(top_name_ref); if (old_mod) design->remove(old_mod); design->add(m); @@ -1122,7 +1163,7 @@ struct HierarchyPass : public Pass { { did_something = false; - std::set> used_modules; + std::set used_modules; if (top_mod != NULL) { log_header(design, "Analyzing design hierarchy..\n"); hierarchy_worker(design, used_modules, top_mod, 0); @@ -1223,17 +1264,19 @@ struct HierarchyPass : public Pass { RTLIL::Module *cell_mod = design->module(cell->type); if (cell_mod == nullptr) continue; - for (auto &conn : cell->connections()) - if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') { + for (auto &conn : cell->connections()) { + std::string conn_name = design->twines.str(conn.first); + if (!conn_name.empty() && conn_name[0] == '$' && '0' <= conn_name[1] && conn_name[1] <= '9') { pos_mods.insert(design->module(cell->type)); pos_work.push_back(std::pair(mod, cell)); break; } + } pool> params_rename; for (const auto &p : cell->parameters) { int id; - if (read_id_num(p.first, &id)) { + if (read_id_num(*design, p.first, &id)) { if (id <= 0 || id > GetSize(cell_mod->avail_parameters)) { log(" Failed to map positional parameter %d of cell %s.%s (%s).\n", id, mod, cell, cell->type.unescape()); @@ -1251,7 +1294,7 @@ struct HierarchyPass : public Pass { for (auto module : pos_mods) for (auto wire : module->wires()) { if (wire->port_id > 0) - pos_map[std::pair(module, wire->port_id)] = wire->name; + pos_map[std::pair(module, wire->port_id)] = IdString(wire->name); } for (auto &work : pos_work) { @@ -1259,21 +1302,21 @@ struct HierarchyPass : public Pass { RTLIL::Cell *cell = work.second; log("Mapping positional arguments of cell %s.%s (%s).\n", module, cell, cell->type.unescape()); - dict new_connections; + dict new_connections_twine; for (auto &conn : cell->connections()) { int id; - if (read_id_num(conn.first, &id)) { + if (read_id_num(*design, conn.first, &id)) { std::pair key(design->module(cell->type), id); if (pos_map.count(key) == 0) { log(" Failed to map positional argument %d of cell %s.%s (%s).\n", id, module, cell, cell->type.unescape()); - new_connections[conn.first] = conn.second; + new_connections_twine[conn.first] = conn.second; } else - new_connections[pos_map.at(key)] = conn.second; + new_connections_twine[pos_map.at(key)] = conn.second; } else - new_connections[conn.first] = conn.second; + new_connections_twine[conn.first] = conn.second; } - cell->connections_ = new_connections; + cell->connections_ = new_connections_twine; } } @@ -1289,6 +1332,7 @@ struct HierarchyPass : public Pass { // Process SV implicit wildcard port connections std::set blackbox_derivatives; std::vector design_modules = design->modules(); + std::optional implicit_port_search; for (auto module : design_modules) { @@ -1304,11 +1348,11 @@ struct HierarchyPass : public Pass { // Need accurate port widths for error checking; so must derive blackboxes with dynamic port widths if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute(ID::dynports)) { - IdString new_m_name = m->derive(design, cell->parameters, true); - if (new_m_name.empty()) + IdString new_m_ref = m->derive(design, cell->parameters, true); + if (new_m_ref == IdString{}) continue; - if (new_m_name != m->name) { - m = design->module(new_m_name); + if (new_m_ref != m->name) { + m = design->module(new_m_ref); blackbox_derivatives.insert(m); } } @@ -1321,7 +1365,7 @@ struct HierarchyPass : public Pass { if (old_connections.count(wire->name)) continue; // Make sure a wire of correct name exists in the parent - Wire* parent_wire = find_implicit_port_wire(module, cell, wire->name.str()); + Wire* parent_wire = find_implicit_port_wire(module, cell, wire->name.str(), implicit_port_search); // Missing wires are OK when a default value is set if (!nodefaults && parent_wire == nullptr && defaults_db.count(cell->type) && defaults_db.at(cell->type).count(wire->name)) @@ -1350,16 +1394,20 @@ struct HierarchyPass : public Pass { if (keep_positionals) { bool found_positionals = false; - for (auto &conn : cell->connections()) - if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') + for (auto &conn : cell->connections()) { + std::string conn_name = design->twines.str(conn.first); + if (!conn_name.empty() && conn_name[0] == '$' && '0' <= conn_name[1] && conn_name[1] <= '9') found_positionals = true; + } if (found_positionals) continue; } - for (auto &it : defaults_db.at(cell->type)) - if (!cell->hasPort(it.first)) - cell->setPort(it.first, it.second); + for (auto &it : defaults_db.at(cell->type)) { + IdString port_ref = it.first; + if (!cell->hasPort(port_ref)) + cell->setPort(port_ref, it.second); + } } } @@ -1489,11 +1537,11 @@ struct HierarchyPass : public Pass { bool boxed_params = false; if (m->get_blackbox_attribute() && !cell->parameters.empty()) { if (m->get_bool_attribute(ID::dynports)) { - IdString new_m_name = m->derive(design, cell->parameters, true); - if (new_m_name.empty()) + IdString new_m_ref = m->derive(design, cell->parameters, true); + if (new_m_ref == IdString{}) continue; - if (new_m_name != m->name) { - m = design->module(new_m_name); + if (new_m_ref != m->name) { + m = design->module(new_m_ref); blackbox_derivatives.insert(m); } } else { @@ -1516,7 +1564,7 @@ struct HierarchyPass : public Pass { bool resize_widths = !keep_portwidths && GetSize(w) != GetSize(conn.second); if (resize_widths && verific_mod && boxed_params) log_debug("Ignoring width mismatch on %s.%s.%s from verific, is port width parametrizable?\n", - module, cell, conn.first.unescape() + module, cell, PooledName(design, conn.first).unescape() ); else if (resize_widths) { if (GetSize(w) < GetSize(conn.second)) @@ -1541,13 +1589,13 @@ struct HierarchyPass : public Pass { if (!conn.second.is_fully_const() || !w->port_input || w->port_output) log_warning("Resizing cell port %s.%s.%s from %d bits to %d bits.\n", module, cell, - conn.first.unescape(), GetSize(conn.second), GetSize(sig)); + PooledName(design, conn.first).unescape(), GetSize(conn.second), GetSize(sig)); cell->setPort(conn.first, sig); } if (w->port_output && !w->port_input && sig.has_const()) log_error("Output port %s.%s.%s (%s) is connected to constants: %s\n", - module, cell, conn.first.unescape(), cell->type.unescape(), log_signal(sig)); + module, cell, PooledName(design, conn.first).unescape(), cell->type.unescape(), log_signal(sig)); } } } diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc index 941f4dce8..f064e02ce 100644 --- a/passes/hierarchy/uniquify.cc +++ b/passes/hierarchy/uniquify.cc @@ -71,25 +71,27 @@ struct UniquifyPass : public Pass { for (auto cell : module->selected_cells()) { Module *tmod = design->module(cell->type); - IdString newname = module->name.str() + "." + cell->name.unescape(); if (tmod == nullptr) continue; + std::string newname = module->name.str() + "." + cell->name.unescape(); + if (tmod->get_blackbox_attribute()) continue; - if (tmod->get_bool_attribute(ID::unique) && newname == tmod->name) + IdString newname_ref = design->twines.add(std::string(newname)); + if (tmod->get_bool_attribute(ID::unique) && newname_ref == tmod->name) continue; - log("Creating module %s from %s.\n", newname.unescape(), tmod); + log("Creating module %s from %s.\n", RTLIL::unescape_id(newname), tmod->name.unescape()); auto smod = tmod->clone(); - smod->name = newname; - cell->type = newname; + smod->name = newname_ref; + cell->type = newname_ref; smod->set_bool_attribute(ID::unique); if (smod->attributes.count(ID::hdlname) == 0) - smod->attributes[ID::hdlname] = string(tmod->name.unescape()); + smod->attributes[ID::hdlname] = RTLIL::Const(tmod->name.unescape()); design->add(smod); did_something = true; diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 833aa634b..3f189fc96 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -26,6 +26,8 @@ PRIVATE_NAMESPACE_BEGIN struct rules_t { + Design *design = nullptr; + struct portinfo_t { int group, index, dupidx; int wrmode, enable, transp, clocks, clkpol; @@ -36,7 +38,7 @@ struct rules_t }; struct bram_t { - IdString name; + PooledName name; int variant; int groups, abits, dbits, init; @@ -95,7 +97,7 @@ struct rules_t return portinfos; } - void find_variant_params(dict &variant_params, const bram_t &other) const + void find_variant_params(TwinePool &twines, dict &variant_params, const bram_t &other) const { log_assert(name == other.name); @@ -114,21 +116,22 @@ struct rules_t if (ports[i] != other.ports[i]) log_error("Bram %s variants %d and %d have different number of %c-ports.\n", name.unescape(), variant, other.variant, 'A'+i); if (wrmode[i] != other.wrmode[i]) - variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[i]; + variant_params[twines.add(stringf("\\CFG_WRMODE_%c", 'A' + i))] = wrmode[i]; if (enable[i] != other.enable[i]) - variant_params[stringf("\\CFG_ENABLE_%c", 'A' + i)] = enable[i]; + variant_params[twines.add(stringf("\\CFG_ENABLE_%c", 'A' + i))] = enable[i]; if (transp[i] != other.transp[i]) - variant_params[stringf("\\CFG_TRANSP_%c", 'A' + i)] = transp[i]; + variant_params[twines.add(stringf("\\CFG_TRANSP_%c", 'A' + i))] = transp[i]; if (clocks[i] != other.clocks[i]) - variant_params[stringf("\\CFG_CLOCKS_%c", 'A' + i)] = clocks[i]; + variant_params[twines.add(stringf("\\CFG_CLOCKS_%c", 'A' + i))] = clocks[i]; if (clkpol[i] != other.clkpol[i]) - variant_params[stringf("\\CFG_CLKPOL_%c", 'A' + i)] = clkpol[i]; + variant_params[twines.add(stringf("\\CFG_CLKPOL_%c", 'A' + i))] = clkpol[i]; } } + }; struct match_t { - IdString name; + PooledName name; dict min_limits, max_limits; bool or_next_if_better, make_transp, make_outreg; char shuffle_enable; @@ -211,7 +214,7 @@ struct rules_t void parse_bram() { - IdString bram_name = RTLIL::escape_id(tokens[1]); + PooledName bram_name(design, design->twines.add(RTLIL::escape_id(tokens[1]))); if (GetSize(tokens) != 2) syntax_error(); @@ -296,7 +299,7 @@ struct rules_t syntax_error(); match_t data; - data.name = RTLIL::escape_id(tokens[1]); + data.name = PooledName(design, design->twines.add(RTLIL::escape_id(tokens[1]))); data.or_next_if_better = false; data.make_transp = false; data.make_outreg = false; @@ -349,7 +352,7 @@ struct rules_t size_t c1 = tokens[idx][0] == '!' ? 1 : 0; size_t c2 = tokens[idx].find("="); bool exists = (c1 == 0); - IdString key = RTLIL::escape_id(tokens[idx].substr(c1, c2)); + IdString key = design->twines.add(RTLIL::escape_id(tokens[idx].substr(c1, c2))); Const val = c2 != std::string::npos ? tokens[idx].substr(c2+1) : RTLIL::Const(1); data.attributes.back().emplace_back(exists, key, map_case(val)); @@ -361,8 +364,9 @@ struct rules_t } } - void parse(string filename) + void parse(string filename, Design *design) { + this->design = design; rewrite_filename(filename); infile.open(filename); linecount = 0; @@ -759,7 +763,7 @@ grow_read_ports:; if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << key.unescape(); + ss << PooledName(mem.module, key).unescape(); const Const &value = rules.map_case(std::get<2>(sums.front())); if (exists && value != Const(1)) ss << "=\"" << value.decode_string() << "\""; @@ -862,7 +866,7 @@ grow_read_ports:; dict variant_params; for (auto &other_bram : rules.brams.at(bram.name)) - bram.find_variant_params(variant_params, other_bram); + bram.find_variant_params(module->design->twines, variant_params, other_bram); // actually replace that memory cell @@ -873,7 +877,7 @@ grow_read_ports:; for (int grid_a = 0; grid_a < acells; grid_a++) for (int dupidx = 0; dupidx < dup_count; dupidx++) { - Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", mem.memid, grid_d, grid_a, dupidx)), bram.name); + Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", mem.memid.str(), grid_d, grid_a, dupidx)), bram.name); log(" Creating %s cell at grid position <%d %d %d>: %s\n", bram.name.unescape(), grid_d, grid_a, dupidx, c); for (auto &vp : variant_params) @@ -1137,7 +1141,7 @@ void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals) if (!exists) ss << "!"; IdString key = std::get<1>(sums.front()); - ss << key.unescape(); + ss << PooledName(mem.module, key).unescape(); const Const &value = rules.map_case(std::get<2>(sums.front())); if (exists && value != Const(1)) ss << "=\"" << value.decode_string() << "\""; @@ -1313,7 +1317,7 @@ struct MemoryBramPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-rules" && argidx+1 < args.size()) { - rules.parse(args[++argidx]); + rules.parse(args[++argidx], design); continue; } break; diff --git a/passes/memory/memory_libmap.cc b/passes/memory/memory_libmap.cc index 7d7091c42..76ea2d402 100644 --- a/passes/memory/memory_libmap.cc +++ b/passes/memory/memory_libmap.cc @@ -130,6 +130,11 @@ struct MemConfig { typedef std::vector MemConfigs; +static void set_ram_port(RTLIL::Cell *cell, const std::string &port_name, const RTLIL::SigSpec &sig) +{ + cell->setPort(cell->module->design->twines.add(port_name), sig); +} + struct MapWorker { Module *module; ModWalker modwalker; @@ -204,7 +209,7 @@ struct MemMapping { if (!check_init(rdef)) continue; if (rdef.prune_rom && mem.wr_ports.empty()) { - log_debug("memory %s.%s: rejecting mapping to %s: ROM mapping disabled (prune_rom set)\n", mem.module->name.unescape(), mem.memid.unescape(), rdef.id.unescape()); + log_debug("memory %s.%s: rejecting mapping to %s: ROM mapping disabled (prune_rom set)\n", mem.module, mem.memid.unescape(), RTLIL::unescape_id(rdef.id)); continue; } MemConfig cfg; @@ -323,7 +328,7 @@ struct MemMapping { void log_reject(const Ram &ram, std::string message) { if(ys_debug(1)) { - rejected_cfg_debug_msgs += stringf("can't map to to %s: ", ram.id.unescape()); + rejected_cfg_debug_msgs += stringf("can't map to to %s: ", RTLIL::unescape_id(ram.id)); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -338,7 +343,7 @@ struct MemMapping { rejected_cfg_debug_msgs += portname; first = false; } - rejected_cfg_debug_msgs += stringf("] of %s: ", ram.id.unescape()); + rejected_cfg_debug_msgs += stringf("] of %s: ", RTLIL::unescape_id(ram.id)); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -361,7 +366,7 @@ struct MemMapping { rejected_cfg_debug_msgs += portname; first = false; } - rejected_cfg_debug_msgs += stringf("] of %s: ", ram.id.unescape()); + rejected_cfg_debug_msgs += stringf("] of %s: ", RTLIL::unescape_id(ram.id)); rejected_cfg_debug_msgs += message; rejected_cfg_debug_msgs += "\n"; } @@ -380,7 +385,7 @@ void MemMapping::dump_configs(int stage) { default: abort(); } - log_debug("Memory %s.%s mapping candidates (%s):\n", mem.module->name.unescape(), mem.memid.unescape(), stage_name); + log_debug("Memory %s.%s mapping candidates (%s):\n", mem.module, mem.memid.unescape(), stage_name); if (logic_ok) { log_debug("- logic fallback\n"); log_debug(" - cost: %f\n", logic_cost); @@ -391,7 +396,7 @@ void MemMapping::dump_configs(int stage) { } void MemMapping::dump_config(MemConfig &cfg) { - log_debug("- %s:\n", cfg.def->id.unescape()); + log_debug("- %s:\n", RTLIL::unescape_id(cfg.def->id)); for (auto &it: cfg.def->options) log_debug(" - option %s %s\n", it.first, log_const(it.second)); log_debug(" - emulation score: %d\n", cfg.score_emu); @@ -527,7 +532,7 @@ void MemMapping::determine_style() { auto find_attr = search_for_attribute(mem, ID::lram); if (find_attr.first && find_attr.second.as_bool()) { kind = RamKind::Huge; - log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", mem.module->name.unescape(), mem.memid.unescape()); + log("found attribute 'lram' on memory %s.%s, forced mapping to huge RAM\n", mem.module, mem.memid.unescape()); return; } for (auto attr: {ID::ram_block, ID::rom_block, ID::ram_style, ID::rom_style, ID::ramstyle, ID::romstyle, ID::syn_ramstyle, ID::syn_romstyle}) { @@ -536,7 +541,7 @@ void MemMapping::determine_style() { Const val = find_attr.second; if (val == 1) { kind = RamKind::NotLogic; - log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", attr.unescape(), mem.module->name.unescape(), mem.memid.unescape()); + log("found attribute '%s = 1' on memory %s.%s, disabled mapping to FF\n", ID::unescaped_str(attr), mem.module, mem.memid.unescape()); return; } std::string val_s = val.decode_string(); @@ -549,20 +554,20 @@ void MemMapping::determine_style() { // Nothing. } else if (val_s == "logic" || val_s == "registers") { kind = RamKind::Logic; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to FF\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to FF\n", ID::unescaped_str(attr), val_s, mem.module, mem.memid.unescape()); } else if (val_s == "distributed") { kind = RamKind::Distributed; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to distributed RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to distributed RAM\n", ID::unescaped_str(attr), val_s, mem.module, mem.memid.unescape()); } else if (val_s == "block" || val_s == "block_ram" || val_s == "ebr") { kind = RamKind::Block; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to block RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to block RAM\n", ID::unescaped_str(attr), val_s, mem.module, mem.memid.unescape()); } else if (val_s == "huge" || val_s == "ultra") { kind = RamKind::Huge; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to huge RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape()); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to huge RAM\n", ID::unescaped_str(attr), val_s, mem.module, mem.memid.unescape()); } else { kind = RamKind::NotLogic; style = val_s; - log("found attribute '%s = %s' on memory %s.%s, forced mapping to %s RAM\n", attr.unescape(), val_s, mem.module->name.unescape(), mem.memid.unescape(), val_s); + log("found attribute '%s = %s' on memory %s.%s, forced mapping to %s RAM\n", ID::unescaped_str(attr), val_s, mem.module, mem.memid.unescape(), val_s); } return; } @@ -1755,9 +1760,9 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons cell->setParam(stringf("\\PORT_%s_CLK_POL", name), clk_pol); } for (auto cell: cells) { - cell->setPort(stringf("\\PORT_%s_CLK", name), clk); + set_ram_port(cell, stringf("\\PORT_%s_CLK", name), clk); if (pdef.clk_en) - cell->setPort(stringf("\\PORT_%s_CLK_EN", name), clk_en); + set_ram_port(cell, stringf("\\PORT_%s_CLK_EN", name), clk_en); } } @@ -1819,7 +1824,7 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons for (int i = 0; i < hw_wr_wide_log2 && i < hw_rd_wide_log2; i++) hw_addr[i] = State::S0; for (auto cell: cells) - cell->setPort(stringf("\\PORT_%s_ADDR", name), hw_addr); + set_ram_port(cell, stringf("\\PORT_%s_ADDR", name), hw_addr); // Write part. if (pdef.kind != PortKind::Ar && pdef.kind != PortKind::Sr) { @@ -1850,31 +1855,31 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons hw_wren.append(big_wren[bit.mux_idx][bit.bit]); } } - cell->setPort(stringf("\\PORT_%s_WR_DATA", name), hw_wdata); + set_ram_port(cell, stringf("\\PORT_%s_WR_DATA", name), hw_wdata); if (pdef.wrbe_separate) { // TODO make some use of it SigSpec en = mem.module->ReduceOr(NEW_ID, hw_wren); - cell->setPort(stringf("\\PORT_%s_WR_EN", name), en); - cell->setPort(stringf("\\PORT_%s_WR_BE", name), hw_wren); + set_ram_port(cell, stringf("\\PORT_%s_WR_EN", name), en); + set_ram_port(cell, stringf("\\PORT_%s_WR_BE", name), hw_wren); if (cfg.def->width_mode != WidthMode::Single) cell->setParam(stringf("\\PORT_%s_WR_BE_WIDTH", name), GetSize(hw_wren)); } else { - cell->setPort(stringf("\\PORT_%s_WR_EN", name), hw_wren); + set_ram_port(cell, stringf("\\PORT_%s_WR_EN", name), hw_wren); if (cfg.def->byte != 0 && (cfg.def->width_mode != WidthMode::Single || opts.force_params)) cell->setParam(stringf("\\PORT_%s_WR_EN_WIDTH", name), GetSize(hw_wren)); } } } else { for (auto cell: cells) { - cell->setPort(stringf("\\PORT_%s_WR_DATA", name), Const(State::Sx, width)); + set_ram_port(cell, stringf("\\PORT_%s_WR_DATA", name), Const(State::Sx, width)); SigSpec hw_wren = Const(State::S0, width / effective_byte); if (pdef.wrbe_separate) { - cell->setPort(stringf("\\PORT_%s_WR_EN", name), State::S0); - cell->setPort(stringf("\\PORT_%s_WR_BE", name), hw_wren); + set_ram_port(cell, stringf("\\PORT_%s_WR_EN", name), State::S0); + set_ram_port(cell, stringf("\\PORT_%s_WR_BE", name), hw_wren); if (cfg.def->width_mode != WidthMode::Single) cell->setParam(stringf("\\PORT_%s_WR_BE_WIDTH", name), GetSize(hw_wren)); } else { - cell->setPort(stringf("\\PORT_%s_WR_EN", name), hw_wren); + set_ram_port(cell, stringf("\\PORT_%s_WR_EN", name), hw_wren); if (cfg.def->byte != 0 && cfg.def->width_mode != WidthMode::Single) cell->setParam(stringf("\\PORT_%s_WR_EN_WIDTH", name), GetSize(hw_wren)); } @@ -1894,11 +1899,11 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons auto cell = cells[rd]; if (pdef.kind == PortKind::Sr || pdef.kind == PortKind::Srsw) { if (pdef.rd_en) - cell->setPort(stringf("\\PORT_%s_RD_EN", name), rpcfg.rd_en_to_clk_en ? State::S1 : rport.en); + set_ram_port(cell, stringf("\\PORT_%s_RD_EN", name), rpcfg.rd_en_to_clk_en ? State::S1 : rport.en); if (pdef.rdarstval != ResetValKind::None) - cell->setPort(stringf("\\PORT_%s_RD_ARST", name), rport.arst); + set_ram_port(cell, stringf("\\PORT_%s_RD_ARST", name), rport.arst); if (pdef.rdsrstval != ResetValKind::None) - cell->setPort(stringf("\\PORT_%s_RD_SRST", name), rport.srst); + set_ram_port(cell, stringf("\\PORT_%s_RD_SRST", name), rport.srst); if (pdef.rdinitval == ResetValKind::Any || pdef.rdinitval == ResetValKind::NoUndef) { Const val = rport.init_value; if (pdef.rdarstval == ResetValKind::Init && rport.arst != State::S0) { @@ -1949,7 +1954,7 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons } } SigSpec hw_rdata = mem.module->addWire(NEW_ID, width); - cell->setPort(stringf("\\PORT_%s_RD_DATA", name), hw_rdata); + set_ram_port(cell, stringf("\\PORT_%s_RD_DATA", name), hw_rdata); SigSpec lhs; SigSpec rhs; for (int i = 0; i < GetSize(hw_rdata); i++) { @@ -1965,11 +1970,11 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons for (auto cell: cells) { if (pdef.kind == PortKind::Sr || pdef.kind == PortKind::Srsw) { if (pdef.rd_en) - cell->setPort(stringf("\\PORT_%s_RD_EN", name), State::S0); + set_ram_port(cell, stringf("\\PORT_%s_RD_EN", name), State::S0); if (pdef.rdarstval != ResetValKind::None) - cell->setPort(stringf("\\PORT_%s_RD_ARST", name), State::S0); + set_ram_port(cell, stringf("\\PORT_%s_RD_ARST", name), State::S0); if (pdef.rdsrstval != ResetValKind::None) - cell->setPort(stringf("\\PORT_%s_RD_SRST", name), State::S0); + set_ram_port(cell, stringf("\\PORT_%s_RD_SRST", name), State::S0); if (pdef.rdinitval == ResetValKind::Any) cell->setParam(stringf("\\PORT_%s_RD_INIT_VALUE", name), Const(State::Sx, width)); else if (pdef.rdinitval == ResetValKind::NoUndef) @@ -1984,14 +1989,14 @@ void MemMapping::emit_port(const MemConfig &cfg, std::vector &cells, cons cell->setParam(stringf("\\PORT_%s_RD_SRST_VALUE", name), Const(State::S0, width)); } SigSpec hw_rdata = mem.module->addWire(NEW_ID, width); - cell->setPort(stringf("\\PORT_%s_RD_DATA", name), hw_rdata); + set_ram_port(cell, stringf("\\PORT_%s_RD_DATA", name), hw_rdata); } } } } void MemMapping::emit(const MemConfig &cfg) { - log("mapping memory %s.%s via %s\n", mem.module->name.unescape(), mem.memid.unescape(), cfg.def->id.unescape()); + log("mapping memory %s.%s via %s\n", mem.module, mem.memid.unescape(), RTLIL::unescape_id(cfg.def->id)); // First, handle emulations. if (cfg.emu_read_first) mem.emulate_read_first(&worker.initvals); @@ -2068,7 +2073,7 @@ void MemMapping::emit(const MemConfig &cfg) { for (int rp = 0; rp < cfg.repl_port; rp++) { std::vector cells; for (int rd = 0; rd < cfg.repl_d; rd++) { - Cell *cell = mem.module->addCell(stringf("%s.%d.%d", mem.memid, rp, rd), cfg.def->id); + Cell *cell = mem.module->addCell(stringf("%s.%d.%d", mem.memid.str(), rp, rd), mem.module->design->twines.add(std::string(cfg.def->id))); if (cfg.def->width_mode == WidthMode::Global || opts.force_params) cell->setParam(ID::WIDTH, cfg.def->dbits[cfg.base_width_log2]); if (opts.force_params) @@ -2086,12 +2091,12 @@ void MemMapping::emit(const MemConfig &cfg) { auto &ccfg = cfg.shared_clocks[i]; if (cdef.anyedge) { cell->setParam(stringf("\\CLK_%s_POL", cdef.name), ccfg.used ? ccfg.polarity : true); - cell->setPort(stringf("\\CLK_%s", cdef.name), ccfg.used ? ccfg.clk : State::S0); + set_ram_port(cell, stringf("\\CLK_%s", cdef.name), ccfg.used ? ccfg.clk : State::S0); } else { SigSpec sig = ccfg.used ? ccfg.clk : State::S0; if (ccfg.used && ccfg.invert) sig = mem.module->Not(NEW_ID, sig); - cell->setPort(stringf("\\CLK_%s", cdef.name), sig); + set_ram_port(cell, stringf("\\CLK_%s", cdef.name), sig); } } if (cfg.def->init == MemoryInitKind::Any || cfg.def->init == MemoryInitKind::NoUndef) { @@ -2252,9 +2257,9 @@ struct MemoryLibMapPass : public Pass { int best = map.logic_cost; if (!map.logic_ok) { if (map.cfgs.empty()) { - log_debug("Rejected candidates for mapping memory %s.%s:\n", module->name.unescape(), mem.memid.unescape()); + log_debug("Rejected candidates for mapping memory %s.%s:\n", module, mem.memid.unescape()); log_debug("%s", map.rejected_cfg_debug_msgs); - log_error("no valid mapping found for memory %s.%s\n", module->name.unescape(), mem.memid.unescape()); + log_error("no valid mapping found for memory %s.%s\n", module, mem.memid.unescape()); } idx = 0; best = map.cfgs[0].cost; @@ -2266,7 +2271,7 @@ struct MemoryLibMapPass : public Pass { } } if (idx == -1) { - log("using FF mapping for memory %s.%s\n", module->name.unescape(), mem.memid.unescape()); + log("using FF mapping for memory %s.%s\n", module, mem.memid.unescape()); } else { map.emit(map.cfgs[idx]); // Rebuild indices after modifying module diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index cc8dce13e..f5183296f 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -33,7 +33,7 @@ struct MemoryMapWorker bool rom_only = false; bool keepdc = false; bool formal = false; - dict> attributes; + dict> attributes; RTLIL::Design *design; RTLIL::Module *module; @@ -42,6 +42,9 @@ struct MemoryMapWorker std::map, RTLIL::SigBit> decoder_cache; + + pool wire_names; + MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), sigmap(module), initvals(&sigmap, module) {} std::string map_case(std::string value) const @@ -63,7 +66,7 @@ struct MemoryMapWorker std::string genid(RTLIL::IdString name, std::string token1 = "", int i = -1, std::string token2 = "", int j = -1, std::string token3 = "", int k = -1, std::string token4 = "") { std::stringstream sstr; - sstr << "$memory" << name.str() << token1; + sstr << "$memory" << design->twines.str(name) << token1; if (i >= 0) sstr << "[" << i << "]"; @@ -115,11 +118,12 @@ struct MemoryMapWorker // check if attributes allow us to infer FFRAM for this memory for (const auto &attr : attributes) { - if (mem.attributes.count(attr.first)) { - const auto &cell_attr = mem.attributes[attr.first]; + IdString attr_ref = design->twines.find(attr.first); + if (attr_ref != IdString::Null && mem.attributes.count(attr_ref)) { + const auto &cell_attr = mem.attributes[attr_ref]; if (attr.second.empty()) { log("Not mapping memory %s in module %s (attribute %s is set).\n", - mem.memid.c_str(), module->name.c_str(), attr.first.c_str()); + mem.memid, module->name, attr.first); return; } @@ -133,10 +137,10 @@ struct MemoryMapWorker if (!found) { if (cell_attr.flags & RTLIL::CONST_FLAG_STRING) { log("Not mapping memory %s in module %s (attribute %s is set to \"%s\").\n", - mem.memid.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.decode_string().c_str()); + mem.memid, module->name, attr.first, cell_attr.decode_string().c_str()); } else { log("Not mapping memory %s in module %s (attribute %s is set to %d).\n", - mem.memid.c_str(), module->name.c_str(), attr.first.c_str(), cell_attr.as_int()); + mem.memid, module->name, attr.first, cell_attr.as_int()); } return; } @@ -170,24 +174,24 @@ struct MemoryMapWorker static_only = false; if (GetSize(refclock) != 0) log("Not mapping memory %s in module %s (mixed clocked and async write ports).\n", - mem.memid.c_str(), module->name.c_str()); + mem.memid, module->name); if (!formal) log("Not mapping memory %s in module %s (write port %d has no clock).\n", - mem.memid.c_str(), module->name.c_str(), i); + mem.memid, module->name, i); async_wr = true; continue; } static_only = false; if (async_wr) log("Not mapping memory %s in module %s (mixed clocked and async write ports).\n", - mem.memid.c_str(), module->name.c_str()); + mem.memid, module->name); if (refclock.size() == 0) { refclock = port.clk; refclock_pol = port.clk_polarity; } if (port.clk != refclock || port.clk_polarity != refclock_pol) { log("Not mapping memory %s in module %s (write clock %d is incompatible with other clocks).\n", - mem.memid.c_str(), module->name.c_str(), i); + mem.memid, module->name, i); return; } } @@ -244,16 +248,17 @@ struct MemoryMapWorker data_reg_in[idx] = w_in; c->setPort(ID::D, w_in); - std::string w_out_name = stringf("%s[%d]", mem.memid, addr); - if (module->wires_.count(w_out_name) > 0) + std::string w_out_name = stringf("%s[%d]", mem.memid.str(), addr); + if (wire_names.count(w_out_name)) w_out_name = genid(mem.memid, "", addr, "$q"); RTLIL::Wire *w_out = module->addWire(w_out_name, mem.width); + wire_names.insert(w_out->name.str()); - if (formal && mem.packed && mem.cell->name.c_str()[0] == '\\') { + if (formal && mem.packed && mem.cell->name.isPublic()) { auto hdlname = mem.cell->get_hdlname_attribute(); if (hdlname.empty()) - hdlname.push_back(mem.cell->name.c_str() + 1); + hdlname.push_back(mem.cell->name.unescape()); hdlname.push_back(stringf("[%d]", addr)); w_out->set_hdlname_attribute(hdlname); } @@ -389,6 +394,9 @@ struct MemoryMapWorker void run() { + for (auto wire : module->wires()) + wire_names.insert(wire->name.str()); + for (auto &mem : Mem::get_selected_memories(module)) handle_memory(mem); } @@ -436,7 +444,7 @@ struct MemoryMapPass : public Pass { bool rom_only = false; bool keepdc = false; bool formal = false; - dict> attributes; + dict> attributes; log_header(design, "Executing MEMORY_MAP pass (converting memories to logic and flip-flops).\n"); diff --git a/passes/opt/clean/cells_all.cc b/passes/opt/clean/cells_all.cc index 0c4eccf59..8d41e0b30 100644 --- a/passes/opt/clean/cells_all.cc +++ b/passes/opt/clean/cells_all.cc @@ -200,9 +200,10 @@ ConflictLogs explore(CellAnalysis& analysis, CellTraversal& traversal, const Sig continue; auto bit = actx.assign_map(raw_bit); if (bit.wire == nullptr && clean_ctx.ct_all.cell_known(cell->type)) { + const TwinePool &twines = cell->module->design->twines; std::string msg = stringf("Driver-driver conflict " "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", - log_signal(raw_bit), cell->name.unescape(), it2.first.unescape(), log_signal(bit), actx.mod->name.unescape()); + log_signal(raw_bit), cell->name.unescape(), twines.unescaped_str(it2.first), log_signal(bit), actx.mod->name.unescape()); logs.logs.insert(ctx, {wire_map(raw_bit), msg}); } if (bit.wire != nullptr) @@ -237,7 +238,7 @@ struct MemAnalysis { dict indices; MemAnalysis(const RTLIL::Module* mod) : unused(mod->memories.size()), indices() { for (int i = 0; i < GetSize(mod->memories); ++i) { - indices[mod->memories.element(i)->first.str()] = i; + indices[mod->design->twines.str(mod->memories.element(i)->first)] = i; unused[i].store(true, std::memory_order_relaxed); } } @@ -324,9 +325,9 @@ void remove_mems(RTLIL::Module* mod, const MemAnalysis& mem_analysis, bool verbo for (const auto &it : mem_analysis.indices) { if (!mem_analysis.unused[it.second].load(std::memory_order_relaxed)) continue; - RTLIL::IdString id(it.first); + IdString id = mod->design->twines.add(it.first); if (verbose) - log_debug(" removing unused memory `%s'.\n", id.unescape()); + log_debug(" removing unused memory `%s'.\n", mod->memories.at(id)->name.unescape()); delete mod->memories.at(id); mod->memories.erase(id); } diff --git a/passes/opt/clean/wires.cc b/passes/opt/clean/wires.cc index 616426f9d..fb7e345bb 100644 --- a/passes/opt/clean/wires.cc +++ b/passes/opt/clean/wires.cc @@ -130,7 +130,7 @@ bool compare_signals(const RTLIL::SigBit &s1, const RTLIL::SigBit &s2, const Sha if (w1->port_output != w2->port_output) return w2->port_output; - if (w1->name[0] != w2->name[0]) + if (w1->name.isPublic() != w2->name.isPublic()) return w2->name.isPublic(); int attrs1 = count_nontrivial_wire_attrs(w1); @@ -142,14 +142,14 @@ bool compare_signals(const RTLIL::SigBit &s1, const RTLIL::SigBit &s2, const Sha return w2->name.lt_by_name(w1->name); } -bool check_public_name(RTLIL::IdString id) +bool check_public_name(RTLIL::Wire *wire) { - if (id.begins_with("$")) + if (!wire->name.isPublic()) return false; - const std::string &id_str = id.str(); - if (id.begins_with("\\_") && (id.ends_with("_") || id_str.find("_[") != std::string::npos)) + std::string name = wire->name.unescape(); + if (name[0] == '_' && (name.back() == '_' || name.find("_[") != std::string::npos)) return false; - if (id_str.find(".$") != std::string::npos) + if (name.find(".$") != std::string::npos) return false; return true; } @@ -415,7 +415,7 @@ struct WireDeleter { if (wire->port_id != 0 || wire->get_bool_attribute(ID::keep) || !initval.is_fully_undef()) { // do not delete anything with "keep" or module ports or initialized wires } else - if (!purge_mode && check_public_name(wire->name) && (check_any(used_sig_analysis.raw_connected, s1) || check_any(used_sig_analysis.connected, s2) || s1 != s2)) { + if (!purge_mode && check_public_name(wire) && (check_any(used_sig_analysis.raw_connected, s1) || check_any(used_sig_analysis.connected, s2) || s1 != s2)) { // do not get rid of public names unless in purge mode or if the wire is entirely unused, not even aliased } else if (!check_any(used_sig_analysis.raw_connected, s1)) { @@ -467,7 +467,7 @@ struct WireDeleter { int delete_wires(RTLIL::Module* mod, bool verbose) { int deleted_and_unreported = 0; for (auto wire : del_wires_queue) { - if (ys_debug() || (check_public_name(wire->name) && verbose)) + if (ys_debug() || (check_public_name(wire) && verbose)) log_debug(" removing unused non-port wire %s.\n", wire->name); else deleted_and_unreported++; diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index cb9d1ce36..7417dadf0 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -73,7 +73,7 @@ void replace_undriven(RTLIL::Module *module, const NewCellTypes &ct) { RTLIL::SigSpec sig = c; - if (c.wire->name[0] == '$') + if (!c.wire->name.isPublic()) sig = used_signals.extract(sig); if (sig.size() == 0) continue; @@ -124,8 +124,8 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, out_val.extend_u0(Y.size(), false); log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n", - cell->type.c_str(), cell->name.c_str(), info.c_str(), - module->name.c_str(), log_signal(Y), log_signal(out_val)); + cell->type, cell->name, info, + module->name, log_signal(Y), log_signal(out_val)); // log_cell(cell); assign_map.add(Y, out_val); module->connect(Y, out_val); @@ -138,7 +138,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ IdString b_name = cell->hasPort(ID::B) ? ID::B : ID::A; bool a_signed = cell->parameters.at(ID::A_SIGNED).as_bool(); - bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool(); + bool b_signed = cell->parameters.at(b_name == ID::B ? ID::B_SIGNED : ID::A_SIGNED).as_bool(); RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID::A)); RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name)); @@ -308,7 +308,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", - port.unescape(), cell->type.unescape(), cell, cell->module, + PooledName(cell->module, port).unescape(), cell->type.unescape(), cell, cell->module, log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); cell->setParam(param, !cell->getParam(param).as_bool()); @@ -333,14 +333,14 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin } } - if (cell->type.in(type1, type2)) { + if (cell->type == type1 || cell->type == type2) { SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", - port.unescape(), cell->type.unescape(), cell, cell->module, + PooledName(cell->module, port).unescape(), cell->type.unescape(), cell, cell->module, log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); - cell->type = cell->type == type1 ? type2 : type1; + cell->type = cell->module->design->twines.add(cell->type == type1 ? type2 : type1); } } } @@ -398,7 +398,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons dict invert_map; for (auto cell : module->cells()) { - if (design->selected(module, cell) && cell->type[0] == '$') { + if (design->selected(module, cell) && !cell->type.isPublic()) { if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1) invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A)); @@ -802,7 +802,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (GetSize(new_sig_a) < GetSize(sig_a)) { log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a)); + cell->type, cell->name, module->name, log_signal(sig_a), log_signal(new_sig_a)); cell->setPort(ID::A, new_sig_a); cell->parameters.at(ID::A_WIDTH) = GetSize(new_sig_a); did_something = true; @@ -824,7 +824,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (GetSize(new_sig_b) < GetSize(sig_b)) { log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b)); + cell->type, cell->name, module->name, log_signal(sig_b), log_signal(new_sig_b)); cell->setPort(ID::B, new_sig_b); cell->parameters.at(ID::B_WIDTH) = GetSize(new_sig_b); did_something = true; @@ -849,7 +849,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) { log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); + cell->type, cell->name, module->name, log_signal(sig_a), log_signal(new_a)); cell->setPort(ID::A, sig_a = new_a); cell->parameters.at(ID::A_WIDTH) = 1; did_something = true; @@ -874,7 +874,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) { log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); + cell->type, cell->name, module->name, log_signal(sig_a), log_signal(new_a)); cell->setPort(ID::A, sig_a = new_a); cell->parameters.at(ID::A_WIDTH) = 1; did_something = true; @@ -899,7 +899,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) { log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b)); + cell->type, cell->name, module->name, log_signal(sig_b), log_signal(new_b)); cell->setPort(ID::B, sig_b = new_b); cell->parameters.at(ID::B_WIDTH) = 1; did_something = true; @@ -1171,7 +1171,7 @@ skip_fine_alu: ACTION_DO(ID::Y, cell->getPort(ID::A)); if (input == State::S0 && !a.is_fully_undef()) { log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str()); + cell->type, cell->name, module->name); cell->setPort(ID::A, SigSpec(State::Sx, GetSize(a))); did_something = true; goto next_cell; @@ -1375,7 +1375,7 @@ skip_fine_alu: if (identity_wrt_a || identity_wrt_b) { log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n", - cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B'); + cell->type, cell->name, module->name, identity_wrt_a ? 'A' : 'B'); if (cell->type == ID($alu)) { bool a_signed = cell->parameters[ID::A_SIGNED].as_bool(); @@ -1672,14 +1672,14 @@ skip_identity: // 2^B = 1<name.c_str(), module->name.c_str()); + cell->name, module->name); cell->type = ID($shl); cell->parameters[ID::A_WIDTH] = 1; cell->setPort(ID::A, Const(State::S1, 1)); } else { log_debug("Replacing pow cell `%s' in module `%s' with multiply and left-shift\n", - cell->name.c_str(), module->name.c_str()); + cell->name, module->name); cell->type = ID($mul); cell->setPort(ID::A, Const(bit_idx, cell->parameters[ID::A_WIDTH].as_int())); @@ -1710,7 +1710,7 @@ skip_identity: if (sig_a.is_fully_zero()) { log_debug("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n", - cell->name.c_str(), module->name.c_str()); + cell->name, module->name); module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size()))); module->remove(cell); @@ -1723,7 +1723,7 @@ skip_identity: if (sig_a.is_onehot(&exp) && !(a_signed && exp == GetSize(sig_a) - 1)) { log_debug("Replacing multiply-by-%s cell `%s' in module `%s' with shift-by-%d.\n", - log_signal(sig_a), cell->name.c_str(), module->name.c_str(), exp); + log_signal(sig_a), cell->name, module->name, exp); if (!swapped_ab) { cell->setPort(ID::A, cell->getPort(ID::B)); @@ -1756,7 +1756,7 @@ skip_identity: if (a_zeros || b_zeros) { int y_zeros = a_zeros + b_zeros; log_debug("Removing low %d A and %d B bits from cell `%s' in module `%s'.\n", - a_zeros, b_zeros, cell->name.c_str(), module->name.c_str()); + a_zeros, b_zeros, cell->name, module->name); if (y_zeros >= GetSize(sig_y)) { module->connect(sig_y, RTLIL::SigSpec(0, GetSize(sig_y))); @@ -1797,7 +1797,7 @@ skip_identity: if (sig_b.is_fully_zero()) { log_debug("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n", - cell->name.c_str(), module->name.c_str()); + cell->name, module->name); module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size()))); module->remove(cell); @@ -1814,7 +1814,7 @@ skip_identity: bool is_truncating = cell->type == ID($div); log_debug("Replacing %s-divide-by-%s cell `%s' in module `%s' with shift-by-%d.\n", is_truncating ? "truncating" : "flooring", - log_signal(sig_b), cell->name.c_str(), module->name.c_str(), exp); + log_signal(sig_b), cell->name, module->name, exp); Const new_b = exp; @@ -1842,7 +1842,7 @@ skip_identity: bool is_truncating = cell->type == ID($mod); log_debug("Replacing %s-modulo-by-%s cell `%s' in module `%s' with bitmask.\n", is_truncating ? "truncating" : "flooring", - log_signal(sig_b), cell->name.c_str(), module->name.c_str()); + log_signal(sig_b), cell->name, module->name); // truncating modulo has the same masked bits as flooring modulo, but // the sign bits are those of A (except when R=0) @@ -1924,7 +1924,7 @@ skip_identity: for (auto &p : split_points) log_debug("Splitting $alu cell `%s' in module `%s' at const-carry point %d.\n", - cell->name.c_str(), module->name.c_str(), p.first); + cell->name, module->name, p.first); if (split_points.back().first != GetSize(sig_y)) split_points.push_back(std::make_pair(GetSize(sig_y), State::Sx)); @@ -2010,7 +2010,7 @@ skip_alu_split: sig_y.append(RTLIL::SigSpec(State::S0, y_width - k)); log_debug("Replacing `(2^%d-1) - B` $sub cell `%s' in module `%s' with $not.\n", - k, cell->name.c_str(), module->name.c_str()); + k, cell->name, module->name); module->connect(cell->getPort(ID::Y), sig_y); module->remove(cell); did_something = true; diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 1836806cc..42109a9b9 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -59,7 +59,7 @@ struct ExtSigSpec { ExtSigSpec() {} - ExtSigSpec(RTLIL::SigSpec s, RTLIL::SigSpec sign = RTLIL::Const(0, 1), bool is_signed = false, RTLIL::IdString semantics = RTLIL::IdString()) : sig(s), sign(sign), is_signed(is_signed), semantics(semantics) {} + ExtSigSpec(RTLIL::SigSpec s, RTLIL::SigSpec sign = RTLIL::Const(0, 1), bool is_signed = false, RTLIL::IdString semantics = RTLIL::IdString::Null) : sig(s), sign(sign), is_signed(is_signed), semantics(semantics) {} bool empty() const { return sig.empty(); } @@ -115,11 +115,11 @@ bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) if (mergeable_type_map.empty()) { mergeable_type_map.insert({ID($sub), ID($add)}); } - auto a_type = a->type; + IdString a_type = a->type; if (mergeable_type_map.count(a_type)) a_type = mergeable_type_map.at(a_type); - auto b_type = b->type; + IdString b_type = b->type; if (mergeable_type_map.count(b_type)) b_type = mergeable_type_map.at(b_type); @@ -134,7 +134,7 @@ RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_na if (cell->type.in(ID($_ANDNOT_), ID($_ORNOT_))) return port_name; - return ""; + return RTLIL::IdString::Null; } RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) { @@ -152,8 +152,9 @@ bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name) if (cell->type.in(BITWISE_OPS, LOGICAL_OPS)) return false; - if (cell->hasParam(port_name.str() + "_SIGNED")) - return cell->getParam(port_name.str() + "_SIGNED").as_bool(); + RTLIL::IdString param_name = port_name == ID::A ? ID::A_SIGNED : ID::B_SIGNED; + if (cell->hasParam(param_name)) + return cell->getParam(param_name).as_bool(); return false; } diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1f8c11ba6..416248c16 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -234,8 +234,9 @@ struct WreduceWorker void run_reduce_inport(Cell *cell, char port, int max_port_size, bool &port_signed, bool &did_something) { - port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool(); - SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port))); + IdString port_name = port == 'A' ? ID::A : ID::B; + port_signed = cell->getParam(port == 'A' ? ID::A_SIGNED : ID::B_SIGNED).as_bool(); + SigSpec sig = mi.sigmap(cell->getPort(port_name)); if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) port_signed = false; @@ -259,7 +260,7 @@ struct WreduceWorker if (bits_removed) { log("Removed top %d bits (of %d) from port %c of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, port, module, cell, cell->type.unescape()); - cell->setPort(stringf("\\%c", port), sig); + cell->setPort(port_name, sig); did_something = true; } } @@ -575,6 +576,10 @@ struct WreducePass : public Pass { if (module->has_processes_warn()) continue; + dict memory_by_name; + for (auto &it : module->memories) + memory_by_name[design->twines.str(it.first)] = it.second; + for (auto c : module->selected_cells()) { if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), @@ -625,8 +630,8 @@ struct WreducePass : public Pass { } if (!opt_memx && c->type.in(ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2), ID($meminit), ID($meminit_v2))) { - IdString memid = c->getParam(ID::MEMID).decode_string(); - RTLIL::Memory *mem = module->memories.at(memid); + std::string memid = c->getParam(ID::MEMID).decode_string(); + RTLIL::Memory *mem = memory_by_name.at(memid); if (mem->start_offset >= 0) { int cur_addrbits = c->getParam(ID::ABITS).as_int(); int max_addrbits = ceil_log2(mem->start_offset + mem->size); @@ -634,7 +639,7 @@ struct WreducePass : public Pass { log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", cur_addrbits-max_addrbits, cur_addrbits, c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init", - module, c, memid.unescape()); + module, c, mem->name.unescape()); c->setParam(ID::ABITS, max_addrbits); c->setPort(ID::ADDR, c->getPort(ID::ADDR).extract(0, max_addrbits)); } diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index f754bc948..1a460529b 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -215,7 +215,7 @@ void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map) RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable); if (!en.is_fully_zero()) { log_error("Async reset %s causes memory write to %s.\n", - log_signal(sync->signal), memwr.memid.unescape()); + log_signal(sync->signal), PooledName(mod, memwr.memid).unescape()); } apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address); apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data); @@ -288,11 +288,14 @@ struct ProcArstPass : public Pass { extra_args(args, argidx, design); pool delete_initattr_wires; + IdString global_arst_ref = global_arst.empty() ? IdString::Null + : design->twines.find(global_arst); + for (auto mod : design->all_selected_modules()) { SigMap assign_map(mod); for (auto proc : mod->selected_processes()) { proc_arst(mod, proc, assign_map); - if (global_arst.empty() || mod->wire(global_arst) == nullptr) + if (global_arst_ref == IdString::Null || mod->wire(global_arst_ref) == nullptr) continue; std::vector arst_actions; for (auto sync : proc->syncs) @@ -309,14 +312,14 @@ struct ProcArstPass : public Pass { } if (arst_sig.size()) { log("Added global reset to process %s: %s <- %s\n", - proc->name.c_str(), log_signal(arst_sig), log_signal(arst_val)); + proc->name, log_signal(arst_sig), log_signal(arst_val)); arst_actions.push_back(RTLIL::SigSig(arst_sig, arst_val)); } } if (!arst_actions.empty()) { RTLIL::SyncRule *sync = new RTLIL::SyncRule; sync->type = global_arst_neg ? RTLIL::SyncType::ST0 : RTLIL::SyncType::ST1; - sync->signal = mod->wire(global_arst); + sync->signal = mod->wire(global_arst_ref); sync->actions = arst_actions; proc->syncs.push_back(sync); } diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc index 2535d716b..4a42e494b 100644 --- a/passes/proc/proc_memwr.cc +++ b/passes/proc/proc_memwr.cc @@ -29,13 +29,14 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &next_port_id) +void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &next_port_id) { for (auto sr : proc->syncs) { std::vector prev_port_ids; for (auto memwr : sr->mem_write_actions) { - int port_id = next_port_id[memwr.memid]++; + std::string memid = mod->design->twines.str(memwr.memid); + int port_id = next_port_id[memid]++; Const priority_mask(State::S0, port_id); for (int i = 0; i < GetSize(prev_port_ids); i++) if (memwr.priority_mask[i] == State::S1) @@ -44,7 +45,7 @@ void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &n RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr_v2)); cell->attributes = memwr.attributes; - cell->setParam(ID::MEMID, Const(memwr.memid.str())); + cell->setParam(ID::MEMID, Const(memid)); cell->setParam(ID::ABITS, GetSize(memwr.address)); cell->setParam(ID::WIDTH, GetSize(memwr.data)); cell->setParam(ID::PORTID, port_id); @@ -100,11 +101,11 @@ struct ProcMemWrPass : public Pass { extra_args(args, 1, design); for (auto mod : design->all_selected_modules()) { - dict next_port_id; + dict next_port_id; for (auto cell : mod->cells()) { if (cell->type.in(ID($memwr), ID($memwr_v2))) { bool is_compat = cell->type == ID($memwr); - IdString memid = cell->parameters.at(ID::MEMID).decode_string(); + std::string memid = cell->parameters.at(ID::MEMID).decode_string(); int port_id = cell->parameters.at(is_compat ? ID::PRIORITY : ID::PORTID).as_int(); if (port_id >= next_port_id[memid]) next_port_id[memid] = port_id + 1; diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc index 5dd1b07b4..0b04fe009 100644 --- a/passes/sat/miter.cc +++ b/passes/sat/miter.cc @@ -71,16 +71,16 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: if (argidx+3 != args.size() || args[argidx].compare(0, 1, "-") == 0) that->cmd_error(args, argidx, "command argument error"); - RTLIL::IdString gold_name = RTLIL::escape_id(args[argidx++]); - RTLIL::IdString gate_name = RTLIL::escape_id(args[argidx++]); - RTLIL::IdString miter_name = RTLIL::escape_id(args[argidx++]); + IdString gold_name = design->twines.add(RTLIL::escape_id(args[argidx++])); + IdString gate_name = design->twines.add(RTLIL::escape_id(args[argidx++])); + IdString miter_name = design->twines.add(RTLIL::escape_id(args[argidx++])); if (design->module(gold_name) == nullptr) - log_cmd_error("Can't find gold module %s!\n", gold_name); + log_cmd_error("Can't find gold module %s!\n", design->twines.str(gold_name)); if (design->module(gate_name) == nullptr) - log_cmd_error("Can't find gate module %s!\n", gate_name); + log_cmd_error("Can't find gate module %s!\n", design->twines.str(gate_name)); if (design->module(miter_name) != nullptr) - log_cmd_error("There is already a module %s!\n", miter_name); + log_cmd_error("There is already a module %s!\n", design->twines.str(miter_name)); RTLIL::Module *gold_module = design->module(gold_name); RTLIL::Module *gate_module = design->module(gate_name); @@ -128,14 +128,15 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name); } - log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", miter_name.unescape(), gold_name.unescape(), gate_name.unescape()); + log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", PooledName(design, miter_name).unescape(), PooledName(design, gold_name).unescape(), PooledName(design, gate_name).unescape()); RTLIL::Module *miter_module = new RTLIL::Module; + miter_module->design = design; miter_module->name = miter_name; design->add(miter_module); - RTLIL::Cell *gold_cell = miter_module->addCell(ID(gold), gold_name); - RTLIL::Cell *gate_cell = miter_module->addCell(ID(gate), gate_name); + RTLIL::Cell *gold_cell = miter_module->addCell(ID::gold, gold_module->name); + RTLIL::Cell *gate_cell = miter_module->addCell(ID::gate, gate_module->name); RTLIL::SigSpec all_conditions; @@ -318,13 +319,13 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL if ((argidx+1 != args.size() && argidx+2 != args.size()) || args[argidx].compare(0, 1, "-") == 0) that->cmd_error(args, argidx, "command argument error"); - IdString module_name = RTLIL::escape_id(args[argidx++]); - IdString miter_name = argidx < args.size() ? RTLIL::escape_id(args[argidx++]) : ""; + IdString module_name = design->twines.add(RTLIL::escape_id(args[argidx++])); + IdString miter_name = argidx < args.size() ? design->twines.add(RTLIL::escape_id(args[argidx++])) : IdString::Null; if (design->module(module_name) == nullptr) - log_cmd_error("Can't find module %s!\n", module_name); + log_cmd_error("Can't find module %s!\n", design->twines.str(module_name)); if (!miter_name.empty() && design->module(miter_name) != nullptr) - log_cmd_error("There is already a module %s!\n", miter_name); + log_cmd_error("There is already a module %s!\n", design->twines.str(miter_name)); Module *module = design->module(module_name); diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index b892683a8..5f2671924 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -47,11 +47,11 @@ pool validate_design_and_get_inputs(RTLIL::Module *module, bool ass found_1bit_output = true; } for (auto cell : module->cells()) { - if (cell->type == "$allconst") + if (cell->type == ID($allconst)) found_input = true; - if (cell->type == "$anyconst") + if (cell->type == ID($anyconst)) found_hole = true; - if (cell->type.in("$assert", "$assume")) + if (cell->type.in(ID($assert), ID($assume))) found_assert_assume = true; } if (!found_input) @@ -82,6 +82,7 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) { log_cmd_error("could not read solution file.\n"); std::string buf; + TwineSearch search(&module->design->twines); while (std::getline(fin, buf)) { bool bit_assn = true; if (!std::regex_search(buf, bit_m, hole_bit_assn_regex)) { @@ -100,8 +101,8 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) { //We have two options to identify holes. First, try to match wire names. If we can't find a matching wire, //then try to find a cell with a matching location. RTLIL::SigBit hole_sigbit; - if (module->wire(hole_name) != nullptr) { - RTLIL::Wire *hole_wire = module->wire(hole_name); + if (module->wire(search.find(hole_name)) != nullptr) { + RTLIL::Wire *hole_wire = module->wire(search.find(hole_name)); hole_sigbit = RTLIL::SigSpec(hole_wire)[hole_offset]; } else { auto locs = split_tokens(hole_loc, "|"); @@ -159,11 +160,12 @@ void specialize(RTLIL::Module *module, const QbfSolutionType &sol, bool quiet = } void allconstify_inputs(RTLIL::Module *module, const pool &input_wires) { + TwineSearch search(&module->design->twines); for (auto &n : input_wires) { - RTLIL::Wire *input = module->wire(n); + RTLIL::Wire *input = module->wire(search.find(n)); log_assert(input != nullptr); - RTLIL::Cell *allconst = module->addCell("$allconst$" + n, "$allconst"); + RTLIL::Cell *allconst = module->addCell("$allconst$" + n, ID($allconst)); allconst->setParam(ID(WIDTH), input->width); allconst->setPort(ID::Y, input); allconst->set_src_attribute(input->get_src_attribute()); @@ -255,8 +257,8 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { const std::string tempdir_name = make_temp_dir(get_base_tmpdir() + "/yosys-qbfsat-XXXXXX"); RTLIL::Module *module = mod; RTLIL::Design *design = module->design; - std::string module_name = module->name.str(); - RTLIL::IdString wire_to_optimize_name = ""; + IdString module_name = module->name; + IdString wire_to_optimize_name = IdString::Null; bool maximize = false; log_assert(module->design != nullptr); @@ -270,14 +272,14 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { //Find the wire to be optimized, if any: for (auto wire : module->wires()) { - if (wire->get_bool_attribute("\\maximize") || wire->get_bool_attribute("\\minimize")) { + if (wire->get_bool_attribute(ID::maximize) || wire->get_bool_attribute(ID::minimize)) { wire_to_optimize_name = wire->name; - maximize = wire->get_bool_attribute("\\maximize"); + maximize = wire->get_bool_attribute(ID::maximize); if (opt.nooptimize) { if (maximize) - wire->set_bool_attribute("\\maximize", false); + wire->set_bool_attribute(ID::maximize, false); else - wire->set_bool_attribute("\\minimize", false); + wire->set_bool_attribute(ID::minimize, false); } } } @@ -292,7 +294,7 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { Pass::call(module->design, "opt"); } - if (opt.nobisection || opt.nooptimize || wire_to_optimize_name == "") { + if (opt.nobisection || opt.nooptimize || wire_to_optimize_name == IdString::Null) { ret = call_qbf_solver(module, opt, tempdir_name, false, 0); } else { //Do the iterated bisection method: @@ -301,9 +303,9 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { unsigned int failure = 0; unsigned int cur_thresh = 0; - log_assert(wire_to_optimize_name != ""); + log_assert(wire_to_optimize_name != IdString::Null); log_assert(module->wire(wire_to_optimize_name) != nullptr); - log("%s wire \"%s\".\n", (maximize? "Maximizing" : "Minimizing"), wire_to_optimize_name); + log("%s wire \"%s\".\n", (maximize? "Maximizing" : "Minimizing"), design->twines.str(wire_to_optimize_name)); //If maximizing, grow until we get a failure. Then bisect success and failure. while (failure == 0 || difference(success, failure) > 1) { @@ -315,8 +317,8 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { RTLIL::SigSpec comparator = maximize? module->Ge(NEW_ID, module->wire(wire_to_optimize_name), RTLIL::Const(cur_thresh), false) : module->Le(NEW_ID, module->wire(wire_to_optimize_name), RTLIL::Const(cur_thresh), false); - module->addAssume(wire_to_optimize_name.str() + "__threshold", comparator, RTLIL::Const(1, 1)); - log("Trying to solve with %s %s %d.\n", wire_to_optimize_name, (maximize? ">=" : "<="), cur_thresh); + module->addAssume(design->twines.str(wire_to_optimize_name) + "__threshold", comparator, RTLIL::Const(1, 1)); + log("Trying to solve with %s %s %d.\n", design->twines.str(wire_to_optimize_name), (maximize? ">=" : "<="), cur_thresh); } ret = call_qbf_solver(module, opt, tempdir_name, false, iter_num); @@ -328,7 +330,7 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { specialize(module, ret, true); RTLIL::SigSpec wire, value, undef; - RTLIL::SigSpec::parse_sel(wire, design, module, wire_to_optimize_name.str()); + RTLIL::SigSpec::parse_sel(wire, design, module, design->twines.str(wire_to_optimize_name)); ConstEval ce(module); value = wire; @@ -337,7 +339,7 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { log_assert(value.is_fully_const()); success = value.as_const().as_int(); best_soln = ret; - log("Problem is satisfiable with %s = %d.\n", wire_to_optimize_name, success); + log("Problem is satisfiable with %s = %d.\n", design->twines.str(wire_to_optimize_name), success); Pass::call(design, "design -pop"); module = design->module(module_name); @@ -355,7 +357,7 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { break; } else - log("Problem is NOT satisfiable with %s %s %d.\n", wire_to_optimize_name, (maximize? ">=" : "<="), failure); + log("Problem is NOT satisfiable with %s %s %d.\n", design->twines.str(wire_to_optimize_name), (maximize? ">=" : "<="), failure); } iter_num++; @@ -367,7 +369,7 @@ QbfSolutionType qbf_solve(RTLIL::Module *mod, const QbfSolveOptions &opt) { cur_thresh = (success + failure) / 2; //bisection } if (success != 0 || failure != 0) { - log("Wire %s is %s at %d.\n", wire_to_optimize_name, (maximize? "maximized" : "minimized"), success); + log("Wire %s is %s at %d.\n", design->twines.str(wire_to_optimize_name), (maximize? "maximized" : "minimized"), success); ret = best_soln; } } @@ -606,7 +608,7 @@ struct QbfSatPass : public Pass { log_push(); if (!opt.specialize_from_file) { //Save the design to restore after modiyfing the current module. - std::string module_name = module->name.str(); + IdString module_name = module->name; QbfSolutionType ret = qbf_solve(module, opt); module = design->module(module_name); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 973dafd28..a8c989a32 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -277,7 +277,7 @@ struct SimInstance } } - if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) { + if ((shared->fst) && !(shared->hide_internal && !wire->name.isPublic())) { fstHandle id = shared->fst->getHandle(scope + "." + wire->name.unescape()); if (id==0 && wire->name.isPublic()) log_warning("Unable to find wire %s in input file.\n", (scope + "." + wire->name.unescape())); @@ -302,8 +302,10 @@ struct SimInstance } memories = Mem::get_all_memories(module); + dict memid_by_name; for (auto &mem : memories) { auto &mdb = mem_database[mem.memid]; + memid_by_name[mem.memid.unescape()] = mem.memid; mdb.mem = &mem; for (auto &port : mem.wr_ports) { mdb.past_wr_clk.push_back(Const(State::Sx)); @@ -351,10 +353,13 @@ struct SimInstance if (cell->is_mem_cell()) { - std::string name = cell->parameters.at(ID::MEMID).decode_string(); + std::string name_str = cell->parameters.at(ID::MEMID).decode_string(); + auto mit = memid_by_name.find(RTLIL::unescape_id(name_str)); + IdString name = mit != memid_by_name.end() ? mit->second + : module->design->twines.add(std::string(name_str)); mem_cells[cell] = name; if (shared->fst) - fst_memories[name] = shared->fst->getMemoryHandles(scope + "." + RTLIL::unescape_id(name)); + fst_memories[name] = shared->fst->getMemoryHandles(scope + "." + RTLIL::unescape_id(name_str)); } if (cell->type.in(ID($assert), ID($cover), ID($assume))) @@ -523,7 +528,7 @@ struct SimInstance { auto &state = mem_database[memid]; if (offset >= state.mem->size * state.mem->width) - log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, memid.unescape()); + log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, PooledName(state.mem->module, memid).unescape()); if (state.data[offset] != data) { state.data.set(offset, data); dirty_memories.insert(memid); @@ -1016,7 +1021,7 @@ struct SimInstance { for (auto wire : module->wires()) { - if (shared->hide_internal && wire->name[0] == '$') + if (shared->hide_internal && !wire->name.isPublic()) continue; signal_database[wire] = {id, Const(), sigmap(wire)}; @@ -1027,17 +1032,17 @@ struct SimInstance child.second->register_signals(id); } - void write_output_header(std::function enter_scope, std::function exit_scope, std::function register_signal) + void write_output_header(std::function enter_scope, std::function exit_scope, std::function register_signal) { int exit_scopes = 1; if (shared->hdlname && instance != nullptr && instance->name.isPublic() && instance->has_attribute(ID::hdlname)) { auto hdlname = instance->get_hdlname_attribute(); log_assert(!hdlname.empty()); for (auto name : hdlname) - enter_scope("\\" + name); + enter_scope(name); exit_scopes = hdlname.size(); } else - enter_scope(name()); + enter_scope(module->design->twines.unescaped_str(name())); dict registers; for (auto cell : module->cells()) @@ -1059,7 +1064,7 @@ struct SimInstance auto signal_name = std::move(hdlname.back()); hdlname.pop_back(); for (auto name : hdlname) - enter_scope("\\" + name); + enter_scope(name); register_signal(signal_name.c_str(), GetSize(signal.first), signal.first, signal.second.id, registers.count(signal.first)!=0); for (auto name : hdlname) exit_scope(); @@ -1083,9 +1088,9 @@ struct SimInstance signal_name = std::move(hdlname.back()); hdlname.pop_back(); for (auto name : hdlname) - enter_scope("\\" + name); + enter_scope(name); } else { - signal_name = memid.unescape(); + signal_name = module->design->twines.unescaped_str(memid); } for (auto &trace_index : trace_mem.second) { @@ -1181,7 +1186,7 @@ struct SimInstance for (auto cell : module->cells()) { if (cell->is_mem_cell()) { - std::string memid = cell->parameters.at(ID::MEMID).decode_string(); + IdString memid = module->design->twines.add(cell->parameters.at(ID::MEMID).decode_string()); for (auto &data : fst_memories[memid]) { std::string v = shared->fst->valueOf(data.second); @@ -1212,7 +1217,7 @@ struct SimInstance } } if (!found) - log_error("Unable to find required '%s' signal in file\n",(scope + "." + sig_y.as_wire()->name.unescape())); + log_error("Unable to find required '%s' signal in file\n",(scope + "." + module->design->twines.unescaped_str(sig_y.as_wire()->name))); } } } @@ -1257,7 +1262,7 @@ struct SimInstance issue_count++; any_undriven_found = true; - std::string wire_name = scope + "." + RTLIL::unescape_id(wire->name); + std::string wire_name = scope + "." + wire->name.unescape(); log_warning("Input trace contains undriven signal `%s` (%s).\n", wire_name.c_str(), log_signal(undriven)); } } @@ -1295,7 +1300,7 @@ struct SimInstance } } - void setMemState(dict> bits, std::string values) + void setMemState(dict> bits, std::string values) { for(auto bit : bits) { if (bit.first >= GetSize(values)) @@ -1457,10 +1462,11 @@ struct SimWorker : SimShared { for (auto portname : ports) { - Wire *w = top->module->wire(portname); + IdString portref = portname; + Wire *w = top->module->wire(portref); if (w == nullptr) - log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); + log_error("Can't find port %s on module %s.\n", PooledName(top->module, portref).unescape(), top->module); top->set_state(w, value); } @@ -1541,26 +1547,28 @@ struct SimWorker : SimShared for (auto portname : clock) { - Wire *w = topmod->wire(portname); + IdString portref = portname; + Wire *w = topmod->wire(portref); if (!w) - log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); + log_error("Can't find port %s on module %s.\n", PooledName(topmod, portref).unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); - fstHandle id = fst->getHandle(scope + "." + portname.unescape()); + log_error("Clock port %s on module %s is not input.\n", PooledName(topmod, portref).unescape(), top->module); + fstHandle id = fst->getHandle(scope + "." + topmod->design->twines.unescaped_str(portref)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); + log_error("Can't find port %s.%s in FST.\n", scope, PooledName(topmod, portref).unescape()); fst_clock.push_back(id); } for (auto portname : clockn) { - Wire *w = topmod->wire(portname); + IdString portref = portname; + Wire *w = topmod->wire(portref); if (!w) - log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); + log_error("Can't find port %s on module %s.\n", PooledName(topmod, portref).unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); - fstHandle id = fst->getHandle(scope + "." + portname.unescape()); + log_error("Clock port %s on module %s is not input.\n", PooledName(topmod, portref).unescape(), top->module); + fstHandle id = fst->getHandle(scope + "." + topmod->design->twines.unescaped_str(portref)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); + log_error("Can't find port %s.%s in FST.\n", scope, PooledName(topmod, portref).unescape()); fst_clock.push_back(id); } @@ -1680,20 +1688,20 @@ struct SimWorker : SimShared std::string type, symbol; int variable, index; dict> inputs, inits, latches; - dict> mem_inits, mem_latches; + dict> mem_inits, mem_latches; if (mf.fail()) log_cmd_error("Not able to read AIGER witness map file.\n"); while (mf >> type >> variable >> index >> symbol) { - RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); + IdString escaped_s = topmod->design->twines.add(RTLIL::escape_id(symbol)); Wire *w = topmod->wire(escaped_s); if (!w) { - escaped_s = RTLIL::escape_id(cell_name(symbol)); + escaped_s = topmod->design->twines.add(RTLIL::escape_id(cell_name(symbol))); Cell *c = topmod->cell(escaped_s); if (!c) log_warning("Wire/cell %s not present in module %s\n",symbol,topmod); if (c->is_mem_cell()) { - std::string memid = c->parameters.at(ID::MEMID).decode_string(); + IdString memid = topmod->design->twines.add(c->parameters.at(ID::MEMID).decode_string()); auto &state = top->mem_database[memid]; int offset = (mem_cell_addr(symbol) - state.mem->start_offset) * state.mem->width + index; @@ -1833,6 +1841,8 @@ struct SimWorker : SimShared int curr_cycle = 0; std::vector parts; size_t len = 0; + TwinePool& twines = topmod->design->twines; + std::optional search; while (!f.eof()) { std::string line; @@ -1865,6 +1875,8 @@ struct SimWorker : SimShared continue; } + if (!search) + search.emplace(&twines); switch(state) { case 0: @@ -1883,13 +1895,15 @@ struct SimWorker : SimShared if (len<3 || len>4) log_error("Invalid set state line content.\n"); - RTLIL::IdString escaped_s = RTLIL::escape_id(signal_name(parts[len-1])); + std::string unescaped_s = signal_name(parts[len-1]); + std::string escaped_s = RTLIL::escape_id(unescaped_s); + IdString found = search->find(escaped_s); if (len==3) { - Wire *w = topmod->wire(escaped_s); + Wire *w = topmod->wire(found); if (!w) { - Cell *c = topmod->cell(escaped_s); + Cell *c = topmod->cell(found); if (!c) - log_warning("Wire/cell %s not present in module %s\n",escaped_s.unescape(),topmod); + log_warning("Wire/cell %s not present in module %s\n", unescaped_s, topmod); else if (c->type.in(ID($anyconst), ID($anyseq))) { SigSpec sig_y= c->getPort(ID::Y); if ((int)parts[1].size() != GetSize(sig_y)) @@ -1902,15 +1916,15 @@ struct SimWorker : SimShared top->set_state(w, Const::from_string(parts[1])); } } else { - Cell *c = topmod->cell(escaped_s); + Cell *c = topmod->cell(found); if (!c) - log_error("Cell %s not present in module %s\n",escaped_s.unescape(),topmod); + log_error("Cell %s not present in module %s\n", unescaped_s,topmod); if (!c->is_mem_cell()) - log_error("Cell %s is not memory cell in module %s\n",escaped_s.unescape(),topmod); + log_error("Cell %s is not memory cell in module %s\n", unescaped_s,topmod); Const addr = Const::from_string(parts[1].substr(1,parts[1].size()-2)); Const data = Const::from_string(parts[2]); - top->set_memory_state(c->parameters.at(ID::MEMID).decode_string(), addr, data); + top->set_memory_state(topmod->design->twines.add(c->parameters.at(ID::MEMID).decode_string()), addr, data); } break; } @@ -1935,7 +1949,7 @@ struct SimWorker : SimShared { YwHierarchy hierarchy; pool paths; - dict> mem_paths; + dict> mem_paths; for (auto &signal : yw.signals) paths.insert(signal.path); @@ -2206,27 +2220,29 @@ struct SimWorker : SimShared for (auto portname : clock) { - Wire *w = topmod->wire(portname); + IdString portref = portname; + Wire *w = topmod->wire(portref); if (!w) - log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); + log_error("Can't find port %s on module %s.\n", PooledName(topmod, portref).unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); - fstHandle id = fst->getHandle(scope + "." + portname.unescape()); + log_error("Clock port %s on module %s is not input.\n", PooledName(topmod, portref).unescape(), top->module); + fstHandle id = fst->getHandle(scope + "." + topmod->design->twines.unescaped_str(portref)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); + log_error("Can't find port %s.%s in FST.\n", scope, PooledName(topmod, portref).unescape()); fst_clock.push_back(id); clocks[w] = id; } for (auto portname : clockn) { - Wire *w = topmod->wire(portname); + IdString portref = portname; + Wire *w = topmod->wire(portref); if (!w) - log_error("Can't find port %s on module %s.\n", portname.unescape(), top->module); + log_error("Can't find port %s on module %s.\n", PooledName(topmod, portref).unescape(), top->module); if (!w->port_input) - log_error("Clock port %s on module %s is not input.\n", portname.unescape(), top->module); - fstHandle id = fst->getHandle(scope + "." + portname.unescape()); + log_error("Clock port %s on module %s is not input.\n", PooledName(topmod, portref).unescape(), top->module); + fstHandle id = fst->getHandle(scope + "." + topmod->design->twines.unescaped_str(portref)); if (id==0) - log_error("Can't find port %s.%s in FST.\n", scope, portname.unescape()); + log_error("Can't find port %s.%s in FST.\n", scope, PooledName(topmod, portref).unescape()); fst_clock.push_back(id); clocks[w] = id; } @@ -2419,7 +2435,7 @@ struct VCDWriter : public OutputWriter vcdfile << stringf("$timescale %s $end\n", worker->timescale); worker->top->write_output_header( - [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", name.unescape()); }, + [this](const std::string& name) { vcdfile << stringf("$scope module %s $end\n", name); }, [this]() { vcdfile << stringf("$upscope $end\n");}, [this,use_signal](const char *name, int size, Wire *w, int id, bool is_reg) { if (!use_signal.at(id)) return; @@ -2485,7 +2501,7 @@ struct FSTWriter : public OutputWriter fstWriterSetRepackOnClose(fstfile, 1); worker->top->write_output_header( - [this](IdString name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, stringf("%s",name.unescape()).c_str(), nullptr); }, + [this](const std::string& name) { fstWriterSetScope(fstfile, FST_ST_VCD_MODULE, name.c_str(), nullptr); }, [this]() { fstWriterSetUpscope(fstfile); }, [this,use_signal](const char *name, int size, Wire *w, int id, bool is_reg) { if (!use_signal.at(id)) return; @@ -2545,10 +2561,10 @@ struct AIWWriter : public OutputWriter if (mf.fail()) log_cmd_error("Not able to read AIGER witness map file.\n"); while (mf >> type >> variable >> index >> symbol) { - RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); + IdString escaped_s = worker->top->module->design->twines.add(RTLIL::escape_id(symbol)); Wire *w = worker->top->module->wire(escaped_s); if (!w) - log_error("Wire %s not present in module %s\n",escaped_s.unescape(),worker->top->module); + log_error("Wire %s not present in module %s\n", PooledName(worker->top->module, escaped_s).unescape(), worker->top->module); if (index < w->start_offset || index > w->start_offset + w->width) log_error("Index %d for wire %s is out of range\n", index, log_signal(w)); if (type == "input") { @@ -2571,7 +2587,7 @@ struct AIWWriter : public OutputWriter } worker->top->write_output_header( - [](IdString) {}, + [](const std::string&) {}, []() {}, [this](const char */*name*/, int /*size*/, Wire *wire, int id, bool) { if (wire != nullptr) mapping[wire] = id; } ); @@ -2826,19 +2842,19 @@ struct SimPass : public Pass { continue; } if (args[argidx] == "-clock" && argidx+1 < args.size()) { - worker.clock.insert(RTLIL::escape_id(args[++argidx])); + worker.clock.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-clockn" && argidx+1 < args.size()) { - worker.clockn.insert(RTLIL::escape_id(args[++argidx])); + worker.clockn.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-reset" && argidx+1 < args.size()) { - worker.reset.insert(RTLIL::escape_id(args[++argidx])); + worker.reset.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-resetn" && argidx+1 < args.size()) { - worker.resetn.insert(RTLIL::escape_id(args[++argidx])); + worker.resetn.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-timescale" && argidx+1 < args.size()) { @@ -3053,11 +3069,11 @@ struct Fst2TbPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-clock" && argidx+1 < args.size()) { - worker.clock.insert(RTLIL::escape_id(args[++argidx])); + worker.clock.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-clockn" && argidx+1 < args.size()) { - worker.clockn.insert(RTLIL::escape_id(args[++argidx])); + worker.clockn.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-r" && argidx+1 < args.size()) { diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 9ea843f2a..ef93e7eba 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -329,7 +329,8 @@ struct AbcModuleState { int map_signal(const AbcSigMap &assign_map, RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1, int in2 = -1, int in3 = -1, int in4 = -1); void mark_port(const AbcSigMap &assign_map, RTLIL::SigSpec sig); bool prepare_cell(const AbcSigMap &assign_map, RTLIL::Cell *cell, bool keepff); - std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullptr); + std::string remap_name(const std::string &abc_name, RTLIL::Wire **orig_wire = nullptr); + RTLIL::IdString remap_ref(RTLIL::Module *module, const std::string &abc_name); void dump_loop_graph(FILE *f, int &nr, dict> &edges, pool &workpool, std::vector &in_counts); void handle_loops(AbcSigMap &assign_map, RTLIL::Module *module); void prepare_module(RTLIL::Design *design, RTLIL::Module *module, AbcSigMap &assign_map, const std::vector &cells, @@ -599,7 +600,12 @@ bool AbcModuleState::prepare_cell(const AbcSigMap &assign_map, RTLIL::Cell *cell return false; } -std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire) +RTLIL::IdString AbcModuleState::remap_ref(RTLIL::Module *module, const std::string &abc_name) +{ + return module->design->twines.add(remap_name(abc_name)); +} + +std::string AbcModuleState::remap_name(const std::string &abc_name, RTLIL::Wire **orig_wire) { std::string abc_sname = abc_name.substr(1); bool isnew = false; @@ -622,7 +628,7 @@ std::string AbcModuleState::remap_name(RTLIL::IdString abc_name, RTLIL::Wire **o const auto &bit = signal_bits.at(sid); if (bit.wire != nullptr) { - std::string s = stringf("$abc$%d$%s", map_autoidx, bit.wire->name.c_str()+1); + std::string s = stringf("$abc$%d$%s", map_autoidx, bit.wire->name.str().substr(1)); if (bit.wire->width != 1) s += stringf("[%d]", bit.offset); if (isnew) @@ -740,9 +746,9 @@ void AbcModuleState::handle_loops(AbcSigMap &assign_map, RTLIL::Module *module) id1 = id2; else if (w2 == nullptr) continue; - else if (w1->name[0] == '$' && w2->name[0] == '\\') + else if (!w1->name.isPublic() && w2->name.isPublic()) id1 = id2; - else if (w1->name[0] == '\\' && w2->name[0] == '$') + else if (w1->name.isPublic() && !w2->name.isPublic()) continue; else if (edges[id1].size() < edges[id2].size()) id1 = id2; @@ -980,31 +986,31 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module clk_polarity = false; clk_str = clk_str.substr(1); } - if (module->wire(RTLIL::escape_id(clk_str)) != nullptr) - clk_sig = assign_map(module->wire(RTLIL::escape_id(clk_str))); + if (RTLIL::Wire *wire = RTLIL::wire_by_name(module, clk_str)) + clk_sig = assign_map(wire); if (en_str != "") { if (en_str[0] == '!') { en_polarity = false; en_str = en_str.substr(1); } - if (module->wire(RTLIL::escape_id(en_str)) != nullptr) - en_sig = assign_map(module->wire(RTLIL::escape_id(en_str))); + if (RTLIL::Wire *wire = RTLIL::wire_by_name(module, en_str)) + en_sig = assign_map(wire); } if (arst_str != "") { if (arst_str[0] == '!') { arst_polarity = false; arst_str = arst_str.substr(1); } - if (module->wire(RTLIL::escape_id(arst_str)) != nullptr) - arst_sig = assign_map(module->wire(RTLIL::escape_id(arst_str))); + if (RTLIL::Wire *wire = RTLIL::wire_by_name(module, arst_str)) + arst_sig = assign_map(wire); } if (srst_str != "") { if (srst_str[0] == '!') { srst_polarity = false; srst_str = srst_str.substr(1); } - if (module->wire(RTLIL::escape_id(srst_str)) != nullptr) - srst_sig = assign_map(module->wire(RTLIL::escape_id(srst_str))); + if (RTLIL::Wire *wire = RTLIL::wire_by_name(module, srst_str)) + srst_sig = assign_map(wire); } } @@ -1019,7 +1025,7 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module run_abc.per_run_tempdir_name += proc_program_prefix() + "yosys-abc-XXXXXX"; run_abc.per_run_tempdir_name = make_temp_dir(run_abc.per_run_tempdir_name); log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n", - module->name.c_str(), replace_tempdir(run_abc.per_run_tempdir_name, config.global_tempdir_name, run_abc.per_run_tempdir_name, config.show_tempdir).c_str()); + module->name, replace_tempdir(run_abc.per_run_tempdir_name, config.global_tempdir_name, run_abc.per_run_tempdir_name, config.show_tempdir).c_str()); run_abc.abc_script = stringf("read_blif \"%s/input.blif\"; ", run_abc.per_run_tempdir_name); @@ -1542,7 +1548,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) ifs.close(); log_header(design, "Re-integrating ABC results.\n"); - RTLIL::Module *mapped_mod = mapped_design->module(ID(netlist)); + RTLIL::Module *mapped_mod = mapped_design->module(ID::netlist); if (mapped_mod == nullptr) log_error("ABC output file does not contain a module `netlist'.\n"); bool markgroups = run_abc.config.markgroups; @@ -1566,7 +1572,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) cell_stats[c->type.unescape()]++; if (c->type.in(ID(ZERO), ID(ONE))) { RTLIL::SigSig conn; - RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name); + IdString name_y = remap_ref(module, c->getPort(ID::Y).as_wire()->name); conn.first = module->wire(name_y); conn.second = RTLIL::SigSpec(c->type == ID(ZERO) ? 0 : 1, 1); module->connect(conn); @@ -1574,89 +1580,89 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) } if (c->type == ID(BUF)) { RTLIL::SigSig conn; - RTLIL::IdString name_y = remap_name(c->getPort(ID::Y).as_wire()->name); - RTLIL::IdString name_a = remap_name(c->getPort(ID::A).as_wire()->name); + IdString name_y = remap_ref(module, c->getPort(ID::Y).as_wire()->name); + IdString name_a = remap_ref(module, c->getPort(ID::A).as_wire()->name); conn.first = module->wire(name_y); conn.second = module->wire(name_a); module->connect(conn); continue; } if (c->type == ID(NOT)) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_NOT_)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), ID($_NOT_)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type.in(ID(AND), ID(OR), ID(XOR), ID(NAND), ID(NOR), ID(XNOR), ID(ANDNOT), ID(ORNOT))) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), stringf("$_%s_", c->type.unescape().c_str())); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type.in(ID(MUX), ID(NMUX))) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), stringf("$_%s_", c->type.unescape().c_str())); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::S, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type == ID(MUX4)) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX4_)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), ID($_MUX4_)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::S, ID::T, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type == ID(MUX8)) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX8_)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), ID($_MUX8_)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::S, ID::T, ID::U, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type == ID(MUX16)) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), ID($_MUX16_)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), ID($_MUX16_)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::E, ID::F, ID::G, ID::H, ID::I, ID::J, ID::K, ID::L, ID::M, ID::N, ID::O, ID::P, ID::S, ID::T, ID::U, ID::V, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type.in(ID(AOI3), ID(OAI3))) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), stringf("$_%s_", c->type.unescape().c_str())); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::C, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); continue; } if (c->type.in(ID(AOI4), ID(OAI4))) { - RTLIL::Cell *cell = module->addCell(remap_name(c->name), stringf("$_%s_", c->type.c_str()+1)); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), stringf("$_%s_", c->type.unescape().c_str())); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; for (auto name : {ID::A, ID::B, ID::C, ID::D, ID::Y}) { - RTLIL::IdString remapped_name = remap_name(c->getPort(name).as_wire()->name); + IdString remapped_name = remap_ref(module, c->getPort(name).as_wire()->name); cell->setPort(name, module->wire(remapped_name)); } design->select(module, cell); @@ -1664,7 +1670,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) } if (c->type == ID(DFF)) { log_assert(clk_sig.size() == 1); - FfData ff(module, &initvals, remap_name(c->name)); + FfData ff(module, &initvals, remap_ref(module, c->name)); ff.width = 1; ff.is_fine = true; ff.has_clk = true; @@ -1695,8 +1701,8 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) ff.sig_srst = srst_sig; ff.val_srst = init; } - ff.sig_d = module->wire(remap_name(c->getPort(ID::D).as_wire()->name)); - ff.sig_q = module->wire(remap_name(c->getPort(ID::Q).as_wire()->name)); + ff.sig_d = module->wire(remap_ref(module, c->getPort(ID::D).as_wire()->name)); + ff.sig_q = module->wire(remap_ref(module, c->getPort(ID::Q).as_wire()->name)); RTLIL::Cell *cell = ff.emit(); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; design->select(module, cell); @@ -1708,7 +1714,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) if (c->type.in(ID(_const0_), ID(_const1_))) { RTLIL::SigSig conn; - conn.first = module->wire(remap_name(c->connections().begin()->second.as_wire()->name)); + conn.first = module->wire(remap_ref(module, c->connections().begin()->second.as_wire()->name)); conn.second = RTLIL::SigSpec(c->type == ID(_const0_) ? 0 : 1, 1); module->connect(conn); continue; @@ -1716,7 +1722,7 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) if (c->type == ID(_dff_)) { log_assert(clk_sig.size() == 1); - FfData ff(module, &initvals, remap_name(c->name)); + FfData ff(module, &initvals, remap_ref(module, c->name)); ff.width = 1; ff.is_fine = true; ff.has_clk = true; @@ -1744,8 +1750,8 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) ff.sig_srst = srst_sig; ff.val_srst = init; } - ff.sig_d = module->wire(remap_name(c->getPort(ID::D).as_wire()->name)); - ff.sig_q = module->wire(remap_name(c->getPort(ID::Q).as_wire()->name)); + ff.sig_d = module->wire(remap_ref(module, c->getPort(ID::D).as_wire()->name)); + ff.sig_q = module->wire(remap_ref(module, c->getPort(ID::Q).as_wire()->name)); RTLIL::Cell *cell = ff.emit(); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; design->select(module, cell); @@ -1753,22 +1759,22 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) } if (c->type == ID($lut) && GetSize(c->getPort(ID::A)) == 1 && c->getParam(ID::LUT).as_int() == 2) { - SigSpec my_a = module->wire(remap_name(c->getPort(ID::A).as_wire()->name)); - SigSpec my_y = module->wire(remap_name(c->getPort(ID::Y).as_wire()->name)); + SigSpec my_a = module->wire(remap_ref(module, c->getPort(ID::A).as_wire()->name)); + SigSpec my_y = module->wire(remap_ref(module, c->getPort(ID::Y).as_wire()->name)); module->connect(RTLIL::SigSig(my_a, my_y)); continue; } - RTLIL::Cell *cell = module->addCell(remap_name(c->name), c->type); + RTLIL::Cell *cell = module->addCell(remap_ref(module, c->name), module->design->twines.copy_from(mapped_design->twines, c->type)); if (markgroups) cell->attributes[ID::abcgroup] = map_autoidx; - cell->parameters = c->parameters; + RTLIL::copy_attr_dict(cell->parameters, c->parameters, c->module->design, module->design); for (auto &conn : c->connections()) { RTLIL::SigSpec newsig; for (auto &c : conn.second.chunks()) { if (c.width == 0) continue; log_assert(c.width == 1); - newsig.append(module->wire(remap_name(c.wire->name))); + newsig.append(module->wire(remap_ref(module, c.wire->name))); } cell->setPort(conn.first, newsig); } @@ -1777,9 +1783,9 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) for (auto conn : mapped_mod->connections()) { if (!conn.first.is_fully_const()) - conn.first = module->wire(remap_name(conn.first.as_wire()->name)); + conn.first = module->wire(remap_ref(module, conn.first.as_wire()->name)); if (!conn.second.is_fully_const()) - conn.second = module->wire(remap_name(conn.second.as_wire()->name)); + conn.second = module->wire(remap_ref(module, conn.second.as_wire()->name)); module->connect(conn); } @@ -1794,10 +1800,10 @@ void AbcModuleState::extract(RTLIL::Design *design, RTLIL::Module *module) RTLIL::SigSig conn; if (si.type != G(NONE)) { conn.first = signal_bits[si.id]; - conn.second = module->wire(remap_name(buffer)); + conn.second = module->wire(remap_ref(module, buffer)); out_wires++; } else { - conn.first = module->wire(remap_name(buffer)); + conn.first = module->wire(remap_ref(module, buffer)); conn.second = signal_bits[si.id]; in_wires++; } diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 465a3f608..25b0d8376 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -325,11 +325,11 @@ struct Abc9Pass : public ScriptPass else { // Rename all submod-s to _TECHMAP_REPLACE_ to inherit name + attrs for (auto module : active_design->selected_modules()) { - active_design->selected_active_module = module->name.str(); - if (module->cell(stringf("%s_$abc9_flop", module->name))) + active_design->selected_active_module = module->name; + if (module->cell(active_design->twines.find(stringf("%s_$abc9_flop", module->name)))) run(stringf("rename %s_$abc9_flop _TECHMAP_REPLACE_", module->name)); } - active_design->selected_active_module.clear(); + active_design->selected_active_module = IdString::Null; } run("abc9_ops -prep_dff_unmap", " (only if -dff)"); run("design -copy-to $abc9 =*_$abc9_flop", " (only if -dff)"); // copy submod out @@ -400,6 +400,8 @@ struct Abc9Pass : public ScriptPass log_push(); active_design->select(mod); + GarbageCollectionGuard gc_guard(false); + // this check does nothing because the above line adds the whole module to the selection if (!active_design->selected_whole_module(mod)) log_error("Can't handle partially selected module %s!\n", mod); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 4faa981c3..22b11d618 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -28,6 +28,12 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +// Bring a name handle from `src`'s twine pool into `dst`'s. +IdString translate(RTLIL::Design *dst, RTLIL::Design *src, IdString name) +{ + return dst->twines.copy_from(src->twines, name); +} + void check(RTLIL::Design *design, bool dff_mode) { dict box_lookup; @@ -40,10 +46,10 @@ void check(RTLIL::Design *design, bool dff_mode) continue; if (it != m->attributes.end()) { auto id = it->second.as_int(); - auto r = box_lookup.insert(std::make_pair(stringf("$__boxid%d", id), m->name)); + auto r = box_lookup.insert(std::make_pair(design->twines.add(stringf("$__boxid%d", id)), IdString(m->name))); if (!r.second) log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", - m, id, r.first->second.unescape()); + m, id, design->twines.unescaped_str(r.first->second)); } } @@ -130,7 +136,7 @@ void check(RTLIL::Design *design, bool dff_mode) if (!derived_module->get_bool_attribute(ID::abc9_flop)) continue; if (derived_module->get_blackbox_attribute(true /* ignore_wb */)) - log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", derived_type.unescape()); + log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", design->twines.unescaped_str(derived_type)); if (derived_module->has_processes()) Pass::call_on_module(design, derived_module, "proc -noopt"); @@ -200,7 +206,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) } } if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass) && !has_timing) { - if (unmap_design->module(derived_type)) { + if (unmap_design->module(translate(unmap_design, design, derived_type))) { // If derived_type is present in unmap_design, it means that it was processed previously, but found to be incompatible -- e.g. if // it contained a non-zero initial state. In this case, continue to replace the cell type/parameters so that it has the same properties // as a compatible type, yet will be safely unmapped later @@ -212,7 +218,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) } } - if (!unmap_design->module(derived_type)) { + if (!unmap_design->module(translate(unmap_design, design, derived_type))) { if (derived_module->has_processes()) Pass::call_on_module(design, derived_module, "proc -noopt"); @@ -242,10 +248,10 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) } if (derived_type != cell->type) { - auto unmap_module = unmap_design->addModule(derived_type); - auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); + auto unmap_module = unmap_design->addModule(translate(unmap_design, design, derived_type)); + auto replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, translate(unmap_design, cell->module->design, cell->type)); for (auto port : derived_module->ports) { - auto w = unmap_module->addWire(port, derived_module->wire(port)); + auto w = unmap_module->addWire(translate(unmap_design, design, port), derived_module->wire(port)); // Do not propagate (* init *) values into the box, // in fact, remove it from outside too if (w->port_output) @@ -255,12 +261,15 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) // the techmapped cell w->attributes[ID::techmap_autopurge] = 1; - replace_cell->setPort(port, w); + replace_cell->setPort(translate(unmap_design, design, port), w); } - unmap_module->ports = derived_module->ports; + unmap_module->ports.clear(); + for (auto port : derived_module->ports) + unmap_module->ports.push_back(translate(unmap_design, design, port)); unmap_module->check(); - replace_cell->parameters = cell->parameters; + RTLIL::copy_attr_dict(replace_cell->parameters, cell->parameters, + cell->module->design, unmap_design); } } @@ -330,13 +339,15 @@ void prep_bypass(RTLIL::Design *design) // Copy inst_module into map_design, with the same interface // and duplicate $abc9$* wires for its output ports - auto map_module = map_design->addModule(cell->type); + auto map_module = map_design->addModule(translate(map_design, design, cell->type)); for (auto port_name : inst_module->ports) { - auto w = map_module->addWire(port_name, inst_module->wire(port_name)); + auto w = map_module->addWire(translate(map_design, design, port_name), inst_module->wire(port_name)); if (w->port_output) w->attributes.erase(ID::init); } - map_module->ports = inst_module->ports; + map_module->ports.clear(); + for (auto port_name : inst_module->ports) + map_module->ports.push_back(translate(map_design, design, port_name)); map_module->check(); map_module->set_bool_attribute(ID::whitebox); @@ -349,7 +360,7 @@ void prep_bypass(RTLIL::Design *design) if (!port->port_output) continue; auto dst = bypass_module->addWire(port_name, port); - auto src = bypass_module->addWire("$abc9byp$" + port_name.str(), GetSize(port)); + auto src = bypass_module->addWire("$abc9byp$" + design->twines.str(port_name), GetSize(port)); src->port_input = true; // For these new input ports driven by the replaced // cell, then create a new simple-path specify entry: @@ -424,20 +435,20 @@ void prep_bypass(RTLIL::Design *design) // and a bypass cell that has the same inputs/outputs as the // original cell, but with additional inputs taken from the // replaced cell - auto replace_cell = map_module->addCell(ID::_TECHMAP_REPLACE_, cell->type); - auto bypass_cell = map_module->addCell(NEW_ID, cell->type.str() + "_$abc9_byp"); + auto replace_cell = map_module->addCell(ID::_TECHMAP_REPLACE_, translate(map_design, cell->module->design, cell->type)); + auto bypass_cell = map_module->addCell(NEW_ID, map_module->design->twines.add(std::string{cell->type.str() + "_$abc9_byp"})); for (const auto &conn : cell->connections()) { - auto port = map_module->wire(conn.first); + auto port = map_module->wire(translate(map_design, design, conn.first)); if (cell->input(conn.first)) { - replace_cell->setPort(conn.first, port); + replace_cell->setPort(translate(map_design, design, conn.first), port); if (bypass_module->wire(conn.first)) - bypass_cell->setPort(conn.first, port); + bypass_cell->setPort(translate(map_design, design, conn.first), port); } if (cell->output(conn.first)) { - bypass_cell->setPort(conn.first, port); - auto n = "$abc9byp$" + conn.first.str(); + bypass_cell->setPort(translate(map_design, design, conn.first), port); + auto n = "$abc9byp$" + design->twines.str(conn.first); auto w = map_module->addWire(n, GetSize(conn.second)); - replace_cell->setPort(conn.first, w); + replace_cell->setPort(translate(map_design, design, conn.first), w); bypass_cell->setPort(n, w); } } @@ -448,10 +459,10 @@ void prep_bypass(RTLIL::Design *design) // driving the outputs auto unmap_module = unmap_design->addModule(cell->type.str() + "_$abc9_byp"); for (auto port_name : inst_module->ports) { - auto w = unmap_module->addWire(port_name, inst_module->wire(port_name)); + auto w = unmap_module->addWire(translate(unmap_design, design, port_name), inst_module->wire(port_name)); if (w->port_output) { w->attributes.erase(ID::init); - auto w2 = unmap_module->addWire("$abc9byp$" + port_name.str(), GetSize(w)); + auto w2 = unmap_module->addWire("$abc9byp$" + design->twines.str(port_name), GetSize(w)); w2->port_input = true; unmap_module->connect(w, w2); } @@ -541,7 +552,7 @@ void prep_dff_unmap(RTLIL::Design *design) // Make sure the box module has all the same ports present on flop cell auto replace_cell = module->cell(ID::_TECHMAP_REPLACE_); log_assert(replace_cell); - auto box_module = design->module(module->name.str() + "_$abc9_flop"); + auto box_module = design->module(design->twines.find(module->name.str() + "_$abc9_flop")); log_assert(box_module); for (auto port_name : module->ports) { auto port = module->wire(port_name); @@ -557,14 +568,16 @@ void prep_dff_unmap(RTLIL::Design *design) } box_module->fixup_ports(); - auto unmap_module = unmap_design->addModule(box_module->name); - replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name); + auto unmap_module = unmap_design->addModule(translate(unmap_design, design, box_module->name)); + replace_cell = unmap_module->addCell(ID::_TECHMAP_REPLACE_, module->name.str()); for (auto port_name : box_module->ports) { - auto w = unmap_module->addWire(port_name, box_module->wire(port_name)); + auto w = unmap_module->addWire(translate(unmap_design, design, port_name), box_module->wire(port_name)); if (module->wire(port_name)) - replace_cell->setPort(port_name, w); + replace_cell->setPort(translate(unmap_design, design, port_name), w); } - unmap_module->ports = box_module->ports; + unmap_module->ports.clear(); + for (auto port_name : box_module->ports) + unmap_module->ports.push_back(translate(unmap_design, design, port_name)); unmap_module->check(); } } @@ -678,7 +691,7 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) auto port_wire = inst_module->wire(i.first.name); if (!port_wire) log_error("Port %s in cell %s (type %s) from module %s does not actually exist", - i.first.name.unescape(), cell, cell->type.unescape(), module); + design->twines.unescaped_str(i.first.name), cell, cell->type.unescape(), module); log_assert(port_wire->port_input); auto d = i.second.first; @@ -697,13 +710,13 @@ void prep_delays(RTLIL::Design *design, bool dff_mode) if (ys_debug(1)) { static pool> seen; if (seen.emplace(cell->type, i.first).second) log("%s.%s[%d] abc9_required = %d\n", - cell->type.unescape(), i.first.name.unescape(), offset, d); + cell->type.unescape(), design->twines.unescaped_str(i.first.name), offset, d); } #endif auto r = box_cache.insert(d); if (r.second) { r.first->second = delay_module->derive(design, {{ID::DELAY, d}}); - log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY=")); + log_assert(design->twines.str(r.first->second).starts_with("$paramod$__ABC9_DELAY\\DELAY=")); } auto box = module->addCell(NEW_ID, r.first->second); box->setPort(ID::I, rhs[offset]); @@ -765,7 +778,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) return; // Build the same topo graph for the initial pass and the optional retry. - auto build_toposort = [&](TopoSort &toposort) { + auto build_toposort = [&](TopoSort &toposort) { dict> bit_drivers, bit_users; for (auto cell : module->cells()) { @@ -806,7 +819,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) }; // Build TopoSort in a container, as we may need to conditionally rebuild it on retry. - std::optional> toposort; + std::optional> toposort; toposort.emplace(); bool no_loops = build_toposort(toposort.value()); @@ -869,7 +882,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) r.first->second = new Design; RTLIL::Design *holes_design = r.first->second; log_assert(holes_design); - RTLIL::Module *holes_module = holes_design->addModule(module->name); + RTLIL::Module *holes_module = holes_design->addModule(translate(holes_design, design, module->name)); log_assert(holes_module); dict cell_cache; @@ -891,7 +904,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) // be instantiating the derived module which will have had any parameters constant-propagated. // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design. // Please file a bug report! - log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", cell_name.unescape(), cell->type.unescape()); + log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", design->twines.unescaped_str(cell_name), cell->type.unescape()); } log_assert(box_module->get_blackbox_attribute()); @@ -901,7 +914,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) auto &holes_cell = r.first->second; if (r.second) { if (box_module->get_bool_attribute(ID::whitebox)) { - holes_cell = holes_module->addCell(NEW_ID, cell->type); + holes_cell = holes_module->addCell(NEW_ID, translate(holes_design, cell->module->design, cell->type)); if (box_module->has_processes()) Pass::call_on_module(design, box_module, "proc -noopt"); @@ -911,11 +924,11 @@ void prep_xaiger(RTLIL::Module *module, bool dff) RTLIL::Wire *w = box_module->wire(port_name); log_assert(w); log_assert(!w->port_input || !w->port_output); - auto &conn = holes_cell->connections_[port_name]; + auto &conn = holes_cell->connections_[translate(holes_design, design, port_name)]; if (w->port_input) { for (int i = 0; i < GetSize(w); i++) { box_inputs++; - RTLIL::Wire *holes_wire = holes_module->wire(stringf("\\i%d", box_inputs)); + RTLIL::Wire *holes_wire = holes_module->wire(holes_design->twines.find(stringf("\\i%d", box_inputs))); if (!holes_wire) { holes_wire = holes_module->addWire(stringf("\\i%d", box_inputs)); holes_wire->port_input = true; @@ -926,7 +939,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) } } else if (w->port_output) - conn = holes_module->addWire(stringf("%s.%s", cell->type, port_name.unescape()), GetSize(w)); + conn = holes_module->addWire(stringf("%s.%s", cell->type, design->twines.unescaped_str(port_name)), GetSize(w)); } } else // box_module is a blackbox @@ -938,12 +951,12 @@ void prep_xaiger(RTLIL::Module *module, bool dff) log_assert(w); if (!w->port_output) continue; - Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, port_name.unescape()), GetSize(w)); + Wire *holes_wire = holes_module->addWire(stringf("$abc%s.%s", cell->name, design->twines.unescaped_str(port_name)), GetSize(w)); holes_wire->port_output = true; holes_wire->port_id = port_id++; holes_module->ports.push_back(holes_wire->name); if (holes_cell) // whitebox - holes_module->connect(holes_wire, holes_cell->getPort(port_name)); + holes_module->connect(holes_wire, holes_cell->getPort(translate(holes_design, design, port_name))); else // blackbox holes_module->connect(holes_wire, Const(State::S0, GetSize(w))); } @@ -990,9 +1003,9 @@ void prep_lut(RTLIL::Design *design, int maxlut) auto r = table.emplace(K, entry); if (!r.second) { if (r.first->second.area != entry.area) - log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", module, r.first->second.name.unescape()); + log_error("Modules '%s' and '%s' have conflicting (* abc9_lut *) values.\n", module, design->twines.unescaped_str(r.first->second.name)); if (r.first->second.delays != entry.delays) - log_error("Modules '%s' and '%s' have conflicting specify entries.\n", module, r.first->second.name.unescape()); + log_error("Modules '%s' and '%s' have conflicting specify entries.\n", module, design->twines.unescaped_str(r.first->second.name)); } } @@ -1011,7 +1024,7 @@ void prep_lut(RTLIL::Design *design, int maxlut) ss << std::endl; } for (const auto &i : table) { - ss << "# " << i.second.name.unescape() << std::endl; + ss << "# " << design->twines.unescaped_str(i.second.name) << std::endl; ss << i.first << " " << i.second.area; for (const auto &j : i.second.delays) ss << " " << j; @@ -1099,7 +1112,7 @@ void prep_box(RTLIL::Design *design) if (ys_debug(1)) { static std::set> seen; if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", module, - port_name.unescape(), it->second.first); + design->twines.unescaped_str(port_name), it->second.first); } #endif } diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 96ef1bb4e..4965d1ee0 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -170,6 +170,7 @@ struct AbcNewPass : public ScriptPass { } for (auto mod : selected_modules) { + GarbageCollectionGuard gc_guard(false); std::string tmpdir = ""; std::string modname = ""; std::string exe_options = "[options]"; @@ -192,7 +193,7 @@ struct AbcNewPass : public ScriptPass { } run(stringf(" abc9_ops -write_box %s/input.box", tmpdir)); - run(stringf(" write_xaiger2 -mapping_prep -map-refs -map2 %s/input.map2 %s/input.xaig", tmpdir, tmpdir)); + run(stringf(" write_xaiger2 -mapping_prep -map2 %s/input.map2 %s/input.xaig", tmpdir, tmpdir)); run(stringf(" abc9_exe %s -cwd %s -box %s/input.box", exe_options, tmpdir, tmpdir)); run(stringf(" read_aiger -xaiger -module_name %s$abc9 %s/output.aig", modname, tmpdir)); diff --git a/passes/techmap/abc_ops_reintegrate.cc b/passes/techmap/abc_ops_reintegrate.cc index 7b5980bcc..b6223e83d 100644 --- a/passes/techmap/abc_ops_reintegrate.cc +++ b/passes/techmap/abc_ops_reintegrate.cc @@ -29,9 +29,28 @@ PRIVATE_NAMESPACE_BEGIN int map_autoidx; -inline std::string remap_name(RTLIL::IdString abc9_name) +inline std::string remap_name(const std::string &abc9_name) { - return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); + return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str() + 1); +} + +inline IdString remap_ref(RTLIL::Design *design, IdString n) +{ + return design->twines.add(remap_name(design->twines.str(n))); +} + +inline IdString ref_from_token(RTLIL::Design *design, const std::string &tok) +{ + IdString ref = design->twines.ref_from_token(tok); + if (ref == IdString::Null) + log_error("Bad map file: '%s' is not a live name reference of this yosys run.\n", tok.c_str()); + return ref; +} + +inline IdString indexed_name(RTLIL::Design *design, IdString base, int index) +{ + return design->twines.add(Twine::Suffix{base.untag(), stringf("[%d]", index)}) + .tag(base.isPublic()); } struct PseudoPo { @@ -57,7 +76,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s map_autoidx = autoidx++; - RTLIL::Module *mapped_mod = design->module(stringf("%s$abc9", module->name)); + RTLIL::Module *mapped_mod = design->module(design->twines.find(stringf("%s$abc9", module->name))); if (mapped_mod == NULL) log_error("ABC output file does not contain a module `%s$abc'.\n", module); @@ -73,43 +92,46 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s std::ifstream mf(map_filename); std::string type, symbol; int variable, index; + while (mf >> type >> variable >> index >> symbol) { - RTLIL::IdString escaped_s = RTLIL::escape_id(symbol); + IdString escaped_ref = ref_from_token(design, symbol); if (type == "input") { log_assert(variable < input_count); - RTLIL::Wire* wire = mapped_mod->wire(stringf("$aiger$i%d", variable + 1)); + RTLIL::Wire* wire = mapped_mod->wire(design->twines.find(stringf("$aiger$i%d", variable + 1))); log_assert(wire); log_assert(wire->port_input); log_debug("Renaming input %s", wire); RTLIL::Wire *existing = nullptr; + IdString name_ref; if (index == 0) { + name_ref = escaped_ref; // Cope with the fact that a CI might be identical // to a PI (necessary due to ABC); in those cases // simply connect the latter to the former - existing = mapped_mod->wire(escaped_s); + existing = mapped_mod->wire(name_ref); if (!existing) - mapped_mod->rename(wire, escaped_s); + mapped_mod->rename(wire, name_ref); else { wire->port_input = false; mapped_mod->connect(wire, existing); } - log_debug(" -> %s\n", escaped_s); + log_debug(" -> %s\n", design->twines.unescaped_str(escaped_ref)); } else { - RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index); - existing = mapped_mod->wire(indexed_name); + name_ref = indexed_name(design, escaped_ref, index); + existing = mapped_mod->wire(name_ref); if (!existing) - mapped_mod->rename(wire, indexed_name); + mapped_mod->rename(wire, name_ref); else { mapped_mod->connect(wire, existing); wire->port_input = false; } - log_debug(" -> %s\n", indexed_name); + log_debug(" -> %s\n", design->twines.unescaped_str(name_ref)); } if (!existing) { - auto r = wideports_cache.insert(escaped_s); + auto r = wideports_cache.insert(escaped_ref); if (r.second) { r.first->second.first = index; r.first->second.second = index; @@ -122,42 +144,44 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s } else if (type == "output") { log_assert(variable + co_count < output_count); - RTLIL::Wire* wire = mapped_mod->wire(stringf("$aiger$o%d", variable + co_count)); + RTLIL::Wire* wire = mapped_mod->wire(design->twines.find(stringf("$aiger$o%d", variable + co_count))); log_assert(wire); log_assert(wire->port_output); log_debug("Renaming output %s", wire); RTLIL::Wire *existing; + IdString name_ref; if (index == 0) { + name_ref = escaped_ref; // Cope with the fact that a CO might be identical // to a PO (necessary due to ABC); in those cases // simply connect the latter to the former - existing = mapped_mod->wire(escaped_s); + existing = mapped_mod->wire(name_ref); if (!existing) - mapped_mod->rename(wire, escaped_s); + mapped_mod->rename(wire, name_ref); else { wire->port_output = false; existing->port_output = true; mapped_mod->connect(wire, existing); wire = existing; } - log_debug(" -> %s\n", escaped_s); + log_debug(" -> %s\n", design->twines.unescaped_str(escaped_ref)); } else { - RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index); - existing = mapped_mod->wire(indexed_name); + name_ref = indexed_name(design, escaped_ref, index); + existing = mapped_mod->wire(name_ref); if (!existing) - mapped_mod->rename(wire, indexed_name); + mapped_mod->rename(wire, name_ref); else { wire->port_output = false; existing->port_output = true; mapped_mod->connect(wire, existing); } - log_debug(" -> %s\n", indexed_name); + log_debug(" -> %s\n", design->twines.unescaped_str(name_ref)); } if (!existing) { - auto r = wideports_cache.insert(escaped_s); + auto r = wideports_cache.insert(escaped_ref); if (r.second) { r.first->second.first = index; r.first->second.second = index; @@ -171,35 +195,35 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s else if (type == "pseudopo") { std::string port; mf >> port; - RTLIL::IdString escaped_p = RTLIL::escape_id(port); + IdString escaped_p = ref_from_token(design, port); log_assert(variable + co_count < output_count); - RTLIL::IdString wire_name = stringf("$aiger$o%d", variable + co_count); + IdString wire_name = design->twines.find(stringf("$aiger$o%d", variable + co_count)); RTLIL::Wire* wire = mapped_mod->wire(wire_name); log_assert(wire); log_assert(wire->port_output); log_debug("Mapping pseudo output %s", wire); - pseudopos.insert({wire_name, PseudoPo{escaped_s, escaped_p, index}}); - log_debug(" -> %s.%s[%d]\n", escaped_s, escaped_p, index); + pseudopos.insert({wire_name, PseudoPo{escaped_ref, escaped_p, index}}); + log_debug(" -> %s.%s[%d]\n", design->twines.unescaped_str(escaped_ref), design->twines.unescaped_str(escaped_p), index); } else if (type == "keepwire") { log_assert(variable + co_count < output_count); - RTLIL::IdString wire_name = stringf("$aiger$o%d", variable + co_count); + RTLIL::IdString wire_name = design->twines.add(stringf("$aiger$o%d", variable + co_count)); RTLIL::Wire* wire = mapped_mod->wire(wire_name); log_assert(wire); log_assert(wire->port_output); log_debug("Mapping kept wire %s", wire); - keptwires.insert({wire_name, KeptWire{escaped_s, index}}); - log_debug(" -> %s[%d]\n", escaped_s, index); + keptwires.insert({wire_name, KeptWire{escaped_ref, index}}); + log_debug(" -> %s[%d]\n", PooledName(design, escaped_ref), index); } else if (type == "box") { - RTLIL::Cell* cell = mapped_mod->cell(stringf("$box%d", variable)); + RTLIL::Cell* cell = mapped_mod->cell(design->twines.find(stringf("$box%d", variable))); if (!cell) - log_debug("Box %d (%s) no longer exists.\n", variable, escaped_s.unescape()); + log_debug("Box %d (%s) no longer exists.\n", variable, design->twines.unescaped_str(escaped_ref)); else - mapped_mod->rename(cell, escaped_s); + mapped_mod->rename(cell, escaped_ref); } else log_error("Symbol type '%s' not recognised.\n", type); @@ -207,7 +231,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s } for (auto &wp : wideports_cache) { - auto name = wp.first; + IdString name = wp.first; int min = wp.second.first; int max = wp.second.second; if (min == 0 && max == 0) @@ -215,13 +239,13 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s RTLIL::Wire *wire = mapped_mod->wire(name); if (wire) - mapped_mod->rename(wire, RTLIL::escape_id(stringf("%s[%d]", name, 0))); + mapped_mod->rename(wire, indexed_name(design, name, 0)); // Do not make ports with a mix of input/output into // wide ports bool port_input = false, port_output = false; for (int i = min; i <= max; i++) { - RTLIL::IdString other_name = name.str() + stringf("[%d]", i); + IdString other_name = indexed_name(design, name, i); RTLIL::Wire *other_wire = mapped_mod->wire(other_name); if (other_wire) { port_input = port_input || other_wire->port_input; @@ -235,7 +259,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s wire->port_output = port_output; for (int i = min; i <= max; i++) { - RTLIL::IdString other_name = stringf("%s[%d]", name, i); + IdString other_name = indexed_name(design, name, i); RTLIL::Wire *other_wire = mapped_mod->wire(other_name); if (other_wire) { other_wire->port_input = false; @@ -251,7 +275,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s mapped_mod->fixup_ports(); for (auto w : mapped_mod->wires()) { - auto nw = module->addWire(remap_name(w->name), GetSize(w)); + auto nw = module->addWire(remap_ref(design, w->name), GetSize(w)); nw->start_offset = w->start_offset; // Remove all (* init *) since they only exist on $_DFF_[NP]_ w->attributes.erase(ID::init); @@ -328,7 +352,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s } dict> bit_drivers, bit_users; - TopoSort toposort; + TopoSort toposort; dict not2drivers; dict> bit2sinks; @@ -341,8 +365,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s SigBit D = mapped_cell->getPort(ID::D); SigBit Q = mapped_cell->getPort(ID::Q); if (D.wire) - D.wire = module->wires_.at(remap_name(D.wire->name)); - Q.wire = module->wires_.at(remap_name(Q.wire->name)); + D.wire = module->wire(remap_ref(design, D.wire->name)); + Q.wire = module->wire(remap_ref(design, Q.wire->name)); module->connect(Q, D); continue; } @@ -362,7 +386,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s if (!a_bit.wire) { mapped_cell->setPort(ID::Y, module->addWire(NEW_ID)); - RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); + RTLIL::Wire *wire = module->wire(remap_ref(design, y_bit.wire->name)); log_assert(wire); module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); } @@ -374,20 +398,21 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s // find the driver LUT and clone that to guarantee that we won't // increase the max logic depth // (TODO: Optimise by not cloning unless will increase depth) - RTLIL::IdString driver_name; + std::string driver_name; if (GetSize(a_bit.wire) == 1) driver_name = stringf("$lut%s", a_bit.wire->name); else driver_name = stringf("$lut%s[%d]", a_bit.wire->name, a_bit.offset); - driver_lut = mapped_mod->cell(driver_name); + IdString driver_ref = design->twines.find(driver_name); + driver_lut = driver_ref.empty() ? nullptr : mapped_mod->cell(driver_ref); } if (!driver_lut) { // If a driver couldn't be found (could be from PI or box CI) // then implement using a LUT RTLIL::Cell *cell = module->addLut(remap_name(stringf("$lut%s", mapped_cell->name)), - RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), - RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), + RTLIL::SigBit(module->wire(remap_ref(design, a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wire(remap_ref(design, y_bit.wire->name)), y_bit.offset), RTLIL::Const::from_string("01")); bit2sinks[cell->getPort(ID::A)].push_back(cell); cell_stats[ID($lut)]++; @@ -402,9 +427,9 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s unmapped_error(mapped_cell); if (mapped_cell->type == ID($lut) || mapped_cell->get_bool_attribute(ID::abc9_cell)) { - RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); - cell->parameters = mapped_cell->parameters; - cell->attributes = mapped_cell->attributes; + RTLIL::Cell *cell = module->addCell(remap_ref(design, mapped_cell->name), mapped_cell->type); + RTLIL::copy_attr_dict(cell->parameters, mapped_cell->parameters, mapped_mod->design, design); + RTLIL::copy_attr_dict(cell->attributes, mapped_cell->attributes, mapped_mod->design, design); for (auto &mapped_conn : mapped_cell->connections()) { RTLIL::SigSpec newsig; @@ -413,7 +438,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s continue; //log_assert(c.width == 1); if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); + c.wire = module->wire(remap_ref(design, c.wire->name)); newsig.append(c); } cell->setPort(mapped_conn.first, newsig); @@ -440,9 +465,9 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s SigBit I = mapped_cell->getPort(ID(i)); SigBit O = mapped_cell->getPort(ID(o)); if (I.wire) - I.wire = module->wires_.at(remap_name(I.wire->name)); + I.wire = module->wire(remap_ref(design, I.wire->name)); log_assert(O.wire); - O.wire = module->wires_.at(remap_name(O.wire->name)); + O.wire = module->wire(remap_ref(design, O.wire->name)); module->connect(O, I); continue; } @@ -452,9 +477,9 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s log_assert(mapped_cell->type == stringf("$__boxid%d", box_module->attributes.at(ID::abc9_box_id).as_int())); mapped_cell->type = existing_cell->type; - RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type); - cell->parameters = existing_cell->parameters; - cell->attributes = existing_cell->attributes; + RTLIL::Cell *cell = module->addCell(remap_ref(design, mapped_cell->name), mapped_cell->type); + RTLIL::copy_attr_dict(cell->parameters, existing_cell->parameters, existing_cell->module->design, design); + RTLIL::copy_attr_dict(cell->attributes, existing_cell->attributes, existing_cell->module->design, design); module->swap_names(cell, existing_cell); boxes.insert(existing_cell); @@ -483,7 +508,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s old_q = existing_cell->getPort(port_name); } auto new_q = outputs[0]; - new_q.wire = module->wires_.at(remap_name(new_q.wire->name)); + new_q.wire = module->wire(remap_ref(design, new_q.wire->name)); module->connect(old_q, new_q); } else { @@ -516,7 +541,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s continue; //log_assert(c.width == 1); if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); + c.wire = module->wire(remap_ref(design, c.wire->name)); newsig.append(c); } @@ -539,21 +564,21 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s if (!conn.first.is_fully_const()) { std::vector chunks = conn.first.chunks(); for (auto &c : chunks) - c.wire = module->wires_.at(remap_name(c.wire->name)); + c.wire = module->wire(remap_ref(design, c.wire->name)); conn.first = std::move(chunks); } if (!conn.second.is_fully_const()) { std::vector chunks = conn.second.chunks(); for (auto &c : chunks) if (c.wire) - c.wire = module->wires_.at(remap_name(c.wire->name)); + c.wire = module->wire(remap_ref(design, c.wire->name)); conn.second = std::move(chunks); } module->connect(conn); } for (auto &it : cell_stats) - log("ABC RESULTS: %15s cells: %8d\n", it.first, it.second); + log("ABC RESULTS: %15s cells: %8d\n", design->twines.str(it.first), it.second); int in_wires = 0, out_wires = 0; for (auto pseudopo : pseudopos) { @@ -566,7 +591,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s log_assert(box); // replace only the driven bit - RTLIL::Wire *remap_wire = module->wire(remap_name(wire_name)); + RTLIL::Wire *remap_wire = module->wire(remap_ref(design, wire_name)); RTLIL::SigSpec port = box->getPort(target.port); log_assert(target.offset < GetSize(port)); port[target.offset] = remap_wire; @@ -579,7 +604,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s for (auto &[wire_name, kept] : keptwires) { RTLIL::Wire *mapped_wire = mapped_mod->wire(wire_name); log_assert(mapped_wire); - RTLIL::Wire *remap_wire = module->wire(remap_name(wire_name)); + RTLIL::Wire *remap_wire = module->wire(remap_ref(design, wire_name)); log_assert(remap_wire); RTLIL::Wire *wire = module->wire(kept.wire); @@ -597,7 +622,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s RTLIL::Wire *wire = module->wire(port); log_assert(wire); - RTLIL::Wire *remap_wire = module->wire(remap_name(port)); + RTLIL::Wire *remap_wire = module->wire(remap_ref(design, mapped_wire->name)); RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire)); log_assert(GetSize(signal) >= GetSize(remap_wire)); @@ -648,8 +673,8 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, bool stdcell_mode, std::s RTLIL::SigBit y_bit = not_cell->getPort(ID::Y); RTLIL::Const driver_mask; - a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name)); - y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name)); + a_bit.wire = module->wire(remap_ref(design, a_bit.wire->name)); + y_bit.wire = module->wire(remap_ref(design, y_bit.wire->name)); auto jt = bit2sinks.find(a_bit); if (jt == bit2sinks.end()) @@ -698,7 +723,7 @@ clone_lut: y_bit, driver_mask); for (auto &bit : cell->connections_.at(ID::A)) { - bit.wire = module->wires_.at(remap_name(bit.wire->name)); + bit.wire = module->wire(remap_ref(design, bit.wire->name)); bit2sinks[bit].push_back(cell); } } diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc index 4c97f6ab1..fccf25560 100644 --- a/passes/techmap/attrmap.cc +++ b/passes/techmap/attrmap.cc @@ -52,10 +52,10 @@ bool string_compare_nocase(const string &str1, const string &str2) return true; } -bool match_name(string &name, IdString &id, bool ignore_case=false) +bool match_name(string &name, const string &id, bool ignore_case=false) { string str1 = RTLIL::escape_id(name); - string str2 = id.str(); + string str2 = id; if (ignore_case) return string_compare_nocase(str1, str2); @@ -76,12 +76,12 @@ bool match_value(string &value, Const &val, bool ignore_case=false) struct AttrmapAction { virtual ~AttrmapAction() { } - virtual bool apply(IdString &id, Const &val) = 0; + virtual bool apply(string &id, Const &val) = 0; }; struct AttrmapTocase : AttrmapAction { string name; - bool apply(IdString &id, Const&) override { + bool apply(string &id, Const&) override { if (match_name(name, id, true)) id = RTLIL::escape_id(name); return true; @@ -90,7 +90,7 @@ struct AttrmapTocase : AttrmapAction { struct AttrmapRename : AttrmapAction { string old_name, new_name; - bool apply(IdString &id, Const&) override { + bool apply(string &id, Const&) override { if (match_name(old_name, id)) id = RTLIL::escape_id(new_name); return true; @@ -101,7 +101,7 @@ struct AttrmapMap : AttrmapAction { bool imap; string old_name, new_name; string old_value, new_value; - bool apply(IdString &id, Const &val) override { + bool apply(string &id, Const &val) override { if (match_name(old_name, id) && match_value(old_value, val, true)) { id = RTLIL::escape_id(new_name); val = make_value(new_value); @@ -113,31 +113,34 @@ struct AttrmapMap : AttrmapAction { struct AttrmapRemove : AttrmapAction { bool has_value; string name, value; - bool apply(IdString &id, Const &val) override { + bool apply(string &id, Const &val) override { return !(match_name(name, id) && (!has_value || match_value(value, val))); } }; -void attrmap_apply(string objname, vector> &actions, dict &attributes) +void attrmap_apply(RTLIL::Design *design, string objname, vector> &actions, dict &attributes) { dict new_attributes; for (auto attr : attributes) { - auto new_attr = attr; + string old_name = design->twines.str(attr.first); + string new_name = old_name; + Const new_value = attr.second; for (auto &action : actions) - if (!action->apply(new_attr.first, new_attr.second)) + if (!action->apply(new_name, new_value)) goto delete_this_attr; - if (new_attr != attr) + if (new_name != old_name || new_value != attr.second) log("Changed attribute on %s: %s=%s -> %s=%s\n", objname, - attr.first.unescape(), log_const(attr.second), new_attr.first.unescape(), log_const(new_attr.second)); + RTLIL::unescape_id(old_name), log_const(attr.second), + RTLIL::unescape_id(new_name), log_const(new_value)); - new_attributes[new_attr.first] = new_attr.second; + new_attributes[design->twines.add(std::move(new_name))] = new_value; if (0) delete_this_attr: - log("Removed attribute on %s: %s=%s\n", objname, attr.first.unescape(), log_const(attr.second)); + log("Removed attribute on %s: %s=%s\n", objname, RTLIL::unescape_id(old_name), log_const(attr.second)); } attributes.swap(new_attributes); @@ -264,14 +267,14 @@ struct AttrmapPass : public Pass { if (modattr_mode) { for (auto module : design->all_selected_whole_modules()) - attrmap_apply(stringf("%s", module), actions, module->attributes); + attrmap_apply(design, stringf("%s", module), actions, module->attributes); } else { for (auto module : design->all_selected_modules()) { for (auto memb : module->selected_members()) - attrmap_apply(stringf("%s.%s", module, memb), actions, memb->attributes); + attrmap_apply(design, stringf("%s.%s", module, design->obj_name(memb).c_str()), actions, memb->attributes); // attrmap already applied to process itself during above loop, but not its children for (auto proc : module->selected_processes()) @@ -280,10 +283,10 @@ struct AttrmapPass : public Pass { while (!all_cases.empty()) { RTLIL::CaseRule *cs = all_cases.back(); all_cases.pop_back(); - attrmap_apply(stringf("%s.%s (case)", module, proc), actions, cs->attributes); + attrmap_apply(design, stringf("%s.%s (case)", module, proc), actions, cs->attributes); for (auto &sw : cs->switches) { - attrmap_apply(stringf("%s.%s (switch)", module, proc), actions, sw->attributes); + attrmap_apply(design, stringf("%s.%s (switch)", module, proc), actions, sw->attributes); all_cases.insert(all_cases.end(), sw->cases.begin(), sw->cases.end()); } } @@ -328,7 +331,7 @@ struct ParamapPass : public Pass { for (auto module : design->selected_modules()) for (auto cell : module->selected_cells()) - attrmap_apply(stringf("%s.%s", module, cell), actions, cell->parameters); + attrmap_apply(design, stringf("%s.%s", module, cell), actions, cell->parameters); } } ParamapPass; diff --git a/passes/techmap/cellmatch.cc b/passes/techmap/cellmatch.cc index a2e2393d0..f7bc15701 100644 --- a/passes/techmap/cellmatch.cc +++ b/passes/techmap/cellmatch.cc @@ -275,26 +275,26 @@ struct CellmatchPass : Pass { // Add target.module to map_design ("$cellmatch") // as a techmap rule to match m and replace it with target.module Module *map = map_design->addModule(stringf("\\_60_%s_%s", m, target.module)); - Cell *cell = map->addCell(ID::_TECHMAP_REPLACE_, target.module->name); + Cell *cell = map->addCell(ID::_TECHMAP_REPLACE_, map_design->twines.copy_from(target.module->design->twines, target.module->name)); map->attributes[ID(techmap_celltype)] = m->name.str(); for (int i = 0; i < outputs.size(); i++) { log_assert(outputs[i].is_wire()); - Wire *w = map->addWire(outputs[i].wire->name, 1); + Wire *w = map->addWire(map_design->twines.copy_from(m->design->twines, outputs[i].wire->name), 1); w->port_id = outputs[i].wire->port_id; w->port_output = true; log_assert(target_outputs[output_map[i]].is_wire()); - cell->setPort(target_outputs[output_map[i]].wire->name, w); + cell->setPort(map_design->twines.copy_from(target.module->design->twines, target_outputs[output_map[i]].wire->name), w); } for (int i = 0; i < inputs.size(); i++) { log_assert(inputs[i].is_wire()); - Wire *w = map->addWire(inputs[i].wire->name, 1); + Wire *w = map->addWire(map_design->twines.copy_from(m->design->twines, inputs[i].wire->name), 1); w->port_id = inputs[i].wire->port_id; w->port_input = true; log_assert(target_inputs[input_map[i]].is_wire()); - cell->setPort(target_inputs[input_map[i]].wire->name, w); + cell->setPort(map_design->twines.copy_from(target.module->design->twines, target_inputs[input_map[i]].wire->name), w); } map->fixup_ports(); diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 6a160b4d9..55edc2ee4 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -29,7 +29,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct cell_mapping { - IdString cell_name; + std::string cell_name; std::map ports; }; static std::map cell_mappings; @@ -37,9 +37,9 @@ static std::map cell_mappings; static void logmap(IdString dff) { if (cell_mappings.count(dff) == 0) { - log(" unmapped dff/dlatch cell: %s\n", dff); + log(" unmapped dff/dlatch cell: %s\n", ID::str(dff)); } else { - log(" %s %s (", cell_mappings[dff].cell_name, dff.substr(1)); + log(" %s %s (", cell_mappings[dff].cell_name, ID::str(dff).substr(1)); bool first = true; for (auto &port : cell_mappings[dff].ports) { char arg[3] = { port.second, 0, 0 }; @@ -423,12 +423,17 @@ static void find_cell(std::vector cells, IdString cell_type, } if (best.cell != nullptr) { - log(" cell %s (%s) is a direct match for cell type %s.\n", best.cell->args[0], best.rank.description(), cell_type); + log(" cell %s (%s) is a direct match for cell type %s.\n", best.cell->args[0], best.rank.description(), ID::str(cell_type)); cell_mappings[cell_type].cell_name = RTLIL::escape_id(best.cell->args[0]); cell_mappings[cell_type].ports = best.ports; } } +static IdString port_name_ref(TwinePool &twines, char port) +{ + return twines.add(stringf("\\%c", port)); +} + static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) { log("Mapping DFF/DLATCH cells in module `%s':\n", module->name); @@ -449,18 +454,20 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) notmap[sigmap(cell->getPort(ID::A))].insert(cell); } + auto &twines = module->design->twines; + std::map stats; for (auto cell : cell_list) { - auto cell_type = cell->type; - auto cell_name = cell->name; + IdString cell_type = cell->type; + IdString cell_name = cell->name; auto cell_connections = cell->connections(); dict attributes = std::move(cell->attributes); module->remove(cell); cell_mapping &cm = cell_mappings[cell_type]; - RTLIL::Cell *new_cell = module->addCell(cell_name, cm.cell_name); + RTLIL::Cell *new_cell = module->addCell(cell_name, twines.add(cm.cell_name)); new_cell->attributes = std::move(attributes); @@ -473,10 +480,10 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) for (auto &port : cm.ports) { RTLIL::SigSpec sig; if ('A' <= port.second && port.second <= 'Z') { - sig = cell_connections[std::string("\\") + port.second]; + sig = cell_connections[port_name_ref(twines, port.second)]; } else if (port.second == 'q') { - RTLIL::SigSpec old_sig = cell_connections[std::string("\\") + char(port.second - ('a' - 'A'))]; + RTLIL::SigSpec old_sig = cell_connections[port_name_ref(twines, char(port.second - ('a' - 'A')))]; sig = module->addWire(NEW_ID, GetSize(old_sig)); if (has_q && has_qn) { for (auto &it : notmap[sigmap(old_sig)]) { @@ -488,7 +495,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) } } else if ('a' <= port.second && port.second <= 'z') { - sig = cell_connections[std::string("\\") + char(port.second - ('a' - 'A'))]; + sig = cell_connections[port_name_ref(twines, char(port.second - ('a' - 'A')))]; sig = module->NotGate(NEW_ID, sig); } else if (port.second == '0' || port.second == '1') { @@ -501,7 +508,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module) new_cell->setPort("\\" + port.first, sig); } - stats[stringf("%s cells to %s cells", cell_type, new_cell->type)]++; + stats[stringf("%s cells to %s cells", twines.str(cell_type), new_cell->type.str())]++; } for (auto &stat: stats) @@ -654,7 +661,7 @@ struct DfflibmapPass : public Pass { if (!map_only_mode) { std::string dfflegalize_cmd = "dfflegalize"; for (auto it : cell_mappings) - dfflegalize_cmd += stringf(" -cell %s 01", it.first); + dfflegalize_cmd += stringf(" -cell %s 01", ID::str(it.first)); dfflegalize_cmd += " t:$_DFF* t:$_SDFF* t:$_DLATCH*"; if (info_mode) { log("dfflegalize command line: %s\n", dfflegalize_cmd); diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index f63123a23..03b110dfc 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -50,9 +50,9 @@ public: return true; } - RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value) + RTLIL::Const unified_param(const std::string &type_str, RTLIL::IdString param, RTLIL::Const value) { - if (!cell_type.begins_with("$") || cell_type.begins_with("$_")) + if (!type_str.starts_with("$") || type_str.starts_with("$_")) return value; #define param_bool(_n) if (param == _n) return value.as_bool(); @@ -105,12 +105,14 @@ public: if (!ignore_parameters) { std::map needle_param, haystack_param; + std::string needle_type = needleCell->type.str(); + std::string haystack_type = haystackCell->type.str(); for (auto &it : needleCell->parameters) if (!ignored_parameters.count(std::pair(needleCell->type, it.first))) - needle_param[it.first] = unified_param(needleCell->type, it.first, it.second); + needle_param[it.first] = unified_param(needle_type, it.first, it.second); for (auto &it : haystackCell->parameters) if (!ignored_parameters.count(std::pair(haystackCell->type, it.first))) - haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second); + haystack_param[it.first] = unified_param(haystack_type, it.first, it.second); if (needle_param != haystack_param) return false; } @@ -127,7 +129,7 @@ public: for (auto &conn : needleCell->connections()) { RTLIL::SigSpec needleSig = conn.second; - RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str())); + RTLIL::SigSpec haystackSig = haystackCell->getPort(haystackCell->module->design->twines.add(std::string{portMapping.at(needleCell->module->design->twines.str(conn.first))})); for (int i = 0; i < min(needleSig.size(), haystackSig.size()); i++) { RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire; @@ -149,10 +151,11 @@ struct bit_ref_t { }; bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = nullptr, - int max_fanout = -1, std::set> *split = nullptr) + int max_fanout = -1, std::set> *split = nullptr) { SigMap sigmap(mod); std::map sig_bit_ref; + auto &tw = mod->design->twines; if (sel && !sel->selected(mod)) { log(" Skipping module %s as it is not selected.\n", mod->name.unescape()); @@ -206,9 +209,9 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, for (auto &conn : cell->connections()) { - graph.createPort(cell->name.str(), conn.first.str(), conn.second.size()); + graph.createPort(cell->name.str(), tw.str(conn.first), conn.second.size()); - if (split && split->count(std::pair(cell->type, conn.first)) > 0) + if (split && split->count(std::pair(cell->type.str(), tw.str(conn.first))) > 0) continue; RTLIL::SigSpec conn_sig = conn.second; @@ -224,9 +227,9 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, if (bit == RTLIL::State::S0) node = "$const$0"; if (bit == RTLIL::State::S1) node = "$const$1"; if (bit == RTLIL::State::Sz) node = "$const$z"; - graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0); + graph.createConnection(cell->name.str(), tw.str(conn.first), i, node, "\\Y", 0); } else - graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data)); + graph.createConstant(cell->name.str(), tw.str(conn.first), i, int(bit.data)); continue; } @@ -239,12 +242,12 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, if (sig_bit_ref.count(bit) == 0) { bit_ref_t &bit_ref = sig_bit_ref[bit]; bit_ref.cell = cell->name.str(); - bit_ref.port = conn.first.str(); + bit_ref.port = tw.str(conn.first); bit_ref.bit = i; } bit_ref_t &bit_ref = sig_bit_ref[bit]; - graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i); + graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), tw.str(conn.first), i); } } } @@ -289,17 +292,18 @@ bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match) { SigMap sigmap(needle); - SigSet> sig2port; + SigSet> sig2port; + auto &tw = needle->design->twines; // create new cell - RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name, autoidx++), needle->name); + RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name, autoidx++), haystack->design->twines.copy_from(tw, needle->name)); - // create cell ports for (auto wire : needle->wires()) { if (wire->port_id > 0) { + IdString portname = haystack->design->twines.add(tw.str(wire->name)); for (int i = 0; i < wire->width; i++) - sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair(wire->name, i)); - cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width)); + sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair(portname, i)); + cell->setPort(portname, RTLIL::SigSpec(RTLIL::State::Sz, wire->width)); } } @@ -315,10 +319,10 @@ RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit: for (auto &conn : needle_cell->connections()) { RTLIL::SigSpec sig = sigmap(conn.second); - if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) { + if (mapping.portMapping.count(tw.str(conn.first)) > 0 && sig2port.has(sigmap(sig))) { for (int i = 0; i < sig.size(); i++) for (auto &port : sig2port.find(sig[i])) { - RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1); + RTLIL::SigSpec bitsig = haystack_cell->getPort(haystack_cell->module->design->twines.add(std::string{mapping.portMapping[tw.str(conn.first)]})).extract(i, 1); RTLIL::SigSpec new_sig = cell->getPort(port.first); new_sig.replace(port.second, bitsig); cell->setPort(port.first, new_sig); @@ -452,7 +456,7 @@ struct ExtractPass : public Pass { int mine_min_freq = 10; int mine_limit_mod = -1; int mine_max_fanout = -1; - std::set> mine_split; + std::set> mine_split; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -483,7 +487,7 @@ struct ExtractPass : public Pass { continue; } if (args[argidx] == "-mine_split" && argidx+2 < args.size()) { - mine_split.insert(std::pair(RTLIL::escape_id(args[argidx+1]), RTLIL::escape_id(args[argidx+2]))); + mine_split.insert(std::pair(RTLIL::escape_id(args[argidx+1]), RTLIL::escape_id(args[argidx+2]))); argidx += 2; continue; } @@ -540,11 +544,11 @@ struct ExtractPass : public Pass { continue; } if (args[argidx] == "-cell_attr" && argidx+1 < args.size()) { - solver.cell_attr.insert(RTLIL::escape_id(args[++argidx])); + solver.cell_attr.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-wire_attr" && argidx+1 < args.size()) { - solver.wire_attr.insert(RTLIL::escape_id(args[++argidx])); + solver.wire_attr.insert(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } if (args[argidx] == "-ignore_parameters") { @@ -552,7 +556,7 @@ struct ExtractPass : public Pass { continue; } if (args[argidx] == "-ignore_param" && argidx+2 < args.size()) { - solver.ignored_parameters.insert(std::pair(RTLIL::escape_id(args[argidx+1]), RTLIL::escape_id(args[argidx+2]))); + solver.ignored_parameters.insert(std::pair(design->twines.add(RTLIL::escape_id(args[argidx+1])), design->twines.add(RTLIL::escape_id(args[argidx+2])))); argidx += 2; continue; } @@ -596,7 +600,7 @@ struct ExtractPass : public Pass { } for (auto mod : saved_designs.at(filename.substr(1))->modules()) if (!map->has(mod->name)) - map->add(mod->clone()); + mod->clone(map); } else { @@ -715,12 +719,10 @@ struct ExtractPass : public Pass { wires.insert(chunk.wire); } - RTLIL::Module *newMod = new RTLIL::Module; - newMod->name = stringf("\\needle%05d_%s_%dx", needleCounter++, haystack_map.at(result.graphId)->name.unescape(), result.totalMatchesAfterLimits); - map->add(newMod); + RTLIL::Module *newMod = map->addModule(stringf("\\needle%05d_%s_%dx", needleCounter++, haystack_map.at(result.graphId)->name.unescape(), result.totalMatchesAfterLimits)); for (auto wire : wires) { - RTLIL::Wire *newWire = newMod->addWire(wire->name, wire->width); + RTLIL::Wire *newWire = newMod->addWire(wire->name.unescape(), wire->width); newWire->port_input = true; newWire->port_output = true; } @@ -728,13 +730,13 @@ struct ExtractPass : public Pass { newMod->fixup_ports(); for (auto cell : cells) { - RTLIL::Cell *newCell = newMod->addCell(cell->name, cell->type); + RTLIL::Cell *newCell = newMod->addCell(cell->name.unescape(), cell->type.str()); newCell->parameters = cell->parameters; for (auto &conn : cell->connections()) { std::vector chunks = sigmap(conn.second); for (auto &chunk : chunks) if (chunk.wire != nullptr) - chunk.wire = newMod->wire(chunk.wire->name); + chunk.wire = newMod->wire(map->twines.add(chunk.wire->name.unescape())); newCell->setPort(conn.first, chunks); } } diff --git a/passes/techmap/mcm.cc b/passes/techmap/mcm.cc index de988575b..7c86e51f7 100644 --- a/passes/techmap/mcm.cc +++ b/passes/techmap/mcm.cc @@ -438,7 +438,7 @@ struct McmWorker { auto value = constant.try_as_int(is_signed); if (!value || *value == std::numeric_limits::min()) { log_debug("Skipping constant multiplier %s: coefficient %s is outside the supported range.\n", - log_id(cell), log_const(constant)); + cell, log_const(constant)); return false; } @@ -479,7 +479,7 @@ struct McmWorker { int depth = graph.depth.at(odd) + (group.items[i].coefficient < 0 ? 1 : 0); if (depth > config.search.max_depth) { log_debug("Skipping constant multiplier %s: output negation exceeds depth %d.\n", - log_id(group.items[i].cell), config.search.max_depth); + group.items[i].cell, config.search.max_depth); continue; } plan.active_items.push_back(i); @@ -566,7 +566,7 @@ struct McmWorker { if (is_profitable(plan)) return true; log_debug("Skipping MCM group in module %s: estimated bit cost %lld vs %lld " - "does not meet %d%% minimum gain.\n", log_id(module), plan.shared_cost, + "does not meet %d%% minimum gain.\n", module, plan.shared_cost, plan.independent_cost, config.min_gain); return false; } @@ -761,7 +761,7 @@ struct McmPass : public Pass { worker.run(); if (worker.n_muls) log("Module %s: replaced %d constant multiplier(s) in %d group(s) " - "with %d adder(s).\n", log_id(module), worker.n_muls, worker.n_groups, worker.n_adders); + "with %d adder(s).\n", module, worker.n_muls, worker.n_groups, worker.n_adders); total_groups += worker.n_groups; total_muls += worker.n_muls; total_adders += worker.n_adders; diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 2dbeef7a3..de4b2257b 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -39,7 +39,7 @@ YOSYS_NAMESPACE_END USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -void apply_prefix(IdString prefix, IdString &id) +void apply_prefix(const std::string &prefix, std::string &id) { if (id[0] == '\\') id = stringf("%s.%s", prefix, id.c_str()+1); @@ -47,17 +47,63 @@ void apply_prefix(IdString prefix, IdString &id) id = stringf("$techmap%s.%s", prefix, id); } -void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module) +struct PrefixApplier { - vector chunks = sig; - for (auto &chunk : chunks) - if (chunk.wire != nullptr) { - IdString wire_name = chunk.wire->name; - apply_prefix(prefix, wire_name); - log_assert(module->wire(wire_name) != nullptr); - chunk.wire = module->wire(wire_name); + RTLIL::Design *dst; + RTLIL::Design *src; + IdString cell_name; + IdString pub_prefix; + IdString priv_prefix = IdString::Null; + dict memo; + + PrefixApplier(RTLIL::Design *dst, IdString prefix, RTLIL::Design *src) + : dst(dst), src(src), cell_name(prefix) + { + pub_prefix = dst->twines.add(Twine::Suffix{prefix, "."}); + } + + IdString techmap_prefix() + { + if (priv_prefix == IdString::Null) + priv_prefix = dst->twines.add("$techmap" + dst->twines.str(cell_name) + "."); + return priv_prefix; + } + + IdString name(IdString obj_ref) + { + if (auto it = memo.find(obj_ref); it != memo.end()) + return it->second; + + const TwineNode &node = src->twines[obj_ref]; + IdString result; + if (node.is_suffix()) { + const Twine::Suffix &sfx = node.suffix(); + IdString prefix = name(sfx.prefix.tag(obj_ref.isPublic())); + result = dst->twines.add(Twine::Suffix{prefix, sfx.tail}); + } else { + IdString prefix = obj_ref.isPublic() ? pub_prefix : techmap_prefix(); + result = dst->twines.add(Twine::Suffix{prefix, node.leaf()}); } - sig = chunks; + memo[obj_ref] = result; + return result; + } + + void apply(RTLIL::SigSpec &sig, RTLIL::Module *module) + { + vector chunks = sig; + for (auto &chunk : chunks) + if (chunk.wire != nullptr) { + IdString wire_ref = name(chunk.wire->name); + log_assert(module->wire(wire_ref) != nullptr); + chunk.wire = module->wire(wire_ref); + } + sig = chunks; + } +}; + +static RTLIL::Wire *map_port(RTLIL::Module *tpl, RTLIL::Design *src, IdString name) +{ + return tpl->wire(tpl->design->twines.find(src->twines.str(name))); } struct TechmapWorker @@ -75,7 +121,7 @@ struct TechmapWorker RTLIL::SigSpec value; }; - typedef dict> TechmapWires; + typedef dict> TechmapWires; bool extern_mode = false; bool assert_mode = false; @@ -86,6 +132,7 @@ struct TechmapWorker std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) { std::string constmap_info; + auto &twines = cell->module->design->twines; dict> connbits_map; for (auto &conn : cell->connections()) @@ -93,17 +140,17 @@ struct TechmapWorker RTLIL::SigBit bit = sigmap(conn.second[i]); if (bit.wire == nullptr) { if (verbose) - log(" Constant input on bit %d of port %s: %s\n", i, conn.first.unescape(), log_signal(bit)); - constmap_info += stringf("|%s %d %d", conn.first.unescape(), i, bit.data); + log(" Constant input on bit %d of port %s: %s\n", i, twines.unescaped_str(conn.first).data(), log_signal(bit)); + constmap_info += stringf("|%s %d %d", twines.unescaped_str(conn.first).data(), i, bit.data); } else if (connbits_map.count(bit)) { if (verbose) - log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, conn.first.unescape(), - connbits_map.at(bit).second, connbits_map.at(bit).first.unescape()); - constmap_info += stringf("|%s %d %s %d", conn.first.unescape(), i, - connbits_map.at(bit).first.unescape(), connbits_map.at(bit).second); + log(" Bit %d of port %s and bit %d of port %s are connected.\n", i, twines.unescaped_str(conn.first).data(), + connbits_map.at(bit).second, twines.unescaped_str(connbits_map.at(bit).first).data()); + constmap_info += stringf("|%s %d %s %d", twines.unescaped_str(conn.first).data(), i, + twines.unescaped_str(connbits_map.at(bit).first).data(), connbits_map.at(bit).second); } else { connbits_map.emplace(bit, std::make_pair(conn.first, i)); - constmap_info += stringf("|%s %d", conn.first.unescape(), i); + constmap_info += stringf("|%s %d", twines.unescaped_str(conn.first).data(), i); } } @@ -118,7 +165,7 @@ struct TechmapWorker return result; for (auto w : module->wires()) { - if (*w->name.c_str() == '$') + if (w->name.str()[0] == '$') continue; if (w->name.contains("_TECHMAP_") && !w->name.contains("_TECHMAP_REPLACE_")) { @@ -146,7 +193,7 @@ struct TechmapWorker if (tpl->processes.size() != 0) { log("Technology map yielded processes:"); for (auto &it : tpl->processes) - log(" %s",it.first.unescape()); + log(" %s", PooledName(tpl, it.first).unescape()); log("\n"); if (autoproc_mode) { Pass::call_on_module(tpl->design, tpl, "proc"); @@ -165,15 +212,19 @@ struct TechmapWorker break; } - dict memory_renames; + PrefixApplier ap(module->design, cell->name, tpl->design); + + dict memory_renames; for (auto &it : tpl->memories) { - IdString m_name = it.first; - apply_prefix(cell->name, m_name); - RTLIL::Memory *m = module->addMemory(m_name, it.second); - if (m->attributes.count(ID::src)) + std::string old_m_id = tpl->design->twines.str(it.first); + std::string m_name_id = old_m_id; + apply_prefix(cell->name, m_name_id); + IdString m_ref = module->design->twines.add(std::string(m_name_id)); + RTLIL::Memory *m = module->addMemory(m_ref, it.second); + if (m->has_attribute(ID::src)) m->add_strpool_attribute(ID::src, extra_src_attrs); - memory_renames[it.first] = m->name; + memory_renames[old_m_id] = m_name_id; design->select(module, m); } @@ -185,12 +236,13 @@ struct TechmapWorker { if (tpl_w->port_id > 0) { - IdString posportname = stringf("$%d", tpl_w->port_id); - positional_ports.emplace(posportname, tpl_w->name); + IdString posportref = module->design->twines.add(std::string{stringf("$%d", tpl_w->port_id)}); + positional_ports.emplace(posportref, tpl_w->name); + IdString tpl_portname = module->design->twines.find(tpl_w->name.str()); if (tpl_w->get_bool_attribute(ID::techmap_autopurge) && - (!cell->hasPort(tpl_w->name) || !GetSize(cell->getPort(tpl_w->name))) && - (!cell->hasPort(posportname) || !GetSize(cell->getPort(posportname)))) + (!cell->hasPort(tpl_portname) || !GetSize(cell->getPort(tpl_portname))) && + (!cell->hasPort(posportref) || !GetSize(cell->getPort(posportref)))) { if (sigmaps.count(tpl) == 0) sigmaps[tpl].set(tpl); @@ -200,16 +252,15 @@ struct TechmapWorker autopurge_tpl_bits.insert(bit); } } - IdString w_name = tpl_w->name; - apply_prefix(cell->name, w_name); - RTLIL::Wire *w = module->wire(w_name); + IdString w_ref = ap.name(tpl_w->name); + RTLIL::Wire *w = module->wire(w_ref); if (w != nullptr) { temp_renamed_wires[w] = w->name; module->rename(w, NEW_ID); w = nullptr; } if (w == nullptr) { - w = module->addWire(w_name, tpl_w); + w = module->addWire(w_ref, tpl_w); w->port_input = false; w->port_output = false; w->port_id = 0; @@ -221,9 +272,9 @@ struct TechmapWorker } design->select(module, w); - if (const char *p = strstr(tpl_w->name.c_str(), "_TECHMAP_REPLACE_.")) { - IdString replace_name = stringf("%s%s", orig_cell_name, p + strlen("_TECHMAP_REPLACE_")); - Wire *replace_w = module->addWire(replace_name, tpl_w); + std::string tpl_w_name = tpl_w->name.str(); + if (const char *p = strstr(tpl_w_name.c_str(), "_TECHMAP_REPLACE_.")) { + Wire *replace_w = module->addWire(std::string(orig_cell_name) + (p + strlen("_TECHMAP_REPLACE_")), tpl_w); module->connect(replace_w, w); } } @@ -243,35 +294,37 @@ struct TechmapWorker for (auto &it : cell->connections()) { IdString portname = it.first; + RTLIL::Wire *w; if (positional_ports.count(portname) > 0) - portname = positional_ports.at(portname); - if (tpl->wire(portname) == nullptr || tpl->wire(portname)->port_id == 0) { - if (portname.begins_with("$")) - log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname, cell->name, tpl->name); + w = tpl->wire(positional_ports.at(portname)); + else + w = map_port(tpl, design, portname); + if (w == nullptr || w->port_id == 0) { + if (design->twines.str(portname).starts_with("$")) + log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", PooledName(design, portname).unescape(), cell->name.unescape(), tpl->name.unescape()); continue; } if (GetSize(it.second) == 0) continue; - RTLIL::Wire *w = tpl->wire(portname); RTLIL::SigSig c, extra_connect; if (w->port_output && !w->port_input) { c.first = it.second; c.second = RTLIL::SigSpec(w); - apply_prefix(cell->name, c.second, module); + ap.apply(c.second, module); extra_connect.first = c.second; extra_connect.second = c.first; } else if (!w->port_output && w->port_input) { c.first = RTLIL::SigSpec(w); c.second = it.second; - apply_prefix(cell->name, c.first, module); + ap.apply(c.first, module); extra_connect.first = c.first; extra_connect.second = c.second; } else { SigSpec sig_tpl = w, sig_tpl_pf = w, sig_mod = it.second; - apply_prefix(cell->name, sig_tpl_pf, module); + ap.apply(sig_tpl_pf, module); for (int i = 0; i < GetSize(sig_tpl) && i < GetSize(sig_mod); i++) { if (tpl_written_bits.count(sig_tpl[i])) { c.first.append(sig_mod[i]); @@ -321,21 +374,22 @@ struct TechmapWorker for (auto tpl_cell : tpl->cells()) { - IdString c_name = tpl_cell->name; - bool techmap_replace_cell = c_name.ends_with("_TECHMAP_REPLACE_"); + bool techmap_replace_cell = tpl_cell->name.ends_with("_TECHMAP_REPLACE_"); + std::string tpl_cell_name = tpl_cell->name.str(); + IdString c_ref; if (techmap_replace_cell) - c_name = orig_cell_name; - else if (const char *p = strstr(tpl_cell->name.c_str(), "_TECHMAP_REPLACE_.")) - c_name = stringf("%s%s", orig_cell_name, p + strlen("_TECHMAP_REPLACE_")); + c_ref = module->design->twines.add(std::string{orig_cell_name}); + else if (const char *p = strstr(tpl_cell_name.c_str(), "_TECHMAP_REPLACE_.")) + c_ref = module->design->twines.add(stringf("%s%s", orig_cell_name, p + strlen("_TECHMAP_REPLACE_"))); else - apply_prefix(cell->name, c_name); + c_ref = ap.name(tpl_cell->name); - RTLIL::Cell *c = module->addCell(c_name, tpl_cell); + RTLIL::Cell *c = module->addCell(c_ref, tpl_cell); design->select(module, c); if (c->type == ID::_TECHMAP_PLACEHOLDER_ && tpl_cell->has_attribute(ID::techmap_chtype)) { - c->type = RTLIL::escape_id(tpl_cell->get_string_attribute(ID::techmap_chtype)); + c->type = module->design->twines.add(std::string{RTLIL::escape_id(tpl_cell->get_string_attribute(ID::techmap_chtype))}); c->attributes.erase(ID::techmap_chtype); } @@ -357,7 +411,7 @@ struct TechmapWorker autopurge_ports.push_back(conn.first); } else { RTLIL::SigSpec new_conn = conn.second; - apply_prefix(cell->name, new_conn, module); + ap.apply(new_conn, module); port_signal_map.apply(new_conn); c->setPort(conn.first, std::move(new_conn)); } @@ -367,11 +421,11 @@ struct TechmapWorker c->unsetPort(it2); if (c->has_memid()) { - IdString memid = c->getParam(ID::MEMID).decode_string(); + std::string memid = c->getParam(ID::MEMID).decode_string(); log_assert(memory_renames.count(memid) != 0); - c->setParam(ID::MEMID, Const(memory_renames[memid].str())); + c->setParam(ID::MEMID, Const(memory_renames[memid])); } else if (c->is_mem_cell()) { - IdString memid = c->getParam(ID::MEMID).decode_string(); + std::string memid = c->getParam(ID::MEMID).decode_string(); apply_prefix(cell->name, memid); c->setParam(ID::MEMID, Const(memid.c_str())); } @@ -389,8 +443,8 @@ struct TechmapWorker for (auto &it : tpl->connections()) { RTLIL::SigSig c = it; - apply_prefix(cell->name.str(), c.first, module); - apply_prefix(cell->name.str(), c.second, module); + ap.apply(c.first, module); + ap.apply(c.second, module); port_signal_map.apply(c.first); port_signal_map.apply(c.second); module->connect(c); @@ -449,7 +503,7 @@ struct TechmapWorker for (auto &tpl_name : celltypeMap.at(cell->type)) { RTLIL::Module *tpl = map->module(tpl_name); - RTLIL::Wire *port = tpl->wire(conn.first); + RTLIL::Wire *port = map_port(tpl, design, conn.first); if (port && port->port_input) cell_to_inbit[cell].insert(sig.begin(), sig.end()); if (port && port->port_output) @@ -477,8 +531,10 @@ struct TechmapWorker for (auto &tpl_name : celltypeMap.at(cell->type)) { IdString derived_name = tpl_name; - RTLIL::Module *tpl = map->module(tpl_name); - dict parameters(cell->parameters); + RTLIL::Module *tpl = map->module(derived_name); + dict parameters; + for (auto &p : cell->parameters) + parameters[map->twines.copy_from(design->twines, p.first)] = p.second; if (tpl->get_blackbox_attribute(ignore_wb)) continue; @@ -501,13 +557,13 @@ struct TechmapWorker std::string m_name = stringf("$extern:%s:%s", extmapper_name, cell->type.unescape()); for (auto &c : cell->parameters) - m_name += stringf(":%s=%s", c.first.unescape(), log_signal(c.second)); + m_name += stringf(":%s=%s", PooledName(cell->module, c.first).unescape(), log_signal(c.second)); if (extmapper_name == "wrap") m_name += ":" + sha1(tpl->attributes.at(ID::techmap_wrap).decode_string()); RTLIL::Design *extmapper_design = extern_mode && !in_recursion ? design : tpl->design; - RTLIL::Module *extmapper_module = extmapper_design->module(m_name); + RTLIL::Module *extmapper_module = extmapper_design->module(extmapper_design->twines.add(std::string{m_name})); if (extmapper_module == nullptr) { @@ -519,7 +575,7 @@ struct TechmapWorker int port_counter = 1; for (auto &c : extmapper_cell->connections_) { RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second)); - if (w->name.in(ID::Y, ID::Q)) + if (w->name.in(IdString{ID::Y}, IdString{ID::Q})) w->port_output = true; else w->port_input = true; @@ -540,7 +596,7 @@ struct TechmapWorker if (extmapper_name == "maccmap") { log("Creating %s with maccmap.\n", extmapper_module); - if (!extmapper_cell->type.in(ID($macc), ID($macc_v2))) + if (!extmapper_cell->type.in(IdString{ID($macc)}, IdString{ID($macc_v2)})) log_error("The maccmap mapper can only map $macc/$macc_v2 (not %s) cells!\n", extmapper_cell->type.unescape()); maccmap(extmapper_module, extmapper_cell); extmapper_module->remove(extmapper_cell); @@ -555,7 +611,7 @@ struct TechmapWorker } } - cell->type = extmapper_module->name; + cell->type = cell->module->design->twines.add(std::string{m_name}); cell->parameters.clear(); if (!extern_mode || in_recursion) { @@ -601,13 +657,15 @@ struct TechmapWorker } for (auto &conn : cell->connections()) { - if (conn.first.begins_with("$")) + if (!conn.first.isPublic()) continue; - if (tpl->wire(conn.first) != nullptr && tpl->wire(conn.first)->port_id > 0) + RTLIL::Wire *tpl_port = map_port(tpl, design, conn.first); + if (tpl_port != nullptr && tpl_port->port_id > 0) continue; - if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0) + IdString conn_id = map->twines.copy_from(design->twines, conn.first); + if (!conn.second.is_fully_const() || parameters.count(conn_id) > 0 || tpl->avail_parameters.count(conn_id) == 0) goto next_tpl; - parameters[conn.first] = conn.second.as_const(); + parameters[conn_id] = conn.second.as_const(); } if (0) { @@ -621,21 +679,21 @@ struct TechmapWorker parameters.emplace(ID::_TECHMAP_CELLNAME_, cell->name.unescape()); for (auto &conn : cell->connections()) { - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape())) != 0) { + if (tpl->avail_parameters.count(map->twines.add(stringf("\\_TECHMAP_CONSTMSK_%s_", design->twines.unescaped_str(conn.first)))) != 0) { std::vector v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0); - parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const()); + parameters.emplace(map->twines.add(stringf("\\_TECHMAP_CONSTMSK_%s_", design->twines.unescaped_str(conn.first))), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape())) != 0) { + if (tpl->avail_parameters.count(map->twines.add(stringf("\\_TECHMAP_CONSTVAL_%s_", design->twines.unescaped_str(conn.first)))) != 0) { std::vector v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) if (bit.wire != nullptr) bit = RTLIL::SigBit(RTLIL::State::Sx); - parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", conn.first.unescape()), RTLIL::SigSpec(v).as_const()); + parameters.emplace(map->twines.add(stringf("\\_TECHMAP_CONSTVAL_%s_", design->twines.unescaped_str(conn.first))), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape())) != 0) { - parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", conn.first.unescape()), initvals(conn.second)); + if (tpl->avail_parameters.count(map->twines.add(stringf("\\_TECHMAP_WIREINIT_%s_", design->twines.unescaped_str(conn.first)))) != 0) { + parameters.emplace(map->twines.add(stringf("\\_TECHMAP_WIREINIT_%s_", design->twines.unescaped_str(conn.first))), initvals(conn.second)); } } @@ -648,7 +706,7 @@ struct TechmapWorker unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++; for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) { + if (tpl->avail_parameters.count(map->twines.add(stringf("\\_TECHMAP_CONNMAP_%s_", design->twines.unescaped_str(conn.first)))) != 0) { for (auto &bit : sigmap(conn.second)) if (unique_bit_id.count(bit) == 0) unique_bit_id[bit] = unique_bit_id_counter++; @@ -665,7 +723,7 @@ struct TechmapWorker parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits; for (auto &conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape())) != 0) { + if (tpl->avail_parameters.count(map->twines.add(stringf("\\_TECHMAP_CONNMAP_%s_", design->twines.unescaped_str(conn.first)))) != 0) { SigSpec sm = sigmap(conn.second); RTLIL::Const::Builder builder(GetSize(sm) * bits); for (auto &bit : sm) { @@ -675,7 +733,7 @@ struct TechmapWorker val = val >> 1; } } - parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", conn.first.unescape()), builder.build()); + parameters.emplace(map->twines.add(stringf("\\_TECHMAP_CONNMAP_%s_", design->twines.unescaped_str(conn.first))), builder.build()); } } @@ -698,7 +756,7 @@ struct TechmapWorker } } - RTLIL::Module *constmapped_tpl = map->module(constmap_tpl_name(sigmap, tpl, cell, false)); + RTLIL::Module *constmapped_tpl = map->module(map->twines.add(std::string{constmap_tpl_name(sigmap, tpl, cell, false)})); if (constmapped_tpl != nullptr) tpl = constmapped_tpl; @@ -707,7 +765,7 @@ struct TechmapWorker bool keep_running = true; techmap_do_cache[tpl] = true; - pool techmap_wire_names; + pool techmap_wire_names; while (keep_running) { @@ -724,7 +782,7 @@ struct TechmapWorker RTLIL::SigSpec value = elem.value; if (value.is_fully_const() && value.as_bool()) { log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", - derived_name.c_str(), elem.wire->name.unescape(), log_signal(value)); + PooledName(map, derived_name).unescape(), elem.wire->name.unescape().data(), log_signal(value)); techmap_do_cache[tpl] = false; } } @@ -735,7 +793,7 @@ struct TechmapWorker for (auto &it : twd) { - if (!it.first.contains("_TECHMAP_DO_") || it.second.empty()) + if (!(it.first.find("_TECHMAP_DO_") != std::string::npos) || it.second.empty()) continue; auto &data = it.second.front(); @@ -745,9 +803,9 @@ struct TechmapWorker techmap_wire_names.erase(it.first); - const char *p = data.wire->name.c_str(); - const char *q = strrchr(p+1, '.'); - q = q ? q+1 : p+1; + std::string final_id = data.wire->name.escaped(); + size_t last_dot = final_id.find_last_of('.'); + size_t split_idx = (last_dot != std::string::npos) ? (last_dot + 1) : 1; std::string cmd_string = data.value.as_const().decode_string(); @@ -757,8 +815,8 @@ struct TechmapWorker cmd_string = cmd_string.substr(strlen("CONSTMAP; ")); log("Analyzing pattern of constant bits for this cell:\n"); - IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); - log("Creating constmapped module `%s'.\n", new_tpl_name.unescape()); + IdString new_tpl_name = map->twines.add(constmap_tpl_name(sigmap, tpl, cell, true)); + log("Creating constmapped module `%s'.\n", PooledName(map, new_tpl_name).unescape()); log_assert(map->module(new_tpl_name) == nullptr); RTLIL::Module *new_tpl = map->addModule(new_tpl_name); @@ -793,7 +851,7 @@ struct TechmapWorker // Handle outputs first, as these cannot be remapped. for (auto &conn : cell->connections()) { - Wire *twire = tpl->wire(conn.first); + Wire *twire = map_port(tpl, design, conn.first); if (!twire->port_output) continue; @@ -807,7 +865,7 @@ struct TechmapWorker // Now handle inputs, remapping as necessary. for (auto &conn : cell->connections()) { - Wire *twire = tpl->wire(conn.first); + Wire *twire = map_port(tpl, design, conn.first); if (twire->port_output) continue; @@ -851,9 +909,11 @@ struct TechmapWorker Pass::call_on_module(map, tpl, cmd_string); - log_assert(!strncmp(q, "_TECHMAP_DO_", 12)); - std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12); - while (tpl->wire(new_name) != nullptr) + log_assert(final_id.compare(split_idx, 12, "_TECHMAP_DO_") == 0); + std::string new_name = final_id.substr(0, split_idx) + + "_TECHMAP_DONE_" + + final_id.substr(split_idx + 12); + while (tpl->wire(tpl->design->twines.add(std::string{new_name})) != nullptr) new_name += "_"; tpl->rename(data.wire->name, new_name); @@ -864,8 +924,8 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { - if (!it.first.ends_with("_TECHMAP_FAIL_") && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.contains("_TECHMAP_DO_") && !it.first.contains("_TECHMAP_DONE_")) - log_error("Techmap yielded unknown config wire %s.\n", it.first.unescape()); + if (!it.first.ends_with("_TECHMAP_FAIL_") && (!it.first.starts_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !(it.first.find("_TECHMAP_DO_") != std::string::npos) && !(it.first.find("_TECHMAP_DONE_") != std::string::npos)) + log_error("Techmap yielded unknown config wire %s.\n", RTLIL::unescape_id(it.first)); if (techmap_do_cache[tpl]) for (auto &it2 : it.second) if (!it2.value.is_fully_const()) @@ -874,7 +934,7 @@ struct TechmapWorker } for (auto &it : techmap_wire_names) - log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", it.unescape()); + log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", RTLIL::unescape_id(it)); if (recursive_mode) { if (log_continue) { @@ -897,11 +957,12 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { - if (it.first.begins_with("\\_TECHMAP_REMOVEINIT_")) { + if (it.first.starts_with("\\_TECHMAP_REMOVEINIT_")) { for (auto &it2 : it.second) { auto val = it2.value.as_const(); auto wirename = RTLIL::escape_id(it.first.substr(21, it.first.size() - 21 - 1)); - auto it = cell->connections().find(wirename); + IdString wirename_ref = cell->module->design->twines.add(std::string{wirename}); + auto it = cell->connections().find(wirename_ref); if (it != cell->connections().end()) { auto sig = sigmap(it->second); for (int i = 0; i < sig.size(); i++) @@ -914,9 +975,9 @@ struct TechmapWorker if (extern_mode && !in_recursion) { - std::string m_name = stringf("$extern:%s", tpl); + std::string m_name = stringf("$extern:%s", tpl->name.unescape()); - if (!design->module(m_name)) + if (!design->module(design->twines.add(std::string{m_name}))) { RTLIL::Module *m = design->addModule(m_name); tpl->cloneInto(m); @@ -924,18 +985,18 @@ struct TechmapWorker module_queue.insert(m); } - log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, module, cell, m_name); - cell->type = m_name; + log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), module->name.unescape(), cell->name.unescape(), m_name.c_str()); + cell->type = cell->module->design->twines.add(std::string{m_name}); cell->parameters.clear(); } else { - auto msg = stringf("Using template %s for cells of type %s.", tpl, cell->type.unescape()); + auto msg = stringf("Using template %s for cells of type %s.", tpl->name.unescape(), cell->type.unescape()); if (!log_msg_cache.count(msg)) { log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, module, cell, cell->type.unescape(), tpl); + log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), module->name.unescape(), cell->name.unescape(), cell->type.unescape(), tpl->name.unescape()); techmap_module_worker(design, module, cell, tpl); cell = nullptr; } @@ -1196,7 +1257,7 @@ struct TechmapPass : public Pass { continue; } if (args[argidx] == "-dont_map" && argidx+1 < args.size()) { - dont_map.push_back(RTLIL::escape_id(args[++argidx])); + dont_map.push_back(design->twines.add(RTLIL::escape_id(args[++argidx]))); continue; } break; @@ -1213,9 +1274,10 @@ struct TechmapPass : public Pass { delete map; log_cmd_error("Can't open saved design `%s'.\n", fn.c_str()+1); } - for (auto mod : saved_designs.at(fn.substr(1))->modules()) - if (!map->module(mod->name)) - map->add(mod->clone()); + auto saved = saved_designs.at(fn.substr(1)); + for (auto mod : saved->modules()) + if (!map->module(map->twines.copy_from(saved->twines, mod->name))) + mod->clone(map); } else { Frontend::frontend_call(map, nullptr, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : verilog_frontend)); } @@ -1236,7 +1298,7 @@ struct TechmapPass : public Pass { auto pos = name.find('['); if (pos == std::string::npos) { // No further expansion. - celltypeMap[RTLIL::escape_id(name)].insert(module->name); + celltypeMap[design->twines.add(RTLIL::escape_id(name))].insert(module->name); } else { // Expand [] in this name. auto epos = name.find(']', pos); @@ -1250,9 +1312,9 @@ struct TechmapPass : public Pass { } free(p); } else { - IdString module_name = module->name.begins_with("\\$") ? + std::string module_name = module->name.begins_with("\\$") ? module->name.substr(1) : module->name.str(); - celltypeMap[module_name].insert(module->name); + celltypeMap[design->twines.add(std::move(module_name))].insert(module->name); } } @@ -1262,11 +1324,11 @@ struct TechmapPass : public Pass { log_debug("Cell type mappings to use:\n"); for (auto &i : celltypeMap) { - i.second.sort(RTLIL::sort_by_id_str()); + i.second.sort(RTLIL::sort_by_id_str(map->twines)); std::string maps = ""; - for (auto &map : i.second) - maps += stringf(" %s", map.unescape()); - log_debug(" %s:%s\n", i.first.unescape(), maps); + for (auto &m : i.second) + maps += stringf(" %s", PooledName(map, m).unescape()); + log_debug(" %s:%s\n", PooledName(design, i.first).unescape(), maps.c_str()); } log_debug("\n"); diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 3f2588bd1..2bd7280e3 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -602,15 +602,19 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: } vlog_file << stringf(" %s_expr uut_expr(", uut_name); - for (int i = 0; i < GetSize(gold_mod->ports); i++) - vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", gold_mod->ports[i].unescape(), gold_mod->ports[i].unescape(), + for (int i = 0; i < GetSize(gold_mod->ports); i++) { + std::string port_name = gold_mod->design->twines.str(gold_mod->ports[i]); + vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", port_name, port_name, gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_expr"); + } vlog_file << stringf(");\n"); vlog_file << stringf(" %s_expr uut_noexpr(", uut_name); - for (int i = 0; i < GetSize(gold_mod->ports); i++) - vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", gold_mod->ports[i].unescape(), gold_mod->ports[i].unescape(), + for (int i = 0; i < GetSize(gold_mod->ports); i++) { + std::string port_name = gold_mod->design->twines.str(gold_mod->ports[i]); + vlog_file << stringf("%s.%s(%s%s)", i ? ", " : "", port_name, port_name, gold_mod->wire(gold_mod->ports[i])->port_input ? "" : "_noexpr"); + } vlog_file << stringf(");\n"); vlog_file << stringf(" task run;\n"); @@ -1076,6 +1080,13 @@ struct TestCellPass : public Pass { cell_types[ID($_AOI4_)] = "ABCDYb"; cell_types[ID($_OAI4_)] = "ABCDYb"; + auto find_type = [&](const std::string &s) -> IdString { + for (auto &it : cell_types) + if (ID::str(it.first) == s) + return it.first; + return IdString::Null; + }; + for (; argidx < GetSize(args); argidx++) { if (args[argidx].rfind("-", 0) == 0) @@ -1091,29 +1102,30 @@ struct TestCellPass : public Pass { if (args[argidx].compare(0, 1, "/") == 0) { std::vector new_selected_cell_types; for (auto it : selected_cell_types) - if (it != args[argidx].substr(1)) + if (ID::str(it) != args[argidx].substr(1)) new_selected_cell_types.push_back(it); new_selected_cell_types.swap(selected_cell_types); continue; } - if (cell_types.count(args[argidx]) == 0) { + IdString arg_type = find_type(args[argidx]); + if (arg_type == IdString::Null) { std::string cell_type_list; int charcount = 100; for (auto &it : cell_types) { if (charcount > 60) { - cell_type_list += stringf("\n%s", it.first.unescape()); + cell_type_list += stringf("\n%s", ID::str(it.first).c_str()); charcount = 0; } else - cell_type_list += stringf(" %s", it.first.unescape()); - charcount += GetSize(it.first); + cell_type_list += stringf(" %s", ID::str(it.first).c_str()); + charcount += GetSize(ID::str(it.first)); } log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n", args[argidx].c_str(), cell_type_list.c_str()); } - if (std::count(selected_cell_types.begin(), selected_cell_types.end(), args[argidx]) == 0) - selected_cell_types.push_back(args[argidx]); + if (std::count(selected_cell_types.begin(), selected_cell_types.end(), arg_type) == 0) + selected_cell_types.push_back(arg_type); } if (!rtlil_file.empty()) { @@ -1151,13 +1163,13 @@ struct TestCellPass : public Pass { bool is_unconverted = false; for (auto *mod : design->selected_modules()) for (auto *cell : mod->selected_cells()) - if (!cell->type.in(ID::$_NOT_, ID::$_AND_)) { + if (!cell->type.in(ID($_NOT_), ID($_AND_))) { is_unconverted = true; break; } if (is_unconverted) { // skip unconverted cells - log_warning("Skipping %s\n", cell_type); + log_warning("Skipping %s\n", ID::str(cell_type).c_str()); delete design; break; } else { @@ -1165,7 +1177,7 @@ struct TestCellPass : public Pass { suffix = "aag"; } } - Pass::call(design, stringf("%s %s_%s_%05d.%s", writer, write_prefix, cell_type.c_str()+1, i, suffix)); + Pass::call(design, stringf("%s %s_%s_%05d.%s", writer, write_prefix, ID::str(cell_type).c_str()+1, i, suffix)); } else if (edges) { Pass::call(design, "dump gold"); run_edges_test(design, verbose); @@ -1180,7 +1192,7 @@ struct TestCellPass : public Pass { Pass::call(design, "dump gold"); if (!nosat) Pass::call(design, "sat -verify -enable_undef -prove trigger 0 -show-inputs -show-outputs miter"); - std::string uut_name = stringf("uut_%s_%d", cell_type.substr(1), i); + std::string uut_name = stringf("uut_%s_%d", ID::str(cell_type).substr(1), i); if (vlog_file.is_open()) { Pass::call(design, stringf("copy gold %s_expr; select %s_expr", uut_name, uut_name)); Backend::backend_call(design, &vlog_file, "", "verilog -selected"); @@ -1207,14 +1219,14 @@ struct TestCellPass : public Pass { // Expected to run once int num_cells_estimate = costs.get(uut); if (num_cells <= num_cells_estimate) { - log_debug("Correct upper bound for %s: %d <= %d\n", cell_type, num_cells, num_cells_estimate); + log_debug("Correct upper bound for %s: %d <= %d\n", design->twines.str(cell_type).c_str(), num_cells, num_cells_estimate); } else { failed++; if (worst_abs < num_cells - num_cells_estimate) { worst_abs = num_cells - num_cells_estimate; worst_rel = (float)(num_cells - num_cells_estimate) / (float)num_cells_estimate; } - log_warning("Upper bound violated for %s: %d > %d\n", cell_type, num_cells, num_cells_estimate); + log_warning("Upper bound violated for %s: %d > %d\n", design->twines.str(cell_type).c_str(), num_cells, num_cells_estimate); } } } @@ -1224,7 +1236,7 @@ struct TestCellPass : public Pass { if (check_cost && failed) { log_warning("Cell type %s cost underestimated in %.1f%% cases " "with worst offender being by %d (%.1f%%)\n", - cell_type.c_str(), 100 * (float)failed / (float)num_iter, + ID::str(cell_type).c_str(), 100 * (float)failed / (float)num_iter, worst_abs, 100 * worst_rel); } }