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*>()>
|
template <typename T_User, bool = fitsSpaceAllocatedFor<T_User, void*>()>
|
||||||
class DfgUserMap;
|
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
|
// Dataflow graph vertex type enum
|
||||||
|
|
||||||
|
|
@ -574,6 +543,39 @@ public:
|
||||||
sinkCone(const std::vector<const DfgVertex*>&) const VL_MT_DISABLED;
|
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
|
// Map from DfgVertices to T_Value implemeneted via DfgVertex::m_userStorage
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,8 @@ class DataflowOptimize final {
|
||||||
// - bit1: Written via AstVarXRef (hierarchical reference)
|
// - bit1: Written via AstVarXRef (hierarchical reference)
|
||||||
// - bit2: Read by logic in same module/netlist not represented in DFG
|
// - bit2: Read by logic in same module/netlist not represented in DFG
|
||||||
// - bit3: Written 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
|
// AstNode::user2/user3/user4 can be used by various DFG algorithms
|
||||||
const VNUser1InUse m_user1InUse;
|
const VNUser1InUse m_user1InUse;
|
||||||
|
|
@ -285,6 +286,12 @@ class DataflowOptimize final {
|
||||||
senItemp->foreach([](const AstVarRef* refp) {
|
senItemp->foreach([](const AstVarRef* refp) {
|
||||||
DfgVertexVar::setHasExtRdRefs(refp->varScopep());
|
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 {
|
} else {
|
||||||
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||||
|
|
@ -296,13 +303,20 @@ class DataflowOptimize final {
|
||||||
if (hasExtWr) DfgVertexVar::setHasExtWrRefs(varp);
|
if (hasExtWr) DfgVertexVar::setHasExtWrRefs(varp);
|
||||||
return;
|
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
|
// Check hierarchical references
|
||||||
if (const AstVarXRef* const xrefp = VN_CAST(nodep, VarXRef)) {
|
if (const AstVarXRef* const xrefp = VN_CAST(nodep, VarXRef)) {
|
||||||
AstVar* const tgtp = xrefp->varp();
|
AstVar* const tgtp = xrefp->varp();
|
||||||
if (!tgtp) return;
|
if (!tgtp) return;
|
||||||
if (xrefp->access().isReadOrRW()) DfgVertexVar::setHasExtRdRefs(tgtp);
|
if (xrefp->access().isReadOrRW()) DfgVertexVar::setHasExtRdRefs(tgtp);
|
||||||
if (xrefp->access().isWriteOrRW()) DfgVertexVar::setHasExtWrRefs(tgtp);
|
if (xrefp->access().isWriteOrRW()) DfgVertexVar::setHasExtWrRefs(tgtp);
|
||||||
|
if (xrefp->access().isRW()) DfgVertexVar::setHasRWRefs(tgtp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check cell ports
|
// Check cell ports
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ class AstToDfgConverter final : public VNVisitor {
|
||||||
// Returns {nullptr, 0}, if the given LValue expression is not supported.
|
// Returns {nullptr, 0}, if the given LValue expression is not supported.
|
||||||
std::pair<DfgVertexSplice*, uint32_t> convertLValue(AstNodeExpr* nodep) {
|
std::pair<DfgVertexSplice*, uint32_t> convertLValue(AstNodeExpr* nodep) {
|
||||||
if (const AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
|
if (const AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
|
||||||
|
UASSERT_OBJ(vrefp->access().isWriteOnly(), vrefp, "Non-WriteOnly reference");
|
||||||
if (!isSupported(vrefp)) {
|
if (!isSupported(vrefp)) {
|
||||||
++m_ctx.m_conv.nonRepLValue;
|
++m_ctx.m_conv.nonRepLValue;
|
||||||
return {nullptr, 0};
|
return {nullptr, 0};
|
||||||
|
|
@ -366,7 +367,8 @@ class AstToDfgConverter final : public VNVisitor {
|
||||||
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
||||||
if (unhandled(nodep)) return;
|
if (unhandled(nodep)) return;
|
||||||
// This visit method is only called on RValues, where only read refs are supported
|
// 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_foundUnhandled = true;
|
||||||
++m_ctx.m_conv.nonRepVarRef;
|
++m_ctx.m_conv.nonRepVarRef;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,8 @@ class DfgVertexVar VL_NOT_FINAL : public DfgVertex {
|
||||||
#endif
|
#endif
|
||||||
// Increment reference count
|
// Increment reference count
|
||||||
AstNode* const variablep = nodep();
|
AstNode* const variablep = nodep();
|
||||||
variablep->user1(variablep->user1() + 0x10);
|
variablep->user1(variablep->user1() + 0x20);
|
||||||
UASSERT_OBJ((variablep->user1() >> 4) > 0, variablep, "Reference count overflow");
|
UASSERT_OBJ((variablep->user1() >> 5) > 0, variablep, "Reference count overflow");
|
||||||
// Allocate sources
|
// Allocate sources
|
||||||
newInput();
|
newInput();
|
||||||
newInput();
|
newInput();
|
||||||
|
|
@ -87,8 +87,8 @@ public:
|
||||||
~DfgVertexVar() {
|
~DfgVertexVar() {
|
||||||
// Decrement reference count
|
// Decrement reference count
|
||||||
AstNode* const variablep = nodep();
|
AstNode* const variablep = nodep();
|
||||||
variablep->user1(variablep->user1() - 0x10);
|
variablep->user1(variablep->user1() - 0x20);
|
||||||
UASSERT_OBJ((variablep->user1() >> 4) >= 0, variablep, "Reference count underflow");
|
UASSERT_OBJ((variablep->user1() >> 5) >= 0, variablep, "Reference count underflow");
|
||||||
}
|
}
|
||||||
ASTGEN_MEMBERS_DfgVertexVar;
|
ASTGEN_MEMBERS_DfgVertexVar;
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ public:
|
||||||
void driverFileLine(FileLine* flp) { m_driverFileLine = flp; }
|
void driverFileLine(FileLine* flp) { m_driverFileLine = flp; }
|
||||||
|
|
||||||
// Variable referenced from other DFG in the same module/netlist
|
// 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
|
// Variable referenced from Ast code in the same module/netlist
|
||||||
static bool hasModRdRefs(const AstNode* nodep) { return nodep->user1() & 0x04; }
|
static bool hasModRdRefs(const AstNode* nodep) { return nodep->user1() & 0x04; }
|
||||||
|
|
@ -140,6 +140,10 @@ public:
|
||||||
bool hasExtWrRefs() const { return hasExtWrRefs(nodep()); }
|
bool hasExtWrRefs() const { return hasExtWrRefs(nodep()); }
|
||||||
bool hasExtRefs() const { return hasExtRdRefs() || hasExtWrRefs(); }
|
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
|
// True iff the value of this variable is read outside this DfgGraph
|
||||||
bool isObserved() const {
|
bool isObserved() const {
|
||||||
// A DfgVarVertex is written in exactly one DfgGraph, and might be read in an arbitrary
|
// A DfgVarVertex is written in exactly one DfgGraph, and might be read in an arbitrary
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue