mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Fix same variable on the RHS forced to two different LHSs. (#6269)
This commit is contained in:
+25
-13
@@ -148,15 +148,16 @@ private:
|
||||
// AstVar::user1p -> ForceComponentsVar* instance (via m_forceComponentsVar)
|
||||
// AstVarScope::user1p -> ForceComponentsVarScope* instance (via m_forceComponentsVarScope)
|
||||
// AstVarRef::user2 -> Flag indicating not to replace reference
|
||||
// AstVarScope::user3 -> AstVarScope*, a `valVscp` force component for each VarScope of
|
||||
// forced RHS
|
||||
// AstVarScope::user4p -> AstNodeExpr*, the RHS expression
|
||||
// AstVarScope::user3p -> AstNodeExpr*, the RHS expression
|
||||
const VNUser1InUse m_user1InUse;
|
||||
const VNUser2InUse m_user2InUse;
|
||||
const VNUser3InUse m_user3InUse;
|
||||
const VNUser4InUse m_user4InUse;
|
||||
AstUser1Allocator<AstVar, ForceComponentsVar> m_forceComponentsVar;
|
||||
AstUser1Allocator<AstVarScope, ForceComponentsVarScope> m_forceComponentsVarScope;
|
||||
std::unordered_map<const AstVarScope*,
|
||||
std::pair<std::unordered_set<AstVarScope*>, std::vector<AstVarScope*>>>
|
||||
m_valVscps;
|
||||
// `valVscp` force components of a forced RHS
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
@@ -172,11 +173,21 @@ public:
|
||||
}
|
||||
static bool isNotReplaceable(const AstVarRef* const nodep) { return nodep->user2(); }
|
||||
static void markNonReplaceable(AstVarRef* const nodep) { nodep->user2SetOnce(); }
|
||||
static AstVarScope* getValVscp(AstVarRef* const refp) {
|
||||
return VN_CAST(refp->varScopep()->user3p(), VarScope);
|
||||
|
||||
// Get all ValVscps for a VarScope
|
||||
const std::vector<AstVarScope*>* getValVscps(AstVarRef* const refp) const {
|
||||
auto it = m_valVscps.find(refp->varScopep());
|
||||
if (it != m_valVscps.end()) return &(it->second.second);
|
||||
return nullptr;
|
||||
}
|
||||
static void setValVscp(AstNodeVarRef* const refp, AstVarScope* const vscp) {
|
||||
refp->varScopep()->user3p(vscp);
|
||||
|
||||
// Add a ValVscp for a VarScope
|
||||
void addValVscp(AstVarRef* const refp, AstVarScope* const valVscp) {
|
||||
if (m_valVscps[refp->varScopep()].first.find(valVscp)
|
||||
!= m_valVscps[refp->varScopep()].first.end())
|
||||
return;
|
||||
m_valVscps[refp->varScopep()].first.emplace(valVscp);
|
||||
m_valVscps[refp->varScopep()].second.push_back(valVscp);
|
||||
}
|
||||
|
||||
// METHODS
|
||||
@@ -188,10 +199,10 @@ public:
|
||||
return m_forceComponentsVarScope.tryGet(nodep->varScopep());
|
||||
}
|
||||
void setValVscpRhsExpr(AstVarScope* valVscp, AstNodeExpr* rhsExpr) {
|
||||
valVscp->user4p(rhsExpr);
|
||||
valVscp->user3p(rhsExpr);
|
||||
}
|
||||
AstNodeExpr* getValVscpRhsExpr(AstVarScope* valVscp) const {
|
||||
return VN_CAST(valVscp->user4p(), NodeExpr);
|
||||
return VN_CAST(valVscp->user3p(), NodeExpr);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -242,7 +253,7 @@ class ForceConvertVisitor final : public VNVisitor {
|
||||
transformWritenVarScopes(setValp->lhsp(), [this, rhsp](AstVarScope* vscp) {
|
||||
AstVarScope* const valVscp = m_state.getForceComponents(vscp).m_valVscp;
|
||||
m_state.setValVscpRhsExpr(valVscp, rhsp->cloneTreePure(false));
|
||||
rhsp->foreach([valVscp](AstVarRef* refp) { ForceState::setValVscp(refp, valVscp); });
|
||||
rhsp->foreach([valVscp, this](AstVarRef* refp) { m_state.addValVscp(refp, valVscp); });
|
||||
return valVscp;
|
||||
});
|
||||
|
||||
@@ -380,7 +391,8 @@ class ForceReplaceVisitor final : public VNVisitor {
|
||||
m_stmtp->addNextHere(new AstAssign{flp, lhsp, rhsp});
|
||||
}
|
||||
// Emit valVscp update after each write to any VarRef on forced RHS.
|
||||
if (AstVarScope* const valVscp = ForceState::getValVscp(nodep)) {
|
||||
if (!m_state.getValVscps(nodep)) break;
|
||||
for (AstVarScope* const valVscp : *m_state.getValVscps(nodep)) {
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstVarRef* const valp = new AstVarRef{flp, valVscp, VAccess::WRITE};
|
||||
AstNodeExpr* rhsp = m_state.getValVscpRhsExpr(valVscp);
|
||||
@@ -396,7 +408,7 @@ class ForceReplaceVisitor final : public VNVisitor {
|
||||
}
|
||||
default:
|
||||
if (!m_inLogic) return;
|
||||
if (m_state.tryGetForceComponents(nodep) || ForceState::getValVscp(nodep)) {
|
||||
if (m_state.tryGetForceComponents(nodep) || m_state.getValVscps(nodep)) {
|
||||
nodep->v3error(
|
||||
"Unsupported: Signals used via read-write reference cannot be forced");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user