mirror of
https://github.com/YosysHQ/yosys
synced 2026-07-15 03:35:40 +00:00
twine: fix replayability, reduce TwineSearch usage
This commit is contained in:
parent
e9eb3889b7
commit
7c73fd62e4
41 changed files with 273 additions and 272 deletions
|
|
@ -39,12 +39,6 @@ void manufacture_info(InputType flop, OutputType& info, FfInitVals *initvals) {
|
|||
info.sig_q = cell->getPort(TW::Q);
|
||||
info.width = GetSize(info.sig_q);
|
||||
info.attributes = cell->attributes;
|
||||
// Carry src across construction → emit() as an owning Twine
|
||||
// reference. Retaining a slot on the source pool keeps it
|
||||
// alive even if the source cell gets removed between
|
||||
// manufacture_info() and emit(); emit() then transfers the
|
||||
// id verbatim into the new cell — no flatten/re-intern, no
|
||||
// pipe-leaf risk for cells whose src is a Concat.
|
||||
if (cell->src_id() != Twine::Null && cell->module && cell->module->design)
|
||||
info.src_twine = cell->src_id();
|
||||
if (initvals)
|
||||
|
|
@ -762,7 +756,6 @@ Cell *FfData::emit() {
|
|||
}
|
||||
}
|
||||
// src is carried in info.src_twine (an OwnedTwine retaining the
|
||||
// source slot). Transfer the id verbatim to the new cell — same
|
||||
// pool, no flatten. The OwnedTwine still holds its own ref until
|
||||
// FfData is destroyed; set_src_id retains on the cell's behalf.
|
||||
cell->attributes = attributes;
|
||||
|
|
|
|||
|
|
@ -172,8 +172,9 @@ struct FfData : FfTypeData {
|
|||
dict<IdString, Const> attributes;
|
||||
// Stashed src across construction → emit. Refcount-managed so the
|
||||
// source cell's pool slot survives if the cell itself is removed
|
||||
// before emit() runs. Empty when the source cell had no src.
|
||||
TwineRef src_twine;
|
||||
// before emit() runs. Null when the source cell had no src (default
|
||||
// TwineRef() is index 0, a valid constid, so it must be Null here).
|
||||
TwineRef src_twine = Twine::Null;
|
||||
|
||||
FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
|
||||
width = 0;
|
||||
|
|
|
|||
|
|
@ -887,7 +887,6 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
|||
return nullptr;
|
||||
|
||||
// Keep src as a "@N" reference into the design's twine pool throughout
|
||||
// — never flatten to a literal path string. That way every addX call
|
||||
// below adopts the same slot as Mem itself (via set_src_attribute's
|
||||
// "@N" parse_ref path), and there's no flatten → re-intern → pipe-
|
||||
// leaf round-trip on cells whose src is a Concat node.
|
||||
|
|
@ -998,7 +997,6 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
|
|||
|
||||
IdString name = stringf("$%s$rdreg[%d]", memid, idx);
|
||||
FfData ff(module, initvals, name);
|
||||
// Carry mem's src into the ff via the OwnedTwine handle — same
|
||||
// pool, direct id retain. emit() transfers verbatim.
|
||||
ff.src_twine = mem_src;
|
||||
ff.width = GetSize(port.data);
|
||||
|
|
|
|||
|
|
@ -953,7 +953,6 @@ bool RTLIL::AttrObject::get_bool_attribute(IdString id) const
|
|||
void RTLIL::AttrObject::set_string_attribute(IdString id, string value)
|
||||
{
|
||||
// ID::src on the base AttrObject is not routable here because the base
|
||||
// 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");
|
||||
|
|
@ -965,7 +964,6 @@ void RTLIL::AttrObject::set_string_attribute(IdString id, string value)
|
|||
|
||||
string RTLIL::AttrObject::get_string_attribute(IdString id) const
|
||||
{
|
||||
// ID::src is not in the dict — callers must use the subtype helper.
|
||||
log_assert(id != ID::src && "get_string_attribute(ID::src) on AttrObject base; use the subtype helper");
|
||||
std::string value;
|
||||
const auto it = attributes.find(id);
|
||||
|
|
@ -1821,22 +1819,22 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_modules(RTLIL::SelectPartial
|
|||
switch (boxes)
|
||||
{
|
||||
case RTLIL::SB_UNBOXED_WARN:
|
||||
log_warning("Ignoring boxed module %s.\n", twines.str(it.first).c_str());
|
||||
log_warning("Ignoring boxed module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SB_EXCL_BB_WARN:
|
||||
log_warning("Ignoring blackbox module %s.\n", twines.str(it.first).c_str());
|
||||
log_warning("Ignoring blackbox module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SB_UNBOXED_ERR:
|
||||
log_error("Unsupported boxed module %s.\n", twines.str(it.first).c_str());
|
||||
log_error("Unsupported boxed module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SB_EXCL_BB_ERR:
|
||||
log_error("Unsupported blackbox module %s.\n", twines.str(it.first).c_str());
|
||||
log_error("Unsupported blackbox module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SB_UNBOXED_CMDERR:
|
||||
log_cmd_error("Unsupported boxed module %s.\n", twines.str(it.first).c_str());
|
||||
log_cmd_error("Unsupported boxed module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SB_EXCL_BB_CMDERR:
|
||||
log_cmd_error("Unsupported blackbox module %s.\n", twines.str(it.first).c_str());
|
||||
log_cmd_error("Unsupported blackbox module %s.\n", log_id(it.second));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1845,13 +1843,13 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_modules(RTLIL::SelectPartial
|
|||
switch(partials)
|
||||
{
|
||||
case RTLIL::SELECT_WHOLE_WARN:
|
||||
log_warning("Ignoring partially selected module %s.\n", twines.str(it.first).c_str());
|
||||
log_warning("Ignoring partially selected module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SELECT_WHOLE_ERR:
|
||||
log_error("Unsupported partially selected module %s.\n", twines.str(it.first).c_str());
|
||||
log_error("Unsupported partially selected module %s.\n", log_id(it.second));
|
||||
break;
|
||||
case RTLIL::SELECT_WHOLE_CMDERR:
|
||||
log_cmd_error("Unsupported partially selected module %s.\n", twines.str(it.first).c_str());
|
||||
log_cmd_error("Unsupported partially selected module %s.\n", log_id(it.second));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1893,7 +1891,6 @@ RTLIL::Module::~Module()
|
|||
delete pr.second;
|
||||
for (auto binding : bindings_)
|
||||
delete binding;
|
||||
// Module's own src — release last so the pool stays valid for
|
||||
// inner releases above.
|
||||
if (design)
|
||||
design->obj_release_src(this);
|
||||
|
|
@ -3172,7 +3169,6 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons
|
|||
// 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.
|
||||
if (this->design && new_mod->design)
|
||||
copy_src_into(this, this->design, new_mod, new_mod->design);
|
||||
|
|
@ -3189,7 +3185,6 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons
|
|||
return;
|
||||
// Preserve name already set by addWire/addCell (in dst's pool).
|
||||
TwineRef saved_name = dst_obj->meta_ ? dst_obj->meta_->name : Twine::Null;
|
||||
// Recycle old meta slot (no field releases — name's retain lives on).
|
||||
if (dst_obj->meta_) {
|
||||
dst_obj->meta_->name = Twine::Null;
|
||||
dst_obj->meta_->src = Twine::Null;
|
||||
|
|
@ -3274,7 +3269,6 @@ void RTLIL::Module::cloneInto(RTLIL::Module *new_mod, bool src_id_verbatim) cons
|
|||
// TwinePool allocates slots sequentially as copy_src_into →
|
||||
// copy_from interns each wire's src, so the destination pool
|
||||
// ends up with leaves in the same order the frontend
|
||||
// originally interned them — that lets write_rtlil emit
|
||||
// byte-equal "@N" refs across single-module clones into an
|
||||
// existing destination design.
|
||||
// Re-intern each wire/cell name from the source design's pool into
|
||||
|
|
@ -3472,7 +3466,6 @@ void RTLIL::Module::add(RTLIL::Process *process)
|
|||
processes[process->meta_->name] = process;
|
||||
process->module = this;
|
||||
// Propagate module back-pointer to every CaseRule/SwitchRule in the
|
||||
// root case tree and every MemWriteAction in the sync rules — so the
|
||||
// per-Design src meta vector can be resolved from any inner-process
|
||||
// AttrObject via `module->design` after attach.
|
||||
process->root_case.setModuleRecursive(this);
|
||||
|
|
@ -3853,7 +3846,6 @@ RTLIL::Memory *RTLIL::Module::addMemory(TwineRef name, const RTLIL::Memory *othe
|
|||
mem->size = other->size;
|
||||
mem->attributes = other->attributes;
|
||||
{
|
||||
// Clone path drops src for now — caller responsible for migrating
|
||||
// src across the design boundary if needed. addMemory(name) is the
|
||||
// common case.
|
||||
(void)other;
|
||||
|
|
@ -6783,7 +6775,6 @@ RTLIL::CaseRule *RTLIL::CaseRule::clone() const
|
|||
new_caserule->compare = compare;
|
||||
new_caserule->actions = actions;
|
||||
new_caserule->attributes = attributes;
|
||||
// clone() drops src — CaseRule has no pool backpointer, so we can't
|
||||
// retain. The caller (Module::addProcess(name, other)) is responsible
|
||||
// for walking the cloned tree and migrating src via context.
|
||||
for (auto &it : switches)
|
||||
|
|
@ -6807,7 +6798,6 @@ RTLIL::SwitchRule *RTLIL::SwitchRule::clone() const
|
|||
RTLIL::SwitchRule *new_switchrule = new RTLIL::SwitchRule;
|
||||
new_switchrule->signal = signal;
|
||||
new_switchrule->attributes = attributes;
|
||||
// clone() drops src — see CaseRule::clone for rationale.
|
||||
for (auto &it : cases)
|
||||
new_switchrule->cases.push_back(it->clone());
|
||||
return new_switchrule;
|
||||
|
|
@ -6821,7 +6811,6 @@ RTLIL::SyncRule *RTLIL::SyncRule::clone() const
|
|||
new_syncrule->signal = signal;
|
||||
new_syncrule->actions = actions;
|
||||
new_syncrule->mem_write_actions = mem_write_actions;
|
||||
// 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).
|
||||
|
|
@ -6974,7 +6963,6 @@ void RTLIL::Memory::absorb_attrs(dict<IdString, RTLIL::Const> &&buf)
|
|||
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.
|
||||
TwineRef RTLIL::CaseRule::src_id() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -555,12 +555,16 @@ struct RTLIL::IdString
|
|||
|
||||
// often one needs to check if a given IdString is part of a list (for example a list
|
||||
// of cell types). the following functions helps with that.
|
||||
// Constrained to 2+ args so a single argument always resolves to a concrete
|
||||
// overload below; otherwise a single argument matching none of them (e.g. a
|
||||
// TwineRef) would re-match this template and recurse infinitely.
|
||||
template<typename... Args>
|
||||
bool in(const Args &... args) const {
|
||||
bool in(const Args &... args) const requires (sizeof...(Args) != 1) {
|
||||
return (... || in(args));
|
||||
}
|
||||
|
||||
bool in(IdString rhs) const { return *this == rhs; }
|
||||
inline bool in(TwineRef rhs) const;
|
||||
bool in(const char *rhs) const { return *this == rhs; }
|
||||
bool in(const std::string &rhs) const { return *this == rhs; }
|
||||
inline bool in(const pool<IdString> &rhs) const;
|
||||
|
|
@ -600,6 +604,8 @@ inline bool operator==(TwineRef a, RTLIL::IdString b) {
|
|||
}
|
||||
inline bool operator==(RTLIL::IdString a, TwineRef b) { return b == a; }
|
||||
|
||||
inline bool RTLIL::IdString::in(TwineRef rhs) const { return *this == rhs; }
|
||||
|
||||
struct RTLIL::OwningIdString : public RTLIL::IdString {
|
||||
inline OwningIdString() { }
|
||||
inline OwningIdString(const OwningIdString &str) : IdString(str) { get_reference(); }
|
||||
|
|
@ -1402,7 +1408,6 @@ inline bool operator!=(RTLIL::IdString lhs, const RTLIL::NameMasqBase<Derived> &
|
|||
|
||||
// Read-only masquerade for Wire::name. Reads materialise the TwineRef in
|
||||
// the owning Design's twines pool into a temporary IdString. Writes are
|
||||
// intentionally unsupported — use Module::rename(wire, new_name) instead.
|
||||
// Defined before Wire so it can be used as a [[no_unique_address]] member.
|
||||
struct RTLIL::WireNameMasq : RTLIL::NameMasqBase<RTLIL::WireNameMasq> {
|
||||
WireNameMasq() = default;
|
||||
|
|
@ -2194,7 +2199,6 @@ struct RTLIL::Design
|
|||
|
||||
// Wholesale-copy this design into `dst`. `dst` must be empty (no
|
||||
// modules). Copies twines verbatim and clones each module
|
||||
// preserving src_id_ values directly — avoids the per-module
|
||||
// copy_from pool rebuild and yields byte-identical RTLIL output
|
||||
// across design -push/-pop, -save/-load, etc.
|
||||
void clone_into(RTLIL::Design *dst) const;
|
||||
|
|
@ -2325,7 +2329,6 @@ private:
|
|||
friend struct RTLIL::Patch;
|
||||
public:
|
||||
// Shadows NamedObject::name. Reads materialise via twines; writes
|
||||
// are a compile error — use Module::rename(wire, new_name) instead.
|
||||
[[no_unique_address]] RTLIL::WireNameMasq name;
|
||||
|
||||
Hasher::hash_t hashidx_;
|
||||
|
|
@ -2395,7 +2398,6 @@ struct RTLIL::Memory : public RTLIL::AttrObject
|
|||
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 resolve uniformly via module->design.
|
||||
|
|
@ -2436,7 +2438,6 @@ private:
|
|||
bool bufnorm_handle_setPort(TwineRef portname, RTLIL::SigSpec &signal, dict<TwineRef, RTLIL::SigSpec>::iterator conn_it);
|
||||
public:
|
||||
// Shadows NamedObject::name. Reads materialise via twines; writes
|
||||
// are a compile error — use Module::rename(cell, new_name) instead.
|
||||
[[no_unique_address]] RTLIL::CellNameMasq name;
|
||||
|
||||
Hasher::hash_t hashidx_;
|
||||
|
|
@ -2525,7 +2526,6 @@ struct RTLIL::CaseRule : public RTLIL::AttrObject
|
|||
|
||||
// Walk the whole CaseRule subtree (this case, every switch, every
|
||||
// nested case, every MemWriteAction inside this process's sync rules
|
||||
// — those are reached through Process, not here) and set `module` on
|
||||
// each. Idempotent.
|
||||
void setModuleRecursive(RTLIL::Module *m);
|
||||
|
||||
|
|
@ -2706,7 +2706,6 @@ inline Hasher RTLIL::SigBit::hash_into(Hasher h) const {
|
|||
inline Hasher RTLIL::SigBit::hash_top() const {
|
||||
Hasher h;
|
||||
if (wire) {
|
||||
// Use the wire's name (TwineRef) directly — avoids IdString materialisation.
|
||||
TwineRef name = wire->meta_ ? wire->meta_->name : Twine::Null;
|
||||
h.eat(name);
|
||||
h.eat(offset);
|
||||
|
|
@ -3075,7 +3074,6 @@ public:
|
|||
virtual RTLIL::Module *clone() const;
|
||||
// Clone variant that attaches the new module to `dst` BEFORE cloneInto
|
||||
// runs. This is the right pattern when the destination design is known
|
||||
// up front — it avoids the "detached module, attach later" flow and
|
||||
// the pending-literal src stashing it entails. Subtypes override to
|
||||
// preserve their type (AstModule). `src_id_verbatim` is forwarded to
|
||||
// cloneInto.
|
||||
|
|
@ -3104,7 +3102,6 @@ public:
|
|||
return design->selected_member(meta_->name, member->meta_->name);
|
||||
}
|
||||
|
||||
// Primary (fast) overloads — key directly into the dict.
|
||||
RTLIL::Wire* wire(TwineRef id) {
|
||||
auto it = wires_.find(id);
|
||||
return it == wires_.end() ? nullptr : it->second;
|
||||
|
|
|
|||
|
|
@ -1172,7 +1172,6 @@ bool RTLIL::Cell::bufnorm_handle_setPort(TwineRef portname, SigSpec &signal, dic
|
|||
}
|
||||
|
||||
auto dir = port_dir(portname);
|
||||
// Fast path: connecting a full driverless wire to an output port — everything else
|
||||
// goes through the bufnorm queues and is handled during the next bufNormalize call
|
||||
if ((dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) && signal.is_wire()) {
|
||||
Wire *w = signal.as_wire();
|
||||
|
|
|
|||
|
|
@ -145,7 +145,6 @@ void twine_prepopulate() {
|
|||
// log_assert(parent->is_flat() && "Suffix parent must be a flat node (Leaf or Suffix)");
|
||||
// if (tail.empty()) {
|
||||
// // No tail means "the same string as parent". Hand back a fresh
|
||||
// // owning ref on parent — semantically equivalent to a degenerate
|
||||
// // suffix node, but we avoid allocating a slot for it.
|
||||
// retain(parent);
|
||||
// return parent;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ struct TW {
|
|||
};
|
||||
|
||||
#define TW(id) ((size_t)std::integral_constant<int, lookup_well_known_id(#id)>::value)
|
||||
// #define TW(name) TW::lookup(#name)
|
||||
|
||||
struct Twine {
|
||||
static constexpr TwineRef Null = std::numeric_limits<size_t>::max();
|
||||
|
|
@ -120,19 +119,31 @@ struct Twine {
|
|||
auto operator<=>(const Suffix&) const = default;
|
||||
};
|
||||
|
||||
struct AutoPrefix {
|
||||
|
||||
struct AutoSuffix {
|
||||
const std::string *prefix;
|
||||
std::string tail;
|
||||
auto operator<=>(const AutoPrefix&) const = default;
|
||||
auto operator<=>(const AutoSuffix&) const = default;
|
||||
};
|
||||
|
||||
std::variant<std::monostate, std::string, std::vector<TwineRef>, Suffix, AutoPrefix> data;
|
||||
std::variant<
|
||||
// Unused slot
|
||||
std::monostate,
|
||||
// "leaf", regular deduplicated string
|
||||
std::string,
|
||||
// "concat", for src only, requires concatenating character convention - '|' for src attributes, others for others in the future
|
||||
std::vector<TwineRef>,
|
||||
// "suffix", deduplicates shared prefixes
|
||||
Suffix,
|
||||
// transient suffix constructed with NEW_TWINE and NEW_TWINE_SUFFIX
|
||||
// turned into a regular Suffix when added to a TwinePool
|
||||
AutoSuffix> data;
|
||||
|
||||
bool is_dead() const { return std::holds_alternative<std::monostate>(data); }
|
||||
bool is_leaf() const { return std::holds_alternative<std::string>(data); }
|
||||
bool is_concat() const { return std::holds_alternative<std::vector<TwineRef>>(data); }
|
||||
bool is_suffix() const { return std::holds_alternative<Suffix>(data); }
|
||||
bool is_auto_prefix() const { return std::holds_alternative<AutoPrefix>(data); }
|
||||
bool is_auto_prefix() const { return std::holds_alternative<AutoSuffix>(data); }
|
||||
bool is_flat() const { return is_leaf() || is_suffix(); }
|
||||
const std::string &leaf() const { return std::get<std::string>(data); }
|
||||
const std::vector<TwineRef> &children() const { return std::get<std::vector<TwineRef>>(data); }
|
||||
|
|
@ -150,7 +161,6 @@ struct TwineHash {
|
|||
|
||||
size_t operator()(const Twine& t) const noexcept;
|
||||
size_t operator()(TwineRef ref) const noexcept;
|
||||
// size_t operator()(std::string_view v) const noexcept;
|
||||
};
|
||||
|
||||
struct TwineEq {
|
||||
|
|
@ -161,8 +171,6 @@ struct TwineEq {
|
|||
bool operator()(TwineRef a, TwineRef b) const noexcept;
|
||||
bool operator()(TwineRef a, const Twine& b) const noexcept;
|
||||
bool operator()(const Twine& a, TwineRef b) const noexcept;
|
||||
// bool operator()(TwineRef a, std::string_view b) const noexcept;
|
||||
// bool operator()(std::string_view a, TwineRef b) const noexcept;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -365,12 +373,8 @@ struct TwinePool {
|
|||
return ref;
|
||||
}
|
||||
|
||||
// Interns a structural Twine verbatim and returns the handle. Leaf content
|
||||
// is stored as-is — callers holding an escaped string must strip the '\'
|
||||
// and tag publicity themselves (or use the add(std::string) overload).
|
||||
// Suffix names inherit the prefix handle's publicity.
|
||||
TwineRef add(Twine t) {
|
||||
if (auto *ap = std::get_if<Twine::AutoPrefix>(&t.data)) {
|
||||
if (auto *ap = std::get_if<Twine::AutoSuffix>(&t.data)) {
|
||||
TwineRef pref = add_inner(Twine{*ap->prefix});
|
||||
return add_inner(Twine{Twine::Suffix{pref, std::move(ap->tail)}});
|
||||
}
|
||||
|
|
@ -612,7 +616,7 @@ struct DeepTwineEq {
|
|||
// Required by unordered_set to handle hash collisions between two TwineRefs.
|
||||
bool operator()(TwineRef a, TwineRef b) const {
|
||||
if (a == b) return true; // Index or structural equality shortcut
|
||||
std::string fb = flatten(b);
|
||||
std::string fb = pool->unescaped_str(b);
|
||||
return (*this)(a, std::string_view(fb));
|
||||
}
|
||||
|
||||
|
|
@ -660,7 +664,7 @@ struct TwineChildPool {
|
|||
|
||||
// Local analog of TwinePool::add; see there for the convention.
|
||||
TwineRef add(Twine t) {
|
||||
if (auto *ap = std::get_if<Twine::AutoPrefix>(&t.data)) {
|
||||
if (auto *ap = std::get_if<Twine::AutoSuffix>(&t.data)) {
|
||||
TwineRef pref = add_inner(Twine{*ap->prefix});
|
||||
return add_inner(Twine{Twine::Suffix{pref, std::move(ap->tail)}});
|
||||
}
|
||||
|
|
@ -731,6 +735,11 @@ struct TwineSearch {
|
|||
index.insert(STATIC_TWINE_END + idx);
|
||||
}
|
||||
}
|
||||
// Keep a hoisted search current after adding a ref to the pool, so the
|
||||
// search need not be rebuilt (O(pool)) between finds in a loop.
|
||||
void insert(TwineRef ref) {
|
||||
index.insert(twine_untag(ref));
|
||||
}
|
||||
// Escaped-name aware. Resolves both statics and locals by content.
|
||||
TwineRef find(std::string_view sv) const {
|
||||
bool is_public = !sv.empty() && sv[0] == '\\';
|
||||
|
|
|
|||
|
|
@ -134,7 +134,6 @@ namespace {
|
|||
void apply_src(Module* mod, Cell* root, const std::vector<Cell*>& extras,
|
||||
const std::vector<Cell*>& targets, Cell* merge_src_into)
|
||||
{
|
||||
// Without a design there's no pool — the cells can't carry typed
|
||||
// src, so silently drop merge-of-src in that path.
|
||||
if (!mod || !mod->design)
|
||||
return;
|
||||
|
|
@ -205,7 +204,6 @@ void Patch::patch(Cell* root_cell, TwineRef old_port, SigSpec new_sig,
|
|||
apply_src(mod, root_cell, extras, committed, merge_src_into);
|
||||
|
||||
// Drop root_cell's driver on the output port BEFORE wiring old_sig to
|
||||
// new_sig — otherwise old_sig would briefly have two drivers (root_cell
|
||||
// and new_sig) which signorm flags as conflicting.
|
||||
root_cell->unsetPort(old_port);
|
||||
|
||||
|
|
@ -213,7 +211,6 @@ void Patch::patch(Cell* root_cell, TwineRef old_port, SigSpec new_sig,
|
|||
map->add(old_sig, new_sig);
|
||||
mod->connect_incremental(old_sig, new_sig);
|
||||
|
||||
// Remove root cell only — no input-cone walk.
|
||||
mod->remove(root_cell);
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +274,6 @@ void Patch::commit_inheriting_src(Cell* src_source) {
|
|||
Cell *committed = commit_cell(std::move(cell));
|
||||
// commit_cell attaches the cell to mod, so adopt_src_from can
|
||||
// now resolve the pool via committed->module->design. Direct
|
||||
// id transfer — no flatten/re-intern detour.
|
||||
if (src_source)
|
||||
committed->adopt_src_from(src_source);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
// No virtual methods — subclasses cannot be dispatched through a Patch pointer.
|
||||
struct RTLIL::Patch : public CellAdderMixin<RTLIL::Patch>
|
||||
{
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -127,7 +127,6 @@ public:
|
|||
|
||||
|
||||
// ---------------------------------------------------
|
||||
// BitGrouper — partition output bits by a per-bit key
|
||||
// ---------------------------------------------------
|
||||
//
|
||||
// Many passes that split a multi-bit cell or word-level FF into smaller
|
||||
|
|
|
|||
|
|
@ -305,12 +305,12 @@ RTLIL::IdString new_id_suffix(std::string_view file, int line, std::string_view
|
|||
#define NEW_ID_SUFFIX(suffix) \
|
||||
YOSYS_NAMESPACE_PREFIX new_id_suffix(__FILE__, __LINE__, __FUNCTION__, suffix)
|
||||
#define NEW_TWINE \
|
||||
YOSYS_NAMESPACE_PREFIX Twine{YOSYS_NAMESPACE_PREFIX Twine::AutoPrefix{[](std::string_view func) -> const std::string * { \
|
||||
YOSYS_NAMESPACE_PREFIX Twine{YOSYS_NAMESPACE_PREFIX Twine::AutoSuffix{[](std::string_view func) -> const std::string * { \
|
||||
static std::unique_ptr<const std::string> prefix(YOSYS_NAMESPACE_PREFIX create_id_prefix(__FILE__, __LINE__, func)); \
|
||||
return prefix.get(); \
|
||||
}(__FUNCTION__), std::to_string(YOSYS_NAMESPACE_PREFIX autoidx++)}}
|
||||
#define NEW_TWINE_SUFFIX(suffix) \
|
||||
YOSYS_NAMESPACE_PREFIX Twine{YOSYS_NAMESPACE_PREFIX Twine::AutoPrefix{[](std::string_view func) -> const std::string * { \
|
||||
YOSYS_NAMESPACE_PREFIX Twine{YOSYS_NAMESPACE_PREFIX Twine::AutoSuffix{[](std::string_view func) -> const std::string * { \
|
||||
static std::unique_ptr<const std::string> prefix(YOSYS_NAMESPACE_PREFIX create_id_prefix(__FILE__, __LINE__, func)); \
|
||||
return prefix.get(); \
|
||||
}(__FUNCTION__), std::string(suffix) + "$" + std::to_string(YOSYS_NAMESPACE_PREFIX autoidx++)}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue