diff --git a/frontends/aiger2/xaiger.cc b/frontends/aiger2/xaiger.cc index 6cb15350f..27f5f592b 100644 --- a/frontends/aiger2/xaiger.cc +++ b/frontends/aiger2/xaiger.cc @@ -37,6 +37,14 @@ IdString read_idstring(std::istream &f) return RTLIL::escape_id(str); } +IdString resolve_sym(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; +} + struct Xaiger2Frontend : public Frontend { Xaiger2Frontend() : Frontend("xaiger2", "(experimental) read XAIGER file") { diff --git a/frontends/ast/ast_binding.cc b/frontends/ast/ast_binding.cc index c20d1df4d..6544a544c 100644 --- a/frontends/ast/ast_binding.cc +++ b/frontends/ast/ast_binding.cc @@ -34,14 +34,14 @@ AST::Binding::Binding(RTLIL::IdString target_type, } std::string -AST::Binding::describe() const +AST::Binding::describe(const RTLIL::Design *design) const { std::ostringstream oss; oss << "directive to bind " << ast_node->str - << " to " << target_name.str(); + << " to " << design->twines.str(target_name); if (!target_type.empty()) oss << " (target type: " - << target_type.str() + << design->twines.str(target_type) << ")"; return oss.str(); } diff --git a/frontends/ast/ast_binding.h b/frontends/ast/ast_binding.h index 641497d52..c75c8c065 100644 --- a/frontends/ast/ast_binding.h +++ b/frontends/ast/ast_binding.h @@ -45,7 +45,7 @@ namespace AST RTLIL::IdString target_name, const AstNode &cell); - std::string describe() const override; + std::string describe(const RTLIL::Design *design) const override; private: // The syntax-level representation of the cell to be bound. diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 220c317ec..22701813e 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -57,7 +57,7 @@ static bool read_next_line(char *&buffer, size_t &buffer_size, int &line_count, } } -static std::pair wideports_split(std::string name) +static std::pair wideports_split(std::string name) { int pos = -1; @@ -78,10 +78,10 @@ static std::pair wideports_split(std::string name) } if (pos >= 0) - return std::pair("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1)); + return std::pair("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1)); failed: - return std::pair(RTLIL::IdString(), 0); + return std::pair(std::string(), 0); } void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports) @@ -115,11 +115,11 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool } } - IdString wire_id = RTLIL::escape_id(wire_name); - Wire *wire = module->wire(wire_id); + IdString wire_ref = design->twines.add(RTLIL::escape_id(wire_name)); + Wire *wire = module->wire(wire_ref); if (wire == nullptr) - wire = module->addWire(wire_id); + wire = module->addWire(wire_ref); return wire; }; @@ -167,11 +167,12 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (module != nullptr) goto error; module = new RTLIL::Module; + module->design = design; lastcell = nullptr; char *name = strtok(NULL, " \t\r\n"); if (name == nullptr) goto error; - module->name = RTLIL::escape_id(name); + module->name = design->twines.add(RTLIL::escape_id(name)); obj_attributes = &module->attributes; obj_parameters = nullptr; if (design->module(module->name)) @@ -202,8 +203,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool wire->port_output = !isinput; for (int i = 0; i < width; i++) { - RTLIL::IdString other_name = name.str() + stringf("[%d]", i); - RTLIL::Wire *other_wire = module->wire(other_name); + std::string other_name = design->twines.str(name) + stringf("[%d]", i); + IdString other_ref = design->twines.find(other_name); + RTLIL::Wire *other_wire = module->wire(other_ref); if (other_wire) { other_wire->port_input = false; other_wire->port_output = false; @@ -232,9 +234,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool for (auto cell : remove_cells) module->remove(cell); - Wire *true_wire = module->wire(ID($true)); - Wire *false_wire = module->wire(ID($false)); - Wire *undef_wire = module->wire(ID($undef)); + Wire *true_wire = module->wire(ID::lookup("$true")); + Wire *false_wire = module->wire(ID::lookup("$false")); + Wire *undef_wire = module->wire(ID::lookup("$undef")); if (true_wire != nullptr) module->rename(true_wire, stringf("$true$%d", ++blif_maxnum)); @@ -271,20 +273,22 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool char *p; while ((p = strtok(NULL, " \t\r\n")) != NULL) { - RTLIL::IdString wire_name(stringf("\\%s", p)); - RTLIL::Wire *wire = module->wire(wire_name); + std::string wire_name_str = stringf("\\%s", p); + IdString wire_ref = design->twines.add(std::string{wire_name_str}); + RTLIL::Wire *wire = module->wire(wire_ref); if (wire == nullptr) - wire = module->addWire(wire_name); + wire = module->addWire(wire_ref); if (!strcmp(cmd, ".inputs")) wire->port_input = true; else wire->port_output = true; if (wideports) { - std::pair wp = wideports_split(p); + std::pair wp = wideports_split(p); if (!wp.first.empty() && wp.second >= 0) { - wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second + 1); - wideports_cache[wp.first].second = !strcmp(cmd, ".inputs"); + IdString wp_ref = design->twines.add(std::string(wp.first)); + wideports_cache[wp_ref].first = std::max(wideports_cache[wp_ref].first, wp.second + 1); + wideports_cache[wp_ref].second = !strcmp(cmd, ".inputs"); } } } @@ -312,7 +316,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (!strcmp(cmd, ".attr") || !strcmp(cmd, ".param")) { char *n = strtok(NULL, " \t\r\n"); char *v = strtok(NULL, "\r\n"); - IdString id_n = RTLIL::escape_id(n); + IdString id_n = design->twines.add(RTLIL::escape_id(n)); Const const_v; if (v[0] == '"') { std::string str(v+1); @@ -372,7 +376,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool cell = module->addDlatchGate(NEW_ID, blif_wire(clock), blif_wire(d), blif_wire(q), false); else { no_latch_clock: - if (dff_name.empty()) { + if (dff_name == IdString::Null) { cell = module->addFfGate(NEW_ID, blif_wire(d), blif_wire(q)); } else { cell = module->addCell(NEW_ID, dff_name); @@ -393,9 +397,9 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (p == NULL) goto error; - IdString celltype = RTLIL::escape_id(p); + IdString celltype = design->twines.add(RTLIL::escape_id(p)); RTLIL::Cell *cell = module->addCell(NEW_ID, celltype); - RTLIL::Module *cell_mod = design->module(celltype); + RTLIL::Module *cell_mod = design->module(cell->type); dict> cell_wideports_cache; @@ -407,13 +411,17 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool *(q++) = 0; if (wideports) { - std::pair wp = wideports_split(p); - if (wp.first.empty()) - cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec()); - else - cell_wideports_cache[wp.first][wp.second] = blif_wire(q); + std::pair wp = wideports_split(p); + if (wp.first.empty()) { + IdString port_ref = design->twines.add(RTLIL::escape_id(p)); + cell->setPort(port_ref, *q ? blif_wire(q) : SigSpec()); + } else { + IdString wp_ref = design->twines.add(std::string(wp.first)); + cell_wideports_cache[wp_ref][wp.second] = blif_wire(q); + } } else { - cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec()); + IdString port_ref = design->twines.add(RTLIL::escape_id(p)); + cell->setPort(port_ref, *q ? blif_wire(q) : SigSpec()); } } @@ -686,7 +694,7 @@ struct BlifFrontend : public Frontend { } extra_args(f, filename, args, argidx); - parse_blif(design, *f, "", true, sop_mode, wideports); + parse_blif(design, *f, IdString::Null, true, sop_mode, wideports); } } BlifFrontend; diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 0fac902b5..b34910269 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -274,14 +274,14 @@ Const json_parse_attr_param_value(JsonNode *node) return value; } -void json_parse_attr_param(dict &results, JsonNode *node) +void json_parse_attr_param(RTLIL::Design *design, dict &results, JsonNode *node) { if (node->type != 'D') log_error("JSON attributes or parameters node is not a dictionary.\n"); for (auto it : node->data_dict) { - IdString key = RTLIL::escape_id(it.first.c_str()); + IdString key = design->twines.add(RTLIL::escape_id(it.first.c_str())); Const value = json_parse_attr_param_value(it.second); results[key] = value; } @@ -292,7 +292,8 @@ void json_import(Design *design, string &modname, JsonNode *node) log("Importing module %s from JSON tree.\n", modname); Module *module = new RTLIL::Module; - module->name = RTLIL::escape_id(modname.c_str()); + module->design = design; + module->name = design->twines.add(RTLIL::escape_id(modname)); if (design->module(module->name)) log_error("Re-definition of module %s.\n", module->name.unescape()); @@ -300,10 +301,10 @@ void json_import(Design *design, string &modname, JsonNode *node) design->add(module); if (node->data_dict.count("attributes")) - json_parse_attr_param(module->attributes, node->data_dict.at("attributes")); + json_parse_attr_param(design, module->attributes, node->data_dict.at("attributes")); if (node->data_dict.count("parameter_default_values")) - json_parse_attr_param(module->parameter_default_values, node->data_dict.at("parameter_default_values")); + json_parse_attr_param(design, module->parameter_default_values, node->data_dict.at("parameter_default_values")); dict signal_bits; @@ -316,31 +317,31 @@ void json_import(Design *design, string &modname, JsonNode *node) for (int port_id = 1; port_id <= GetSize(ports_node->data_dict_keys); port_id++) { - IdString port_name = RTLIL::escape_id(ports_node->data_dict_keys[port_id-1].c_str()); + IdString port_ref = design->twines.add(RTLIL::escape_id(ports_node->data_dict_keys[port_id-1])); JsonNode *port_node = ports_node->data_dict.at(ports_node->data_dict_keys[port_id-1]); if (port_node->type != 'D') - log_error("JSON port node '%s' is not a dictionary.\n", port_name.unescape()); + log_error("JSON port node '%s' is not a dictionary.\n", PooledName(design, port_ref).unescape()); if (port_node->data_dict.count("direction") == 0) - log_error("JSON port node '%s' has no direction attribute.\n", port_name.unescape()); + log_error("JSON port node '%s' has no direction attribute.\n", PooledName(design, port_ref).unescape()); if (port_node->data_dict.count("bits") == 0) - log_error("JSON port node '%s' has no bits attribute.\n", port_name.unescape()); + log_error("JSON port node '%s' has no bits attribute.\n", PooledName(design, port_ref).unescape()); JsonNode *port_direction_node = port_node->data_dict.at("direction"); JsonNode *port_bits_node = port_node->data_dict.at("bits"); if (port_direction_node->type != 'S') - log_error("JSON port node '%s' has non-string direction attribute.\n", port_name.unescape()); + log_error("JSON port node '%s' has non-string direction attribute.\n", PooledName(design, port_ref).unescape()); if (port_bits_node->type != 'A') - log_error("JSON port node '%s' has non-array bits attribute.\n", port_name.unescape()); + log_error("JSON port node '%s' has non-array bits attribute.\n", PooledName(design, port_ref).unescape()); - Wire *port_wire = module->wire(port_name); + Wire *port_wire = module->wire(port_ref); if (port_wire == nullptr) - port_wire = module->addWire(port_name, GetSize(port_bits_node->data_array)); + port_wire = module->addWire(port_ref, GetSize(port_bits_node->data_array)); if (port_node->data_dict.count("upto") != 0) { JsonNode *val = port_node->data_dict.at("upto"); @@ -370,7 +371,7 @@ void json_import(Design *design, string &modname, JsonNode *node) port_wire->port_input = true; port_wire->port_output = true; } else - log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", port_name.unescape(), port_direction_node->data_string); + log_error("JSON port node '%s' has invalid '%s' direction attribute.\n", PooledName(design, port_ref).unescape(), port_direction_node->data_string); port_wire->port_id = port_id; @@ -390,7 +391,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->connect(sigbit, State::Sz); else log_error("JSON port node '%s' has invalid '%s' bit string value on bit %d.\n", - port_name.unescape(), bitval_node->data_string.c_str(), i); + PooledName(design, port_ref).unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -405,7 +406,7 @@ void json_import(Design *design, string &modname, JsonNode *node) signal_bits[bitidx] = sigbit; } } else - log_error("JSON port node '%s' has invalid bit value on bit %d.\n", port_name.unescape(), i); + log_error("JSON port node '%s' has invalid bit value on bit %d.\n", PooledName(design, port_ref).unescape(), i); } } @@ -421,24 +422,24 @@ void json_import(Design *design, string &modname, JsonNode *node) for (auto &net : netnames_node->data_dict) { - IdString net_name = RTLIL::escape_id(net.first.c_str()); + IdString net_ref = design->twines.add(RTLIL::escape_id(net.first)); JsonNode *net_node = net.second; if (net_node->type != 'D') - log_error("JSON netname node '%s' is not a dictionary.\n", net_name.unescape()); + log_error("JSON netname node '%s' is not a dictionary.\n", PooledName(design, net_ref).unescape()); if (net_node->data_dict.count("bits") == 0) - log_error("JSON netname node '%s' has no bits attribute.\n", net_name.unescape()); + log_error("JSON netname node '%s' has no bits attribute.\n", PooledName(design, net_ref).unescape()); JsonNode *bits_node = net_node->data_dict.at("bits"); if (bits_node->type != 'A') - log_error("JSON netname node '%s' has non-array bits attribute.\n", net_name.unescape()); + log_error("JSON netname node '%s' has non-array bits attribute.\n", PooledName(design, net_ref).unescape()); - Wire *wire = module->wire(net_name); + Wire *wire = module->wire(net_ref); if (wire == nullptr) - wire = module->addWire(net_name, GetSize(bits_node->data_array)); + wire = module->addWire(net_ref, GetSize(bits_node->data_array)); if (net_node->data_dict.count("upto") != 0) { JsonNode *val = net_node->data_dict.at("upto"); @@ -468,7 +469,7 @@ void json_import(Design *design, string &modname, JsonNode *node) module->connect(sigbit, State::Sz); else log_error("JSON netname node '%s' has invalid '%s' bit string value on bit %d.\n", - net_name.unescape(), bitval_node->data_string.c_str(), i); + PooledName(design, net_ref).unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -479,11 +480,11 @@ void json_import(Design *design, string &modname, JsonNode *node) signal_bits[bitidx] = sigbit; } } else - log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", net_name.unescape(), i); + log_error("JSON netname node '%s' has invalid bit value on bit %d.\n", PooledName(design, net_ref).unescape(), i); } if (net_node->data_dict.count("attributes")) - json_parse_attr_param(wire->attributes, net_node->data_dict.at("attributes")); + json_parse_attr_param(design, wire->attributes, net_node->data_dict.at("attributes")); } } @@ -496,39 +497,39 @@ void json_import(Design *design, string &modname, JsonNode *node) for (auto &cell_node_it : cells_node->data_dict) { - IdString cell_name = RTLIL::escape_id(cell_node_it.first.c_str()); + IdString cell_ref = design->twines.add(RTLIL::escape_id(cell_node_it.first)); JsonNode *cell_node = cell_node_it.second; if (cell_node->type != 'D') - log_error("JSON cells node '%s' is not a dictionary.\n", cell_name.unescape()); + log_error("JSON cells node '%s' is not a dictionary.\n", PooledName(design, cell_ref).unescape()); if (cell_node->data_dict.count("type") == 0) - log_error("JSON cells node '%s' has no type attribute.\n", cell_name.unescape()); + log_error("JSON cells node '%s' has no type attribute.\n", PooledName(design, cell_ref).unescape()); JsonNode *type_node = cell_node->data_dict.at("type"); if (type_node->type != 'S') - log_error("JSON cells node '%s' has a non-string type.\n", cell_name.unescape()); + log_error("JSON cells node '%s' has a non-string type.\n", PooledName(design, cell_ref).unescape()); - IdString cell_type = RTLIL::escape_id(type_node->data_string.c_str()); + IdString cell_type = design->twines.add(RTLIL::escape_id(type_node->data_string)); - Cell *cell = module->addCell(cell_name, cell_type); + Cell *cell = module->addCell(cell_ref, cell_type); if (cell_node->data_dict.count("connections") == 0) - log_error("JSON cells node '%s' has no connections attribute.\n", cell_name.unescape()); + log_error("JSON cells node '%s' has no connections attribute.\n", PooledName(design, cell_ref).unescape()); JsonNode *connections_node = cell_node->data_dict.at("connections"); if (connections_node->type != 'D') - log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", cell_name.unescape()); + log_error("JSON cells node '%s' has non-dictionary connections attribute.\n", PooledName(design, cell_ref).unescape()); for (auto &conn_it : connections_node->data_dict) { - IdString conn_name = RTLIL::escape_id(conn_it.first.c_str()); + IdString conn_ref = design->twines.add(RTLIL::escape_id(conn_it.first)); JsonNode *conn_node = conn_it.second; if (conn_node->type != 'A') - log_error("JSON cells node '%s' connection '%s' is not an array.\n", cell_name.unescape(), conn_name.unescape()); + log_error("JSON cells node '%s' connection '%s' is not an array.\n", PooledName(design, cell_ref).unescape(), PooledName(design, conn_ref).unescape()); SigSpec sig; @@ -547,7 +548,7 @@ void json_import(Design *design, string &modname, JsonNode *node) sig.append(State::Sz); else log_error("JSON cells node '%s' connection '%s' has invalid '%s' bit string value on bit %d.\n", - cell_name.unescape(), conn_name.unescape(), bitval_node->data_string.c_str(), i); + PooledName(design, cell_ref).unescape(), PooledName(design, conn_ref).unescape(), bitval_node->data_string.c_str(), i); } else if (bitval_node->type == 'N') { int bitidx = bitval_node->data_number; @@ -556,18 +557,18 @@ void json_import(Design *design, string &modname, JsonNode *node) sig.append(signal_bits.at(bitidx)); } else log_error("JSON cells node '%s' connection '%s' has invalid bit value on bit %d.\n", - cell_name.unescape(), conn_name.unescape(), i); + PooledName(design, cell_ref).unescape(), PooledName(design, conn_ref).unescape(), i); } - cell->setPort(conn_name, sig); + cell->setPort(conn_ref, sig); } if (cell_node->data_dict.count("attributes")) - json_parse_attr_param(cell->attributes, cell_node->data_dict.at("attributes")); + json_parse_attr_param(design, cell->attributes, cell_node->data_dict.at("attributes")); if (cell_node->data_dict.count("parameters")) - json_parse_attr_param(cell->parameters, cell_node->data_dict.at("parameters")); + json_parse_attr_param(design, cell->parameters, cell_node->data_dict.at("parameters")); } } @@ -580,27 +581,27 @@ void json_import(Design *design, string &modname, JsonNode *node) for (auto &memory_node_it : memories_node->data_dict) { - IdString memory_name = RTLIL::escape_id(memory_node_it.first.c_str()); JsonNode *memory_node = memory_node_it.second; RTLIL::Memory *mem = new RTLIL::Memory; - mem->name = memory_name; + mem->name = design->twines.add(RTLIL::escape_id(memory_node_it.first)); + mem->module = module; if (memory_node->type != 'D') - log_error("JSON memory node '%s' is not a dictionary.\n", memory_name.unescape()); + log_error("JSON memory node '%s' is not a dictionary.\n", mem->name.unescape()); if (memory_node->data_dict.count("width") == 0) - log_error("JSON memory node '%s' has no width attribute.\n", memory_name.unescape()); + log_error("JSON memory node '%s' has no width attribute.\n", mem->name.unescape()); JsonNode *width_node = memory_node->data_dict.at("width"); if (width_node->type != 'N') - log_error("JSON memory node '%s' has a non-number width.\n", memory_name.unescape()); + log_error("JSON memory node '%s' has a non-number width.\n", mem->name.unescape()); mem->width = width_node->data_number; if (memory_node->data_dict.count("size") == 0) - log_error("JSON memory node '%s' has no size attribute.\n", memory_name.unescape()); + log_error("JSON memory node '%s' has no size attribute.\n", mem->name.unescape()); JsonNode *size_node = memory_node->data_dict.at("size"); if (size_node->type != 'N') - log_error("JSON memory node '%s' has a non-number size.\n", memory_name.unescape()); + log_error("JSON memory node '%s' has a non-number size.\n", mem->name.unescape()); mem->size = size_node->data_number; mem->start_offset = 0; @@ -611,7 +612,7 @@ void json_import(Design *design, string &modname, JsonNode *node) } if (memory_node->data_dict.count("attributes")) - json_parse_attr_param(mem->attributes, memory_node->data_dict.at("attributes")); + json_parse_attr_param(design, mem->attributes, memory_node->data_dict.at("attributes")); module->memories[mem->name] = mem; } diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 76c1ecca3..291900b0e 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -47,11 +47,13 @@ static RTLIL::SigSpec parse_func_identifier(RTLIL::Module *module, const char *& return *(expr++) == '0' ? RTLIL::State::S0 : RTLIL::State::S1; std::string id = RTLIL::escape_id(std::string(expr, id_len)); - if (!module->wires_.count(id)) + IdString wire_ref = module->design->twines.find(id); + RTLIL::Wire *w = module->wire(wire_ref); + if (!w) log_error("Can't resolve wire name %s in %s.\n", RTLIL::unescape_id(id), module); expr += id_len; - return module->wires_.at(id); + return w; } static bool parse_func_reduce(RTLIL::Module *module, std::vector &stack, token_t next_token) @@ -196,8 +198,10 @@ static void create_latch_ff_wires(RTLIL::Module *module, const LibertyAst *node) static std::pair find_latch_ff_wires(RTLIL::Module *module, const LibertyAst *node) { - auto* iq_wire = module->wire(RTLIL::escape_id(node->args.at(0))); - auto* iqn_wire = module->wire(RTLIL::escape_id(node->args.at(1))); + IdString iq_ref = module->design->twines.find(RTLIL::escape_id(node->args.at(0))); + IdString iqn_ref = module->design->twines.find(RTLIL::escape_id(node->args.at(1))); + auto* iq_wire = module->wire(iq_ref); + auto* iqn_wire = module->wire(iqn_ref); log_assert(iq_wire && iqn_wire); return std::make_pair(iq_wire, iqn_wire); } @@ -239,7 +243,7 @@ static void create_ff(RTLIL::Module *module, const LibertyAst *node) module->addNotGate(NEW_ID, q_sig, out_sig); } - RTLIL::Cell* cell = module->addCell(NEW_ID, ""); + RTLIL::Cell* cell = module->addCell(NEW_ID, IdString::Null); cell->setPort(ID::D, data_sig); cell->setPort(ID::Q, q_sig); cell->setPort(ID::C, clk_sig); @@ -505,8 +509,10 @@ struct LibertyFrontend : public Frontend { parse_type_map(type_map, cell); RTLIL::Module *module = new RTLIL::Module; + module->design = design; std::string cell_name = RTLIL::escape_id(cell->args.at(0)); - module->name = cell_name; + IdString cell_name_ref = design->twines.add(std::string{cell_name}); + module->name = cell_name_ref; if (flag_lib) module->set_bool_attribute(ID::blackbox); @@ -519,7 +525,7 @@ struct LibertyFrontend : public Frontend { module->attributes[ID::area] = area->value; for (auto &attr : attributes) - module->attributes[attr] = 1; + module->attributes[design->twines.add(std::string(attr))] = 1; bool simple_comb_cell = true, has_outputs = false; @@ -626,7 +632,8 @@ struct LibertyFrontend : public Frontend { if (flag_lib && dir->value == "internal") continue; - RTLIL::Wire *wire = module->wires_.at(RTLIL::escape_id(node->args.at(0))); + IdString wire_ref = module->design->twines.find(RTLIL::escape_id(node->args.at(0))); + RTLIL::Wire *wire = module->wire(wire_ref); log_assert(wire); const LibertyAst *capacitance = node->find("capacitance"); @@ -710,8 +717,8 @@ struct LibertyFrontend : public Frontend { } } - if (design->has(cell_name)) { - Module *existing_mod = design->module(cell_name); + if (design->has(cell_name_ref)) { + Module *existing_mod = design->module(cell_name_ref); if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute(ID::blackbox)) { log_error("Re-definition of cell/module %s!\n", RTLIL::unescape_id(cell_name)); } else if (flag_nooverwrite) { diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc index 418837cf9..4dd32460e 100644 --- a/frontends/rtlil/rtlil_frontend.cc +++ b/frontends/rtlil/rtlil_frontend.cc @@ -491,6 +491,136 @@ struct RTLILFrontendWorker { expect_eol(); } + bool static_ids_match(const std::vector &ordered_ids) + { + for (size_t id : ordered_ids) { + if (id >= STATIC_TWINE_END) + continue; + const TwineDesc &desc = twine_descs.at(id); + IdString found; + if (desc.kind == TwineDesc::Leaf) + found = design->twines.find(Twine{Twine::Leaf{desc.text}}); + else + found = design->twines.find(Twine{Twine::Suffix{ + IdString(desc.parent), desc.text}}); + if (found == IdString::Null || found.untag().raw() != id) + return false; + } + return true; + } + + IdString resolve_file_twine(size_t id, bool is_public = false) + { + return materialize_file_twine(id).tag(is_public); + } + + IdString materialize_file_twine(size_t id) + { + auto rit = twine_remap.find(id); + if (rit != twine_remap.end()) + return rit->second; + auto dit = twine_descs.find(id); + if (dit == twine_descs.end()) { + if (id < STATIC_TWINE_END) + return IdString(id); + error("Unknown twine reference @%zu at line %d", id, line_num); + } + TwineDesc &desc = dit->second; + if (desc.materializing) + error("Cyclic twine reference @%zu at line %d", id, line_num); + desc.materializing = true; + IdString ref; + switch (desc.kind) { + case TwineDesc::Leaf: + ref = design->twines.add(Twine::Leaf{desc.text}); + break; + case TwineDesc::Suffix: + ref = design->twines.add(Twine::Suffix{ + materialize_file_twine(desc.parent), + desc.text}); + break; + } + desc.materializing = false; + twine_remap[id] = ref; + return ref; + } + + std::optional try_parse_twine_handle() + { + bool is_public; + size_t prefix = IdString::handle_token_prefix(line, is_public); + if (prefix == 0) + return std::nullopt; + line = line.substr(prefix); + return resolve_file_twine(parse_integer(), is_public); + } + + std::optional try_parse_twine() + { + if (std::optional handle = try_parse_twine_handle()) + return handle; + std::optional id = try_parse_id(); + if (!id) + return std::nullopt; + return design->twines.add(std::move(*id)); + } + + IdString parse_twine() + { + std::optional t = try_parse_twine(); + if (!t) + error("Expected twine reference or ID, got `%s'.", error_token()); + return *t; + } + + void parse_twines() + { + expect_eol(); + while (true) { + if (try_parse_keyword("end")) + break; + if (try_parse_keyword("leaf")) { + size_t file_id = parse_integer(); + TwineDesc &desc = twine_descs[file_id]; + desc.kind = TwineDesc::Leaf; + desc.text = parse_string(); + expect_eol(); + continue; + } + if (try_parse_keyword("suffix")) { + size_t file_id = parse_integer(); + TwineDesc &desc = twine_descs[file_id]; + desc.kind = TwineDesc::Suffix; + desc.parent = parse_integer(); + desc.text = parse_string(); + expect_eol(); + continue; + } + error("Expected `leaf` or `suffix` inside twines block, got `%s'.", + error_token()); + } + std::vector ordered_ids; + ordered_ids.reserve(twine_descs.size()); + for (auto &it : twine_descs) + ordered_ids.push_back(it.first); + std::sort(ordered_ids.begin(), ordered_ids.end()); + if (static_ids_match(ordered_ids)) { + std::vector dynamic_ids; + dynamic_ids.reserve(ordered_ids.size()); + for (size_t id : ordered_ids) { + if (id < STATIC_TWINE_END) + twine_descs.erase(id); + else + dynamic_ids.push_back(id); + } + ordered_ids.swap(dynamic_ids); + } + for (size_t id : ordered_ids) + materialize_file_twine(id); + twine_descs.clear(); + expect_eol(); + } + void parse_parameter() { RTLIL::IdString id = parse_id(); diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 2c35b42d5..e037dc214 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -549,9 +549,11 @@ struct VerilogFrontend : public Frontend { for (auto &child : parse_state.current_ast->children) { if (child->type == AST::AST_MODULE) - for (auto &attr : attributes) - if (child->attributes.count(attr) == 0) - child->attributes[attr] = AST::AstNode::mkconst_int(top_loc, 1, false); + for (auto &attr : attributes) { + IdString attr_id = AST::intern_attr_name(attr); + if (child->attributes.count(attr_id) == 0) + child->attributes[attr_id] = AST::AstNode::mkconst_int(top_loc, 1, false); + } } if (flag_nodpi) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index b394ce074..f87c831f1 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -69,10 +69,10 @@ struct ParseState { int port_counter; dict port_stubs; - std::unique_ptr>> attr_list; - dict> default_attr_list; - std::stack>>> attr_list_stack; - std::unique_ptr>> albuf; + std::unique_ptr>> attr_list; + dict> default_attr_list; + std::stack>>> attr_list_stack; + std::unique_ptr>> albuf; std::vector user_type_stack; dict pkg_user_types; std::vector ast_stack; @@ -98,15 +98,15 @@ bool isInLocalScope(const std::string *name); void rewriteGenForDeclInit(AstNode *loop); void ensureAsgnExprAllowed(const parser::location_type loc, bool sv_mode); - const AstNode *addIncOrDecStmt(std::unique_ptr>> stmt_attr, + const AstNode *addIncOrDecStmt(std::unique_ptr>> stmt_attr, std::unique_ptr lhs, - std::unique_ptr>> op_attr, AST::AstNodeType op, + std::unique_ptr>> op_attr, AST::AstNodeType op, parser::location_type loc); std::unique_ptr addIncOrDecExpr(std::unique_ptr lhs, - std::unique_ptr>> attr, + std::unique_ptr>> attr, AST::AstNodeType op, parser::location_type loc, bool undo, bool sv_mode); // add a binary operator assignment statement, e.g., a += b - std::unique_ptr addAsgnBinopStmt(std::unique_ptr>> attr, + std::unique_ptr addAsgnBinopStmt(std::unique_ptr>> attr, std::unique_ptr eq_lhs, AST::AstNodeType op, std::unique_ptr rhs); }; struct ParseMode { @@ -154,17 +154,17 @@ return Location(begin.begin, end.end); } - static void append_attr(AstNode *ast, std::unique_ptr>> al) + static void append_attr(AstNode *ast, std::unique_ptr>> al) { for (auto &it : *al) { - ast->attributes[it.first] = std::move(it.second); + ast->attributes[AST::intern_attr_name(it.first)] = std::move(it.second); } } - static void append_attr_clone(AstNode *ast, std::unique_ptr>> &al) + static void append_attr_clone(AstNode *ast, std::unique_ptr>> &al) { for (auto &it : *al) { - ast->attributes[it.first] = it.second->clone(); + ast->attributes[AST::intern_attr_name(it.first)] = it.second->clone(); } } @@ -361,9 +361,9 @@ } // add a pre/post-increment/decrement statement - const AstNode *ParseState::addIncOrDecStmt(std::unique_ptr>> stmt_attr, + const AstNode *ParseState::addIncOrDecStmt(std::unique_ptr>> stmt_attr, std::unique_ptr lhs, - std::unique_ptr>> op_attr, AST::AstNodeType op, + std::unique_ptr>> op_attr, AST::AstNodeType op, Location loc) { auto one = AstNode::mkconst_int(loc, 1, true); @@ -380,7 +380,7 @@ // create a pre/post-increment/decrement expression, and add the corresponding statement std::unique_ptr ParseState::addIncOrDecExpr(std::unique_ptr lhs, - std::unique_ptr>> attr, AST::AstNodeType op, Location loc, bool undo, bool sv_mode) { @@ -397,7 +397,7 @@ } // add a binary operator assignment statement, e.g., a += b - std::unique_ptr ParseState::addAsgnBinopStmt(std::unique_ptr>> attr, + std::unique_ptr ParseState::addAsgnBinopStmt(std::unique_ptr>> attr, std::unique_ptr eq_lhs, AST::AstNodeType op, std::unique_ptr rhs) { Location loc = location_range(eq_lhs->location, rhs->location); @@ -462,7 +462,7 @@ using string_t = std::unique_ptr; using ast_t = std::unique_ptr; - using al_t = std::unique_ptr>>; + using al_t = std::unique_ptr>>; using specify_target_ptr_t = std::unique_ptr; using specify_triple_ptr_t = std::unique_ptr; using specify_rise_fall_ptr_t = std::unique_ptr; @@ -617,7 +617,7 @@ attr: { if (extra->attr_list) extra->attr_list_stack.push(std::move(extra->attr_list)); - extra->attr_list = std::make_unique>>(); + extra->attr_list = std::make_unique>>(); for (auto &it : extra->default_attr_list) (*extra->attr_list)[it.first] = it.second->clone(); } attr_opt { @@ -639,7 +639,7 @@ defattr: DEFATTR_BEGIN { if (extra->attr_list != nullptr) extra->attr_list_stack.push(std::move(extra->attr_list)); - extra->attr_list = std::make_unique>>(); + extra->attr_list = std::make_unique>>(); extra->default_attr_list.clear(); } opt_attr_list { extra->attr_list->swap(extra->default_attr_list); @@ -1302,7 +1302,7 @@ task_func_port: if (!extra->astbuf1) { if (!mode->sv) err_at_loc(@$, "task/function argument direction missing"); - extra->albuf = std::make_unique>>(); + extra->albuf = std::make_unique>>(); extra->astbuf1 = std::make_unique(@$, AST_WIRE); extra->current_wire_rand = false; extra->current_wire_const = false; @@ -2911,7 +2911,7 @@ behavioral_stmt: // we have to undangle it from the stack patch_block_on_stack = true; } else if (outer->get_bool_attribute(ID::full_case)) - (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false); } auto expr = std::make_unique(@$, AST_REDUCE_BOOL, std::move($4)); if (!node) { @@ -2957,22 +2957,22 @@ if_attr: AstNode *context = extra->ast_stack.back(); if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) err_at_loc(@2, "unique0 keyword cannot be used for 'else if' branch."); - (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false); $$ = std::move($1); } | attr TOK_PRIORITY { AstNode *context = extra->ast_stack.back(); if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) err_at_loc(@2, "priority keyword cannot be used for 'else if' branch."); - (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false); $$ = std::move($1); } | attr TOK_UNIQUE { AstNode *context = extra->ast_stack.back(); if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) err_at_loc(@2, "unique keyword cannot be used for 'else if' branch."); - (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); - (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false); $$ = std::move($1); }; @@ -2981,16 +2981,16 @@ case_attr: $$ = std::move($1); } | attr TOK_UNIQUE0 { - (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false); $$ = std::move($1); } | attr TOK_PRIORITY { - (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false); $$ = std::move($1); } | attr TOK_UNIQUE { - (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); - (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::full_case)] = AstNode::mkconst_int(@$, 1, false); + (*$1)[ID::str(ID::parallel_case)] = AstNode::mkconst_int(@$, 1, false); $$ = std::move($1); };