diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 927e7fa1e..a25510578 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -122,7 +122,7 @@ struct BtorWorker string infostr = obj->name.unescape(); if (!srcsym && !print_internal_names && infostr[0] == '$') return ""; if (obj->has_attribute(ID::src)) { - string raw_src = module && module->design ? obj->get_src_attribute(&module->design->src_twines) : std::string(); + string raw_src = module && module->design ? module->design->get_src_attribute(obj) : std::string(); string src = module && module->design ? module->design->resolve_src(raw_src) : raw_src; if (srcsym && infostr[0] == '$') { std::replace(src.begin(), src.end(), ' ', '_'); diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 537d0bb80..e9e33a1f4 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -44,7 +44,7 @@ static const int FIRRTL_MAX_DSH_WIDTH_ERROR = 20; // For historic reasons, this std::string getFileinfo(const RTLIL::AttrObject *design_entity, const RTLIL::Design *design = nullptr) { - std::string src = design ? design_entity->get_src_attribute(&design->src_twines) : std::string(); + std::string src = design ? design->get_src_attribute(design_entity) : std::string(); std::string fileinfo_str = src.empty() ? "" : "@[" + src + "]"; return fileinfo_str; } diff --git a/backends/json/json.cc b/backends/json/json.cc index 0a53e14e1..7550b4df0 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -135,9 +135,9 @@ struct JsonWriter bool first = true; // Emit the typed src field first if present — it lives outside the // attribute dict after the typed-src migration. - if (src_obj && src_obj->src_id() != Twine::Null && design) { + if (src_obj && design && design->obj_src_id(src_obj) != Twine::Null) { f << stringf("\n %s%s: ", for_module ? "" : " ", get_name(RTLIL::ID::src)); - write_parameter_value(RTLIL::Const(src_obj->get_src_attribute(&design->src_twines))); + write_parameter_value(RTLIL::Const(design->get_src_attribute(src_obj))); first = false; } for (auto ¶m : parameters) { diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 7c260b537..f4bbfb1c4 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -37,12 +37,13 @@ void RTLIL_BACKEND::dump_attributes(std::ostream &f, std::string indent, const R // Emit the typed src field first. It is not stored in obj->attributes // — the dict no longer holds ID::src under any circumstance. Backends // that want to materialize the pipe-joined literal pass resolve_src. - if (obj->src_id() != Twine::Null && design) { + if (design && design->obj_src_id(obj) != Twine::Null) { + Twine::Id id = design->obj_src_id(obj); f << stringf("%s" "attribute \\src ", indent); if (resolve_src) { - dump_const(f, RTLIL::Const(design->src_twines.flatten(obj->src_id()))); + dump_const(f, RTLIL::Const(design->src_twines.flatten(id))); } else { - dump_const(f, RTLIL::Const(TwinePool::format_ref(obj->src_id()))); + dump_const(f, RTLIL::Const(TwinePool::format_ref(id))); } f << stringf("\n"); } diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 38ffe61b6..fe1bc4659 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1114,7 +1114,7 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast) return; const auto &loc = ast->location; if (!loc.begin.filename || loc.begin.filename->empty()) { - obj->set_src_attribute(¤t_module->design->src_twines, ast->loc_string()); + current_module->design->set_src_attribute(obj, ast->loc_string()); return; } // Split filename and per-location tail so the filename interns once @@ -1129,8 +1129,8 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast) loc.end.line, loc.end.column); Twine::Id suffix_id = pool->intern_suffix(file_id, tail); pool->release(file_id); // suffix internally holds a ref now - obj->set_src_id(pool, suffix_id); - pool->release(suffix_id); // set_src_id retained on obj's behalf + current_module->design->obj_set_src_id(obj, suffix_id); + pool->release(suffix_id); // obj_set_src_id retained on obj's behalf } static bool param_has_no_default(const AstNode* param) { diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 3e808c03e..5e81cab8a 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -169,7 +169,7 @@ static void check_unique_id(RTLIL::Module *module, RTLIL::IdString id, auto already_exists = [&](const RTLIL::AttrObject *existing, const char *existing_kind) { std::string src; if (module->design) - src = existing->get_src_attribute(&module->design->src_twines); + src = module->design->get_src_attribute(existing); std::string location_str = "earlier"; if (!src.empty()) location_str = "at " + src; diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index fb704dfa7..4354f0730 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -288,9 +288,9 @@ void json_parse_attr_param(dict &results, JsonNode *node) } // AttrObject-aware overload: extracts ID::src and routes it to the typed -// src_id_ field via set_src_attribute. Other keys still land in the -// attributes dict via the generic path. -void json_parse_attributes(TwinePool *pool, RTLIL::AttrObject *obj, JsonNode *node) +// meta-vector slot via Design::set_src_attribute. Other keys still land +// in the attributes dict via the generic path. +void json_parse_attributes(RTLIL::Design *design, RTLIL::AttrObject *obj, JsonNode *node) { if (node->type != 'D') log_error("JSON attributes or parameters node is not a dictionary.\n"); @@ -300,7 +300,7 @@ void json_parse_attributes(TwinePool *pool, RTLIL::AttrObject *obj, JsonNode *no IdString key = RTLIL::escape_id(it.first.c_str()); Const value = json_parse_attr_param_value(it.second); if (key == ID::src && (value.flags & RTLIL::CONST_FLAG_STRING)) - obj->set_src_attribute(pool, value.decode_string()); + design->set_src_attribute(obj, value.decode_string()); else obj->attributes[key] = value; } @@ -319,7 +319,7 @@ void json_import(Design *design, string &modname, JsonNode *node) design->add(module); if (node->data_dict.count("attributes")) - json_parse_attributes(&design->src_twines, module, node->data_dict.at("attributes")); + json_parse_attributes(design, module, 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")); @@ -502,7 +502,7 @@ void json_import(Design *design, string &modname, JsonNode *node) } if (net_node->data_dict.count("attributes")) - json_parse_attributes(&design->src_twines, wire, net_node->data_dict.at("attributes")); + json_parse_attributes(design, wire, net_node->data_dict.at("attributes")); } } @@ -583,7 +583,7 @@ void json_import(Design *design, string &modname, JsonNode *node) } if (cell_node->data_dict.count("attributes")) - json_parse_attributes(&design->src_twines, cell, cell_node->data_dict.at("attributes")); + json_parse_attributes(design, cell, 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")); @@ -631,7 +631,7 @@ void json_import(Design *design, string &modname, JsonNode *node) } if (memory_node->data_dict.count("attributes")) - json_parse_attributes(&design->src_twines, mem, memory_node->data_dict.at("attributes")); + json_parse_attributes(design, mem, memory_node->data_dict.at("attributes")); module->memories[mem->name] = mem; } diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc index 7b0eedc6b..9160204ea 100644 --- a/frontends/rtlil/rtlil_frontend.cc +++ b/frontends/rtlil/rtlil_frontend.cc @@ -452,7 +452,7 @@ struct RTLILFrontendWorker { current_module->attributes = std::move(attrbuf); } else { design->add(current_module); - current_module->absorb_attrs(&design->src_twines, std::move(attrbuf)); + current_module->absorb_attrs(std::move(attrbuf)); } while (true) @@ -666,7 +666,7 @@ struct RTLILFrontendWorker { error("Unexpected wire option: %s", error_token()); } - wire->absorb_attrs(&design->src_twines, std::move(attrbuf)); + wire->absorb_attrs(std::move(attrbuf)); wire->width = width; wire->upto = upto; wire->start_offset = start_offset; @@ -681,7 +681,7 @@ struct RTLILFrontendWorker { { RTLIL::Memory *memory = new RTLIL::Memory; memory->module = current_module; - memory->absorb_attrs(&design->src_twines, std::move(attrbuf)); + memory->absorb_attrs(std::move(attrbuf)); int width = 1; int start_offset = 0; @@ -749,7 +749,7 @@ struct RTLILFrontendWorker { error("RTLIL error: redefinition of cell %s.", cell_name); } RTLIL::Cell *cell = current_module->addCell(cell_name, cell_type); - cell->absorb_attrs(&design->src_twines, std::move(attrbuf)); + cell->absorb_attrs(std::move(attrbuf)); while (true) { @@ -839,7 +839,7 @@ struct RTLILFrontendWorker { { RTLIL::SwitchRule *rule = new RTLIL::SwitchRule; rule->signal = parse_sigspec(); - rule->absorb_attrs(&design->src_twines, std::move(attrbuf)); + rule->absorb_attrs(std::move(attrbuf)); switch_stack.back()->push_back(rule); expect_eol(); @@ -856,7 +856,7 @@ struct RTLILFrontendWorker { expect_keyword("case"); RTLIL::CaseRule *case_rule = new RTLIL::CaseRule; - case_rule->absorb_attrs(&design->src_twines, std::move(attrbuf)); + case_rule->absorb_attrs(std::move(attrbuf)); rule->cases.push_back(case_rule); switch_stack.push_back(&case_rule->switches); case_stack.push_back(case_rule); @@ -890,7 +890,7 @@ struct RTLILFrontendWorker { error("RTLIL error: redefinition of process %s.", proc_name); } RTLIL::Process *proc = current_module->addProcess(std::move(proc_name)); - proc->absorb_attrs(&design->src_twines, std::move(attrbuf)); + proc->absorb_attrs(std::move(attrbuf)); switch_stack.clear(); switch_stack.push_back(&proc->root_case.switches); @@ -939,13 +939,18 @@ struct RTLILFrontendWorker { break; RTLIL::MemWriteAction act; - act.absorb_attrs(&design->src_twines, std::move(attrbuf)); + act.module = current_module; + design->absorb_attrs(&act, std::move(attrbuf)); act.memid = parse_id(); act.address = parse_sigspec(); act.data = parse_sigspec(); act.enable = parse_sigspec(); act.priority_mask = parse_const(); - rule->mem_write_actions.push_back(std::move(act)); + rule->mem_write_actions.push_back(act); + // meta_idx_ is a weak ref — drop ours so the pushed copy + // in the vector is the sole holder. Process::~Process + // walks the tree to actually release. + act.meta_idx_ = RTLIL::AttrObject::NO_META; expect_eol(); } // The old parser allowed dangling attributes before a "sync" to carry through diff --git a/kernel/ff.cc b/kernel/ff.cc index 1de3b9ae5..d60e440f7 100644 --- a/kernel/ff.cc +++ b/kernel/ff.cc @@ -770,13 +770,13 @@ Cell *FfData::emit() { if (!src_twine.empty() && cell->module && cell->module->design) { TwinePool *dst_pool = &cell->module->design->src_twines; if (src_twine.pool() == dst_pool) { - cell->set_src_id(dst_pool, src_twine.id()); + cell->set_src_id(src_twine.id()); } else { // Cross-pool (unusual — FfData migrated between // designs). Rebuild the twine structure into the // destination pool, then adopt that fresh id. Twine::Id migrated = dst_pool->copy_from(*src_twine.pool(), src_twine.id()); - cell->set_src_id(dst_pool, migrated); + cell->set_src_id(migrated); dst_pool->release(migrated); } } diff --git a/kernel/mem.cc b/kernel/mem.cc index 6d3bba551..4bf345cac 100644 --- a/kernel/mem.cc +++ b/kernel/mem.cc @@ -895,8 +895,9 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) { // "@N" parse_ref path), and there's no flatten → re-intern → pipe- // leaf round-trip on cells whose src is a Concat node. TwinePool *src_pool = (module && module->design) ? &module->design->src_twines : nullptr; - std::string mem_src = (src_pool && src_id_ != Twine::Null) ? - TwinePool::format_ref(src_id_) : std::string(); + Twine::Id mem_src_id = (module && module->design) ? module->design->obj_src_id(this) : Twine::Null; + std::string mem_src = (src_pool && mem_src_id != Twine::Null) ? + TwinePool::format_ref(mem_src_id) : std::string(); Cell *c; @@ -1004,8 +1005,8 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) { FfData ff(module, initvals, name); // Carry mem's src into the ff via the OwnedTwine handle — same // pool, direct id retain. emit() transfers verbatim. - if (src_pool && src_id_ != Twine::Null) - ff.src_twine = OwnedTwine(src_pool, src_id_); + if (src_pool && mem_src_id != Twine::Null) + ff.src_twine = OwnedTwine(src_pool, mem_src_id); ff.width = GetSize(port.data); ff.has_clk = true; ff.sig_clk = port.clk; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 601d3693e..e6d417d6c 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -914,93 +914,10 @@ RTLIL::Const RTLIL::Const::extract(int offset, int len, RTLIL::State padding) co } #undef check /* check(condition) for Const */ -void RTLIL::AttrObject::set_src_id(TwinePool *pool, Twine::Id id) -{ - log_assert(pool != nullptr); - if (id == src_id_) - return; - if (src_id_ != Twine::Null) - pool->release(src_id_); - src_id_ = id; - if (src_id_ != Twine::Null) - pool->retain(src_id_); -} - -void RTLIL::AttrObject::set_src_attribute(TwinePool *pool, const RTLIL::SrcAttr &src) -{ - if (src.empty()) { - if (src_id_ != Twine::Null) { - log_assert(pool != nullptr); - pool->release(src_id_); - src_id_ = Twine::Null; - } - return; - } - log_assert(pool != nullptr); - Twine::Id new_id = Twine::Null; - if (src.id != Twine::Null) { - // Direct id form — the caller (e.g. `other->src_ref()`) is - // responsible for keeping the slot alive. Retain on our - // behalf. - log_assert(pool->is_alive(src.id) && "set_src_attribute: SrcAttr id points to dead slot"); - new_id = src.id; - pool->retain(new_id); - } else { - // Literal-string form. "@N" → adopt slot directly. Anything - // else → intern as leaf (returns +1). - new_id = TwinePool::parse_ref(src.literal); - if (new_id != Twine::Null) { - log_assert(pool->is_alive(new_id) && "set_src_attribute: @N ref points to dead slot"); - pool->retain(new_id); - } else { - new_id = pool->intern(src.literal); - } - } - if (src_id_ != Twine::Null) - pool->release(src_id_); - src_id_ = new_id; -} - -std::string RTLIL::AttrObject::get_src_attribute(const TwinePool *pool) const -{ - log_assert(pool); - return pool->flatten(src_id_); -} - -void RTLIL::AttrObject::adopt_src_from(TwinePool *pool, const RTLIL::AttrObject *source) -{ - adopt_src_from(pool, source, pool); -} - -void RTLIL::AttrObject::adopt_src_from(TwinePool *dst_pool, - const RTLIL::AttrObject *source, const TwinePool *src_pool) -{ - if (!source || source->src_id() == Twine::Null) { - if (src_id_ != Twine::Null) { - log_assert(dst_pool != nullptr); - dst_pool->release(src_id_); - src_id_ = Twine::Null; - } - return; - } - log_assert(dst_pool != nullptr); - if (src_pool == dst_pool || src_pool == nullptr) { - // Same-pool transfer — the source id is valid in dst_pool. - set_src_id(dst_pool, source->src_id()); - return; - } - // Cross-pool: rebuild source's twine subtree into dst_pool via - // copy_from, then adopt the fresh id. copy_from returns +1. - Twine::Id new_id = dst_pool->copy_from(*src_pool, source->src_id()); - if (src_id_ != Twine::Null) - dst_pool->release(src_id_); - src_id_ = new_id; -} - bool RTLIL::AttrObject::has_attribute(RTLIL::IdString id) const { if (id == ID::src) - return src_id_ != Twine::Null; + return meta_idx_ != RTLIL::AttrObject::NO_META; return attributes.count(id); } @@ -1016,7 +933,7 @@ void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id, bool value) bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const { if (id == ID::src) - return src_id_ != Twine::Null; + return meta_idx_ != RTLIL::AttrObject::NO_META; const auto it = attributes.find(id); if (it == attributes.end()) return false; @@ -1026,9 +943,9 @@ bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const void RTLIL::AttrObject::set_string_attribute(RTLIL::IdString id, string value) { // ID::src on the base AttrObject is not routable here because the base - // has no pool — callers needing string-form src must go through the - // subtype helper (Cell::set_src_attribute / Wire::… / …) which derives - // the pool from context. + // has no Design context — callers needing string-form src must go + // through the subtype helper (Cell::set_src_attribute / Wire::… / …) + // which derives the design from context. log_assert(id != ID::src && "set_string_attribute(ID::src,...) on AttrObject base; use the subtype helper"); if (value.empty()) attributes.erase(id); @@ -1047,34 +964,128 @@ string RTLIL::AttrObject::get_string_attribute(RTLIL::IdString id) const return value; } -void RTLIL::AttrObject::absorb_attrs(TwinePool *pool, dict &&buf) +void RTLIL::Design::obj_set_src_id_by_idx(uint32_t &meta_idx, Twine::Id id) +{ + if (meta_idx == RTLIL::AttrObject::NO_META) { + if (id == Twine::Null) + return; + meta_idx = alloc_obj_meta(); + } + Twine::Id &slot = obj_meta_src_[meta_idx]; + if (slot == id) + return; + if (slot != Twine::Null) + src_twines.release(slot); + slot = id; + if (slot != Twine::Null) + src_twines.retain(slot); + if (slot == Twine::Null) { + // Cleared — return the slot to the freelist. + free_obj_meta(meta_idx); + meta_idx = RTLIL::AttrObject::NO_META; + } +} + +void RTLIL::Design::obj_release_src_by_idx(uint32_t &meta_idx) +{ + if (meta_idx == RTLIL::AttrObject::NO_META) + return; + Twine::Id &slot = obj_meta_src_[meta_idx]; + if (slot != Twine::Null) { + src_twines.release(slot); + slot = Twine::Null; + } + free_obj_meta(meta_idx); + meta_idx = RTLIL::AttrObject::NO_META; +} + +void RTLIL::Design::set_src_attribute(RTLIL::AttrObject *obj, const RTLIL::SrcAttr &src) +{ + if (src.empty()) { + obj_set_src_id(obj, Twine::Null); + return; + } + Twine::Id new_id = Twine::Null; + if (src.id != Twine::Null) { + // Direct id form — the caller is responsible for keeping the + // slot alive while we retain. obj_set_src_id handles retain. + log_assert(src_twines.is_alive(src.id) && "set_src_attribute: SrcAttr id points to dead slot"); + new_id = src.id; + obj_set_src_id(obj, new_id); + } else { + // Literal-string form. "@N" → adopt slot directly. Anything else + // → intern as leaf (returns +1, which we release after the retain + // inside obj_set_src_id balances). + new_id = TwinePool::parse_ref(src.literal); + if (new_id != Twine::Null) { + log_assert(src_twines.is_alive(new_id) && "set_src_attribute: @N ref points to dead slot"); + obj_set_src_id(obj, new_id); + } else { + new_id = src_twines.intern(src.literal); + obj_set_src_id(obj, new_id); + src_twines.release(new_id); + } + } +} + +std::string RTLIL::Design::get_src_attribute(const RTLIL::AttrObject *obj) const +{ + return src_twines.flatten(obj_src_id(obj)); +} + +void RTLIL::Design::adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source) +{ + adopt_src_from(obj, source, &src_twines); +} + +void RTLIL::Design::adopt_src_from(RTLIL::AttrObject *obj, + const RTLIL::AttrObject *source, const TwinePool *src_pool) +{ + (void)src_pool; + if (!source || source->meta_idx_ == RTLIL::AttrObject::NO_META) { + obj_set_src_id(obj, Twine::Null); + return; + } + // Same-pool semantics: source's meta-vector entry is meaningful in + // our pool. Cross-pool adoption goes through copy_src_into directly + // (taking a src Design*), since AttrObject is not polymorphic and + // we can't downcast to recover the source design from here. + Twine::Id source_id = obj_src_id(source); + obj_set_src_id(obj, source_id); +} + +void RTLIL::Design::absorb_attrs(RTLIL::AttrObject *obj, dict &&buf) { auto it = buf.find(ID::src); if (it != buf.end()) { if (it->second.flags & RTLIL::CONST_FLAG_STRING) - set_src_attribute(pool, it->second.decode_string()); + set_src_attribute(obj, it->second.decode_string()); buf.erase(it); } - attributes = std::move(buf); + obj->attributes = std::move(buf); } -// Transfer src from `src` to `dst`. Both pools are supplied by the caller; -// in cross-pool transfers the source twine structure is rebuilt inside the -// destination pool via copy_from (preserving concats), in same-pool we just -// retain the existing slot via set_src_id. +// Cross-design src transfer. Source is in `src_design`, dst in this design. +// Both AttrObjects must have their meta_idx_ resolvable through the +// respective designs. namespace { - void copy_src_into(const RTLIL::AttrObject *src, const TwinePool *src_pool, - RTLIL::AttrObject *dst, TwinePool *dst_pool) + void copy_src_into(const RTLIL::AttrObject *src, const RTLIL::Design *src_design, + RTLIL::AttrObject *dst, RTLIL::Design *dst_design) { - if (!src || src->src_id() == Twine::Null || !src_pool || !dst_pool) + if (!src || !src_design || !dst_design) return; - if (src_pool == dst_pool) { - dst->set_src_id(dst_pool, src->src_id()); + Twine::Id src_id = src_design->obj_src_id(src); + if (src_id == Twine::Null) { + dst_design->obj_set_src_id(dst, Twine::Null); return; } - Twine::Id new_id = dst_pool->copy_from(*src_pool, src->src_id()); - dst->set_src_id(dst_pool, new_id); - dst_pool->release(new_id); + if (src_design == dst_design) { + dst_design->obj_set_src_id(dst, src_id); + return; + } + Twine::Id new_id = dst_design->src_twines.copy_from(src_design->src_twines, src_id); + dst_design->obj_set_src_id(dst, new_id); + dst_design->src_twines.release(new_id); } } @@ -1101,14 +1112,18 @@ void RTLIL::Design::free_obj_meta(uint32_t idx) void RTLIL::Design::merge_src(RTLIL::AttrObject *target, const RTLIL::AttrObject *source) { std::vector ids; - if (target->src_id() != Twine::Null) - ids.push_back(target->src_id()); - if (source && source->src_id() != Twine::Null) - ids.push_back(source->src_id()); + Twine::Id tgt_id = obj_src_id(target); + if (tgt_id != Twine::Null) + ids.push_back(tgt_id); + if (source) { + Twine::Id src_id = obj_src_id(source); + if (src_id != Twine::Null) + ids.push_back(src_id); + } if (ids.empty()) return; Twine::Id merged = src_twines.concat(std::span{ids}); - target->set_src_id(&src_twines, merged); + obj_set_src_id(target, merged); src_twines.release(merged); } @@ -1116,8 +1131,9 @@ void RTLIL::Design::merge_src(RTLIL::AttrObject *target, const pool { std::vector ids; std::vector temp_interns; - if (target->src_id() != Twine::Null) - ids.push_back(target->src_id()); + Twine::Id tgt_id = obj_src_id(target); + if (tgt_id != Twine::Null) + ids.push_back(tgt_id); for (const auto &leaf : leaves) { if (leaf.empty()) continue; @@ -1131,7 +1147,7 @@ void RTLIL::Design::merge_src(RTLIL::AttrObject *target, const pool if (ids.empty()) return; Twine::Id merged = src_twines.concat(std::span{ids}); - target->set_src_id(&src_twines, merged); + obj_set_src_id(target, merged); src_twines.release(merged); for (Twine::Id id : temp_interns) src_twines.release(id); @@ -1177,33 +1193,37 @@ size_t RTLIL::Design::gc_twines() if (before == 0) return 0; - // Mark phase: every live src_id_ on any AttrObject is a root. + // Mark phase: every live src_id on any AttrObject is a root. pool live; walk_attr_objects(this, [&](const RTLIL::AttrObject *obj) { - if (obj->src_id_ != Twine::Null) - live.insert(obj->src_id_); + Twine::Id id = obj_src_id(obj); + if (id != Twine::Null) + live.insert(id); }); // Sweep + compact: rebuild the pool keeping only reachable nodes, // receiving an old-id -> new-id remap. dict remap = src_twines.gc(live); - // Rewrite every src_id_ through the remap. The pool was rebuilt, so - // the old ids no longer mean anything — set_src_id with the new id is - // the canonical update. + // Rewrite every meta-vector src_id through the remap. The pool was + // rebuilt, so the old ids no longer mean anything — we update the + // vector slots directly (bypassing retain/release, which the rebuilt + // pool already accounts for). walk_attr_objects(this, [&](RTLIL::AttrObject *obj) { - if (obj->src_id_ == Twine::Null) + if (obj->meta_idx_ == RTLIL::AttrObject::NO_META) return; - auto it = remap.find(obj->src_id_); + Twine::Id &slot = obj_meta_src_[obj->meta_idx_]; + if (slot == Twine::Null) + return; + auto it = remap.find(slot); if (it == remap.end()) { - // Wasn't in live set (design corruption) — just zero the id - // since the old pool is gone. - obj->src_id_ = Twine::Null; + // Wasn't in live set (design corruption) — zero out. + slot = Twine::Null; + free_obj_meta(obj->meta_idx_); + obj->meta_idx_ = RTLIL::AttrObject::NO_META; return; } - // Rewrite without going through retain/release — the rebuilt - // pool already accounts for ownership. - obj->src_id_ = it->second; + slot = it->second; }); return before - src_twines.size(); @@ -1212,12 +1232,13 @@ size_t RTLIL::Design::gc_twines() pool RTLIL::Design::src_leaves(const RTLIL::AttrObject *obj) const { pool result; - if (obj->src_id() == Twine::Null) + Twine::Id id = obj_src_id(obj); + if (id == Twine::Null) return result; const TwinePool *pool = &src_twines; - const Twine &n = (*pool)[obj->src_id()]; + const Twine &n = (*pool)[id]; if (n.is_flat()) { - result.insert(pool->flat_string(obj->src_id())); + result.insert(pool->flat_string(id)); } else { // Flat-children invariant: every concat child is a Leaf or Suffix. for (Twine::Id c : n.children()) @@ -1657,11 +1678,14 @@ void RTLIL::Design::optimize() void RTLIL::Design::clone_into(RTLIL::Design *dst) const { log_assert(dst->modules_.empty()); - // Copy the twine pool wholesale. Any prior pool state in dst (e.g. - // dead slots left over from a -reset / -pop preceding the clone) is - // discarded by the assignment. The copied refcounts will balance the - // per-AttrObject src_id_ refs assigned below 1:1. + // Copy the twine pool and the per-object src meta vector wholesale. + // Any prior pool / meta state in dst (e.g. dead slots left over from + // a -reset / -pop preceding the clone) is discarded by the + // assignment. The copied refcounts and the same meta_idx_ values + // assigned below 1:1 to cloned AttrObjects line up by construction. dst->src_twines = src_twines; + dst->obj_meta_src_ = obj_meta_src_; + dst->obj_meta_free_ = obj_meta_free_; // Iterate via rbegin/rend so cloned modules land in dst in forward // insertion order — same as how the source design's modules dict was // built — keeping write_rtlil output byte-stable across clone cycles. @@ -1810,17 +1834,9 @@ RTLIL::Module::Module() RTLIL::Module::~Module() { clear_sig_norm_index(); - // Release src for Memories (they have no module backpointer) before - // destroying them. Wire/Cell/Process release themselves via their - // own dtor through module->design. - if (design) { - TwinePool *pool = &design->src_twines; - for (auto &pr : memories) - if (pr.second->src_id_ != Twine::Null) { - pool->release(pr.second->src_id_); - pr.second->src_id_ = Twine::Null; - } - } + // Wire/Cell/Process/Memory release their own src via their dtors + // through module->design. They run after their respective deletes + // below, so we let them handle their own meta_idx_ cleanup. for (auto &pr : wires_) delete pr.second; for (auto &pr : memories) @@ -1831,35 +1847,52 @@ RTLIL::Module::~Module() delete pr.second; for (auto binding : bindings_) delete binding; - // Module's own src_id_ — release last so the pool stays valid for + // Module's own src — release last so the pool stays valid for // inner releases above. - if (design && src_id_ != Twine::Null) { - design->src_twines.release(src_id_); - src_id_ = Twine::Null; - } + if (design) + design->obj_release_src(this); #ifdef YOSYS_ENABLE_PYTHON RTLIL::Module::get_all_modules()->erase(hashidx_); #endif } +Twine::Id RTLIL::Module::src_id() const +{ + if (!design) + return Twine::Null; + return design->obj_src_id(this); +} + +void RTLIL::Module::set_src_id(Twine::Id id) +{ + log_assert(design && "Module::set_src_id requires the module to be attached to a design"); + design->obj_set_src_id(this, id); +} + void RTLIL::Module::set_src_attribute(const RTLIL::SrcAttr &src) { - if (src.empty() && src_id_ == Twine::Null) + if (src.empty() && meta_idx_ == NO_META) return; log_assert(design && "Module::set_src_attribute requires the module to be attached to a design"); - AttrObject::set_src_attribute(&design->src_twines, src); + design->set_src_attribute(this, src); } void RTLIL::Module::adopt_src_from(const RTLIL::AttrObject *source) { log_assert(design && "Module::adopt_src_from requires the module to be attached to a design"); - AttrObject::adopt_src_from(&design->src_twines, source); + design->adopt_src_from(this, source); } std::string RTLIL::Module::get_src_attribute() const { log_assert(design); - return AttrObject::get_src_attribute(&design->src_twines); + return design->get_src_attribute(this); +} + +void RTLIL::Module::absorb_attrs(dict &&buf) +{ + log_assert(design && "Module::absorb_attrs requires the module to be attached to a design"); + design->absorb_attrs(this, std::move(buf)); } #ifdef YOSYS_ENABLE_PYTHON @@ -3071,28 +3104,29 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons for (auto &attr : attributes) new_mod->attributes[attr.first] = attr.second; if (src_id_verbatim) { - // Caller (Design::clone_into) copied src_twines wholesale, so - // the same Twine::Id is valid in the destination pool — and - // the copied refcounts already pre-account for these new + // Caller (Design::clone_into) copied src_twines AND the obj + // meta vector wholesale, so the same meta_idx_ resolves to + // the same Twine::Id in the destination pool — and the + // copied refcounts already pre-account for these new // AttrObjects. Direct assignment, no retain. - new_mod->src_id_ = src_id_; + new_mod->meta_idx_ = meta_idx_; } else { // Transfer src across designs. Both modules must be attached // to a design for the migration to happen; in the // detached-clone() scratch flow (equiv_make, etc.) src is // dropped here — those callers don't preserve src across the // temp clone by design. - const TwinePool *src_pool = this->design ? &this->design->src_twines : nullptr; - TwinePool *dst_pool = new_mod->design ? &new_mod->design->src_twines : nullptr; - copy_src_into(this, src_pool, new_mod, dst_pool); + if (this->design && new_mod->design) + copy_src_into(this, this->design, new_mod, new_mod->design); } if (src_id_verbatim) { // Build fresh wires/cells/memories/processes and transfer - // src_id_ verbatim. The non-verbatim branch goes through + // meta_idx_ verbatim. The non-verbatim branch goes through // addWire/addCell/addProcess(name, other) which call - // copy_src_into to migrate src across pools; here both pools - // already match, so we skip that and copy the id directly. + // copy_src_into to migrate src across designs; here both + // designs already share the same meta vector / pool, so we + // skip that and copy the index directly. for (auto it = wires_.rbegin(); it != wires_.rend(); ++it) { const RTLIL::Wire *o = it->second; RTLIL::Wire *w = new_mod->addWire(it->first, o->width); @@ -3103,7 +3137,7 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons w->upto = o->upto; w->is_signed = o->is_signed; w->attributes = o->attributes; - w->src_id_ = o->src_id_; + w->meta_idx_ = o->meta_idx_; } for (auto it = memories.rbegin(); it != memories.rend(); ++it) { const RTLIL::Memory *o = it->second; @@ -3112,7 +3146,7 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons m->start_offset = o->start_offset; m->size = o->size; m->attributes = o->attributes; - m->src_id_ = o->src_id_; + m->meta_idx_ = o->meta_idx_; } for (auto it = cells_.rbegin(); it != cells_.rend(); ++it) { const RTLIL::Cell *o = it->second; @@ -3120,28 +3154,28 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons c->connections_ = o->connections_; c->parameters = o->parameters; c->attributes = o->attributes; - c->src_id_ = o->src_id_; + c->meta_idx_ = o->meta_idx_; } for (auto it = processes.rbegin(); it != processes.rend(); ++it) { const RTLIL::Process *o = it->second; RTLIL::Process *p = o->clone(); p->name = it->first; new_mod->add(p); - // Process::clone drops src_id_ across the inner tree - // (no pool backpointer there); now that p has a module - // we can copy them verbatim. - p->src_id_ = o->src_id_; + // Process::clone drops meta_idx_ across the inner tree + // (no module backpointer there before attach); now that + // p has a module we can copy them verbatim. + p->meta_idx_ = o->meta_idx_; std::vector> case_stack; case_stack.emplace_back(&o->root_case, &p->root_case); while (!case_stack.empty()) { auto [s_cs, d_cs] = case_stack.back(); case_stack.pop_back(); - d_cs->src_id_ = s_cs->src_id_; + d_cs->meta_idx_ = s_cs->meta_idx_; log_assert(s_cs->switches.size() == d_cs->switches.size()); for (size_t i = 0; i < s_cs->switches.size(); i++) { const auto *s_sw = s_cs->switches[i]; auto *d_sw = d_cs->switches[i]; - d_sw->src_id_ = s_sw->src_id_; + d_sw->meta_idx_ = s_sw->meta_idx_; log_assert(s_sw->cases.size() == d_sw->cases.size()); for (size_t j = 0; j < s_sw->cases.size(); j++) case_stack.emplace_back(s_sw->cases[j], d_sw->cases[j]); @@ -3153,7 +3187,7 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons auto *d_sync = p->syncs[i]; log_assert(s_sync->mem_write_actions.size() == d_sync->mem_write_actions.size()); for (size_t j = 0; j < s_sync->mem_write_actions.size(); j++) - d_sync->mem_write_actions[j].src_id_ = s_sync->mem_write_actions[j].src_id_; + d_sync->mem_write_actions[j].meta_idx_ = s_sync->mem_write_actions[j].meta_idx_; } } } else { @@ -3577,9 +3611,9 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *oth wire->is_signed = other->is_signed; wire->attributes = other->attributes; { - const TwinePool *src_pool = other->module && other->module->design ? &other->module->design->src_twines : nullptr; - TwinePool *dst_pool = this->design ? &this->design->src_twines : nullptr; - copy_src_into(other, src_pool, wire, dst_pool); + const RTLIL::Design *src_design = other->module ? other->module->design : nullptr; + if (src_design && this->design) + copy_src_into(other, src_design, wire, this->design); } return wire; } @@ -3600,9 +3634,9 @@ RTLIL::Cell *RTLIL::Module::addCell(RTLIL::IdString name, const RTLIL::Cell *oth cell->parameters = other->parameters; cell->attributes = other->attributes; { - const TwinePool *src_pool = other->module && other->module->design ? &other->module->design->src_twines : nullptr; - TwinePool *dst_pool = this->design ? &this->design->src_twines : nullptr; - copy_src_into(other, src_pool, cell, dst_pool); + const RTLIL::Design *src_design = other->module ? other->module->design : nullptr; + if (src_design && this->design) + copy_src_into(other, src_design, cell, this->design); } return cell; } @@ -3648,11 +3682,11 @@ namespace { // design boundary for every AttrObject (CaseRule, SwitchRule, // MemWriteAction). Process::clone() drops src on these inner objects // because they have no pool backpointer; this restores it now that - // both source and destination pools are known. - void migrate_process_tree_src(const RTLIL::Process *src, const TwinePool *src_pool, - RTLIL::Process *dst, TwinePool *dst_pool) + // both source and destination designs are known. + void migrate_process_tree_src(const RTLIL::Process *src, const RTLIL::Design *src_design, + RTLIL::Process *dst, RTLIL::Design *dst_design) { - if (!src_pool || !dst_pool) + if (!src_design || !dst_design) return; // Top-level Process src is handled by the addProcess() caller via // copy_src_into; here we only walk inner objects. @@ -3661,12 +3695,12 @@ namespace { while (!case_stack.empty()) { auto [s_cs, d_cs] = case_stack.back(); case_stack.pop_back(); - copy_src_into(s_cs, src_pool, d_cs, dst_pool); + copy_src_into(s_cs, src_design, d_cs, dst_design); log_assert(s_cs->switches.size() == d_cs->switches.size()); for (size_t i = 0; i < s_cs->switches.size(); i++) { const auto *s_sw = s_cs->switches[i]; auto *d_sw = d_cs->switches[i]; - copy_src_into(s_sw, src_pool, d_sw, dst_pool); + copy_src_into(s_sw, src_design, d_sw, dst_design); log_assert(s_sw->cases.size() == d_sw->cases.size()); for (size_t j = 0; j < s_sw->cases.size(); j++) case_stack.emplace_back(s_sw->cases[j], d_sw->cases[j]); @@ -3678,8 +3712,8 @@ namespace { auto *d_sync = dst->syncs[i]; log_assert(s_sync->mem_write_actions.size() == d_sync->mem_write_actions.size()); for (size_t j = 0; j < s_sync->mem_write_actions.size(); j++) - copy_src_into(&s_sync->mem_write_actions[j], src_pool, - &d_sync->mem_write_actions[j], dst_pool); + copy_src_into(&s_sync->mem_write_actions[j], src_design, + &d_sync->mem_write_actions[j], dst_design); } } } @@ -3691,16 +3725,16 @@ RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name, const RTLIL::Pro add(proc); // Migrate src across the design boundary for the inner-process tree. // Process::clone drops src on CaseRule/SwitchRule/MemWriteAction since - // those types have no module backpointer; with both pools now known + // those types have no module backpointer; with both designs now known // (other's via other->module->design; ours via this->design) we can // walk in parallel and migrate. if (other->module && other->module->design && this->design) { - const TwinePool *src_pool = &other->module->design->src_twines; - TwinePool *dst_pool = &this->design->src_twines; + const RTLIL::Design *src_design = other->module->design; + RTLIL::Design *dst_design = this->design; // Top-level Process src. - copy_src_into(other, src_pool, proc, dst_pool); + copy_src_into(other, src_design, proc, dst_design); // Inner tree. - migrate_process_tree_src(other, src_pool, proc, dst_pool); + migrate_process_tree_src(other, src_design, proc, dst_design); } return proc; } @@ -4712,32 +4746,51 @@ RTLIL::Wire::Wire(ConstructToken) RTLIL::Wire::~Wire() { - if (module && module->design && src_id_ != Twine::Null) - module->design->src_twines.release(src_id_); + if (module && module->design) + module->design->obj_release_src(this); #ifdef YOSYS_ENABLE_PYTHON RTLIL::Wire::get_all_wires()->erase(hashidx_); #endif } +Twine::Id RTLIL::Wire::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} + +void RTLIL::Wire::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "Wire::set_src_id requires the wire to be attached to a module in a design"); + module->design->obj_set_src_id(this, id); +} + void RTLIL::Wire::set_src_attribute(const RTLIL::SrcAttr &src) { - if (src.empty() && src_id_ == Twine::Null) + if (src.empty() && meta_idx_ == NO_META) return; log_assert(module && module->design && "Wire::set_src_attribute requires the wire to be attached to a module in a design"); - AttrObject::set_src_attribute(&module->design->src_twines, src); + module->design->set_src_attribute(this, src); } std::string RTLIL::Wire::get_src_attribute() const { log_assert(module); log_assert(module->design); - return AttrObject::get_src_attribute(&module->design->src_twines); + return module->design->get_src_attribute(this); } void RTLIL::Wire::adopt_src_from(const RTLIL::AttrObject *source) { log_assert(module && module->design && "Wire::adopt_src_from requires the wire to be attached to a module in a design"); - AttrObject::adopt_src_from(&module->design->src_twines, source); + module->design->adopt_src_from(this, source); +} + +void RTLIL::Wire::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "Wire::absorb_attrs requires the wire to be attached to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); } std::string RTLIL::Wire::to_rtlil_str() const @@ -4806,32 +4859,51 @@ RTLIL::Cell::Cell(ConstructToken) : module(nullptr) RTLIL::Cell::~Cell() { - if (module && module->design && src_id_ != Twine::Null) - module->design->src_twines.release(src_id_); + if (module && module->design) + module->design->obj_release_src(this); #ifdef YOSYS_ENABLE_PYTHON RTLIL::Cell::get_all_cells()->erase(hashidx_); #endif } +Twine::Id RTLIL::Cell::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} + +void RTLIL::Cell::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "Cell::set_src_id requires the cell to be attached to a module in a design"); + module->design->obj_set_src_id(this, id); +} + void RTLIL::Cell::set_src_attribute(const RTLIL::SrcAttr &src) { - if (src.empty() && src_id_ == Twine::Null) + if (src.empty() && meta_idx_ == NO_META) return; log_assert(module && module->design && "Cell::set_src_attribute requires the cell to be attached to a module in a design"); - AttrObject::set_src_attribute(&module->design->src_twines, src); + module->design->set_src_attribute(this, src); } std::string RTLIL::Cell::get_src_attribute() const { log_assert(module); log_assert(module->design); - return module->design->src_twines.flatten(src_id_); + return module->design->get_src_attribute(this); } void RTLIL::Cell::adopt_src_from(const RTLIL::AttrObject *source) { log_assert(module && module->design && "Cell::adopt_src_from requires the cell to be attached to a module in a design"); - AttrObject::adopt_src_from(&module->design->src_twines, source); + module->design->adopt_src_from(this, source); +} + +void RTLIL::Cell::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "Cell::absorb_attrs requires the cell to be attached to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); } std::string RTLIL::Cell::to_rtlil_str() const @@ -6493,76 +6565,89 @@ RTLIL::SyncRule *RTLIL::SyncRule::clone() const new_syncrule->signal = signal; new_syncrule->actions = actions; new_syncrule->mem_write_actions = mem_write_actions; - // Drop src_id_ on the cloned MemWriteActions — the integer was copied - // by the vector assignment above without retaining the pool slot, and - // the caller is responsible for migrating src across the clone via - // context (see Process::clone). + // Drop meta_idx_ on the cloned MemWriteActions — the integer was + // copied by the vector assignment above without registering with + // any pool; the caller is responsible for migrating src across the + // clone via context (see Process::clone). for (auto &mwa : new_syncrule->mem_write_actions) - mwa.src_id_ = Twine::Null; + mwa.meta_idx_ = RTLIL::AttrObject::NO_META; return new_syncrule; } -RTLIL::Process::~Process() -{ - // Process owns the refcount lifecycle for its inner AttrObject tree: - // CaseRule/SwitchRule/MemWriteAction have no module backpointer so - // can't release their own src_id_. Walk the tree first while we still - // have access to the pool via module->design. - if (module && module->design) { - TwinePool *pool = &module->design->src_twines; - std::vector case_stack{&root_case}; +namespace { + // Release the meta src slot on each AttrObject inside a Process tree. + // Called from Process::~Process while module->design is still valid. + void release_process_tree_src(RTLIL::Process *p) + { + if (!p->module || !p->module->design) + return; + RTLIL::Design *d = p->module->design; + std::vector case_stack{&p->root_case}; while (!case_stack.empty()) { RTLIL::CaseRule *cs = case_stack.back(); case_stack.pop_back(); - if (cs->src_id_ != Twine::Null) { - pool->release(cs->src_id_); - cs->src_id_ = Twine::Null; - } + d->obj_release_src(cs); for (auto *sw : cs->switches) { - if (sw->src_id_ != Twine::Null) { - pool->release(sw->src_id_); - sw->src_id_ = Twine::Null; - } + d->obj_release_src(sw); for (auto *case_ : sw->cases) case_stack.push_back(case_); } } - for (auto *sync : syncs) - for (auto &mwa : sync->mem_write_actions) { - if (mwa.src_id_ != Twine::Null) { - pool->release(mwa.src_id_); - mwa.src_id_ = Twine::Null; - } - } - // Process's own src_id_ (lives in the AttrObject base). - if (src_id_ != Twine::Null) { - pool->release(src_id_); - src_id_ = Twine::Null; - } + for (auto *sync : p->syncs) + for (auto &mwa : sync->mem_write_actions) + d->obj_release_src(&mwa); } +} + +RTLIL::Process::~Process() +{ + // Walk the inner tree first while module->design is still valid, + // then release Process's own src. + release_process_tree_src(this); + if (module && module->design) + module->design->obj_release_src(this); for (auto it = syncs.begin(); it != syncs.end(); it++) delete *it; } +Twine::Id RTLIL::Process::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} + +void RTLIL::Process::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "Process::set_src_id requires the process to be attached to a module in a design"); + module->design->obj_set_src_id(this, id); +} + void RTLIL::Process::set_src_attribute(const RTLIL::SrcAttr &src) { - if (src.empty() && src_id_ == Twine::Null) + if (src.empty() && meta_idx_ == NO_META) return; log_assert(module && module->design && "Process::set_src_attribute requires the process to be attached to a module in a design"); - AttrObject::set_src_attribute(&module->design->src_twines, src); + module->design->set_src_attribute(this, src); } std::string RTLIL::Process::get_src_attribute() const { if (!module || !module->design) return {}; - return AttrObject::get_src_attribute(&module->design->src_twines); + return module->design->get_src_attribute(this); } void RTLIL::Process::adopt_src_from(const RTLIL::AttrObject *source) { log_assert(module && module->design && "Process::adopt_src_from requires the process to be attached to a module in a design"); - AttrObject::adopt_src_from(&module->design->src_twines, source); + module->design->adopt_src_from(this, source); +} + +void RTLIL::Process::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "Process::absorb_attrs requires the process to be attached to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); } RTLIL::Process *RTLIL::Process::clone() const @@ -6585,11 +6670,163 @@ RTLIL::Process *RTLIL::Process::clone() const return new_proc; } -#ifdef YOSYS_ENABLE_PYTHON RTLIL::Memory::~Memory() { + if (module && module->design) + module->design->obj_release_src(this); +#ifdef YOSYS_ENABLE_PYTHON RTLIL::Memory::get_all_memorys()->erase(hashidx_); +#endif } + +Twine::Id RTLIL::Memory::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} + +void RTLIL::Memory::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "Memory::set_src_id requires the memory to be attached to a module in a design"); + module->design->obj_set_src_id(this, id); +} + +void RTLIL::Memory::set_src_attribute(const RTLIL::SrcAttr &src) +{ + if (src.empty() && meta_idx_ == NO_META) + return; + log_assert(module && module->design && "Memory::set_src_attribute requires the memory to be attached to a module in a design"); + module->design->set_src_attribute(this, src); +} + +std::string RTLIL::Memory::get_src_attribute() const +{ + if (!module || !module->design) + return {}; + return module->design->get_src_attribute(this); +} + +void RTLIL::Memory::adopt_src_from(const RTLIL::AttrObject *source) +{ + log_assert(module && module->design && "Memory::adopt_src_from requires the memory to be attached to a module in a design"); + module->design->adopt_src_from(this, source); +} + +void RTLIL::Memory::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "Memory::absorb_attrs requires the memory to be attached to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); +} + +// CaseRule / SwitchRule / MemWriteAction src helpers — all delegate to +// module->design->obj_* via the back-pointer added in the earlier commit. +Twine::Id RTLIL::CaseRule::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} +void RTLIL::CaseRule::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "CaseRule::set_src_id requires the case to belong to a module in a design"); + module->design->obj_set_src_id(this, id); +} +void RTLIL::CaseRule::set_src_attribute(const RTLIL::SrcAttr &src) +{ + if (src.empty() && meta_idx_ == NO_META) + return; + log_assert(module && module->design && "CaseRule::set_src_attribute requires the case to belong to a module in a design"); + module->design->set_src_attribute(this, src); +} +std::string RTLIL::CaseRule::get_src_attribute() const +{ + if (!module || !module->design) + return {}; + return module->design->get_src_attribute(this); +} +void RTLIL::CaseRule::adopt_src_from(const RTLIL::AttrObject *source) +{ + log_assert(module && module->design && "CaseRule::adopt_src_from requires the case to belong to a module in a design"); + module->design->adopt_src_from(this, source); +} +void RTLIL::CaseRule::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "CaseRule::absorb_attrs requires the case to belong to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); +} + +Twine::Id RTLIL::SwitchRule::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} +void RTLIL::SwitchRule::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "SwitchRule::set_src_id requires the switch to belong to a module in a design"); + module->design->obj_set_src_id(this, id); +} +void RTLIL::SwitchRule::set_src_attribute(const RTLIL::SrcAttr &src) +{ + if (src.empty() && meta_idx_ == NO_META) + return; + log_assert(module && module->design && "SwitchRule::set_src_attribute requires the switch to belong to a module in a design"); + module->design->set_src_attribute(this, src); +} +std::string RTLIL::SwitchRule::get_src_attribute() const +{ + if (!module || !module->design) + return {}; + return module->design->get_src_attribute(this); +} +void RTLIL::SwitchRule::adopt_src_from(const RTLIL::AttrObject *source) +{ + log_assert(module && module->design && "SwitchRule::adopt_src_from requires the switch to belong to a module in a design"); + module->design->adopt_src_from(this, source); +} +void RTLIL::SwitchRule::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "SwitchRule::absorb_attrs requires the switch to belong to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); +} + +Twine::Id RTLIL::MemWriteAction::src_id() const +{ + if (!module || !module->design) + return Twine::Null; + return module->design->obj_src_id(this); +} +void RTLIL::MemWriteAction::set_src_id(Twine::Id id) +{ + log_assert(module && module->design && "MemWriteAction::set_src_id requires the action to belong to a module in a design"); + module->design->obj_set_src_id(this, id); +} +void RTLIL::MemWriteAction::set_src_attribute(const RTLIL::SrcAttr &src) +{ + if (src.empty() && meta_idx_ == NO_META) + return; + log_assert(module && module->design && "MemWriteAction::set_src_attribute requires the action to belong to a module in a design"); + module->design->set_src_attribute(this, src); +} +std::string RTLIL::MemWriteAction::get_src_attribute() const +{ + if (!module || !module->design) + return {}; + return module->design->get_src_attribute(this); +} +void RTLIL::MemWriteAction::adopt_src_from(const RTLIL::AttrObject *source) +{ + log_assert(module && module->design && "MemWriteAction::adopt_src_from requires the action to belong to a module in a design"); + module->design->adopt_src_from(this, source); +} +void RTLIL::MemWriteAction::absorb_attrs(dict &&buf) +{ + log_assert(module && module->design && "MemWriteAction::absorb_attrs requires the action to belong to a module in a design"); + module->design->absorb_attrs(this, std::move(buf)); +} + +#ifdef YOSYS_ENABLE_PYTHON static std::map all_memorys; std::map *RTLIL::Memory::get_all_memorys(void) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 1f8d2299b..b74791f71 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1295,17 +1295,21 @@ struct RTLIL::AttrObject { dict attributes; - // Typed src field. Outside the attribute dict — src is a structured - // reference into a TwinePool. The pool is NOT stored here: every live - // AttrObject is reachable from a Design (Cell/Wire/Process via their - // module, Module via its design field), and inner-process AttrObjects - // (CaseRule, SwitchRule, MemWriteAction) are owned by a Process whose - // dtor drives their refcount on their behalf. src_id_ is a "weak" - // integer reference — copying it does not retain; destroying the - // AttrObject does not release. Lifecycle is driven by the leaf - // subtype's destructor (Cell, Wire, Module, Process) walking up to - // its owning pool, and by Process::~Process for the nested types. - Twine::Id src_id_ = Twine::Null; + // Per-Design metadata slot index, or NO_META. The slot lives in + // Design::obj_meta_src_ and holds this object's Twine::Id src; the + // slot is allocated lazily on the first non-null src write and + // freed when src returns to null. Per-object cost is just this + // 4-byte index (replacing the prior inline 4-byte src_id_). + // + // AttrObject can't resolve its owning Design on its own. Lookups + // route either through a leaf subtype's src_id() sugar (which knows + // its container chain — Cell/Wire/Process/Memory via module->design, + // Module via design, CaseRule/SwitchRule/MemWriteAction via the + // module back-pointer added in prior commits) or through the + // Design::obj_src_id / obj_set_src_id / obj_release_src helpers + // when generic AttrObject* code already has a Design* in hand. + static constexpr uint32_t NO_META = ~0u; + uint32_t meta_idx_ = NO_META; bool has_attribute(RTLIL::IdString id) const; @@ -1325,50 +1329,6 @@ struct RTLIL::AttrObject void add_strpool_attribute(RTLIL::IdString id, const pool &data); pool get_strpool_attribute(RTLIL::IdString id) const; - Twine::Id src_id() const { return src_id_; } - - // Store an interned id and manage refcount via the provided pool: - // retain the new id; release the previous one if any. Twine::Null - // clears. The caller supplies the pool because AttrObject does not - // store one — typically derived from context (cell->module->design-> - // src_twines and friends) or known directly (frontends, copy_from). - void set_src_id(TwinePool *pool, Twine::Id id); - - // Apply `src` to this AttrObject via `pool`. If `src` carries a - // pre-interned id (returned by e.g. `other->src_ref()`) it is - // retained directly — no flatten/intern. Otherwise `src.literal` - // is interned (handling "@N" refs and splitting pipe-joined - // multi-leaf inputs into a Concat). Empty `src` clears src_id_. - void set_src_attribute(TwinePool *pool, const RTLIL::SrcAttr &src); - // Flatten the held src_id_ via `pool` to its pipe-joined literal. - std::string get_src_attribute(const TwinePool *pool) const; - - // Transfer src verbatim from `source` to this object. The two-arg - // form assumes same-pool: `source`'s src_id_ is retained directly - // on the destination in `pool`. The three-arg form handles the - // cross-pool case by rebuilding `source`'s subtree (Concat/Suffix/ - // Leaf) into `dst_pool` via copy_from. Either way no flatten/ - // re-intern round-trip on the canonical leaf strings, so a Concat - // src never collapses into a pipe-containing Leaf. - void adopt_src_from(TwinePool *pool, const RTLIL::AttrObject *source); - void adopt_src_from(TwinePool *dst_pool, const RTLIL::AttrObject *source, - const TwinePool *src_pool); - - // The raw twine id naming this object's src. Pass this — never the - // flattened path string from get_src_attribute() — when handing - // src to a CellAdder method or to another object's set_src: every - // CellAdder method has a Twine::Id overload that adopts the slot - // directly with no flatten/intern round-trip, preserving Suffix/ - // Concat structure and never producing a pipe-containing Leaf - // from a Concat src. - Twine::Id src_ref() const { return src_id_; } - - // Replace `attributes` with `buf`, extracting any ID::src entry first - // and routing it via `pool` to the typed src_id_ field. Use this in - // frontends instead of `obj->attributes = std::move(buf)` so file src - // lands in the twine pool rather than the attribute dict. - void absorb_attrs(TwinePool *pool, dict &&buf); - void set_hdlname_attribute(const vector &hierarchy); vector get_hdlname_attribute() const; @@ -2009,6 +1969,46 @@ struct RTLIL::Design uint32_t alloc_obj_meta(); void free_obj_meta(uint32_t idx); + // Read src for `meta_idx`. NO_META → Twine::Null. + Twine::Id obj_src_id_by_idx(uint32_t meta_idx) const { + if (meta_idx == RTLIL::AttrObject::NO_META) + return Twine::Null; + return obj_meta_src_[meta_idx]; + } + + // Set src for `meta_idx`, allocating a slot lazily and freeing it + // when `id` is Twine::Null. Manages retain/release on src_twines. + // `meta_idx` is mutated as needed (NO_META -> allocated slot, or + // allocated slot -> NO_META after clearing). + void obj_set_src_id_by_idx(uint32_t &meta_idx, Twine::Id id); + + // Release the slot's Twine ref and free the index. No-op if NO_META. + // Use from destructors. `meta_idx` becomes NO_META on return. + void obj_release_src_by_idx(uint32_t &meta_idx); + + // AttrObject-keyed convenience overloads — dispatch to the _by_idx + // versions on obj->meta_idx_. Use these from generic helpers that + // already have a Design* in scope. + Twine::Id obj_src_id(const RTLIL::AttrObject *obj) const { + return obj_src_id_by_idx(obj->meta_idx_); + } + void obj_set_src_id(RTLIL::AttrObject *obj, Twine::Id id) { + obj_set_src_id_by_idx(obj->meta_idx_, id); + } + void obj_release_src(RTLIL::AttrObject *obj) { + obj_release_src_by_idx(obj->meta_idx_); + } + + // Replacements for the methods that used to live on AttrObject and + // took an explicit TwinePool*. Same semantics; the pool resolves + // to this->src_twines internally. + void set_src_attribute(RTLIL::AttrObject *obj, const RTLIL::SrcAttr &src); + std::string get_src_attribute(const RTLIL::AttrObject *obj) const; + void adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source); + void adopt_src_from(RTLIL::AttrObject *obj, const RTLIL::AttrObject *source, + const TwinePool *src_pool); + void absorb_attrs(RTLIL::AttrObject *obj, dict &&buf); + // Resolve a stored src-attribute string to its flat path:line.col // representation. If `raw` is a twine reference ("@N") returns // src_twines.flatten(N); otherwise returns `raw` unchanged. Backends @@ -2239,16 +2239,17 @@ public: int width, start_offset, port_id; bool port_input, port_output, upto, is_signed; - // Context-aware src helpers. Resolve the destination pool via - // `module->design->src_twines`; assert the wire is attached. - using AttrObject::set_src_attribute; - using AttrObject::get_src_attribute; - using AttrObject::adopt_src_from; + // Context-aware src helpers. Resolve Design via module->design and + // route to the per-Design meta vector; assert the wire is attached. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); void set_src_attribute(const RTLIL::SrcAttr &src); std::string get_src_attribute() const; // Transfer src from `source` verbatim (same pool). Asserts attached - // to a design — derives the pool via module->design->src_twines. + // to a design. void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); bool known_driver() const { return driverCell_ != nullptr; } @@ -2285,17 +2286,26 @@ struct RTLIL::Memory : public RTLIL::NamedObject [[nodiscard]] Hasher hash_into(Hasher h) const { h.eat(hashidx_); return h; } Memory(); + ~Memory(); // Back-pointer to the owning module — same role as Cell::module / // Wire::module. Set by Module::addMemory / the frontends that // construct Memory free-standing before attaching to a module. - // Lets Memory's src access (and the upcoming per-Design meta vector - // lookup) resolve uniformly via module->design. + // Lets Memory's src access resolve uniformly via module->design. RTLIL::Module *module = nullptr; + // Context-aware src helpers. Resolve Design via module->design and + // route to the per-Design meta vector; assert the memory is attached. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); + void set_src_attribute(const RTLIL::SrcAttr &src); + std::string get_src_attribute() const; + void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); + int width, start_offset, size; #ifdef YOSYS_ENABLE_PYTHON - ~Memory(); static std::map *get_all_memorys(void); #endif @@ -2334,16 +2344,15 @@ public: dict connections_; dict parameters; - // Context-aware src helpers. Resolve the destination pool via - // `module->design->src_twines`; assert the cell is attached. - using AttrObject::set_src_attribute; - using AttrObject::get_src_attribute; - using AttrObject::adopt_src_from; + // Context-aware src helpers. Resolve Design via module->design and + // route to the per-Design meta vector; assert the cell is attached. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); void set_src_attribute(const RTLIL::SrcAttr &src); std::string get_src_attribute() const; - // Transfer src from `source` verbatim (same pool). Asserts attached - // to a design — derives the pool via module->design->src_twines. void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); // access cell ports bool hasPort(RTLIL::IdString portname) const; @@ -2408,6 +2417,15 @@ struct RTLIL::CaseRule : public RTLIL::AttrObject // each. Idempotent. void setModuleRecursive(RTLIL::Module *m); + // Context-aware src helpers via module->design. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); + void set_src_attribute(const RTLIL::SrcAttr &src); + std::string get_src_attribute() const; + void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); + template void rewrite_sigspecs(T &functor); template void rewrite_sigspecs2(T &functor); RTLIL::CaseRule *clone() const; @@ -2427,6 +2445,15 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject void setModuleRecursive(RTLIL::Module *m); + // Context-aware src helpers via module->design. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); + void set_src_attribute(const RTLIL::SrcAttr &src); + std::string get_src_attribute() const; + void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); + template void rewrite_sigspecs(T &functor); template void rewrite_sigspecs2(T &functor); RTLIL::SwitchRule *clone() const; @@ -2442,6 +2469,15 @@ struct RTLIL::MemWriteAction : RTLIL::AttrObject RTLIL::SigSpec data; RTLIL::SigSpec enable; RTLIL::Const priority_mask; + + // Context-aware src helpers via module->design. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); + void set_src_attribute(const RTLIL::SrcAttr &src); + std::string get_src_attribute() const; + void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); }; struct RTLIL::SyncRule @@ -2476,16 +2512,15 @@ public: RTLIL::CaseRule root_case; std::vector syncs; - // Context-aware src helpers. Resolve the destination pool via - // `module->design->src_twines`; assert the process is attached. - using AttrObject::set_src_attribute; - using AttrObject::get_src_attribute; - using AttrObject::adopt_src_from; + // Context-aware src helpers. Resolve Design via module->design and + // route to the per-Design meta vector; assert the process is attached. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); void set_src_attribute(const RTLIL::SrcAttr &src); std::string get_src_attribute() const; - // Transfer src from `source` verbatim (same pool). Asserts attached - // to a design — derives the pool via module->design->src_twines. void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); template void rewrite_sigspecs(T &functor); template void rewrite_sigspecs2(T &functor); @@ -2826,16 +2861,15 @@ public: dict memories; dict processes; - // Context-aware src helpers. Resolve the destination pool via - // `design->src_twines`; assert the module is attached. - using AttrObject::set_src_attribute; - using AttrObject::get_src_attribute; - using AttrObject::adopt_src_from; + // Context-aware src helpers. Resolve Design via this->design and + // route to the per-Design meta vector; assert the module is attached. + Twine::Id src_id() const; + Twine::Id src_ref() const { return src_id(); } + void set_src_id(Twine::Id id); void set_src_attribute(const RTLIL::SrcAttr &src); std::string get_src_attribute() const; - // Transfer src from `source` verbatim (same pool). Asserts attached - // to a design — derives the pool via module->design->src_twines. void adopt_src_from(const RTLIL::AttrObject *source); + void absorb_attrs(dict &&buf); Module(); virtual ~Module(); diff --git a/kernel/unstable/patch.cc b/kernel/unstable/patch.cc index 631960e5e..60f3744e3 100644 --- a/kernel/unstable/patch.cc +++ b/kernel/unstable/patch.cc @@ -105,9 +105,9 @@ namespace { pool.dump("twine pool state"); } for (Cell* c : targets) - c->set_src_id(&pool, merged); + c->set_src_id(merged); if (merge_src_into) - merge_src_into->set_src_id(&pool, merged); + merge_src_into->set_src_id(merged); pool.release(merged); } diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc index 5d86b6c3e..946c55358 100644 --- a/passes/cmds/chformal.cc +++ b/passes/cmds/chformal.cc @@ -376,7 +376,7 @@ struct ChformalPass : public Pass { Cell *cover = module->addCell(NEW_ID_SUFFIX("coverenable"), ID($check)); cover->attributes = cell->attributes; if (cell->src_id() != Twine::Null && module->design) - cover->set_src_id(&module->design->src_twines, cell->src_id()); + cover->set_src_id(cell->src_id()); cover->parameters = cell->parameters; cover->setParam(ID(FLAVOR), Const("cover")); @@ -423,7 +423,7 @@ struct ChformalPass : public Pass { plain_cell->attributes = cell->attributes; if (cell->src_id() != Twine::Null && module->design) - plain_cell->set_src_id(&module->design->src_twines, cell->src_id()); + plain_cell->set_src_id(cell->src_id()); SigBit sig_a = cell->getPort(ID::A); SigBit sig_en = cell->getPort(ID::EN); diff --git a/passes/cmds/printattrs.cc b/passes/cmds/printattrs.cc index 99f695bc3..cd91854bf 100644 --- a/passes/cmds/printattrs.cc +++ b/passes/cmds/printattrs.cc @@ -54,12 +54,12 @@ struct PrintAttrsPass : public Pass { log_assert(x.flags & RTLIL::CONST_FLAG_STRING || x.flags == RTLIL::CONST_FLAG_NONE); //intended to fail } - static void log_src(const Yosys::TwinePool *pool, const RTLIL::AttrObject *obj, const unsigned int indent) { + static void log_src(const RTLIL::Design *design, const RTLIL::AttrObject *obj, const unsigned int indent) { // Emit src outside the attributes loop — it lives on the typed - // src_id_ field, not in obj->attributes. - if (obj->src_id() != Twine::Null && pool) + // meta-vector slot, not in obj->attributes. + if (design && design->obj_src_id(obj) != Twine::Null) log("%s(* src=\"%s\" *)\n", get_indent_str(indent), - obj->get_src_attribute(pool).c_str()); + design->get_src_attribute(obj).c_str()); } void execute(std::vector args, RTLIL::Design *design) override @@ -73,7 +73,7 @@ struct PrintAttrsPass : public Pass { if (design->selected_whole_module(mod)) { log("%s%s\n", get_indent_str(indent), mod->name.unescape()); indent += 2; - log_src(design ? &design->src_twines : nullptr, mod, indent); + log_src(design, mod, indent); for (auto &it : mod->attributes) log_const(it.first, it.second, indent); } @@ -81,7 +81,7 @@ struct PrintAttrsPass : public Pass { for (auto cell : mod->selected_cells()) { log("%s%s\n", get_indent_str(indent), cell->name.unescape()); indent += 2; - log_src(design ? &design->src_twines : nullptr, cell, indent); + log_src(design, cell, indent); for (auto &it : cell->attributes) log_const(it.first, it.second, indent); indent -= 2; @@ -90,7 +90,7 @@ struct PrintAttrsPass : public Pass { for (auto wire : mod->selected_wires()) { log("%s%s\n", get_indent_str(indent), wire->name.unescape()); indent += 2; - log_src(design ? &design->src_twines : nullptr, wire, indent); + log_src(design, wire, indent); for (auto &it : wire->attributes) log_const(it.first, it.second, indent); indent -= 2; diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 7dcb6d292..7eae5065d 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -145,14 +145,14 @@ static bool match_attr(const dict &attributes, co // through the normal match_attr path. Other ID::src-shaped patterns like // wildcards still flow through the (empty) dict and won't match src — those // uses were rare and the dict-path migration is a separate concern. -static bool match_attr(const Yosys::TwinePool *pool, const RTLIL::AttrObject *obj, const std::string &match_expr) +static bool match_attr(const RTLIL::Design *design, const RTLIL::AttrObject *obj, const std::string &match_expr) { - if (obj->src_id() != Twine::Null && pool) { + if (design && obj->meta_idx_ != RTLIL::AttrObject::NO_META) { size_t pos = match_expr.find_first_of(""); std::string name_part = (pos == std::string::npos) ? match_expr : match_expr.substr(0, pos); if (name_part == "src" || name_part == "\\src") { dict synthesized; - synthesized[RTLIL::ID::src] = RTLIL::Const(obj->get_src_attribute(pool)); + synthesized[RTLIL::ID::src] = RTLIL::Const(design->get_src_attribute(obj)); return match_attr(synthesized, match_expr); } } @@ -971,18 +971,17 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "a:") == 0) { - Yosys::TwinePool *pool = design ? &design->src_twines : nullptr; for (auto wire : mod->wires()) - if (match_attr(pool, wire, arg_memb.substr(2))) + if (match_attr(design, wire, arg_memb.substr(2))) sel.selected_members[mod->name].insert(wire->name); for (auto &it : mod->memories) - if (match_attr(pool, it.second, arg_memb.substr(2))) + if (match_attr(design, it.second, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); for (auto cell : mod->cells()) - if (match_attr(pool, cell, arg_memb.substr(2))) + if (match_attr(design, cell, arg_memb.substr(2))) sel.selected_members[mod->name].insert(cell->name); for (auto &it : mod->processes) - if (match_attr(pool, it.second, arg_memb.substr(2))) + if (match_attr(design, it.second, arg_memb.substr(2))) sel.selected_members[mod->name].insert(it.first); } else if (arg_memb.compare(0, 2, "r:") == 0) { diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index ab0277cd1..314a62175 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -116,8 +116,10 @@ struct MemoryMapWorker // possibly-Concat src as a single pipe-joined leaf on every // new cell. set_src_attribute's parse_ref path retains the // pool slot directly. - mem_src = (mem.module && mem.module->design && mem.src_id() != Twine::Null) ? - TwinePool::format_ref(mem.src_id()) : std::string(); + { + Twine::Id mid = (mem.module && mem.module->design) ? mem.module->design->obj_src_id(&mem) : Twine::Null; + mem_src = (mid != Twine::Null) ? TwinePool::format_ref(mid) : std::string(); + } SigSpec init_data = mem.get_init_data(); diff --git a/passes/proc/proc_rom.cc b/passes/proc/proc_rom.cc index 2e707dd8e..bdf37825d 100644 --- a/passes/proc/proc_rom.cc +++ b/passes/proc/proc_rom.cc @@ -185,8 +185,8 @@ struct RomWorker mem.emit(); if (sw->src_id() != Twine::Null && module->design) { - mem.inits[0].cell->set_src_id(&module->design->src_twines, sw->src_id()); - mem.rd_ports[0].cell->set_src_id(&module->design->src_twines, sw->src_id()); + mem.inits[0].cell->set_src_id(sw->src_id()); + mem.rd_ports[0].cell->set_src_id(sw->src_id()); } for (auto cs: sw->cases) diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc index 66447deed..9bd08ecd1 100644 --- a/passes/sat/assertpmux.cc +++ b/passes/sat/assertpmux.cc @@ -177,7 +177,7 @@ struct AssertpmuxWorker Cell *assert_cell = module->addAssert(NEW_ID, assert_a, assert_en); if (pmux->src_id() != Twine::Null && module->design) - assert_cell->set_src_id(&module->design->src_twines, pmux->src_id()); + assert_cell->set_src_id(pmux->src_id()); } }; diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index acf4c3111..d45586642 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1552,7 +1552,7 @@ void AbcModuleState::extract(AbcSigMap &assign_map, RTLIL::Design *design, RTLIL RTLIL::Wire *orig_wire = nullptr; RTLIL::Wire *wire = module->addWire(remap_name(w->name, &orig_wire)); if (orig_wire != nullptr && orig_wire->src_id() != Twine::Null && module->design) - wire->set_src_id(&module->design->src_twines, orig_wire->src_id()); + wire->set_src_id(orig_wire->src_id()); if (markgroups) wire->attributes[ID::abcgroup] = map_autoidx; design->select(module, wire); } diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 021644c3b..ab36abd20 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -29,7 +29,7 @@ YOSYS_NAMESPACE_BEGIN static void transfer_src (Cell* to, const Cell* from) { if (from->src_id() != Twine::Null && to->module && to->module->design) - to->set_src_id(&to->module->design->src_twines, from->src_id()); + to->set_src_id(from->src_id()); } void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) diff --git a/techlibs/ice40/ice40_wrapcarry.cc b/techlibs/ice40/ice40_wrapcarry.cc index ebed9b447..084d7f0c4 100644 --- a/techlibs/ice40/ice40_wrapcarry.cc +++ b/techlibs/ice40/ice40_wrapcarry.cc @@ -71,11 +71,10 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) // Propagate one of the cell-level srcs to the wrapper too so backends // emitting `attribute \src` see a usable value on the wrapper. if (cell->module && cell->module->design) { - TwinePool *pool = &cell->module->design->src_twines; if (st.carry->src_id() != Twine::Null) - cell->set_src_id(pool, st.carry->src_id()); + cell->set_src_id(st.carry->src_id()); else if (st.lut->src_id() != Twine::Null) - cell->set_src_id(pool, st.lut->src_id()); + cell->set_src_id(st.lut->src_id()); } cell->attributes[IdString{"\\SB_LUT4.name"}] = Const(st.lut->name.str()); if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep))