Fix mis-ignoring virtual interface member triggers (#5116 reopened) (#6613)

This commit is contained in:
Geza Lore 2025-10-29 22:27:15 +01:00 committed by GitHub
parent 50b89ac9b5
commit 287fdb7312
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 56 additions and 44 deletions

View File

@ -395,11 +395,16 @@ AstSenTree* createTriggerSenTree(AstNetlist* netlistp, AstVarScope* const vscp,
// Helper that creates virtual interface trigger resets
void addVirtIfaceTriggerAssignments(const VirtIfaceTriggers& virtIfaceTriggers,
size_t vifTriggerIndex, const TriggerKit& actTrig) {
for (const auto& p : virtIfaceTriggers) {
size_t vifTriggerIndex, size_t vifMemberTriggerIndex,
const TriggerKit& actTrig) {
for (const auto& p : virtIfaceTriggers.m_ifaceTriggers) {
actTrig.addExtraTriggerAssignment(p.second, vifTriggerIndex);
++vifTriggerIndex;
}
for (const auto& p : virtIfaceTriggers.m_memberTriggers) {
actTrig.addExtraTriggerAssignment(p.second, vifMemberTriggerIndex);
++vifMemberTriggerIndex;
}
}
// Order the combinational logic to create the settle loop
@ -490,9 +495,15 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
? extraTriggers.allocate("DPI export trigger")
: std::numeric_limits<unsigned>::max();
const size_t firstVifTriggerIndex = extraTriggers.size();
for (const auto& p : virtIfaceTriggers) {
for (const auto& p : virtIfaceTriggers.m_ifaceTriggers) {
extraTriggers.allocate("virtual interface: " + p.first->name());
}
const size_t firstVifMemberTriggerIndex = extraTriggers.size();
for (const auto& p : virtIfaceTriggers.m_memberTriggers) {
const auto& item = p.first;
extraTriggers.allocate("virtual interface member: " + item.m_ifacep->name() + "."
+ item.m_memberp->name());
}
// Gather the relevant sensitivity expressions and create the trigger kit
const auto& senTreeps = getSenTreesUsedBy({&logic});
@ -502,7 +513,8 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
if (dpiExportTriggerVscp) {
trig.addExtraTriggerAssignment(dpiExportTriggerVscp, dpiExportTriggerIndex);
}
addVirtIfaceTriggerAssignments(virtIfaceTriggers, firstVifTriggerIndex, trig);
addVirtIfaceTriggerAssignments(virtIfaceTriggers, firstVifTriggerIndex,
firstVifMemberTriggerIndex, trig);
// Remap sensitivities
remapSensitivities(logic, trig.m_map);
@ -522,7 +534,7 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
const auto& vifTriggeredIco
= virtIfaceTriggers.makeIfaceToSensMap(netlistp, firstVifTriggerIndex, trig.m_vscp);
const auto& vifMemberTriggeredIco
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifTriggerIndex, trig.m_vscp);
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifMemberTriggerIndex, trig.m_vscp);
// Create and Order the body function
AstCFunc* const icoFuncp = V3Order::order(
@ -747,25 +759,23 @@ void createEval(AstNetlist* netlistp, //
VirtIfaceTriggers::IfaceSensMap
VirtIfaceTriggers::makeIfaceToSensMap(AstNetlist* const netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const {
std::map<const AstIface*, AstSenTree*> ifaceToSensMap;
for (const auto& p : *this) {
ifaceToSensMap.emplace(
std::make_pair(p.first, createTriggerSenTree(netlistp, trigVscp, vifTriggerIndex)));
std::map<const AstIface*, AstSenTree*> map;
for (const auto& p : m_ifaceTriggers) {
map.emplace(p.first, createTriggerSenTree(netlistp, trigVscp, vifTriggerIndex));
++vifTriggerIndex;
}
return ifaceToSensMap;
return map;
}
VirtIfaceTriggers::IfaceMemberSensMap
VirtIfaceTriggers::makeMemberToSensMap(AstNetlist* const netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const {
IfaceMemberSensMap memberToSensMap;
IfaceMemberSensMap map;
for (const auto& p : m_memberTriggers) {
memberToSensMap.emplace(
std::make_pair(p.first, createTriggerSenTree(netlistp, trigVscp, vifTriggerIndex)));
map.emplace(p.first, createTriggerSenTree(netlistp, trigVscp, vifTriggerIndex));
++vifTriggerIndex;
}
return memberToSensMap;
return map;
}
//============================================================================
@ -866,9 +876,15 @@ void schedule(AstNetlist* netlistp) {
? extraTriggers.allocate("DPI export trigger")
: std::numeric_limits<unsigned>::max();
const size_t firstVifTriggerIndex = extraTriggers.size();
for (const auto& p : virtIfaceTriggers) {
for (const auto& p : virtIfaceTriggers.m_ifaceTriggers) {
extraTriggers.allocate("virtual interface: " + p.first->name());
}
const size_t firstVifMemberTriggerIndex = extraTriggers.size();
for (const auto& p : virtIfaceTriggers.m_memberTriggers) {
const auto& item = p.first;
extraTriggers.allocate("virtual interface member: " + item.m_ifacep->name() + "."
+ item.m_memberp->name());
}
const auto& senTreeps = getSenTreesUsedBy({&logicRegions.m_pre, //
&logicRegions.m_act, //
@ -885,7 +901,8 @@ void schedule(AstNetlist* netlistp) {
if (dpiExportTriggerVscp) {
actTrig.addExtraTriggerAssignment(dpiExportTriggerVscp, dpiExportTriggerIndex);
}
addVirtIfaceTriggerAssignments(virtIfaceTriggers, firstVifTriggerIndex, actTrig);
addVirtIfaceTriggerAssignments(virtIfaceTriggers, firstVifTriggerIndex,
firstVifMemberTriggerIndex, actTrig);
AstVarScope* const actTrigVscp = actTrig.m_vscp;
AstVarScope* const preTrigVscp = scopeTopp->createTempLike("__VpreTriggered", actTrigVscp);
@ -939,8 +956,8 @@ void schedule(AstNetlist* netlistp) {
const auto& vifTriggeredAct
= virtIfaceTriggers.makeIfaceToSensMap(netlistp, firstVifTriggerIndex, actTrig.m_vscp);
const auto& vifMemberTriggeredAct
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifTriggerIndex, actTrig.m_vscp);
const auto& vifMemberTriggeredAct = virtIfaceTriggers.makeMemberToSensMap(
netlistp, firstVifMemberTriggerIndex, actTrig.m_vscp);
AstCFunc* const actFuncp = V3Order::order(
netlistp, {&logicRegions.m_pre, &logicRegions.m_act, &logicReplicas.m_act}, trigToSenAct,
@ -979,8 +996,8 @@ void schedule(AstNetlist* netlistp) {
: nullptr;
const auto& vifTriggered
= virtIfaceTriggers.makeIfaceToSensMap(netlistp, firstVifTriggerIndex, trigVscp);
const auto& vifMemberTriggered
= virtIfaceTriggers.makeMemberToSensMap(netlistp, firstVifTriggerIndex, trigVscp);
const auto& vifMemberTriggered = virtIfaceTriggers.makeMemberToSensMap(
netlistp, firstVifMemberTriggerIndex, trigVscp);
const auto& timingDomains = timingKit.remapDomains(trigMap);
AstCFunc* const funcp = V3Order::order(

View File

@ -207,39 +207,33 @@ class VirtIfaceTriggers final {
// Represents a specific member in a virtual interface
struct IfaceMember final {
const AstIface* m_ifacep; // Interface type
const AstVar* m_memberVarp; // pointer to member field
IfaceMember(const AstIface* ifacep, const AstVar* memberVarp)
: m_ifacep{ifacep}
, m_memberVarp{memberVarp} {}
const AstVar* m_memberp; // Member variable
// TODO: sorting by pointer is non-deterministic
bool operator<(const IfaceMember& other) const {
if (m_ifacep != other.m_ifacep) return m_ifacep < other.m_ifacep;
return m_memberVarp < other.m_memberVarp;
return m_memberp < other.m_memberp;
}
};
public:
using IfaceMemberTrigger = std::pair<IfaceMember, AstVarScope*>;
using IfaceMemberTriggerVec = std::vector<IfaceMemberTrigger>;
using IfaceSensMap = std::map<const AstIface*, AstSenTree*>;
using IfaceMemberSensMap = std::map<IfaceMember, AstSenTree*>;
using IfaceTrigger = std::pair<const AstIface*, AstVarScope*>;
using IfaceTriggerVec = std::vector<IfaceTrigger>;
using IfaceSensMap = std::map<const AstIface*, AstSenTree*>;
std::vector<std::pair<const AstIface*, AstVarScope*>> m_ifaceTriggers;
std::vector<std::pair<IfaceMember, AstVarScope*>> m_memberTriggers;
IfaceMemberTriggerVec m_memberTriggers;
IfaceTriggerVec m_ifaceTriggers;
void addMemberTrigger(const AstIface* ifacep, const AstVar* memberVarp,
AstVarScope* triggerVscp) {
m_memberTriggers.emplace_back(IfaceMember(ifacep, memberVarp), triggerVscp);
void addIfaceTrigger(const AstIface* ifacep, AstVarScope* vscp) {
m_ifaceTriggers.emplace_back(ifacep, vscp);
}
void addMemberTrigger(const AstIface* ifacep, const AstVar* memberp, AstVarScope* vscp) {
m_memberTriggers.emplace_back(IfaceMember{ifacep, memberp}, vscp);
}
AstVarScope* findMemberTrigger(const AstIface* ifacep, const AstVar* memberVarp) const {
IfaceMember target{ifacep, memberVarp};
AstVarScope* findMemberTrigger(const AstIface* ifacep, const AstVar* memberp) const {
for (const auto& pair : m_memberTriggers) {
if (!(pair.first < target) && !(target < pair.first)) return pair.second;
const IfaceMember& item = pair.first;
if (item.m_ifacep == ifacep && item.m_memberp == memberp) return pair.second;
}
return nullptr;
}
@ -247,9 +241,6 @@ public:
IfaceMemberSensMap makeMemberToSensMap(AstNetlist* netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const;
void emplace_back(IfaceTrigger&& p) { m_ifaceTriggers.emplace_back(std::move(p)); }
IfaceTriggerVec::const_iterator begin() const { return m_ifaceTriggers.begin(); }
IfaceTriggerVec::const_iterator end() const { return m_ifaceTriggers.end(); }
IfaceSensMap makeIfaceToSensMap(AstNetlist* netlistp, size_t vifTriggerIndex,
AstVarScope* trigVscp) const;

View File

@ -117,7 +117,7 @@ private:
AstScope* const scopeTopp = m_netlistp->topScopep()->scopep();
AstVarScope* const vscp = scopeTopp->createTemp(m_vifTriggerNames.get(ifacep), 1);
ifacep->user1p(vscp);
m_triggers.emplace_back(std::make_pair(ifacep, vscp));
m_triggers.addIfaceTrigger(ifacep, vscp);
}
return new AstVarRef{flp, VN_AS(ifacep->user1p(), VarScope), VAccess::WRITE};
}

View File

@ -9,6 +9,8 @@
import vltest_bootstrap
test.skip("Test is broken, see #6613")
test.scenarios('simulator')
test.compile(verilator_flags2=['--binary'])

View File

@ -9,6 +9,8 @@
import vltest_bootstrap
test.skip("Test is broken, see #6613")
test.scenarios('simulator')
test.compile(verilator_flags2=['--binary'])