diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index e6d417d6c..3bfb135af 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -971,16 +971,15 @@ void RTLIL::Design::obj_set_src_id_by_idx(uint32_t &meta_idx, Twine::Id id) return; meta_idx = alloc_obj_meta(); } - Twine::Id &slot = obj_meta_src_[meta_idx]; - if (slot == id) + ObjMeta &m = obj_meta_[meta_idx]; + if (m.src == 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. + if (m.src != Twine::Null) + src_twines.release(m.src); + m.src = id; + if (m.src != Twine::Null) + src_twines.retain(m.src); + if (m.src == Twine::Null && m.name.empty()) { free_obj_meta(meta_idx); meta_idx = RTLIL::AttrObject::NO_META; } @@ -990,13 +989,42 @@ 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; + ObjMeta &m = obj_meta_[meta_idx]; + if (m.src != Twine::Null) { + src_twines.release(m.src); + m.src = Twine::Null; + } + if (m.name.empty()) { + free_obj_meta(meta_idx); + meta_idx = RTLIL::AttrObject::NO_META; + } +} + +void RTLIL::Design::obj_set_name_by_idx(uint32_t &meta_idx, RTLIL::IdString name) +{ + if (meta_idx == RTLIL::AttrObject::NO_META) { + if (name.empty()) + return; + meta_idx = alloc_obj_meta(); + } + ObjMeta &m = obj_meta_[meta_idx]; + m.name = name; + if (m.name.empty() && m.src == Twine::Null) { + free_obj_meta(meta_idx); + meta_idx = RTLIL::AttrObject::NO_META; + } +} + +void RTLIL::Design::obj_release_name_by_idx(uint32_t &meta_idx) +{ + if (meta_idx == RTLIL::AttrObject::NO_META) + return; + ObjMeta &m = obj_meta_[meta_idx]; + m.name = RTLIL::IdString(); + if (m.src == Twine::Null) { + free_obj_meta(meta_idx); + meta_idx = RTLIL::AttrObject::NO_META; } - free_obj_meta(meta_idx); - meta_idx = RTLIL::AttrObject::NO_META; } void RTLIL::Design::set_src_attribute(RTLIL::AttrObject *obj, const RTLIL::SrcAttr &src) @@ -1094,18 +1122,19 @@ uint32_t RTLIL::Design::alloc_obj_meta() if (!obj_meta_free_.empty()) { uint32_t idx = obj_meta_free_.back(); obj_meta_free_.pop_back(); - obj_meta_src_[idx] = Twine::Null; + obj_meta_[idx] = ObjMeta{}; return idx; } - uint32_t idx = static_cast(obj_meta_src_.size()); - obj_meta_src_.push_back(Twine::Null); + uint32_t idx = static_cast(obj_meta_.size()); + obj_meta_.emplace_back(); return idx; } void RTLIL::Design::free_obj_meta(uint32_t idx) { - log_assert(idx < obj_meta_src_.size()); - log_assert(obj_meta_src_[idx] == Twine::Null); + log_assert(idx < obj_meta_.size()); + log_assert(obj_meta_[idx].src == Twine::Null); + log_assert(obj_meta_[idx].name.empty()); obj_meta_free_.push_back(idx); } @@ -1212,18 +1241,19 @@ size_t RTLIL::Design::gc_twines() walk_attr_objects(this, [&](RTLIL::AttrObject *obj) { if (obj->meta_idx_ == RTLIL::AttrObject::NO_META) return; - Twine::Id &slot = obj_meta_src_[obj->meta_idx_]; - if (slot == Twine::Null) + ObjMeta &m = obj_meta_[obj->meta_idx_]; + if (m.src == Twine::Null) return; - auto it = remap.find(slot); + auto it = remap.find(m.src); if (it == remap.end()) { - // 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; + m.src = Twine::Null; + if (m.name.empty()) { + free_obj_meta(obj->meta_idx_); + obj->meta_idx_ = RTLIL::AttrObject::NO_META; + } return; } - slot = it->second; + m.src = it->second; }); return before - src_twines.size(); @@ -1684,7 +1714,7 @@ void RTLIL::Design::clone_into(RTLIL::Design *dst) const // 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_ = obj_meta_; 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 diff --git a/kernel/rtlil.h b/kernel/rtlil.h index b74791f71..338b7442a 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1953,42 +1953,39 @@ struct RTLIL::Design // via cell->module->design->src_twines. TwinePool src_twines; - // Per-object src metadata, indexed by AttrObject::meta_idx_. Holds the - // Twine::Id for an object's src — the future home of any other per- - // object cold metadata we want to evacuate from inline storage (e.g. - // name once IdString/Twine unify). Freed slots are recycled via - // obj_meta_free_ (LIFO), mirroring TwinePool's freelist. - // - // alloc_obj_meta returns a fresh index whose entry is Twine::Null; - // free_obj_meta requires the slot's src_id to already have been - // released via src_twines.release() — the freelist only handles - // the index itself, not the referenced pool slot. - std::vector obj_meta_src_; + // Per-object metadata indexed by AttrObject::meta_idx_. Slots are + // allocated lazily on first non-null write and recycled via the + // LIFO freelist obj_meta_free_. Both src and name share one slot + // so subtypes that carry either pay only one index field. + struct ObjMeta { + Twine::Id src = Twine::Null; + RTLIL::IdString name; + }; + std::vector obj_meta_; std::vector obj_meta_free_; 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]; + return obj_meta_[meta_idx].src; } - // 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). + // `meta_idx` is mutated as needed: NO_META -> allocated slot on first + // non-null write; allocated slot -> NO_META if src cleared and name empty. 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. + RTLIL::IdString obj_name_by_idx(uint32_t meta_idx) const { + if (meta_idx == RTLIL::AttrObject::NO_META) + return RTLIL::IdString(); + return obj_meta_[meta_idx].name; + } + void obj_set_name_by_idx(uint32_t &meta_idx, RTLIL::IdString name); + void obj_release_name_by_idx(uint32_t &meta_idx); + Twine::Id obj_src_id(const RTLIL::AttrObject *obj) const { return obj_src_id_by_idx(obj->meta_idx_); } @@ -1998,6 +1995,15 @@ struct RTLIL::Design void obj_release_src(RTLIL::AttrObject *obj) { obj_release_src_by_idx(obj->meta_idx_); } + RTLIL::IdString obj_name(const RTLIL::AttrObject *obj) const { + return obj_name_by_idx(obj->meta_idx_); + } + void obj_set_name(RTLIL::AttrObject *obj, RTLIL::IdString name) { + obj_set_name_by_idx(obj->meta_idx_, name); + } + void obj_release_name(RTLIL::AttrObject *obj) { + obj_release_name_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