Optimize CReset in Dfg
This commit is contained in:
parent
e6a070b93b
commit
0278b1e475
|
|
@ -91,6 +91,11 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
|||
for (const DfgVertex& vtx : m_opVertices) {
|
||||
switch (vtx.type()) {
|
||||
#include "V3Dfg__gen_clone_cases.h" // From ./astgen
|
||||
case VDfgType::CReset: { // LCOV_EXCL_START - No algorithm actually hits this today
|
||||
DfgCReset* const cp = new DfgCReset{*clonep, vtx.fileline(), vtx.dtype()};
|
||||
vtxp2clonep.emplace(&vtx, cp);
|
||||
break;
|
||||
} // LCOV_EXCL_STOP
|
||||
case VDfgType::Sel: {
|
||||
DfgSel* const cp = new DfgSel{*clonep, vtx.fileline(), vtx.dtype()};
|
||||
cp->lsb(vtx.as<DfgSel>()->lsb());
|
||||
|
|
@ -132,11 +137,14 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
|||
VL_UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
vtx.v3fatalSrc("Unhandled operation vertex type: " + vtx.typeName());
|
||||
case VDfgType::AstRd: // LCOV_EXCL_START
|
||||
case VDfgType::Const:
|
||||
case VDfgType::VarArray:
|
||||
case VDfgType::VarPacked: {
|
||||
vtx.v3fatalSrc("Vertex should have been handled above: " + vtx.typeName());
|
||||
VL_UNREACHABLE;
|
||||
break;
|
||||
}
|
||||
} // LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
UASSERT(size() == clonep->size(), "Size of clone should be the same");
|
||||
|
|
@ -618,6 +626,10 @@ void DfgVertex::typeCheck(const DfgGraph& dfg) const {
|
|||
CHECK(isPacked(), "Should be Packed type");
|
||||
return;
|
||||
}
|
||||
case VDfgType::CReset: {
|
||||
CHECK(isPacked() || isArray(), "Should be Packed or Array type");
|
||||
return;
|
||||
}
|
||||
case VDfgType::AstRd: {
|
||||
const DfgAstRd& v = *as<DfgAstRd>();
|
||||
CHECK(v.isPacked() || v.isArray(), "Should be Packed or Array type");
|
||||
|
|
|
|||
|
|
@ -125,6 +125,12 @@ class ColorStronglyConnectedComponents final {
|
|||
|
||||
// Initialize state of operation vertices
|
||||
for (const DfgVertex& vtx : m_dfg.opVertices()) {
|
||||
// If it has no inputs or no outputs, it cannot be part of a non-trivial SCC.
|
||||
if (!vtx.nInputs() || !vtx.hasSinks()) {
|
||||
index(vtx) = 0;
|
||||
component(vtx) = 0;
|
||||
continue;
|
||||
}
|
||||
index(vtx) = UNASSIGNED;
|
||||
component(vtx) = UNASSIGNED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class V3DfgCse final {
|
|||
|
||||
// Special vertices
|
||||
case VDfgType::Const: // LCOV_EXCL_START
|
||||
case VDfgType::CReset:
|
||||
case VDfgType::VarArray:
|
||||
case VDfgType::VarPacked:
|
||||
case VDfgType::AstRd: // LCOV_EXCL_STOP
|
||||
|
|
@ -170,6 +171,7 @@ class V3DfgCse final {
|
|||
|
||||
// Special vertices
|
||||
case VDfgType::Const: return a.as<DfgConst>()->num().isCaseEq(b.as<DfgConst>()->num());
|
||||
case VDfgType::CReset: return false;
|
||||
|
||||
case VDfgType::VarArray:
|
||||
case VDfgType::VarPacked: // CSE does not combine variables
|
||||
|
|
@ -303,6 +305,10 @@ class V3DfgCse final {
|
|||
for (const DfgVertexVar& vtx : dfg.varVertices()) m_hashCache[vtx] = V3Hash{++varHash};
|
||||
// Pre-hash Ast references, these are all unique like variables
|
||||
for (const DfgVertexAst& vtx : dfg.astVertices()) m_hashCache[vtx] = V3Hash{++varHash};
|
||||
// Pre-hash CReset vertices, these are all unique
|
||||
for (const DfgVertex& vtx : dfg.opVertices()) {
|
||||
if (vtx.is<DfgCReset>()) m_hashCache[vtx] = V3Hash{++varHash};
|
||||
}
|
||||
|
||||
// Similarly pre-hash constants for speed. While we don't combine constants, we do want
|
||||
// expressions using the same constants to be combined, so we do need to hash equal
|
||||
|
|
|
|||
|
|
@ -227,6 +227,13 @@ class DfgToAstVisitor final : DfgVisitor {
|
|||
void visit(DfgConst* vtxp) override { //
|
||||
m_resultp = new AstConst{vtxp->fileline(), vtxp->num()};
|
||||
}
|
||||
void visit(DfgCReset* vtxp) override {
|
||||
DfgVertex* const sinkp = vtxp->singleSink();
|
||||
UASSERT_OBJ(sinkp, vtxp, "CReset should only have one sink");
|
||||
UASSERT_OBJ(sinkp->is<DfgVertexVar>(), sinkp, "CReset should drive a variable");
|
||||
AstVar* const varp = sinkp->as<DfgVertexVar>()->vscp()->varp();
|
||||
m_resultp = new AstCReset{vtxp->fileline(), varp, false};
|
||||
}
|
||||
|
||||
void visit(DfgRep* vtxp) override {
|
||||
FileLine* const flp = vtxp->fileline();
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ void V3DfgPasses::inlineVars(DfgGraph& dfg) {
|
|||
// Partial driver cannot be inlined
|
||||
if (srcp->is<DfgVertexSplice>()) continue;
|
||||
if (srcp->is<DfgUnitArray>()) continue;
|
||||
// Don't inline CReset
|
||||
if (srcp->is<DfgCReset>()) continue;
|
||||
// Okie dokie, here we go ...
|
||||
vtx.replaceWith(srcp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1158,7 +1158,7 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
|
||||
// Sel from a partial variable (including narrowed vertex)
|
||||
if (DfgVarPacked* const varp = fromp->cast<DfgVarPacked>()) {
|
||||
if (varp->srcp() && !varp->isVolatile()) {
|
||||
if (varp->srcp() && !varp->isVolatile() && !varp->srcp()->is<DfgCReset>()) {
|
||||
// Must be a splice, otherwise it would have been inlined
|
||||
DfgSplicePacked* splicep = varp->srcp()->as<DfgSplicePacked>();
|
||||
DfgVertex* driverp = nullptr;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ class V3DfgPushDownSels final {
|
|||
m_stack.push_back(&vtx);
|
||||
}
|
||||
for (DfgConst& vtx : m_dfg.constVertices()) m_stack.push_back(&vtx);
|
||||
for (DfgVertex& vtx : m_dfg.opVertices()) {
|
||||
if (!vtx.nInputs()) m_stack.push_back(&vtx);
|
||||
}
|
||||
|
||||
// Reverse post order number to assign to next vertex
|
||||
uint32_t rpoNext = m_dfg.size();
|
||||
|
|
|
|||
|
|
@ -100,6 +100,9 @@ class DfgRegularize final {
|
|||
// No need to add a temporary if the single sink is a variable already
|
||||
if (sink.is<DfgVertexVar>()) return false;
|
||||
|
||||
// CReset always needs to be driving a variable
|
||||
if (aVtx.is<DfgCReset>()) return true;
|
||||
|
||||
// Do not inline expressions into a loop body
|
||||
if (const DfgAstRd* const astRdp = sink.cast<DfgAstRd>()) { return astRdp->inLoop(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -384,6 +384,24 @@ class AstToDfgConverter final : public VNVisitor {
|
|||
nodep->user2p(vtxp);
|
||||
}
|
||||
}
|
||||
void visit(AstCReset* nodep) override {
|
||||
UASSERT_OBJ(m_converting, nodep, "AstToDfg visit called without m_converting");
|
||||
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
||||
if (unhandled(nodep)) return;
|
||||
|
||||
const DfgDataType* const dtypep = DfgDataType::fromAst(nodep->dtypep());
|
||||
if (!dtypep) {
|
||||
m_foundUnhandled = true;
|
||||
++m_ctx.m_conv.nonRepDType;
|
||||
return;
|
||||
}
|
||||
|
||||
UASSERT_OBJ(!nodep->constructing(), nodep,
|
||||
"CReset should be non-constructing at this stage");
|
||||
|
||||
DfgVertex* const vtxp = make<DfgCReset>(nodep->fileline(), *dtypep);
|
||||
nodep->user2p(vtxp);
|
||||
}
|
||||
void visit(AstReplicate* nodep) override {
|
||||
UASSERT_OBJ(m_converting, nodep, "AstToDfg visit called without m_converting");
|
||||
UASSERT_OBJ(!nodep->user2p(), nodep, "Already has Dfg vertex");
|
||||
|
|
|
|||
|
|
@ -248,6 +248,14 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class DfgCReset final : public DfgVertexNullary {
|
||||
public:
|
||||
DfgCReset(DfgGraph& dfg, FileLine* flp, const DfgDataType& dtype)
|
||||
: DfgVertexNullary{dfg, dfgType(), flp, dtype} {}
|
||||
|
||||
ASTGEN_MEMBERS_DfgCReset;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Unary vertices - 1 inputs
|
||||
|
||||
|
|
|
|||
|
|
@ -570,4 +570,11 @@ module t (
|
|||
wire logic [7:0] func_3 = pkg::branchy(rand_a[7:0], rand_b[7:0]);
|
||||
`signal(FUNC_3, func_3);
|
||||
|
||||
logic [1:0] via_creset;
|
||||
always_comb begin
|
||||
automatic logic [1:0] a /* = AstCReset */;
|
||||
via_creset = a + 2'd1;
|
||||
end
|
||||
`signal(VIA_CRESET, via_creset);
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
Loading…
Reference in New Issue