diff --git a/src/V3Dfg.h b/src/V3Dfg.h index d1378e34a..7133085ec 100644 --- a/src/V3Dfg.h +++ b/src/V3Dfg.h @@ -68,37 +68,6 @@ class DfgVisitor; template ()> class DfgUserMap; -namespace V3Dfg { -//----------------------------------------------------------------------- -// Functions for compatibility tests - -// Returns true if variable can be represented in the graph -inline bool isSupported(const AstVar* varp) { - if (varp->isIfaceRef()) return false; // Cannot handle interface references - if (varp->delayp()) return false; // Cannot handle delayed variables - if (varp->isSc()) return false; // SystemC variables are special and rare, we can ignore - if (varp->dfgMultidriven()) return false; // Discovered as multidriven on earlier DFG run - return DfgDataType::fromAst(varp->dtypep()); -} - -// Returns true if variable can be represented in the graph -inline bool isSupported(const AstVarScope* vscp) { - const AstNodeModule* const modp = vscp->scopep()->modp(); - if (VN_IS(modp, Module)) { - // Regular module supported - } else if (const AstIface* const ifacep = VN_CAST(modp, Iface)) { - // Interfaces supported if there are no virtual interfaces for - // them, otherwise they cannot be resovled statically. - if (ifacep->hasVirtualRef()) return false; - } else { - return false; // Anything else (package, class, etc) not supported - } - // Check the AstVar - return isSupported(vscp->varp()); -} - -} //namespace V3Dfg - //------------------------------------------------------------------------------ // Dataflow graph vertex type enum @@ -574,6 +543,39 @@ public: sinkCone(const std::vector&) const VL_MT_DISABLED; }; +namespace V3Dfg { +//----------------------------------------------------------------------- +// Functions for compatibility tests + +// Returns true if variable can be represented in the graph +inline bool isSupported(const AstVar* varp) { + if (varp->isIfaceRef()) return false; // Cannot handle interface references + if (varp->delayp()) return false; // Cannot handle delayed variables + if (varp->isSc()) return false; // SystemC variables are special and rare, we can ignore + if (varp->dfgMultidriven()) return false; // Discovered as multidriven on earlier DFG run + if (DfgVertexVar::hasRWRefs(varp)) return false; // Referenced via READWRITE references + return DfgDataType::fromAst(varp->dtypep()); +} + +// Returns true if variable can be represented in the graph +inline bool isSupported(const AstVarScope* vscp) { + const AstNodeModule* const modp = vscp->scopep()->modp(); + if (VN_IS(modp, Module)) { + // Regular module supported + } else if (const AstIface* const ifacep = VN_CAST(modp, Iface)) { + // Interfaces supported if there are no virtual interfaces for + // them, otherwise they cannot be resovled statically. + if (ifacep->hasVirtualRef()) return false; + } else { + return false; // Anything else (package, class, etc) not supported + } + if (DfgVertexVar::hasRWRefs(vscp)) return false; // Referenced via READWRITE references + // Check the AstVar + return isSupported(vscp->varp()); +} + +} //namespace V3Dfg + //------------------------------------------------------------------------------ // Map from DfgVertices to T_Value implemeneted via DfgVertex::m_userStorage diff --git a/src/V3DfgOptimizer.cpp b/src/V3DfgOptimizer.cpp index 54a9030ab..77f9a2308 100644 --- a/src/V3DfgOptimizer.cpp +++ b/src/V3DfgOptimizer.cpp @@ -246,7 +246,8 @@ class DataflowOptimize final { // - bit1: Written via AstVarXRef (hierarchical reference) // - bit2: Read by logic in same module/netlist not represented in DFG // - bit3: Written by logic in same module/netlist not represented in DFG - // - bit31-4: Reference count, how many DfgVertexVar represent this variable + // - bit4: Has READWRITE references + // - bit31-5: Reference count, how many DfgVertexVar represent this variable // // AstNode::user2/user3/user4 can be used by various DFG algorithms const VNUser1InUse m_user1InUse; @@ -285,6 +286,12 @@ class DataflowOptimize final { senItemp->foreach([](const AstVarRef* refp) { DfgVertexVar::setHasExtRdRefs(refp->varScopep()); }); + return; + } + // Check direct references + if (const AstVarRef* const refp = VN_CAST(nodep, VarRef)) { + if (refp->access().isRW()) DfgVertexVar::setHasRWRefs(refp->varScopep()); + return; } } else { if (AstVar* const varp = VN_CAST(nodep, Var)) { @@ -296,13 +303,20 @@ class DataflowOptimize final { if (hasExtWr) DfgVertexVar::setHasExtWrRefs(varp); return; } + // Check direct references + if (const AstVarRef* const refp = VN_CAST(nodep, VarRef)) { + if (refp->access().isRW()) DfgVertexVar::setHasRWRefs(refp->varp()); + return; + } } + // Check hierarchical references if (const AstVarXRef* const xrefp = VN_CAST(nodep, VarXRef)) { AstVar* const tgtp = xrefp->varp(); if (!tgtp) return; if (xrefp->access().isReadOrRW()) DfgVertexVar::setHasExtRdRefs(tgtp); if (xrefp->access().isWriteOrRW()) DfgVertexVar::setHasExtWrRefs(tgtp); + if (xrefp->access().isRW()) DfgVertexVar::setHasRWRefs(tgtp); return; } // Check cell ports diff --git a/src/V3DfgSynthesize.cpp b/src/V3DfgSynthesize.cpp index 8c31e51de..92e24d99a 100644 --- a/src/V3DfgSynthesize.cpp +++ b/src/V3DfgSynthesize.cpp @@ -145,6 +145,7 @@ class AstToDfgConverter final : public VNVisitor { // Returns {nullptr, 0}, if the given LValue expression is not supported. std::pair convertLValue(AstNodeExpr* nodep) { if (const AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) { + UASSERT_OBJ(vrefp->access().isWriteOnly(), vrefp, "Non-WriteOnly reference"); if (!isSupported(vrefp)) { ++m_ctx.m_conv.nonRepLValue; return {nullptr, 0}; @@ -366,7 +367,8 @@ class AstToDfgConverter final : public VNVisitor { UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex"); if (unhandled(nodep)) return; // This visit method is only called on RValues, where only read refs are supported - if (!nodep->access().isReadOnly() || !isSupported(nodep)) { + UASSERT_OBJ(nodep->access().isReadOnly(), nodep, "Non-ReadOnly reference"); + if (!isSupported(nodep)) { m_foundUnhandled = true; ++m_ctx.m_conv.nonRepVarRef; return; diff --git a/src/V3DfgVertices.h b/src/V3DfgVertices.h index 553c455c4..e6ba29161 100644 --- a/src/V3DfgVertices.h +++ b/src/V3DfgVertices.h @@ -70,8 +70,8 @@ class DfgVertexVar VL_NOT_FINAL : public DfgVertex { #endif // Increment reference count AstNode* const variablep = nodep(); - variablep->user1(variablep->user1() + 0x10); - UASSERT_OBJ((variablep->user1() >> 4) > 0, variablep, "Reference count overflow"); + variablep->user1(variablep->user1() + 0x20); + UASSERT_OBJ((variablep->user1() >> 5) > 0, variablep, "Reference count overflow"); // Allocate sources newInput(); newInput(); @@ -87,8 +87,8 @@ public: ~DfgVertexVar() { // Decrement reference count AstNode* const variablep = nodep(); - variablep->user1(variablep->user1() - 0x10); - UASSERT_OBJ((variablep->user1() >> 4) >= 0, variablep, "Reference count underflow"); + variablep->user1(variablep->user1() - 0x20); + UASSERT_OBJ((variablep->user1() >> 5) >= 0, variablep, "Reference count underflow"); } ASTGEN_MEMBERS_DfgVertexVar; @@ -118,7 +118,7 @@ public: void driverFileLine(FileLine* flp) { m_driverFileLine = flp; } // Variable referenced from other DFG in the same module/netlist - bool hasDfgRefs() const { return nodep()->user1() >> 5; } // I.e.: (nodep()->user1() >> 4) > 1 + bool hasDfgRefs() const { return nodep()->user1() >> 6; } // I.e.: (nodep()->user1() >> 5) > 1 // Variable referenced from Ast code in the same module/netlist static bool hasModRdRefs(const AstNode* nodep) { return nodep->user1() & 0x04; } @@ -140,6 +140,10 @@ public: bool hasExtWrRefs() const { return hasExtWrRefs(nodep()); } bool hasExtRefs() const { return hasExtRdRefs() || hasExtWrRefs(); } + // Variable referenced via READWRITE references + static bool hasRWRefs(const AstNode* nodep) { return nodep->user1() & 0x10; } + static void setHasRWRefs(AstNode* nodep) { nodep->user1(nodep->user1() | 0x10); } + // True iff the value of this variable is read outside this DfgGraph bool isObserved() const { // A DfgVarVertex is written in exactly one DfgGraph, and might be read in an arbitrary