Internals: Cleanup cppcheck warnings (#6317)
`make cppcheck-4` is now clean.
This commit is contained in:
parent
3d3462b209
commit
67da797816
|
|
@ -97,6 +97,7 @@ protected:
|
|||
result = vertexp->user();
|
||||
break;
|
||||
case LatchDetectGraphVertex::VT_BLOCK: // (OR of potentially many siblings)
|
||||
// cppcheck-suppress constVariableReference
|
||||
for (V3GraphEdge& edge : vertexp->outEdges()) {
|
||||
if (latchCheckInternal(castVertexp(edge.top()))) {
|
||||
result = true;
|
||||
|
|
@ -128,6 +129,7 @@ public:
|
|||
}
|
||||
// Clear out userp field of referenced outputs on destruction
|
||||
// (occurs at the end of each combinational always block)
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void clear() {
|
||||
m_outputs.clear();
|
||||
// Calling base class clear will unlink & delete all edges & vertices
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ private:
|
|||
const V3TaskConnects tconnects = V3Task::taskConnects(funcrefp, propp->stmtsp());
|
||||
for (const auto& tconnect : tconnects) {
|
||||
const AstVar* const portp = tconnect.first;
|
||||
// cppcheck-suppress constVariablePointer // 'exprp' unlinked below
|
||||
AstArg* const argp = tconnect.second;
|
||||
AstNode* const pinp = argp->exprp()->unlinkFrBack();
|
||||
replaceVarRefsWithExprRecurse(propExprp, portp, pinp);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ bool AstNodeFTaskRef::isPure() {
|
|||
}
|
||||
|
||||
bool AstNodeFTaskRef::getPurityRecurse() const {
|
||||
// cppcheck-suppress shadowFunction
|
||||
AstNodeFTask* const taskp = this->taskp();
|
||||
// Unlinked yet, so treat as impure
|
||||
if (!taskp) return false;
|
||||
|
|
@ -1098,6 +1099,7 @@ std::pair<uint32_t, uint32_t> AstNodeDType::dimensions(bool includeBasic) const
|
|||
|
||||
int AstNodeDType::widthPow2() const {
|
||||
// I.e. width 30 returns 32, width 32 returns 32.
|
||||
// cppcheck-suppress shadowFunction
|
||||
const uint32_t width = this->width();
|
||||
for (int p2 = 30; p2 >= 0; p2--) {
|
||||
if (width > (1UL << p2)) return (1UL << (p2 + 1));
|
||||
|
|
@ -1374,6 +1376,7 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd,
|
|||
return newp;
|
||||
}
|
||||
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
||||
const VBasicTypeKey key{nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(),
|
||||
nodep->nrange()};
|
||||
|
|
@ -1462,7 +1465,7 @@ AstVarScope* AstConstPool::findTable(AstInitArray* initp) {
|
|||
UASSERT_OBJ(VN_IS(valuep, Const), valuep, "Const pool table entry must be Const");
|
||||
}
|
||||
// Try to find an existing table with the same content
|
||||
// cppcheck-has-bug-suppress unreadVariable
|
||||
// cppcheck-suppress unreadVariable
|
||||
const V3Hash hash = V3Hasher::uncachedHash(initp);
|
||||
const auto& er = m_tables.equal_range(hash.value());
|
||||
for (auto it = er.first; it != er.second; ++it) {
|
||||
|
|
@ -1492,7 +1495,7 @@ static bool sameInit(const AstConst* ap, const AstConst* bp) {
|
|||
|
||||
AstVarScope* AstConstPool::findConst(AstConst* initp, bool mergeDType) {
|
||||
// Try to find an existing constant with the same value
|
||||
// cppcheck-has-bug-suppress unreadVariable
|
||||
// cppcheck-suppress unreadVariable
|
||||
const V3Hash hash = initp->num().toHash();
|
||||
const auto& er = m_consts.equal_range(hash.value());
|
||||
for (auto it = er.first; it != er.second; ++it) {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ class CastVisitor final : public VNVisitor {
|
|||
if (!nodep->isNull()) insertCast(nodep, castSize(nodep->backp()));
|
||||
}
|
||||
}
|
||||
// cppcheck-suppress constParameterPointer // lhsp might be changed
|
||||
void ensureLower32Cast(AstCCast* nodep) {
|
||||
// If we have uint64 = CAST(uint64(x)) then the upcasting
|
||||
// really needs to be CAST(uint64(CAST(uint32(x))).
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ class CombineVisitor final : VNVisitor {
|
|||
return replaced;
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterPointer
|
||||
void process(AstNetlist* netlistp) {
|
||||
// First, remove empty functions. We need to do this separately, because removing
|
||||
// calls can change the hashes of the callers.
|
||||
|
|
|
|||
|
|
@ -1058,7 +1058,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// Someday we'll sort the biops completely and this can be simplified
|
||||
// This often results from our simplified clock generation:
|
||||
// if (rst) ... else if (enable)... -> OR(rst,AND(!rst,enable))
|
||||
AstNodeExpr* ap;
|
||||
const AstNodeExpr* ap;
|
||||
AstNodeBiop* andp;
|
||||
if (VN_IS(nodep->lhsp(), And)) {
|
||||
andp = VN_AS(nodep->lhsp(), And);
|
||||
|
|
@ -1080,7 +1080,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
AstNodeExpr* const bp = notp->lhsp();
|
||||
const AstNodeExpr* const bp = notp->lhsp();
|
||||
if (!operandsSame(ap, bp)) return false;
|
||||
// Do it
|
||||
cp->unlinkFrBack();
|
||||
|
|
@ -1099,6 +1099,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// (otherwise we'd be trading one operation for two operations)
|
||||
// V3Clean often makes this pattern, as it postpones the AND until
|
||||
// as high as possible, which is usually the right choice, except for this.
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstCond* const condp = VN_CAST(nodep->rhsp(), Cond);
|
||||
if (!condp) return false;
|
||||
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
|
||||
|
|
@ -1322,6 +1323,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// A pattern created by []'s after offsets have been removed
|
||||
// SEL(EXTEND(any,width,...),(width-1),0) -> ...
|
||||
// Since select's return unsigned, this is always an extend
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstExtend* const extendp = VN_CAST(nodep->fromp(), Extend);
|
||||
if (!(m_doV && extendp && VN_IS(nodep->lsbp(), Const) && nodep->lsbConst() == 0
|
||||
&& static_cast<int>(nodep->widthConst()) == extendp->lhsp()->width()))
|
||||
|
|
@ -1347,7 +1349,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
// AND({a}, SHIFTR({b}, {c})) is often shorthand in C for Verilog {b}[{c} :+ {a}]
|
||||
// becomes thought other optimizations
|
||||
// SEL(SHIFTR({a},{b}),{lsb},{width}) -> SEL({a},{lsb+b},{width})
|
||||
AstShiftR* const shiftp = VN_CAST(nodep->fromp(), ShiftR);
|
||||
const AstShiftR* const shiftp = VN_CAST(nodep->fromp(), ShiftR);
|
||||
if (!(m_doV && shiftp && VN_IS(shiftp->rhsp(), Const) && VN_IS(nodep->lsbp(), Const))) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2005,21 +2007,22 @@ class ConstVisitor final : public VNVisitor {
|
|||
|
||||
// Skip if we're not const'ing an entire module (IE doing only one assign, etc)
|
||||
if (!m_modp) return false;
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstSel* const sel1p = VN_CAST(nodep->lhsp(), Sel);
|
||||
if (!sel1p) return false;
|
||||
AstNodeAssign* const nextp = VN_CAST(nodep->nextp(), NodeAssign);
|
||||
if (!nextp) return false;
|
||||
if (nodep->type() != nextp->type()) return false;
|
||||
AstSel* const sel2p = VN_CAST(nextp->lhsp(), Sel);
|
||||
const AstSel* const sel2p = VN_CAST(nextp->lhsp(), Sel);
|
||||
if (!sel2p) return false;
|
||||
AstVarRef* const varref1p = VN_CAST(sel1p->fromp(), VarRef);
|
||||
if (!varref1p) return false;
|
||||
AstVarRef* const varref2p = VN_CAST(sel2p->fromp(), VarRef);
|
||||
const AstVarRef* const varref2p = VN_CAST(sel2p->fromp(), VarRef);
|
||||
if (!varref2p) return false;
|
||||
if (!varref1p->sameGateTree(varref2p)) return false;
|
||||
AstConst* const con1p = VN_CAST(sel1p->lsbp(), Const);
|
||||
const AstConst* const con1p = VN_CAST(sel1p->lsbp(), Const);
|
||||
if (!con1p) return false;
|
||||
AstConst* const con2p = VN_CAST(sel2p->lsbp(), Const);
|
||||
const AstConst* const con2p = VN_CAST(sel2p->lsbp(), Const);
|
||||
if (!con2p) return false;
|
||||
// We need to make sure there's no self-references involved in either
|
||||
// assignment. For speed, we only look 3 deep, then give up.
|
||||
|
|
@ -2600,6 +2603,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
|
||||
void replaceSelSel(AstSel* nodep) {
|
||||
// SEL(SEL({x},a,b),c,d) => SEL({x},a+c,d)
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstSel* const belowp = VN_AS(nodep->fromp(), Sel);
|
||||
AstNodeExpr* const fromp = belowp->fromp()->unlinkFrBack();
|
||||
AstNodeExpr* const lsb1p = nodep->lsbp()->unlinkFrBack();
|
||||
|
|
@ -2667,9 +2671,10 @@ class ConstVisitor final : public VNVisitor {
|
|||
bool operandSelReplicate(AstSel* nodep) {
|
||||
// SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long
|
||||
// as SEL's width <= b's width
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstReplicate* const repp = VN_AS(nodep->fromp(), Replicate);
|
||||
AstNodeExpr* const fromp = repp->srcp();
|
||||
AstConst* const lsbp = VN_CAST(nodep->lsbp(), Const);
|
||||
const AstConst* const lsbp = VN_CAST(nodep->lsbp(), Const);
|
||||
if (!lsbp) return false;
|
||||
UASSERT_OBJ(fromp->width(), nodep, "Not widthed");
|
||||
if ((lsbp->toUInt() / fromp->width())
|
||||
|
|
@ -2687,6 +2692,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
}
|
||||
bool operandRepRep(AstReplicate* nodep) {
|
||||
// REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2))
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstReplicate* const rep2p = VN_AS(nodep->srcp(), Replicate);
|
||||
AstNodeExpr* const from2p = rep2p->srcp();
|
||||
AstConst* const cnt1p = VN_CAST(nodep->countp(), Const);
|
||||
|
|
@ -2713,13 +2719,13 @@ class ConstVisitor final : public VNVisitor {
|
|||
AstNodeExpr* from2p = nodep->rhsp();
|
||||
uint32_t cnt2 = 1;
|
||||
if (VN_IS(from1p, Replicate)) {
|
||||
AstConst* const cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->countp(), Const);
|
||||
const AstConst* const cnt1p = VN_CAST(VN_CAST(from1p, Replicate)->countp(), Const);
|
||||
if (!cnt1p) return false;
|
||||
from1p = VN_AS(from1p, Replicate)->srcp();
|
||||
cnt1 = cnt1p->toUInt();
|
||||
}
|
||||
if (VN_IS(from2p, Replicate)) {
|
||||
AstConst* const cnt2p = VN_CAST(VN_CAST(from2p, Replicate)->countp(), Const);
|
||||
const AstConst* const cnt2p = VN_CAST(VN_CAST(from2p, Replicate)->countp(), Const);
|
||||
if (!cnt2p) return false;
|
||||
from2p = VN_AS(from2p, Replicate)->srcp();
|
||||
cnt2 = cnt2p->toUInt();
|
||||
|
|
@ -2826,9 +2832,9 @@ class ConstVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
|
||||
did = true;
|
||||
} else if (m_selp && VN_IS(valuep, InitArray)) {
|
||||
AstInitArray* const initarp = VN_AS(valuep, InitArray);
|
||||
const AstInitArray* const initarp = VN_AS(valuep, InitArray);
|
||||
const uint32_t bit = m_selp->bitConst();
|
||||
AstNode* const itemp = initarp->getIndexDefaultedValuep(bit);
|
||||
const AstNode* const itemp = initarp->getIndexDefaultedValuep(bit);
|
||||
if (VN_IS(itemp, Const)) {
|
||||
const V3Number& num = VN_AS(itemp, Const)->num();
|
||||
// UINFO(2, "constVisit " << cvtToHex(valuep) << " " << num);
|
||||
|
|
@ -3060,8 +3066,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (!nextp) break;
|
||||
AstSenItem* const lItemp = senp;
|
||||
AstSenItem* const rItemp = nextp;
|
||||
AstNodeExpr* const lSenp = lItemp->sensp();
|
||||
AstNodeExpr* const rSenp = rItemp->sensp();
|
||||
const AstNodeExpr* const lSenp = lItemp->sensp();
|
||||
const AstNodeExpr* const rSenp = rItemp->sensp();
|
||||
if (!lSenp || !rSenp) continue;
|
||||
|
||||
if (lSenp->sameGateTree(rSenp)) {
|
||||
|
|
@ -3085,8 +3091,8 @@ class ConstVisitor final : public VNVisitor {
|
|||
|
||||
// Not identical terms, check if they can be combined
|
||||
if (lSenp->width() != rSenp->width()) continue;
|
||||
if (AstAnd* const lAndp = VN_CAST(lSenp, And)) {
|
||||
if (AstAnd* const rAndp = VN_CAST(rSenp, And)) {
|
||||
if (const AstAnd* const lAndp = VN_CAST(lSenp, And)) {
|
||||
if (const AstAnd* const rAndp = VN_CAST(rSenp, And)) {
|
||||
if (AstConst* const lConstp = VN_CAST(lAndp->lhsp(), Const)) {
|
||||
if (AstConst* const rConstp = VN_CAST(rAndp->lhsp(), Const)) {
|
||||
if (lAndp->rhsp()->sameTree(rAndp->rhsp())) {
|
||||
|
|
@ -3204,6 +3210,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
void visit(AstRelease* nodep) override {
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
if (AstConcat* const concatp = VN_CAST(nodep->lhsp(), Concat)) {
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstRelease* const newLp = new AstRelease{flp, concatp->lhsp()->unlinkFrBack()};
|
||||
|
|
@ -3282,6 +3289,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
UINFO(4,
|
||||
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})");
|
||||
AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign);
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstNodeAssign* const elsesp = VN_AS(nodep->elsesp(), NodeAssign);
|
||||
thensp->unlinkFrBack();
|
||||
AstNodeExpr* const condp = nodep->condp()->unlinkFrBack();
|
||||
|
|
@ -3330,6 +3338,7 @@ class ConstVisitor final : public VNVisitor {
|
|||
if (!prevp->fmtp() || prevp->fmtp()->nextp() || !nodep->fmtp() || nodep->fmtp()->nextp())
|
||||
return false;
|
||||
AstSFormatF* const pformatp = prevp->fmtp();
|
||||
// cppcheck-suppress constVariablePointer // children unlinked below
|
||||
AstSFormatF* const nformatp = nodep->fmtp();
|
||||
// We don't merge scopeNames as can have only one and might be different scopes (late in
|
||||
// process) Also rare for real code to print %m multiple times in same message
|
||||
|
|
@ -3979,6 +3988,7 @@ void V3Const::constifyParamsEdit(AstNode* nodep) {
|
|||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthParamsEdit(nodep);
|
||||
ConstVisitor visitor{ConstVisitor::PROC_PARAMS, /* globalPass: */ false};
|
||||
// cppcheck-suppress constVariablePointer // edited below
|
||||
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
|
@ -4000,6 +4010,7 @@ void V3Const::constifyParamsNoWarnEdit(AstNode* nodep) {
|
|||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthParamsEdit(nodep);
|
||||
ConstVisitor visitor{ConstVisitor::PROC_PARAMS_NOWARN, /* globalPass: */ false};
|
||||
// cppcheck-suppress constVariablePointer // edited below
|
||||
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
|
@ -4029,6 +4040,7 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
|
|||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthGenerateParamsEdit(nodep);
|
||||
ConstVisitor visitor{ConstVisitor::PROC_GENERATE, /* globalPass: */ false};
|
||||
// cppcheck-suppress constVariablePointer // edited below
|
||||
if (AstVar* const varp = VN_CAST(nodep, Var)) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ class DeadVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterPointer
|
||||
void checkAll(AstNode* nodep) {
|
||||
if (AstNode* const subnodep = nodep->dtypep()) {
|
||||
if (nodep != subnodep // Not NodeDTypes reference themselves
|
||||
|
|
@ -473,7 +474,9 @@ class DeadVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterPointer
|
||||
void preserveTopIfaces(AstNetlist* rootp) {
|
||||
// cppcheck-suppress constVariablePointer
|
||||
for (AstNodeModule* modp = rootp->modulesp(); modp && modp->level() <= 2;
|
||||
modp = VN_AS(modp->nextp(), NodeModule)) {
|
||||
for (AstNode* subnodep = modp->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
// Remove duplicates
|
||||
V3Const::constifyExpensiveEdit(m_senTreep);
|
||||
}
|
||||
// cppcheck-suppress constParameterPointer
|
||||
void addSensitivity(AstSenTree* nodep) { addSensitivity(nodep->sensesp()); }
|
||||
};
|
||||
|
||||
|
|
@ -1126,7 +1127,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
|
||||
// First gather all senItems
|
||||
AstSenItem* senItemp = nullptr;
|
||||
for (AstSenTree* const domainp : m_timingDomains) {
|
||||
for (const AstSenTree* const domainp : m_timingDomains) {
|
||||
if (domainp->sensesp())
|
||||
senItemp = AstNode::addNext(senItemp, domainp->sensesp()->cloneTree(true));
|
||||
}
|
||||
|
|
@ -1216,6 +1217,7 @@ class DelayedVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_currNbaLhsRefp);
|
||||
UASSERT_OBJ(!m_currNbaLhsRefp, nodep, "NBAs should not nest");
|
||||
nodep->lhsp()->foreach([&](AstNode* currp) {
|
||||
// cppcheck-suppress constVariablePointer
|
||||
if (AstExprStmt* const exprp = VN_CAST(currp, ExprStmt)) {
|
||||
// Move statements before the NBA
|
||||
nodep->addHereThisAsNext(exprp->stmtsp()->unlinkFrBackWithNext());
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
|||
// Hook up inputs of cloned variables
|
||||
for (const DfgVertexVar& vtx : m_varVertices) {
|
||||
// All variable vertices are unary
|
||||
if (DfgVertex* const srcp = vtx.srcp()) {
|
||||
if (const DfgVertex* const srcp = vtx.srcp()) {
|
||||
vtxp2clonep.at(&vtx)->as<DfgVertexVar>()->srcp(vtxp2clonep.at(srcp));
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
|||
const DfgSpliceArray* const vp = vtx.as<DfgSpliceArray>();
|
||||
DfgSpliceArray* const cp = vtxp2clonep.at(vp)->as<DfgSpliceArray>();
|
||||
vp->forEachSourceEdge([&](const DfgEdge& edge, size_t i) {
|
||||
if (DfgVertex* const srcp = edge.sourcep()) {
|
||||
if (const DfgVertex* const srcp = edge.sourcep()) {
|
||||
cp->addDriver(vp->driverFileLine(i), //
|
||||
vp->driverLo(i), //
|
||||
vtxp2clonep.at(srcp));
|
||||
|
|
@ -158,7 +158,7 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
|||
const DfgSplicePacked* const vp = vtx.as<DfgSplicePacked>();
|
||||
DfgSplicePacked* const cp = vtxp2clonep.at(vp)->as<DfgSplicePacked>();
|
||||
vp->forEachSourceEdge([&](const DfgEdge& edge, size_t i) {
|
||||
if (DfgVertex* const srcVp = edge.sourcep()) {
|
||||
if (const DfgVertex* const srcVp = edge.sourcep()) {
|
||||
DfgVertex* const srcCp = vtxp2clonep.at(srcVp);
|
||||
UASSERT_OBJ(!srcCp->is<DfgLogic>(), srcCp, "Cannot clone DfgLogic");
|
||||
if (srcVp == vp->defaultp()) {
|
||||
|
|
@ -183,7 +183,7 @@ std::unique_ptr<DfgGraph> DfgGraph::clone() const {
|
|||
UASSERT_OBJ(oSourceEdges.second == cSourceEdges.second, &vtx,
|
||||
"Mismatched source count");
|
||||
for (size_t i = 0; i < oSourceEdges.second; ++i) {
|
||||
if (DfgVertex* const srcp = oSourceEdges.first[i].sourcep()) {
|
||||
if (const DfgVertex* const srcp = oSourceEdges.first[i].sourcep()) {
|
||||
cSourceEdges.first[i].relinkSource(vtxp2clonep.at(srcp));
|
||||
}
|
||||
}
|
||||
|
|
@ -244,11 +244,11 @@ std::string DfgGraph::makeUniqueName(const std::string& prefix, size_t n) {
|
|||
// Construct the tmpNameStub if we have not done so yet
|
||||
if (m_tmpNameStub.empty()) {
|
||||
// Use the hash of the graph name (avoid long names and non-identifiers)
|
||||
const std::string name = V3Hash{m_name}.toString();
|
||||
const std::string hash = V3Hash{m_name}.toString();
|
||||
// We need to keep every variable globally unique, and graph hashed
|
||||
// names might not be, so keep a static table to track multiplicity
|
||||
static std::unordered_map<std::string, uint32_t> s_multiplicity;
|
||||
m_tmpNameStub += '_' + name + '_' + std::to_string(s_multiplicity[name]++) + '_';
|
||||
m_tmpNameStub += '_' + hash + '_' + std::to_string(s_multiplicity[hash]++) + '_';
|
||||
}
|
||||
// Assemble the globally unique name
|
||||
return "__Vdfg" + prefix + m_tmpNameStub + std::to_string(n);
|
||||
|
|
@ -287,12 +287,12 @@ static const std::string toDotId(const DfgVertex& vtx) { return '"' + cvtToHex(&
|
|||
static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
||||
|
||||
if (const DfgVarPacked* const varVtxp = vtx.cast<DfgVarPacked>()) {
|
||||
AstNode* const nodep = varVtxp->nodep();
|
||||
AstVar* const varp = varVtxp->varp();
|
||||
const AstNode* const nodep = varVtxp->nodep();
|
||||
const AstVar* const varp = varVtxp->varp();
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << nodep->prettyName() << '\n';
|
||||
os << cvtToHex(varVtxp) << '\n';
|
||||
if (AstNode* const tmpForp = varVtxp->tmpForp()) {
|
||||
if (const AstNode* const tmpForp = varVtxp->tmpForp()) {
|
||||
os << "temporary for: " << tmpForp->prettyName() << "\n";
|
||||
}
|
||||
varVtxp->dtypep()->dumpSmall(os);
|
||||
|
|
@ -320,12 +320,12 @@ static void dumpDotVertex(std::ostream& os, const DfgVertex& vtx) {
|
|||
}
|
||||
|
||||
if (const DfgVarArray* const arrVtxp = vtx.cast<DfgVarArray>()) {
|
||||
AstNode* const nodep = arrVtxp->nodep();
|
||||
AstVar* const varp = arrVtxp->varp();
|
||||
const AstNode* const nodep = arrVtxp->nodep();
|
||||
const AstVar* const varp = arrVtxp->varp();
|
||||
os << toDotId(vtx);
|
||||
os << " [label=\"" << nodep->prettyName() << '\n';
|
||||
os << cvtToHex(arrVtxp) << '\n';
|
||||
if (AstNode* const tmpForp = arrVtxp->tmpForp()) {
|
||||
if (const AstNode* const tmpForp = arrVtxp->tmpForp()) {
|
||||
os << "temporary for: " << tmpForp->prettyName() << "\n";
|
||||
}
|
||||
arrVtxp->dtypep()->dumpSmall(os);
|
||||
|
|
@ -512,11 +512,12 @@ void DfgGraph::dumpDotFilePrefixed(const std::string& label,
|
|||
|
||||
template <bool T_SinksNotSources>
|
||||
static std::unique_ptr<std::unordered_set<const DfgVertex*>>
|
||||
dfgGraphCollectCone(const std::vector<const DfgVertex*> vtxps) {
|
||||
dfgGraphCollectCone(const std::vector<const DfgVertex*>& vtxps) {
|
||||
// Work queue for traversal starting from all the seed vertices
|
||||
std::vector<const DfgVertex*> queue = vtxps;
|
||||
// Set of already visited vertices
|
||||
std::unordered_set<const DfgVertex*>* const resp = new std::unordered_set<const DfgVertex*>{};
|
||||
std::unique_ptr<std::unordered_set<const DfgVertex*>> resp{
|
||||
new std::unordered_set<const DfgVertex*>{}};
|
||||
// Depth first traversal
|
||||
while (!queue.empty()) {
|
||||
// Pop next work item
|
||||
|
|
@ -532,16 +533,16 @@ dfgGraphCollectCone(const std::vector<const DfgVertex*> vtxps) {
|
|||
}
|
||||
}
|
||||
// Done
|
||||
return std::unique_ptr<std::unordered_set<const DfgVertex*>>{resp};
|
||||
return resp;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::unordered_set<const DfgVertex*>>
|
||||
DfgGraph::sourceCone(const std::vector<const DfgVertex*> vtxps) const {
|
||||
DfgGraph::sourceCone(const std::vector<const DfgVertex*>& vtxps) const {
|
||||
return dfgGraphCollectCone<false>(vtxps);
|
||||
}
|
||||
|
||||
std::unique_ptr<std::unordered_set<const DfgVertex*>>
|
||||
DfgGraph::sinkCone(const std::vector<const DfgVertex*> vtxps) const {
|
||||
DfgGraph::sinkCone(const std::vector<const DfgVertex*>& vtxps) const {
|
||||
return dfgGraphCollectCone<true>(vtxps);
|
||||
}
|
||||
|
||||
|
|
@ -578,12 +579,12 @@ void DfgEdge::unlinkSource() {
|
|||
if (!m_sourcep) return;
|
||||
#ifdef VL_DEBUG
|
||||
{
|
||||
DfgEdge* sinkp = m_sourcep->m_sinksp;
|
||||
while (sinkp) {
|
||||
if (sinkp == this) break;
|
||||
sinkp = sinkp->m_nextp;
|
||||
DfgEdge* currp = m_sourcep->m_sinksp;
|
||||
while (currp) {
|
||||
if (currp == this) break;
|
||||
currp = currp->m_nextp;
|
||||
}
|
||||
UASSERT(sinkp, "'m_sourcep' does not have this edge as sink");
|
||||
UASSERT(currp, "'m_sourcep' does not have this edge as sink");
|
||||
}
|
||||
#endif
|
||||
// Relink pointers of predecessor and successor
|
||||
|
|
@ -677,7 +678,7 @@ V3Hash DfgVertex::hash() {
|
|||
// variables, which we rely on.
|
||||
if (!is<DfgVertexVar>()) {
|
||||
hash += m_type;
|
||||
if (AstUnpackArrayDType* const adtypep = VN_CAST(dtypep(), UnpackArrayDType)) {
|
||||
if (const AstUnpackArrayDType* const adtypep = VN_CAST(dtypep(), UnpackArrayDType)) {
|
||||
hash += adtypep->elementsConst();
|
||||
// TODO: maybe include sub-dtype, but not hugely important at the moment
|
||||
} else {
|
||||
|
|
@ -685,9 +686,9 @@ V3Hash DfgVertex::hash() {
|
|||
}
|
||||
const auto pair = sourceEdges();
|
||||
const DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
const size_t nEdges = pair.second;
|
||||
// Sources must always be connected in well-formed graphs
|
||||
for (size_t i = 0; i < arity; ++i) hash += edgesp[i].m_sourcep->hash();
|
||||
for (size_t i = 0; i < nEdges; ++i) hash += edgesp[i].m_sourcep->hash();
|
||||
}
|
||||
result = hash;
|
||||
}
|
||||
|
|
@ -758,11 +759,15 @@ DfgVertexVar* DfgVertex::getResultVar() {
|
|||
|
||||
AstScope* DfgVertex::scopep(ScopeCache& cache, bool tryResultVar) VL_MT_DISABLED {
|
||||
// If this is a variable, we are done
|
||||
if (DfgVertexVar* const varp = this->cast<DfgVertexVar>()) return varp->varScopep()->scopep();
|
||||
if (const DfgVertexVar* const varp = this->cast<DfgVertexVar>()) {
|
||||
return varp->varScopep()->scopep();
|
||||
}
|
||||
|
||||
// Try the result var first if instructed (usully only in the recursive case)
|
||||
if (tryResultVar) {
|
||||
if (DfgVertexVar* const varp = this->getResultVar()) return varp->varScopep()->scopep();
|
||||
if (const DfgVertexVar* const varp = this->getResultVar()) {
|
||||
return varp->varScopep()->scopep();
|
||||
}
|
||||
}
|
||||
|
||||
// Note: the recursive invocation can cause a re-hash but that will not invalidate references
|
||||
|
|
@ -775,7 +780,7 @@ AstScope* DfgVertex::scopep(ScopeCache& cache, bool tryResultVar) VL_MT_DISABLED
|
|||
AstScope* foundp = rootp;
|
||||
const auto edges = sourceEdges();
|
||||
for (size_t i = 0; i < edges.second; ++i) {
|
||||
DfgEdge& edge = edges.first[i];
|
||||
const DfgEdge& edge = edges.first[i];
|
||||
foundp = edge.sourcep()->scopep(cache, true);
|
||||
if (foundp != rootp) break;
|
||||
}
|
||||
|
|
|
|||
38
src/V3Dfg.h
38
src/V3Dfg.h
|
|
@ -705,7 +705,8 @@ public:
|
|||
// Split this graph into individual components (unique sub-graphs with no edges between them).
|
||||
// Also removes any vertices that are not weakly connected to any variable.
|
||||
// Leaves 'this' graph empty.
|
||||
std::vector<std::unique_ptr<DfgGraph>> splitIntoComponents(std::string label) VL_MT_DISABLED;
|
||||
std::vector<std::unique_ptr<DfgGraph>>
|
||||
splitIntoComponents(const std::string& label) VL_MT_DISABLED;
|
||||
|
||||
// Extract cyclic sub-graphs from 'this' graph. Cyclic sub-graphs are those that contain at
|
||||
// least one strongly connected component (SCC) plus any other vertices that feed or sink from
|
||||
|
|
@ -716,7 +717,7 @@ public:
|
|||
// to be a DAG (acyclic). 'this' will not necessarily be a connected graph at the end, even if
|
||||
// it was originally connected.
|
||||
std::vector<std::unique_ptr<DfgGraph>>
|
||||
extractCyclicComponents(std::string label) VL_MT_DISABLED;
|
||||
extractCyclicComponents(const std::string& label) VL_MT_DISABLED;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Debug dumping
|
||||
|
|
@ -742,10 +743,10 @@ public:
|
|||
|
||||
// Returns the set of vertices in the upstream cones of the given vertices
|
||||
std::unique_ptr<std::unordered_set<const DfgVertex*>>
|
||||
sourceCone(const std::vector<const DfgVertex*>) const VL_MT_DISABLED;
|
||||
sourceCone(const std::vector<const DfgVertex*>&) const VL_MT_DISABLED;
|
||||
// Returns the set of vertices in the downstream cones of the given vertices
|
||||
std::unique_ptr<std::unordered_set<const DfgVertex*>>
|
||||
sinkCone(const std::vector<const DfgVertex*>) const VL_MT_DISABLED;
|
||||
sinkCone(const std::vector<const DfgVertex*>&) const VL_MT_DISABLED;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Static methods for data types
|
||||
|
|
@ -824,9 +825,7 @@ T& DfgVertex::user() {
|
|||
UDEBUGONLY(UASSERT_OBJ(userCurrent, this, "DfgVertex user data used without reserving"););
|
||||
if (m_userCnt != userCurrent) {
|
||||
m_userCnt = userCurrent;
|
||||
// cppcheck-has-bug-suppress uninitvar
|
||||
VL_ATTR_UNUSED T* const resultp = new (storagep) T{};
|
||||
UDEBUGONLY(UASSERT_OBJ(resultp == storagep, this, "Something is odd"););
|
||||
new (storagep) T{};
|
||||
}
|
||||
return *storagep;
|
||||
}
|
||||
|
|
@ -864,8 +863,8 @@ void DfgVertex::setUser(T value) {
|
|||
void DfgVertex::forEachSource(std::function<void(DfgVertex&)> f) {
|
||||
const auto pair = sourceEdges();
|
||||
const DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
for (size_t i = 0; i < arity; ++i) {
|
||||
const size_t nEdges = pair.second;
|
||||
for (size_t i = 0; i < nEdges; ++i) {
|
||||
if (DfgVertex* const sourcep = edgesp[i].m_sourcep) f(*sourcep);
|
||||
}
|
||||
}
|
||||
|
|
@ -873,8 +872,8 @@ void DfgVertex::forEachSource(std::function<void(DfgVertex&)> f) {
|
|||
void DfgVertex::forEachSource(std::function<void(const DfgVertex&)> f) const {
|
||||
const auto pair = sourceEdges();
|
||||
const DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
for (size_t i = 0; i < arity; ++i) {
|
||||
const size_t nEdges = pair.second;
|
||||
for (size_t i = 0; i < nEdges; ++i) {
|
||||
if (DfgVertex* const sourcep = edgesp[i].m_sourcep) f(*sourcep);
|
||||
}
|
||||
}
|
||||
|
|
@ -893,15 +892,15 @@ void DfgVertex::forEachSink(std::function<void(const DfgVertex&)> f) const {
|
|||
void DfgVertex::forEachSourceEdge(std::function<void(DfgEdge&, size_t)> f) {
|
||||
const auto pair = sourceEdges();
|
||||
DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
for (size_t i = 0; i < arity; ++i) f(edgesp[i], i);
|
||||
const size_t nEdges = pair.second;
|
||||
for (size_t i = 0; i < nEdges; ++i) f(edgesp[i], i);
|
||||
}
|
||||
|
||||
void DfgVertex::forEachSourceEdge(std::function<void(const DfgEdge&, size_t)> f) const {
|
||||
const auto pair = sourceEdges();
|
||||
const DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
for (size_t i = 0; i < arity; ++i) f(edgesp[i], i);
|
||||
const size_t nEdges = pair.second;
|
||||
for (size_t i = 0; i < nEdges; ++i) f(edgesp[i], i);
|
||||
}
|
||||
|
||||
void DfgVertex::forEachSinkEdge(std::function<void(DfgEdge&)> f) {
|
||||
|
|
@ -921,8 +920,8 @@ void DfgVertex::forEachSinkEdge(std::function<void(const DfgEdge&)> f) const {
|
|||
const DfgEdge* DfgVertex::findSourceEdge(std::function<bool(const DfgEdge&, size_t)> p) const {
|
||||
const auto pair = sourceEdges();
|
||||
const DfgEdge* const edgesp = pair.first;
|
||||
const size_t arity = pair.second;
|
||||
for (size_t i = 0; i < arity; ++i) {
|
||||
const size_t nEdges = pair.second;
|
||||
for (size_t i = 0; i < nEdges; ++i) {
|
||||
const DfgEdge& edge = edgesp[i];
|
||||
if (p(edge, i)) return &edge;
|
||||
}
|
||||
|
|
@ -979,8 +978,8 @@ DfgVertex* DfgVertexSplice::wholep() const {
|
|||
if (driverLo(0) != 0) return nullptr;
|
||||
DfgVertex* const srcp = DfgVertexVariadic::source(1);
|
||||
if (srcp->size() != size()) return nullptr;
|
||||
if (DfgUnitArray* const uap = srcp->cast<DfgUnitArray>()) {
|
||||
if (DfgVertexSplice* sp = uap->srcp()->cast<DfgVertexSplice>()) {
|
||||
if (const DfgUnitArray* const uap = srcp->cast<DfgUnitArray>()) {
|
||||
if (const DfgVertexSplice* sp = uap->srcp()->cast<DfgVertexSplice>()) {
|
||||
if (!sp->wholep()) return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1014,6 +1013,7 @@ DfgVertexVar::DfgVertexVar(DfgGraph& dfg, VDfgType type, AstVarScope* vscp)
|
|||
|
||||
DfgVertexVar::~DfgVertexVar() {
|
||||
// Decrement reference count
|
||||
// cppcheck-suppress shadowFunction
|
||||
AstNode* const nodep = this->nodep();
|
||||
nodep->user1(nodep->user1() - 0x10);
|
||||
UASSERT_OBJ((nodep->user1() >> 4) >= 0, nodep, "Reference count underflow");
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ class TraceDriver final : public DfgVisitor {
|
|||
|
||||
struct Hash final {
|
||||
size_t operator()(const Visited& item) const {
|
||||
V3Hash hash{reinterpret_cast<uintptr_t>(item.m_vtxp)};
|
||||
// cppcheck-suppress unreadVariable
|
||||
V3Hash hash{item.m_vtxp};
|
||||
hash += item.m_lsb;
|
||||
hash += item.m_msb;
|
||||
return hash.value();
|
||||
|
|
@ -244,7 +245,7 @@ class TraceDriver final : public DfgVisitor {
|
|||
// Somewhat rudimentary but sufficient for current purposes.
|
||||
static bool knownToBeZeroAtAndAbove(const DfgVertex* vtxp, uint32_t idx) {
|
||||
if (const DfgConcat* const catp = vtxp->cast<DfgConcat>()) {
|
||||
DfgConst* const lConstp = catp->lhsp()->cast<DfgConst>();
|
||||
const DfgConst* const lConstp = catp->lhsp()->cast<DfgConst>();
|
||||
return lConstp && idx >= catp->rhsp()->width() && lConstp->isZero();
|
||||
}
|
||||
if (const DfgExtend* const extp = vtxp->cast<DfgExtend>()) {
|
||||
|
|
@ -256,7 +257,7 @@ class TraceDriver final : public DfgVisitor {
|
|||
// Like knownToBeZeroAtAndAbove, but checks vtxp[idx:0]
|
||||
static bool knownToBeZeroAtAndBelow(const DfgVertex* vtxp, uint32_t idx) {
|
||||
if (const DfgConcat* const catp = vtxp->cast<DfgConcat>()) {
|
||||
DfgConst* const rConstp = catp->rhsp()->cast<DfgConst>();
|
||||
const DfgConst* const rConstp = catp->rhsp()->cast<DfgConst>();
|
||||
return rConstp && idx < rConstp->width() && rConstp->isZero();
|
||||
}
|
||||
return false;
|
||||
|
|
@ -381,10 +382,10 @@ class TraceDriver final : public DfgVisitor {
|
|||
|
||||
void visit(DfgArraySel* vtxp) override {
|
||||
// Only constant select
|
||||
DfgConst* const idxp = vtxp->bitp()->cast<DfgConst>();
|
||||
const DfgConst* const idxp = vtxp->bitp()->cast<DfgConst>();
|
||||
if (!idxp) return;
|
||||
// From a variable
|
||||
DfgVarArray* varp = vtxp->fromp()->cast<DfgVarArray>();
|
||||
const DfgVarArray* varp = vtxp->fromp()->cast<DfgVarArray>();
|
||||
if (!varp) return;
|
||||
// Skip through intermediate variables
|
||||
while (varp->srcp() && varp->srcp()->is<DfgVarArray>()) {
|
||||
|
|
@ -394,10 +395,10 @@ class TraceDriver final : public DfgVisitor {
|
|||
if (!varp->srcp()) return;
|
||||
|
||||
// Driver might be a splice
|
||||
if (DfgSpliceArray* const splicep = varp->srcp()->cast<DfgSpliceArray>()) {
|
||||
DfgVertex* const driverp = splicep->driverAt(idxp->toSizeT());
|
||||
if (const DfgSpliceArray* const splicep = varp->srcp()->cast<DfgSpliceArray>()) {
|
||||
const DfgVertex* const driverp = splicep->driverAt(idxp->toSizeT());
|
||||
if (!driverp) return;
|
||||
DfgUnitArray* const uap = driverp->cast<DfgUnitArray>();
|
||||
const DfgUnitArray* const uap = driverp->cast<DfgUnitArray>();
|
||||
if (!uap) return;
|
||||
// Trace the driver
|
||||
SET_RESULT(trace(uap->srcp(), m_msb, m_lsb));
|
||||
|
|
@ -405,7 +406,7 @@ class TraceDriver final : public DfgVisitor {
|
|||
}
|
||||
|
||||
// Or a unit array
|
||||
DfgUnitArray* const uap = varp->srcp()->cast<DfgUnitArray>();
|
||||
const DfgUnitArray* const uap = varp->srcp()->cast<DfgUnitArray>();
|
||||
if (!uap) return;
|
||||
// Trace the driver
|
||||
UASSERT_OBJ(idxp->toSizeT() == 0, vtxp, "Array Index out of range");
|
||||
|
|
@ -523,7 +524,7 @@ class TraceDriver final : public DfgVisitor {
|
|||
|
||||
void visit(DfgShiftR* vtxp) override {
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
if (DfgConst* const rConstp = vtxp->rhsp()->cast<DfgConst>()) {
|
||||
if (const DfgConst* const rConstp = vtxp->rhsp()->cast<DfgConst>()) {
|
||||
const uint32_t shiftAmnt = rConstp->toU32();
|
||||
// Width of lower half of result
|
||||
const uint32_t lowerWidth = shiftAmnt > vtxp->width() ? 0 : vtxp->width() - shiftAmnt;
|
||||
|
|
@ -558,7 +559,7 @@ class TraceDriver final : public DfgVisitor {
|
|||
|
||||
void visit(DfgShiftL* vtxp) override {
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
if (DfgConst* const rConstp = vtxp->rhsp()->cast<DfgConst>()) {
|
||||
if (const DfgConst* const rConstp = vtxp->rhsp()->cast<DfgConst>()) {
|
||||
const uint32_t shiftAmnt = rConstp->toU32();
|
||||
// Width of lower half of result
|
||||
const uint32_t lowerWidth = shiftAmnt > vtxp->width() ? vtxp->width() : shiftAmnt;
|
||||
|
|
@ -642,13 +643,13 @@ public:
|
|||
// partial trace succeded, but an eventual one falied). Because new
|
||||
// vertices should be created depth first, it is enough to do a single
|
||||
// reverse pass over the collectoin
|
||||
for (DfgVertex* const vtxp : vlstd::reverse_view(traceDriver.m_newVtxps)) {
|
||||
for (DfgVertex* const newp : vlstd::reverse_view(traceDriver.m_newVtxps)) {
|
||||
// Keep the actual result!
|
||||
if (vtxp == resultp) continue;
|
||||
if (newp == resultp) continue;
|
||||
// Keep used ones!
|
||||
if (vtxp->hasSinks()) continue;
|
||||
if (newp->hasSinks()) continue;
|
||||
// Delete it
|
||||
VL_DO_DANGLING(vtxp->unlinkDelete(dfg), vtxp);
|
||||
VL_DO_DANGLING(newp->unlinkDelete(dfg), newp);
|
||||
}
|
||||
// Return the result
|
||||
return resultp;
|
||||
|
|
@ -733,10 +734,10 @@ class IndependentBits final : public DfgVisitor {
|
|||
|
||||
void visit(DfgArraySel* vtxp) override {
|
||||
// Only constant select
|
||||
DfgConst* const idxp = vtxp->bitp()->cast<DfgConst>();
|
||||
const DfgConst* const idxp = vtxp->bitp()->cast<DfgConst>();
|
||||
if (!idxp) return;
|
||||
// From a variable
|
||||
DfgVarArray* varp = vtxp->fromp()->cast<DfgVarArray>();
|
||||
const DfgVarArray* varp = vtxp->fromp()->cast<DfgVarArray>();
|
||||
if (!varp) return;
|
||||
// Skip through intermediate variables
|
||||
while (varp->srcp() && varp->srcp()->is<DfgVarArray>()) {
|
||||
|
|
@ -744,11 +745,11 @@ class IndependentBits final : public DfgVisitor {
|
|||
}
|
||||
// Find driver
|
||||
if (!varp->srcp()) return;
|
||||
DfgSpliceArray* const splicep = varp->srcp()->cast<DfgSpliceArray>();
|
||||
const DfgSpliceArray* const splicep = varp->srcp()->cast<DfgSpliceArray>();
|
||||
if (!splicep) return;
|
||||
DfgVertex* const driverp = splicep->driverAt(idxp->toSizeT());
|
||||
const DfgVertex* const driverp = splicep->driverAt(idxp->toSizeT());
|
||||
if (!driverp) return;
|
||||
DfgUnitArray* const uap = driverp->cast<DfgUnitArray>();
|
||||
const DfgUnitArray* const uap = driverp->cast<DfgUnitArray>();
|
||||
if (!uap) return;
|
||||
// Update mask
|
||||
MASK(vtxp) = MASK(uap->srcp());
|
||||
|
|
@ -1046,7 +1047,7 @@ class FixUpIndependentRanges final {
|
|||
V3Number result{vtxp->fileline(), static_cast<int>(vtxp->width()), 0};
|
||||
vtxp->forEachSink([&result](DfgVertex& sink) {
|
||||
// If used via a Sel, mark the selected bits used
|
||||
if (DfgSel* const selp = sink.cast<DfgSel>()) {
|
||||
if (const DfgSel* const selp = sink.cast<DfgSel>()) {
|
||||
uint32_t lsb = selp->lsb();
|
||||
uint32_t msb = lsb + selp->width() - 1;
|
||||
for (uint32_t i = lsb; i <= msb; ++i) result.setBit(i, '1');
|
||||
|
|
@ -1058,12 +1059,12 @@ class FixUpIndependentRanges final {
|
|||
return result;
|
||||
}
|
||||
|
||||
static std::string debugStr(DfgVertex* vtxp) {
|
||||
if (DfgArraySel* const aselp = vtxp->cast<DfgArraySel>()) {
|
||||
static std::string debugStr(const DfgVertex* vtxp) {
|
||||
if (const DfgArraySel* const aselp = vtxp->cast<DfgArraySel>()) {
|
||||
const size_t i = aselp->bitp()->as<DfgConst>()->toSizeT();
|
||||
return debugStr(aselp->fromp()) + "[" + std::to_string(i) + "]";
|
||||
}
|
||||
if (DfgVertexVar* const varp = vtxp->cast<DfgVertexVar>()) {
|
||||
if (const DfgVertexVar* const varp = vtxp->cast<DfgVertexVar>()) {
|
||||
return varp->nodep()->name();
|
||||
}
|
||||
vtxp->v3fatalSrc("Unhandled node type"); // LCOV_EXCL_LINE
|
||||
|
|
@ -1165,7 +1166,7 @@ class FixUpIndependentRanges final {
|
|||
|
||||
// If no imporovement was possible, delete the terms we just created
|
||||
if (!nImprovements) {
|
||||
for (DfgVertex* const vtxp : termps) VL_DO_DANGLING(vtxp->unlinkDelete(dfg), vtxp);
|
||||
for (DfgVertex* const termp : termps) VL_DO_DANGLING(termp->unlinkDelete(dfg), termp);
|
||||
termps.clear();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -282,22 +282,22 @@ inline void cache(CacheTernary& cache, DfgVertexTernary* vtxp) {
|
|||
}
|
||||
|
||||
// These remove an existing vertex from the cache, if it is the cached vertex
|
||||
inline void invalidateByValue(CacheSel& cache, DfgSel* vtxp) {
|
||||
inline void invalidateByValue(CacheSel& cache, const DfgSel* vtxp) {
|
||||
const auto it = find(cache, vtxp->dtypep(), vtxp->fromp(), vtxp->lsb());
|
||||
if (it != cache.end() && it->second == vtxp) cache.erase(it);
|
||||
}
|
||||
|
||||
inline void invalidateByValue(CacheUnary& cache, DfgVertexUnary* vtxp) {
|
||||
inline void invalidateByValue(CacheUnary& cache, const DfgVertexUnary* vtxp) {
|
||||
const auto it = find(cache, vtxp->dtypep(), vtxp->source<0>());
|
||||
if (it != cache.end() && it->second == vtxp) cache.erase(it);
|
||||
}
|
||||
|
||||
inline void invalidateByValue(CacheBinary& cache, DfgVertexBinary* vtxp) {
|
||||
inline void invalidateByValue(CacheBinary& cache, const DfgVertexBinary* vtxp) {
|
||||
const auto it = find(cache, vtxp->dtypep(), vtxp->source<0>(), vtxp->source<1>());
|
||||
if (it != cache.end() && it->second == vtxp) cache.erase(it);
|
||||
}
|
||||
|
||||
inline void invalidateByValue(CacheTernary& cache, DfgVertexTernary* vtxp) {
|
||||
inline void invalidateByValue(CacheTernary& cache, const DfgVertexTernary* vtxp) {
|
||||
const auto it
|
||||
= find(cache, vtxp->dtypep(), vtxp->source<0>(), vtxp->source<1>(), vtxp->source<2>());
|
||||
if (it != cache.end() && it->second == vtxp) cache.erase(it);
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class ColorStronglyConnectedComponents final {
|
|||
}
|
||||
}
|
||||
|
||||
ColorStronglyConnectedComponents(DfgGraph& dfg)
|
||||
explicit ColorStronglyConnectedComponents(DfgGraph& dfg)
|
||||
: m_dfg{dfg} {
|
||||
UASSERT(dfg.size() < UNASSIGNED, "Graph too big " << dfg.name());
|
||||
// Yet another implementation of Pearce's algorithm.
|
||||
|
|
|
|||
|
|
@ -352,8 +352,8 @@ public:
|
|||
, m_prefix{VString::removeWhitespace(label) + "-"} {}
|
||||
|
||||
~V3DfgContext() {
|
||||
const string prefix = "Optimizations, DFG " + label() + " General, ";
|
||||
V3Stats::addStat(prefix + "modules", m_modules);
|
||||
const string front = "Optimizations, DFG " + label() + " General, ";
|
||||
V3Stats::addStat(front + "modules", m_modules);
|
||||
|
||||
// Print the collected patterns
|
||||
if (v3Global.opt.stats()) {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<DfgGraph>> DfgGraph::splitIntoComponents(std::string label) {
|
||||
std::vector<std::unique_ptr<DfgGraph>> DfgGraph::splitIntoComponents(const std::string& label) {
|
||||
return SplitIntoComponents::apply(*this, label);
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ class ExtractCyclicComponents final {
|
|||
uint64_t& m_userr;
|
||||
|
||||
public:
|
||||
VertexState(DfgVertex& vtx)
|
||||
explicit VertexState(DfgVertex& vtx)
|
||||
: m_userr{vtx.getUser<uint64_t>()} {}
|
||||
bool merged() const { return m_userr >> 63; }
|
||||
void setMerged() { m_userr |= 1ULL << 63; }
|
||||
|
|
@ -266,11 +266,11 @@ class ExtractCyclicComponents final {
|
|||
dfg.forEachVertex([&](const DfgVertex& vtx) { vertices.insert(&vtx); });
|
||||
|
||||
// Check that each edge connects to a vertex that is within the same graph
|
||||
dfg.forEachVertex([&](DfgVertex& vtx) {
|
||||
vtx.forEachSource([&](DfgVertex& src) {
|
||||
dfg.forEachVertex([&](const DfgVertex& vtx) {
|
||||
vtx.forEachSource([&](const DfgVertex& src) {
|
||||
UASSERT_OBJ(vertices.count(&src), &vtx, "Source vertex not in graph");
|
||||
});
|
||||
vtx.forEachSink([&](DfgVertex& snk) {
|
||||
vtx.forEachSink([&](const DfgVertex& snk) {
|
||||
UASSERT_OBJ(vertices.count(&snk), &snk, "Sink vertex not in graph");
|
||||
});
|
||||
});
|
||||
|
|
@ -287,7 +287,7 @@ class ExtractCyclicComponents final {
|
|||
// earlier merging of components ensured crossing in fact only happen at variable
|
||||
// boundaries). Note that fixing up the edges can create clones of variables. Clones do
|
||||
// not need fixing up, so we do not need to iterate them.
|
||||
DfgVertex* const lastp = m_dfg.varVertices().backp();
|
||||
const DfgVertex* const lastp = m_dfg.varVertices().backp();
|
||||
for (DfgVertexVar& vtx : m_dfg.varVertices()) {
|
||||
// Fix up the edges crossing components
|
||||
fixEdges(vtx);
|
||||
|
|
@ -337,6 +337,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<DfgGraph>> DfgGraph::extractCyclicComponents(std::string label) {
|
||||
std::vector<std::unique_ptr<DfgGraph>>
|
||||
DfgGraph::extractCyclicComponents(const std::string& label) {
|
||||
return ExtractCyclicComponents::apply(*this, label);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ class DfgToAstVisitor final : DfgVisitor {
|
|||
AstConst* const idxp = new AstConst{dflp, sArrayp->driverLo(i)};
|
||||
AstArraySel* const nLhsp = new AstArraySel{dflp, lhsp->cloneTreePure(false), idxp};
|
||||
// Convert source
|
||||
if (DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) {
|
||||
if (const DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) {
|
||||
convertDriver(assignments, dflp, nLhsp, uap->srcp());
|
||||
} else {
|
||||
convertDriver(assignments, dflp, nLhsp, driverp);
|
||||
|
|
@ -205,7 +205,7 @@ class DfgToAstVisitor final : DfgVisitor {
|
|||
return;
|
||||
}
|
||||
|
||||
if (DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) {
|
||||
if (const DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) {
|
||||
// Single element array being assigned a unit array. Needs an ArraySel.
|
||||
AstConst* const idxp = new AstConst{flp, 0};
|
||||
AstArraySel* const nLhsp = new AstArraySel{flp, lhsp->cloneTreePure(false), idxp};
|
||||
|
|
|
|||
|
|
@ -164,7 +164,9 @@ class DataflowExtractVisitor final : public VNVisitor {
|
|||
|
||||
void visit(AstAssignW* nodep) override {
|
||||
// Mark LHS variable as combinationally driven
|
||||
if (AstVarRef* const vrefp = VN_CAST(nodep->lhsp(), VarRef)) vrefp->varp()->user4(true);
|
||||
if (const AstVarRef* const vrefp = VN_CAST(nodep->lhsp(), VarRef)) {
|
||||
vrefp->varp()->user4(true);
|
||||
}
|
||||
//
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -312,7 +312,7 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
|
|||
v3Global.rootp()->typeTablep()->addTypesp(tabDTypep);
|
||||
|
||||
// The index variable
|
||||
DfgVarPacked* const idxVtxp = [&]() {
|
||||
AstVar* const idxVarp = [&]() {
|
||||
// If there is an existing result variable, use that, otherwise create a new variable
|
||||
DfgVarPacked* varp = nullptr;
|
||||
if (DfgVertexVar* const vp = srcp->getResultVar()) {
|
||||
|
|
@ -324,7 +324,7 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
|
|||
varp->srcp(srcp);
|
||||
}
|
||||
varp->setHasModRdRefs();
|
||||
return varp;
|
||||
return varp->varp();
|
||||
}();
|
||||
// The previous index variable - we don't need a vertex for this
|
||||
AstVar* const preVarp = [&]() {
|
||||
|
|
@ -381,13 +381,13 @@ void V3DfgPasses::binToOneHot(DfgGraph& dfg, V3DfgBinToOneHotContext& ctx) {
|
|||
logicp->addStmtsp(new AstAssign{
|
||||
flp, //
|
||||
new AstArraySel{flp, new AstVarRef{flp, tabVtxp->varp(), VAccess::WRITE},
|
||||
new AstVarRef{flp, idxVtxp->varp(), VAccess::READ}}, //
|
||||
new AstVarRef{flp, idxVarp, VAccess::READ}}, //
|
||||
new AstConst{flp, AstConst::BitTrue{}}});
|
||||
}
|
||||
{ // pre = idx
|
||||
logicp->addStmtsp(new AstAssign{flp, //
|
||||
new AstVarRef{flp, preVarp, VAccess::WRITE}, //
|
||||
new AstVarRef{flp, idxVtxp->varp(), VAccess::READ}});
|
||||
new AstVarRef{flp, idxVarp, VAccess::READ}});
|
||||
}
|
||||
|
||||
// Replace terms with ArraySels
|
||||
|
|
@ -500,7 +500,7 @@ void V3DfgPasses::eliminateVars(DfgGraph& dfg, V3DfgEliminateVarsContext& ctx) {
|
|||
++ctx.m_varsRemoved;
|
||||
varp->replaceWith(varp->srcp());
|
||||
ctx.m_deleteps.push_back(varp->nodep()); // Delete variable at the end
|
||||
} else if (DfgVarPacked* const driverp = varp->srcp()->cast<DfgVarPacked>()) {
|
||||
} else if (const DfgVarPacked* const driverp = varp->srcp()->cast<DfgVarPacked>()) {
|
||||
// If it's driven from another variable, it can be replaced by that.
|
||||
// Mark it for replacement
|
||||
++ctx.m_varsReplaced;
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
|
||||
// Same as above, but 'flp' and 'dtypep' are taken from the given example vertex
|
||||
template <typename Vertex, typename... Operands>
|
||||
Vertex* make(DfgVertex* examplep, Operands... operands) {
|
||||
Vertex* make(const DfgVertex* examplep, Operands... operands) {
|
||||
return make<Vertex>(examplep->fileline(), examplep->dtypep(), operands...);
|
||||
}
|
||||
|
||||
|
|
@ -408,8 +408,8 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
// If both sides are variable references, order the side in some defined way. This
|
||||
// allows CSE to later merge 'a op b' with 'b op a'.
|
||||
if (lhsp->is<DfgVertexVar>() && rhsp->is<DfgVertexVar>()) {
|
||||
AstNode* const lVarp = lhsp->as<DfgVertexVar>()->nodep();
|
||||
AstNode* const rVarp = rhsp->as<DfgVertexVar>()->nodep();
|
||||
const AstNode* const lVarp = lhsp->as<DfgVertexVar>()->nodep();
|
||||
const AstNode* const rVarp = rhsp->as<DfgVertexVar>()->nodep();
|
||||
if (lVarp->name() > rVarp->name()) {
|
||||
APPLYING(SWAP_VAR_IN_COMMUTATIVE_BINARY) {
|
||||
Vertex* const replacementp = make<Vertex>(vtxp, rhsp, lhsp);
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ class AstToDfgConverter final : public VNVisitor {
|
|||
}
|
||||
|
||||
// Get (or create a new) temporary for this variable
|
||||
DfgVertexVar* const vtxp = [&]() -> DfgVertexVar* {
|
||||
const DfgVertexVar* const vtxp = [&]() -> DfgVertexVar* {
|
||||
// The variable being assigned
|
||||
Variable* const tgtp = getTarget(vrefp);
|
||||
|
||||
|
|
@ -240,7 +240,9 @@ class AstToDfgConverter final : public VNVisitor {
|
|||
|
||||
// Return the splice driver
|
||||
DfgVertex* driverp = splicep->driverAt(index);
|
||||
if (DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) driverp = uap->srcp();
|
||||
if (const DfgUnitArray* const uap = driverp->cast<DfgUnitArray>()) {
|
||||
driverp = uap->srcp();
|
||||
}
|
||||
return {driverp->as<DfgVertexSplice>(), 0};
|
||||
}
|
||||
|
||||
|
|
@ -1319,6 +1321,7 @@ class AstToDfgSynthesize final {
|
|||
const bool missing = m_logicp->findSink<DfgVertex>([&](const DfgVertex& sink) -> bool {
|
||||
const DfgUnresolved* const unresolvedp = sink.as<DfgUnresolved>();
|
||||
AstNode* const tgtp = unresolvedp->singleSink()->as<DfgVertexVar>()->nodep();
|
||||
// cppcheck-suppress constVariablePointer
|
||||
Variable* const varp = reinterpret_cast<Variable*>(tgtp);
|
||||
return !oSymTab.count(varp);
|
||||
});
|
||||
|
|
@ -1331,6 +1334,7 @@ class AstToDfgSynthesize final {
|
|||
m_logicp->forEachSink([&](DfgVertex& sink) {
|
||||
DfgUnresolved* const unresolvedp = sink.as<DfgUnresolved>();
|
||||
AstNode* const tgtp = unresolvedp->singleSink()->as<DfgVertexVar>()->nodep();
|
||||
// cppcheck-suppress constVariablePointer
|
||||
Variable* const varp = reinterpret_cast<Variable*>(tgtp);
|
||||
DfgVertexVar* const resp = oSymTab.at(varp);
|
||||
UASSERT_OBJ(resp->srcp(), resp, "Undriven result");
|
||||
|
|
@ -1489,7 +1493,7 @@ class AstToDfgSynthesize final {
|
|||
//-------------------------------------------------------------------
|
||||
UINFO(5, "Step 2: Revert drivers of variables with unsynthesizeable drivers");
|
||||
// We do this as the variables might be multi-driven, we just can't know at this point
|
||||
for (DfgVertexVar& var : m_dfg.varVertices()) {
|
||||
for (const DfgVertexVar& var : m_dfg.varVertices()) {
|
||||
if (!var.srcp()) continue;
|
||||
DfgUnresolved* const unresolvedp = var.srcp()->cast<DfgUnresolved>();
|
||||
if (!unresolvedp) break; // Stop when reached the synthesized temporaries
|
||||
|
|
@ -1509,7 +1513,7 @@ class AstToDfgSynthesize final {
|
|||
// List of multi-driven variables
|
||||
std::vector<DfgVertexVar*> multidrivenps;
|
||||
// Map from variable to its resolved driver
|
||||
std::unordered_map<DfgVertexVar*, DfgVertexSplice*> resolvedDrivers;
|
||||
std::unordered_map<const DfgVertexVar*, DfgVertexSplice*> resolvedDrivers;
|
||||
// Compute resolved drivers of all variablees
|
||||
for (DfgVertexVar& var : m_dfg.varVertices()) {
|
||||
if (!var.srcp()) continue;
|
||||
|
|
@ -1536,7 +1540,7 @@ class AstToDfgSynthesize final {
|
|||
UASSERT_OBJ(newEntry, &var, "Dupliacte driver");
|
||||
}
|
||||
// Revert and remove drivers of multi-driven variables
|
||||
for (DfgVertexVar* const vtxp : multidrivenps) {
|
||||
for (const DfgVertexVar* const vtxp : multidrivenps) {
|
||||
// Mark as multidriven for future DFG runs - here, so we get all warning before
|
||||
vtxp->varp()->setDfgMultidriven();
|
||||
// Might not have a driver if transitively removed on an earlier iteration
|
||||
|
|
@ -1546,7 +1550,7 @@ class AstToDfgSynthesize final {
|
|||
revertTransivelyAndRemove(unresolvedp, m_ctx.m_synt.revertMultidrive);
|
||||
}
|
||||
// Replace all DfgUnresolved with the resolved drivers
|
||||
for (DfgVertexVar& var : m_dfg.varVertices()) {
|
||||
for (const DfgVertexVar& var : m_dfg.varVertices()) {
|
||||
if (!var.srcp()) continue;
|
||||
DfgUnresolved* const srcp = var.srcp()->cast<DfgUnresolved>();
|
||||
if (!srcp) break; // Stop when reached the synthesized temporaries
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ public:
|
|||
// the actual driver this DfgVertexSplice can be replaced with.
|
||||
inline DfgVertex* wholep() const;
|
||||
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void resetSources() {
|
||||
m_driverData.clear();
|
||||
// Unlink default driver
|
||||
|
|
@ -375,7 +376,7 @@ class DfgUnresolved final : public DfgVertexVariadic {
|
|||
// Represents a collection of unresolved variable drivers before synthesis
|
||||
|
||||
public:
|
||||
DfgUnresolved(DfgGraph& dfg, DfgVertexVar* vtxp)
|
||||
DfgUnresolved(DfgGraph& dfg, const DfgVertexVar* vtxp)
|
||||
: DfgVertexVariadic{dfg, dfgType(), vtxp->fileline(), vtxp->dtypep(), 1u} {}
|
||||
ASTGEN_MEMBERS_DfgUnresolved;
|
||||
|
||||
|
|
@ -383,6 +384,7 @@ public:
|
|||
void addDriver(DfgLogic* vtxp) { addSource()->relinkSource(vtxp); }
|
||||
void addDriver(DfgVertexSplice* vtxp) { addSource()->relinkSource(vtxp); }
|
||||
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void clearSources() { DfgVertexVariadic::clearSources(); }
|
||||
|
||||
DfgVertex* singleSource() const { return arity() == 1 ? source(0) : nullptr; }
|
||||
|
|
|
|||
|
|
@ -649,18 +649,19 @@ void v3errorEndFatal(std::ostringstream& sstr)
|
|||
|
||||
/// Based on debug level, call UINFO then dumpTree on nodep, using given message prefix
|
||||
/// If uinfo_msg = "", suppress the first UINFO
|
||||
/// If dt_msg = "", use the uinfo_msg; note any uinfo_msg side effects will happen twice.
|
||||
#define UINFOTREE(level, nodep, uinfo_msg, dt_msg) \
|
||||
/// If dumptree_msg = "", use the uinfo_msg; note any uinfo_msg side effects will happen twice.
|
||||
#define UINFOTREE(level, nodep, uinfo_msg, dumptree_msg) \
|
||||
do { \
|
||||
if (VL_UNCOVERABLE(debug() >= (level))) { \
|
||||
std::ostringstream us; \
|
||||
us << uinfo_msg; \
|
||||
if (!us.str().empty()) UINFO(level, us.str()); \
|
||||
std::ostringstream ss; \
|
||||
ss << dt_msg; \
|
||||
if (ss.str().empty()) ss << uinfo_msg; \
|
||||
if (nodep) \
|
||||
nodep->dumpTree("- "s + V3Error::lineStr(__FILE__, __LINE__) + ss.str() + " - "); \
|
||||
if (nodep) { \
|
||||
std::ostringstream ss; \
|
||||
ss << dumptree_msg; \
|
||||
if (ss.str().empty()) ss << uinfo_msg; \
|
||||
nodep->dumpTree("- " + V3Error::lineStr(__FILE__, __LINE__) + ss.str() + " - "); \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
|
|
@ -722,6 +723,8 @@ void v3errorEndFatal(std::ostringstream& sstr)
|
|||
// Takes an optional "name" (as __VA_ARGS__)
|
||||
#define VL_DEFINE_DEBUG(...) \
|
||||
VL_ATTR_UNUSED static int debug##__VA_ARGS__() VL_MT_SAFE { \
|
||||
/* Don't complain this function is unused */ \
|
||||
(void)&debug##__VA_ARGS__; \
|
||||
static int level = -1; \
|
||||
if (VL_UNLIKELY(level < 0)) { \
|
||||
std::string tag{VL_STRINGIFY(__VA_ARGS__)}; \
|
||||
|
|
@ -739,6 +742,8 @@ void v3errorEndFatal(std::ostringstream& sstr)
|
|||
// Takes an optional "name" (as __VA_ARGS__)
|
||||
#define VL_DEFINE_DUMP(func, tag) \
|
||||
VL_ATTR_UNUSED static int dump##func() VL_MT_SAFE { \
|
||||
/* Don't complain this function is unused */ \
|
||||
(void)&dump##func; \
|
||||
static int level = -1; \
|
||||
if (VL_UNLIKELY(level < 0)) { \
|
||||
const unsigned dumpTag = v3Global.opt.dumpLevel(tag); \
|
||||
|
|
@ -762,6 +767,7 @@ void v3errorEndFatal(std::ostringstream& sstr)
|
|||
VL_DEFINE_DUMP(TreeJsonLevel, \
|
||||
"tree-json"); /* Define 'int dumpTreeJsonLevel()' for dumpi-tree-json */ \
|
||||
VL_ATTR_UNUSED static int dumpTreeEitherLevel() { \
|
||||
/* Don't complain this function is unused */ (void)&dumpTreeEitherLevel; \
|
||||
return dumpTreeJsonLevel() >= dumpTreeLevel() ? dumpTreeJsonLevel() : dumpTreeLevel(); \
|
||||
} \
|
||||
static_assert(true, "")
|
||||
|
|
|
|||
|
|
@ -302,7 +302,9 @@ public:
|
|||
puts("\n");
|
||||
}
|
||||
virtual void putsHeader() {}
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void puts(const char* strg) { putsNoTracking(strg); }
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void puts(const string& strg) { putsNoTracking(strg); }
|
||||
|
||||
// METHODS
|
||||
|
|
@ -388,7 +390,9 @@ public:
|
|||
~V3OutMkFile() override = default;
|
||||
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
|
||||
// No automatic indentation yet.
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void puts(const char* strg) { putsNoTracking(strg); }
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
void puts(const string& strg) { putsNoTracking(strg); }
|
||||
// Put VARIABLE = VALUE
|
||||
void putSet(const string& var, const string& value) {
|
||||
|
|
|
|||
11
src/V3Hash.h
11
src/V3Hash.h
|
|
@ -38,14 +38,17 @@ public:
|
|||
: m_value{0} {}
|
||||
explicit V3Hash(uint32_t val)
|
||||
: m_value{val} {}
|
||||
explicit V3Hash(int32_t val)
|
||||
: m_value{static_cast<uint32_t>(val)} {}
|
||||
explicit V3Hash(uint64_t val)
|
||||
: m_value{combine(static_cast<uint32_t>(val), static_cast<uint32_t>(val >> 32))} {}
|
||||
explicit V3Hash(int64_t val)
|
||||
: m_value{combine(static_cast<uint32_t>(val), static_cast<uint32_t>(val >> 32))} {}
|
||||
explicit V3Hash(const std::string& val);
|
||||
|
||||
explicit V3Hash(int32_t val)
|
||||
: V3Hash{static_cast<uint32_t>(val)} {}
|
||||
explicit V3Hash(int64_t val)
|
||||
: V3Hash{static_cast<uint64_t>(val)} {}
|
||||
explicit V3Hash(void* val)
|
||||
: V3Hash{reinterpret_cast<uintptr_t>(val)} {}
|
||||
|
||||
// METHODS
|
||||
uint32_t value() const VL_MT_SAFE { return m_value; }
|
||||
std::string toString() const VL_MT_SAFE;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public:
|
|||
Link m_next; // Next in list of sibling heaps
|
||||
Link m_kids; // Head of list of child heaps
|
||||
Node** m_ownerpp = nullptr; // Pointer to the Link pointer pointing to this heap
|
||||
T_Key m_key; // The key in the heap
|
||||
T_Key m_key{}; // The key in the heap
|
||||
|
||||
// CONSTRUCTOR
|
||||
explicit Node() = default;
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ private:
|
|||
V3Number fieldNum{nump, width};
|
||||
fieldNum.opSel(*nump, msb, lsb);
|
||||
out << itemp->name() << ": ";
|
||||
if (AstNodeDType* const childTypep = itemp->subDTypep()) {
|
||||
if (const AstNodeDType* const childTypep = itemp->subDTypep()) {
|
||||
out << prettyNumber(&fieldNum, childTypep);
|
||||
} else {
|
||||
out << fieldNum;
|
||||
|
|
@ -179,7 +179,7 @@ private:
|
|||
return out.str();
|
||||
}
|
||||
} else if (const AstPackArrayDType* const arrayp = VN_CAST(dtypep, PackArrayDType)) {
|
||||
if (AstNodeDType* const childTypep = arrayp->subDTypep()) {
|
||||
if (const AstNodeDType* const childTypep = arrayp->subDTypep()) {
|
||||
std::ostringstream out;
|
||||
out << "[";
|
||||
const int arrayElements = arrayp->elementsConst();
|
||||
|
|
@ -226,7 +226,7 @@ public:
|
|||
conIt != tconnects->end(); ++conIt) {
|
||||
const AstVar* const portp = conIt->first;
|
||||
AstNodeExpr* const pinp = conIt->second->exprp();
|
||||
AstNodeDType* const dtypep = pinp->dtypep();
|
||||
const AstNodeDType* const dtypep = pinp->dtypep();
|
||||
if (AstConst* const valp = fetchConstNull(pinp)) {
|
||||
stack << "\n " << portp->prettyName() << " = "
|
||||
<< prettyNumber(&valp->num(), dtypep);
|
||||
|
|
@ -876,7 +876,7 @@ private:
|
|||
void visit(AstArraySel* nodep) override {
|
||||
checkNodeInfo(nodep);
|
||||
iterateChildrenConst(nodep);
|
||||
if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
|
||||
if (const AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) {
|
||||
const AstConst* const indexp = fetchConst(nodep->bitp());
|
||||
const uint32_t offset = indexp->num().toUInt();
|
||||
AstNodeExpr* const itemp = initp->getIndexDefaultedValuep(offset);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ duplInheritedMember:src/V3AstNode*.h
|
|||
duplInheritedMember:src/obj_*/V3Ast__gen_impl.h
|
||||
// We intentionally redefine DfgVertex methods to match Ast
|
||||
duplInheritedMember:src/obj_*/V3Dfg__gen_auto_classes.h
|
||||
// TODO: fix - maybe?
|
||||
duplInheritedMember:src/V3File*.h
|
||||
// They are used after astgen expansion
|
||||
unusedPrivateFunction:src/V3Const.cpp
|
||||
// These are all inappropriate
|
||||
constVariablePointer:src/V3DfgPeephole.cpp
|
||||
constParameterPointer:src/V3DfgPeephole.cpp
|
||||
|
|
|
|||
Loading…
Reference in New Issue