diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index e2c0d3640..469c9eeee 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3304,6 +3304,14 @@ void RTLIL::Module::add(RTLIL::Process *process) log_assert(count_id(process->name) == 0); processes[process->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); + for (auto *sync : process->syncs) + for (auto &mwa : sync->mem_write_actions) + mwa.module = this; } void RTLIL::Module::add(RTLIL::Binding *binding) @@ -6405,6 +6413,20 @@ bool RTLIL::CaseRule::empty() const return actions.empty() && switches.empty(); } +void RTLIL::CaseRule::setModuleRecursive(RTLIL::Module *m) +{ + module = m; + for (auto *sw : switches) + sw->setModuleRecursive(m); +} + +void RTLIL::SwitchRule::setModuleRecursive(RTLIL::Module *m) +{ + module = m; + for (auto *cs : cases) + cs->setModuleRecursive(m); +} + RTLIL::CaseRule *RTLIL::CaseRule::clone() const { RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 2a268ef11..b28b73115 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -2363,6 +2363,14 @@ public: struct RTLIL::CaseRule : public RTLIL::AttrObject { + // Back-pointer to the owning module. Set by the frontend / kernel + // attach path before any src access; the per-Design src meta vector + // is resolved as `module->design`. Frontends that construct an + // inner-process tree must call setModuleRecursive() on the root before + // the tree is consumed (e.g. before set_src_attribute is invoked on + // any nested CaseRule/SwitchRule/MemWriteAction). + RTLIL::Module *module = nullptr; + std::vector compare; std::vector actions; std::vector switches; @@ -2371,6 +2379,12 @@ struct RTLIL::CaseRule : public RTLIL::AttrObject bool empty() const; + // 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); + template void rewrite_sigspecs(T &functor); template void rewrite_sigspecs2(T &functor); RTLIL::CaseRule *clone() const; @@ -2378,6 +2392,9 @@ struct RTLIL::CaseRule : public RTLIL::AttrObject struct RTLIL::SwitchRule : public RTLIL::AttrObject { + // Back-pointer to the owning module; see CaseRule::module. + RTLIL::Module *module = nullptr; + RTLIL::SigSpec signal; std::vector cases; @@ -2385,6 +2402,8 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject bool empty() const; + void setModuleRecursive(RTLIL::Module *m); + template void rewrite_sigspecs(T &functor); template void rewrite_sigspecs2(T &functor); RTLIL::SwitchRule *clone() const; @@ -2392,6 +2411,9 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject struct RTLIL::MemWriteAction : RTLIL::AttrObject { + // Back-pointer to the owning module; see CaseRule::module. + RTLIL::Module *module = nullptr; + RTLIL::IdString memid; RTLIL::SigSpec address; RTLIL::SigSpec data;