Internals: Do not optimize variables with RW refs in Dfg
This commit is contained in:
parent
f12cdac8da
commit
9ed7a9f98b
64
src/V3Dfg.h
64
src/V3Dfg.h
|
|
@ -68,37 +68,6 @@ class DfgVisitor;
|
|||
template <typename T_User, bool = fitsSpaceAllocatedFor<T_User, void*>()>
|
||||
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 DfgVertex*>&) 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ class AstToDfgConverter final : public VNVisitor {
|
|||
// Returns {nullptr, 0}, if the given LValue expression is not supported.
|
||||
std::pair<DfgVertexSplice*, uint32_t> 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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue