From 8d0c06e5704352799bf45853af0ad5fb965f3b8c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 31 Aug 2022 19:49:24 -0400 Subject: [PATCH 01/75] devel release --- Changes | 6 ++++++ configure.ac | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 98f97de74..3cb14209e 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,12 @@ The changes in each Verilator version are described below. The contributors that suggested a given feature are shown in []. Thanks! +Verilator 4.227 devel +========================== + +**Minor:** + + Verilator 4.226 2022-08-31 ========================== diff --git a/configure.ac b/configure.ac index c7ef7c1be..7caacbd45 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,7 @@ # Then 'make maintainer-dist' #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[4.226 2022-08-31], +AC_INIT([Verilator],[4.227 devel], [https://verilator.org], [verilator],[https://verilator.org]) From 5c828b7e60a5dd95a805792c5f6285b5972b69b1 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Thu, 1 Sep 2022 18:03:51 +0100 Subject: [PATCH 02/75] V3Partition: use V3Lists to keep track of SiblingMCs Replace std::set with V3Lists to keep track of SiblingMCs associated with MTasks, use a std::set for ensuring uniqueness. This yields a bit more speed in PartContraction. --- src/V3Partition.cpp | 134 +++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index 1b11a00b5..a2978e93a 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -24,6 +24,7 @@ #include "V3File.h" #include "V3GraphStream.h" #include "V3InstrCount.h" +#include "V3List.h" #include "V3Os.h" #include "V3PairingHeap.h" #include "V3PartitionGraph.h" @@ -35,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -217,10 +219,12 @@ private: // Store the outgoing and incoming edges in a heap sorted by the critical path length std::array m_edgeHeap; - // SiblingMC for which storage is owned by this MTask - std::set m_ownSibs; - // SiblingMC for which storage is owned by the opposite MTask - std::set m_farSibps; + // MTasks for which a SiblingMC exists with 'this' as the higher ID MTask (m_ap in SiblingMC) + std::set m_siblings; + // List of SiblingMCs for which this is the higher ID MTask (m_ap in SiblingMC) + V3List m_aSiblingMCs; + // List of SiblingMCs for which this is the lower ID MTask (m_bp in SiblingMC) + V3List m_bSiblingMCs; public: // CONSTRUCTORS @@ -240,8 +244,9 @@ public: } // METHODS - std::set& ownSibs() { return m_ownSibs; }; - std::set& farSibs() { return m_farSibps; }; + std::set& siblings() { return m_siblings; }; + V3List& aSiblingMCs() { return m_aSiblingMCs; }; + V3List& bSiblingMCs() { return m_bSiblingMCs; }; void moveAllVerticesFrom(LogicMTask* otherp) { // splice() is constant time @@ -465,10 +470,12 @@ static_assert(sizeof(MergeCandidate) == sizeof(MergeCandidateScoreboard::Node), // A pair of associated LogicMTask's that are merge candidates for sibling // contraction class SiblingMC final : public MergeCandidate { -private: LogicMTask* const m_ap; LogicMTask* const m_bp; + V3ListEnt m_aEnt; // List entry for m_ap->aSiblingMCs() + V3ListEnt m_bEnt; // List entry for m_bp->bSiblingMCs() + public: // CONSTRUCTORS SiblingMC() = delete; @@ -476,26 +483,33 @@ public: : MergeCandidate{/* isSiblingMC: */ true} , m_ap{ap} , m_bp{bp} { - // operator< and storage management depends on this + // Storage management depends on this UASSERT(ap->id() > bp->id(), "Should be ordered"); + UDEBUGONLY(UASSERT(ap->siblings().count(bp), "Should be in sibling map");); + m_aEnt.pushBack(m_ap->aSiblingMCs(), this); + m_bEnt.pushBack(m_bp->bSiblingMCs(), this); } ~SiblingMC() = default; + // METHODS + SiblingMC* aNextp() const { return m_aEnt.nextp(); } + SiblingMC* bNextp() const { return m_bEnt.nextp(); } + void unlinkA() { + VL_ATTR_UNUSED const size_t removed = m_ap->siblings().erase(m_bp); + UDEBUGONLY(UASSERT(removed == 1, "Should have been in sibling set");); + m_aEnt.unlink(m_ap->aSiblingMCs(), this); + } + void unlinkB() { m_bEnt.unlink(m_bp->bSiblingMCs(), this); } + LogicMTask* ap() const { return m_ap; } LogicMTask* bp() const { return m_bp; } bool mergeWouldCreateCycle() const { return (LogicMTask::pathExistsFrom(m_ap, m_bp, nullptr) || LogicMTask::pathExistsFrom(m_bp, m_ap, nullptr)); } - bool operator<(const SiblingMC& other) const { - if (m_ap->id() < other.m_ap->id()) return true; - if (m_ap->id() > other.m_ap->id()) return false; - return m_bp->id() < other.m_bp->id(); - } }; -static_assert(sizeof(SiblingMC) == sizeof(MergeCandidate) + 2 * sizeof(LogicMTask*), - "Should not have a vtable"); +static_assert(!std::is_polymorphic::value, "Should not have a vtable"); // GraphEdge for the MTask graph class MTaskEdge final : public V3GraphEdge, public MergeCandidate { @@ -1385,12 +1399,13 @@ public: // New edges would be AC->B and B->AC which is not a DAG. // Do not allow this. if (mergeCanp->mergeWouldCreateCycle()) { - // Remove this edge from scoreboard so we don't keep + // Remove this candidate from scoreboard so we don't keep // reconsidering it on every loop. m_sb.remove(mergeCanp); if (SiblingMC* const smcp = mergeCanp->toSiblingMC()) { - smcp->bp()->farSibs().erase(smcp); - smcp->ap()->ownSibs().erase(*smcp); // Kills *smcp, so do last + smcp->unlinkA(); + smcp->unlinkB(); + delete smcp; } continue; } @@ -1455,29 +1470,45 @@ private: } void removeSiblingMCsWith(LogicMTask* mtaskp) { - for (const SiblingMC& pair : mtaskp->ownSibs()) { - m_sb.remove(const_cast(&pair)); - // Owner is always ap(), remove from the opposite side - pair.bp()->farSibs().erase(&pair); + for (SiblingMC *smcp = mtaskp->aSiblingMCs().begin(), *nextp; // lintok-begin-on-ref + smcp; smcp = nextp) { + nextp = smcp->aNextp(); + m_sb.remove(smcp); + smcp->unlinkB(); + delete smcp; } - for (const SiblingMC* const pairp : mtaskp->farSibs()) { - m_sb.remove(const_cast(pairp)); - // Owner is always ap(), remove from the opposite side - pairp->ap()->ownSibs().erase(*pairp); + for (SiblingMC *smcp = mtaskp->bSiblingMCs().begin(), *nextp; // lintok-begin-on-ref + smcp; smcp = nextp) { + nextp = smcp->bNextp(); + m_sb.remove(smcp); + smcp->unlinkA(); + delete smcp; } - mtaskp->ownSibs().clear(); - mtaskp->farSibs().clear(); + } + + void removeSiblingMCs(LogicMTask* recipientp, LogicMTask* donorp) { + // The lists here should be disjoint (there should be only one SiblingMC involving these + // two MTasks, and we removed that elsewhere), so no need for unlinking from the lists we + // are clearing. + removeSiblingMCsWith(recipientp); + removeSiblingMCsWith(donorp); + + // Clear the sibling map of the recipient. The donor will be deleted anyway, so we can + // leave that in a corrupt for efficiency. + recipientp->siblings().clear(); + recipientp->aSiblingMCs().reset(); + recipientp->bSiblingMCs().reset(); } void contract(MergeCandidate* mergeCanp) { LogicMTask* top = nullptr; LogicMTask* fromp = nullptr; - MTaskEdge* mergeEdgep = mergeCanp->toMTaskEdge(); + MTaskEdge* const mergeEdgep = mergeCanp->toMTaskEdge(); + SiblingMC* const mergeSibsp = mergeCanp->toSiblingMC(); if (mergeEdgep) { top = static_cast(mergeEdgep->top()); fromp = static_cast(mergeEdgep->fromp()); } else { - const SiblingMC* mergeSibsp = static_cast(mergeCanp); top = mergeSibsp->ap(); fromp = mergeSibsp->bp(); } @@ -1513,14 +1544,19 @@ private: const NewCp recipientNewCpRev = newCp(recipientp, donorp, mergeEdgep); const NewCp donorNewCpRev = newCp(donorp, recipientp, mergeEdgep); + m_sb.remove(mergeCanp); + if (mergeEdgep) { - // Remove and free the connecting edge. Must do this before - // propagating CP's below. - m_sb.remove(mergeCanp); + // Remove and free the connecting edge. Must do this before propagating CP's below. mergeEdgep->fromMTaskp()->removeRelativeMTask(mergeEdgep->toMTaskp()); mergeEdgep->fromMTaskp()->removeRelativeEdge(mergeEdgep); mergeEdgep->toMTaskp()->removeRelativeEdge(mergeEdgep); - VL_DO_CLEAR(mergeEdgep->unlinkDelete(), mergeEdgep = nullptr); + VL_DO_DANGLING(mergeEdgep->unlinkDelete(), mergeEdgep); + } else { + // Remove the siblingMC + mergeSibsp->unlinkA(); + mergeSibsp->unlinkB(); + VL_DO_DANGLING(delete mergeEdgep, mergeEdgep); } // This also updates cost and stepCost on recipientp @@ -1552,13 +1588,10 @@ private: m_forwardPropagator.go(); m_reversePropagator.go(); - // Remove all SiblingMCs that include donorp. This Includes the one - // we're merging, if we're merging a SiblingMC. - removeSiblingMCsWith(donorp); - // Remove all SiblingMCs that include recipientp also, so we can't - // get huge numbers of SiblingMCs. We'll recreate them below, up + // Remove all other SiblingMCs that include recipientp or donorp. We remove all siblingMCs + // of recipientp so we do not get huge numbers of SiblingMCs. We'll recreate them below, up // to a bounded number. - removeSiblingMCsWith(recipientp); + removeSiblingMCs(recipientp, donorp); // Redirect all edges, delete donorp partRedirectEdgesFrom(m_mtasksp, recipientp, donorp, &m_sb); @@ -1607,20 +1640,19 @@ private: void makeSiblingMC(LogicMTask* ap, LogicMTask* bp) { if (ap->id() < bp->id()) std::swap(ap, bp); - // The higher id vertex owns the storage - const auto emplaceResult = ap->ownSibs().emplace(ap, bp); - if (emplaceResult.second) { - SiblingMC* const newSibsp = const_cast(&(*emplaceResult.first)); - bp->farSibs().insert(newSibsp); - m_sb.add(newSibsp); - } else if (m_slowAsserts) { + // The higher id vertex owns the association set + const auto first = ap->siblings().insert(bp).second; + if (first) { + m_sb.add(new SiblingMC{ap, bp}); + } else if (VL_UNLIKELY(m_slowAsserts)) { // It's fine if we already have this SiblingMC, we may have // created it earlier. Just confirm that we have associated data. bool found = false; - for (const SiblingMC& sibs : ap->ownSibs()) { - UASSERT_OBJ(sibs.ap() == ap, ap, "Inconsistent SiblingMC"); - UASSERT_OBJ(m_sb.contains(&sibs), ap, "Must be on the scoreboard"); - if (sibs.bp() == bp) found = true; + for (const SiblingMC* smcp = ap->aSiblingMCs().begin(); // lintok-begin-on-ref + smcp; smcp = smcp->aNextp()) { + UASSERT_OBJ(smcp->ap() == ap, ap, "Inconsistent SiblingMC"); + UASSERT_OBJ(m_sb.contains(smcp), ap, "Must be on the scoreboard"); + if (smcp->bp() == bp) found = true; } UASSERT_OBJ(found, ap, "Sibling not found"); } From 2ba39b25f1a2c8f821a903cbceb28afad3da416c Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 2 Sep 2022 11:29:02 +0100 Subject: [PATCH 03/75] Replace dynamic_casts with static_casts dynamic_cast is not free. Replace obvious instances (where the result is unconditionally dereferenced) with static_cast in contexts with performance implications. --- src/V3Gate.cpp | 14 +++++++------- src/V3Order.cpp | 14 +++++++------- src/V3VariableOrder.cpp | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 88a9332d4..726bbbfa8 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -107,7 +107,7 @@ public: VNUser iterateInEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { VNUser ret = VNUser(0); for (V3GraphEdge* edgep = inBeginp(); edgep; edgep = edgep->inNextp()) { - ret = dynamic_cast(edgep->fromp())->accept(v, vu); + ret = static_cast(edgep->fromp())->accept(v, vu); } return ret; } @@ -121,7 +121,7 @@ public: for (V3GraphEdge* edgep = outBeginp(); edgep; edgep = next_edgep) { // Need to find the next edge before visiting in case the edge is deleted next_edgep = edgep->outNextp(); - ret = dynamic_cast(edgep->top())->accept(v, vu); + ret = static_cast(edgep->top())->accept(v, vu); } return ret; } @@ -683,7 +683,7 @@ bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp, varscopes.insert(vscp); } for (V3GraphEdge* edgep = consumeVertexp->outBeginp(); edgep; edgep = edgep->outNextp()) { - const GateVarVertex* const consVVertexp = dynamic_cast(edgep->top()); + const GateVarVertex* const consVVertexp = static_cast(edgep->top()); AstVarScope* const vscp = consVVertexp->varScp(); if (varscopes.find(vscp) != varscopes.end()) { UINFO(9, " Block-unopt, insertion generates input vscp " << vscp << endl); @@ -764,8 +764,8 @@ void GateVisitor::consumedMove() { if (!vvertexp->consumed() && !vvertexp->user()) { UINFO(8, "Unconsumed " << vvertexp->varScp() << endl); } - } - if (const GateLogicVertex* const lvertexp = dynamic_cast(vertexp)) { + } else { + const GateLogicVertex* const lvertexp = static_cast(vertexp); AstNode* const nodep = lvertexp->nodep(); const AstActive* const oldactp = lvertexp->activep(); // nullptr under cfunc if (!lvertexp->consumed() && oldactp) { @@ -1108,7 +1108,7 @@ private: // Replace all of this varvertex's consumers with dupVarRefp for (V3GraphEdge* outedgep = vvertexp->outBeginp(); outedgep;) { const GateLogicVertex* const consumeVertexp - = dynamic_cast(outedgep->top()); + = static_cast(outedgep->top()); AstNode* const consumerp = consumeVertexp->nodep(); // if (debug() >= 9) m_graphp->dumpDotFilePrefixed("gate_preelim"); UINFO(9, @@ -1283,7 +1283,7 @@ private: V3GraphEdge* oedgep = ledgep; ledgep = ledgep->inNextp(); GateEitherVertex* const fromvp - = dynamic_cast(oedgep->fromp()); + = static_cast(oedgep->fromp()); new V3GraphEdge(m_graphp, fromvp, m_logicvp, 1); VL_DO_DANGLING(oedgep->unlinkDelete(), oedgep); } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 1d83983ea..9c20558e4 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -1027,8 +1027,8 @@ class OrderVerticesByDomainThenScope final { public: virtual bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { - const MTaskMoveVertex* const l_vxp = dynamic_cast(lhsp); - const MTaskMoveVertex* const r_vxp = dynamic_cast(rhsp); + const MTaskMoveVertex* const l_vxp = static_cast(lhsp); + const MTaskMoveVertex* const r_vxp = static_cast(rhsp); uint64_t l_id = m_ids.findId(l_vxp->domainp()); uint64_t r_id = m_ids.findId(r_vxp->domainp()); if (l_id < r_id) return true; @@ -1047,8 +1047,8 @@ public: // Sort vertex's, which must be AbstractMTask's, into a deterministic // order by comparing their serial IDs. virtual bool operator()(const V3GraphVertex* lhsp, const V3GraphVertex* rhsp) const { - const AbstractMTask* const lmtaskp = dynamic_cast(lhsp); - const AbstractMTask* const rmtaskp = dynamic_cast(rhsp); + const AbstractMTask* const lmtaskp = static_cast(lhsp); + const AbstractMTask* const rmtaskp = static_cast(rhsp); return lmtaskp->id() < rmtaskp->id(); } }; @@ -1932,7 +1932,7 @@ void OrderProcess::processMTasks() { GraphStream emit_logic(&logicGraph); const V3GraphVertex* moveVxp; while ((moveVxp = emit_logic.nextp())) { - const MTaskMoveVertex* const movep = dynamic_cast(moveVxp); + const MTaskMoveVertex* const movep = static_cast(moveVxp); const unsigned mtaskId = movep->color(); UASSERT(mtaskId > 0, "Every MTaskMoveVertex should have an mtask assignment >0"); if (movep->logicp()) { @@ -1976,7 +1976,7 @@ void OrderProcess::processMTasks() { GraphStream emit_mtasks(&mtasks); const V3GraphVertex* mtaskVxp; while ((mtaskVxp = emit_mtasks.nextp())) { - const AbstractLogicMTask* const mtaskp = dynamic_cast(mtaskVxp); + const AbstractLogicMTask* const mtaskp = static_cast(mtaskVxp); // Create a body for this mtask AstMTaskBody* const bodyp = new AstMTaskBody(rootFlp); @@ -2018,7 +2018,7 @@ void OrderProcess::processMTasks() { for (V3GraphEdge* inp = mtaskp->inBeginp(); inp; inp = inp->inNextp()) { const V3GraphVertex* fromVxp = inp->fromp(); const AbstractLogicMTask* const fromp - = dynamic_cast(fromVxp); + = static_cast(fromVxp); const MTaskState& fromState = mtaskStates[fromp->id()]; new V3GraphEdge(depGraphp, fromState.m_execMTaskp, state.m_execMTaskp, 1); } diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp index d62cfb50f..d3ea7aa3d 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -52,14 +52,14 @@ public: ~VarTspSorter() override = default; // METHODS virtual bool operator<(const TspStateBase& other) const override { - return operator<(dynamic_cast(other)); + return operator<(static_cast(other)); } bool operator<(const VarTspSorter& other) const { return m_serial < other.m_serial; } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } virtual int cost(const TspStateBase* otherp) const override { - return cost(dynamic_cast(otherp)); + return cost(static_cast(otherp)); } - virtual int cost(const VarTspSorter* otherp) const { + int cost(const VarTspSorter* otherp) const { int cost = diffs(m_mtaskIds, otherp->m_mtaskIds); cost += diffs(otherp->m_mtaskIds, m_mtaskIds); return cost; From 8e8f4b1e5c14467503f0f5d6651e0cf8c7a00350 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 2 Sep 2022 16:38:06 +0100 Subject: [PATCH 04/75] Remove AstVarScope::valuep() and related code This is detritus from when V3TraceDecl used to run after V3Gate, today V3TraceDecl runs before V3Gate and this value has no function at all. No functional change intended. --- src/V3AstNodes.h | 3 --- src/V3Gate.cpp | 66 +-------------------------------------------- src/V3TraceDecl.cpp | 6 +---- 3 files changed, 2 insertions(+), 73 deletions(-) diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 64c25e494..cef18db50 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2553,9 +2553,6 @@ public: AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable AstScope* scopep() const { return m_scopep; } // Pointer to scope it's under void scopep(AstScope* nodep) { m_scopep = nodep; } - // op1 = Calculation of value of variable, nullptr=complicated - AstNode* valuep() const { return op1p(); } - void valuep(AstNode* valuep) { addOp1p(valuep); } bool isCircular() const { return m_circular; } void circular(bool flag) { m_circular = flag; } bool isTrace() const { return m_trace; } diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 726bbbfa8..a4c72d5d4 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -408,7 +408,6 @@ private: void consumedMark(); void consumedMarkRecurse(GateEitherVertex* vertexp); void consumedMove(); - void replaceAssigns(); void dedupe(); void mergeAssigns(); void decomposeClkVectors(); @@ -445,7 +444,6 @@ private: m_graph.dumpDotFilePrefixed("gate_opt"); // Rewrite assignments consumedMove(); - replaceAssigns(); } virtual void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); @@ -654,14 +652,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) { while (V3GraphEdge* const edgep = vvertexp->inBeginp()) { VL_DO_DANGLING(edgep->unlinkDelete(), edgep); } - // Clone tree so we remember it for tracing, and keep the pointer - // to the "ALWAYS" part of the tree as part of this statement - // That way if a later signal optimization that - // retained a pointer to the always can - // optimize it further - VL_DO_DANGLING(vvertexp->varScp()->valuep(logicp->unlinkFrBack()), logicp); - // Mark the vertex so we don't mark it as being - // unconsumed in the next step + // Mark the vertex so we don't mark it as being unconsumed in the next step vvertexp->user(true); logicVertexp->user(true); } @@ -693,45 +684,6 @@ bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp, return true; } -void GateVisitor::replaceAssigns() { - for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { - if (const GateVarVertex* const vvertexp = dynamic_cast(itp)) { - // Take the Comments/assigns that were moved to the VarScope and change them to a - // simple value assignment - const AstVarScope* const vscp = vvertexp->varScp(); - if (vscp->valuep() && !VN_IS(vscp->valuep(), NodeMath)) { - // if (debug() > 9) vscp->dumpTree(cout, "-vscPre: "); - while (AstNode* delp = VN_CAST(vscp->valuep(), Comment)) { - VL_DO_DANGLING(delp->unlinkFrBack()->deleteTree(), delp); - } - if (AstInitial* const delp = VN_CAST(vscp->valuep(), Initial)) { - AstNode* const bodyp = delp->bodysp(); - bodyp->unlinkFrBackWithNext(); - delp->replaceWith(bodyp); - VL_DO_DANGLING(delp->deleteTree(), delp); - } - if (AstAlways* const delp = VN_CAST(vscp->valuep(), Always)) { - AstNode* const bodyp = delp->bodysp(); - bodyp->unlinkFrBackWithNext(); - delp->replaceWith(bodyp); - VL_DO_DANGLING(delp->deleteTree(), delp); - } - if (AstNodeAssign* const delp = VN_CAST(vscp->valuep(), NodeAssign)) { - AstNode* const rhsp = delp->rhsp(); - rhsp->unlinkFrBack(); - delp->replaceWith(rhsp); - VL_DO_DANGLING(delp->deleteTree(), delp); - } - // if (debug() > 9) {vscp->dumpTree(cout, "-vscDone: "); cout<valuep(), NodeMath) || vscp->valuep()->nextp()) { - vscp->dumpTree(std::cerr, "vscStrange: "); - vscp->v3fatalSrc("Value of varscope not mathematical"); - } - } - } - } -} - //---------------------------------------------------------------------- void GateVisitor::consumedMark() { @@ -1132,11 +1084,6 @@ private: while (V3GraphEdge* const inedgep = vvertexp->inBeginp()) { VL_DO_DANGLING(inedgep->unlinkDelete(), inedgep); } - // replaceAssigns() does the deleteTree on lvertexNodep in a later step - AstNode* lvertexNodep = lvertexp->nodep(); - lvertexNodep->unlinkFrBack(); - vvertexp->varScp()->valuep(lvertexNodep); - lvertexNodep = nullptr; vvertexp->user(true); lvertexp->user(true); } @@ -1527,16 +1474,5 @@ void GateVisitor::decomposeClkVectors() { void V3Gate::gateAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { const GateVisitor visitor{nodep}; } // Destruct before checking - - nodep->foreach([](AstVarScope* nodep) { - if (AstNodeAssign* const assp = VN_CAST(nodep->valuep(), NodeAssign)) { - UINFO(5, " Removeassign " << assp << endl); - AstNode* const valuep = assp->rhsp(); - valuep->unlinkFrBack(); - assp->replaceWith(valuep); - VL_DO_DANGLING(assp->deleteTree(), assp); - } - }); - V3Global::dumpCheckGlobalTree("gate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 6fc9a8726..4a596e434 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -280,11 +280,7 @@ private: addIgnore(ignoreReasonp); } else { ++m_statSigs; - if (AstNode* const valuep = m_traVscp->valuep()) { - m_traValuep = valuep->cloneTree(false); - } else { - m_traValuep = new AstVarRef{m_traVscp->fileline(), m_traVscp, VAccess::READ}; - } + m_traValuep = new AstVarRef{m_traVscp->fileline(), m_traVscp, VAccess::READ}; // Recurse into data type of the signal. The visit methods will add AstTraceDecls. iterate(m_traVscp->varp()->dtypep()->skipRefToEnump()); // Cleanup From d42a2d6494d6c13b5884bd5e2b6be929310856ba Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 2 Sep 2022 19:31:13 +0100 Subject: [PATCH 05/75] Fix V3Gate crash on circular logic The recent patch to defer substitutions on V3Gate crashes on circular logic that has cycle length >= 3 with all inlineable signals (cycle length 2 is detected correctly and is not inlined). Fix by stopping recursion at the loop-back edge. Fixes #3543 --- Changes | 2 ++ src/V3Gate.cpp | 16 +++++++++++++--- test_regress/t/t_gate_loop.pl | 18 ++++++++++++++++++ test_regress/t/t_gate_loop.v | 14 ++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100755 test_regress/t/t_gate_loop.pl create mode 100644 test_regress/t/t_gate_loop.v diff --git a/Changes b/Changes index 3cb14209e..5cae1fc1c 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,8 @@ Verilator 4.227 devel **Minor:** +Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] + Verilator 4.226 2022-08-31 ========================== diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index a4c72d5d4..e4b2e8853 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -985,11 +985,18 @@ static void eliminate(AstNode* logicp, const std::unordered_map& substitutions, GateDedupeVarVisitor* varVisp) { - const std::function visit - = [&substitutions, &visit, varVisp](AstNodeVarRef* nodep) -> void { + // Recursion filter holding already replaced variables + std::unordered_set replaced(substitutions.size() * 2); + + const std::function visit = [&, varVisp](AstNodeVarRef* nodep) -> void { // See if this variable has a substitution - const auto& it = substitutions.find(nodep->varScopep()); + AstVarScope* const vscp = nodep->varScopep(); + const auto& it = substitutions.find(vscp); if (it == substitutions.end()) return; + + // Do not substitute circular logic + if (!replaced.insert(vscp).second) return; + AstNode* const substp = it->second; // Substitute in the new tree @@ -1016,6 +1023,9 @@ static void eliminate(AstNode* logicp, VL_DO_DANGLING(nodep->deleteTree(), nodep); // Recursively substitute the new tree newp->foreach(visit); + + // Remove from recursion filter + replaced.erase(vscp); }; logicp->foreach(visit); diff --git a/test_regress/t/t_gate_loop.pl b/test_regress/t/t_gate_loop.pl new file mode 100755 index 000000000..1d9caab1c --- /dev/null +++ b/test_regress/t/t_gate_loop.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Geza Lore. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + verilator_flags2 => ["-Wno-UNOPTFLAT"] + ); + +ok(1); +1; diff --git a/test_regress/t/t_gate_loop.v b/test_regress/t/t_gate_loop.v new file mode 100644 index 000000000..13ce7c416 --- /dev/null +++ b/test_regress/t/t_gate_loop.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Geza Lore. +// SPDX-License-Identifier: CC0-1.0 + +module t; + wire a; + wire b; + wire c; + assign a = b; + assign b = c; + assign c = a; +endmodule From 937e893b6d689a641d2d0be91cfec1f40ff05dca Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 3 Sep 2022 22:10:07 +0100 Subject: [PATCH 06/75] Build verilator_bin with -O3 (#3592) This is consistently a few percent faster. --- src/Makefile_obj.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 140be6086..1496cc411 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -79,7 +79,7 @@ ifeq ($(VL_NOOPT),1) CPPFLAGS += -O0 else ifeq ($(VL_DEBUG),) # Optimize -CPPFLAGS += -O2 +CPPFLAGS += -O3 else # Debug CPPFLAGS += @CFG_CXXFLAGS_DEBUG@ -DVL_DEBUG -D_GLIBCXX_DEBUG From fb931087abf52db1f0dbb6d3679c2b1b71cf56f3 Mon Sep 17 00:00:00 2001 From: Krzysztof Bieganski Date: Mon, 5 Sep 2022 17:20:38 +0200 Subject: [PATCH 07/75] Add stats tracking for `V3Undriven`. (#3600) Signed-off-by: Krzysztof Bieganski --- src/V3Undriven.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 0732dafa1..4f6374cde 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -30,6 +30,7 @@ #include "V3Ast.h" #include "V3Global.h" +#include "V3Stats.h" #include "V3String.h" #include @@ -475,4 +476,5 @@ public: void V3Undriven::undrivenAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { UndrivenVisitor{nodep}; } + if (v3Global.opt.stats()) V3Stats::statsStage("undriven"); } From 6b6790fc501dde4bc5d14c5b97a1a061584a2191 Mon Sep 17 00:00:00 2001 From: Krzysztof Bieganski Date: Mon, 29 Aug 2022 15:26:00 +0200 Subject: [PATCH 08/75] Preserve return type of `AstNode::addNext` via templating (#3597) No functional change intended. Signed-off-by: Krzysztof Bieganski --- src/V3Ast.cpp | 8 +++++--- src/V3Ast.h | 35 ++++++++++++++++++++++++++--------- src/V3AstInlines.h | 9 ++++++++- src/V3Const.cpp | 2 +- src/V3ParseGrammar.cpp | 4 ++-- src/V3Slice.cpp | 9 +++++---- src/verilog.y | 4 ++-- 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 213ddd3fb..2f1467f03 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -213,7 +213,7 @@ string AstNode::prettyTypeName() const { // Insertion inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int lineno, - bool next){ + bool next) { #ifdef VL_DEBUG // Called on all major tree changers. // Only for use for those really nasty bugs relating to internals @@ -234,7 +234,8 @@ inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, i #endif } -AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { +template <> +AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { // Add to m_nextp, returns this UDEBUGONLY(UASSERT_OBJ(newp, nodep, "Null item passed to addNext");); debugTreeChange(nodep, "-addNextThs: ", __LINE__, false); @@ -272,7 +273,8 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { return nodep; } -AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) { +template <> +AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) { if (!newp) return nodep; return addNext(nodep, newp); } diff --git a/src/V3Ast.h b/src/V3Ast.h index b05c43318..9e50846cd 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1759,16 +1759,27 @@ public: // METHODS - Tree modifications // Returns nodep, adds newp to end of nodep's list - static AstNode* addNext(AstNode* nodep, AstNode* newp); - // Returns nodep, adds newp (maybe nullptr) to end of nodep's list - static AstNode* addNextNull(AstNode* nodep, AstNode* newp); - inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); } - inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); } - void addNextHere(AstNode* newp); // Insert newp at this->nextp - void addPrev(AstNode* newp) { - replaceWith(newp); - newp->addNext(this); + template + static T_NodeResult* addNext(T_NodeResult* nodep, T_NodeNext* newp) { + static_assert(std::is_base_of::value, + "'T_NodeResult' must be a subtype of AstNode"); + static_assert(std::is_base_of::value, + "'T_NodeNext' must be a subtype of 'T_NodeResult'"); + return static_cast(addNext(nodep, newp)); } + // Returns nodep, adds newp (maybe nullptr) to end of nodep's list + template + static T_NodeResult* addNextNull(T_NodeResult* nodep, T_NodeNext* newp) { + static_assert(std::is_base_of::value, + "'T_NodeResult' must be a subtype of AstNode"); + static_assert(std::is_base_of::value, + "'T_NodeNext' must be a subtype of 'T_NodeResult'"); + return static_cast(addNextNull(nodep, newp)); + } + inline AstNode* addNext(AstNode* newp); + inline AstNode* addNextNull(AstNode* newp); + void addNextHere(AstNode* newp); // Insert newp at this->nextp + inline void addPrev(AstNode* newp); void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node AstNode* unlinkFrBack(VNRelinker* linkerp @@ -2056,6 +2067,12 @@ public: } }; +// Forward declarations of specializations defined in V3Ast.cpp +template <> +AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp); +template <> +AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp); + // Specialisations of privateTypeTest #include "V3Ast__gen_impl.h" // From ./astgen diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 6d8e93b35..9ad974a69 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -23,7 +23,14 @@ #endif //###################################################################### -// Inline ACCESSORS +// Inline METHODS + +inline AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); } +inline AstNode* AstNode::addNextNull(AstNode* newp) { return addNextNull(this, newp); } +inline void AstNode::addPrev(AstNode* newp) { + replaceWith(newp); + newp->addNext(this); +} inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index fb90cf866..096510af1 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -2079,7 +2079,7 @@ private: AstSel* const sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2 - lsb2 + 1); // Make new assigns of same flavor as old one //*** Not cloneTree; just one node. - AstNode* newp = nullptr; + AstNodeAssign* newp = nullptr; if (!need_temp) { AstNodeAssign* const asn1ap = VN_AS(nodep->cloneType(lc1p, sel1p), NodeAssign); AstNodeAssign* const asn2ap = VN_AS(nodep->cloneType(lc2p, sel2p), NodeAssign); diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 38bae0374..8e95d13c8 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -67,10 +67,10 @@ void V3ParseImp::parserClear() { //====================================================================== // V3ParseGrammar functions requiring bison state -AstNode* V3ParseGrammar::argWrapList(AstNode* nodep) { +AstArg* V3ParseGrammar::argWrapList(AstNode* nodep) { // Convert list of expressions to list of arguments if (!nodep) return nullptr; - AstNode* outp = nullptr; + AstArg* outp = nullptr; AstBegin* const tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep); while (nodep) { AstNode* const nextp = nodep->nextp(); diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 94a70fe99..b143373f2 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -139,12 +139,13 @@ class SliceVisitor final : public VNVisitor { // Left and right could have different msb/lsbs/endianness, but #elements is common // and all variables are realigned to start at zero // Assign of a little endian'ed slice to a big endian one must reverse the elements - AstNode* newlistp = nullptr; + AstNodeAssign* newlistp = nullptr; const int elements = arrayp->rangep()->elementsConst(); for (int offset = 0; offset < elements; ++offset) { - AstNode* const newp = nodep->cloneType // AstNodeAssign - (cloneAndSel(nodep->lhsp(), elements, offset), - cloneAndSel(nodep->rhsp(), elements, offset)); + AstNodeAssign* const newp + = VN_AS(nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, offset), + cloneAndSel(nodep->rhsp(), elements, offset)), + NodeAssign); if (debug() >= 9) newp->dumpTree(cout, "-new "); newlistp = AstNode::addNextNull(newlistp, newp); } diff --git a/src/verilog.y b/src/verilog.y index 907ca05d2..3d77c680b 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -91,7 +91,7 @@ public: } // METHODS - AstNode* argWrapList(AstNode* nodep); + AstArg* argWrapList(AstNode* nodep); bool allTracingOn(FileLine* fl) { return v3Global.opt.trace() && m_tracingParse && fl->tracingOn(); } @@ -5103,7 +5103,7 @@ idArrayedForeach: // IEEE: id + select (under foreach expression) | idArrayed '[' expr ',' loop_variables ']' { $3 = AstNode::addNextNull($3, $5); $$ = new AstSelLoopVars($2, $1, $3); } | idArrayed '[' ',' loop_variables ']' - { $4 = AstNode::addNextNull(new AstEmpty{$3}, $4); $$ = new AstSelLoopVars($2, $1, $4); } + { $4 = AstNode::addNextNull(static_cast(new AstEmpty{$3}), $4); $$ = new AstSelLoopVars($2, $1, $4); } ; // VarRef without any dots or vectorizaion From 1c9263a25b4a3fc0ab3286262305f42e3acb2bdb Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 5 Sep 2022 15:20:08 -0400 Subject: [PATCH 09/75] Commentary --- docs/guide/simulating.rst | 6 +++--- test_regress/t/t_EXAMPLE.v | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/guide/simulating.rst b/docs/guide/simulating.rst index 01dd7f844..7209a0a19 100644 --- a/docs/guide/simulating.rst +++ b/docs/guide/simulating.rst @@ -7,9 +7,9 @@ Simulating (Verilated-Model Runtime) ************************************ -This section describes items related to simulating, that using a Verilated -model's executable. For the runtime arguments to a simulated model, see -:ref:`Simulation Runtime Arguments`. +This section describes items related to simulating, that is, the use of a +Verilated model's executable. For the runtime arguments to a simulated +model, see :ref:`Simulation Runtime Arguments`. .. _Benchmarking & Optimization: diff --git a/test_regress/t/t_EXAMPLE.v b/test_regress/t/t_EXAMPLE.v index 0e3a9b428..236e0f85d 100644 --- a/test_regress/t/t_EXAMPLE.v +++ b/test_regress/t/t_EXAMPLE.v @@ -13,7 +13,7 @@ // please note it here, otherwise:** // // This file ONLY is placed under the Creative Commons Public Domain, for -// any use, without warranty, 2022 by ____YOUR_NAME_HERE____. +// any use, without warranty, 2022 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 module t(/*AUTOARG*/ From 1af046986d3aeb1daa7d0f96e9c17a46fe214d5f Mon Sep 17 00:00:00 2001 From: Mladen Slijepcevic <77167949+mslijepc@users.noreply.github.com> Date: Tue, 6 Sep 2022 00:42:12 +0200 Subject: [PATCH 10/75] Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). --- docs/CONTRIBUTORS | 1 + include/verilated_funcs.h | 46 ++++-- test_regress/t/t_var_sc_bv.cpp | 220 +++++++++++++++++++++++++++++ test_regress/t/t_var_sc_bv.pl | 24 ++++ test_regress/t/t_var_sc_bv.v | 246 +++++++++++++++++++++++++++++++++ 5 files changed, 522 insertions(+), 15 deletions(-) create mode 100644 test_regress/t/t_var_sc_bv.cpp create mode 100755 test_regress/t/t_var_sc_bv.pl create mode 100644 test_regress/t/t_var_sc_bv.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 9c10dbb6f..83ab9f830 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -82,6 +82,7 @@ Michael Killough Michaël Lefebvre Mike Popoloski Miodrag Milanović +Mladen Slijepcevic Morten Borup Petersen Mostafa Gamal Nandu Raj diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index a7c3fcc73..acba15530 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -446,14 +446,21 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE { { (vvar) = VL_CLEAN_QQ((obits), (obits), (svar).read().to_uint64()); } #define VL_ASSIGN_WSB(obits, owp, svar) \ { \ - const int words = VL_WORDS_I(obits); \ - sc_biguint<(obits)> _butemp = (svar).read(); \ - for (int i = 0; i < words; ++i) { \ - int msb = ((i + 1) * VL_IDATASIZE) - 1; \ - msb = (msb >= (obits)) ? ((obits)-1) : msb; \ - (owp)[i] = _butemp.range(msb, i * VL_IDATASIZE).to_uint(); \ - } \ - (owp)[words - 1] &= VL_MASK_E(obits); \ + const int words = VL_WORDS_I(obits); \ + sc_biguint<(obits)> _butemp = (svar).read(); \ + uint32_t* chunk = _butemp.get_raw(); \ + int32_t lsb = 0; \ + while (lsb < obits - BITS_PER_DIGIT) { \ + const uint32_t data = *chunk; \ + ++chunk; \ + _vl_insert_WI(owp.data(), data, lsb+BITS_PER_DIGIT-1, lsb); \ + lsb += BITS_PER_DIGIT; \ + } \ + if (lsb < obits) { \ + const uint32_t msb_data = *chunk; \ + _vl_insert_WI(owp.data(), msb_data, obits-1, lsb); \ + } \ + (owp)[words - 1] &= VL_MASK_E(obits); \ } // Copying verilog format from systemc integers and bit vectors. @@ -492,15 +499,24 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE { { (svar).write(rd); } #define VL_ASSIGN_SBQ(obits, svar, rd) \ { (svar).write(rd); } +#define VL_SC_BITS_PER_DIGIT 30 // This comes from sc_nbdefs.h BITS_PER_DIGIT #define VL_ASSIGN_SBW(obits, svar, rwp) \ { \ - sc_biguint<(obits)> _butemp; \ - for (int i = 0; i < VL_WORDS_I(obits); ++i) { \ - int msb = ((i + 1) * VL_IDATASIZE) - 1; \ - msb = (msb >= (obits)) ? ((obits)-1) : msb; \ - _butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \ - } \ - (svar).write(_butemp); \ + sc_biguint<(obits)> _butemp; \ + int32_t lsb = 0; \ + uint32_t* chunk = _butemp.get_raw(); \ + while (lsb + VL_SC_BITS_PER_DIGIT < (obits)) { \ + static_assert(std::is_same::value, "IData and EData missmatch"); \ + const uint32_t data = VL_SEL_IWII(lsb+VL_SC_BITS_PER_DIGIT+1, (rwp).data(), lsb, VL_SC_BITS_PER_DIGIT); \ + *chunk = data & VL_MASK_E(VL_SC_BITS_PER_DIGIT); \ + ++chunk; \ + lsb += VL_SC_BITS_PER_DIGIT; \ + } \ + if (lsb < (obits)) { \ + const uint32_t msb_data = VL_SEL_IWII((obits)+1, (rwp).data(), lsb, (obits) - lsb); \ + *chunk = msb_data & VL_MASK_E((obits) - lsb); \ + } \ + (svar).write(_butemp); \ } //=================================================================== diff --git a/test_regress/t/t_var_sc_bv.cpp b/test_regress/t/t_var_sc_bv.cpp new file mode 100644 index 000000000..d8324bf2f --- /dev/null +++ b/test_regress/t/t_var_sc_bv.cpp @@ -0,0 +1,220 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +#include VM_PREFIX_INCLUDE + +VM_PREFIX* tb = nullptr; +bool pass = true; + +double sc_time_stamp() { return 0; } + +void compare_signals(const sc_signal>& ls, const sc_signal>& rs) { + if (ls.read() != rs.read()) { + pass &= false; + VL_PRINTF("%%Error: Data missmatch in signals %s and %s\n", ls.name(), rs.name()); + } +} + +void compareWls(int obits, WDataInP const lwp, WDataInP const rwp) { + const int words = VL_WORDS_I(obits); + bool same = true; + + for (int i = 0; (i < (words - 1)); ++i) { + if (lwp[i] != rwp[i]) { same = false; } + } + if ((lwp[words - 1] & VL_MASK_E(obits)) != (rwp[words - 1] & VL_MASK_E(obits))) { + same = false; + } + + if (!same) { + pass &= false; + VL_PRINTF("%%Error: There is a difference in VlWide variable %d bits wide\n", obits); + } +} + +// old macro which is correct but has MT issue with range +#define VL_ASSIGN_SBW_MT_ISSUE(obits, svar, rwp) \ + { \ + sc_biguint<(obits)> _butemp; \ + for (int i = 0; i < VL_WORDS_I(obits); ++i) { \ + int msb = ((i + 1) * VL_IDATASIZE) - 1; \ + msb = (msb >= (obits)) ? ((obits)-1) : msb; \ + _butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \ + } \ + (svar).write(_butemp); \ + } + +#ifdef SYSTEMC_VERSION +int sc_main(int, char**) +#else +int main() +#endif +{ + Verilated::debug(0); + tb = new VM_PREFIX("tb"); + + VlWide<8> /*255:0*/ input_var; + VlWide<8> /*255:0*/ out_var; + + // msb is always set to F not to be false positive on checking equality + input_var.m_storage[0] = 0xF2341234; + input_var.m_storage[1] = 0xFEADBEEF; + input_var.m_storage[2] = 0xF5A5A5A5; + input_var.m_storage[3] = 0xF1B2C3D4; + input_var.m_storage[4] = 0xFFFFFFFF; + input_var.m_storage[5] = 0xFAAABBBB; + input_var.m_storage[6] = 0xF000AAAA; + input_var.m_storage[7] = 0xF0101010; + +#ifdef SYSTEMC_VERSION + // clang-format off + sc_signal> SC_NAMED(i_29_s), SC_NAMED(i_29_old_s), SC_NAMED(o_29_s), SC_NAMED(o_29_old_s), + SC_NAMED(i_30_s), SC_NAMED(i_30_old_s), SC_NAMED(o_30_s), SC_NAMED(o_30_old_s), + SC_NAMED(i_31_s), SC_NAMED(i_31_old_s), SC_NAMED(o_31_s), SC_NAMED(o_31_old_s), + SC_NAMED(i_32_s), SC_NAMED(i_32_old_s), SC_NAMED(o_32_s), SC_NAMED(o_32_old_s), + SC_NAMED(i_59_s), SC_NAMED(i_59_old_s), SC_NAMED(o_59_s), SC_NAMED(o_59_old_s), + SC_NAMED(i_60_s), SC_NAMED(i_60_old_s), SC_NAMED(o_60_s), SC_NAMED(o_60_old_s), + SC_NAMED(i_62_s), SC_NAMED(i_62_old_s), SC_NAMED(o_62_s), SC_NAMED(o_62_old_s), + SC_NAMED(i_64_s), SC_NAMED(i_64_old_s), SC_NAMED(o_64_s), SC_NAMED(o_64_old_s), + SC_NAMED(i_119_s), SC_NAMED(i_119_old_s), SC_NAMED(o_119_s), SC_NAMED(o_119_old_s), + SC_NAMED(i_120_s), SC_NAMED(i_120_old_s), SC_NAMED(o_120_s), SC_NAMED(o_120_old_s), + SC_NAMED(i_121_s), SC_NAMED(i_121_old_s), SC_NAMED(o_121_s), SC_NAMED(o_121_old_s), + SC_NAMED(i_127_s), SC_NAMED(i_127_old_s), SC_NAMED(o_127_s), SC_NAMED(o_127_old_s), + SC_NAMED(i_128_s), SC_NAMED(i_128_old_s), SC_NAMED(o_128_s), SC_NAMED(o_128_old_s), + SC_NAMED(i_255_s), SC_NAMED(i_255_old_s), SC_NAMED(o_255_s), SC_NAMED(o_255_old_s), + SC_NAMED(i_256_s), SC_NAMED(i_256_old_s), SC_NAMED(o_256_s), SC_NAMED(o_256_old_s); + + + tb->i_29(i_29_s); tb->i_29_old(i_29_old_s); tb->o_29(o_29_s); tb->o_29_old(o_29_old_s); + tb->i_30(i_30_s); tb->i_30_old(i_30_old_s); tb->o_30(o_30_s); tb->o_30_old(o_30_old_s); + tb->i_31(i_31_s); tb->i_31_old(i_31_old_s); tb->o_31(o_31_s); tb->o_31_old(o_31_old_s); + tb->i_32(i_32_s); tb->i_32_old(i_32_old_s); tb->o_32(o_32_s); tb->o_32_old(o_32_old_s); + tb->i_59(i_59_s); tb->i_59_old(i_59_old_s); tb->o_59(o_59_s); tb->o_59_old(o_59_old_s); + tb->i_60(i_60_s); tb->i_60_old(i_60_old_s); tb->o_60(o_60_s); tb->o_60_old(o_60_old_s); + tb->i_62(i_62_s); tb->i_62_old(i_62_old_s); tb->o_62(o_62_s); tb->o_62_old(o_62_old_s); + tb->i_64(i_64_s); tb->i_64_old(i_64_old_s); tb->o_64(o_64_s); tb->o_64_old(o_64_old_s); + tb->i_119(i_119_s); tb->i_119_old(i_119_old_s); tb->o_119(o_119_s); tb->o_119_old(o_119_old_s); + tb->i_120(i_120_s); tb->i_120_old(i_120_old_s); tb->o_120(o_120_s); tb->o_120_old(o_120_old_s); + tb->i_121(i_121_s); tb->i_121_old(i_121_old_s); tb->o_121(o_121_s); tb->o_121_old(o_121_old_s); + tb->i_127(i_127_s); tb->i_127_old(i_127_old_s); tb->o_127(o_127_s); tb->o_127_old(o_127_old_s); + tb->i_128(i_128_s); tb->i_128_old(i_128_old_s); tb->o_128(o_128_s); tb->o_128_old(o_128_old_s); + tb->i_255(i_255_s); tb->i_255_old(i_255_old_s); tb->o_255(o_255_s); tb->o_255_old(o_255_old_s); + tb->i_256(i_256_s); tb->i_256_old(i_256_old_s); tb->o_256(o_256_s); tb->o_256_old(o_256_old_s); + + // clang-format on + +#endif + +// clang-format off +#ifdef SYSTEMC_VERSION + sc_start(1, SC_NS); +#else + tb->eval(); +#endif + // This testcase is testing multi-thread safe VL_ASSIGN_SBW and VL_ASSIGN_WSB macros. + // Testbench is assigning different number of bits from VlWide input_var variable to different inputs. + // Values around multiple of 30 (i.e. BITS_PER_DIGIT defined in SystemC sc_nbdefs.h) are tested with the special care, since + // it is the value by which the data_ptr of sc_biguint underlying data type is increased by (and not expected 32, as width of uint32_t). + // Correctness of the output is compared against the 'old' macro, which is correct but has multi-threaded issue since it's using range function. + // Second part is testing VL_ASSIGN_WSB in a reverse way, it is reading signals from the previous test, + // and comparing the output with (fraction) of VlWide input_var variable. + + // clang-format on + VL_ASSIGN_SBW(29, i_29_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(29, i_29_old_s, input_var); + VL_ASSIGN_SBW(30, i_30_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(30, i_30_old_s, input_var); + VL_ASSIGN_SBW(31, i_31_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(31, i_31_old_s, input_var); + VL_ASSIGN_SBW(32, i_32_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(32, i_32_old_s, input_var); + VL_ASSIGN_SBW(59, i_59_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(59, i_59_old_s, input_var); + VL_ASSIGN_SBW(60, i_60_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(60, i_60_old_s, input_var); + VL_ASSIGN_SBW(62, i_62_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(62, i_62_old_s, input_var); + VL_ASSIGN_SBW(64, i_64_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(64, i_64_old_s, input_var); + VL_ASSIGN_SBW(119, i_119_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(119, i_119_old_s, input_var); + VL_ASSIGN_SBW(120, i_120_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(120, i_120_old_s, input_var); + VL_ASSIGN_SBW(121, i_121_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(121, i_121_old_s, input_var); + VL_ASSIGN_SBW(127, i_127_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(127, i_127_old_s, input_var); + VL_ASSIGN_SBW(128, i_128_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(128, i_128_old_s, input_var); + VL_ASSIGN_SBW(255, i_255_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(255, i_255_old_s, input_var); + VL_ASSIGN_SBW(256, i_256_s, input_var); + VL_ASSIGN_SBW_MT_ISSUE(256, i_256_old_s, input_var); + +#ifdef SYSTEMC_VERSION + sc_start(1, SC_NS); +#else + tb->eval(); +#endif + compare_signals(o_29_s, o_29_old_s); + compare_signals(o_30_s, o_30_old_s); + compare_signals(o_31_s, o_31_old_s); + compare_signals(o_32_s, o_32_old_s); + compare_signals(o_59_s, o_59_old_s); + compare_signals(o_60_s, o_60_old_s); + compare_signals(o_62_s, o_62_old_s); + compare_signals(o_64_s, o_64_old_s); + compare_signals(o_119_s, o_119_old_s); + compare_signals(o_120_s, o_120_old_s); + compare_signals(o_121_s, o_121_old_s); + compare_signals(o_127_s, o_127_old_s); + compare_signals(o_128_s, o_128_old_s); + compare_signals(o_255_s, o_255_old_s); + compare_signals(o_256_s, o_256_old_s); + + //////////////////////////////// + + VL_ASSIGN_WSB(29, out_var, o_29_s); + compareWls(29, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(30, out_var, o_30_s); + compareWls(30, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(31, out_var, o_31_s); + compareWls(31, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(32, out_var, o_32_s); + compareWls(32, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(59, out_var, o_59_s); + compareWls(59, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(60, out_var, o_60_s); + compareWls(60, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(62, out_var, o_62_s); + compareWls(62, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(64, out_var, o_64_s); + compareWls(64, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(119, out_var, o_119_s); + compareWls(119, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(120, out_var, o_120_s); + compareWls(120, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(121, out_var, o_121_s); + compareWls(121, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(127, out_var, o_127_s); + compareWls(127, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(128, out_var, o_128_s); + compareWls(128, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(255, out_var, o_255_s); + compareWls(255, input_var.data(), out_var.data()); + VL_ASSIGN_WSB(256, out_var, o_256_s); + compareWls(256, input_var.data(), out_var.data()); + + tb->final(); + VL_DO_DANGLING(delete tb, tb); + + if (pass) { + VL_PRINTF("*-* All Finished *-*\n"); + } else { + vl_fatal(__FILE__, __LINE__, "top", "Unexpected results from test\n"); + } + return 0; +} diff --git a/test_regress/t/t_var_sc_bv.pl b/test_regress/t/t_var_sc_bv.pl new file mode 100755 index 000000000..0091e49f0 --- /dev/null +++ b/test_regress/t/t_var_sc_bv.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt_all => 1); + +compile( + make_top_shell => 0, + make_main => 0, + verilator_flags2 => ["--exe $Self->{t_dir}/t_var_sc_bv.cpp --sc -fno-inline"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_var_sc_bv.v b/test_regress/t/t_var_sc_bv.v new file mode 100644 index 000000000..d3164ee09 --- /dev/null +++ b/test_regress/t/t_var_sc_bv.v @@ -0,0 +1,246 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2008 by Lane Brooks. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Outputs + o_29,o_29_old, + o_30,o_30_old, + o_31,o_31_old, + o_32,o_32_old, + o_59,o_59_old, + o_60,o_60_old, + o_62,o_62_old, + o_64,o_64_old, + o_119,o_119_old, + o_120,o_120_old, + o_121,o_121_old, + o_127,o_127_old, + o_128,o_128_old, + o_255,o_255_old, + o_256,o_256_old, + // Inputs + i_29,i_29_old, + i_30,i_30_old, + i_31,i_31_old, + i_32,i_32_old, + i_59,i_59_old, + i_60,i_60_old, + i_62,i_62_old, + i_64,i_64_old, + i_119,i_119_old, + i_120,i_120_old, + i_121,i_121_old, + i_127,i_127_old, + i_128,i_128_old, + i_255,i_255_old, + i_256,i_256_old + ); + input [255:0] i_29; + output wire [255:0] o_29; + input [255:0] i_29_old; + output wire [255:0] o_29_old; + input [255:0] i_30; + output wire [255:0] o_30; + input [255:0] i_30_old; + output wire [255:0] o_30_old; + input [255:0] i_31; + output wire [255:0] o_31; + input [255:0] i_31_old; + output wire [255:0] o_31_old; + input [255:0] i_32; + output wire [255:0] o_32; + input [255:0] i_32_old; + output wire [255:0] o_32_old; + input [255:0] i_59; + output wire [255:0] o_59; + input [255:0] i_59_old; + output wire [255:0] o_59_old; + input [255:0] i_60; + output wire [255:0] o_60; + input [255:0] i_60_old; + output wire [255:0] o_60_old; + input [255:0] i_62; + output wire [255:0] o_62; + input [255:0] i_62_old; + output wire [255:0] o_62_old; + input [255:0] i_64; + output wire [255:0] o_64; + input [255:0] i_64_old; + output wire [255:0] o_64_old; + input [255:0] i_119; + output wire [255:0] o_119; + input [255:0] i_119_old; + output wire [255:0] o_119_old; + input [255:0] i_120; + output wire [255:0] o_120; + input [255:0] i_120_old; + output wire [255:0] o_120_old; + input [255:0] i_121; + output wire [255:0] o_121; + input [255:0] i_121_old; + output wire [255:0] o_121_old; + input [255:0] i_127; + output wire [255:0] o_127; + input [255:0] i_127_old; + output wire [255:0] o_127_old; + input [255:0] i_128; + output wire [255:0] o_128; + input [255:0] i_128_old; + output wire [255:0] o_128_old; + input [255:0] i_255; + output wire [255:0] o_255; + input [255:0] i_255_old; + output wire [255:0] o_255_old; + input [255:0] i_256; + output wire [255:0] o_256; + input [255:0] i_256_old; + output wire [255:0] o_256_old; + + sub sub (.*); +endmodule + +module sub (/*AUTOARG*/ + // Outputs + o_29,o_29_old, + o_30,o_30_old, + o_31,o_31_old, + o_32,o_32_old, + o_59,o_59_old, + o_60,o_60_old, + o_62,o_62_old, + o_64,o_64_old, + o_119,o_119_old, + o_120,o_120_old, + o_121,o_121_old, + o_127,o_127_old, + o_128,o_128_old, + o_255,o_255_old, + o_256,o_256_old, + // Inputs + i_29,i_29_old, + i_30,i_30_old, + i_31,i_31_old, + i_32,i_32_old, + i_59,i_59_old, + i_60,i_60_old, + i_62,i_62_old, + i_64,i_64_old, + i_119,i_119_old, + i_120,i_120_old, + i_121,i_121_old, + i_127,i_127_old, + i_128,i_128_old, + i_255,i_255_old, + i_256,i_256_old + ); + + input [255:0] i_29; + output wire [255:0] o_29; + input [255:0] i_29_old; + output wire [255:0] o_29_old; + input [255:0] i_30; + output wire [255:0] o_30; + input [255:0] i_30_old; + output wire [255:0] o_30_old; + input [255:0] i_31; + output wire [255:0] o_31; + input [255:0] i_31_old; + output wire [255:0] o_31_old; + input [255:0] i_32; + output wire [255:0] o_32; + input [255:0] i_32_old; + output wire [255:0] o_32_old; + input [255:0] i_59; + output wire [255:0] o_59; + input [255:0] i_59_old; + output wire [255:0] o_59_old; + input [255:0] i_60; + output wire [255:0] o_60; + input [255:0] i_60_old; + output wire [255:0] o_60_old; + input [255:0] i_62; + output wire [255:0] o_62; + input [255:0] i_62_old; + output wire [255:0] o_62_old; + input [255:0] i_64; + output wire [255:0] o_64; + input [255:0] i_64_old; + output wire [255:0] o_64_old; + input [255:0] i_119; + output wire [255:0] o_119; + input [255:0] i_119_old; + output wire [255:0] o_119_old; + input [255:0] i_120; + output wire [255:0] o_120; + input [255:0] i_120_old; + output wire [255:0] o_120_old; + input [255:0] i_121; + output wire [255:0] o_121; + input [255:0] i_121_old; + output wire [255:0] o_121_old; + input [255:0] i_127; + output wire [255:0] o_127; + input [255:0] i_127_old; + output wire [255:0] o_127_old; + input [255:0] i_128; + output wire [255:0] o_128; + input [255:0] i_128_old; + output wire [255:0] o_128_old; + input [255:0] i_255; + output wire [255:0] o_255; + input [255:0] i_255_old; + output wire [255:0] o_255_old; + input [255:0] i_256; + output wire [255:0] o_256; + input [255:0] i_256_old; + output wire [255:0] o_256_old; + + assign o_29 = i_29; + assign o_29_old = i_29_old; + + assign o_30 = i_30; + assign o_30_old = i_30_old; + + assign o_31 = i_31; + assign o_31_old = i_31_old; + + assign o_32 = i_32; + assign o_32_old = i_32_old; + + assign o_59 = i_59; + assign o_59_old = i_59_old; + + assign o_60 = i_60; + assign o_60_old = i_60_old; + + assign o_62 = i_62; + assign o_62_old = i_62_old; + + assign o_64 = i_64; + assign o_64_old = i_64_old; + + assign o_119 = i_119; + assign o_119_old = i_119_old; + + assign o_120 = i_120; + assign o_120_old = i_120_old; + + assign o_121 = i_121; + assign o_121_old = i_121_old; + + assign o_127 = i_127; + assign o_127_old = i_127_old; + + assign o_128 = i_128; + assign o_128_old = i_128_old; + + assign o_255 = i_255; + assign o_255_old = i_255_old; + + assign o_256 = i_256; + assign o_256_old = i_256_old; + +endmodule From e94cdcf29c22fac332ca42fc711d0e186e7d8369 Mon Sep 17 00:00:00 2001 From: github action Date: Mon, 5 Sep 2022 22:43:09 +0000 Subject: [PATCH 11/75] Apply 'make format' --- include/verilated_funcs.h | 63 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index acba15530..8bcef8019 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -446,21 +446,21 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE { { (vvar) = VL_CLEAN_QQ((obits), (obits), (svar).read().to_uint64()); } #define VL_ASSIGN_WSB(obits, owp, svar) \ { \ - const int words = VL_WORDS_I(obits); \ - sc_biguint<(obits)> _butemp = (svar).read(); \ - uint32_t* chunk = _butemp.get_raw(); \ - int32_t lsb = 0; \ - while (lsb < obits - BITS_PER_DIGIT) { \ - const uint32_t data = *chunk; \ - ++chunk; \ - _vl_insert_WI(owp.data(), data, lsb+BITS_PER_DIGIT-1, lsb); \ - lsb += BITS_PER_DIGIT; \ - } \ - if (lsb < obits) { \ - const uint32_t msb_data = *chunk; \ - _vl_insert_WI(owp.data(), msb_data, obits-1, lsb); \ - } \ - (owp)[words - 1] &= VL_MASK_E(obits); \ + const int words = VL_WORDS_I(obits); \ + sc_biguint<(obits)> _butemp = (svar).read(); \ + uint32_t* chunk = _butemp.get_raw(); \ + int32_t lsb = 0; \ + while (lsb < obits - BITS_PER_DIGIT) { \ + const uint32_t data = *chunk; \ + ++chunk; \ + _vl_insert_WI(owp.data(), data, lsb + BITS_PER_DIGIT - 1, lsb); \ + lsb += BITS_PER_DIGIT; \ + } \ + if (lsb < obits) { \ + const uint32_t msb_data = *chunk; \ + _vl_insert_WI(owp.data(), msb_data, obits - 1, lsb); \ + } \ + (owp)[words - 1] &= VL_MASK_E(obits); \ } // Copying verilog format from systemc integers and bit vectors. @@ -499,24 +499,25 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE { { (svar).write(rd); } #define VL_ASSIGN_SBQ(obits, svar, rd) \ { (svar).write(rd); } -#define VL_SC_BITS_PER_DIGIT 30 // This comes from sc_nbdefs.h BITS_PER_DIGIT +#define VL_SC_BITS_PER_DIGIT 30 // This comes from sc_nbdefs.h BITS_PER_DIGIT #define VL_ASSIGN_SBW(obits, svar, rwp) \ { \ - sc_biguint<(obits)> _butemp; \ - int32_t lsb = 0; \ - uint32_t* chunk = _butemp.get_raw(); \ - while (lsb + VL_SC_BITS_PER_DIGIT < (obits)) { \ - static_assert(std::is_same::value, "IData and EData missmatch"); \ - const uint32_t data = VL_SEL_IWII(lsb+VL_SC_BITS_PER_DIGIT+1, (rwp).data(), lsb, VL_SC_BITS_PER_DIGIT); \ - *chunk = data & VL_MASK_E(VL_SC_BITS_PER_DIGIT); \ - ++chunk; \ - lsb += VL_SC_BITS_PER_DIGIT; \ - } \ - if (lsb < (obits)) { \ - const uint32_t msb_data = VL_SEL_IWII((obits)+1, (rwp).data(), lsb, (obits) - lsb); \ - *chunk = msb_data & VL_MASK_E((obits) - lsb); \ - } \ - (svar).write(_butemp); \ + sc_biguint<(obits)> _butemp; \ + int32_t lsb = 0; \ + uint32_t* chunk = _butemp.get_raw(); \ + while (lsb + VL_SC_BITS_PER_DIGIT < (obits)) { \ + static_assert(std::is_same::value, "IData and EData missmatch"); \ + const uint32_t data = VL_SEL_IWII(lsb + VL_SC_BITS_PER_DIGIT + 1, (rwp).data(), lsb, \ + VL_SC_BITS_PER_DIGIT); \ + *chunk = data & VL_MASK_E(VL_SC_BITS_PER_DIGIT); \ + ++chunk; \ + lsb += VL_SC_BITS_PER_DIGIT; \ + } \ + if (lsb < (obits)) { \ + const uint32_t msb_data = VL_SEL_IWII((obits) + 1, (rwp).data(), lsb, (obits)-lsb); \ + *chunk = msb_data & VL_MASK_E((obits)-lsb); \ + } \ + (svar).write(_butemp); \ } //=================================================================== From 361cef463372fdef59b8c1e2245de47988dac5b6 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 7 Sep 2022 21:48:52 -0400 Subject: [PATCH 12/75] Fix pylint warnings. --- Makefile.in | 2 +- bin/verilator_difftree | 2 +- bin/verilator_gantt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index fc9b6b1a9..6903e37f9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -391,7 +391,7 @@ yapf: FLAKE8 = flake8 FLAKE8_FLAGS = \ --extend-exclude=fastcov.py \ - --ignore=E123,E129,E251,E501,W503,W504,E701 + --ignore=E123,E129,E251,E402,E501,W503,W504,E701 PYLINT = pylint PYLINT_FLAGS = --disable=R0801 diff --git a/bin/verilator_difftree b/bin/verilator_difftree index 3e8315691..d7c65a28e 100755 --- a/bin/verilator_difftree +++ b/bin/verilator_difftree @@ -38,7 +38,7 @@ def diff_dir(a, b): anyfile = False for base in sorted(files.keys()): - if (not 'a' in files[base]) or (not 'b' in files[base]): + if ('a' not in files[base]) or ('b' not in files[base]): continue a = files[base]['a'] b = files[base]['b'] diff --git a/bin/verilator_gantt b/bin/verilator_gantt index 616af30dc..03a7a16af 100755 --- a/bin/verilator_gantt +++ b/bin/verilator_gantt @@ -149,7 +149,8 @@ def report(): for thread in Threads: # Make potentially multiple characters per column for start in Threads[thread]: - if not Threads[thread][start]: continue + if not Threads[thread][start]: + continue cpu = Threads[thread][start]['cpu'] elapsed = Threads[thread][start]['end'] - start if cpu not in Global['cpus']: From 5a1bcf97946cc683beb0186b3a752e981370d1ab Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 7 Sep 2022 22:04:57 -0400 Subject: [PATCH 13/75] Tests: Add lint-py checker --- Makefile.in | 2 +- test_regress/t/t_dist_lint_py.pl | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100755 test_regress/t/t_dist_lint_py.pl diff --git a/Makefile.in b/Makefile.in index 6903e37f9..08271b047 100644 --- a/Makefile.in +++ b/Makefile.in @@ -394,7 +394,7 @@ FLAKE8_FLAGS = \ --ignore=E123,E129,E251,E402,E501,W503,W504,E701 PYLINT = pylint -PYLINT_FLAGS = --disable=R0801 +PYLINT_FLAGS = --score=n --disable=R0801 lint-py: -$(FLAKE8) $(FLAKE8_FLAGS) $(PY_PROGRAMS) diff --git a/test_regress/t/t_dist_lint_py.pl b/test_regress/t/t_dist_lint_py.pl new file mode 100755 index 000000000..b0af4f6e6 --- /dev/null +++ b/test_regress/t/t_dist_lint_py.pl @@ -0,0 +1,34 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(dist => 1); + +my $root = ".."; + +if (!-r "$root/.git") { + skip("Not in a git repository"); +} else { + my $cmd = "cd $root && make lint-py"; + my $out = `$cmd`; + my $first; + foreach my $line (split /\n+/, $out) { + next if $line =~ /^---/; + next if $line =~ /^flake8/; + next if $line =~ /^pylint/; + print "$line\n"; + if (!defined $first) { + $first = $line; + error("lint-py failed: ", $first); + } + } +} + +ok(1); +1; From 42283150d7847954ff0c359cfc71834adadd4368 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 7 Sep 2022 22:13:02 -0400 Subject: [PATCH 14/75] Actions: Use 22.04 for contrib action --- .github/workflows/contributor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/contributor.yml b/.github/workflows/contributor.yml index 627d00ab3..bbc00ce97 100644 --- a/.github/workflows/contributor.yml +++ b/.github/workflows/contributor.yml @@ -11,7 +11,7 @@ on: jobs: Test: name: "'docs/CONTRIBUTORS' was signed" - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 - run: test_regress/t/t_dist_contributors.pl From 9a27004ae547757579a87734fd4bc4a26f90589a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 7 Sep 2022 22:49:09 -0400 Subject: [PATCH 15/75] Github actions: Avoid cpan cert expirations. --- ci/ci-install.bash | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/ci-install.bash b/ci/ci-install.bash index 4f61f06c4..576b39974 100755 --- a/ci/ci-install.bash +++ b/ci/ci-install.bash @@ -19,6 +19,9 @@ set -x cd $(dirname "$0")/.. +# Avoid occasional cpan failures "Issued certificate has expired." +export PERL_LWP_SSL_VERIFY_HOSTNAME=0 + fatal() { echo "ERROR: $(basename "$0"): $1" >&2; exit 1; } From 249feaae7ca78da5295c25a8aca565bbc41d8d1f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 7 Sep 2022 22:59:32 -0400 Subject: [PATCH 16/75] Tests: Remove lint-py, need ci package. --- test_regress/t/t_dist_lint_py.pl | 34 -------------------------------- 1 file changed, 34 deletions(-) delete mode 100755 test_regress/t/t_dist_lint_py.pl diff --git a/test_regress/t/t_dist_lint_py.pl b/test_regress/t/t_dist_lint_py.pl deleted file mode 100755 index b0af4f6e6..000000000 --- a/test_regress/t/t_dist_lint_py.pl +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env perl -if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } -# DESCRIPTION: Verilator: Verilog Test driver/expect definition -# -# Copyright 2022 by Wilson Snyder. This program is free software; you -# can redistribute it and/or modify it under the terms of either the GNU -# Lesser General Public License Version 3 or the Perl Artistic License -# Version 2.0. -# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 - -scenarios(dist => 1); - -my $root = ".."; - -if (!-r "$root/.git") { - skip("Not in a git repository"); -} else { - my $cmd = "cd $root && make lint-py"; - my $out = `$cmd`; - my $first; - foreach my $line (split /\n+/, $out) { - next if $line =~ /^---/; - next if $line =~ /^flake8/; - next if $line =~ /^pylint/; - print "$line\n"; - if (!defined $first) { - $first = $line; - error("lint-py failed: ", $first); - } - } -} - -ok(1); -1; From 45d622e4bc3ceb8922aa60af2612806028b5309a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 8 Sep 2022 11:06:44 -0400 Subject: [PATCH 17/75] Github actions: Avoid cpan cert expirations. --- ci/ci-install.bash | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/ci-install.bash b/ci/ci-install.bash index 576b39974..2e7325cea 100755 --- a/ci/ci-install.bash +++ b/ci/ci-install.bash @@ -21,6 +21,7 @@ cd $(dirname "$0")/.. # Avoid occasional cpan failures "Issued certificate has expired." export PERL_LWP_SSL_VERIFY_HOSTNAME=0 +echo "check_certificate = off" >> ~/.wgetrc fatal() { echo "ERROR: $(basename "$0"): $1" >&2; exit 1; From 47e64535d6d3e1069e6acebfa828030f66e527c5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 11 Sep 2022 12:25:44 -0400 Subject: [PATCH 18/75] Commentary --- src/V3Waiver.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/V3Waiver.cpp b/src/V3Waiver.cpp index 42d222fe8..41a07c1ff 100644 --- a/src/V3Waiver.cpp +++ b/src/V3Waiver.cpp @@ -6,9 +6,10 @@ // //************************************************************************* // -// Copyright 2020 by Wilson Snyder. This program is free software; you can -// redistribute it and/or modify it under the terms of either the GNU Lesser -// General Public License Version 3 or the Perl Artistic License Version 2.0. +// Copyright 2020-2022 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 // //************************************************************************* From 47262cd4ecc81eac363350f70085dada72ecd60b Mon Sep 17 00:00:00 2001 From: Gustav Svensk Date: Sun, 11 Sep 2022 18:33:31 +0200 Subject: [PATCH 19/75] Fix arguments in non-static method call (#3547) (#3582) --- src/V3Width.cpp | 1 + test_regress/t/t_class_method_str_literal.pl | 21 +++++++++++++++ test_regress/t/t_class_method_str_literal.v | 28 ++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100755 test_regress/t/t_class_method_str_literal.pl create mode 100644 test_regress/t/t_class_method_str_literal.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a9f784e06..9b85d5c12 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -3218,6 +3218,7 @@ private: nodep->dtypeFrom(ftaskp); nodep->classOrPackagep(classp); if (VN_IS(ftaskp, Task)) nodep->makeStatement(); + processFTaskRefArgs(nodep); } return; } diff --git a/test_regress/t/t_class_method_str_literal.pl b/test_regress/t/t_class_method_str_literal.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_class_method_str_literal.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_method_str_literal.v b/test_regress/t/t_class_method_str_literal.v new file mode 100644 index 000000000..3e5e9225d --- /dev/null +++ b/test_regress/t/t_class_method_str_literal.v @@ -0,0 +1,28 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + +class T; + function automatic void print_str(input string a_string); + $display(a_string); + endfunction + + static function automatic void static_print_str(input string a_string); + $display(a_string); + endfunction +endclass + + +initial begin + T t_c = new; + t_c.print_str("function though member"); + t_c.static_print_str("static function through member"); + T::static_print_str("static function through class"); + $write("*-* All Finished *-*\n"); + $finish; +end +endmodule From 752f425025d6ad36815ca181667aba4c9e8ea8fa Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 11 Sep 2022 13:05:13 -0400 Subject: [PATCH 20/75] Tests: Process/Semaphore/Mailbox testing (all fail until supported) --- src/V3Width.cpp | 2 +- test_regress/t/t_mailbox.out | 6 ++++-- test_regress/t/t_mailbox.v | 2 +- test_regress/t/t_mailbox_bad.out | 6 ++++++ test_regress/t/t_mailbox_bad.pl | 22 ++++++++++++++++++++++ test_regress/t/t_mailbox_bad.v | 17 +++++++++++++++++ test_regress/t/t_process.v | 8 ++++---- test_regress/t/t_process_bad.out | 10 ++++++++++ test_regress/t/t_process_bad.pl | 22 ++++++++++++++++++++++ test_regress/t/t_process_bad.v | 20 ++++++++++++++++++++ test_regress/t/t_semaphore.out | 3 +++ test_regress/t/t_semaphore.v | 8 +++++++- test_regress/t/t_semaphore_bad.out | 7 +++++++ test_regress/t/t_semaphore_bad.pl | 22 ++++++++++++++++++++++ test_regress/t/t_semaphore_bad.v | 17 +++++++++++++++++ 15 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 test_regress/t/t_mailbox_bad.out create mode 100755 test_regress/t/t_mailbox_bad.pl create mode 100644 test_regress/t/t_mailbox_bad.v create mode 100644 test_regress/t/t_process_bad.out create mode 100755 test_regress/t/t_process_bad.pl create mode 100644 test_regress/t/t_process_bad.v create mode 100644 test_regress/t/t_semaphore_bad.out create mode 100755 test_regress/t/t_semaphore_bad.pl create mode 100644 test_regress/t/t_semaphore_bad.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 9b85d5c12..7fdbf20f0 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -538,7 +538,7 @@ private: || VN_IS(vdtypep, DynArrayDType) // || VN_IS(vdtypep, QueueDType)) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Concatenation to form " - << vdtypep->prettyDTypeNameQ() << "data type"); + << vdtypep->prettyDTypeNameQ() << " data type"); } iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); diff --git a/test_regress/t/t_mailbox.out b/test_regress/t/t_mailbox.out index 5a7cc1581..4d5432212 100644 --- a/test_regress/t/t_mailbox.out +++ b/test_regress/t/t_mailbox.out @@ -1,4 +1,6 @@ %Error: t/t_mailbox.v:20:4: Can't find typedef: 'mailbox' - 20 | mailbox m; + 20 | mailbox #(int) m; | ^~~~~~~ -%Error: Exiting due to +%Error: Internal Error: t/t_mailbox.v:20:14: ../V3LinkDot.cpp:#: Pin not under instance? + 20 | mailbox #(int) m; + | ^~~ diff --git a/test_regress/t/t_mailbox.v b/test_regress/t/t_mailbox.v index 21eadf323..06ea1f834 100644 --- a/test_regress/t/t_mailbox.v +++ b/test_regress/t/t_mailbox.v @@ -17,7 +17,7 @@ // endclass module t(/*AUTOARG*/); - mailbox m; + mailbox #(int) m; int msg; int out; diff --git a/test_regress/t/t_mailbox_bad.out b/test_regress/t/t_mailbox_bad.out new file mode 100644 index 000000000..4d5432212 --- /dev/null +++ b/test_regress/t/t_mailbox_bad.out @@ -0,0 +1,6 @@ +%Error: t/t_mailbox.v:20:4: Can't find typedef: 'mailbox' + 20 | mailbox #(int) m; + | ^~~~~~~ +%Error: Internal Error: t/t_mailbox.v:20:14: ../V3LinkDot.cpp:#: Pin not under instance? + 20 | mailbox #(int) m; + | ^~~ diff --git a/test_regress/t/t_mailbox_bad.pl b/test_regress/t/t_mailbox_bad.pl new file mode 100755 index 000000000..8de551634 --- /dev/null +++ b/test_regress/t/t_mailbox_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +top_filename("t_mailbox.v"); + +lint( + verilator_flags2 => ["--xml-only"], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_mailbox_bad.v b/test_regress/t/t_mailbox_bad.v new file mode 100644 index 000000000..a8bcb84fc --- /dev/null +++ b/test_regress/t/t_mailbox_bad.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + mailbox #(int) m; + + initial begin + m = new(4); + if (m.bad_method() != 0) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_process.v b/test_regress/t/t_process.v index f6ee27bac..0d495ab17 100644 --- a/test_regress/t/t_process.v +++ b/test_regress/t/t_process.v @@ -6,16 +6,16 @@ // Methods defined by IEEE: // class process; -// enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED }; +// enum state { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED }; // UVM uses KILLED, FINISHED // static function process self(); // function state status(); // function void kill(); // task await(); // Warn as unsupported (no UVM library use) // function void suspend(); // Warn as unsupported (no UVM library use) // function void resume(); // Warn as unsupported (no UVM library use) -// function void srandom( int seed ); // Just ignore? -// function string get_randstate(); // Just ignore? -// function void set_randstate( string state ); // Just ignore? +// function void srandom( int seed ); // Operate on all proceses for now? +// function string get_randstate(); // Operate on all proceses for now? +// function void set_randstate( string state ); // Operate on all proceses for now? // endclass module t(/*AUTOARG*/); diff --git a/test_regress/t/t_process_bad.out b/test_regress/t/t_process_bad.out new file mode 100644 index 000000000..a4ada3778 --- /dev/null +++ b/test_regress/t/t_process_bad.out @@ -0,0 +1,10 @@ +%Error: t/t_process.v:22:4: Can't find typedef: 'process' + 22 | process p; + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_process.v:26:20: Unsupported: 'process' + 26 | p = process::self(); + | ^~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Internal Error: t/t_process.v:26:11: ../V3LinkDot.cpp:#: Bad package link + 26 | p = process::self(); + | ^~~~~~~ diff --git a/test_regress/t/t_process_bad.pl b/test_regress/t/t_process_bad.pl new file mode 100755 index 000000000..7be24ae56 --- /dev/null +++ b/test_regress/t/t_process_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +top_filename("t_process.v"); + +lint( + verilator_flags2 => ["--xml-only"], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_process_bad.v b/test_regress/t/t_process_bad.v new file mode 100644 index 000000000..d32afb72b --- /dev/null +++ b/test_regress/t/t_process_bad.v @@ -0,0 +1,20 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + process p; + + initial begin + if (p != null) $stop; + p = process::self(); + if (p.bad_method() != 0) $stop; + + p.bad_method_2(); + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_semaphore.out b/test_regress/t/t_semaphore.out index 21345fd35..76d60e04d 100644 --- a/test_regress/t/t_semaphore.out +++ b/test_regress/t/t_semaphore.out @@ -1,4 +1,7 @@ %Error: t/t_semaphore.v:17:4: Can't find typedef: 'semaphore' 17 | semaphore s; | ^~~~~~~~~ +%Error: t/t_semaphore.v:18:4: Can't find typedef: 'semaphore' + 18 | semaphore s2; + | ^~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_semaphore.v b/test_regress/t/t_semaphore.v index 322a8541a..bc229ad75 100644 --- a/test_regress/t/t_semaphore.v +++ b/test_regress/t/t_semaphore.v @@ -13,8 +13,9 @@ // endclass module t(/*AUTOARG*/); - //From UVM: + // From UVM: semaphore s; + semaphore s2; int msg; initial begin @@ -30,6 +31,7 @@ module t(/*AUTOARG*/); s.put(2); if (s.try_get(2) <= 0) $stop; +`ifndef VERILATOR fork begin #10; // So later then get() starts below @@ -42,6 +44,10 @@ module t(/*AUTOARG*/); s.get(); end join +`endif + + s2 = new; + if (s2.try_get() != 0) $stop; $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_semaphore_bad.out b/test_regress/t/t_semaphore_bad.out new file mode 100644 index 000000000..76d60e04d --- /dev/null +++ b/test_regress/t/t_semaphore_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_semaphore.v:17:4: Can't find typedef: 'semaphore' + 17 | semaphore s; + | ^~~~~~~~~ +%Error: t/t_semaphore.v:18:4: Can't find typedef: 'semaphore' + 18 | semaphore s2; + | ^~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_semaphore_bad.pl b/test_regress/t/t_semaphore_bad.pl new file mode 100755 index 000000000..92483cce2 --- /dev/null +++ b/test_regress/t/t_semaphore_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +top_filename("t_semaphore.v"); + +lint( + verilator_flags2 => ["--xml-only"], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_semaphore_bad.v b/test_regress/t/t_semaphore_bad.v new file mode 100644 index 000000000..68e6ee38b --- /dev/null +++ b/test_regress/t/t_semaphore_bad.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + semaphore s; + + initial begin + s = new(4); + if (s.bad_method() != 0) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule From 9b2266f68cc1b4f7b936d293b3f6ca6da3e1307e Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Mon, 12 Sep 2022 17:59:14 +0200 Subject: [PATCH 21/75] Internals: Remove usage of global state in V3EmitCFunc (#3615). No functional change intended. --- src/V3EmitCFunc.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 9d863c7e5..27af5ad6a 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -36,18 +36,20 @@ constexpr int EMITC_NUM_CONSTW = 8; class EmitCLazyDecls final : public VNVisitor { // NODE STATE/TYPES - // AstNode::user2() -> bool. Already emitted decl for symbols. - const VNUser2InUse m_inuser2; + // None allowed to support threaded emitting // MEMBERS std::unordered_set m_emittedManually; // Set of names already declared manually. EmitCBaseVisitor& m_emitter; // For access to file output bool m_needsBlankLine = false; // Emit blank line if any declarations were emitted (cosmetic) + std::set m_emitted; // -> in set. Already emitted decl for symbols. // METHODS + bool declaredOnce(AstNode* nodep) { return m_emitted.insert(nodep).second; } + void lazyDeclare(AstCFunc* funcp) { // Already declared in this compilation unit - if (funcp->user2SetOnce()) return; + if (!declaredOnce(funcp)) return; // Check if this kind of function is lazily declared if (!(funcp->isMethod() && funcp->isLoose()) && !funcp->dpiImportPrototype()) return; // Already declared manually @@ -58,7 +60,7 @@ class EmitCLazyDecls final : public VNVisitor { } void lazyDeclareConstPoolVar(AstVar* varp) { - if (varp->user2SetOnce()) return; // Already declared + if (!declaredOnce(varp)) return; // Already declared const string nameProtect = m_emitter.topClassName() + "__ConstPool__" + varp->nameProtect(); m_emitter.puts("extern const "); @@ -106,8 +108,8 @@ public: m_emitter.puts(suffix); m_emitter.ensureNewLine(); } - void declared(AstCFunc* nodep) { nodep->user2SetOnce(); } - void reset() { AstNode::user2ClearTree(); } + void declared(AstCFunc* nodep) { m_emitted.insert(nodep); } + void reset() { m_emitted.clear(); } }; //###################################################################### From 4d49db48a39fccdb5c29c87d5c3f06405f62a27f Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Mon, 12 Sep 2022 18:00:41 +0200 Subject: [PATCH 22/75] Internals: Remove usage of user1 from EmitCTrace (#3617). No Functional change intended. --- src/V3EmitCImp.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 9bea7b2c0..b31e30b88 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -551,14 +551,13 @@ public: class EmitCTrace final : EmitCFunc { // NODE STATE/TYPES - // Cleared on netlist - // AstNode::user1() -> int. Enum number - const VNUser1InUse m_inuser1; + // None allowed to support threaded emitting // MEMBERS const bool m_slow; // Making slow file int m_enumNum = 0; // Enumeration number (whole netlist) V3UniqueNames m_uniqueNames; // For generating unique file names + std::unordered_map m_enumNumMap; // EnumDType to enumeration number // METHODS void openNextOutputFile() { @@ -710,10 +709,10 @@ class EmitCTrace final : EmitCFunc { // Skip over refs-to-refs, but stop before final ref so can get data type name // Alternatively back in V3Width we could push enum names from upper typedefs if (AstEnumDType* const enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) { - int enumNum = enump->user1(); + int enumNum = m_enumNumMap[enump]; if (!enumNum) { enumNum = ++m_enumNum; - enump->user1(enumNum); + m_enumNumMap[enump] = enumNum; int nvals = 0; puts("{\n"); puts("const char* " + protect("__VenumItemNames") + "[]\n"); From 08b6bdddf9e2f54ec36d1fcbe212521ed28ebc7c Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Mon, 12 Sep 2022 17:21:27 +0100 Subject: [PATCH 23/75] Update default --mod-prefix when --prefix is repeated Fixes #3603 --- src/V3Options.cpp | 5 +--- test_regress/t/t_flag_prefix.pl | 49 +++++++++++++++++++++++++++++++++ test_regress/t/t_flag_prefix.v | 35 +++++++++++++++++++++++ 3 files changed, 85 insertions(+), 4 deletions(-) create mode 100755 test_regress/t/t_flag_prefix.pl create mode 100755 test_regress/t/t_flag_prefix.v diff --git a/src/V3Options.cpp b/src/V3Options.cpp index d88f6df3c..e1f194e8b 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1270,10 +1270,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-pins-uint8", OnOff, &m_pinsUint8); DECL_OPTION("-pipe-filter", Set, &m_pipeFilter); DECL_OPTION("-pp-comments", OnOff, &m_ppComments); - DECL_OPTION("-prefix", CbVal, [this](const char* valp) { - m_prefix = valp; - if (m_modPrefix == "") m_modPrefix = m_prefix; - }); + DECL_OPTION("-prefix", Set, &m_prefix); DECL_OPTION("-private", CbCall, [this]() { m_public = false; }); DECL_OPTION("-prof-c", OnOff, &m_profC); DECL_OPTION("-prof-cfuncs", CbCall, [this]() { m_profC = m_profCFuncs = true; }); diff --git a/test_regress/t/t_flag_prefix.pl b/test_regress/t/t_flag_prefix.pl new file mode 100755 index 000000000..adcce742d --- /dev/null +++ b/test_regress/t/t_flag_prefix.pl @@ -0,0 +1,49 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Geza Lore. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + verilator_flags2 => ["--prefix t_flag_prefix", # should be overridden + "--prefix Vprefix", + "--exe", "--main", "--stats", "--build"], + verilator_make_cmake => 0, + verilator_make_gmake => 0, + make_main => 0, + ); + +execute( + check_finished => 1, + executable => "$Self->{obj_dir}/Vprefix", + ); + +sub check_files { + foreach my $path (glob("$Self->{obj_dir}/*")) { + my $filename = substr $path, ((length $Self->{obj_dir}) + 1); + next if ($filename =~ /^.*\.log$/); + if ($filename =~ /t_flag_prefix/) { + error("bad filename $filename"); + next; + } + next if ($filename =~ /^(.*\.(o|a)|Vprefix)$/); + my $fh = IO::File->new("<$path") or error("$! $filenme"); + while (defined(my $line = $fh->getline)) { + $line =~ s/--prefix V?t_flag_prefix//g; + $line =~ s/obj_vlt\/t_flag_prefix//g; + $line =~ s/t\/t_flag_prefix\.v//g; + error("bad line in $filename: $line") if $line =~ /t_flag_prefix/; + } + } +} + +check_files(); + +ok(1); +1; diff --git a/test_regress/t/t_flag_prefix.v b/test_regress/t/t_flag_prefix.v new file mode 100755 index 000000000..00634520b --- /dev/null +++ b/test_regress/t/t_flag_prefix.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Geza Lore. +// SPDX-License-Identifier: CC0-1.0 + +module t; + sub sub(); +endmodule + +module sub; + // no_inline_module, so it goes into separate file + /* verilator no_inline_module */ + + // Goes into const pool which is separate file + wire bit [255:0] C = {32'h1111_1111, + 32'h2222_2222, + 32'h3333_3333, + 32'h4444_4444, + 32'h5555_5555, + 32'h6666_6666, + 32'h7777_7777, + 32'h8888_8888}; + + initial begin + // Note: Base index via $c to prevent optimization + $display("0x%32x", C[$c(0*32)+:32]); + $display("0x%32x", C[$c(2*32)+:32]); + $display("0x%32x", C[$c(4*32)+:32]); + $display("0x%32x", C[$c(6*32)+:32]); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule From 81fe35ee2e71ee8db894bb7e6bf5a490b2fdbb71 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 12 Sep 2022 18:03:47 -0400 Subject: [PATCH 24/75] Fix typedef'ed class conversion to boolean (#3616). --- Changes | 3 ++- src/V3Width.cpp | 12 ++++++------ test_regress/t/t_class1.v | 6 ++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Changes b/Changes index 5cae1fc1c..202e279c2 100644 --- a/Changes +++ b/Changes @@ -13,7 +13,8 @@ Verilator 4.227 devel **Minor:** -Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] +* Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] +* Fix typedef'ed class conversion to boolean (#3616). [Aleksander Kiryk] Verilator 4.226 2022-08-31 diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 7fdbf20f0..081fc526e 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -5808,7 +5808,8 @@ private: "Node has no type"); // Perhaps forgot to do a prelim visit on it? // // For DOUBLE under a logical op, add implied test against zero, never a warning - if (underp && underp->isDouble()) { + AstNodeDType* const underVDTypep = underp ? underp->dtypep()->skipRefp() : nullptr; + if (underp && underVDTypep->isDouble()) { UINFO(6, " spliceCvtCmpD0: " << underp << endl); VNRelinker linker; underp->unlinkFrBack(&linker); @@ -5816,13 +5817,12 @@ private: = new AstNeqD(nodep->fileline(), underp, new AstConst(nodep->fileline(), AstConst::RealDouble(), 0.0)); linker.relink(newp); - } else if (VN_IS(underp->dtypep(), ClassRefDType) - || (VN_IS(underp->dtypep(), BasicDType) - && VN_AS(underp->dtypep(), BasicDType)->keyword() - == VBasicDTypeKwd::CHANDLE)) { + } else if (VN_IS(underVDTypep, ClassRefDType) + || (VN_IS(underVDTypep, BasicDType) + && VN_AS(underVDTypep, BasicDType)->keyword() == VBasicDTypeKwd::CHANDLE)) { // Allow warning-free "if (handle)" VL_DO_DANGLING(fixWidthReduce(underp), underp); // Changed - } else if (!underp->dtypep()->basicp()) { + } else if (!underVDTypep->basicp()) { nodep->v3error("Logical operator " << nodep->prettyTypeName() << " expects a non-complex data type on the " << side << "."); diff --git a/test_regress/t/t_class1.v b/test_regress/t/t_class1.v index b584c5be6..c10125c51 100644 --- a/test_regress/t/t_class1.v +++ b/test_regress/t/t_class1.v @@ -12,14 +12,20 @@ class Cls; endclass : Cls module t (/*AUTOARG*/); + typedef Cls Cls2; + initial begin Cls c; + Cls2 c2; if (c != null) $stop; if (c) $stop; + if (c2) $stop; $display("Display: null = \"%p\"", c); // null c = new; + c2 = new; if (c == null) $stop; if (!c) $stop; + if (!c2) $stop; $display("Display: newed = \"%p\"", c); // '{imembera:0, imemberb:0} c.imembera = 10; c.imemberb = 20; From 93a044f587cec70d67e2ee2dbebdc632843f5e41 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Tue, 13 Sep 2022 18:15:34 +0200 Subject: [PATCH 25/75] Internals: Rework addFilesp towards parallel emit (#3620). No functional change intended. --- src/V3EmitCBase.cpp | 4 ++-- src/V3EmitCBase.h | 2 +- src/V3EmitCImp.cpp | 45 ++++++++++++++++++++++++++++++++------------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/V3EmitCBase.cpp b/src/V3EmitCBase.cpp index 1e3e9383f..40198fa76 100644 --- a/src/V3EmitCBase.cpp +++ b/src/V3EmitCBase.cpp @@ -57,11 +57,11 @@ string EmitCBaseVisitor::funcNameProtect(const AstCFunc* nodep, const AstNodeMod return name; } -AstCFile* EmitCBaseVisitor::newCFile(const string& filename, bool slow, bool source) { +AstCFile* EmitCBaseVisitor::newCFile(const string& filename, bool slow, bool source, bool add) { AstCFile* const cfilep = new AstCFile(v3Global.rootp()->fileline(), filename); cfilep->slow(slow); cfilep->source(source); - v3Global.rootp()->addFilesp(cfilep); + if (add) v3Global.rootp()->addFilesp(cfilep); return cfilep; } diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 66b954f35..2451cfdfc 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -100,7 +100,7 @@ public: && (varp->basicp() && !varp->basicp()->isOpaque()); // Aggregates can't be anon } - static AstCFile* newCFile(const string& filename, bool slow, bool source); + static AstCFile* newCFile(const string& filename, bool slow, bool source, bool add = true); string cFuncArgs(const AstCFunc* nodep); void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope); void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false); diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index b31e30b88..988a8b7fd 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -148,6 +148,7 @@ class EmitCImp final : EmitCFunc { const std::set* m_requiredHeadersp; // Header files required by output file std::string m_subFileName; // substring added to output filenames V3UniqueNames m_uniqueNames; // For generating unique file names + std::deque& m_cfilesr; // cfiles generated by this emit // METHODS void openNextOutputFile(const std::set& headers, const string& subFileName) { @@ -160,7 +161,8 @@ class EmitCImp final : EmitCFunc { // Unfortunately we have some lint checks here, so we can't just skip processing. // We should move them to a different stage. const string filename = VL_DEV_NULL; - newCFile(filename, /* slow: */ m_slow, /* source: */ true); + m_cfilesr.push_back( + newCFile(filename, /* slow: */ m_slow, /* source: */ true, /* add */ false)); m_ofp = new V3OutCFile(filename); } else { string filename = v3Global.opt.makeDir() + "/" + prefixNameProtect(m_fileModp); @@ -170,7 +172,8 @@ class EmitCImp final : EmitCFunc { } if (m_slow) filename += "__Slow"; filename += ".cpp"; - newCFile(filename, /* slow: */ m_slow, /* source: */ true); + m_cfilesr.push_back( + newCFile(filename, /* slow: */ m_slow, /* source: */ true, /* add */ false)); m_ofp = v3Global.opt.systemC() ? new V3OutScFile(filename) : new V3OutCFile(filename); } @@ -522,9 +525,10 @@ class EmitCImp final : EmitCFunc { EmitCFunc::visit(nodep); } - explicit EmitCImp(const AstNodeModule* modp, bool slow) + explicit EmitCImp(const AstNodeModule* modp, bool slow, std::deque& cfilesr) : m_fileModp{modp} - , m_slow{slow} { + , m_slow{slow} + , m_cfilesr{cfilesr} { UINFO(5, " Emitting implementation of " << prefixNameProtect(modp) << endl); m_modp = modp; @@ -543,7 +547,9 @@ class EmitCImp final : EmitCFunc { virtual ~EmitCImp() override = default; public: - static void main(const AstNodeModule* modp, bool slow) { EmitCImp{modp, slow}; } + static void main(const AstNodeModule* modp, bool slow, std::deque& cfilesr) { + EmitCImp{modp, slow, cfilesr}; + } }; //###################################################################### @@ -558,6 +564,7 @@ class EmitCTrace final : EmitCFunc { int m_enumNum = 0; // Enumeration number (whole netlist) V3UniqueNames m_uniqueNames; // For generating unique file names std::unordered_map m_enumNumMap; // EnumDType to enumeration number + std::deque& m_cfilesr; // cfiles generated by this emit // METHODS void openNextOutputFile() { @@ -572,8 +579,9 @@ class EmitCTrace final : EmitCFunc { if (m_slow) filename += "__Slow"; filename += ".cpp"; - AstCFile* const cfilep = newCFile(filename, m_slow, true /*source*/); + AstCFile* const cfilep = newCFile(filename, m_slow, true /*source*/, false /*add*/); cfilep->support(true); + m_cfilesr.push_back(cfilep); if (optSystemC()) { m_ofp = new V3OutScFile(filename); @@ -862,8 +870,9 @@ class EmitCTrace final : EmitCFunc { } } - explicit EmitCTrace(AstNodeModule* modp, bool slow) - : m_slow{slow} { + explicit EmitCTrace(AstNodeModule* modp, bool slow, std::deque& cfilesr) + : m_slow{slow} + , m_cfilesr{cfilesr} { m_modp = modp; // Open output file openNextOutputFile(); @@ -877,7 +886,9 @@ class EmitCTrace final : EmitCFunc { virtual ~EmitCTrace() override = default; public: - static void main(AstNodeModule* modp, bool slow) { EmitCTrace{modp, slow}; } + static void main(AstNodeModule* modp, bool slow, std::deque& cfilesr) { + EmitCTrace{modp, slow, cfilesr}; + } }; //###################################################################### @@ -887,19 +898,27 @@ void V3EmitC::emitcImp() { UINFO(2, __FUNCTION__ << ": " << endl); // Make parent module pointers available. const EmitCParentModule emitCParentModule; + std::list> cfiles; // Process each module in turn for (const AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) { if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage const AstNodeModule* const modp = VN_AS(nodep, NodeModule); - EmitCImp::main(modp, /* slow: */ true); - EmitCImp::main(modp, /* slow: */ false); + cfiles.emplace_back(); + EmitCImp::main(modp, /* slow: */ true, cfiles.back()); + cfiles.emplace_back(); + EmitCImp::main(modp, /* slow: */ false, cfiles.back()); } // Emit trace routines (currently they can only exist in the top module) if (v3Global.opt.trace() && !v3Global.opt.lintOnly()) { - EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true); - EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false); + cfiles.emplace_back(); + EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true, cfiles.back()); + cfiles.emplace_back(); + EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false, cfiles.back()); + } + for (const auto& collr : cfiles) { + for (const auto cfilep : collr) v3Global.rootp()->addFilesp(cfilep); } } From 25644844299af8f987ffdea7aa4859ff00c37065 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Tue, 13 Sep 2022 15:57:22 +0100 Subject: [PATCH 26/75] astgen: Rewrite in a more OOP way, in preparation for extensions Rely less on strings and represent AstNode classes as a 'class Node', with all associated properties kept together, rather than distributed over multiple dictionaries or constructed at retrieval time. No functional change intended. --- src/astgen | 362 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 203 insertions(+), 159 deletions(-) diff --git a/src/astgen b/src/astgen index 44529a0e4..f8860dce0 100755 --- a/src/astgen +++ b/src/astgen @@ -8,9 +8,125 @@ import re import sys # from pprint import pprint, pformat -Types = [] -Classes = {} -Children = {} + +class Node: + def __init__(self, name, superClass): + self._name = name + self._superClass = superClass + self._subClasses = [] # Initially list, but tuple after completion + self._allSuperClasses = None # Computed on demand after completion + self._allSubClasses = None # Computed on demand after completion + self._typeId = None # Concrete type identifier number for leaf classes + self._typeIdMin = None # Lowest type identifier number for class + self._typeIdMax = None # Highest type identifier number for class + + @property + def name(self): + return self._name + + @property + def superClass(self): + return self._superClass + + @property + def isCompleted(self): + return isinstance(self._subClasses, tuple) + + # Pre completion methods + def addSubClass(self, subClass): + assert not self.isCompleted + self._subClasses.append(subClass) + + # Computes derived properties over entire class hierarchy. + # No more changes to the hierarchy are allowed once this was called + def complete(self, typeId=0): + assert not self.isCompleted + # Sort sub-classes and convert to tuple, which marks completion + self._subClasses = tuple(sorted(self._subClasses, + key=lambda _: _.name)) + # Leaves + if self.isLeaf: + self._typeId = typeId + return typeId + 1 + + # Non-leaves + for subClass in self._subClasses: + typeId = subClass.complete(typeId) + return typeId + + # Post completion methods + @property + def subClasses(self): + assert self.isCompleted + return self._subClasses + + @property + def isRoot(self): + assert self.isCompleted + return self.superClass is None + + @property + def isLeaf(self): + assert self.isCompleted + return not self.subClasses + + @property + def allSuperClasses(self): + assert self.isCompleted + if self._allSuperClasses is None: + if self.superClass is None: + self._allSuperClasses = () + else: + self._allSuperClasses = self.superClass.allSuperClasses + ( + self.superClass, ) + return self._allSuperClasses + + @property + def allSubClasses(self): + assert self.isCompleted + if self._allSubClasses is None: + if self.isLeaf: + self._allSubClasses = () + else: + self._allSubClasses = self.subClasses + tuple( + _ for subClass in self.subClasses + for _ in subClass.allSubClasses) + return self._allSubClasses + + @property + def typeId(self): + assert self.isCompleted + assert self.isLeaf + return self._typeId + + @property + def typeIdMin(self): + assert self.isCompleted + if self.isLeaf: + return self.typeId + if self._typeIdMin is None: + self._typeIdMin = min(_.typeIdMin for _ in self.allSubClasses) + return self._typeIdMin + + @property + def typeIdMax(self): + assert self.isCompleted + if self.isLeaf: + return self.typeId + if self._typeIdMax is None: + self._typeIdMax = max(_.typeIdMax for _ in self.allSubClasses) + return self._typeIdMax + + def isSubClassOf(self, other): + assert self.isCompleted + if self is other: + return True + return self in other.allSubClasses + + +Nodes = {} +SortedNodes = None + ClassRefs = {} Stages = {} @@ -111,7 +227,7 @@ class Cpt: self.error("Can't parse from function: " + func) typen = match.group(1) subnodes = match.group(2) - if not subclasses_of(typen): + if Nodes[typen].isRoot: self.error("Unknown AstNode typen: " + typen + ": in " + func) mif = "" @@ -166,7 +282,7 @@ class Cpt: elif match_skip: typen = match_skip.group(1) self.tree_skip_visit[typen] = 1 - if typen not in Classes: + if typen not in Nodes: self.error("Unknown node type: " + typen) else: @@ -296,12 +412,13 @@ class Cpt: self.print( " // Bottom class up, as more simple transforms are generally better\n" ) - for typen in sorted(Classes.keys()): + for node in SortedNodes: out_for_type_sc = [] out_for_type = [] - bases = subclasses_of(typen) - bases.append(typen) - for base in bases: + classes = list(node.allSuperClasses) + classes.append(node) + for base in classes: + base = base.name if base not in self.treeop: continue for typefunc in self.treeop[base]: @@ -328,23 +445,23 @@ class Cpt: if len(out_for_type_sc) > 0: # Short-circuited types self.print( " // Generated by astgen with short-circuiting\n" + - " virtual void visit(Ast" + typen + + " virtual void visit(Ast" + node.name + "* nodep) override {\n" + " iterateAndNextNull(nodep->lhsp());\n" + "".join(out_for_type_sc)) if out_for_type[0]: self.print(" iterateAndNextNull(nodep->rhsp());\n") - if is_subclass_of(typen, "NodeTriop"): + if node.isSubClassOf(Nodes["NodeTriop"]): self.print( " iterateAndNextNull(nodep->thsp());\n") self.print("".join(out_for_type) + " }\n") elif len(out_for_type) > 0: # Other types with something to print - skip = typen in self.tree_skip_visit + skip = node.name in self.tree_skip_visit gen = "Gen" if skip else "" override = "" if skip else " override" self.print( " // Generated by astgen\n" + " virtual void visit" + - gen + "(Ast" + typen + "* nodep)" + override + " {\n" + + gen + "(Ast" + node.name + "* nodep)" + override + " {\n" + ("" if skip else " iterateChildren(nodep);\n") + ''.join(out_for_type) + " }\n") @@ -368,11 +485,13 @@ def read_types(filename): if re.search(r'Ast', supern) or classn == "AstNode": classn = re.sub(r'^Ast', '', classn) supern = re.sub(r'^Ast', '', supern) - Classes[classn] = supern - if supern != '': - if supern not in Children: - Children[supern] = {} - Children[supern][classn] = 1 + if supern: + superClass = Nodes[supern] + node = Node(classn, superClass) + Nodes[supern].addSubClass(node) + else: + node = Node(classn, None) + Nodes[classn] = node def read_stages(filename): @@ -424,37 +543,6 @@ def open_file(filename): return fh -def subclasses_of(typen): - cllist = [] - subclass = Classes[typen] - while True: - if subclass not in Classes: - break - cllist.append(subclass) - subclass = Classes[subclass] - - cllist.reverse() - return cllist - - -def children_of(typen): - cllist = [] - todo = [] - todo.append(typen) - while len(todo) != 0: - subclass = todo.pop(0) - if subclass in Children: - for child in sorted(Children[subclass].keys()): - todo.append(child) - cllist.append(child) - - return cllist - - -def is_subclass_of(typen, what): - return typen == what or (typen in children_of(what)) - - # --------------------------------------------------------------------- @@ -468,20 +556,19 @@ def write_report(filename): fh.write(" " + classn + "\n") fh.write("\nClasses:\n") - for typen in sorted(Classes.keys()): - fh.write(" class Ast%-17s\n" % typen) + for node in SortedNodes: + fh.write(" class Ast%-17s\n" % node.name) fh.write(" parent: ") - for subclass in subclasses_of(typen): - if subclass != 'Node': - fh.write("Ast%-12s " % subclass) + for superClass in node.allSuperClasses: + if not superClass.isRoot: + fh.write("Ast%-12s " % superClass.name) fh.write("\n") fh.write(" childs: ") - for subclass in children_of(typen): - if subclass != 'Node': - fh.write("Ast%-12s " % subclass) + for subClass in node.allSubClasses: + fh.write("Ast%-12s " % subClass.name) fh.write("\n") - if ("Ast" + typen) in ClassRefs: # pylint: disable=superfluous-parens - refs = ClassRefs["Ast" + typen] + if ("Ast" + node.name) in ClassRefs: # pylint: disable=superfluous-parens + refs = ClassRefs["Ast" + node.name] fh.write(" newed: ") for stage in sorted(refs['newed'].keys(), key=lambda val: Stages[val] @@ -500,27 +587,27 @@ def write_report(filename): def write_classes(filename): with open_file(filename) as fh: fh.write("class AstNode;\n") - for typen in sorted(Classes.keys()): - fh.write("class Ast%-17s // " % (typen + ";")) - for subclass in subclasses_of(typen): - fh.write("Ast%-12s " % subclass) + for node in SortedNodes: + fh.write("class Ast%-17s // " % (node.name + ";")) + for superClass in node.allSuperClasses: + fh.write("Ast%-12s " % superClass.name) fh.write("\n") def write_visitor_decls(filename): with open_file(filename) as fh: - for typen in sorted(Classes.keys()): - if typen != "Node": - fh.write("virtual void visit(Ast" + typen + "*);\n") + for node in SortedNodes: + if not node.isRoot: + fh.write("virtual void visit(Ast" + node.name + "*);\n") def write_visitor_defns(filename): with open_file(filename) as fh: - for typen in sorted(Classes.keys()): - if typen != "Node": - base = Classes[typen] - fh.write("void VNVisitor::visit(Ast" + typen + - "* nodep) { visit(static_cast(nodep)); }\n") @@ -528,75 +615,51 @@ def write_impl(filename): with open_file(filename) as fh: fh.write("\n") fh.write("// For internal use. They assume argument is not nullptr.\n") - for typen in sorted(Classes.keys()): + for node in SortedNodes: fh.write("template<> inline bool AstNode::privateTypeTest(const AstNode* nodep) { ") - if typen == "Node": + node.name + ">(const AstNode* nodep) { ") + if node.isRoot: fh.write("return true; ") else: fh.write("return ") - if re.search(r'^Node', typen): + if not node.isLeaf: fh.write( "static_cast(nodep->type()) >= static_cast(VNType::first" - + typen + ") && ") + + node.name + ") && ") fh.write( "static_cast(nodep->type()) <= static_cast(VNType::last" - + typen + "); ") + + node.name + "); ") else: - fh.write("nodep->type() == VNType::at" + typen + "; ") + fh.write("nodep->type() == VNType::at" + node.name + "; ") fh.write("}\n") -def write_type_enum(fh, typen, idx, processed, kind, indent): - # Skip this if it has already been processed - if typen in processed: - return idx - # Mark processed - processed[typen] = 1 - - # The last used index - last = None - - if not re.match(r'^Node', typen): - last = idx - if kind == "concrete-enum": - fh.write(" " * (indent * 4) + "at" + typen + " = " + str(idx) + - ",\n") - elif kind == "concrete-ascii": - fh.write(" " * (indent * 4) + "\"" + typen.upper() + "\",\n") - idx += 1 - elif kind == "abstract-enum": - fh.write(" " * (indent * 4) + "first" + typen + " = " + str(idx) + - ",\n") - - if typen in Children: - for child in sorted(Children[typen].keys()): - (idx, last) = write_type_enum(fh, child, idx, processed, kind, - indent) - - if re.match(r'^Node', typen) and kind == "abstract-enum": - fh.write(" " * (indent * 4) + "last" + typen + " = " + str(last) + - ",\n") - - return [idx, last] - - def write_types(filename): with open_file(filename) as fh: fh.write(" enum en : uint16_t {\n") - (final, ignored) = write_type_enum( # pylint: disable=W0612 - fh, "Node", 0, {}, "concrete-enum", 2) - fh.write(" _ENUM_END = " + str(final) + "\n") + for node in sorted(filter(lambda _: _.isLeaf, SortedNodes), + key=lambda _: _.typeId): + fh.write(" at" + node.name + " = " + str(node.typeId) + + ",\n") + fh.write(" _ENUM_END = " + str(Nodes["Node"].typeIdMax + 1) + + "\n") fh.write(" };\n") fh.write(" enum bounds : uint16_t {\n") - write_type_enum(fh, "Node", 0, {}, "abstract-enum", 2) + for node in sorted(filter(lambda _: not _.isLeaf, SortedNodes), + key=lambda _: _.typeIdMin): + fh.write(" first" + node.name + " = " + + str(node.typeIdMin) + ",\n") + fh.write(" last" + node.name + " = " + str(node.typeIdMax) + + ",\n") fh.write(" _BOUNDS_END\n") fh.write(" };\n") fh.write(" const char* ascii() const {\n") fh.write(" static const char* const names[_ENUM_END + 1] = {\n") - write_type_enum(fh, "Node", 0, {}, "concrete-ascii", 3) + for node in sorted(filter(lambda _: _.isLeaf, SortedNodes), + key=lambda _: _.typeId): + fh.write(" \"" + node.name.upper() + "\",\n") fh.write(" \"_ENUM_END\"\n") fh.write(" };\n") fh.write(" return names[m_e];\n") @@ -605,45 +668,21 @@ def write_types(filename): def write_yystype(filename): with open_file(filename) as fh: - for typen in sorted(Classes.keys()): - fh.write("Ast{t}* {m}p;\n".format(t=typen, - m=typen[0].lower() + typen[1:])) + for node in SortedNodes: + fh.write("Ast{t}* {m}p;\n".format(t=node.name, + m=node.name[0].lower() + + node.name[1:])) def write_macros(filename): with open_file(filename) as fh: - typen = "None" - base = "None" - - in_filename = "V3AstNodes.h" - ifile = Args.I + "/" + in_filename - with open(ifile) as ifh: - for (lineno, line) in enumerate(ifh, 1): - # Drop expanded macro definitions - but keep empty line so compiler - # message locations are accurate - line = re.sub(r'^\s*#(define|undef)\s+ASTGEN_.*$', '', line) - - # Track current node type and base class - match = re.search( - r'\s*class\s*Ast(\S+)\s*(final|VL_NOT_FINAL)?\s*:\s*(public)?\s*(AstNode\S*)', - line) - if match: - typen = match.group(1) - base = match.group(4) - if not typen.startswith("Node"): - macro = "#define ASTGEN_SUPER_{t}(...) {b}(VNType::at{t}, __VA_ARGS__)\n" \ - .format(b=base, t=typen) - fh.write(macro) - - match = re.search(r"ASTGEN_SUPER_(\w+)", line) - if match: - if typen != match.group(1): - print(( - "V3AstNodes.h:{l} ERROR: class Ast{t} calls wrong superclass " - + - "constructor macro (should call ASTGEN_SUPER_{t})" - ).format(l=lineno, t=typen)) - sys.exit(1) + for node in SortedNodes: + # Only care about leaf classes + if not node.isLeaf: + continue + fh.write( + "#define ASTGEN_SUPER_{t}(...) Ast{b}(VNType::at{t}, __VA_ARGS__)\n" + .format(t=node.name, b=node.superClass.name)) ###################################################################### @@ -673,19 +712,24 @@ Args = parser.parse_args() read_types(Args.I + "/V3Ast.h") read_types(Args.I + "/V3AstNodes.h") -for typen in sorted(Classes.keys()): + +# Compute derived properties over the whole AstNode hierarchy +Nodes["Node"].complete() + +SortedNodes = tuple(map(lambda _: Nodes[_], sorted(Nodes.keys()))) + +for node in SortedNodes: # Check all leaves are not AstNode* and non-leaves are AstNode* - children = children_of(typen) - if re.match(r'^Node', typen): - if len(children) == 0: + if re.match(r'^Node', node.name): + if node.isLeaf: sys.exit( "%Error: Final AstNode subclasses must not be named AstNode*: Ast" - + typen) + + node.name) else: - if len(children) != 0: + if not node.isLeaf: sys.exit( "%Error: Non-final AstNode subclasses must be named AstNode*: Ast" - + typen) + + node.name) read_stages(Args.I + "/Verilator.cpp") From ae466b170361af49beac5c827638fbec9a3ab6e2 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Wed, 14 Sep 2022 13:37:51 +0200 Subject: [PATCH 27/75] Internals: Improve Verilation peak memory usage in V3Subst (#3512). --- src/V3Subst.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index ef7562ac5..ce43a7fd0 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -359,6 +359,13 @@ private: } virtual void visit(AstVar*) override {} virtual void visit(AstConst*) override {} + virtual void visit(AstModule* nodep) override { + ++m_ops; + if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA; + iterateChildren(nodep); + // Reduce peak memory usage by reclaiming the edited AstNodes + doDeletes(); + } virtual void visit(AstNode* nodep) override { m_ops++; if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA; From a3c58d7b70b45e42b3b43db5da5a1fecb8d3db59 Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Wed, 14 Sep 2022 13:39:27 +0200 Subject: [PATCH 28/75] Support IEEE constant signal strengths (#3601). --- src/V3Ast.h | 30 ++++ src/V3AstNodes.cpp | 4 + src/V3AstNodes.h | 24 +++ src/V3Const.cpp | 1 + src/V3LinkLValue.cpp | 8 + src/V3ParseGrammar.cpp | 10 +- src/V3ParseImp.cpp | 9 +- src/V3ParseImp.h | 2 + src/V3Tristate.cpp | 147 ++++++++++++++++++ src/verilog.l | 16 +- src/verilog.y | 111 +++++++++---- test_regress/t/t_strength_assignments.pl | 21 +++ test_regress/t/t_strength_assignments.v | 38 +++++ test_regress/t/t_strength_bufif1.out | 5 + test_regress/t/t_strength_bufif1.pl | 19 +++ test_regress/t/t_strength_bufif1.v | 17 ++ test_regress/t/t_strength_highz.out | 14 ++ test_regress/t/t_strength_highz.pl | 19 +++ test_regress/t/t_strength_highz.v | 19 +++ .../t/t_strength_strong1_strong1_bad.out | 4 + .../t/t_strength_strong1_strong1_bad.pl | 19 +++ .../t/t_strength_strong1_strong1_bad.v | 13 ++ test_regress/t/t_weak_nor_strong_assign.pl | 21 +++ test_regress/t/t_weak_nor_strong_assign.v | 18 +++ 24 files changed, 550 insertions(+), 39 deletions(-) create mode 100755 test_regress/t/t_strength_assignments.pl create mode 100644 test_regress/t/t_strength_assignments.v create mode 100644 test_regress/t/t_strength_bufif1.out create mode 100755 test_regress/t/t_strength_bufif1.pl create mode 100644 test_regress/t/t_strength_bufif1.v create mode 100644 test_regress/t/t_strength_highz.out create mode 100755 test_regress/t/t_strength_highz.pl create mode 100644 test_regress/t/t_strength_highz.v create mode 100644 test_regress/t/t_strength_strong1_strong1_bad.out create mode 100755 test_regress/t/t_strength_strong1_strong1_bad.pl create mode 100644 test_regress/t/t_strength_strong1_strong1_bad.v create mode 100755 test_regress/t/t_weak_nor_strong_assign.pl create mode 100644 test_regress/t/t_weak_nor_strong_assign.v diff --git a/src/V3Ast.h b/src/V3Ast.h index 9e50846cd..6e455ef1c 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -732,6 +732,10 @@ public: return (m_e == WIRE || m_e == WREAL || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1 || m_e == PORT || m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == VAR); } + bool isNet() const { + return (m_e == WIRE || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1 + || m_e == SUPPLY0 || m_e == SUPPLY1); + } bool isContAssignable() const { // In Verilog, always ok in SystemVerilog return (m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == WIRE || m_e == WREAL || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1 @@ -975,6 +979,32 @@ inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) { return os << rhs.ascii(); } +//###################################################################### + +class VStrength final { +public: + enum en : uint8_t { HIGHZ, SMALL, MEDIUM, WEAK, LARGE, PULL, STRONG, SUPPLY }; + enum en m_e; + + inline VStrength(en strengthLevel) + : m_e(strengthLevel) {} + explicit inline VStrength(int _e) + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning + + operator en() const { return m_e; } + const char* ascii() const { + static const char* const names[] + = {"highz", "small", "medium", "weak", "large", "pull", "strong", "supply"}; + return names[m_e]; + } +}; +inline bool operator==(const VStrength& lhs, const VStrength& rhs) { return lhs.m_e == rhs.m_e; } +inline bool operator==(const VStrength& lhs, VStrength::en rhs) { return lhs.m_e == rhs; } +inline bool operator==(VStrength::en lhs, const VStrength& rhs) { return lhs == rhs.m_e; } +inline std::ostream& operator<<(std::ostream& os, const VStrength& rhs) { + return os << rhs.ascii(); +} + //###################################################################### // VNumRange - Structure containing numeric range information // See also AstRange, which is a symbolic version of this diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index f8a409247..d534622e5 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1786,6 +1786,10 @@ void AstSenItem::dump(std::ostream& str) const { this->AstNode::dump(str); str << " [" << edgeType().ascii() << "]"; } +void AstStrengthSpec::dump(std::ostream& str) const { + this->AstNode::dump(str); + str << " (" << m_s0.ascii() << ", " << m_s1.ascii() << ")"; +} void AstParseRef::dump(std::ostream& str) const { this->AstNode::dump(str); str << " [" << expect().ascii() << "]"; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index cef18db50..b5724847b 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -290,6 +290,23 @@ public: virtual bool same(const AstNode* /*samep*/) const override { return true; } }; +class AstStrengthSpec final : public AstNode { +private: + VStrength m_s0; // Drive 0 strength + VStrength m_s1; // Drive 1 strength + +public: + AstStrengthSpec(FileLine* fl, VStrength s0, VStrength s1) + : ASTGEN_SUPER_StrengthSpec(fl) + , m_s0{s0} + , m_s1{s1} {} + + ASTNODE_NODE_FUNCS(StrengthSpec) + VStrength strength0() { return m_s0; } + VStrength strength1() { return m_s1; } + virtual void dump(std::ostream& str) const override; +}; + class AstGatePin final : public AstNodeMath { // Possibly expand a gate primitive input pin value to match the range of the gate primitive public: @@ -2094,6 +2111,7 @@ private: bool m_isRand : 1; // Random variable bool m_isConst : 1; // Table contains constant data bool m_isContinuously : 1; // Ever assigned continuously (for force/release) + bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic) bool m_isPulldown : 1; // Tri0 bool m_isPullup : 1; // Tri1 @@ -2134,6 +2152,7 @@ private: m_isRand = false; m_isConst = false; m_isContinuously = false; + m_hasStrengthAssignment = false; m_isStatic = false; m_isPulldown = false; m_isPullup = false; @@ -2297,6 +2316,8 @@ public: void isIfaceParent(bool flag) { m_isIfaceParent = flag; } void funcLocal(bool flag) { m_funcLocal = flag; } void funcReturn(bool flag) { m_funcReturn = flag; } + void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; } + bool hasStrengthAssignment() { return m_hasStrengthAssignment; } void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; } bool isDpiOpenArray() const { return m_isDpiOpenArray; } bool isHideLocal() const { return m_isHideLocal; } @@ -2330,6 +2351,7 @@ public: bool isIfaceRef() const { return (varType() == VVarType::IFACEREF); } bool isIfaceParent() const { return m_isIfaceParent; } bool isSignal() const { return varType().isSignal(); } + bool isNet() const { return varType().isNet(); } bool isTemp() const { return varType().isTemp(); } bool isToggleCoverable() const { return ((isIO() || isSignal()) @@ -3630,6 +3652,8 @@ public: AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignW(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignW) + AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); } + void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); } virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignW(this->fileline(), lhsp, rhsp); } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 096510af1..2c5f10f7b 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -2853,6 +2853,7 @@ private: if (m_wremove && !m_params && m_doNConst && m_modp && operandConst(nodep->rhsp()) && !VN_AS(nodep->rhsp(), Const)->num().isFourState() && varrefp // Don't do messes with BITREFs/ARRAYREFs + && !varrefp->varp()->hasStrengthAssignment() // Strengths are resolved in V3Tristate && !varrefp->varp()->valuep() // Not already constified && !varrefp->varScopep()) { // Not scoped (or each scope may have different initial // value) diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 0e8f4ed65..a05407d37 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -37,6 +37,7 @@ private: // STATE bool m_setContinuously = false; // Set that var has some continuous assignment + bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified. VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments AstNodeFTask* m_ftaskp = nullptr; // Function or task we're inside @@ -51,6 +52,9 @@ private: if (nodep->varp()) { if (nodep->access().isWriteOrRW() && m_setContinuously) { nodep->varp()->isContinuously(true); + // Strength may only be specified in continuous assignment, + // so it is needed to check only if m_setContinuously is true + if (m_setStrengthSpecified) nodep->varp()->hasStrengthAssignment(true); } if (nodep->access().isWriteOrRW() && !m_ftaskp && nodep->varp()->isReadOnly()) { nodep->v3warn(ASSIGNIN, @@ -78,9 +82,13 @@ private: { m_setRefLvalue = VAccess::WRITE; m_setContinuously = VN_IS(nodep, AssignW) || VN_IS(nodep, AssignAlias); + if (AstAssignW* assignwp = VN_CAST(nodep, AssignW)) { + if (assignwp->strengthSpecp()) m_setStrengthSpecified = true; + } iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = VAccess::NOCHANGE; m_setContinuously = false; + m_setStrengthSpecified = false; iterateAndNextNull(nodep->rhsp()); } } diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 8e95d13c8..66670338e 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -84,9 +84,13 @@ AstArg* V3ParseGrammar::argWrapList(AstNode* nodep) { } AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, const string& name, int value) { - return new AstAssignW( - fileline, new AstVarRef(fileline, name, VAccess::WRITE), - new AstConst(fileline, AstConst::StringToParse(), (value ? "'1" : "'0"))); + AstAssignW* assignp + = new AstAssignW{fileline, new AstVarRef{fileline, name, VAccess::WRITE}, + new AstConst{fileline, AstConst::StringToParse{}, (value ? "'1" : "'0")}}; + AstStrengthSpec* strengthSpecp + = new AstStrengthSpec{fileline, VStrength::SUPPLY, VStrength::SUPPLY}; + assignp->strengthSpecp(strengthSpecp); + return assignp; } AstRange* V3ParseGrammar::scrubRange(AstNodeRange* nrangep) { diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 924a5062b..8a1481323 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -398,8 +398,7 @@ void V3ParseImp::tokenPipeline() { const int nexttok = nexttokp->token; yylval = curValue; // Now potentially munge the current token - if (token == '(' - && (nexttok == ygenSTRENGTH || nexttok == ySUPPLY0 || nexttok == ySUPPLY1)) { + if (token == '(' && isStrengthToken(nexttok)) { token = yP_PAR__STRENGTH; } else if (token == ':') { if (nexttok == yBEGIN) { @@ -483,6 +482,12 @@ void V3ParseImp::tokenPipeline() { // effectively returns yylval } +bool V3ParseImp::isStrengthToken(int tok) { + return tok == ygenSTRENGTH || tok == ySUPPLY0 || tok == ySUPPLY1 || tok == ySTRONG0 + || tok == ySTRONG1 || tok == yPULL0 || tok == yPULL1 || tok == yWEAK0 || tok == yWEAK1 + || tok == yHIGHZ0 || tok == yHIGHZ1; +} + void V3ParseImp::tokenPipelineSym() { // If an id, change the type based on symbol table // Note above sometimes converts yGLOBAL to a yaID__LEX diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index c5cf4bd36..54a241365 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -121,6 +121,7 @@ struct V3ParseBisonYYSType { V3ErrorCode::en errcodeen; VAttrType::en attrtypeen; VLifetime::en lifetime; + VStrength::en strength; #include "V3Ast__gen_yystype.h" }; @@ -216,6 +217,7 @@ public: } int lexKwdLastState() const { return m_lexKwdLast; } static const char* tokenName(int tok); + static bool isStrengthToken(int tok); void ppPushText(const string& text) { m_ppBuffers.push_back(text); diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index b5e983978..733d4ad74 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -55,6 +55,33 @@ // duplicating vars and logic that is common between each instance of a // module. // +// +// Another thing done in this phase is signal strength handling. +// Currently they are only supported in assignments and only in case when the strongest assignment +// has constant with all bits equal on the RHS. It is the case when they can be statically +// resolved. +// +// Static resolution is done in the following way: +// - The assignment of value 0 (size may be greater than 1), that has greatest strength (the +// one corresponding to 0) of all other assignments of 0, has to be found. +// - The same is done for value '1 and strength corresponding to value 1. +// - The greater of these two strengths is chosen. If they are equal the one that corresponds +// to 1 is taken as the greatest. +// - All assignments, that have strengths weaker or equal to the one that was found before, are +// removed. They are the assignments with constants on the RHS and also all assignments that have +// both strengths non-greater that the one was found, because they are weaker no matter what is on +// RHS. +// +// All assignments that are stronger than the one with strongest constant are left as they are. +// +// There is a possible problem with equally strong assignments, because multiple assignments with +// the same strength, but different values should result in x value, but these values are +// unsupported. +// +// Singal strength can also be used in simple logic gates parsed as assignments (see verilog.y), +// but these gates are then either removed (if they are weaker than the strongest constant) or +// handled as the gates witout signal strengths are handled now. In other words, gate with greater +// strength won't properly overwrite weaker driver. //************************************************************************* #include "config_build.h" @@ -340,6 +367,8 @@ class TristateVisitor final : public TristateBaseVisitor { // TYPES using RefVec = std::vector; using VarMap = std::unordered_map; + using Assigns = std::vector; + using VarToAssignsMap = std::map; enum : uint8_t { U2_GRAPHING = 1, // bit[0] if did m_graphing visit U2_NONGRAPH = 2, // bit[1] if did !m_graphing visit @@ -352,6 +381,7 @@ class TristateVisitor final : public TristateBaseVisitor { AstNodeModule* m_modp = nullptr; // Current module AstCell* m_cellp = nullptr; // current cell VarMap m_lhsmap; // Tristate left-hand-side driver map + VarToAssignsMap m_assigns; // Assigns in current module int m_unique = 0; bool m_alhs = false; // On LHS of assignment const AstNode* m_logicp = nullptr; // Current logic being built @@ -636,6 +666,117 @@ class TristateVisitor final : public TristateBaseVisitor { nodep->addStmtp(assp); } + void addToAssignmentList(AstAssignW* nodep) { + if (AstVarRef* const varRefp = VN_CAST(nodep->lhsp(), VarRef)) { + if (varRefp->varp()->isNet()) { + m_assigns[varRefp->varp()].push_back(nodep); + } else if (nodep->strengthSpecp()) { + if (!varRefp->varp()->isNet()) + nodep->v3warn(E_UNSUPPORTED, "Unsupported: Signal strengths are unsupported " + "on the following variable type: " + << varRefp->varp()->varType()); + + nodep->strengthSpecp()->unlinkFrBack()->deleteTree(); + } + } else if (nodep->strengthSpecp()) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: Assignments with signal strength with LHS of type: " + << nodep->lhsp()->prettyTypeName()); + } + } + + uint8_t getStrength(AstAssignW* const nodep, bool value) { + if (AstStrengthSpec* const strengthSpec = nodep->strengthSpecp()) { + return value ? strengthSpec->strength1() : strengthSpec->strength0(); + } + return VStrength::STRONG; // default strength is strong + } + + bool assignmentOfValueOnAllBits(AstAssignW* const nodep, bool value) { + if (AstConst* const constp = VN_CAST(nodep->rhsp(), Const)) { + const V3Number num = constp->num(); + return value ? num.isEqAllOnes() : num.isEqZero(); + } + return false; + } + + AstAssignW* getStrongestAssignmentOfValue(const Assigns& assigns, bool value) { + auto maxIt = std::max_element( + assigns.begin(), assigns.end(), [&](AstAssignW* ap, AstAssignW* bp) { + bool valuesOnRhsA = assignmentOfValueOnAllBits(ap, value); + bool valuesOnRhsB = assignmentOfValueOnAllBits(bp, value); + if (!valuesOnRhsA) return valuesOnRhsB; + if (!valuesOnRhsB) return false; + return getStrength(ap, value) < getStrength(bp, value); + }); + // If not all assignments have const with all bits equal to value on the RHS, + // std::max_element will return one of them anyway, so it has to be checked before + // returning + return assignmentOfValueOnAllBits(*maxIt, value) ? *maxIt : nullptr; + } + + void removeWeakerAssignments(Assigns& assigns) { + // Weaker assignments are these assignments that can't change the final value of the net. + // If the value of the RHS is known, only strength corresponding to its value is taken into + // account. Assignments of constants that have bits both 0 and 1 are skipped here, because + // it would involve handling parts of bits separately. + + // First, the strongest assignment, that has value on the RHS consisting of only 1 or only + // 0, has to be found. + AstAssignW* const strongest0p = getStrongestAssignmentOfValue(assigns, 0); + AstAssignW* const strongest1p = getStrongestAssignmentOfValue(assigns, 1); + AstAssignW* strongestp = nullptr; + uint8_t greatestKnownStrength = 0; + const auto getIfStrongest = [&](AstAssignW* const strongestCandidatep, bool value) { + if (!strongestCandidatep) return; + uint8_t strength = getStrength(strongestCandidatep, value); + if (strength >= greatestKnownStrength) { + greatestKnownStrength = strength; + strongestp = strongestCandidatep; + } + }; + getIfStrongest(strongest0p, 0); + getIfStrongest(strongest1p, 1); + + if (strongestp) { + // Then all weaker assignments can be safely removed. + // Assignments of the same strength are also removed, because duplicates aren't needed. + // One problem is with 2 assignments of different values and equal strengths. It should + // result in assignment of x value, but these values aren't supported now. + auto removedIt + = std::remove_if(assigns.begin(), assigns.end(), [&](AstAssignW* assignp) { + if (assignp == strongestp) return false; + const uint8_t strength0 = getStrength(assignp, 0); + const uint8_t strength1 = getStrength(assignp, 1); + const bool toRemove = (strength0 <= greatestKnownStrength + && strength1 <= greatestKnownStrength) + || (strength0 <= greatestKnownStrength + && assignmentOfValueOnAllBits(assignp, 0)) + || (strength1 <= greatestKnownStrength + && assignmentOfValueOnAllBits(assignp, 1)); + if (toRemove) { + // Don't propagate tristate if its assignment is removed. + TristateVertex* const vertexp + = reinterpret_cast(assignp->rhsp()->user5p()); + if (vertexp) vertexp->isTristate(false); + VL_DO_DANGLING(pushDeletep(assignp->unlinkFrBack()), assignp); + return true; + } + return false; + }); + assigns.erase(removedIt, assigns.end()); + } + } + + void resolveMultipleNetAssignments() { + for (auto& varpAssigns : m_assigns) { + if (varpAssigns.second.size() > 1) { + // first the static resolution is tried + removeWeakerAssignments(varpAssigns.second); + } + } + } + // VISITORS virtual void visit(AstConst* nodep) override { UINFO(9, dbgState() << nodep << endl); @@ -889,6 +1030,8 @@ class TristateVisitor final : public TristateBaseVisitor { void visitAssign(AstNodeAssign* nodep) { if (m_graphing) { + if (AstAssignW* assignWp = VN_CAST(nodep, AssignW)) addToAssignmentList(assignWp); + if (nodep->user2() & U2_GRAPHING) return; VL_RESTORER(m_logicp); m_logicp = nodep; @@ -1373,6 +1516,7 @@ class TristateVisitor final : public TristateBaseVisitor { VL_RESTORER(m_graphing); VL_RESTORER(m_unique); VL_RESTORER(m_lhsmap); + VL_RESTORER(m_assigns); // Not preserved, needs pointer instead: TristateGraph origTgraph = m_tgraph; UASSERT_OBJ(m_tgraph.empty(), nodep, "Unsupported: NodeModule under NodeModule"); { @@ -1382,6 +1526,7 @@ class TristateVisitor final : public TristateBaseVisitor { m_unique = 0; m_logicp = nullptr; m_lhsmap.clear(); + m_assigns.clear(); m_modp = nodep; // Walk the graph, finding all variables and tristate constructs { @@ -1389,6 +1534,8 @@ class TristateVisitor final : public TristateBaseVisitor { iterateChildren(nodep); m_graphing = false; } + // resolve multiple net assignments and signal strengths + resolveMultipleNetAssignments(); // Use graph to find tristate signals m_tgraph.graphWalk(nodep); // Build the LHS drivers map for this module diff --git a/src/verilog.l b/src/verilog.l index c3eb40f4c..a3cc59ef6 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -325,8 +325,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "forever" { FL; return yFOREVER; } "fork" { FL; return yFORK; } "function" { FL; return yFUNCTION; } - "highz0" { FL; return ygenSTRENGTH; } - "highz1" { FL; return ygenSTRENGTH; } + "highz0" { FL; return yHIGHZ0; } + "highz1" { FL; return yHIGHZ1; } "if" { FL; return yIF; } "initial" { FL; return yINITIAL; } "inout" { FL; return yINOUT; } @@ -350,8 +350,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "pmos" { FL; return yPMOS; } "posedge" { FL; return yPOSEDGE; } "primitive" { FL; return yPRIMITIVE; } - "pull0" { FL; return ygenSTRENGTH; } - "pull1" { FL; return ygenSTRENGTH; } + "pull0" { FL; return yPULL0; } + "pull1" { FL; return yPULL1; } "pulldown" { FL; return yPULLDOWN; } "pullup" { FL; return yPULLUP; } "rcmos" { FL; return yRCMOS; } @@ -369,8 +369,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "small" { FL; return ygenSTRENGTH; } "specify" { FL; return ySPECIFY; } "specparam" { FL; return ySPECPARAM; } - "strong0" { FL; return ygenSTRENGTH; } - "strong1" { FL; return ygenSTRENGTH; } + "strong0" { FL; return ySTRONG0; } + "strong1" { FL; return ySTRONG1; } "supply0" { FL; return ySUPPLY0; } "supply1" { FL; return ySUPPLY1; } "table" { FL; yy_push_state(TABLE); return yTABLE; } @@ -388,8 +388,8 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "vectored" { FL; return yVECTORED; } "wait" { FL; return yWAIT; } "wand" { FL; return yWAND; } - "weak0" { FL; return ygenSTRENGTH; } - "weak1" { FL; return ygenSTRENGTH; } + "weak0" { FL; return yWEAK0; } + "weak1" { FL; return yWEAK1; } "while" { FL; return yWHILE; } "wire" { FL; return yWIRE; } "wor" { FL; return yWOR; } diff --git a/src/verilog.y b/src/verilog.y index 3d77c680b..161fe8f67 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -40,6 +40,13 @@ #define BBUNSUP(fl, msg) (fl)->v3warn(E_UNSUPPORTED, msg) #define GATEUNSUP(fl, tok) \ { BBUNSUP((fl), "Unsupported: Verilog 1995 gate primitive: " << (tok)); } +#define STRENGTHUNSUP(nodep) \ + { \ + if (nodep) { \ + BBUNSUP((nodep->fileline()), "Unsupported: Strength specifier on this gate type"); \ + nodep->deleteTree(); \ + } \ + } #define PRIMDLYUNSUP(nodep) \ { \ if (nodep) { \ @@ -68,6 +75,7 @@ public: AstNodeDType* m_varDTypep = nullptr; // Pointer to data type for next signal declaration AstNodeDType* m_memDTypep = nullptr; // Pointer to data type for next member declaration AstNode* m_netDelayp = nullptr; // Pointer to delay for next signal declaration + AstStrengthSpec* m_netStrengthp = nullptr; // Pointer to strength for next net declaration AstNodeModule* m_modp = nullptr; // Last module for timeunits bool m_pinAnsi = false; // In ANSI port list FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations @@ -172,6 +180,7 @@ public: m_varDTypep = dtypep; } void setNetDelay(AstNode* netDelayp) { m_netDelayp = netDelayp; } + void setNetStrength(AstStrengthSpec* netStrengthp) { m_netStrengthp = netStrengthp; } void pinPush() { m_pinStack.push(m_pinNum); m_pinNum = 1; @@ -291,6 +300,15 @@ int V3ParseGrammar::s_modTypeImpNum = 0; if (nodep) nodep->deleteTree(); \ } +#define APPLY_STRENGTH_TO_LIST(beginp, strengthSpecNodep, typeToCast) \ + { \ + if (AstStrengthSpec* specp = VN_CAST(strengthSpecNodep, StrengthSpec)) \ + for (auto* nodep = beginp; nodep; nodep = nodep->nextp()) { \ + auto* const assignp = VN_AS(nodep, typeToCast); \ + assignp->strengthSpecp(nodep == beginp ? specp : specp->cloneTree(false)); \ + } \ + } + static void ERRSVKWD(FileLine* fileline, const string& tokname) { static int toldonce = 0; fileline->v3error( @@ -544,6 +562,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yGLOBAL__CLOCKING "global-then-clocking" %token yGLOBAL__ETC "global" %token yGLOBAL__LEX "global-in-lex" +%token yHIGHZ0 "highz0" +%token yHIGHZ1 "highz1" %token yIF "if" %token yIFF "iff" //UNSUP %token yIGNORE_BINS "ignore_bins" @@ -598,6 +618,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yPROGRAM "program" %token yPROPERTY "property" %token yPROTECTED "protected" +%token yPULL0 "pull0" +%token yPULL1 "pull1" %token yPULLDOWN "pulldown" %token yPULLUP "pullup" %token yPURE "pure" @@ -635,6 +657,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token ySTATIC__LEX "static-in-lex" %token ySTRING "string" //UNSUP %token ySTRONG "strong" +%token ySTRONG0 "strong0" +%token ySTRONG1 "strong1" %token ySTRUCT "struct" %token ySUPER "super" %token ySUPPLY0 "supply0" @@ -688,6 +712,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) //UNSUP %token yWAIT_ORDER "wait_order" %token yWAND "wand" //UNSUP %token yWEAK "weak" +%token yWEAK0 "weak0" +%token yWEAK1 "weak1" %token yWHILE "while" //UNSUP %token yWILDCARD "wildcard" %token yWIRE "wire" @@ -1718,11 +1744,18 @@ parameter_port_declarationTypeFrontE: // IEEE: parameter_port_declaration w/o as ; net_declaration: // IEEE: net_declaration - excluding implict - net_declarationFront netSigList ';' { $$ = $2; } + net_declarationFront netSigList ';' + { $$ = $2; + if (GRAMMARP->m_netStrengthp) { + VL_DO_CLEAR(delete GRAMMARP->m_netStrengthp, GRAMMARP->m_netStrengthp = nullptr); + }} ; net_declarationFront: // IEEE: beginning of net_declaration - net_declRESET net_type strengthSpecE net_scalaredE net_dataTypeE { VARDTYPE_NDECL($5); } + net_declRESET net_type driveStrengthE net_scalaredE net_dataTypeE + { VARDTYPE_NDECL($5); + GRAMMARP->setNetStrength(VN_CAST($3, StrengthSpec)); + } //UNSUP net_declRESET yINTERCONNECT signingE rangeListE { VARNET($2); VARDTYPE(x); } ; @@ -2425,9 +2458,10 @@ module_common_item: // ==IEEE: module_common_item ; continuous_assign: // IEEE: continuous_assign - yASSIGN strengthSpecE delayE assignList ';' + yASSIGN driveStrengthE delayE assignList ';' { $$ = $4; + APPLY_STRENGTH_TO_LIST($$, $2, AssignW); if ($3) for (auto* nodep = $$; nodep; nodep = nodep->nextp()) { auto* const assignp = VN_AS(nodep, NodeAssign); @@ -2726,6 +2760,7 @@ netSig: // IEEE: net_decl_assignment - one element from | netId sigAttrListE '=' expr { $$ = VARDONEA($1, *$1, nullptr, $2); auto* const assignp = new AstAssignW{$3, new AstVarRef{$1, *$1, VAccess::WRITE}, $4}; + if (GRAMMARP->m_netStrengthp) assignp->strengthSpecp(GRAMMARP->m_netStrengthp->cloneTree(false)); if ($$->delayp()) assignp->addTimingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3 $$->addNext(assignp); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } @@ -4718,18 +4753,30 @@ stream_expressionOrDataType: // IEEE: from streaming_concatenation // Gate declarations gateDecl: - yBUF delayE gateBufList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yBUFIF0 delayE gateBufif0List ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yBUFIF1 delayE gateBufif1List ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yNOT delayE gateNotList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yNOTIF0 delayE gateNotif0List ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yNOTIF1 delayE gateNotif1List ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yAND delayE gateAndList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yNAND delayE gateNandList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yOR delayE gateOrList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yNOR delayE gateNorList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yXOR delayE gateXorList ';' { $$ = $3; PRIMDLYUNSUP($2); } - | yXNOR delayE gateXnorList ';' { $$ = $3; PRIMDLYUNSUP($2); } + yBUF driveStrengthE delayE gateBufList ';' + { $$ = $4; STRENGTHUNSUP($2); PRIMDLYUNSUP($3); } + | yBUFIF0 driveStrengthE delayE gateBufif0List ';' + { $$ = $4; STRENGTHUNSUP($2); PRIMDLYUNSUP($3); } + | yBUFIF1 driveStrengthE delayE gateBufif1List ';' + { $$ = $4; STRENGTHUNSUP($2); PRIMDLYUNSUP($3); } + | yNOT driveStrengthE delayE gateNotList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } + | yNOTIF0 driveStrengthE delayE gateNotif0List ';' + { $$ = $4; STRENGTHUNSUP($2); PRIMDLYUNSUP($3); } + | yNOTIF1 driveStrengthE delayE gateNotif1List ';' + { $$ = $4; STRENGTHUNSUP($2); PRIMDLYUNSUP($3); } + | yAND driveStrengthE delayE gateAndList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } + | yNAND driveStrengthE delayE gateNandList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } + | yOR driveStrengthE delayE gateOrList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } + | yNOR driveStrengthE delayE gateNorList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } + | yXOR driveStrengthE delayE gateXorList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } + | yXNOR driveStrengthE delayE gateXnorList ';' + { $$ = $4; APPLY_STRENGTH_TO_LIST($$, $2, AssignW); PRIMDLYUNSUP($3); } | yPULLUP delayE gatePullupList ';' { $$ = $3; PRIMDLYUNSUP($2); } | yPULLDOWN delayE gatePulldownList ';' { $$ = $3; PRIMDLYUNSUP($2); } | yNMOS delayE gateBufif1List ';' { $$ = $3; PRIMDLYUNSUP($2); } // ~=bufif1, as don't have strengths yet @@ -4901,21 +4948,33 @@ gatePinExpr: expr { $$ = GRAMMARP->createGatePin($1); } ; -// This list is also hardcoded in VParseLex.l -strength: // IEEE: strength0+strength1 - plus HIGHZ/SMALL/MEDIUM/LARGE - ygenSTRENGTH { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); } - | ySUPPLY0 { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); } - | ySUPPLY1 { BBUNSUP($1, "Unsupported: Verilog 1995 strength specifiers"); } +strength0: + ySUPPLY0 { $$ = VStrength::SUPPLY; } + | ySTRONG0 { $$ = VStrength::STRONG; } + | yPULL0 { $$ = VStrength::PULL; } + | yWEAK0 { $$ = VStrength::WEAK; } ; -strengthSpecE: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty - /* empty */ { } - | strengthSpec { } +strength1: + ySUPPLY1 { $$ = VStrength::SUPPLY; } + | ySTRONG1 { $$ = VStrength::STRONG; } + | yPULL1 { $$ = VStrength::PULL; } + | yWEAK1 { $$ = VStrength::WEAK; } ; -strengthSpec: // IEEE: drive_strength + pullup_strength + pulldown_strength + charge_strength - plus empty - yP_PAR__STRENGTH strength ')' { } - | yP_PAR__STRENGTH strength ',' strength ')' { } +driveStrengthE: + /* empty */ { $$ = nullptr; } + | driveStrength { $$ = $1; } + ; + + +driveStrength: + yP_PAR__STRENGTH strength0 ',' strength1 ')' { $$ = new AstStrengthSpec{$1, $2, $4}; } + | yP_PAR__STRENGTH strength1 ',' strength0 ')' { $$ = new AstStrengthSpec{$1, $4, $2}; } + | yP_PAR__STRENGTH strength0 ',' yHIGHZ1 ')' { BBUNSUP($4, "Unsupported: highz strength"); } + | yP_PAR__STRENGTH strength1 ',' yHIGHZ0 ')' { BBUNSUP($4, "Unsupported: highz strength"); } + | yP_PAR__STRENGTH yHIGHZ0 ',' strength1 ')' { BBUNSUP($2, "Unsupported: highz strength"); } + | yP_PAR__STRENGTH yHIGHZ1 ',' strength0 ')' { BBUNSUP($2, "Unsupported: highz strength"); } ; //************************************************ diff --git a/test_regress/t/t_strength_assignments.pl b/test_regress/t/t_strength_assignments.pl new file mode 100755 index 000000000..f5e338520 --- /dev/null +++ b/test_regress/t/t_strength_assignments.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_assignments.v b/test_regress/t/t_strength_assignments.v new file mode 100644 index 000000000..8344adbdd --- /dev/null +++ b/test_regress/t/t_strength_assignments.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + wire a; + assign (weak0, weak1) a = 1; + assign (weak0, supply1) a = 1; + assign (strong0, strong1) a = 0; + + wire (weak0, weak1) b = 1; + assign (strong0, strong1) b = 0; + + wire [1:0] c; + assign (weak0, supply1) c = '1; + assign (supply0, pull1) c = '1; + assign (strong0, strong1) c = '0; + + supply0 d; + assign (strong0, strong1) d = 1; + + wire (supply0, supply1) e = 'z; + assign (weak0, weak1) e = 1; + + always begin + if (a && !b && c === '1 && !d && e) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else begin + $write("Error: a = %b, b = %b, c = %b, d = %b, e = %b ", a, b, c, d, e); + $write("expected: a = 1, b = 0, c = 11, d = 0, e = 1\n"); + $stop; + end + end +endmodule diff --git a/test_regress/t/t_strength_bufif1.out b/test_regress/t/t_strength_bufif1.out new file mode 100644 index 000000000..0ac300369 --- /dev/null +++ b/test_regress/t/t_strength_bufif1.out @@ -0,0 +1,5 @@ +%Error-UNSUPPORTED: t/t_strength_bufif1.v:9:11: Unsupported: Strength specifier on this gate type + 9 | bufif1 (strong0, strong1) (a, 1'b1, 1'b1); + | ^ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_strength_bufif1.pl b/test_regress/t/t_strength_bufif1.pl new file mode 100755 index 000000000..35c0dfe5b --- /dev/null +++ b/test_regress/t/t_strength_bufif1.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_bufif1.v b/test_regress/t/t_strength_bufif1.v new file mode 100644 index 000000000..0a78b107c --- /dev/null +++ b/test_regress/t/t_strength_bufif1.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + wire a; + bufif1 (strong0, strong1) (a, 1'b1, 1'b1); + + always begin + if (a) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_strength_highz.out b/test_regress/t/t_strength_highz.out new file mode 100644 index 000000000..06f32f6e9 --- /dev/null +++ b/test_regress/t/t_strength_highz.out @@ -0,0 +1,14 @@ +%Error-UNSUPPORTED: t/t_strength_highz.v:8:17: Unsupported: highz strength + 8 | wire (weak0, highz1) a = 1; + | ^~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_strength_highz.v:9:19: Unsupported: highz strength + 9 | wire (strong1, highz0) b = 0; + | ^~~~~~ +%Error-UNSUPPORTED: t/t_strength_highz.v:10:10: Unsupported: highz strength + 10 | wire (highz0, pull1) c = 0; + | ^~~~~~ +%Error-UNSUPPORTED: t/t_strength_highz.v:11:10: Unsupported: highz strength + 11 | wire (highz1, supply0) d = 1; + | ^~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_strength_highz.pl b/test_regress/t/t_strength_highz.pl new file mode 100755 index 000000000..48bf31461 --- /dev/null +++ b/test_regress/t/t_strength_highz.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_highz.v b/test_regress/t/t_strength_highz.v new file mode 100644 index 000000000..340723aba --- /dev/null +++ b/test_regress/t/t_strength_highz.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + wire (weak0, highz1) a = 1; + wire (strong1, highz0) b = 0; + wire (highz0, pull1) c = 0; + wire (highz1, supply0) d = 1; + + always begin + if (a === 1'bz && b === 1'bz && c === 1'bz && d === 1'bz) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_strength_strong1_strong1_bad.out b/test_regress/t/t_strength_strong1_strong1_bad.out new file mode 100644 index 000000000..b1e299714 --- /dev/null +++ b/test_regress/t/t_strength_strong1_strong1_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_strength_strong1_strong1_bad.v:8:19: syntax error, unexpected strong1 + 8 | wire (strong1, strong1) a = 1; + | ^~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_strength_strong1_strong1_bad.pl b/test_regress/t/t_strength_strong1_strong1_bad.pl new file mode 100755 index 000000000..19ba90d40 --- /dev/null +++ b/test_regress/t/t_strength_strong1_strong1_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_strong1_strong1_bad.v b/test_regress/t/t_strength_strong1_strong1_bad.v new file mode 100644 index 000000000..ab84216cc --- /dev/null +++ b/test_regress/t/t_strength_strong1_strong1_bad.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + wire (strong1, strong1) a = 1; + initial begin + $stop; + end + +endmodule diff --git a/test_regress/t/t_weak_nor_strong_assign.pl b/test_regress/t/t_weak_nor_strong_assign.pl new file mode 100755 index 000000000..f5e338520 --- /dev/null +++ b/test_regress/t/t_weak_nor_strong_assign.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_weak_nor_strong_assign.v b/test_regress/t/t_weak_nor_strong_assign.v new file mode 100644 index 000000000..a3811ca71 --- /dev/null +++ b/test_regress/t/t_weak_nor_strong_assign.v @@ -0,0 +1,18 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + wire a; + nor (pull0, weak1) n1(a, 0, 0); + assign (strong0, weak1) a = 0; + + always begin + if (!a) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule From 7aa01625d833461abc45c1c9a9c6da6a88cb80d5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 14 Sep 2022 08:15:42 -0400 Subject: [PATCH 29/75] Commentary: Changes update --- Changes | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index 202e279c2..e2a1c13a8 100644 --- a/Changes +++ b/Changes @@ -13,7 +13,11 @@ Verilator 4.227 devel **Minor:** +* Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro] +* Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic] * Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] +* Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk] +* Fix default --mod-prefix when --prefix is repeated (#3603). [Geza Lore] * Fix typedef'ed class conversion to boolean (#3616). [Aleksander Kiryk] @@ -34,7 +38,7 @@ Verilator 4.226 2022-08-31 * Fix incorrect tristate logic (#3399) [shareefj, Vighnesh Iyer] * Fix incorrect bit op tree optimization (#3470). [algrobman] * Fix bisonpre for MSYS2 (#3471). -* Fix max memory usage (#3483). [Kamil Rakoczy] +* Fix max memory usage (#3483). [Kamil Rakoczy/Antmicro] * Fix empty string arguments to display (#3484). [Grulfen] * Fix table misoptimizing away display (#3488). [Stefan Post] * Fix unique_ptr memory header for MinGW64 (#3493). @@ -45,7 +49,7 @@ Verilator 4.226 2022-08-31 * Fix segfault exporting non-existant package (#3535). * Fix void-cast queue pop_front or pop_back (#3542) (#3364). [Drew Ranck] * Fix case statement comparing string literal (#3544). [Gustav Svensk] -* Fix === with some tristate constants (#3551). [Ryszard Rozak] +* Fix === with some tristate constants (#3551). [Ryszard Rozak/Antmicro] * Fix converting subclasses to string (#3552). [Arkadiusz Kozdra/Antmicro] * Fix --hierarchical with order-based pin connections (#3583) (#3585). [Kelin9298] From 9efd64ab9804258f4c34b4ddafc7438ad5f5fe89 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 14 Sep 2022 20:13:28 -0400 Subject: [PATCH 30/75] Commentary --- Changes | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changes b/Changes index e2a1c13a8..5502f48a7 100644 --- a/Changes +++ b/Changes @@ -11,6 +11,12 @@ contributors that suggested a given feature are shown in []. Thanks! Verilator 4.227 devel ========================== +**Announcement:** + +* The next release is anticipated primere Verilator Version 5. Please + consider beta-testing the github 'develop-v5' branch, which will soon + merge into the github 'master' branch (#3383). + **Minor:** * Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro] From 75fd71d7e5523a2eb8f841618981743c74a39563 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 14 Sep 2022 20:18:40 -0400 Subject: [PATCH 31/75] Add --main to generate main() C++ (previously was experimental only) (#3265). --- Changes | 1 + bin/verilator | 1 + docs/guide/exe_verilator.rst | 9 +++++++++ src/V3Options.cpp | 17 ++++++++++------- src/V3Options.h | 3 ++- test_regress/t/t_flag_main.pl | 3 +++ 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Changes b/Changes index 5502f48a7..d0f057a5e 100644 --- a/Changes +++ b/Changes @@ -20,6 +20,7 @@ Verilator 4.227 devel **Minor:** * Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro] +* Add --main to generate main() C++ (previously was experimental only). * Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic] * Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] * Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk] diff --git a/bin/verilator b/bin/verilator index 62f7be232..74c5b49c6 100755 --- a/bin/verilator +++ b/bin/verilator @@ -343,6 +343,7 @@ detailed descriptions of these arguments. --lint-only Lint, but do not make output --make Generate scripts for specified build tool -MAKEFLAGS Arguments to pass to make during --build + --main Generate C++ main() --max-num-width Maximum number width (default: 64K) --Mdir Name of output object directory --MMD Create .d dependency files diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 0348c4db2..8d2ccda86 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -709,6 +709,15 @@ Summary: (e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be required for simple builds using the host toolchain. +.. option:: --main + + Generates a top-level C++ main() file that supports parsing arguments, + but does not drive any inputs. This is sufficient to use for top-level + SystemVerilog designs that has no inputs, and does not need the C++ to + do any time advancement. + + Implies :vlopt:`--cc` if no other output mode was provided. + .. option:: --max-num-width Set the maximum number literal width (e.g. in 1024'd22 this it the diff --git a/src/V3Options.cpp b/src/V3Options.cpp index e1f194e8b..474cc3e57 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -435,6 +435,11 @@ string V3Options::allArgsStringForHierBlock(bool forTop) const { return out; } +void V3Options::ccSet() { // --cc + m_outFormatOk = true; + m_systemC = false; +} + //###################################################################### // File searching @@ -719,9 +724,10 @@ bool V3Options::systemCFound() { // V3 Options notification methods void V3Options::notify() { - FileLine* const cmdfl = new FileLine(FileLine::commandLineFilename()); - // Notify that all arguments have been passed and final modification can be made. + FileLine* const cmdfl = new FileLine{FileLine::commandLineFilename()}; + + if (!outFormatOk() && v3Global.opt.main()) ccSet(); // --main implies --cc if not provided if (!outFormatOk() && !cdc() && !dpiHdrOnly() && !lintOnly() && !preprocOnly() && !xmlOnly()) { v3fatal("verilator: Need --cc, --sc, --cdc, --dpi-hdr-only, --lint-only, " "--xml-only or --E option"); @@ -1002,10 +1008,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-build", Set, &m_build); DECL_OPTION("-CFLAGS", CbVal, callStrSetter(&V3Options::addCFlags)); - DECL_OPTION("-cc", CbCall, [this]() { - m_outFormatOk = true; - m_systemC = false; - }); + DECL_OPTION("-cc", CbCall, [this]() { ccSet(); }); DECL_OPTION("-cdc", OnOff, &m_cdc); DECL_OPTION("-clk", CbVal, callStrSetter(&V3Options::addClocker)); DECL_OPTION("-no-clk", CbVal, callStrSetter(&V3Options::addNoClocker)); @@ -1175,7 +1178,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char m_makeDir = valp; addIncDirFallback(m_makeDir); // Need to find generated files there too }); - DECL_OPTION("-main", OnOff, &m_main).undocumented(); // Future + DECL_OPTION("-main", OnOff, &m_main); DECL_OPTION("-make", CbVal, [this, fl](const char* valp) { if (!strcmp(valp, "cmake")) { m_cmake = true; diff --git a/src/V3Options.h b/src/V3Options.h index 8637277bb..190d4c7ab 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -410,8 +410,9 @@ public: void addNoClocker(const string& signame); void addVFile(const string& filename); void addForceInc(const string& filename); - void notify(); bool available() const { return m_available; } + void ccSet(); + void notify(); // ACCESSORS (options) bool preprocOnly() const { return m_preprocOnly; } diff --git a/test_regress/t/t_flag_main.pl b/test_regress/t/t_flag_main.pl index 381004460..57041562f 100755 --- a/test_regress/t/t_flag_main.pl +++ b/test_regress/t/t_flag_main.pl @@ -11,6 +11,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( + verilator_flags => [# Custom as don't want -cc + "-Mdir $Self->{obj_dir}", + "--debug-check", ], verilator_flags2 => ['--exe --build --main'], verilator_make_cmake => 0, verilator_make_gmake => 0, From d85b90905456870a12dd6dc63a37c64347ec4456 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 14 Sep 2022 21:10:19 -0400 Subject: [PATCH 32/75] Internals: Use std:: for mem and str functions. --- examples/make_protect_lib/sim_main.cpp | 2 +- examples/make_tracing_sc/sc_main.cpp | 2 +- src/V3Ast.cpp | 8 ++--- src/V3Ast.h | 5 +-- src/V3Begin.cpp | 2 +- src/V3EmitCModel.cpp | 2 +- src/V3EmitCSyms.cpp | 2 +- src/V3File.cpp | 10 +++--- src/V3File.h | 4 +-- src/V3FileLine.cpp | 4 +-- src/V3LinkDot.cpp | 2 +- src/V3Number.cpp | 16 +++++----- src/V3OptionParser.cpp | 8 ++--- src/V3Options.cpp | 39 ++++++++++++------------ src/V3Os.cpp | 2 +- src/V3ParseImp.cpp | 10 +++--- src/V3PreLex.l | 4 +-- src/V3PreProc.cpp | 16 +++++----- src/V3String.cpp | 4 +-- src/V3Width.cpp | 2 +- src/verilog.l | 2 +- test_regress/driver.pl | 2 +- test_regress/t/TestCheck.h | 2 +- test_regress/t/TestSimulator.h | 6 ++-- test_regress/t/t_dpi_arg_inout_type.cpp | 16 +++++----- test_regress/t/t_dpi_arg_input_type.cpp | 8 ++--- test_regress/t/t_dpi_arg_output_type.cpp | 8 ++--- test_regress/t/t_dpi_export_c.cpp | 7 +++-- test_regress/t/t_dpi_result_type.cpp | 8 ++--- test_regress/t/t_dpi_string_c.cpp | 2 +- test_regress/t/t_dpi_var.cpp | 4 +-- test_regress/t/t_sc_names.cpp | 2 +- test_regress/t/t_scope_map.cpp | 2 +- test_regress/t/t_vpi_get.cpp | 2 +- test_regress/t/t_vpi_module.cpp | 6 ++-- test_regress/t/t_vpi_param.cpp | 2 +- test_regress/t/t_vpi_unimpl.cpp | 2 +- test_regress/t/t_vpi_var.cpp | 6 ++-- 38 files changed, 118 insertions(+), 113 deletions(-) diff --git a/examples/make_protect_lib/sim_main.cpp b/examples/make_protect_lib/sim_main.cpp index b3096b4c5..fefcb0c5a 100644 --- a/examples/make_protect_lib/sim_main.cpp +++ b/examples/make_protect_lib/sim_main.cpp @@ -32,7 +32,7 @@ int main(int argc, char** argv, char** env) { // When tracing, the contents of the secret module will not be seen VerilatedVcdC* tfp = nullptr; const char* flag = contextp->commandArgsPlusMatch("trace"); - if (flag && 0 == strcmp(flag, "+trace")) { + if (flag && 0 == std::strcmp(flag, "+trace")) { contextp->traceEverOn(true); VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n"); tfp = new VerilatedVcdC; diff --git a/examples/make_tracing_sc/sc_main.cpp b/examples/make_tracing_sc/sc_main.cpp index 93861ceea..3d3cb1392 100644 --- a/examples/make_tracing_sc/sc_main.cpp +++ b/examples/make_tracing_sc/sc_main.cpp @@ -89,7 +89,7 @@ int sc_main(int argc, char* argv[]) { // and if at run time passed the +trace argument, turn on tracing VerilatedVcdSc* tfp = nullptr; const char* flag = Verilated::commandArgsPlusMatch("trace"); - if (flag && 0 == strcmp(flag, "+trace")) { + if (flag && 0 == std::strcmp(flag, "+trace")) { cout << "Enabling waves into logs/vlt_dump.vcd...\n"; tfp = new VerilatedVcdSc; top->trace(tfp, 99); // Trace 99 levels of hierarchy diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 2f1467f03..7694e1e69 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -165,22 +165,22 @@ string AstNode::prettyName(const string& namein) { continue; } if (pos[0] == '_' && pos[1] == '_') { // Short-circuit - if (0 == strncmp(pos, "__BRA__", 7)) { + if (0 == std::strncmp(pos, "__BRA__", 7)) { pretty += "["; pos += 7; continue; } - if (0 == strncmp(pos, "__KET__", 7)) { + if (0 == std::strncmp(pos, "__KET__", 7)) { pretty += "]"; pos += 7; continue; } - if (0 == strncmp(pos, "__DOT__", 7)) { + if (0 == std::strncmp(pos, "__DOT__", 7)) { pretty += "."; pos += 7; continue; } - if (0 == strncmp(pos, "__PVT__", 7)) { + if (0 == std::strncmp(pos, "__PVT__", 7)) { pretty += ""; pos += 7; continue; diff --git a/src/V3Ast.h b/src/V3Ast.h index 6e455ef1c..bb945564c 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -467,8 +467,9 @@ public: return names[m_e]; } static void selfTest() { - UASSERT(0 == strcmp(VBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), "SelfTest: Enum mismatch"); - UASSERT(0 == strcmp(VBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), + UASSERT(0 == std::strcmp(VBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), + "SelfTest: Enum mismatch"); + UASSERT(0 == std::strcmp(VBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), "SelfTest: Enum mismatch"); } inline VBasicDTypeKwd() diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 0e4176739..6a40e1233 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -85,7 +85,7 @@ private: string::size_type pos; while ((pos = dottedname.find("__DOT__")) != string::npos) { const string ident = dottedname.substr(0, pos); - dottedname = dottedname.substr(pos + strlen("__DOT__")); + dottedname = dottedname.substr(pos + std::strlen("__DOT__")); if (nodep->name() != "") { m_displayScope = dot(m_displayScope, ident); m_namedScope = dot(m_namedScope, ident); diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp index 28687c19c..c8dc7b521 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -565,7 +565,7 @@ class EmitCModel final : public EmitCFunc { // Some hackery to locate handle__V for trace_init_task // Considered a pragma on the handle, but that still doesn't help us attach it here string handle = funcp->name(); - const size_t wr_len = strlen("__Vdpiimwrap_"); + const size_t wr_len = std::strlen("__Vdpiimwrap_"); UASSERT_OBJ(handle.substr(0, wr_len) == "__Vdpiimwrap_", funcp, "Strange trace_init_task function name"); handle = "vlSymsp->TOP." + handle.substr(wr_len); diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 5193bd7e6..2bff31190 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -211,7 +211,7 @@ class EmitCSyms final : EmitCBaseVisitor { const string::size_type dpos = whole.rfind("__DOT__"); if (dpos != string::npos) { scpName = whole.substr(0, dpos); - varBase = whole.substr(dpos + strlen("__DOT__")); + varBase = whole.substr(dpos + std::strlen("__DOT__")); } else { varBase = whole; } diff --git a/src/V3File.cpp b/src/V3File.cpp index 57452b969..c4adf58bc 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -94,7 +94,7 @@ class V3FileDependImp final { const string fn = filename(); const int err = stat(fn.c_str(), &m_stat); if (err != 0) { - memset(&m_stat, 0, sizeof(m_stat)); + std::memset(&m_stat, 0, sizeof(m_stat)); m_stat.st_mtime = 1; m_exists = false; // Not an error... This can occur due to `line directives in the .vpp files @@ -389,7 +389,7 @@ private: if (!m_pidExited && waitpid(m_pid, &m_pidStatus, hang ? 0 : WNOHANG)) { UINFO(1, "--pipe-filter: Exited, status " << m_pidStatus << " exit=" << WEXITSTATUS(m_pidStatus) << " err" - << strerror(errno) << endl); + << std::strerror(errno) << endl); m_readEof = true; m_pidExited = true; } @@ -495,7 +495,7 @@ private: constexpr int P_WR = 1; if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) { - v3fatal("--pipe-filter: Can't pipe: " << strerror(errno)); + v3fatal("--pipe-filter: Can't pipe: " << std::strerror(errno)); } if (fd_stdin[P_RD] <= 2 || fd_stdin[P_WR] <= 2 || fd_stdout[P_RD] <= 2 || fd_stdout[P_WR] <= 2) { @@ -507,7 +507,7 @@ private: UINFO(1, "--pipe-filter: /bin/sh -c " << command << endl); const pid_t pid = fork(); - if (pid < 0) v3fatal("--pipe-filter: fork failed: " << strerror(errno)); + if (pid < 0) v3fatal("--pipe-filter: fork failed: " << std::strerror(errno)); if (pid == 0) { // Child UINFO(6, "In child\n"); close(fd_stdin[P_WR]); @@ -518,7 +518,7 @@ private: execl("/bin/sh", "sh", "-c", command.c_str(), static_cast(nullptr)); // Don't use v3fatal, we don't share the common structures any more - fprintf(stderr, "--pipe-filter: exec failed: %s\n", strerror(errno)); + fprintf(stderr, "--pipe-filter: exec failed: %s\n", std::strerror(errno)); _exit(1); } else { // Parent UINFO(6, "In parent, child pid " << pid << " stdin " << fd_stdin[P_WR] << "->" diff --git a/src/V3File.h b/src/V3File.h index 309f136c9..95b29eb8d 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -224,7 +224,7 @@ private: std::size_t len = strlen(str); std::size_t availableBytes = WRITE_BUFFER_SIZE_BYTES - m_usedBytes; while (VL_UNLIKELY(len >= availableBytes)) { - memcpy(m_bufferp->data() + m_usedBytes, str, availableBytes); + std::memcpy(m_bufferp->data() + m_usedBytes, str, availableBytes); m_usedBytes = WRITE_BUFFER_SIZE_BYTES; writeBlock(); str += availableBytes; @@ -232,7 +232,7 @@ private: availableBytes = WRITE_BUFFER_SIZE_BYTES; } if (len > 0) { - memcpy(m_bufferp->data() + m_usedBytes, str, len); + std::memcpy(m_bufferp->data() + m_usedBytes, str, len); m_usedBytes += len; } } diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 6b7b2e58b..0d9705c82 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -185,7 +185,7 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) { const char* const ln = textp; while (*textp && !isspace(*textp)) textp++; if (isdigit(*ln)) { - lineno(atoi(ln)); + lineno(std::atoi(ln)); } else { fail = true; } @@ -207,7 +207,7 @@ void FileLine::lineDirective(const char* textp, int& enterExitRef) { // Grab level while (*textp && (isspace(*textp) || *textp == '"')) textp++; if (isdigit(*textp)) { - enterExitRef = atoi(textp); + enterExitRef = std::atoi(textp); if (enterExitRef >= 3) fail = true; } else { enterExitRef = 0; diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 02e6b439b..493beaf4d 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -919,7 +919,7 @@ class LinkDotFindVisitor final : public VNVisitor { string::size_type pos; if ((pos = dottedname.rfind("__DOT__")) != string::npos) { const string dotted = dottedname.substr(0, pos); - const string ident = dottedname.substr(pos + strlen("__DOT__")); + const string ident = dottedname.substr(pos + std::strlen("__DOT__")); string baddot; VSymEnt* okSymp; aboveSymp = m_statep->findDotted(nodep->fileline(), aboveSymp, dotted, baddot, okSymp); diff --git a/src/V3Number.cpp b/src/V3Number.cpp index d7473cd29..81b059442 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -156,14 +156,15 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) } value_startp = cp; - if (atoi(widthn.c_str())) { - if (atoi(widthn.c_str()) < 0 || atoi(widthn.c_str()) > v3Global.opt.maxNumWidth()) { + if (std::atoi(widthn.c_str())) { + if (std::atoi(widthn.c_str()) < 0 + || std::atoi(widthn.c_str()) > v3Global.opt.maxNumWidth()) { // atoi might convert large number to negative, so can't tell which v3error("Unsupported: Width of number exceeds implementation limit: " << sourcep << " (IEEE 1800-2017 6.9.1)"); width(v3Global.opt.maxNumWidth(), true); } else { - width(atoi(widthn.c_str()), true); + width(std::atoi(widthn.c_str()), true); } } } else { @@ -278,7 +279,8 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) } } else { // Convert bin/octal number to hex - for (const char* cp = value_startp + strlen(value_startp) - 1; cp >= value_startp; cp--) { + for (const char* cp = value_startp + std::strlen(value_startp) - 1; cp >= value_startp; + cp--) { if (*cp != '_' && *cp != '0' && obit >= width()) { v3error("Too many digits for " << width() << " bit number: " << sourcep); break; @@ -698,7 +700,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { if (fmtsize != "0") str += ' '; } } - const size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); + const size_t fmtsizen = static_cast(std::atoi(fmtsize.c_str())); str = displayPad(fmtsizen, ' ', left, str); return str; } @@ -747,7 +749,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { } const bool zeropad = fmtsize.length() > 0 && fmtsize[0] == '0'; // fmtsize might have changed since we parsed the %fmtsize - const size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); + const size_t fmtsizen = static_cast(std::atoi(fmtsize.c_str())); str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str); return str; } @@ -802,7 +804,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { return str; } case '@': { // Packed string - const size_t fmtsizen = static_cast(atoi(fmtsize.c_str())); + const size_t fmtsizen = static_cast(std::atoi(fmtsize.c_str())); str = displayPad(fmtsizen, ' ', left, toString()); return str; } diff --git a/src/V3OptionParser.cpp b/src/V3OptionParser.cpp index 308a26e10..8035916e7 100644 --- a/src/V3OptionParser.cpp +++ b/src/V3OptionParser.cpp @@ -130,8 +130,8 @@ V3OptionParser::ActionIfs* V3OptionParser::find(const char* optp) { for (auto&& act : m_pimpl->m_options) { if (act.second->isFOnOffAllowed()) { // Find starts with "-fno" if (const char* const nop - = VString::startsWith(optp, "-fno-") ? (optp + strlen("-fno-")) : nullptr) { - if (act.first.substr(strlen("-f"), std::string::npos) + = VString::startsWith(optp, "-fno-") ? (optp + std::strlen("-fno-")) : nullptr) { + if (act.first.substr(std::strlen("-f"), std::string::npos) == nop) { // [-f]opt = [-fno-]opt return act.second.get(); } @@ -139,7 +139,7 @@ V3OptionParser::ActionIfs* V3OptionParser::find(const char* optp) { } if (act.second->isOnOffAllowed()) { // Find starts with "-no" if (const char* const nop - = VString::startsWith(optp, "-no") ? (optp + strlen("-no")) : nullptr) { + = VString::startsWith(optp, "-no") ? (optp + std::strlen("-no")) : nullptr) { if (act.first == nop || act.first == (std::string{"-"} + nop)) { return act.second.get(); } @@ -206,7 +206,7 @@ void V3OptionParser::finalize() { m_pimpl->m_spellCheck.pushCandidate(opt.first); if (opt.second->isFOnOffAllowed()) { m_pimpl->m_spellCheck.pushCandidate( - "-fno-" + opt.first.substr(strlen("-f"), std::string::npos)); + "-fno-" + opt.first.substr(std::strlen("-f"), std::string::npos)); } if (opt.second->isOnOffAllowed()) m_pimpl->m_spellCheck.pushCandidate("-no" + opt.first); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 474cc3e57..0580fdac4 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -908,8 +908,8 @@ void V3Options::parseOpts(FileLine* fl, int argc, char** argv) { //====================================================================== bool V3Options::suffixed(const string& sw, const char* arg) { - if (strlen(arg) > sw.length()) return false; - return (0 == strcmp(sw.c_str() + sw.length() - strlen(arg), arg)); + if (std::strlen(arg) > sw.length()) return false; + return (0 == std::strcmp(sw.c_str() + sw.length() - std::strlen(arg), arg)); } void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv) { @@ -1019,15 +1019,15 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-comp-limit-parens", Set, &m_compLimitParens).undocumented(); DECL_OPTION("-comp-limit-syms", CbVal, [](int val) { VName::maxLength(val); }).undocumented(); DECL_OPTION("-compiler", CbVal, [this, fl](const char* valp) { - if (!strcmp(valp, "clang")) { + if (!std::strcmp(valp, "clang")) { m_compLimitBlocks = 80; // limit unknown m_compLimitMembers = 64; // soft limit, has slowdown bug as of clang++ 3.8 m_compLimitParens = 240; // controlled by -fbracket-depth, which defaults to 256 - } else if (!strcmp(valp, "gcc")) { + } else if (!std::strcmp(valp, "gcc")) { m_compLimitBlocks = 0; // Bug free m_compLimitMembers = 64; // soft limit, has slowdown bug as of g++ 7.1 m_compLimitParens = 240; // Unlimited, but generate same code as for clang - } else if (!strcmp(valp, "msvc")) { + } else if (!std::strcmp(valp, "msvc")) { m_compLimitBlocks = 80; // 128, but allow some room m_compLimitMembers = 0; // probably ok, and AFAIK doesn't support anon structs m_compLimitParens = 80; // 128, but allow some room @@ -1180,9 +1180,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char }); DECL_OPTION("-main", OnOff, &m_main); DECL_OPTION("-make", CbVal, [this, fl](const char* valp) { - if (!strcmp(valp, "cmake")) { + if (!std::strcmp(valp, "cmake")) { m_cmake = true; - } else if (!strcmp(valp, "gmake")) { + } else if (!std::strcmp(valp, "gmake")) { m_gmake = true; } else { fl->v3fatal("Unknown --make system specified: '" << valp << "'"); @@ -1329,13 +1329,13 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char if (m_threads < 0) fl->v3fatal("--threads must be >= 0: " << valp); }); DECL_OPTION("-threads-dpi", CbVal, [this, fl](const char* valp) { - if (!strcmp(valp, "all")) { + if (!std::strcmp(valp, "all")) { m_threadsDpiPure = true; m_threadsDpiUnpure = true; - } else if (!strcmp(valp, "none")) { + } else if (!std::strcmp(valp, "none")) { m_threadsDpiPure = false; m_threadsDpiUnpure = false; - } else if (!strcmp(valp, "pure")) { + } else if (!std::strcmp(valp, "pure")) { m_threadsDpiPure = true; m_threadsDpiUnpure = false; } else { @@ -1470,13 +1470,13 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-waiver-output", Set, &m_waiverOutput); DECL_OPTION("-x-assign", CbVal, [this, fl](const char* valp) { - if (!strcmp(valp, "0")) { + if (!std::strcmp(valp, "0")) { m_xAssign = "0"; - } else if (!strcmp(valp, "1")) { + } else if (!std::strcmp(valp, "1")) { m_xAssign = "1"; - } else if (!strcmp(valp, "fast")) { + } else if (!std::strcmp(valp, "fast")) { m_xAssign = "fast"; - } else if (!strcmp(valp, "unique")) { + } else if (!std::strcmp(valp, "unique")) { m_xAssign = "unique"; } else { fl->v3fatal("Unknown setting for --x-assign: '" @@ -1485,11 +1485,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char } }); DECL_OPTION("-x-initial", CbVal, [this, fl](const char* valp) { - if (!strcmp(valp, "0")) { + if (!std::strcmp(valp, "0")) { m_xInitial = "0"; - } else if (!strcmp(valp, "fast")) { + } else if (!std::strcmp(valp, "fast")) { m_xInitial = "fast"; - } else if (!strcmp(valp, "unique")) { + } else if (!std::strcmp(valp, "unique")) { m_xInitial = "unique"; } else { fl->v3fatal("Unknown setting for --x-initial: '" @@ -1511,11 +1511,12 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char for (int i = 0; i < argc;) { UINFO(9, " Option: " << argv[i] << endl); - if (!strcmp(argv[i], "-j") || !strcmp(argv[i], "--j")) { // Allow gnu -- switches + if (!std::strcmp(argv[i], "-j") + || !std::strcmp(argv[i], "--j")) { // Allow gnu -- switches ++i; m_buildJobs = 0; // Unlimited parallelism if (i < argc && isdigit(argv[i][0])) { - m_buildJobs = atoi(argv[i]); + m_buildJobs = std::atoi(argv[i]); if (m_buildJobs <= 0) { fl->v3error("-j accepts positive integer, but '" << argv[i] << "' is passed"); } diff --git a/src/V3Os.cpp b/src/V3Os.cpp index c410c6735..2abc200c0 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -347,7 +347,7 @@ int V3Os::system(const string& command) { const int ret = ::system(command.c_str()); if (VL_UNCOVERABLE(ret == -1)) { v3fatal("Failed to execute command:" // LCOV_EXCL_LINE - << command << " " << strerror(errno)); + << command << " " << std::strerror(errno)); return -1; // LCOV_EXCL_LINE } else { UASSERT(WIFEXITED(ret), "system(" << command << ") returned unexpected value of " << ret); diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 8a1481323..1d2832ce5 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -150,8 +150,8 @@ void V3ParseImp::lexVerilatorCmtLint(FileLine* fl, const char* textp, bool warnO void V3ParseImp::lexVerilatorCmtBad(FileLine* fl, const char* textp) { string cmtparse = textp; - if (cmtparse.substr(0, strlen("/*verilator")) == "/*verilator") { - cmtparse.replace(0, strlen("/*verilator"), ""); + if (cmtparse.substr(0, std::strlen("/*verilator")) == "/*verilator") { + cmtparse.replace(0, std::strlen("/*verilator"), ""); } while (isspace(cmtparse[0])) cmtparse.replace(0, 1, ""); string cmtname; @@ -178,14 +178,14 @@ void V3ParseImp::lexErrorPreprocDirective(FileLine* fl, const char* textp) { } string V3ParseImp::lexParseTag(const char* textp) { - string tmp = textp + strlen("/*verilator tag "); + string tmp = textp + std::strlen("/*verilator tag "); string::size_type pos; if ((pos = tmp.rfind("*/")) != string::npos) tmp.erase(pos); return tmp; } double V3ParseImp::lexParseTimenum(const char* textp) { - const size_t length = strlen(textp); + const size_t length = std::strlen(textp); char* const strgp = new char[length + 1]; char* dp = strgp; const char* sp = textp; @@ -234,7 +234,7 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) { m_ppBuffers.push_front(remainder); // Put back remainder for next time len = (max_size - got); } - memcpy(buf + got, front.c_str(), len); + std::memcpy(buf + got, front.c_str(), len); got += len; } if (debug() >= 9) { diff --git a/src/V3PreLex.l b/src/V3PreLex.l index bfe69e7c7..a83a55db9 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -126,7 +126,7 @@ bom [\357\273\277] if (LEXP->m_protBytes > 0) { LEXP->curFilelinep()->v3warn(BADSTDPRAGMA, "multiple `pragma protected encoding sections"); } - res = sscanf(yytext + strlen("encoding"), " = (enctype = \"%15[A-Za-z0-9]\", line_length = %d, bytes = %d)", &enctype[0], &LEXP->m_protLength, &LEXP->m_protBytes); + res = sscanf(yytext + std::strlen("encoding"), " = (enctype = \"%15[A-Za-z0-9]\", line_length = %d, bytes = %d)", &enctype[0], &LEXP->m_protLength, &LEXP->m_protBytes); if (res == 0) LEXP->curFilelinep()->v3warn(BADSTDPRAGMA, "`pragma protected encoding must have an \"enctype\" field"); LEXP->m_encType = !VL_STRCASECMP(enctype, "uuencode") ? Enctype::UUENCODE : @@ -242,7 +242,7 @@ bom [\357\273\277] "`__LINE__" { FL_FWDC; static char buf[25]; VL_SNPRINTF(buf, 25, "%d", LEXP->curFilelinep()->lastLineno()); - yytext = buf; yyleng = strlen(yytext); + yytext = buf; yyleng = std::strlen(yytext); return VP_TEXT; } /* Pass-through strings */ diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 59ba4398b..0cf66dc24 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -395,7 +395,7 @@ string V3PreProcImp::commentCleanup(const string& text) { } bool V3PreProcImp::commentTokenMatch(string& cmdr, const char* strg) { - int len = strlen(strg); + int len = std::strlen(strg); if (VString::startsWith(cmdr, strg) && (cmdr[len] == '\0' || isspace(cmdr[len]))) { if (isspace(cmdr[len])) len++; cmdr = cmdr.substr(len); @@ -425,27 +425,27 @@ void V3PreProcImp::comment(const string& text) { bool synth = false; bool vlcomment = false; if ((cp[0] == 'v' || cp[0] == 'V') && VString::startsWith(cp + 1, "erilator")) { - cp += strlen("verilator"); + cp += std::strlen("verilator"); if (*cp == '_') { fileline()->v3error("Extra underscore in meta-comment;" " use /*verilator {...}*/ not /*verilator_{...}*/"); } vlcomment = true; } else if (VString::startsWith(cp, "synopsys")) { - cp += strlen("synopsys"); + cp += std::strlen("synopsys"); synth = true; if (*cp == '_') { fileline()->v3error("Extra underscore in meta-comment;" " use /*synopsys {...}*/ not /*synopsys_{...}*/"); } } else if (VString::startsWith(cp, "cadence")) { - cp += strlen("cadence"); + cp += std::strlen("cadence"); synth = true; } else if (VString::startsWith(cp, "pragma")) { - cp += strlen("pragma"); + cp += std::strlen("pragma"); synth = true; } else if (VString::startsWith(cp, "ambit synthesis")) { - cp += strlen("ambit synthesis"); + cp += std::strlen("ambit synthesis"); synth = true; } else { return; @@ -478,7 +478,7 @@ void V3PreProcImp::comment(const string& text) { string::size_type pos; if ((pos = cmd.find("public_flat_rw")) != string::npos) { // "/*verilator public_flat_rw @(foo) */" -> "/*verilator public_flat_rw*/ @(foo)" - cmd = cmd.substr(pos + strlen("public_flat_rw")); + cmd = cmd.substr(pos + std::strlen("public_flat_rw")); while (isspace(cmd[0])) cmd = cmd.substr(1); if (!printed) insertUnreadback("/*verilator public_flat_rw*/ " + cmd + " /**/"); } else { @@ -1593,7 +1593,7 @@ string V3PreProcImp::getline() { if (isEof()) return ""; const char* rtnp; bool gotEof = false; - while (nullptr == (rtnp = strchr(m_lineChars.c_str(), '\n')) && !gotEof) { + while (nullptr == (rtnp = std::strchr(m_lineChars.c_str(), '\n')) && !gotEof) { string buf; const int tok = getFinalToken(buf /*ref*/); if (debug() >= 5) { diff --git a/src/V3String.cpp b/src/V3String.cpp index 9d20bd078..1a42ee2e7 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -150,7 +150,7 @@ double VString::parseDouble(const string& str, bool* successp) { char* endp = strgp; const double d = strtod(strgp, &endp); const size_t parsed_len = endp - strgp; - if (parsed_len != strlen(strgp)) { + if (parsed_len != std::strlen(strgp)) { if (successp) *successp = false; } VL_DO_DANGLING(delete[] strgp, strgp); @@ -402,7 +402,7 @@ void VHashSha256::selfTest() { string VName::dehash(const string& in) { static const char VHSH[] = "__Vhsh"; - static const size_t DOT_LEN = strlen("__DOT__"); + static const size_t DOT_LEN = std::strlen("__DOT__"); std::string dehashed; // Need to split 'in' into components separated by __DOT__, 'last_dot_pos' diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 081fc526e..a784b3024 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -5963,7 +5963,7 @@ private: } if ((VN_IS(nodep, Add) && underp->width() == 1 && underp->isOne()) || (VN_IS(nodep, Sub) && underp->width() == 1 && underp->isOne() - && 0 == strcmp(side, "RHS"))) { + && 0 == std::strcmp(side, "RHS"))) { // "foo + 1'b1", or "foo - 1'b1" are very common, people assume // they extend correctly warnOn = false; diff --git a/src/verilog.l b/src/verilog.l index a3cc59ef6..46f612ef4 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -1004,7 +1004,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} return yaT_RESETALL; } // Rest handled by preproc "`suppress_faults" { FL_FWD; FL_BRK; } // Verilog-XL compatibility "`timescale"{ws}+[^\n\r]* { FL; PARSEP->lexTimescaleParse(yylval.fl, - yytext + strlen("`timescale")); + yytext + std::strlen("`timescale")); FL_BRK; } "`unconnected_drive"{ws}+"pull0" { FL; return yaT_UNCONNECTED_PULL0; } "`unconnected_drive"{ws}+"pull1" { FL; return yaT_UNCONNECTED_PULL1; } diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 22a2a67f8..fe0bd9498 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -1845,7 +1845,7 @@ sub _make_main { if ($self->{savable}) { $fh->print(" const char* save_time_strp = contextp->commandArgsPlusMatch(\"save_time=\");\n"); - $fh->print(" unsigned int save_time = !save_time_strp[0] ? 0 : atoi(save_time_strp+strlen(\"+save_time=\"));\n"); + $fh->print(" unsigned int save_time = !save_time_strp[0] ? 0 : std::atoi(save_time_strp + std::strlen(\"+save_time=\"));\n"); $fh->print(" const char* save_restore_strp = contextp->commandArgsPlusMatch(\"save_restore=\");\n"); $fh->print(" unsigned int save_restore = !save_restore_strp[0] ? 0 : 1;\n"); } diff --git a/test_regress/t/TestCheck.h b/test_regress/t/TestCheck.h index ac42dde3b..2f8cf2283 100644 --- a/test_regress/t/TestCheck.h +++ b/test_regress/t/TestCheck.h @@ -34,7 +34,7 @@ static const bool verbose = false; #define TEST_CHECK_EQ(got, exp) TEST_CHECK(got, exp, ((got) == (exp))); #define TEST_CHECK_NE(got, exp) TEST_CHECK(got, exp, ((got) != (exp))); -#define TEST_CHECK_CSTR(got, exp) TEST_CHECK(got, exp, 0 == strcmp((got), (exp))); +#define TEST_CHECK_CSTR(got, exp) TEST_CHECK(got, exp, 0 == std::strcmp((got), (exp))); #define TEST_CHECK_HEX_EQ(got, exp) \ do { \ diff --git a/test_regress/t/TestSimulator.h b/test_regress/t/TestSimulator.h index 6272887d8..c25304f6e 100644 --- a/test_regress/t/TestSimulator.h +++ b/test_regress/t/TestSimulator.h @@ -28,13 +28,13 @@ private: public: TestSimulator() { vpi_get_vlog_info(&m_info); - if (0 == strcmp(m_info.product, "Verilator")) { + if (0 == std::strcmp(m_info.product, "Verilator")) { m_simulators.verilator = true; - } else if (0 == strcmp(m_info.product, "Verilator")) { + } else if (0 == std::strcmp(m_info.product, "Verilator")) { m_simulators.icarus = true; } else if (0 == strncmp(m_info.product, "Chronologic Simulation VCS", - strlen("Chronologic Simulation VCS"))) { + std::strlen("Chronologic Simulation VCS"))) { m_simulators.vcs = true; } else { printf("%%Warning: %s:%d: Unknown simulator in TestSimulator.h: %s\n", __FILE__, diff --git a/test_regress/t/t_dpi_arg_inout_type.cpp b/test_regress/t/t_dpi_arg_inout_type.cpp index a5c346d8f..f5b109b39 100644 --- a/test_regress/t/t_dpi_arg_inout_type.cpp +++ b/test_regress/t/t_dpi_arg_inout_type.cpp @@ -168,10 +168,10 @@ void i_string(const char** x) { static int n = 0; printf("i_string %d\n", n); if (n++ % 2 == 0) { - if (strcmp(*x, "Hello") != 0) stop(); + if (std::strcmp(*x, "Hello") != 0) stop(); *x = "Good"; } else { - if (strcmp(*x, "World") != 0) stop(); + if (std::strcmp(*x, "World") != 0) stop(); *x = "Bye"; } } @@ -296,10 +296,10 @@ void i_string_t(const char** x) { static int n = 0; printf("i_string_t %d\n", n); if (n++ % 2 == 0) { - if (strcmp(*x, "World") != 0) stop(); + if (std::strcmp(*x, "World") != 0) stop(); *x = "Bye"; } else { - if (strcmp(*x, "Hello") != 0) stop(); + if (std::strcmp(*x, "Hello") != 0) stop(); *x = "Good"; } } @@ -962,10 +962,10 @@ void check_exports() { e_string(&x_string); if ((n % 2) == 0) { if (x_chandle) stop(); - if (strcmp(x_string, "Hello") != 0) stop(); + if (std::strcmp(x_string, "Hello") != 0) stop(); } else { if (x_chandle) stop(); - if (strcmp(x_string, "World") != 0) stop(); + if (std::strcmp(x_string, "World") != 0) stop(); } x_bit = n % 2; @@ -1045,10 +1045,10 @@ void check_exports() { e_string_t(&x_string_t); if ((n % 2) == 0) { if (x_chandle_t != NULL) stop(); - if (strcmp(x_string_t, "World") != 0) stop(); + if (std::strcmp(x_string_t, "World") != 0) stop(); } else { if (x_chandle_t != NULL) stop(); - if (strcmp(x_string_t, "Hello") != 0) stop(); + if (std::strcmp(x_string_t, "Hello") != 0) stop(); } x_bit_t = n % 2; diff --git a/test_regress/t/t_dpi_arg_input_type.cpp b/test_regress/t/t_dpi_arg_input_type.cpp index 1593e1dfc..ee7f56d79 100644 --- a/test_regress/t/t_dpi_arg_input_type.cpp +++ b/test_regress/t/t_dpi_arg_input_type.cpp @@ -155,9 +155,9 @@ void i_string(const char* i) { static int n = 0; printf("i_string %d\n", n); if (n++ % 2 == 0) { - if (strcmp(i, "World") != 0) stop(); + if (std::strcmp(i, "World") != 0) stop(); } else { - if (strcmp(i, "Hello") != 0) stop(); + if (std::strcmp(i, "Hello") != 0) stop(); } } @@ -266,9 +266,9 @@ void i_string_t(const char* i) { static int n = 0; printf("i_string_t %d\n", n); if (n++ % 2 == 0) { - if (strcmp(i, "World") != 0) stop(); + if (std::strcmp(i, "World") != 0) stop(); } else { - if (strcmp(i, "Hello") != 0) stop(); + if (std::strcmp(i, "Hello") != 0) stop(); } } diff --git a/test_regress/t/t_dpi_arg_output_type.cpp b/test_regress/t/t_dpi_arg_output_type.cpp index cf127ee6e..b8eda4a74 100644 --- a/test_regress/t/t_dpi_arg_output_type.cpp +++ b/test_regress/t/t_dpi_arg_output_type.cpp @@ -711,9 +711,9 @@ void check_exports() { e_string(&x_string); if ((n % 2) == 0) { - if (strcmp(x_string, "Hello") != 0) stop(); + if (std::strcmp(x_string, "Hello") != 0) stop(); } else { - if (strcmp(x_string, "World") != 0) stop(); + if (std::strcmp(x_string, "World") != 0) stop(); } e_bit(&x_bit); @@ -772,9 +772,9 @@ void check_exports() { e_string_t(&x_string_t); if ((n % 2) == 0) { - if (strcmp(x_string_t, "Hello") != 0) stop(); + if (std::strcmp(x_string_t, "Hello") != 0) stop(); } else { - if (strcmp(x_string_t, "World") != 0) stop(); + if (std::strcmp(x_string_t, "World") != 0) stop(); } e_bit_t(&x_bit_t); diff --git a/test_regress/t/t_dpi_export_c.cpp b/test_regress/t/t_dpi_export_c.cpp index da9fee221..8b60a1c66 100644 --- a/test_regress/t/t_dpi_export_c.cpp +++ b/test_regress/t/t_dpi_export_c.cpp @@ -115,9 +115,10 @@ int dpix_run_tests() { #ifndef CADENCE // Unimplemented; how hard is it? printf("svDpiVersion: %s\n", svDpiVersion()); - CHECK_RESULT( - bool, - strcmp(svDpiVersion(), "1800-2005") == 0 || strcmp(svDpiVersion(), "P1800-2005") == 0, 1); + CHECK_RESULT(bool, + std::strcmp(svDpiVersion(), "1800-2005") == 0 + || std::strcmp(svDpiVersion(), "P1800-2005") == 0, + 1); #endif CHECK_RESULT(int, dpix_int123(), 0x123); diff --git a/test_regress/t/t_dpi_result_type.cpp b/test_regress/t/t_dpi_result_type.cpp index a0d7b3cb5..bc8314a15 100644 --- a/test_regress/t/t_dpi_result_type.cpp +++ b/test_regress/t/t_dpi_result_type.cpp @@ -303,9 +303,9 @@ void check_exports() { #endif if (e_chandle()) stop(); if ((n % 2) == 0) { - if (strcmp(e_string(), "Hello") != 0) stop(); + if (std::strcmp(e_string(), "Hello") != 0) stop(); } else { - if (strcmp(e_string(), "World") != 0) stop(); + if (std::strcmp(e_string(), "World") != 0) stop(); } if (e_bit() != (n % 2)) stop(); if (e_logic() != !(n % 2)) stop(); @@ -327,9 +327,9 @@ void check_exports() { #endif if (e_chandle_t()) stop(); if ((n % 2) == 0) { - if (strcmp(e_string_t(), "Hello") != 0) stop(); + if (std::strcmp(e_string_t(), "Hello") != 0) stop(); } else { - if (strcmp(e_string_t(), "World") != 0) stop(); + if (std::strcmp(e_string_t(), "World") != 0) stop(); } if (e_bit_t() != (n % 2)) stop(); if (e_logic_t() != !(n % 2)) stop(); diff --git a/test_regress/t/t_dpi_string_c.cpp b/test_regress/t/t_dpi_string_c.cpp index 05b001886..9216d9316 100644 --- a/test_regress/t/t_dpi_string_c.cpp +++ b/test_regress/t/t_dpi_string_c.cpp @@ -39,5 +39,5 @@ extern int dpii_string(const char* s); int dpii_string(const char* s) { printf("dpii_string: %s\n", s); - return strlen(s); + return std::strlen(s); } diff --git a/test_regress/t/t_dpi_var.cpp b/test_regress/t/t_dpi_var.cpp index f35647d41..5f9ee79f1 100644 --- a/test_regress/t/t_dpi_var.cpp +++ b/test_regress/t/t_dpi_var.cpp @@ -60,9 +60,9 @@ void mon_scope_name(const char* namep) { #ifdef TEST_VERBOSE VL_PRINTF("- mon_scope_name('%s', \"%s\");\n", modp, namep); #endif - if (strcmp(namep, "t.sub")) + if (std::strcmp(namep, "t.sub")) vl_fatal(__FILE__, __LINE__, "", (std::string{"Unexp scope name "} + namep).c_str()); - if (strcmp(modp, "t.sub")) + if (std::strcmp(modp, "t.sub")) vl_fatal(__FILE__, __LINE__, "", (std::string{"Unexp dpiscope name "} + modp).c_str()); } diff --git a/test_regress/t/t_sc_names.cpp b/test_regress/t/t_sc_names.cpp index 6839252b0..6f73c4c1d 100644 --- a/test_regress/t/t_sc_names.cpp +++ b/test_regress/t/t_sc_names.cpp @@ -15,7 +15,7 @@ int sc_main(int argc, char* argv[]) { /* We expect to find clk in here. */ for (int i = 0; i < ch.size(); ++i) { - if (!strcmp(ch[i]->basename(), "clk")) found = true; + if (!std::strcmp(ch[i]->basename(), "clk")) found = true; } if (found) { diff --git a/test_regress/t/t_scope_map.cpp b/test_regress/t/t_scope_map.cpp index 9136c8ee3..d9f554d8b 100644 --- a/test_regress/t/t_scope_map.cpp +++ b/test_regress/t/t_scope_map.cpp @@ -100,7 +100,7 @@ int main(int argc, char** argv, char** env) { #endif // Clear out the data - memset(varData, 0, (varBits + 7) / 8); + std::memset(varData, 0, (varBits + 7) / 8); } } diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp index fdd93ee01..898664841 100644 --- a/test_regress/t/t_vpi_get.cpp +++ b/test_regress/t/t_vpi_get.cpp @@ -71,7 +71,7 @@ } #define CHECK_RESULT_CSTR(got, exp) \ - if (strcmp((got), (exp))) { \ + if (std::strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ (got) ? (got) : "", (exp) ? (exp) : ""); \ return __LINE__; \ diff --git a/test_regress/t/t_vpi_module.cpp b/test_regress/t/t_vpi_module.cpp index 754cc2660..1c2de048c 100644 --- a/test_regress/t/t_vpi_module.cpp +++ b/test_regress/t/t_vpi_module.cpp @@ -61,7 +61,7 @@ } #define CHECK_RESULT_CSTR(got, exp) \ - if (strcmp((got), (exp))) { \ + if (std::strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ (got) ? (got) : "", (exp) ? (exp) : ""); \ return __LINE__; \ @@ -100,7 +100,7 @@ int mon_check() { CHECK_RESULT_NZ(t_name); // Icarus reports the top most module as "top" - if (strcmp(t_name, "top") == 0) { + if (std::strcmp(t_name, "top") == 0) { it = vpi_iterate(vpiModule, topmod); CHECK_RESULT_NZ(it); CHECK_RESULT(vpi_get(vpiType, it), vpiModule); @@ -129,7 +129,7 @@ int mon_check() { CHECK_RESULT_NZ(mod3); const char* mod_c_name = vpi_get_str(vpiName, mod3); - if (strcmp(mod_c_name, "mod_b") == 0) { + if (std::strcmp(mod_c_name, "mod_b") == 0) { // Full visibility in other simulators, skip mod_b TestVpiHandle mod4 = vpi_scan(it3); CHECK_RESULT_NZ(mod4); diff --git a/test_regress/t/t_vpi_param.cpp b/test_regress/t/t_vpi_param.cpp index 51415a38b..dcc4a7fb9 100644 --- a/test_regress/t/t_vpi_param.cpp +++ b/test_regress/t/t_vpi_param.cpp @@ -71,7 +71,7 @@ } #define CHECK_RESULT_CSTR(got, exp) \ - if (strcmp((got), (exp))) { \ + if (std::strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ (got) ? (got) : "", (exp) ? (exp) : ""); \ return __LINE__; \ diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp index 549d66e1e..e91515a6e 100644 --- a/test_regress/t/t_vpi_unimpl.cpp +++ b/test_regress/t/t_vpi_unimpl.cpp @@ -66,7 +66,7 @@ unsigned int callback_count = 0; } #define CHECK_RESULT_CSTR(got, exp) \ - if (strcmp((got), (exp))) { \ + if (std::strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ (got) ? (got) : "", (exp) ? (exp) : ""); \ return __LINE__; \ diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index b8186c281..1c5c76f50 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -90,7 +90,7 @@ bool verbose = false; } #define CHECK_RESULT_CSTR(got, exp) \ - if (strcmp((got), (exp))) { \ + if (std::strcmp((got), (exp))) { \ printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ ((got) != NULL) ? (got) : "", ((exp) != NULL) ? (exp) : ""); \ return __LINE__; \ @@ -117,7 +117,7 @@ int _mon_check_mcd() { } status = vpi_mcd_printf(mcd, (PLI_BYTE8*)"hello %s", "vpi_mcd_printf"); - CHECK_RESULT(status, strlen("hello vpi_mcd_printf")); + CHECK_RESULT(status, std::strlen("hello vpi_mcd_printf")); status = vpi_mcd_printf(0, (PLI_BYTE8*)"empty"); CHECK_RESULT(status, 0); @@ -634,7 +634,7 @@ int _mon_check_vlog_info() { CHECK_RESULT_Z(vlog_info.argv[4]); if (TestSimulator::is_verilator()) { CHECK_RESULT_CSTR(vlog_info.product, "Verilator"); - CHECK_RESULT(strlen(vlog_info.version) > 0, 1); + CHECK_RESULT(std::strlen(vlog_info.version) > 0, 1); } return 0; } From e43c089ab833ed4ec62466ee37c63bf613f74603 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 14 Sep 2022 23:26:34 -0400 Subject: [PATCH 33/75] Commentary --- README.rst | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index 8dd636245..d46296d02 100644 --- a/README.rst +++ b/README.rst @@ -28,7 +28,7 @@ Welcome to Verilator - |Logo| * - |verilator multithreaded performance| - **Fast** - * Outperforms many commercial simulators + * Outperforms many closed-source commercial simulators * Single- and multi-threaded output models * - **Widely Used** * Wide industry and academic deployment @@ -55,20 +55,19 @@ performing lint checks, and optionally inserting assertion checks and coverage-analysis points. It outputs single- or multi-threaded .cpp and .h files, the "Verilated" code. -The user writes a little C++/SystemC wrapper file, which instantiates the -"Verilated" model of the user's top level module. These C++/SystemC files -are then compiled by a C++ compiler (gcc/clang/MSVC++). Executing the -resulting executable performs the design simulation. Verilator also -supports linking Verilated generated libraries, optionally encrypted, into -other simulators. +These Verilated C++/SystemC files are then compiled by a C++ compiler +(gcc/clang/MSVC++), optionally along with a user's own C++/SystemC wrapper +file to instantiate the Verilated model. Executing the resulting executable +performs the design simulation. Verilator also supports linking Verilated +generated libraries, optionally encrypted, into other simulators. Verilator may not be the best choice if you are expecting a full featured -replacement for Incisive, ModelSim/Questa, VCS or another commercial -Verilog simulator, or if you are looking for a behavioral Verilog simulator -e.g. for a quick class project (we recommend `Icarus Verilog`_ for this.) -However, if you are looking for a path to migrate SystemVerilog to C++ or -SystemC, or your team is comfortable writing just a touch of C++ code, -Verilator is the tool for you. +replacement for a closed-source Verilog simulator, need SDF annotation, +mixed-signal simulation, or are doing a quick class project (we recommend +`Icarus Verilog`_ for classwork.) However, if you are looking for a path +to migrate SystemVerilog to C++/SystemC, or want high speed simulation of +synthesizable designs containing limited verification constructs, Verilator +is the tool for you. Performance @@ -85,9 +84,11 @@ multithreading (yielding 200-1000x total over interpreted simulators). Verilator has typically similar or better performance versus the closed-source Verilog simulators (Carbon Design Systems Carbonator, -Modelsim, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and Pragmatic -CVer/CVC). But, Verilator is open-sourced, so you can spend on computes -rather than licenses. Thus Verilator gives you the best cycles/dollar. +Modelsim/Questa, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and +Pragmatic CVer/CVC). But, Verilator is open-sourced, so you can spend on +computes rather than licenses. Thus Verilator gives you the best +cycles/dollar. + Installation & Documentation ============================ From 22b9dfb9c9c3a44fdb97b8b17f40f8a19abf7680 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Thu, 15 Sep 2022 13:10:39 +0100 Subject: [PATCH 34/75] Split and re-order AstNode definitions (#3622) - Move DType representations into V3AstNodeDType.h - Move AstNodeMath and subclasses into V3AstNodeMath.h - Move any other AstNode subtypes into V3AstNodeOther.h - Fix up out-of-order definitions via inline methods and implementations in V3Inlines.h and V3AstNodes.cpp - Enforce declaration order of AstNode subtypes via astgen, which will now fail when definitions are mis-ordered. --- docs/internals.rst | 5 +- src/Makefile_obj.in | 17 +- src/V3Ast.h | 1119 +---- src/V3AstInlines.h | 124 +- src/V3AstNodeDType.h | 1341 ++++++ src/V3AstNodeMath.h | 4426 +++++++++++++++++++ src/V3AstNodeOther.h | 4363 +++++++++++++++++++ src/V3AstNodes.cpp | 270 ++ src/V3AstNodes.h | 9592 ----------------------------------------- src/astgen | 92 +- src/cppcheck_filtered | 2 +- 11 files changed, 10651 insertions(+), 10700 deletions(-) create mode 100644 src/V3AstNodeDType.h create mode 100644 src/V3AstNodeMath.h create mode 100644 src/V3AstNodeOther.h delete mode 100644 src/V3AstNodes.h diff --git a/docs/internals.rst b/docs/internals.rst index 499e0fa12..c9e00d7dd 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -1153,8 +1153,9 @@ Generally what would you do to add a new feature? language and has a lot of back-and-forth with Verilator's grammar. Copy the appropriate rules to src/verilog.y and modify the productions. -4. If a new Ast type is needed, add it to V3AstNodes.h. Follow the - convention described above about the AstNode type hierarchy. +4. If a new Ast type is needed, add it to the appropriate V3AstNode*.h. + Follow the convention described above about the AstNode type hierarchy. + Ordering of definitions is enforced by ``astgen``. 5. Now you can run "test_regress/t/t_.pl --debug" and it'll probably fail but you'll see a diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 1496cc411..346521767 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -276,9 +276,16 @@ VLCOV_OBJS = \ NON_STANDALONE_HEADERS = \ V3AstInlines.h \ - V3AstNodes.h \ + V3AstNodeDType.h \ + V3AstNodeMath.h \ + V3AstNodeOther.h \ V3WidthCommit.h \ +AST_DEFS := \ + V3AstNodeDType.h \ + V3AstNodeMath.h \ + V3AstNodeOther.h \ + #### Linking ifeq ($(VL_VLCOV),) @@ -301,8 +308,8 @@ V3Number_test: V3Number_test.o #### Modules -%__gen.cpp: %.cpp $(ASTGEN) V3Ast.h V3AstNodes.h - $(PYTHON3) $(ASTGEN) -I $(srcdir) $*.cpp +%__gen.cpp: %.cpp $(ASTGEN) $(AST_DEFS) + $(PYTHON3) $(ASTGEN) -I $(srcdir) $(foreach f,$(AST_DEFS),--astdef $f) $*.cpp %.o: %.cpp $(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} -c $< -o $@ @@ -332,8 +339,8 @@ vlcovgen.d: $(VLCOVGEN) $(srcdir)/../include/verilated_cov_key.h $(PYTHON3) $(VLCOVGEN) --srcdir $(srcdir) touch $@ -V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h - $(PYTHON3) $(ASTGEN) -I $(srcdir) --classes +V3Ast__gen_classes.h : $(ASTGEN) $(AST_DEFS) + $(PYTHON3) $(ASTGEN) -I $(srcdir) $(foreach f,$(AST_DEFS),--astdef $f) --classes V3ParseBison.h: V3ParseBison.c diff --git a/src/V3Ast.h b/src/V3Ast.h index bb945564c..3df21ffb4 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -36,8 +36,6 @@ #include #include #include -// Things like: -// class V3AstNode; // Forward declarations class V3Graph; @@ -2367,1084 +2365,6 @@ struct std::equal_to> final { } }; -//###################################################################### -//=== AstNode* : Derived generic node types - -#define ASTNODE_BASE_FUNCS(name) \ - virtual ~Ast##name() override = default; \ - static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ - } \ - Ast##name* cloneTree(bool cloneNext) { \ - return static_cast(AstNode::cloneTree(cloneNext)); \ - } \ - Ast##name* clonep() const { return static_cast(AstNode::clonep()); } - -class AstNodeMath VL_NOT_FINAL : public AstNode { - // Math -- anything that's part of an expression tree -protected: - AstNodeMath(VNType t, FileLine* fl) - : AstNode{t, fl} {} - -public: - ASTNODE_BASE_FUNCS(NodeMath) - // METHODS - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV - // For documentation on emitC format see EmitCFunc::emitOpName - virtual string emitC() = 0; - virtual string emitSimpleOperator() { return ""; } // "" means not ok to use - virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS - virtual bool cleanOut() const = 0; // True if output has extra upper bits zero - // Someday we will generically support data types on every math node - // Until then isOpaque indicates we shouldn't constant optimize this node type - bool isOpaque() const { return VN_IS(this, CvtPackString); } -}; - -class AstNodeTermop VL_NOT_FINAL : public AstNodeMath { - // Terminal operator -- a operator with no "inputs" -protected: - AstNodeTermop(VNType t, FileLine* fl) - : AstNodeMath{t, fl} {} - -public: - ASTNODE_BASE_FUNCS(NodeTermop) - // Know no children, and hot function, so skip iterator for speed - // See checkTreeIter also that asserts no children - // cppcheck-suppress functionConst - void iterateChildren(VNVisitor& v) {} - virtual void dump(std::ostream& str) const override; -}; - -class AstNodeUniop VL_NOT_FINAL : public AstNodeMath { - // Unary math -protected: - AstNodeUniop(VNType t, FileLine* fl, AstNode* lhsp) - : AstNodeMath{t, fl} { - dtypeFrom(lhsp); - setOp1p(lhsp); - } - -public: - ASTNODE_BASE_FUNCS(NodeUniop) - AstNode* lhsp() const { return op1p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - // METHODS - virtual void dump(std::ostream& str) const override; - // Set out to evaluation of a AstConst'ed lhs - virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; - virtual bool cleanLhs() const = 0; - virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size - virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors? - // Signed flavor of nodes with both flavors? - virtual bool signedFlavor() const { return false; } - virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } -}; - -class AstNodeBiop VL_NOT_FINAL : public AstNodeMath { - // Binary math -protected: - AstNodeBiop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) - : AstNodeMath{t, fl} { - setOp1p(lhs); - setOp2p(rhs); - } - -public: - ASTNODE_BASE_FUNCS(NodeBiop) - // Clone single node, just get same type back. - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; - // ACCESSORS - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - // METHODS - // Set out to evaluation of a AstConst'ed - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0; - virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero - virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero - virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size - virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size - virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors? - // Signed flavor of nodes with both flavors? - virtual bool signedFlavor() const { return false; } - virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } -}; - -class AstNodeTriop VL_NOT_FINAL : public AstNodeMath { - // Trinary math -protected: - AstNodeTriop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) - : AstNodeMath{t, fl} { - setOp1p(lhs); - setOp2p(rhs); - setOp3p(ths); - } - -public: - ASTNODE_BASE_FUNCS(NodeTriop) - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - AstNode* thsp() const { return op3p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - void thsp(AstNode* nodep) { return setOp3p(nodep); } - // METHODS - virtual void dump(std::ostream& str) const override; - // Set out to evaluation of a AstConst'ed - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) - = 0; - virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero - virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero - virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero - virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size - virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size - virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } -}; - -class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath { - // Quaternary math -protected: - AstNodeQuadop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs) - : AstNodeMath{t, fl} { - setOp1p(lhs); - setOp2p(rhs); - setOp3p(ths); - setOp4p(fhs); - } - -public: - ASTNODE_BASE_FUNCS(NodeQuadop) - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - AstNode* thsp() const { return op3p(); } - AstNode* fhsp() const { return op4p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - void thsp(AstNode* nodep) { return setOp3p(nodep); } - void fhsp(AstNode* nodep) { return setOp4p(nodep); } - // METHODS - // Set out to evaluation of a AstConst'ed - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths, const V3Number& fhs) - = 0; - virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero - virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero - virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero - virtual bool cleanFhs() const = 0; // True if THS must have extra upper bits zero - virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size - virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size - virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size - virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } -}; - -class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop { - // Binary math with commutative properties -protected: - AstNodeBiCom(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) - : AstNodeBiop{t, fl, lhs, rhs} {} - -public: - ASTNODE_BASE_FUNCS(NodeBiCom) -}; - -class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom { - // Binary math with commutative & associative properties -protected: - AstNodeBiComAsv(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) - : AstNodeBiCom{t, fl, lhs, rhs} {} - -public: - ASTNODE_BASE_FUNCS(NodeBiComAsv) -}; - -class AstNodeCond VL_NOT_FINAL : public AstNodeTriop { -protected: - AstNodeCond(VNType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : AstNodeTriop{t, fl, condp, expr1p, expr2p} { - if (expr1p) { - dtypeFrom(expr1p); - } else if (expr2p) { - dtypeFrom(expr2p); - } - } - -public: - ASTNODE_BASE_FUNCS(NodeCond) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override; - AstNode* condp() const { return op1p(); } // op1 = Condition - AstNode* expr1p() const { return op2p(); } // op2 = If true... - AstNode* expr2p() const { return op3p(); } // op3 = If false... - virtual string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; } - virtual string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; } - virtual bool cleanOut() const override { return false; } // clean if e1 & e2 clean - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } // Propagates up - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0; -}; - -class AstNodeBlock VL_NOT_FINAL : public AstNode { - // A Begin/fork block - // Parents: statement - // Children: statements -private: - string m_name; // Name of block - bool m_unnamed; // Originally unnamed (name change does not affect this) -protected: - AstNodeBlock(VNType t, FileLine* fl, const string& name, AstNode* stmtsp) - : AstNode{t, fl} - , m_name{name} { - addNOp1p(stmtsp); - m_unnamed = (name == ""); - } - -public: - ASTNODE_BASE_FUNCS(NodeBlock) - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } // * = Block name - virtual void name(const string& name) override { m_name = name; } - // op1 = Statements - AstNode* stmtsp() const { return op1p(); } // op1 = List of statements - void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } - bool unnamed() const { return m_unnamed; } - bool isFirstInMyListOfStatements(AstNode* nodep) const override { return nodep == stmtsp(); } -}; - -class AstNodePreSel VL_NOT_FINAL : public AstNode { - // Something that becomes an AstSel -protected: - AstNodePreSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* rhs, AstNode* ths) - : AstNode{t, fl} { - setOp1p(fromp); - setOp2p(rhs); - setNOp3p(ths); - } - -public: - ASTNODE_BASE_FUNCS(NodePreSel) - AstNode* fromp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - AstNode* thsp() const { return op3p(); } - AstAttrOf* attrp() const { return VN_AS(op4p(), AttrOf); } - void fromp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - void thsp(AstNode* nodep) { return setOp3p(nodep); } - void attrp(AstAttrOf* nodep) { return setOp4p(reinterpret_cast(nodep)); } - // METHODS - virtual bool same(const AstNode*) const override { return true; } -}; - -class AstNodeProcedure VL_NOT_FINAL : public AstNode { - // IEEE procedure: initial, final, always -protected: - AstNodeProcedure(VNType t, FileLine* fl, AstNode* bodysp) - : AstNode{t, fl} { - addNOp2p(bodysp); - } - -public: - ASTNODE_BASE_FUNCS(NodeProcedure) - // METHODS - virtual void dump(std::ostream& str) const override; - AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate - void addStmtp(AstNode* nodep) { addOp2p(nodep); } - bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } -}; - -class AstNodeStmt VL_NOT_FINAL : public AstNode { - // Statement -- anything that's directly under a function - bool m_statement; // Really a statement (e.g. not a function with return) -protected: - AstNodeStmt(VNType t, FileLine* fl, bool statement = true) - : AstNode{t, fl} - , m_statement{statement} {} - -public: - ASTNODE_BASE_FUNCS(NodeStmt) - // METHODS - bool isStatement() const { return m_statement; } // Really a statement - void statement(bool flag) { m_statement = flag; } - virtual void addNextStmt(AstNode* newp, - AstNode* belowp) override; // Stop statement searchback here - virtual void addBeforeStmt(AstNode* newp, - AstNode* belowp) override; // Stop statement searchback here - virtual void dump(std::ostream& str = std::cout) const override; -}; - -class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt { -protected: - AstNodeAssign(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, - AstNode* timingControlp = nullptr) - : AstNodeStmt{t, fl} { - setOp1p(rhsp); - setOp2p(lhsp); - addNOp3p(timingControlp); - dtypeFrom(lhsp); - } - -public: - ASTNODE_BASE_FUNCS(NodeAssign) - // Clone single node, just get same type back. - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; - // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 - AstNode* rhsp() const { return op1p(); } // op1 = Assign from - AstNode* lhsp() const { return op2p(); } // op2 = Assign to - // op3 = Timing controls (delays, event controls) - AstNode* timingControlp() const { return op3p(); } - void addTimingControlp(AstNode* const np) { addNOp3p(np); } - void rhsp(AstNode* np) { setOp1p(np); } - void lhsp(AstNode* np) { setOp2p(np); } - virtual bool hasDType() const override { return true; } - virtual bool cleanRhs() const { return true; } - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } - virtual string verilogKwd() const override { return "="; } - virtual bool brokeLhsMustBeLvalue() const = 0; -}; - -class AstNodeFor VL_NOT_FINAL : public AstNodeStmt { -protected: - AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, - AstNode* bodysp) - : AstNodeStmt{t, fl} { - addNOp1p(initsp); - setOp2p(condp); - addNOp3p(incsp); - addNOp4p(bodysp); - } - -public: - ASTNODE_BASE_FUNCS(NodeFor) - AstNode* initsp() const { return op1p(); } // op1 = initial statements - AstNode* condp() const { return op2p(); } // op2 = condition to continue - AstNode* incsp() const { return op3p(); } // op3 = increment statements - AstNode* bodysp() const { return op4p(); } // op4 = body of loop - virtual bool isGateOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { -private: - VBranchPred m_branchPred; // Branch prediction as taken/untaken? - bool m_isBoundsCheck; // True if this if node was inserted for array bounds checking -protected: - AstNodeIf(VNType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) - : AstNodeStmt{t, fl} { - setOp1p(condp); - addNOp2p(ifsp); - addNOp3p(elsesp); - isBoundsCheck(false); - } - -public: - ASTNODE_BASE_FUNCS(NodeIf) - AstNode* condp() const { return op1p(); } // op1 = condition - AstNode* ifsp() const { return op2p(); } // op2 = list of true statements - AstNode* elsesp() const { return op3p(); } // op3 = list of false statements - void condp(AstNode* newp) { setOp1p(newp); } - void addIfsp(AstNode* newp) { addOp2p(newp); } - void addElsesp(AstNode* newp) { addOp3p(newp); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isGateDedupable() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - void branchPred(VBranchPred flag) { m_branchPred = flag; } - VBranchPred branchPred() const { return m_branchPred; } - void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; } - bool isBoundsCheck() const { return m_isBoundsCheck; } - bool isFirstInMyListOfStatements(AstNode* n) const override { - return n == ifsp() || n == elsesp(); - } -}; - -class AstNodeCase VL_NOT_FINAL : public AstNodeStmt { -protected: - AstNodeCase(VNType t, FileLine* fl, AstNode* exprp, AstNode* casesp) - : AstNodeStmt{t, fl} { - setOp1p(exprp); - addNOp2p(casesp); - } - -public: - ASTNODE_BASE_FUNCS(NodeCase) - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - AstNode* exprp() const { return op1p(); } // op1 = case condition - AstCaseItem* itemsp() const { - return VN_AS(op2p(), CaseItem); - } // op2 = list of case expressions - AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's - void addItemsp(AstNode* nodep) { addOp2p(nodep); } - void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } -}; - -class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath { - // An AstVarRef or AstVarXRef -private: - VAccess m_access; // Left hand side assignment - AstVar* m_varp; // [AfterLink] Pointer to variable itself - AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy - AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy - string m_name; // Name of variable - string m_selfPointer; // Output code object pointer (e.g.: 'this') - -protected: - AstNodeVarRef(VNType t, FileLine* fl, const string& name, const VAccess& access) - : AstNodeMath{t, fl} - , m_access{access} - , m_name{name} { - varp(nullptr); - } - AstNodeVarRef(VNType t, FileLine* fl, const string& name, AstVar* varp, const VAccess& access) - : AstNodeMath{t, fl} - , m_access{access} - , m_name{name} { - // May have varp==nullptr - this->varp(varp); - } - -public: - ASTNODE_BASE_FUNCS(NodeVarRef) - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual const char* broken() const override; - virtual int instrCount() const override { return widthInstrs(); } - virtual void cloneRelink() override; - virtual string name() const override { return m_name; } // * = Var name - virtual void name(const string& name) override { m_name = name; } - VAccess access() const { return m_access; } - void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor - AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable - void varp(AstVar* varp); - AstVarScope* varScopep() const { return m_varScopep; } - void varScopep(AstVarScope* varscp) { m_varScopep = varscp; } - string selfPointer() const { return m_selfPointer; } - void selfPointer(const string& value) { m_selfPointer = value; } - string selfPointerProtect(bool useSelfForThis) const; - AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } - void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } - // Know no children, and hot function, so skip iterator for speed - // See checkTreeIter also that asserts no children - // cppcheck-suppress functionConst - void iterateChildren(VNVisitor& v) {} -}; - -class AstNodeText VL_NOT_FINAL : public AstNode { -private: - string m_text; - -protected: - // Node that puts text into the output stream - AstNodeText(VNType t, FileLine* fl, const string& textp) - : AstNode{t, fl} { - m_text = textp; // Copy it - } - -public: - ASTNODE_BASE_FUNCS(NodeText) - virtual void dump(std::ostream& str = std::cout) const override; - virtual bool same(const AstNode* samep) const override { - const AstNodeText* asamep = static_cast(samep); - return text() == asamep->text(); - } - const string& text() const { return m_text; } -}; - -class AstNodeDType VL_NOT_FINAL : public AstNode { - // Ideally width() would migrate to BasicDType as that's where it makes sense, - // but it's currently so prevalent in the code we leave it here. - // Note the below members are included in AstTypeTable::Key lookups -private: - int m_width; // (also in AstTypeTable::Key) Bit width of operation - int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation - VSigning m_numeric; // (also in AstTypeTable::Key) Node is signed - // Other members - bool m_generic; // Simple globally referenced type, don't garbage collect - // Unique number assigned to each dtype during creation for IEEE matching - static int s_uniqueNum; - -protected: - // CONSTRUCTORS - AstNodeDType(VNType t, FileLine* fl) - : AstNode{t, fl} { - m_width = 0; - m_widthMin = 0; - m_generic = false; - } - -public: - ASTNODE_BASE_FUNCS(NodeDType) - // ACCESSORS - virtual void dump(std::ostream& str) const override; - virtual void dumpSmall(std::ostream& str) const; - virtual bool hasDType() const override { return true; } - /// Require VlUnpacked, instead of [] for POD elements. - /// A non-POD object is always compound, but some POD elements - /// are compound when methods calls operate on object, or when - /// under another compound-requiring object e.g. class - virtual bool isCompound() const = 0; - // (Slow) recurse down to find basic data type - virtual AstBasicDType* basicp() const = 0; - // recurses over typedefs/const/enum to next non-typeref type - virtual AstNodeDType* skipRefp() const = 0; - // recurses over typedefs to next non-typeref-or-const type - virtual AstNodeDType* skipRefToConstp() const = 0; - // recurses over typedefs/const to next non-typeref-or-enum/struct type - virtual AstNodeDType* skipRefToEnump() const = 0; - // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const = 0; - // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const = 0; - virtual bool maybePointedTo() const override { return true; } - // Iff has a non-null refDTypep(), as generic node function - virtual AstNodeDType* virtRefDTypep() const { return nullptr; } - // Iff has refDTypep(), set as generic node function - virtual void virtRefDTypep(AstNodeDType* nodep) {} - // Iff has a non-null second dtypep, as generic node function - virtual AstNodeDType* virtRefDType2p() const { return nullptr; } - // Iff has second dtype, set as generic node function - virtual void virtRefDType2p(AstNodeDType* nodep) {} - // Assignable equivalence. Call skipRefp() on this and samep before calling - virtual bool similarDType(AstNodeDType* samep) const = 0; - // Iff has a non-null subDTypep(), as generic node function - virtual AstNodeDType* subDTypep() const { return nullptr; } - virtual bool isFourstate() const; - // Ideally an IEEE $typename - virtual string prettyDTypeName() const { return prettyTypeName(); } - string prettyDTypeNameQ() const { return "'" + prettyDTypeName() + "'"; } - // - // Changing the width may confuse the data type resolution, so must clear - // TypeTable cache after use. - void widthForce(int width, int widthMin) { - m_width = width; - m_widthMin = widthMin; - } - // For backward compatibility inherit width and signing from the subDType/base type - void widthFromSub(AstNodeDType* nodep) { - m_width = nodep->m_width; - m_widthMin = nodep->m_widthMin; - m_numeric = nodep->m_numeric; - } - // - int width() const { return m_width; } - void numeric(VSigning flag) { m_numeric = flag; } - bool isSigned() const { return m_numeric.isSigned(); } - bool isNosign() const { return m_numeric.isNosign(); } - VSigning numeric() const { return m_numeric; } - int widthWords() const { return VL_WORDS_I(width()); } - int widthMin() const { // If sized, the size, if unsized the min digits to represent it - return m_widthMin ? m_widthMin : m_width; - } - int widthPow2() const; - void widthMinFromWidth() { m_widthMin = m_width; } - bool widthSized() const { return !m_widthMin || m_widthMin == m_width; } - bool generic() const { return m_generic; } - void generic(bool flag) { m_generic = flag; } - std::pair dimensions(bool includeBasic); - uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions - static int uniqueNumInc() { return ++s_uniqueNum; } - const char* charIQWN() const { - return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); - } - string cType(const string& name, bool forFunc, bool isRef) const; - bool isLiteralType() const; // Does this represent a C++ LiteralType? (can be constexpr) - -private: - class CTypeRecursed; - CTypeRecursed cTypeRecurse(bool compound) const; -}; - -class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType { - // A struct or union; common handling -private: - // TYPES - using MemberNameMap = std::map; - // MEMBERS - string m_name; // Name from upper typedef, if any - bool m_packed; - bool m_isFourstate; - MemberNameMap m_members; - const int m_uniqueNum; - -protected: - AstNodeUOrStructDType(VNType t, FileLine* fl, VSigning numericUnpack) - : AstNodeDType{t, fl} - , m_uniqueNum{uniqueNumInc()} { - // VSigning::NOSIGN overloaded to indicate not packed - m_packed = (numericUnpack != VSigning::NOSIGN); - m_isFourstate = false; // V3Width computes - numeric(VSigning::fromBool(numericUnpack.isSigned())); - } - -public: - ASTNODE_BASE_FUNCS(NodeUOrStructDType) - int uniqueNum() const { return m_uniqueNum; } - virtual const char* broken() const override; - virtual void dump(std::ostream& str) const override; - virtual bool isCompound() const override { return false; } // Because don't support unpacked - // For basicp() we reuse the size to indicate a "fake" basic type of same size - virtual AstBasicDType* basicp() const override { - return (isFourstate() - ? VN_AS(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), - BasicDType) - : VN_AS(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), - BasicDType)); - } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const override; - // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const override; - // op1 = members - virtual bool similarDType(AstNodeDType* samep) const override { - return this == samep; // We don't compare members, require exact equivalence - } - virtual string name() const override { return m_name; } - virtual void name(const string& flag) override { m_name = flag; } - AstMemberDType* membersp() const { - return VN_AS(op1p(), MemberDType); - } // op1 = AstMember list - void addMembersp(AstNode* nodep) { addNOp1p(nodep); } - bool packed() const { return m_packed; } - // packed() but as don't support unpacked, presently all structs - static bool packedUnsup() { return true; } - void isFourstate(bool flag) { m_isFourstate = flag; } - virtual bool isFourstate() const override { return m_isFourstate; } - void clearCache() { m_members.clear(); } - void repairMemberCache(); - AstMemberDType* findMember(const string& name) const { - const auto it = m_members.find(name); - return (it == m_members.end()) ? nullptr : it->second; - } - static int lo() { return 0; } - int hi() const { return dtypep()->width() - 1; } // Packed classes look like arrays - VNumRange declRange() const { return VNumRange{hi(), lo()}; } -}; - -class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType { - // Array data type, ie "some_dtype var_name [2:0]" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: RANGE (array bounds) -private: - AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) - AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable -protected: - AstNodeArrayDType(VNType t, FileLine* fl) - : AstNodeDType{t, fl} {} - -public: - ASTNODE_BASE_FUNCS(NodeArrayDType) - virtual void dump(std::ostream& str) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstNodeArrayDType* const asamep = static_cast(samep); - return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep() - && rangenp()->sameTree(asamep->rangenp())); - } // HashedDT doesn't recurse, so need to check children - virtual bool similarDType(AstNodeDType* samep) const override { - const AstNodeArrayDType* const asamep = static_cast(samep); - return (asamep && type() == samep->type() && hi() == asamep->hi() - && rangenp()->sameTree(asamep->rangenp()) - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); - } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable - void rangep(AstRange* nodep); - // METHODS - virtual AstBasicDType* basicp() const override { - return subDTypep()->basicp(); - } // (Slow) recurse down to find basic data type - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { - return elementsConst() * subDTypep()->widthTotalBytes(); - } - int left() const; - int right() const; - int hi() const; - int lo() const; - int elementsConst() const; - VNumRange declRange() const; -}; - -class AstNodeSel VL_NOT_FINAL : public AstNodeBiop { - // Single bit range extraction, perhaps with non-constant selection or array selection -protected: - AstNodeSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* bitp) - : AstNodeBiop{t, fl, fromp, bitp} {} - -public: - ASTNODE_BASE_FUNCS(NodeSel) - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression - void bitp(AstNode* nodep) { setOp2p(nodep); } - int bitConst() const; - virtual bool hasDType() const override { return true; } -}; - -class AstNodeStream VL_NOT_FINAL : public AstNodeBiop { - // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() -protected: - AstNodeStream(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : AstNodeBiop{t, fl, lhsp, rhsp} { - if (lhsp->dtypep()) dtypeSetLogicSized(lhsp->dtypep()->width(), VSigning::UNSIGNED); - } - -public: - ASTNODE_BASE_FUNCS(NodeStream) -}; - -//###################################################################### -// Tasks/functions common handling - -class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt { - // A call of a C++ function, perhaps a AstCFunc or perhaps globally named - // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. - AstCFunc* m_funcp; - string m_argTypes; - -protected: - AstNodeCCall(VNType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) - : AstNodeStmt{t, fl, true} - , m_funcp{funcp} { - addNOp2p(argsp); - } - -public: - ASTNODE_BASE_FUNCS(NodeCCall) - virtual void dump(std::ostream& str = std::cout) const override; - virtual void cloneRelink() override; - virtual const char* broken() const override; - virtual int instrCount() const override { return INSTR_COUNT_CALL; } - virtual bool same(const AstNode* samep) const override { - const AstNodeCCall* const asamep = static_cast(samep); - return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes()); - } - AstNode* exprsp() const { return op2p(); } // op2 = expressions to print - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override; - virtual bool isOutputter() const override { return !isPure(); } - AstCFunc* funcp() const { return m_funcp; } - void funcp(AstCFunc* funcp) { m_funcp = funcp; } - void argTypes(const string& str) { m_argTypes = str; } - string argTypes() const { return m_argTypes; } - // op1p reserved for AstCMethodCall - AstNode* argsp() const { return op2p(); } - void addArgsp(AstNode* nodep) { addOp2p(nodep); } -}; - -class AstNodeFTask VL_NOT_FINAL : public AstNode { -private: - string m_name; // Name of task - string m_cname; // Name of task if DPI import - uint64_t m_dpiOpenParent = 0; // DPI import open array, if !=0, how many callees - bool m_taskPublic : 1; // Public task - bool m_attrIsolateAssign : 1; // User isolate_assignments attribute - bool m_classMethod : 1; // Class method - bool m_externProto : 1; // Extern prototype - bool m_externDef : 1; // Extern definition - bool m_prototype : 1; // Just a prototype - bool m_dpiExport : 1; // DPI exported - bool m_dpiImport : 1; // DPI imported - bool m_dpiContext : 1; // DPI import context - bool m_dpiOpenChild : 1; // DPI import open array child wrapper - bool m_dpiTask : 1; // DPI import task (vs. void function) - bool m_dpiTraceInit : 1; // DPI trace_init - bool m_isConstructor : 1; // Class constructor - bool m_isHideLocal : 1; // Verilog local - bool m_isHideProtected : 1; // Verilog protected - bool m_pure : 1; // DPI import pure (vs. virtual pure) - bool m_pureVirtual : 1; // Pure virtual - bool m_recursive : 1; // Recusive or part of recursion - bool m_underGenerate : 1; // Under generate (for warning) - bool m_virtual : 1; // Virtual method in class - VLifetime m_lifetime; // Lifetime -protected: - AstNodeFTask(VNType t, FileLine* fl, const string& name, AstNode* stmtsp) - : AstNode{t, fl} - , m_name{name} - , m_taskPublic{false} - , m_attrIsolateAssign{false} - , m_classMethod{false} - , m_externProto{false} - , m_externDef{false} - , m_prototype{false} - , m_dpiExport{false} - , m_dpiImport{false} - , m_dpiContext{false} - , m_dpiOpenChild{false} - , m_dpiTask{false} - , m_dpiTraceInit{false} - , m_isConstructor{false} - , m_isHideLocal{false} - , m_isHideProtected{false} - , m_pure{false} - , m_pureVirtual{false} - , m_recursive{false} - , m_underGenerate{false} - , m_virtual{false} { - addNOp3p(stmtsp); - cname(name); // Might be overridden by dpi import/export - } - -public: - ASTNODE_BASE_FUNCS(NodeFTask) - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool maybePointedTo() const override { return true; } - virtual bool isGateOptimizable() const override { - return !((m_dpiExport || m_dpiImport) && !m_pure); - } - // {AstFunc only} op1 = Range output variable - virtual void name(const string& name) override { m_name = name; } - string cname() const { return m_cname; } - void cname(const string& cname) { m_cname = cname; } - // op1 = Output variable (functions only, nullptr for tasks) - AstNode* fvarp() const { return op1p(); } - void addFvarp(AstNode* nodep) { addNOp1p(nodep); } - bool isFunction() const { return fvarp() != nullptr; } - // op2 = Class/package scope - AstNode* classOrPackagep() const { return op2p(); } - void classOrPackagep(AstNode* nodep) { setNOp2p(nodep); } - // op3 = Statements/Ports/Vars - AstNode* stmtsp() const { return op3p(); } // op3 = List of statements - void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } - // op4 = scope name - AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); } - // MORE ACCESSORS - void dpiOpenParentInc() { ++m_dpiOpenParent; } - void dpiOpenParentClear() { m_dpiOpenParent = 0; } - uint64_t dpiOpenParent() const { return m_dpiOpenParent; } - void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } - void taskPublic(bool flag) { m_taskPublic = flag; } - bool taskPublic() const { return m_taskPublic; } - void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } - bool attrIsolateAssign() const { return m_attrIsolateAssign; } - void classMethod(bool flag) { m_classMethod = flag; } - bool classMethod() const { return m_classMethod; } - void isExternProto(bool flag) { m_externProto = flag; } - bool isExternProto() const { return m_externProto; } - void isExternDef(bool flag) { m_externDef = flag; } - bool isExternDef() const { return m_externDef; } - void prototype(bool flag) { m_prototype = flag; } - bool prototype() const { return m_prototype; } - void dpiExport(bool flag) { m_dpiExport = flag; } - bool dpiExport() const { return m_dpiExport; } - void dpiImport(bool flag) { m_dpiImport = flag; } - bool dpiImport() const { return m_dpiImport; } - void dpiContext(bool flag) { m_dpiContext = flag; } - bool dpiContext() const { return m_dpiContext; } - void dpiOpenChild(bool flag) { m_dpiOpenChild = flag; } - bool dpiOpenChild() const { return m_dpiOpenChild; } - void dpiTask(bool flag) { m_dpiTask = flag; } - bool dpiTask() const { return m_dpiTask; } - void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; } - bool dpiTraceInit() const { return m_dpiTraceInit; } - void isConstructor(bool flag) { m_isConstructor = flag; } - bool isConstructor() const { return m_isConstructor; } - bool isHideLocal() const { return m_isHideLocal; } - void isHideLocal(bool flag) { m_isHideLocal = flag; } - bool isHideProtected() const { return m_isHideProtected; } - void isHideProtected(bool flag) { m_isHideProtected = flag; } - void pure(bool flag) { m_pure = flag; } - bool pure() const { return m_pure; } - void pureVirtual(bool flag) { m_pureVirtual = flag; } - bool pureVirtual() const { return m_pureVirtual; } - void recursive(bool flag) { m_recursive = flag; } - bool recursive() const { return m_recursive; } - void underGenerate(bool flag) { m_underGenerate = flag; } - bool underGenerate() const { return m_underGenerate; } - void isVirtual(bool flag) { m_virtual = flag; } - bool isVirtual() const { return m_virtual; } - void lifetime(const VLifetime& flag) { m_lifetime = flag; } - VLifetime lifetime() const { return m_lifetime; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } -}; - -class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt { - // A reference to a task (or function) - // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. -private: - AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced - AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy - string m_name; // Name of variable - string m_dotted; // Dotted part of scope the name()ed task/func is under or "" - string m_inlinedDots; // Dotted hierarchy flattened out - bool m_pli = false; // Pli system call ($name) -protected: - AstNodeFTaskRef(VNType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp) - : AstNodeStmt{t, fl, statement} { - setOp1p(namep); - addNOp3p(pinsp); - } - AstNodeFTaskRef(VNType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp) - : AstNodeStmt{t, fl, statement} - , m_name{name} { - addNOp3p(pinsp); - } - -public: - ASTNODE_BASE_FUNCS(NodeFTaskRef) - virtual const char* broken() const override; - virtual void cloneRelink() override; - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool isGateOptimizable() const override { - return m_taskp && m_taskp->isGateOptimizable(); - } - string dotted() const { return m_dotted; } // * = Scope name or "" - string inlinedDots() const { return m_inlinedDots; } - void inlinedDots(const string& flag) { m_inlinedDots = flag; } - AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable - void taskp(AstNodeFTask* taskp) { m_taskp = taskp; } - virtual void name(const string& name) override { m_name = name; } - void dotted(const string& name) { m_dotted = name; } - AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } - void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } - bool pli() const { return m_pli; } - void pli(bool flag) { m_pli = flag; } - // op1 = namep - AstNode* namep() const { return op1p(); } - // op2 = reserved for AstMethodCall - // op3 = Pin interconnection list - AstNode* pinsp() const { return op3p(); } - void addPinsp(AstNode* nodep) { addOp3p(nodep); } - // op4 = scope tracking - AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); } - void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } -}; - -class AstNodeModule VL_NOT_FINAL : public AstNode { - // A module, package, program or interface declaration; - // something that can live directly under the TOP, - // excluding $unit package stuff -private: - string m_name; // Name of the module - const string m_origName; // Name of the module, ignoring name() changes, for dot lookup - string m_someInstanceName; // Hierarchical name of some arbitrary instance of this module. - // Used for user messages only. - bool m_modPublic : 1; // Module has public references - bool m_modTrace : 1; // Tracing this module - bool m_inLibrary : 1; // From a library, no error if not used, never top level - bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors - bool m_hierBlock : 1; // Hiearchical Block marked by HIER_BLOCK pragma - bool m_internal : 1; // Internally created - bool m_recursive : 1; // Recursive module - bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr - int m_level = 0; // 1=top module, 2=cell off top module, ... - VLifetime m_lifetime; // Lifetime - VTimescale m_timeunit; // Global time unit - VOptionBool m_unconnectedDrive; // State of `unconnected_drive -protected: - AstNodeModule(VNType t, FileLine* fl, const string& name) - : AstNode{t, fl} - , m_name{name} - , m_origName{name} - , m_modPublic{false} - , m_modTrace{false} - , m_inLibrary{false} - , m_dead{false} - , m_hierBlock{false} - , m_internal{false} - , m_recursive{false} - , m_recursiveClone{false} {} - -public: - ASTNODE_BASE_FUNCS(NodeModule) - virtual void dump(std::ostream& str) const override; - virtual bool maybePointedTo() const override { return true; } - virtual string name() const override { return m_name; } - virtual bool timescaleMatters() const = 0; - AstNode* stmtsp() const { return op2p(); } // op2 = List of statements - AstActive* activesp() const { return VN_AS(op3p(), Active); } // op3 = List of i/sblocks - // METHODS - void addInlinesp(AstNode* nodep) { addOp1p(nodep); } - void addStmtp(AstNode* nodep) { addNOp2p(nodep); } - void addActivep(AstNode* nodep) { addOp3p(nodep); } - // ACCESSORS - virtual void name(const string& name) override { m_name = name; } - virtual string origName() const override { return m_origName; } - string someInstanceName() const { return m_someInstanceName; } - void someInstanceName(const string& name) { m_someInstanceName = name; } - bool inLibrary() const { return m_inLibrary; } - void inLibrary(bool flag) { m_inLibrary = flag; } - void level(int level) { m_level = level; } - int level() const { return m_level; } - bool isTop() const { return level() == 1; } - void modPublic(bool flag) { m_modPublic = flag; } - bool modPublic() const { return m_modPublic; } - void modTrace(bool flag) { m_modTrace = flag; } - bool modTrace() const { return m_modTrace; } - void dead(bool flag) { m_dead = flag; } - bool dead() const { return m_dead; } - void hierBlock(bool flag) { m_hierBlock = flag; } - bool hierBlock() const { return m_hierBlock; } - void internal(bool flag) { m_internal = flag; } - bool internal() const { return m_internal; } - void recursive(bool flag) { m_recursive = flag; } - bool recursive() const { return m_recursive; } - void recursiveClone(bool flag) { m_recursiveClone = flag; } - bool recursiveClone() const { return m_recursiveClone; } - void lifetime(const VLifetime& flag) { m_lifetime = flag; } - VLifetime lifetime() const { return m_lifetime; } - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } - void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; } - VOptionBool unconnectedDrive() const { return m_unconnectedDrive; } -}; - -class AstNodeRange VL_NOT_FINAL : public AstNode { - // A range, sized or unsized -protected: - AstNodeRange(VNType t, FileLine* fl) - : AstNode{t, fl} {} - -public: - ASTNODE_BASE_FUNCS(NodeRange) - virtual void dump(std::ostream& str) const override; -}; - //###################################################################### // Inline VNVisitor METHODS @@ -3470,8 +2390,43 @@ inline AstNode* VNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) { return nodep->iterateSubtreeReturnEdits(*this); } -//###################################################################### +// ###################################################################### +// Standard defines for all AstNode subclasses -#include "V3AstNodes.h" +#define ASTNODE_BASE_FUNCS(name) \ + virtual ~Ast##name() override = default; \ + static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ + return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ + } \ + Ast##name* cloneTree(bool cloneNext) { \ + return static_cast(AstNode::cloneTree(cloneNext)); \ + } \ + Ast##name* clonep() const { return static_cast(AstNode::clonep()); } + +#define ASTNODE_NODE_FUNCS_NO_DTOR(name) \ + virtual void accept(VNVisitor& v) override { v.visit(this); } \ + virtual AstNode* clone() override { return new Ast##name(*this); } \ + static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ + return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ + } \ + Ast##name* cloneTree(bool cloneNext) { \ + return static_cast(AstNode::cloneTree(cloneNext)); \ + } \ + Ast##name* clonep() const { return static_cast(AstNode::clonep()); } + +#define ASTNODE_NODE_FUNCS(name) \ + virtual ~Ast##name() override = default; \ + ASTNODE_NODE_FUNCS_NO_DTOR(name) + +// Macros generated by 'astgen' +#include "V3AstNodes__gen_macros.h" + +// AstNode subclasses +#include "V3AstNodeDType.h" +#include "V3AstNodeMath.h" +#include "V3AstNodeOther.h" + +// Inline function definitions need to go last +#include "V3AstInlines.h" #endif // Guard diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 9ad974a69..d532feb01 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -17,9 +17,9 @@ #ifndef VERILATOR_V3ASTINLINES_H_ #define VERILATOR_V3ASTINLINES_H_ -#ifndef VERILATOR_V3ASTNODES_H_ +#ifndef VERILATOR_V3AST_H_ #error "Use V3Ast.h as the include" -#include "V3AstNodes.h" // This helps code analysis tools pick up symbols in V3Ast.h and V3AstNodes.h +#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h and relaed #endif //###################################################################### @@ -91,4 +91,124 @@ inline void AstIfaceRefDType::cloneRelink() { if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); } +AstRange::AstRange(FileLine* fl, int left, int right) + : ASTGEN_SUPER_Range(fl) { + setOp2p(new AstConst{fl, static_cast(left)}); + setOp3p(new AstConst{fl, static_cast(right)}); +} +AstRange::AstRange(FileLine* fl, const VNumRange& range) + : ASTGEN_SUPER_Range(fl) { + setOp2p(new AstConst{fl, static_cast(range.left())}); + setOp3p(new AstConst{fl, static_cast(range.right())}); +} +int AstRange::leftConst() const { + AstConst* const constp = VN_CAST(leftp(), Const); + return (constp ? constp->toSInt() : 0); +} +int AstRange::rightConst() const { + AstConst* const constp = VN_CAST(rightp(), Const); + return (constp ? constp->toSInt() : 0); +} + +int AstQueueDType::boundConst() const { + AstConst* const constp = VN_CAST(boundp(), Const); + return (constp ? constp->toSInt() : 0); +} + +AstPin::AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) + : ASTGEN_SUPER_Pin(fl) + , m_pinNum{pinNum} + , m_name{varname->name()} { + setNOp1p(exprp); +} + +AstDpiExportUpdated::AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep) + : ASTGEN_SUPER_DpiExportUpdated(fl) { + addOp1p(new AstVarRef{fl, varScopep, VAccess::WRITE}); +} + +AstVarScope* AstDpiExportUpdated::varScopep() const { return VN_AS(op1p(), VarRef)->varScopep(); } + +AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, + AstRange* rangep) + : ASTGEN_SUPER_PackArrayDType(fl) { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + setOp2p(rangep); + dtypep(nullptr); // V3Width will resolve + const int width = subDTypep()->width() * rangep->elementsConst(); + widthForce(width, width); +} +AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep) + : ASTGEN_SUPER_PackArrayDType(fl) { + refDTypep(dtp); + setOp2p(rangep); + dtypep(this); + const int width = subDTypep()->width() * rangep->elementsConst(); + widthForce(width, width); +} + +int AstBasicDType::hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); } +int AstBasicDType::lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); } +int AstBasicDType::elements() const { + return (rangep() ? rangep()->elementsConst() : m.m_nrange.elements()); +} +bool AstBasicDType::littleEndian() const { + return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); +} + +bool AstActive::hasInitial() const { return m_sensesp->hasInitial(); } +bool AstActive::hasSettle() const { return m_sensesp->hasSettle(); } +bool AstActive::hasClocked() const { return m_sensesp->hasClocked(); } + +AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp) + : ASTGEN_SUPER_ElabDisplay(fl) { + setOp1p(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp}); + m_displayType = dispType; +} + +AstCStmt::AstCStmt(FileLine* fl, const string& textStmt) + : ASTGEN_SUPER_CStmt(fl) { + addNOp1p(new AstText{fl, textStmt, true}); +} + +AstCMath::AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut) + : ASTGEN_SUPER_CMath(fl) + , m_cleanOut{cleanOut} + , m_pure{true} { + addNOp1p(new AstText{fl, textStmt, true}); + if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); +} + +AstVarRef::AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access) + : ASTGEN_SUPER_VarRef(fl, varp->name(), varp, access) {} +// This form only allowed post-link (see above) +AstVarRef::AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access) + : ASTGEN_SUPER_VarRef(fl, varscp->varp()->name(), varscp->varp(), access) { + varScopep(varscp); +} +bool AstVarRef::same(const AstVarRef* samep) const { + if (varScopep()) { + return (varScopep() == samep->varScopep() && access() == samep->access()); + } else { + return (selfPointer() == samep->selfPointer() && varp()->name() == samep->varp()->name() + && access() == samep->access()); + } +} +bool AstVarRef::sameNoLvalue(AstVarRef* samep) const { + if (varScopep()) { + return (varScopep() == samep->varScopep()); + } else { + return (selfPointer() == samep->selfPointer() + && (!selfPointer().empty() || !samep->selfPointer().empty()) + && varp()->name() == samep->varp()->name()); + } +} + +AstVarXRef::AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access) + : ASTGEN_SUPER_VarXRef(fl, varp->name(), varp, access) + , m_dotted{dotted} { + dtypeFrom(varp); +} + #endif // Guard diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h new file mode 100644 index 000000000..4740ec685 --- /dev/null +++ b/src/V3AstNodeDType.h @@ -0,0 +1,1341 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: AstNode sub-types representing data types +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2022 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* +// +// This files contains all 'AstNode' sub-types that relate to the +// representation of data types. +// +//************************************************************************* + +#ifndef VERILATOR_V3ASTNODEDTYPE_H_ +#define VERILATOR_V3ASTNODEDTYPE_H_ + +#ifndef VERILATOR_V3AST_H_ +#error "Use V3Ast.h as the include" +#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h +#define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE +#endif + +// === Abstract base node types (AstNode*) ===================================== + +class AstNodeDType VL_NOT_FINAL : public AstNode { + // Ideally width() would migrate to BasicDType as that's where it makes sense, + // but it's currently so prevalent in the code we leave it here. + // Note the below members are included in AstTypeTable::Key lookups +private: + int m_width; // (also in AstTypeTable::Key) Bit width of operation + int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation + VSigning m_numeric; // (also in AstTypeTable::Key) Node is signed + // Other members + bool m_generic; // Simple globally referenced type, don't garbage collect + // Unique number assigned to each dtype during creation for IEEE matching + static int s_uniqueNum; + +protected: + // CONSTRUCTORS + AstNodeDType(VNType t, FileLine* fl) + : AstNode{t, fl} { + m_width = 0; + m_widthMin = 0; + m_generic = false; + } + +public: + ASTNODE_BASE_FUNCS(NodeDType) + // ACCESSORS + virtual void dump(std::ostream& str) const override; + virtual void dumpSmall(std::ostream& str) const; + virtual bool hasDType() const override { return true; } + /// Require VlUnpacked, instead of [] for POD elements. + /// A non-POD object is always compound, but some POD elements + /// are compound when methods calls operate on object, or when + /// under another compound-requiring object e.g. class + virtual bool isCompound() const = 0; + // (Slow) recurse down to find basic data type + virtual AstBasicDType* basicp() const = 0; + // recurses over typedefs/const/enum to next non-typeref type + virtual AstNodeDType* skipRefp() const = 0; + // recurses over typedefs to next non-typeref-or-const type + virtual AstNodeDType* skipRefToConstp() const = 0; + // recurses over typedefs/const to next non-typeref-or-enum/struct type + virtual AstNodeDType* skipRefToEnump() const = 0; + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const = 0; + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthTotalBytes() const = 0; + virtual bool maybePointedTo() const override { return true; } + // Iff has a non-null refDTypep(), as generic node function + virtual AstNodeDType* virtRefDTypep() const { return nullptr; } + // Iff has refDTypep(), set as generic node function + virtual void virtRefDTypep(AstNodeDType* nodep) {} + // Iff has a non-null second dtypep, as generic node function + virtual AstNodeDType* virtRefDType2p() const { return nullptr; } + // Iff has second dtype, set as generic node function + virtual void virtRefDType2p(AstNodeDType* nodep) {} + // Assignable equivalence. Call skipRefp() on this and samep before calling + virtual bool similarDType(AstNodeDType* samep) const = 0; + // Iff has a non-null subDTypep(), as generic node function + virtual AstNodeDType* subDTypep() const { return nullptr; } + virtual bool isFourstate() const; + // Ideally an IEEE $typename + virtual string prettyDTypeName() const { return prettyTypeName(); } + string prettyDTypeNameQ() const { return "'" + prettyDTypeName() + "'"; } + // + // Changing the width may confuse the data type resolution, so must clear + // TypeTable cache after use. + void widthForce(int width, int widthMin) { + m_width = width; + m_widthMin = widthMin; + } + // For backward compatibility inherit width and signing from the subDType/base type + void widthFromSub(AstNodeDType* nodep) { + m_width = nodep->m_width; + m_widthMin = nodep->m_widthMin; + m_numeric = nodep->m_numeric; + } + // + int width() const { return m_width; } + void numeric(VSigning flag) { m_numeric = flag; } + bool isSigned() const { return m_numeric.isSigned(); } + bool isNosign() const { return m_numeric.isNosign(); } + VSigning numeric() const { return m_numeric; } + int widthWords() const { return VL_WORDS_I(width()); } + int widthMin() const { // If sized, the size, if unsized the min digits to represent it + return m_widthMin ? m_widthMin : m_width; + } + int widthPow2() const; + void widthMinFromWidth() { m_widthMin = m_width; } + bool widthSized() const { return !m_widthMin || m_widthMin == m_width; } + bool generic() const { return m_generic; } + void generic(bool flag) { m_generic = flag; } + std::pair dimensions(bool includeBasic); + uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions + static int uniqueNumInc() { return ++s_uniqueNum; } + const char* charIQWN() const { + return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); + } + string cType(const string& name, bool forFunc, bool isRef) const; + bool isLiteralType() const; // Does this represent a C++ LiteralType? (can be constexpr) + +private: + class CTypeRecursed; + CTypeRecursed cTypeRecurse(bool compound) const; +}; +class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType { + // Array data type, ie "some_dtype var_name [2:0]" + // Children: DTYPE (moved to refDTypep() in V3Width) + // Children: RANGE (array bounds) +private: + AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) + AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable +protected: + AstNodeArrayDType(VNType t, FileLine* fl) + : AstNodeDType{t, fl} {} + +public: + ASTNODE_BASE_FUNCS(NodeArrayDType) + virtual void dump(std::ostream& str) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + virtual bool same(const AstNode* samep) const override { + const AstNodeArrayDType* const asamep = static_cast(samep); + return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep() + && rangenp()->sameTree(asamep->rangenp())); + } // HashedDT doesn't recurse, so need to check children + virtual bool similarDType(AstNodeDType* samep) const override { + const AstNodeArrayDType* const asamep = static_cast(samep); + return (asamep && type() == samep->type() && hi() == asamep->hi() + && rangenp()->sameTree(asamep->rangenp()) + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable + void rangep(AstRange* nodep); + // METHODS + virtual AstBasicDType* basicp() const override { + return subDTypep()->basicp(); + } // (Slow) recurse down to find basic data type + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { + return elementsConst() * subDTypep()->widthTotalBytes(); + } + int left() const; + int right() const; + int hi() const; + int lo() const; + int elementsConst() const; + VNumRange declRange() const; +}; +class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType { + // A struct or union; common handling +private: + // TYPES + using MemberNameMap = std::map; + // MEMBERS + string m_name; // Name from upper typedef, if any + bool m_packed; + bool m_isFourstate; + MemberNameMap m_members; + const int m_uniqueNum; + +protected: + AstNodeUOrStructDType(VNType t, FileLine* fl, VSigning numericUnpack) + : AstNodeDType{t, fl} + , m_uniqueNum{uniqueNumInc()} { + // VSigning::NOSIGN overloaded to indicate not packed + m_packed = (numericUnpack != VSigning::NOSIGN); + m_isFourstate = false; // V3Width computes + numeric(VSigning::fromBool(numericUnpack.isSigned())); + } + +public: + ASTNODE_BASE_FUNCS(NodeUOrStructDType) + int uniqueNum() const { return m_uniqueNum; } + virtual const char* broken() const override; + virtual void dump(std::ostream& str) const override; + virtual bool isCompound() const override { return false; } // Because don't support unpacked + // For basicp() we reuse the size to indicate a "fake" basic type of same size + virtual AstBasicDType* basicp() const override { + return (isFourstate() + ? VN_AS(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), + BasicDType) + : VN_AS(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), + BasicDType)); + } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const override; + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthTotalBytes() const override; + // op1 = members + virtual bool similarDType(AstNodeDType* samep) const override { + return this == samep; // We don't compare members, require exact equivalence + } + virtual string name() const override { return m_name; } + virtual void name(const string& flag) override { m_name = flag; } + AstMemberDType* membersp() const { + return VN_AS(op1p(), MemberDType); + } // op1 = AstMember list + void addMembersp(AstNode* nodep) { addNOp1p(nodep); } + bool packed() const { return m_packed; } + // packed() but as don't support unpacked, presently all structs + static bool packedUnsup() { return true; } + void isFourstate(bool flag) { m_isFourstate = flag; } + virtual bool isFourstate() const override { return m_isFourstate; } + void clearCache() { m_members.clear(); } + void repairMemberCache(); + AstMemberDType* findMember(const string& name) const { + const auto it = m_members.find(name); + return (it == m_members.end()) ? nullptr : it->second; + } + static int lo() { return 0; } + int hi() const { return dtypep()->width() - 1; } // Packed classes look like arrays + VNumRange declRange() const { return VNumRange{hi(), lo()}; } +}; + +// === Concrete node types ===================================================== + +// === AstNode === +class AstEnumItem final : public AstNode { +private: + string m_name; + +public: + // Parents: ENUM + AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp) + : ASTGEN_SUPER_EnumItem(fl) + , m_name{name} { + addNOp1p(rangep); + addNOp2p(initp); + } + ASTNODE_NODE_FUNCS(EnumItem) + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual void name(const string& flag) override { m_name = flag; } + AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range for name appending + void rangep(AstRange* nodep) { addOp1p((AstNode*)nodep); } + AstNode* valuep() const { return op2p(); } // op2 = Value + void valuep(AstNode* nodep) { addOp2p(nodep); } +}; + +// === AstNodeDType === +class AstAssocArrayDType final : public AstNodeDType { + // Associative array data type, ie "[some_dtype]" + // Children: DTYPE (moved to refDTypep() in V3Width) + // Children: DTYPE (the key, which remains here as a pointer) +private: + AstNodeDType* m_refDTypep; // Elements of this type (after widthing) + AstNodeDType* m_keyDTypep; // Keys of this type (after widthing) +public: + AstAssocArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeDType* keyDtp) + : ASTGEN_SUPER_AssocArrayDType(fl) { + childDTypep(dtp); // Only for parser + keyChildDTypep(keyDtp); // Only for parser + refDTypep(nullptr); + keyDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve + } + AstAssocArrayDType(FileLine* fl, AstNodeDType* dtp, AstNodeDType* keyDtp) + : ASTGEN_SUPER_AssocArrayDType(fl) { + refDTypep(dtp); + keyDTypep(keyDtp); + dtypep(dtp); + } + ASTNODE_NODE_FUNCS(AssocArrayDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists()) + || (!m_keyDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + if (m_keyDTypep && m_keyDTypep->clonep()) m_keyDTypep = m_keyDTypep->clonep(); + } + virtual bool same(const AstNode* samep) const override { + const AstAssocArrayDType* const asamep = static_cast(samep); + if (!asamep->subDTypep()) return false; + if (!asamep->keyDTypep()) return false; + return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep()); + } + virtual bool similarDType(AstNodeDType* samep) const override { + const AstAssocArrayDType* const asamep = static_cast(samep); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + } + virtual string prettyDTypeName() const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + virtual AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + virtual AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; } + virtual void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); } + // + AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); } + void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } + // op1 = Range of variable + AstNodeDType* keyChildDTypep() const { return VN_AS(op2p(), NodeDType); } + void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); } + // METHODS + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } +}; +class AstBasicDType final : public AstNodeDType { + // Builtin atomic/vectored data type + // Children: RANGE (converted to constant in V3Width) +private: + struct Members { + VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type + VNumRange m_nrange; // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword) + bool operator==(const Members& rhs) const { + return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange; + } + } m; + // See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned) +public: + AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN) + : ASTGEN_SUPER_BasicDType(fl) { + init(kwd, signst, 0, -1, nullptr); + } + AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth) + : ASTGEN_SUPER_BasicDType(fl) { + init(VBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr); + } + AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth) + : ASTGEN_SUPER_BasicDType(fl) { + init(VBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr); + } + AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin) + : ASTGEN_SUPER_BasicDType(fl) { + init(kwd, numer, wantwidth, widthmin, nullptr); + } + AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, VNumRange range, int widthmin) + : ASTGEN_SUPER_BasicDType(fl) { + init(kwd, numer, range.elements(), widthmin, nullptr); + m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be + } + // See also addRange in verilog.y +private: + void init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin, + AstRange* rangep); + +public: + ASTNODE_NODE_FUNCS(BasicDType) + virtual void dump(std::ostream& str) const override; + // width/widthMin/numeric compared elsewhere + virtual bool same(const AstNode* samep) const override { + const AstBasicDType* const sp = static_cast(samep); + return m == sp->m; + } + virtual bool similarDType(AstNodeDType* samep) const override { + return type() == samep->type() && same(samep); + } + virtual string name() const override { return m.m_keyword.ascii(); } + virtual string prettyDTypeName() const override; + virtual const char* broken() const override { + BROKEN_RTN(dtypep() != this); + return nullptr; + } + AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range of variable + void rangep(AstRange* nodep) { setNOp1p((AstNode*)nodep); } + void setSignedState(const VSigning& signst) { + // Note NOSIGN does NOT change the state; this is required by the parser + if (signst == VSigning::UNSIGNED) { + numeric(signst); + } else if (signst == VSigning::SIGNED) { + numeric(signst); + } + } + // METHODS + virtual AstBasicDType* basicp() const override { return (AstBasicDType*)this; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const override; + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthTotalBytes() const override; + virtual bool isFourstate() const override { return keyword().isFourstate(); } + VBasicDTypeKwd keyword() const { // Avoid using - use isSomething accessors instead + return m.m_keyword; + } + bool isBitLogic() const { return keyword().isBitLogic(); } + bool isDouble() const { return keyword().isDouble(); } + bool isEventValue() const { return keyword().isEventValue(); } + bool isOpaque() const { return keyword().isOpaque(); } + bool isString() const { return keyword().isString(); } + bool isZeroInit() const { return keyword().isZeroInit(); } + bool isRanged() const { return rangep() || m.m_nrange.ranged(); } + bool isDpiBitVec() const { // DPI uses svBitVecVal + return keyword() == VBasicDTypeKwd::BIT && isRanged(); + } + bool isDpiLogicVec() const { // DPI uses svLogicVecVal + return keyword().isFourstate() && !(keyword() == VBasicDTypeKwd::LOGIC && !isRanged()); + } + bool isDpiPrimitive() const { // DPI uses a primitive type + return !isDpiBitVec() && !isDpiLogicVec(); + } + // Generally the lo/hi/left/right funcs should be used instead of nrange() + const VNumRange& nrange() const { return m.m_nrange; } + inline int hi() const; + inline int lo() const; + inline int elements() const; + int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration + int right() const { return littleEndian() ? hi() : lo(); } + inline bool littleEndian() const; + bool implicit() const { return keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT; } + VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; } + void cvtRangeConst(); // Convert to smaller representation + virtual bool isCompound() const override { return isString(); } +}; +class AstBracketArrayDType final : public AstNodeDType { + // Associative/Queue/Normal array data type, ie "[dtype_or_expr]" + // only for early parsing then becomes another data type + // Children: DTYPE (moved to refDTypep() in V3Width) + // Children: DTYPE (the key) +public: + AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* elementsp) + : ASTGEN_SUPER_BracketArrayDType(fl) { + setOp1p(dtp); // Only for parser + setOp2p(elementsp); // Only for parser + } + ASTNODE_NODE_FUNCS(BracketArrayDType) + virtual bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + virtual AstNodeDType* subDTypep() const override { return childDTypep(); } + // op2 = Range of variable + AstNode* elementsp() const { return op2p(); } + // METHODS + // Will be removed in V3Width, which relies on this + // being a child not a dtype pointed node + virtual bool maybePointedTo() const override { return false; } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } + virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } + virtual bool isCompound() const override { return true; } +}; +class AstClassRefDType final : public AstNodeDType { + // Reference to a class + // Children: PINs (for parameter settings) +private: + AstClass* m_classp; // data type pointed to, BELOW the AstTypedef + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy +public: + AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp) + : ASTGEN_SUPER_ClassRefDType(fl) + , m_classp{classp} { + dtypep(this); + addNOp4p(paramsp); + } + ASTNODE_NODE_FUNCS(ClassRefDType) + // METHODS + const char* broken() const override; + void cloneRelink() override; + virtual bool same(const AstNode* samep) const override { + const AstClassRefDType* const asamep = static_cast(samep); + return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); + } + virtual bool similarDType(AstNodeDType* samep) const override { + return this == samep || (type() == samep->type() && same(samep)); + } + virtual void dump(std::ostream& str = std::cout) const override; + virtual void dumpSmall(std::ostream& str) const override; + string name() const override; + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 0; } + virtual int widthTotalBytes() const override { return 0; } + virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } + virtual void virtRefDTypep(AstNodeDType* nodep) override {} + virtual AstNodeDType* subDTypep() const override { return nullptr; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } + AstClass* classp() const { return m_classp; } + void classp(AstClass* nodep) { m_classp = nodep; } + AstPin* paramsp() const { return VN_AS(op4p(), Pin); } + virtual bool isCompound() const override { return true; } +}; +class AstConstDType final : public AstNodeDType { + // const data type, ie "const some_dtype var_name [2:0]" + // ConstDType are removed in V3LinkLValue and become AstVar::isConst. + // When more generic types are supported AstConstDType will be propagated further. +private: + AstNodeDType* m_refDTypep = nullptr; // Inherit from this base data type +public: + AstConstDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_ConstDType(fl) { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve + widthFromSub(subDTypep()); + } + ASTNODE_NODE_FUNCS(ConstDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + virtual bool same(const AstNode* samep) const override { + const AstConstDType* const sp = static_cast(samep); + return (m_refDTypep == sp->m_refDTypep); + } + virtual bool similarDType(AstNodeDType* samep) const override { + return skipRefp()->similarDType(samep->skipRefp()); + } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + // METHODS + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } +}; +class AstDefImplicitDType final : public AstNodeDType { + // For parsing enum/struct/unions that are declared with a variable rather than typedef + // This allows "var enum {...} a,b" to share the enum definition for both variables + // After link, these become typedefs +private: + string m_name; + void* m_containerp; // In what scope is the name unique, so we can know what are duplicate + // definitions (arbitrary value) + const int m_uniqueNum; + +public: + AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType, + AstNodeDType* dtp) + : ASTGEN_SUPER_DefImplicitDType(fl) + , m_name{name} + , m_containerp{containerp} + , m_uniqueNum{uniqueNumInc()} { + childDTypep(dtp); // Only for parser + dtypep(nullptr); // V3Width will resolve + } + ASTNODE_NODE_FUNCS(DefImplicitDType) + int uniqueNum() const { return m_uniqueNum; } + virtual bool same(const AstNode* samep) const override { + const AstDefImplicitDType* const sp = static_cast(samep); + return uniqueNum() == sp->uniqueNum(); + } + virtual bool similarDType(AstNodeDType* samep) const override { + return type() == samep->type() && same(samep); + } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return dtypep() ? dtypep() : childDTypep(); + } + void* containerp() const { return m_containerp; } + // METHODS + // op1 = Range of variable + AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } + virtual string name() const override { return m_name; } + virtual void name(const string& flag) override { m_name = flag; } + virtual bool isCompound() const override { return false; } +}; +class AstDynArrayDType final : public AstNodeDType { + // Dynamic array data type, ie "[]" + // Children: DTYPE (moved to refDTypep() in V3Width) +private: + AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) +public: + AstDynArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_DynArrayDType(fl) { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve + } + AstDynArrayDType(FileLine* fl, AstNodeDType* dtp) + : ASTGEN_SUPER_DynArrayDType(fl) { + refDTypep(dtp); + dtypep(nullptr); // V3Width will resolve + } + ASTNODE_NODE_FUNCS(DynArrayDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + virtual bool same(const AstNode* samep) const override { + const AstAssocArrayDType* const asamep = static_cast(samep); + if (!asamep->subDTypep()) return false; + return subDTypep() == asamep->subDTypep(); + } + virtual bool similarDType(AstNodeDType* samep) const override { + const AstAssocArrayDType* const asamep = static_cast(samep); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + } + virtual string prettyDTypeName() const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + // METHODS + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } +}; +class AstEmptyQueueDType final : public AstNodeDType { + // For EmptyQueue +public: + explicit AstEmptyQueueDType(FileLine* fl) + : ASTGEN_SUPER_EmptyQueueDType(fl) { + dtypep(this); + } + ASTNODE_NODE_FUNCS(EmptyQueueDType) + virtual void dumpSmall(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual bool undead() const override { return true; } + virtual AstNodeDType* subDTypep() const override { return nullptr; } + virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } + virtual void virtRefDTypep(AstNodeDType* nodep) override {} + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual AstBasicDType* basicp() const override { return nullptr; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 1; } + virtual int widthTotalBytes() const override { return 1; } + virtual bool isCompound() const override { return false; } +}; +class AstEnumDType final : public AstNodeDType { + // Parents: TYPEDEF/MODULE + // Children: ENUMVALUEs +private: + string m_name; // Name from upper typedef, if any + AstNodeDType* m_refDTypep = nullptr; // Elements are of this type after V3Width + const int m_uniqueNum = 0; + +public: + AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp) + : ASTGEN_SUPER_EnumDType(fl) + , m_uniqueNum{uniqueNumInc()} { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + addNOp2p(itemsp); + dtypep(nullptr); // V3Width will resolve + widthFromSub(subDTypep()); + } + ASTNODE_NODE_FUNCS(EnumDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + int uniqueNum() const { return m_uniqueNum; } + virtual bool same(const AstNode* samep) const override { + const AstEnumDType* const sp = static_cast(samep); + return uniqueNum() == sp->uniqueNum(); + } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } // op1 = Data type + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + // op1 = Range of variable + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + virtual string name() const override { return m_name; } + virtual void name(const string& flag) override { m_name = flag; } + AstEnumItem* itemsp() const { return VN_AS(op2p(), EnumItem); } // op2 = AstEnumItem's + // METHODS + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { + return subDTypep()->skipRefToConstp(); + } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + int itemCount() const { + size_t count = 0; + for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++; + return count; + } + virtual bool isCompound() const override { return false; } +}; +class AstIfaceRefDType final : public AstNodeDType { + // Reference to an interface, either for a port, or inside parent cell +private: + FileLine* m_modportFileline; // Where modport token was + string m_cellName; // "" = no cell, such as when connects to 'input' iface + string m_ifaceName; // Interface name + string m_modportName; // "" = no modport + AstIface* m_ifacep = nullptr; // Pointer to interface; note cellp() should override + AstCell* m_cellp = nullptr; // When exact parent cell known; not a guess + AstModport* m_modportp = nullptr; // nullptr = unlinked or no modport +public: + AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName) + : ASTGEN_SUPER_IfaceRefDType(fl) + , m_modportFileline{nullptr} + , m_cellName{cellName} + , m_ifaceName{ifaceName} + , m_modportName{""} {} + AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName, + const string& ifaceName, const string& modport) + : ASTGEN_SUPER_IfaceRefDType(fl) + , m_modportFileline{modportFl} + , m_cellName{cellName} + , m_ifaceName{ifaceName} + , m_modportName{modport} {} + ASTNODE_NODE_FUNCS(IfaceRefDType) + // METHODS + virtual const char* broken() const override; + virtual void dump(std::ostream& str = std::cout) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual void cloneRelink() override; + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual int widthAlignBytes() const override { return 1; } + virtual int widthTotalBytes() const override { return 1; } + FileLine* modportFileline() const { return m_modportFileline; } + string cellName() const { return m_cellName; } + void cellName(const string& name) { m_cellName = name; } + string ifaceName() const { return m_ifaceName; } + void ifaceName(const string& name) { m_ifaceName = name; } + string modportName() const { return m_modportName; } + AstIface* ifaceViaCellp() const; // Use cellp or ifacep + AstIface* ifacep() const { return m_ifacep; } + void ifacep(AstIface* nodep) { m_ifacep = nodep; } + AstCell* cellp() const { return m_cellp; } + void cellp(AstCell* nodep) { m_cellp = nodep; } + AstModport* modportp() const { return m_modportp; } + void modportp(AstModport* modportp) { m_modportp = modportp; } + bool isModport() { return !m_modportName.empty(); } + virtual bool isCompound() const override { return true; } // But not relevant +}; +class AstMemberDType final : public AstNodeDType { + // A member of a struct/union + // PARENT: AstNodeUOrStructDType +private: + AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) + string m_name; // Name of variable + string m_tag; // Holds the string of the verilator tag -- used in XML output. + int m_lsb = -1; // Within this level's packed struct, the LSB of the first bit of the member + // UNSUP: int m_randType; // Randomization type (IEEE) +public: + AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_MemberDType(fl) + , m_name{name} { + childDTypep(dtp); // Only for parser + dtypep(nullptr); // V3Width will resolve + refDTypep(nullptr); + } + AstMemberDType(FileLine* fl, const string& name, AstNodeDType* dtp) + : ASTGEN_SUPER_MemberDType(fl) + , m_name{name} { + UASSERT(dtp, "AstMember created with no dtype"); + refDTypep(dtp); + dtypep(this); + widthFromSub(subDTypep()); + } + ASTNODE_NODE_FUNCS(MemberDType) + virtual string name() const override { return m_name; } // * = Var name + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual const char* broken() const override { + BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + // + // (Slow) recurse down to find basic data type (Note don't need virtual - + // AstVar isn't a NodeDType) + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) + AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { + return subDTypep()->skipRefToConstp(); + } + virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + // METHODS + virtual void name(const string& name) override { m_name = name; } + virtual void tag(const string& text) override { m_tag = text; } + virtual string tag() const override { return m_tag; } + int lsb() const { return m_lsb; } + void lsb(int lsb) { m_lsb = lsb; } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } +}; +class AstParamTypeDType final : public AstNodeDType { + // Parents: MODULE + // A parameter type statement; much like a var or typedef +private: + const VVarType m_varType; // Type of variable (for localparam vs. param) + string m_name; // Name of variable +public: + AstParamTypeDType(FileLine* fl, VVarType type, const string& name, VFlagChildDType, + AstNodeDType* dtp) + : ASTGEN_SUPER_ParamTypeDType(fl) + , m_varType{type} + , m_name{name} { + childDTypep(dtp); // Only for parser + dtypep(nullptr); // V3Width will resolve + } + ASTNODE_NODE_FUNCS(ParamTypeDType) + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return dtypep() ? dtypep() : childDTypep(); + } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { + return subDTypep()->skipRefToConstp(); + } + virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + virtual bool similarDType(AstNodeDType* samep) const override { + const AstParamTypeDType* const sp = static_cast(samep); + return type() == samep->type() && sp + && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()); + } + virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } + // METHODS + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual void name(const string& flag) override { m_name = flag; } + VVarType varType() const { return m_varType; } // * = Type of variable + bool isParam() const { return true; } + bool isGParam() const { return (varType() == VVarType::GPARAM); } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } +}; +class AstParseTypeDType final : public AstNodeDType { + // Parents: VAR + // During parsing, this indicates the type of a parameter is a "parameter type" + // e.g. the data type is a container of any data type +public: + explicit AstParseTypeDType(FileLine* fl) + : ASTGEN_SUPER_ParseTypeDType(fl) {} + ASTNODE_NODE_FUNCS(ParseTypeDType) + AstNodeDType* dtypep() const { return nullptr; } + // METHODS + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return nullptr; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 0; } + virtual int widthTotalBytes() const override { return 0; } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } +}; +class AstQueueDType final : public AstNodeDType { + // Queue array data type, ie "[ $ ]" + // Children: DTYPE (moved to refDTypep() in V3Width) +private: + AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) +public: + AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp) + : ASTGEN_SUPER_QueueDType(fl) { + setNOp2p(boundp); + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve + } + AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNode* boundp) + : ASTGEN_SUPER_QueueDType(fl) { + setNOp2p(boundp); + refDTypep(dtp); + dtypep(dtp); + } + ASTNODE_NODE_FUNCS(QueueDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + virtual bool same(const AstNode* samep) const override { + const AstQueueDType* const asamep = static_cast(samep); + if (!asamep->subDTypep()) return false; + return (subDTypep() == asamep->subDTypep()); + } + virtual bool similarDType(AstNodeDType* samep) const override { + const AstQueueDType* const asamep = static_cast(samep); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + } + virtual void dumpSmall(std::ostream& str) const override; + virtual string prettyDTypeName() const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + AstNode* boundp() const { return op2p(); } // op2 = Bound, nullptr = none + void boundp(AstNode* nodep) { setNOp2p(nodep); } + inline int boundConst() const; + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + // METHODS + virtual AstBasicDType* basicp() const override { return nullptr; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } +}; +class AstRefDType final : public AstNodeDType { +private: + // Pre-Width must reference the Typeref, not what it points to, as some child + // types like AstBracketArrayType will disappear and can't lose the handle + AstTypedef* m_typedefp = nullptr; // referenced type + // Post-width typedefs are removed and point to type directly + AstNodeDType* m_refDTypep = nullptr; // data type pointed to, BELOW the AstTypedef + string m_name; // Name of an AstTypedef + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy +public: + AstRefDType(FileLine* fl, const string& name) + : ASTGEN_SUPER_RefDType(fl) + , m_name{name} {} + AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp) + : ASTGEN_SUPER_RefDType(fl) + , m_name{name} { + setNOp3p(classOrPackagep); + addNOp4p(paramsp); + } + class FlagTypeOfExpr {}; // type(expr) for parser only + AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp) + : ASTGEN_SUPER_RefDType(fl) { + setOp2p(typeofp); + } + ASTNODE_NODE_FUNCS(RefDType) + // METHODS + const char* broken() const override; + void cloneRelink() override; + virtual bool same(const AstNode* samep) const override { + const AstRefDType* const asamep = static_cast(samep); + return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep + && m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep); + } + virtual bool similarDType(AstNodeDType* samep) const override { + return skipRefp()->similarDType(samep->skipRefp()); + } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } + virtual string prettyDTypeName() const override { + return subDTypep() ? subDTypep()->name() : prettyName(); + } + virtual AstBasicDType* basicp() const override { + return subDTypep() ? subDTypep()->basicp() : nullptr; + } + AstNodeDType* subDTypep() const override; + virtual AstNodeDType* skipRefp() const override { + // Skip past both the Ref and the Typedef + if (subDTypep()) { + return subDTypep()->skipRefp(); + } else { + v3fatalSrc("Typedef not linked"); + return nullptr; + } + } + virtual AstNodeDType* skipRefToConstp() const override { + if (subDTypep()) { + return subDTypep()->skipRefToConstp(); + } else { + v3fatalSrc("Typedef not linked"); + return nullptr; + } + } + virtual AstNodeDType* skipRefToEnump() const override { + if (subDTypep()) { + return subDTypep()->skipRefToEnump(); + } else { + v3fatalSrc("Typedef not linked"); + return nullptr; + } + } + virtual int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } + virtual void name(const string& flag) override { m_name = flag; } + // op1 = Range of variable + AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } + AstTypedef* typedefp() const { return m_typedefp; } + void typedefp(AstTypedef* nodep) { m_typedefp = nodep; } + AstNodeDType* refDTypep() const { return m_refDTypep; } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return refDTypep(); } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } + AstNode* typeofp() const { return op2p(); } + AstNode* classOrPackageOpp() const { return op3p(); } + AstPin* paramsp() const { return VN_AS(op4p(), Pin); } + virtual bool isCompound() const override { + v3fatalSrc("call isCompound on subdata type, not reference"); + return false; + } +}; +class AstUnsizedArrayDType final : public AstNodeDType { + // Unsized/open-range Array data type, ie "some_dtype var_name []" + // Children: DTYPE (moved to refDTypep() in V3Width) +private: + AstNodeDType* m_refDTypep; // Elements of this type (after widthing) +public: + AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_UnsizedArrayDType(fl) { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve + } + ASTNODE_NODE_FUNCS(UnsizedArrayDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + bool same(const AstNode* samep) const override; + bool similarDType(AstNodeDType* samep) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + // METHODS + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + virtual bool isCompound() const override { return true; } +}; +class AstVoidDType final : public AstNodeDType { + // For e.g. a function returning void +public: + explicit AstVoidDType(FileLine* fl) + : ASTGEN_SUPER_VoidDType(fl) { + dtypep(this); + } + ASTNODE_NODE_FUNCS(VoidDType) + virtual void dumpSmall(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual bool undead() const override { return true; } + virtual AstNodeDType* subDTypep() const override { return nullptr; } + virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } + virtual void virtRefDTypep(AstNodeDType* nodep) override {} + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual AstBasicDType* basicp() const override { return nullptr; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + // cppcheck-suppress csyleCast + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 1; } + virtual int widthTotalBytes() const override { return 1; } + virtual bool isCompound() const override { return false; } +}; +class AstWildcardArrayDType final : public AstNodeDType { + // Wildcard index type associative array data type, ie "some_dtype var_name [*]" + // Children: DTYPE (moved to refDTypep() in V3Width) +private: + AstNodeDType* m_refDTypep; // Elements of this type (after widthing) +public: + AstWildcardArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_WildcardArrayDType(fl) { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve + } + ASTNODE_NODE_FUNCS(WildcardArrayDType) + virtual const char* broken() const override { + BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) + || (!m_refDTypep && childDTypep()))); + return nullptr; + } + virtual void cloneRelink() override { + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + } + bool same(const AstNode* samep) const override; + bool similarDType(AstNodeDType* samep) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } + void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + // METHODS + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { + return sizeof(std::map); + } + virtual int widthTotalBytes() const override { + return sizeof(std::map); + } + virtual bool isCompound() const override { return true; } +}; + +// === AstNodeArrayDType === +class AstPackArrayDType final : public AstNodeArrayDType { + // Packed array data type, ie "some_dtype [2:0] var_name" + // Children: DTYPE (moved to refDTypep() in V3Width) + // Children: RANGE (array bounds) +public: + inline AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep); + inline AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep); + ASTNODE_NODE_FUNCS(PackArrayDType) + virtual string prettyDTypeName() const override; + virtual bool isCompound() const override { return false; } +}; +class AstUnpackArrayDType final : public AstNodeArrayDType { + // Array data type, ie "some_dtype var_name [2:0]" + // Children: DTYPE (moved to refDTypep() in V3Width) + // Children: RANGE (array bounds) + bool m_isCompound = false; // Non-POD subDType, or parent requires compound +public: + AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) + : ASTGEN_SUPER_UnpackArrayDType(fl) { + childDTypep(dtp); // Only for parser + refDTypep(nullptr); + setOp2p((AstNode*)rangep); + dtypep(nullptr); // V3Width will resolve + // For backward compatibility AstNodeArrayDType and others inherit + // width and signing from the subDType/base type + widthFromSub(subDTypep()); + } + AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep) + : ASTGEN_SUPER_UnpackArrayDType(fl) { + refDTypep(dtp); + setOp2p((AstNode*)rangep); + dtypep(this); + // For backward compatibility AstNodeArrayDType and others inherit + // width and signing from the subDType/base type + widthFromSub(subDTypep()); + } + ASTNODE_NODE_FUNCS(UnpackArrayDType) + virtual string prettyDTypeName() const override; + virtual bool same(const AstNode* samep) const override { + const AstUnpackArrayDType* const sp = static_cast(samep); + return m_isCompound == sp->m_isCompound; + } + // Outer dimension comes first. The first element is this node. + std::vector unpackDimensions(); + void isCompound(bool flag) { m_isCompound = flag; } + virtual bool isCompound() const override { return m_isCompound; } +}; + +// === AstNodeUOrStructDType === +class AstStructDType final : public AstNodeUOrStructDType { +public: + // VSigning below is mispurposed to indicate if packed or not + AstStructDType(FileLine* fl, VSigning numericUnpack) + : ASTGEN_SUPER_StructDType(fl, numericUnpack) {} + ASTNODE_NODE_FUNCS(StructDType) + virtual string verilogKwd() const override { return "struct"; } +}; +class AstUnionDType final : public AstNodeUOrStructDType { +public: + // UNSUP: bool isTagged; + // VSigning below is mispurposed to indicate if packed or not + AstUnionDType(FileLine* fl, VSigning numericUnpack) + : ASTGEN_SUPER_UnionDType(fl, numericUnpack) {} + ASTNODE_NODE_FUNCS(UnionDType) + virtual string verilogKwd() const override { return "union"; } +}; + +#endif // Guard diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h new file mode 100644 index 000000000..ce1ca2338 --- /dev/null +++ b/src/V3AstNodeMath.h @@ -0,0 +1,4426 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: AstNode sub-types representing expressions +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2022 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* +// +// This files contains all 'AstNode' sub-types that representing expressions, +// i.e.: those constructs that evaluate to [a possible void/unit] value. The +// root of the hierarchy is 'AstNodeMath', which could also be called +// 'AstNodeExpr'. +// +// Warning: Although the above is what we are aiming for, currently there are +// some 'AstNode' sub-types defined elsewhere, that represent expressions but +// are not part of the `AstNodeMath` hierarchy (e.g.: 'AstNodeCall' and its +// sub-types). These should eventually be fixed and moved under 'AstNodeMath'. +// +//************************************************************************* + +#ifndef VERILATOR_V3ASTNODEMATH_H_ +#define VERILATOR_V3ASTNODEMATH_H_ + +#ifndef VERILATOR_V3AST_H_ +#error "Use V3Ast.h as the include" +#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h +#define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE +#endif + +// === Abstract base node types (AstNode*) ===================================== + +class AstNodeMath VL_NOT_FINAL : public AstNode { + // Math -- anything that's part of an expression tree +protected: + AstNodeMath(VNType t, FileLine* fl) + : AstNode{t, fl} {} + +public: + ASTNODE_BASE_FUNCS(NodeMath) + // METHODS + virtual void dump(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV + // For documentation on emitC format see EmitCFunc::emitOpName + virtual string emitC() = 0; + virtual string emitSimpleOperator() { return ""; } // "" means not ok to use + virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS + virtual bool cleanOut() const = 0; // True if output has extra upper bits zero + // Someday we will generically support data types on every math node + // Until then isOpaque indicates we shouldn't constant optimize this node type + bool isOpaque() const { return VN_IS(this, CvtPackString); } +}; +class AstNodeBiop VL_NOT_FINAL : public AstNodeMath { + // Binary math +protected: + AstNodeBiop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) + : AstNodeMath{t, fl} { + setOp1p(lhs); + setOp2p(rhs); + } + +public: + ASTNODE_BASE_FUNCS(NodeBiop) + // Clone single node, just get same type back. + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; + // ACCESSORS + AstNode* lhsp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } + void lhsp(AstNode* nodep) { return setOp1p(nodep); } + void rhsp(AstNode* nodep) { return setOp2p(nodep); } + // METHODS + // Set out to evaluation of a AstConst'ed + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0; + virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero + virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero + virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size + virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size + virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors? + // Signed flavor of nodes with both flavors? + virtual bool signedFlavor() const { return false; } + virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode*) const override { return true; } +}; +class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop { + // Binary math with commutative properties +protected: + AstNodeBiCom(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) + : AstNodeBiop{t, fl, lhs, rhs} {} + +public: + ASTNODE_BASE_FUNCS(NodeBiCom) +}; +class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom { + // Binary math with commutative & associative properties +protected: + AstNodeBiComAsv(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) + : AstNodeBiCom{t, fl, lhs, rhs} {} + +public: + ASTNODE_BASE_FUNCS(NodeBiComAsv) +}; +class AstNodeSel VL_NOT_FINAL : public AstNodeBiop { + // Single bit range extraction, perhaps with non-constant selection or array selection +protected: + AstNodeSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* bitp) + : AstNodeBiop{t, fl, fromp, bitp} {} + +public: + ASTNODE_BASE_FUNCS(NodeSel) + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) + void fromp(AstNode* nodep) { setOp1p(nodep); } + AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression + void bitp(AstNode* nodep) { setOp2p(nodep); } + int bitConst() const; + virtual bool hasDType() const override { return true; } +}; +class AstNodeStream VL_NOT_FINAL : public AstNodeBiop { + // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() +protected: + AstNodeStream(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : AstNodeBiop{t, fl, lhsp, rhsp} { + if (lhsp->dtypep()) dtypeSetLogicSized(lhsp->dtypep()->width(), VSigning::UNSIGNED); + } + +public: + ASTNODE_BASE_FUNCS(NodeStream) +}; +class AstNodeSystemBiop VL_NOT_FINAL : public AstNodeBiop { +public: + AstNodeSystemBiop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : AstNodeBiop(t, fl, lhsp, rhsp) { + dtypeSetDouble(); + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath { + // Quaternary math +protected: + AstNodeQuadop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs) + : AstNodeMath{t, fl} { + setOp1p(lhs); + setOp2p(rhs); + setOp3p(ths); + setOp4p(fhs); + } + +public: + ASTNODE_BASE_FUNCS(NodeQuadop) + AstNode* lhsp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } + AstNode* thsp() const { return op3p(); } + AstNode* fhsp() const { return op4p(); } + void lhsp(AstNode* nodep) { return setOp1p(nodep); } + void rhsp(AstNode* nodep) { return setOp2p(nodep); } + void thsp(AstNode* nodep) { return setOp3p(nodep); } + void fhsp(AstNode* nodep) { return setOp4p(nodep); } + // METHODS + // Set out to evaluation of a AstConst'ed + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths, const V3Number& fhs) + = 0; + virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero + virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero + virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero + virtual bool cleanFhs() const = 0; // True if THS must have extra upper bits zero + virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size + virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size + virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size + virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode*) const override { return true; } +}; +class AstNodeTermop VL_NOT_FINAL : public AstNodeMath { + // Terminal operator -- a operator with no "inputs" +protected: + AstNodeTermop(VNType t, FileLine* fl) + : AstNodeMath{t, fl} {} + +public: + ASTNODE_BASE_FUNCS(NodeTermop) + // Know no children, and hot function, so skip iterator for speed + // See checkTreeIter also that asserts no children + // cppcheck-suppress functionConst + void iterateChildren(VNVisitor& v) {} + virtual void dump(std::ostream& str) const override; +}; +class AstNodeTriop VL_NOT_FINAL : public AstNodeMath { + // Trinary math +protected: + AstNodeTriop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) + : AstNodeMath{t, fl} { + setOp1p(lhs); + setOp2p(rhs); + setOp3p(ths); + } + +public: + ASTNODE_BASE_FUNCS(NodeTriop) + AstNode* lhsp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } + AstNode* thsp() const { return op3p(); } + void lhsp(AstNode* nodep) { return setOp1p(nodep); } + void rhsp(AstNode* nodep) { return setOp2p(nodep); } + void thsp(AstNode* nodep) { return setOp3p(nodep); } + // METHODS + virtual void dump(std::ostream& str) const override; + // Set out to evaluation of a AstConst'ed + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) + = 0; + virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero + virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero + virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero + virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size + virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size + virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode*) const override { return true; } +}; +class AstNodeCond VL_NOT_FINAL : public AstNodeTriop { +protected: + AstNodeCond(VNType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) + : AstNodeTriop{t, fl, condp, expr1p, expr2p} { + if (expr1p) { + dtypeFrom(expr1p); + } else if (expr2p) { + dtypeFrom(expr2p); + } + } + +public: + ASTNODE_BASE_FUNCS(NodeCond) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override; + AstNode* condp() const { return op1p(); } // op1 = Condition + AstNode* expr1p() const { return op2p(); } // op2 = If true... + AstNode* expr2p() const { return op3p(); } // op3 = If false... + virtual string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; } + virtual string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; } + virtual bool cleanOut() const override { return false; } // clean if e1 & e2 clean + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } // Propagates up + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0; +}; +class AstNodeUniop VL_NOT_FINAL : public AstNodeMath { + // Unary math +protected: + AstNodeUniop(VNType t, FileLine* fl, AstNode* lhsp) + : AstNodeMath{t, fl} { + dtypeFrom(lhsp); + setOp1p(lhsp); + } + +public: + ASTNODE_BASE_FUNCS(NodeUniop) + AstNode* lhsp() const { return op1p(); } + void lhsp(AstNode* nodep) { return setOp1p(nodep); } + // METHODS + virtual void dump(std::ostream& str) const override; + // Set out to evaluation of a AstConst'ed lhs + virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; + virtual bool cleanLhs() const = 0; + virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size + virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors? + // Signed flavor of nodes with both flavors? + virtual bool signedFlavor() const { return false; } + virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode*) const override { return true; } +}; +class AstNodeSystemUniop VL_NOT_FINAL : public AstNodeUniop { +public: + AstNodeSystemUniop(VNType t, FileLine* fl, AstNode* lhsp) + : AstNodeUniop(t, fl, lhsp) { + dtypeSetDouble(); + } + ASTNODE_BASE_FUNCS(NodeSystemUniop) + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath { + // An AstVarRef or AstVarXRef +private: + VAccess m_access; // Left hand side assignment + AstVar* m_varp; // [AfterLink] Pointer to variable itself + AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy + string m_name; // Name of variable + string m_selfPointer; // Output code object pointer (e.g.: 'this') + +protected: + AstNodeVarRef(VNType t, FileLine* fl, const string& name, const VAccess& access) + : AstNodeMath{t, fl} + , m_access{access} + , m_name{name} { + varp(nullptr); + } + AstNodeVarRef(VNType t, FileLine* fl, const string& name, AstVar* varp, const VAccess& access) + : AstNodeMath{t, fl} + , m_access{access} + , m_name{name} { + // May have varp==nullptr + this->varp(varp); + } + +public: + ASTNODE_BASE_FUNCS(NodeVarRef) + virtual void dump(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + virtual const char* broken() const override; + virtual int instrCount() const override { return widthInstrs(); } + virtual void cloneRelink() override; + virtual string name() const override { return m_name; } // * = Var name + virtual void name(const string& name) override { m_name = name; } + VAccess access() const { return m_access; } + void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor + AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable + void varp(AstVar* varp); + AstVarScope* varScopep() const { return m_varScopep; } + void varScopep(AstVarScope* varscp) { m_varScopep = varscp; } + string selfPointer() const { return m_selfPointer; } + void selfPointer(const string& value) { m_selfPointer = value; } + string selfPointerProtect(bool useSelfForThis) const; + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } + // Know no children, and hot function, so skip iterator for speed + // See checkTreeIter also that asserts no children + // cppcheck-suppress functionConst + void iterateChildren(VNVisitor& v) {} +}; + +// === Concrete node types ===================================================== + +// === AstNodeMath === +class AstAddrOfCFunc final : public AstNodeMath { + // Get address of CFunc +private: + AstCFunc* m_funcp; // Pointer to function itself + +public: + AstAddrOfCFunc(FileLine* fl, AstCFunc* funcp) + : ASTGEN_SUPER_AddrOfCFunc(fl) + , m_funcp{funcp} { + dtypep(findCHandleDType()); + } + +public: + ASTNODE_NODE_FUNCS(AddrOfCFunc) + virtual void cloneRelink() override; + virtual const char* broken() const override; + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + AstCFunc* funcp() const { return m_funcp; } +}; +class AstCMath final : public AstNodeMath { +private: + const bool m_cleanOut; + bool m_pure; // Pure optimizable +public: + // Emit C textual math function (like AstUCFunc) + AstCMath(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_CMath(fl) + , m_cleanOut{true} + , m_pure{false} { + addOp1p(exprsp); + dtypeFrom(exprsp); + } + inline AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true); + ASTNODE_NODE_FUNCS(CMath) + virtual bool isGateOptimizable() const override { return m_pure; } + virtual bool isPredictOptimizable() const override { return m_pure; } + virtual bool cleanOut() const override { return m_cleanOut; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + void addBodysp(AstNode* nodep) { addNOp1p(nodep); } + AstNode* bodysp() const { return op1p(); } // op1 = expressions to print + bool pure() const { return m_pure; } + void pure(bool flag) { m_pure = flag; } +}; +class AstConsAssoc final : public AstNodeMath { + // Construct an assoc array and return object, '{} + // Parents: math + // Children: expression (elements or other queues) +public: + AstConsAssoc(FileLine* fl, AstNode* defaultp) + : ASTGEN_SUPER_ConsAssoc(fl) { + setNOp1p(defaultp); + } + ASTNODE_NODE_FUNCS(ConsAssoc) + virtual string emitVerilog() override { return "'{}"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* defaultp() const { return op1p(); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstConsDynArray final : public AstNodeMath { + // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} + // Parents: math + // Children: expression (elements or other queues) +public: + explicit AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) + : ASTGEN_SUPER_ConsDynArray(fl) { + setNOp1p(lhsp); + setNOp2p(rhsp); + } + ASTNODE_NODE_FUNCS(ConsDynArray) + virtual string emitVerilog() override { return "'{%l, %r}"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* lhsp() const { return op1p(); } // op1 = expression + AstNode* rhsp() const { return op2p(); } // op2 = expression + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstConsQueue final : public AstNodeMath { + // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} + // Parents: math + // Children: expression (elements or other queues) +public: + explicit AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) + : ASTGEN_SUPER_ConsQueue(fl) { + setNOp1p(lhsp); + setNOp2p(rhsp); + } + ASTNODE_NODE_FUNCS(ConsQueue) + virtual string emitVerilog() override { return "'{%l, %r}"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* lhsp() const { return op1p(); } // op1 = expression + AstNode* rhsp() const { return op2p(); } // op2 = expression + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstConsWildcard final : public AstNodeMath { + // Construct a wildcard assoc array and return object, '{} + // Parents: math + // Children: expression (elements or other queues) +public: + AstConsWildcard(FileLine* fl, AstNode* defaultp) + : ASTGEN_SUPER_ConsWildcard(fl) { + setNOp1p(defaultp); + } + ASTNODE_NODE_FUNCS(ConsWildcard) + virtual string emitVerilog() override { return "'{}"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* defaultp() const { return op1p(); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstConst final : public AstNodeMath { + // A constant +private: + V3Number m_num; // Constant value + void initWithNumber() { + if (m_num.isDouble()) { + dtypeSetDouble(); + } else if (m_num.isString()) { + dtypeSetString(); + } else { + dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()), + VSigning::fromBool(m_num.isSigned())); + } + m_num.nodep(this); + } + +public: + AstConst(FileLine* fl, const V3Number& num) + : ASTGEN_SUPER_Const(fl) + , m_num(num) { + initWithNumber(); + } + class WidthedValue {}; // for creator type-overload selection + AstConst(FileLine* fl, WidthedValue, int width, uint32_t value) + : ASTGEN_SUPER_Const(fl) + , m_num(this, width, value) { + initWithNumber(); + } + class DTyped {}; // for creator type-overload selection + // Zero/empty constant with a type matching nodetypep + AstConst(FileLine* fl, DTyped, const AstNodeDType* nodedtypep) + : ASTGEN_SUPER_Const(fl) + , m_num(this, nodedtypep) { + initWithNumber(); + } + class StringToParse {}; // for creator type-overload selection + AstConst(FileLine* fl, StringToParse, const char* sourcep) + : ASTGEN_SUPER_Const(fl) + , m_num(this, sourcep) { + initWithNumber(); + } + class VerilogStringLiteral {}; // for creator type-overload selection + AstConst(FileLine* fl, VerilogStringLiteral, const string& str) + : ASTGEN_SUPER_Const(fl) + , m_num(V3Number::VerilogStringLiteral(), this, str) { + initWithNumber(); + } + AstConst(FileLine* fl, uint32_t num) + : ASTGEN_SUPER_Const(fl) + , m_num(this, 32, num) { + dtypeSetLogicUnsized(m_num.width(), 0, VSigning::UNSIGNED); + } + class Unsized32 {}; // for creator type-overload selection + AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value + : ASTGEN_SUPER_Const(fl) + , m_num(this, 32, num) { + m_num.width(32, false); + dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::UNSIGNED); + } + class Signed32 {}; // for creator type-overload selection + AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value + : ASTGEN_SUPER_Const(fl) + , m_num(this, 32, num) { + m_num.width(32, true); + dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::SIGNED); + } + class Unsized64 {}; // for creator type-overload selection + AstConst(FileLine* fl, Unsized64, uint64_t num) + : ASTGEN_SUPER_Const(fl) + , m_num(this, 64, 0) { + m_num.setQuad(num); + dtypeSetLogicSized(64, VSigning::UNSIGNED); + } + class SizedEData {}; // for creator type-overload selection + AstConst(FileLine* fl, SizedEData, uint64_t num) + : ASTGEN_SUPER_Const(fl) + , m_num(this, VL_EDATASIZE, 0) { + m_num.setQuad(num); + dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED); + } + class RealDouble {}; // for creator type-overload selection + AstConst(FileLine* fl, RealDouble, double num) + : ASTGEN_SUPER_Const(fl) + , m_num(this, 64) { + m_num.setDouble(num); + dtypeSetDouble(); + } + class String {}; // for creator type-overload selection + AstConst(FileLine* fl, String, const string& num) + : ASTGEN_SUPER_Const(fl) + , m_num(V3Number::String(), this, num) { + dtypeSetString(); + } + class BitFalse {}; + AstConst(FileLine* fl, BitFalse) // Shorthand const 0, dtype should be a logic of size 1 + : ASTGEN_SUPER_Const(fl) + , m_num(this, 1, 0) { + dtypeSetBit(); + } + // Shorthand const 1 (or with argument 0/1), dtype should be a logic of size 1 + class BitTrue {}; + AstConst(FileLine* fl, BitTrue, bool on = true) + : ASTGEN_SUPER_Const(fl) + , m_num(this, 1, on) { + dtypeSetBit(); + } + class Null {}; + AstConst(FileLine* fl, Null) + : ASTGEN_SUPER_Const(fl) + , m_num(V3Number::Null{}, this) { + dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here + initWithNumber(); + } + ASTNODE_NODE_FUNCS(Const) + virtual string name() const override { return num().ascii(); } // * = Value + const V3Number& num() const { return m_num; } // * = Value + V3Number& num() { return m_num; } // * = Value + uint32_t toUInt() const { return num().toUInt(); } + int32_t toSInt() const { return num().toSInt(); } + uint64_t toUQuad() const { return num().toUQuad(); } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* samep) const override { + const AstConst* const sp = static_cast(samep); + return num().isCaseEq(sp->num()); + } + virtual int instrCount() const override { return widthInstrs(); } + bool isEqAllOnes() const { return num().isEqAllOnes(width()); } + bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); } + // Parse string and create appropriate type of AstConst. + // May return nullptr on parse failure. + static AstConst* parseParamLiteral(FileLine* fl, const string& literal); +}; +class AstEmptyQueue final : public AstNodeMath { +public: + explicit AstEmptyQueue(FileLine* fl) + : ASTGEN_SUPER_EmptyQueue(fl) {} + ASTNODE_NODE_FUNCS(EmptyQueue) + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitVerilog() override { return "{}"; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual bool cleanOut() const override { return true; } +}; +class AstEnumItemRef final : public AstNodeMath { +private: + AstEnumItem* m_itemp; // [AfterLink] Pointer to item + AstNodeModule* m_classOrPackagep; // Package hierarchy +public: + AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep) + : ASTGEN_SUPER_EnumItemRef(fl) + , m_itemp{itemp} + , m_classOrPackagep{classOrPackagep} { + dtypeFrom(m_itemp); + } + ASTNODE_NODE_FUNCS(EnumItemRef) + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return itemp()->name(); } + virtual int instrCount() const override { return 0; } + const char* broken() const override; + virtual void cloneRelink() override { + if (m_itemp->clonep()) m_itemp = m_itemp->clonep(); + } + virtual bool same(const AstNode* samep) const override { + const AstEnumItemRef* const sp = static_cast(samep); + return itemp() == sp->itemp(); + } + AstEnumItem* itemp() const { return m_itemp; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } +}; +class AstExprStmt final : public AstNodeMath { + // Perform a statement, often assignment inside an expression/math node, + // the parent gets passed the 'resultp()'. + // resultp is evaluated AFTER the statement(s). +public: + AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNode* resultp) + : ASTGEN_SUPER_ExprStmt(fl) { + addOp1p(stmtsp); + setOp2p(resultp); // Possibly in future nullptr could mean return rhsp() + dtypeFrom(resultp); + } + ASTNODE_NODE_FUNCS(ExprStmt) + // ACCESSORS + AstNode* stmtsp() const { return op1p(); } + void addStmtsp(AstNode* nodep) { addOp1p(nodep); } + AstNode* resultp() const { return op2p(); } + // METHODS + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode*) const override { return true; } +}; +class AstFError final : public AstNodeMath { +public: + AstFError(FileLine* fl, AstNode* filep, AstNode* strp) + : ASTGEN_SUPER_FError(fl) { + setOp1p(filep); + setOp2p(strp); + } + ASTNODE_NODE_FUNCS(FError) + virtual string emitVerilog() override { return "%f$ferror(%l, %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const { return true; } + virtual bool sizeMattersLhs() const { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + void filep(AstNode* nodep) { setOp1p(nodep); } + AstNode* filep() const { return op1p(); } + void strp(AstNode* nodep) { setOp2p(nodep); } + AstNode* strp() const { return op2p(); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstFRead final : public AstNodeMath { + // Parents: expr + // Children: varrefs to load + // Children: file which must be a varref + // Children: low index + // Children: count +public: + AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, AstNode* startp, AstNode* countp) + : ASTGEN_SUPER_FRead(fl) { + setOp1p(memp); + setOp2p(filep); + setNOp3p(startp); + setNOp4p(countp); + } + ASTNODE_NODE_FUNCS(FRead) + virtual string verilogKwd() const override { return "$fread"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* memp() const { return op1p(); } + void memp(AstNode* nodep) { setOp1p(nodep); } + AstNode* filep() const { return op2p(); } + void filep(AstNode* nodep) { setOp2p(nodep); } + AstNode* startp() const { return op3p(); } + void startp(AstNode* nodep) { setNOp3p(nodep); } + AstNode* countp() const { return op4p(); } + void countp(AstNode* nodep) { setNOp4p(nodep); } +}; +class AstFRewind final : public AstNodeMath { + // Parents: stmtlist + // Children: file which must be a varref +public: + AstFRewind(FileLine* fl, AstNode* filep) + : ASTGEN_SUPER_FRewind(fl) { + setNOp2p(filep); + } + ASTNODE_NODE_FUNCS(FRewind) + virtual string verilogKwd() const override { return "$frewind"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op2p(); } + void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } +}; +class AstFScanF final : public AstNodeMath { + // Parents: expr + // Children: file which must be a varref + // Children: varrefs to load +private: + string m_text; + +public: + AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp) + : ASTGEN_SUPER_FScanF(fl) + , m_text{text} { + addNOp1p(exprsp); + setNOp2p(filep); + } + ASTNODE_NODE_FUNCS(FScanF) + virtual string name() const override { return m_text; } + virtual string verilogKwd() const override { return "$fscanf"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* samep) const override { + return text() == static_cast(samep)->text(); + } + AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output + void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output + string text() const { return m_text; } // * = Text to display + void text(const string& text) { m_text = text; } + AstNode* filep() const { return op2p(); } + void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } +}; +class AstFSeek final : public AstNodeMath { + // Parents: expr + // Children: file which must be a varref + // Children: offset + // Children: operation +public: + AstFSeek(FileLine* fl, AstNode* filep, AstNode* offset, AstNode* operation) + : ASTGEN_SUPER_FSeek(fl) { + setOp2p(filep); + setNOp3p(offset); + setNOp4p(operation); + } + ASTNODE_NODE_FUNCS(FSeek) + virtual string verilogKwd() const override { return "$fseek"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op2p(); } + void filep(AstNode* nodep) { setOp2p(nodep); } + AstNode* offset() const { return op3p(); } + void offset(AstNode* nodep) { setNOp3p(nodep); } + AstNode* operation() const { return op4p(); } + void operation(AstNode* nodep) { setNOp4p(nodep); } +}; +class AstFTell final : public AstNodeMath { + // Parents: stmtlist + // Children: file which must be a varref +public: + AstFTell(FileLine* fl, AstNode* filep) + : ASTGEN_SUPER_FTell(fl) { + setNOp2p(filep); + } + ASTNODE_NODE_FUNCS(FTell) + virtual string verilogKwd() const override { return "$ftell"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op2p(); } + void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } +}; +class AstFell final : public AstNodeMath { + // Verilog $fell + // Parents: math + // Children: expression +public: + AstFell(FileLine* fl, AstNode* exprp) + : ASTGEN_SUPER_Fell(fl) { + addOp1p(exprp); + } + ASTNODE_NODE_FUNCS(Fell) + virtual string emitVerilog() override { return "$fell(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* exprp() const { return op1p(); } // op1 = expression + AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain + void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstGatePin final : public AstNodeMath { + // Possibly expand a gate primitive input pin value to match the range of the gate primitive +public: + AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep) + : ASTGEN_SUPER_GatePin(fl) { + setOp1p(lhsp); + setOp2p((AstNode*)rangep); + } + ASTNODE_NODE_FUNCS(GatePin) + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + AstNode* exprp() const { return op1p(); } // op1 = Pin expression + AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Range of pin +}; +class AstImplication final : public AstNodeMath { + // Verilog |-> |=> + // Parents: math + // Children: expression +public: + AstImplication(FileLine* fl, AstNode* lhs, AstNode* rhs) + : ASTGEN_SUPER_Implication(fl) { + setOp1p(lhs); + setOp2p(rhs); + } + ASTNODE_NODE_FUNCS(Implication) + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* lhsp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } + void lhsp(AstNode* nodep) { return setOp1p(nodep); } + void rhsp(AstNode* nodep) { return setOp2p(nodep); } + AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain + void sentreep(AstSenTree* sentreep) { addOp4p((AstNode*)sentreep); } // op4 = clock domain + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstInside final : public AstNodeMath { +public: + AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp) + : ASTGEN_SUPER_Inside(fl) { + addOp1p(exprp); + addOp2p(itemsp); + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Inside) + AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with + // op2 = RHS, possibly a list of expr or AstInsideRange + AstNode* itemsp() const { return op2p(); } + virtual string emitVerilog() override { return "%l inside { %r }"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } // NA +}; +class AstInsideRange final : public AstNodeMath { +public: + AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_InsideRange(fl) { + addOp1p(lhsp); + addOp2p(rhsp); + } + ASTNODE_NODE_FUNCS(InsideRange) + AstNode* lhsp() const { return op1p(); } // op1 = LHS + AstNode* rhsp() const { return op2p(); } // op2 = RHS + virtual string emitVerilog() override { return "[%l:%r]"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } // NA + // Create AstAnd(AstGte(...), AstLte(...)) + AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp); +}; +class AstLambdaArgRef final : public AstNodeMath { + // Lambda argument usage + // These are not AstVarRefs because we need to be able to delete/clone lambdas during + // optimizations and AstVar's are painful to remove. +private: + string m_name; // Name of variable + bool m_index; // Index, not value + +public: + AstLambdaArgRef(FileLine* fl, const string& name, bool index) + : ASTGEN_SUPER_LambdaArgRef(fl) + , m_name{name} + , m_index(index) {} + ASTNODE_NODE_FUNCS(LambdaArgRef) + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual string emitVerilog() override { return name(); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual string name() const override { return m_name; } // * = Var name + virtual void name(const string& name) override { m_name = name; } + bool index() const { return m_index; } +}; +class AstMemberSel final : public AstNodeMath { + // Parents: math|stmt + // Children: varref|arraysel, math +private: + // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it + string m_name; + AstVar* m_varp = nullptr; // Post link, variable within class that is target of selection +public: + AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name) + : ASTGEN_SUPER_MemberSel(fl) + , m_name{name} { + setOp1p(fromp); + dtypep(nullptr); // V3Width will resolve + } + AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp) + : ASTGEN_SUPER_MemberSel(fl) + , m_name{dtp->name()} { + setOp1p(fromp); + dtypep(dtp); + } + ASTNODE_NODE_FUNCS(MemberSel) + void cloneRelink() override; + const char* broken() const override; + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* samep) const override { + return true; + } // dtype comparison does it + virtual int instrCount() const override { return widthInstrs(); } + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) + void fromp(AstNode* nodep) { setOp1p(nodep); } + AstVar* varp() const { return m_varp; } + void varp(AstVar* nodep) { m_varp = nodep; } +}; +class AstNewCopy final : public AstNodeMath { + // New as shallow copy + // Parents: math|stmt + // Children: varref|arraysel, math +public: + AstNewCopy(FileLine* fl, AstNode* rhsp) + : ASTGEN_SUPER_NewCopy(fl) { + dtypeFrom(rhsp); // otherwise V3Width will resolve + setNOp1p(rhsp); + } + ASTNODE_NODE_FUNCS(NewCopy) + virtual string emitVerilog() override { return "new"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* rhsp() const { return op1p(); } +}; +class AstNewDynamic final : public AstNodeMath { + // New for dynamic array + // Parents: math|stmt + // Children: varref|arraysel, math +public: + AstNewDynamic(FileLine* fl, AstNode* sizep, AstNode* rhsp) + : ASTGEN_SUPER_NewDynamic(fl) { + dtypeFrom(rhsp); // otherwise V3Width will resolve + setNOp1p(sizep); + setNOp2p(rhsp); + } + ASTNODE_NODE_FUNCS(NewDynamic) + virtual string emitVerilog() override { return "new"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* sizep() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } +}; +class AstPast final : public AstNodeMath { + // Verilog $past + // Parents: math + // Children: expression +public: + AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp) + : ASTGEN_SUPER_Past(fl) { + addOp1p(exprp); + addNOp2p(ticksp); + } + ASTNODE_NODE_FUNCS(Past) + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* exprp() const { return op1p(); } // op1 = expression + AstNode* ticksp() const { return op2p(); } // op2 = ticks or nullptr means 1 + AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain + void sentreep(AstSenTree* sentreep) { addOp4p((AstNode*)sentreep); } // op4 = clock domain + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstPatMember final : public AstNodeMath { + // Verilog '{a} or '{a{b}} + // Parents: AstPattern + // Children: expression, AstPattern, replication count +private: + bool m_default = false; + +public: + AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) + : ASTGEN_SUPER_PatMember(fl) { + addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); + } + ASTNODE_NODE_FUNCS(PatMember) + virtual string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs() * 2; } + virtual void dump(std::ostream& str = std::cout) const override; + // op1 = expression to assign or another AstPattern (list if replicated) + AstNode* lhssp() const { return op1p(); } + AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) + AstNode* repp() const { return op3p(); } // op3 = replication count, or nullptr for count 1 + bool isDefault() const { return m_default; } + void isDefault(bool flag) { m_default = flag; } +}; +class AstPattern final : public AstNodeMath { + // Verilog '{a,b,c,d...} + // Parents: AstNodeAssign, AstPattern, ... + // Children: expression, AstPattern, AstPatReplicate +public: + AstPattern(FileLine* fl, AstNode* itemsp) + : ASTGEN_SUPER_Pattern(fl) { + addNOp2p(itemsp); + } + ASTNODE_NODE_FUNCS(Pattern) + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } + // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + AstNode* itemsp() const { return op2p(); } // op2 = AstPatReplicate, AstPatMember, etc + void addItemsp(AstNode* nodep) { addOp2p(nodep); } +}; +class AstRand final : public AstNodeMath { + // $random/$random(seed) or $urandom/$urandom(seed) + // Return a random number, based upon width() +private: + const bool m_urandom = false; // $urandom vs $random + const bool m_reset = false; // Random reset, versus always random +public: + class Reset {}; + AstRand(FileLine* fl, Reset, AstNodeDType* dtp, bool reset) + : ASTGEN_SUPER_Rand(fl) + , m_reset{reset} { + dtypep(dtp); + } + AstRand(FileLine* fl, AstNode* seedp, bool urandom) + : ASTGEN_SUPER_Rand(fl) + , m_urandom(urandom) { + setNOp1p(seedp); + } + ASTNODE_NODE_FUNCS(Rand) + virtual string emitVerilog() override { + return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)") + : (m_urandom ? "%f$urandom()" : "%f$random()"); + } + virtual string emitC() override { + return m_reset ? "VL_RAND_RESET_%nq(%nw, %P)" + : seedp() + ? (urandom() ? "VL_URANDOM_SEEDED_%nq%lq(%li)" : "VL_RANDOM_SEEDED_%nq%lq(%li)") + : isWide() ? "VL_RANDOM_%nq(%nw, %P)" // + : "VL_RANDOM_%nq()"; + } + virtual bool cleanOut() const override { return false; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool combinable(const AstRand* samep) const { + return !seedp() && !samep->seedp() && reset() == samep->reset() + && urandom() == samep->urandom(); + } + AstNode* seedp() const { return op1p(); } + bool reset() const { return m_reset; } + bool urandom() const { return m_urandom; } +}; +class AstRose final : public AstNodeMath { + // Verilog $rose + // Parents: math + // Children: expression +public: + AstRose(FileLine* fl, AstNode* exprp) + : ASTGEN_SUPER_Rose(fl) { + addOp1p(exprp); + } + ASTNODE_NODE_FUNCS(Rose) + virtual string emitVerilog() override { return "$rose(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* exprp() const { return op1p(); } // op1 = expression + AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain + void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstSScanF final : public AstNodeMath { + // Parents: expr + // Children: file which must be a varref + // Children: varrefs to load +private: + string m_text; + +public: + AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp) + : ASTGEN_SUPER_SScanF(fl) + , m_text{text} { + addNOp1p(exprsp); + setOp2p(fromp); + } + ASTNODE_NODE_FUNCS(SScanF) + virtual string name() const override { return m_text; } + virtual string verilogKwd() const override { return "$sscanf"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* samep) const override { + return text() == static_cast(samep)->text(); + } + AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output + void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output + string text() const { return m_text; } // * = Text to display + void text(const string& text) { m_text = text; } + AstNode* fromp() const { return op2p(); } + void fromp(AstNode* nodep) { setOp2p(nodep); } +}; +class AstSampled final : public AstNodeMath { + // Verilog $sampled + // Parents: math + // Children: expression +public: + AstSampled(FileLine* fl, AstNode* exprp) + : ASTGEN_SUPER_Sampled(fl) { + addOp1p(exprp); + } + ASTNODE_NODE_FUNCS(Sampled) + virtual string emitVerilog() override { return "$sampled(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return 0; } + AstNode* exprp() const { return op1p(); } // op1 = expression + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstScopeName final : public AstNodeMath { + // For display %m and DPI context imports + // Parents: DISPLAY + // Children: TEXT +private: + bool m_dpiExport = false; // Is for dpiExport + const bool m_forFormat = false; // Is for a format %m + string scopeNameFormatter(AstText* scopeTextp) const; + string scopePrettyNameFormatter(AstText* scopeTextp) const; + +public: + class ForFormat {}; + AstScopeName(FileLine* fl, bool forFormat) + : ASTGEN_SUPER_ScopeName(fl) + , m_forFormat{forFormat} { + dtypeSetUInt64(); + } + ASTNODE_NODE_FUNCS(ScopeName) + virtual bool same(const AstNode* samep) const override { + return (m_dpiExport == static_cast(samep)->m_dpiExport + && m_forFormat == static_cast(samep)->m_forFormat); + } + virtual string emitVerilog() override { return ""; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; + AstText* scopeAttrp() const { return VN_AS(op1p(), Text); } + void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } + AstText* scopeEntrp() const { return VN_AS(op2p(), Text); } + void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } + string scopeSymName() const { // Name for __Vscope variable including children + return scopeNameFormatter(scopeAttrp()); + } + string scopeDpiName() const { // Name for DPI import scope + return scopeNameFormatter(scopeEntrp()); + } + string scopePrettySymName() const { // Name for __Vscope variable including children + return scopePrettyNameFormatter(scopeAttrp()); + } + string scopePrettyDpiName() const { // Name for __Vscope variable including children + return scopePrettyNameFormatter(scopeEntrp()); + } + bool dpiExport() const { return m_dpiExport; } + void dpiExport(bool flag) { m_dpiExport = flag; } + bool forFormat() const { return m_forFormat; } +}; +class AstSetAssoc final : public AstNodeMath { + // Set an assoc array element and return object, '{} + // Parents: math + // Children: expression (elements or other queues) +public: + AstSetAssoc(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep) + : ASTGEN_SUPER_SetAssoc(fl) { + setOp1p(lhsp); + setNOp2p(keyp); + setOp3p(valuep); + } + ASTNODE_NODE_FUNCS(SetAssoc) + virtual string emitVerilog() override { return "'{}"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* lhsp() const { return op1p(); } + AstNode* keyp() const { return op2p(); } + AstNode* valuep() const { return op3p(); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstSetWildcard final : public AstNodeMath { + // Set a wildcard assoc array element and return object, '{} + // Parents: math + // Children: expression (elements or other queues) +public: + AstSetWildcard(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep) + : ASTGEN_SUPER_SetWildcard(fl) { + setOp1p(lhsp); + setNOp2p(keyp); + setOp3p(valuep); + } + ASTNODE_NODE_FUNCS(SetWildcard) + virtual string emitVerilog() override { return "'{}"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* lhsp() const { return op1p(); } + AstNode* keyp() const { return op2p(); } + AstNode* valuep() const { return op3p(); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstStable final : public AstNodeMath { + // Verilog $stable + // Parents: math + // Children: expression +public: + AstStable(FileLine* fl, AstNode* exprp) + : ASTGEN_SUPER_Stable(fl) { + addOp1p(exprp); + } + ASTNODE_NODE_FUNCS(Stable) + virtual string emitVerilog() override { return "$stable(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + AstNode* exprp() const { return op1p(); } // op1 = expression + AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain + void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstSystemF final : public AstNodeMath { + // $system used as function +public: + AstSystemF(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_SystemF(fl) { + setOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(SystemF) + virtual string verilogKwd() const override { return "$system"; } + virtual string emitVerilog() override { return verilogKwd(); } + virtual string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* lhsp() const { return op1p(); } +}; +class AstTestPlusArgs final : public AstNodeMath { + // Parents: expr + // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs +public: + AstTestPlusArgs(FileLine* fl, AstNode* searchp) + : ASTGEN_SUPER_TestPlusArgs(fl) { + setOp1p(searchp); + } + ASTNODE_NODE_FUNCS(TestPlusArgs) + virtual string verilogKwd() const override { return "$test$plusargs"; } + virtual string emitVerilog() override { return verilogKwd(); } + virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* searchp() const { return op1p(); } // op1 = Search expression + void searchp(AstNode* nodep) { setOp1p(nodep); } +}; +class AstUCFunc final : public AstNodeMath { + // User's $c function + // Perhaps this should be an AstNodeListop; but there's only one list math right now +public: + AstUCFunc(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_UCFunc(fl) { + addNOp1p(exprsp); + } + ASTNODE_NODE_FUNCS(UCFunc) + virtual bool cleanOut() const override { return false; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + AstNode* bodysp() const { return op1p(); } // op1 = expressions to print + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isSubstOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstUnbounded final : public AstNodeMath { + // A $ in the parser, used for unbounded and queues + // Due to where is used, treated as Signed32 +public: + explicit AstUnbounded(FileLine* fl) + : ASTGEN_SUPER_Unbounded(fl) { + dtypeSetSigned32(); + } + ASTNODE_NODE_FUNCS(Unbounded) + virtual string emitVerilog() override { return "$"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } +}; +class AstValuePlusArgs final : public AstNodeMath { + // Parents: expr + // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs +public: + AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp) + : ASTGEN_SUPER_ValuePlusArgs(fl) { + setOp1p(searchp); + setOp2p(outp); + } + ASTNODE_NODE_FUNCS(ValuePlusArgs) + virtual string verilogKwd() const override { return "$value$plusargs"; } + virtual string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return !outp(); } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* searchp() const { return op1p(); } // op1 = Search expression + void searchp(AstNode* nodep) { setOp1p(nodep); } + AstNode* outp() const { return op2p(); } // op2 = Expressions to output + void outp(AstNode* nodep) { setOp2p(nodep); } +}; + +// === AstNodeBiop === +class AstBufIf1 final : public AstNodeBiop { + // lhs is enable, rhs is data to drive + // Note unlike the Verilog bufif1() UDP, this allows any width; each lhsp + // bit enables respective rhsp bit +public: + AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_BufIf1(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(BufIf1) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstBufIf1(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opBufIf1(lhs, rhs); + } + virtual string emitVerilog() override { return "bufif(%r,%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstCastDynamic final : public AstNodeBiop { + // Verilog $cast used as a function + // Task usage of $cast is converted during parse to assert($cast(...)) + // Parents: MATH + // Children: MATH + // lhsp() is value (we are converting FROM) to match AstCCast etc, this + // is opposite of $cast's order, because the first access is to the + // value reading from. Suggest use fromp()/top() instead of lhsp/rhsp(). +public: + AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(CastDynamic) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstCastDynamic(this->fileline(), lhsp, rhsp); + } + virtual string emitVerilog() override { return "%f$cast(%r, %l)"; } + virtual string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 20; } + virtual bool isPure() const override { return true; } + AstNode* fromp() const { return lhsp(); } + AstNode* top() const { return rhsp(); } +}; +class AstCompareNN final : public AstNodeBiop { + // Verilog str.compare() and str.icompare() +private: + const bool m_ignoreCase; // True for str.icompare() +public: + AstCompareNN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, bool ignoreCase) + : ASTGEN_SUPER_CompareNN(fl, lhsp, rhsp) + , m_ignoreCase{ignoreCase} { + dtypeSetUInt32(); + } + ASTNODE_NODE_FUNCS(CompareNN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opCompareNN(lhs, rhs, m_ignoreCase); + } + virtual string name() const override { return m_ignoreCase ? "icompare" : "compare"; } + virtual string emitVerilog() override { + return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))"; + } + virtual string emitC() override { + return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)"; + } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstConcat final : public AstNodeBiop { + // If you're looking for {#{}}, see AstReplicate +public: + AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Concat(fl, lhsp, rhsp) { + if (lhsp->dtypep() && rhsp->dtypep()) { + dtypeSetLogicSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(), + VSigning::UNSIGNED); + } + } + ASTNODE_NODE_FUNCS(Concat) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstConcat(this->fileline(), lhsp, rhsp); + } + virtual string emitVerilog() override { return "%f{%l, %k%r}"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opConcat(lhs, rhs); + } + virtual string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } +}; +class AstConcatN final : public AstNodeBiop { + // String concatenate +public: + AstConcatN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_ConcatN(fl, lhsp, rhsp) { + dtypeSetString(); + } + ASTNODE_NODE_FUNCS(ConcatN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstConcatN(this->fileline(), lhsp, rhsp); + } + virtual string emitVerilog() override { return "%f{%l, %k%r}"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opConcatN(lhs, rhs); + } + virtual string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; +class AstDiv final : public AstNodeBiop { +public: + AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Div(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Div) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstDiv(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opDiv(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } + virtual string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } +}; +class AstDivD final : public AstNodeBiop { +public: + AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_DivD(fl, lhsp, rhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(DivD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstDivD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opDivD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "/"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstDivS final : public AstNodeBiop { +public: + AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_DivS(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(DivS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstDivS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opDivS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } + virtual string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } + virtual bool signedFlavor() const override { return true; } +}; +class AstEqWild final : public AstNodeBiop { + // Note wildcard operator rhs differs from lhs +public: + AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_EqWild(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(EqWild) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstEqWild(this->fileline(), lhsp, rhsp); + } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, + AstNode* rhsp); // Return AstEqWild/AstEqD + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opWildEq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f==? %r)"; } + virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstFGetS final : public AstNodeBiop { +public: + AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(FGetS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstFGetS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%f$fgets(%l,%r)"; } + virtual string emitC() override { + return strgp()->dtypep()->basicp()->isString() ? "VL_FGETS_NI(%li, %ri)" + : "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } + AstNode* strgp() const { return lhsp(); } + AstNode* filep() const { return rhsp(); } +}; +class AstFUngetC final : public AstNodeBiop { +public: + AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(FUngetC) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstFUngetC(this->fileline(), lhsp, rhsp); + } + virtual string emitVerilog() override { return "%f$ungetc(%r, %l)"; } + // Non-existent filehandle returns EOF + virtual string emitC() override { + return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + AstNode* filep() const { return lhsp(); } + AstNode* charp() const { return rhsp(); } +}; +class AstGetcN final : public AstNodeBiop { + // Verilog string.getc() +public: + AstGetcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GetcN(fl, lhsp, rhsp) { + dtypeSetBitSized(8, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(GetcN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGetcN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGetcN(lhs, rhs); + } + virtual string name() const override { return "getc"; } + virtual string emitVerilog() override { return "%k(%l.getc(%r))"; } + virtual string emitC() override { return "VL_GETC_N(%li,%ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstGetcRefN final : public AstNodeBiop { + // Verilog string[#] on the left-hand-side of assignment + // Spec says is of type byte (not string of single character) +public: + AstGetcRefN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GetcRefN(fl, lhsp, rhsp) { + dtypeSetBitSized(8, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(GetcRefN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGetcRefN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%k%l[%r]"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstGt final : public AstNodeBiop { +public: + AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Gt(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Gt) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGt(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGt(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ">"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstGtD final : public AstNodeBiop { +public: + AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GtD(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(GtD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGtD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGtD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstGtN final : public AstNodeBiop { +public: + AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GtN(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(GtN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGtN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGtN(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; +class AstGtS final : public AstNodeBiop { +public: + AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GtS(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(GtS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGtS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGtS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } +}; +class AstGte final : public AstNodeBiop { +public: + AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Gte(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Gte) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGte(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGte(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ">="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstGteD final : public AstNodeBiop { +public: + AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GteD(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(GteD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGteD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGteD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstGteN final : public AstNodeBiop { +public: + AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GteN(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(GteN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGteN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGteN(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; +class AstGteS final : public AstNodeBiop { +public: + AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_GteS(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(GteS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstGteS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opGteS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } +}; +class AstLogAnd final : public AstNodeBiop { +public: + AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LogAnd(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LogAnd) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLogAnd(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLogAnd(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f&& %r)"; } + virtual string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "&&"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } +}; +class AstLogIf final : public AstNodeBiop { +public: + AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LogIf(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LogIf) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLogIf(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLogIf(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f-> %r)"; } + virtual string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "->"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } +}; +class AstLogOr final : public AstNodeBiop { + // LOGOR with optional side effects + // Side effects currently used in some V3Width code + // TBD if this concept is generally adopted for side-effect tracking + // versus V3Const tracking it itself + bool m_sideEffect = false; // Has side effect, relies on short-circuiting +public: + AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LogOr(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LogOr) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLogOr(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLogOr(lhs, rhs); + } + virtual bool same(const AstNode* samep) const override { + const AstLogOr* const sp = static_cast(samep); + return m_sideEffect == sp->m_sideEffect; + } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string emitVerilog() override { return "%k(%l %f|| %r)"; } + virtual string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "||"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + virtual bool isPure() const override { return !m_sideEffect; } + void sideEffect(bool flag) { m_sideEffect = flag; } + bool sideEffect() const { return m_sideEffect; } +}; +class AstLt final : public AstNodeBiop { +public: + AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Lt(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Lt) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLt(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLt(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstLtD final : public AstNodeBiop { +public: + AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LtD(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LtD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLtD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLtD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstLtN final : public AstNodeBiop { +public: + AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LtN(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LtN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLtN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLtN(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; +class AstLtS final : public AstNodeBiop { +public: + AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LtS(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LtS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLtS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLtS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } +}; +class AstLte final : public AstNodeBiop { +public: + AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Lte(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Lte) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLte(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLte(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstLteD final : public AstNodeBiop { +public: + AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LteD(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LteD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLteD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLteD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstLteN final : public AstNodeBiop { +public: + AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LteN(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LteN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLteN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLteN(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; +class AstLteS final : public AstNodeBiop { +public: + AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LteS(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LteS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLteS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLteS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } +}; +class AstModDiv final : public AstNodeBiop { +public: + AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_ModDiv(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(ModDiv) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstModDiv(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opModDiv(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } + virtual string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } +}; +class AstModDivS final : public AstNodeBiop { +public: + AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_ModDivS(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(ModDivS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstModDivS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opModDivS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } + virtual string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } + virtual bool signedFlavor() const override { return true; } +}; +class AstNeqWild final : public AstNodeBiop { +public: + AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_NeqWild(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(NeqWild) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstNeqWild(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opWildNeq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f!=? %r)"; } + virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstPow final : public AstNodeBiop { +public: + AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Pow(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Pow) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstPow(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opPow(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } +}; +class AstPowD final : public AstNodeBiop { +public: + AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_PowD(fl, lhsp, rhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(PowD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstPowD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opPowD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { return "pow(%li,%ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstPowSS final : public AstNodeBiop { +public: + AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_PowSS(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(PowSS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstPowSS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opPowSS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { + return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; + } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + virtual bool signedFlavor() const override { return true; } +}; +class AstPowSU final : public AstNodeBiop { +public: + AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_PowSU(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(PowSU) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstPowSU(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opPowSU(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { + return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; + } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + virtual bool signedFlavor() const override { return true; } +}; +class AstPowUS final : public AstNodeBiop { +public: + AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_PowUS(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(PowUS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstPowUS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opPowUS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { + return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; + } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + virtual bool signedFlavor() const override { return true; } +}; +class AstReplicate final : public AstNodeBiop { + // Also used as a "Uniop" flavor of Concat, e.g. "{a}" + // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp() +public: + AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Replicate(fl, lhsp, rhsp) { + if (lhsp) { + if (const AstConst* const constp = VN_CAST(rhsp, Const)) { + dtypeSetLogicSized(lhsp->width() * constp->toUInt(), VSigning::UNSIGNED); + } + } + } + AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount) + : AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {} + ASTNODE_NODE_FUNCS(Replicate) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstReplicate(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opRepl(lhs, rhs); + } + virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } + virtual string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } +}; +class AstReplicateN final : public AstNodeBiop { + // String replicate +public: + AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_ReplicateN(fl, lhsp, rhsp) { + dtypeSetString(); + } + AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount) + : AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {} + ASTNODE_NODE_FUNCS(ReplicateN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstReplicateN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opReplN(lhs, rhs); + } + virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } + virtual string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } + virtual bool stringFlavor() const override { return true; } +}; +class AstShiftL final : public AstNodeBiop { +public: + AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) + : ASTGEN_SUPER_ShiftL(fl, lhsp, rhsp) { + if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(ShiftL) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstShiftL(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opShiftL(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f<< %r)"; } + virtual string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { + return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstShiftR final : public AstNodeBiop { +public: + AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) + : ASTGEN_SUPER_ShiftR(fl, lhsp, rhsp) { + if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(ShiftR) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstShiftR(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opShiftR(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f>> %r)"; } + virtual string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { + return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + // LHS size might be > output size, so don't want to force size + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstShiftRS final : public AstNodeBiop { + // Shift right with sign extension, >>> operator + // Output data type's width determines which bit is used for sign extension +public: + AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) + : ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) { + // Important that widthMin be correct, as opExtend requires it after V3Expand + if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED); + } + ASTNODE_NODE_FUNCS(ShiftRS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstShiftRS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opShiftRS(lhs, rhs, lhsp()->widthMinV()); + } + virtual string emitVerilog() override { return "%k(%l %f>>> %r)"; } + virtual string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } +}; +class AstSub final : public AstNodeBiop { +public: + AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Sub(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Sub) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstSub(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opSub(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f- %r)"; } + virtual string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } +}; +class AstSubD final : public AstNodeBiop { +public: + AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_SubD(fl, lhsp, rhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(SubD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstSubD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opSubD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f- %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstURandomRange final : public AstNodeBiop { + // $urandom_range +public: + explicit AstURandomRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_URandomRange(fl, lhsp, rhsp) { + dtypeSetUInt32(); // Says IEEE + } + ASTNODE_NODE_FUNCS(URandomRange) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstURandomRange(fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%f$urandom_range(%l, %r)"; } + virtual string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } +}; + +// === AstNodeBiCom === +class AstEq final : public AstNodeBiCom { +public: + AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Eq(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Eq) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstEq(this->fileline(), lhsp, rhsp); + } + static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, + AstNode* rhsp); // Return AstEq/AstEqD + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opEq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f== %r)"; } + virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstEqCase final : public AstNodeBiCom { +public: + AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_EqCase(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(EqCase) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstEqCase(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opCaseEq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f=== %r)"; } + virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstEqD final : public AstNodeBiCom { +public: + AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_EqD(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(EqD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstEqD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opEqD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f== %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstEqN final : public AstNodeBiCom { +public: + AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_EqN(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(EqN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstEqN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opEqN(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f== %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; +class AstLogEq final : public AstNodeBiCom { +public: + AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_LogEq(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LogEq) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstLogEq(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opLogEq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f<-> %r)"; } + virtual string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<->"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } +}; +class AstNeq final : public AstNodeBiCom { +public: + AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Neq(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(Neq) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstNeq(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opNeq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } + virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstNeqCase final : public AstNodeBiCom { +public: + AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_NeqCase(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(NeqCase) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstNeqCase(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opCaseNeq(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f!== %r)"; } + virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstNeqD final : public AstNodeBiCom { +public: + AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_NeqD(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(NeqD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstNeqD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opNeqD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstNeqN final : public AstNodeBiCom { +public: + AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_NeqN(fl, lhsp, rhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(NeqN) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstNeqN(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opNeqN(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_STR; } + virtual bool stringFlavor() const override { return true; } +}; + +// === AstNodeBiComAsv === +class AstAdd final : public AstNodeBiComAsv { +public: + AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Add(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Add) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAdd(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opAdd(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } + virtual string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "+"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } +}; +class AstAddD final : public AstNodeBiComAsv { +public: + AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_AddD(fl, lhsp, rhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(AddD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAddD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opAddD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "+"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstAnd final : public AstNodeBiComAsv { +public: + AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_And(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(And) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAnd(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opAnd(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f& %r)"; } + virtual string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "&"; } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstMul final : public AstNodeBiComAsv { +public: + AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Mul(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Mul) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstMul(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opMul(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f* %r)"; } + virtual string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "*"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } +}; +class AstMulD final : public AstNodeBiComAsv { +public: + AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_MulD(fl, lhsp, rhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(MulD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstMulD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opMulD(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f* %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "*"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstMulS final : public AstNodeBiComAsv { +public: + AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_MulS(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(MulS) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstMulS(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opMulS(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f* %r)"; } + virtual string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } + virtual bool signedFlavor() const override { return true; } +}; +class AstOr final : public AstNodeBiComAsv { +public: + AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Or(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Or) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstOr(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opOr(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f| %r)"; } + virtual string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "|"; } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; +class AstXor final : public AstNodeBiComAsv { +public: + AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Xor(fl, lhsp, rhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Xor) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstXor(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opXor(lhs, rhs); + } + virtual string emitVerilog() override { return "%k(%l %f^ %r)"; } + virtual string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "^"; } + virtual bool cleanOut() const override { return false; } // Lclean && Rclean + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } +}; + +// === AstNodeSel === +class AstArraySel final : public AstNodeSel { + // Parents: math|stmt + // Children: varref|arraysel, math +private: + void init(AstNode* fromp) { + if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) { + // Strip off array to find what array references + dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); + } + } + +public: + AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp) + : ASTGEN_SUPER_ArraySel(fl, fromp, bitp) { + init(fromp); + } + AstArraySel(FileLine* fl, AstNode* fromp, int bit) + : ASTGEN_SUPER_ArraySel(fl, fromp, new AstConst(fl, bit)) { + init(fromp); + } + ASTNODE_NODE_FUNCS(ArraySel) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstArraySel(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; /* How can from be a const? */ + } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { return "%li%k[%ri]"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { + return true; + } // esp for V3Const::ifSameAssign + virtual bool isPredictOptimizable() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + // Special operators + // Return base var (or const) nodep dereferences + static AstNode* baseFromp(AstNode* nodep, bool overMembers); +}; +class AstAssocSel final : public AstNodeSel { + // Parents: math|stmt + // Children: varref|arraysel, math +private: + void init(AstNode* fromp) { + if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) { + // Strip off array to find what array references + dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep()); + } + } + +public: + AstAssocSel(FileLine* fl, AstNode* fromp, AstNode* bitp) + : ASTGEN_SUPER_AssocSel(fl, fromp, bitp) { + init(fromp); + } + ASTNODE_NODE_FUNCS(AssocSel) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssocSel(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { return "%li%k[%ri]"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { + return true; + } // esp for V3Const::ifSameAssign + virtual bool isPredictOptimizable() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } +}; +class AstWildcardSel final : public AstNodeSel { + // Parents: math|stmt + // Children: varref|arraysel, math +private: + void init(AstNode* fromp) { + if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) { + // Strip off array to find what array references + dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep()); + } + } + +public: + AstWildcardSel(FileLine* fl, AstNode* fromp, AstNode* bitp) + : ASTGEN_SUPER_WildcardSel(fl, fromp, bitp) { + init(fromp); + } + ASTNODE_NODE_FUNCS(WildcardSel) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstWildcardSel{this->fileline(), lhsp, rhsp}; + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { return "%li%k[%ri]"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { + return true; + } // esp for V3Const::ifSameAssign + virtual bool isPredictOptimizable() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } +}; +class AstWordSel final : public AstNodeSel { + // Select a single word from a multi-word wide value +public: + AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp) + : ASTGEN_SUPER_WordSel(fl, fromp, bitp) { + dtypeSetUInt32(); // Always used on WData arrays so returns edata size + } + ASTNODE_NODE_FUNCS(WordSel) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstWordSel(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { + return "%li[%ri]"; + } // Not %k, as usually it's a small constant rhsp + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; + +// === AstNodeStream === +class AstStreamL final : public AstNodeStream { + // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() +public: + AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(StreamL) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstStreamL(this->fileline(), lhsp, rhsp); + } + virtual string emitVerilog() override { return "%f{ << %r %k{%l} }"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opStreamL(lhs, rhs); + } + virtual string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } +}; +class AstStreamR final : public AstNodeStream { + // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() +public: + AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(StreamR) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstStreamR(this->fileline(), lhsp, rhsp); + } + virtual string emitVerilog() override { return "%f{ >> %r %k{%l} }"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.opAssign(lhs); + } + virtual string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } +}; + +// === AstNodeSystemBiop === +class AstAtan2D final : public AstNodeSystemBiop { +public: + AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(Atan2D) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAtan2D(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.setDouble(std::atan2(lhs.toDouble(), rhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$atan2(%l,%r)"; } + virtual string emitC() override { return "atan2(%li,%ri)"; } +}; +class AstHypotD final : public AstNodeSystemBiop { +public: + AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(HypotD) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstHypotD(this->fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + out.setDouble(std::hypot(lhs.toDouble(), rhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$hypot(%l,%r)"; } + virtual string emitC() override { return "hypot(%li,%ri)"; } +}; + +// === AstNodeQuadop === +class AstCountBits final : public AstNodeQuadop { + // Number of bits set in vector +public: + AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p) + : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTree(false), + ctrl1p->cloneTree(false)) {} + AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p) + : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTree(false)) {} + AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p, AstNode* ctrl3p) + : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {} + ASTNODE_NODE_FUNCS(CountBits) + virtual void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1, + const V3Number& ctrl2, const V3Number& ctrl3) override { + out.opCountBits(expr, ctrl1, ctrl2, ctrl3); + } + virtual string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; } + virtual string emitC() override { return ""; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool cleanFhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual bool sizeMattersFhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } +}; + +// === AstNodeTermop === +class AstTime final : public AstNodeTermop { + VTimescale m_timeunit; // Parent module time unit +public: + AstTime(FileLine* fl, const VTimescale& timeunit) + : ASTGEN_SUPER_Time(fl) + , m_timeunit{timeunit} { + dtypeSetUInt64(); + } + ASTNODE_NODE_FUNCS(Time) + virtual string emitVerilog() override { return "%f$time"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_TIME; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } +}; +class AstTimeD final : public AstNodeTermop { + VTimescale m_timeunit; // Parent module time unit +public: + AstTimeD(FileLine* fl, const VTimescale& timeunit) + : ASTGEN_SUPER_TimeD(fl) + , m_timeunit{timeunit} { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(TimeD) + virtual string emitVerilog() override { return "%f$realtime"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_TIME; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } +}; + +// === AstNodeTriop === +class AstPostAdd final : public AstNodeTriop { + // Post-increment/add + // Parents: MATH + // Children: lhsp: AstConst (1) as currently support only ++ not += + // Children: rhsp: tree with AstVarRef that is value to read before operation + // Children: thsp: tree with AstVarRef LValue that is stored after operation +public: + AstPostAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) + : ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {} + ASTNODE_NODE_FUNCS(PostAdd) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { + V3ERROR_NA; // Need to modify lhs + } + virtual string emitVerilog() override { return "%k(%r++)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } +}; +class AstPostSub final : public AstNodeTriop { + // Post-decrement/subtract + // Parents: MATH + // Children: lhsp: AstConst (1) as currently support only -- not -= + // Children: rhsp: tree with AstVarRef that is value to read before operation + // Children: thsp: tree with AstVarRef LValue that is stored after operation +public: + AstPostSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) + : ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {} + ASTNODE_NODE_FUNCS(PostSub) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { + V3ERROR_NA; // Need to modify lhs + } + virtual string emitVerilog() override { return "%k(%r--)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } +}; +class AstPreAdd final : public AstNodeTriop { + // Pre-increment/add + // Parents: MATH + // Children: lhsp: AstConst (1) as currently support only ++ not += + // Children: rhsp: tree with AstVarRef that is value to read before operation + // Children: thsp: tree with AstVarRef LValue that is stored after operation +public: + AstPreAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) + : ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {} + ASTNODE_NODE_FUNCS(PreAdd) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { + V3ERROR_NA; // Need to modify lhs + } + virtual string emitVerilog() override { return "%k(++%r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } +}; +class AstPreSub final : public AstNodeTriop { + // Pre-decrement/subtract + // Parents: MATH + // Children: lhsp: AstConst (1) as currently support only -- not -= + // Children: rhsp: tree with AstVarRef that is value to read before operation + // Children: thsp: tree with AstVarRef LValue that is stored after operation +public: + AstPreSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) + : ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {} + ASTNODE_NODE_FUNCS(PreSub) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { + V3ERROR_NA; // Need to modify lhs + } + virtual string emitVerilog() override { return "%k(--%r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } +}; +class AstPutcN final : public AstNodeTriop { + // Verilog string.putc() +public: + AstPutcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) + : ASTGEN_SUPER_PutcN(fl, lhsp, rhsp, ths) { + dtypeSetString(); + } + ASTNODE_NODE_FUNCS(PutcN) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { + out.opPutcN(lhs, rhs, ths); + } + virtual string name() const override { return "putc"; } + virtual string emitVerilog() override { return "%k(%l.putc(%r,%t))"; } + virtual string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } +}; +class AstSel final : public AstNodeTriop { + // Multiple bit range extraction + // Parents: math|stmt + // Children: varref|arraysel, math, constant math + // Tempting to have an access() style method here as LHS selects are quite + // different, but that doesn't play well with V3Inst and bidirects which don't know direction +private: + VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid + int m_declElWidth; // If a packed array, the number of bits per element +public: + AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp) + : ASTGEN_SUPER_Sel(fl, fromp, lsbp, widthp) + , m_declElWidth{1} { + if (VN_IS(widthp, Const)) { + dtypeSetLogicSized(VN_AS(widthp, Const)->toUInt(), VSigning::UNSIGNED); + } + } + AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth) + : ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth)) + , m_declElWidth{1} { + dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(Sel) + virtual void dump(std::ostream& str) const override; + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, + const V3Number& width) override { + out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt()); + } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { + return widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%lw, %P, %li, %ri)" + : isWide() ? "VL_SEL_%nq%lq%rq%tq(%nw,%lw, %P, %li, %ri, %ti)" + : "VL_SEL_%nq%lq%rq%tq(%lw, %P, %li, %ri, %ti)"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual bool same(const AstNode*) const override { return true; } + virtual int instrCount() const override { + return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); + } + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) + AstNode* lsbp() const { return op2p(); } // op2 = Msb selection expression + AstNode* widthp() const { return op3p(); } // op3 = Width + int widthConst() const { return VN_AS(widthp(), Const)->toSInt(); } + int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); } + int msbConst() const { return lsbConst() + widthConst() - 1; } + VNumRange& declRange() { return m_declRange; } + const VNumRange& declRange() const { return m_declRange; } + void declRange(const VNumRange& flag) { m_declRange = flag; } + int declElWidth() const { return m_declElWidth; } + void declElWidth(int flag) { m_declElWidth = flag; } +}; +class AstSliceSel final : public AstNodeTriop { + // Multiple array element extraction + // Parents: math|stmt + // Children: varref|arraysel, math, constant math +private: + VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid +public: + AstSliceSel(FileLine* fl, AstNode* fromp, const VNumRange& declRange) + : ASTGEN_SUPER_SliceSel(fl, fromp, new AstConst(fl, declRange.lo()), + new AstConst(fl, declRange.elements())) + , m_declRange{declRange} {} + ASTNODE_NODE_FUNCS(SliceSel) + virtual void dump(std::ostream& str) const override; + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, + const V3Number& width) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual bool same(const AstNode*) const override { return true; } + virtual int instrCount() const override { return 10; } // Removed before matters + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) + // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods + VNumRange& declRange() { return m_declRange; } + const VNumRange& declRange() const { return m_declRange; } + void declRange(const VNumRange& flag) { m_declRange = flag; } +}; +class AstSubstrN final : public AstNodeTriop { + // Verilog string.substr() +public: + AstSubstrN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) + : ASTGEN_SUPER_SubstrN(fl, lhsp, rhsp, ths) { + dtypeSetString(); + } + ASTNODE_NODE_FUNCS(SubstrN) + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { + out.opSubstrN(lhs, rhs, ths); + } + virtual string name() const override { return "substr"; } + virtual string emitVerilog() override { return "%k(%l.substr(%r,%t))"; } + virtual string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } +}; + +// === AstNodeCond === +class AstCond final : public AstNodeCond { + // Conditional ?: statement + // Parents: MATH + // Children: MATH +public: + AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) + : ASTGEN_SUPER_Cond(fl, condp, expr1p, expr2p) {} + ASTNODE_NODE_FUNCS(Cond) + virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { + return new AstCond(this->fileline(), condp, expr1p, expr2p); + } +}; +class AstCondBound final : public AstNodeCond { + // Conditional ?: statement, specially made for safety checking of array bounds + // Parents: MATH + // Children: MATH +public: + AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) + : ASTGEN_SUPER_CondBound(fl, condp, expr1p, expr2p) {} + ASTNODE_NODE_FUNCS(CondBound) + virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { + return new AstCondBound(this->fileline(), condp, expr1p, expr2p); + } +}; + +// === AstNodeUniop === +class AstAtoN final : public AstNodeUniop { + // string.atoi(), atobin(), atohex(), atooct(), atoireal() +public: + enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 }; + +private: + const FmtType m_fmt; // Operation type +public: + AstAtoN(FileLine* fl, AstNode* lhsp, FmtType fmt) + : ASTGEN_SUPER_AtoN(fl, lhsp) + , m_fmt{fmt} { + fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32(); + } + ASTNODE_NODE_FUNCS(AtoN) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opAtoN(lhs, m_fmt); + } + virtual string name() const override { + switch (m_fmt) { + case ATOI: return "atoi"; + case ATOHEX: return "atohex"; + case ATOOCT: return "atooct"; + case ATOBIN: return "atobin"; + case ATOREAL: return "atoreal"; + default: V3ERROR_NA; + } + } + virtual string emitVerilog() override { return "%l." + name() + "()"; } + virtual string emitC() override { + switch (m_fmt) { + case ATOI: return "VL_ATOI_N(%li, 10)"; + case ATOHEX: return "VL_ATOI_N(%li, 16)"; + case ATOOCT: return "VL_ATOI_N(%li, 8)"; + case ATOBIN: return "VL_ATOI_N(%li, 2)"; + case ATOREAL: return "std::atof(%li.c_str())"; + default: V3ERROR_NA; + } + } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + FmtType format() const { return m_fmt; } +}; +class AstBitsToRealD final : public AstNodeUniop { +public: + AstBitsToRealD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_BitsToRealD(fl, lhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(BitsToRealD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opBitsToRealD(lhs); + } + virtual string emitVerilog() override { return "%f$bitstoreal(%l)"; } + virtual string emitC() override { return "VL_CVT_D_Q(%li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters + virtual int instrCount() const override { return INSTR_COUNT_DBL; } +}; +class AstCCast final : public AstNodeUniop { + // Cast to C-based data type +private: + int m_size; + +public: + AstCCast(FileLine* fl, AstNode* lhsp, int setwidth, int minwidth = -1) + : ASTGEN_SUPER_CCast(fl, lhsp) { + m_size = setwidth; + if (setwidth) { + if (minwidth == -1) minwidth = setwidth; + dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED); + } + } + AstCCast(FileLine* fl, AstNode* lhsp, AstNode* typeFromp) + : ASTGEN_SUPER_CCast(fl, lhsp) { + dtypeFrom(typeFromp); + m_size = width(); + } + ASTNODE_NODE_FUNCS(CCast) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } + virtual string emitVerilog() override { return "%f$_CAST(%l)"; } + virtual string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast + virtual bool same(const AstNode* samep) const override { + return size() == static_cast(samep)->size(); + } + virtual void dump(std::ostream& str = std::cout) const override; + // + int size() const { return m_size; } +}; +class AstCLog2 final : public AstNodeUniop { +public: + AstCLog2(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CLog2(fl, lhsp) { + dtypeSetSigned32(); + } + ASTNODE_NODE_FUNCS(CLog2) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); } + virtual string emitVerilog() override { return "%f$clog2(%l)"; } + virtual string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } +}; +class AstCountOnes final : public AstNodeUniop { + // Number of bits set in vector +public: + AstCountOnes(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CountOnes(fl, lhsp) {} + ASTNODE_NODE_FUNCS(CountOnes) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opCountOnes(lhs); + } + virtual string emitVerilog() override { return "%f$countones(%l)"; } + virtual string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } +}; +class AstCvtPackString final : public AstNodeUniop { + // Convert to Verilator Packed String (aka verilog "string") +public: + AstCvtPackString(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CvtPackString(fl, lhsp) { + dtypeSetString(); + } + ASTNODE_NODE_FUNCS(CvtPackString) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%f$_CAST(%l)"; } + virtual string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstExtend final : public AstNodeUniop { + // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width() +public: + AstExtend(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Extend(fl, lhsp) {} + AstExtend(FileLine* fl, AstNode* lhsp, int width) + : ASTGEN_SUPER_Extend(fl, lhsp) { + dtypeSetLogicSized(width, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(Extend) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { + return false; // Because the EXTEND operator self-casts + } + virtual int instrCount() const override { return 0; } +}; +class AstExtendS final : public AstNodeUniop { + // Expand a value into a wider entity by sign extension. Width is implied from nodep->width() +public: + AstExtendS(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_ExtendS(fl, lhsp) {} + AstExtendS(FileLine* fl, AstNode* lhsp, int width) + // Important that widthMin be correct, as opExtend requires it after V3Expand + : ASTGEN_SUPER_ExtendS(fl, lhsp) { + dtypeSetLogicSized(width, VSigning::UNSIGNED); + } + ASTNODE_NODE_FUNCS(ExtendS) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opExtendS(lhs, lhsp()->widthMinV()); + } + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { + return false; // Because the EXTEND operator self-casts + } + virtual int instrCount() const override { return 0; } + virtual bool signedFlavor() const override { return true; } +}; +class AstFEof final : public AstNodeUniop { +public: + AstFEof(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_FEof(fl, lhsp) {} + ASTNODE_NODE_FUNCS(FEof) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%f$feof(%l)"; } + virtual string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + AstNode* filep() const { return lhsp(); } +}; +class AstFGetC final : public AstNodeUniop { +public: + AstFGetC(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_FGetC(fl, lhsp) {} + ASTNODE_NODE_FUNCS(FGetC) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%f$fgetc(%l)"; } + // Non-existent filehandle returns EOF + virtual string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + AstNode* filep() const { return lhsp(); } +}; +class AstISToRD final : public AstNodeUniop { + // $itor where lhs is signed +public: + AstISToRD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_ISToRD(fl, lhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(ISToRD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); } + virtual string emitVerilog() override { return "%f$itor($signed(%l))"; } + virtual string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } +}; +class AstIToRD final : public AstNodeUniop { + // $itor where lhs is unsigned +public: + AstIToRD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_IToRD(fl, lhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(IToRD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); } + virtual string emitVerilog() override { return "%f$itor(%l)"; } + virtual string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } +}; +class AstIsUnbounded final : public AstNodeUniop { + // True if is unmbounded ($) +public: + AstIsUnbounded(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_IsUnbounded(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(IsUnbounded) + virtual void numberOperate(V3Number& out, const V3Number&) override { + // Any constant isn't unbounded + out.setZero(); + } + virtual string emitVerilog() override { return "%f$isunbounded(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstIsUnknown final : public AstNodeUniop { + // True if any unknown bits +public: + AstIsUnknown(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_IsUnknown(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(IsUnknown) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opIsUnknown(lhs); + } + virtual string emitVerilog() override { return "%f$isunknown(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstLenN final : public AstNodeUniop { + // Length of a string +public: + AstLenN(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_LenN(fl, lhsp) { + dtypeSetSigned32(); + } + ASTNODE_NODE_FUNCS(LenN) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); } + virtual string emitVerilog() override { return "%f(%l)"; } + virtual string emitC() override { return "VL_LEN_IN(%li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstLogNot final : public AstNodeUniop { +public: + AstLogNot(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_LogNot(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(LogNot) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } + virtual string emitVerilog() override { return "%f(! %l)"; } + virtual string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } + virtual string emitSimpleOperator() override { return "!"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstNegate final : public AstNodeUniop { +public: + AstNegate(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Negate(fl, lhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Negate) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); } + virtual string emitVerilog() override { return "%f(- %l)"; } + virtual string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } +}; +class AstNegateD final : public AstNodeUniop { +public: + AstNegateD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_NegateD(fl, lhsp) { + dtypeSetDouble(); + } + ASTNODE_NODE_FUNCS(NegateD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); } + virtual string emitVerilog() override { return "%f(- %l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } + virtual bool doubleFlavor() const override { return true; } +}; +class AstNot final : public AstNodeUniop { +public: + AstNot(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Not(fl, lhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Not) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); } + virtual string emitVerilog() override { return "%f(~ %l)"; } + virtual string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; } + virtual string emitSimpleOperator() override { return "~"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } +}; +class AstNullCheck final : public AstNodeUniop { + // Return LHS after checking that LHS is non-null + // Children: VarRef or something returning pointer +public: + AstNullCheck(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_NullCheck(fl, lhsp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(NullCheck) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual int instrCount() const override { return 1; } // Rarely executes + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool same(const AstNode* samep) const override { + return fileline() == samep->fileline(); + } +}; +class AstOneHot final : public AstNodeUniop { + // True if only single bit set in vector +public: + AstOneHot(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_OneHot(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(OneHot) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } + virtual string emitVerilog() override { return "%f$onehot(%l)"; } + virtual string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 4; } +}; +class AstOneHot0 final : public AstNodeUniop { + // True if only single bit, or no bits set in vector +public: + AstOneHot0(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_OneHot0(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(OneHot0) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } + virtual string emitVerilog() override { return "%f$onehot0(%l)"; } + virtual string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 3; } +}; +class AstRToIRoundS final : public AstNodeUniop { + // Convert real to integer, with arbitrary sized output (not just "integer" format) +public: + AstRToIRoundS(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_RToIRoundS(fl, lhsp) { + dtypeSetSigned32(); + } + ASTNODE_NODE_FUNCS(RToIRoundS) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opRToIRoundS(lhs); + } + virtual string emitVerilog() override { return "%f$rtoi_rounded(%l)"; } + virtual string emitC() override { + return isWide() ? "VL_RTOIROUND_%nq_D(%nw, %P, %li)" : "VL_RTOIROUND_%nq_D(%li)"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_DBL; } +}; +class AstRToIS final : public AstNodeUniop { + // $rtoi(lhs) +public: + AstRToIS(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_RToIS(fl, lhsp) { + dtypeSetSigned32(); + } + ASTNODE_NODE_FUNCS(RToIS) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); } + virtual string emitVerilog() override { return "%f$rtoi(%l)"; } + virtual string emitC() override { return "VL_RTOI_I_D(%li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters + virtual int instrCount() const override { return INSTR_COUNT_DBL; } +}; +class AstRealToBits final : public AstNodeUniop { +public: + AstRealToBits(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_RealToBits(fl, lhsp) { + dtypeSetUInt64(); + } + ASTNODE_NODE_FUNCS(RealToBits) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opRealToBits(lhs); + } + virtual string emitVerilog() override { return "%f$realtobits(%l)"; } + virtual string emitC() override { return "VL_CVT_Q_D(%li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters + virtual int instrCount() const override { return INSTR_COUNT_DBL; } +}; +class AstRedAnd final : public AstNodeUniop { +public: + AstRedAnd(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_RedAnd(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(RedAnd) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } + virtual string emitVerilog() override { return "%f(& %l)"; } + virtual string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstRedOr final : public AstNodeUniop { +public: + AstRedOr(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_RedOr(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(RedOr) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } + virtual string emitVerilog() override { return "%f(| %l)"; } + virtual string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstRedXor final : public AstNodeUniop { +public: + AstRedXor(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_RedXor(fl, lhsp) { + dtypeSetBit(); + } + ASTNODE_NODE_FUNCS(RedXor) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } + virtual string emitVerilog() override { return "%f(^ %l)"; } + virtual string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { + const int w = lhsp()->width(); + return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16); + } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } +}; +class AstSigned final : public AstNodeUniop { + // $signed(lhs) +public: + AstSigned(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Signed(fl, lhsp) { + UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, + "not coded to create after dtypes resolved"); + } + ASTNODE_NODE_FUNCS(Signed) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opAssign(lhs); + out.isSigned(false); + } + virtual string emitVerilog() override { return "%f$signed(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters + virtual int instrCount() const override { return 0; } +}; +class AstTimeImport final : public AstNodeUniop { + // Take a constant that represents a time and needs conversion based on time units + VTimescale m_timeunit; // Parent module time unit +public: + AstTimeImport(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_TimeImport(fl, lhsp) {} + ASTNODE_NODE_FUNCS(TimeImport) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual void dump(std::ostream& str = std::cout) const override; + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } +}; +class AstToLowerN final : public AstNodeUniop { + // string.tolower() +public: + AstToLowerN(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_ToLowerN(fl, lhsp) { + dtypeSetString(); + } + ASTNODE_NODE_FUNCS(ToLowerN) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opToLowerN(lhs); + } + virtual string emitVerilog() override { return "%l.tolower()"; } + virtual string emitC() override { return "VL_TOLOWER_NN(%li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstToUpperN final : public AstNodeUniop { + // string.toupper() +public: + AstToUpperN(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_ToUpperN(fl, lhsp) { + dtypeSetString(); + } + ASTNODE_NODE_FUNCS(ToUpperN) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opToUpperN(lhs); + } + virtual string emitVerilog() override { return "%l.toupper()"; } + virtual string emitC() override { return "VL_TOUPPER_NN(%li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } +}; +class AstUnsigned final : public AstNodeUniop { + // $unsigned(lhs) +public: + AstUnsigned(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Unsigned(fl, lhsp) { + UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, + "not coded to create after dtypes resolved"); + } + ASTNODE_NODE_FUNCS(Unsigned) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opAssign(lhs); + out.isSigned(false); + } + virtual string emitVerilog() override { return "%f$unsigned(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters + virtual int instrCount() const override { return 0; } +}; + +// === AstNodeSystemUniop === +class AstAcosD final : public AstNodeSystemUniop { +public: + AstAcosD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_AcosD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(AcosD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::acos(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$acos(%l)"; } + virtual string emitC() override { return "acos(%li)"; } +}; +class AstAcoshD final : public AstNodeSystemUniop { +public: + AstAcoshD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_AcoshD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(AcoshD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::acosh(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$acosh(%l)"; } + virtual string emitC() override { return "acosh(%li)"; } +}; +class AstAsinD final : public AstNodeSystemUniop { +public: + AstAsinD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_AsinD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(AsinD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::asin(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$asin(%l)"; } + virtual string emitC() override { return "asin(%li)"; } +}; +class AstAsinhD final : public AstNodeSystemUniop { +public: + AstAsinhD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_AsinhD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(AsinhD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::asinh(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$asinh(%l)"; } + virtual string emitC() override { return "asinh(%li)"; } +}; +class AstAtanD final : public AstNodeSystemUniop { +public: + AstAtanD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_AtanD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(AtanD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::atan(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$atan(%l)"; } + virtual string emitC() override { return "atan(%li)"; } +}; +class AstAtanhD final : public AstNodeSystemUniop { +public: + AstAtanhD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_AtanhD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(AtanhD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::atanh(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$atanh(%l)"; } + virtual string emitC() override { return "atanh(%li)"; } +}; +class AstCeilD final : public AstNodeSystemUniop { +public: + AstCeilD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CeilD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(CeilD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::ceil(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$ceil(%l)"; } + virtual string emitC() override { return "ceil(%li)"; } +}; +class AstCosD final : public AstNodeSystemUniop { +public: + AstCosD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CosD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(CosD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::cos(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$cos(%l)"; } + virtual string emitC() override { return "cos(%li)"; } +}; +class AstCoshD final : public AstNodeSystemUniop { +public: + AstCoshD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CoshD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(CoshD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::cosh(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$cosh(%l)"; } + virtual string emitC() override { return "cosh(%li)"; } +}; +class AstExpD final : public AstNodeSystemUniop { +public: + AstExpD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_ExpD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(ExpD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::exp(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$exp(%l)"; } + virtual string emitC() override { return "exp(%li)"; } +}; +class AstFloorD final : public AstNodeSystemUniop { +public: + AstFloorD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_FloorD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(FloorD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::floor(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$floor(%l)"; } + virtual string emitC() override { return "floor(%li)"; } +}; +class AstLog10D final : public AstNodeSystemUniop { +public: + AstLog10D(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Log10D(fl, lhsp) {} + ASTNODE_NODE_FUNCS(Log10D) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::log10(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$log10(%l)"; } + virtual string emitC() override { return "log10(%li)"; } +}; +class AstLogD final : public AstNodeSystemUniop { +public: + AstLogD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_LogD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(LogD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::log(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$ln(%l)"; } + virtual string emitC() override { return "log(%li)"; } +}; +class AstSinD final : public AstNodeSystemUniop { +public: + AstSinD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_SinD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(SinD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::sin(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$sin(%l)"; } + virtual string emitC() override { return "sin(%li)"; } +}; +class AstSinhD final : public AstNodeSystemUniop { +public: + AstSinhD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_SinhD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(SinhD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::sinh(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$sinh(%l)"; } + virtual string emitC() override { return "sinh(%li)"; } +}; +class AstSqrtD final : public AstNodeSystemUniop { +public: + AstSqrtD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_SqrtD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(SqrtD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::sqrt(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$sqrt(%l)"; } + virtual string emitC() override { return "sqrt(%li)"; } +}; +class AstTanD final : public AstNodeSystemUniop { +public: + AstTanD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_TanD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(TanD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::tan(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$tan(%l)"; } + virtual string emitC() override { return "tan(%li)"; } +}; +class AstTanhD final : public AstNodeSystemUniop { +public: + AstTanhD(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_TanhD(fl, lhsp) {} + ASTNODE_NODE_FUNCS(TanhD) + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.setDouble(std::tanh(lhs.toDouble())); + } + virtual string emitVerilog() override { return "%f$tanh(%l)"; } + virtual string emitC() override { return "tanh(%li)"; } +}; + +// === AstNodeVarRef === +class AstVarRef final : public AstNodeVarRef { + // A reference to a variable (lvalue or rvalue) +public: + AstVarRef(FileLine* fl, const string& name, const VAccess& access) + : ASTGEN_SUPER_VarRef(fl, name, nullptr, access) {} + // This form only allowed post-link because output/wire compression may + // lead to deletion of AstVar's + inline AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access); + // This form only allowed post-link (see above) + inline AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access); + ASTNODE_NODE_FUNCS(VarRef) + virtual void dump(std::ostream& str) const override; + bool same(const AstNode* samep) const override; + inline bool same(const AstVarRef* samep) const; + inline bool sameNoLvalue(AstVarRef* samep) const; + virtual int instrCount() const override { + return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1); + } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } +}; +class AstVarXRef final : public AstNodeVarRef { + // A VarRef to something in another module before AstScope. + // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope +private: + string m_dotted; // Dotted part of scope the name()'ed reference is under or "" + string m_inlinedDots; // Dotted hierarchy flattened out +public: + AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access) + : ASTGEN_SUPER_VarXRef(fl, name, nullptr, access) + , m_dotted{dotted} {} + inline AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access); + ASTNODE_NODE_FUNCS(VarXRef) + virtual void dump(std::ostream& str) const override; + string dotted() const { return m_dotted; } + void dotted(const string& dotted) { m_dotted = dotted; } + string inlinedDots() const { return m_inlinedDots; } + void inlinedDots(const string& flag) { m_inlinedDots = flag; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode* samep) const override { + const AstVarXRef* asamep = static_cast(samep); + return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp() + && name() == asamep->name() && dotted() == asamep->dotted()); + } +}; + +#endif // Guard diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h new file mode 100644 index 000000000..b197e18bd --- /dev/null +++ b/src/V3AstNodeOther.h @@ -0,0 +1,4363 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: AstNode sub-types representing other constructs +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2022 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* +// +// This files contains all 'AstNode' sub-types that relate to other constructs +// not covered by the more speficic V3AstNode*.h files. +// +//************************************************************************* + +#ifndef VERILATOR_V3ASTNODES_H_ +#define VERILATOR_V3ASTNODES_H_ + +#ifndef VERILATOR_V3AST_H_ +#error "Use V3Ast.h as the include" +#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h +#define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE +#endif + +// === Abstract base node types (AstNode*) ===================================== + +class AstNodeBlock VL_NOT_FINAL : public AstNode { + // A Begin/fork block + // Parents: statement + // Children: statements +private: + string m_name; // Name of block + bool m_unnamed; // Originally unnamed (name change does not affect this) +protected: + AstNodeBlock(VNType t, FileLine* fl, const string& name, AstNode* stmtsp) + : AstNode{t, fl} + , m_name{name} { + addNOp1p(stmtsp); + m_unnamed = (name == ""); + } + +public: + ASTNODE_BASE_FUNCS(NodeBlock) + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } // * = Block name + virtual void name(const string& name) override { m_name = name; } + // op1 = Statements + AstNode* stmtsp() const { return op1p(); } // op1 = List of statements + void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } + bool unnamed() const { return m_unnamed; } + bool isFirstInMyListOfStatements(AstNode* nodep) const override { return nodep == stmtsp(); } +}; +class AstNodeFTask VL_NOT_FINAL : public AstNode { +private: + string m_name; // Name of task + string m_cname; // Name of task if DPI import + uint64_t m_dpiOpenParent = 0; // DPI import open array, if !=0, how many callees + bool m_taskPublic : 1; // Public task + bool m_attrIsolateAssign : 1; // User isolate_assignments attribute + bool m_classMethod : 1; // Class method + bool m_externProto : 1; // Extern prototype + bool m_externDef : 1; // Extern definition + bool m_prototype : 1; // Just a prototype + bool m_dpiExport : 1; // DPI exported + bool m_dpiImport : 1; // DPI imported + bool m_dpiContext : 1; // DPI import context + bool m_dpiOpenChild : 1; // DPI import open array child wrapper + bool m_dpiTask : 1; // DPI import task (vs. void function) + bool m_dpiTraceInit : 1; // DPI trace_init + bool m_isConstructor : 1; // Class constructor + bool m_isHideLocal : 1; // Verilog local + bool m_isHideProtected : 1; // Verilog protected + bool m_pure : 1; // DPI import pure (vs. virtual pure) + bool m_pureVirtual : 1; // Pure virtual + bool m_recursive : 1; // Recusive or part of recursion + bool m_underGenerate : 1; // Under generate (for warning) + bool m_virtual : 1; // Virtual method in class + VLifetime m_lifetime; // Lifetime +protected: + AstNodeFTask(VNType t, FileLine* fl, const string& name, AstNode* stmtsp) + : AstNode{t, fl} + , m_name{name} + , m_taskPublic{false} + , m_attrIsolateAssign{false} + , m_classMethod{false} + , m_externProto{false} + , m_externDef{false} + , m_prototype{false} + , m_dpiExport{false} + , m_dpiImport{false} + , m_dpiContext{false} + , m_dpiOpenChild{false} + , m_dpiTask{false} + , m_dpiTraceInit{false} + , m_isConstructor{false} + , m_isHideLocal{false} + , m_isHideProtected{false} + , m_pure{false} + , m_pureVirtual{false} + , m_recursive{false} + , m_underGenerate{false} + , m_virtual{false} { + addNOp3p(stmtsp); + cname(name); // Might be overridden by dpi import/export + } + +public: + ASTNODE_BASE_FUNCS(NodeFTask) + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool maybePointedTo() const override { return true; } + virtual bool isGateOptimizable() const override { + return !((m_dpiExport || m_dpiImport) && !m_pure); + } + // {AstFunc only} op1 = Range output variable + virtual void name(const string& name) override { m_name = name; } + string cname() const { return m_cname; } + void cname(const string& cname) { m_cname = cname; } + // op1 = Output variable (functions only, nullptr for tasks) + AstNode* fvarp() const { return op1p(); } + void addFvarp(AstNode* nodep) { addNOp1p(nodep); } + bool isFunction() const { return fvarp() != nullptr; } + // op2 = Class/package scope + AstNode* classOrPackagep() const { return op2p(); } + void classOrPackagep(AstNode* nodep) { setNOp2p(nodep); } + // op3 = Statements/Ports/Vars + AstNode* stmtsp() const { return op3p(); } // op3 = List of statements + void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } + // op4 = scope name + AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); } + // MORE ACCESSORS + void dpiOpenParentInc() { ++m_dpiOpenParent; } + void dpiOpenParentClear() { m_dpiOpenParent = 0; } + uint64_t dpiOpenParent() const { return m_dpiOpenParent; } + void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } + void taskPublic(bool flag) { m_taskPublic = flag; } + bool taskPublic() const { return m_taskPublic; } + void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } + bool attrIsolateAssign() const { return m_attrIsolateAssign; } + void classMethod(bool flag) { m_classMethod = flag; } + bool classMethod() const { return m_classMethod; } + void isExternProto(bool flag) { m_externProto = flag; } + bool isExternProto() const { return m_externProto; } + void isExternDef(bool flag) { m_externDef = flag; } + bool isExternDef() const { return m_externDef; } + void prototype(bool flag) { m_prototype = flag; } + bool prototype() const { return m_prototype; } + void dpiExport(bool flag) { m_dpiExport = flag; } + bool dpiExport() const { return m_dpiExport; } + void dpiImport(bool flag) { m_dpiImport = flag; } + bool dpiImport() const { return m_dpiImport; } + void dpiContext(bool flag) { m_dpiContext = flag; } + bool dpiContext() const { return m_dpiContext; } + void dpiOpenChild(bool flag) { m_dpiOpenChild = flag; } + bool dpiOpenChild() const { return m_dpiOpenChild; } + void dpiTask(bool flag) { m_dpiTask = flag; } + bool dpiTask() const { return m_dpiTask; } + void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; } + bool dpiTraceInit() const { return m_dpiTraceInit; } + void isConstructor(bool flag) { m_isConstructor = flag; } + bool isConstructor() const { return m_isConstructor; } + bool isHideLocal() const { return m_isHideLocal; } + void isHideLocal(bool flag) { m_isHideLocal = flag; } + bool isHideProtected() const { return m_isHideProtected; } + void isHideProtected(bool flag) { m_isHideProtected = flag; } + void pure(bool flag) { m_pure = flag; } + bool pure() const { return m_pure; } + void pureVirtual(bool flag) { m_pureVirtual = flag; } + bool pureVirtual() const { return m_pureVirtual; } + void recursive(bool flag) { m_recursive = flag; } + bool recursive() const { return m_recursive; } + void underGenerate(bool flag) { m_underGenerate = flag; } + bool underGenerate() const { return m_underGenerate; } + void isVirtual(bool flag) { m_virtual = flag; } + bool isVirtual() const { return m_virtual; } + void lifetime(const VLifetime& flag) { m_lifetime = flag; } + VLifetime lifetime() const { return m_lifetime; } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } +}; +class AstNodeFile VL_NOT_FINAL : public AstNode { + // Emitted Otput file + // Parents: NETLIST + // Children: AstTextBlock +private: + string m_name; ///< Filename +public: + AstNodeFile(VNType t, FileLine* fl, const string& name) + : AstNode(t, fl) { + m_name = name; + } + ASTNODE_BASE_FUNCS(NodeFile) + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + void tblockp(AstTextBlock* tblockp) { setOp1p((AstNode*)tblockp); } + AstTextBlock* tblockp() { return VN_AS(op1p(), TextBlock); } +}; +class AstNodeModule VL_NOT_FINAL : public AstNode { + // A module, package, program or interface declaration; + // something that can live directly under the TOP, + // excluding $unit package stuff +private: + string m_name; // Name of the module + const string m_origName; // Name of the module, ignoring name() changes, for dot lookup + string m_someInstanceName; // Hierarchical name of some arbitrary instance of this module. + // Used for user messages only. + bool m_modPublic : 1; // Module has public references + bool m_modTrace : 1; // Tracing this module + bool m_inLibrary : 1; // From a library, no error if not used, never top level + bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors + bool m_hierBlock : 1; // Hiearchical Block marked by HIER_BLOCK pragma + bool m_internal : 1; // Internally created + bool m_recursive : 1; // Recursive module + bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr + int m_level = 0; // 1=top module, 2=cell off top module, ... + VLifetime m_lifetime; // Lifetime + VTimescale m_timeunit; // Global time unit + VOptionBool m_unconnectedDrive; // State of `unconnected_drive +protected: + AstNodeModule(VNType t, FileLine* fl, const string& name) + : AstNode{t, fl} + , m_name{name} + , m_origName{name} + , m_modPublic{false} + , m_modTrace{false} + , m_inLibrary{false} + , m_dead{false} + , m_hierBlock{false} + , m_internal{false} + , m_recursive{false} + , m_recursiveClone{false} {} + +public: + ASTNODE_BASE_FUNCS(NodeModule) + virtual void dump(std::ostream& str) const override; + virtual bool maybePointedTo() const override { return true; } + virtual string name() const override { return m_name; } + virtual bool timescaleMatters() const = 0; + AstNode* stmtsp() const { return op2p(); } // op2 = List of statements + AstActive* activesp() const { return VN_AS(op3p(), Active); } // op3 = List of i/sblocks + // METHODS + void addInlinesp(AstNode* nodep) { addOp1p(nodep); } + void addStmtp(AstNode* nodep) { addNOp2p(nodep); } + void addActivep(AstNode* nodep) { addOp3p(nodep); } + // ACCESSORS + virtual void name(const string& name) override { m_name = name; } + virtual string origName() const override { return m_origName; } + string someInstanceName() const { return m_someInstanceName; } + void someInstanceName(const string& name) { m_someInstanceName = name; } + bool inLibrary() const { return m_inLibrary; } + void inLibrary(bool flag) { m_inLibrary = flag; } + void level(int level) { m_level = level; } + int level() const { return m_level; } + bool isTop() const { return level() == 1; } + void modPublic(bool flag) { m_modPublic = flag; } + bool modPublic() const { return m_modPublic; } + void modTrace(bool flag) { m_modTrace = flag; } + bool modTrace() const { return m_modTrace; } + void dead(bool flag) { m_dead = flag; } + bool dead() const { return m_dead; } + void hierBlock(bool flag) { m_hierBlock = flag; } + bool hierBlock() const { return m_hierBlock; } + void internal(bool flag) { m_internal = flag; } + bool internal() const { return m_internal; } + void recursive(bool flag) { m_recursive = flag; } + bool recursive() const { return m_recursive; } + void recursiveClone(bool flag) { m_recursiveClone = flag; } + bool recursiveClone() const { return m_recursiveClone; } + void lifetime(const VLifetime& flag) { m_lifetime = flag; } + VLifetime lifetime() const { return m_lifetime; } + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } + void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; } + VOptionBool unconnectedDrive() const { return m_unconnectedDrive; } +}; +class AstNodePreSel VL_NOT_FINAL : public AstNode { + // Something that becomes an AstSel +protected: + AstNodePreSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* rhs, AstNode* ths) + : AstNode{t, fl} { + setOp1p(fromp); + setOp2p(rhs); + setNOp3p(ths); + } + +public: + ASTNODE_BASE_FUNCS(NodePreSel) + AstNode* fromp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } + AstNode* thsp() const { return op3p(); } + AstAttrOf* attrp() const { return VN_AS(op4p(), AttrOf); } + void fromp(AstNode* nodep) { return setOp1p(nodep); } + void rhsp(AstNode* nodep) { return setOp2p(nodep); } + void thsp(AstNode* nodep) { return setOp3p(nodep); } + void attrp(AstAttrOf* nodep) { return setOp4p(reinterpret_cast(nodep)); } + // METHODS + virtual bool same(const AstNode*) const override { return true; } +}; +class AstNodeProcedure VL_NOT_FINAL : public AstNode { + // IEEE procedure: initial, final, always +protected: + AstNodeProcedure(VNType t, FileLine* fl, AstNode* bodysp) + : AstNode{t, fl} { + addNOp2p(bodysp); + } + +public: + ASTNODE_BASE_FUNCS(NodeProcedure) + // METHODS + virtual void dump(std::ostream& str) const override; + AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate + void addStmtp(AstNode* nodep) { addOp2p(nodep); } + bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } +}; +class AstNodeRange VL_NOT_FINAL : public AstNode { + // A range, sized or unsized +protected: + AstNodeRange(VNType t, FileLine* fl) + : AstNode{t, fl} {} + +public: + ASTNODE_BASE_FUNCS(NodeRange) + virtual void dump(std::ostream& str) const override; +}; +class AstNodeStmt VL_NOT_FINAL : public AstNode { + // Statement -- anything that's directly under a function + bool m_statement; // Really a statement (e.g. not a function with return) +protected: + AstNodeStmt(VNType t, FileLine* fl, bool statement = true) + : AstNode{t, fl} + , m_statement{statement} {} + +public: + ASTNODE_BASE_FUNCS(NodeStmt) + // METHODS + bool isStatement() const { return m_statement; } // Really a statement + void statement(bool flag) { m_statement = flag; } + virtual void addNextStmt(AstNode* newp, + AstNode* belowp) override; // Stop statement searchback here + virtual void addBeforeStmt(AstNode* newp, + AstNode* belowp) override; // Stop statement searchback here + virtual void dump(std::ostream& str = std::cout) const override; +}; +class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt { +protected: + AstNodeAssign(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, + AstNode* timingControlp = nullptr) + : AstNodeStmt{t, fl} { + setOp1p(rhsp); + setOp2p(lhsp); + addNOp3p(timingControlp); + dtypeFrom(lhsp); + } + +public: + ASTNODE_BASE_FUNCS(NodeAssign) + // Clone single node, just get same type back. + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; + // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 + AstNode* rhsp() const { return op1p(); } // op1 = Assign from + AstNode* lhsp() const { return op2p(); } // op2 = Assign to + // op3 = Timing controls (delays, event controls) + AstNode* timingControlp() const { return op3p(); } + void addTimingControlp(AstNode* const np) { addNOp3p(np); } + void rhsp(AstNode* np) { setOp1p(np); } + void lhsp(AstNode* np) { setOp2p(np); } + virtual bool hasDType() const override { return true; } + virtual bool cleanRhs() const { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode*) const override { return true; } + virtual string verilogKwd() const override { return "="; } + virtual bool brokeLhsMustBeLvalue() const = 0; +}; +class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt { + // A call of a C++ function, perhaps a AstCFunc or perhaps globally named + // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. + AstCFunc* m_funcp; + string m_argTypes; + +protected: + AstNodeCCall(VNType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) + : AstNodeStmt{t, fl, true} + , m_funcp{funcp} { + addNOp2p(argsp); + } + +public: + ASTNODE_BASE_FUNCS(NodeCCall) + virtual void dump(std::ostream& str = std::cout) const override; + virtual void cloneRelink() override; + virtual const char* broken() const override; + virtual int instrCount() const override { return INSTR_COUNT_CALL; } + virtual bool same(const AstNode* samep) const override { + const AstNodeCCall* const asamep = static_cast(samep); + return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes()); + } + AstNode* exprsp() const { return op2p(); } // op2 = expressions to print + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override; + virtual bool isOutputter() const override { return !isPure(); } + AstCFunc* funcp() const { return m_funcp; } + void funcp(AstCFunc* funcp) { m_funcp = funcp; } + void argTypes(const string& str) { m_argTypes = str; } + string argTypes() const { return m_argTypes; } + // op1p reserved for AstCMethodCall + AstNode* argsp() const { return op2p(); } + void addArgsp(AstNode* nodep) { addOp2p(nodep); } +}; +class AstNodeCase VL_NOT_FINAL : public AstNodeStmt { +protected: + AstNodeCase(VNType t, FileLine* fl, AstNode* exprp, AstNode* casesp) + : AstNodeStmt{t, fl} { + setOp1p(exprp); + addNOp2p(casesp); + } + +public: + ASTNODE_BASE_FUNCS(NodeCase) + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + AstNode* exprp() const { return op1p(); } // op1 = case condition + AstCaseItem* itemsp() const { + return VN_AS(op2p(), CaseItem); + } // op2 = list of case expressions + AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's + void addItemsp(AstNode* nodep) { addOp2p(nodep); } + void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } +}; +class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt { + // Cover or Assert + // Parents: {statement list} + // Children: expression, report string +private: + const bool m_immediate; // Immediate assertion/cover + string m_name; // Name to report +public: + AstNodeCoverOrAssert(VNType t, FileLine* fl, AstNode* propp, AstNode* passsp, bool immediate, + const string& name = "") + : AstNodeStmt{t, fl} + , m_immediate{immediate} + , m_name{name} { + addOp1p(propp); + addNOp4p(passsp); + } + ASTNODE_BASE_FUNCS(NodeCoverOrAssert) + virtual string name() const override { return m_name; } // * = Var name + virtual bool same(const AstNode* samep) const override { return samep->name() == name(); } + virtual void name(const string& name) override { m_name = name; } + virtual void dump(std::ostream& str = std::cout) const override; + AstNode* propp() const { return op1p(); } // op1 = property + AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain + void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain + AstNode* passsp() const { return op4p(); } // op4 = statements (assert/cover passes) + bool immediate() const { return m_immediate; } +}; +class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt { + // A reference to a task (or function) + // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. +private: + AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced + AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy + string m_name; // Name of variable + string m_dotted; // Dotted part of scope the name()ed task/func is under or "" + string m_inlinedDots; // Dotted hierarchy flattened out + bool m_pli = false; // Pli system call ($name) +protected: + AstNodeFTaskRef(VNType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp) + : AstNodeStmt{t, fl, statement} { + setOp1p(namep); + addNOp3p(pinsp); + } + AstNodeFTaskRef(VNType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp) + : AstNodeStmt{t, fl, statement} + , m_name{name} { + addNOp3p(pinsp); + } + +public: + ASTNODE_BASE_FUNCS(NodeFTaskRef) + virtual const char* broken() const override; + virtual void cloneRelink() override; + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool isGateOptimizable() const override { + return m_taskp && m_taskp->isGateOptimizable(); + } + string dotted() const { return m_dotted; } // * = Scope name or "" + string inlinedDots() const { return m_inlinedDots; } + void inlinedDots(const string& flag) { m_inlinedDots = flag; } + AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable + void taskp(AstNodeFTask* taskp) { m_taskp = taskp; } + virtual void name(const string& name) override { m_name = name; } + void dotted(const string& name) { m_dotted = name; } + AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } + bool pli() const { return m_pli; } + void pli(bool flag) { m_pli = flag; } + // op1 = namep + AstNode* namep() const { return op1p(); } + // op2 = reserved for AstMethodCall + // op3 = Pin interconnection list + AstNode* pinsp() const { return op3p(); } + void addPinsp(AstNode* nodep) { addOp3p(nodep); } + // op4 = scope tracking + AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); } + void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } +}; +class AstNodeFor VL_NOT_FINAL : public AstNodeStmt { +protected: + AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, + AstNode* bodysp) + : AstNodeStmt{t, fl} { + addNOp1p(initsp); + setOp2p(condp); + addNOp3p(incsp); + addNOp4p(bodysp); + } + +public: + ASTNODE_BASE_FUNCS(NodeFor) + AstNode* initsp() const { return op1p(); } // op1 = initial statements + AstNode* condp() const { return op2p(); } // op2 = condition to continue + AstNode* incsp() const { return op3p(); } // op3 = increment statements + AstNode* bodysp() const { return op4p(); } // op4 = body of loop + virtual bool isGateOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { +private: + VBranchPred m_branchPred; // Branch prediction as taken/untaken? + bool m_isBoundsCheck; // True if this if node was inserted for array bounds checking +protected: + AstNodeIf(VNType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) + : AstNodeStmt{t, fl} { + setOp1p(condp); + addNOp2p(ifsp); + addNOp3p(elsesp); + isBoundsCheck(false); + } + +public: + ASTNODE_BASE_FUNCS(NodeIf) + AstNode* condp() const { return op1p(); } // op1 = condition + AstNode* ifsp() const { return op2p(); } // op2 = list of true statements + AstNode* elsesp() const { return op3p(); } // op3 = list of false statements + void condp(AstNode* newp) { setOp1p(newp); } + void addIfsp(AstNode* newp) { addOp2p(newp); } + void addElsesp(AstNode* newp) { addOp3p(newp); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isGateDedupable() const override { return true; } + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + void branchPred(VBranchPred flag) { m_branchPred = flag; } + VBranchPred branchPred() const { return m_branchPred; } + void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; } + bool isBoundsCheck() const { return m_isBoundsCheck; } + bool isFirstInMyListOfStatements(AstNode* n) const override { + return n == ifsp() || n == elsesp(); + } +}; +class AstNodeReadWriteMem VL_NOT_FINAL : public AstNodeStmt { +private: + const bool m_isHex; // readmemh, not readmemb +public: + AstNodeReadWriteMem(VNType t, FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, + AstNode* lsbp, AstNode* msbp) + : AstNodeStmt(t, fl) + , m_isHex(hex) { + setOp1p(filenamep); + setOp2p(memp); + setNOp3p(lsbp); + setNOp4p(msbp); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* samep) const override { + return isHex() == static_cast(samep)->isHex(); + } + bool isHex() const { return m_isHex; } + AstNode* filenamep() const { return op1p(); } + AstNode* memp() const { return op2p(); } + AstNode* lsbp() const { return op3p(); } + AstNode* msbp() const { return op4p(); } + virtual const char* cFuncPrefixp() const = 0; +}; +class AstNodeText VL_NOT_FINAL : public AstNode { +private: + string m_text; + +protected: + // Node that puts text into the output stream + AstNodeText(VNType t, FileLine* fl, const string& textp) + : AstNode{t, fl} { + m_text = textp; // Copy it + } + +public: + ASTNODE_BASE_FUNCS(NodeText) + virtual void dump(std::ostream& str = std::cout) const override; + virtual bool same(const AstNode* samep) const override { + const AstNodeText* asamep = static_cast(samep); + return text() == asamep->text(); + } + const string& text() const { return m_text; } +}; +class AstNodeSimpleText VL_NOT_FINAL : public AstNodeText { +private: + bool m_tracking; // When emit, it's ok to parse the string to do indentation +public: + AstNodeSimpleText(VNType t, FileLine* fl, const string& textp, bool tracking = false) + : AstNodeText(t, fl, textp) + , m_tracking(tracking) {} + ASTNODE_BASE_FUNCS(NodeSimpleText) + void tracking(bool flag) { m_tracking = flag; } + bool tracking() const { return m_tracking; } +}; + +// === Concrete node types ===================================================== + +// === AstNode === +class AstActive final : public AstNode { + // Block of code with sensitivity activation + // Parents: MODULE | CFUNC + // Children: SENTREE, statements +private: + string m_name; + AstSenTree* m_sensesp; + +public: + AstActive(FileLine* fl, const string& name, AstSenTree* sensesp) + : ASTGEN_SUPER_Active(fl) { + m_name = name; // Copy it + UASSERT(sensesp, "Sensesp required arg"); + m_sensesp = sensesp; + } + ASTNODE_NODE_FUNCS(Active) + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } + const char* broken() const override; + void cloneRelink() override; + // Statements are broken into pieces, as some must come before others. + void sensesp(AstSenTree* nodep) { m_sensesp = nodep; } + AstSenTree* sensesp() const { return m_sensesp; } + // op1 = Sensitivity tree, if a clocked block in early stages + void sensesStorep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } + AstSenTree* sensesStorep() const { return VN_AS(op1p(), SenTree); } + // op2 = Combo logic + AstNode* stmtsp() const { return op2p(); } + void addStmtsp(AstNode* nodep) { addOp2p(nodep); } + // METHODS + inline bool hasInitial() const; + inline bool hasSettle() const; + inline bool hasClocked() const; +}; +class AstArg final : public AstNode { + // An argument to a function/task +private: + string m_name; // Pin name, or "" for number based interconnect +public: + AstArg(FileLine* fl, const string& name, AstNode* exprp) + : ASTGEN_SUPER_Arg(fl) + , m_name{name} { + setNOp1p(exprp); + } + ASTNODE_NODE_FUNCS(Arg) + virtual string name() const override { return m_name; } // * = Pin name, ""=go by number + virtual void name(const string& name) override { m_name = name; } + void exprp(AstNode* nodep) { addOp1p(nodep); } + // op1 = Expression connected to pin, nullptr if unconnected + AstNode* exprp() const { return op1p(); } + bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } +}; +class AstAttrOf final : public AstNode { +private: + // Return a value of a attribute, for example a LSB or array LSB of a signal + VAttrType m_attrType; // What sort of extraction +public: + AstAttrOf(FileLine* fl, VAttrType attrtype, AstNode* fromp = nullptr, AstNode* dimp = nullptr) + : ASTGEN_SUPER_AttrOf(fl) { + setNOp1p(fromp); + setNOp2p(dimp); + m_attrType = attrtype; + } + ASTNODE_NODE_FUNCS(AttrOf) + AstNode* fromp() const { return op1p(); } + AstNode* dimp() const { return op2p(); } + VAttrType attrType() const { return m_attrType; } + virtual void dump(std::ostream& str = std::cout) const override; +}; +class AstBind final : public AstNode { + // Parents: MODULE + // Children: CELL +private: + string m_name; // Binding to name +public: + AstBind(FileLine* fl, const string& name, AstNode* cellsp) + : ASTGEN_SUPER_Bind(fl) + , m_name{name} { + UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound"); + addNOp1p(cellsp); + } + ASTNODE_NODE_FUNCS(Bind) + // ACCESSORS + virtual string name() const override { return m_name; } // * = Bind Target name + virtual void name(const string& name) override { m_name = name; } + AstNode* cellsp() const { return op1p(); } // op1 = cells +}; +class AstCFunc final : public AstNode { + // C++ function + // Parents: MODULE/SCOPE + // Children: VAR/statements +private: + AstScope* m_scopep; + string m_name; + string m_cname; // C name, for dpiExports + string m_rtnType; // void, bool, or other return type + string m_argTypes; // Argument types + string m_ctorInits; // Constructor sub-class inits + string m_ifdef; // #ifdef symbol around this function + VBoolOrUnknown m_isConst; // Function is declared const (*this not changed) + bool m_isStatic : 1; // Function is static (no need for a 'this' pointer) + bool m_isTrace : 1; // Function is related to tracing + bool m_dontCombine : 1; // V3Combine shouldn't compare this func tree, it's special + bool m_declPrivate : 1; // Declare it private + bool m_isFinal : 1; // This is a function corresponding to a SystemVerilog 'final' block + bool m_slow : 1; // Slow routine, called once or just at init time + bool m_funcPublic : 1; // From user public task/function + bool m_isConstructor : 1; // Is C class constructor + bool m_isDestructor : 1; // Is C class destructor + bool m_isMethod : 1; // Is inside a class definition + bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function + // with an explicitly passed 'self' pointer as the first argument + bool m_isInline : 1; // Inline function + bool m_isVirtual : 1; // Virtual function + bool m_entryPoint : 1; // User may call into this top level function + bool m_pure : 1; // Pure function + bool m_dpiContext : 1; // Declared as 'context' DPI import/export function + bool m_dpiExportDispatcher : 1; // This is the DPI export entry point (i.e.: called by user) + bool m_dpiExportImpl : 1; // DPI export implementation (called from DPI dispatcher via lookup) + bool m_dpiImportPrototype : 1; // This is the DPI import prototype (i.e.: provided by user) + bool m_dpiImportWrapper : 1; // Wrapper for invoking DPI import prototype from generated code + bool m_dpiTraceInit : 1; // DPI trace_init +public: + AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType = "") + : ASTGEN_SUPER_CFunc(fl) { + m_isConst = VBoolOrUnknown::BU_UNKNOWN; // Unknown until analyzed + m_scopep = scopep; + m_name = name; + m_rtnType = rtnType; + m_isStatic = false; + m_isTrace = false; + m_dontCombine = false; + m_declPrivate = false; + m_isFinal = false; + m_slow = false; + m_funcPublic = false; + m_isConstructor = false; + m_isDestructor = false; + m_isMethod = true; + m_isLoose = false; + m_isInline = false; + m_isVirtual = false; + m_entryPoint = false; + m_pure = false; + m_dpiContext = false; + m_dpiExportDispatcher = false; + m_dpiExportImpl = false; + m_dpiImportPrototype = false; + m_dpiImportWrapper = false; + m_dpiTraceInit = false; + } + ASTNODE_NODE_FUNCS(CFunc) + virtual string name() const override { return m_name; } + const char* broken() const override; + void cloneRelink() override; + virtual bool maybePointedTo() const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; + virtual bool same(const AstNode* samep) const override { + const AstCFunc* const asamep = static_cast(samep); + return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid()) + && (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits()) + && isLoose() == asamep->isLoose() + && (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name())); + } + // + virtual void name(const string& name) override { m_name = name; } + virtual int instrCount() const override { + return dpiImportPrototype() ? v3Global.opt.instrCountDpi() : 0; + } + VBoolOrUnknown isConst() const { return m_isConst; } + void isConst(bool flag) { m_isConst.setTrueOrFalse(flag); } + void isConst(VBoolOrUnknown flag) { m_isConst = flag; } + bool isStatic() const { return m_isStatic; } + void isStatic(bool flag) { m_isStatic = flag; } + bool isTrace() const { return m_isTrace; } + void isTrace(bool flag) { m_isTrace = flag; } + void cname(const string& name) { m_cname = name; } + string cname() const { return m_cname; } + AstScope* scopep() const { return m_scopep; } + void scopep(AstScope* nodep) { m_scopep = nodep; } + string rtnTypeVoid() const { return ((m_rtnType == "") ? "void" : m_rtnType); } + bool dontCombine() const { return m_dontCombine || isTrace() || entryPoint(); } + void dontCombine(bool flag) { m_dontCombine = flag; } + bool dontInline() const { return dontCombine() || slow() || funcPublic(); } + bool declPrivate() const { return m_declPrivate; } + void declPrivate(bool flag) { m_declPrivate = flag; } + bool isFinal() const { return m_isFinal; } + void isFinal(bool flag) { m_isFinal = flag; } + bool slow() const { return m_slow; } + void slow(bool flag) { m_slow = flag; } + bool funcPublic() const { return m_funcPublic; } + void funcPublic(bool flag) { m_funcPublic = flag; } + void argTypes(const string& str) { m_argTypes = str; } + string argTypes() const { return m_argTypes; } + void ctorInits(const string& str) { m_ctorInits = str; } + string ctorInits() const { return m_ctorInits; } + void ifdef(const string& str) { m_ifdef = str; } + string ifdef() const { return m_ifdef; } + bool isConstructor() const { return m_isConstructor; } + void isConstructor(bool flag) { m_isConstructor = flag; } + bool isDestructor() const { return m_isDestructor; } + void isDestructor(bool flag) { m_isDestructor = flag; } + bool isMethod() const { return m_isMethod; } + void isMethod(bool flag) { m_isMethod = flag; } + bool isLoose() const { return m_isLoose; } + void isLoose(bool flag) { m_isLoose = flag; } + bool isProperMethod() const { return isMethod() && !isLoose(); } + bool isInline() const { return m_isInline; } + void isInline(bool flag) { m_isInline = flag; } + bool isVirtual() const { return m_isVirtual; } + void isVirtual(bool flag) { m_isVirtual = flag; } + bool entryPoint() const { return m_entryPoint; } + void entryPoint(bool flag) { m_entryPoint = flag; } + bool pure() const { return m_pure; } + void pure(bool flag) { m_pure = flag; } + bool dpiContext() const { return m_dpiContext; } + void dpiContext(bool flag) { m_dpiContext = flag; } + bool dpiExportDispatcher() const { return m_dpiExportDispatcher; } + void dpiExportDispatcher(bool flag) { m_dpiExportDispatcher = flag; } + bool dpiExportImpl() const { return m_dpiExportImpl; } + void dpiExportImpl(bool flag) { m_dpiExportImpl = flag; } + bool dpiImportPrototype() const { return m_dpiImportPrototype; } + void dpiImportPrototype(bool flag) { m_dpiImportPrototype = flag; } + bool dpiImportWrapper() const { return m_dpiImportWrapper; } + void dpiImportWrapper(bool flag) { m_dpiImportWrapper = flag; } + void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; } + bool dpiTraceInit() const { return m_dpiTraceInit; } + // + // If adding node accessors, see below emptyBody + AstNode* argsp() const { return op1p(); } + void addArgsp(AstNode* nodep) { addOp1p(nodep); } + AstNode* initsp() const { return op2p(); } + void addInitsp(AstNode* nodep) { addOp2p(nodep); } + AstNode* stmtsp() const { return op3p(); } + void addStmtsp(AstNode* nodep) { addOp3p(nodep); } + AstNode* finalsp() const { return op4p(); } + void addFinalsp(AstNode* nodep) { addOp4p(nodep); } + // Special methods + bool emptyBody() const { + return argsp() == nullptr && initsp() == nullptr && stmtsp() == nullptr + && finalsp() == nullptr; + } +}; +class AstCUse final : public AstNode { + // C++ use of a class or #include; indicates need of forward declaration + // Parents: NODEMODULE +private: + const VUseType m_useType; // What sort of use this is + const string m_name; + +public: + AstCUse(FileLine* fl, VUseType useType, const string& name) + : ASTGEN_SUPER_CUse(fl) + , m_useType{useType} + , m_name{name} {} + ASTNODE_NODE_FUNCS(CUse) + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } + VUseType useType() const { return m_useType; } +}; +class AstCaseItem final : public AstNode { + // Single item of a case statement + // Parents: CASE + // condsp Children: MATH (Null condition used for default block) + // bodysp Children: Statements +public: + AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* bodysp) + : ASTGEN_SUPER_CaseItem(fl) { + addNOp1p(condsp); + addNOp2p(bodysp); + } + ASTNODE_NODE_FUNCS(CaseItem) + virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions + AstNode* bodysp() const { return op2p(); } // op2 = what to do + void condsp(AstNode* nodep) { setOp1p(nodep); } + void addBodysp(AstNode* newp) { addOp2p(newp); } + bool isDefault() const { return condsp() == nullptr; } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } +}; +class AstCast final : public AstNode { + // Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc +public: + AstCast(FileLine* fl, AstNode* lhsp, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_Cast(fl) { + setOp1p(lhsp); + setOp2p(dtp); + dtypeFrom(dtp); + } + AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) + : ASTGEN_SUPER_Cast(fl) { + setOp1p(lhsp); + dtypeFrom(dtp); + } + ASTNODE_NODE_FUNCS(Cast) + virtual bool hasDType() const override { return true; } + virtual string emitVerilog() { return "((%d)'(%l))"; } + virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } + virtual bool cleanLhs() const { return true; } + virtual bool sizeMattersLhs() const { return false; } + AstNode* lhsp() const { return op1p(); } + AstNode* fromp() const { return lhsp(); } + void lhsp(AstNode* nodep) { setOp1p(nodep); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* childDTypep() const { return VN_AS(op2p(), NodeDType); } + virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } +}; +class AstCastParse final : public AstNode { + // Cast to appropriate type, where we haven't determined yet what the data type is +public: + AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp) + : ASTGEN_SUPER_CastParse(fl) { + setOp1p(lhsp); + setOp2p(dtp); + } + ASTNODE_NODE_FUNCS(CastParse) + virtual string emitVerilog() { return "((%d)'(%l))"; } + virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } + virtual bool cleanLhs() const { return true; } + virtual bool sizeMattersLhs() const { return false; } + AstNode* lhsp() const { return op1p(); } + AstNode* dtp() const { return op2p(); } +}; +class AstCastSize final : public AstNode { + // Cast to specific size; signed/twostate inherited from lower element per IEEE +public: + AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp) + : ASTGEN_SUPER_CastSize(fl) { + setOp1p(lhsp); + setOp2p((AstNode*)rhsp); + } + ASTNODE_NODE_FUNCS(CastSize) + // No hasDType because widthing removes this node before the hasDType check + virtual string emitVerilog() { return "((%r)'(%l))"; } + virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } + virtual bool cleanLhs() const { return true; } + virtual bool sizeMattersLhs() const { return false; } + AstNode* lhsp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } +}; +class AstCell final : public AstNode { + // A instantiation cell or interface call (don't know which until link) +private: + FileLine* m_modNameFileline; // Where module the cell instances token was + string m_name; // Cell name + string m_origName; // Original name before dot addition + string m_modName; // Module the cell instances + AstNodeModule* m_modp = nullptr; // [AfterLink] Pointer to module instanced + bool m_hasIfaceVar : 1; // True if a Var has been created for this cell + bool m_recursive : 1; // Self-recursive module + bool m_trace : 1; // Trace this cell +public: + AstCell(FileLine* fl, FileLine* mfl, const string& instName, const string& modName, + AstPin* pinsp, AstPin* paramsp, AstRange* rangep) + : ASTGEN_SUPER_Cell(fl) + , m_modNameFileline{mfl} + , m_name{instName} + , m_origName{instName} + , m_modName{modName} + , m_hasIfaceVar{false} + , m_recursive{false} + , m_trace{true} { + addNOp1p((AstNode*)pinsp); + addNOp2p((AstNode*)paramsp); + setNOp3p((AstNode*)rangep); + } + ASTNODE_NODE_FUNCS(Cell) + // No cloneRelink, we presume cloneee's want the same module linkages + virtual void dump(std::ostream& str) const override; + const char* broken() const override; + virtual bool maybePointedTo() const override { return true; } + // ACCESSORS + virtual string name() const override { return m_name; } // * = Cell name + virtual void name(const string& name) override { m_name = name; } + virtual string origName() const override { return m_origName; } // * = Original name + void origName(const string& name) { m_origName = name; } + string modName() const { return m_modName; } // * = Instance name + void modName(const string& name) { m_modName = name; } + FileLine* modNameFileline() const { return m_modNameFileline; } + AstPin* pinsp() const { return VN_AS(op1p(), Pin); } // op1 = List of cell ports + // op2 = List of parameter #(##) values + AstPin* paramsp() const { return VN_AS(op2p(), Pin); } + // op3 = Range of arrayed instants (nullptr=not ranged) + AstRange* rangep() const { return VN_AS(op3p(), Range); } + // op4 = List of interface references + AstIntfRef* intfRefp() const { return VN_AS(op4p(), IntfRef); } + AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated + void addPinsp(AstPin* nodep) { addOp1p((AstNode*)nodep); } + void addParamsp(AstPin* nodep) { addOp2p((AstNode*)nodep); } + void addIntfRefp(AstIntfRef* nodep) { addOp4p((AstNode*)nodep); } + void modp(AstNodeModule* nodep) { m_modp = nodep; } + bool hasIfaceVar() const { return m_hasIfaceVar; } + void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; } + void trace(bool flag) { m_trace = flag; } + bool isTrace() const { return m_trace; } + void recursive(bool flag) { m_recursive = flag; } + bool recursive() const { return m_recursive; } +}; +class AstCellArrayRef final : public AstNode { + // As-of-yet unlinkable reference into an array of cells +private: + string m_name; // Array name +public: + AstCellArrayRef(FileLine* fl, const string& name, AstNode* selectExprp) + : ASTGEN_SUPER_CellArrayRef(fl) + , m_name{name} { + addNOp1p(selectExprp); + } + ASTNODE_NODE_FUNCS(CellArrayRef) + // ACCESSORS + virtual string name() const override { return m_name; } // * = Array name + AstNode* selp() const { return op1p(); } // op1 = Select expression +}; +class AstCellInline final : public AstNode { + // A instantiation cell that was removed by inlining + // For communication between V3Inline and V3LinkDot, + // except for VPI runs where it exists until the end. + // It is augmented with the scope in V3Scope for VPI. + // Children: When 2 levels inlined, other CellInline under this +private: + string m_name; // Cell name, possibly {a}__DOT__{b}... + const string + m_origModName; // Original name of the module, ignoring name() changes, for dot lookup + AstScope* m_scopep = nullptr; // The scope that the cell is inlined into + VTimescale m_timeunit; // Parent module time unit +public: + AstCellInline(FileLine* fl, const string& name, const string& origModName, + const VTimescale& timeunit) + : ASTGEN_SUPER_CellInline(fl) + , m_name{name} + , m_origModName{origModName} + , m_timeunit{timeunit} {} + ASTNODE_NODE_FUNCS(CellInline) + virtual void dump(std::ostream& str) const override; + const char* broken() const override; + // ACCESSORS + virtual string name() const override { return m_name; } // * = Cell name + string origModName() const { return m_origModName; } // * = modp()->origName() before inlining + virtual void name(const string& name) override { m_name = name; } + void scopep(AstScope* scp) { m_scopep = scp; } + AstScope* scopep() const { return m_scopep; } + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } +}; +class AstCellRef final : public AstNode { + // As-of-yet unlinkable reference into a cell +private: + string m_name; // Cell name +public: + AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp) + : ASTGEN_SUPER_CellRef(fl) + , m_name{name} { + addNOp1p(cellp); + addNOp2p(exprp); + } + ASTNODE_NODE_FUNCS(CellRef) + // ACCESSORS + virtual string name() const override { return m_name; } // * = Array name + AstNode* cellp() const { return op1p(); } // op1 = Cell + AstNode* exprp() const { return op2p(); } // op2 = Expression +}; +class AstClassExtends final : public AstNode { + // Children: List of AstParseRef for packages/classes + // during early parse, then moves to dtype +public: + AstClassExtends(FileLine* fl, AstNode* classOrPkgsp) + : ASTGEN_SUPER_ClassExtends(fl) { + setNOp2p(classOrPkgsp); // Only for parser + } + ASTNODE_NODE_FUNCS(ClassExtends) + virtual bool hasDType() const override { return true; } + virtual string verilogKwd() const override { return "extends"; } + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + AstNode* classOrPkgsp() const { return op2p(); } + AstClass* classp() const; // Class being extended (after link) +}; +class AstClassOrPackageRef final : public AstNode { +private: + string m_name; + // Node not NodeModule to appease some early parser usage + AstNode* m_classOrPackageNodep; // Package hierarchy +public: + AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep, + AstNode* paramsp) + : ASTGEN_SUPER_ClassOrPackageRef(fl) + , m_name{name} + , m_classOrPackageNodep{classOrPackageNodep} { + addNOp4p(paramsp); + } + ASTNODE_NODE_FUNCS(ClassOrPackageRef) + // METHODS + virtual const char* broken() const override { + BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists()); + return nullptr; + } + virtual void cloneRelink() override { + if (m_classOrPackageNodep && m_classOrPackageNodep->clonep()) { + m_classOrPackageNodep = m_classOrPackageNodep->clonep(); + } + } + virtual bool same(const AstNode* samep) const override { + return (m_classOrPackageNodep + == static_cast(samep)->m_classOrPackageNodep); + } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } // * = Var name + AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } + void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } + AstNodeModule* classOrPackagep() const; + AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); } + void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = (AstNode*)nodep; } + AstPin* paramsp() const { return VN_AS(op4p(), Pin); } +}; +class AstClocking final : public AstNode { + // Set default clock region + // Parents: MODULE + // Children: Assertions +public: + AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp) + : ASTGEN_SUPER_Clocking(fl) { + addOp1p((AstNode*)sensesp); + addNOp2p(bodysp); + } + ASTNODE_NODE_FUNCS(Clocking) + // op1 = Sensitivity list + AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } + AstNode* bodysp() const { return op2p(); } // op2 = Body +}; +class AstConstPool final : public AstNode { + // Container for const static data + std::unordered_multimap m_tables; // Constant tables (unpacked arrays) + std::unordered_multimap m_consts; // Constant tables (scalars) + AstModule* const m_modp; // The Module holding the Scope below ... + AstScope* const m_scopep; // Scope holding the constant variables + + AstVarScope* createNewEntry(const string& name, AstNode* initp); + +public: + explicit AstConstPool(FileLine* fl); + ASTNODE_NODE_FUNCS(ConstPool) + virtual bool maybePointedTo() const override { return true; } + const char* broken() const override; + virtual void cloneRelink() override { V3ERROR_NA; } + AstModule* modp() const { return m_modp; } + + // Find a table (unpacked array) within the constant pool which is initialized with the + // given value, or create one if one does not already exists. The returned VarScope *might* + // have a different dtype than the given initp->dtypep(), including a different element type, + // but it will always have the same size and element width. In contexts where this matters, + // the caller must handle the dtype difference as appropriate. + AstVarScope* findTable(AstInitArray* initp); + // Find a constant within the constant pool which is initialized with the given value, or + // create one if one does not already exists. If 'mergeDType' is true, then the returned + // VarScope *might* have a different type than the given initp->dtypep(). In contexts where + // this matters, the caller must handle the dtype difference as appropriate. If 'mergeDType' is + // false, the returned VarScope will have _->dtypep()->sameTree(initp->dtypep()) return true. + AstVarScope* findConst(AstConst* initp, bool mergeDType); +}; +class AstDefParam final : public AstNode { + // A defparam assignment + // Parents: MODULE + // Children: math +private: + string m_name; // Name of variable getting set + string m_path; // Dotted cellname to set parameter of +public: + AstDefParam(FileLine* fl, const string& path, const string& name, AstNode* rhsp) + : ASTGEN_SUPER_DefParam(fl) { + setOp1p(rhsp); + m_name = name; + m_path = path; + } + virtual string name() const override { return m_name; } // * = Scope name + ASTNODE_NODE_FUNCS(DefParam) + virtual bool same(const AstNode*) const override { return true; } + AstNode* rhsp() const { return op1p(); } // op1 = Assign from + string path() const { return m_path; } +}; +class AstDot final : public AstNode { + // A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef + // These are eliminated in the link stage + const bool m_colon; // Is a "::" instead of a "." (lhs must be package/class) +public: + AstDot(FileLine* fl, bool colon, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_Dot(fl) + , m_colon{colon} { + setOp1p(lhsp); + setOp2p(rhsp); + } + ASTNODE_NODE_FUNCS(Dot) + // For parser, make only if non-null package + static AstNode* newIfPkg(FileLine* fl, AstNode* packageOrClassp, AstNode* rhsp) { + if (!packageOrClassp) return rhsp; + return new AstDot(fl, true, packageOrClassp, rhsp); + } + virtual void dump(std::ostream& str) const override; + AstNode* lhsp() const { return op1p(); } + void rhsp(AstNode* nodep) { setOp2p(nodep); } + AstNode* rhsp() const { return op2p(); } + bool colon() const { return m_colon; } +}; +class AstDpiExport final : public AstNode { + // We could put an AstNodeFTaskRef instead of the verilog function name, + // however we're not *calling* it, so that seems somehow wrong. + // (Probably AstNodeFTaskRef should be renamed AstNodeFTaskCall and have-a AstNodeFTaskRef) +private: + string m_name; // Name of function + string m_cname; // Name of function on c side +public: + AstDpiExport(FileLine* fl, const string& vname, const string& cname) + : ASTGEN_SUPER_DpiExport(fl) + , m_name{vname} + , m_cname{cname} {} + ASTNODE_NODE_FUNCS(DpiExport) + virtual string name() const override { return m_name; } + virtual void name(const string& name) override { m_name = name; } + string cname() const { return m_cname; } + void cname(const string& cname) { m_cname = cname; } +}; +class AstElabDisplay final : public AstNode { + // Parents: stmtlist + // Children: SFORMATF to generate print string +private: + VDisplayType m_displayType; + +public: + inline AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp); + ASTNODE_NODE_FUNCS(ElabDisplay) + virtual const char* broken() const override { + BROKEN_RTN(!fmtp()); + return nullptr; + } + virtual string verilogKwd() const override { + return (string("$") + string(displayType().ascii())); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* samep) const override { + return displayType() == static_cast(samep)->displayType(); + } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + VDisplayType displayType() const { return m_displayType; } + void displayType(VDisplayType type) { m_displayType = type; } + void fmtp(AstSFormatF* nodep) { addOp1p((AstNode*)nodep); } // op1 = To-String formatter + AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } +}; +class AstEmpty final : public AstNode { + // Represents something missing, e.g. a missing argument in FOREACH +public: + explicit AstEmpty(FileLine* fl) + : ASTGEN_SUPER_Empty(fl) {} + ASTNODE_NODE_FUNCS(Empty) + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstExecGraph final : public AstNode { + // For parallel execution, this node contains a dependency graph. Each + // vertex in the graph is an ExecMTask, which contains a body for the + // mtask (an AstMTaskBody), which contains sequentially executed statements. + // + // The AstMTaskBody nodes are also children of this node, so we can visit + // them without traversing the graph. +private: + V3Graph* const m_depGraphp; // contains ExecMTask vertices + const string m_name; // Name of this AstExecGraph (for uniqueness at code generation) + +public: + explicit AstExecGraph(FileLine* fl, const string& name); + ASTNODE_NODE_FUNCS_NO_DTOR(ExecGraph) + virtual ~AstExecGraph() override; + virtual const char* broken() const override { + BROKEN_RTN(!m_depGraphp); + return nullptr; + } + virtual string name() const override { return m_name; } + V3Graph* depGraphp() { return m_depGraphp; } + const V3Graph* depGraphp() const { return m_depGraphp; } + // op1: The mtask bodies + AstMTaskBody* mTaskBodiesp() const { return VN_AS(op1p(), MTaskBody); } + void addMTaskBodyp(AstMTaskBody* bodyp) { addOp1p((AstNode*)bodyp); } + // op2: In later phases, the statements that start the parallel execution + void addStmtsp(AstNode* stmtp) { addOp2p(stmtp); } +}; +class AstImplicit final : public AstNode { + // Create implicit wires and do nothing else, for gates that are ignored + // Parents: MODULE +public: + AstImplicit(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_Implicit(fl) { + addNOp1p(exprsp); + } + ASTNODE_NODE_FUNCS(Implicit) + AstNode* exprsp() const { return op1p(); } // op1 = Assign from +}; +class AstInitArray final : public AstNode { + // Set a var to a map of values + // The list of initsp() is not relevant + // If default is specified, the vector may be sparse, and not provide each value. + // Key values are C++ array style, with lo() at index 0 + // Parents: ASTVAR::init() + // Children: AstInitItem +public: + using KeyItemMap = std::map; + +private: + KeyItemMap m_map; // Node value for each array index +public: + AstInitArray(FileLine* fl, AstNodeDType* newDTypep, AstNode* defaultp) + : ASTGEN_SUPER_InitArray(fl) { + dtypep(newDTypep); + addNOp1p(defaultp); + } + ASTNODE_NODE_FUNCS(InitArray) + virtual void dump(std::ostream& str) const override; + const char* broken() const override; + void cloneRelink() override; + virtual bool hasDType() const override { return true; } + virtual bool same(const AstNode* samep) const override { + // Only works if exact same children, instead should override comparison + // of children list, and instead use map-vs-map key/value compare + return m_map == static_cast(samep)->m_map; + } + AstNode* defaultp() const { return op1p(); } // op1 = Default if sparse + void defaultp(AstNode* newp) { setOp1p(newp); } + AstNode* initsp() const { return op2p(); } // op2 = Initial value expressions + void addValuep(AstNode* newp) { addIndexValuep(m_map.size(), newp); } + const KeyItemMap& map() const { return m_map; } + AstNode* addIndexValuep(uint64_t index, AstNode* newp); + AstNode* getIndexValuep(uint64_t index) const; + AstNode* getIndexDefaultedValuep(uint64_t index) const; +}; +class AstInitItem final : public AstNode { + // Container for a item in an init array + // This container is present so that the value underneath may get replaced with a new nodep + // and the upper AstInitArray's map will remain correct (pointing to this InitItem) +public: + // Parents: INITARRAY + AstInitItem(FileLine* fl, AstNode* valuep) + : ASTGEN_SUPER_InitItem(fl) { + addOp1p(valuep); + } + ASTNODE_NODE_FUNCS(InitItem) + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return false; } // See valuep()'s dtype instead + AstNode* valuep() const { return op1p(); } // op1 = Value + void valuep(AstNode* nodep) { addOp1p(nodep); } +}; +class AstIntfRef final : public AstNode { + // An interface reference +private: + string m_name; // Name of the reference +public: + AstIntfRef(FileLine* fl, const string& name) + : ASTGEN_SUPER_IntfRef(fl) + , m_name{name} {} + virtual string name() const override { return m_name; } + ASTNODE_NODE_FUNCS(IntfRef) +}; +class AstMTaskBody final : public AstNode { + // Hold statements for each MTask +private: + ExecMTask* m_execMTaskp = nullptr; + +public: + explicit AstMTaskBody(FileLine* fl) + : ASTGEN_SUPER_MTaskBody(fl) {} + ASTNODE_NODE_FUNCS(MTaskBody); + virtual const char* broken() const override { + BROKEN_RTN(!m_execMTaskp); + return nullptr; + } + AstNode* stmtsp() const { return op1p(); } + void addStmtsp(AstNode* nodep) { addOp1p(nodep); } + void addStmtsFirstp(AstNode* nodep) { + if (stmtsp()) { + stmtsp()->addHereThisAsNext(nodep); + } else { + addStmtsp(nodep); + } + } + ExecMTask* execMTaskp() const { return m_execMTaskp; } + void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; } + virtual void dump(std::ostream& str = std::cout) const override; +}; +class AstModport final : public AstNode { + // A modport in an interface +private: + string m_name; // Name of the modport +public: + AstModport(FileLine* fl, const string& name, AstNode* varsp) + : ASTGEN_SUPER_Modport(fl) + , m_name{name} { + addNOp1p(varsp); + } + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + ASTNODE_NODE_FUNCS(Modport) + AstNode* varsp() const { return op1p(); } // op1 = List of Vars +}; +class AstModportFTaskRef final : public AstNode { + // An import/export referenced under a modport + // The storage for the function itself is inside the + // interface/instantiator, thus this is a reference + // PARENT: AstModport +private: + string m_name; // Name of the variable referenced + bool m_export; // Type of the function (import/export) + AstNodeFTask* m_ftaskp = nullptr; // Link to the function +public: + AstModportFTaskRef(FileLine* fl, const string& name, bool isExport) + : ASTGEN_SUPER_ModportFTaskRef(fl) + , m_name{name} + , m_export{isExport} {} + ASTNODE_NODE_FUNCS(ModportFTaskRef) + const char* broken() const override; + void cloneRelink() override; + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + bool isImport() const { return !m_export; } + bool isExport() const { return m_export; } + AstNodeFTask* ftaskp() const { return m_ftaskp; } // [After Link] Pointer to variable + void ftaskp(AstNodeFTask* ftaskp) { m_ftaskp = ftaskp; } +}; +class AstModportVarRef final : public AstNode { + // A input/output/etc variable referenced under a modport + // The storage for the variable itself is inside the interface, thus this is a reference + // PARENT: AstModport +private: + string m_name; // Name of the variable referenced + VDirection m_direction; // Direction of the variable (in/out) + AstVar* m_varp = nullptr; // Link to the actual Var +public: + AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction) + : ASTGEN_SUPER_ModportVarRef(fl) + , m_name{name} + , m_direction{direction} {} + ASTNODE_NODE_FUNCS(ModportVarRef) + const char* broken() const override; + void cloneRelink() override; + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + void direction(const VDirection& flag) { m_direction = flag; } + VDirection direction() const { return m_direction; } + AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable + void varp(AstVar* varp) { m_varp = varp; } +}; +class AstNetlist final : public AstNode { + // All modules are under this single top node. + // Parents: none + // Children: MODULEs & CFILEs +private: + AstTypeTable* const m_typeTablep; // Reference to top type table, for faster lookup + AstConstPool* const m_constPoolp; // Reference to constant pool, for faster lookup + AstPackage* m_dollarUnitPkgp = nullptr; // $unit + AstCFunc* m_evalp = nullptr; // The '_eval' function + AstVarScope* m_dpiExportTriggerp = nullptr; // The DPI export trigger variable + AstTopScope* m_topScopep = nullptr; // The singleton AstTopScope under the top module + VTimescale m_timeunit; // Global time unit + VTimescale m_timeprecision; // Global time precision + bool m_changeRequest = false; // Have _change_request method + bool m_timescaleSpecified = false; // Input HDL specified timescale + uint32_t m_nextFreeMTaskID = 1; // Next unique MTask ID within netlist + // starts at 1 so 0 means no MTask ID + uint32_t m_nextFreeMTaskProfilingID = 0; // Next unique ID to use for PGO +public: + AstNetlist(); + ASTNODE_NODE_FUNCS(Netlist) + const char* broken() const override; + virtual void cloneRelink() override { V3ERROR_NA; } + virtual string name() const override { return "$root"; } + virtual void dump(std::ostream& str) const override; + AstNodeModule* modulesp() const { // op1 = List of modules + return VN_AS(op1p(), NodeModule); + } + AstNodeModule* topModulep() const { // Top module in hierarchy + return modulesp(); // First one in the list, for now + } + void addModulep(AstNodeModule* modulep) { addOp1p((AstNode*)modulep); } + AstNodeFile* filesp() const { return VN_AS(op2p(), NodeFile); } // op2 = List of files + void addFilesp(AstNodeFile* filep) { addOp2p((AstNode*)filep); } + void addMiscsp(AstNode* nodep) { addOp3p(nodep); } + AstTypeTable* typeTablep() { return m_typeTablep; } + void changeRequest(bool specified) { m_changeRequest = specified; } + bool changeRequest() const { return m_changeRequest; } + AstConstPool* constPoolp() { return m_constPoolp; } + AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; } + AstPackage* dollarUnitPkgAddp(); + AstCFunc* evalp() const { return m_evalp; } + void evalp(AstCFunc* evalp) { m_evalp = evalp; } + AstVarScope* dpiExportTriggerp() const { return m_dpiExportTriggerp; } + void dpiExportTriggerp(AstVarScope* varScopep) { m_dpiExportTriggerp = varScopep; } + AstTopScope* topScopep() const { return m_topScopep; } + void createTopScope(AstScope* scopep); + VTimescale timeunit() const { return m_timeunit; } + void timeunit(const VTimescale& value) { m_timeunit = value; } + VTimescale timeprecision() const { return m_timeprecision; } + void timeInit() { + m_timeunit = v3Global.opt.timeDefaultUnit(); + m_timeprecision = v3Global.opt.timeDefaultPrec(); + } + void timeprecisionMerge(FileLine*, const VTimescale& value); + void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; } + bool timescaleSpecified() const { return m_timescaleSpecified; } + uint32_t allocNextMTaskID() { return m_nextFreeMTaskID++; } + uint32_t allocNextMTaskProfilingID() { return m_nextFreeMTaskProfilingID++; } + uint32_t usedMTaskProfilingIDs() const { return m_nextFreeMTaskProfilingID; } +}; +class AstPackageExport final : public AstNode { +private: + // A package export declaration + string m_name; + AstPackage* m_packagep; // Package hierarchy +public: + AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name) + : ASTGEN_SUPER_PackageExport(fl) + , m_name{name} + , m_packagep{packagep} {} + ASTNODE_NODE_FUNCS(PackageExport) + const char* broken() const override; + void cloneRelink() override; + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + AstPackage* packagep() const { return m_packagep; } + void packagep(AstPackage* nodep) { m_packagep = nodep; } +}; +class AstPackageExportStarStar final : public AstNode { + // A package export *::* declaration +public: + // cppcheck-suppress noExplicitConstructor + AstPackageExportStarStar(FileLine* fl) + : ASTGEN_SUPER_PackageExportStarStar(fl) {} + ASTNODE_NODE_FUNCS(PackageExportStarStar) +}; +class AstPackageImport final : public AstNode { +private: + // A package import declaration + string m_name; + AstPackage* m_packagep; // Package hierarchy +public: + AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name) + : ASTGEN_SUPER_PackageImport(fl) + , m_name{name} + , m_packagep{packagep} {} + ASTNODE_NODE_FUNCS(PackageImport) + const char* broken() const override; + void cloneRelink() override; + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + AstPackage* packagep() const { return m_packagep; } + void packagep(AstPackage* nodep) { m_packagep = nodep; } +}; +class AstParseRef final : public AstNode { + // A reference to a variable, function or task + // We don't know which at parse time due to bison constraints + // The link stages will replace this with AstVarRef, or AstTaskRef, etc. + // Parents: math|stmt + // Children: TEXT|DOT|SEL*|TASK|FUNC (or expression under sel) +private: + VParseRefExp m_expect; // Type we think it should resolve to + string m_name; + +public: + AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, AstNode* lhsp = nullptr, + AstNodeFTaskRef* ftaskrefp = nullptr) + : ASTGEN_SUPER_ParseRef(fl) + , m_expect{expect} + , m_name{name} { + setNOp1p(lhsp); + setNOp2p((AstNode*)ftaskrefp); + } + ASTNODE_NODE_FUNCS(ParseRef) + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool same(const AstNode* samep) const override { + const AstParseRef* const asamep = static_cast(samep); + return (expect() == asamep->expect() && m_name == asamep->m_name); + } + virtual void name(const string& name) override { m_name = name; } + VParseRefExp expect() const { return m_expect; } + void expect(VParseRefExp exp) { m_expect = exp; } + // op1 = Components + AstNode* lhsp() const { return op1p(); } // op1 = List of statements + AstNode* ftaskrefp() const { return op2p(); } // op2 = Function/task reference + // op2 = Function/task reference + void ftaskrefp(AstNodeFTaskRef* nodep) { setNOp2p((AstNode*)nodep); } +}; +class AstPin final : public AstNode { + // A pin on a cell +private: + int m_pinNum; // Pin number + string m_name; // Pin name, or "" for number based interconnect + AstVar* m_modVarp = nullptr; // Input/output this pin connects to on submodule. + AstParamTypeDType* m_modPTypep = nullptr; // Param type this pin connects to on submodule. + bool m_param = false; // Pin connects to parameter + bool m_svImplicit = false; // Pin is SystemVerilog .name'ed +public: + AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) + : ASTGEN_SUPER_Pin(fl) + , m_pinNum{pinNum} + , m_name{name} { + setNOp1p(exprp); + } + inline AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp); + ASTNODE_NODE_FUNCS(Pin) + virtual void dump(std::ostream& str) const override; + const char* broken() const override; + virtual string name() const override { return m_name; } // * = Pin name, ""=go by number + virtual void name(const string& name) override { m_name = name; } + string prettyOperatorName() const override; + bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked + int pinNum() const { return m_pinNum; } + void exprp(AstNode* nodep) { addOp1p(nodep); } + // op1 = Expression connected to pin, nullptr if unconnected + AstNode* exprp() const { return op1p(); } + AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable + void modVarp(AstVar* nodep) { m_modVarp = nodep; } + // [After Link] Pointer to variable + AstParamTypeDType* modPTypep() const { return m_modPTypep; } + void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; } + bool param() const { return m_param; } + void param(bool flag) { m_param = flag; } + bool svImplicit() const { return m_svImplicit; } + void svImplicit(bool flag) { m_svImplicit = flag; } +}; +class AstPort final : public AstNode { + // A port (in/out/inout) on a module +private: + int m_pinNum; // Pin number + string m_name; // Name of pin +public: + AstPort(FileLine* fl, int pinnum, const string& name) + : ASTGEN_SUPER_Port(fl) + , m_pinNum{pinnum} + , m_name{name} {} + ASTNODE_NODE_FUNCS(Port) + virtual string name() const override { return m_name; } // * = Port name + int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation + AstNode* exprp() const { return op1p(); } // op1 = Expression connected to port +}; +class AstPragma final : public AstNode { +private: + const VPragmaType m_pragType; // Type of pragma +public: + // Pragmas don't result in any output code, they're just flags that affect + // other processing in verilator. + AstPragma(FileLine* fl, VPragmaType pragType) + : ASTGEN_SUPER_Pragma(fl) + , m_pragType{pragType} {} + ASTNODE_NODE_FUNCS(Pragma) + VPragmaType pragType() const { return m_pragType; } // *=type of the pragma + virtual bool isPredictOptimizable() const override { return false; } + virtual bool same(const AstNode* samep) const override { + return pragType() == static_cast(samep)->pragType(); + } +}; +class AstPropClocked final : public AstNode { + // A clocked property + // Parents: ASSERT|COVER (property) + // Children: SENITEM, Properties +public: + AstPropClocked(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp) + : ASTGEN_SUPER_PropClocked(fl) { + addNOp1p((AstNode*)sensesp); + addNOp2p(disablep); + addOp3p(propp); + } + ASTNODE_NODE_FUNCS(PropClocked) + virtual bool hasDType() const override { + return true; + } // Used under Cover, which expects a bool child + AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } // op1 = Sensitivity list + AstNode* disablep() const { return op2p(); } // op2 = disable + AstNode* propp() const { return op3p(); } // op3 = property +}; +class AstPull final : public AstNode { +private: + bool m_direction; + +public: + AstPull(FileLine* fl, AstNode* lhsp, bool direction) + : ASTGEN_SUPER_Pull(fl) { + setOp1p(lhsp); + m_direction = direction; + } + ASTNODE_NODE_FUNCS(Pull) + virtual bool same(const AstNode* samep) const override { + return direction() == static_cast(samep)->direction(); + } + void lhsp(AstNode* np) { setOp1p(np); } + AstNode* lhsp() const { return op1p(); } // op1 = Assign to + uint32_t direction() const { return (uint32_t)m_direction; } +}; +class AstSFormatF final : public AstNode { + // Convert format to string, generally under an AstDisplay or AstSFormat + // Also used as "real" function for /*verilator sformat*/ functions + string m_text; + const bool m_hidden; // Under display, etc + bool m_hasFormat; // Has format code + const char m_missingArgChar; // Format code when argument without format, 'h'/'o'/'b' + VTimescale m_timeunit; // Parent module time unit +public: + class NoFormat {}; + AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp, + char missingArgChar = 'd') + : ASTGEN_SUPER_SFormatF(fl) + , m_text{text} + , m_hidden{hidden} + , m_hasFormat{true} + , m_missingArgChar{missingArgChar} { + dtypeSetString(); + addNOp1p(exprsp); + addNOp2p(nullptr); + } + AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd', + bool hidden = true) + : ASTGEN_SUPER_SFormatF(fl) + , m_text{""} + , m_hidden{hidden} + , m_hasFormat{false} + , m_missingArgChar{missingArgChar} { + dtypeSetString(); + addNOp1p(exprsp); + addNOp2p(nullptr); + } + ASTNODE_NODE_FUNCS(SFormatF) + virtual string name() const override { return m_text; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + virtual bool hasDType() const override { return true; } + virtual bool same(const AstNode* samep) const override { + return text() == static_cast(samep)->text(); + } + virtual string verilogKwd() const override { return "$sformatf"; } + void addExprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output + AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output + string text() const { return m_text; } // * = Text to display + void text(const string& text) { m_text = text; } + AstScopeName* scopeNamep() const { return VN_AS(op2p(), ScopeName); } + void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } + bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive + return (name().find("%m") != string::npos || name().find("%M") != string::npos); + } + bool hidden() const { return m_hidden; } + void hasFormat(bool flag) { m_hasFormat = flag; } + bool hasFormat() const { return m_hasFormat; } + char missingArgChar() const { return m_missingArgChar; } + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } +}; +class AstScope final : public AstNode { + // A particular usage of a cell + // Parents: MODULE + // Children: NODEBLOCK +private: + // An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope + string m_name; // Name + AstScope* const m_aboveScopep; // Scope above this one in the hierarchy (nullptr if top) + AstCell* const m_aboveCellp; // Cell above this in the hierarchy (nullptr if top) + AstNodeModule* const m_modp; // Module scope corresponds to +public: + AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep, + AstCell* aboveCellp) + : ASTGEN_SUPER_Scope(fl) + , m_name{name} + , m_aboveScopep{aboveScopep} + , m_aboveCellp{aboveCellp} + , m_modp{modp} {} + ASTNODE_NODE_FUNCS(Scope) + virtual void cloneRelink() override; + virtual const char* broken() const override; + virtual bool maybePointedTo() const override { return true; } + virtual string name() const override { return m_name; } // * = Scope name + virtual void name(const string& name) override { m_name = name; } + virtual void dump(std::ostream& str) const override; + string nameDotless() const; + string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); } + AstNodeModule* modp() const { return m_modp; } + void addVarp(AstVarScope* nodep) { addOp1p((AstNode*)nodep); } + AstVarScope* varsp() const { return VN_AS(op1p(), VarScope); } // op1 = AstVarScope's + void addActivep(AstNode* nodep) { addOp2p(nodep); } + AstNode* blocksp() const { return op2p(); } // op2 = Block names + void addFinalClkp(AstNode* nodep) { addOp3p(nodep); } + AstNode* finalClksp() const { return op3p(); } // op3 = Final assigns for clock correction + AstScope* aboveScopep() const { return m_aboveScopep; } + AstCell* aboveCellp() const { return m_aboveCellp; } + bool isTop() const { return aboveScopep() == nullptr; } // At top of hierarchy +}; +class AstSelLoopVars final : public AstNode { + // Parser only concept "[id, id, id]" for a foreach statement + // Unlike normal selects elements is a list +public: + AstSelLoopVars(FileLine* fl, AstNode* fromp, AstNode* elementsp) + : ASTGEN_SUPER_SelLoopVars(fl) { + setOp1p(fromp); + addNOp2p(elementsp); + } + ASTNODE_NODE_FUNCS(SelLoopVars) + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual bool maybePointedTo() const override { return false; } + AstNode* fromp() const { return op1p(); } + void fromp(AstNode* nodep) { setOp1p(nodep); } + AstNode* elementsp() const { return op2p(); } +}; +class AstSenItem final : public AstNode { + // Parents: SENTREE + // Children: (optional) VARREF +private: + VEdgeType m_edgeType; // Edge type +public: + class Combo {}; // for creator type-overload selection + class Illegal {}; // for creator type-overload selection + class Initial {}; // for creator type-overload selection + class Settle {}; // for creator type-overload selection + class Never {}; // for creator type-overload selection + AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* varrefp) + : ASTGEN_SUPER_SenItem(fl) + , m_edgeType{edgeType} { + setOp1p(varrefp); + } + AstSenItem(FileLine* fl, Combo) + : ASTGEN_SUPER_SenItem(fl) + , m_edgeType{VEdgeType::ET_COMBO} {} + AstSenItem(FileLine* fl, Illegal) + : ASTGEN_SUPER_SenItem(fl) + , m_edgeType{VEdgeType::ET_ILLEGAL} {} + AstSenItem(FileLine* fl, Initial) + : ASTGEN_SUPER_SenItem(fl) + , m_edgeType{VEdgeType::ET_INITIAL} {} + AstSenItem(FileLine* fl, Settle) + : ASTGEN_SUPER_SenItem(fl) + , m_edgeType{VEdgeType::ET_SETTLE} {} + AstSenItem(FileLine* fl, Never) + : ASTGEN_SUPER_SenItem(fl) + , m_edgeType{VEdgeType::ET_NEVER} {} + ASTNODE_NODE_FUNCS(SenItem) + virtual void dump(std::ostream& str) const override; + virtual bool same(const AstNode* samep) const override { + return edgeType() == static_cast(samep)->edgeType(); + } + VEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge + void edgeType(VEdgeType type) { + m_edgeType = type; + editCountInc(); + } // * = Posedge/negedge + AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized + AstNodeVarRef* varrefp() const { + return VN_CAST(op1p(), NodeVarRef); + } // op1 = Signal sensitized + // + bool isClocked() const { return edgeType().clockedStmt(); } + bool isCombo() const { return edgeType() == VEdgeType::ET_COMBO; } + bool isInitial() const { return edgeType() == VEdgeType::ET_INITIAL; } + bool isIllegal() const { return edgeType() == VEdgeType::ET_ILLEGAL; } + bool isSettle() const { return edgeType() == VEdgeType::ET_SETTLE; } + bool isNever() const { return edgeType() == VEdgeType::ET_NEVER; } + bool hasVar() const { return !(isCombo() || isInitial() || isSettle() || isNever()); } +}; +class AstSenTree final : public AstNode { + // A list of senitems + // Parents: MODULE | SBLOCK + // Children: SENITEM list +private: + bool m_multi = false; // Created from combo logic by ORing multiple clock domains +public: + AstSenTree(FileLine* fl, AstSenItem* sensesp) + : ASTGEN_SUPER_SenTree(fl) { + addNOp1p(sensesp); + } + ASTNODE_NODE_FUNCS(SenTree) + virtual void dump(std::ostream& str) const override; + virtual bool maybePointedTo() const override { return true; } + bool isMulti() const { return m_multi; } + // op1 = Sensitivity list + AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } + void addSensesp(AstSenItem* nodep) { addOp1p(nodep); } + void multi(bool flag) { m_multi = true; } + // METHODS + bool hasClocked() const; // Includes a clocked statement + bool hasSettle() const; // Includes a SETTLE SenItem + bool hasInitial() const; // Includes a INITIAL SenItem + bool hasCombo() const; // Includes a COMBO SenItem +}; +class AstSplitPlaceholder final : public AstNode { +public: + // Dummy node used within V3Split; never exists outside of V3Split. + explicit AstSplitPlaceholder(FileLine* fl) + : ASTGEN_SUPER_SplitPlaceholder(fl) {} + ASTNODE_NODE_FUNCS(SplitPlaceholder) +}; +class AstStrengthSpec final : public AstNode { +private: + VStrength m_s0; // Drive 0 strength + VStrength m_s1; // Drive 1 strength + +public: + AstStrengthSpec(FileLine* fl, VStrength s0, VStrength s1) + : ASTGEN_SUPER_StrengthSpec(fl) + , m_s0{s0} + , m_s1{s1} {} + + ASTNODE_NODE_FUNCS(StrengthSpec) + VStrength strength0() { return m_s0; } + VStrength strength1() { return m_s1; } + virtual void dump(std::ostream& str) const override; +}; +class AstTopScope final : public AstNode { + // A singleton, held under the top level AstModule. Holds the top level AstScope, + // and after V3ActiveTop, the global list of AstSenTrees (list of unique sensitivity lists). + // Parent: Top level AstModule + // Children: AstSenTree, AstScope + friend class AstNetlist; // Only the AstNetlist can create one + AstTopScope(FileLine* fl, AstScope* ascopep) + : ASTGEN_SUPER_TopScope(fl) { + addOp2p(ascopep); + } + +public: + ASTNODE_NODE_FUNCS(TopScope) + virtual bool maybePointedTo() const override { return true; } + AstSenTree* senTreesp() const { return VN_AS(op1p(), SenTree); } + void addSenTreep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } + AstScope* scopep() const { return VN_AS(op2p(), Scope); } +}; +class AstTypeTable final : public AstNode { + // Container for hash of standard data types + // Children: NODEDTYPEs + AstEmptyQueueDType* m_emptyQueuep = nullptr; + AstQueueDType* m_queueIndexp = nullptr; + AstVoidDType* m_voidp = nullptr; + AstBasicDType* m_basicps[VBasicDTypeKwd::_ENUM_MAX]{}; + // + using DetailedMap = std::map; + DetailedMap m_detailedMap; + +public: + explicit AstTypeTable(FileLine* fl); + ASTNODE_NODE_FUNCS(TypeTable) + virtual bool maybePointedTo() const override { return true; } + virtual const char* broken() const override { + BROKEN_RTN(m_emptyQueuep && !m_emptyQueuep->brokeExists()); + BROKEN_RTN(m_queueIndexp && !m_queueIndexp->brokeExists()); + BROKEN_RTN(m_voidp && !m_voidp->brokeExists()); + return nullptr; + } + virtual void cloneRelink() override { V3ERROR_NA; } + AstNodeDType* typesp() const { return VN_AS(op1p(), NodeDType); } // op1 = List of dtypes + void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); } + AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd); + AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width, int widthMin, + VSigning numeric); + AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, const VNumRange& range, + int widthMin, VSigning numeric); + AstBasicDType* findInsertSameDType(AstBasicDType* nodep); + AstEmptyQueueDType* findEmptyQueueDType(FileLine* fl); + AstQueueDType* findQueueIndexDType(FileLine* fl); + AstVoidDType* findVoidDType(FileLine* fl); + void clearCache(); + void repairCache(); + virtual void dump(std::ostream& str = std::cout) const override; +}; +class AstTypedef final : public AstNode { +private: + string m_name; + bool m_attrPublic; + string m_tag; // Holds the string of the verilator tag -- used in XML output. +public: + AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, + AstNodeDType* dtp) + : ASTGEN_SUPER_Typedef(fl) + , m_name{name} { + childDTypep(dtp); // Only for parser + addAttrsp(attrsp); + dtypep(nullptr); // V3Width will resolve + m_attrPublic = false; + } + ASTNODE_NODE_FUNCS(Typedef) + virtual void dump(std::ostream& str) const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Type assigning to + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } + void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } + AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse + // METHODS + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual void name(const string& flag) override { m_name = flag; } + bool attrPublic() const { return m_attrPublic; } + void attrPublic(bool flag) { m_attrPublic = flag; } + virtual void tag(const string& text) override { m_tag = text; } + virtual string tag() const override { return m_tag; } +}; +class AstTypedefFwd final : public AstNode { + // Forward declaration of a type; stripped after netlist parsing is complete +private: + string m_name; + +public: + AstTypedefFwd(FileLine* fl, const string& name) + : ASTGEN_SUPER_TypedefFwd(fl) + , m_name{name} {} + ASTNODE_NODE_FUNCS(TypedefFwd) + // METHODS + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } +}; +class AstUdpTable final : public AstNode { +public: + AstUdpTable(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER_UdpTable(fl) { + addNOp1p(bodysp); + } + ASTNODE_NODE_FUNCS(UdpTable) + // op1 = List of UdpTableLines + AstUdpTableLine* bodysp() const { return VN_AS(op1p(), UdpTableLine); } +}; +class AstUdpTableLine final : public AstNode { + string m_text; + +public: + AstUdpTableLine(FileLine* fl, const string& text) + : ASTGEN_SUPER_UdpTableLine(fl) + , m_text{text} {} + ASTNODE_NODE_FUNCS(UdpTableLine) + virtual string name() const override { return m_text; } + string text() const { return m_text; } +}; +class AstUnlinkedRef final : public AstNode { + // As-of-yet unlinkable Ref +private: + string m_name; // Var name +public: + AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* crp) + : ASTGEN_SUPER_UnlinkedRef(fl) + , m_name{name} { + addNOp1p(refp); + addNOp2p(crp); + } + ASTNODE_NODE_FUNCS(UnlinkedRef) + // ACCESSORS + virtual string name() const override { return m_name; } // * = Var name + AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef + AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef +}; +class AstVar final : public AstNode { + // A variable (in/out/wire/reg/param) inside a module +private: + string m_name; // Name of variable + string m_origName; // Original name before dot addition + string m_tag; // Holds the string of the verilator tag -- used in XML output. + VVarType m_varType; // Type of variable + VDirection m_direction; // Direction input/output etc + VDirection m_declDirection; // Declared direction input/output etc + VBasicDTypeKwd m_declKwd; // Keyword at declaration time + VLifetime m_lifetime; // Lifetime + VVarAttrClocker m_attrClocker; + MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var + int m_pinNum = 0; // For XML, if non-zero the connection pin number + bool m_ansi : 1; // ANSI port list variable (for dedup check) + bool m_declTyped : 1; // Declared as type (for dedup check) + bool m_tristate : 1; // Inout or triwire or trireg + bool m_primaryIO : 1; // In/out to top level (or directly assigned from same) + bool m_sc : 1; // SystemC variable + bool m_scClocked : 1; // SystemC sc_clk<> needed + bool m_scSensitive : 1; // SystemC sensitive() needed + bool m_sigPublic : 1; // User C code accesses this signal or is top signal + bool m_sigModPublic : 1; // User C code accesses this signal and module + bool m_sigUserRdPublic : 1; // User C code accesses this signal, read only + bool m_sigUserRWPublic : 1; // User C code accesses this signal, read-write + bool m_usedClock : 1; // Signal used as a clock + bool m_usedParam : 1; // Parameter is referenced (on link; later signals not setup) + bool m_usedLoopIdx : 1; // Variable subject of for unrolling + bool m_funcLocal : 1; // Local variable for a function + bool m_funcReturn : 1; // Return variable for a function + bool m_attrClockEn : 1; // User clock enable attribute + bool m_attrScBv : 1; // User force bit vector attribute + bool m_attrIsolateAssign : 1; // User isolate_assignments attribute + bool m_attrSFormat : 1; // User sformat attribute + bool m_attrSplitVar : 1; // declared with split_var metacomment + bool m_fileDescr : 1; // File descriptor + bool m_isRand : 1; // Random variable + bool m_isConst : 1; // Table contains constant data + bool m_isContinuously : 1; // Ever assigned continuously (for force/release) + bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier + bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic) + bool m_isPulldown : 1; // Tri0 + bool m_isPullup : 1; // Tri1 + bool m_isIfaceParent : 1; // dtype is reference to interface present in this module + bool m_isDpiOpenArray : 1; // DPI import open array + bool m_isHideLocal : 1; // Verilog local + bool m_isHideProtected : 1; // Verilog protected + bool m_noReset : 1; // Do not do automated reset/randomization + bool m_noSubst : 1; // Do not substitute out references + bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam + bool m_trace : 1; // Trace this variable + bool m_isLatched : 1; // Not assigned in all control paths of combo always + bool m_isForceable : 1; // May be forced/released externally from user C code + + void init() { + m_ansi = false; + m_declTyped = false; + m_tristate = false; + m_primaryIO = false; + m_sc = false; + m_scClocked = false; + m_scSensitive = false; + m_usedClock = false; + m_usedParam = false; + m_usedLoopIdx = false; + m_sigPublic = false; + m_sigModPublic = false; + m_sigUserRdPublic = false; + m_sigUserRWPublic = false; + m_funcLocal = false; + m_funcReturn = false; + m_attrClockEn = false; + m_attrScBv = false; + m_attrIsolateAssign = false; + m_attrSFormat = false; + m_attrSplitVar = false; + m_fileDescr = false; + m_isRand = false; + m_isConst = false; + m_isContinuously = false; + m_hasStrengthAssignment = false; + m_isStatic = false; + m_isPulldown = false; + m_isPullup = false; + m_isIfaceParent = false; + m_isDpiOpenArray = false; + m_isHideLocal = false; + m_isHideProtected = false; + m_noReset = false; + m_noSubst = false; + m_overridenParam = false; + m_trace = false; + m_isLatched = false; + m_isForceable = false; + m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN; + } + +public: + AstVar(FileLine* fl, VVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) + : ASTGEN_SUPER_Var(fl) + , m_name{name} + , m_origName{name} { + init(); + combineType(type); + childDTypep(dtp); // Only for parser + dtypep(nullptr); // V3Width will resolve + if (dtp->basicp()) { + m_declKwd = dtp->basicp()->keyword(); + } else { + m_declKwd = VBasicDTypeKwd::LOGIC; + } + } + AstVar(FileLine* fl, VVarType type, const string& name, AstNodeDType* dtp) + : ASTGEN_SUPER_Var(fl) + , m_name{name} + , m_origName{name} { + init(); + combineType(type); + UASSERT(dtp, "AstVar created with no dtype"); + dtypep(dtp); + if (dtp->basicp()) { + m_declKwd = dtp->basicp()->keyword(); + } else { + m_declKwd = VBasicDTypeKwd::LOGIC; + } + } + AstVar(FileLine* fl, VVarType type, const string& name, VFlagLogicPacked, int wantwidth) + : ASTGEN_SUPER_Var(fl) + , m_name{name} + , m_origName{name} { + init(); + combineType(type); + dtypeSetLogicSized(wantwidth, VSigning::UNSIGNED); + m_declKwd = VBasicDTypeKwd::LOGIC; + } + AstVar(FileLine* fl, VVarType type, const string& name, VFlagBitPacked, int wantwidth) + : ASTGEN_SUPER_Var(fl) + , m_name{name} + , m_origName{name} { + init(); + combineType(type); + dtypeSetBitSized(wantwidth, VSigning::UNSIGNED); + m_declKwd = VBasicDTypeKwd::BIT; + } + AstVar(FileLine* fl, VVarType type, const string& name, AstVar* examplep) + : ASTGEN_SUPER_Var(fl) + , m_name{name} + , m_origName{name} { + init(); + combineType(type); + if (examplep->childDTypep()) childDTypep(examplep->childDTypep()->cloneTree(true)); + dtypeFrom(examplep); + m_declKwd = examplep->declKwd(); + } + ASTNODE_NODE_FUNCS(Var) + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual string origName() const override { return m_origName; } // * = Original name + void origName(const string& name) { m_origName = name; } + VVarType varType() const { return m_varType; } // * = Type of variable + void direction(const VDirection& flag) { + m_direction = flag; + if (m_direction == VDirection::INOUT) m_tristate = true; + } + VDirection direction() const { return m_direction; } + bool isIO() const { return m_direction != VDirection::NONE; } + void declDirection(const VDirection& flag) { m_declDirection = flag; } + VDirection declDirection() const { return m_declDirection; } + void varType(VVarType type) { m_varType = type; } + void varType2Out() { + m_tristate = false; + m_direction = VDirection::OUTPUT; + } + void varType2In() { + m_tristate = false; + m_direction = VDirection::INPUT; + } + VBasicDTypeKwd declKwd() const { return m_declKwd; } + string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv + // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. + string cPubArgType(bool named, bool forReturn) const; + string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument + string dpiTmpVarType(const string& varName) const; + // Return Verilator internal type for argument: CData, SData, IData, WData + string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "", + bool asRef = false) const; + string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc + string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc + string vlPropDecl(const string& propName) const; // Return VerilatorVarProps declaration + void combineType(VVarType type); + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + // op1 = Range of variable + AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } + // op2 = Net delay + AstNode* delayp() const { return op2p(); } + void delayp(AstNode* const nodep) { setNOp2p(nodep); } + AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } + // (Slow) recurse down to find basic data type (Note don't need virtual - + // AstVar isn't a NodeDType) + AstBasicDType* basicp() const { return subDTypep()->basicp(); } + // op3 = Initial value that never changes (static const), or constructor argument for + // MTASKSTATE variables + AstNode* valuep() const { return op3p(); } + // It's valuep(), not constp(), as may be more complicated than an AstConst + void valuep(AstNode* nodep) { setOp3p(nodep); } + void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } + AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } + void ansi(bool flag) { m_ansi = flag; } + void declTyped(bool flag) { m_declTyped = flag; } + void attrClockEn(bool flag) { m_attrClockEn = flag; } + void attrClocker(VVarAttrClocker flag) { m_attrClocker = flag; } + void attrFileDescr(bool flag) { m_fileDescr = flag; } + void attrScClocked(bool flag) { m_scClocked = flag; } + void attrScBv(bool flag) { m_attrScBv = flag; } + void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } + void attrSFormat(bool flag) { m_attrSFormat = flag; } + void attrSplitVar(bool flag) { m_attrSplitVar = flag; } + void usedClock(bool flag) { m_usedClock = flag; } + void usedParam(bool flag) { m_usedParam = flag; } + void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; } + void sigPublic(bool flag) { m_sigPublic = flag; } + void sigModPublic(bool flag) { m_sigModPublic = flag; } + void sigUserRdPublic(bool flag) { + m_sigUserRdPublic = flag; + if (flag) sigPublic(true); + } + void sigUserRWPublic(bool flag) { + m_sigUserRWPublic = flag; + if (flag) sigUserRdPublic(true); + } + void sc(bool flag) { m_sc = flag; } + void scSensitive(bool flag) { m_scSensitive = flag; } + void primaryIO(bool flag) { m_primaryIO = flag; } + void isRand(bool flag) { m_isRand = flag; } + void isConst(bool flag) { m_isConst = flag; } + void isContinuously(bool flag) { m_isContinuously = flag; } + void isStatic(bool flag) { m_isStatic = flag; } + void isIfaceParent(bool flag) { m_isIfaceParent = flag; } + void funcLocal(bool flag) { m_funcLocal = flag; } + void funcReturn(bool flag) { m_funcReturn = flag; } + void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; } + bool hasStrengthAssignment() { return m_hasStrengthAssignment; } + void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; } + bool isDpiOpenArray() const { return m_isDpiOpenArray; } + bool isHideLocal() const { return m_isHideLocal; } + void isHideLocal(bool flag) { m_isHideLocal = flag; } + bool isHideProtected() const { return m_isHideProtected; } + void isHideProtected(bool flag) { m_isHideProtected = flag; } + void noReset(bool flag) { m_noReset = flag; } + bool noReset() const { return m_noReset; } + void noSubst(bool flag) { m_noSubst = flag; } + bool noSubst() const { return m_noSubst; } + void overriddenParam(bool flag) { m_overridenParam = flag; } + bool overriddenParam() const { return m_overridenParam; } + void trace(bool flag) { m_trace = flag; } + void isLatched(bool flag) { m_isLatched = flag; } + bool isForceable() const { return m_isForceable; } + void setForceable() { m_isForceable = true; } + // METHODS + virtual void name(const string& name) override { m_name = name; } + virtual void tag(const string& text) override { m_tag = text; } + virtual string tag() const override { return m_tag; } + bool isAnsi() const { return m_ansi; } + bool isContinuously() const { return m_isContinuously; } + bool isDeclTyped() const { return m_declTyped; } + bool isInoutish() const { return m_direction.isInoutish(); } + bool isNonOutput() const { return m_direction.isNonOutput(); } + bool isReadOnly() const { return m_direction.isReadOnly(); } + bool isWritable() const { return m_direction.isWritable(); } + bool isTristate() const { return m_tristate; } + bool isPrimaryIO() const { return m_primaryIO; } + bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); } + bool isIfaceRef() const { return (varType() == VVarType::IFACEREF); } + bool isIfaceParent() const { return m_isIfaceParent; } + bool isSignal() const { return varType().isSignal(); } + bool isNet() const { return varType().isNet(); } + bool isTemp() const { return varType().isTemp(); } + bool isToggleCoverable() const { + return ((isIO() || isSignal()) + && (isIO() || isBitLogic()) + // Wrapper would otherwise duplicate wrapped module's coverage + && !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString()); + } + bool isClassMember() const { return varType() == VVarType::MEMBER; } + bool isStatementTemp() const { return (varType() == VVarType::STMTTEMP); } + bool isXTemp() const { return (varType() == VVarType::XTEMP); } + bool isParam() const { + return (varType() == VVarType::LPARAM || varType() == VVarType::GPARAM); + } + bool isGParam() const { return (varType() == VVarType::GPARAM); } + bool isGenVar() const { return (varType() == VVarType::GENVAR); } + bool isBitLogic() const { + AstBasicDType* bdtypep = basicp(); + return bdtypep && bdtypep->isBitLogic(); + } + bool isUsedClock() const { return m_usedClock; } + bool isUsedParam() const { return m_usedParam; } + bool isUsedLoopIdx() const { return m_usedLoopIdx; } + bool isSc() const { return m_sc; } + bool isScQuad() const; + bool isScBv() const; + bool isScUint() const; + bool isScBigUint() const; + bool isScSensitive() const { return m_scSensitive; } + bool isSigPublic() const; + bool isSigModPublic() const { return m_sigModPublic; } + bool isSigUserRdPublic() const { return m_sigUserRdPublic; } + bool isSigUserRWPublic() const { return m_sigUserRWPublic; } + bool isTrace() const { return m_trace; } + bool isRand() const { return m_isRand; } + bool isConst() const { return m_isConst; } + bool isStatic() const { return m_isStatic; } + bool isLatched() const { return m_isLatched; } + bool isFuncLocal() const { return m_funcLocal; } + bool isFuncReturn() const { return m_funcReturn; } + bool isPullup() const { return m_isPullup; } + bool isPulldown() const { return m_isPulldown; } + bool attrClockEn() const { return m_attrClockEn; } + bool attrScBv() const { return m_attrScBv; } + bool attrFileDescr() const { return m_fileDescr; } + bool attrScClocked() const { return m_scClocked; } + bool attrSFormat() const { return m_attrSFormat; } + bool attrSplitVar() const { return m_attrSplitVar; } + bool attrIsolateAssign() const { return m_attrIsolateAssign; } + VVarAttrClocker attrClocker() const { return m_attrClocker; } + virtual string verilogKwd() const override; + void lifetime(const VLifetime& flag) { m_lifetime = flag; } + VLifetime lifetime() const { return m_lifetime; } + void propagateAttrFrom(AstVar* fromp) { + // This is getting connected to fromp; keep attributes + // Note the method below too + if (fromp->attrClockEn()) attrClockEn(true); + if (fromp->attrFileDescr()) attrFileDescr(true); + if (fromp->attrIsolateAssign()) attrIsolateAssign(true); + if (fromp->isContinuously()) isContinuously(true); + } + bool gateMultiInputOptimizable() const { + // Ok to gate optimize; must return false if propagateAttrFrom would do anything + return (!attrClockEn() && !isUsedClock()); + } + void combineType(AstVar* typevarp) { + // This is same as typevarp (for combining input & reg decls) + // "this" is the input var. typevarp is the reg var. + propagateAttrFrom(typevarp); + combineType(typevarp->varType()); + if (typevarp->isSigPublic()) sigPublic(true); + if (typevarp->isSigModPublic()) sigModPublic(true); + if (typevarp->isSigUserRdPublic()) sigUserRdPublic(true); + if (typevarp->isSigUserRWPublic()) sigUserRWPublic(true); + if (typevarp->attrScClocked()) attrScClocked(true); + } + void inlineAttrReset(const string& name) { + if (direction() == VDirection::INOUT && varType() == VVarType::WIRE) { + m_varType = VVarType::TRIWIRE; + } + m_direction = VDirection::NONE; + m_name = name; + } + static AstVar* scVarRecurse(AstNode* nodep); + void addProducingMTaskId(int id) { m_mtaskIds.insert(id); } + void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); } + const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } + void pinNum(int id) { m_pinNum = id; } + int pinNum() const { return m_pinNum; } +}; +class AstVarScope final : public AstNode { + // A particular scoped usage of a variable + // That is, as a module is used under multiple cells, we get a different + // varscope for each var in the module + // Parents: MODULE + // Children: none +private: + AstScope* m_scopep; // Scope variable is underneath + AstVar* m_varp; // [AfterLink] Pointer to variable itself + bool m_circular : 1; // Used in circular ordering dependency, need change detect + bool m_trace : 1; // Tracing is turned on for this scope +public: + AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp) + : ASTGEN_SUPER_VarScope(fl) + , m_scopep{scopep} + , m_varp{varp} { + UASSERT_OBJ(scopep, fl, "Scope must be non-null"); + UASSERT_OBJ(varp, fl, "Var must be non-null"); + m_circular = false; + m_trace = true; + dtypeFrom(varp); + } + ASTNODE_NODE_FUNCS(VarScope) + virtual void cloneRelink() override { + if (m_varp && m_varp->clonep()) { + m_varp = m_varp->clonep(); + UASSERT(m_scopep->clonep(), "No clone cross link: " << this); + m_scopep = m_scopep->clonep(); + } + } + virtual const char* broken() const override { + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); + return nullptr; + } + virtual bool maybePointedTo() const override { return true; } + virtual string name() const override { return scopep()->name() + "->" + varp()->name(); } + virtual void dump(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable + AstScope* scopep() const { return m_scopep; } // Pointer to scope it's under + void scopep(AstScope* nodep) { m_scopep = nodep; } + bool isCircular() const { return m_circular; } + void circular(bool flag) { m_circular = flag; } + bool isTrace() const { return m_trace; } + void trace(bool flag) { m_trace = flag; } +}; + +// === AstNodeBlock === +class AstBegin final : public AstNodeBlock { + // A Begin/end named block, only exists shortly after parsing until linking + // Parents: statement + // Children: statements +private: + bool m_generate; // Underneath a generate + const bool m_implied; // Not inserted by user +public: + // Node that puts name into the output stream + AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false, + bool implied = false) + : ASTGEN_SUPER_Begin(fl, name, stmtsp) + , m_generate{generate} + , m_implied{implied} {} + ASTNODE_NODE_FUNCS(Begin) + virtual void dump(std::ostream& str) const override; + // op1p is statements in NodeBlock + AstNode* genforp() const { return op2p(); } // op2 = GENFOR, if applicable, + // might NOT be a GenFor, as loop unrolling replaces with Begin + void addGenforp(AstGenFor* nodep) { addOp2p((AstNode*)nodep); } + void generate(bool flag) { m_generate = flag; } + bool generate() const { return m_generate; } + bool implied() const { return m_implied; } +}; +class AstFork final : public AstNodeBlock { + // A fork named block + // Parents: statement + // Children: statements +private: + VJoinType m_joinType; // Join keyword type +public: + // Node that puts name into the output stream + AstFork(FileLine* fl, const string& name, AstNode* stmtsp) + : ASTGEN_SUPER_Fork(fl, name, stmtsp) {} + ASTNODE_NODE_FUNCS(Fork) + virtual void dump(std::ostream& str) const override; + VJoinType joinType() const { return m_joinType; } + void joinType(const VJoinType& flag) { m_joinType = flag; } +}; + +// === AstNodeFTask === +class AstFunc final : public AstNodeFTask { + // A function inside a module +public: + AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp) + : ASTGEN_SUPER_Func(fl, name, stmtp) { + addNOp1p(fvarsp); + } + ASTNODE_NODE_FUNCS(Func) + virtual bool hasDType() const override { return true; } +}; +class AstTask final : public AstNodeFTask { + // A task inside a module +public: + AstTask(FileLine* fl, const string& name, AstNode* stmtp) + : ASTGEN_SUPER_Task(fl, name, stmtp) {} + ASTNODE_NODE_FUNCS(Task) +}; + +// === AstNodeFile === +class AstCFile final : public AstNodeFile { + // C++ output file + // Parents: NETLIST +private: + bool m_slow : 1; ///< Compile w/o optimization + bool m_source : 1; ///< Source file (vs header file) + bool m_support : 1; ///< Support file (non systemc) +public: + AstCFile(FileLine* fl, const string& name) + : ASTGEN_SUPER_CFile(fl, name) + , m_slow{false} + , m_source{false} + , m_support{false} {} + ASTNODE_NODE_FUNCS(CFile) + virtual void dump(std::ostream& str = std::cout) const override; + bool slow() const { return m_slow; } + void slow(bool flag) { m_slow = flag; } + bool source() const { return m_source; } + void source(bool flag) { m_source = flag; } + bool support() const { return m_support; } + void support(bool flag) { m_support = flag; } +}; +class AstVFile final : public AstNodeFile { + // Verilog output file + // Parents: NETLIST +public: + AstVFile(FileLine* fl, const string& name) + : ASTGEN_SUPER_VFile(fl, name) {} + ASTNODE_NODE_FUNCS(VFile) + virtual void dump(std::ostream& str = std::cout) const override; +}; + +// === AstNodeModule === +class AstClass final : public AstNodeModule { + // TYPES + using MemberNameMap = std::map; + // MEMBERS + MemberNameMap m_members; // Members or method children + AstClassPackage* m_classOrPackagep = nullptr; // Class package this is under + bool m_virtual = false; // Virtual class + bool m_extended = false; // Is extension or extended by other classes + void insertCache(AstNode* nodep); + +public: + AstClass(FileLine* fl, const string& name) + : ASTGEN_SUPER_Class(fl, name) {} + ASTNODE_NODE_FUNCS(Class) + virtual string verilogKwd() const override { return "class"; } + virtual bool maybePointedTo() const override { return true; } + virtual void dump(std::ostream& str) const override; + const char* broken() const override; + void cloneRelink() override; + virtual bool timescaleMatters() const override { return false; } + // op1/op2/op3 in AstNodeModule + AstClassPackage* classOrPackagep() const { return m_classOrPackagep; } + void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; } + AstNode* membersp() const { return stmtsp(); } // op2 = List of statements + void addMembersp(AstNode* nodep) { + insertCache(nodep); + addStmtp(nodep); + } + AstClassExtends* extendsp() const { return VN_AS(op4p(), ClassExtends); } + void extendsp(AstNode* nodep) { addNOp4p(nodep); } + void clearCache() { m_members.clear(); } + void repairCache(); + AstNode* findMember(const string& name) const { + const auto it = m_members.find(name); + return (it == m_members.end()) ? nullptr : it->second; + } + bool isExtended() const { return m_extended; } + void isExtended(bool flag) { m_extended = flag; } + bool isVirtual() const { return m_virtual; } + void isVirtual(bool flag) { m_virtual = flag; } + // Return true if this class is an extension of base class (SLOW) + // Accepts nullptrs + static bool isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp); +}; +class AstClassPackage final : public AstNodeModule { + // The static information portion of a class (treated similarly to a package) + AstClass* m_classp + = nullptr; // Class package this is under (weak pointer, hard link is other way) +public: + AstClassPackage(FileLine* fl, const string& name) + : ASTGEN_SUPER_ClassPackage(fl, name) {} + ASTNODE_NODE_FUNCS(ClassPackage) + virtual string verilogKwd() const override { return "classpackage"; } + virtual const char* broken() const override; + virtual void cloneRelink() override; + virtual bool timescaleMatters() const override { return false; } + AstClass* classp() const { return m_classp; } + void classp(AstClass* classp) { m_classp = classp; } +}; +class AstIface final : public AstNodeModule { + // A module declaration +public: + AstIface(FileLine* fl, const string& name) + : ASTGEN_SUPER_Iface(fl, name) {} + ASTNODE_NODE_FUNCS(Iface) + // Interfaces have `timescale applicability but lots of code seems to + // get false warnings if we enable this + virtual string verilogKwd() const override { return "interface"; } + virtual bool timescaleMatters() const override { return false; } +}; +class AstModule final : public AstNodeModule { + // A module declaration +private: + const bool m_isProgram; // Module represents a program +public: + AstModule(FileLine* fl, const string& name, bool program = false) + : ASTGEN_SUPER_Module(fl, name) + , m_isProgram{program} {} + ASTNODE_NODE_FUNCS(Module) + virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; } + virtual bool timescaleMatters() const override { return true; } +}; +class AstNotFoundModule final : public AstNodeModule { + // A missing module declaration +public: + AstNotFoundModule(FileLine* fl, const string& name) + : ASTGEN_SUPER_NotFoundModule(fl, name) {} + ASTNODE_NODE_FUNCS(NotFoundModule) + virtual string verilogKwd() const override { return "/*not-found-*/ module"; } + virtual bool timescaleMatters() const override { return false; } +}; +class AstPackage final : public AstNodeModule { + // A package declaration +public: + AstPackage(FileLine* fl, const string& name) + : ASTGEN_SUPER_Package(fl, name) {} + ASTNODE_NODE_FUNCS(Package) + virtual string verilogKwd() const override { return "package"; } + virtual bool timescaleMatters() const override { return !isDollarUnit(); } + static string dollarUnitName() { return AstNode::encodeName("$unit"); } + bool isDollarUnit() const { return name() == dollarUnitName(); } +}; +class AstPrimitive final : public AstNodeModule { + // A primitive declaration +public: + AstPrimitive(FileLine* fl, const string& name) + : ASTGEN_SUPER_Primitive(fl, name) {} + ASTNODE_NODE_FUNCS(Primitive) + virtual string verilogKwd() const override { return "primitive"; } + virtual bool timescaleMatters() const override { return false; } +}; + +// === AstNodePreSel === +class AstSelBit final : public AstNodePreSel { + // Single bit range extraction, perhaps with non-constant selection or array selection + // Gets replaced during link with AstArraySel or AstSel +public: + AstSelBit(FileLine* fl, AstNode* fromp, AstNode* bitp) + : ASTGEN_SUPER_SelBit(fl, fromp, bitp, nullptr) { + UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, + "not coded to create after dtypes resolved"); + } + ASTNODE_NODE_FUNCS(SelBit) + AstNode* bitp() const { return rhsp(); } +}; +class AstSelExtract final : public AstNodePreSel { + // Range extraction, gets replaced with AstSel +public: + AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp) + : ASTGEN_SUPER_SelExtract(fl, fromp, msbp, lsbp) {} + ASTNODE_NODE_FUNCS(SelExtract) + AstNode* leftp() const { return rhsp(); } + AstNode* rightp() const { return thsp(); } +}; +class AstSelMinus final : public AstNodePreSel { + // -: range extraction, perhaps with non-constant selection + // Gets replaced during link with AstSel +public: + AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) + : ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {} + ASTNODE_NODE_FUNCS(SelMinus) + AstNode* bitp() const { return rhsp(); } + AstNode* widthp() const { return thsp(); } +}; +class AstSelPlus final : public AstNodePreSel { + // +: range extraction, perhaps with non-constant selection + // Gets replaced during link with AstSel +public: + AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) + : ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {} + ASTNODE_NODE_FUNCS(SelPlus) + AstNode* bitp() const { return rhsp(); } + AstNode* widthp() const { return thsp(); } +}; + +// === AstNodeProcedure === +class AstAlways final : public AstNodeProcedure { + const VAlwaysKwd m_keyword; + +public: + AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp) + : ASTGEN_SUPER_Always(fl, bodysp) + , m_keyword{keyword} { + addNOp1p(sensesp); + } + ASTNODE_NODE_FUNCS(Always) + // + virtual void dump(std::ostream& str) const override; + AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list + void sensesp(AstSenTree* nodep) { setOp1p(nodep); } + VAlwaysKwd keyword() const { return m_keyword; } +}; +class AstAlwaysPost final : public AstNodeProcedure { + // Like always but post assignments for memory assignment IFs +public: + AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) + : ASTGEN_SUPER_AlwaysPost(fl, bodysp) { + addNOp1p(sensesp); + } + ASTNODE_NODE_FUNCS(AlwaysPost) +}; +class AstAlwaysPostponed final : public AstNodeProcedure { + // Like always but postponement scheduling region + +public: + AstAlwaysPostponed(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER_AlwaysPostponed(fl, bodysp) {} + ASTNODE_NODE_FUNCS(AlwaysPostponed) +}; +class AstFinal final : public AstNodeProcedure { +public: + AstFinal(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER_Final(fl, bodysp) {} + ASTNODE_NODE_FUNCS(Final) +}; +class AstInitial final : public AstNodeProcedure { +public: + AstInitial(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER_Initial(fl, bodysp) {} + ASTNODE_NODE_FUNCS(Initial) +}; +class AstInitialAutomatic final : public AstNodeProcedure { + // Automatic variable initialization + // That is, it runs every function start, or class construction +public: + AstInitialAutomatic(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER_InitialAutomatic(fl, bodysp) {} + ASTNODE_NODE_FUNCS(InitialAutomatic) +}; +class AstInitialStatic final : public AstNodeProcedure { + // Static variable initialization + // That is, it runs at the beginning of simulation, before 'initial' blocks +public: + AstInitialStatic(FileLine* fl, AstNode* bodysp) + : ASTGEN_SUPER_InitialStatic(fl, bodysp) {} + ASTNODE_NODE_FUNCS(InitialStatic) +}; + +// === AstNodeRange === +class AstBracketRange final : public AstNodeRange { + // Parser only concept "[lhsp]", a AstUnknownRange, QueueRange or Range, + // unknown until lhsp type is determined +public: + AstBracketRange(FileLine* fl, AstNode* elementsp) + : ASTGEN_SUPER_BracketRange(fl) { + setOp1p(elementsp); + } + ASTNODE_NODE_FUNCS(BracketRange) + virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // Will be removed in V3Width, which relies on this + // being a child not a dtype pointed node + virtual bool maybePointedTo() const override { return false; } + AstNode* elementsp() const { return op1p(); } +}; +class AstRange final : public AstNodeRange { + // Range specification, for use under variables and cells +public: + AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp) + : ASTGEN_SUPER_Range(fl) { + setOp2p(leftp); + setOp3p(rightp); + } + inline AstRange(FileLine* fl, int left, int right); + inline AstRange(FileLine* fl, const VNumRange& range); + ASTNODE_NODE_FUNCS(Range) + AstNode* leftp() const { return op2p(); } + AstNode* rightp() const { return op3p(); } + inline int leftConst() const; + inline int rightConst() const; + int hiConst() const { + const int l = leftConst(); + const int r = rightConst(); + return l > r ? l : r; + } + int loConst() const { + const int l = leftConst(); + const int r = rightConst(); + return l > r ? r : l; + } + int elementsConst() const { return hiConst() - loConst() + 1; } + bool littleEndian() const { return leftConst() < rightConst(); } + virtual void dump(std::ostream& str) const override; + virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstUnsizedRange final : public AstNodeRange { + // Unsized range specification, for open arrays +public: + explicit AstUnsizedRange(FileLine* fl) + : ASTGEN_SUPER_UnsizedRange(fl) {} + ASTNODE_NODE_FUNCS(UnsizedRange) + virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual string emitVerilog() { return "[]"; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstWildcardRange final : public AstNodeRange { + // Wildcard range specification, for wildcard index type associative arrays +public: + explicit AstWildcardRange(FileLine* fl) + : ASTGEN_SUPER_WildcardRange(fl) {} + ASTNODE_NODE_FUNCS(WildcardRange) + virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual string emitVerilog() { return "[*]"; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; + +// === AstNodeStmt === +class AstAlwaysPublic final : public AstNodeStmt { + // "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/ + // Body statements are just AstVarRefs to the public signals +public: + AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) + : ASTGEN_SUPER_AlwaysPublic(fl) { + addNOp1p(sensesp); + addNOp2p(bodysp); + } + ASTNODE_NODE_FUNCS(AlwaysPublic) + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // + AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list + AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate + void addStmtp(AstNode* nodep) { addOp2p(nodep); } + // Special accessors + bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } +}; +class AstBreak final : public AstNodeStmt { +public: + explicit AstBreak(FileLine* fl) + : ASTGEN_SUPER_Break(fl) {} + ASTNODE_NODE_FUNCS(Break) + virtual string verilogKwd() const override { return "break"; } + virtual bool isBrancher() const override { + return true; // SPECIAL: We don't process code after breaks + } +}; +class AstCMethodHard final : public AstNodeStmt { + // A reference to a "C" hardcoded member task (or function) + // PARENTS: stmt/math + // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. +private: + string m_name; // Name of method + bool m_pure = false; // Pure optimizable +public: + AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, + AstNode* pinsp = nullptr) + : ASTGEN_SUPER_CMethodHard(fl, false) + , m_name{name} { + setOp1p(fromp); + dtypep(nullptr); // V3Width will resolve + addNOp2p(pinsp); + } + AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp = nullptr) + : ASTGEN_SUPER_CMethodHard(fl, false) + , m_name{name} { + setOp1p(fromp); + addNOp2p(pinsp); + } + ASTNODE_NODE_FUNCS(CMethodHard) + virtual string name() const override { return m_name; } // * = Var name + virtual bool hasDType() const override { return true; } + virtual void name(const string& name) override { m_name = name; } + virtual bool same(const AstNode* samep) const override { + const AstCMethodHard* asamep = static_cast(samep); + return (m_name == asamep->m_name); + } + virtual bool isPure() const override { return m_pure; } + void pure(bool flag) { m_pure = flag; } + void makeStatement() { + statement(true); + dtypeSetVoid(); + } + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) + void fromp(AstNode* nodep) { setOp1p(nodep); } + AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list + void addPinsp(AstNode* nodep) { addOp2p(nodep); } +}; +class AstCReset final : public AstNodeStmt { + // Reset variable at startup +public: + AstCReset(FileLine* fl, AstVarRef* exprsp) + : ASTGEN_SUPER_CReset(fl) { + addNOp1p((AstNode*)exprsp); + } + ASTNODE_NODE_FUNCS(CReset) + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstVarRef* varrefp() const { return VN_AS(op1p(), VarRef); } // op1 = varref to reset +}; +class AstCReturn final : public AstNodeStmt { + // C++ return from a function + // Parents: CFUNC/statement + // Children: Math +public: + AstCReturn(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_CReturn(fl) { + setOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(CReturn) + virtual int instrCount() const override { return widthInstrs(); } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // + AstNode* lhsp() const { return op1p(); } +}; +class AstCStmt final : public AstNodeStmt { + // Emit C statement +public: + AstCStmt(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_CStmt(fl) { + addNOp1p(exprsp); + } + inline AstCStmt(FileLine* fl, const string& textStmt); + ASTNODE_NODE_FUNCS(CStmt) + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + void addBodysp(AstNode* nodep) { addNOp1p(nodep); } + AstNode* bodysp() const { return op1p(); } // op1 = expressions to print +}; +class AstChangeDet final : public AstNodeStmt { + // A comparison to determine change detection, common & must be fast. +public: + // Null lhs+rhs used to indicate change needed with no spec vars + AstChangeDet(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_ChangeDet(fl) { + setNOp1p(lhsp); + setNOp2p(rhsp); + } + ASTNODE_NODE_FUNCS(ChangeDet) + AstNode* lhsp() const { return op1p(); } + AstNode* rhsp() const { return op2p(); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } // xor, or/logor + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstComment final : public AstNodeStmt { + // Some comment to put into the output stream + // Parents: {statement list} + // Children: none +private: + const bool m_showAt; // Show "at " + const string m_name; // Text of comment +public: + AstComment(FileLine* fl, const string& name, bool showAt = false) + : ASTGEN_SUPER_Comment(fl) + , m_showAt{showAt} + , m_name{name} {} + ASTNODE_NODE_FUNCS(Comment) + virtual string name() const override { return m_name; } // * = Text + virtual bool same(const AstNode* samep) const override { + return true; + } // Ignore name in comments + virtual bool showAt() const { return m_showAt; } +}; +class AstContinue final : public AstNodeStmt { +public: + explicit AstContinue(FileLine* fl) + : ASTGEN_SUPER_Continue(fl) {} + ASTNODE_NODE_FUNCS(Continue) + virtual string verilogKwd() const override { return "continue"; } + virtual bool isBrancher() const override { + return true; // SPECIAL: We don't process code after breaks + } +}; +class AstCoverDecl final : public AstNodeStmt { + // Coverage analysis point declaration + // Parents: {statement list} + // Children: none +private: + AstCoverDecl* m_dataDeclp; // [After V3CoverageJoin] Pointer to duplicate declaration to get + // data from instead + string m_page; + string m_text; + string m_hier; + string m_linescov; + int m_offset; // Offset column numbers to uniq-ify IFs + int m_binNum; // Set by V3EmitCSyms to tell final V3Emit what to increment +public: + AstCoverDecl(FileLine* fl, const string& page, const string& comment, const string& linescov, + int offset) + : ASTGEN_SUPER_CoverDecl(fl) { + m_page = page; + m_text = comment; + m_linescov = linescov; + m_offset = offset; + m_binNum = 0; + m_dataDeclp = nullptr; + } + ASTNODE_NODE_FUNCS(CoverDecl) + virtual const char* broken() const override { + BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); + if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing + v3fatalSrc("dataDeclp should point to real data, not be a list"); + } + return nullptr; + } + virtual void cloneRelink() override { + if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); + } + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } + virtual bool maybePointedTo() const override { return true; } + void binNum(int flag) { m_binNum = flag; } + int binNum() const { return m_binNum; } + int offset() const { return m_offset; } + const string& comment() const { return m_text; } // text to insert in code + const string& linescov() const { return m_linescov; } + const string& page() const { return m_page; } + const string& hier() const { return m_hier; } + void hier(const string& flag) { m_hier = flag; } + void comment(const string& flag) { m_text = flag; } + virtual bool same(const AstNode* samep) const override { + const AstCoverDecl* const asamep = static_cast(samep); + return (fileline() == asamep->fileline() && linescov() == asamep->linescov() + && hier() == asamep->hier() && comment() == asamep->comment()); + } + virtual bool isPredictOptimizable() const override { return false; } + void dataDeclp(AstCoverDecl* nodep) { m_dataDeclp = nodep; } + // dataDecl nullptr means "use this one", but often you want "this" to + // indicate to get data from here + AstCoverDecl* dataDeclNullp() const { return m_dataDeclp; } + AstCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } +}; +class AstCoverInc final : public AstNodeStmt { + // Coverage analysis point; increment coverage count + // Parents: {statement list} + // Children: none +private: + AstCoverDecl* m_declp; // [After V3Coverage] Pointer to declaration +public: + AstCoverInc(FileLine* fl, AstCoverDecl* declp) + : ASTGEN_SUPER_CoverInc(fl) + , m_declp{declp} {} + ASTNODE_NODE_FUNCS(CoverInc) + virtual const char* broken() const override { + BROKEN_RTN(!declp()->brokeExists()); + return nullptr; + } + virtual void cloneRelink() override { + if (m_declp->clonep()) m_declp = m_declp->clonep(); + } + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } + virtual bool same(const AstNode* samep) const override { + return declp() == static_cast(samep)->declp(); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isOutputter() const override { return true; } + // but isPure() true + AstCoverDecl* declp() const { return m_declp; } // Where defined +}; +class AstCoverToggle final : public AstNodeStmt { + // Toggle analysis of given signal + // Parents: MODULE + // Children: AstCoverInc, orig var, change det var +public: + AstCoverToggle(FileLine* fl, AstCoverInc* incp, AstNode* origp, AstNode* changep) + : ASTGEN_SUPER_CoverToggle(fl) { + setOp1p(incp); + setOp2p(origp); + setOp3p(changep); + } + ASTNODE_NODE_FUNCS(CoverToggle) + virtual int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return true; } + virtual bool isOutputter() const override { + return false; // Though the AstCoverInc under this is an outputter + } + // but isPure() true + AstCoverInc* incp() const { return VN_AS(op1p(), CoverInc); } + void incp(AstCoverInc* nodep) { setOp1p(nodep); } + AstNode* origp() const { return op2p(); } + AstNode* changep() const { return op3p(); } +}; +class AstDelay final : public AstNodeStmt { + // Delay statement +public: + AstDelay(FileLine* fl, AstNode* lhsp, AstNode* stmtsp) + : ASTGEN_SUPER_Delay(fl) { + setOp1p(lhsp); + setNOp2p(stmtsp); + } + ASTNODE_NODE_FUNCS(Delay) + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // + AstNode* lhsp() const { return op1p(); } // op1 = delay value + void lhsp(AstNode* nodep) { setOp1p(nodep); } + void stmtsp(AstNode* nodep) { setOp2p(nodep); } // op2 = statements under delay + AstNode* stmtsp() const { return op2p(); } +}; +class AstDisable final : public AstNodeStmt { +private: + string m_name; // Name of block +public: + AstDisable(FileLine* fl, const string& name) + : ASTGEN_SUPER_Disable(fl) + , m_name{name} {} + ASTNODE_NODE_FUNCS(Disable) + virtual string name() const override { return m_name; } // * = Block name + virtual void name(const string& flag) override { m_name = flag; } + virtual bool isBrancher() const override { + return true; // SPECIAL: We don't process code after breaks + } +}; +class AstDisableFork final : public AstNodeStmt { + // A "disable fork" statement +public: + explicit AstDisableFork(FileLine* fl) + : ASTGEN_SUPER_DisableFork(fl) {} + ASTNODE_NODE_FUNCS(DisableFork) +}; +class AstDisplay final : public AstNodeStmt { + // Parents: stmtlist + // Children: file which must be a varref + // Children: SFORMATF to generate print string +private: + VDisplayType m_displayType; + +public: + AstDisplay(FileLine* fl, VDisplayType dispType, const string& text, AstNode* filep, + AstNode* exprsp, char missingArgChar = 'd') + : ASTGEN_SUPER_Display(fl) { + setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); + setNOp3p(filep); + m_displayType = dispType; + } + AstDisplay(FileLine* fl, VDisplayType dispType, AstNode* filep, AstNode* exprsp, + char missingArgChar = 'd') + : ASTGEN_SUPER_Display(fl) { + setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); + setNOp3p(filep); + m_displayType = dispType; + } + ASTNODE_NODE_FUNCS(Display) + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { + BROKEN_RTN(!fmtp()); + return nullptr; + } + virtual string verilogKwd() const override { + return (filep() ? string("$f") + string(displayType().ascii()) + : string("$") + string(displayType().ascii())); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* samep) const override { + return displayType() == static_cast(samep)->displayType(); + } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + VDisplayType displayType() const { return m_displayType; } + void displayType(VDisplayType type) { m_displayType = type; } + // * = Add a newline for $display + bool addNewline() const { return displayType().addNewline(); } + void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter + AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } + AstNode* filep() const { return op3p(); } + void filep(AstNodeVarRef* nodep) { setNOp3p((AstNode*)nodep); } +}; +class AstDpiExportUpdated final : public AstNodeStmt { + // Denotes that the referenced variable may have been updated via a DPI Export +public: + inline AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep); + ASTNODE_NODE_FUNCS(DpiExportUpdated) + inline AstVarScope* varScopep() const; +}; +class AstDumpCtl final : public AstNodeStmt { + // $dumpon etc + // Parents: expr + // Child: expr based on type of control statement + const VDumpCtlType m_ctlType; // Type of operation +public: + AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = nullptr) + : ASTGEN_SUPER_DumpCtl(fl) + , m_ctlType{ctlType} { + setNOp1p(exprp); + } + ASTNODE_NODE_FUNCS(DumpCtl) + virtual string verilogKwd() const override { return ctlType().ascii(); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool cleanOut() const { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + VDumpCtlType ctlType() const { return m_ctlType; } + AstNode* exprp() const { return op1p(); } // op2 = Expressions to output + void exprp(AstNode* nodep) { setOp1p(nodep); } +}; +class AstEventControl final : public AstNodeStmt { + // Parents: stmtlist +public: + AstEventControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) + : ASTGEN_SUPER_EventControl(fl) { + setNOp1p(sensesp); + setNOp2p(stmtsp); + } + ASTNODE_NODE_FUNCS(EventControl) + virtual string verilogKwd() const override { return "@(%l) %r"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return false; } + virtual int instrCount() const override { return 0; } + AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } + AstNode* stmtsp() const { return op2p(); } +}; +class AstFClose final : public AstNodeStmt { + // Parents: stmtlist + // Children: file which must be a varref +public: + AstFClose(FileLine* fl, AstNode* filep) + : ASTGEN_SUPER_FClose(fl) { + setNOp2p(filep); + } + ASTNODE_NODE_FUNCS(FClose) + virtual string verilogKwd() const override { return "$fclose"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op2p(); } + void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } +}; +class AstFFlush final : public AstNodeStmt { + // Parents: stmtlist + // Children: file which must be a varref +public: + AstFFlush(FileLine* fl, AstNode* filep) + : ASTGEN_SUPER_FFlush(fl) { + setNOp2p(filep); + } + ASTNODE_NODE_FUNCS(FFlush) + virtual string verilogKwd() const override { return "$fflush"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op2p(); } + void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } +}; +class AstFOpen final : public AstNodeStmt { + // Although a system function in IEEE, here a statement which sets the file pointer (MCD) +public: + AstFOpen(FileLine* fl, AstNode* filep, AstNode* filenamep, AstNode* modep) + : ASTGEN_SUPER_FOpen(fl) { + setOp1p(filep); + setOp2p(filenamep); + setOp3p(modep); + } + ASTNODE_NODE_FUNCS(FOpen) + virtual string verilogKwd() const override { return "$fopen"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op1p(); } + AstNode* filenamep() const { return op2p(); } + AstNode* modep() const { return op3p(); } +}; +class AstFOpenMcd final : public AstNodeStmt { + // Although a system function in IEEE, here a statement which sets the file pointer (MCD) +public: + AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep) + : ASTGEN_SUPER_FOpenMcd(fl) { + setOp1p(filep); + setOp2p(filenamep); + } + ASTNODE_NODE_FUNCS(FOpenMcd) + virtual string verilogKwd() const override { return "$fopen"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* filep() const { return op1p(); } + AstNode* filenamep() const { return op2p(); } +}; +class AstFinish final : public AstNodeStmt { +public: + explicit AstFinish(FileLine* fl) + : ASTGEN_SUPER_Finish(fl) {} + ASTNODE_NODE_FUNCS(Finish) + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual int instrCount() const override { return 0; } // Rarely executes + virtual bool same(const AstNode* samep) const override { + return fileline() == samep->fileline(); + } +}; +class AstForeach final : public AstNodeStmt { +public: + AstForeach(FileLine* fl, AstNode* arrayp, AstNode* bodysp) + : ASTGEN_SUPER_Foreach(fl) { + setOp1p(arrayp); + addNOp4p(bodysp); + } + ASTNODE_NODE_FUNCS(Foreach) + AstNode* arrayp() const { return op1p(); } // op1 = array and index vars + AstNode* bodysp() const { return op4p(); } // op4 = body of loop + virtual bool isGateOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } +}; +class AstJumpBlock final : public AstNodeStmt { + // Block of code including a JumpGo and JumpLabel + // Parents: {statement list} + // Children: {statement list, with JumpGo and JumpLabel below} +private: + AstJumpLabel* m_labelp = nullptr; // [After V3Jump] Pointer to declaration + int m_labelNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment +public: + // After construction must call ->labelp to associate with appropriate label + AstJumpBlock(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_JumpBlock(fl) { + addNOp1p(stmtsp); + } + virtual const char* broken() const override; + virtual void cloneRelink() override; + ASTNODE_NODE_FUNCS(JumpBlock) + virtual int instrCount() const override { return 0; } + virtual bool maybePointedTo() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // op1 = Statements + AstNode* stmtsp() const { return op1p(); } // op1 = List of statements + void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } + AstNode* endStmtsp() const { return op2p(); } // op1 = List of end-of-block + void addEndStmtsp(AstNode* nodep) { addNOp2p(nodep); } + int labelNum() const { return m_labelNum; } + void labelNum(int flag) { m_labelNum = flag; } + AstJumpLabel* labelp() const { return m_labelp; } + void labelp(AstJumpLabel* labelp) { m_labelp = labelp; } +}; +class AstJumpGo final : public AstNodeStmt { + // Jump point; branch down to a JumpLabel + // No support for backward jumps at present + // Parents: {statement list with JumpBlock above} + // Children: none +private: + AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration +public: + AstJumpGo(FileLine* fl, AstJumpLabel* labelp) + : ASTGEN_SUPER_JumpGo(fl) + , m_labelp{labelp} {} + ASTNODE_NODE_FUNCS(JumpGo); + const char* broken() const override; + void cloneRelink() override; + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual bool same(const AstNode* samep) const override { + return labelp() == static_cast(samep)->labelp(); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isBrancher() const override { + return true; // SPECIAL: We don't process code after breaks + } + AstJumpLabel* labelp() const { return m_labelp; } +}; +class AstJumpLabel final : public AstNodeStmt { + // Jump point declaration + // Parents: {statement list with JumpBlock above} + // Children: none +private: + AstJumpBlock* m_blockp; // [After V3Jump] Pointer to declaration +public: + AstJumpLabel(FileLine* fl, AstJumpBlock* blockp) + : ASTGEN_SUPER_JumpLabel(fl) + , m_blockp{blockp} {} + ASTNODE_NODE_FUNCS(JumpLabel) + virtual bool maybePointedTo() const override { return true; } + virtual const char* broken() const override { + BROKEN_RTN(!blockp()->brokeExistsAbove()); + BROKEN_RTN(blockp()->labelp() != this); + return nullptr; + } + virtual void cloneRelink() override { + if (m_blockp->clonep()) m_blockp = m_blockp->clonep(); + } + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 0; } + virtual bool same(const AstNode* samep) const override { + return blockp() == static_cast(samep)->blockp(); + } + AstJumpBlock* blockp() const { return m_blockp; } +}; +class AstMonitorOff final : public AstNodeStmt { + const bool m_off; // Monitor off. Using 0=on allows faster init and comparison + +public: + AstMonitorOff(FileLine* fl, bool off) + : ASTGEN_SUPER_MonitorOff(fl) + , m_off{off} {} + ASTNODE_NODE_FUNCS(MonitorOff) + virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; } + virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt + virtual bool isPredictOptimizable() const override { + return false; + } // Though deleted before opt + virtual bool isPure() const override { return false; } // Though deleted before opt + virtual bool isOutputter() const override { return true; } // Though deleted before opt + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + virtual bool same(const AstNode* samep) const override { + return m_off == static_cast(samep)->m_off; + } + bool off() const { return m_off; } +}; +class AstPrintTimeScale final : public AstNodeStmt { + // Parents: stmtlist + string m_name; // Parent module name + VTimescale m_timeunit; // Parent module time unit +public: + explicit AstPrintTimeScale(FileLine* fl) + : ASTGEN_SUPER_PrintTimeScale(fl) {} + ASTNODE_NODE_FUNCS(PrintTimeScale) + virtual void name(const string& name) override { m_name = name; } + virtual string name() const override { return m_name; } // * = Var name + virtual void dump(std::ostream& str) const override; + virtual string verilogKwd() const override { return "$printtimescale"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + void timeunit(const VTimescale& flag) { m_timeunit = flag; } + VTimescale timeunit() const { return m_timeunit; } +}; +class AstRelease final : public AstNodeStmt { + // Procedural 'release' statement +public: + AstRelease(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_Release(fl) { + setOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(Release); + AstNode* lhsp() const { return op1p(); } +}; +class AstRepeat final : public AstNodeStmt { +public: + AstRepeat(FileLine* fl, AstNode* countp, AstNode* bodysp) + : ASTGEN_SUPER_Repeat(fl) { + setOp2p(countp); + addNOp3p(bodysp); + } + ASTNODE_NODE_FUNCS(Repeat) + AstNode* countp() const { return op2p(); } // op2 = condition to continue + AstNode* bodysp() const { return op3p(); } // op3 = body of loop + virtual bool isGateOptimizable() const override { + return false; + } // Not relevant - converted to FOR + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } +}; +class AstReturn final : public AstNodeStmt { +public: + explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr) + : ASTGEN_SUPER_Return(fl) { + setNOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(Return) + virtual string verilogKwd() const override { return "return"; } + AstNode* lhsp() const { return op1p(); } + virtual bool isBrancher() const override { + return true; // SPECIAL: We don't process code after breaks + } +}; +class AstSFormat final : public AstNodeStmt { + // Parents: statement container + // Children: string to load + // Children: SFORMATF to generate print string +public: + AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp, + char missingArgChar = 'd') + : ASTGEN_SUPER_SFormat(fl) { + setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); + setOp3p(lhsp); + } + AstSFormat(FileLine* fl, AstNode* lhsp, AstNode* exprsp, char missingArgChar = 'd') + : ASTGEN_SUPER_SFormat(fl) { + setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); + setOp3p(lhsp); + } + ASTNODE_NODE_FUNCS(SFormat) + virtual const char* broken() const override { + BROKEN_RTN(!fmtp()); + return nullptr; + } + virtual string verilogKwd() const override { return "$sformat"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return true; } + virtual bool isPure() const override { return true; } + virtual bool isOutputter() const override { return false; } + virtual bool cleanOut() const { return false; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter + AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } + AstNode* lhsp() const { return op3p(); } + void lhsp(AstNode* nodep) { setOp3p(nodep); } +}; +class AstStop final : public AstNodeStmt { +public: + AstStop(FileLine* fl, bool maybe) + : ASTGEN_SUPER_Stop(fl) {} + ASTNODE_NODE_FUNCS(Stop) + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual int instrCount() const override { return 0; } // Rarely executes + virtual bool same(const AstNode* samep) const override { + return fileline() == samep->fileline(); + } +}; +class AstSysFuncAsTask final : public AstNodeStmt { + // Call what is normally a system function (with a return) in a non-return context + // Parents: stmtlist + // Children: a system function +public: + AstSysFuncAsTask(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_SysFuncAsTask(fl) { + addNOp1p(exprsp); + } + ASTNODE_NODE_FUNCS(SysFuncAsTask) + virtual string verilogKwd() const override { return ""; } + virtual bool isGateOptimizable() const override { return true; } + virtual bool isPredictOptimizable() const override { return true; } + virtual bool isPure() const override { return true; } + virtual bool isOutputter() const override { return false; } + virtual int instrCount() const override { return 0; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval + void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval +}; +class AstSysIgnore final : public AstNodeStmt { + // Parents: stmtlist + // Children: varrefs or exprs +public: + AstSysIgnore(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_SysIgnore(fl) { + addNOp1p(exprsp); + } + ASTNODE_NODE_FUNCS(SysIgnore) + virtual string verilogKwd() const override { return "$ignored"; } + virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt + virtual bool isPredictOptimizable() const override { + return false; + } // Though deleted before opt + virtual bool isPure() const override { return false; } // Though deleted before opt + virtual bool isOutputter() const override { return true; } // Though deleted before opt + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output + void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output +}; +class AstSystemT final : public AstNodeStmt { + // $system used as task +public: + AstSystemT(FileLine* fl, AstNode* lhsp) + : ASTGEN_SUPER_SystemT(fl) { + setOp1p(lhsp); + } + ASTNODE_NODE_FUNCS(SystemT) + virtual string verilogKwd() const override { return "$system"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + AstNode* lhsp() const { return op1p(); } +}; +class AstTimeFormat final : public AstNodeStmt { + // Parents: stmtlist +public: + AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp, + AstNode* widthp) + : ASTGEN_SUPER_TimeFormat(fl) { + setOp1p(unitsp); + setOp2p(precisionp); + setOp3p(suffixp); + setOp4p(widthp); + } + ASTNODE_NODE_FUNCS(TimeFormat) + virtual string verilogKwd() const override { return "$timeformat"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual int instrCount() const override { return INSTR_COUNT_PLI; } + AstNode* unitsp() const { return op1p(); } + AstNode* precisionp() const { return op2p(); } + AstNode* suffixp() const { return op3p(); } + AstNode* widthp() const { return op4p(); } +}; +class AstTraceDecl final : public AstNodeStmt { + // Trace point declaration + // Separate from AstTraceInc; as a declaration can't be deleted + // Parents: {statement list} + // Children: expression being traced +private: + uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines + const string m_showname; // Name of variable + const VNumRange m_bitRange; // Property of var the trace details + const VNumRange m_arrayRange; // Property of var the trace details + const uint32_t m_codeInc; // Code increment + const VVarType m_varType; // Type of variable (for localparam vs. param) + const VBasicDTypeKwd m_declKwd; // Keyword at declaration time + const VDirection m_declDirection; // Declared direction input/output etc +public: + AstTraceDecl(FileLine* fl, const string& showname, + AstVar* varp, // For input/output state etc + AstNode* valuep, const VNumRange& bitRange, const VNumRange& arrayRange) + : ASTGEN_SUPER_TraceDecl(fl) + , m_showname{showname} + , m_bitRange{bitRange} + , m_arrayRange{arrayRange} + , m_codeInc( + ((arrayRange.ranged() ? arrayRange.elements() : 1) * valuep->dtypep()->widthWords() + * (VL_EDATASIZE / 32))) // A code is always 32-bits + , m_varType{varp->varType()} + , m_declKwd{varp->declKwd()} + , m_declDirection{varp->declDirection()} { + dtypeFrom(valuep); + addNOp1p(valuep); + } + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 100; } // Large... + ASTNODE_NODE_FUNCS(TraceDecl) + virtual string name() const override { return m_showname; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual bool same(const AstNode* samep) const override { return false; } + string showname() const { return m_showname; } // * = Var name + // Details on what we're tracing + uint32_t code() const { return m_code; } + void code(uint32_t code) { m_code = code; } + uint32_t codeInc() const { return m_codeInc; } + const VNumRange& bitRange() const { return m_bitRange; } + const VNumRange& arrayRange() const { return m_arrayRange; } + VVarType varType() const { return m_varType; } + VBasicDTypeKwd declKwd() const { return m_declKwd; } + VDirection declDirection() const { return m_declDirection; } + AstNode* valuep() const { return op1p(); } +}; +class AstTraceInc final : public AstNodeStmt { + // Trace point dump + // Parents: {statement list} + // Children: op1: things to emit before this node, + // op2: expression being traced (from decl) + +private: + AstTraceDecl* m_declp; // Pointer to declaration + const bool m_full; // Is this a full vs incremental dump + const uint32_t m_baseCode; // Trace code base value in function containing this AstTraceInc + +public: + AstTraceInc(FileLine* fl, AstTraceDecl* declp, bool full, uint32_t baseCode = 0) + : ASTGEN_SUPER_TraceInc(fl) + , m_declp{declp} + , m_full{full} + , m_baseCode{baseCode} { + dtypeFrom(declp); + addOp2p(declp->valuep()->cloneTree(true)); + } + ASTNODE_NODE_FUNCS(TraceInc) + virtual const char* broken() const override { + BROKEN_RTN(!declp()->brokeExists()); + return nullptr; + } + virtual void cloneRelink() override { + if (m_declp->clonep()) m_declp = m_declp->clonep(); + } + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 10 + 2 * INSTR_COUNT_LD; } + virtual bool hasDType() const override { return true; } + virtual bool same(const AstNode* samep) const override { + return declp() == static_cast(samep)->declp(); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isOutputter() const override { return true; } + // but isPure() true + // op1 = Statements before the value + AstNode* precondsp() const { return op1p(); } + void addPrecondsp(AstNode* newp) { addOp1p(newp); } + AstNode* valuep() const { return op2p(); } + AstTraceDecl* declp() const { return m_declp; } + bool full() const { return m_full; } + uint32_t baseCode() const { return m_baseCode; } +}; +class AstTracePopNamePrefix final : public AstNodeStmt { + const unsigned m_count; // How many levels to pop +public: + AstTracePopNamePrefix(FileLine* fl, unsigned count) + : ASTGEN_SUPER_TracePopNamePrefix(fl) + , m_count{count} {} + ASTNODE_NODE_FUNCS(TracePopNamePrefix) + virtual bool same(const AstNode* samep) const override { return false; } + unsigned count() const { return m_count; } +}; +class AstTracePushNamePrefix final : public AstNodeStmt { + const string m_prefix; // Prefix to add to signal names +public: + AstTracePushNamePrefix(FileLine* fl, const string& prefix) + : ASTGEN_SUPER_TracePushNamePrefix(fl) + , m_prefix{prefix} {} + ASTNODE_NODE_FUNCS(TracePushNamePrefix) + virtual bool same(const AstNode* samep) const override { return false; } + string prefix() const { return m_prefix; } +}; +class AstUCStmt final : public AstNodeStmt { + // User $c statement +public: + AstUCStmt(FileLine* fl, AstNode* exprsp) + : ASTGEN_SUPER_UCStmt(fl) { + addNOp1p(exprsp); + } + ASTNODE_NODE_FUNCS(UCStmt) + AstNode* bodysp() const { return op1p(); } // op1 = expressions to print + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } +}; +class AstWait final : public AstNodeStmt { +public: + AstWait(FileLine* fl, AstNode* condp, AstNode* bodysp) + : ASTGEN_SUPER_Wait(fl) { + setOp2p(condp); + addNOp3p(bodysp); + } + ASTNODE_NODE_FUNCS(Wait) + AstNode* bodysp() const { return op3p(); } // op3 = body of loop + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } +}; +class AstWaitFork final : public AstNodeStmt { + // A "wait fork" statement +public: + explicit AstWaitFork(FileLine* fl) + : ASTGEN_SUPER_WaitFork(fl) {} + ASTNODE_NODE_FUNCS(WaitFork) +}; +class AstWhile final : public AstNodeStmt { +public: + AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp = nullptr, AstNode* incsp = nullptr) + : ASTGEN_SUPER_While(fl) { + setOp2p(condp); + addNOp3p(bodysp); + addNOp4p(incsp); + } + ASTNODE_NODE_FUNCS(While) + // op1 = prepare statements for condition (exec every loop) + AstNode* precondsp() const { return op1p(); } + AstNode* condp() const { return op2p(); } // op2 = condition to continue + AstNode* bodysp() const { return op3p(); } // op3 = body of loop + AstNode* incsp() const { return op4p(); } // op4 = increment (if from a FOR loop) + void addPrecondsp(AstNode* newp) { addOp1p(newp); } + void addBodysp(AstNode* newp) { addOp3p(newp); } + void addIncsp(AstNode* newp) { addOp4p(newp); } + virtual bool isGateOptimizable() const override { return false; } + virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // Stop statement searchback here + virtual void addBeforeStmt(AstNode* newp, AstNode* belowp) override; + // Stop statement searchback here + virtual void addNextStmt(AstNode* newp, AstNode* belowp) override; + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } +}; +class AstWith final : public AstNodeStmt { + // Used as argument to method, then to AstCMethodHard + // dtypep() contains the with lambda's return dtype + // Parents: funcref (similar to AstArg) + // Children: LambdaArgRef that declares the item variable + // Children: LambdaArgRef that declares the item.index variable + // Children: math (equation establishing the with) +public: + AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp, + AstNode* exprp) + : ASTGEN_SUPER_With(fl) { + addOp1p((AstNode*)indexArgRefp); + addOp2p((AstNode*)valueArgRefp); + addNOp3p(exprp); + } + ASTNODE_NODE_FUNCS(With) + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual bool hasDType() const override { return true; } + virtual const char* broken() const override { + BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype + BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype + return nullptr; + } + // + AstLambdaArgRef* indexArgRefp() const { return VN_AS(op1p(), LambdaArgRef); } + AstLambdaArgRef* valueArgRefp() const { return VN_AS(op2p(), LambdaArgRef); } + AstNode* exprp() const { return op3p(); } +}; +class AstWithParse final : public AstNodeStmt { + // In early parse, FUNC(index) WITH equation-using-index + // Replaced with AstWith + // Parents: math|stmt + // Children: funcref, math +public: + AstWithParse(FileLine* fl, bool stmt, AstNode* funcrefp, AstNode* exprp) + : ASTGEN_SUPER_WithParse(fl) { + statement(stmt); + setOp1p(funcrefp); + addNOp2p(exprp); + } + ASTNODE_NODE_FUNCS(WithParse) + virtual bool same(const AstNode* /*samep*/) const override { return true; } + // + AstNode* funcrefp() const { return op1p(); } + AstNode* exprp() const { return op2p(); } +}; + +// === AstNodeAssign === +class AstAssign final : public AstNodeAssign { +public: + AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) + : ASTGEN_SUPER_Assign(fl, lhsp, rhsp, timingControlp) { + dtypeFrom(lhsp); + } + ASTNODE_NODE_FUNCS(Assign) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssign(this->fileline(), lhsp, rhsp); + } + virtual bool brokeLhsMustBeLvalue() const override { return true; } +}; +class AstAssignAlias final : public AstNodeAssign { + // Like AstAssignW, but a true bidirect interconnection alias + // If both sides are wires, there's no LHS vs RHS, +public: + AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp) + : ASTGEN_SUPER_AssignAlias(fl, (AstNode*)lhsp, (AstNode*)rhsp) {} + ASTNODE_NODE_FUNCS(AssignAlias) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + V3ERROR_NA_RETURN(nullptr); + } + virtual bool brokeLhsMustBeLvalue() const override { return false; } +}; +class AstAssignDly final : public AstNodeAssign { +public: + AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) + : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp, timingControlp) {} + ASTNODE_NODE_FUNCS(AssignDly) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssignDly(this->fileline(), lhsp, rhsp); + } + virtual bool isGateOptimizable() const override { return false; } + virtual string verilogKwd() const override { return "<="; } + virtual bool brokeLhsMustBeLvalue() const override { return true; } +}; +class AstAssignForce final : public AstNodeAssign { + // Procedural 'force' statement +public: + AstAssignForce(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_AssignForce(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(AssignForce) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssignForce{this->fileline(), lhsp, rhsp}; + } + virtual bool brokeLhsMustBeLvalue() const override { return true; } +}; +class AstAssignPost final : public AstNodeAssign { + // Like Assign, but predelayed assignment requiring special order handling +public: + AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_AssignPost(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(AssignPost) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssignPost(this->fileline(), lhsp, rhsp); + } + virtual bool brokeLhsMustBeLvalue() const override { return true; } +}; +class AstAssignPre final : public AstNodeAssign { + // Like Assign, but predelayed assignment requiring special order handling +public: + AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_AssignPre(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(AssignPre) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssignPre(this->fileline(), lhsp, rhsp); + } + virtual bool brokeLhsMustBeLvalue() const override { return true; } +}; +class AstAssignVarScope final : public AstNodeAssign { + // Assign two VarScopes to each other +public: + AstAssignVarScope(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_AssignVarScope(fl, lhsp, rhsp) { + dtypeFrom(rhsp); + } + ASTNODE_NODE_FUNCS(AssignVarScope) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssignVarScope(this->fileline(), lhsp, rhsp); + } + virtual bool brokeLhsMustBeLvalue() const override { return false; } +}; +class AstAssignW final : public AstNodeAssign { + // Like assign, but wire/assign's in verilog, the only setting of the specified variable +public: + AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER_AssignW(fl, lhsp, rhsp) {} + ASTNODE_NODE_FUNCS(AssignW) + AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); } + void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstAssignW(this->fileline(), lhsp, rhsp); + } + virtual bool brokeLhsMustBeLvalue() const override { return true; } + AstAlways* convertToAlways() { + AstNode* const lhs1p = lhsp()->unlinkFrBack(); + AstNode* const rhs1p = rhsp()->unlinkFrBack(); + AstAlways* const newp = new AstAlways(fileline(), VAlwaysKwd::ALWAYS, nullptr, + new AstAssign(fileline(), lhs1p, rhs1p)); + replaceWith(newp); // User expected to then deleteTree(); + return newp; + } +}; + +// === AstNodeCCall === +class AstCCall final : public AstNodeCCall { + // C++ function call + // Parents: Anything above a statement + // Children: Args to the function + + string m_selfPointer; // Output code object pointer (e.g.: 'this') + +public: + AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) + : ASTGEN_SUPER_CCall(fl, funcp, argsp) {} + ASTNODE_NODE_FUNCS(CCall) + + string selfPointer() const { return m_selfPointer; } + void selfPointer(const string& value) { m_selfPointer = value; } + string selfPointerProtect(bool useSelfForThis) const; +}; +class AstCMethodCall final : public AstNodeCCall { + // C++ method call + // Parents: Anything above a statement + // Children: Args to the function +public: + AstCMethodCall(FileLine* fl, AstNode* fromp, AstCFunc* funcp, AstNode* argsp = nullptr) + : ASTGEN_SUPER_CMethodCall(fl, funcp, argsp) { + setOp1p(fromp); + } + ASTNODE_NODE_FUNCS(CMethodCall) + virtual const char* broken() const override { + BROKEN_BASE_RTN(AstNodeCCall::broken()); + BROKEN_RTN(!fromp()); + return nullptr; + } + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) + void fromp(AstNode* nodep) { setOp1p(nodep); } +}; +class AstCNew final : public AstNodeCCall { + // C++ new() call + // Parents: Anything above an expression + // Children: Args to the function +public: + AstCNew(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) + : ASTGEN_SUPER_CNew(fl, funcp, argsp) { + statement(false); + } + virtual bool hasDType() const override { return true; } + ASTNODE_NODE_FUNCS(CNew) +}; + +// === AstNodeCase === +class AstCase final : public AstNodeCase { + // Case statement + // Parents: {statement list} + // exprp Children: MATHs + // casesp Children: CASEITEMs +private: + VCaseType m_casex; // 0=case, 1=casex, 2=casez + bool m_fullPragma = false; // Synthesis full_case + bool m_parallelPragma = false; // Synthesis parallel_case + bool m_uniquePragma = false; // unique case + bool m_unique0Pragma = false; // unique0 case + bool m_priorityPragma = false; // priority case +public: + AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp) + : ASTGEN_SUPER_Case(fl, exprp, casesp) + , m_casex{casex} {} + ASTNODE_NODE_FUNCS(Case) + virtual string verilogKwd() const override { + return casez() ? "casez" : casex() ? "casex" : "case"; + } + virtual bool same(const AstNode* samep) const override { + return m_casex == static_cast(samep)->m_casex; + } + bool casex() const { return m_casex == VCaseType::CT_CASEX; } + bool casez() const { return m_casex == VCaseType::CT_CASEZ; } + bool caseInside() const { return m_casex == VCaseType::CT_CASEINSIDE; } + bool caseSimple() const { return m_casex == VCaseType::CT_CASE; } + void caseInsideSet() { m_casex = VCaseType::CT_CASEINSIDE; } + bool fullPragma() const { return m_fullPragma; } + void fullPragma(bool flag) { m_fullPragma = flag; } + bool parallelPragma() const { return m_parallelPragma; } + void parallelPragma(bool flag) { m_parallelPragma = flag; } + bool uniquePragma() const { return m_uniquePragma; } + void uniquePragma(bool flag) { m_uniquePragma = flag; } + bool unique0Pragma() const { return m_unique0Pragma; } + void unique0Pragma(bool flag) { m_unique0Pragma = flag; } + bool priorityPragma() const { return m_priorityPragma; } + void priorityPragma(bool flag) { m_priorityPragma = flag; } +}; +class AstGenCase final : public AstNodeCase { + // Generate Case statement + // Parents: {statement list} + // exprp Children: MATHs + // casesp Children: CASEITEMs +public: + AstGenCase(FileLine* fl, AstNode* exprp, AstNode* casesp) + : ASTGEN_SUPER_GenCase(fl, exprp, casesp) {} + ASTNODE_NODE_FUNCS(GenCase) +}; + +// === AstNodeCoverOrAssert === +class AstAssert final : public AstNodeCoverOrAssert { +public: + ASTNODE_NODE_FUNCS(Assert) + AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, + const string& name = "") + : ASTGEN_SUPER_Assert(fl, propp, passsp, immediate, name) { + addNOp3p(failsp); + } + AstNode* failsp() const { return op3p(); } // op3 = if assertion fails +}; +class AstAssertIntrinsic final : public AstNodeCoverOrAssert { + // A $cast or other compiler inserted assert, that must run even without --assert option +public: + ASTNODE_NODE_FUNCS(AssertIntrinsic) + AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, + bool immediate, const string& name = "") + : ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, immediate, name) { + addNOp3p(failsp); + } + AstNode* failsp() const { return op3p(); } // op3 = if assertion fails +}; +class AstCover final : public AstNodeCoverOrAssert { +public: + ASTNODE_NODE_FUNCS(Cover) + AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate, + const string& name = "") + : ASTGEN_SUPER_Cover(fl, propp, stmtsp, immediate, name) {} + AstNode* coverincp() const { return op3p(); } // op3 = coverage node + void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node + virtual bool immediate() const { return false; } +}; +class AstRestrict final : public AstNodeCoverOrAssert { +public: + ASTNODE_NODE_FUNCS(Restrict) + AstRestrict(FileLine* fl, AstNode* propp) + : ASTGEN_SUPER_Restrict(fl, propp, nullptr, false, "") {} +}; + +// === AstNodeFTaskRef === +class AstFuncRef final : public AstNodeFTaskRef { + // A reference to a function +public: + AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) + : ASTGEN_SUPER_FuncRef(fl, false, namep, pinsp) {} + AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) + : ASTGEN_SUPER_FuncRef(fl, false, name, pinsp) {} + ASTNODE_NODE_FUNCS(FuncRef) + virtual bool hasDType() const override { return true; } +}; +class AstMethodCall final : public AstNodeFTaskRef { + // A reference to a member task (or function) + // PARENTS: stmt/math + // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. + // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it +public: + AstMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, + AstNode* pinsp) + : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { + setOp2p(fromp); + dtypep(nullptr); // V3Width will resolve + } + AstMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) + : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { + setOp2p(fromp); + } + ASTNODE_NODE_FUNCS(MethodCall) + virtual const char* broken() const override { + BROKEN_BASE_RTN(AstNodeFTaskRef::broken()); + BROKEN_RTN(!fromp()); + return nullptr; + } + virtual void dump(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + void makeStatement() { + statement(true); + dtypeSetVoid(); + } + AstNode* fromp() const { + return op2p(); + } // op2 = Extracting what (nullptr=TBD during parsing) + void fromp(AstNode* nodep) { setOp2p(nodep); } +}; +class AstNew final : public AstNodeFTaskRef { + // New as constructor + // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it + // Parents: math|stmt + // Children: varref|arraysel, math +public: + AstNew(FileLine* fl, AstNode* pinsp) + : ASTGEN_SUPER_New(fl, false, "new", pinsp) {} + ASTNODE_NODE_FUNCS(New) + virtual bool cleanOut() const { return true; } + virtual bool same(const AstNode* /*samep*/) const override { return true; } + virtual bool hasDType() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } +}; +class AstTaskRef final : public AstNodeFTaskRef { + // A reference to a task +public: + AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) + : ASTGEN_SUPER_TaskRef(fl, true, namep, pinsp) { + statement(true); + } + AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp) + : ASTGEN_SUPER_TaskRef(fl, true, name, pinsp) {} + ASTNODE_NODE_FUNCS(TaskRef) +}; + +// === AstNodeFor === +class AstGenFor final : public AstNodeFor { +public: + AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) + : ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, bodysp) {} + ASTNODE_NODE_FUNCS(GenFor) +}; + +// === AstNodeIf === +class AstGenIf final : public AstNodeIf { +public: + AstGenIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) + : ASTGEN_SUPER_GenIf(fl, condp, ifsp, elsesp) {} + ASTNODE_NODE_FUNCS(GenIf) +}; +class AstIf final : public AstNodeIf { +private: + bool m_uniquePragma; // unique case + bool m_unique0Pragma; // unique0 case + bool m_priorityPragma; // priority case +public: + AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp = nullptr, AstNode* elsesp = nullptr) + : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) { + m_uniquePragma = false; + m_unique0Pragma = false; + m_priorityPragma = false; + } + ASTNODE_NODE_FUNCS(If) + bool uniquePragma() const { return m_uniquePragma; } + void uniquePragma(bool flag) { m_uniquePragma = flag; } + bool unique0Pragma() const { return m_unique0Pragma; } + void unique0Pragma(bool flag) { m_unique0Pragma = flag; } + bool priorityPragma() const { return m_priorityPragma; } + void priorityPragma(bool flag) { m_priorityPragma = flag; } +}; + +// === AstNodeReadWriteMem === +class AstReadMem final : public AstNodeReadWriteMem { +public: + AstReadMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, + AstNode* msbp) + : ASTGEN_SUPER_ReadMem(fl, hex, filenamep, memp, lsbp, msbp) {} + ASTNODE_NODE_FUNCS(ReadMem); + virtual string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); } + virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; } +}; +class AstWriteMem final : public AstNodeReadWriteMem { +public: + AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, + AstNode* msbp) + : ASTGEN_SUPER_WriteMem(fl, hex, filenamep, memp, lsbp, msbp) {} + ASTNODE_NODE_FUNCS(WriteMem) + virtual string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); } + virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } +}; + +// === AstNodeText === +class AstScCtor final : public AstNodeText { +public: + AstScCtor(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScCtor(fl, textp) {} + ASTNODE_NODE_FUNCS(ScCtor) + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } +}; +class AstScDtor final : public AstNodeText { +public: + AstScDtor(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScDtor(fl, textp) {} + ASTNODE_NODE_FUNCS(ScDtor) + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } +}; +class AstScHdr final : public AstNodeText { +public: + AstScHdr(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScHdr(fl, textp) {} + ASTNODE_NODE_FUNCS(ScHdr) + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } +}; +class AstScImp final : public AstNodeText { +public: + AstScImp(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScImp(fl, textp) {} + ASTNODE_NODE_FUNCS(ScImp) + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } +}; +class AstScImpHdr final : public AstNodeText { +public: + AstScImpHdr(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScImpHdr(fl, textp) {} + ASTNODE_NODE_FUNCS(ScImpHdr) + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } +}; +class AstScInt final : public AstNodeText { +public: + AstScInt(FileLine* fl, const string& textp) + : ASTGEN_SUPER_ScInt(fl, textp) {} + ASTNODE_NODE_FUNCS(ScInt) + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } +}; + +// === AstNodeSimpleText === +class AstText final : public AstNodeSimpleText { +public: + AstText(FileLine* fl, const string& textp, bool tracking = false) + : ASTGEN_SUPER_Text(fl, textp, tracking) {} + ASTNODE_NODE_FUNCS(Text) +}; +class AstTextBlock final : public AstNodeSimpleText { +private: + bool m_commas; // Comma separate emitted children +public: + explicit AstTextBlock(FileLine* fl, const string& textp = "", bool tracking = false, + bool commas = false) + : ASTGEN_SUPER_TextBlock(fl, textp, tracking) + , m_commas(commas) {} + ASTNODE_NODE_FUNCS(TextBlock) + void commas(bool flag) { m_commas = flag; } + bool commas() const { return m_commas; } + AstNode* nodesp() const { return op1p(); } + void addNodep(AstNode* nodep) { addOp1p(nodep); } + void addText(FileLine* fl, const string& textp, bool tracking = false) { + addNodep(new AstText(fl, textp, tracking)); + } +}; + +#endif // Guard diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index d534622e5..3ed73a6a7 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -155,6 +155,51 @@ void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Numb } } +void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin, + AstRange* rangep) { + // wantwidth=0 means figure it out, but if a widthmin is >=0 + // we allow width 0 so that {{0{x}},y} works properly + // wantwidthmin=-1: default, use wantwidth if it is non zero + m.m_keyword = kwd; + // Implicitness: // "parameter X" is implicit and sized from initial + // value, "parameter reg x" not + if (keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT) { + if (rangep || wantwidth) m.m_keyword = VBasicDTypeKwd::LOGIC; + } + if (numer == VSigning::NOSIGN) { + if (keyword().isSigned()) { + numer = VSigning::SIGNED; + } else if (keyword().isUnsigned()) { + numer = VSigning::UNSIGNED; + } + } + numeric(numer); + if (!rangep && (wantwidth || wantwidthmin >= 0)) { // Constant width + if (wantwidth > 1) m.m_nrange.init(wantwidth - 1, 0, false); + const int wmin = wantwidthmin >= 0 ? wantwidthmin : wantwidth; + widthForce(wantwidth, wmin); + } else if (!rangep) { // Set based on keyword properties + // V3Width will pull from this width + if (keyword().width() > 1 && !isOpaque()) { + m.m_nrange.init(keyword().width() - 1, 0, false); + } + widthForce(keyword().width(), keyword().width()); + } else { + widthForce(rangep->elementsConst(), + rangep->elementsConst()); // Maybe unknown if parameters underneath it + } + setNOp1p(rangep); + dtypep(this); +} + +void AstBasicDType::cvtRangeConst() { + if (rangep() && VN_IS(rangep()->leftp(), Const) && VN_IS(rangep()->rightp(), Const)) { + m.m_nrange = VNumRange{rangep()->leftConst(), rangep()->rightConst()}; + rangep()->unlinkFrBackWithNext()->deleteTree(); + rangep(nullptr); + } +} + int AstBasicDType::widthAlignBytes() const { if (width() <= 8) { return 1; @@ -1026,6 +1071,11 @@ AstConstPool::AstConstPool(FileLine* fl) addOp1p(m_modp); m_modp->addStmtp(m_scopep); } +const char* AstConstPool::broken() const { + BROKEN_RTN(m_modp && !m_modp->brokeExists()); + BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); + return nullptr; +} AstVarScope* AstConstPool::createNewEntry(const string& name, AstNode* initp) { FileLine* const fl = initp->fileline(); @@ -1297,11 +1347,19 @@ void AstCell::dump(std::ostream& str) const { str << " ->UNLINKED:" << modName(); } } +const char* AstCell::broken() const { + BROKEN_RTN(m_modp && !m_modp->brokeExists()); + return nullptr; +} void AstCellInline::dump(std::ostream& str) const { this->AstNode::dump(str); str << " -> " << origModName(); str << " [scopep=" << reinterpret_cast(scopep()) << "]"; } +const char* AstCellInline::broken() const { + BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); + return nullptr; +} const char* AstClassPackage::broken() const { BROKEN_BASE_RTN(AstNodeModule::broken()); BROKEN_RTN(m_classp && !m_classp->brokeExists()); @@ -1346,6 +1404,17 @@ void AstClass::dump(std::ostream& str) const { if (isExtended()) str << " [EXT]"; if (isVirtual()) str << " [VIRT]"; } +const char* AstClass::broken() const { + BROKEN_BASE_RTN(AstNodeModule::broken()); + BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); + return nullptr; +} +void AstClass::cloneRelink() { + AstNodeModule::cloneRelink(); + if (m_classOrPackagep && m_classOrPackagep->clonep()) { + m_classOrPackagep = m_classOrPackagep->clonep(); + } +} AstClass* AstClassExtends::classp() const { const AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType); if (VL_UNLIKELY(!refp)) { // LinkDot uses this for 'super.' @@ -1368,6 +1437,18 @@ void AstClassRefDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "class:" << name(); } +const char* AstClassRefDType::broken() const { + BROKEN_RTN(m_classp && !m_classp->brokeExists()); + BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); + return nullptr; +} +void AstClassRefDType::cloneRelink() { + if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep(); + if (m_classOrPackagep && m_classOrPackagep->clonep()) { + m_classOrPackagep = m_classOrPackagep->clonep(); + } +} +string AstClassRefDType::name() const { return classp() ? classp()->name() : ""; } void AstNodeCoverOrAssert::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); if (immediate()) str << " [IMMEDIATE]"; @@ -1385,6 +1466,11 @@ void AstEnumItemRef::dump(std::ostream& str) const { str << "UNLINKED"; } } +const char* AstEnumItemRef::broken() const { + BROKEN_RTN(m_itemp && !m_itemp->brokeExists()); + BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); + return nullptr; +} void AstIfaceRefDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); if (cellName() != "") str << " cell=" << cellName(); @@ -1416,6 +1502,46 @@ void AstInitArray::dump(std::ostream& str) const { str << " [" << itr.first << "]=" << reinterpret_cast(itr.second); } } +const char* AstInitArray::broken() const { + for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { + BROKEN_RTN(!it->second); + BROKEN_RTN(!it->second->brokeExists()); + } + return nullptr; +} +void AstInitArray::cloneRelink() { + for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) { + if (it->second->clonep()) it->second = it->second->clonep(); + } +} +AstNode* AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) { + // Returns old value, caller must garbage collect + AstNode* oldp = nullptr; + const auto it = m_map.find(index); + if (it != m_map.end()) { + oldp = it->second->valuep(); + it->second->valuep(newp); + } else { + AstInitItem* const itemp = new AstInitItem(fileline(), newp); + m_map.emplace(index, itemp); + addOp2p(itemp); + } + return oldp; +} +AstNode* AstInitArray::getIndexValuep(uint64_t index) const { + const auto it = m_map.find(index); + if (it == m_map.end()) { + return nullptr; + } else { + return it->second->valuep(); + } +} +AstNode* AstInitArray::getIndexDefaultedValuep(uint64_t index) const { + AstNode* valuep = getIndexValuep(index); + if (!valuep) valuep = defaultp(); + return valuep; +} + void AstJumpGo::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); str << " -> "; @@ -1425,6 +1551,13 @@ void AstJumpGo::dump(std::ostream& str) const { str << "%Error:UNLINKED"; } } +const char* AstJumpGo::broken() const { + BROKEN_RTN(!labelp()->brokeExistsBelow()); + return nullptr; +} +void AstJumpGo::cloneRelink() { + if (m_labelp->clonep()) m_labelp = m_labelp->clonep(); +} void AstJumpLabel::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); str << " -> "; @@ -1447,6 +1580,13 @@ void AstMemberSel::dump(std::ostream& str) const { str << "%Error:UNLINKED"; } } +void AstMemberSel::cloneRelink() { + if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); +} +const char* AstMemberSel::broken() const { + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + return nullptr; +} void AstMethodCall::dump(std::ostream& str) const { this->AstNodeFTaskRef::dump(str); if (isStatement()) str << " [STMT]"; @@ -1468,6 +1608,13 @@ void AstModportFTaskRef::dump(std::ostream& str) const { str << " -> UNLINKED"; } } +const char* AstModportFTaskRef::broken() const { + BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists()); + return nullptr; +} +void AstModportFTaskRef::cloneRelink() { + if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep(); +} void AstModportVarRef::dump(std::ostream& str) const { this->AstNode::dump(str); if (direction().isAny()) str << " " << direction(); @@ -1478,6 +1625,13 @@ void AstModportVarRef::dump(std::ostream& str) const { str << " -> UNLINKED"; } } +const char* AstModportVarRef::broken() const { + BROKEN_RTN(m_varp && !m_varp->brokeExists()); + return nullptr; +} +void AstModportVarRef::cloneRelink() { + if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); +} void AstPin::dump(std::ostream& str) const { this->AstNode::dump(str); if (modVarp()) { @@ -1488,6 +1642,17 @@ void AstPin::dump(std::ostream& str) const { } if (svImplicit()) str << " [.SV]"; } +const char* AstPin::broken() const { + BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); + BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists()); + return nullptr; +} +string AstPin::prettyOperatorName() const { + return modVarp() + ? ((modVarp()->direction().isAny() ? modVarp()->direction().prettyName() + " " : "") + + "port connection " + modVarp()->prettyNameQ()) + : "port connection"; +} void AstPrintTimeScale::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); str << " " << timeunit(); @@ -1533,6 +1698,23 @@ void AstRefDType::dump(std::ostream& str) const { str << " -> UNLINKED"; } } +const char* AstRefDType::broken() const { + BROKEN_RTN(m_typedefp && !m_typedefp->brokeExists()); + BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); + BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); + return nullptr; +} +void AstRefDType::cloneRelink() { + if (m_typedefp && m_typedefp->clonep()) m_typedefp = m_typedefp->clonep(); + if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); + if (m_classOrPackagep && m_classOrPackagep->clonep()) { + m_classOrPackagep = m_classOrPackagep->clonep(); + } +} +AstNodeDType* AstRefDType::subDTypep() const { + if (typedefp()) return typedefp()->subDTypep(); + return refDTypep(); // Maybe nullptr +} void AstNodeUOrStructDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); if (packed()) str << " [PACKED]"; @@ -1603,6 +1785,32 @@ void AstNetlist::dump(std::ostream& str) const { this->AstNode::dump(str); str << " [" << timeunit() << "/" << timeprecision() << "]"; } +const char* AstNetlist::broken() const { + BROKEN_RTN(m_typeTablep && !m_typeTablep->brokeExists()); + BROKEN_RTN(m_constPoolp && !m_constPoolp->brokeExists()); + BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); + BROKEN_RTN(m_evalp && !m_evalp->brokeExists()); + BROKEN_RTN(m_dpiExportTriggerp && !m_dpiExportTriggerp->brokeExists()); + BROKEN_RTN(m_topScopep && !m_topScopep->brokeExists()); + return nullptr; +} +AstPackage* AstNetlist::dollarUnitPkgAddp() { + if (!m_dollarUnitPkgp) { + m_dollarUnitPkgp = new AstPackage(fileline(), AstPackage::dollarUnitName()); + // packages are always libraries; don't want to make them a "top" + m_dollarUnitPkgp->inLibrary(true); + m_dollarUnitPkgp->modTrace(false); // may reconsider later + m_dollarUnitPkgp->internal(true); + addModulep(m_dollarUnitPkgp); + } + return m_dollarUnitPkgp; +} +void AstNetlist::createTopScope(AstScope* scopep) { + UASSERT(scopep, "Must not be nullptr"); + UASSERT_OBJ(!m_topScopep, scopep, "TopScope already exits"); + m_topScopep = new AstTopScope{scopep->modp()->fileline(), scopep}; + scopep->modp()->addStmtp(v3Global.rootp()->topScopep()); +} void AstNodeModule::dump(std::ostream& str) const { this->AstNode::dump(str); str << " L" << level(); @@ -1620,10 +1828,24 @@ void AstPackageExport::dump(std::ostream& str) const { this->AstNode::dump(str); str << " -> " << packagep(); } +const char* AstPackageExport ::broken() const { + BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); + return nullptr; +} +void AstPackageExport::cloneRelink() { + if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); +} void AstPackageImport::dump(std::ostream& str) const { this->AstNode::dump(str); str << " -> " << packagep(); } +const char* AstPackageImport::broken() const { + BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); + return nullptr; +} +void AstPackageImport::cloneRelink() { + if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); +} void AstPatMember::dump(std::ostream& str) const { this->AstNodeMath::dump(str); if (isDefault()) str << " [DEFAULT]"; @@ -1691,10 +1913,30 @@ void AstWildcardArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "[*]"; } +bool AstWildcardArrayDType::same(const AstNode* samep) const { + const AstNodeArrayDType* const asamep = static_cast(samep); + if (!asamep->subDTypep()) return false; + return (subDTypep() == asamep->subDTypep()); +} +bool AstWildcardArrayDType::similarDType(AstNodeDType* samep) const { + const AstNodeArrayDType* const asamep = static_cast(samep); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); +} void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "[]"; } +bool AstUnsizedArrayDType::same(const AstNode* samep) const { + const AstNodeArrayDType* const asamep = static_cast(samep); + if (!asamep->subDTypep()) return false; + return (subDTypep() == asamep->subDTypep()); +} +bool AstUnsizedArrayDType::similarDType(AstNodeDType* samep) const { + const AstNodeArrayDType* const asamep = static_cast(samep); + return type() == samep->type() && asamep->subDTypep() + && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); +} void AstEmptyQueueDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "emptyq"; @@ -1742,6 +1984,9 @@ void AstVarRef::dump(std::ostream& str) const { str << "UNLINKED"; } } +bool AstVarRef::same(const AstNode* samep) const { + return same(static_cast(samep)); +} void AstVar::dump(std::ostream& str) const { this->AstNode::dump(str); if (isSc()) str << " [SC]"; @@ -1804,6 +2049,13 @@ void AstClassOrPackageRef::dump(std::ostream& str) const { str << "UNLINKED"; } } +AstNodeModule* AstClassOrPackageRef::classOrPackagep() const { + AstNode* foundp = m_classOrPackageNodep; + while (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep(); + if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp(); + return VN_CAST(foundp, NodeModule); +} + void AstDot::dump(std::ostream& str) const { this->AstNode::dump(str); if (colon()) str << " [::]"; @@ -1817,6 +2069,16 @@ void AstActive::dump(std::ostream& str) const { str << "UNLINKED"; } } +const char* AstActive::broken() const { + BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists()); + return nullptr; +} +void AstActive::cloneRelink() { + if (m_sensesp->clonep()) { + m_sensesp = m_sensesp->clonep(); + UASSERT(m_sensesp, "Bad clone cross link: " << this); + } +} void AstNodeFTaskRef::dump(std::ostream& str) const { this->AstNodeStmt::dump(str); if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep()); @@ -1920,6 +2182,14 @@ void AstCFunc::dump(std::ostream& str) const { if (isDestructor()) str << " [DTOR]"; if (isVirtual()) str << " [VIRT]"; } +const char* AstCFunc::broken() const { + BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); + return nullptr; +} +void AstCFunc::cloneRelink() { + if (m_scopep && m_scopep->clonep()) m_scopep = m_scopep->clonep(); +} + void AstCUse::dump(std::ostream& str) const { this->AstNode::dump(str); str << " [" << useType() << "]"; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h deleted file mode 100644 index b5724847b..000000000 --- a/src/V3AstNodes.h +++ /dev/null @@ -1,9592 +0,0 @@ -// -*- mode: C++; c-file-style: "cc-mode" -*- -//************************************************************************* -// DESCRIPTION: Verilator: Ast node structure -// -// Code available from: https://verilator.org -// -//************************************************************************* -// -// Copyright 2003-2022 by Wilson Snyder. This program is free software; you -// can redistribute it and/or modify it under the terms of either the GNU -// Lesser General Public License Version 3 or the Perl Artistic License -// Version 2.0. -// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -// -//************************************************************************* - -#ifndef VERILATOR_V3ASTNODES_H_ -#define VERILATOR_V3ASTNODES_H_ - -#ifndef VERILATOR_V3AST_H_ -#error "Use V3Ast.h as the include" -#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h -#endif - -//###################################################################### -// Standard defines for all AstNode final classes - -#define ASTNODE_NODE_FUNCS_NO_DTOR(name) \ - virtual void accept(VNVisitor& v) override { v.visit(this); } \ - virtual AstNode* clone() override { return new Ast##name(*this); } \ - static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ - } \ - Ast##name* cloneTree(bool cloneNext) { \ - return static_cast(AstNode::cloneTree(cloneNext)); \ - } \ - Ast##name* clonep() const { return static_cast(AstNode::clonep()); } - -#define ASTNODE_NODE_FUNCS(name) \ - virtual ~Ast##name() override = default; \ - ASTNODE_NODE_FUNCS_NO_DTOR(name) - -//###################################################################### -// Macros generated by 'astgen' - -#include "V3AstNodes__gen_macros.h" - -//###################################################################### -//=== Ast* : Specific types -// Netlist interconnect - -class AstConst final : public AstNodeMath { - // A constant -private: - V3Number m_num; // Constant value - void initWithNumber() { - if (m_num.isDouble()) { - dtypeSetDouble(); - } else if (m_num.isString()) { - dtypeSetString(); - } else { - dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()), - VSigning::fromBool(m_num.isSigned())); - } - m_num.nodep(this); - } - -public: - AstConst(FileLine* fl, const V3Number& num) - : ASTGEN_SUPER_Const(fl) - , m_num(num) { - initWithNumber(); - } - class WidthedValue {}; // for creator type-overload selection - AstConst(FileLine* fl, WidthedValue, int width, uint32_t value) - : ASTGEN_SUPER_Const(fl) - , m_num(this, width, value) { - initWithNumber(); - } - class DTyped {}; // for creator type-overload selection - // Zero/empty constant with a type matching nodetypep - AstConst(FileLine* fl, DTyped, const AstNodeDType* nodedtypep) - : ASTGEN_SUPER_Const(fl) - , m_num(this, nodedtypep) { - initWithNumber(); - } - class StringToParse {}; // for creator type-overload selection - AstConst(FileLine* fl, StringToParse, const char* sourcep) - : ASTGEN_SUPER_Const(fl) - , m_num(this, sourcep) { - initWithNumber(); - } - class VerilogStringLiteral {}; // for creator type-overload selection - AstConst(FileLine* fl, VerilogStringLiteral, const string& str) - : ASTGEN_SUPER_Const(fl) - , m_num(V3Number::VerilogStringLiteral(), this, str) { - initWithNumber(); - } - AstConst(FileLine* fl, uint32_t num) - : ASTGEN_SUPER_Const(fl) - , m_num(this, 32, num) { - dtypeSetLogicUnsized(m_num.width(), 0, VSigning::UNSIGNED); - } - class Unsized32 {}; // for creator type-overload selection - AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value - : ASTGEN_SUPER_Const(fl) - , m_num(this, 32, num) { - m_num.width(32, false); - dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::UNSIGNED); - } - class Signed32 {}; // for creator type-overload selection - AstConst(FileLine* fl, Signed32, int32_t num) // Signed 32-bit integer of specified value - : ASTGEN_SUPER_Const(fl) - , m_num(this, 32, num) { - m_num.width(32, true); - dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::SIGNED); - } - class Unsized64 {}; // for creator type-overload selection - AstConst(FileLine* fl, Unsized64, uint64_t num) - : ASTGEN_SUPER_Const(fl) - , m_num(this, 64, 0) { - m_num.setQuad(num); - dtypeSetLogicSized(64, VSigning::UNSIGNED); - } - class SizedEData {}; // for creator type-overload selection - AstConst(FileLine* fl, SizedEData, uint64_t num) - : ASTGEN_SUPER_Const(fl) - , m_num(this, VL_EDATASIZE, 0) { - m_num.setQuad(num); - dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED); - } - class RealDouble {}; // for creator type-overload selection - AstConst(FileLine* fl, RealDouble, double num) - : ASTGEN_SUPER_Const(fl) - , m_num(this, 64) { - m_num.setDouble(num); - dtypeSetDouble(); - } - class String {}; // for creator type-overload selection - AstConst(FileLine* fl, String, const string& num) - : ASTGEN_SUPER_Const(fl) - , m_num(V3Number::String(), this, num) { - dtypeSetString(); - } - class BitFalse {}; - AstConst(FileLine* fl, BitFalse) // Shorthand const 0, dtype should be a logic of size 1 - : ASTGEN_SUPER_Const(fl) - , m_num(this, 1, 0) { - dtypeSetBit(); - } - // Shorthand const 1 (or with argument 0/1), dtype should be a logic of size 1 - class BitTrue {}; - AstConst(FileLine* fl, BitTrue, bool on = true) - : ASTGEN_SUPER_Const(fl) - , m_num(this, 1, on) { - dtypeSetBit(); - } - class Null {}; - AstConst(FileLine* fl, Null) - : ASTGEN_SUPER_Const(fl) - , m_num(V3Number::Null{}, this) { - dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here - initWithNumber(); - } - ASTNODE_NODE_FUNCS(Const) - virtual string name() const override { return num().ascii(); } // * = Value - const V3Number& num() const { return m_num; } // * = Value - V3Number& num() { return m_num; } // * = Value - uint32_t toUInt() const { return num().toUInt(); } - int32_t toSInt() const { return num().toSInt(); } - uint64_t toUQuad() const { return num().toUQuad(); } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* samep) const override { - const AstConst* const sp = static_cast(samep); - return num().isCaseEq(sp->num()); - } - virtual int instrCount() const override { return widthInstrs(); } - bool isEqAllOnes() const { return num().isEqAllOnes(width()); } - bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); } - // Parse string and create appropriate type of AstConst. - // May return nullptr on parse failure. - static AstConst* parseParamLiteral(FileLine* fl, const string& literal); -}; - -class AstEmpty final : public AstNode { - // Represents something missing, e.g. a missing argument in FOREACH -public: - explicit AstEmpty(FileLine* fl) - : ASTGEN_SUPER_Empty(fl) {} - ASTNODE_NODE_FUNCS(Empty) - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstEmptyQueue final : public AstNodeMath { -public: - explicit AstEmptyQueue(FileLine* fl) - : ASTGEN_SUPER_EmptyQueue(fl) {} - ASTNODE_NODE_FUNCS(EmptyQueue) - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitVerilog() override { return "{}"; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool cleanOut() const override { return true; } -}; - -class AstRange final : public AstNodeRange { - // Range specification, for use under variables and cells -public: - AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp) - : ASTGEN_SUPER_Range(fl) { - setOp2p(leftp); - setOp3p(rightp); - } - AstRange(FileLine* fl, int left, int right) - : ASTGEN_SUPER_Range(fl) { - setOp2p(new AstConst(fl, left)); - setOp3p(new AstConst(fl, right)); - } - AstRange(FileLine* fl, const VNumRange& range) - : ASTGEN_SUPER_Range(fl) { - setOp2p(new AstConst(fl, range.left())); - setOp3p(new AstConst(fl, range.right())); - } - ASTNODE_NODE_FUNCS(Range) - AstNode* leftp() const { return op2p(); } - AstNode* rightp() const { return op3p(); } - int leftConst() const { - AstConst* const constp = VN_CAST(leftp(), Const); - return (constp ? constp->toSInt() : 0); - } - int rightConst() const { - AstConst* const constp = VN_CAST(rightp(), Const); - return (constp ? constp->toSInt() : 0); - } - int hiConst() const { - const int l = leftConst(); - const int r = rightConst(); - return l > r ? l : r; - } - int loConst() const { - const int l = leftConst(); - const int r = rightConst(); - return l > r ? r : l; - } - int elementsConst() const { return hiConst() - loConst() + 1; } - bool littleEndian() const { return leftConst() < rightConst(); } - virtual void dump(std::ostream& str) const override; - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstBracketRange final : public AstNodeRange { - // Parser only concept "[lhsp]", a AstUnknownRange, QueueRange or Range, - // unknown until lhsp type is determined -public: - AstBracketRange(FileLine* fl, AstNode* elementsp) - : ASTGEN_SUPER_BracketRange(fl) { - setOp1p(elementsp); - } - ASTNODE_NODE_FUNCS(BracketRange) - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // Will be removed in V3Width, which relies on this - // being a child not a dtype pointed node - virtual bool maybePointedTo() const override { return false; } - AstNode* elementsp() const { return op1p(); } -}; - -class AstUnsizedRange final : public AstNodeRange { - // Unsized range specification, for open arrays -public: - explicit AstUnsizedRange(FileLine* fl) - : ASTGEN_SUPER_UnsizedRange(fl) {} - ASTNODE_NODE_FUNCS(UnsizedRange) - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitVerilog() { return "[]"; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstWildcardRange final : public AstNodeRange { - // Wildcard range specification, for wildcard index type associative arrays -public: - explicit AstWildcardRange(FileLine* fl) - : ASTGEN_SUPER_WildcardRange(fl) {} - ASTNODE_NODE_FUNCS(WildcardRange) - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitVerilog() { return "[*]"; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstStrengthSpec final : public AstNode { -private: - VStrength m_s0; // Drive 0 strength - VStrength m_s1; // Drive 1 strength - -public: - AstStrengthSpec(FileLine* fl, VStrength s0, VStrength s1) - : ASTGEN_SUPER_StrengthSpec(fl) - , m_s0{s0} - , m_s1{s1} {} - - ASTNODE_NODE_FUNCS(StrengthSpec) - VStrength strength0() { return m_s0; } - VStrength strength1() { return m_s1; } - virtual void dump(std::ostream& str) const override; -}; - -class AstGatePin final : public AstNodeMath { - // Possibly expand a gate primitive input pin value to match the range of the gate primitive -public: - AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep) - : ASTGEN_SUPER_GatePin(fl) { - setOp1p(lhsp); - setOp2p(rangep); - } - ASTNODE_NODE_FUNCS(GatePin) - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - AstNode* exprp() const { return op1p(); } // op1 = Pin expression - AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Range of pin -}; - -//###################################################################### -// Classes - -class AstClassPackage final : public AstNodeModule { - // The static information portion of a class (treated similarly to a package) - AstClass* m_classp - = nullptr; // Class package this is under (weak pointer, hard link is other way) -public: - AstClassPackage(FileLine* fl, const string& name) - : ASTGEN_SUPER_ClassPackage(fl, name) {} - ASTNODE_NODE_FUNCS(ClassPackage) - virtual string verilogKwd() const override { return "classpackage"; } - virtual const char* broken() const override; - virtual void cloneRelink() override; - virtual bool timescaleMatters() const override { return false; } - AstClass* classp() const { return m_classp; } - void classp(AstClass* classp) { m_classp = classp; } -}; - -class AstClass final : public AstNodeModule { - // TYPES - using MemberNameMap = std::map; - // MEMBERS - MemberNameMap m_members; // Members or method children - AstClassPackage* m_classOrPackagep = nullptr; // Class package this is under - bool m_virtual = false; // Virtual class - bool m_extended = false; // Is extension or extended by other classes - void insertCache(AstNode* nodep); - -public: - AstClass(FileLine* fl, const string& name) - : ASTGEN_SUPER_Class(fl, name) {} - ASTNODE_NODE_FUNCS(Class) - virtual string verilogKwd() const override { return "class"; } - virtual bool maybePointedTo() const override { return true; } - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { - BROKEN_BASE_RTN(AstNodeModule::broken()); - BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - AstNodeModule::cloneRelink(); - if (m_classOrPackagep && m_classOrPackagep->clonep()) { - m_classOrPackagep = m_classOrPackagep->clonep(); - } - } - virtual bool timescaleMatters() const override { return false; } - // op1/op2/op3 in AstNodeModule - AstClassPackage* classOrPackagep() const { return m_classOrPackagep; } - void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; } - AstNode* membersp() const { return stmtsp(); } // op2 = List of statements - void addMembersp(AstNode* nodep) { - insertCache(nodep); - addStmtp(nodep); - } - AstClassExtends* extendsp() const { return VN_AS(op4p(), ClassExtends); } - void extendsp(AstNode* nodep) { addNOp4p(nodep); } - void clearCache() { m_members.clear(); } - void repairCache(); - AstNode* findMember(const string& name) const { - const auto it = m_members.find(name); - return (it == m_members.end()) ? nullptr : it->second; - } - bool isExtended() const { return m_extended; } - void isExtended(bool flag) { m_extended = flag; } - bool isVirtual() const { return m_virtual; } - void isVirtual(bool flag) { m_virtual = flag; } - // Return true if this class is an extension of base class (SLOW) - // Accepts nullptrs - static bool isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp); -}; - -class AstClassExtends final : public AstNode { - // Children: List of AstParseRef for packages/classes - // during early parse, then moves to dtype -public: - AstClassExtends(FileLine* fl, AstNode* classOrPkgsp) - : ASTGEN_SUPER_ClassExtends(fl) { - setNOp2p(classOrPkgsp); // Only for parser - } - ASTNODE_NODE_FUNCS(ClassExtends) - virtual bool hasDType() const override { return true; } - virtual string verilogKwd() const override { return "extends"; } - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - AstNode* classOrPkgsp() const { return op2p(); } - AstClass* classp() const; // Class being extended (after link) -}; - -//###################################################################### -//==== Data Types - -class AstParamTypeDType final : public AstNodeDType { - // Parents: MODULE - // A parameter type statement; much like a var or typedef -private: - const VVarType m_varType; // Type of variable (for localparam vs. param) - string m_name; // Name of variable -public: - AstParamTypeDType(FileLine* fl, VVarType type, const string& name, VFlagChildDType, - AstNodeDType* dtp) - : ASTGEN_SUPER_ParamTypeDType(fl) - , m_varType{type} - , m_name{name} { - childDTypep(dtp); // Only for parser - dtypep(nullptr); // V3Width will resolve - } - ASTNODE_NODE_FUNCS(ParamTypeDType) - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Type assigning to - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return dtypep() ? dtypep() : childDTypep(); - } - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { - return subDTypep()->skipRefToConstp(); - } - virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } - virtual bool similarDType(AstNodeDType* samep) const override { - const AstParamTypeDType* const sp = static_cast(samep); - return type() == samep->type() && sp - && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()); - } - virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } - // METHODS - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual void name(const string& flag) override { m_name = flag; } - VVarType varType() const { return m_varType; } // * = Type of variable - bool isParam() const { return true; } - bool isGParam() const { return (varType() == VVarType::GPARAM); } - virtual bool isCompound() const override { - v3fatalSrc("call isCompound on subdata type, not reference"); - return false; - } -}; - -class AstTypedef final : public AstNode { -private: - string m_name; - bool m_attrPublic; - string m_tag; // Holds the string of the verilator tag -- used in XML output. -public: - AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, - AstNodeDType* dtp) - : ASTGEN_SUPER_Typedef(fl) - , m_name{name} { - childDTypep(dtp); // Only for parser - addAttrsp(attrsp); - dtypep(nullptr); // V3Width will resolve - m_attrPublic = false; - } - ASTNODE_NODE_FUNCS(Typedef) - virtual void dump(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Type assigning to - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } - AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse - // METHODS - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual void name(const string& flag) override { m_name = flag; } - bool attrPublic() const { return m_attrPublic; } - void attrPublic(bool flag) { m_attrPublic = flag; } - virtual void tag(const string& text) override { m_tag = text; } - virtual string tag() const override { return m_tag; } -}; - -class AstTypedefFwd final : public AstNode { - // Forward declaration of a type; stripped after netlist parsing is complete -private: - string m_name; - -public: - AstTypedefFwd(FileLine* fl, const string& name) - : ASTGEN_SUPER_TypedefFwd(fl) - , m_name{name} {} - ASTNODE_NODE_FUNCS(TypedefFwd) - // METHODS - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } -}; - -class AstDefImplicitDType final : public AstNodeDType { - // For parsing enum/struct/unions that are declared with a variable rather than typedef - // This allows "var enum {...} a,b" to share the enum definition for both variables - // After link, these become typedefs -private: - string m_name; - void* m_containerp; // In what scope is the name unique, so we can know what are duplicate - // definitions (arbitrary value) - const int m_uniqueNum; - -public: - AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType, - AstNodeDType* dtp) - : ASTGEN_SUPER_DefImplicitDType(fl) - , m_name{name} - , m_containerp{containerp} - , m_uniqueNum{uniqueNumInc()} { - childDTypep(dtp); // Only for parser - dtypep(nullptr); // V3Width will resolve - } - ASTNODE_NODE_FUNCS(DefImplicitDType) - int uniqueNum() const { return m_uniqueNum; } - virtual bool same(const AstNode* samep) const override { - const AstDefImplicitDType* const sp = static_cast(samep); - return uniqueNum() == sp->uniqueNum(); - } - virtual bool similarDType(AstNodeDType* samep) const override { - return type() == samep->type() && same(samep); - } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return dtypep() ? dtypep() : childDTypep(); - } - void* containerp() const { return m_containerp; } - // METHODS - // op1 = Range of variable - AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } - virtual string name() const override { return m_name; } - virtual void name(const string& flag) override { m_name = flag; } - virtual bool isCompound() const override { return false; } -}; - -class AstAssocArrayDType final : public AstNodeDType { - // Associative array data type, ie "[some_dtype]" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: DTYPE (the key, which remains here as a pointer) -private: - AstNodeDType* m_refDTypep; // Elements of this type (after widthing) - AstNodeDType* m_keyDTypep; // Keys of this type (after widthing) -public: - AstAssocArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeDType* keyDtp) - : ASTGEN_SUPER_AssocArrayDType(fl) { - childDTypep(dtp); // Only for parser - keyChildDTypep(keyDtp); // Only for parser - refDTypep(nullptr); - keyDTypep(nullptr); - dtypep(nullptr); // V3Width will resolve - } - AstAssocArrayDType(FileLine* fl, AstNodeDType* dtp, AstNodeDType* keyDtp) - : ASTGEN_SUPER_AssocArrayDType(fl) { - refDTypep(dtp); - keyDTypep(keyDtp); - dtypep(dtp); - } - ASTNODE_NODE_FUNCS(AssocArrayDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists()) - || (!m_keyDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - if (m_keyDTypep && m_keyDTypep->clonep()) m_keyDTypep = m_keyDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstAssocArrayDType* const asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - if (!asamep->keyDTypep()) return false; - return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep()); - } - virtual bool similarDType(AstNodeDType* samep) const override { - const AstAssocArrayDType* const asamep = static_cast(samep); - return type() == samep->type() && asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); - } - virtual string prettyDTypeName() const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - virtual AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - virtual AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; } - virtual void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); } - // - AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); } - void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } - // op1 = Range of variable - AstNodeDType* keyChildDTypep() const { return VN_AS(op2p(), NodeDType); } - void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); } - // METHODS - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } -}; - -class AstBracketArrayDType final : public AstNodeDType { - // Associative/Queue/Normal array data type, ie "[dtype_or_expr]" - // only for early parsing then becomes another data type - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: DTYPE (the key) -public: - AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* elementsp) - : ASTGEN_SUPER_BracketArrayDType(fl) { - setOp1p(dtp); // Only for parser - setOp2p(elementsp); // Only for parser - } - ASTNODE_NODE_FUNCS(BracketArrayDType) - virtual bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - virtual AstNodeDType* subDTypep() const override { return childDTypep(); } - // op2 = Range of variable - AstNode* elementsp() const { return op2p(); } - // METHODS - // Will be removed in V3Width, which relies on this - // being a child not a dtype pointed node - virtual bool maybePointedTo() const override { return false; } - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } - virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } - virtual bool isCompound() const override { return true; } -}; - -class AstDynArrayDType final : public AstNodeDType { - // Dynamic array data type, ie "[]" - // Children: DTYPE (moved to refDTypep() in V3Width) -private: - AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) -public: - AstDynArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_DynArrayDType(fl) { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - dtypep(nullptr); // V3Width will resolve - } - AstDynArrayDType(FileLine* fl, AstNodeDType* dtp) - : ASTGEN_SUPER_DynArrayDType(fl) { - refDTypep(dtp); - dtypep(nullptr); // V3Width will resolve - } - ASTNODE_NODE_FUNCS(DynArrayDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstAssocArrayDType* const asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return subDTypep() == asamep->subDTypep(); - } - virtual bool similarDType(AstNodeDType* samep) const override { - const AstAssocArrayDType* const asamep = static_cast(samep); - return type() == samep->type() && asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); - } - virtual string prettyDTypeName() const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - // METHODS - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } -}; - -class AstPackArrayDType final : public AstNodeArrayDType { - // Packed array data type, ie "some_dtype [2:0] var_name" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: RANGE (array bounds) -public: - AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) - : ASTGEN_SUPER_PackArrayDType(fl) { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - setOp2p(rangep); - dtypep(nullptr); // V3Width will resolve - const int width = subDTypep()->width() * rangep->elementsConst(); - widthForce(width, width); - } - AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep) - : ASTGEN_SUPER_PackArrayDType(fl) { - refDTypep(dtp); - setOp2p(rangep); - dtypep(this); - const int width = subDTypep()->width() * rangep->elementsConst(); - widthForce(width, width); - } - ASTNODE_NODE_FUNCS(PackArrayDType) - virtual string prettyDTypeName() const override; - virtual bool isCompound() const override { return false; } -}; - -class AstUnpackArrayDType final : public AstNodeArrayDType { - // Array data type, ie "some_dtype var_name [2:0]" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: RANGE (array bounds) - bool m_isCompound = false; // Non-POD subDType, or parent requires compound -public: - AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) - : ASTGEN_SUPER_UnpackArrayDType(fl) { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - setOp2p(rangep); - dtypep(nullptr); // V3Width will resolve - // For backward compatibility AstNodeArrayDType and others inherit - // width and signing from the subDType/base type - widthFromSub(subDTypep()); - } - AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep) - : ASTGEN_SUPER_UnpackArrayDType(fl) { - refDTypep(dtp); - setOp2p(rangep); - dtypep(this); - // For backward compatibility AstNodeArrayDType and others inherit - // width and signing from the subDType/base type - widthFromSub(subDTypep()); - } - ASTNODE_NODE_FUNCS(UnpackArrayDType) - virtual string prettyDTypeName() const override; - virtual bool same(const AstNode* samep) const override { - const AstUnpackArrayDType* const sp = static_cast(samep); - return m_isCompound == sp->m_isCompound; - } - // Outer dimension comes first. The first element is this node. - std::vector unpackDimensions(); - void isCompound(bool flag) { m_isCompound = flag; } - virtual bool isCompound() const override { return m_isCompound; } -}; - -class AstUnsizedArrayDType final : public AstNodeDType { - // Unsized/open-range Array data type, ie "some_dtype var_name []" - // Children: DTYPE (moved to refDTypep() in V3Width) -private: - AstNodeDType* m_refDTypep; // Elements of this type (after widthing) -public: - AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_UnsizedArrayDType(fl) { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - dtypep(nullptr); // V3Width will resolve - } - ASTNODE_NODE_FUNCS(UnsizedArrayDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstNodeArrayDType* const asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep() == asamep->subDTypep()); - } - virtual bool similarDType(AstNodeDType* samep) const override { - const AstNodeArrayDType* const asamep = static_cast(samep); - return type() == samep->type() && asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); - } - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } -}; - -class AstWildcardArrayDType final : public AstNodeDType { - // Wildcard index type associative array data type, ie "some_dtype var_name [*]" - // Children: DTYPE (moved to refDTypep() in V3Width) -private: - AstNodeDType* m_refDTypep; // Elements of this type (after widthing) -public: - AstWildcardArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_WildcardArrayDType(fl) { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - dtypep(nullptr); // V3Width will resolve - } - ASTNODE_NODE_FUNCS(WildcardArrayDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstNodeArrayDType* const asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep() == asamep->subDTypep()); - } - virtual bool similarDType(AstNodeDType* samep) const override { - const AstNodeArrayDType* const asamep = static_cast(samep); - return type() == samep->type() && asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); - } - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { - return sizeof(std::map); - } - virtual int widthTotalBytes() const override { - return sizeof(std::map); - } - virtual bool isCompound() const override { return true; } -}; - -class AstBasicDType final : public AstNodeDType { - // Builtin atomic/vectored data type - // Children: RANGE (converted to constant in V3Width) -private: - struct Members { - VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type - VNumRange m_nrange; // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword) - bool operator==(const Members& rhs) const { - return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange; - } - } m; - // See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned) -public: - AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN) - : ASTGEN_SUPER_BasicDType(fl) { - init(kwd, signst, 0, -1, nullptr); - } - AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth) - : ASTGEN_SUPER_BasicDType(fl) { - init(VBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr); - } - AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth) - : ASTGEN_SUPER_BasicDType(fl) { - init(VBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr); - } - AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin) - : ASTGEN_SUPER_BasicDType(fl) { - init(kwd, numer, wantwidth, widthmin, nullptr); - } - AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, VNumRange range, int widthmin) - : ASTGEN_SUPER_BasicDType(fl) { - init(kwd, numer, range.elements(), widthmin, nullptr); - m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be - } - // See also addRange in verilog.y -private: - void init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin, - AstRange* rangep) { - // wantwidth=0 means figure it out, but if a widthmin is >=0 - // we allow width 0 so that {{0{x}},y} works properly - // wantwidthmin=-1: default, use wantwidth if it is non zero - m.m_keyword = kwd; - // Implicitness: // "parameter X" is implicit and sized from initial - // value, "parameter reg x" not - if (keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT) { - if (rangep || wantwidth) m.m_keyword = VBasicDTypeKwd::LOGIC; - } - if (numer == VSigning::NOSIGN) { - if (keyword().isSigned()) { - numer = VSigning::SIGNED; - } else if (keyword().isUnsigned()) { - numer = VSigning::UNSIGNED; - } - } - numeric(numer); - if (!rangep && (wantwidth || wantwidthmin >= 0)) { // Constant width - if (wantwidth > 1) m.m_nrange.init(wantwidth - 1, 0, false); - const int wmin = wantwidthmin >= 0 ? wantwidthmin : wantwidth; - widthForce(wantwidth, wmin); - } else if (!rangep) { // Set based on keyword properties - // V3Width will pull from this width - if (keyword().width() > 1 && !isOpaque()) { - m.m_nrange.init(keyword().width() - 1, 0, false); - } - widthForce(keyword().width(), keyword().width()); - } else { - widthForce(rangep->elementsConst(), - rangep->elementsConst()); // Maybe unknown if parameters underneath it - } - setNOp1p(rangep); - dtypep(this); - } - -public: - ASTNODE_NODE_FUNCS(BasicDType) - virtual void dump(std::ostream& str) const override; - // width/widthMin/numeric compared elsewhere - virtual bool same(const AstNode* samep) const override { - const AstBasicDType* const sp = static_cast(samep); - return m == sp->m; - } - virtual bool similarDType(AstNodeDType* samep) const override { - return type() == samep->type() && same(samep); - } - virtual string name() const override { return m.m_keyword.ascii(); } - virtual string prettyDTypeName() const override; - virtual const char* broken() const override { - BROKEN_RTN(dtypep() != this); - return nullptr; - } - AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range of variable - void rangep(AstRange* nodep) { setNOp1p(nodep); } - void setSignedState(const VSigning& signst) { - // Note NOSIGN does NOT change the state; this is required by the parser - if (signst == VSigning::UNSIGNED) { - numeric(signst); - } else if (signst == VSigning::SIGNED) { - numeric(signst); - } - } - // METHODS - virtual AstBasicDType* basicp() const override { return (AstBasicDType*)this; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const override; - // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const override; - virtual bool isFourstate() const override { return keyword().isFourstate(); } - VBasicDTypeKwd keyword() const { // Avoid using - use isSomething accessors instead - return m.m_keyword; - } - bool isBitLogic() const { return keyword().isBitLogic(); } - bool isDouble() const { return keyword().isDouble(); } - bool isEventValue() const { return keyword().isEventValue(); } - bool isOpaque() const { return keyword().isOpaque(); } - bool isString() const { return keyword().isString(); } - bool isZeroInit() const { return keyword().isZeroInit(); } - bool isRanged() const { return rangep() || m.m_nrange.ranged(); } - bool isDpiBitVec() const { // DPI uses svBitVecVal - return keyword() == VBasicDTypeKwd::BIT && isRanged(); - } - bool isDpiLogicVec() const { // DPI uses svLogicVecVal - return keyword().isFourstate() && !(keyword() == VBasicDTypeKwd::LOGIC && !isRanged()); - } - bool isDpiPrimitive() const { // DPI uses a primitive type - return !isDpiBitVec() && !isDpiLogicVec(); - } - // Generally the lo/hi/left/right funcs should be used instead of nrange() - const VNumRange& nrange() const { return m.m_nrange; } - int hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); } - int lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); } - int elements() const { return (rangep() ? rangep()->elementsConst() : m.m_nrange.elements()); } - int left() const { return littleEndian() ? lo() : hi(); } // How to show a declaration - int right() const { return littleEndian() ? hi() : lo(); } - bool littleEndian() const { - return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian()); - } - bool implicit() const { return keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT; } - VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; } - void cvtRangeConst() { // Convert to smaller representation - if (rangep() && VN_IS(rangep()->leftp(), Const) && VN_IS(rangep()->rightp(), Const)) { - m.m_nrange = VNumRange{rangep()->leftConst(), rangep()->rightConst()}; - rangep()->unlinkFrBackWithNext()->deleteTree(); - rangep(nullptr); - } - } - virtual bool isCompound() const override { return isString(); } -}; - -class AstConstDType final : public AstNodeDType { - // const data type, ie "const some_dtype var_name [2:0]" - // ConstDType are removed in V3LinkLValue and become AstVar::isConst. - // When more generic types are supported AstConstDType will be propagated further. -private: - AstNodeDType* m_refDTypep = nullptr; // Inherit from this base data type -public: - AstConstDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_ConstDType(fl) { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); // V3Width will resolve - dtypep(nullptr); // V3Width will resolve - widthFromSub(subDTypep()); - } - ASTNODE_NODE_FUNCS(ConstDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstConstDType* const sp = static_cast(samep); - return (m_refDTypep == sp->m_refDTypep); - } - virtual bool similarDType(AstNodeDType* samep) const override { - return skipRefp()->similarDType(samep->skipRefp()); - } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { - v3fatalSrc("call isCompound on subdata type, not reference"); - return false; - } -}; - -class AstClassRefDType final : public AstNodeDType { - // Reference to a class - // Children: PINs (for parameter settings) -private: - AstClass* m_classp; // data type pointed to, BELOW the AstTypedef - AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy -public: - AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp) - : ASTGEN_SUPER_ClassRefDType(fl) - , m_classp{classp} { - dtypep(this); - addNOp4p(paramsp); - } - ASTNODE_NODE_FUNCS(ClassRefDType) - // METHODS - virtual const char* broken() const override { - BROKEN_RTN(m_classp && !m_classp->brokeExists()); - BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep(); - if (m_classOrPackagep && m_classOrPackagep->clonep()) { - m_classOrPackagep = m_classOrPackagep->clonep(); - } - } - virtual bool same(const AstNode* samep) const override { - const AstClassRefDType* const asamep = static_cast(samep); - return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); - } - virtual bool similarDType(AstNodeDType* samep) const override { - return this == samep || (type() == samep->type() && same(samep)); - } - virtual void dump(std::ostream& str = std::cout) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual string name() const override { return classp() ? classp()->name() : ""; } - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 0; } - virtual int widthTotalBytes() const override { return 0; } - virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } - virtual void virtRefDTypep(AstNodeDType* nodep) override {} - virtual AstNodeDType* subDTypep() const override { return nullptr; } - AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } - void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } - AstClass* classp() const { return m_classp; } - void classp(AstClass* nodep) { m_classp = nodep; } - AstPin* paramsp() const { return VN_AS(op4p(), Pin); } - virtual bool isCompound() const override { return true; } -}; - -class AstIfaceRefDType final : public AstNodeDType { - // Reference to an interface, either for a port, or inside parent cell -private: - FileLine* m_modportFileline; // Where modport token was - string m_cellName; // "" = no cell, such as when connects to 'input' iface - string m_ifaceName; // Interface name - string m_modportName; // "" = no modport - AstIface* m_ifacep = nullptr; // Pointer to interface; note cellp() should override - AstCell* m_cellp = nullptr; // When exact parent cell known; not a guess - AstModport* m_modportp = nullptr; // nullptr = unlinked or no modport -public: - AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName) - : ASTGEN_SUPER_IfaceRefDType(fl) - , m_modportFileline{nullptr} - , m_cellName{cellName} - , m_ifaceName{ifaceName} - , m_modportName{""} {} - AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName, - const string& ifaceName, const string& modport) - : ASTGEN_SUPER_IfaceRefDType(fl) - , m_modportFileline{modportFl} - , m_cellName{cellName} - , m_ifaceName{ifaceName} - , m_modportName{modport} {} - ASTNODE_NODE_FUNCS(IfaceRefDType) - // METHODS - virtual const char* broken() const override; - virtual void dump(std::ostream& str = std::cout) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual void cloneRelink() override; - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual int widthAlignBytes() const override { return 1; } - virtual int widthTotalBytes() const override { return 1; } - FileLine* modportFileline() const { return m_modportFileline; } - string cellName() const { return m_cellName; } - void cellName(const string& name) { m_cellName = name; } - string ifaceName() const { return m_ifaceName; } - void ifaceName(const string& name) { m_ifaceName = name; } - string modportName() const { return m_modportName; } - AstIface* ifaceViaCellp() const; // Use cellp or ifacep - AstIface* ifacep() const { return m_ifacep; } - void ifacep(AstIface* nodep) { m_ifacep = nodep; } - AstCell* cellp() const { return m_cellp; } - void cellp(AstCell* nodep) { m_cellp = nodep; } - AstModport* modportp() const { return m_modportp; } - void modportp(AstModport* modportp) { m_modportp = modportp; } - bool isModport() { return !m_modportName.empty(); } - virtual bool isCompound() const override { return true; } // But not relevant -}; - -class AstQueueDType final : public AstNodeDType { - // Queue array data type, ie "[ $ ]" - // Children: DTYPE (moved to refDTypep() in V3Width) -private: - AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) -public: - AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp) - : ASTGEN_SUPER_QueueDType(fl) { - setNOp2p(boundp); - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - dtypep(nullptr); // V3Width will resolve - } - AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNode* boundp) - : ASTGEN_SUPER_QueueDType(fl) { - setNOp2p(boundp); - refDTypep(dtp); - dtypep(dtp); - } - ASTNODE_NODE_FUNCS(QueueDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstQueueDType* const asamep = static_cast(samep); - if (!asamep->subDTypep()) return false; - return (subDTypep() == asamep->subDTypep()); - } - virtual bool similarDType(AstNodeDType* samep) const override { - const AstQueueDType* const asamep = static_cast(samep); - return type() == samep->type() && asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); - } - virtual void dumpSmall(std::ostream& str) const override; - virtual string prettyDTypeName() const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - AstNode* boundp() const { return op2p(); } // op2 = Bound, nullptr = none - void boundp(AstNode* nodep) { setNOp2p(nodep); } - int boundConst() const { - AstConst* const constp = VN_CAST(boundp(), Const); - return (constp ? constp->toSInt() : 0); - } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - // METHODS - virtual AstBasicDType* basicp() const override { return nullptr; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } -}; - -class AstRefDType final : public AstNodeDType { -private: - // Pre-Width must reference the Typeref, not what it points to, as some child - // types like AstBracketArrayType will disappear and can't lose the handle - AstTypedef* m_typedefp = nullptr; // referenced type - // Post-width typedefs are removed and point to type directly - AstNodeDType* m_refDTypep = nullptr; // data type pointed to, BELOW the AstTypedef - string m_name; // Name of an AstTypedef - AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy -public: - AstRefDType(FileLine* fl, const string& name) - : ASTGEN_SUPER_RefDType(fl) - , m_name{name} {} - AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp) - : ASTGEN_SUPER_RefDType(fl) - , m_name{name} { - setNOp3p(classOrPackagep); - addNOp4p(paramsp); - } - class FlagTypeOfExpr {}; // type(expr) for parser only - AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp) - : ASTGEN_SUPER_RefDType(fl) { - setOp2p(typeofp); - } - ASTNODE_NODE_FUNCS(RefDType) - // METHODS - virtual const char* broken() const override { - BROKEN_RTN(m_typedefp && !m_typedefp->brokeExists()); - BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); - BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_typedefp && m_typedefp->clonep()) m_typedefp = m_typedefp->clonep(); - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - if (m_classOrPackagep && m_classOrPackagep->clonep()) { - m_classOrPackagep = m_classOrPackagep->clonep(); - } - } - virtual bool same(const AstNode* samep) const override { - const AstRefDType* const asamep = static_cast(samep); - return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep - && m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep); - } - virtual bool similarDType(AstNodeDType* samep) const override { - return skipRefp()->similarDType(samep->skipRefp()); - } - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } - virtual string prettyDTypeName() const override { - return subDTypep() ? subDTypep()->name() : prettyName(); - } - virtual AstBasicDType* basicp() const override { - return subDTypep() ? subDTypep()->basicp() : nullptr; - } - virtual AstNodeDType* subDTypep() const override { - if (typedefp()) return typedefp()->subDTypep(); - return refDTypep(); // Maybe nullptr - } - virtual AstNodeDType* skipRefp() const override { - // Skip past both the Ref and the Typedef - if (subDTypep()) { - return subDTypep()->skipRefp(); - } else { - v3fatalSrc("Typedef not linked"); - return nullptr; - } - } - virtual AstNodeDType* skipRefToConstp() const override { - if (subDTypep()) { - return subDTypep()->skipRefToConstp(); - } else { - v3fatalSrc("Typedef not linked"); - return nullptr; - } - } - virtual AstNodeDType* skipRefToEnump() const override { - if (subDTypep()) { - return subDTypep()->skipRefToEnump(); - } else { - v3fatalSrc("Typedef not linked"); - return nullptr; - } - } - virtual int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } - virtual void name(const string& flag) override { m_name = flag; } - // op1 = Range of variable - AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - AstTypedef* typedefp() const { return m_typedefp; } - void typedefp(AstTypedef* nodep) { m_typedefp = nodep; } - AstNodeDType* refDTypep() const { return m_refDTypep; } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return refDTypep(); } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } - void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } - AstNode* typeofp() const { return op2p(); } - AstNode* classOrPackageOpp() const { return op3p(); } - AstPin* paramsp() const { return VN_AS(op4p(), Pin); } - virtual bool isCompound() const override { - v3fatalSrc("call isCompound on subdata type, not reference"); - return false; - } -}; - -class AstStructDType final : public AstNodeUOrStructDType { -public: - // VSigning below is mispurposed to indicate if packed or not - AstStructDType(FileLine* fl, VSigning numericUnpack) - : ASTGEN_SUPER_StructDType(fl, numericUnpack) {} - ASTNODE_NODE_FUNCS(StructDType) - virtual string verilogKwd() const override { return "struct"; } -}; - -class AstUnionDType final : public AstNodeUOrStructDType { -public: - // UNSUP: bool isTagged; - // VSigning below is mispurposed to indicate if packed or not - AstUnionDType(FileLine* fl, VSigning numericUnpack) - : ASTGEN_SUPER_UnionDType(fl, numericUnpack) {} - ASTNODE_NODE_FUNCS(UnionDType) - virtual string verilogKwd() const override { return "union"; } -}; - -class AstMemberDType final : public AstNodeDType { - // A member of a struct/union - // PARENT: AstNodeUOrStructDType -private: - AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) - string m_name; // Name of variable - string m_tag; // Holds the string of the verilator tag -- used in XML output. - int m_lsb = -1; // Within this level's packed struct, the LSB of the first bit of the member - // UNSUP: int m_randType; // Randomization type (IEEE) -public: - AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_MemberDType(fl) - , m_name{name} { - childDTypep(dtp); // Only for parser - dtypep(nullptr); // V3Width will resolve - refDTypep(nullptr); - } - AstMemberDType(FileLine* fl, const string& name, AstNodeDType* dtp) - : ASTGEN_SUPER_MemberDType(fl) - , m_name{name} { - UASSERT(dtp, "AstMember created with no dtype"); - refDTypep(dtp); - dtypep(this); - widthFromSub(subDTypep()); - } - ASTNODE_NODE_FUNCS(MemberDType) - virtual string name() const override { return m_name; } // * = Var name - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { - BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - // - // (Slow) recurse down to find basic data type (Note don't need virtual - - // AstVar isn't a NodeDType) - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) - AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { - return subDTypep()->skipRefToConstp(); - } - virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } - // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - // METHODS - virtual void name(const string& name) override { m_name = name; } - virtual void tag(const string& text) override { m_tag = text; } - virtual string tag() const override { return m_tag; } - int lsb() const { return m_lsb; } - void lsb(int lsb) { m_lsb = lsb; } - virtual bool isCompound() const override { - v3fatalSrc("call isCompound on subdata type, not reference"); - return false; - } -}; - -class AstEmptyQueueDType final : public AstNodeDType { - // For EmptyQueue -public: - explicit AstEmptyQueueDType(FileLine* fl) - : ASTGEN_SUPER_EmptyQueueDType(fl) { - dtypep(this); - } - ASTNODE_NODE_FUNCS(EmptyQueueDType) - virtual void dumpSmall(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual bool undead() const override { return true; } - virtual AstNodeDType* subDTypep() const override { return nullptr; } - virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } - virtual void virtRefDTypep(AstNodeDType* nodep) override {} - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstBasicDType* basicp() const override { return nullptr; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 1; } - virtual int widthTotalBytes() const override { return 1; } - virtual bool isCompound() const override { return false; } -}; - -class AstVoidDType final : public AstNodeDType { - // For e.g. a function returning void -public: - explicit AstVoidDType(FileLine* fl) - : ASTGEN_SUPER_VoidDType(fl) { - dtypep(this); - } - ASTNODE_NODE_FUNCS(VoidDType) - virtual void dumpSmall(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual bool undead() const override { return true; } - virtual AstNodeDType* subDTypep() const override { return nullptr; } - virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } - virtual void virtRefDTypep(AstNodeDType* nodep) override {} - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstBasicDType* basicp() const override { return nullptr; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 1; } - virtual int widthTotalBytes() const override { return 1; } - virtual bool isCompound() const override { return false; } -}; - -class AstEnumItem final : public AstNode { -private: - string m_name; - -public: - // Parents: ENUM - AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp) - : ASTGEN_SUPER_EnumItem(fl) - , m_name{name} { - addNOp1p(rangep); - addNOp2p(initp); - } - ASTNODE_NODE_FUNCS(EnumItem) - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual void name(const string& flag) override { m_name = flag; } - AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range for name appending - void rangep(AstRange* nodep) { addOp1p(nodep); } - AstNode* valuep() const { return op2p(); } // op2 = Value - void valuep(AstNode* nodep) { addOp2p(nodep); } -}; - -class AstEnumItemRef final : public AstNodeMath { -private: - AstEnumItem* m_itemp; // [AfterLink] Pointer to item - AstNodeModule* m_classOrPackagep; // Package hierarchy -public: - AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep) - : ASTGEN_SUPER_EnumItemRef(fl) - , m_itemp{itemp} - , m_classOrPackagep{classOrPackagep} { - dtypeFrom(m_itemp); - } - ASTNODE_NODE_FUNCS(EnumItemRef) - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return itemp()->name(); } - virtual int instrCount() const override { return 0; } - virtual const char* broken() const override { - BROKEN_RTN(m_itemp && !m_itemp->brokeExists()); - BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_itemp->clonep()) m_itemp = m_itemp->clonep(); - } - virtual bool same(const AstNode* samep) const override { - const AstEnumItemRef* const sp = static_cast(samep); - return itemp() == sp->itemp(); - } - AstEnumItem* itemp() const { return m_itemp; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } - void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } -}; - -class AstEnumDType final : public AstNodeDType { - // Parents: TYPEDEF/MODULE - // Children: ENUMVALUEs -private: - string m_name; // Name from upper typedef, if any - AstNodeDType* m_refDTypep = nullptr; // Elements are of this type after V3Width - const int m_uniqueNum = 0; - -public: - AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp) - : ASTGEN_SUPER_EnumDType(fl) - , m_uniqueNum{uniqueNumInc()} { - childDTypep(dtp); // Only for parser - refDTypep(nullptr); - addNOp2p(itemsp); - dtypep(nullptr); // V3Width will resolve - widthFromSub(subDTypep()); - } - ASTNODE_NODE_FUNCS(EnumDType) - virtual const char* broken() const override { - BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) - || (!m_refDTypep && childDTypep()))); - return nullptr; - } - virtual void cloneRelink() override { - if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); - } - int uniqueNum() const { return m_uniqueNum; } - virtual bool same(const AstNode* samep) const override { - const AstEnumDType* const sp = static_cast(samep); - return uniqueNum() == sp->uniqueNum(); - } - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } // op1 = Data type - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - // op1 = Range of variable - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } - void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - virtual string name() const override { return m_name; } - virtual void name(const string& flag) override { m_name = flag; } - AstEnumItem* itemsp() const { return VN_AS(op2p(), EnumItem); } // op2 = AstEnumItem's - // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { - return subDTypep()->skipRefToConstp(); - } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - int itemCount() const { - size_t count = 0; - for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++; - return count; - } - virtual bool isCompound() const override { return false; } -}; - -class AstParseTypeDType final : public AstNodeDType { - // Parents: VAR - // During parsing, this indicates the type of a parameter is a "parameter type" - // e.g. the data type is a container of any data type -public: - explicit AstParseTypeDType(FileLine* fl) - : ASTGEN_SUPER_ParseTypeDType(fl) {} - ASTNODE_NODE_FUNCS(ParseTypeDType) - AstNodeDType* dtypep() const { return nullptr; } - // METHODS - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return nullptr; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 0; } - virtual int widthTotalBytes() const override { return 0; } - virtual bool isCompound() const override { - v3fatalSrc("call isCompound on subdata type, not reference"); - return false; - } -}; - -//###################################################################### - -class AstArraySel final : public AstNodeSel { - // Parents: math|stmt - // Children: varref|arraysel, math -private: - void init(AstNode* fromp) { - if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) { - // Strip off array to find what array references - dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep()); - } - } - -public: - AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp) - : ASTGEN_SUPER_ArraySel(fl, fromp, bitp) { - init(fromp); - } - AstArraySel(FileLine* fl, AstNode* fromp, int bit) - : ASTGEN_SUPER_ArraySel(fl, fromp, new AstConst(fl, bit)) { - init(fromp); - } - ASTNODE_NODE_FUNCS(ArraySel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstArraySel(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; /* How can from be a const? */ - } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { return "%li%k[%ri]"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { - return true; - } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - // Special operators - // Return base var (or const) nodep dereferences - static AstNode* baseFromp(AstNode* nodep, bool overMembers); -}; - -class AstAssocSel final : public AstNodeSel { - // Parents: math|stmt - // Children: varref|arraysel, math -private: - void init(AstNode* fromp) { - if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) { - // Strip off array to find what array references - dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep()); - } - } - -public: - AstAssocSel(FileLine* fl, AstNode* fromp, AstNode* bitp) - : ASTGEN_SUPER_AssocSel(fl, fromp, bitp) { - init(fromp); - } - ASTNODE_NODE_FUNCS(AssocSel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssocSel(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { return "%li%k[%ri]"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { - return true; - } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } -}; - -class AstWildcardSel final : public AstNodeSel { - // Parents: math|stmt - // Children: varref|arraysel, math -private: - void init(AstNode* fromp) { - if (fromp && VN_IS(fromp->dtypep()->skipRefp(), WildcardArrayDType)) { - // Strip off array to find what array references - dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), WildcardArrayDType)->subDTypep()); - } - } - -public: - AstWildcardSel(FileLine* fl, AstNode* fromp, AstNode* bitp) - : ASTGEN_SUPER_WildcardSel(fl, fromp, bitp) { - init(fromp); - } - ASTNODE_NODE_FUNCS(WildcardSel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstWildcardSel{this->fileline(), lhsp, rhsp}; - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { return "%li%k[%ri]"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { - return true; - } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } -}; - -class AstWordSel final : public AstNodeSel { - // Select a single word from a multi-word wide value -public: - AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp) - : ASTGEN_SUPER_WordSel(fl, fromp, bitp) { - dtypeSetUInt32(); // Always used on WData arrays so returns edata size - } - ASTNODE_NODE_FUNCS(WordSel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstWordSel(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { - return "%li[%ri]"; - } // Not %k, as usually it's a small constant rhsp - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstSelLoopVars final : public AstNode { - // Parser only concept "[id, id, id]" for a foreach statement - // Unlike normal selects elements is a list -public: - AstSelLoopVars(FileLine* fl, AstNode* fromp, AstNode* elementsp) - : ASTGEN_SUPER_SelLoopVars(fl) { - setOp1p(fromp); - addNOp2p(elementsp); - } - ASTNODE_NODE_FUNCS(SelLoopVars) - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool maybePointedTo() const override { return false; } - AstNode* fromp() const { return op1p(); } - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstNode* elementsp() const { return op2p(); } -}; - -class AstSelExtract final : public AstNodePreSel { - // Range extraction, gets replaced with AstSel -public: - AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp) - : ASTGEN_SUPER_SelExtract(fl, fromp, msbp, lsbp) {} - ASTNODE_NODE_FUNCS(SelExtract) - AstNode* leftp() const { return rhsp(); } - AstNode* rightp() const { return thsp(); } -}; - -class AstSelBit final : public AstNodePreSel { - // Single bit range extraction, perhaps with non-constant selection or array selection - // Gets replaced during link with AstArraySel or AstSel -public: - AstSelBit(FileLine* fl, AstNode* fromp, AstNode* bitp) - : ASTGEN_SUPER_SelBit(fl, fromp, bitp, nullptr) { - UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, - "not coded to create after dtypes resolved"); - } - ASTNODE_NODE_FUNCS(SelBit) - AstNode* bitp() const { return rhsp(); } -}; - -class AstSelPlus final : public AstNodePreSel { - // +: range extraction, perhaps with non-constant selection - // Gets replaced during link with AstSel -public: - AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) - : ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {} - ASTNODE_NODE_FUNCS(SelPlus) - AstNode* bitp() const { return rhsp(); } - AstNode* widthp() const { return thsp(); } -}; - -class AstSelMinus final : public AstNodePreSel { - // -: range extraction, perhaps with non-constant selection - // Gets replaced during link with AstSel -public: - AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) - : ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {} - ASTNODE_NODE_FUNCS(SelMinus) - AstNode* bitp() const { return rhsp(); } - AstNode* widthp() const { return thsp(); } -}; - -class AstSel final : public AstNodeTriop { - // Multiple bit range extraction - // Parents: math|stmt - // Children: varref|arraysel, math, constant math - // Tempting to have an access() style method here as LHS selects are quite - // different, but that doesn't play well with V3Inst and bidirects which don't know direction -private: - VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid - int m_declElWidth; // If a packed array, the number of bits per element -public: - AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp) - : ASTGEN_SUPER_Sel(fl, fromp, lsbp, widthp) - , m_declElWidth{1} { - if (VN_IS(widthp, Const)) { - dtypeSetLogicSized(VN_AS(widthp, Const)->toUInt(), VSigning::UNSIGNED); - } - } - AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth) - : ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth)) - , m_declElWidth{1} { - dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(Sel) - virtual void dump(std::ostream& str) const override; - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, - const V3Number& width) override { - out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt()); - } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { - return widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%lw, %P, %li, %ri)" - : isWide() ? "VL_SEL_%nq%lq%rq%tq(%nw,%lw, %P, %li, %ri, %ti)" - : "VL_SEL_%nq%lq%rq%tq(%lw, %P, %li, %ri, %ti)"; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual bool same(const AstNode*) const override { return true; } - virtual int instrCount() const override { - return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); - } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - AstNode* lsbp() const { return op2p(); } // op2 = Msb selection expression - AstNode* widthp() const { return op3p(); } // op3 = Width - int widthConst() const { return VN_AS(widthp(), Const)->toSInt(); } - int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); } - int msbConst() const { return lsbConst() + widthConst() - 1; } - VNumRange& declRange() { return m_declRange; } - const VNumRange& declRange() const { return m_declRange; } - void declRange(const VNumRange& flag) { m_declRange = flag; } - int declElWidth() const { return m_declElWidth; } - void declElWidth(int flag) { m_declElWidth = flag; } -}; - -class AstSliceSel final : public AstNodeTriop { - // Multiple array element extraction - // Parents: math|stmt - // Children: varref|arraysel, math, constant math -private: - VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid -public: - AstSliceSel(FileLine* fl, AstNode* fromp, const VNumRange& declRange) - : ASTGEN_SUPER_SliceSel(fl, fromp, new AstConst(fl, declRange.lo()), - new AstConst(fl, declRange.elements())) - , m_declRange{declRange} {} - ASTNODE_NODE_FUNCS(SliceSel) - virtual void dump(std::ostream& str) const override; - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, - const V3Number& width) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual bool same(const AstNode*) const override { return true; } - virtual int instrCount() const override { return 10; } // Removed before matters - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods - VNumRange& declRange() { return m_declRange; } - const VNumRange& declRange() const { return m_declRange; } - void declRange(const VNumRange& flag) { m_declRange = flag; } -}; - -class AstMethodCall final : public AstNodeFTaskRef { - // A reference to a member task (or function) - // PARENTS: stmt/math - // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. - // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it -public: - AstMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, - AstNode* pinsp) - : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { - setOp2p(fromp); - dtypep(nullptr); // V3Width will resolve - } - AstMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) - : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { - setOp2p(fromp); - } - ASTNODE_NODE_FUNCS(MethodCall) - virtual const char* broken() const override { - BROKEN_BASE_RTN(AstNodeFTaskRef::broken()); - BROKEN_RTN(!fromp()); - return nullptr; - } - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - void makeStatement() { - statement(true); - dtypeSetVoid(); - } - AstNode* fromp() const { - return op2p(); - } // op2 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp2p(nodep); } -}; - -class AstCMethodHard final : public AstNodeStmt { - // A reference to a "C" hardcoded member task (or function) - // PARENTS: stmt/math - // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. -private: - string m_name; // Name of method - bool m_pure = false; // Pure optimizable -public: - AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, - AstNode* pinsp = nullptr) - : ASTGEN_SUPER_CMethodHard(fl, false) - , m_name{name} { - setOp1p(fromp); - dtypep(nullptr); // V3Width will resolve - addNOp2p(pinsp); - } - AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp = nullptr) - : ASTGEN_SUPER_CMethodHard(fl, false) - , m_name{name} { - setOp1p(fromp); - addNOp2p(pinsp); - } - ASTNODE_NODE_FUNCS(CMethodHard) - virtual string name() const override { return m_name; } // * = Var name - virtual bool hasDType() const override { return true; } - virtual void name(const string& name) override { m_name = name; } - virtual bool same(const AstNode* samep) const override { - const AstCMethodHard* asamep = static_cast(samep); - return (m_name == asamep->m_name); - } - virtual bool isPure() const override { return m_pure; } - void pure(bool flag) { m_pure = flag; } - void makeStatement() { - statement(true); - dtypeSetVoid(); - } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list - void addPinsp(AstNode* nodep) { addOp2p(nodep); } -}; - -class AstVar final : public AstNode { - // A variable (in/out/wire/reg/param) inside a module -private: - string m_name; // Name of variable - string m_origName; // Original name before dot addition - string m_tag; // Holds the string of the verilator tag -- used in XML output. - VVarType m_varType; // Type of variable - VDirection m_direction; // Direction input/output etc - VDirection m_declDirection; // Declared direction input/output etc - VBasicDTypeKwd m_declKwd; // Keyword at declaration time - VLifetime m_lifetime; // Lifetime - VVarAttrClocker m_attrClocker; - MTaskIdSet m_mtaskIds; // MTaskID's that read or write this var - int m_pinNum = 0; // For XML, if non-zero the connection pin number - bool m_ansi : 1; // ANSI port list variable (for dedup check) - bool m_declTyped : 1; // Declared as type (for dedup check) - bool m_tristate : 1; // Inout or triwire or trireg - bool m_primaryIO : 1; // In/out to top level (or directly assigned from same) - bool m_sc : 1; // SystemC variable - bool m_scClocked : 1; // SystemC sc_clk<> needed - bool m_scSensitive : 1; // SystemC sensitive() needed - bool m_sigPublic : 1; // User C code accesses this signal or is top signal - bool m_sigModPublic : 1; // User C code accesses this signal and module - bool m_sigUserRdPublic : 1; // User C code accesses this signal, read only - bool m_sigUserRWPublic : 1; // User C code accesses this signal, read-write - bool m_usedClock : 1; // Signal used as a clock - bool m_usedParam : 1; // Parameter is referenced (on link; later signals not setup) - bool m_usedLoopIdx : 1; // Variable subject of for unrolling - bool m_funcLocal : 1; // Local variable for a function - bool m_funcReturn : 1; // Return variable for a function - bool m_attrClockEn : 1; // User clock enable attribute - bool m_attrScBv : 1; // User force bit vector attribute - bool m_attrIsolateAssign : 1; // User isolate_assignments attribute - bool m_attrSFormat : 1; // User sformat attribute - bool m_attrSplitVar : 1; // declared with split_var metacomment - bool m_fileDescr : 1; // File descriptor - bool m_isRand : 1; // Random variable - bool m_isConst : 1; // Table contains constant data - bool m_isContinuously : 1; // Ever assigned continuously (for force/release) - bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier - bool m_isStatic : 1; // Static C variable (for Verilog see instead isAutomatic) - bool m_isPulldown : 1; // Tri0 - bool m_isPullup : 1; // Tri1 - bool m_isIfaceParent : 1; // dtype is reference to interface present in this module - bool m_isDpiOpenArray : 1; // DPI import open array - bool m_isHideLocal : 1; // Verilog local - bool m_isHideProtected : 1; // Verilog protected - bool m_noReset : 1; // Do not do automated reset/randomization - bool m_noSubst : 1; // Do not substitute out references - bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam - bool m_trace : 1; // Trace this variable - bool m_isLatched : 1; // Not assigned in all control paths of combo always - bool m_isForceable : 1; // May be forced/released externally from user C code - - void init() { - m_ansi = false; - m_declTyped = false; - m_tristate = false; - m_primaryIO = false; - m_sc = false; - m_scClocked = false; - m_scSensitive = false; - m_usedClock = false; - m_usedParam = false; - m_usedLoopIdx = false; - m_sigPublic = false; - m_sigModPublic = false; - m_sigUserRdPublic = false; - m_sigUserRWPublic = false; - m_funcLocal = false; - m_funcReturn = false; - m_attrClockEn = false; - m_attrScBv = false; - m_attrIsolateAssign = false; - m_attrSFormat = false; - m_attrSplitVar = false; - m_fileDescr = false; - m_isRand = false; - m_isConst = false; - m_isContinuously = false; - m_hasStrengthAssignment = false; - m_isStatic = false; - m_isPulldown = false; - m_isPullup = false; - m_isIfaceParent = false; - m_isDpiOpenArray = false; - m_isHideLocal = false; - m_isHideProtected = false; - m_noReset = false; - m_noSubst = false; - m_overridenParam = false; - m_trace = false; - m_isLatched = false; - m_isForceable = false; - m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN; - } - -public: - AstVar(FileLine* fl, VVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_Var(fl) - , m_name{name} - , m_origName{name} { - init(); - combineType(type); - childDTypep(dtp); // Only for parser - dtypep(nullptr); // V3Width will resolve - if (dtp->basicp()) { - m_declKwd = dtp->basicp()->keyword(); - } else { - m_declKwd = VBasicDTypeKwd::LOGIC; - } - } - AstVar(FileLine* fl, VVarType type, const string& name, AstNodeDType* dtp) - : ASTGEN_SUPER_Var(fl) - , m_name{name} - , m_origName{name} { - init(); - combineType(type); - UASSERT(dtp, "AstVar created with no dtype"); - dtypep(dtp); - if (dtp->basicp()) { - m_declKwd = dtp->basicp()->keyword(); - } else { - m_declKwd = VBasicDTypeKwd::LOGIC; - } - } - AstVar(FileLine* fl, VVarType type, const string& name, VFlagLogicPacked, int wantwidth) - : ASTGEN_SUPER_Var(fl) - , m_name{name} - , m_origName{name} { - init(); - combineType(type); - dtypeSetLogicSized(wantwidth, VSigning::UNSIGNED); - m_declKwd = VBasicDTypeKwd::LOGIC; - } - AstVar(FileLine* fl, VVarType type, const string& name, VFlagBitPacked, int wantwidth) - : ASTGEN_SUPER_Var(fl) - , m_name{name} - , m_origName{name} { - init(); - combineType(type); - dtypeSetBitSized(wantwidth, VSigning::UNSIGNED); - m_declKwd = VBasicDTypeKwd::BIT; - } - AstVar(FileLine* fl, VVarType type, const string& name, AstVar* examplep) - : ASTGEN_SUPER_Var(fl) - , m_name{name} - , m_origName{name} { - init(); - combineType(type); - if (examplep->childDTypep()) childDTypep(examplep->childDTypep()->cloneTree(true)); - dtypeFrom(examplep); - m_declKwd = examplep->declKwd(); - } - ASTNODE_NODE_FUNCS(Var) - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual string origName() const override { return m_origName; } // * = Original name - void origName(const string& name) { m_origName = name; } - VVarType varType() const { return m_varType; } // * = Type of variable - void direction(const VDirection& flag) { - m_direction = flag; - if (m_direction == VDirection::INOUT) m_tristate = true; - } - VDirection direction() const { return m_direction; } - bool isIO() const { return m_direction != VDirection::NONE; } - void declDirection(const VDirection& flag) { m_declDirection = flag; } - VDirection declDirection() const { return m_declDirection; } - void varType(VVarType type) { m_varType = type; } - void varType2Out() { - m_tristate = false; - m_direction = VDirection::OUTPUT; - } - void varType2In() { - m_tristate = false; - m_direction = VDirection::INPUT; - } - VBasicDTypeKwd declKwd() const { return m_declKwd; } - string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv - // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc. - string cPubArgType(bool named, bool forReturn) const; - string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument - string dpiTmpVarType(const string& varName) const; - // Return Verilator internal type for argument: CData, SData, IData, WData - string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "", - bool asRef = false) const; - string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc - string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc - string vlPropDecl(const string& propName) const; // Return VerilatorVarProps declaration - void combineType(VVarType type); - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - // op2 = Net delay - AstNode* delayp() const { return op2p(); } - void delayp(AstNode* const nodep) { setNOp2p(nodep); } - AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - // (Slow) recurse down to find basic data type (Note don't need virtual - - // AstVar isn't a NodeDType) - AstBasicDType* basicp() const { return subDTypep()->basicp(); } - // op3 = Initial value that never changes (static const), or constructor argument for - // MTASKSTATE variables - AstNode* valuep() const { return op3p(); } - // It's valuep(), not constp(), as may be more complicated than an AstConst - void valuep(AstNode* nodep) { setOp3p(nodep); } - void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } - AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - void ansi(bool flag) { m_ansi = flag; } - void declTyped(bool flag) { m_declTyped = flag; } - void attrClockEn(bool flag) { m_attrClockEn = flag; } - void attrClocker(VVarAttrClocker flag) { m_attrClocker = flag; } - void attrFileDescr(bool flag) { m_fileDescr = flag; } - void attrScClocked(bool flag) { m_scClocked = flag; } - void attrScBv(bool flag) { m_attrScBv = flag; } - void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } - void attrSFormat(bool flag) { m_attrSFormat = flag; } - void attrSplitVar(bool flag) { m_attrSplitVar = flag; } - void usedClock(bool flag) { m_usedClock = flag; } - void usedParam(bool flag) { m_usedParam = flag; } - void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; } - void sigPublic(bool flag) { m_sigPublic = flag; } - void sigModPublic(bool flag) { m_sigModPublic = flag; } - void sigUserRdPublic(bool flag) { - m_sigUserRdPublic = flag; - if (flag) sigPublic(true); - } - void sigUserRWPublic(bool flag) { - m_sigUserRWPublic = flag; - if (flag) sigUserRdPublic(true); - } - void sc(bool flag) { m_sc = flag; } - void scSensitive(bool flag) { m_scSensitive = flag; } - void primaryIO(bool flag) { m_primaryIO = flag; } - void isRand(bool flag) { m_isRand = flag; } - void isConst(bool flag) { m_isConst = flag; } - void isContinuously(bool flag) { m_isContinuously = flag; } - void isStatic(bool flag) { m_isStatic = flag; } - void isIfaceParent(bool flag) { m_isIfaceParent = flag; } - void funcLocal(bool flag) { m_funcLocal = flag; } - void funcReturn(bool flag) { m_funcReturn = flag; } - void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; } - bool hasStrengthAssignment() { return m_hasStrengthAssignment; } - void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; } - bool isDpiOpenArray() const { return m_isDpiOpenArray; } - bool isHideLocal() const { return m_isHideLocal; } - void isHideLocal(bool flag) { m_isHideLocal = flag; } - bool isHideProtected() const { return m_isHideProtected; } - void isHideProtected(bool flag) { m_isHideProtected = flag; } - void noReset(bool flag) { m_noReset = flag; } - bool noReset() const { return m_noReset; } - void noSubst(bool flag) { m_noSubst = flag; } - bool noSubst() const { return m_noSubst; } - void overriddenParam(bool flag) { m_overridenParam = flag; } - bool overriddenParam() const { return m_overridenParam; } - void trace(bool flag) { m_trace = flag; } - void isLatched(bool flag) { m_isLatched = flag; } - bool isForceable() const { return m_isForceable; } - void setForceable() { m_isForceable = true; } - // METHODS - virtual void name(const string& name) override { m_name = name; } - virtual void tag(const string& text) override { m_tag = text; } - virtual string tag() const override { return m_tag; } - bool isAnsi() const { return m_ansi; } - bool isContinuously() const { return m_isContinuously; } - bool isDeclTyped() const { return m_declTyped; } - bool isInoutish() const { return m_direction.isInoutish(); } - bool isNonOutput() const { return m_direction.isNonOutput(); } - bool isReadOnly() const { return m_direction.isReadOnly(); } - bool isWritable() const { return m_direction.isWritable(); } - bool isTristate() const { return m_tristate; } - bool isPrimaryIO() const { return m_primaryIO; } - bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); } - bool isIfaceRef() const { return (varType() == VVarType::IFACEREF); } - bool isIfaceParent() const { return m_isIfaceParent; } - bool isSignal() const { return varType().isSignal(); } - bool isNet() const { return varType().isNet(); } - bool isTemp() const { return varType().isTemp(); } - bool isToggleCoverable() const { - return ((isIO() || isSignal()) - && (isIO() || isBitLogic()) - // Wrapper would otherwise duplicate wrapped module's coverage - && !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString()); - } - bool isClassMember() const { return varType() == VVarType::MEMBER; } - bool isStatementTemp() const { return (varType() == VVarType::STMTTEMP); } - bool isXTemp() const { return (varType() == VVarType::XTEMP); } - bool isParam() const { - return (varType() == VVarType::LPARAM || varType() == VVarType::GPARAM); - } - bool isGParam() const { return (varType() == VVarType::GPARAM); } - bool isGenVar() const { return (varType() == VVarType::GENVAR); } - bool isBitLogic() const { - AstBasicDType* bdtypep = basicp(); - return bdtypep && bdtypep->isBitLogic(); - } - bool isUsedClock() const { return m_usedClock; } - bool isUsedParam() const { return m_usedParam; } - bool isUsedLoopIdx() const { return m_usedLoopIdx; } - bool isSc() const { return m_sc; } - bool isScQuad() const; - bool isScBv() const; - bool isScUint() const; - bool isScBigUint() const; - bool isScSensitive() const { return m_scSensitive; } - bool isSigPublic() const; - bool isSigModPublic() const { return m_sigModPublic; } - bool isSigUserRdPublic() const { return m_sigUserRdPublic; } - bool isSigUserRWPublic() const { return m_sigUserRWPublic; } - bool isTrace() const { return m_trace; } - bool isRand() const { return m_isRand; } - bool isConst() const { return m_isConst; } - bool isStatic() const { return m_isStatic; } - bool isLatched() const { return m_isLatched; } - bool isFuncLocal() const { return m_funcLocal; } - bool isFuncReturn() const { return m_funcReturn; } - bool isPullup() const { return m_isPullup; } - bool isPulldown() const { return m_isPulldown; } - bool attrClockEn() const { return m_attrClockEn; } - bool attrScBv() const { return m_attrScBv; } - bool attrFileDescr() const { return m_fileDescr; } - bool attrScClocked() const { return m_scClocked; } - bool attrSFormat() const { return m_attrSFormat; } - bool attrSplitVar() const { return m_attrSplitVar; } - bool attrIsolateAssign() const { return m_attrIsolateAssign; } - VVarAttrClocker attrClocker() const { return m_attrClocker; } - virtual string verilogKwd() const override; - void lifetime(const VLifetime& flag) { m_lifetime = flag; } - VLifetime lifetime() const { return m_lifetime; } - void propagateAttrFrom(AstVar* fromp) { - // This is getting connected to fromp; keep attributes - // Note the method below too - if (fromp->attrClockEn()) attrClockEn(true); - if (fromp->attrFileDescr()) attrFileDescr(true); - if (fromp->attrIsolateAssign()) attrIsolateAssign(true); - if (fromp->isContinuously()) isContinuously(true); - } - bool gateMultiInputOptimizable() const { - // Ok to gate optimize; must return false if propagateAttrFrom would do anything - return (!attrClockEn() && !isUsedClock()); - } - void combineType(AstVar* typevarp) { - // This is same as typevarp (for combining input & reg decls) - // "this" is the input var. typevarp is the reg var. - propagateAttrFrom(typevarp); - combineType(typevarp->varType()); - if (typevarp->isSigPublic()) sigPublic(true); - if (typevarp->isSigModPublic()) sigModPublic(true); - if (typevarp->isSigUserRdPublic()) sigUserRdPublic(true); - if (typevarp->isSigUserRWPublic()) sigUserRWPublic(true); - if (typevarp->attrScClocked()) attrScClocked(true); - } - void inlineAttrReset(const string& name) { - if (direction() == VDirection::INOUT && varType() == VVarType::WIRE) { - m_varType = VVarType::TRIWIRE; - } - m_direction = VDirection::NONE; - m_name = name; - } - static AstVar* scVarRecurse(AstNode* nodep); - void addProducingMTaskId(int id) { m_mtaskIds.insert(id); } - void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); } - const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } - void pinNum(int id) { m_pinNum = id; } - int pinNum() const { return m_pinNum; } -}; - -class AstDefParam final : public AstNode { - // A defparam assignment - // Parents: MODULE - // Children: math -private: - string m_name; // Name of variable getting set - string m_path; // Dotted cellname to set parameter of -public: - AstDefParam(FileLine* fl, const string& path, const string& name, AstNode* rhsp) - : ASTGEN_SUPER_DefParam(fl) { - setOp1p(rhsp); - m_name = name; - m_path = path; - } - virtual string name() const override { return m_name; } // * = Scope name - ASTNODE_NODE_FUNCS(DefParam) - virtual bool same(const AstNode*) const override { return true; } - AstNode* rhsp() const { return op1p(); } // op1 = Assign from - string path() const { return m_path; } -}; - -class AstImplicit final : public AstNode { - // Create implicit wires and do nothing else, for gates that are ignored - // Parents: MODULE -public: - AstImplicit(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_Implicit(fl) { - addNOp1p(exprsp); - } - ASTNODE_NODE_FUNCS(Implicit) - AstNode* exprsp() const { return op1p(); } // op1 = Assign from -}; - -class AstScope final : public AstNode { - // A particular usage of a cell - // Parents: MODULE - // Children: NODEBLOCK -private: - // An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope - string m_name; // Name - AstScope* const m_aboveScopep; // Scope above this one in the hierarchy (nullptr if top) - AstCell* const m_aboveCellp; // Cell above this in the hierarchy (nullptr if top) - AstNodeModule* const m_modp; // Module scope corresponds to -public: - AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep, - AstCell* aboveCellp) - : ASTGEN_SUPER_Scope(fl) - , m_name{name} - , m_aboveScopep{aboveScopep} - , m_aboveCellp{aboveCellp} - , m_modp{modp} {} - ASTNODE_NODE_FUNCS(Scope) - virtual void cloneRelink() override; - virtual const char* broken() const override; - virtual bool maybePointedTo() const override { return true; } - virtual string name() const override { return m_name; } // * = Scope name - virtual void name(const string& name) override { m_name = name; } - virtual void dump(std::ostream& str) const override; - string nameDotless() const; - string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); } - AstNodeModule* modp() const { return m_modp; } - void addVarp(AstVarScope* nodep) { addOp1p((AstNode*)nodep); } - AstVarScope* varsp() const { return VN_AS(op1p(), VarScope); } // op1 = AstVarScope's - void addActivep(AstNode* nodep) { addOp2p(nodep); } - AstNode* blocksp() const { return op2p(); } // op2 = Block names - void addFinalClkp(AstNode* nodep) { addOp3p(nodep); } - AstNode* finalClksp() const { return op3p(); } // op3 = Final assigns for clock correction - AstScope* aboveScopep() const { return m_aboveScopep; } - AstCell* aboveCellp() const { return m_aboveCellp; } - bool isTop() const { return aboveScopep() == nullptr; } // At top of hierarchy -}; - -class AstTopScope final : public AstNode { - // A singleton, held under the top level AstModule. Holds the top level AstScope, - // and after V3ActiveTop, the global list of AstSenTrees (list of unique sensitivity lists). - // Parent: Top level AstModule - // Children: AstSenTree, AstScope - friend class AstNetlist; // Only the AstNetlist can create one - AstTopScope(FileLine* fl, AstScope* ascopep) - : ASTGEN_SUPER_TopScope(fl) { - addOp2p(ascopep); - } - -public: - ASTNODE_NODE_FUNCS(TopScope) - virtual bool maybePointedTo() const override { return true; } - AstSenTree* senTreesp() const { return VN_AS(op1p(), SenTree); } - void addSenTreep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } - AstScope* scopep() const { return VN_AS(op2p(), Scope); } -}; - -class AstVarScope final : public AstNode { - // A particular scoped usage of a variable - // That is, as a module is used under multiple cells, we get a different - // varscope for each var in the module - // Parents: MODULE - // Children: none -private: - AstScope* m_scopep; // Scope variable is underneath - AstVar* m_varp; // [AfterLink] Pointer to variable itself - bool m_circular : 1; // Used in circular ordering dependency, need change detect - bool m_trace : 1; // Tracing is turned on for this scope -public: - AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp) - : ASTGEN_SUPER_VarScope(fl) - , m_scopep{scopep} - , m_varp{varp} { - UASSERT_OBJ(scopep, fl, "Scope must be non-null"); - UASSERT_OBJ(varp, fl, "Var must be non-null"); - m_circular = false; - m_trace = true; - dtypeFrom(varp); - } - ASTNODE_NODE_FUNCS(VarScope) - virtual void cloneRelink() override { - if (m_varp && m_varp->clonep()) { - m_varp = m_varp->clonep(); - UASSERT(m_scopep->clonep(), "No clone cross link: " << this); - m_scopep = m_scopep->clonep(); - } - } - virtual const char* broken() const override { - BROKEN_RTN(m_varp && !m_varp->brokeExists()); - BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); - return nullptr; - } - virtual bool maybePointedTo() const override { return true; } - virtual string name() const override { return scopep()->name() + "->" + varp()->name(); } - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable - AstScope* scopep() const { return m_scopep; } // Pointer to scope it's under - void scopep(AstScope* nodep) { m_scopep = nodep; } - bool isCircular() const { return m_circular; } - void circular(bool flag) { m_circular = flag; } - bool isTrace() const { return m_trace; } - void trace(bool flag) { m_trace = flag; } -}; - -class AstVarRef final : public AstNodeVarRef { - // A reference to a variable (lvalue or rvalue) -public: - AstVarRef(FileLine* fl, const string& name, const VAccess& access) - : ASTGEN_SUPER_VarRef(fl, name, nullptr, access) {} - // This form only allowed post-link because output/wire compression may - // lead to deletion of AstVar's - AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access) - : ASTGEN_SUPER_VarRef(fl, varp->name(), varp, access) {} - // This form only allowed post-link (see above) - AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access) - : ASTGEN_SUPER_VarRef(fl, varscp->varp()->name(), varscp->varp(), access) { - varScopep(varscp); - } - ASTNODE_NODE_FUNCS(VarRef) - virtual void dump(std::ostream& str) const override; - virtual bool same(const AstNode* samep) const override { - return same(static_cast(samep)); - } - inline bool same(const AstVarRef* samep) const { - if (varScopep()) { - return (varScopep() == samep->varScopep() && access() == samep->access()); - } else { - return (selfPointer() == samep->selfPointer() - && varp()->name() == samep->varp()->name() && access() == samep->access()); - } - } - inline bool sameNoLvalue(AstVarRef* samep) const { - if (varScopep()) { - return (varScopep() == samep->varScopep()); - } else { - return (selfPointer() == samep->selfPointer() - && (!selfPointer().empty() || !samep->selfPointer().empty()) - && varp()->name() == samep->varp()->name()); - } - } - virtual int instrCount() const override { - return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1); - } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } -}; - -class AstVarXRef final : public AstNodeVarRef { - // A VarRef to something in another module before AstScope. - // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope -private: - string m_dotted; // Dotted part of scope the name()'ed reference is under or "" - string m_inlinedDots; // Dotted hierarchy flattened out -public: - AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access) - : ASTGEN_SUPER_VarXRef(fl, name, nullptr, access) - , m_dotted{dotted} {} - AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access) - : ASTGEN_SUPER_VarXRef(fl, varp->name(), varp, access) - , m_dotted{dotted} { - dtypeFrom(varp); - } - ASTNODE_NODE_FUNCS(VarXRef) - virtual void dump(std::ostream& str) const override; - string dotted() const { return m_dotted; } - void dotted(const string& dotted) { m_dotted = dotted; } - string inlinedDots() const { return m_inlinedDots; } - void inlinedDots(const string& flag) { m_inlinedDots = flag; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode* samep) const override { - const AstVarXRef* asamep = static_cast(samep); - return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp() - && name() == asamep->name() && dotted() == asamep->dotted()); - } -}; - -class AstAddrOfCFunc final : public AstNodeMath { - // Get address of CFunc -private: - AstCFunc* m_funcp; // Pointer to function itself - -public: - AstAddrOfCFunc(FileLine* fl, AstCFunc* funcp) - : ASTGEN_SUPER_AddrOfCFunc(fl) - , m_funcp{funcp} { - dtypep(findCHandleDType()); - } - -public: - ASTNODE_NODE_FUNCS(AddrOfCFunc) - virtual void cloneRelink() override; - virtual const char* broken() const override; - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - AstCFunc* funcp() const { return m_funcp; } -}; - -class AstPin final : public AstNode { - // A pin on a cell -private: - int m_pinNum; // Pin number - string m_name; // Pin name, or "" for number based interconnect - AstVar* m_modVarp = nullptr; // Input/output this pin connects to on submodule. - AstParamTypeDType* m_modPTypep = nullptr; // Param type this pin connects to on submodule. - bool m_param = false; // Pin connects to parameter - bool m_svImplicit = false; // Pin is SystemVerilog .name'ed -public: - AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) - : ASTGEN_SUPER_Pin(fl) - , m_pinNum{pinNum} - , m_name{name} { - setNOp1p(exprp); - } - AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) - : ASTGEN_SUPER_Pin(fl) - , m_pinNum{pinNum} - , m_name{varname->name()} { - setNOp1p(exprp); - } - ASTNODE_NODE_FUNCS(Pin) - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { - BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); - BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists()); - return nullptr; - } - virtual string name() const override { return m_name; } // * = Pin name, ""=go by number - virtual void name(const string& name) override { m_name = name; } - virtual string prettyOperatorName() const override { - return modVarp() - ? ((modVarp()->direction().isAny() ? modVarp()->direction().prettyName() + " " - : "") - + "port connection " + modVarp()->prettyNameQ()) - : "port connection"; - } - bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked - int pinNum() const { return m_pinNum; } - void exprp(AstNode* nodep) { addOp1p(nodep); } - // op1 = Expression connected to pin, nullptr if unconnected - AstNode* exprp() const { return op1p(); } - AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable - void modVarp(AstVar* nodep) { m_modVarp = nodep; } - // [After Link] Pointer to variable - AstParamTypeDType* modPTypep() const { return m_modPTypep; } - void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; } - bool param() const { return m_param; } - void param(bool flag) { m_param = flag; } - bool svImplicit() const { return m_svImplicit; } - void svImplicit(bool flag) { m_svImplicit = flag; } -}; - -class AstArg final : public AstNode { - // An argument to a function/task -private: - string m_name; // Pin name, or "" for number based interconnect -public: - AstArg(FileLine* fl, const string& name, AstNode* exprp) - : ASTGEN_SUPER_Arg(fl) - , m_name{name} { - setNOp1p(exprp); - } - ASTNODE_NODE_FUNCS(Arg) - virtual string name() const override { return m_name; } // * = Pin name, ""=go by number - virtual void name(const string& name) override { m_name = name; } - void exprp(AstNode* nodep) { addOp1p(nodep); } - // op1 = Expression connected to pin, nullptr if unconnected - AstNode* exprp() const { return op1p(); } - bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } -}; - -class AstModule final : public AstNodeModule { - // A module declaration -private: - const bool m_isProgram; // Module represents a program -public: - AstModule(FileLine* fl, const string& name, bool program = false) - : ASTGEN_SUPER_Module(fl, name) - , m_isProgram{program} {} - ASTNODE_NODE_FUNCS(Module) - virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; } - virtual bool timescaleMatters() const override { return true; } -}; - -class AstNotFoundModule final : public AstNodeModule { - // A missing module declaration -public: - AstNotFoundModule(FileLine* fl, const string& name) - : ASTGEN_SUPER_NotFoundModule(fl, name) {} - ASTNODE_NODE_FUNCS(NotFoundModule) - virtual string verilogKwd() const override { return "/*not-found-*/ module"; } - virtual bool timescaleMatters() const override { return false; } -}; - -class AstPackage final : public AstNodeModule { - // A package declaration -public: - AstPackage(FileLine* fl, const string& name) - : ASTGEN_SUPER_Package(fl, name) {} - ASTNODE_NODE_FUNCS(Package) - virtual string verilogKwd() const override { return "package"; } - virtual bool timescaleMatters() const override { return !isDollarUnit(); } - static string dollarUnitName() { return AstNode::encodeName("$unit"); } - bool isDollarUnit() const { return name() == dollarUnitName(); } -}; - -class AstPrimitive final : public AstNodeModule { - // A primitive declaration -public: - AstPrimitive(FileLine* fl, const string& name) - : ASTGEN_SUPER_Primitive(fl, name) {} - ASTNODE_NODE_FUNCS(Primitive) - virtual string verilogKwd() const override { return "primitive"; } - virtual bool timescaleMatters() const override { return false; } -}; - -class AstPackageExportStarStar final : public AstNode { - // A package export *::* declaration -public: - // cppcheck-suppress noExplicitConstructor - AstPackageExportStarStar(FileLine* fl) - : ASTGEN_SUPER_PackageExportStarStar(fl) {} - ASTNODE_NODE_FUNCS(PackageExportStarStar) -}; - -class AstPackageExport final : public AstNode { -private: - // A package export declaration - string m_name; - AstPackage* m_packagep; // Package hierarchy -public: - AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name) - : ASTGEN_SUPER_PackageExport(fl) - , m_name{name} - , m_packagep{packagep} {} - ASTNODE_NODE_FUNCS(PackageExport) - virtual const char* broken() const override { - BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - AstPackage* packagep() const { return m_packagep; } - void packagep(AstPackage* nodep) { m_packagep = nodep; } -}; - -class AstPackageImport final : public AstNode { -private: - // A package import declaration - string m_name; - AstPackage* m_packagep; // Package hierarchy -public: - AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name) - : ASTGEN_SUPER_PackageImport(fl) - , m_name{name} - , m_packagep{packagep} {} - ASTNODE_NODE_FUNCS(PackageImport) - virtual const char* broken() const override { - BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - AstPackage* packagep() const { return m_packagep; } - void packagep(AstPackage* nodep) { m_packagep = nodep; } -}; - -class AstIface final : public AstNodeModule { - // A module declaration -public: - AstIface(FileLine* fl, const string& name) - : ASTGEN_SUPER_Iface(fl, name) {} - ASTNODE_NODE_FUNCS(Iface) - // Interfaces have `timescale applicability but lots of code seems to - // get false warnings if we enable this - virtual string verilogKwd() const override { return "interface"; } - virtual bool timescaleMatters() const override { return false; } -}; - -class AstMemberSel final : public AstNodeMath { - // Parents: math|stmt - // Children: varref|arraysel, math -private: - // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it - string m_name; - AstVar* m_varp = nullptr; // Post link, variable within class that is target of selection -public: - AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name) - : ASTGEN_SUPER_MemberSel(fl) - , m_name{name} { - setOp1p(fromp); - dtypep(nullptr); // V3Width will resolve - } - AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp) - : ASTGEN_SUPER_MemberSel(fl) - , m_name{dtp->name()} { - setOp1p(fromp); - dtypep(dtp); - } - ASTNODE_NODE_FUNCS(MemberSel) - virtual void cloneRelink() override { - if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); - } - virtual const char* broken() const override { - BROKEN_RTN(m_varp && !m_varp->brokeExists()); - return nullptr; - } - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return true; - } // dtype comparison does it - virtual int instrCount() const override { return widthInstrs(); } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstVar* varp() const { return m_varp; } - void varp(AstVar* nodep) { m_varp = nodep; } -}; - -class AstModportFTaskRef final : public AstNode { - // An import/export referenced under a modport - // The storage for the function itself is inside the - // interface/instantiator, thus this is a reference - // PARENT: AstModport -private: - string m_name; // Name of the variable referenced - bool m_export; // Type of the function (import/export) - AstNodeFTask* m_ftaskp = nullptr; // Link to the function -public: - AstModportFTaskRef(FileLine* fl, const string& name, bool isExport) - : ASTGEN_SUPER_ModportFTaskRef(fl) - , m_name{name} - , m_export{isExport} {} - ASTNODE_NODE_FUNCS(ModportFTaskRef) - virtual const char* broken() const override { - BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists()); - return nullptr; - } - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - virtual void cloneRelink() override { - if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep(); - } - bool isImport() const { return !m_export; } - bool isExport() const { return m_export; } - AstNodeFTask* ftaskp() const { return m_ftaskp; } // [After Link] Pointer to variable - void ftaskp(AstNodeFTask* ftaskp) { m_ftaskp = ftaskp; } -}; - -class AstModportVarRef final : public AstNode { - // A input/output/etc variable referenced under a modport - // The storage for the variable itself is inside the interface, thus this is a reference - // PARENT: AstModport -private: - string m_name; // Name of the variable referenced - VDirection m_direction; // Direction of the variable (in/out) - AstVar* m_varp = nullptr; // Link to the actual Var -public: - AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction) - : ASTGEN_SUPER_ModportVarRef(fl) - , m_name{name} - , m_direction{direction} {} - ASTNODE_NODE_FUNCS(ModportVarRef) - virtual const char* broken() const override { - BROKEN_RTN(m_varp && !m_varp->brokeExists()); - return nullptr; - } - virtual void dump(std::ostream& str) const override; - virtual void cloneRelink() override { - if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); - } - virtual string name() const override { return m_name; } - void direction(const VDirection& flag) { m_direction = flag; } - VDirection direction() const { return m_direction; } - AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable - void varp(AstVar* varp) { m_varp = varp; } -}; - -class AstModport final : public AstNode { - // A modport in an interface -private: - string m_name; // Name of the modport -public: - AstModport(FileLine* fl, const string& name, AstNode* varsp) - : ASTGEN_SUPER_Modport(fl) - , m_name{name} { - addNOp1p(varsp); - } - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - ASTNODE_NODE_FUNCS(Modport) - AstNode* varsp() const { return op1p(); } // op1 = List of Vars -}; - -class AstIntfRef final : public AstNode { - // An interface reference -private: - string m_name; // Name of the reference -public: - AstIntfRef(FileLine* fl, const string& name) - : ASTGEN_SUPER_IntfRef(fl) - , m_name{name} {} - virtual string name() const override { return m_name; } - ASTNODE_NODE_FUNCS(IntfRef) -}; - -class AstCell final : public AstNode { - // A instantiation cell or interface call (don't know which until link) -private: - FileLine* m_modNameFileline; // Where module the cell instances token was - string m_name; // Cell name - string m_origName; // Original name before dot addition - string m_modName; // Module the cell instances - AstNodeModule* m_modp = nullptr; // [AfterLink] Pointer to module instanced - bool m_hasIfaceVar : 1; // True if a Var has been created for this cell - bool m_recursive : 1; // Self-recursive module - bool m_trace : 1; // Trace this cell -public: - AstCell(FileLine* fl, FileLine* mfl, const string& instName, const string& modName, - AstPin* pinsp, AstPin* paramsp, AstRange* rangep) - : ASTGEN_SUPER_Cell(fl) - , m_modNameFileline{mfl} - , m_name{instName} - , m_origName{instName} - , m_modName{modName} - , m_hasIfaceVar{false} - , m_recursive{false} - , m_trace{true} { - addNOp1p(pinsp); - addNOp2p(paramsp); - setNOp3p(rangep); - } - ASTNODE_NODE_FUNCS(Cell) - // No cloneRelink, we presume cloneee's want the same module linkages - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { - BROKEN_RTN(m_modp && !m_modp->brokeExists()); - return nullptr; - } - virtual bool maybePointedTo() const override { return true; } - // ACCESSORS - virtual string name() const override { return m_name; } // * = Cell name - virtual void name(const string& name) override { m_name = name; } - virtual string origName() const override { return m_origName; } // * = Original name - void origName(const string& name) { m_origName = name; } - string modName() const { return m_modName; } // * = Instance name - void modName(const string& name) { m_modName = name; } - FileLine* modNameFileline() const { return m_modNameFileline; } - AstPin* pinsp() const { return VN_AS(op1p(), Pin); } // op1 = List of cell ports - // op2 = List of parameter #(##) values - AstPin* paramsp() const { return VN_AS(op2p(), Pin); } - // op3 = Range of arrayed instants (nullptr=not ranged) - AstRange* rangep() const { return VN_AS(op3p(), Range); } - // op4 = List of interface references - AstIntfRef* intfRefp() const { return VN_AS(op4p(), IntfRef); } - AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated - void addPinsp(AstPin* nodep) { addOp1p(nodep); } - void addParamsp(AstPin* nodep) { addOp2p(nodep); } - void addIntfRefp(AstIntfRef* nodep) { addOp4p(nodep); } - void modp(AstNodeModule* nodep) { m_modp = nodep; } - bool hasIfaceVar() const { return m_hasIfaceVar; } - void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; } - void trace(bool flag) { m_trace = flag; } - bool isTrace() const { return m_trace; } - void recursive(bool flag) { m_recursive = flag; } - bool recursive() const { return m_recursive; } -}; - -class AstCellInline final : public AstNode { - // A instantiation cell that was removed by inlining - // For communication between V3Inline and V3LinkDot, - // except for VPI runs where it exists until the end. - // It is augmented with the scope in V3Scope for VPI. - // Children: When 2 levels inlined, other CellInline under this -private: - string m_name; // Cell name, possibly {a}__DOT__{b}... - const string - m_origModName; // Original name of the module, ignoring name() changes, for dot lookup - AstScope* m_scopep = nullptr; // The scope that the cell is inlined into - VTimescale m_timeunit; // Parent module time unit -public: - AstCellInline(FileLine* fl, const string& name, const string& origModName, - const VTimescale& timeunit) - : ASTGEN_SUPER_CellInline(fl) - , m_name{name} - , m_origModName{origModName} - , m_timeunit{timeunit} {} - ASTNODE_NODE_FUNCS(CellInline) - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { - BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); - return nullptr; - } - // ACCESSORS - virtual string name() const override { return m_name; } // * = Cell name - string origModName() const { return m_origModName; } // * = modp()->origName() before inlining - virtual void name(const string& name) override { m_name = name; } - void scopep(AstScope* scp) { m_scopep = scp; } - AstScope* scopep() const { return m_scopep; } - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } -}; - -class AstCellRef final : public AstNode { - // As-of-yet unlinkable reference into a cell -private: - string m_name; // Cell name -public: - AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp) - : ASTGEN_SUPER_CellRef(fl) - , m_name{name} { - addNOp1p(cellp); - addNOp2p(exprp); - } - ASTNODE_NODE_FUNCS(CellRef) - // ACCESSORS - virtual string name() const override { return m_name; } // * = Array name - AstNode* cellp() const { return op1p(); } // op1 = Cell - AstNode* exprp() const { return op2p(); } // op2 = Expression -}; - -class AstCellArrayRef final : public AstNode { - // As-of-yet unlinkable reference into an array of cells -private: - string m_name; // Array name -public: - AstCellArrayRef(FileLine* fl, const string& name, AstNode* selectExprp) - : ASTGEN_SUPER_CellArrayRef(fl) - , m_name{name} { - addNOp1p(selectExprp); - } - ASTNODE_NODE_FUNCS(CellArrayRef) - // ACCESSORS - virtual string name() const override { return m_name; } // * = Array name - AstNode* selp() const { return op1p(); } // op1 = Select expression -}; - -class AstUnlinkedRef final : public AstNode { - // As-of-yet unlinkable Ref -private: - string m_name; // Var name -public: - AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* crp) - : ASTGEN_SUPER_UnlinkedRef(fl) - , m_name{name} { - addNOp1p(refp); - addNOp2p(crp); - } - ASTNODE_NODE_FUNCS(UnlinkedRef) - // ACCESSORS - virtual string name() const override { return m_name; } // * = Var name - AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef - AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef -}; - -class AstBind final : public AstNode { - // Parents: MODULE - // Children: CELL -private: - string m_name; // Binding to name -public: - AstBind(FileLine* fl, const string& name, AstNode* cellsp) - : ASTGEN_SUPER_Bind(fl) - , m_name{name} { - UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound"); - addNOp1p(cellsp); - } - ASTNODE_NODE_FUNCS(Bind) - // ACCESSORS - virtual string name() const override { return m_name; } // * = Bind Target name - virtual void name(const string& name) override { m_name = name; } - AstNode* cellsp() const { return op1p(); } // op1 = cells -}; - -class AstPort final : public AstNode { - // A port (in/out/inout) on a module -private: - int m_pinNum; // Pin number - string m_name; // Name of pin -public: - AstPort(FileLine* fl, int pinnum, const string& name) - : ASTGEN_SUPER_Port(fl) - , m_pinNum{pinnum} - , m_name{name} {} - ASTNODE_NODE_FUNCS(Port) - virtual string name() const override { return m_name; } // * = Port name - int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation - AstNode* exprp() const { return op1p(); } // op1 = Expression connected to port -}; - -//###################################################################### - -class AstParseRef final : public AstNode { - // A reference to a variable, function or task - // We don't know which at parse time due to bison constraints - // The link stages will replace this with AstVarRef, or AstTaskRef, etc. - // Parents: math|stmt - // Children: TEXT|DOT|SEL*|TASK|FUNC (or expression under sel) -private: - VParseRefExp m_expect; // Type we think it should resolve to - string m_name; - -public: - AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, AstNode* lhsp = nullptr, - AstNodeFTaskRef* ftaskrefp = nullptr) - : ASTGEN_SUPER_ParseRef(fl) - , m_expect{expect} - , m_name{name} { - setNOp1p(lhsp); - setNOp2p(ftaskrefp); - } - ASTNODE_NODE_FUNCS(ParseRef) - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool same(const AstNode* samep) const override { - const AstParseRef* const asamep = static_cast(samep); - return (expect() == asamep->expect() && m_name == asamep->m_name); - } - virtual void name(const string& name) override { m_name = name; } - VParseRefExp expect() const { return m_expect; } - void expect(VParseRefExp exp) { m_expect = exp; } - // op1 = Components - AstNode* lhsp() const { return op1p(); } // op1 = List of statements - AstNode* ftaskrefp() const { return op2p(); } // op2 = Function/task reference - void ftaskrefp(AstNodeFTaskRef* nodep) { setNOp2p(nodep); } // op2 = Function/task reference -}; - -class AstClassOrPackageRef final : public AstNode { -private: - string m_name; - // Node not NodeModule to appease some early parser usage - AstNode* m_classOrPackageNodep; // Package hierarchy -public: - AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep, - AstNode* paramsp) - : ASTGEN_SUPER_ClassOrPackageRef(fl) - , m_name{name} - , m_classOrPackageNodep{classOrPackageNodep} { - addNOp4p(paramsp); - } - ASTNODE_NODE_FUNCS(ClassOrPackageRef) - // METHODS - virtual const char* broken() const override { - BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_classOrPackageNodep && m_classOrPackageNodep->clonep()) { - m_classOrPackageNodep = m_classOrPackageNodep->clonep(); - } - } - virtual bool same(const AstNode* samep) const override { - return (m_classOrPackageNodep - == static_cast(samep)->m_classOrPackageNodep); - } - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } // * = Var name - AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } - void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } - AstNodeModule* classOrPackagep() const { - AstNode* foundp = m_classOrPackageNodep; - while (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep(); - if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp(); - return VN_CAST(foundp, NodeModule); - } - AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); } - void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = nodep; } - AstPin* paramsp() const { return VN_AS(op4p(), Pin); } -}; - -class AstDot final : public AstNode { - // A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef - // These are eliminated in the link stage - const bool m_colon; // Is a "::" instead of a "." (lhs must be package/class) -public: - AstDot(FileLine* fl, bool colon, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Dot(fl) - , m_colon{colon} { - setOp1p(lhsp); - setOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(Dot) - // For parser, make only if non-null package - static AstNode* newIfPkg(FileLine* fl, AstNode* packageOrClassp, AstNode* rhsp) { - if (!packageOrClassp) return rhsp; - return new AstDot(fl, true, packageOrClassp, rhsp); - } - virtual void dump(std::ostream& str) const override; - AstNode* lhsp() const { return op1p(); } - void rhsp(AstNode* nodep) { setOp2p(nodep); } - AstNode* rhsp() const { return op2p(); } - bool colon() const { return m_colon; } -}; - -class AstUnbounded final : public AstNodeMath { - // A $ in the parser, used for unbounded and queues - // Due to where is used, treated as Signed32 -public: - explicit AstUnbounded(FileLine* fl) - : ASTGEN_SUPER_Unbounded(fl) { - dtypeSetSigned32(); - } - ASTNODE_NODE_FUNCS(Unbounded) - virtual string emitVerilog() override { return "$"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } -}; - -//###################################################################### - -class AstTask final : public AstNodeFTask { - // A task inside a module -public: - AstTask(FileLine* fl, const string& name, AstNode* stmtp) - : ASTGEN_SUPER_Task(fl, name, stmtp) {} - ASTNODE_NODE_FUNCS(Task) -}; - -class AstFunc final : public AstNodeFTask { - // A function inside a module -public: - AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp) - : ASTGEN_SUPER_Func(fl, name, stmtp) { - addNOp1p(fvarsp); - } - ASTNODE_NODE_FUNCS(Func) - virtual bool hasDType() const override { return true; } -}; - -class AstTaskRef final : public AstNodeFTaskRef { - // A reference to a task -public: - AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) - : ASTGEN_SUPER_TaskRef(fl, true, namep, pinsp) { - statement(true); - } - AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp) - : ASTGEN_SUPER_TaskRef(fl, true, name, pinsp) {} - ASTNODE_NODE_FUNCS(TaskRef) -}; - -class AstFuncRef final : public AstNodeFTaskRef { - // A reference to a function -public: - AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp) - : ASTGEN_SUPER_FuncRef(fl, false, namep, pinsp) {} - AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) - : ASTGEN_SUPER_FuncRef(fl, false, name, pinsp) {} - ASTNODE_NODE_FUNCS(FuncRef) - virtual bool hasDType() const override { return true; } -}; - -class AstDpiExport final : public AstNode { - // We could put an AstNodeFTaskRef instead of the verilog function name, - // however we're not *calling* it, so that seems somehow wrong. - // (Probably AstNodeFTaskRef should be renamed AstNodeFTaskCall and have-a AstNodeFTaskRef) -private: - string m_name; // Name of function - string m_cname; // Name of function on c side -public: - AstDpiExport(FileLine* fl, const string& vname, const string& cname) - : ASTGEN_SUPER_DpiExport(fl) - , m_name{vname} - , m_cname{cname} {} - ASTNODE_NODE_FUNCS(DpiExport) - virtual string name() const override { return m_name; } - virtual void name(const string& name) override { m_name = name; } - string cname() const { return m_cname; } - void cname(const string& cname) { m_cname = cname; } -}; - -class AstWithParse final : public AstNodeStmt { - // In early parse, FUNC(index) WITH equation-using-index - // Replaced with AstWith - // Parents: math|stmt - // Children: funcref, math -public: - AstWithParse(FileLine* fl, bool stmt, AstNode* funcrefp, AstNode* exprp) - : ASTGEN_SUPER_WithParse(fl) { - statement(stmt); - setOp1p(funcrefp); - addNOp2p(exprp); - } - ASTNODE_NODE_FUNCS(WithParse) - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // - AstNode* funcrefp() const { return op1p(); } - AstNode* exprp() const { return op2p(); } -}; - -class AstLambdaArgRef final : public AstNodeMath { - // Lambda argument usage - // These are not AstVarRefs because we need to be able to delete/clone lambdas during - // optimizations and AstVar's are painful to remove. -private: - string m_name; // Name of variable - bool m_index; // Index, not value - -public: - AstLambdaArgRef(FileLine* fl, const string& name, bool index) - : ASTGEN_SUPER_LambdaArgRef(fl) - , m_name{name} - , m_index(index) {} - ASTNODE_NODE_FUNCS(LambdaArgRef) - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual string emitVerilog() override { return name(); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - virtual string name() const override { return m_name; } // * = Var name - virtual void name(const string& name) override { m_name = name; } - bool index() const { return m_index; } -}; - -class AstWith final : public AstNodeStmt { - // Used as argument to method, then to AstCMethodHard - // dtypep() contains the with lambda's return dtype - // Parents: funcref (similar to AstArg) - // Children: LambdaArgRef that declares the item variable - // Children: LambdaArgRef that declares the item.index variable - // Children: math (equation establishing the with) -public: - AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp, - AstNode* exprp) - : ASTGEN_SUPER_With(fl) { - addOp1p(indexArgRefp); - addOp2p(valueArgRefp); - addNOp3p(exprp); - } - ASTNODE_NODE_FUNCS(With) - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool hasDType() const override { return true; } - virtual const char* broken() const override { - BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype - BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype - return nullptr; - } - // - AstLambdaArgRef* indexArgRefp() const { return VN_AS(op1p(), LambdaArgRef); } - AstLambdaArgRef* valueArgRefp() const { return VN_AS(op2p(), LambdaArgRef); } - AstNode* exprp() const { return op3p(); } -}; - -//###################################################################### - -class AstSenItem final : public AstNode { - // Parents: SENTREE - // Children: (optional) VARREF -private: - VEdgeType m_edgeType; // Edge type -public: - class Combo {}; // for creator type-overload selection - class Illegal {}; // for creator type-overload selection - class Initial {}; // for creator type-overload selection - class Settle {}; // for creator type-overload selection - class Never {}; // for creator type-overload selection - AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* varrefp) - : ASTGEN_SUPER_SenItem(fl) - , m_edgeType{edgeType} { - setOp1p(varrefp); - } - AstSenItem(FileLine* fl, Combo) - : ASTGEN_SUPER_SenItem(fl) - , m_edgeType{VEdgeType::ET_COMBO} {} - AstSenItem(FileLine* fl, Illegal) - : ASTGEN_SUPER_SenItem(fl) - , m_edgeType{VEdgeType::ET_ILLEGAL} {} - AstSenItem(FileLine* fl, Initial) - : ASTGEN_SUPER_SenItem(fl) - , m_edgeType{VEdgeType::ET_INITIAL} {} - AstSenItem(FileLine* fl, Settle) - : ASTGEN_SUPER_SenItem(fl) - , m_edgeType{VEdgeType::ET_SETTLE} {} - AstSenItem(FileLine* fl, Never) - : ASTGEN_SUPER_SenItem(fl) - , m_edgeType{VEdgeType::ET_NEVER} {} - ASTNODE_NODE_FUNCS(SenItem) - virtual void dump(std::ostream& str) const override; - virtual bool same(const AstNode* samep) const override { - return edgeType() == static_cast(samep)->edgeType(); - } - VEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge - void edgeType(VEdgeType type) { - m_edgeType = type; - editCountInc(); - } // * = Posedge/negedge - AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized - AstNodeVarRef* varrefp() const { - return VN_CAST(op1p(), NodeVarRef); - } // op1 = Signal sensitized - // - bool isClocked() const { return edgeType().clockedStmt(); } - bool isCombo() const { return edgeType() == VEdgeType::ET_COMBO; } - bool isInitial() const { return edgeType() == VEdgeType::ET_INITIAL; } - bool isIllegal() const { return edgeType() == VEdgeType::ET_ILLEGAL; } - bool isSettle() const { return edgeType() == VEdgeType::ET_SETTLE; } - bool isNever() const { return edgeType() == VEdgeType::ET_NEVER; } - bool hasVar() const { return !(isCombo() || isInitial() || isSettle() || isNever()); } -}; - -class AstSenTree final : public AstNode { - // A list of senitems - // Parents: MODULE | SBLOCK - // Children: SENITEM list -private: - bool m_multi = false; // Created from combo logic by ORing multiple clock domains -public: - AstSenTree(FileLine* fl, AstSenItem* sensesp) - : ASTGEN_SUPER_SenTree(fl) { - addNOp1p(sensesp); - } - ASTNODE_NODE_FUNCS(SenTree) - virtual void dump(std::ostream& str) const override; - virtual bool maybePointedTo() const override { return true; } - bool isMulti() const { return m_multi; } - // op1 = Sensitivity list - AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } - void addSensesp(AstSenItem* nodep) { addOp1p(nodep); } - void multi(bool flag) { m_multi = true; } - // METHODS - bool hasClocked() const; // Includes a clocked statement - bool hasSettle() const; // Includes a SETTLE SenItem - bool hasInitial() const; // Includes a INITIAL SenItem - bool hasCombo() const; // Includes a COMBO SenItem -}; - -class AstFinal final : public AstNodeProcedure { -public: - AstFinal(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_Final(fl, bodysp) {} - ASTNODE_NODE_FUNCS(Final) -}; - -class AstInitial final : public AstNodeProcedure { -public: - AstInitial(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_Initial(fl, bodysp) {} - ASTNODE_NODE_FUNCS(Initial) -}; - -class AstInitialAutomatic final : public AstNodeProcedure { - // Automatic variable initialization - // That is, it runs every function start, or class construction -public: - AstInitialAutomatic(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_InitialAutomatic(fl, bodysp) {} - ASTNODE_NODE_FUNCS(InitialAutomatic) -}; - -class AstInitialStatic final : public AstNodeProcedure { - // Static variable initialization - // That is, it runs at the beginning of simulation, before 'initial' blocks -public: - AstInitialStatic(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_InitialStatic(fl, bodysp) {} - ASTNODE_NODE_FUNCS(InitialStatic) -}; - -class AstAlways final : public AstNodeProcedure { - const VAlwaysKwd m_keyword; - -public: - AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp) - : ASTGEN_SUPER_Always(fl, bodysp) - , m_keyword{keyword} { - addNOp1p(sensesp); - } - ASTNODE_NODE_FUNCS(Always) - // - virtual void dump(std::ostream& str) const override; - AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list - void sensesp(AstSenTree* nodep) { setOp1p(nodep); } - VAlwaysKwd keyword() const { return m_keyword; } -}; - -class AstAlwaysPostponed final : public AstNodeProcedure { - // Like always but postponement scheduling region - -public: - AstAlwaysPostponed(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_AlwaysPostponed(fl, bodysp) {} - ASTNODE_NODE_FUNCS(AlwaysPostponed) -}; - -class AstAlwaysPost final : public AstNodeProcedure { - // Like always but post assignments for memory assignment IFs -public: - AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) - : ASTGEN_SUPER_AlwaysPost(fl, bodysp) { - addNOp1p(sensesp); - } - ASTNODE_NODE_FUNCS(AlwaysPost) -}; - -class AstAlwaysPublic final : public AstNodeStmt { - // "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/ - // Body statements are just AstVarRefs to the public signals -public: - AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) - : ASTGEN_SUPER_AlwaysPublic(fl) { - addNOp1p(sensesp); - addNOp2p(bodysp); - } - ASTNODE_NODE_FUNCS(AlwaysPublic) - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // - AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list - AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate - void addStmtp(AstNode* nodep) { addOp2p(nodep); } - // Special accessors - bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } -}; - -class AstAssign final : public AstNodeAssign { -public: - AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) - : ASTGEN_SUPER_Assign(fl, lhsp, rhsp, timingControlp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Assign) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssign(this->fileline(), lhsp, rhsp); - } - virtual bool brokeLhsMustBeLvalue() const override { return true; } -}; - -class AstAssignAlias final : public AstNodeAssign { - // Like AstAssignW, but a true bidirect interconnection alias - // If both sides are wires, there's no LHS vs RHS, -public: - AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp) - : ASTGEN_SUPER_AssignAlias(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignAlias) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - V3ERROR_NA_RETURN(nullptr); - } - virtual bool brokeLhsMustBeLvalue() const override { return false; } -}; - -class AstAssignDly final : public AstNodeAssign { -public: - AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) - : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp, timingControlp) {} - ASTNODE_NODE_FUNCS(AssignDly) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssignDly(this->fileline(), lhsp, rhsp); - } - virtual bool isGateOptimizable() const override { return false; } - virtual string verilogKwd() const override { return "<="; } - virtual bool brokeLhsMustBeLvalue() const override { return true; } -}; - -class AstAssignW final : public AstNodeAssign { - // Like assign, but wire/assign's in verilog, the only setting of the specified variable -public: - AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AssignW(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignW) - AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); } - void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssignW(this->fileline(), lhsp, rhsp); - } - virtual bool brokeLhsMustBeLvalue() const override { return true; } - AstAlways* convertToAlways() { - AstNode* const lhs1p = lhsp()->unlinkFrBack(); - AstNode* const rhs1p = rhsp()->unlinkFrBack(); - AstAlways* const newp = new AstAlways(fileline(), VAlwaysKwd::ALWAYS, nullptr, - new AstAssign(fileline(), lhs1p, rhs1p)); - replaceWith(newp); // User expected to then deleteTree(); - return newp; - } -}; - -class AstAssignVarScope final : public AstNodeAssign { - // Assign two VarScopes to each other -public: - AstAssignVarScope(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AssignVarScope(fl, lhsp, rhsp) { - dtypeFrom(rhsp); - } - ASTNODE_NODE_FUNCS(AssignVarScope) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssignVarScope(this->fileline(), lhsp, rhsp); - } - virtual bool brokeLhsMustBeLvalue() const override { return false; } -}; - -class AstPull final : public AstNode { -private: - bool m_direction; - -public: - AstPull(FileLine* fl, AstNode* lhsp, bool direction) - : ASTGEN_SUPER_Pull(fl) { - setOp1p(lhsp); - m_direction = direction; - } - ASTNODE_NODE_FUNCS(Pull) - virtual bool same(const AstNode* samep) const override { - return direction() == static_cast(samep)->direction(); - } - void lhsp(AstNode* np) { setOp1p(np); } - AstNode* lhsp() const { return op1p(); } // op1 = Assign to - uint32_t direction() const { return (uint32_t)m_direction; } -}; - -class AstAssignForce final : public AstNodeAssign { - // Procedural 'force' statement -public: - AstAssignForce(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AssignForce(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignForce) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssignForce{this->fileline(), lhsp, rhsp}; - } - virtual bool brokeLhsMustBeLvalue() const override { return true; } -}; - -class AstRelease final : public AstNodeStmt { - // Procedural 'release' statement -public: - AstRelease(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Release(fl) { - setOp1p(lhsp); - } - ASTNODE_NODE_FUNCS(Release); - AstNode* lhsp() const { return op1p(); } -}; - -class AstAssignPre final : public AstNodeAssign { - // Like Assign, but predelayed assignment requiring special order handling -public: - AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AssignPre(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignPre) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssignPre(this->fileline(), lhsp, rhsp); - } - virtual bool brokeLhsMustBeLvalue() const override { return true; } -}; - -class AstAssignPost final : public AstNodeAssign { - // Like Assign, but predelayed assignment requiring special order handling -public: - AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AssignPost(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignPost) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAssignPost(this->fileline(), lhsp, rhsp); - } - virtual bool brokeLhsMustBeLvalue() const override { return true; } -}; - -class AstDpiExportUpdated final : public AstNodeStmt { - // Denotes that the referenced variable may have been updated via a DPI Export -public: - AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep) - : ASTGEN_SUPER_DpiExportUpdated(fl) { - addOp1p(new AstVarRef{fl, varScopep, VAccess::WRITE}); - } - ASTNODE_NODE_FUNCS(DpiExportUpdated) - AstVarScope* varScopep() const { return VN_AS(op1p(), VarRef)->varScopep(); } -}; - -class AstExprStmt final : public AstNodeMath { - // Perform a statement, often assignment inside an expression/math node, - // the parent gets passed the 'resultp()'. - // resultp is evaluated AFTER the statement(s). -public: - AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNode* resultp) - : ASTGEN_SUPER_ExprStmt(fl) { - addOp1p(stmtsp); - setOp2p(resultp); // Possibly in future nullptr could mean return rhsp() - dtypeFrom(resultp); - } - ASTNODE_NODE_FUNCS(ExprStmt) - // ACCESSORS - AstNode* stmtsp() const { return op1p(); } - void addStmtsp(AstNode* nodep) { addOp1p(nodep); } - AstNode* resultp() const { return op2p(); } - // METHODS - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode*) const override { return true; } -}; - -class AstComment final : public AstNodeStmt { - // Some comment to put into the output stream - // Parents: {statement list} - // Children: none -private: - const bool m_showAt; // Show "at " - const string m_name; // Text of comment -public: - AstComment(FileLine* fl, const string& name, bool showAt = false) - : ASTGEN_SUPER_Comment(fl) - , m_showAt{showAt} - , m_name{name} {} - ASTNODE_NODE_FUNCS(Comment) - virtual string name() const override { return m_name; } // * = Text - virtual bool same(const AstNode* samep) const override { - return true; - } // Ignore name in comments - virtual bool showAt() const { return m_showAt; } -}; - -class AstCond final : public AstNodeCond { - // Conditional ?: statement - // Parents: MATH - // Children: MATH -public: - AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : ASTGEN_SUPER_Cond(fl, condp, expr1p, expr2p) {} - ASTNODE_NODE_FUNCS(Cond) - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { - return new AstCond(this->fileline(), condp, expr1p, expr2p); - } -}; - -class AstCondBound final : public AstNodeCond { - // Conditional ?: statement, specially made for safety checking of array bounds - // Parents: MATH - // Children: MATH -public: - AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : ASTGEN_SUPER_CondBound(fl, condp, expr1p, expr2p) {} - ASTNODE_NODE_FUNCS(CondBound) - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { - return new AstCondBound(this->fileline(), condp, expr1p, expr2p); - } -}; - -class AstCoverDecl final : public AstNodeStmt { - // Coverage analysis point declaration - // Parents: {statement list} - // Children: none -private: - AstCoverDecl* m_dataDeclp; // [After V3CoverageJoin] Pointer to duplicate declaration to get - // data from instead - string m_page; - string m_text; - string m_hier; - string m_linescov; - int m_offset; // Offset column numbers to uniq-ify IFs - int m_binNum; // Set by V3EmitCSyms to tell final V3Emit what to increment -public: - AstCoverDecl(FileLine* fl, const string& page, const string& comment, const string& linescov, - int offset) - : ASTGEN_SUPER_CoverDecl(fl) { - m_page = page; - m_text = comment; - m_linescov = linescov; - m_offset = offset; - m_binNum = 0; - m_dataDeclp = nullptr; - } - ASTNODE_NODE_FUNCS(CoverDecl) - virtual const char* broken() const override { - BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); - if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing - v3fatalSrc("dataDeclp should point to real data, not be a list"); - } - return nullptr; - } - virtual void cloneRelink() override { - if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } - virtual bool maybePointedTo() const override { return true; } - void binNum(int flag) { m_binNum = flag; } - int binNum() const { return m_binNum; } - int offset() const { return m_offset; } - const string& comment() const { return m_text; } // text to insert in code - const string& linescov() const { return m_linescov; } - const string& page() const { return m_page; } - const string& hier() const { return m_hier; } - void hier(const string& flag) { m_hier = flag; } - void comment(const string& flag) { m_text = flag; } - virtual bool same(const AstNode* samep) const override { - const AstCoverDecl* const asamep = static_cast(samep); - return (fileline() == asamep->fileline() && linescov() == asamep->linescov() - && hier() == asamep->hier() && comment() == asamep->comment()); - } - virtual bool isPredictOptimizable() const override { return false; } - void dataDeclp(AstCoverDecl* nodep) { m_dataDeclp = nodep; } - // dataDecl nullptr means "use this one", but often you want "this" to - // indicate to get data from here - AstCoverDecl* dataDeclNullp() const { return m_dataDeclp; } - AstCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } -}; - -class AstCoverInc final : public AstNodeStmt { - // Coverage analysis point; increment coverage count - // Parents: {statement list} - // Children: none -private: - AstCoverDecl* m_declp; // [After V3Coverage] Pointer to declaration -public: - AstCoverInc(FileLine* fl, AstCoverDecl* declp) - : ASTGEN_SUPER_CoverInc(fl) - , m_declp{declp} {} - ASTNODE_NODE_FUNCS(CoverInc) - virtual const char* broken() const override { - BROKEN_RTN(!declp()->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_declp->clonep()) m_declp = m_declp->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } - virtual bool same(const AstNode* samep) const override { - return declp() == static_cast(samep)->declp(); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isOutputter() const override { return true; } - // but isPure() true - AstCoverDecl* declp() const { return m_declp; } // Where defined -}; - -class AstCoverToggle final : public AstNodeStmt { - // Toggle analysis of given signal - // Parents: MODULE - // Children: AstCoverInc, orig var, change det var -public: - AstCoverToggle(FileLine* fl, AstCoverInc* incp, AstNode* origp, AstNode* changep) - : ASTGEN_SUPER_CoverToggle(fl) { - setOp1p(incp); - setOp2p(origp); - setOp3p(changep); - } - ASTNODE_NODE_FUNCS(CoverToggle) - virtual int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return true; } - virtual bool isOutputter() const override { - return false; // Though the AstCoverInc under this is an outputter - } - // but isPure() true - AstCoverInc* incp() const { return VN_AS(op1p(), CoverInc); } - void incp(AstCoverInc* nodep) { setOp1p(nodep); } - AstNode* origp() const { return op2p(); } - AstNode* changep() const { return op3p(); } -}; - -class AstDelay final : public AstNodeStmt { - // Delay statement -public: - AstDelay(FileLine* fl, AstNode* lhsp, AstNode* stmtsp) - : ASTGEN_SUPER_Delay(fl) { - setOp1p(lhsp); - setNOp2p(stmtsp); - } - ASTNODE_NODE_FUNCS(Delay) - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // - AstNode* lhsp() const { return op1p(); } // op1 = delay value - void lhsp(AstNode* nodep) { setOp1p(nodep); } - void stmtsp(AstNode* nodep) { setOp2p(nodep); } // op2 = statements under delay - AstNode* stmtsp() const { return op2p(); } -}; - -class AstGenCase final : public AstNodeCase { - // Generate Case statement - // Parents: {statement list} - // exprp Children: MATHs - // casesp Children: CASEITEMs -public: - AstGenCase(FileLine* fl, AstNode* exprp, AstNode* casesp) - : ASTGEN_SUPER_GenCase(fl, exprp, casesp) {} - ASTNODE_NODE_FUNCS(GenCase) -}; - -class AstCase final : public AstNodeCase { - // Case statement - // Parents: {statement list} - // exprp Children: MATHs - // casesp Children: CASEITEMs -private: - VCaseType m_casex; // 0=case, 1=casex, 2=casez - bool m_fullPragma = false; // Synthesis full_case - bool m_parallelPragma = false; // Synthesis parallel_case - bool m_uniquePragma = false; // unique case - bool m_unique0Pragma = false; // unique0 case - bool m_priorityPragma = false; // priority case -public: - AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp) - : ASTGEN_SUPER_Case(fl, exprp, casesp) - , m_casex{casex} {} - ASTNODE_NODE_FUNCS(Case) - virtual string verilogKwd() const override { - return casez() ? "casez" : casex() ? "casex" : "case"; - } - virtual bool same(const AstNode* samep) const override { - return m_casex == static_cast(samep)->m_casex; - } - bool casex() const { return m_casex == VCaseType::CT_CASEX; } - bool casez() const { return m_casex == VCaseType::CT_CASEZ; } - bool caseInside() const { return m_casex == VCaseType::CT_CASEINSIDE; } - bool caseSimple() const { return m_casex == VCaseType::CT_CASE; } - void caseInsideSet() { m_casex = VCaseType::CT_CASEINSIDE; } - bool fullPragma() const { return m_fullPragma; } - void fullPragma(bool flag) { m_fullPragma = flag; } - bool parallelPragma() const { return m_parallelPragma; } - void parallelPragma(bool flag) { m_parallelPragma = flag; } - bool uniquePragma() const { return m_uniquePragma; } - void uniquePragma(bool flag) { m_uniquePragma = flag; } - bool unique0Pragma() const { return m_unique0Pragma; } - void unique0Pragma(bool flag) { m_unique0Pragma = flag; } - bool priorityPragma() const { return m_priorityPragma; } - void priorityPragma(bool flag) { m_priorityPragma = flag; } -}; - -class AstCaseItem final : public AstNode { - // Single item of a case statement - // Parents: CASE - // condsp Children: MATH (Null condition used for default block) - // bodysp Children: Statements -public: - AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* bodysp) - : ASTGEN_SUPER_CaseItem(fl) { - addNOp1p(condsp); - addNOp2p(bodysp); - } - ASTNODE_NODE_FUNCS(CaseItem) - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } - AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions - AstNode* bodysp() const { return op2p(); } // op2 = what to do - void condsp(AstNode* nodep) { setOp1p(nodep); } - void addBodysp(AstNode* newp) { addOp2p(newp); } - bool isDefault() const { return condsp() == nullptr; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } -}; - -class AstSFormatF final : public AstNode { - // Convert format to string, generally under an AstDisplay or AstSFormat - // Also used as "real" function for /*verilator sformat*/ functions - string m_text; - const bool m_hidden; // Under display, etc - bool m_hasFormat; // Has format code - const char m_missingArgChar; // Format code when argument without format, 'h'/'o'/'b' - VTimescale m_timeunit; // Parent module time unit -public: - class NoFormat {}; - AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp, - char missingArgChar = 'd') - : ASTGEN_SUPER_SFormatF(fl) - , m_text{text} - , m_hidden{hidden} - , m_hasFormat{true} - , m_missingArgChar{missingArgChar} { - dtypeSetString(); - addNOp1p(exprsp); - addNOp2p(nullptr); - } - AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd', - bool hidden = true) - : ASTGEN_SUPER_SFormatF(fl) - , m_text{""} - , m_hidden{hidden} - , m_hasFormat{false} - , m_missingArgChar{missingArgChar} { - dtypeSetString(); - addNOp1p(exprsp); - addNOp2p(nullptr); - } - ASTNODE_NODE_FUNCS(SFormatF) - virtual string name() const override { return m_text; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { - return text() == static_cast(samep)->text(); - } - virtual string verilogKwd() const override { return "$sformatf"; } - void addExprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - string text() const { return m_text; } // * = Text to display - void text(const string& text) { m_text = text; } - AstScopeName* scopeNamep() const { return VN_AS(op2p(), ScopeName); } - void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } - bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive - return (name().find("%m") != string::npos || name().find("%M") != string::npos); - } - bool hidden() const { return m_hidden; } - void hasFormat(bool flag) { m_hasFormat = flag; } - bool hasFormat() const { return m_hasFormat; } - char missingArgChar() const { return m_missingArgChar; } - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } -}; - -class AstDisplay final : public AstNodeStmt { - // Parents: stmtlist - // Children: file which must be a varref - // Children: SFORMATF to generate print string -private: - VDisplayType m_displayType; - -public: - AstDisplay(FileLine* fl, VDisplayType dispType, const string& text, AstNode* filep, - AstNode* exprsp, char missingArgChar = 'd') - : ASTGEN_SUPER_Display(fl) { - setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); - setNOp3p(filep); - m_displayType = dispType; - } - AstDisplay(FileLine* fl, VDisplayType dispType, AstNode* filep, AstNode* exprsp, - char missingArgChar = 'd') - : ASTGEN_SUPER_Display(fl) { - setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); - setNOp3p(filep); - m_displayType = dispType; - } - ASTNODE_NODE_FUNCS(Display) - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { - BROKEN_RTN(!fmtp()); - return nullptr; - } - virtual string verilogKwd() const override { - return (filep() ? string("$f") + string(displayType().ascii()) - : string("$") + string(displayType().ascii())); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* samep) const override { - return displayType() == static_cast(samep)->displayType(); - } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - VDisplayType displayType() const { return m_displayType; } - void displayType(VDisplayType type) { m_displayType = type; } - // * = Add a newline for $display - bool addNewline() const { return displayType().addNewline(); } - void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } - AstNode* filep() const { return op3p(); } - void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); } -}; - -class AstDumpCtl final : public AstNodeStmt { - // $dumpon etc - // Parents: expr - // Child: expr based on type of control statement - const VDumpCtlType m_ctlType; // Type of operation -public: - AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = nullptr) - : ASTGEN_SUPER_DumpCtl(fl) - , m_ctlType{ctlType} { - setNOp1p(exprp); - } - ASTNODE_NODE_FUNCS(DumpCtl) - virtual string verilogKwd() const override { return ctlType().ascii(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - VDumpCtlType ctlType() const { return m_ctlType; } - AstNode* exprp() const { return op1p(); } // op2 = Expressions to output - void exprp(AstNode* nodep) { setOp1p(nodep); } -}; - -class AstElabDisplay final : public AstNode { - // Parents: stmtlist - // Children: SFORMATF to generate print string -private: - VDisplayType m_displayType; - -public: - AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp) - : ASTGEN_SUPER_ElabDisplay(fl) { - setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp)); - m_displayType = dispType; - } - ASTNODE_NODE_FUNCS(ElabDisplay) - virtual const char* broken() const override { - BROKEN_RTN(!fmtp()); - return nullptr; - } - virtual string verilogKwd() const override { - return (string("$") + string(displayType().ascii())); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* samep) const override { - return displayType() == static_cast(samep)->displayType(); - } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - VDisplayType displayType() const { return m_displayType; } - void displayType(VDisplayType type) { m_displayType = type; } - void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } -}; - -class AstSFormat final : public AstNodeStmt { - // Parents: statement container - // Children: string to load - // Children: SFORMATF to generate print string -public: - AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp, - char missingArgChar = 'd') - : ASTGEN_SUPER_SFormat(fl) { - setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); - setOp3p(lhsp); - } - AstSFormat(FileLine* fl, AstNode* lhsp, AstNode* exprsp, char missingArgChar = 'd') - : ASTGEN_SUPER_SFormat(fl) { - setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); - setOp3p(lhsp); - } - ASTNODE_NODE_FUNCS(SFormat) - virtual const char* broken() const override { - BROKEN_RTN(!fmtp()); - return nullptr; - } - virtual string verilogKwd() const override { return "$sformat"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return true; } - virtual bool isPure() const override { return true; } - virtual bool isOutputter() const override { return false; } - virtual bool cleanOut() const { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } - AstNode* lhsp() const { return op3p(); } - void lhsp(AstNode* nodep) { setOp3p(nodep); } -}; - -class AstSysFuncAsTask final : public AstNodeStmt { - // Call what is normally a system function (with a return) in a non-return context - // Parents: stmtlist - // Children: a system function -public: - AstSysFuncAsTask(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_SysFuncAsTask(fl) { - addNOp1p(exprsp); - } - ASTNODE_NODE_FUNCS(SysFuncAsTask) - virtual string verilogKwd() const override { return ""; } - virtual bool isGateOptimizable() const override { return true; } - virtual bool isPredictOptimizable() const override { return true; } - virtual bool isPure() const override { return true; } - virtual bool isOutputter() const override { return false; } - virtual int instrCount() const override { return 0; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval - void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval -}; - -class AstSysIgnore final : public AstNodeStmt { - // Parents: stmtlist - // Children: varrefs or exprs -public: - AstSysIgnore(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_SysIgnore(fl) { - addNOp1p(exprsp); - } - ASTNODE_NODE_FUNCS(SysIgnore) - virtual string verilogKwd() const override { return "$ignored"; } - virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt - virtual bool isPredictOptimizable() const override { - return false; - } // Though deleted before opt - virtual bool isPure() const override { return false; } // Though deleted before opt - virtual bool isOutputter() const override { return true; } // Though deleted before opt - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output -}; - -class AstFClose final : public AstNodeStmt { - // Parents: stmtlist - // Children: file which must be a varref -public: - AstFClose(FileLine* fl, AstNode* filep) - : ASTGEN_SUPER_FClose(fl) { - setNOp2p(filep); - } - ASTNODE_NODE_FUNCS(FClose) - virtual string verilogKwd() const override { return "$fclose"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } -}; - -class AstFOpen final : public AstNodeStmt { - // Although a system function in IEEE, here a statement which sets the file pointer (MCD) -public: - AstFOpen(FileLine* fl, AstNode* filep, AstNode* filenamep, AstNode* modep) - : ASTGEN_SUPER_FOpen(fl) { - setOp1p(filep); - setOp2p(filenamep); - setOp3p(modep); - } - ASTNODE_NODE_FUNCS(FOpen) - virtual string verilogKwd() const override { return "$fopen"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op1p(); } - AstNode* filenamep() const { return op2p(); } - AstNode* modep() const { return op3p(); } -}; - -class AstFOpenMcd final : public AstNodeStmt { - // Although a system function in IEEE, here a statement which sets the file pointer (MCD) -public: - AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep) - : ASTGEN_SUPER_FOpenMcd(fl) { - setOp1p(filep); - setOp2p(filenamep); - } - ASTNODE_NODE_FUNCS(FOpenMcd) - virtual string verilogKwd() const override { return "$fopen"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op1p(); } - AstNode* filenamep() const { return op2p(); } -}; - -class AstFFlush final : public AstNodeStmt { - // Parents: stmtlist - // Children: file which must be a varref -public: - AstFFlush(FileLine* fl, AstNode* filep) - : ASTGEN_SUPER_FFlush(fl) { - setNOp2p(filep); - } - ASTNODE_NODE_FUNCS(FFlush) - virtual string verilogKwd() const override { return "$fflush"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } -}; - -class AstFRead final : public AstNodeMath { - // Parents: expr - // Children: varrefs to load - // Children: file which must be a varref - // Children: low index - // Children: count -public: - AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, AstNode* startp, AstNode* countp) - : ASTGEN_SUPER_FRead(fl) { - setOp1p(memp); - setOp2p(filep); - setNOp3p(startp); - setNOp4p(countp); - } - ASTNODE_NODE_FUNCS(FRead) - virtual string verilogKwd() const override { return "$fread"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* memp() const { return op1p(); } - void memp(AstNode* nodep) { setOp1p(nodep); } - AstNode* filep() const { return op2p(); } - void filep(AstNode* nodep) { setOp2p(nodep); } - AstNode* startp() const { return op3p(); } - void startp(AstNode* nodep) { setNOp3p(nodep); } - AstNode* countp() const { return op4p(); } - void countp(AstNode* nodep) { setNOp4p(nodep); } -}; - -class AstFRewind final : public AstNodeMath { - // Parents: stmtlist - // Children: file which must be a varref -public: - AstFRewind(FileLine* fl, AstNode* filep) - : ASTGEN_SUPER_FRewind(fl) { - setNOp2p(filep); - } - ASTNODE_NODE_FUNCS(FRewind) - virtual string verilogKwd() const override { return "$frewind"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } -}; - -class AstFTell final : public AstNodeMath { - // Parents: stmtlist - // Children: file which must be a varref -public: - AstFTell(FileLine* fl, AstNode* filep) - : ASTGEN_SUPER_FTell(fl) { - setNOp2p(filep); - } - ASTNODE_NODE_FUNCS(FTell) - virtual string verilogKwd() const override { return "$ftell"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } -}; - -class AstFSeek final : public AstNodeMath { - // Parents: expr - // Children: file which must be a varref - // Children: offset - // Children: operation -public: - AstFSeek(FileLine* fl, AstNode* filep, AstNode* offset, AstNode* operation) - : ASTGEN_SUPER_FSeek(fl) { - setOp2p(filep); - setNOp3p(offset); - setNOp4p(operation); - } - ASTNODE_NODE_FUNCS(FSeek) - virtual string verilogKwd() const override { return "$fseek"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNode* nodep) { setOp2p(nodep); } - AstNode* offset() const { return op3p(); } - void offset(AstNode* nodep) { setNOp3p(nodep); } - AstNode* operation() const { return op4p(); } - void operation(AstNode* nodep) { setNOp4p(nodep); } -}; - -class AstFScanF final : public AstNodeMath { - // Parents: expr - // Children: file which must be a varref - // Children: varrefs to load -private: - string m_text; - -public: - AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp) - : ASTGEN_SUPER_FScanF(fl) - , m_text{text} { - addNOp1p(exprsp); - setNOp2p(filep); - } - ASTNODE_NODE_FUNCS(FScanF) - virtual string name() const override { return m_text; } - virtual string verilogKwd() const override { return "$fscanf"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return text() == static_cast(samep)->text(); - } - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output - string text() const { return m_text; } // * = Text to display - void text(const string& text) { m_text = text; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } -}; - -class AstSScanF final : public AstNodeMath { - // Parents: expr - // Children: file which must be a varref - // Children: varrefs to load -private: - string m_text; - -public: - AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp) - : ASTGEN_SUPER_SScanF(fl) - , m_text{text} { - addNOp1p(exprsp); - setOp2p(fromp); - } - ASTNODE_NODE_FUNCS(SScanF) - virtual string name() const override { return m_text; } - virtual string verilogKwd() const override { return "$sscanf"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return text() == static_cast(samep)->text(); - } - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output - string text() const { return m_text; } // * = Text to display - void text(const string& text) { m_text = text; } - AstNode* fromp() const { return op2p(); } - void fromp(AstNode* nodep) { setOp2p(nodep); } -}; - -class AstNodeReadWriteMem VL_NOT_FINAL : public AstNodeStmt { -private: - const bool m_isHex; // readmemh, not readmemb -public: - AstNodeReadWriteMem(VNType t, FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, - AstNode* lsbp, AstNode* msbp) - : AstNodeStmt(t, fl) - , m_isHex(hex) { - setOp1p(filenamep); - setOp2p(memp); - setNOp3p(lsbp); - setNOp4p(msbp); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* samep) const override { - return isHex() == static_cast(samep)->isHex(); - } - bool isHex() const { return m_isHex; } - AstNode* filenamep() const { return op1p(); } - AstNode* memp() const { return op2p(); } - AstNode* lsbp() const { return op3p(); } - AstNode* msbp() const { return op4p(); } - virtual const char* cFuncPrefixp() const = 0; -}; - -class AstReadMem final : public AstNodeReadWriteMem { -public: - AstReadMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, - AstNode* msbp) - : ASTGEN_SUPER_ReadMem(fl, hex, filenamep, memp, lsbp, msbp) {} - ASTNODE_NODE_FUNCS(ReadMem); - virtual string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); } - virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; } -}; - -class AstWriteMem final : public AstNodeReadWriteMem { -public: - AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, - AstNode* msbp) - : ASTGEN_SUPER_WriteMem(fl, hex, filenamep, memp, lsbp, msbp) {} - ASTNODE_NODE_FUNCS(WriteMem) - virtual string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); } - virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } -}; - -class AstMonitorOff final : public AstNodeStmt { - const bool m_off; // Monitor off. Using 0=on allows faster init and comparison - -public: - AstMonitorOff(FileLine* fl, bool off) - : ASTGEN_SUPER_MonitorOff(fl) - , m_off{off} {} - ASTNODE_NODE_FUNCS(MonitorOff) - virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; } - virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt - virtual bool isPredictOptimizable() const override { - return false; - } // Though deleted before opt - virtual bool isPure() const override { return false; } // Though deleted before opt - virtual bool isOutputter() const override { return true; } // Though deleted before opt - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* samep) const override { - return m_off == static_cast(samep)->m_off; - } - bool off() const { return m_off; } -}; - -class AstSystemT final : public AstNodeStmt { - // $system used as task -public: - AstSystemT(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_SystemT(fl) { - setOp1p(lhsp); - } - ASTNODE_NODE_FUNCS(SystemT) - virtual string verilogKwd() const override { return "$system"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* lhsp() const { return op1p(); } -}; - -class AstSystemF final : public AstNodeMath { - // $system used as function -public: - AstSystemF(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_SystemF(fl) { - setOp1p(lhsp); - } - ASTNODE_NODE_FUNCS(SystemF) - virtual string verilogKwd() const override { return "$system"; } - virtual string emitVerilog() override { return verilogKwd(); } - virtual string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* lhsp() const { return op1p(); } -}; - -class AstValuePlusArgs final : public AstNodeMath { - // Parents: expr - // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs -public: - AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp) - : ASTGEN_SUPER_ValuePlusArgs(fl) { - setOp1p(searchp); - setOp2p(outp); - } - ASTNODE_NODE_FUNCS(ValuePlusArgs) - virtual string verilogKwd() const override { return "$value$plusargs"; } - virtual string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return !outp(); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* searchp() const { return op1p(); } // op1 = Search expression - void searchp(AstNode* nodep) { setOp1p(nodep); } - AstNode* outp() const { return op2p(); } // op2 = Expressions to output - void outp(AstNode* nodep) { setOp2p(nodep); } -}; - -class AstTestPlusArgs final : public AstNodeMath { - // Parents: expr - // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs -public: - AstTestPlusArgs(FileLine* fl, AstNode* searchp) - : ASTGEN_SUPER_TestPlusArgs(fl) { - setOp1p(searchp); - } - ASTNODE_NODE_FUNCS(TestPlusArgs) - virtual string verilogKwd() const override { return "$test$plusargs"; } - virtual string emitVerilog() override { return verilogKwd(); } - virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* searchp() const { return op1p(); } // op1 = Search expression - void searchp(AstNode* nodep) { setOp1p(nodep); } -}; - -class AstGenFor final : public AstNodeFor { -public: - AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) - : ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, bodysp) {} - ASTNODE_NODE_FUNCS(GenFor) -}; - -class AstForeach final : public AstNodeStmt { -public: - AstForeach(FileLine* fl, AstNode* arrayp, AstNode* bodysp) - : ASTGEN_SUPER_Foreach(fl) { - setOp1p(arrayp); - addNOp4p(bodysp); - } - ASTNODE_NODE_FUNCS(Foreach) - AstNode* arrayp() const { return op1p(); } // op1 = array and index vars - AstNode* bodysp() const { return op4p(); } // op4 = body of loop - virtual bool isGateOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } -}; - -class AstRepeat final : public AstNodeStmt { -public: - AstRepeat(FileLine* fl, AstNode* countp, AstNode* bodysp) - : ASTGEN_SUPER_Repeat(fl) { - setOp2p(countp); - addNOp3p(bodysp); - } - ASTNODE_NODE_FUNCS(Repeat) - AstNode* countp() const { return op2p(); } // op2 = condition to continue - AstNode* bodysp() const { return op3p(); } // op3 = body of loop - virtual bool isGateOptimizable() const override { - return false; - } // Not relevant - converted to FOR - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } -}; - -class AstWait final : public AstNodeStmt { -public: - AstWait(FileLine* fl, AstNode* condp, AstNode* bodysp) - : ASTGEN_SUPER_Wait(fl) { - setOp2p(condp); - addNOp3p(bodysp); - } - ASTNODE_NODE_FUNCS(Wait) - AstNode* bodysp() const { return op3p(); } // op3 = body of loop - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } -}; - -class AstWhile final : public AstNodeStmt { -public: - AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp = nullptr, AstNode* incsp = nullptr) - : ASTGEN_SUPER_While(fl) { - setOp2p(condp); - addNOp3p(bodysp); - addNOp4p(incsp); - } - ASTNODE_NODE_FUNCS(While) - // op1 = prepare statements for condition (exec every loop) - AstNode* precondsp() const { return op1p(); } - AstNode* condp() const { return op2p(); } // op2 = condition to continue - AstNode* bodysp() const { return op3p(); } // op3 = body of loop - AstNode* incsp() const { return op4p(); } // op4 = increment (if from a FOR loop) - void addPrecondsp(AstNode* newp) { addOp1p(newp); } - void addBodysp(AstNode* newp) { addOp3p(newp); } - void addIncsp(AstNode* newp) { addOp4p(newp); } - virtual bool isGateOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // Stop statement searchback here - virtual void addBeforeStmt(AstNode* newp, AstNode* belowp) override; - // Stop statement searchback here - virtual void addNextStmt(AstNode* newp, AstNode* belowp) override; - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } -}; - -class AstBreak final : public AstNodeStmt { -public: - explicit AstBreak(FileLine* fl) - : ASTGEN_SUPER_Break(fl) {} - ASTNODE_NODE_FUNCS(Break) - virtual string verilogKwd() const override { return "break"; } - virtual bool isBrancher() const override { - return true; // SPECIAL: We don't process code after breaks - } -}; - -class AstContinue final : public AstNodeStmt { -public: - explicit AstContinue(FileLine* fl) - : ASTGEN_SUPER_Continue(fl) {} - ASTNODE_NODE_FUNCS(Continue) - virtual string verilogKwd() const override { return "continue"; } - virtual bool isBrancher() const override { - return true; // SPECIAL: We don't process code after breaks - } -}; - -class AstDisable final : public AstNodeStmt { -private: - string m_name; // Name of block -public: - AstDisable(FileLine* fl, const string& name) - : ASTGEN_SUPER_Disable(fl) - , m_name{name} {} - ASTNODE_NODE_FUNCS(Disable) - virtual string name() const override { return m_name; } // * = Block name - virtual void name(const string& flag) override { m_name = flag; } - virtual bool isBrancher() const override { - return true; // SPECIAL: We don't process code after breaks - } -}; - -class AstDisableFork final : public AstNodeStmt { - // A "disable fork" statement -public: - explicit AstDisableFork(FileLine* fl) - : ASTGEN_SUPER_DisableFork(fl) {} - ASTNODE_NODE_FUNCS(DisableFork) -}; - -class AstWaitFork final : public AstNodeStmt { - // A "wait fork" statement -public: - explicit AstWaitFork(FileLine* fl) - : ASTGEN_SUPER_WaitFork(fl) {} - ASTNODE_NODE_FUNCS(WaitFork) -}; - -class AstReturn final : public AstNodeStmt { -public: - explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr) - : ASTGEN_SUPER_Return(fl) { - setNOp1p(lhsp); - } - ASTNODE_NODE_FUNCS(Return) - virtual string verilogKwd() const override { return "return"; } - AstNode* lhsp() const { return op1p(); } - virtual bool isBrancher() const override { - return true; // SPECIAL: We don't process code after breaks - } -}; - -class AstGenIf final : public AstNodeIf { -public: - AstGenIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) - : ASTGEN_SUPER_GenIf(fl, condp, ifsp, elsesp) {} - ASTNODE_NODE_FUNCS(GenIf) -}; - -class AstIf final : public AstNodeIf { -private: - bool m_uniquePragma; // unique case - bool m_unique0Pragma; // unique0 case - bool m_priorityPragma; // priority case -public: - AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp = nullptr, AstNode* elsesp = nullptr) - : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) { - m_uniquePragma = false; - m_unique0Pragma = false; - m_priorityPragma = false; - } - ASTNODE_NODE_FUNCS(If) - bool uniquePragma() const { return m_uniquePragma; } - void uniquePragma(bool flag) { m_uniquePragma = flag; } - bool unique0Pragma() const { return m_unique0Pragma; } - void unique0Pragma(bool flag) { m_unique0Pragma = flag; } - bool priorityPragma() const { return m_priorityPragma; } - void priorityPragma(bool flag) { m_priorityPragma = flag; } -}; - -class AstJumpBlock final : public AstNodeStmt { - // Block of code including a JumpGo and JumpLabel - // Parents: {statement list} - // Children: {statement list, with JumpGo and JumpLabel below} -private: - AstJumpLabel* m_labelp = nullptr; // [After V3Jump] Pointer to declaration - int m_labelNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment -public: - // After construction must call ->labelp to associate with appropriate label - AstJumpBlock(FileLine* fl, AstNode* stmtsp) - : ASTGEN_SUPER_JumpBlock(fl) { - addNOp1p(stmtsp); - } - virtual const char* broken() const override; - virtual void cloneRelink() override; - ASTNODE_NODE_FUNCS(JumpBlock) - virtual int instrCount() const override { return 0; } - virtual bool maybePointedTo() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // op1 = Statements - AstNode* stmtsp() const { return op1p(); } // op1 = List of statements - void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } - AstNode* endStmtsp() const { return op2p(); } // op1 = List of end-of-block - void addEndStmtsp(AstNode* nodep) { addNOp2p(nodep); } - int labelNum() const { return m_labelNum; } - void labelNum(int flag) { m_labelNum = flag; } - AstJumpLabel* labelp() const { return m_labelp; } - void labelp(AstJumpLabel* labelp) { m_labelp = labelp; } -}; - -class AstJumpLabel final : public AstNodeStmt { - // Jump point declaration - // Parents: {statement list with JumpBlock above} - // Children: none -private: - AstJumpBlock* m_blockp; // [After V3Jump] Pointer to declaration -public: - AstJumpLabel(FileLine* fl, AstJumpBlock* blockp) - : ASTGEN_SUPER_JumpLabel(fl) - , m_blockp{blockp} {} - ASTNODE_NODE_FUNCS(JumpLabel) - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { - BROKEN_RTN(!blockp()->brokeExistsAbove()); - BROKEN_RTN(blockp()->labelp() != this); - return nullptr; - } - virtual void cloneRelink() override { - if (m_blockp->clonep()) m_blockp = m_blockp->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 0; } - virtual bool same(const AstNode* samep) const override { - return blockp() == static_cast(samep)->blockp(); - } - AstJumpBlock* blockp() const { return m_blockp; } -}; - -class AstJumpGo final : public AstNodeStmt { - // Jump point; branch down to a JumpLabel - // No support for backward jumps at present - // Parents: {statement list with JumpBlock above} - // Children: none -private: - AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration -public: - AstJumpGo(FileLine* fl, AstJumpLabel* labelp) - : ASTGEN_SUPER_JumpGo(fl) - , m_labelp{labelp} {} - ASTNODE_NODE_FUNCS(JumpGo); - virtual const char* broken() const override { - BROKEN_RTN(!labelp()->brokeExistsBelow()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_labelp->clonep()) m_labelp = m_labelp->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* samep) const override { - return labelp() == static_cast(samep)->labelp(); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isBrancher() const override { - return true; // SPECIAL: We don't process code after breaks - } - AstJumpLabel* labelp() const { return m_labelp; } -}; - -class AstChangeDet final : public AstNodeStmt { - // A comparison to determine change detection, common & must be fast. -public: - // Null lhs+rhs used to indicate change needed with no spec vars - AstChangeDet(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_ChangeDet(fl) { - setNOp1p(lhsp); - setNOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(ChangeDet) - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } // xor, or/logor - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstConsAssoc final : public AstNodeMath { - // Construct an assoc array and return object, '{} - // Parents: math - // Children: expression (elements or other queues) -public: - AstConsAssoc(FileLine* fl, AstNode* defaultp) - : ASTGEN_SUPER_ConsAssoc(fl) { - setNOp1p(defaultp); - } - ASTNODE_NODE_FUNCS(ConsAssoc) - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* defaultp() const { return op1p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; -class AstSetAssoc final : public AstNodeMath { - // Set an assoc array element and return object, '{} - // Parents: math - // Children: expression (elements or other queues) -public: - AstSetAssoc(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep) - : ASTGEN_SUPER_SetAssoc(fl) { - setOp1p(lhsp); - setNOp2p(keyp); - setOp3p(valuep); - } - ASTNODE_NODE_FUNCS(SetAssoc) - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } - AstNode* keyp() const { return op2p(); } - AstNode* valuep() const { return op3p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstConsWildcard final : public AstNodeMath { - // Construct a wildcard assoc array and return object, '{} - // Parents: math - // Children: expression (elements or other queues) -public: - AstConsWildcard(FileLine* fl, AstNode* defaultp) - : ASTGEN_SUPER_ConsWildcard(fl) { - setNOp1p(defaultp); - } - ASTNODE_NODE_FUNCS(ConsWildcard) - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* defaultp() const { return op1p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; -class AstSetWildcard final : public AstNodeMath { - // Set a wildcard assoc array element and return object, '{} - // Parents: math - // Children: expression (elements or other queues) -public: - AstSetWildcard(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep) - : ASTGEN_SUPER_SetWildcard(fl) { - setOp1p(lhsp); - setNOp2p(keyp); - setOp3p(valuep); - } - ASTNODE_NODE_FUNCS(SetWildcard) - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } - AstNode* keyp() const { return op2p(); } - AstNode* valuep() const { return op3p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstConsDynArray final : public AstNodeMath { - // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} - // Parents: math - // Children: expression (elements or other queues) -public: - explicit AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) - : ASTGEN_SUPER_ConsDynArray(fl) { - setNOp1p(lhsp); - setNOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(ConsDynArray) - virtual string emitVerilog() override { return "'{%l, %r}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } // op1 = expression - AstNode* rhsp() const { return op2p(); } // op2 = expression - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstConsQueue final : public AstNodeMath { - // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} - // Parents: math - // Children: expression (elements or other queues) -public: - explicit AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) - : ASTGEN_SUPER_ConsQueue(fl) { - setNOp1p(lhsp); - setNOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(ConsQueue) - virtual string emitVerilog() override { return "'{%l, %r}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } // op1 = expression - AstNode* rhsp() const { return op2p(); } // op2 = expression - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstBegin final : public AstNodeBlock { - // A Begin/end named block, only exists shortly after parsing until linking - // Parents: statement - // Children: statements -private: - bool m_generate; // Underneath a generate - const bool m_implied; // Not inserted by user -public: - // Node that puts name into the output stream - AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false, - bool implied = false) - : ASTGEN_SUPER_Begin(fl, name, stmtsp) - , m_generate{generate} - , m_implied{implied} {} - ASTNODE_NODE_FUNCS(Begin) - virtual void dump(std::ostream& str) const override; - // op1p is statements in NodeBlock - AstNode* genforp() const { return op2p(); } // op2 = GENFOR, if applicable, - // might NOT be a GenFor, as loop unrolling replaces with Begin - void addGenforp(AstGenFor* nodep) { addOp2p(nodep); } - void generate(bool flag) { m_generate = flag; } - bool generate() const { return m_generate; } - bool implied() const { return m_implied; } -}; - -class AstFork final : public AstNodeBlock { - // A fork named block - // Parents: statement - // Children: statements -private: - VJoinType m_joinType; // Join keyword type -public: - // Node that puts name into the output stream - AstFork(FileLine* fl, const string& name, AstNode* stmtsp) - : ASTGEN_SUPER_Fork(fl, name, stmtsp) {} - ASTNODE_NODE_FUNCS(Fork) - virtual void dump(std::ostream& str) const override; - VJoinType joinType() const { return m_joinType; } - void joinType(const VJoinType& flag) { m_joinType = flag; } -}; - -class AstInside final : public AstNodeMath { -public: - AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp) - : ASTGEN_SUPER_Inside(fl) { - addOp1p(exprp); - addOp2p(itemsp); - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Inside) - AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with - // op2 = RHS, possibly a list of expr or AstInsideRange - AstNode* itemsp() const { return op2p(); } - virtual string emitVerilog() override { return "%l inside { %r }"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } // NA -}; - -class AstInsideRange final : public AstNodeMath { -public: - AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_InsideRange(fl) { - addOp1p(lhsp); - addOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(InsideRange) - AstNode* lhsp() const { return op1p(); } // op1 = LHS - AstNode* rhsp() const { return op2p(); } // op2 = RHS - virtual string emitVerilog() override { return "[%l:%r]"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } // NA - // Create AstAnd(AstGte(...), AstLte(...)) - AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp); -}; - -class AstInitItem final : public AstNode { - // Container for a item in an init array - // This container is present so that the value underneath may get replaced with a new nodep - // and the upper AstInitArray's map will remain correct (pointing to this InitItem) -public: - // Parents: INITARRAY - AstInitItem(FileLine* fl, AstNode* valuep) - : ASTGEN_SUPER_InitItem(fl) { - addOp1p(valuep); - } - ASTNODE_NODE_FUNCS(InitItem) - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return false; } // See valuep()'s dtype instead - AstNode* valuep() const { return op1p(); } // op1 = Value - void valuep(AstNode* nodep) { addOp1p(nodep); } -}; - -class AstInitArray final : public AstNode { - // Set a var to a map of values - // The list of initsp() is not relevant - // If default is specified, the vector may be sparse, and not provide each value. - // Key values are C++ array style, with lo() at index 0 - // Parents: ASTVAR::init() - // Children: AstInitItem -public: - using KeyItemMap = std::map; - -private: - KeyItemMap m_map; // Node value for each array index -public: - AstInitArray(FileLine* fl, AstNodeDType* newDTypep, AstNode* defaultp) - : ASTGEN_SUPER_InitArray(fl) { - dtypep(newDTypep); - addNOp1p(defaultp); - } - ASTNODE_NODE_FUNCS(InitArray) - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { - for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { - BROKEN_RTN(!it->second); - BROKEN_RTN(!it->second->brokeExists()); - } - return nullptr; - } - virtual void cloneRelink() override { - for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) { - if (it->second->clonep()) it->second = it->second->clonep(); - } - } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { - // Only works if exact same children, instead should override comparison - // of children list, and instead use map-vs-map key/value compare - return m_map == static_cast(samep)->m_map; - } - AstNode* defaultp() const { return op1p(); } // op1 = Default if sparse - void defaultp(AstNode* newp) { setOp1p(newp); } - AstNode* initsp() const { return op2p(); } // op2 = Initial value expressions - void addValuep(AstNode* newp) { addIndexValuep(m_map.size(), newp); } - const KeyItemMap& map() const { return m_map; } - AstNode* addIndexValuep(uint64_t index, AstNode* newp) { - // Returns old value, caller must garbage collect - AstNode* oldp = nullptr; - const auto it = m_map.find(index); - if (it != m_map.end()) { - oldp = it->second->valuep(); - it->second->valuep(newp); - } else { - AstInitItem* const itemp = new AstInitItem(fileline(), newp); - m_map.emplace(index, itemp); - addOp2p(itemp); - } - return oldp; - } - AstNode* getIndexValuep(uint64_t index) const { - const auto it = m_map.find(index); - if (it == m_map.end()) { - return nullptr; - } else { - return it->second->valuep(); - } - } - AstNode* getIndexDefaultedValuep(uint64_t index) const { - AstNode* valuep = getIndexValuep(index); - if (!valuep) valuep = defaultp(); - return valuep; - } -}; - -class AstNew final : public AstNodeFTaskRef { - // New as constructor - // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it - // Parents: math|stmt - // Children: varref|arraysel, math -public: - AstNew(FileLine* fl, AstNode* pinsp) - : ASTGEN_SUPER_New(fl, false, "new", pinsp) {} - ASTNODE_NODE_FUNCS(New) - virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool hasDType() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } -}; - -class AstNewCopy final : public AstNodeMath { - // New as shallow copy - // Parents: math|stmt - // Children: varref|arraysel, math -public: - AstNewCopy(FileLine* fl, AstNode* rhsp) - : ASTGEN_SUPER_NewCopy(fl) { - dtypeFrom(rhsp); // otherwise V3Width will resolve - setNOp1p(rhsp); - } - ASTNODE_NODE_FUNCS(NewCopy) - virtual string emitVerilog() override { return "new"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* rhsp() const { return op1p(); } -}; - -class AstNewDynamic final : public AstNodeMath { - // New for dynamic array - // Parents: math|stmt - // Children: varref|arraysel, math -public: - AstNewDynamic(FileLine* fl, AstNode* sizep, AstNode* rhsp) - : ASTGEN_SUPER_NewDynamic(fl) { - dtypeFrom(rhsp); // otherwise V3Width will resolve - setNOp1p(sizep); - setNOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(NewDynamic) - virtual string emitVerilog() override { return "new"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* sizep() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } -}; - -class AstPragma final : public AstNode { -private: - const VPragmaType m_pragType; // Type of pragma -public: - // Pragmas don't result in any output code, they're just flags that affect - // other processing in verilator. - AstPragma(FileLine* fl, VPragmaType pragType) - : ASTGEN_SUPER_Pragma(fl) - , m_pragType{pragType} {} - ASTNODE_NODE_FUNCS(Pragma) - VPragmaType pragType() const { return m_pragType; } // *=type of the pragma - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return pragType() == static_cast(samep)->pragType(); - } -}; - -class AstPrintTimeScale final : public AstNodeStmt { - // Parents: stmtlist - string m_name; // Parent module name - VTimescale m_timeunit; // Parent module time unit -public: - explicit AstPrintTimeScale(FileLine* fl) - : ASTGEN_SUPER_PrintTimeScale(fl) {} - ASTNODE_NODE_FUNCS(PrintTimeScale) - virtual void name(const string& name) override { m_name = name; } - virtual string name() const override { return m_name; } // * = Var name - virtual void dump(std::ostream& str) const override; - virtual string verilogKwd() const override { return "$printtimescale"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } -}; - -class AstStop final : public AstNodeStmt { -public: - AstStop(FileLine* fl, bool maybe) - : ASTGEN_SUPER_Stop(fl) {} - ASTNODE_NODE_FUNCS(Stop) - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual int instrCount() const override { return 0; } // Rarely executes - virtual bool same(const AstNode* samep) const override { - return fileline() == samep->fileline(); - } -}; - -class AstFinish final : public AstNodeStmt { -public: - explicit AstFinish(FileLine* fl) - : ASTGEN_SUPER_Finish(fl) {} - ASTNODE_NODE_FUNCS(Finish) - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual int instrCount() const override { return 0; } // Rarely executes - virtual bool same(const AstNode* samep) const override { - return fileline() == samep->fileline(); - } -}; - -class AstNullCheck final : public AstNodeUniop { - // Return LHS after checking that LHS is non-null - // Children: VarRef or something returning pointer -public: - AstNullCheck(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_NullCheck(fl, lhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(NullCheck) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual int instrCount() const override { return 1; } // Rarely executes - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return fileline() == samep->fileline(); - } -}; - -class AstEventControl final : public AstNodeStmt { - // Parents: stmtlist -public: - AstEventControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) - : ASTGEN_SUPER_EventControl(fl) { - setNOp1p(sensesp); - setNOp2p(stmtsp); - } - ASTNODE_NODE_FUNCS(EventControl) - virtual string verilogKwd() const override { return "@(%l) %r"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return false; } - virtual int instrCount() const override { return 0; } - AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } - AstNode* stmtsp() const { return op2p(); } -}; - -class AstTimeFormat final : public AstNodeStmt { - // Parents: stmtlist -public: - AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp, - AstNode* widthp) - : ASTGEN_SUPER_TimeFormat(fl) { - setOp1p(unitsp); - setOp2p(precisionp); - setOp3p(suffixp); - setOp4p(widthp); - } - ASTNODE_NODE_FUNCS(TimeFormat) - virtual string verilogKwd() const override { return "$timeformat"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - AstNode* unitsp() const { return op1p(); } - AstNode* precisionp() const { return op2p(); } - AstNode* suffixp() const { return op3p(); } - AstNode* widthp() const { return op4p(); } -}; - -class AstTracePushNamePrefix final : public AstNodeStmt { - const string m_prefix; // Prefix to add to signal names -public: - AstTracePushNamePrefix(FileLine* fl, const string& prefix) - : ASTGEN_SUPER_TracePushNamePrefix(fl) - , m_prefix{prefix} {} - ASTNODE_NODE_FUNCS(TracePushNamePrefix) - virtual bool same(const AstNode* samep) const override { return false; } - string prefix() const { return m_prefix; } -}; - -class AstTracePopNamePrefix final : public AstNodeStmt { - const unsigned m_count; // How many levels to pop -public: - AstTracePopNamePrefix(FileLine* fl, unsigned count) - : ASTGEN_SUPER_TracePopNamePrefix(fl) - , m_count{count} {} - ASTNODE_NODE_FUNCS(TracePopNamePrefix) - virtual bool same(const AstNode* samep) const override { return false; } - unsigned count() const { return m_count; } -}; - -class AstTraceDecl final : public AstNodeStmt { - // Trace point declaration - // Separate from AstTraceInc; as a declaration can't be deleted - // Parents: {statement list} - // Children: expression being traced -private: - uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines - const string m_showname; // Name of variable - const VNumRange m_bitRange; // Property of var the trace details - const VNumRange m_arrayRange; // Property of var the trace details - const uint32_t m_codeInc; // Code increment - const VVarType m_varType; // Type of variable (for localparam vs. param) - const VBasicDTypeKwd m_declKwd; // Keyword at declaration time - const VDirection m_declDirection; // Declared direction input/output etc -public: - AstTraceDecl(FileLine* fl, const string& showname, - AstVar* varp, // For input/output state etc - AstNode* valuep, const VNumRange& bitRange, const VNumRange& arrayRange) - : ASTGEN_SUPER_TraceDecl(fl) - , m_showname{showname} - , m_bitRange{bitRange} - , m_arrayRange{arrayRange} - , m_codeInc( - ((arrayRange.ranged() ? arrayRange.elements() : 1) * valuep->dtypep()->widthWords() - * (VL_EDATASIZE / 32))) // A code is always 32-bits - , m_varType{varp->varType()} - , m_declKwd{varp->declKwd()} - , m_declDirection{varp->declDirection()} { - dtypeFrom(valuep); - addNOp1p(valuep); - } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 100; } // Large... - ASTNODE_NODE_FUNCS(TraceDecl) - virtual string name() const override { return m_showname; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { return false; } - string showname() const { return m_showname; } // * = Var name - // Details on what we're tracing - uint32_t code() const { return m_code; } - void code(uint32_t code) { m_code = code; } - uint32_t codeInc() const { return m_codeInc; } - const VNumRange& bitRange() const { return m_bitRange; } - const VNumRange& arrayRange() const { return m_arrayRange; } - VVarType varType() const { return m_varType; } - VBasicDTypeKwd declKwd() const { return m_declKwd; } - VDirection declDirection() const { return m_declDirection; } - AstNode* valuep() const { return op1p(); } -}; - -class AstTraceInc final : public AstNodeStmt { - // Trace point dump - // Parents: {statement list} - // Children: op1: things to emit before this node, - // op2: expression being traced (from decl) - -private: - AstTraceDecl* m_declp; // Pointer to declaration - const bool m_full; // Is this a full vs incremental dump - const uint32_t m_baseCode; // Trace code base value in function containing this AstTraceInc - -public: - AstTraceInc(FileLine* fl, AstTraceDecl* declp, bool full, uint32_t baseCode = 0) - : ASTGEN_SUPER_TraceInc(fl) - , m_declp{declp} - , m_full{full} - , m_baseCode{baseCode} { - dtypeFrom(declp); - addOp2p(declp->valuep()->cloneTree(true)); - } - ASTNODE_NODE_FUNCS(TraceInc) - virtual const char* broken() const override { - BROKEN_RTN(!declp()->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_declp->clonep()) m_declp = m_declp->clonep(); - } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 10 + 2 * INSTR_COUNT_LD; } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { - return declp() == static_cast(samep)->declp(); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isOutputter() const override { return true; } - // but isPure() true - // op1 = Statements before the value - AstNode* precondsp() const { return op1p(); } - void addPrecondsp(AstNode* newp) { addOp1p(newp); } - AstNode* valuep() const { return op2p(); } - AstTraceDecl* declp() const { return m_declp; } - bool full() const { return m_full; } - uint32_t baseCode() const { return m_baseCode; } -}; - -class AstActive final : public AstNode { - // Block of code with sensitivity activation - // Parents: MODULE | CFUNC - // Children: SENTREE, statements -private: - string m_name; - AstSenTree* m_sensesp; - -public: - AstActive(FileLine* fl, const string& name, AstSenTree* sensesp) - : ASTGEN_SUPER_Active(fl) { - m_name = name; // Copy it - UASSERT(sensesp, "Sensesp required arg"); - m_sensesp = sensesp; - } - ASTNODE_NODE_FUNCS(Active) - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } - virtual const char* broken() const override { - BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { - if (m_sensesp->clonep()) { - m_sensesp = m_sensesp->clonep(); - UASSERT(m_sensesp, "Bad clone cross link: " << this); - } - } - // Statements are broken into pieces, as some must come before others. - void sensesp(AstSenTree* nodep) { m_sensesp = nodep; } - AstSenTree* sensesp() const { return m_sensesp; } - // op1 = Sensitivity tree, if a clocked block in early stages - void sensesStorep(AstSenTree* nodep) { addOp1p(nodep); } - AstSenTree* sensesStorep() const { return VN_AS(op1p(), SenTree); } - // op2 = Combo logic - AstNode* stmtsp() const { return op2p(); } - void addStmtsp(AstNode* nodep) { addOp2p(nodep); } - // METHODS - bool hasInitial() const { return m_sensesp->hasInitial(); } - bool hasSettle() const { return m_sensesp->hasSettle(); } - bool hasClocked() const { return m_sensesp->hasClocked(); } -}; - -class AstAttrOf final : public AstNode { -private: - // Return a value of a attribute, for example a LSB or array LSB of a signal - VAttrType m_attrType; // What sort of extraction -public: - AstAttrOf(FileLine* fl, VAttrType attrtype, AstNode* fromp = nullptr, AstNode* dimp = nullptr) - : ASTGEN_SUPER_AttrOf(fl) { - setNOp1p(fromp); - setNOp2p(dimp); - m_attrType = attrtype; - } - ASTNODE_NODE_FUNCS(AttrOf) - AstNode* fromp() const { return op1p(); } - AstNode* dimp() const { return op2p(); } - VAttrType attrType() const { return m_attrType; } - virtual void dump(std::ostream& str = std::cout) const override; -}; - -class AstScopeName final : public AstNodeMath { - // For display %m and DPI context imports - // Parents: DISPLAY - // Children: TEXT -private: - bool m_dpiExport = false; // Is for dpiExport - const bool m_forFormat = false; // Is for a format %m - string scopeNameFormatter(AstText* scopeTextp) const; - string scopePrettyNameFormatter(AstText* scopeTextp) const; - -public: - class ForFormat {}; - AstScopeName(FileLine* fl, bool forFormat) - : ASTGEN_SUPER_ScopeName(fl) - , m_forFormat{forFormat} { - dtypeSetUInt64(); - } - ASTNODE_NODE_FUNCS(ScopeName) - virtual bool same(const AstNode* samep) const override { - return (m_dpiExport == static_cast(samep)->m_dpiExport - && m_forFormat == static_cast(samep)->m_forFormat); - } - virtual string emitVerilog() override { return ""; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; - AstText* scopeAttrp() const { return VN_AS(op1p(), Text); } - void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } - AstText* scopeEntrp() const { return VN_AS(op2p(), Text); } - void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } - string scopeSymName() const { // Name for __Vscope variable including children - return scopeNameFormatter(scopeAttrp()); - } - string scopeDpiName() const { // Name for DPI import scope - return scopeNameFormatter(scopeEntrp()); - } - string scopePrettySymName() const { // Name for __Vscope variable including children - return scopePrettyNameFormatter(scopeAttrp()); - } - string scopePrettyDpiName() const { // Name for __Vscope variable including children - return scopePrettyNameFormatter(scopeEntrp()); - } - bool dpiExport() const { return m_dpiExport; } - void dpiExport(bool flag) { m_dpiExport = flag; } - bool forFormat() const { return m_forFormat; } -}; - -class AstUdpTable final : public AstNode { -public: - AstUdpTable(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_UdpTable(fl) { - addNOp1p(bodysp); - } - ASTNODE_NODE_FUNCS(UdpTable) - // op1 = List of UdpTableLines - AstUdpTableLine* bodysp() const { return VN_AS(op1p(), UdpTableLine); } -}; - -class AstUdpTableLine final : public AstNode { - string m_text; - -public: - AstUdpTableLine(FileLine* fl, const string& text) - : ASTGEN_SUPER_UdpTableLine(fl) - , m_text{text} {} - ASTNODE_NODE_FUNCS(UdpTableLine) - virtual string name() const override { return m_text; } - string text() const { return m_text; } -}; - -//====================================================================== -// non-ary ops - -class AstRand final : public AstNodeMath { - // $random/$random(seed) or $urandom/$urandom(seed) - // Return a random number, based upon width() -private: - const bool m_urandom = false; // $urandom vs $random - const bool m_reset = false; // Random reset, versus always random -public: - class Reset {}; - AstRand(FileLine* fl, Reset, AstNodeDType* dtp, bool reset) - : ASTGEN_SUPER_Rand(fl) - , m_reset{reset} { - dtypep(dtp); - } - AstRand(FileLine* fl, AstNode* seedp, bool urandom) - : ASTGEN_SUPER_Rand(fl) - , m_urandom(urandom) { - setNOp1p(seedp); - } - ASTNODE_NODE_FUNCS(Rand) - virtual string emitVerilog() override { - return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)") - : (m_urandom ? "%f$urandom()" : "%f$random()"); - } - virtual string emitC() override { - return m_reset ? "VL_RAND_RESET_%nq(%nw, %P)" - : seedp() - ? (urandom() ? "VL_URANDOM_SEEDED_%nq%lq(%li)" : "VL_RANDOM_SEEDED_%nq%lq(%li)") - : isWide() ? "VL_RANDOM_%nq(%nw, %P)" // - : "VL_RANDOM_%nq()"; - } - virtual bool cleanOut() const override { return false; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - bool combinable(const AstRand* samep) const { - return !seedp() && !samep->seedp() && reset() == samep->reset() - && urandom() == samep->urandom(); - } - AstNode* seedp() const { return op1p(); } - bool reset() const { return m_reset; } - bool urandom() const { return m_urandom; } -}; - -class AstURandomRange final : public AstNodeBiop { - // $urandom_range -public: - explicit AstURandomRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_URandomRange(fl, lhsp, rhsp) { - dtypeSetUInt32(); // Says IEEE - } - ASTNODE_NODE_FUNCS(URandomRange) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstURandomRange(fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { return "%f$urandom_range(%l, %r)"; } - virtual string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } -}; - -class AstTime final : public AstNodeTermop { - VTimescale m_timeunit; // Parent module time unit -public: - AstTime(FileLine* fl, const VTimescale& timeunit) - : ASTGEN_SUPER_Time(fl) - , m_timeunit{timeunit} { - dtypeSetUInt64(); - } - ASTNODE_NODE_FUNCS(Time) - virtual string emitVerilog() override { return "%f$time"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_TIME; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } -}; - -class AstTimeD final : public AstNodeTermop { - VTimescale m_timeunit; // Parent module time unit -public: - AstTimeD(FileLine* fl, const VTimescale& timeunit) - : ASTGEN_SUPER_TimeD(fl) - , m_timeunit{timeunit} { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(TimeD) - virtual string emitVerilog() override { return "%f$realtime"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_TIME; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } -}; - -class AstUCFunc final : public AstNodeMath { - // User's $c function - // Perhaps this should be an AstNodeListop; but there's only one list math right now -public: - AstUCFunc(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_UCFunc(fl) { - addNOp1p(exprsp); - } - ASTNODE_NODE_FUNCS(UCFunc) - virtual bool cleanOut() const override { return false; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isSubstOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -//====================================================================== -// Unary ops - -class AstNegate final : public AstNodeUniop { -public: - AstNegate(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Negate(fl, lhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Negate) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); } - virtual string emitVerilog() override { return "%f(- %l)"; } - virtual string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } -}; -class AstNegateD final : public AstNodeUniop { -public: - AstNegateD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_NegateD(fl, lhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(NegateD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); } - virtual string emitVerilog() override { return "%f(- %l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstRedAnd final : public AstNodeUniop { -public: - AstRedAnd(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_RedAnd(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(RedAnd) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } - virtual string emitVerilog() override { return "%f(& %l)"; } - virtual string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstRedOr final : public AstNodeUniop { -public: - AstRedOr(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_RedOr(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(RedOr) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } - virtual string emitVerilog() override { return "%f(| %l)"; } - virtual string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstRedXor final : public AstNodeUniop { -public: - AstRedXor(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_RedXor(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(RedXor) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } - virtual string emitVerilog() override { return "%f(^ %l)"; } - virtual string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { - const int w = lhsp()->width(); - return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16); - } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } -}; - -class AstLenN final : public AstNodeUniop { - // Length of a string -public: - AstLenN(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_LenN(fl, lhsp) { - dtypeSetSigned32(); - } - ASTNODE_NODE_FUNCS(LenN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); } - virtual string emitVerilog() override { return "%f(%l)"; } - virtual string emitC() override { return "VL_LEN_IN(%li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstLogNot final : public AstNodeUniop { -public: - AstLogNot(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_LogNot(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LogNot) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } - virtual string emitVerilog() override { return "%f(! %l)"; } - virtual string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } - virtual string emitSimpleOperator() override { return "!"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstNot final : public AstNodeUniop { -public: - AstNot(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Not(fl, lhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Not) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); } - virtual string emitVerilog() override { return "%f(~ %l)"; } - virtual string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; } - virtual string emitSimpleOperator() override { return "~"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } -}; -class AstExtend final : public AstNodeUniop { - // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width() -public: - AstExtend(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Extend(fl, lhsp) {} - AstExtend(FileLine* fl, AstNode* lhsp, int width) - : ASTGEN_SUPER_Extend(fl, lhsp) { - dtypeSetLogicSized(width, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(Extend) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { - return false; // Because the EXTEND operator self-casts - } - virtual int instrCount() const override { return 0; } -}; -class AstExtendS final : public AstNodeUniop { - // Expand a value into a wider entity by sign extension. Width is implied from nodep->width() -public: - AstExtendS(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_ExtendS(fl, lhsp) {} - AstExtendS(FileLine* fl, AstNode* lhsp, int width) - // Important that widthMin be correct, as opExtend requires it after V3Expand - : ASTGEN_SUPER_ExtendS(fl, lhsp) { - dtypeSetLogicSized(width, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(ExtendS) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opExtendS(lhs, lhsp()->widthMinV()); - } - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { - return false; // Because the EXTEND operator self-casts - } - virtual int instrCount() const override { return 0; } - virtual bool signedFlavor() const override { return true; } -}; -class AstSigned final : public AstNodeUniop { - // $signed(lhs) -public: - AstSigned(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Signed(fl, lhsp) { - UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, - "not coded to create after dtypes resolved"); - } - ASTNODE_NODE_FUNCS(Signed) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opAssign(lhs); - out.isSigned(false); - } - virtual string emitVerilog() override { return "%f$signed(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters - virtual int instrCount() const override { return 0; } -}; -class AstUnsigned final : public AstNodeUniop { - // $unsigned(lhs) -public: - AstUnsigned(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Unsigned(fl, lhsp) { - UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, - "not coded to create after dtypes resolved"); - } - ASTNODE_NODE_FUNCS(Unsigned) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opAssign(lhs); - out.isSigned(false); - } - virtual string emitVerilog() override { return "%f$unsigned(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters - virtual int instrCount() const override { return 0; } -}; -class AstRToIS final : public AstNodeUniop { - // $rtoi(lhs) -public: - AstRToIS(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_RToIS(fl, lhsp) { - dtypeSetSigned32(); - } - ASTNODE_NODE_FUNCS(RToIS) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); } - virtual string emitVerilog() override { return "%f$rtoi(%l)"; } - virtual string emitC() override { return "VL_RTOI_I_D(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters - virtual int instrCount() const override { return INSTR_COUNT_DBL; } -}; -class AstRToIRoundS final : public AstNodeUniop { - // Convert real to integer, with arbitrary sized output (not just "integer" format) -public: - AstRToIRoundS(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_RToIRoundS(fl, lhsp) { - dtypeSetSigned32(); - } - ASTNODE_NODE_FUNCS(RToIRoundS) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opRToIRoundS(lhs); - } - virtual string emitVerilog() override { return "%f$rtoi_rounded(%l)"; } - virtual string emitC() override { - return isWide() ? "VL_RTOIROUND_%nq_D(%nw, %P, %li)" : "VL_RTOIROUND_%nq_D(%li)"; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } -}; -class AstIToRD final : public AstNodeUniop { - // $itor where lhs is unsigned -public: - AstIToRD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_IToRD(fl, lhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(IToRD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); } - virtual string emitVerilog() override { return "%f$itor(%l)"; } - virtual string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } -}; -class AstISToRD final : public AstNodeUniop { - // $itor where lhs is signed -public: - AstISToRD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_ISToRD(fl, lhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(ISToRD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); } - virtual string emitVerilog() override { return "%f$itor($signed(%l))"; } - virtual string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } -}; -class AstRealToBits final : public AstNodeUniop { -public: - AstRealToBits(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_RealToBits(fl, lhsp) { - dtypeSetUInt64(); - } - ASTNODE_NODE_FUNCS(RealToBits) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opRealToBits(lhs); - } - virtual string emitVerilog() override { return "%f$realtobits(%l)"; } - virtual string emitC() override { return "VL_CVT_Q_D(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters - virtual int instrCount() const override { return INSTR_COUNT_DBL; } -}; -class AstBitsToRealD final : public AstNodeUniop { -public: - AstBitsToRealD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_BitsToRealD(fl, lhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(BitsToRealD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opBitsToRealD(lhs); - } - virtual string emitVerilog() override { return "%f$bitstoreal(%l)"; } - virtual string emitC() override { return "VL_CVT_D_Q(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters - virtual int instrCount() const override { return INSTR_COUNT_DBL; } -}; - -class AstCLog2 final : public AstNodeUniop { -public: - AstCLog2(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CLog2(fl, lhsp) { - dtypeSetSigned32(); - } - ASTNODE_NODE_FUNCS(CLog2) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); } - virtual string emitVerilog() override { return "%f$clog2(%l)"; } - virtual string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } -}; -class AstCountBits final : public AstNodeQuadop { - // Number of bits set in vector -public: - AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p) - : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTree(false), - ctrl1p->cloneTree(false)) {} - AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p) - : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTree(false)) {} - AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p, AstNode* ctrl3p) - : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {} - ASTNODE_NODE_FUNCS(CountBits) - virtual void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1, - const V3Number& ctrl2, const V3Number& ctrl3) override { - out.opCountBits(expr, ctrl1, ctrl2, ctrl3); - } - virtual string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; } - virtual string emitC() override { return ""; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool cleanFhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual bool sizeMattersFhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } -}; -class AstCountOnes final : public AstNodeUniop { - // Number of bits set in vector -public: - AstCountOnes(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CountOnes(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CountOnes) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opCountOnes(lhs); - } - virtual string emitVerilog() override { return "%f$countones(%l)"; } - virtual string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } -}; -class AstIsUnknown final : public AstNodeUniop { - // True if any unknown bits -public: - AstIsUnknown(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_IsUnknown(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(IsUnknown) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opIsUnknown(lhs); - } - virtual string emitVerilog() override { return "%f$isunknown(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstIsUnbounded final : public AstNodeUniop { - // True if is unmbounded ($) -public: - AstIsUnbounded(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_IsUnbounded(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(IsUnbounded) - virtual void numberOperate(V3Number& out, const V3Number&) override { - // Any constant isn't unbounded - out.setZero(); - } - virtual string emitVerilog() override { return "%f$isunbounded(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstOneHot final : public AstNodeUniop { - // True if only single bit set in vector -public: - AstOneHot(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_OneHot(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(OneHot) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } - virtual string emitVerilog() override { return "%f$onehot(%l)"; } - virtual string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 4; } -}; -class AstOneHot0 final : public AstNodeUniop { - // True if only single bit, or no bits set in vector -public: - AstOneHot0(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_OneHot0(fl, lhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(OneHot0) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } - virtual string emitVerilog() override { return "%f$onehot0(%l)"; } - virtual string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 3; } -}; - -class AstCast final : public AstNode { - // Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc -public: - AstCast(FileLine* fl, AstNode* lhsp, VFlagChildDType, AstNodeDType* dtp) - : ASTGEN_SUPER_Cast(fl) { - setOp1p(lhsp); - setOp2p(dtp); - dtypeFrom(dtp); - } - AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) - : ASTGEN_SUPER_Cast(fl) { - setOp1p(lhsp); - dtypeFrom(dtp); - } - ASTNODE_NODE_FUNCS(Cast) - virtual bool hasDType() const override { return true; } - virtual string emitVerilog() { return "((%d)'(%l))"; } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - AstNode* lhsp() const { return op1p(); } - AstNode* fromp() const { return lhsp(); } - void lhsp(AstNode* nodep) { setOp1p(nodep); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_AS(op2p(), NodeDType); } - virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } -}; - -class AstCastDynamic final : public AstNodeBiop { - // Verilog $cast used as a function - // Task usage of $cast is converted during parse to assert($cast(...)) - // Parents: MATH - // Children: MATH - // lhsp() is value (we are converting FROM) to match AstCCast etc, this - // is opposite of $cast's order, because the first access is to the - // value reading from. Suggest use fromp()/top() instead of lhsp/rhsp(). -public: - AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(CastDynamic) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstCastDynamic(this->fileline(), lhsp, rhsp); - } - virtual string emitVerilog() override { return "%f$cast(%r, %l)"; } - virtual string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 20; } - virtual bool isPure() const override { return true; } - AstNode* fromp() const { return lhsp(); } - AstNode* top() const { return rhsp(); } -}; - -class AstCastParse final : public AstNode { - // Cast to appropriate type, where we haven't determined yet what the data type is -public: - AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp) - : ASTGEN_SUPER_CastParse(fl) { - setOp1p(lhsp); - setOp2p(dtp); - } - ASTNODE_NODE_FUNCS(CastParse) - virtual string emitVerilog() { return "((%d)'(%l))"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - AstNode* lhsp() const { return op1p(); } - AstNode* dtp() const { return op2p(); } -}; - -class AstCastSize final : public AstNode { - // Cast to specific size; signed/twostate inherited from lower element per IEEE -public: - AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp) - : ASTGEN_SUPER_CastSize(fl) { - setOp1p(lhsp); - setOp2p(rhsp); - } - ASTNODE_NODE_FUNCS(CastSize) - // No hasDType because widthing removes this node before the hasDType check - virtual string emitVerilog() { return "((%r)'(%l))"; } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } -}; - -class AstCCast final : public AstNodeUniop { - // Cast to C-based data type -private: - int m_size; - -public: - AstCCast(FileLine* fl, AstNode* lhsp, int setwidth, int minwidth = -1) - : ASTGEN_SUPER_CCast(fl, lhsp) { - m_size = setwidth; - if (setwidth) { - if (minwidth == -1) minwidth = setwidth; - dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED); - } - } - AstCCast(FileLine* fl, AstNode* lhsp, AstNode* typeFromp) - : ASTGEN_SUPER_CCast(fl, lhsp) { - dtypeFrom(typeFromp); - m_size = width(); - } - ASTNODE_NODE_FUNCS(CCast) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } - virtual string emitVerilog() override { return "%f$_CAST(%l)"; } - virtual string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast - virtual bool same(const AstNode* samep) const override { - return size() == static_cast(samep)->size(); - } - virtual void dump(std::ostream& str = std::cout) const override; - // - int size() const { return m_size; } -}; - -class AstCvtPackString final : public AstNodeUniop { - // Convert to Verilator Packed String (aka verilog "string") -public: - AstCvtPackString(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CvtPackString(fl, lhsp) { - dtypeSetString(); - } - ASTNODE_NODE_FUNCS(CvtPackString) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$_CAST(%l)"; } - virtual string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstFEof final : public AstNodeUniop { -public: - AstFEof(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_FEof(fl, lhsp) {} - ASTNODE_NODE_FUNCS(FEof) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$feof(%l)"; } - virtual string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - AstNode* filep() const { return lhsp(); } -}; - -class AstFError final : public AstNodeMath { -public: - AstFError(FileLine* fl, AstNode* filep, AstNode* strp) - : ASTGEN_SUPER_FError(fl) { - setOp1p(filep); - setOp2p(strp); - } - ASTNODE_NODE_FUNCS(FError) - virtual string emitVerilog() override { return "%f$ferror(%l, %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - void filep(AstNode* nodep) { setOp1p(nodep); } - AstNode* filep() const { return op1p(); } - void strp(AstNode* nodep) { setOp2p(nodep); } - AstNode* strp() const { return op2p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstFGetC final : public AstNodeUniop { -public: - AstFGetC(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_FGetC(fl, lhsp) {} - ASTNODE_NODE_FUNCS(FGetC) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$fgetc(%l)"; } - // Non-existent filehandle returns EOF - virtual string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - AstNode* filep() const { return lhsp(); } -}; - -class AstFUngetC final : public AstNodeBiop { -public: - AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(FUngetC) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstFUngetC(this->fileline(), lhsp, rhsp); - } - virtual string emitVerilog() override { return "%f$ungetc(%r, %l)"; } - // Non-existent filehandle returns EOF - virtual string emitC() override { - return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - AstNode* filep() const { return lhsp(); } - AstNode* charp() const { return rhsp(); } -}; - -class AstNodeSystemUniop VL_NOT_FINAL : public AstNodeUniop { -public: - AstNodeSystemUniop(VNType t, FileLine* fl, AstNode* lhsp) - : AstNodeUniop(t, fl, lhsp) { - dtypeSetDouble(); - } - ASTNODE_BASE_FUNCS(NodeSystemUniop) - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } - virtual bool doubleFlavor() const override { return true; } -}; - -class AstLogD final : public AstNodeSystemUniop { -public: - AstLogD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_LogD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(LogD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::log(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$ln(%l)"; } - virtual string emitC() override { return "log(%li)"; } -}; -class AstLog10D final : public AstNodeSystemUniop { -public: - AstLog10D(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_Log10D(fl, lhsp) {} - ASTNODE_NODE_FUNCS(Log10D) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::log10(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$log10(%l)"; } - virtual string emitC() override { return "log10(%li)"; } -}; - -class AstExpD final : public AstNodeSystemUniop { -public: - AstExpD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_ExpD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(ExpD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::exp(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$exp(%l)"; } - virtual string emitC() override { return "exp(%li)"; } -}; - -class AstSqrtD final : public AstNodeSystemUniop { -public: - AstSqrtD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_SqrtD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(SqrtD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::sqrt(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$sqrt(%l)"; } - virtual string emitC() override { return "sqrt(%li)"; } -}; - -class AstFloorD final : public AstNodeSystemUniop { -public: - AstFloorD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_FloorD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(FloorD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::floor(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$floor(%l)"; } - virtual string emitC() override { return "floor(%li)"; } -}; - -class AstCeilD final : public AstNodeSystemUniop { -public: - AstCeilD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CeilD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CeilD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::ceil(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$ceil(%l)"; } - virtual string emitC() override { return "ceil(%li)"; } -}; - -class AstSinD final : public AstNodeSystemUniop { -public: - AstSinD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_SinD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(SinD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::sin(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$sin(%l)"; } - virtual string emitC() override { return "sin(%li)"; } -}; - -class AstCosD final : public AstNodeSystemUniop { -public: - AstCosD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CosD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CosD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::cos(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$cos(%l)"; } - virtual string emitC() override { return "cos(%li)"; } -}; - -class AstTanD final : public AstNodeSystemUniop { -public: - AstTanD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_TanD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(TanD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::tan(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$tan(%l)"; } - virtual string emitC() override { return "tan(%li)"; } -}; - -class AstAsinD final : public AstNodeSystemUniop { -public: - AstAsinD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_AsinD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AsinD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::asin(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$asin(%l)"; } - virtual string emitC() override { return "asin(%li)"; } -}; - -class AstAcosD final : public AstNodeSystemUniop { -public: - AstAcosD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_AcosD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AcosD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::acos(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$acos(%l)"; } - virtual string emitC() override { return "acos(%li)"; } -}; - -class AstAtanD final : public AstNodeSystemUniop { -public: - AstAtanD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_AtanD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AtanD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::atan(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$atan(%l)"; } - virtual string emitC() override { return "atan(%li)"; } -}; - -class AstSinhD final : public AstNodeSystemUniop { -public: - AstSinhD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_SinhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(SinhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::sinh(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$sinh(%l)"; } - virtual string emitC() override { return "sinh(%li)"; } -}; - -class AstCoshD final : public AstNodeSystemUniop { -public: - AstCoshD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CoshD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CoshD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::cosh(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$cosh(%l)"; } - virtual string emitC() override { return "cosh(%li)"; } -}; - -class AstTanhD final : public AstNodeSystemUniop { -public: - AstTanhD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_TanhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(TanhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::tanh(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$tanh(%l)"; } - virtual string emitC() override { return "tanh(%li)"; } -}; - -class AstAsinhD final : public AstNodeSystemUniop { -public: - AstAsinhD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_AsinhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AsinhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::asinh(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$asinh(%l)"; } - virtual string emitC() override { return "asinh(%li)"; } -}; - -class AstAcoshD final : public AstNodeSystemUniop { -public: - AstAcoshD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_AcoshD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AcoshD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::acosh(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$acosh(%l)"; } - virtual string emitC() override { return "acosh(%li)"; } -}; - -class AstAtanhD final : public AstNodeSystemUniop { -public: - AstAtanhD(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_AtanhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AtanhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.setDouble(std::atanh(lhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$atanh(%l)"; } - virtual string emitC() override { return "atanh(%li)"; } -}; -class AstToLowerN final : public AstNodeUniop { - // string.tolower() -public: - AstToLowerN(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_ToLowerN(fl, lhsp) { - dtypeSetString(); - } - ASTNODE_NODE_FUNCS(ToLowerN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opToLowerN(lhs); - } - virtual string emitVerilog() override { return "%l.tolower()"; } - virtual string emitC() override { return "VL_TOLOWER_NN(%li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstToUpperN final : public AstNodeUniop { - // string.toupper() -public: - AstToUpperN(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_ToUpperN(fl, lhsp) { - dtypeSetString(); - } - ASTNODE_NODE_FUNCS(ToUpperN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opToUpperN(lhs); - } - virtual string emitVerilog() override { return "%l.toupper()"; } - virtual string emitC() override { return "VL_TOUPPER_NN(%li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } -}; -class AstTimeImport final : public AstNodeUniop { - // Take a constant that represents a time and needs conversion based on time units - VTimescale m_timeunit; // Parent module time unit -public: - AstTimeImport(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_TimeImport(fl, lhsp) {} - ASTNODE_NODE_FUNCS(TimeImport) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual void dump(std::ostream& str = std::cout) const override; - void timeunit(const VTimescale& flag) { m_timeunit = flag; } - VTimescale timeunit() const { return m_timeunit; } -}; - -class AstAtoN final : public AstNodeUniop { - // string.atoi(), atobin(), atohex(), atooct(), atoireal() -public: - enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 }; - -private: - const FmtType m_fmt; // Operation type -public: - AstAtoN(FileLine* fl, AstNode* lhsp, FmtType fmt) - : ASTGEN_SUPER_AtoN(fl, lhsp) - , m_fmt{fmt} { - fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32(); - } - ASTNODE_NODE_FUNCS(AtoN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opAtoN(lhs, m_fmt); - } - virtual string name() const override { - switch (m_fmt) { - case ATOI: return "atoi"; - case ATOHEX: return "atohex"; - case ATOOCT: return "atooct"; - case ATOBIN: return "atobin"; - case ATOREAL: return "atoreal"; - default: V3ERROR_NA; - } - } - virtual string emitVerilog() override { return "%l." + name() + "()"; } - virtual string emitC() override { - switch (m_fmt) { - case ATOI: return "VL_ATOI_N(%li, 10)"; - case ATOHEX: return "VL_ATOI_N(%li, 16)"; - case ATOOCT: return "VL_ATOI_N(%li, 8)"; - case ATOBIN: return "VL_ATOI_N(%li, 2)"; - case ATOREAL: return "std::atof(%li.c_str())"; - default: V3ERROR_NA; - } - } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - FmtType format() const { return m_fmt; } -}; - -//====================================================================== -// Binary ops - -class AstLogOr final : public AstNodeBiop { - // LOGOR with optional side effects - // Side effects currently used in some V3Width code - // TBD if this concept is generally adopted for side-effect tracking - // versus V3Const tracking it itself - bool m_sideEffect = false; // Has side effect, relies on short-circuiting -public: - AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LogOr(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LogOr) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLogOr(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLogOr(lhs, rhs); - } - virtual bool same(const AstNode* samep) const override { - const AstLogOr* const sp = static_cast(samep); - return m_sideEffect == sp->m_sideEffect; - } - virtual void dump(std::ostream& str = std::cout) const override; - virtual string emitVerilog() override { return "%k(%l %f|| %r)"; } - virtual string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "||"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } - virtual bool isPure() const override { return !m_sideEffect; } - void sideEffect(bool flag) { m_sideEffect = flag; } - bool sideEffect() const { return m_sideEffect; } -}; -class AstLogAnd final : public AstNodeBiop { -public: - AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LogAnd(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LogAnd) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLogAnd(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLogAnd(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f&& %r)"; } - virtual string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "&&"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } -}; -class AstLogEq final : public AstNodeBiCom { -public: - AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LogEq(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LogEq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLogEq(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLogEq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f<-> %r)"; } - virtual string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "<->"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } -}; -class AstLogIf final : public AstNodeBiop { -public: - AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LogIf(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LogIf) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLogIf(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLogIf(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f-> %r)"; } - virtual string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "->"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } -}; -class AstOr final : public AstNodeBiComAsv { -public: - AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Or(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Or) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstOr(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opOr(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f| %r)"; } - virtual string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "|"; } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstAnd final : public AstNodeBiComAsv { -public: - AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_And(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(And) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAnd(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opAnd(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f& %r)"; } - virtual string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "&"; } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstXor final : public AstNodeBiComAsv { -public: - AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Xor(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Xor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstXor(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opXor(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f^ %r)"; } - virtual string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "^"; } - virtual bool cleanOut() const override { return false; } // Lclean && Rclean - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstEq final : public AstNodeBiCom { -public: - AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Eq(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Eq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstEq(this->fileline(), lhsp, rhsp); - } - static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, - AstNode* rhsp); // Return AstEq/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opEq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f== %r)"; } - virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstEqD final : public AstNodeBiCom { -public: - AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_EqD(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(EqD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstEqD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opEqD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f== %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstEqN final : public AstNodeBiCom { -public: - AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_EqN(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(EqN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstEqN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opEqN(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f== %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstNeq final : public AstNodeBiCom { -public: - AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Neq(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Neq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstNeq(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opNeq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } - virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstNeqD final : public AstNodeBiCom { -public: - AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_NeqD(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(NeqD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstNeqD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opNeqD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstNeqN final : public AstNodeBiCom { -public: - AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_NeqN(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(NeqN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstNeqN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opNeqN(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstLt final : public AstNodeBiop { -public: - AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Lt(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Lt) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLt(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLt(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "<"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstLtD final : public AstNodeBiop { -public: - AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LtD(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LtD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLtD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLtD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstLtS final : public AstNodeBiop { -public: - AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LtS(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LtS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLtS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLtS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } -}; -class AstLtN final : public AstNodeBiop { -public: - AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LtN(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LtN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLtN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLtN(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstGt final : public AstNodeBiop { -public: - AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Gt(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Gt) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGt(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGt(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ">"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstGtD final : public AstNodeBiop { -public: - AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GtD(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(GtD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGtD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGtD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstGtS final : public AstNodeBiop { -public: - AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GtS(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(GtS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGtS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGtS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } -}; -class AstGtN final : public AstNodeBiop { -public: - AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GtN(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(GtN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGtN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGtN(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstGte final : public AstNodeBiop { -public: - AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Gte(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Gte) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGte(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGte(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ">="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstGteD final : public AstNodeBiop { -public: - AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GteD(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(GteD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGteD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGteD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstGteS final : public AstNodeBiop { -public: - AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GteS(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(GteS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGteS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGteS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } -}; -class AstGteN final : public AstNodeBiop { -public: - AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GteN(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(GteN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGteN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGteN(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstLte final : public AstNodeBiop { -public: - AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Lte(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(Lte) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLte(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLte(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "<="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstLteD final : public AstNodeBiop { -public: - AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LteD(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LteD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLteD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLteD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstLteS final : public AstNodeBiop { -public: - AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LteS(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LteS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLteS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLteS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } -}; -class AstLteN final : public AstNodeBiop { -public: - AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_LteN(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(LteN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstLteN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opLteN(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstShiftL final : public AstNodeBiop { -public: - AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) - : ASTGEN_SUPER_ShiftL(fl, lhsp, rhsp) { - if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(ShiftL) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstShiftL(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opShiftL(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f<< %r)"; } - virtual string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { - return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<"; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstShiftR final : public AstNodeBiop { -public: - AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) - : ASTGEN_SUPER_ShiftR(fl, lhsp, rhsp) { - if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(ShiftR) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstShiftR(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opShiftR(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f>> %r)"; } - virtual string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { - return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>"; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - // LHS size might be > output size, so don't want to force size - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstShiftRS final : public AstNodeBiop { - // Shift right with sign extension, >>> operator - // Output data type's width determines which bit is used for sign extension -public: - AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0) - : ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) { - // Important that widthMin be correct, as opExtend requires it after V3Expand - if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED); - } - ASTNODE_NODE_FUNCS(ShiftRS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstShiftRS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opShiftRS(lhs, rhs, lhsp()->widthMinV()); - } - virtual string emitVerilog() override { return "%k(%l %f>>> %r)"; } - virtual string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } -}; -class AstAdd final : public AstNodeBiComAsv { -public: - AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Add(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Add) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAdd(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opAdd(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } - virtual string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "+"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } -}; -class AstAddD final : public AstNodeBiComAsv { -public: - AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_AddD(fl, lhsp, rhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(AddD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAddD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opAddD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "+"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstSub final : public AstNodeBiop { -public: - AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Sub(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Sub) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstSub(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opSub(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f- %r)"; } - virtual string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } -}; -class AstSubD final : public AstNodeBiop { -public: - AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_SubD(fl, lhsp, rhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(SubD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstSubD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opSubD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f- %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstMul final : public AstNodeBiComAsv { -public: - AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Mul(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Mul) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstMul(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opMul(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f* %r)"; } - virtual string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "*"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } -}; -class AstMulD final : public AstNodeBiComAsv { -public: - AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_MulD(fl, lhsp, rhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(MulD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstMulD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opMulD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f* %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "*"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstMulS final : public AstNodeBiComAsv { -public: - AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_MulS(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(MulS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstMulS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opMulS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f* %r)"; } - virtual string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } - virtual bool signedFlavor() const override { return true; } -}; -class AstDiv final : public AstNodeBiop { -public: - AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Div(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Div) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstDiv(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opDiv(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } - virtual string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } -}; -class AstDivD final : public AstNodeBiop { -public: - AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_DivD(fl, lhsp, rhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(DivD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstDivD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opDivD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "/"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstDivS final : public AstNodeBiop { -public: - AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_DivS(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(DivS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstDivS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opDivS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } - virtual string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } - virtual bool signedFlavor() const override { return true; } -}; -class AstModDiv final : public AstNodeBiop { -public: - AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_ModDiv(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(ModDiv) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstModDiv(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opModDiv(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } - virtual string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } -}; -class AstModDivS final : public AstNodeBiop { -public: - AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_ModDivS(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(ModDivS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstModDivS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opModDivS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } - virtual string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } - virtual bool signedFlavor() const override { return true; } -}; -class AstPow final : public AstNodeBiop { -public: - AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Pow(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(Pow) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstPow(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opPow(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } -}; -class AstPowD final : public AstNodeBiop { -public: - AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_PowD(fl, lhsp, rhsp) { - dtypeSetDouble(); - } - ASTNODE_NODE_FUNCS(PowD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstPowD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opPowD(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { return "pow(%li,%ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; } - virtual bool doubleFlavor() const override { return true; } -}; -class AstPowSU final : public AstNodeBiop { -public: - AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_PowSU(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(PowSU) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstPowSU(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opPowSU(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { - return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; - } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } - virtual bool signedFlavor() const override { return true; } -}; -class AstPowSS final : public AstNodeBiop { -public: - AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_PowSS(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(PowSS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstPowSS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opPowSS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { - return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; - } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } - virtual bool signedFlavor() const override { return true; } -}; -class AstPowUS final : public AstNodeBiop { -public: - AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_PowUS(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(PowUS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstPowUS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opPowUS(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { - return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; - } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } - virtual bool signedFlavor() const override { return true; } -}; -class AstPreAdd final : public AstNodeTriop { - // Pre-increment/add - // Parents: MATH - // Children: lhsp: AstConst (1) as currently support only ++ not += - // Children: rhsp: tree with AstVarRef that is value to read before operation - // Children: thsp: tree with AstVarRef LValue that is stored after operation -public: - AstPreAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) - : ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PreAdd) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { - V3ERROR_NA; // Need to modify lhs - } - virtual string emitVerilog() override { return "%k(++%r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } -}; -class AstPreSub final : public AstNodeTriop { - // Pre-decrement/subtract - // Parents: MATH - // Children: lhsp: AstConst (1) as currently support only -- not -= - // Children: rhsp: tree with AstVarRef that is value to read before operation - // Children: thsp: tree with AstVarRef LValue that is stored after operation -public: - AstPreSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) - : ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PreSub) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { - V3ERROR_NA; // Need to modify lhs - } - virtual string emitVerilog() override { return "%k(--%r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } -}; -class AstPostAdd final : public AstNodeTriop { - // Post-increment/add - // Parents: MATH - // Children: lhsp: AstConst (1) as currently support only ++ not += - // Children: rhsp: tree with AstVarRef that is value to read before operation - // Children: thsp: tree with AstVarRef LValue that is stored after operation -public: - AstPostAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) - : ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PostAdd) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { - V3ERROR_NA; // Need to modify lhs - } - virtual string emitVerilog() override { return "%k(%r++)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } -}; -class AstPostSub final : public AstNodeTriop { - // Post-decrement/subtract - // Parents: MATH - // Children: lhsp: AstConst (1) as currently support only -- not -= - // Children: rhsp: tree with AstVarRef that is value to read before operation - // Children: thsp: tree with AstVarRef LValue that is stored after operation -public: - AstPostSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) - : ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PostSub) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { - V3ERROR_NA; // Need to modify lhs - } - virtual string emitVerilog() override { return "%k(%r--)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } -}; -class AstEqCase final : public AstNodeBiCom { -public: - AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_EqCase(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(EqCase) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstEqCase(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opCaseEq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f=== %r)"; } - virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstNeqCase final : public AstNodeBiCom { -public: - AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_NeqCase(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(NeqCase) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstNeqCase(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opCaseNeq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f!== %r)"; } - virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstEqWild final : public AstNodeBiop { - // Note wildcard operator rhs differs from lhs -public: - AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_EqWild(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(EqWild) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstEqWild(this->fileline(), lhsp, rhsp); - } - static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, - AstNode* rhsp); // Return AstEqWild/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opWildEq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f==? %r)"; } - virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstNeqWild final : public AstNodeBiop { -public: - AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_NeqWild(fl, lhsp, rhsp) { - dtypeSetBit(); - } - ASTNODE_NODE_FUNCS(NeqWild) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstNeqWild(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opWildNeq(lhs, rhs); - } - virtual string emitVerilog() override { return "%k(%l %f!=? %r)"; } - virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstConcat final : public AstNodeBiop { - // If you're looking for {#{}}, see AstReplicate -public: - AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Concat(fl, lhsp, rhsp) { - if (lhsp->dtypep() && rhsp->dtypep()) { - dtypeSetLogicSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(), - VSigning::UNSIGNED); - } - } - ASTNODE_NODE_FUNCS(Concat) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstConcat(this->fileline(), lhsp, rhsp); - } - virtual string emitVerilog() override { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opConcat(lhs, rhs); - } - virtual string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } -}; -class AstConcatN final : public AstNodeBiop { - // String concatenate -public: - AstConcatN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_ConcatN(fl, lhsp, rhsp) { - dtypeSetString(); - } - ASTNODE_NODE_FUNCS(ConcatN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstConcatN(this->fileline(), lhsp, rhsp); - } - virtual string emitVerilog() override { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opConcatN(lhs, rhs); - } - virtual string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } -}; -class AstReplicate final : public AstNodeBiop { - // Also used as a "Uniop" flavor of Concat, e.g. "{a}" - // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp() -public: - AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Replicate(fl, lhsp, rhsp) { - if (lhsp) { - if (const AstConst* const constp = VN_CAST(rhsp, Const)) { - dtypeSetLogicSized(lhsp->width() * constp->toUInt(), VSigning::UNSIGNED); - } - } - } - AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount) - : AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {} - ASTNODE_NODE_FUNCS(Replicate) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstReplicate(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opRepl(lhs, rhs); - } - virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } - virtual string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } -}; -class AstReplicateN final : public AstNodeBiop { - // String replicate -public: - AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_ReplicateN(fl, lhsp, rhsp) { - dtypeSetString(); - } - AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount) - : AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {} - ASTNODE_NODE_FUNCS(ReplicateN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstReplicateN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opReplN(lhs, rhs); - } - virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } - virtual string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } - virtual bool stringFlavor() const override { return true; } -}; -class AstStreamL final : public AstNodeStream { - // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() -public: - AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(StreamL) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstStreamL(this->fileline(), lhsp, rhsp); - } - virtual string emitVerilog() override { return "%f{ << %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opStreamL(lhs, rhs); - } - virtual string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } -}; -class AstStreamR final : public AstNodeStream { - // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() -public: - AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(StreamR) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstStreamR(this->fileline(), lhsp, rhsp); - } - virtual string emitVerilog() override { return "%f{ >> %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opAssign(lhs); - } - virtual string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } -}; -class AstBufIf1 final : public AstNodeBiop { - // lhs is enable, rhs is data to drive - // Note unlike the Verilog bufif1() UDP, this allows any width; each lhsp - // bit enables respective rhsp bit -public: - AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_BufIf1(fl, lhsp, rhsp) { - dtypeFrom(lhsp); - } - ASTNODE_NODE_FUNCS(BufIf1) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstBufIf1(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opBufIf1(lhs, rhs); - } - virtual string emitVerilog() override { return "bufif(%r,%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; -class AstFGetS final : public AstNodeBiop { -public: - AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(FGetS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstFGetS(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { return "%f$fgets(%l,%r)"; } - virtual string emitC() override { - return strgp()->dtypep()->basicp()->isString() ? "VL_FGETS_NI(%li, %ri)" - : "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - AstNode* strgp() const { return lhsp(); } - AstNode* filep() const { return rhsp(); } -}; - -class AstNodeSystemBiop VL_NOT_FINAL : public AstNodeBiop { -public: - AstNodeSystemBiop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : AstNodeBiop(t, fl, lhsp, rhsp) { - dtypeSetDouble(); - } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } - virtual bool doubleFlavor() const override { return true; } -}; - -class AstAtan2D final : public AstNodeSystemBiop { -public: - AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(Atan2D) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstAtan2D(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.setDouble(std::atan2(lhs.toDouble(), rhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$atan2(%l,%r)"; } - virtual string emitC() override { return "atan2(%li,%ri)"; } -}; - -class AstHypotD final : public AstNodeSystemBiop { -public: - AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(HypotD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstHypotD(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.setDouble(std::hypot(lhs.toDouble(), rhs.toDouble())); - } - virtual string emitVerilog() override { return "%f$hypot(%l,%r)"; } - virtual string emitC() override { return "hypot(%li,%ri)"; } -}; - -class AstPutcN final : public AstNodeTriop { - // Verilog string.putc() -public: - AstPutcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) - : ASTGEN_SUPER_PutcN(fl, lhsp, rhsp, ths) { - dtypeSetString(); - } - ASTNODE_NODE_FUNCS(PutcN) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { - out.opPutcN(lhs, rhs, ths); - } - virtual string name() const override { return "putc"; } - virtual string emitVerilog() override { return "%k(%l.putc(%r,%t))"; } - virtual string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } -}; - -class AstGetcN final : public AstNodeBiop { - // Verilog string.getc() -public: - AstGetcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GetcN(fl, lhsp, rhsp) { - dtypeSetBitSized(8, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(GetcN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGetcN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opGetcN(lhs, rhs); - } - virtual string name() const override { return "getc"; } - virtual string emitVerilog() override { return "%k(%l.getc(%r))"; } - virtual string emitC() override { return "VL_GETC_N(%li,%ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; - -class AstGetcRefN final : public AstNodeBiop { - // Verilog string[#] on the left-hand-side of assignment - // Spec says is of type byte (not string of single character) -public: - AstGetcRefN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : ASTGEN_SUPER_GetcRefN(fl, lhsp, rhsp) { - dtypeSetBitSized(8, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(GetcRefN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstGetcRefN(this->fileline(), lhsp, rhsp); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - V3ERROR_NA; - } - virtual string emitVerilog() override { return "%k%l[%r]"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; - -class AstSubstrN final : public AstNodeTriop { - // Verilog string.substr() -public: - AstSubstrN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths) - : ASTGEN_SUPER_SubstrN(fl, lhsp, rhsp, ths) { - dtypeSetString(); - } - ASTNODE_NODE_FUNCS(SubstrN) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { - out.opSubstrN(lhs, rhs, ths); - } - virtual string name() const override { return "substr"; } - virtual string emitVerilog() override { return "%k(%l.substr(%r,%t))"; } - virtual string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } -}; - -class AstCompareNN final : public AstNodeBiop { - // Verilog str.compare() and str.icompare() -private: - const bool m_ignoreCase; // True for str.icompare() -public: - AstCompareNN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, bool ignoreCase) - : ASTGEN_SUPER_CompareNN(fl, lhsp, rhsp) - , m_ignoreCase{ignoreCase} { - dtypeSetUInt32(); - } - ASTNODE_NODE_FUNCS(CompareNN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase); - } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { - out.opCompareNN(lhs, rhs, m_ignoreCase); - } - virtual string name() const override { return m_ignoreCase ? "icompare" : "compare"; } - virtual string emitVerilog() override { - return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))"; - } - virtual string emitC() override { - return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)"; - } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } -}; - -class AstFell final : public AstNodeMath { - // Verilog $fell - // Parents: math - // Children: expression -public: - AstFell(FileLine* fl, AstNode* exprp) - : ASTGEN_SUPER_Fell(fl) { - addOp1p(exprp); - } - ASTNODE_NODE_FUNCS(Fell) - virtual string emitVerilog() override { return "$fell(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstPast final : public AstNodeMath { - // Verilog $past - // Parents: math - // Children: expression -public: - AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp) - : ASTGEN_SUPER_Past(fl) { - addOp1p(exprp); - addNOp2p(ticksp); - } - ASTNODE_NODE_FUNCS(Past) - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstNode* ticksp() const { return op2p(); } // op2 = ticks or nullptr means 1 - AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain - void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstRose final : public AstNodeMath { - // Verilog $rose - // Parents: math - // Children: expression -public: - AstRose(FileLine* fl, AstNode* exprp) - : ASTGEN_SUPER_Rose(fl) { - addOp1p(exprp); - } - ASTNODE_NODE_FUNCS(Rose) - virtual string emitVerilog() override { return "$rose(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstSampled final : public AstNodeMath { - // Verilog $sampled - // Parents: math - // Children: expression -public: - AstSampled(FileLine* fl, AstNode* exprp) - : ASTGEN_SUPER_Sampled(fl) { - addOp1p(exprp); - } - ASTNODE_NODE_FUNCS(Sampled) - virtual string emitVerilog() override { return "$sampled(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return 0; } - AstNode* exprp() const { return op1p(); } // op1 = expression - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstStable final : public AstNodeMath { - // Verilog $stable - // Parents: math - // Children: expression -public: - AstStable(FileLine* fl, AstNode* exprp) - : ASTGEN_SUPER_Stable(fl) { - addOp1p(exprp); - } - ASTNODE_NODE_FUNCS(Stable) - virtual string emitVerilog() override { return "$stable(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -class AstPattern final : public AstNodeMath { - // Verilog '{a,b,c,d...} - // Parents: AstNodeAssign, AstPattern, ... - // Children: expression, AstPattern, AstPatReplicate -public: - AstPattern(FileLine* fl, AstNode* itemsp) - : ASTGEN_SUPER_Pattern(fl) { - addNOp2p(itemsp); - } - ASTNODE_NODE_FUNCS(Pattern) - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - // op1 = Type assigning to - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - AstNode* itemsp() const { return op2p(); } // op2 = AstPatReplicate, AstPatMember, etc - void addItemsp(AstNode* nodep) { addOp2p(nodep); } -}; -class AstPatMember final : public AstNodeMath { - // Verilog '{a} or '{a{b}} - // Parents: AstPattern - // Children: expression, AstPattern, replication count -private: - bool m_default = false; - -public: - AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) - : ASTGEN_SUPER_PatMember(fl) { - addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); - } - ASTNODE_NODE_FUNCS(PatMember) - virtual string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs() * 2; } - virtual void dump(std::ostream& str = std::cout) const override; - // op1 = expression to assign or another AstPattern (list if replicated) - AstNode* lhssp() const { return op1p(); } - AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) - AstNode* repp() const { return op3p(); } // op3 = replication count, or nullptr for count 1 - bool isDefault() const { return m_default; } - void isDefault(bool flag) { m_default = flag; } -}; - -class AstImplication final : public AstNodeMath { - // Verilog |-> |=> - // Parents: math - // Children: expression -public: - AstImplication(FileLine* fl, AstNode* lhs, AstNode* rhs) - : ASTGEN_SUPER_Implication(fl) { - setOp1p(lhs); - setOp2p(rhs); - } - ASTNODE_NODE_FUNCS(Implication) - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain - void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -//====================================================================== -// Assertions - -class AstClocking final : public AstNode { - // Set default clock region - // Parents: MODULE - // Children: Assertions -public: - AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp) - : ASTGEN_SUPER_Clocking(fl) { - addOp1p(sensesp); - addNOp2p(bodysp); - } - ASTNODE_NODE_FUNCS(Clocking) - // op1 = Sensitivity list - AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } - AstNode* bodysp() const { return op2p(); } // op2 = Body -}; - -//====================================================================== -// PSL - -class AstPropClocked final : public AstNode { - // A clocked property - // Parents: ASSERT|COVER (property) - // Children: SENITEM, Properties -public: - AstPropClocked(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp) - : ASTGEN_SUPER_PropClocked(fl) { - addNOp1p(sensesp); - addNOp2p(disablep); - addOp3p(propp); - } - ASTNODE_NODE_FUNCS(PropClocked) - virtual bool hasDType() const override { - return true; - } // Used under Cover, which expects a bool child - AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } // op1 = Sensitivity list - AstNode* disablep() const { return op2p(); } // op2 = disable - AstNode* propp() const { return op3p(); } // op3 = property -}; - -class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt { - // Cover or Assert - // Parents: {statement list} - // Children: expression, report string -private: - const bool m_immediate; // Immediate assertion/cover - string m_name; // Name to report -public: - AstNodeCoverOrAssert(VNType t, FileLine* fl, AstNode* propp, AstNode* passsp, bool immediate, - const string& name = "") - : AstNodeStmt{t, fl} - , m_immediate{immediate} - , m_name{name} { - addOp1p(propp); - addNOp4p(passsp); - } - ASTNODE_BASE_FUNCS(NodeCoverOrAssert) - virtual string name() const override { return m_name; } // * = Var name - virtual bool same(const AstNode* samep) const override { return samep->name() == name(); } - virtual void name(const string& name) override { m_name = name; } - virtual void dump(std::ostream& str = std::cout) const override; - AstNode* propp() const { return op1p(); } // op1 = property - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - AstNode* passsp() const { return op4p(); } // op4 = statements (assert/cover passes) - bool immediate() const { return m_immediate; } -}; - -class AstAssert final : public AstNodeCoverOrAssert { -public: - ASTNODE_NODE_FUNCS(Assert) - AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, - const string& name = "") - : ASTGEN_SUPER_Assert(fl, propp, passsp, immediate, name) { - addNOp3p(failsp); - } - AstNode* failsp() const { return op3p(); } // op3 = if assertion fails -}; - -class AstAssertIntrinsic final : public AstNodeCoverOrAssert { - // A $cast or other compiler inserted assert, that must run even without --assert option -public: - ASTNODE_NODE_FUNCS(AssertIntrinsic) - AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, - bool immediate, const string& name = "") - : ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, immediate, name) { - addNOp3p(failsp); - } - AstNode* failsp() const { return op3p(); } // op3 = if assertion fails -}; - -class AstCover final : public AstNodeCoverOrAssert { -public: - ASTNODE_NODE_FUNCS(Cover) - AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate, - const string& name = "") - : ASTGEN_SUPER_Cover(fl, propp, stmtsp, immediate, name) {} - AstNode* coverincp() const { return op3p(); } // op3 = coverage node - void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node - virtual bool immediate() const { return false; } -}; - -class AstRestrict final : public AstNodeCoverOrAssert { -public: - ASTNODE_NODE_FUNCS(Restrict) - AstRestrict(FileLine* fl, AstNode* propp) - : ASTGEN_SUPER_Restrict(fl, propp, nullptr, false, "") {} -}; - -//====================================================================== -// Text based nodes - -class AstNodeSimpleText VL_NOT_FINAL : public AstNodeText { -private: - bool m_tracking; // When emit, it's ok to parse the string to do indentation -public: - AstNodeSimpleText(VNType t, FileLine* fl, const string& textp, bool tracking = false) - : AstNodeText(t, fl, textp) - , m_tracking(tracking) {} - ASTNODE_BASE_FUNCS(NodeSimpleText) - void tracking(bool flag) { m_tracking = flag; } - bool tracking() const { return m_tracking; } -}; - -class AstText final : public AstNodeSimpleText { -public: - AstText(FileLine* fl, const string& textp, bool tracking = false) - : ASTGEN_SUPER_Text(fl, textp, tracking) {} - ASTNODE_NODE_FUNCS(Text) -}; - -class AstTextBlock final : public AstNodeSimpleText { -private: - bool m_commas; // Comma separate emitted children -public: - explicit AstTextBlock(FileLine* fl, const string& textp = "", bool tracking = false, - bool commas = false) - : ASTGEN_SUPER_TextBlock(fl, textp, tracking) - , m_commas(commas) {} - ASTNODE_NODE_FUNCS(TextBlock) - void commas(bool flag) { m_commas = flag; } - bool commas() const { return m_commas; } - AstNode* nodesp() const { return op1p(); } - void addNodep(AstNode* nodep) { addOp1p(nodep); } - void addText(FileLine* fl, const string& textp, bool tracking = false) { - addNodep(new AstText(fl, textp, tracking)); - } -}; - -class AstScCtor final : public AstNodeText { -public: - AstScCtor(FileLine* fl, const string& textp) - : ASTGEN_SUPER_ScCtor(fl, textp) {} - ASTNODE_NODE_FUNCS(ScCtor) - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } -}; - -class AstScDtor final : public AstNodeText { -public: - AstScDtor(FileLine* fl, const string& textp) - : ASTGEN_SUPER_ScDtor(fl, textp) {} - ASTNODE_NODE_FUNCS(ScDtor) - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } -}; - -class AstScHdr final : public AstNodeText { -public: - AstScHdr(FileLine* fl, const string& textp) - : ASTGEN_SUPER_ScHdr(fl, textp) {} - ASTNODE_NODE_FUNCS(ScHdr) - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } -}; - -class AstScImp final : public AstNodeText { -public: - AstScImp(FileLine* fl, const string& textp) - : ASTGEN_SUPER_ScImp(fl, textp) {} - ASTNODE_NODE_FUNCS(ScImp) - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } -}; - -class AstScImpHdr final : public AstNodeText { -public: - AstScImpHdr(FileLine* fl, const string& textp) - : ASTGEN_SUPER_ScImpHdr(fl, textp) {} - ASTNODE_NODE_FUNCS(ScImpHdr) - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } -}; - -class AstScInt final : public AstNodeText { -public: - AstScInt(FileLine* fl, const string& textp) - : ASTGEN_SUPER_ScInt(fl, textp) {} - ASTNODE_NODE_FUNCS(ScInt) - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } -}; - -class AstUCStmt final : public AstNodeStmt { - // User $c statement -public: - AstUCStmt(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_UCStmt(fl) { - addNOp1p(exprsp); - } - ASTNODE_NODE_FUNCS(UCStmt) - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } -}; - -//====================================================================== -// Emitted file nodes - -class AstNodeFile VL_NOT_FINAL : public AstNode { - // Emitted Otput file - // Parents: NETLIST - // Children: AstTextBlock -private: - string m_name; ///< Filename -public: - AstNodeFile(VNType t, FileLine* fl, const string& name) - : AstNode(t, fl) { - m_name = name; - } - ASTNODE_BASE_FUNCS(NodeFile) - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - void tblockp(AstTextBlock* tblockp) { setOp1p(tblockp); } - AstTextBlock* tblockp() { return VN_AS(op1p(), TextBlock); } -}; - -//====================================================================== -// Emit V nodes - -class AstVFile final : public AstNodeFile { - // Verilog output file - // Parents: NETLIST -public: - AstVFile(FileLine* fl, const string& name) - : ASTGEN_SUPER_VFile(fl, name) {} - ASTNODE_NODE_FUNCS(VFile) - virtual void dump(std::ostream& str = std::cout) const override; -}; - -//====================================================================== -// Emit C nodes - -class AstCFile final : public AstNodeFile { - // C++ output file - // Parents: NETLIST -private: - bool m_slow : 1; ///< Compile w/o optimization - bool m_source : 1; ///< Source file (vs header file) - bool m_support : 1; ///< Support file (non systemc) -public: - AstCFile(FileLine* fl, const string& name) - : ASTGEN_SUPER_CFile(fl, name) - , m_slow{false} - , m_source{false} - , m_support{false} {} - ASTNODE_NODE_FUNCS(CFile) - virtual void dump(std::ostream& str = std::cout) const override; - bool slow() const { return m_slow; } - void slow(bool flag) { m_slow = flag; } - bool source() const { return m_source; } - void source(bool flag) { m_source = flag; } - bool support() const { return m_support; } - void support(bool flag) { m_support = flag; } -}; - -class AstCFunc final : public AstNode { - // C++ function - // Parents: MODULE/SCOPE - // Children: VAR/statements -private: - AstScope* m_scopep; - string m_name; - string m_cname; // C name, for dpiExports - string m_rtnType; // void, bool, or other return type - string m_argTypes; // Argument types - string m_ctorInits; // Constructor sub-class inits - string m_ifdef; // #ifdef symbol around this function - VBoolOrUnknown m_isConst; // Function is declared const (*this not changed) - bool m_isStatic : 1; // Function is static (no need for a 'this' pointer) - bool m_isTrace : 1; // Function is related to tracing - bool m_dontCombine : 1; // V3Combine shouldn't compare this func tree, it's special - bool m_declPrivate : 1; // Declare it private - bool m_isFinal : 1; // This is a function corresponding to a SystemVerilog 'final' block - bool m_slow : 1; // Slow routine, called once or just at init time - bool m_funcPublic : 1; // From user public task/function - bool m_isConstructor : 1; // Is C class constructor - bool m_isDestructor : 1; // Is C class destructor - bool m_isMethod : 1; // Is inside a class definition - bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function - // with an explicitly passed 'self' pointer as the first argument - bool m_isInline : 1; // Inline function - bool m_isVirtual : 1; // Virtual function - bool m_entryPoint : 1; // User may call into this top level function - bool m_pure : 1; // Pure function - bool m_dpiContext : 1; // Declared as 'context' DPI import/export function - bool m_dpiExportDispatcher : 1; // This is the DPI export entry point (i.e.: called by user) - bool m_dpiExportImpl : 1; // DPI export implementation (called from DPI dispatcher via lookup) - bool m_dpiImportPrototype : 1; // This is the DPI import prototype (i.e.: provided by user) - bool m_dpiImportWrapper : 1; // Wrapper for invoking DPI import prototype from generated code - bool m_dpiTraceInit : 1; // DPI trace_init -public: - AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType = "") - : ASTGEN_SUPER_CFunc(fl) { - m_isConst = VBoolOrUnknown::BU_UNKNOWN; // Unknown until analyzed - m_scopep = scopep; - m_name = name; - m_rtnType = rtnType; - m_isStatic = false; - m_isTrace = false; - m_dontCombine = false; - m_declPrivate = false; - m_isFinal = false; - m_slow = false; - m_funcPublic = false; - m_isConstructor = false; - m_isDestructor = false; - m_isMethod = true; - m_isLoose = false; - m_isInline = false; - m_isVirtual = false; - m_entryPoint = false; - m_pure = false; - m_dpiContext = false; - m_dpiExportDispatcher = false; - m_dpiExportImpl = false; - m_dpiImportPrototype = false; - m_dpiImportWrapper = false; - m_dpiTraceInit = false; - } - ASTNODE_NODE_FUNCS(CFunc) - virtual string name() const override { return m_name; } - virtual const char* broken() const override { - BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); - return nullptr; - } - virtual void cloneRelink() override { - if (m_scopep && m_scopep->clonep()) m_scopep = m_scopep->clonep(); - } - virtual bool maybePointedTo() const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; - virtual bool same(const AstNode* samep) const override { - const AstCFunc* const asamep = static_cast(samep); - return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid()) - && (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits()) - && isLoose() == asamep->isLoose() - && (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name())); - } - // - virtual void name(const string& name) override { m_name = name; } - virtual int instrCount() const override { - return dpiImportPrototype() ? v3Global.opt.instrCountDpi() : 0; - } - VBoolOrUnknown isConst() const { return m_isConst; } - void isConst(bool flag) { m_isConst.setTrueOrFalse(flag); } - void isConst(VBoolOrUnknown flag) { m_isConst = flag; } - bool isStatic() const { return m_isStatic; } - void isStatic(bool flag) { m_isStatic = flag; } - bool isTrace() const { return m_isTrace; } - void isTrace(bool flag) { m_isTrace = flag; } - void cname(const string& name) { m_cname = name; } - string cname() const { return m_cname; } - AstScope* scopep() const { return m_scopep; } - void scopep(AstScope* nodep) { m_scopep = nodep; } - string rtnTypeVoid() const { return ((m_rtnType == "") ? "void" : m_rtnType); } - bool dontCombine() const { return m_dontCombine || isTrace() || entryPoint(); } - void dontCombine(bool flag) { m_dontCombine = flag; } - bool dontInline() const { return dontCombine() || slow() || funcPublic(); } - bool declPrivate() const { return m_declPrivate; } - void declPrivate(bool flag) { m_declPrivate = flag; } - bool isFinal() const { return m_isFinal; } - void isFinal(bool flag) { m_isFinal = flag; } - bool slow() const { return m_slow; } - void slow(bool flag) { m_slow = flag; } - bool funcPublic() const { return m_funcPublic; } - void funcPublic(bool flag) { m_funcPublic = flag; } - void argTypes(const string& str) { m_argTypes = str; } - string argTypes() const { return m_argTypes; } - void ctorInits(const string& str) { m_ctorInits = str; } - string ctorInits() const { return m_ctorInits; } - void ifdef(const string& str) { m_ifdef = str; } - string ifdef() const { return m_ifdef; } - bool isConstructor() const { return m_isConstructor; } - void isConstructor(bool flag) { m_isConstructor = flag; } - bool isDestructor() const { return m_isDestructor; } - void isDestructor(bool flag) { m_isDestructor = flag; } - bool isMethod() const { return m_isMethod; } - void isMethod(bool flag) { m_isMethod = flag; } - bool isLoose() const { return m_isLoose; } - void isLoose(bool flag) { m_isLoose = flag; } - bool isProperMethod() const { return isMethod() && !isLoose(); } - bool isInline() const { return m_isInline; } - void isInline(bool flag) { m_isInline = flag; } - bool isVirtual() const { return m_isVirtual; } - void isVirtual(bool flag) { m_isVirtual = flag; } - bool entryPoint() const { return m_entryPoint; } - void entryPoint(bool flag) { m_entryPoint = flag; } - bool pure() const { return m_pure; } - void pure(bool flag) { m_pure = flag; } - bool dpiContext() const { return m_dpiContext; } - void dpiContext(bool flag) { m_dpiContext = flag; } - bool dpiExportDispatcher() const { return m_dpiExportDispatcher; } - void dpiExportDispatcher(bool flag) { m_dpiExportDispatcher = flag; } - bool dpiExportImpl() const { return m_dpiExportImpl; } - void dpiExportImpl(bool flag) { m_dpiExportImpl = flag; } - bool dpiImportPrototype() const { return m_dpiImportPrototype; } - void dpiImportPrototype(bool flag) { m_dpiImportPrototype = flag; } - bool dpiImportWrapper() const { return m_dpiImportWrapper; } - void dpiImportWrapper(bool flag) { m_dpiImportWrapper = flag; } - void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; } - bool dpiTraceInit() const { return m_dpiTraceInit; } - // - // If adding node accessors, see below emptyBody - AstNode* argsp() const { return op1p(); } - void addArgsp(AstNode* nodep) { addOp1p(nodep); } - AstNode* initsp() const { return op2p(); } - void addInitsp(AstNode* nodep) { addOp2p(nodep); } - AstNode* stmtsp() const { return op3p(); } - void addStmtsp(AstNode* nodep) { addOp3p(nodep); } - AstNode* finalsp() const { return op4p(); } - void addFinalsp(AstNode* nodep) { addOp4p(nodep); } - // Special methods - bool emptyBody() const { - return argsp() == nullptr && initsp() == nullptr && stmtsp() == nullptr - && finalsp() == nullptr; - } -}; - -class AstCCall final : public AstNodeCCall { - // C++ function call - // Parents: Anything above a statement - // Children: Args to the function - - string m_selfPointer; // Output code object pointer (e.g.: 'this') - -public: - AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) - : ASTGEN_SUPER_CCall(fl, funcp, argsp) {} - ASTNODE_NODE_FUNCS(CCall) - - string selfPointer() const { return m_selfPointer; } - void selfPointer(const string& value) { m_selfPointer = value; } - string selfPointerProtect(bool useSelfForThis) const; -}; - -class AstCMethodCall final : public AstNodeCCall { - // C++ method call - // Parents: Anything above a statement - // Children: Args to the function -public: - AstCMethodCall(FileLine* fl, AstNode* fromp, AstCFunc* funcp, AstNode* argsp = nullptr) - : ASTGEN_SUPER_CMethodCall(fl, funcp, argsp) { - setOp1p(fromp); - } - ASTNODE_NODE_FUNCS(CMethodCall) - virtual const char* broken() const override { - BROKEN_BASE_RTN(AstNodeCCall::broken()); - BROKEN_RTN(!fromp()); - return nullptr; - } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } -}; - -class AstCNew final : public AstNodeCCall { - // C++ new() call - // Parents: Anything above an expression - // Children: Args to the function -public: - AstCNew(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) - : ASTGEN_SUPER_CNew(fl, funcp, argsp) { - statement(false); - } - virtual bool hasDType() const override { return true; } - ASTNODE_NODE_FUNCS(CNew) -}; - -class AstCReturn final : public AstNodeStmt { - // C++ return from a function - // Parents: CFUNC/statement - // Children: Math -public: - AstCReturn(FileLine* fl, AstNode* lhsp) - : ASTGEN_SUPER_CReturn(fl) { - setOp1p(lhsp); - } - ASTNODE_NODE_FUNCS(CReturn) - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - // - AstNode* lhsp() const { return op1p(); } -}; - -class AstCMath final : public AstNodeMath { -private: - const bool m_cleanOut; - bool m_pure; // Pure optimizable -public: - // Emit C textual math function (like AstUCFunc) - AstCMath(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_CMath(fl) - , m_cleanOut{true} - , m_pure{false} { - addOp1p(exprsp); - dtypeFrom(exprsp); - } - AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true) - : ASTGEN_SUPER_CMath(fl) - , m_cleanOut{cleanOut} - , m_pure{true} { - addNOp1p(new AstText(fl, textStmt, true)); - if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); - } - ASTNODE_NODE_FUNCS(CMath) - virtual bool isGateOptimizable() const override { return m_pure; } - virtual bool isPredictOptimizable() const override { return m_pure; } - virtual bool cleanOut() const override { return m_cleanOut; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - void addBodysp(AstNode* nodep) { addNOp1p(nodep); } - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - bool pure() const { return m_pure; } - void pure(bool flag) { m_pure = flag; } -}; - -class AstCReset final : public AstNodeStmt { - // Reset variable at startup -public: - AstCReset(FileLine* fl, AstVarRef* exprsp) - : ASTGEN_SUPER_CReset(fl) { - addNOp1p(exprsp); - } - ASTNODE_NODE_FUNCS(CReset) - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - AstVarRef* varrefp() const { return VN_AS(op1p(), VarRef); } // op1 = varref to reset -}; - -class AstCStmt final : public AstNodeStmt { - // Emit C statement -public: - AstCStmt(FileLine* fl, AstNode* exprsp) - : ASTGEN_SUPER_CStmt(fl) { - addNOp1p(exprsp); - } - AstCStmt(FileLine* fl, const string& textStmt) - : ASTGEN_SUPER_CStmt(fl) { - addNOp1p(new AstText(fl, textStmt, true)); - } - ASTNODE_NODE_FUNCS(CStmt) - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - void addBodysp(AstNode* nodep) { addNOp1p(nodep); } - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print -}; - -class AstCUse final : public AstNode { - // C++ use of a class or #include; indicates need of forward declaration - // Parents: NODEMODULE -private: - const VUseType m_useType; // What sort of use this is - const string m_name; - -public: - AstCUse(FileLine* fl, VUseType useType, const string& name) - : ASTGEN_SUPER_CUse(fl) - , m_useType{useType} - , m_name{name} {} - ASTNODE_NODE_FUNCS(CUse) - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } - VUseType useType() const { return m_useType; } -}; - -class AstMTaskBody final : public AstNode { - // Hold statements for each MTask -private: - ExecMTask* m_execMTaskp = nullptr; - -public: - explicit AstMTaskBody(FileLine* fl) - : ASTGEN_SUPER_MTaskBody(fl) {} - ASTNODE_NODE_FUNCS(MTaskBody); - virtual const char* broken() const override { - BROKEN_RTN(!m_execMTaskp); - return nullptr; - } - AstNode* stmtsp() const { return op1p(); } - void addStmtsp(AstNode* nodep) { addOp1p(nodep); } - void addStmtsFirstp(AstNode* nodep) { - if (stmtsp()) { - stmtsp()->addHereThisAsNext(nodep); - } else { - addStmtsp(nodep); - } - } - ExecMTask* execMTaskp() const { return m_execMTaskp; } - void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; } - virtual void dump(std::ostream& str = std::cout) const override; -}; - -class AstExecGraph final : public AstNode { - // For parallel execution, this node contains a dependency graph. Each - // vertex in the graph is an ExecMTask, which contains a body for the - // mtask (an AstMTaskBody), which contains sequentially executed statements. - // - // The AstMTaskBody nodes are also children of this node, so we can visit - // them without traversing the graph. -private: - V3Graph* const m_depGraphp; // contains ExecMTask vertices - const string m_name; // Name of this AstExecGraph (for uniqueness at code generation) - -public: - explicit AstExecGraph(FileLine* fl, const string& name); - ASTNODE_NODE_FUNCS_NO_DTOR(ExecGraph) - virtual ~AstExecGraph() override; - virtual const char* broken() const override { - BROKEN_RTN(!m_depGraphp); - return nullptr; - } - virtual string name() const override { return m_name; } - V3Graph* depGraphp() { return m_depGraphp; } - const V3Graph* depGraphp() const { return m_depGraphp; } - // op1: The mtask bodies - AstMTaskBody* mTaskBodiesp() const { return VN_AS(op1p(), MTaskBody); } - void addMTaskBodyp(AstMTaskBody* bodyp) { addOp1p(bodyp); } - // op2: In later phases, the statements that start the parallel execution - void addStmtsp(AstNode* stmtp) { addOp2p(stmtp); } -}; - -class AstSplitPlaceholder final : public AstNode { -public: - // Dummy node used within V3Split; never exists outside of V3Split. - explicit AstSplitPlaceholder(FileLine* fl) - : ASTGEN_SUPER_SplitPlaceholder(fl) {} - ASTNODE_NODE_FUNCS(SplitPlaceholder) -}; - -//###################################################################### -// Right below top - -class AstTypeTable final : public AstNode { - // Container for hash of standard data types - // Children: NODEDTYPEs - AstEmptyQueueDType* m_emptyQueuep = nullptr; - AstQueueDType* m_queueIndexp = nullptr; - AstVoidDType* m_voidp = nullptr; - AstBasicDType* m_basicps[VBasicDTypeKwd::_ENUM_MAX]{}; - // - using DetailedMap = std::map; - DetailedMap m_detailedMap; - -public: - explicit AstTypeTable(FileLine* fl); - ASTNODE_NODE_FUNCS(TypeTable) - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { - BROKEN_RTN(m_emptyQueuep && !m_emptyQueuep->brokeExists()); - BROKEN_RTN(m_queueIndexp && !m_queueIndexp->brokeExists()); - BROKEN_RTN(m_voidp && !m_voidp->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { V3ERROR_NA; } - AstNodeDType* typesp() const { return VN_AS(op1p(), NodeDType); } // op1 = List of dtypes - void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); } - AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd); - AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width, int widthMin, - VSigning numeric); - AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, const VNumRange& range, - int widthMin, VSigning numeric); - AstBasicDType* findInsertSameDType(AstBasicDType* nodep); - AstEmptyQueueDType* findEmptyQueueDType(FileLine* fl); - AstQueueDType* findQueueIndexDType(FileLine* fl); - AstVoidDType* findVoidDType(FileLine* fl); - void clearCache(); - void repairCache(); - virtual void dump(std::ostream& str = std::cout) const override; -}; - -class AstConstPool final : public AstNode { - // Container for const static data - std::unordered_multimap m_tables; // Constant tables (unpacked arrays) - std::unordered_multimap m_consts; // Constant tables (scalars) - AstModule* const m_modp; // The Module holding the Scope below ... - AstScope* const m_scopep; // Scope holding the constant variables - - AstVarScope* createNewEntry(const string& name, AstNode* initp); - -public: - explicit AstConstPool(FileLine* fl); - ASTNODE_NODE_FUNCS(ConstPool) - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { - BROKEN_RTN(m_modp && !m_modp->brokeExists()); - BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { V3ERROR_NA; } - AstModule* modp() const { return m_modp; } - - // Find a table (unpacked array) within the constant pool which is initialized with the - // given value, or create one if one does not already exists. The returned VarScope *might* - // have a different dtype than the given initp->dtypep(), including a different element type, - // but it will always have the same size and element width. In contexts where this matters, - // the caller must handle the dtype difference as appropriate. - AstVarScope* findTable(AstInitArray* initp); - // Find a constant within the constant pool which is initialized with the given value, or - // create one if one does not already exists. If 'mergeDType' is true, then the returned - // VarScope *might* have a different type than the given initp->dtypep(). In contexts where - // this matters, the caller must handle the dtype difference as appropriate. If 'mergeDType' is - // false, the returned VarScope will have _->dtypep()->sameTree(initp->dtypep()) return true. - AstVarScope* findConst(AstConst* initp, bool mergeDType); -}; - -//###################################################################### -// Top - -class AstNetlist final : public AstNode { - // All modules are under this single top node. - // Parents: none - // Children: MODULEs & CFILEs -private: - AstTypeTable* const m_typeTablep; // Reference to top type table, for faster lookup - AstConstPool* const m_constPoolp; // Reference to constant pool, for faster lookup - AstPackage* m_dollarUnitPkgp = nullptr; // $unit - AstCFunc* m_evalp = nullptr; // The '_eval' function - AstVarScope* m_dpiExportTriggerp = nullptr; // The DPI export trigger variable - AstTopScope* m_topScopep = nullptr; // The singleton AstTopScope under the top module - VTimescale m_timeunit; // Global time unit - VTimescale m_timeprecision; // Global time precision - bool m_changeRequest = false; // Have _change_request method - bool m_timescaleSpecified = false; // Input HDL specified timescale - uint32_t m_nextFreeMTaskID = 1; // Next unique MTask ID within netlist - // starts at 1 so 0 means no MTask ID - uint32_t m_nextFreeMTaskProfilingID = 0; // Next unique ID to use for PGO -public: - AstNetlist(); - ASTNODE_NODE_FUNCS(Netlist) - virtual const char* broken() const override { - BROKEN_RTN(m_typeTablep && !m_typeTablep->brokeExists()); - BROKEN_RTN(m_constPoolp && !m_constPoolp->brokeExists()); - BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); - BROKEN_RTN(m_evalp && !m_evalp->brokeExists()); - BROKEN_RTN(m_dpiExportTriggerp && !m_dpiExportTriggerp->brokeExists()); - BROKEN_RTN(m_topScopep && !m_topScopep->brokeExists()); - return nullptr; - } - virtual void cloneRelink() override { V3ERROR_NA; } - virtual string name() const override { return "$root"; } - virtual void dump(std::ostream& str) const override; - AstNodeModule* modulesp() const { // op1 = List of modules - return VN_AS(op1p(), NodeModule); - } - AstNodeModule* topModulep() const { // Top module in hierarchy - return modulesp(); // First one in the list, for now - } - void addModulep(AstNodeModule* modulep) { addOp1p(modulep); } - AstNodeFile* filesp() const { return VN_AS(op2p(), NodeFile); } // op2 = List of files - void addFilesp(AstNodeFile* filep) { addOp2p(filep); } - void addMiscsp(AstNode* nodep) { addOp3p(nodep); } - AstTypeTable* typeTablep() { return m_typeTablep; } - void changeRequest(bool specified) { m_changeRequest = specified; } - bool changeRequest() const { return m_changeRequest; } - AstConstPool* constPoolp() { return m_constPoolp; } - AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; } - AstPackage* dollarUnitPkgAddp() { - if (!m_dollarUnitPkgp) { - m_dollarUnitPkgp = new AstPackage(fileline(), AstPackage::dollarUnitName()); - // packages are always libraries; don't want to make them a "top" - m_dollarUnitPkgp->inLibrary(true); - m_dollarUnitPkgp->modTrace(false); // may reconsider later - m_dollarUnitPkgp->internal(true); - addModulep(m_dollarUnitPkgp); - } - return m_dollarUnitPkgp; - } - AstCFunc* evalp() const { return m_evalp; } - void evalp(AstCFunc* evalp) { m_evalp = evalp; } - AstVarScope* dpiExportTriggerp() const { return m_dpiExportTriggerp; } - void dpiExportTriggerp(AstVarScope* varScopep) { m_dpiExportTriggerp = varScopep; } - AstTopScope* topScopep() const { return m_topScopep; } - void createTopScope(AstScope* scopep) { - UASSERT(scopep, "Must not be nullptr"); - UASSERT_OBJ(!m_topScopep, scopep, "TopScope already exits"); - m_topScopep = new AstTopScope{scopep->modp()->fileline(), scopep}; - scopep->modp()->addStmtp(v3Global.rootp()->topScopep()); - } - VTimescale timeunit() const { return m_timeunit; } - void timeunit(const VTimescale& value) { m_timeunit = value; } - VTimescale timeprecision() const { return m_timeprecision; } - void timeInit() { - m_timeunit = v3Global.opt.timeDefaultUnit(); - m_timeprecision = v3Global.opt.timeDefaultPrec(); - } - void timeprecisionMerge(FileLine*, const VTimescale& value); - void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; } - bool timescaleSpecified() const { return m_timescaleSpecified; } - uint32_t allocNextMTaskID() { return m_nextFreeMTaskID++; } - uint32_t allocNextMTaskProfilingID() { return m_nextFreeMTaskProfilingID++; } - uint32_t usedMTaskProfilingIDs() const { return m_nextFreeMTaskProfilingID; } -}; - -//###################################################################### - -#include "V3AstInlines.h" - -#endif // Guard diff --git a/src/astgen b/src/astgen index f8860dce0..d1fa39f31 100755 --- a/src/astgen +++ b/src/astgen @@ -4,13 +4,14 @@ import argparse import glob +import os import re import sys # from pprint import pprint, pformat class Node: - def __init__(self, name, superClass): + def __init__(self, name, superClass, file, lineno): self._name = name self._superClass = superClass self._subClasses = [] # Initially list, but tuple after completion @@ -19,6 +20,9 @@ class Node: self._typeId = None # Concrete type identifier number for leaf classes self._typeIdMin = None # Lowest type identifier number for class self._typeIdMax = None # Highest type identifier number for class + self._file = file # File this class is defined in + self._lineno = lineno # Line this class is defined on + self._ordIdx = None # Ordering index of this class @property def name(self): @@ -32,6 +36,14 @@ class Node: def isCompleted(self): return isinstance(self._subClasses, tuple) + @property + def file(self): + return self._file + + @property + def lineno(self): + return self._lineno + # Pre completion methods def addSubClass(self, subClass): assert not self.isCompleted @@ -39,20 +51,25 @@ class Node: # Computes derived properties over entire class hierarchy. # No more changes to the hierarchy are allowed once this was called - def complete(self, typeId=0): + def complete(self, typeId=0, ordIdx=0): assert not self.isCompleted # Sort sub-classes and convert to tuple, which marks completion - self._subClasses = tuple(sorted(self._subClasses, - key=lambda _: _.name)) + self._subClasses = tuple( + sorted(self._subClasses, + key=lambda _: (bool(_._subClasses), _.name))) + + self._ordIdx = ordIdx + ordIdx = ordIdx + 1 + # Leaves if self.isLeaf: self._typeId = typeId - return typeId + 1 + return typeId + 1, ordIdx # Non-leaves for subClass in self._subClasses: - typeId = subClass.complete(typeId) - return typeId + typeId, ordIdx = subClass.complete(typeId, ordIdx) + return typeId, ordIdx # Post completion methods @property @@ -117,6 +134,11 @@ class Node: self._typeIdMax = max(_.typeIdMax for _ in self.allSubClasses) return self._typeIdMax + @property + def ordIdx(self): + assert self.isCompleted + return self._ordIdx + def isSubClassOf(self, other): assert self.isCompleted if self is other: @@ -472,7 +494,7 @@ class Cpt: def read_types(filename): with open(filename) as fh: - for line in fh: + for (lineno, line) in enumerate(fh, start=1): line = re.sub(r'//.*$', '', line) if re.match(r'^\s*$', line): continue @@ -485,12 +507,12 @@ def read_types(filename): if re.search(r'Ast', supern) or classn == "AstNode": classn = re.sub(r'^Ast', '', classn) supern = re.sub(r'^Ast', '', supern) - if supern: - superClass = Nodes[supern] - node = Node(classn, superClass) - Nodes[supern].addSubClass(node) - else: - node = Node(classn, None) + if not supern: + sys.exit("%Error: 'Ast{}' has no super-class".format( + classn)) + superClass = Nodes[supern] + node = Node(classn, superClass, filename, lineno) + superClass.addSubClass(node) Nodes[classn] = node @@ -701,6 +723,9 @@ Version 2.0. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""") parser.add_argument('-I', action='store', help='source code include directory') +parser.add_argument('--astdef', + action='append', + help='add AST definition file (relative to -I)') parser.add_argument('--classes', action='store_true', help='makes class declaration files') @@ -710,8 +735,13 @@ parser.add_argument('infiles', nargs='*', help='list of input .cpp filenames') Args = parser.parse_args() -read_types(Args.I + "/V3Ast.h") -read_types(Args.I + "/V3AstNodes.h") +# Set up the root AstNode type. It is standalone so we don't need to parse the +# sources for this. +Nodes["Node"] = Node("Node", None, "AstNode", 1) + +# Read Ast node definitions +for filename in Args.astdef: + read_types(os.path.join(Args.I, filename)) # Compute derived properties over the whole AstNode hierarchy Nodes["Node"].complete() @@ -731,6 +761,36 @@ for node in SortedNodes: "%Error: Non-final AstNode subclasses must be named AstNode*: Ast" + node.name) +# Check ordering of node definitions +files = tuple(sorted(set(_.file for _ in SortedNodes))) + +hasOrderingError = False +for file in files: + nodes = tuple(filter(lambda _, f=file: _.file == f, SortedNodes)) + expectOrder = tuple(sorted(nodes, key=lambda _: (_.isLeaf, _.ordIdx))) + actualOrder = tuple(sorted(nodes, key=lambda _: _.lineno)) + expect = { + node: pred + for pred, node in zip((None, ) + expectOrder[:-1], expectOrder) + } + actual = { + node: pred + for pred, node in zip((None, ) + actualOrder[:-1], actualOrder) + } + for node in nodes: + if expect[node] != actual[node]: + hasOrderingError = True + pred = expect[node] + print(file + ":" + str(node.lineno) + + ": %Error: Definition of 'Ast" + node.name + + "' is out of order. Should be " + + ("right after 'Ast" + pred.name + + "'" if pred else "first in file") + ".", + file=sys.stderr) + +if hasOrderingError: + sys.exit("%Error: Stopping due to out of order definitions listed above") + read_stages(Args.I + "/Verilator.cpp") source_files = glob.glob(Args.I + "/*.y") diff --git a/src/cppcheck_filtered b/src/cppcheck_filtered index 7e803b306..2b96dc070 100755 --- a/src/cppcheck_filtered +++ b/src/cppcheck_filtered @@ -117,7 +117,7 @@ def _suppress(filename, linenum, eid): if filename == "*": return False - # Cleanup for e.g. ../V3AstNodes.h + # Cleanup for e.g. ../V3AstNode*.h filename = re.sub(r'^\.\./(.*)', r'src/\1', filename) # Specific suppressions From da20da264bb9472a1ef835d316c59446735d4308 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Thu, 15 Sep 2022 14:28:58 +0200 Subject: [PATCH 35/75] Add --build-jobs, and rework arguments for -j (#3623) --- bin/verilator | 3 +- docs/guide/exe_verilator.rst | 18 ++++++++---- src/V3Options.cpp | 26 ++++++++++++++--- src/V3Options.h | 2 +- src/Verilator.cpp | 6 +--- test_regress/t/t_flag_build-jobs_bad.out | 1 + ...flag_j_bad.pl => t_flag_build-jobs_bad.pl} | 2 +- test_regress/t/t_flag_build_jobs_and_j.pl | 29 +++++++++++++++++++ test_regress/t/t_flag_j_bad.out | 2 -- 9 files changed, 70 insertions(+), 19 deletions(-) create mode 100644 test_regress/t/t_flag_build-jobs_bad.out rename test_regress/t/{t_flag_j_bad.pl => t_flag_build-jobs_bad.pl} (91%) create mode 100755 test_regress/t/t_flag_build_jobs_and_j.pl delete mode 100644 test_regress/t/t_flag_j_bad.out diff --git a/bin/verilator b/bin/verilator index 74c5b49c6..852ad516c 100755 --- a/bin/verilator +++ b/bin/verilator @@ -284,6 +284,7 @@ detailed descriptions of these arguments. --bbox-unsup Blackbox unsupported language features --bin Override Verilator binary --build Build model executable/library after Verilation + --build-jobs Parallelism for --build --cc Create C++ output --cdc Clock domain crossing analysis -CFLAGS C++ compiler arguments for makefile @@ -334,7 +335,7 @@ detailed descriptions of these arguments. +incdir+ Directory to search for includes --inline-mult Tune module inlining --instr-count-dpi Assumed dynamic instruction count of DPI imports - -j Parallelism for --build + -j Parallelism for --build (alias to --build-jobs) --l2-name Verilog scope name of the top module --language Default language standard to parse -LDFLAGS Linker pre-object arguments for makefile diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 8d2ccda86..cf7690a14 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -129,6 +129,15 @@ Summary: is also used). Verilator manages the build itself, and for this --build requires GNU Make to be available on the platform. +.. option:: --build-jobs [] + + Specify the level of parallelism for :vlopt:`--build`. If zero, uses the + number of threads in the current hardware. Otherwise, the must + be a positive integer specifying the maximum number of parallel build + jobs. + + See also :vlopt:`-j`. + .. option:: --cc Specifies C++ without SystemC output mode; see also :vlopt:`--sc` @@ -615,11 +624,10 @@ Summary: .. option:: -j [] - Specify the level of parallelism for :vlopt:`--build`. The must - be a positive integer specifying the maximum number of parallel build - jobs, or can be omitted. When is omitted, the build will not try - to limit the number of parallel build jobs but attempt to execute all - independent build steps in parallel. + Specify the level of parallelism for :vlopt:`--build` if + :vlopt:`--build-jobs` isn't provided. If zero, uses the number of threads + in the current hardware. Otherwise, the must be a positive + integer specifying the maximum number of parallel build jobs. .. option:: --l2-name diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 0580fdac4..6836b5167 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "config_rev.h" @@ -1006,6 +1007,17 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char }); DECL_OPTION("-bin", Set, &m_bin); DECL_OPTION("-build", Set, &m_build); + DECL_OPTION("-build-jobs", CbVal, [this, fl](const char* valp) { + int val = std::atoi(valp); + if (val < 0) { + fl->v3fatal("--build-jobs requires a non-negative integer, but '" << valp + << "' was passed"); + val = 1; + } else if (val == 0) { + val = std::thread::hardware_concurrency(); + } + m_buildJobs = val; + }); DECL_OPTION("-CFLAGS", CbVal, callStrSetter(&V3Options::addCFlags)); DECL_OPTION("-cc", CbCall, [this]() { ccSet(); }); @@ -1514,14 +1526,19 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char if (!std::strcmp(argv[i], "-j") || !std::strcmp(argv[i], "--j")) { // Allow gnu -- switches ++i; - m_buildJobs = 0; // Unlimited parallelism + int val = 0; if (i < argc && isdigit(argv[i][0])) { - m_buildJobs = std::atoi(argv[i]); - if (m_buildJobs <= 0) { - fl->v3error("-j accepts positive integer, but '" << argv[i] << "' is passed"); + val = atoi(argv[i]); + if (val < 0) { + fl->v3error("-j requires a non-negative integer argument, but '" + << argv[i] << "' was passed"); + val = 1; // Fall-back value, though we will exit on error. + } else if (val == 0) { + val = std::thread::hardware_concurrency(); } ++i; } + if (m_buildJobs == -1) m_buildJobs = val; } else if (argv[i][0] == '-' || argv[i][0] == '+') { const char* argvNoDashp = (argv[i][1] == '-') ? (argv[i] + 2) : (argv[i] + 1); if (const int consumed = parser.parse(i, argc, argv)) { @@ -1553,6 +1570,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char ++i; } } + if (m_buildJobs == -1) m_buildJobs = 1; } //====================================================================== diff --git a/src/V3Options.h b/src/V3Options.h index 190d4c7ab..028171c5a 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -283,7 +283,7 @@ private: bool m_xInitialEdge = false; // main switch: --x-initial-edge bool m_xmlOnly = false; // main switch: --xml-only - int m_buildJobs = 1; // main switch: -j + int m_buildJobs = -1; // main switch: --build-jobs, -j int m_convergeLimit = 100; // main switch: --converge-limit int m_coverageMaxWidth = 256; // main switch: --coverage-max-width int m_dumpTree = 0; // main switch: --dump-tree diff --git a/src/Verilator.cpp b/src/Verilator.cpp index b5d2df2cb..eb07fb664 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -663,11 +663,7 @@ static string buildMakeCmd(const string& makefile, const string& target) { cmd << v3Global.opt.getenvMAKE(); cmd << " -C " << v3Global.opt.makeDir(); cmd << " -f " << makefile; - if (jobs == 0) { - cmd << " -j"; - } else if (jobs > 1) { - cmd << " -j " << jobs; - } + if (jobs > 0) cmd << " -j " << jobs; for (const string& flag : makeFlags) cmd << ' ' << flag; if (!target.empty()) cmd << ' ' << target; diff --git a/test_regress/t/t_flag_build-jobs_bad.out b/test_regress/t/t_flag_build-jobs_bad.out new file mode 100644 index 000000000..341b1b979 --- /dev/null +++ b/test_regress/t/t_flag_build-jobs_bad.out @@ -0,0 +1 @@ +%Error: --build-jobs requires a non-negative integer, but '-1' was passed diff --git a/test_regress/t/t_flag_j_bad.pl b/test_regress/t/t_flag_build-jobs_bad.pl similarity index 91% rename from test_regress/t/t_flag_j_bad.pl rename to test_regress/t/t_flag_build-jobs_bad.pl index ee3d0fdc8..8432e74c6 100755 --- a/test_regress/t/t_flag_j_bad.pl +++ b/test_regress/t/t_flag_build-jobs_bad.pl @@ -14,7 +14,7 @@ top_filename("t/t_flag_werror.v"); lint( fails => 1, - verilator_flags => [qw(-j 0 --build)], + verilator_flags => [qw(--build-jobs -1 --build)], expect_filename => $Self->{golden_filename}, ); diff --git a/test_regress/t/t_flag_build_jobs_and_j.pl b/test_regress/t/t_flag_build_jobs_and_j.pl new file mode 100755 index 000000000..03ce21108 --- /dev/null +++ b/test_regress/t/t_flag_build_jobs_and_j.pl @@ -0,0 +1,29 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd.. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); +top_filename("t/t_flag_make_cmake.v"); + +compile( + verilator_make_cmake => 0, + verilator_make_gmake => 0, + verilator_flags2 => ['--exe --cc --build -j 10 --build-jobs 2', + '../' . $Self->{main_filename}, + '-MAKEFLAGS -p --trace'], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{obj_dir} . '/vlt_compile.log', qr/MAKEFLAGS = pw -j2/); + +ok(1); +1; diff --git a/test_regress/t/t_flag_j_bad.out b/test_regress/t/t_flag_j_bad.out deleted file mode 100644 index 2fe652c5d..000000000 --- a/test_regress/t/t_flag_j_bad.out +++ /dev/null @@ -1,2 +0,0 @@ -%Error: -j accepts positive integer, but '0' is passed -%Error: Exiting due to From d74536a4dc6a8770dc9fb33186881594fb8b7496 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 15 Sep 2022 08:54:04 -0400 Subject: [PATCH 36/75] Internals: Cleanup some constructors. No functional change intended. --- src/V3Ast.h | 1 + src/V3AstNodeDType.h | 16 ++++------ src/V3AstNodeMath.h | 2 +- src/V3AstNodeOther.h | 74 +++++++++++++++++++------------------------- src/Verilator.cpp | 2 +- 5 files changed, 41 insertions(+), 54 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index 3df21ffb4..3e8d474a9 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -985,6 +985,7 @@ public: enum en : uint8_t { HIGHZ, SMALL, MEDIUM, WEAK, LARGE, PULL, STRONG, SUPPLY }; enum en m_e; + // cppcheck-suppress noExplicitConstructor inline VStrength(en strengthLevel) : m_e(strengthLevel) {} explicit inline VStrength(int _e) diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 4740ec685..9066caeed 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -35,22 +35,19 @@ class AstNodeDType VL_NOT_FINAL : public AstNode { // but it's currently so prevalent in the code we leave it here. // Note the below members are included in AstTypeTable::Key lookups private: - int m_width; // (also in AstTypeTable::Key) Bit width of operation - int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation + int m_width = 0; // (also in AstTypeTable::Key) Bit width of operation + int m_widthMin + = 0; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation VSigning m_numeric; // (also in AstTypeTable::Key) Node is signed // Other members - bool m_generic; // Simple globally referenced type, don't garbage collect + bool m_generic = false; // Simple globally referenced type, don't garbage collect // Unique number assigned to each dtype during creation for IEEE matching static int s_uniqueNum; protected: // CONSTRUCTORS AstNodeDType(VNType t, FileLine* fl) - : AstNode{t, fl} { - m_width = 0; - m_widthMin = 0; - m_generic = false; - } + : AstNode{t, fl} {} public: ASTNODE_BASE_FUNCS(NodeDType) @@ -204,7 +201,7 @@ private: // MEMBERS string m_name; // Name from upper typedef, if any bool m_packed; - bool m_isFourstate; + bool m_isFourstate = false; // V3Width computes MemberNameMap m_members; const int m_uniqueNum; @@ -214,7 +211,6 @@ protected: , m_uniqueNum{uniqueNumInc()} { // VSigning::NOSIGN overloaded to indicate not packed m_packed = (numericUnpack != VSigning::NOSIGN); - m_isFourstate = false; // V3Width computes numeric(VSigning::fromBool(numericUnpack.isSigned())); } diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index ce1ca2338..e019298f9 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -1117,7 +1117,7 @@ public: } AstRand(FileLine* fl, AstNode* seedp, bool urandom) : ASTGEN_SUPER_Rand(fl) - , m_urandom(urandom) { + , m_urandom{urandom} { setNOp1p(seedp); } ASTNODE_NODE_FUNCS(Rand) diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index b197e18bd..e942e7c00 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -191,9 +191,8 @@ private: string m_name; ///< Filename public: AstNodeFile(VNType t, FileLine* fl, const string& name) - : AstNode(t, fl) { - m_name = name; - } + : AstNode(t, fl) + , m_name{name} {} ASTNODE_BASE_FUNCS(NodeFile) virtual void dump(std::ostream& str) const override; virtual string name() const override { return m_name; } @@ -599,10 +598,9 @@ private: protected: // Node that puts text into the output stream - AstNodeText(VNType t, FileLine* fl, const string& textp) - : AstNode{t, fl} { - m_text = textp; // Copy it - } + AstNodeText(VNType t, FileLine* fl, const string& text) + : AstNode{t, fl} + , m_text{text} {} public: ASTNODE_BASE_FUNCS(NodeText) @@ -638,10 +636,10 @@ private: public: AstActive(FileLine* fl, const string& name, AstSenTree* sensesp) - : ASTGEN_SUPER_Active(fl) { - m_name = name; // Copy it + : ASTGEN_SUPER_Active(fl) + , m_name{name} + , m_sensesp{sensesp} { UASSERT(sensesp, "Sensesp required arg"); - m_sensesp = sensesp; } ASTNODE_NODE_FUNCS(Active) virtual void dump(std::ostream& str = std::cout) const override; @@ -1197,10 +1195,10 @@ private: string m_path; // Dotted cellname to set parameter of public: AstDefParam(FileLine* fl, const string& path, const string& name, AstNode* rhsp) - : ASTGEN_SUPER_DefParam(fl) { + : ASTGEN_SUPER_DefParam(fl) + , m_name{name} + , m_path{path} { setOp1p(rhsp); - m_name = name; - m_path = path; } virtual string name() const override { return m_name; } // * = Scope name ASTNODE_NODE_FUNCS(DefParam) @@ -1714,9 +1712,9 @@ private: public: AstPull(FileLine* fl, AstNode* lhsp, bool direction) - : ASTGEN_SUPER_Pull(fl) { + : ASTGEN_SUPER_Pull(fl) + , m_direction{direction} { setOp1p(lhsp); - m_direction = direction; } ASTNODE_NODE_FUNCS(Pull) virtual bool same(const AstNode* samep) const override { @@ -1996,7 +1994,7 @@ public: class AstTypedef final : public AstNode { private: string m_name; - bool m_attrPublic; + bool m_attrPublic = false; string m_tag; // Holds the string of the verilator tag -- used in XML output. public: AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, @@ -2006,7 +2004,6 @@ public: childDTypep(dtp); // Only for parser addAttrsp(attrsp); dtypep(nullptr); // V3Width will resolve - m_attrPublic = false; } ASTNODE_NODE_FUNCS(Typedef) virtual void dump(std::ostream& str) const override; @@ -3045,25 +3042,22 @@ class AstCoverDecl final : public AstNodeStmt { // Parents: {statement list} // Children: none private: - AstCoverDecl* m_dataDeclp; // [After V3CoverageJoin] Pointer to duplicate declaration to get - // data from instead + AstCoverDecl* m_dataDeclp = nullptr; // [After V3CoverageJoin] Pointer to duplicate + // declaration to get data from instead string m_page; string m_text; string m_hier; string m_linescov; int m_offset; // Offset column numbers to uniq-ify IFs - int m_binNum; // Set by V3EmitCSyms to tell final V3Emit what to increment + int m_binNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment public: AstCoverDecl(FileLine* fl, const string& page, const string& comment, const string& linescov, int offset) - : ASTGEN_SUPER_CoverDecl(fl) { - m_page = page; - m_text = comment; - m_linescov = linescov; - m_offset = offset; - m_binNum = 0; - m_dataDeclp = nullptr; - } + : ASTGEN_SUPER_CoverDecl(fl) + , m_page{page} + , m_text{comment} + , m_linescov{linescov} + , m_offset{offset} {} ASTNODE_NODE_FUNCS(CoverDecl) virtual const char* broken() const override { BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); @@ -3200,17 +3194,17 @@ private: public: AstDisplay(FileLine* fl, VDisplayType dispType, const string& text, AstNode* filep, AstNode* exprsp, char missingArgChar = 'd') - : ASTGEN_SUPER_Display(fl) { - setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); + : ASTGEN_SUPER_Display(fl) + , m_displayType{dispType} { + setOp1p(new AstSFormatF{fl, text, true, exprsp, missingArgChar}); setNOp3p(filep); - m_displayType = dispType; } AstDisplay(FileLine* fl, VDisplayType dispType, AstNode* filep, AstNode* exprsp, char missingArgChar = 'd') - : ASTGEN_SUPER_Display(fl) { - setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); + : ASTGEN_SUPER_Display(fl) + , m_displayType{dispType} { + setOp1p(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp, missingArgChar}); setNOp3p(filep); - m_displayType = dispType; } ASTNODE_NODE_FUNCS(Display) virtual void dump(std::ostream& str) const override; @@ -4246,16 +4240,12 @@ public: }; class AstIf final : public AstNodeIf { private: - bool m_uniquePragma; // unique case - bool m_unique0Pragma; // unique0 case - bool m_priorityPragma; // priority case + bool m_uniquePragma = false; // unique case + bool m_unique0Pragma = false; // unique0 case + bool m_priorityPragma = false; // priority case public: AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp = nullptr, AstNode* elsesp = nullptr) - : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) { - m_uniquePragma = false; - m_unique0Pragma = false; - m_priorityPragma = false; - } + : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) {} ASTNODE_NODE_FUNCS(If) bool uniquePragma() const { return m_uniquePragma; } void uniquePragma(bool flag) { m_uniquePragma = flag; } diff --git a/src/Verilator.cpp b/src/Verilator.cpp index eb07fb664..ffd438ca9 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -716,7 +716,7 @@ int main(int argc, char** argv, char** /*env*/) { // Command option parsing v3Global.opt.bin(argv[0]); const string argString = V3Options::argString(argc - 1, argv + 1); - v3Global.opt.parseOpts(new FileLine(FileLine::commandLineFilename()), argc - 1, argv + 1); + v3Global.opt.parseOpts(new FileLine{FileLine::commandLineFilename()}, argc - 1, argv + 1); // Validate settings (aka Boost.Program_options) v3Global.opt.notify(); From dbe1348b4cecf5035ba664c9d0adf9092b338de9 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Thu, 15 Sep 2022 17:29:50 +0200 Subject: [PATCH 37/75] Tests: Fix earlier commit, add build jobs to stats (#3623) (#3626) --- src/V3StatsReport.cpp | 1 + test_regress/t/t_flag_build_jobs_and_j.pl | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index ad12bd812..85860e43e 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -44,6 +44,7 @@ class StatsReport final { os << "Information:\n"; os << " " << V3Options::version() << '\n'; os << " Arguments: " << v3Global.opt.allArgsString() << '\n'; + os << " Build jobs: " << v3Global.opt.buildJobs() << '\n'; os << '\n'; } diff --git a/test_regress/t/t_flag_build_jobs_and_j.pl b/test_regress/t/t_flag_build_jobs_and_j.pl index 03ce21108..356011fbf 100755 --- a/test_regress/t/t_flag_build_jobs_and_j.pl +++ b/test_regress/t/t_flag_build_jobs_and_j.pl @@ -14,16 +14,15 @@ top_filename("t/t_flag_make_cmake.v"); compile( verilator_make_cmake => 0, verilator_make_gmake => 0, - verilator_flags2 => ['--exe --cc --build -j 10 --build-jobs 2', - '../' . $Self->{main_filename}, - '-MAKEFLAGS -p --trace'], + verilator_flags2 => ['--exe --cc --build -j 10 --build-jobs 2 --stats', + '../' . $Self->{main_filename}], ); execute( check_finished => 1, ); -file_grep($Self->{obj_dir} . '/vlt_compile.log', qr/MAKEFLAGS = pw -j2/); +file_grep($Self->{stats}, qr/Build jobs: 2/); ok(1); 1; From 2dc85a5acdcff82d56fdd4fe156f384ff9a3ea28 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 15 Sep 2022 19:58:01 -0400 Subject: [PATCH 38/75] Internals: enum constructor cleanups. No functional change intended. --- src/V3Ast.cpp | 2 +- src/V3Ast.h | 52 +++++++++++++++++----------------- src/V3AstNodeOther.h | 2 +- src/V3AstNodes.cpp | 2 +- src/V3AstUserAllocator.h | 10 +++---- src/V3Clock.cpp | 2 +- src/V3Error.cpp | 6 ++-- src/V3FileLine.cpp | 8 +++--- src/V3Gate.cpp | 60 ++++++++++++++++++++-------------------- src/V3LangCode.h | 2 +- src/V3Life.cpp | 10 +++---- src/V3LifePost.cpp | 2 +- src/V3LinkDot.cpp | 10 +++---- src/V3LinkLevel.cpp | 4 +-- src/V3LinkParse.cpp | 2 +- src/V3Options.cpp | 6 ++-- src/V3Order.cpp | 5 ++-- src/V3ParseImp.cpp | 8 +++--- src/V3Simulate.h | 8 +++--- src/V3Stats.cpp | 10 +++---- src/V3Table.cpp | 4 +-- src/V3TraceDecl.cpp | 6 ++-- src/V3Unknown.cpp | 6 ++-- src/V3Width.cpp | 2 +- src/V3WidthSel.cpp | 4 +-- src/verilog.y | 11 ++++---- 26 files changed, 123 insertions(+), 121 deletions(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 7694e1e69..3bc1325bc 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -927,7 +927,7 @@ AstNode* AstNode::iterateSubtreeReturnEdits(VNVisitor& v) { } else if (!nodep->backp()) { // Calling on standalone tree; insert a shim node so we can keep // track, then delete it on completion - AstBegin* const tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep); + AstBegin* const tempp = new AstBegin{nodep->fileline(), "[EditWrapper]", nodep}; { VL_DO_DANGLING(tempp->stmtsp()->accept(v), nodep); // nodep to null as may be replaced diff --git a/src/V3Ast.h b/src/V3Ast.h index 3e8d474a9..86d4a324f 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -166,7 +166,7 @@ public: : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } VAccess invert() const { - return (m_e == READWRITE) ? VAccess(m_e) : (m_e == WRITE ? VAccess(READ) : VAccess(WRITE)); + return (m_e == READWRITE) ? VAccess{m_e} : (m_e == WRITE ? VAccess{READ} : VAccess{WRITE}); } bool isReadOnly() const { return m_e == READ; } // False with READWRITE bool isWriteOnly() const { return m_e == WRITE; } // False with READWRITE @@ -200,7 +200,7 @@ public: inline VSigning(en _e) : m_e{_e} {} static inline VSigning fromBool(bool isSigned) { // Factory method - return isSigned ? VSigning(SIGNED) : VSigning(UNSIGNED); + return isSigned ? VSigning{SIGNED} : VSigning{UNSIGNED}; } explicit inline VSigning(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning @@ -465,9 +465,9 @@ public: return names[m_e]; } static void selfTest() { - UASSERT(0 == std::strcmp(VBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), + UASSERT(0 == std::strcmp(VBasicDTypeKwd{_ENUM_MAX}.ascii(), " MAX"), "SelfTest: Enum mismatch"); - UASSERT(0 == std::strcmp(VBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), + UASSERT(0 == std::strcmp(VBasicDTypeKwd{_ENUM_MAX}.dpiType(), " MAX"), "SelfTest: Enum mismatch"); } inline VBasicDTypeKwd() @@ -1172,7 +1172,7 @@ public: AstNode* toNodep() const { return to(); } V3GraphVertex* toGraphVertex() const { return to(); } int toInt() const { return m_u.ui; } - static VNUser fromInt(int i) { return VNUser(i); } + static VNUser fromInt(int i) { return VNUser{i}; } }; //###################################################################### @@ -1438,15 +1438,15 @@ class AstNode VL_NOT_FINAL { static int s_cloneCntGbl; // Count of which userp is set // This member ordering both allows 64 bit alignment and puts associated data together - VNUser m_user1u = VNUser{0}; // Contains any information the user iteration routine wants + VNUser m_user1u{0}; // Contains any information the user iteration routine wants uint32_t m_user1Cnt = 0; // Mark of when userp was set uint32_t m_user2Cnt = 0; // Mark of when userp was set - VNUser m_user2u = VNUser{0}; // Contains any information the user iteration routine wants - VNUser m_user3u = VNUser{0}; // Contains any information the user iteration routine wants + VNUser m_user2u{0}; // Contains any information the user iteration routine wants + VNUser m_user3u{0}; // Contains any information the user iteration routine wants uint32_t m_user3Cnt = 0; // Mark of when userp was set uint32_t m_user4Cnt = 0; // Mark of when userp was set - VNUser m_user4u = VNUser{0}; // Contains any information the user iteration routine wants - VNUser m_user5u = VNUser{0}; // Contains any information the user iteration routine wants + VNUser m_user4u{0}; // Contains any information the user iteration routine wants + VNUser m_user5u{0}; // Contains any information the user iteration routine wants uint32_t m_user5Cnt = 0; // Mark of when userp was set // METHODS @@ -1638,13 +1638,13 @@ public: VNUser user1u() const { // Slows things down measurably, so disabled by default //UASSERT_STATIC(VNUser1InUse::s_userBusy, "userp set w/o busy"); - return ((m_user1Cnt==VNUser1InUse::s_userCntGbl) ? m_user1u : VNUser(0)); + return ((m_user1Cnt==VNUser1InUse::s_userCntGbl) ? m_user1u : VNUser{0}); } AstNode* user1p() const { return user1u().toNodep(); } void user1u(const VNUser& user) { m_user1u=user; m_user1Cnt=VNUser1InUse::s_userCntGbl; } - void user1p(void* userp) { user1u(VNUser(userp)); } + void user1p(void* userp) { user1u(VNUser{userp}); } int user1() const { return user1u().toInt(); } - void user1(int val) { user1u(VNUser(val)); } + void user1(int val) { user1u(VNUser{val}); } int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; } int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc() static void user1ClearTree() { VNUser1InUse::clear(); } // Clear userp()'s across the entire tree @@ -1652,13 +1652,13 @@ public: VNUser user2u() const { // Slows things down measurably, so disabled by default //UASSERT_STATIC(VNUser2InUse::s_userBusy, "userp set w/o busy"); - return ((m_user2Cnt==VNUser2InUse::s_userCntGbl) ? m_user2u : VNUser(0)); + return ((m_user2Cnt==VNUser2InUse::s_userCntGbl) ? m_user2u : VNUser{0}); } AstNode* user2p() const { return user2u().toNodep(); } void user2u(const VNUser& user) { m_user2u=user; m_user2Cnt=VNUser2InUse::s_userCntGbl; } - void user2p(void* userp) { user2u(VNUser(userp)); } + void user2p(void* userp) { user2u(VNUser{userp}); } int user2() const { return user2u().toInt(); } - void user2(int val) { user2u(VNUser(val)); } + void user2(int val) { user2u(VNUser{val}); } int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; } int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; } // Better for cache than user2Inc() static void user2ClearTree() { VNUser2InUse::clear(); } // Clear userp()'s across the entire tree @@ -1666,13 +1666,13 @@ public: VNUser user3u() const { // Slows things down measurably, so disabled by default //UASSERT_STATIC(VNUser3InUse::s_userBusy, "userp set w/o busy"); - return ((m_user3Cnt==VNUser3InUse::s_userCntGbl) ? m_user3u : VNUser(0)); + return ((m_user3Cnt==VNUser3InUse::s_userCntGbl) ? m_user3u : VNUser{0}); } AstNode* user3p() const { return user3u().toNodep(); } void user3u(const VNUser& user) { m_user3u=user; m_user3Cnt=VNUser3InUse::s_userCntGbl; } - void user3p(void* userp) { user3u(VNUser(userp)); } + void user3p(void* userp) { user3u(VNUser{userp}); } int user3() const { return user3u().toInt(); } - void user3(int val) { user3u(VNUser(val)); } + void user3(int val) { user3u(VNUser{val}); } int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; } int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; } // Better for cache than user3Inc() static void user3ClearTree() { VNUser3InUse::clear(); } // Clear userp()'s across the entire tree @@ -1680,13 +1680,13 @@ public: VNUser user4u() const { // Slows things down measurably, so disabled by default //UASSERT_STATIC(VNUser4InUse::s_userBusy, "userp set w/o busy"); - return ((m_user4Cnt==VNUser4InUse::s_userCntGbl) ? m_user4u : VNUser(0)); + return ((m_user4Cnt==VNUser4InUse::s_userCntGbl) ? m_user4u : VNUser{0}); } AstNode* user4p() const { return user4u().toNodep(); } void user4u(const VNUser& user) { m_user4u=user; m_user4Cnt=VNUser4InUse::s_userCntGbl; } - void user4p(void* userp) { user4u(VNUser(userp)); } + void user4p(void* userp) { user4u(VNUser{userp}); } int user4() const { return user4u().toInt(); } - void user4(int val) { user4u(VNUser(val)); } + void user4(int val) { user4u(VNUser{val}); } int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; } int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; } // Better for cache than user4Inc() static void user4ClearTree() { VNUser4InUse::clear(); } // Clear userp()'s across the entire tree @@ -1694,13 +1694,13 @@ public: VNUser user5u() const { // Slows things down measurably, so disabled by default //UASSERT_STATIC(VNUser5InUse::s_userBusy, "userp set w/o busy"); - return ((m_user5Cnt==VNUser5InUse::s_userCntGbl) ? m_user5u : VNUser(0)); + return ((m_user5Cnt==VNUser5InUse::s_userCntGbl) ? m_user5u : VNUser{0}); } AstNode* user5p() const { return user5u().toNodep(); } void user5u(const VNUser& user) { m_user5u=user; m_user5Cnt=VNUser5InUse::s_userCntGbl; } - void user5p(void* userp) { user5u(VNUser(userp)); } + void user5p(void* userp) { user5u(VNUser{userp}); } int user5() const { return user5u().toInt(); } - void user5(int val) { user5u(VNUser(val)); } + void user5(int val) { user5u(VNUser{val}); } int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; } int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; } // Better for cache than user5Inc() static void user5ClearTree() { VNUser5InUse::clear(); } // Clear userp()'s across the entire tree @@ -2406,7 +2406,7 @@ inline AstNode* VNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) { #define ASTNODE_NODE_FUNCS_NO_DTOR(name) \ virtual void accept(VNVisitor& v) override { v.visit(this); } \ - virtual AstNode* clone() override { return new Ast##name(*this); } \ + virtual AstNode* clone() override { return new Ast##name{*this}; } \ static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ } \ diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index e942e7c00..aa35e36a2 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -191,7 +191,7 @@ private: string m_name; ///< Filename public: AstNodeFile(VNType t, FileLine* fl, const string& name) - : AstNode(t, fl) + : AstNode{t, fl} , m_name{name} {} ASTNODE_BASE_FUNCS(NodeFile) virtual void dump(std::ostream& str) const override; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 3ed73a6a7..bf1cac868 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1872,7 +1872,7 @@ void AstTypeTable::dump(std::ostream& str) const { for (int i = 0; i < static_cast(VBasicDTypeKwd::_ENUM_MAX); ++i) { if (AstBasicDType* const subnodep = m_basicps[i]) { str << '\n'; // Newline from caller, so newline first - str << "\t\t" << std::setw(8) << VBasicDTypeKwd(i).ascii(); + str << "\t\t" << std::setw(8) << VBasicDTypeKwd{i}.ascii(); str << " -> "; subnodep->dump(str); } diff --git a/src/V3AstUserAllocator.h b/src/V3AstUserAllocator.h index 76ec4fc5d..478c31dfa 100644 --- a/src/V3AstUserAllocator.h +++ b/src/V3AstUserAllocator.h @@ -56,15 +56,15 @@ private: inline void setUserp(T_Node* nodep, T_Data* userp) const { if VL_CONSTEXPR_CXX17 (T_UserN == 1) { - nodep->user1u(VNUser(userp)); + nodep->user1u(VNUser{userp}); } else if VL_CONSTEXPR_CXX17 (T_UserN == 2) { - nodep->user2u(VNUser(userp)); + nodep->user2u(VNUser{userp}); } else if VL_CONSTEXPR_CXX17 (T_UserN == 3) { - nodep->user3u(VNUser(userp)); + nodep->user3u(VNUser{userp}); } else if VL_CONSTEXPR_CXX17 (T_UserN == 4) { - nodep->user4u(VNUser(userp)); + nodep->user4u(VNUser{userp}); } else { - nodep->user5u(VNUser(userp)); + nodep->user5u(VNUser{userp}); } } diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index d94728f35..f750d2059 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -100,7 +100,7 @@ private: const string newvarname = (string("__Vclklast__") + vscp->scopep()->nameDotless() + "__" + varp->name()); AstVar* const newvarp = new AstVar(vscp->fileline(), VVarType::MODULETEMP, newvarname, - VFlagLogicPacked(), 1); + VFlagLogicPacked{}, 1); newvarp->noReset(true); // Reset by below assign m_modp->addStmtp(newvarp); AstVarScope* const newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp); diff --git a/src/V3Error.cpp b/src/V3Error.cpp index be30eae9b..4912e67b4 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -54,7 +54,7 @@ v3errorIniter v3errorInit; V3ErrorCode::V3ErrorCode(const char* msgp) { // Return error encoding for given string, or ERROR, which is a bad code for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code = V3ErrorCode(codei); + const V3ErrorCode code{codei}; if (0 == VL_STRCASECMP(msgp, code.ascii())) { m_e = code; return; @@ -69,9 +69,9 @@ V3ErrorCode::V3ErrorCode(const char* msgp) { void V3Error::init() { for (int i = 0; i < V3ErrorCode::_ENUM_MAX; i++) { s_describedEachWarn[i] = false; - s_pretendError[i] = V3ErrorCode(i).pretendError(); + s_pretendError[i] = V3ErrorCode{i}.pretendError(); } - if (VL_UNCOVERABLE(string(V3ErrorCode(V3ErrorCode::_ENUM_MAX).ascii()) != " MAX")) { + if (VL_UNCOVERABLE(string(V3ErrorCode{V3ErrorCode::_ENUM_MAX}.ascii()) != " MAX")) { v3fatalSrc("Enum table in V3ErrorCode::EC_ascii() is munged"); } } diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 0d9705c82..93940bac6 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -149,7 +149,7 @@ FileLine::FileLine(FileLine::EmptySecret) { m_warnOn = 0; for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code = V3ErrorCode(codei); + const V3ErrorCode code{codei}; warnOff(code, code.defaultsOff()); } } @@ -309,14 +309,14 @@ bool FileLine::warnOff(const string& msg, bool flag) { void FileLine::warnLintOff(bool flag) { for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code = V3ErrorCode(codei); + const V3ErrorCode code{codei}; if (code.lintError()) warnOff(code, flag); } } void FileLine::warnStyleOff(bool flag) { for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code = V3ErrorCode(codei); + const V3ErrorCode code{codei}; if (code.styleError()) warnOff(code, flag); } } @@ -335,7 +335,7 @@ bool FileLine::warnIsOff(V3ErrorCode code) const { void FileLine::modifyStateInherit(const FileLine* fromp) { // Any warnings that are off in "from", become off in "this". for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code = V3ErrorCode(codei); + const V3ErrorCode code{codei}; if (fromp->warnIsOff(code)) warnOff(code, true); } } diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index e4b2e8853..f7c9ed428 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -62,8 +62,8 @@ public: explicit GateGraphBaseVisitor(V3Graph* graphp) : m_graphp{graphp} {} virtual ~GateGraphBaseVisitor() = default; - virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu = VNUser(0)) = 0; - virtual VNUser visit(GateVarVertex* vertexp, VNUser vu = VNUser(0)) = 0; + virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu = VNUser{0}) = 0; + virtual VNUser visit(GateVarVertex* vertexp, VNUser vu = VNUser{0}) = 0; VL_DEBUG_FUNC; // Declare debug() }; @@ -102,10 +102,10 @@ public: clearReducible(nonReducibleReason); clearDedupable(nonReducibleReason); } - virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) = 0; + virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) = 0; // Returns only the result from the LAST vertex iterated over - VNUser iterateInEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { - VNUser ret = VNUser(0); + VNUser iterateInEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) { + VNUser ret{0}; for (V3GraphEdge* edgep = inBeginp(); edgep; edgep = edgep->inNextp()) { ret = static_cast(edgep->fromp())->accept(v, vu); } @@ -115,8 +115,8 @@ public: // Note: This behaves differently than iterateInEdges() in that it will traverse // all edges that exist when it is initially called, whereas // iterateInEdges() will stop traversing edges if one is deleted - VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { - VNUser ret = VNUser(0); + VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) { + VNUser ret{0}; V3GraphEdge* next_edgep = nullptr; for (V3GraphEdge* edgep = outBeginp(); edgep; edgep = next_edgep) { // Need to find the next edge before visiting in case the edge is deleted @@ -162,7 +162,7 @@ public: setIsClock(); } } - virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) override { + virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) override { return v.visit(this, vu); } }; @@ -188,7 +188,7 @@ public: AstNode* nodep() const { return m_nodep; } AstActive* activep() const { return m_activep; } bool slow() const { return m_slow; } - virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) override { + virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) override { return v.visit(this, vu); } }; @@ -1046,14 +1046,14 @@ private: virtual VNUser visit(GateVarVertex* vvertexp, VNUser) override { // Check that we haven't been here before if (m_depth > GATE_DEDUP_MAX_DEPTH) - return VNUser(0); // Break loops; before user2 set so hit this vertex later - if (vvertexp->varScp()->user2()) return VNUser(0); + return VNUser{0}; // Break loops; before user2 set so hit this vertex later + if (vvertexp->varScp()->user2()) return VNUser{0}; vvertexp->varScp()->user2(true); m_depth++; if (vvertexp->inSize1()) { AstNodeVarRef* const dupVarRefp = static_cast( - vvertexp->iterateInEdges(*this, VNUser(vvertexp)).toNodep()); + vvertexp->iterateInEdges(*this, VNUser{vvertexp}).toNodep()); if (dupVarRefp) { // visit(GateLogicVertex*...) returned match const V3GraphEdge* edgep = vvertexp->inBeginp(); GateLogicVertex* const lvertexp = static_cast(edgep->fromp()); @@ -1100,7 +1100,7 @@ private: } } m_depth--; - return VNUser(0); + return VNUser{0}; } // Given iterated logic, starting at vu which was consumer's GateVarVertex @@ -1118,9 +1118,9 @@ private: // different generated clocks will never compare as equal, even if the // generated clocks are deduped into one clock. AstActive* const activep = lvertexp->activep(); - return VNUser(m_varVisitor.findDupe(nodep, consumerVarScopep, activep)); + return VNUser{m_varVisitor.findDupe(nodep, consumerVarScopep, activep)}; } - return VNUser(0); + return VNUser{0}; } public: @@ -1257,10 +1257,10 @@ private: } } } - return VNUser(0); + return VNUser{0}; } virtual VNUser visit(GateLogicVertex*, VNUser) override { // - return VNUser(0); + return VNUser{0}; } public: @@ -1363,7 +1363,7 @@ private: virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) override { // Check that we haven't been here before AstVarScope* const vsp = vvertexp->varScp(); - if (vsp->user2SetOnce()) return VNUser(0); + if (vsp->user2SetOnce()) return VNUser{0}; UINFO(9, "CLK DECOMP Var - " << vvertexp << " : " << vsp << endl); if (vsp->varp()->width() > 1) { m_seen_clk_vectors++; @@ -1371,10 +1371,10 @@ private: } const GateClkDecompState* const currState = reinterpret_cast(vu.c()); GateClkDecompState nextState(currState->m_offset, vsp); - vvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState)); + vvertexp->iterateCurrentOutEdges(*this, VNUser{&nextState}); if (vsp->varp()->width() > 1) --m_seen_clk_vectors; vsp->user2(false); - return VNUser(0); // Unused + return VNUser{0}; // Unused } virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override { @@ -1390,37 +1390,37 @@ private: UINFO(9, "CLK DECOMP Sel [ " << rselp->msbConst() << " : " << rselp->lsbConst() << " ] dropped clock (" << clk_offset << ")" << endl); - return VNUser(0); + return VNUser{0}; } clk_offset -= rselp->lsbConst(); } else { - return VNUser(0); + return VNUser{0}; } } else if (AstConcat* const catp = VN_CAST(assignp->rhsp(), Concat)) { UINFO(9, "CLK DECOMP Concat searching - " << assignp->lhsp() << endl); int concat_offset; if (!m_concat_visitor.concatOffset(catp, currState->m_last_vsp, concat_offset /*ref*/)) { - return VNUser(0); + return VNUser{0}; } clk_offset += concat_offset; } else if (VN_IS(assignp->rhsp(), VarRef)) { UINFO(9, "CLK DECOMP VarRef searching - " << assignp->lhsp() << endl); } else { - return VNUser(0); + return VNUser{0}; } // LHS if (const AstSel* const lselp = VN_CAST(assignp->lhsp(), Sel)) { if (VN_IS(lselp->lsbp(), Const) && VN_IS(lselp->widthp(), Const)) { clk_offset += lselp->lsbConst(); } else { - return VNUser(0); + return VNUser{0}; } } else if (const AstVarRef* const vrp = VN_CAST(assignp->lhsp(), VarRef)) { if (vrp->dtypep()->width() == 1 && m_seen_clk_vectors) { if (clk_offset != 0) { UINFO(9, "Should only make it here with clk_offset = 0" << endl); - return VNUser(0); + return VNUser{0}; } UINFO(9, "CLK DECOMP Connecting - " << assignp->lhsp() << endl); UINFO(9, " to - " << m_clk_vsp << endl); @@ -1433,12 +1433,12 @@ private: m_total_decomposed_clk_vectors++; } } else { - return VNUser(0); + return VNUser{0}; } GateClkDecompState nextState(clk_offset, currState->m_last_vsp); - return lvertexp->iterateCurrentOutEdges(*this, VNUser(&nextState)); + return lvertexp->iterateCurrentOutEdges(*this, VNUser{&nextState}); } - return VNUser(0); + return VNUser{0}; } public: @@ -1455,7 +1455,7 @@ public: m_clk_vsp = vvertexp->varScp(); m_clk_vvertexp = vvertexp; GateClkDecompState nextState(0, m_clk_vsp); - vvertexp->accept(*this, VNUser(&nextState)); + vvertexp->accept(*this, VNUser{&nextState}); } }; diff --git a/src/V3LangCode.h b/src/V3LangCode.h index 3877dcf3d..0565a948d 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -48,7 +48,7 @@ public: "1800-2005", "1800-2009", "1800-2012", "1800-2017"}; return names[m_e]; } - static V3LangCode mostRecent() { return V3LangCode(L1800_2017); } + static V3LangCode mostRecent() { return V3LangCode{L1800_2017}; } bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009 || m_e == L1800_2012 || m_e == L1800_2017; } diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 112c3920e..482a4d301 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -165,7 +165,7 @@ public: checkRemoveAssign(it); it->second.simpleAssign(assp); } else { - m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::SIMPLEASSIGN(), assp)); + m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::SIMPLEASSIGN{}, assp}); } // lifeDump(); } @@ -175,7 +175,7 @@ public: if (it != m_map.end()) { it->second.complexAssign(); } else { - m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN())); + m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}}); } } void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) { @@ -196,7 +196,7 @@ public: UINFO(4, " usage: " << nodep << endl); it->second.consumed(); } else { - m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::CONSUMED())); + m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::CONSUMED{}}); } } void complexAssignFind(AstVarScope* nodep) { @@ -205,7 +205,7 @@ public: UINFO(4, " casfind: " << it->first << endl); it->second.complexAssign(); } else { - m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::COMPLEXASSIGN())); + m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}}); } } void consumedFind(AstVarScope* nodep) { @@ -213,7 +213,7 @@ public: if (it != m_map.end()) { it->second.consumed(); } else { - m_map.emplace(nodep, LifeVarEntry(LifeVarEntry::CONSUMED())); + m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::CONSUMED{}}); } } void lifeToAbove() { diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index 51b2e0e2c..da18dec1b 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -59,7 +59,7 @@ private: UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (AstVarScope* const newvscp = reinterpret_cast(vscp->user4p())) { UINFO(9, " Replace " << nodep << " to " << newvscp << endl); - AstVarRef* const newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->access()); + AstVarRef* const newrefp = new AstVarRef{nodep->fileline(), newvscp, nodep->access()}; nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 493beaf4d..6a85a0ff4 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1024,7 +1024,7 @@ class LinkDotFindVisitor final : public VNVisitor { } AstVar* const newvarp = new AstVar(nodep->fileline(), VVarType::VAR, nodep->name(), - VFlagChildDType(), dtypep); // Not dtype resolved yet + VFlagChildDType{}, dtypep); // Not dtype resolved yet newvarp->direction(VDirection::OUTPUT); newvarp->lifetime(VLifetime::AUTOMATIC); newvarp->funcReturn(true); @@ -1139,8 +1139,8 @@ class LinkDotFindVisitor final : public VNVisitor { // We first search if the parameter is overwritten and then replace it with a // new value. It will keep the same FileLine information. if (v3Global.opt.hasParameter(nodep->name())) { - AstVar* const newp = new AstVar( - nodep->fileline(), VVarType(VVarType::GPARAM), nodep->name(), nodep); + AstVar* const newp = new AstVar{ + nodep->fileline(), VVarType{VVarType::GPARAM}, nodep->name(), nodep}; newp->combineType(nodep); const string svalue = v3Global.opt.parameter(nodep->name()); if (AstNode* const valuep @@ -1935,7 +1935,7 @@ private: } } AstVar* const newp = new AstVar(nodep->fileline(), VVarType::WIRE, nodep->name(), - VFlagLogicPacked(), 1); + VFlagLogicPacked{}, 1); newp->trace(modp->modTrace()); nodep->varp(newp); modp->addStmtp(newp); @@ -2509,7 +2509,7 @@ private: UINFO(7, " ErrParseRef curSymp=se" << cvtToHex(m_curSymp) << " ds=" << m_ds.ascii() << endl); const string suggest = m_statep->suggestSymFallback( - m_ds.m_dotSymp, nodep->name(), VNodeMatcher()); + m_ds.m_dotSymp, nodep->name(), VNodeMatcher{}); nodep->v3error("Can't find definition of " << expectWhat << ": " << nodep->prettyNameQ() << '\n' << (suggest.empty() ? "" : nodep->warnMore() + suggest)); diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index b9ecca249..3e9130ed3 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -94,7 +94,7 @@ void V3LinkLevel::timescaling(const ModVec& mods) { } } unit = v3Global.opt.timeComputeUnit(unit); // Apply override - if (unit.isNone()) unit = VTimescale(VTimescale::TS_DEFAULT); + if (unit.isNone()) unit = VTimescale{VTimescale::TS_DEFAULT}; v3Global.rootp()->timeunit(unit); bool dunitTimed = false; // $unit had a timeunit @@ -127,7 +127,7 @@ void V3LinkLevel::timescaling(const ModVec& mods) { if (v3Global.rootp()->timeprecision().isNone()) { v3Global.rootp()->timeprecisionMerge(v3Global.rootp()->fileline(), - VTimescale(VTimescale::TS_DEFAULT)); + VTimescale{VTimescale::TS_DEFAULT}); } // Classes under package have timescale propaged in V3LinkParse diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 2acc01f3e..af7185f60 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -73,7 +73,7 @@ private: // We could have verilog.l create a new one on every token, // but that's a lot more structures than only doing AST nodes. if (m_filelines.find(nodep->fileline()) != m_filelines.end()) { - nodep->fileline(new FileLine(nodep->fileline())); + nodep->fileline(new FileLine{nodep->fileline()}); } m_filelines.insert(nodep->fileline()); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 6836b5167..10d83bd1b 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -113,7 +113,7 @@ public: V3LangCode::V3LangCode(const char* textp) { // Return code for given string, or ERROR, which is a bad code for (int codei = V3LangCode::L_ERROR; codei < V3LangCode::_ENUM_END; ++codei) { - const V3LangCode code = V3LangCode(codei); + const V3LangCode code{codei}; if (0 == VL_STRCASECMP(textp, code.ascii())) { m_e = code; return; @@ -265,7 +265,7 @@ void VTimescale::parseSlashed(FileLine* fl, const char* textp, VTimescale& unitr if (!precStr.empty()) { VTimescale prec(VTimescale::NONE); bool precbad; - prec = VTimescale(precStr, precbad /*ref*/); + prec = VTimescale{precStr, precbad /*ref*/}; if (precbad) { fl->v3error("`timescale timeprecision syntax error: '" << precStr << "'"); return; @@ -1164,7 +1164,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-LDFLAGS", CbVal, callStrSetter(&V3Options::addLdLibs)); const auto setLang = [this, fl](const char* valp) { - const V3LangCode optval = V3LangCode(valp); + const V3LangCode optval{valp}; if (optval.legal()) { m_defaultLanguage = optval; } else { diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 9c20558e4..74e4aaf0a 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -1335,9 +1335,10 @@ class OrderProcess final : VNDeleter { ~OrderProcess() override { // Stats for (int type = 0; type < OrderVEdgeType::_ENUM_END; type++) { - const double count = double(m_statCut[type]); + const double count{m_statCut[type]}; if (count != 0.0) { - V3Stats::addStat(string("Order, cut, ") + OrderVEdgeType(type).ascii(), count); + V3Stats::addStat(std::string{"Order, cut, "} + OrderVEdgeType{type}.ascii(), + count); } } } diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 1d2832ce5..37da5a1fc 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -89,19 +89,19 @@ void V3ParseImp::lexTimescaleParse(FileLine* fl, const char* textp) { } void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal, bool precSet, double precVal) { - VTimescale unit(VTimescale::NONE); + VTimescale unit{VTimescale::NONE}; if (unitSet) { bool bad; - unit = VTimescale(unitVal, bad /*ref*/); + unit = VTimescale{unitVal, bad /*ref*/}; if (bad) { UINFO(1, "Value = " << unitVal << endl); fl->v3error("timeunit illegal value"); } } - VTimescale prec(VTimescale::NONE); + VTimescale prec{VTimescale::NONE}; if (precSet) { bool bad; - prec = VTimescale(precVal, bad /*ref*/); + prec = VTimescale{precVal, bad /*ref*/}; if (bad) { UINFO(1, "Value = " << precVal << endl); fl->v3error("timeprecision illegal value"); diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 0c9c6f43f..17f22e127 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -625,8 +625,8 @@ private: iterate(nodep->lhsp()); if (optimizable()) { if (fetchConst(nodep->lhsp())->num().isEqZero()) { - const AstConst cnst(nodep->fileline(), AstConst::WidthedValue(), 1, - 1); // a one + const AstConst cnst{nodep->fileline(), AstConst::WidthedValue{}, 1, + 1}; // a one newValue(nodep, &cnst); // a one } else { iterate(nodep->rhsp()); @@ -1022,8 +1022,8 @@ private: m_callStack.push_back(&stackNode); // Clear output variable if (const auto* const basicp = VN_CAST(funcp->fvarp(), Var)->basicp()) { - AstConst cnst(funcp->fvarp()->fileline(), AstConst::WidthedValue(), basicp->widthMin(), - 0); + AstConst cnst{funcp->fvarp()->fileline(), AstConst::WidthedValue{}, basicp->widthMin(), + 0}; if (basicp->isZeroInit()) { cnst.num().setAllBits0(); } else { diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 97d2514b8..11512254d 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -231,7 +231,7 @@ public: V3Stats::addStat(m_stage, "Var space, scoped, bytes", m_statVarScpBytes); } for (unsigned i = 0; i < m_statVarWidths.size(); i++) { - const double count = double(m_statVarWidths.at(i)); + const double count{m_statVarWidths.at(i)}; if (count != 0.0) { if (v3Global.opt.statsVars()) { const NameMap& nameMapr = m_statVarWidthNames.at(i); @@ -249,7 +249,7 @@ public: } // Node types for (int type = 0; type < VNType::_ENUM_END; type++) { - const double count = double(m_statTypeCount.at(type)); + const double count{m_statTypeCount.at(type)}; if (count != 0.0) { V3Stats::addStat(m_stage, std::string{"Node count, "} + VNType{type}.ascii(), count); @@ -257,18 +257,18 @@ public: } for (int type = 0; type < VNType::_ENUM_END; type++) { for (int type2 = 0; type2 < VNType::_ENUM_END; type2++) { - const double count = double(m_statAbove[type][type2]); + const double count{m_statAbove[type][type2]}; if (count != 0.0) { V3Stats::addStat(m_stage, (std::string{"Node pairs, "} + VNType{type}.ascii() + "_" - + VNType(type2).ascii()), + + VNType{type2}.ascii()), count); } } } // Branch pred for (int type = 0; type < VBranchPred::_ENUM_END; type++) { - const double count = double(m_statPred[type]); + const double count{m_statPred[type]}; if (count != 0.0) { V3Stats::addStat(m_stage, (std::string{"Branch prediction, "} + VBranchPred{type}.ascii()), diff --git a/src/V3Table.cpp b/src/V3Table.cpp index e1f6cc2f0..8829e9cbf 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -298,8 +298,8 @@ private: uint32_t shift = 0; for (AstVarScope* invscp : m_inVarps) { // LSB is first variable, so extract it that way - const AstConst cnst(invscp->fileline(), AstConst::WidthedValue(), invscp->width(), - VL_MASK_I(invscp->width()) & (inValue >> shift)); + const AstConst cnst{invscp->fileline(), AstConst::WidthedValue{}, invscp->width(), + VL_MASK_I(invscp->width()) & (inValue >> shift)}; simvis.newValue(invscp, &cnst); shift += invscp->width(); // We are using 32 bit arithmetic, because there's no way the input table can be diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 4a596e434..8268ec487 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -392,7 +392,7 @@ private: // Everything downstream is packed, so deal with as one trace unit. // This may not be the nicest for user presentation, but is // a much faster way to trace - addTraceDecl(VNumRange(), nodep->width()); + addTraceDecl(VNumRange{}, nodep->width()); } else { FileLine* const flp = nodep->fileline(); AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); @@ -418,7 +418,7 @@ private: // Everything downstream is packed, so deal with as one trace unit // This may not be the nicest for user presentation, but is // a much faster way to trace - addTraceDecl(VNumRange(), nodep->width()); + addTraceDecl(VNumRange{}, nodep->width()); } else if (!nodep->packed()) { addIgnore("Unsupported: Unpacked struct/union"); } else { @@ -454,7 +454,7 @@ private: if (nodep->isString()) { addIgnore("Unsupported: strings"); } else { - addTraceDecl(VNumRange(), 0); + addTraceDecl(VNumRange{}, 0); } } } diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 12f011366..5d027a135 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -331,8 +331,8 @@ private: // We use the special XTEMP type so it doesn't break pure functions UASSERT_OBJ(m_modp, nodep, "X number not under module"); AstVar* const newvarp - = new AstVar(nodep->fileline(), VVarType::XTEMP, m_xrandNames.get(nodep), - VFlagLogicPacked(), nodep->width()); + = new AstVar{nodep->fileline(), VVarType::XTEMP, m_xrandNames.get(nodep), + VFlagLogicPacked{}, nodep->width()}; newvarp->lifetime(VLifetime::STATIC); ++m_statUnkVars; VNRelinker replaceHandle; @@ -454,7 +454,7 @@ private: nodep->unlinkFrBack(&replaceHandle); V3Number xnum(nodep, nodep->width()); if (nodep->isString()) { - xnum = V3Number(V3Number::String(), nodep, ""); + xnum = V3Number{V3Number::String{}, nodep, ""}; } else { xnum.setAllBitsX(); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index a784b3024..6a303ee0b 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6282,7 +6282,7 @@ private: VNumRange declRange; // ranged() set false for (int i = 1; i <= dim; ++i) { // UINFO(9, " dim at "<declRange(); if (i < dim) dtypep = adtypep->subDTypep()->skipRefp(); diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index d958f6d52..19392df58 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -524,8 +524,8 @@ private: // up array: lsb/hi -: width const int32_t msb = VN_IS(nodep, SelPlus) ? rhs + width - 1 : rhs; const int32_t lsb = VN_IS(nodep, SelPlus) ? rhs : rhs - width + 1; - AstSliceSel* const newp = new AstSliceSel( - nodep->fileline(), fromp, VNumRange(msb, lsb, fromRange.littleEndian())); + AstSliceSel* const newp = new AstSliceSel{ + nodep->fileline(), fromp, VNumRange{msb, lsb, fromRange.littleEndian()}}; nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { diff --git a/src/verilog.y b/src/verilog.y index 161fe8f67..3eba4ed3b 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3926,7 +3926,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or | yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); } | yD_RANDOM '(' expr ')' { $$ = new AstRand($1, $3, false); } | yD_RANDOM parenE { $$ = new AstRand($1, nullptr, false); } - | yD_REALTIME parenE { $$ = new AstTimeD($1, VTimescale(VTimescale::NONE)); } + | yD_REALTIME parenE { $$ = new AstTimeD{$1, VTimescale{VTimescale::NONE}}; } | yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); } | yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); } | yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,VAttrType::DIM_RIGHT,$3,nullptr); } @@ -3944,13 +3944,14 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or | yD_SIZE '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,VAttrType::DIM_SIZE,$3,$5); } | yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } - | yD_STIME parenE { $$ = new AstSel($1, new AstTime($1, VTimescale(VTimescale::NONE)), 0, 32); } + | yD_STIME parenE + { $$ = new AstSel{$1, new AstTime{$1, VTimescale{VTimescale::NONE}}, 0, 32}; } | yD_STABLE '(' expr ')' { $$ = new AstStable($1,$3); } | yD_STABLE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $stable and clock arguments"); } | yD_TAN '(' expr ')' { $$ = new AstTanD($1,$3); } | yD_TANH '(' expr ')' { $$ = new AstTanhD($1,$3); } | yD_TESTPLUSARGS '(' expr ')' { $$ = new AstTestPlusArgs($1, $3); } - | yD_TIME parenE { $$ = new AstTime($1, VTimescale(VTimescale::NONE)); } + | yD_TIME parenE { $$ = new AstTime{$1, VTimescale{VTimescale::NONE}}; } | yD_TYPENAME '(' exprOrDataType ')' { $$ = new AstAttrOf($1, VAttrType::TYPENAME, $3); } | yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first | yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,VAttrType::DIM_UNPK_DIMENSIONS,$3); } @@ -6631,7 +6632,7 @@ vltOffFront: | yVLT_TRACING_OFF { $$ = V3ErrorCode::I_TRACING; } | yVLT_LINT_OFF { $$ = V3ErrorCode::I_LINT; } | yVLT_LINT_OFF yVLT_D_RULE idAny - { $$ = V3ErrorCode((*$3).c_str()); + { $$ = V3ErrorCode{(*$3).c_str()}; if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: " << *$3); } } ; @@ -6640,7 +6641,7 @@ vltOnFront: | yVLT_TRACING_ON { $$ = V3ErrorCode::I_TRACING; } | yVLT_LINT_ON { $$ = V3ErrorCode::I_LINT; } | yVLT_LINT_ON yVLT_D_RULE idAny - { $$ = V3ErrorCode((*$3).c_str()); + { $$ = V3ErrorCode{(*$3).c_str()}; if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown Error Code: " << *$3); } } ; From d16619fe8645a51e748c606ff04e9f27b0098ed0 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Thu, 15 Sep 2022 19:43:56 +0100 Subject: [PATCH 39/75] astgen: Explicitly generate AstNode members Generate boilerplate members of AstNode sub-types directly via astgen. This is in preparation for generating additional members. --- src/V3Ast.h | 38 +---- src/V3AstNodeDType.h | 52 +++--- src/V3AstNodeMath.h | 387 ++++++++++++++++++++++--------------------- src/V3AstNodeOther.h | 375 ++++++++++++++++++++--------------------- src/V3AstNodes.cpp | 2 +- src/astgen | 82 +++++++-- 6 files changed, 488 insertions(+), 448 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index 86d4a324f..ff3cce31b 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -2391,36 +2391,14 @@ inline AstNode* VNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) { return nodep->iterateSubtreeReturnEdits(*this); } -// ###################################################################### -// Standard defines for all AstNode subclasses - -#define ASTNODE_BASE_FUNCS(name) \ - virtual ~Ast##name() override = default; \ - static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ - } \ - Ast##name* cloneTree(bool cloneNext) { \ - return static_cast(AstNode::cloneTree(cloneNext)); \ - } \ - Ast##name* clonep() const { return static_cast(AstNode::clonep()); } - -#define ASTNODE_NODE_FUNCS_NO_DTOR(name) \ - virtual void accept(VNVisitor& v) override { v.visit(this); } \ - virtual AstNode* clone() override { return new Ast##name{*this}; } \ - static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ - } \ - Ast##name* cloneTree(bool cloneNext) { \ - return static_cast(AstNode::cloneTree(cloneNext)); \ - } \ - Ast##name* clonep() const { return static_cast(AstNode::clonep()); } - -#define ASTNODE_NODE_FUNCS(name) \ - virtual ~Ast##name() override = default; \ - ASTNODE_NODE_FUNCS_NO_DTOR(name) - -// Macros generated by 'astgen' -#include "V3AstNodes__gen_macros.h" +// Include macros generated by 'astgen'. These include ASTGEN_MEMBERS_ +// for each AstNode sub-type, and ASTGEN_SUPER_ for concrete final +// AstNode sub-types. The generated members include boilerplate methods related +// to cloning, visitor dispatch, and other functionality. ASTGEN_SUPER_ +// is the necessary constructor invocation for concrete AstNode sub-types +// that passes the generated type-id numbers all the way back to AstNode. +// For precise details please read the generated macros. +#include "V3Ast__gen_macros.h" // AstNode subclasses #include "V3AstNodeDType.h" diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 9066caeed..3615650af 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -50,7 +50,7 @@ protected: : AstNode{t, fl} {} public: - ASTNODE_BASE_FUNCS(NodeDType) + ASTGEN_MEMBERS_NodeDType; // ACCESSORS virtual void dump(std::ostream& str) const override; virtual void dumpSmall(std::ostream& str) const; @@ -142,7 +142,7 @@ protected: : AstNodeDType{t, fl} {} public: - ASTNODE_BASE_FUNCS(NodeArrayDType) + ASTGEN_MEMBERS_NodeArrayDType; virtual void dump(std::ostream& str) const override; virtual void dumpSmall(std::ostream& str) const override; virtual const char* broken() const override { @@ -215,7 +215,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeUOrStructDType) + ASTGEN_MEMBERS_NodeUOrStructDType; int uniqueNum() const { return m_uniqueNum; } virtual const char* broken() const override; virtual void dump(std::ostream& str) const override; @@ -276,7 +276,7 @@ public: addNOp1p(rangep); addNOp2p(initp); } - ASTNODE_NODE_FUNCS(EnumItem) + ASTGEN_MEMBERS_EnumItem; virtual string name() const override { return m_name; } virtual bool maybePointedTo() const override { return true; } virtual bool hasDType() const override { return true; } @@ -310,7 +310,7 @@ public: keyDTypep(keyDtp); dtypep(dtp); } - ASTNODE_NODE_FUNCS(AssocArrayDType) + ASTGEN_MEMBERS_AssocArrayDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -403,7 +403,7 @@ private: AstRange* rangep); public: - ASTNODE_NODE_FUNCS(BasicDType) + ASTGEN_MEMBERS_BasicDType; virtual void dump(std::ostream& str) const override; // width/widthMin/numeric compared elsewhere virtual bool same(const AstNode* samep) const override { @@ -482,7 +482,7 @@ public: setOp1p(dtp); // Only for parser setOp2p(elementsp); // Only for parser } - ASTNODE_NODE_FUNCS(BracketArrayDType) + ASTGEN_MEMBERS_BracketArrayDType; virtual bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } @@ -514,7 +514,7 @@ public: dtypep(this); addNOp4p(paramsp); } - ASTNODE_NODE_FUNCS(ClassRefDType) + ASTGEN_MEMBERS_ClassRefDType; // METHODS const char* broken() const override; void cloneRelink() override; @@ -558,7 +558,7 @@ public: dtypep(nullptr); // V3Width will resolve widthFromSub(subDTypep()); } - ASTNODE_NODE_FUNCS(ConstDType) + ASTGEN_MEMBERS_ConstDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -616,7 +616,7 @@ public: childDTypep(dtp); // Only for parser dtypep(nullptr); // V3Width will resolve } - ASTNODE_NODE_FUNCS(DefImplicitDType) + ASTGEN_MEMBERS_DefImplicitDType; int uniqueNum() const { return m_uniqueNum; } virtual bool same(const AstNode* samep) const override { const AstDefImplicitDType* const sp = static_cast(samep); @@ -663,7 +663,7 @@ public: refDTypep(dtp); dtypep(nullptr); // V3Width will resolve } - ASTNODE_NODE_FUNCS(DynArrayDType) + ASTGEN_MEMBERS_DynArrayDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -710,7 +710,7 @@ public: : ASTGEN_SUPER_EmptyQueueDType(fl) { dtypep(this); } - ASTNODE_NODE_FUNCS(EmptyQueueDType) + ASTGEN_MEMBERS_EmptyQueueDType; virtual void dumpSmall(std::ostream& str) const override; virtual bool hasDType() const override { return true; } virtual bool maybePointedTo() const override { return true; } @@ -748,7 +748,7 @@ public: dtypep(nullptr); // V3Width will resolve widthFromSub(subDTypep()); } - ASTNODE_NODE_FUNCS(EnumDType) + ASTGEN_MEMBERS_EnumDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -817,7 +817,7 @@ public: , m_cellName{cellName} , m_ifaceName{ifaceName} , m_modportName{modport} {} - ASTNODE_NODE_FUNCS(IfaceRefDType) + ASTGEN_MEMBERS_IfaceRefDType; // METHODS virtual const char* broken() const override; virtual void dump(std::ostream& str = std::cout) const override; @@ -871,7 +871,7 @@ public: dtypep(this); widthFromSub(subDTypep()); } - ASTNODE_NODE_FUNCS(MemberDType) + ASTGEN_MEMBERS_MemberDType; virtual string name() const override { return m_name; } // * = Var name virtual bool hasDType() const override { return true; } virtual bool maybePointedTo() const override { return true; } @@ -934,7 +934,7 @@ public: childDTypep(dtp); // Only for parser dtypep(nullptr); // V3Width will resolve } - ASTNODE_NODE_FUNCS(ParamTypeDType) + ASTGEN_MEMBERS_ParamTypeDType; virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } @@ -975,7 +975,7 @@ class AstParseTypeDType final : public AstNodeDType { public: explicit AstParseTypeDType(FileLine* fl) : ASTGEN_SUPER_ParseTypeDType(fl) {} - ASTNODE_NODE_FUNCS(ParseTypeDType) + ASTGEN_MEMBERS_ParseTypeDType; AstNodeDType* dtypep() const { return nullptr; } // METHODS virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } @@ -1011,7 +1011,7 @@ public: refDTypep(dtp); dtypep(dtp); } - ASTNODE_NODE_FUNCS(QueueDType) + ASTGEN_MEMBERS_QueueDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -1081,7 +1081,7 @@ public: : ASTGEN_SUPER_RefDType(fl) { setOp2p(typeofp); } - ASTNODE_NODE_FUNCS(RefDType) + ASTGEN_MEMBERS_RefDType; // METHODS const char* broken() const override; void cloneRelink() override; @@ -1160,7 +1160,7 @@ public: refDTypep(nullptr); dtypep(nullptr); // V3Width will resolve } - ASTNODE_NODE_FUNCS(UnsizedArrayDType) + ASTGEN_MEMBERS_UnsizedArrayDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -1198,7 +1198,7 @@ public: : ASTGEN_SUPER_VoidDType(fl) { dtypep(this); } - ASTNODE_NODE_FUNCS(VoidDType) + ASTGEN_MEMBERS_VoidDType; virtual void dumpSmall(std::ostream& str) const override; virtual bool hasDType() const override { return true; } virtual bool maybePointedTo() const override { return true; } @@ -1230,7 +1230,7 @@ public: refDTypep(nullptr); dtypep(nullptr); // V3Width will resolve } - ASTNODE_NODE_FUNCS(WildcardArrayDType) + ASTGEN_MEMBERS_WildcardArrayDType; virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); @@ -1274,7 +1274,7 @@ class AstPackArrayDType final : public AstNodeArrayDType { public: inline AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep); inline AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep); - ASTNODE_NODE_FUNCS(PackArrayDType) + ASTGEN_MEMBERS_PackArrayDType; virtual string prettyDTypeName() const override; virtual bool isCompound() const override { return false; } }; @@ -1303,7 +1303,7 @@ public: // width and signing from the subDType/base type widthFromSub(subDTypep()); } - ASTNODE_NODE_FUNCS(UnpackArrayDType) + ASTGEN_MEMBERS_UnpackArrayDType; virtual string prettyDTypeName() const override; virtual bool same(const AstNode* samep) const override { const AstUnpackArrayDType* const sp = static_cast(samep); @@ -1321,7 +1321,7 @@ public: // VSigning below is mispurposed to indicate if packed or not AstStructDType(FileLine* fl, VSigning numericUnpack) : ASTGEN_SUPER_StructDType(fl, numericUnpack) {} - ASTNODE_NODE_FUNCS(StructDType) + ASTGEN_MEMBERS_StructDType; virtual string verilogKwd() const override { return "struct"; } }; class AstUnionDType final : public AstNodeUOrStructDType { @@ -1330,7 +1330,7 @@ public: // VSigning below is mispurposed to indicate if packed or not AstUnionDType(FileLine* fl, VSigning numericUnpack) : ASTGEN_SUPER_UnionDType(fl, numericUnpack) {} - ASTNODE_NODE_FUNCS(UnionDType) + ASTGEN_MEMBERS_UnionDType; virtual string verilogKwd() const override { return "union"; } }; diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index e019298f9..78360c3c2 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -44,7 +44,7 @@ protected: : AstNode{t, fl} {} public: - ASTNODE_BASE_FUNCS(NodeMath) + ASTGEN_MEMBERS_NodeMath; // METHODS virtual void dump(std::ostream& str) const override; virtual bool hasDType() const override { return true; } @@ -68,7 +68,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeBiop) + ASTGEN_MEMBERS_NodeBiop; // Clone single node, just get same type back. virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // ACCESSORS @@ -97,7 +97,7 @@ protected: : AstNodeBiop{t, fl, lhs, rhs} {} public: - ASTNODE_BASE_FUNCS(NodeBiCom) + ASTGEN_MEMBERS_NodeBiCom; }; class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom { // Binary math with commutative & associative properties @@ -106,7 +106,7 @@ protected: : AstNodeBiCom{t, fl, lhs, rhs} {} public: - ASTNODE_BASE_FUNCS(NodeBiComAsv) + ASTGEN_MEMBERS_NodeBiComAsv; }; class AstNodeSel VL_NOT_FINAL : public AstNodeBiop { // Single bit range extraction, perhaps with non-constant selection or array selection @@ -115,7 +115,7 @@ protected: : AstNodeBiop{t, fl, fromp, bitp} {} public: - ASTNODE_BASE_FUNCS(NodeSel) + ASTGEN_MEMBERS_NodeSel; AstNode* fromp() const { return op1p(); } // op1 = Extracting what (nullptr=TBD during parsing) @@ -134,7 +134,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeStream) + ASTGEN_MEMBERS_NodeStream; }; class AstNodeSystemBiop VL_NOT_FINAL : public AstNodeBiop { public: @@ -142,6 +142,7 @@ public: : AstNodeBiop(t, fl, lhsp, rhsp) { dtypeSetDouble(); } + ASTGEN_MEMBERS_NodeSystemBiop; virtual bool cleanOut() const override { return false; } virtual bool cleanLhs() const override { return false; } virtual bool cleanRhs() const override { return false; } @@ -162,7 +163,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeQuadop) + ASTGEN_MEMBERS_NodeQuadop; AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } AstNode* thsp() const { return op3p(); } @@ -194,7 +195,7 @@ protected: : AstNodeMath{t, fl} {} public: - ASTNODE_BASE_FUNCS(NodeTermop) + ASTGEN_MEMBERS_NodeTermop; // Know no children, and hot function, so skip iterator for speed // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst @@ -212,7 +213,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeTriop) + ASTGEN_MEMBERS_NodeTriop; AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } AstNode* thsp() const { return op3p(); } @@ -246,7 +247,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeCond) + ASTGEN_MEMBERS_NodeCond; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override; AstNode* condp() const { return op1p(); } // op1 = Condition @@ -274,7 +275,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeUniop) + ASTGEN_MEMBERS_NodeUniop; AstNode* lhsp() const { return op1p(); } void lhsp(AstNode* nodep) { return setOp1p(nodep); } // METHODS @@ -296,7 +297,7 @@ public: : AstNodeUniop(t, fl, lhsp) { dtypeSetDouble(); } - ASTNODE_BASE_FUNCS(NodeSystemUniop) + ASTGEN_MEMBERS_NodeSystemUniop; virtual bool cleanOut() const override { return true; } virtual bool cleanLhs() const override { return false; } virtual bool sizeMattersLhs() const override { return false; } @@ -329,7 +330,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeVarRef) + ASTGEN_MEMBERS_NodeVarRef; virtual void dump(std::ostream& str) const override; virtual bool hasDType() const override { return true; } virtual const char* broken() const override; @@ -370,7 +371,7 @@ public: } public: - ASTNODE_NODE_FUNCS(AddrOfCFunc) + ASTGEN_MEMBERS_AddrOfCFunc; virtual void cloneRelink() override; virtual const char* broken() const override; virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -392,7 +393,7 @@ public: dtypeFrom(exprsp); } inline AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true); - ASTNODE_NODE_FUNCS(CMath) + ASTGEN_MEMBERS_CMath; virtual bool isGateOptimizable() const override { return m_pure; } virtual bool isPredictOptimizable() const override { return m_pure; } virtual bool cleanOut() const override { return m_cleanOut; } @@ -413,7 +414,7 @@ public: : ASTGEN_SUPER_ConsAssoc(fl) { setNOp1p(defaultp); } - ASTNODE_NODE_FUNCS(ConsAssoc) + ASTGEN_MEMBERS_ConsAssoc; virtual string emitVerilog() override { return "'{}"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -432,7 +433,7 @@ public: setNOp1p(lhsp); setNOp2p(rhsp); } - ASTNODE_NODE_FUNCS(ConsDynArray) + ASTGEN_MEMBERS_ConsDynArray; virtual string emitVerilog() override { return "'{%l, %r}"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -452,7 +453,7 @@ public: setNOp1p(lhsp); setNOp2p(rhsp); } - ASTNODE_NODE_FUNCS(ConsQueue) + ASTGEN_MEMBERS_ConsQueue; virtual string emitVerilog() override { return "'{%l, %r}"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -471,7 +472,7 @@ public: : ASTGEN_SUPER_ConsWildcard(fl) { setNOp1p(defaultp); } - ASTNODE_NODE_FUNCS(ConsWildcard) + ASTGEN_MEMBERS_ConsWildcard; virtual string emitVerilog() override { return "'{}"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -593,7 +594,7 @@ public: dtypeSetBit(); // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here initWithNumber(); } - ASTNODE_NODE_FUNCS(Const) + ASTGEN_MEMBERS_Const; virtual string name() const override { return num().ascii(); } // * = Value const V3Number& num() const { return m_num; } // * = Value V3Number& num() { return m_num; } // * = Value @@ -618,7 +619,7 @@ class AstEmptyQueue final : public AstNodeMath { public: explicit AstEmptyQueue(FileLine* fl) : ASTGEN_SUPER_EmptyQueue(fl) {} - ASTNODE_NODE_FUNCS(EmptyQueue) + ASTGEN_MEMBERS_EmptyQueue; virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() override { return "{}"; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -635,7 +636,7 @@ public: , m_classOrPackagep{classOrPackagep} { dtypeFrom(m_itemp); } - ASTNODE_NODE_FUNCS(EnumItemRef) + ASTGEN_MEMBERS_EnumItemRef; virtual void dump(std::ostream& str) const override; virtual string name() const override { return itemp()->name(); } virtual int instrCount() const override { return 0; } @@ -665,7 +666,7 @@ public: setOp2p(resultp); // Possibly in future nullptr could mean return rhsp() dtypeFrom(resultp); } - ASTNODE_NODE_FUNCS(ExprStmt) + ASTGEN_MEMBERS_ExprStmt; // ACCESSORS AstNode* stmtsp() const { return op1p(); } void addStmtsp(AstNode* nodep) { addOp1p(nodep); } @@ -683,7 +684,7 @@ public: setOp1p(filep); setOp2p(strp); } - ASTNODE_NODE_FUNCS(FError) + ASTGEN_MEMBERS_FError; virtual string emitVerilog() override { return "%f$ferror(%l, %r)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -713,7 +714,7 @@ public: setNOp3p(startp); setNOp4p(countp); } - ASTNODE_NODE_FUNCS(FRead) + ASTGEN_MEMBERS_FRead; virtual string verilogKwd() const override { return "$fread"; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -740,7 +741,7 @@ public: : ASTGEN_SUPER_FRewind(fl) { setNOp2p(filep); } - ASTNODE_NODE_FUNCS(FRewind) + ASTGEN_MEMBERS_FRewind; virtual string verilogKwd() const override { return "$frewind"; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -768,7 +769,7 @@ public: addNOp1p(exprsp); setNOp2p(filep); } - ASTNODE_NODE_FUNCS(FScanF) + ASTGEN_MEMBERS_FScanF; virtual string name() const override { return m_text; } virtual string verilogKwd() const override { return "$fscanf"; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -800,7 +801,7 @@ public: setNOp3p(offset); setNOp4p(operation); } - ASTNODE_NODE_FUNCS(FSeek) + ASTGEN_MEMBERS_FSeek; virtual string verilogKwd() const override { return "$fseek"; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -825,7 +826,7 @@ public: : ASTGEN_SUPER_FTell(fl) { setNOp2p(filep); } - ASTNODE_NODE_FUNCS(FTell) + ASTGEN_MEMBERS_FTell; virtual string verilogKwd() const override { return "$ftell"; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -848,7 +849,7 @@ public: : ASTGEN_SUPER_Fell(fl) { addOp1p(exprp); } - ASTNODE_NODE_FUNCS(Fell) + ASTGEN_MEMBERS_Fell; virtual string emitVerilog() override { return "$fell(%l)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -867,7 +868,7 @@ public: setOp1p(lhsp); setOp2p((AstNode*)rangep); } - ASTNODE_NODE_FUNCS(GatePin) + ASTGEN_MEMBERS_GatePin; virtual string emitVerilog() override { return "%l"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -884,7 +885,7 @@ public: setOp1p(lhs); setOp2p(rhs); } - ASTNODE_NODE_FUNCS(Implication) + ASTGEN_MEMBERS_Implication; virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -906,7 +907,7 @@ public: addOp2p(itemsp); dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Inside) + ASTGEN_MEMBERS_Inside; AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with // op2 = RHS, possibly a list of expr or AstInsideRange AstNode* itemsp() const { return op2p(); } @@ -921,7 +922,7 @@ public: addOp1p(lhsp); addOp2p(rhsp); } - ASTNODE_NODE_FUNCS(InsideRange) + ASTGEN_MEMBERS_InsideRange; AstNode* lhsp() const { return op1p(); } // op1 = LHS AstNode* rhsp() const { return op2p(); } // op2 = RHS virtual string emitVerilog() override { return "[%l:%r]"; } @@ -943,7 +944,7 @@ public: : ASTGEN_SUPER_LambdaArgRef(fl) , m_name{name} , m_index(index) {} - ASTNODE_NODE_FUNCS(LambdaArgRef) + ASTGEN_MEMBERS_LambdaArgRef; virtual bool same(const AstNode* /*samep*/) const override { return true; } virtual string emitVerilog() override { return name(); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -974,7 +975,7 @@ public: setOp1p(fromp); dtypep(dtp); } - ASTNODE_NODE_FUNCS(MemberSel) + ASTGEN_MEMBERS_MemberSel; void cloneRelink() override; const char* broken() const override; virtual void dump(std::ostream& str) const override; @@ -1003,7 +1004,7 @@ public: dtypeFrom(rhsp); // otherwise V3Width will resolve setNOp1p(rhsp); } - ASTNODE_NODE_FUNCS(NewCopy) + ASTGEN_MEMBERS_NewCopy; virtual string emitVerilog() override { return "new"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -1022,7 +1023,7 @@ public: setNOp1p(sizep); setNOp2p(rhsp); } - ASTNODE_NODE_FUNCS(NewDynamic) + ASTGEN_MEMBERS_NewDynamic; virtual string emitVerilog() override { return "new"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -1041,7 +1042,7 @@ public: addOp1p(exprp); addNOp2p(ticksp); } - ASTNODE_NODE_FUNCS(Past) + ASTGEN_MEMBERS_Past; virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1065,7 +1066,7 @@ public: : ASTGEN_SUPER_PatMember(fl) { addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); } - ASTNODE_NODE_FUNCS(PatMember) + ASTGEN_MEMBERS_PatMember; virtual string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1088,7 +1089,7 @@ public: : ASTGEN_SUPER_Pattern(fl) { addNOp2p(itemsp); } - ASTNODE_NODE_FUNCS(Pattern) + ASTGEN_MEMBERS_Pattern; virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1120,7 +1121,7 @@ public: , m_urandom{urandom} { setNOp1p(seedp); } - ASTNODE_NODE_FUNCS(Rand) + ASTGEN_MEMBERS_Rand; virtual string emitVerilog() override { return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)") : (m_urandom ? "%f$urandom()" : "%f$random()"); @@ -1154,7 +1155,7 @@ public: : ASTGEN_SUPER_Rose(fl) { addOp1p(exprp); } - ASTNODE_NODE_FUNCS(Rose) + ASTGEN_MEMBERS_Rose; virtual string emitVerilog() override { return "$rose(%l)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1179,7 +1180,7 @@ public: addNOp1p(exprsp); setOp2p(fromp); } - ASTNODE_NODE_FUNCS(SScanF) + ASTGEN_MEMBERS_SScanF; virtual string name() const override { return m_text; } virtual string verilogKwd() const override { return "$sscanf"; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -1208,7 +1209,7 @@ public: : ASTGEN_SUPER_Sampled(fl) { addOp1p(exprp); } - ASTNODE_NODE_FUNCS(Sampled) + ASTGEN_MEMBERS_Sampled; virtual string emitVerilog() override { return "$sampled(%l)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1234,7 +1235,7 @@ public: , m_forFormat{forFormat} { dtypeSetUInt64(); } - ASTNODE_NODE_FUNCS(ScopeName) + ASTGEN_MEMBERS_ScopeName; virtual bool same(const AstNode* samep) const override { return (m_dpiExport == static_cast(samep)->m_dpiExport && m_forFormat == static_cast(samep)->m_forFormat); @@ -1274,7 +1275,7 @@ public: setNOp2p(keyp); setOp3p(valuep); } - ASTNODE_NODE_FUNCS(SetAssoc) + ASTGEN_MEMBERS_SetAssoc; virtual string emitVerilog() override { return "'{}"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1296,7 +1297,7 @@ public: setNOp2p(keyp); setOp3p(valuep); } - ASTNODE_NODE_FUNCS(SetWildcard) + ASTGEN_MEMBERS_SetWildcard; virtual string emitVerilog() override { return "'{}"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1316,7 +1317,7 @@ public: : ASTGEN_SUPER_Stable(fl) { addOp1p(exprp); } - ASTNODE_NODE_FUNCS(Stable) + ASTGEN_MEMBERS_Stable; virtual string emitVerilog() override { return "$stable(%l)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } @@ -1334,7 +1335,7 @@ public: : ASTGEN_SUPER_SystemF(fl) { setOp1p(lhsp); } - ASTNODE_NODE_FUNCS(SystemF) + ASTGEN_MEMBERS_SystemF; virtual string verilogKwd() const override { return "$system"; } virtual string emitVerilog() override { return verilogKwd(); } virtual string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; } @@ -1355,7 +1356,7 @@ public: : ASTGEN_SUPER_TestPlusArgs(fl) { setOp1p(searchp); } - ASTNODE_NODE_FUNCS(TestPlusArgs) + ASTGEN_MEMBERS_TestPlusArgs; virtual string verilogKwd() const override { return "$test$plusargs"; } virtual string emitVerilog() override { return verilogKwd(); } virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } @@ -1374,7 +1375,7 @@ public: : ASTGEN_SUPER_UCFunc(fl) { addNOp1p(exprsp); } - ASTNODE_NODE_FUNCS(UCFunc) + ASTGEN_MEMBERS_UCFunc; virtual bool cleanOut() const override { return false; } virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -1395,7 +1396,7 @@ public: : ASTGEN_SUPER_Unbounded(fl) { dtypeSetSigned32(); } - ASTNODE_NODE_FUNCS(Unbounded) + ASTGEN_MEMBERS_Unbounded; virtual string emitVerilog() override { return "$"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -1409,7 +1410,7 @@ public: setOp1p(searchp); setOp2p(outp); } - ASTNODE_NODE_FUNCS(ValuePlusArgs) + ASTGEN_MEMBERS_ValuePlusArgs; virtual string verilogKwd() const override { return "$value$plusargs"; } virtual string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -1434,7 +1435,7 @@ public: : ASTGEN_SUPER_BufIf1(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(BufIf1) + ASTGEN_MEMBERS_BufIf1; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstBufIf1(this->fileline(), lhsp, rhsp); } @@ -1461,7 +1462,7 @@ class AstCastDynamic final : public AstNodeBiop { public: AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(CastDynamic) + ASTGEN_MEMBERS_CastDynamic; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } @@ -1490,7 +1491,7 @@ public: , m_ignoreCase{ignoreCase} { dtypeSetUInt32(); } - ASTNODE_NODE_FUNCS(CompareNN) + ASTGEN_MEMBERS_CompareNN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase); } @@ -1521,7 +1522,7 @@ public: VSigning::UNSIGNED); } } - ASTNODE_NODE_FUNCS(Concat) + ASTGEN_MEMBERS_Concat; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstConcat(this->fileline(), lhsp, rhsp); } @@ -1544,7 +1545,7 @@ public: : ASTGEN_SUPER_ConcatN(fl, lhsp, rhsp) { dtypeSetString(); } - ASTNODE_NODE_FUNCS(ConcatN) + ASTGEN_MEMBERS_ConcatN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstConcatN(this->fileline(), lhsp, rhsp); } @@ -1567,7 +1568,7 @@ public: : ASTGEN_SUPER_Div(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Div) + ASTGEN_MEMBERS_Div; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDiv(this->fileline(), lhsp, rhsp); } @@ -1589,7 +1590,7 @@ public: : ASTGEN_SUPER_DivD(fl, lhsp, rhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(DivD) + ASTGEN_MEMBERS_DivD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDivD(this->fileline(), lhsp, rhsp); } @@ -1613,7 +1614,7 @@ public: : ASTGEN_SUPER_DivS(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(DivS) + ASTGEN_MEMBERS_DivS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDivS(this->fileline(), lhsp, rhsp); } @@ -1637,7 +1638,7 @@ public: : ASTGEN_SUPER_EqWild(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(EqWild) + ASTGEN_MEMBERS_EqWild; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqWild(this->fileline(), lhsp, rhsp); } @@ -1659,7 +1660,7 @@ class AstFGetS final : public AstNodeBiop { public: AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(FGetS) + ASTGEN_MEMBERS_FGetS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstFGetS(this->fileline(), lhsp, rhsp); } @@ -1684,7 +1685,7 @@ class AstFUngetC final : public AstNodeBiop { public: AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(FUngetC) + ASTGEN_MEMBERS_FUngetC; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } @@ -1715,7 +1716,7 @@ public: : ASTGEN_SUPER_GetcN(fl, lhsp, rhsp) { dtypeSetBitSized(8, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(GetcN) + ASTGEN_MEMBERS_GetcN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGetcN(this->fileline(), lhsp, rhsp); } @@ -1740,7 +1741,7 @@ public: : ASTGEN_SUPER_GetcRefN(fl, lhsp, rhsp) { dtypeSetBitSized(8, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(GetcRefN) + ASTGEN_MEMBERS_GetcRefN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGetcRefN(this->fileline(), lhsp, rhsp); } @@ -1762,7 +1763,7 @@ public: : ASTGEN_SUPER_Gt(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Gt) + ASTGEN_MEMBERS_Gt; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGt(this->fileline(), lhsp, rhsp); } @@ -1784,7 +1785,7 @@ public: : ASTGEN_SUPER_GtD(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(GtD) + ASTGEN_MEMBERS_GtD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtD(this->fileline(), lhsp, rhsp); } @@ -1808,7 +1809,7 @@ public: : ASTGEN_SUPER_GtN(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(GtN) + ASTGEN_MEMBERS_GtN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtN(this->fileline(), lhsp, rhsp); } @@ -1832,7 +1833,7 @@ public: : ASTGEN_SUPER_GtS(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(GtS) + ASTGEN_MEMBERS_GtS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtS(this->fileline(), lhsp, rhsp); } @@ -1855,7 +1856,7 @@ public: : ASTGEN_SUPER_Gte(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Gte) + ASTGEN_MEMBERS_Gte; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGte(this->fileline(), lhsp, rhsp); } @@ -1877,7 +1878,7 @@ public: : ASTGEN_SUPER_GteD(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(GteD) + ASTGEN_MEMBERS_GteD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteD(this->fileline(), lhsp, rhsp); } @@ -1901,7 +1902,7 @@ public: : ASTGEN_SUPER_GteN(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(GteN) + ASTGEN_MEMBERS_GteN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteN(this->fileline(), lhsp, rhsp); } @@ -1925,7 +1926,7 @@ public: : ASTGEN_SUPER_GteS(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(GteS) + ASTGEN_MEMBERS_GteS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteS(this->fileline(), lhsp, rhsp); } @@ -1948,7 +1949,7 @@ public: : ASTGEN_SUPER_LogAnd(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LogAnd) + ASTGEN_MEMBERS_LogAnd; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogAnd(this->fileline(), lhsp, rhsp); } @@ -1971,7 +1972,7 @@ public: : ASTGEN_SUPER_LogIf(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LogIf) + ASTGEN_MEMBERS_LogIf; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogIf(this->fileline(), lhsp, rhsp); } @@ -1999,7 +2000,7 @@ public: : ASTGEN_SUPER_LogOr(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LogOr) + ASTGEN_MEMBERS_LogOr; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogOr(this->fileline(), lhsp, rhsp); } @@ -2030,7 +2031,7 @@ public: : ASTGEN_SUPER_Lt(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Lt) + ASTGEN_MEMBERS_Lt; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLt(this->fileline(), lhsp, rhsp); } @@ -2052,7 +2053,7 @@ public: : ASTGEN_SUPER_LtD(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LtD) + ASTGEN_MEMBERS_LtD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtD(this->fileline(), lhsp, rhsp); } @@ -2076,7 +2077,7 @@ public: : ASTGEN_SUPER_LtN(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LtN) + ASTGEN_MEMBERS_LtN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtN(this->fileline(), lhsp, rhsp); } @@ -2100,7 +2101,7 @@ public: : ASTGEN_SUPER_LtS(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LtS) + ASTGEN_MEMBERS_LtS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtS(this->fileline(), lhsp, rhsp); } @@ -2123,7 +2124,7 @@ public: : ASTGEN_SUPER_Lte(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Lte) + ASTGEN_MEMBERS_Lte; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLte(this->fileline(), lhsp, rhsp); } @@ -2145,7 +2146,7 @@ public: : ASTGEN_SUPER_LteD(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LteD) + ASTGEN_MEMBERS_LteD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteD(this->fileline(), lhsp, rhsp); } @@ -2169,7 +2170,7 @@ public: : ASTGEN_SUPER_LteN(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LteN) + ASTGEN_MEMBERS_LteN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteN(this->fileline(), lhsp, rhsp); } @@ -2193,7 +2194,7 @@ public: : ASTGEN_SUPER_LteS(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LteS) + ASTGEN_MEMBERS_LteS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteS(this->fileline(), lhsp, rhsp); } @@ -2216,7 +2217,7 @@ public: : ASTGEN_SUPER_ModDiv(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(ModDiv) + ASTGEN_MEMBERS_ModDiv; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstModDiv(this->fileline(), lhsp, rhsp); } @@ -2238,7 +2239,7 @@ public: : ASTGEN_SUPER_ModDivS(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(ModDivS) + ASTGEN_MEMBERS_ModDivS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstModDivS(this->fileline(), lhsp, rhsp); } @@ -2261,7 +2262,7 @@ public: : ASTGEN_SUPER_NeqWild(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(NeqWild) + ASTGEN_MEMBERS_NeqWild; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqWild(this->fileline(), lhsp, rhsp); } @@ -2283,7 +2284,7 @@ public: : ASTGEN_SUPER_Pow(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Pow) + ASTGEN_MEMBERS_Pow; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPow(this->fileline(), lhsp, rhsp); } @@ -2306,7 +2307,7 @@ public: : ASTGEN_SUPER_PowD(fl, lhsp, rhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(PowD) + ASTGEN_MEMBERS_PowD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowD(this->fileline(), lhsp, rhsp); } @@ -2329,7 +2330,7 @@ public: : ASTGEN_SUPER_PowSS(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(PowSS) + ASTGEN_MEMBERS_PowSS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowSS(this->fileline(), lhsp, rhsp); } @@ -2355,7 +2356,7 @@ public: : ASTGEN_SUPER_PowSU(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(PowSU) + ASTGEN_MEMBERS_PowSU; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowSU(this->fileline(), lhsp, rhsp); } @@ -2381,7 +2382,7 @@ public: : ASTGEN_SUPER_PowUS(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(PowUS) + ASTGEN_MEMBERS_PowUS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowUS(this->fileline(), lhsp, rhsp); } @@ -2415,7 +2416,7 @@ public: } AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount) : AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {} - ASTNODE_NODE_FUNCS(Replicate) + ASTGEN_MEMBERS_Replicate; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstReplicate(this->fileline(), lhsp, rhsp); } @@ -2440,7 +2441,7 @@ public: } AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount) : AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {} - ASTNODE_NODE_FUNCS(ReplicateN) + ASTGEN_MEMBERS_ReplicateN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstReplicateN(this->fileline(), lhsp, rhsp); } @@ -2463,7 +2464,7 @@ public: : ASTGEN_SUPER_ShiftL(fl, lhsp, rhsp) { if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(ShiftL) + ASTGEN_MEMBERS_ShiftL; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftL(this->fileline(), lhsp, rhsp); } @@ -2487,7 +2488,7 @@ public: : ASTGEN_SUPER_ShiftR(fl, lhsp, rhsp) { if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(ShiftR) + ASTGEN_MEMBERS_ShiftR; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftR(this->fileline(), lhsp, rhsp); } @@ -2515,7 +2516,7 @@ public: // Important that widthMin be correct, as opExtend requires it after V3Expand if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED); } - ASTNODE_NODE_FUNCS(ShiftRS) + ASTGEN_MEMBERS_ShiftRS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftRS(this->fileline(), lhsp, rhsp); } @@ -2538,7 +2539,7 @@ public: : ASTGEN_SUPER_Sub(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Sub) + ASTGEN_MEMBERS_Sub; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstSub(this->fileline(), lhsp, rhsp); } @@ -2560,7 +2561,7 @@ public: : ASTGEN_SUPER_SubD(fl, lhsp, rhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(SubD) + ASTGEN_MEMBERS_SubD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstSubD(this->fileline(), lhsp, rhsp); } @@ -2585,7 +2586,7 @@ public: : ASTGEN_SUPER_URandomRange(fl, lhsp, rhsp) { dtypeSetUInt32(); // Says IEEE } - ASTNODE_NODE_FUNCS(URandomRange) + ASTGEN_MEMBERS_URandomRange; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstURandomRange(fileline(), lhsp, rhsp); } @@ -2611,7 +2612,7 @@ public: : ASTGEN_SUPER_Eq(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Eq) + ASTGEN_MEMBERS_Eq; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEq(this->fileline(), lhsp, rhsp); } @@ -2635,7 +2636,7 @@ public: : ASTGEN_SUPER_EqCase(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(EqCase) + ASTGEN_MEMBERS_EqCase; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqCase(this->fileline(), lhsp, rhsp); } @@ -2657,7 +2658,7 @@ public: : ASTGEN_SUPER_EqD(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(EqD) + ASTGEN_MEMBERS_EqD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqD(this->fileline(), lhsp, rhsp); } @@ -2681,7 +2682,7 @@ public: : ASTGEN_SUPER_EqN(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(EqN) + ASTGEN_MEMBERS_EqN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqN(this->fileline(), lhsp, rhsp); } @@ -2705,7 +2706,7 @@ public: : ASTGEN_SUPER_LogEq(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LogEq) + ASTGEN_MEMBERS_LogEq; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogEq(this->fileline(), lhsp, rhsp); } @@ -2728,7 +2729,7 @@ public: : ASTGEN_SUPER_Neq(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(Neq) + ASTGEN_MEMBERS_Neq; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeq(this->fileline(), lhsp, rhsp); } @@ -2750,7 +2751,7 @@ public: : ASTGEN_SUPER_NeqCase(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(NeqCase) + ASTGEN_MEMBERS_NeqCase; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqCase(this->fileline(), lhsp, rhsp); } @@ -2772,7 +2773,7 @@ public: : ASTGEN_SUPER_NeqD(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(NeqD) + ASTGEN_MEMBERS_NeqD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqD(this->fileline(), lhsp, rhsp); } @@ -2796,7 +2797,7 @@ public: : ASTGEN_SUPER_NeqN(fl, lhsp, rhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(NeqN) + ASTGEN_MEMBERS_NeqN; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqN(this->fileline(), lhsp, rhsp); } @@ -2822,7 +2823,7 @@ public: : ASTGEN_SUPER_Add(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Add) + ASTGEN_MEMBERS_Add; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAdd(this->fileline(), lhsp, rhsp); } @@ -2844,7 +2845,7 @@ public: : ASTGEN_SUPER_AddD(fl, lhsp, rhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(AddD) + ASTGEN_MEMBERS_AddD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAddD(this->fileline(), lhsp, rhsp); } @@ -2868,7 +2869,7 @@ public: : ASTGEN_SUPER_And(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(And) + ASTGEN_MEMBERS_And; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAnd(this->fileline(), lhsp, rhsp); } @@ -2890,7 +2891,7 @@ public: : ASTGEN_SUPER_Mul(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Mul) + ASTGEN_MEMBERS_Mul; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMul(this->fileline(), lhsp, rhsp); } @@ -2913,7 +2914,7 @@ public: : ASTGEN_SUPER_MulD(fl, lhsp, rhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(MulD) + ASTGEN_MEMBERS_MulD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMulD(this->fileline(), lhsp, rhsp); } @@ -2937,7 +2938,7 @@ public: : ASTGEN_SUPER_MulS(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(MulS) + ASTGEN_MEMBERS_MulS; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMulS(this->fileline(), lhsp, rhsp); } @@ -2962,7 +2963,7 @@ public: : ASTGEN_SUPER_Or(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Or) + ASTGEN_MEMBERS_Or; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstOr(this->fileline(), lhsp, rhsp); } @@ -2984,7 +2985,7 @@ public: : ASTGEN_SUPER_Xor(fl, lhsp, rhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Xor) + ASTGEN_MEMBERS_Xor; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstXor(this->fileline(), lhsp, rhsp); } @@ -3022,7 +3023,7 @@ public: : ASTGEN_SUPER_ArraySel(fl, fromp, new AstConst(fl, bit)) { init(fromp); } - ASTNODE_NODE_FUNCS(ArraySel) + ASTGEN_MEMBERS_ArraySel; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstArraySel(this->fileline(), lhsp, rhsp); } @@ -3062,7 +3063,7 @@ public: : ASTGEN_SUPER_AssocSel(fl, fromp, bitp) { init(fromp); } - ASTNODE_NODE_FUNCS(AssocSel) + ASTGEN_MEMBERS_AssocSel; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssocSel(this->fileline(), lhsp, rhsp); } @@ -3099,7 +3100,7 @@ public: : ASTGEN_SUPER_WildcardSel(fl, fromp, bitp) { init(fromp); } - ASTNODE_NODE_FUNCS(WildcardSel) + ASTGEN_MEMBERS_WildcardSel; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstWildcardSel{this->fileline(), lhsp, rhsp}; } @@ -3127,7 +3128,7 @@ public: : ASTGEN_SUPER_WordSel(fl, fromp, bitp) { dtypeSetUInt32(); // Always used on WData arrays so returns edata size } - ASTNODE_NODE_FUNCS(WordSel) + ASTGEN_MEMBERS_WordSel; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstWordSel(this->fileline(), lhsp, rhsp); } @@ -3152,7 +3153,7 @@ class AstStreamL final : public AstNodeStream { public: AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(StreamL) + ASTGEN_MEMBERS_StreamL; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstStreamL(this->fileline(), lhsp, rhsp); } @@ -3173,7 +3174,7 @@ class AstStreamR final : public AstNodeStream { public: AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(StreamR) + ASTGEN_MEMBERS_StreamR; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstStreamR(this->fileline(), lhsp, rhsp); } @@ -3195,7 +3196,7 @@ class AstAtan2D final : public AstNodeSystemBiop { public: AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(Atan2D) + ASTGEN_MEMBERS_Atan2D; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAtan2D(this->fileline(), lhsp, rhsp); } @@ -3209,7 +3210,7 @@ class AstHypotD final : public AstNodeSystemBiop { public: AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(HypotD) + ASTGEN_MEMBERS_HypotD; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstHypotD(this->fileline(), lhsp, rhsp); } @@ -3231,7 +3232,7 @@ public: : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTree(false)) {} AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p, AstNode* ctrl3p) : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {} - ASTNODE_NODE_FUNCS(CountBits) + ASTGEN_MEMBERS_CountBits; virtual void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1, const V3Number& ctrl2, const V3Number& ctrl3) override { out.opCountBits(expr, ctrl1, ctrl2, ctrl3); @@ -3259,7 +3260,7 @@ public: , m_timeunit{timeunit} { dtypeSetUInt64(); } - ASTNODE_NODE_FUNCS(Time) + ASTGEN_MEMBERS_Time; virtual string emitVerilog() override { return "%f$time"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -3279,7 +3280,7 @@ public: , m_timeunit{timeunit} { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(TimeD) + ASTGEN_MEMBERS_TimeD; virtual string emitVerilog() override { return "%f$realtime"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const override { return true; } @@ -3302,7 +3303,7 @@ class AstPostAdd final : public AstNodeTriop { public: AstPostAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PostAdd) + ASTGEN_MEMBERS_PostAdd; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs @@ -3327,7 +3328,7 @@ class AstPostSub final : public AstNodeTriop { public: AstPostSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PostSub) + ASTGEN_MEMBERS_PostSub; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs @@ -3352,7 +3353,7 @@ class AstPreAdd final : public AstNodeTriop { public: AstPreAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PreAdd) + ASTGEN_MEMBERS_PreAdd; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs @@ -3377,7 +3378,7 @@ class AstPreSub final : public AstNodeTriop { public: AstPreSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {} - ASTNODE_NODE_FUNCS(PreSub) + ASTGEN_MEMBERS_PreSub; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs @@ -3400,7 +3401,7 @@ public: : ASTGEN_SUPER_PutcN(fl, lhsp, rhsp, ths) { dtypeSetString(); } - ASTNODE_NODE_FUNCS(PutcN) + ASTGEN_MEMBERS_PutcN; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { out.opPutcN(lhs, rhs, ths); @@ -3439,7 +3440,7 @@ public: , m_declElWidth{1} { dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(Sel) + ASTGEN_MEMBERS_Sel; virtual void dump(std::ostream& str) const override; virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, const V3Number& width) override { @@ -3487,7 +3488,7 @@ public: : ASTGEN_SUPER_SliceSel(fl, fromp, new AstConst(fl, declRange.lo()), new AstConst(fl, declRange.elements())) , m_declRange{declRange} {} - ASTNODE_NODE_FUNCS(SliceSel) + ASTGEN_MEMBERS_SliceSel; virtual void dump(std::ostream& str) const override; virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, const V3Number& width) override { @@ -3519,7 +3520,7 @@ public: : ASTGEN_SUPER_SubstrN(fl, lhsp, rhsp, ths) { dtypeSetString(); } - ASTNODE_NODE_FUNCS(SubstrN) + ASTGEN_MEMBERS_SubstrN; virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override { out.opSubstrN(lhs, rhs, ths); @@ -3545,7 +3546,7 @@ class AstCond final : public AstNodeCond { public: AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : ASTGEN_SUPER_Cond(fl, condp, expr1p, expr2p) {} - ASTNODE_NODE_FUNCS(Cond) + ASTGEN_MEMBERS_Cond; virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { return new AstCond(this->fileline(), condp, expr1p, expr2p); } @@ -3557,7 +3558,7 @@ class AstCondBound final : public AstNodeCond { public: AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : ASTGEN_SUPER_CondBound(fl, condp, expr1p, expr2p) {} - ASTNODE_NODE_FUNCS(CondBound) + ASTGEN_MEMBERS_CondBound; virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { return new AstCondBound(this->fileline(), condp, expr1p, expr2p); } @@ -3577,7 +3578,7 @@ public: , m_fmt{fmt} { fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32(); } - ASTNODE_NODE_FUNCS(AtoN) + ASTGEN_MEMBERS_AtoN; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAtoN(lhs, m_fmt); } @@ -3613,7 +3614,7 @@ public: : ASTGEN_SUPER_BitsToRealD(fl, lhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(BitsToRealD) + ASTGEN_MEMBERS_BitsToRealD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opBitsToRealD(lhs); } @@ -3643,7 +3644,7 @@ public: dtypeFrom(typeFromp); m_size = width(); } - ASTNODE_NODE_FUNCS(CCast) + ASTGEN_MEMBERS_CCast; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } virtual string emitVerilog() override { return "%f$_CAST(%l)"; } virtual string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } @@ -3663,7 +3664,7 @@ public: : ASTGEN_SUPER_CLog2(fl, lhsp) { dtypeSetSigned32(); } - ASTNODE_NODE_FUNCS(CLog2) + ASTGEN_MEMBERS_CLog2; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); } virtual string emitVerilog() override { return "%f$clog2(%l)"; } virtual string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; } @@ -3677,7 +3678,7 @@ class AstCountOnes final : public AstNodeUniop { public: AstCountOnes(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CountOnes(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CountOnes) + ASTGEN_MEMBERS_CountOnes; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCountOnes(lhs); } @@ -3695,7 +3696,7 @@ public: : ASTGEN_SUPER_CvtPackString(fl, lhsp) { dtypeSetString(); } - ASTNODE_NODE_FUNCS(CvtPackString) + ASTGEN_MEMBERS_CvtPackString; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } virtual string emitVerilog() override { return "%f$_CAST(%l)"; } virtual string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } @@ -3713,7 +3714,7 @@ public: : ASTGEN_SUPER_Extend(fl, lhsp) { dtypeSetLogicSized(width, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(Extend) + ASTGEN_MEMBERS_Extend; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } virtual string emitVerilog() override { return "%l"; } virtual string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } @@ -3734,7 +3735,7 @@ public: : ASTGEN_SUPER_ExtendS(fl, lhsp) { dtypeSetLogicSized(width, VSigning::UNSIGNED); } - ASTNODE_NODE_FUNCS(ExtendS) + ASTGEN_MEMBERS_ExtendS; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opExtendS(lhs, lhsp()->widthMinV()); } @@ -3752,7 +3753,7 @@ class AstFEof final : public AstNodeUniop { public: AstFEof(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_FEof(fl, lhsp) {} - ASTNODE_NODE_FUNCS(FEof) + ASTGEN_MEMBERS_FEof; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } virtual string emitVerilog() override { return "%f$feof(%l)"; } virtual string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } @@ -3769,7 +3770,7 @@ class AstFGetC final : public AstNodeUniop { public: AstFGetC(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_FGetC(fl, lhsp) {} - ASTNODE_NODE_FUNCS(FGetC) + ASTGEN_MEMBERS_FGetC; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } virtual string emitVerilog() override { return "%f$fgetc(%l)"; } // Non-existent filehandle returns EOF @@ -3790,7 +3791,7 @@ public: : ASTGEN_SUPER_ISToRD(fl, lhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(ISToRD) + ASTGEN_MEMBERS_ISToRD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); } virtual string emitVerilog() override { return "%f$itor($signed(%l))"; } virtual string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; } @@ -3807,7 +3808,7 @@ public: : ASTGEN_SUPER_IToRD(fl, lhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(IToRD) + ASTGEN_MEMBERS_IToRD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); } virtual string emitVerilog() override { return "%f$itor(%l)"; } virtual string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; } @@ -3823,7 +3824,7 @@ public: : ASTGEN_SUPER_IsUnbounded(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(IsUnbounded) + ASTGEN_MEMBERS_IsUnbounded; virtual void numberOperate(V3Number& out, const V3Number&) override { // Any constant isn't unbounded out.setZero(); @@ -3841,7 +3842,7 @@ public: : ASTGEN_SUPER_IsUnknown(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(IsUnknown) + ASTGEN_MEMBERS_IsUnknown; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIsUnknown(lhs); } @@ -3858,7 +3859,7 @@ public: : ASTGEN_SUPER_LenN(fl, lhsp) { dtypeSetSigned32(); } - ASTNODE_NODE_FUNCS(LenN) + ASTGEN_MEMBERS_LenN; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); } virtual string emitVerilog() override { return "%f(%l)"; } virtual string emitC() override { return "VL_LEN_IN(%li)"; } @@ -3872,7 +3873,7 @@ public: : ASTGEN_SUPER_LogNot(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(LogNot) + ASTGEN_MEMBERS_LogNot; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } virtual string emitVerilog() override { return "%f(! %l)"; } virtual string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } @@ -3887,7 +3888,7 @@ public: : ASTGEN_SUPER_Negate(fl, lhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Negate) + ASTGEN_MEMBERS_Negate; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); } virtual string emitVerilog() override { return "%f(- %l)"; } virtual string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; } @@ -3902,7 +3903,7 @@ public: : ASTGEN_SUPER_NegateD(fl, lhsp) { dtypeSetDouble(); } - ASTNODE_NODE_FUNCS(NegateD) + ASTGEN_MEMBERS_NegateD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); } virtual string emitVerilog() override { return "%f(- %l)"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -3919,7 +3920,7 @@ public: : ASTGEN_SUPER_Not(fl, lhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Not) + ASTGEN_MEMBERS_Not; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); } virtual string emitVerilog() override { return "%f(~ %l)"; } virtual string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; } @@ -3936,7 +3937,7 @@ public: : ASTGEN_SUPER_NullCheck(fl, lhsp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(NullCheck) + ASTGEN_MEMBERS_NullCheck; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } virtual int instrCount() const override { return 1; } // Rarely executes virtual string emitVerilog() override { return "%l"; } @@ -3956,7 +3957,7 @@ public: : ASTGEN_SUPER_OneHot(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(OneHot) + ASTGEN_MEMBERS_OneHot; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } virtual string emitVerilog() override { return "%f$onehot(%l)"; } virtual string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } @@ -3972,7 +3973,7 @@ public: : ASTGEN_SUPER_OneHot0(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(OneHot0) + ASTGEN_MEMBERS_OneHot0; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } virtual string emitVerilog() override { return "%f$onehot0(%l)"; } virtual string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } @@ -3988,7 +3989,7 @@ public: : ASTGEN_SUPER_RToIRoundS(fl, lhsp) { dtypeSetSigned32(); } - ASTNODE_NODE_FUNCS(RToIRoundS) + ASTGEN_MEMBERS_RToIRoundS; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIRoundS(lhs); } @@ -4008,7 +4009,7 @@ public: : ASTGEN_SUPER_RToIS(fl, lhsp) { dtypeSetSigned32(); } - ASTNODE_NODE_FUNCS(RToIS) + ASTGEN_MEMBERS_RToIS; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); } virtual string emitVerilog() override { return "%f$rtoi(%l)"; } virtual string emitC() override { return "VL_RTOI_I_D(%li)"; } @@ -4023,7 +4024,7 @@ public: : ASTGEN_SUPER_RealToBits(fl, lhsp) { dtypeSetUInt64(); } - ASTNODE_NODE_FUNCS(RealToBits) + ASTGEN_MEMBERS_RealToBits; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRealToBits(lhs); } @@ -4040,7 +4041,7 @@ public: : ASTGEN_SUPER_RedAnd(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(RedAnd) + ASTGEN_MEMBERS_RedAnd; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } virtual string emitVerilog() override { return "%f(& %l)"; } virtual string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; } @@ -4054,7 +4055,7 @@ public: : ASTGEN_SUPER_RedOr(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(RedOr) + ASTGEN_MEMBERS_RedOr; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } virtual string emitVerilog() override { return "%f(| %l)"; } virtual string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; } @@ -4068,7 +4069,7 @@ public: : ASTGEN_SUPER_RedXor(fl, lhsp) { dtypeSetBit(); } - ASTNODE_NODE_FUNCS(RedXor) + ASTGEN_MEMBERS_RedXor; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } virtual string emitVerilog() override { return "%f(^ %l)"; } virtual string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; } @@ -4088,7 +4089,7 @@ public: UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, "not coded to create after dtypes resolved"); } - ASTNODE_NODE_FUNCS(Signed) + ASTGEN_MEMBERS_Signed; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); out.isSigned(false); @@ -4106,7 +4107,7 @@ class AstTimeImport final : public AstNodeUniop { public: AstTimeImport(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_TimeImport(fl, lhsp) {} - ASTNODE_NODE_FUNCS(TimeImport) + ASTGEN_MEMBERS_TimeImport; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } virtual string emitVerilog() override { return "%l"; } virtual string emitC() override { V3ERROR_NA_RETURN(""); } @@ -4124,7 +4125,7 @@ public: : ASTGEN_SUPER_ToLowerN(fl, lhsp) { dtypeSetString(); } - ASTNODE_NODE_FUNCS(ToLowerN) + ASTGEN_MEMBERS_ToLowerN; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToLowerN(lhs); } @@ -4141,7 +4142,7 @@ public: : ASTGEN_SUPER_ToUpperN(fl, lhsp) { dtypeSetString(); } - ASTNODE_NODE_FUNCS(ToUpperN) + ASTGEN_MEMBERS_ToUpperN; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToUpperN(lhs); } @@ -4159,7 +4160,7 @@ public: UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, "not coded to create after dtypes resolved"); } - ASTNODE_NODE_FUNCS(Unsigned) + ASTGEN_MEMBERS_Unsigned; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); out.isSigned(false); @@ -4177,7 +4178,7 @@ class AstAcosD final : public AstNodeSystemUniop { public: AstAcosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AcosD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AcosD) + ASTGEN_MEMBERS_AcosD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::acos(lhs.toDouble())); } @@ -4188,7 +4189,7 @@ class AstAcoshD final : public AstNodeSystemUniop { public: AstAcoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AcoshD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AcoshD) + ASTGEN_MEMBERS_AcoshD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::acosh(lhs.toDouble())); } @@ -4199,7 +4200,7 @@ class AstAsinD final : public AstNodeSystemUniop { public: AstAsinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AsinD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AsinD) + ASTGEN_MEMBERS_AsinD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::asin(lhs.toDouble())); } @@ -4210,7 +4211,7 @@ class AstAsinhD final : public AstNodeSystemUniop { public: AstAsinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AsinhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AsinhD) + ASTGEN_MEMBERS_AsinhD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::asinh(lhs.toDouble())); } @@ -4221,7 +4222,7 @@ class AstAtanD final : public AstNodeSystemUniop { public: AstAtanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AtanD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AtanD) + ASTGEN_MEMBERS_AtanD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::atan(lhs.toDouble())); } @@ -4232,7 +4233,7 @@ class AstAtanhD final : public AstNodeSystemUniop { public: AstAtanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AtanhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(AtanhD) + ASTGEN_MEMBERS_AtanhD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::atanh(lhs.toDouble())); } @@ -4243,7 +4244,7 @@ class AstCeilD final : public AstNodeSystemUniop { public: AstCeilD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CeilD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CeilD) + ASTGEN_MEMBERS_CeilD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::ceil(lhs.toDouble())); } @@ -4254,7 +4255,7 @@ class AstCosD final : public AstNodeSystemUniop { public: AstCosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CosD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CosD) + ASTGEN_MEMBERS_CosD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::cos(lhs.toDouble())); } @@ -4265,7 +4266,7 @@ class AstCoshD final : public AstNodeSystemUniop { public: AstCoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CoshD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(CoshD) + ASTGEN_MEMBERS_CoshD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::cosh(lhs.toDouble())); } @@ -4276,7 +4277,7 @@ class AstExpD final : public AstNodeSystemUniop { public: AstExpD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_ExpD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(ExpD) + ASTGEN_MEMBERS_ExpD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::exp(lhs.toDouble())); } @@ -4287,7 +4288,7 @@ class AstFloorD final : public AstNodeSystemUniop { public: AstFloorD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_FloorD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(FloorD) + ASTGEN_MEMBERS_FloorD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::floor(lhs.toDouble())); } @@ -4298,7 +4299,7 @@ class AstLog10D final : public AstNodeSystemUniop { public: AstLog10D(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_Log10D(fl, lhsp) {} - ASTNODE_NODE_FUNCS(Log10D) + ASTGEN_MEMBERS_Log10D; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::log10(lhs.toDouble())); } @@ -4309,7 +4310,7 @@ class AstLogD final : public AstNodeSystemUniop { public: AstLogD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_LogD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(LogD) + ASTGEN_MEMBERS_LogD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::log(lhs.toDouble())); } @@ -4320,7 +4321,7 @@ class AstSinD final : public AstNodeSystemUniop { public: AstSinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SinD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(SinD) + ASTGEN_MEMBERS_SinD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::sin(lhs.toDouble())); } @@ -4331,7 +4332,7 @@ class AstSinhD final : public AstNodeSystemUniop { public: AstSinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SinhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(SinhD) + ASTGEN_MEMBERS_SinhD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::sinh(lhs.toDouble())); } @@ -4342,7 +4343,7 @@ class AstSqrtD final : public AstNodeSystemUniop { public: AstSqrtD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SqrtD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(SqrtD) + ASTGEN_MEMBERS_SqrtD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::sqrt(lhs.toDouble())); } @@ -4353,7 +4354,7 @@ class AstTanD final : public AstNodeSystemUniop { public: AstTanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_TanD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(TanD) + ASTGEN_MEMBERS_TanD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::tan(lhs.toDouble())); } @@ -4364,7 +4365,7 @@ class AstTanhD final : public AstNodeSystemUniop { public: AstTanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_TanhD(fl, lhsp) {} - ASTNODE_NODE_FUNCS(TanhD) + ASTGEN_MEMBERS_TanhD; virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::tanh(lhs.toDouble())); } @@ -4383,7 +4384,7 @@ public: inline AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access); // This form only allowed post-link (see above) inline AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access); - ASTNODE_NODE_FUNCS(VarRef) + ASTGEN_MEMBERS_VarRef; virtual void dump(std::ostream& str) const override; bool same(const AstNode* samep) const override; inline bool same(const AstVarRef* samep) const; @@ -4406,7 +4407,7 @@ public: : ASTGEN_SUPER_VarXRef(fl, name, nullptr, access) , m_dotted{dotted} {} inline AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access); - ASTNODE_NODE_FUNCS(VarXRef) + ASTGEN_MEMBERS_VarXRef; virtual void dump(std::ostream& str) const override; string dotted() const { return m_dotted; } void dotted(const string& dotted) { m_dotted = dotted; } diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index aa35e36a2..da62b28d3 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -46,7 +46,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeBlock) + ASTGEN_MEMBERS_NodeBlock; virtual void dump(std::ostream& str) const override; virtual string name() const override { return m_name; } // * = Block name virtual void name(const string& name) override { m_name = name; } @@ -111,7 +111,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeFTask) + ASTGEN_MEMBERS_NodeFTask; virtual void dump(std::ostream& str = std::cout) const override; virtual string name() const override { return m_name; } // * = Var name virtual bool maybePointedTo() const override { return true; } @@ -193,7 +193,7 @@ public: AstNodeFile(VNType t, FileLine* fl, const string& name) : AstNode{t, fl} , m_name{name} {} - ASTNODE_BASE_FUNCS(NodeFile) + ASTGEN_MEMBERS_NodeFile; virtual void dump(std::ostream& str) const override; virtual string name() const override { return m_name; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -236,7 +236,7 @@ protected: , m_recursiveClone{false} {} public: - ASTNODE_BASE_FUNCS(NodeModule) + ASTGEN_MEMBERS_NodeModule; virtual void dump(std::ostream& str) const override; virtual bool maybePointedTo() const override { return true; } virtual string name() const override { return m_name; } @@ -289,7 +289,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodePreSel) + ASTGEN_MEMBERS_NodePreSel; AstNode* fromp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } AstNode* thsp() const { return op3p(); } @@ -310,7 +310,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeProcedure) + ASTGEN_MEMBERS_NodeProcedure; // METHODS virtual void dump(std::ostream& str) const override; AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate @@ -324,7 +324,7 @@ protected: : AstNode{t, fl} {} public: - ASTNODE_BASE_FUNCS(NodeRange) + ASTGEN_MEMBERS_NodeRange; virtual void dump(std::ostream& str) const override; }; class AstNodeStmt VL_NOT_FINAL : public AstNode { @@ -336,7 +336,7 @@ protected: , m_statement{statement} {} public: - ASTNODE_BASE_FUNCS(NodeStmt) + ASTGEN_MEMBERS_NodeStmt; // METHODS bool isStatement() const { return m_statement; } // Really a statement void statement(bool flag) { m_statement = flag; } @@ -358,7 +358,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeAssign) + ASTGEN_MEMBERS_NodeAssign; // Clone single node, just get same type back. virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 @@ -390,7 +390,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeCCall) + ASTGEN_MEMBERS_NodeCCall; virtual void dump(std::ostream& str = std::cout) const override; virtual void cloneRelink() override; virtual const char* broken() const override; @@ -421,7 +421,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeCase) + ASTGEN_MEMBERS_NodeCase; virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } AstNode* exprp() const { return op1p(); } // op1 = case condition AstCaseItem* itemsp() const { @@ -447,7 +447,7 @@ public: addOp1p(propp); addNOp4p(passsp); } - ASTNODE_BASE_FUNCS(NodeCoverOrAssert) + ASTGEN_MEMBERS_NodeCoverOrAssert; virtual string name() const override { return m_name; } // * = Var name virtual bool same(const AstNode* samep) const override { return samep->name() == name(); } virtual void name(const string& name) override { m_name = name; } @@ -481,7 +481,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeFTaskRef) + ASTGEN_MEMBERS_NodeFTaskRef; virtual const char* broken() const override; virtual void cloneRelink() override; virtual void dump(std::ostream& str = std::cout) const override; @@ -522,7 +522,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeFor) + ASTGEN_MEMBERS_NodeFor; AstNode* initsp() const { return op1p(); } // op1 = initial statements AstNode* condp() const { return op2p(); } // op2 = condition to continue AstNode* incsp() const { return op3p(); } // op3 = increment statements @@ -545,7 +545,7 @@ protected: } public: - ASTNODE_BASE_FUNCS(NodeIf) + ASTGEN_MEMBERS_NodeIf; AstNode* condp() const { return op1p(); } // op1 = condition AstNode* ifsp() const { return op2p(); } // op2 = list of true statements AstNode* elsesp() const { return op3p(); } // op3 = list of false statements @@ -577,6 +577,7 @@ public: setNOp3p(lsbp); setNOp4p(msbp); } + ASTGEN_MEMBERS_NodeReadWriteMem; virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } virtual bool isPure() const override { return false; } @@ -603,7 +604,7 @@ protected: , m_text{text} {} public: - ASTNODE_BASE_FUNCS(NodeText) + ASTGEN_MEMBERS_NodeText; virtual void dump(std::ostream& str = std::cout) const override; virtual bool same(const AstNode* samep) const override { const AstNodeText* asamep = static_cast(samep); @@ -618,7 +619,7 @@ public: AstNodeSimpleText(VNType t, FileLine* fl, const string& textp, bool tracking = false) : AstNodeText(t, fl, textp) , m_tracking(tracking) {} - ASTNODE_BASE_FUNCS(NodeSimpleText) + ASTGEN_MEMBERS_NodeSimpleText; void tracking(bool flag) { m_tracking = flag; } bool tracking() const { return m_tracking; } }; @@ -641,7 +642,7 @@ public: , m_sensesp{sensesp} { UASSERT(sensesp, "Sensesp required arg"); } - ASTNODE_NODE_FUNCS(Active) + ASTGEN_MEMBERS_Active; virtual void dump(std::ostream& str = std::cout) const override; virtual string name() const override { return m_name; } const char* broken() const override; @@ -670,7 +671,7 @@ public: , m_name{name} { setNOp1p(exprp); } - ASTNODE_NODE_FUNCS(Arg) + ASTGEN_MEMBERS_Arg; virtual string name() const override { return m_name; } // * = Pin name, ""=go by number virtual void name(const string& name) override { m_name = name; } void exprp(AstNode* nodep) { addOp1p(nodep); } @@ -689,7 +690,7 @@ public: setNOp2p(dimp); m_attrType = attrtype; } - ASTNODE_NODE_FUNCS(AttrOf) + ASTGEN_MEMBERS_AttrOf; AstNode* fromp() const { return op1p(); } AstNode* dimp() const { return op2p(); } VAttrType attrType() const { return m_attrType; } @@ -707,7 +708,7 @@ public: UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound"); addNOp1p(cellsp); } - ASTNODE_NODE_FUNCS(Bind) + ASTGEN_MEMBERS_Bind; // ACCESSORS virtual string name() const override { return m_name; } // * = Bind Target name virtual void name(const string& name) override { m_name = name; } @@ -777,7 +778,7 @@ public: m_dpiImportWrapper = false; m_dpiTraceInit = false; } - ASTNODE_NODE_FUNCS(CFunc) + ASTGEN_MEMBERS_CFunc; virtual string name() const override { return m_name; } const char* broken() const override; void cloneRelink() override; @@ -881,7 +882,7 @@ public: : ASTGEN_SUPER_CUse(fl) , m_useType{useType} , m_name{name} {} - ASTNODE_NODE_FUNCS(CUse) + ASTGEN_MEMBERS_CUse; virtual void dump(std::ostream& str = std::cout) const override; virtual string name() const override { return m_name; } VUseType useType() const { return m_useType; } @@ -897,7 +898,7 @@ public: addNOp1p(condsp); addNOp2p(bodysp); } - ASTNODE_NODE_FUNCS(CaseItem) + ASTGEN_MEMBERS_CaseItem; virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions AstNode* bodysp() const { return op2p(); } // op2 = what to do @@ -920,7 +921,7 @@ public: setOp1p(lhsp); dtypeFrom(dtp); } - ASTNODE_NODE_FUNCS(Cast) + ASTGEN_MEMBERS_Cast; virtual bool hasDType() const override { return true; } virtual string emitVerilog() { return "((%d)'(%l))"; } virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } @@ -941,7 +942,7 @@ public: setOp1p(lhsp); setOp2p(dtp); } - ASTNODE_NODE_FUNCS(CastParse) + ASTGEN_MEMBERS_CastParse; virtual string emitVerilog() { return "((%d)'(%l))"; } virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } @@ -958,7 +959,7 @@ public: setOp1p(lhsp); setOp2p((AstNode*)rhsp); } - ASTNODE_NODE_FUNCS(CastSize) + ASTGEN_MEMBERS_CastSize; // No hasDType because widthing removes this node before the hasDType check virtual string emitVerilog() { return "((%r)'(%l))"; } virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } @@ -993,7 +994,7 @@ public: addNOp2p((AstNode*)paramsp); setNOp3p((AstNode*)rangep); } - ASTNODE_NODE_FUNCS(Cell) + ASTGEN_MEMBERS_Cell; // No cloneRelink, we presume cloneee's want the same module linkages virtual void dump(std::ostream& str) const override; const char* broken() const override; @@ -1035,7 +1036,7 @@ public: , m_name{name} { addNOp1p(selectExprp); } - ASTNODE_NODE_FUNCS(CellArrayRef) + ASTGEN_MEMBERS_CellArrayRef; // ACCESSORS virtual string name() const override { return m_name; } // * = Array name AstNode* selp() const { return op1p(); } // op1 = Select expression @@ -1059,7 +1060,7 @@ public: , m_name{name} , m_origModName{origModName} , m_timeunit{timeunit} {} - ASTNODE_NODE_FUNCS(CellInline) + ASTGEN_MEMBERS_CellInline; virtual void dump(std::ostream& str) const override; const char* broken() const override; // ACCESSORS @@ -1082,7 +1083,7 @@ public: addNOp1p(cellp); addNOp2p(exprp); } - ASTNODE_NODE_FUNCS(CellRef) + ASTGEN_MEMBERS_CellRef; // ACCESSORS virtual string name() const override { return m_name; } // * = Array name AstNode* cellp() const { return op1p(); } // op1 = Cell @@ -1096,7 +1097,7 @@ public: : ASTGEN_SUPER_ClassExtends(fl) { setNOp2p(classOrPkgsp); // Only for parser } - ASTNODE_NODE_FUNCS(ClassExtends) + ASTGEN_MEMBERS_ClassExtends; virtual bool hasDType() const override { return true; } virtual string verilogKwd() const override { return "extends"; } AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } @@ -1117,7 +1118,7 @@ public: , m_classOrPackageNodep{classOrPackageNodep} { addNOp4p(paramsp); } - ASTNODE_NODE_FUNCS(ClassOrPackageRef) + ASTGEN_MEMBERS_ClassOrPackageRef; // METHODS virtual const char* broken() const override { BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists()); @@ -1151,7 +1152,7 @@ public: addOp1p((AstNode*)sensesp); addNOp2p(bodysp); } - ASTNODE_NODE_FUNCS(Clocking) + ASTGEN_MEMBERS_Clocking; // op1 = Sensitivity list AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } AstNode* bodysp() const { return op2p(); } // op2 = Body @@ -1167,7 +1168,7 @@ class AstConstPool final : public AstNode { public: explicit AstConstPool(FileLine* fl); - ASTNODE_NODE_FUNCS(ConstPool) + ASTGEN_MEMBERS_ConstPool; virtual bool maybePointedTo() const override { return true; } const char* broken() const override; virtual void cloneRelink() override { V3ERROR_NA; } @@ -1201,7 +1202,7 @@ public: setOp1p(rhsp); } virtual string name() const override { return m_name; } // * = Scope name - ASTNODE_NODE_FUNCS(DefParam) + ASTGEN_MEMBERS_DefParam; virtual bool same(const AstNode*) const override { return true; } AstNode* rhsp() const { return op1p(); } // op1 = Assign from string path() const { return m_path; } @@ -1217,7 +1218,7 @@ public: setOp1p(lhsp); setOp2p(rhsp); } - ASTNODE_NODE_FUNCS(Dot) + ASTGEN_MEMBERS_Dot; // For parser, make only if non-null package static AstNode* newIfPkg(FileLine* fl, AstNode* packageOrClassp, AstNode* rhsp) { if (!packageOrClassp) return rhsp; @@ -1241,7 +1242,7 @@ public: : ASTGEN_SUPER_DpiExport(fl) , m_name{vname} , m_cname{cname} {} - ASTNODE_NODE_FUNCS(DpiExport) + ASTGEN_MEMBERS_DpiExport; virtual string name() const override { return m_name; } virtual void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } @@ -1255,7 +1256,7 @@ private: public: inline AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp); - ASTNODE_NODE_FUNCS(ElabDisplay) + ASTGEN_MEMBERS_ElabDisplay; virtual const char* broken() const override { BROKEN_RTN(!fmtp()); return nullptr; @@ -1284,7 +1285,7 @@ class AstEmpty final : public AstNode { public: explicit AstEmpty(FileLine* fl) : ASTGEN_SUPER_Empty(fl) {} - ASTNODE_NODE_FUNCS(Empty) + ASTGEN_MEMBERS_Empty; virtual bool same(const AstNode* /*samep*/) const override { return true; } }; class AstExecGraph final : public AstNode { @@ -1300,8 +1301,8 @@ private: public: explicit AstExecGraph(FileLine* fl, const string& name); - ASTNODE_NODE_FUNCS_NO_DTOR(ExecGraph) - virtual ~AstExecGraph() override; + ASTGEN_MEMBERS_ExecGraph; + ~AstExecGraph() override; virtual const char* broken() const override { BROKEN_RTN(!m_depGraphp); return nullptr; @@ -1323,7 +1324,7 @@ public: : ASTGEN_SUPER_Implicit(fl) { addNOp1p(exprsp); } - ASTNODE_NODE_FUNCS(Implicit) + ASTGEN_MEMBERS_Implicit; AstNode* exprsp() const { return op1p(); } // op1 = Assign from }; class AstInitArray final : public AstNode { @@ -1344,7 +1345,7 @@ public: dtypep(newDTypep); addNOp1p(defaultp); } - ASTNODE_NODE_FUNCS(InitArray) + ASTGEN_MEMBERS_InitArray; virtual void dump(std::ostream& str) const override; const char* broken() const override; void cloneRelink() override; @@ -1373,7 +1374,7 @@ public: : ASTGEN_SUPER_InitItem(fl) { addOp1p(valuep); } - ASTNODE_NODE_FUNCS(InitItem) + ASTGEN_MEMBERS_InitItem; virtual bool maybePointedTo() const override { return true; } virtual bool hasDType() const override { return false; } // See valuep()'s dtype instead AstNode* valuep() const { return op1p(); } // op1 = Value @@ -1388,7 +1389,7 @@ public: : ASTGEN_SUPER_IntfRef(fl) , m_name{name} {} virtual string name() const override { return m_name; } - ASTNODE_NODE_FUNCS(IntfRef) + ASTGEN_MEMBERS_IntfRef; }; class AstMTaskBody final : public AstNode { // Hold statements for each MTask @@ -1398,7 +1399,7 @@ private: public: explicit AstMTaskBody(FileLine* fl) : ASTGEN_SUPER_MTaskBody(fl) {} - ASTNODE_NODE_FUNCS(MTaskBody); + ASTGEN_MEMBERS_MTaskBody; virtual const char* broken() const override { BROKEN_RTN(!m_execMTaskp); return nullptr; @@ -1428,7 +1429,7 @@ public: } virtual string name() const override { return m_name; } virtual bool maybePointedTo() const override { return true; } - ASTNODE_NODE_FUNCS(Modport) + ASTGEN_MEMBERS_Modport; AstNode* varsp() const { return op1p(); } // op1 = List of Vars }; class AstModportFTaskRef final : public AstNode { @@ -1445,7 +1446,7 @@ public: : ASTGEN_SUPER_ModportFTaskRef(fl) , m_name{name} , m_export{isExport} {} - ASTNODE_NODE_FUNCS(ModportFTaskRef) + ASTGEN_MEMBERS_ModportFTaskRef; const char* broken() const override; void cloneRelink() override; virtual void dump(std::ostream& str) const override; @@ -1468,7 +1469,7 @@ public: : ASTGEN_SUPER_ModportVarRef(fl) , m_name{name} , m_direction{direction} {} - ASTNODE_NODE_FUNCS(ModportVarRef) + ASTGEN_MEMBERS_ModportVarRef; const char* broken() const override; void cloneRelink() override; virtual void dump(std::ostream& str) const override; @@ -1498,7 +1499,7 @@ private: uint32_t m_nextFreeMTaskProfilingID = 0; // Next unique ID to use for PGO public: AstNetlist(); - ASTNODE_NODE_FUNCS(Netlist) + ASTGEN_MEMBERS_Netlist; const char* broken() const override; virtual void cloneRelink() override { V3ERROR_NA; } virtual string name() const override { return "$root"; } @@ -1549,7 +1550,7 @@ public: : ASTGEN_SUPER_PackageExport(fl) , m_name{name} , m_packagep{packagep} {} - ASTNODE_NODE_FUNCS(PackageExport) + ASTGEN_MEMBERS_PackageExport; const char* broken() const override; void cloneRelink() override; virtual void dump(std::ostream& str) const override; @@ -1563,7 +1564,7 @@ public: // cppcheck-suppress noExplicitConstructor AstPackageExportStarStar(FileLine* fl) : ASTGEN_SUPER_PackageExportStarStar(fl) {} - ASTNODE_NODE_FUNCS(PackageExportStarStar) + ASTGEN_MEMBERS_PackageExportStarStar; }; class AstPackageImport final : public AstNode { private: @@ -1575,7 +1576,7 @@ public: : ASTGEN_SUPER_PackageImport(fl) , m_name{name} , m_packagep{packagep} {} - ASTNODE_NODE_FUNCS(PackageImport) + ASTGEN_MEMBERS_PackageImport; const char* broken() const override; void cloneRelink() override; virtual void dump(std::ostream& str) const override; @@ -1602,7 +1603,7 @@ public: setNOp1p(lhsp); setNOp2p((AstNode*)ftaskrefp); } - ASTNODE_NODE_FUNCS(ParseRef) + ASTGEN_MEMBERS_ParseRef; virtual void dump(std::ostream& str) const override; virtual string name() const override { return m_name; } // * = Var name virtual bool same(const AstNode* samep) const override { @@ -1635,7 +1636,7 @@ public: setNOp1p(exprp); } inline AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp); - ASTNODE_NODE_FUNCS(Pin) + ASTGEN_MEMBERS_Pin; virtual void dump(std::ostream& str) const override; const char* broken() const override; virtual string name() const override { return m_name; } // * = Pin name, ""=go by number @@ -1666,7 +1667,7 @@ public: : ASTGEN_SUPER_Port(fl) , m_pinNum{pinnum} , m_name{name} {} - ASTNODE_NODE_FUNCS(Port) + ASTGEN_MEMBERS_Port; virtual string name() const override { return m_name; } // * = Port name int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation AstNode* exprp() const { return op1p(); } // op1 = Expression connected to port @@ -1680,7 +1681,7 @@ public: AstPragma(FileLine* fl, VPragmaType pragType) : ASTGEN_SUPER_Pragma(fl) , m_pragType{pragType} {} - ASTNODE_NODE_FUNCS(Pragma) + ASTGEN_MEMBERS_Pragma; VPragmaType pragType() const { return m_pragType; } // *=type of the pragma virtual bool isPredictOptimizable() const override { return false; } virtual bool same(const AstNode* samep) const override { @@ -1698,7 +1699,7 @@ public: addNOp2p(disablep); addOp3p(propp); } - ASTNODE_NODE_FUNCS(PropClocked) + ASTGEN_MEMBERS_PropClocked; virtual bool hasDType() const override { return true; } // Used under Cover, which expects a bool child @@ -1716,7 +1717,7 @@ public: , m_direction{direction} { setOp1p(lhsp); } - ASTNODE_NODE_FUNCS(Pull) + ASTGEN_MEMBERS_Pull; virtual bool same(const AstNode* samep) const override { return direction() == static_cast(samep)->direction(); } @@ -1756,7 +1757,7 @@ public: addNOp1p(exprsp); addNOp2p(nullptr); } - ASTNODE_NODE_FUNCS(SFormatF) + ASTGEN_MEMBERS_SFormatF; virtual string name() const override { return m_text; } virtual int instrCount() const override { return INSTR_COUNT_PLI; } virtual bool hasDType() const override { return true; } @@ -1798,7 +1799,7 @@ public: , m_aboveScopep{aboveScopep} , m_aboveCellp{aboveCellp} , m_modp{modp} {} - ASTNODE_NODE_FUNCS(Scope) + ASTGEN_MEMBERS_Scope; virtual void cloneRelink() override; virtual const char* broken() const override; virtual bool maybePointedTo() const override { return true; } @@ -1827,7 +1828,7 @@ public: setOp1p(fromp); addNOp2p(elementsp); } - ASTNODE_NODE_FUNCS(SelLoopVars) + ASTGEN_MEMBERS_SelLoopVars; virtual bool same(const AstNode* /*samep*/) const override { return true; } virtual bool maybePointedTo() const override { return false; } AstNode* fromp() const { return op1p(); } @@ -1865,7 +1866,7 @@ public: AstSenItem(FileLine* fl, Never) : ASTGEN_SUPER_SenItem(fl) , m_edgeType{VEdgeType::ET_NEVER} {} - ASTNODE_NODE_FUNCS(SenItem) + ASTGEN_MEMBERS_SenItem; virtual void dump(std::ostream& str) const override; virtual bool same(const AstNode* samep) const override { return edgeType() == static_cast(samep)->edgeType(); @@ -1899,7 +1900,7 @@ public: : ASTGEN_SUPER_SenTree(fl) { addNOp1p(sensesp); } - ASTNODE_NODE_FUNCS(SenTree) + ASTGEN_MEMBERS_SenTree; virtual void dump(std::ostream& str) const override; virtual bool maybePointedTo() const override { return true; } bool isMulti() const { return m_multi; } @@ -1918,7 +1919,7 @@ public: // Dummy node used within V3Split; never exists outside of V3Split. explicit AstSplitPlaceholder(FileLine* fl) : ASTGEN_SUPER_SplitPlaceholder(fl) {} - ASTNODE_NODE_FUNCS(SplitPlaceholder) + ASTGEN_MEMBERS_SplitPlaceholder; }; class AstStrengthSpec final : public AstNode { private: @@ -1931,7 +1932,7 @@ public: , m_s0{s0} , m_s1{s1} {} - ASTNODE_NODE_FUNCS(StrengthSpec) + ASTGEN_MEMBERS_StrengthSpec; VStrength strength0() { return m_s0; } VStrength strength1() { return m_s1; } virtual void dump(std::ostream& str) const override; @@ -1948,7 +1949,7 @@ class AstTopScope final : public AstNode { } public: - ASTNODE_NODE_FUNCS(TopScope) + ASTGEN_MEMBERS_TopScope; virtual bool maybePointedTo() const override { return true; } AstSenTree* senTreesp() const { return VN_AS(op1p(), SenTree); } void addSenTreep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } @@ -1967,7 +1968,7 @@ class AstTypeTable final : public AstNode { public: explicit AstTypeTable(FileLine* fl); - ASTNODE_NODE_FUNCS(TypeTable) + ASTGEN_MEMBERS_TypeTable; virtual bool maybePointedTo() const override { return true; } virtual const char* broken() const override { BROKEN_RTN(m_emptyQueuep && !m_emptyQueuep->brokeExists()); @@ -2005,7 +2006,7 @@ public: addAttrsp(attrsp); dtypep(nullptr); // V3Width will resolve } - ASTNODE_NODE_FUNCS(Typedef) + ASTGEN_MEMBERS_Typedef; virtual void dump(std::ostream& str) const override; virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Type assigning to @@ -2033,7 +2034,7 @@ public: AstTypedefFwd(FileLine* fl, const string& name) : ASTGEN_SUPER_TypedefFwd(fl) , m_name{name} {} - ASTNODE_NODE_FUNCS(TypedefFwd) + ASTGEN_MEMBERS_TypedefFwd; // METHODS virtual string name() const override { return m_name; } virtual bool maybePointedTo() const override { return true; } @@ -2044,7 +2045,7 @@ public: : ASTGEN_SUPER_UdpTable(fl) { addNOp1p(bodysp); } - ASTNODE_NODE_FUNCS(UdpTable) + ASTGEN_MEMBERS_UdpTable; // op1 = List of UdpTableLines AstUdpTableLine* bodysp() const { return VN_AS(op1p(), UdpTableLine); } }; @@ -2055,7 +2056,7 @@ public: AstUdpTableLine(FileLine* fl, const string& text) : ASTGEN_SUPER_UdpTableLine(fl) , m_text{text} {} - ASTNODE_NODE_FUNCS(UdpTableLine) + ASTGEN_MEMBERS_UdpTableLine; virtual string name() const override { return m_text; } string text() const { return m_text; } }; @@ -2070,7 +2071,7 @@ public: addNOp1p(refp); addNOp2p(crp); } - ASTNODE_NODE_FUNCS(UnlinkedRef) + ASTGEN_MEMBERS_UnlinkedRef; // ACCESSORS virtual string name() const override { return m_name; } // * = Var name AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef @@ -2230,7 +2231,7 @@ public: dtypeFrom(examplep); m_declKwd = examplep->declKwd(); } - ASTNODE_NODE_FUNCS(Var) + ASTGEN_MEMBERS_Var; virtual void dump(std::ostream& str) const override; virtual string name() const override { return m_name; } // * = Var name virtual bool hasDType() const override { return true; } @@ -2467,7 +2468,7 @@ public: m_trace = true; dtypeFrom(varp); } - ASTNODE_NODE_FUNCS(VarScope) + ASTGEN_MEMBERS_VarScope; virtual void cloneRelink() override { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); @@ -2508,7 +2509,7 @@ public: : ASTGEN_SUPER_Begin(fl, name, stmtsp) , m_generate{generate} , m_implied{implied} {} - ASTNODE_NODE_FUNCS(Begin) + ASTGEN_MEMBERS_Begin; virtual void dump(std::ostream& str) const override; // op1p is statements in NodeBlock AstNode* genforp() const { return op2p(); } // op2 = GENFOR, if applicable, @@ -2528,7 +2529,7 @@ public: // Node that puts name into the output stream AstFork(FileLine* fl, const string& name, AstNode* stmtsp) : ASTGEN_SUPER_Fork(fl, name, stmtsp) {} - ASTNODE_NODE_FUNCS(Fork) + ASTGEN_MEMBERS_Fork; virtual void dump(std::ostream& str) const override; VJoinType joinType() const { return m_joinType; } void joinType(const VJoinType& flag) { m_joinType = flag; } @@ -2542,7 +2543,7 @@ public: : ASTGEN_SUPER_Func(fl, name, stmtp) { addNOp1p(fvarsp); } - ASTNODE_NODE_FUNCS(Func) + ASTGEN_MEMBERS_Func; virtual bool hasDType() const override { return true; } }; class AstTask final : public AstNodeFTask { @@ -2550,7 +2551,7 @@ class AstTask final : public AstNodeFTask { public: AstTask(FileLine* fl, const string& name, AstNode* stmtp) : ASTGEN_SUPER_Task(fl, name, stmtp) {} - ASTNODE_NODE_FUNCS(Task) + ASTGEN_MEMBERS_Task; }; // === AstNodeFile === @@ -2567,7 +2568,7 @@ public: , m_slow{false} , m_source{false} , m_support{false} {} - ASTNODE_NODE_FUNCS(CFile) + ASTGEN_MEMBERS_CFile; virtual void dump(std::ostream& str = std::cout) const override; bool slow() const { return m_slow; } void slow(bool flag) { m_slow = flag; } @@ -2582,7 +2583,7 @@ class AstVFile final : public AstNodeFile { public: AstVFile(FileLine* fl, const string& name) : ASTGEN_SUPER_VFile(fl, name) {} - ASTNODE_NODE_FUNCS(VFile) + ASTGEN_MEMBERS_VFile; virtual void dump(std::ostream& str = std::cout) const override; }; @@ -2600,7 +2601,7 @@ class AstClass final : public AstNodeModule { public: AstClass(FileLine* fl, const string& name) : ASTGEN_SUPER_Class(fl, name) {} - ASTNODE_NODE_FUNCS(Class) + ASTGEN_MEMBERS_Class; virtual string verilogKwd() const override { return "class"; } virtual bool maybePointedTo() const override { return true; } virtual void dump(std::ostream& str) const override; @@ -2638,7 +2639,7 @@ class AstClassPackage final : public AstNodeModule { public: AstClassPackage(FileLine* fl, const string& name) : ASTGEN_SUPER_ClassPackage(fl, name) {} - ASTNODE_NODE_FUNCS(ClassPackage) + ASTGEN_MEMBERS_ClassPackage; virtual string verilogKwd() const override { return "classpackage"; } virtual const char* broken() const override; virtual void cloneRelink() override; @@ -2651,7 +2652,7 @@ class AstIface final : public AstNodeModule { public: AstIface(FileLine* fl, const string& name) : ASTGEN_SUPER_Iface(fl, name) {} - ASTNODE_NODE_FUNCS(Iface) + ASTGEN_MEMBERS_Iface; // Interfaces have `timescale applicability but lots of code seems to // get false warnings if we enable this virtual string verilogKwd() const override { return "interface"; } @@ -2665,7 +2666,7 @@ public: AstModule(FileLine* fl, const string& name, bool program = false) : ASTGEN_SUPER_Module(fl, name) , m_isProgram{program} {} - ASTNODE_NODE_FUNCS(Module) + ASTGEN_MEMBERS_Module; virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; } virtual bool timescaleMatters() const override { return true; } }; @@ -2674,7 +2675,7 @@ class AstNotFoundModule final : public AstNodeModule { public: AstNotFoundModule(FileLine* fl, const string& name) : ASTGEN_SUPER_NotFoundModule(fl, name) {} - ASTNODE_NODE_FUNCS(NotFoundModule) + ASTGEN_MEMBERS_NotFoundModule; virtual string verilogKwd() const override { return "/*not-found-*/ module"; } virtual bool timescaleMatters() const override { return false; } }; @@ -2683,7 +2684,7 @@ class AstPackage final : public AstNodeModule { public: AstPackage(FileLine* fl, const string& name) : ASTGEN_SUPER_Package(fl, name) {} - ASTNODE_NODE_FUNCS(Package) + ASTGEN_MEMBERS_Package; virtual string verilogKwd() const override { return "package"; } virtual bool timescaleMatters() const override { return !isDollarUnit(); } static string dollarUnitName() { return AstNode::encodeName("$unit"); } @@ -2694,7 +2695,7 @@ class AstPrimitive final : public AstNodeModule { public: AstPrimitive(FileLine* fl, const string& name) : ASTGEN_SUPER_Primitive(fl, name) {} - ASTNODE_NODE_FUNCS(Primitive) + ASTGEN_MEMBERS_Primitive; virtual string verilogKwd() const override { return "primitive"; } virtual bool timescaleMatters() const override { return false; } }; @@ -2709,7 +2710,7 @@ public: UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, "not coded to create after dtypes resolved"); } - ASTNODE_NODE_FUNCS(SelBit) + ASTGEN_MEMBERS_SelBit; AstNode* bitp() const { return rhsp(); } }; class AstSelExtract final : public AstNodePreSel { @@ -2717,7 +2718,7 @@ class AstSelExtract final : public AstNodePreSel { public: AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp) : ASTGEN_SUPER_SelExtract(fl, fromp, msbp, lsbp) {} - ASTNODE_NODE_FUNCS(SelExtract) + ASTGEN_MEMBERS_SelExtract; AstNode* leftp() const { return rhsp(); } AstNode* rightp() const { return thsp(); } }; @@ -2727,7 +2728,7 @@ class AstSelMinus final : public AstNodePreSel { public: AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) : ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {} - ASTNODE_NODE_FUNCS(SelMinus) + ASTGEN_MEMBERS_SelMinus; AstNode* bitp() const { return rhsp(); } AstNode* widthp() const { return thsp(); } }; @@ -2737,7 +2738,7 @@ class AstSelPlus final : public AstNodePreSel { public: AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp) : ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {} - ASTNODE_NODE_FUNCS(SelPlus) + ASTGEN_MEMBERS_SelPlus; AstNode* bitp() const { return rhsp(); } AstNode* widthp() const { return thsp(); } }; @@ -2752,7 +2753,7 @@ public: , m_keyword{keyword} { addNOp1p(sensesp); } - ASTNODE_NODE_FUNCS(Always) + ASTGEN_MEMBERS_Always; // virtual void dump(std::ostream& str) const override; AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list @@ -2766,7 +2767,7 @@ public: : ASTGEN_SUPER_AlwaysPost(fl, bodysp) { addNOp1p(sensesp); } - ASTNODE_NODE_FUNCS(AlwaysPost) + ASTGEN_MEMBERS_AlwaysPost; }; class AstAlwaysPostponed final : public AstNodeProcedure { // Like always but postponement scheduling region @@ -2774,19 +2775,19 @@ class AstAlwaysPostponed final : public AstNodeProcedure { public: AstAlwaysPostponed(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER_AlwaysPostponed(fl, bodysp) {} - ASTNODE_NODE_FUNCS(AlwaysPostponed) + ASTGEN_MEMBERS_AlwaysPostponed; }; class AstFinal final : public AstNodeProcedure { public: AstFinal(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER_Final(fl, bodysp) {} - ASTNODE_NODE_FUNCS(Final) + ASTGEN_MEMBERS_Final; }; class AstInitial final : public AstNodeProcedure { public: AstInitial(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER_Initial(fl, bodysp) {} - ASTNODE_NODE_FUNCS(Initial) + ASTGEN_MEMBERS_Initial; }; class AstInitialAutomatic final : public AstNodeProcedure { // Automatic variable initialization @@ -2794,7 +2795,7 @@ class AstInitialAutomatic final : public AstNodeProcedure { public: AstInitialAutomatic(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER_InitialAutomatic(fl, bodysp) {} - ASTNODE_NODE_FUNCS(InitialAutomatic) + ASTGEN_MEMBERS_InitialAutomatic; }; class AstInitialStatic final : public AstNodeProcedure { // Static variable initialization @@ -2802,7 +2803,7 @@ class AstInitialStatic final : public AstNodeProcedure { public: AstInitialStatic(FileLine* fl, AstNode* bodysp) : ASTGEN_SUPER_InitialStatic(fl, bodysp) {} - ASTNODE_NODE_FUNCS(InitialStatic) + ASTGEN_MEMBERS_InitialStatic; }; // === AstNodeRange === @@ -2814,7 +2815,7 @@ public: : ASTGEN_SUPER_BracketRange(fl) { setOp1p(elementsp); } - ASTNODE_NODE_FUNCS(BracketRange) + ASTGEN_MEMBERS_BracketRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -2833,7 +2834,7 @@ public: } inline AstRange(FileLine* fl, int left, int right); inline AstRange(FileLine* fl, const VNumRange& range); - ASTNODE_NODE_FUNCS(Range) + ASTGEN_MEMBERS_Range; AstNode* leftp() const { return op2p(); } AstNode* rightp() const { return op3p(); } inline int leftConst() const; @@ -2859,7 +2860,7 @@ class AstUnsizedRange final : public AstNodeRange { public: explicit AstUnsizedRange(FileLine* fl) : ASTGEN_SUPER_UnsizedRange(fl) {} - ASTNODE_NODE_FUNCS(UnsizedRange) + ASTGEN_MEMBERS_UnsizedRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[]"; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -2869,7 +2870,7 @@ class AstWildcardRange final : public AstNodeRange { public: explicit AstWildcardRange(FileLine* fl) : ASTGEN_SUPER_WildcardRange(fl) {} - ASTNODE_NODE_FUNCS(WildcardRange) + ASTGEN_MEMBERS_WildcardRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[*]"; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -2885,7 +2886,7 @@ public: addNOp1p(sensesp); addNOp2p(bodysp); } - ASTNODE_NODE_FUNCS(AlwaysPublic) + ASTGEN_MEMBERS_AlwaysPublic; virtual bool same(const AstNode* /*samep*/) const override { return true; } // AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list @@ -2899,7 +2900,7 @@ class AstBreak final : public AstNodeStmt { public: explicit AstBreak(FileLine* fl) : ASTGEN_SUPER_Break(fl) {} - ASTNODE_NODE_FUNCS(Break) + ASTGEN_MEMBERS_Break; virtual string verilogKwd() const override { return "break"; } virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks @@ -2927,7 +2928,7 @@ public: setOp1p(fromp); addNOp2p(pinsp); } - ASTNODE_NODE_FUNCS(CMethodHard) + ASTGEN_MEMBERS_CMethodHard; virtual string name() const override { return m_name; } // * = Var name virtual bool hasDType() const override { return true; } virtual void name(const string& name) override { m_name = name; } @@ -2955,7 +2956,7 @@ public: : ASTGEN_SUPER_CReset(fl) { addNOp1p((AstNode*)exprsp); } - ASTNODE_NODE_FUNCS(CReset) + ASTGEN_MEMBERS_CReset; virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -2970,7 +2971,7 @@ public: : ASTGEN_SUPER_CReturn(fl) { setOp1p(lhsp); } - ASTNODE_NODE_FUNCS(CReturn) + ASTGEN_MEMBERS_CReturn; virtual int instrCount() const override { return widthInstrs(); } virtual bool same(const AstNode* /*samep*/) const override { return true; } // @@ -2984,7 +2985,7 @@ public: addNOp1p(exprsp); } inline AstCStmt(FileLine* fl, const string& textStmt); - ASTNODE_NODE_FUNCS(CStmt) + ASTGEN_MEMBERS_CStmt; virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -3000,7 +3001,7 @@ public: setNOp1p(lhsp); setNOp2p(rhsp); } - ASTNODE_NODE_FUNCS(ChangeDet) + ASTGEN_MEMBERS_ChangeDet; AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } virtual bool isGateOptimizable() const override { return false; } @@ -3020,7 +3021,7 @@ public: : ASTGEN_SUPER_Comment(fl) , m_showAt{showAt} , m_name{name} {} - ASTNODE_NODE_FUNCS(Comment) + ASTGEN_MEMBERS_Comment; virtual string name() const override { return m_name; } // * = Text virtual bool same(const AstNode* samep) const override { return true; @@ -3031,7 +3032,7 @@ class AstContinue final : public AstNodeStmt { public: explicit AstContinue(FileLine* fl) : ASTGEN_SUPER_Continue(fl) {} - ASTNODE_NODE_FUNCS(Continue) + ASTGEN_MEMBERS_Continue; virtual string verilogKwd() const override { return "continue"; } virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks @@ -3058,7 +3059,7 @@ public: , m_text{comment} , m_linescov{linescov} , m_offset{offset} {} - ASTNODE_NODE_FUNCS(CoverDecl) + ASTGEN_MEMBERS_CoverDecl; virtual const char* broken() const override { BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing @@ -3103,7 +3104,7 @@ public: AstCoverInc(FileLine* fl, AstCoverDecl* declp) : ASTGEN_SUPER_CoverInc(fl) , m_declp{declp} {} - ASTNODE_NODE_FUNCS(CoverInc) + ASTGEN_MEMBERS_CoverInc; virtual const char* broken() const override { BROKEN_RTN(!declp()->brokeExists()); return nullptr; @@ -3133,7 +3134,7 @@ public: setOp2p(origp); setOp3p(changep); } - ASTNODE_NODE_FUNCS(CoverToggle) + ASTGEN_MEMBERS_CoverToggle; virtual int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } virtual bool same(const AstNode* /*samep*/) const override { return true; } virtual bool isGateOptimizable() const override { return false; } @@ -3155,7 +3156,7 @@ public: setOp1p(lhsp); setNOp2p(stmtsp); } - ASTNODE_NODE_FUNCS(Delay) + ASTGEN_MEMBERS_Delay; virtual bool same(const AstNode* /*samep*/) const override { return true; } // AstNode* lhsp() const { return op1p(); } // op1 = delay value @@ -3170,7 +3171,7 @@ public: AstDisable(FileLine* fl, const string& name) : ASTGEN_SUPER_Disable(fl) , m_name{name} {} - ASTNODE_NODE_FUNCS(Disable) + ASTGEN_MEMBERS_Disable; virtual string name() const override { return m_name; } // * = Block name virtual void name(const string& flag) override { m_name = flag; } virtual bool isBrancher() const override { @@ -3182,7 +3183,7 @@ class AstDisableFork final : public AstNodeStmt { public: explicit AstDisableFork(FileLine* fl) : ASTGEN_SUPER_DisableFork(fl) {} - ASTNODE_NODE_FUNCS(DisableFork) + ASTGEN_MEMBERS_DisableFork; }; class AstDisplay final : public AstNodeStmt { // Parents: stmtlist @@ -3206,7 +3207,7 @@ public: setOp1p(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp, missingArgChar}); setNOp3p(filep); } - ASTNODE_NODE_FUNCS(Display) + ASTGEN_MEMBERS_Display; virtual void dump(std::ostream& str) const override; virtual const char* broken() const override { BROKEN_RTN(!fmtp()); @@ -3240,7 +3241,7 @@ class AstDpiExportUpdated final : public AstNodeStmt { // Denotes that the referenced variable may have been updated via a DPI Export public: inline AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep); - ASTNODE_NODE_FUNCS(DpiExportUpdated) + ASTGEN_MEMBERS_DpiExportUpdated; inline AstVarScope* varScopep() const; }; class AstDumpCtl final : public AstNodeStmt { @@ -3254,7 +3255,7 @@ public: , m_ctlType{ctlType} { setNOp1p(exprp); } - ASTNODE_NODE_FUNCS(DumpCtl) + ASTGEN_MEMBERS_DumpCtl; virtual string verilogKwd() const override { return ctlType().ascii(); } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3273,7 +3274,7 @@ public: setNOp1p(sensesp); setNOp2p(stmtsp); } - ASTNODE_NODE_FUNCS(EventControl) + ASTGEN_MEMBERS_EventControl; virtual string verilogKwd() const override { return "@(%l) %r"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3291,7 +3292,7 @@ public: : ASTGEN_SUPER_FClose(fl) { setNOp2p(filep); } - ASTNODE_NODE_FUNCS(FClose) + ASTGEN_MEMBERS_FClose; virtual string verilogKwd() const override { return "$fclose"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3310,7 +3311,7 @@ public: : ASTGEN_SUPER_FFlush(fl) { setNOp2p(filep); } - ASTNODE_NODE_FUNCS(FFlush) + ASTGEN_MEMBERS_FFlush; virtual string verilogKwd() const override { return "$fflush"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3330,7 +3331,7 @@ public: setOp2p(filenamep); setOp3p(modep); } - ASTNODE_NODE_FUNCS(FOpen) + ASTGEN_MEMBERS_FOpen; virtual string verilogKwd() const override { return "$fopen"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3350,7 +3351,7 @@ public: setOp1p(filep); setOp2p(filenamep); } - ASTNODE_NODE_FUNCS(FOpenMcd) + ASTGEN_MEMBERS_FOpenMcd; virtual string verilogKwd() const override { return "$fopen"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3365,7 +3366,7 @@ class AstFinish final : public AstNodeStmt { public: explicit AstFinish(FileLine* fl) : ASTGEN_SUPER_Finish(fl) {} - ASTNODE_NODE_FUNCS(Finish) + ASTGEN_MEMBERS_Finish; virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } virtual bool isPure() const override { @@ -3385,7 +3386,7 @@ public: setOp1p(arrayp); addNOp4p(bodysp); } - ASTNODE_NODE_FUNCS(Foreach) + ASTGEN_MEMBERS_Foreach; AstNode* arrayp() const { return op1p(); } // op1 = array and index vars AstNode* bodysp() const { return op4p(); } // op4 = body of loop virtual bool isGateOptimizable() const override { return false; } @@ -3408,7 +3409,7 @@ public: } virtual const char* broken() const override; virtual void cloneRelink() override; - ASTNODE_NODE_FUNCS(JumpBlock) + ASTGEN_MEMBERS_JumpBlock; virtual int instrCount() const override { return 0; } virtual bool maybePointedTo() const override { return true; } virtual bool same(const AstNode* /*samep*/) const override { return true; } @@ -3433,7 +3434,7 @@ public: AstJumpGo(FileLine* fl, AstJumpLabel* labelp) : ASTGEN_SUPER_JumpGo(fl) , m_labelp{labelp} {} - ASTNODE_NODE_FUNCS(JumpGo); + ASTGEN_MEMBERS_JumpGo; const char* broken() const override; void cloneRelink() override; virtual void dump(std::ostream& str) const override; @@ -3457,7 +3458,7 @@ public: AstJumpLabel(FileLine* fl, AstJumpBlock* blockp) : ASTGEN_SUPER_JumpLabel(fl) , m_blockp{blockp} {} - ASTNODE_NODE_FUNCS(JumpLabel) + ASTGEN_MEMBERS_JumpLabel; virtual bool maybePointedTo() const override { return true; } virtual const char* broken() const override { BROKEN_RTN(!blockp()->brokeExistsAbove()); @@ -3481,7 +3482,7 @@ public: AstMonitorOff(FileLine* fl, bool off) : ASTGEN_SUPER_MonitorOff(fl) , m_off{off} {} - ASTNODE_NODE_FUNCS(MonitorOff) + ASTGEN_MEMBERS_MonitorOff; virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; } virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt virtual bool isPredictOptimizable() const override { @@ -3502,7 +3503,7 @@ class AstPrintTimeScale final : public AstNodeStmt { public: explicit AstPrintTimeScale(FileLine* fl) : ASTGEN_SUPER_PrintTimeScale(fl) {} - ASTNODE_NODE_FUNCS(PrintTimeScale) + ASTGEN_MEMBERS_PrintTimeScale; virtual void name(const string& name) override { m_name = name; } virtual string name() const override { return m_name; } // * = Var name virtual void dump(std::ostream& str) const override; @@ -3522,7 +3523,7 @@ public: : ASTGEN_SUPER_Release(fl) { setOp1p(lhsp); } - ASTNODE_NODE_FUNCS(Release); + ASTGEN_MEMBERS_Release; AstNode* lhsp() const { return op1p(); } }; class AstRepeat final : public AstNodeStmt { @@ -3532,7 +3533,7 @@ public: setOp2p(countp); addNOp3p(bodysp); } - ASTNODE_NODE_FUNCS(Repeat) + ASTGEN_MEMBERS_Repeat; AstNode* countp() const { return op2p(); } // op2 = condition to continue AstNode* bodysp() const { return op3p(); } // op3 = body of loop virtual bool isGateOptimizable() const override { @@ -3548,7 +3549,7 @@ public: : ASTGEN_SUPER_Return(fl) { setNOp1p(lhsp); } - ASTNODE_NODE_FUNCS(Return) + ASTGEN_MEMBERS_Return; virtual string verilogKwd() const override { return "return"; } AstNode* lhsp() const { return op1p(); } virtual bool isBrancher() const override { @@ -3571,7 +3572,7 @@ public: setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); setOp3p(lhsp); } - ASTNODE_NODE_FUNCS(SFormat) + ASTGEN_MEMBERS_SFormat; virtual const char* broken() const override { BROKEN_RTN(!fmtp()); return nullptr; @@ -3593,7 +3594,7 @@ class AstStop final : public AstNodeStmt { public: AstStop(FileLine* fl, bool maybe) : ASTGEN_SUPER_Stop(fl) {} - ASTNODE_NODE_FUNCS(Stop) + ASTGEN_MEMBERS_Stop; virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } virtual bool isPure() const override { @@ -3615,7 +3616,7 @@ public: : ASTGEN_SUPER_SysFuncAsTask(fl) { addNOp1p(exprsp); } - ASTNODE_NODE_FUNCS(SysFuncAsTask) + ASTGEN_MEMBERS_SysFuncAsTask; virtual string verilogKwd() const override { return ""; } virtual bool isGateOptimizable() const override { return true; } virtual bool isPredictOptimizable() const override { return true; } @@ -3634,7 +3635,7 @@ public: : ASTGEN_SUPER_SysIgnore(fl) { addNOp1p(exprsp); } - ASTNODE_NODE_FUNCS(SysIgnore) + ASTGEN_MEMBERS_SysIgnore; virtual string verilogKwd() const override { return "$ignored"; } virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt virtual bool isPredictOptimizable() const override { @@ -3653,7 +3654,7 @@ public: : ASTGEN_SUPER_SystemT(fl) { setOp1p(lhsp); } - ASTNODE_NODE_FUNCS(SystemT) + ASTGEN_MEMBERS_SystemT; virtual string verilogKwd() const override { return "$system"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3674,7 +3675,7 @@ public: setOp3p(suffixp); setOp4p(widthp); } - ASTNODE_NODE_FUNCS(TimeFormat) + ASTGEN_MEMBERS_TimeFormat; virtual string verilogKwd() const override { return "$timeformat"; } virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3719,7 +3720,7 @@ public: } virtual void dump(std::ostream& str) const override; virtual int instrCount() const override { return 100; } // Large... - ASTNODE_NODE_FUNCS(TraceDecl) + ASTGEN_MEMBERS_TraceDecl; virtual string name() const override { return m_showname; } virtual bool maybePointedTo() const override { return true; } virtual bool hasDType() const override { return true; } @@ -3756,7 +3757,7 @@ public: dtypeFrom(declp); addOp2p(declp->valuep()->cloneTree(true)); } - ASTNODE_NODE_FUNCS(TraceInc) + ASTGEN_MEMBERS_TraceInc; virtual const char* broken() const override { BROKEN_RTN(!declp()->brokeExists()); return nullptr; @@ -3788,7 +3789,7 @@ public: AstTracePopNamePrefix(FileLine* fl, unsigned count) : ASTGEN_SUPER_TracePopNamePrefix(fl) , m_count{count} {} - ASTNODE_NODE_FUNCS(TracePopNamePrefix) + ASTGEN_MEMBERS_TracePopNamePrefix; virtual bool same(const AstNode* samep) const override { return false; } unsigned count() const { return m_count; } }; @@ -3798,7 +3799,7 @@ public: AstTracePushNamePrefix(FileLine* fl, const string& prefix) : ASTGEN_SUPER_TracePushNamePrefix(fl) , m_prefix{prefix} {} - ASTNODE_NODE_FUNCS(TracePushNamePrefix) + ASTGEN_MEMBERS_TracePushNamePrefix; virtual bool same(const AstNode* samep) const override { return false; } string prefix() const { return m_prefix; } }; @@ -3809,7 +3810,7 @@ public: : ASTGEN_SUPER_UCStmt(fl) { addNOp1p(exprsp); } - ASTNODE_NODE_FUNCS(UCStmt) + ASTGEN_MEMBERS_UCStmt; AstNode* bodysp() const { return op1p(); } // op1 = expressions to print virtual bool isGateOptimizable() const override { return false; } virtual bool isPredictOptimizable() const override { return false; } @@ -3824,7 +3825,7 @@ public: setOp2p(condp); addNOp3p(bodysp); } - ASTNODE_NODE_FUNCS(Wait) + ASTGEN_MEMBERS_Wait; AstNode* bodysp() const { return op3p(); } // op3 = body of loop bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } }; @@ -3833,7 +3834,7 @@ class AstWaitFork final : public AstNodeStmt { public: explicit AstWaitFork(FileLine* fl) : ASTGEN_SUPER_WaitFork(fl) {} - ASTNODE_NODE_FUNCS(WaitFork) + ASTGEN_MEMBERS_WaitFork; }; class AstWhile final : public AstNodeStmt { public: @@ -3843,7 +3844,7 @@ public: addNOp3p(bodysp); addNOp4p(incsp); } - ASTNODE_NODE_FUNCS(While) + ASTGEN_MEMBERS_While; // op1 = prepare statements for condition (exec every loop) AstNode* precondsp() const { return op1p(); } AstNode* condp() const { return op2p(); } // op2 = condition to continue @@ -3876,7 +3877,7 @@ public: addOp2p((AstNode*)valueArgRefp); addNOp3p(exprp); } - ASTNODE_NODE_FUNCS(With) + ASTGEN_MEMBERS_With; virtual bool same(const AstNode* /*samep*/) const override { return true; } virtual bool hasDType() const override { return true; } virtual const char* broken() const override { @@ -3901,7 +3902,7 @@ public: setOp1p(funcrefp); addNOp2p(exprp); } - ASTNODE_NODE_FUNCS(WithParse) + ASTGEN_MEMBERS_WithParse; virtual bool same(const AstNode* /*samep*/) const override { return true; } // AstNode* funcrefp() const { return op1p(); } @@ -3915,7 +3916,7 @@ public: : ASTGEN_SUPER_Assign(fl, lhsp, rhsp, timingControlp) { dtypeFrom(lhsp); } - ASTNODE_NODE_FUNCS(Assign) + ASTGEN_MEMBERS_Assign; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssign(this->fileline(), lhsp, rhsp); } @@ -3927,7 +3928,7 @@ class AstAssignAlias final : public AstNodeAssign { public: AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp) : ASTGEN_SUPER_AssignAlias(fl, (AstNode*)lhsp, (AstNode*)rhsp) {} - ASTNODE_NODE_FUNCS(AssignAlias) + ASTGEN_MEMBERS_AssignAlias; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { V3ERROR_NA_RETURN(nullptr); } @@ -3937,7 +3938,7 @@ class AstAssignDly final : public AstNodeAssign { public: AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp, timingControlp) {} - ASTNODE_NODE_FUNCS(AssignDly) + ASTGEN_MEMBERS_AssignDly; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignDly(this->fileline(), lhsp, rhsp); } @@ -3950,7 +3951,7 @@ class AstAssignForce final : public AstNodeAssign { public: AstAssignForce(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignForce(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignForce) + ASTGEN_MEMBERS_AssignForce; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignForce{this->fileline(), lhsp, rhsp}; } @@ -3961,7 +3962,7 @@ class AstAssignPost final : public AstNodeAssign { public: AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignPost(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignPost) + ASTGEN_MEMBERS_AssignPost; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignPost(this->fileline(), lhsp, rhsp); } @@ -3972,7 +3973,7 @@ class AstAssignPre final : public AstNodeAssign { public: AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignPre(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignPre) + ASTGEN_MEMBERS_AssignPre; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignPre(this->fileline(), lhsp, rhsp); } @@ -3985,7 +3986,7 @@ public: : ASTGEN_SUPER_AssignVarScope(fl, lhsp, rhsp) { dtypeFrom(rhsp); } - ASTNODE_NODE_FUNCS(AssignVarScope) + ASTGEN_MEMBERS_AssignVarScope; virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignVarScope(this->fileline(), lhsp, rhsp); } @@ -3996,7 +3997,7 @@ class AstAssignW final : public AstNodeAssign { public: AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignW(fl, lhsp, rhsp) {} - ASTNODE_NODE_FUNCS(AssignW) + ASTGEN_MEMBERS_AssignW; AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); } void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); } virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { @@ -4024,7 +4025,7 @@ class AstCCall final : public AstNodeCCall { public: AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) : ASTGEN_SUPER_CCall(fl, funcp, argsp) {} - ASTNODE_NODE_FUNCS(CCall) + ASTGEN_MEMBERS_CCall; string selfPointer() const { return m_selfPointer; } void selfPointer(const string& value) { m_selfPointer = value; } @@ -4039,7 +4040,7 @@ public: : ASTGEN_SUPER_CMethodCall(fl, funcp, argsp) { setOp1p(fromp); } - ASTNODE_NODE_FUNCS(CMethodCall) + ASTGEN_MEMBERS_CMethodCall; virtual const char* broken() const override { BROKEN_BASE_RTN(AstNodeCCall::broken()); BROKEN_RTN(!fromp()); @@ -4060,7 +4061,7 @@ public: statement(false); } virtual bool hasDType() const override { return true; } - ASTNODE_NODE_FUNCS(CNew) + ASTGEN_MEMBERS_CNew; }; // === AstNodeCase === @@ -4080,7 +4081,7 @@ public: AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp) : ASTGEN_SUPER_Case(fl, exprp, casesp) , m_casex{casex} {} - ASTNODE_NODE_FUNCS(Case) + ASTGEN_MEMBERS_Case; virtual string verilogKwd() const override { return casez() ? "casez" : casex() ? "casex" : "case"; } @@ -4111,13 +4112,13 @@ class AstGenCase final : public AstNodeCase { public: AstGenCase(FileLine* fl, AstNode* exprp, AstNode* casesp) : ASTGEN_SUPER_GenCase(fl, exprp, casesp) {} - ASTNODE_NODE_FUNCS(GenCase) + ASTGEN_MEMBERS_GenCase; }; // === AstNodeCoverOrAssert === class AstAssert final : public AstNodeCoverOrAssert { public: - ASTNODE_NODE_FUNCS(Assert) + ASTGEN_MEMBERS_Assert; AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, const string& name = "") : ASTGEN_SUPER_Assert(fl, propp, passsp, immediate, name) { @@ -4128,7 +4129,7 @@ public: class AstAssertIntrinsic final : public AstNodeCoverOrAssert { // A $cast or other compiler inserted assert, that must run even without --assert option public: - ASTNODE_NODE_FUNCS(AssertIntrinsic) + ASTGEN_MEMBERS_AssertIntrinsic; AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, const string& name = "") : ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, immediate, name) { @@ -4138,7 +4139,7 @@ public: }; class AstCover final : public AstNodeCoverOrAssert { public: - ASTNODE_NODE_FUNCS(Cover) + ASTGEN_MEMBERS_Cover; AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate, const string& name = "") : ASTGEN_SUPER_Cover(fl, propp, stmtsp, immediate, name) {} @@ -4148,7 +4149,7 @@ public: }; class AstRestrict final : public AstNodeCoverOrAssert { public: - ASTNODE_NODE_FUNCS(Restrict) + ASTGEN_MEMBERS_Restrict; AstRestrict(FileLine* fl, AstNode* propp) : ASTGEN_SUPER_Restrict(fl, propp, nullptr, false, "") {} }; @@ -4161,7 +4162,7 @@ public: : ASTGEN_SUPER_FuncRef(fl, false, namep, pinsp) {} AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) : ASTGEN_SUPER_FuncRef(fl, false, name, pinsp) {} - ASTNODE_NODE_FUNCS(FuncRef) + ASTGEN_MEMBERS_FuncRef; virtual bool hasDType() const override { return true; } }; class AstMethodCall final : public AstNodeFTaskRef { @@ -4180,7 +4181,7 @@ public: : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { setOp2p(fromp); } - ASTNODE_NODE_FUNCS(MethodCall) + ASTGEN_MEMBERS_MethodCall; virtual const char* broken() const override { BROKEN_BASE_RTN(AstNodeFTaskRef::broken()); BROKEN_RTN(!fromp()); @@ -4205,7 +4206,7 @@ class AstNew final : public AstNodeFTaskRef { public: AstNew(FileLine* fl, AstNode* pinsp) : ASTGEN_SUPER_New(fl, false, "new", pinsp) {} - ASTNODE_NODE_FUNCS(New) + ASTGEN_MEMBERS_New; virtual bool cleanOut() const { return true; } virtual bool same(const AstNode* /*samep*/) const override { return true; } virtual bool hasDType() const override { return true; } @@ -4220,7 +4221,7 @@ public: } AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp) : ASTGEN_SUPER_TaskRef(fl, true, name, pinsp) {} - ASTNODE_NODE_FUNCS(TaskRef) + ASTGEN_MEMBERS_TaskRef; }; // === AstNodeFor === @@ -4228,7 +4229,7 @@ class AstGenFor final : public AstNodeFor { public: AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) : ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, bodysp) {} - ASTNODE_NODE_FUNCS(GenFor) + ASTGEN_MEMBERS_GenFor; }; // === AstNodeIf === @@ -4236,7 +4237,7 @@ class AstGenIf final : public AstNodeIf { public: AstGenIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) : ASTGEN_SUPER_GenIf(fl, condp, ifsp, elsesp) {} - ASTNODE_NODE_FUNCS(GenIf) + ASTGEN_MEMBERS_GenIf; }; class AstIf final : public AstNodeIf { private: @@ -4246,7 +4247,7 @@ private: public: AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp = nullptr, AstNode* elsesp = nullptr) : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) {} - ASTNODE_NODE_FUNCS(If) + ASTGEN_MEMBERS_If; bool uniquePragma() const { return m_uniquePragma; } void uniquePragma(bool flag) { m_uniquePragma = flag; } bool unique0Pragma() const { return m_unique0Pragma; } @@ -4261,7 +4262,7 @@ public: AstReadMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) : ASTGEN_SUPER_ReadMem(fl, hex, filenamep, memp, lsbp, msbp) {} - ASTNODE_NODE_FUNCS(ReadMem); + ASTGEN_MEMBERS_ReadMem; virtual string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); } virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; } }; @@ -4270,7 +4271,7 @@ public: AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) : ASTGEN_SUPER_WriteMem(fl, hex, filenamep, memp, lsbp, msbp) {} - ASTNODE_NODE_FUNCS(WriteMem) + ASTGEN_MEMBERS_WriteMem; virtual string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); } virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } }; @@ -4280,7 +4281,7 @@ class AstScCtor final : public AstNodeText { public: AstScCtor(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScCtor(fl, textp) {} - ASTNODE_NODE_FUNCS(ScCtor) + ASTGEN_MEMBERS_ScCtor; virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs virtual bool isOutputter() const override { return true; } }; @@ -4288,7 +4289,7 @@ class AstScDtor final : public AstNodeText { public: AstScDtor(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScDtor(fl, textp) {} - ASTNODE_NODE_FUNCS(ScDtor) + ASTGEN_MEMBERS_ScDtor; virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs virtual bool isOutputter() const override { return true; } }; @@ -4296,7 +4297,7 @@ class AstScHdr final : public AstNodeText { public: AstScHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScHdr(fl, textp) {} - ASTNODE_NODE_FUNCS(ScHdr) + ASTGEN_MEMBERS_ScHdr; virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs virtual bool isOutputter() const override { return true; } }; @@ -4304,7 +4305,7 @@ class AstScImp final : public AstNodeText { public: AstScImp(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScImp(fl, textp) {} - ASTNODE_NODE_FUNCS(ScImp) + ASTGEN_MEMBERS_ScImp; virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs virtual bool isOutputter() const override { return true; } }; @@ -4312,7 +4313,7 @@ class AstScImpHdr final : public AstNodeText { public: AstScImpHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScImpHdr(fl, textp) {} - ASTNODE_NODE_FUNCS(ScImpHdr) + ASTGEN_MEMBERS_ScImpHdr; virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs virtual bool isOutputter() const override { return true; } }; @@ -4320,7 +4321,7 @@ class AstScInt final : public AstNodeText { public: AstScInt(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScInt(fl, textp) {} - ASTNODE_NODE_FUNCS(ScInt) + ASTGEN_MEMBERS_ScInt; virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs virtual bool isOutputter() const override { return true; } }; @@ -4330,7 +4331,7 @@ class AstText final : public AstNodeSimpleText { public: AstText(FileLine* fl, const string& textp, bool tracking = false) : ASTGEN_SUPER_Text(fl, textp, tracking) {} - ASTNODE_NODE_FUNCS(Text) + ASTGEN_MEMBERS_Text; }; class AstTextBlock final : public AstNodeSimpleText { private: @@ -4340,7 +4341,7 @@ public: bool commas = false) : ASTGEN_SUPER_TextBlock(fl, textp, tracking) , m_commas(commas) {} - ASTNODE_NODE_FUNCS(TextBlock) + ASTGEN_MEMBERS_TextBlock; void commas(bool flag) { m_commas = flag; } bool commas() const { return m_commas; } AstNode* nodesp() const { return op1p(); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index bf1cac868..4dd3d6e77 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -26,7 +26,7 @@ #include "V3PartitionGraph.h" // Just for mtask dumping #include "V3String.h" -#include "V3AstNodes__gen_macros.h" // Generated by 'astgen' +#include "V3Ast__gen_macros.h" // Generated by 'astgen' #include #include diff --git a/src/astgen b/src/astgen index d1fa39f31..02d8d06d6 100755 --- a/src/astgen +++ b/src/astgen @@ -7,6 +7,7 @@ import glob import os import re import sys +import textwrap # from pprint import pprint, pformat @@ -493,28 +494,59 @@ class Cpt: def read_types(filename): + hasErrors = False + + def error(lineno, message): + nonlocal hasErrors + print(filename + ":" + str(lineno) + ": %Error: " + message, + file=sys.stderr) + hasErrors = True + + node = None + hasAstgenMembers = False + + def checkFinishedNode(node): + nonlocal hasAstgenMembers + if not node: + return + if not hasAstgenMembers: + error( + node.lineno, "'Ast" + node.name + + "' does not contain 'ASTGEN_MEMBERS_" + node.name + ";'") + hasAstgenMembers = False + with open(filename) as fh: for (lineno, line) in enumerate(fh, start=1): - line = re.sub(r'//.*$', '', line) - if re.match(r'^\s*$', line): + line = line.strip() + if not line: continue + match = re.search(r'^\s*(class|struct)\s*(\S+)', line) if match: classn = match.group(2) match = re.search(r':\s*public\s+(\S+)', line) supern = match.group(1) if match else "" - assert classn != "AstNode" or supern == "", "AstNode can't have a superclass" - if re.search(r'Ast', supern) or classn == "AstNode": + if re.search(r'Ast', supern): classn = re.sub(r'^Ast', '', classn) supern = re.sub(r'^Ast', '', supern) if not supern: sys.exit("%Error: 'Ast{}' has no super-class".format( classn)) + checkFinishedNode(node) superClass = Nodes[supern] node = Node(classn, superClass, filename, lineno) superClass.addSubClass(node) Nodes[classn] = node + if not node: + continue + + if re.match(r'^\s*ASTGEN_MEMBERS_' + node.name + ';', line): + hasAstgenMembers = True + checkFinishedNode(node) + if hasErrors: + sys.exit("%Error: Stopping due to errors reported above") + def read_stages(filename): with open(filename) as fh: @@ -698,13 +730,41 @@ def write_yystype(filename): def write_macros(filename): with open_file(filename) as fh: - for node in SortedNodes: - # Only care about leaf classes - if not node.isLeaf: - continue + + def emitBlock(pattern, **fmt): fh.write( - "#define ASTGEN_SUPER_{t}(...) Ast{b}(VNType::at{t}, __VA_ARGS__)\n" - .format(t=node.name, b=node.superClass.name)) + textwrap.indent(textwrap.dedent(pattern), + " ").format(**fmt).replace("\n", " \\\n")) + + for node in SortedNodes: + fh.write("#define ASTGEN_MEMBERS_{t} \\\n".format(t=node.name)) + emitBlock('''\ + static Ast{t}* cloneTreeNull(Ast{t}* nodep, bool cloneNextLink) {{ + return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; + }} + Ast{t}* cloneTree(bool cloneNext) {{ + return static_cast(AstNode::cloneTree(cloneNext)); + }} + Ast{t}* clonep() const {{ return static_cast(AstNode::clonep()); }} + ''', + t=node.name) + + if node.isLeaf: + emitBlock('''\ + virtual void accept(VNVisitor& v) override {{ v.visit(this); }} + virtual AstNode* clone() override {{ return new Ast{t}(*this); }} + ''', + t=node.name) + + fh.write( + " static_assert(true, \"\")\n") # Swallowing the semicolon + + # Only care about leaf classes for the rest + if node.isLeaf: + fh.write( + "#define ASTGEN_SUPER_{t}(...) Ast{b}(VNType::at{t}, __VA_ARGS__)\n" + .format(t=node.name, b=node.superClass.name)) + fh.write("\n") ###################################################################### @@ -807,7 +867,7 @@ if Args.classes: write_impl("V3Ast__gen_impl.h") write_types("V3Ast__gen_types.h") write_yystype("V3Ast__gen_yystype.h") - write_macros("V3AstNodes__gen_macros.h") + write_macros("V3Ast__gen_macros.h") for cpt in Args.infiles: if not re.search(r'.cpp$', cpt): From 0c70a0dcbf0ab3b45388b85dba3964b04606aef2 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 16 Sep 2022 11:22:11 +0100 Subject: [PATCH 40/75] Remove redundant 'virtual' keywords from overridden methods 'virtual' is redundant when 'override' is present, so keep only 'override'. Add t/t_dist_cppstyle.pl to check for this. --- include/verilated_fst_sc.h | 21 +- include/verilated_vcd_sc.h | 20 +- src/V3Active.cpp | 58 +- src/V3ActiveTop.cpp | 20 +- src/V3Assert.cpp | 28 +- src/V3AssertPre.cpp | 24 +- src/V3AstNodeDType.h | 646 +++--- src/V3AstNodeMath.h | 3112 ++++++++++++++--------------- src/V3AstNodeOther.h | 1014 +++++----- src/V3AstNodes.cpp | 10 +- src/V3Begin.cpp | 34 +- src/V3Branch.cpp | 10 +- src/V3Broken.cpp | 20 +- src/V3CUse.cpp | 10 +- src/V3Case.cpp | 14 +- src/V3Cast.cpp | 28 +- src/V3Cdc.cpp | 78 +- src/V3Changed.cpp | 12 +- src/V3Class.cpp | 24 +- src/V3Clean.cpp | 58 +- src/V3Clock.cpp | 22 +- src/V3Combine.cpp | 12 +- src/V3Const.cpp | 94 +- src/V3Coverage.cpp | 26 +- src/V3CoverageJoin.cpp | 10 +- src/V3Dead.cpp | 40 +- src/V3Delayed.cpp | 22 +- src/V3Depth.cpp | 20 +- src/V3DepthBlock.cpp | 14 +- src/V3Descope.cpp | 24 +- src/V3EmitCBase.h | 2 +- src/V3EmitCConstInit.h | 8 +- src/V3EmitCConstPool.cpp | 2 +- src/V3EmitCFunc.h | 188 +- src/V3EmitCHeaders.cpp | 2 +- src/V3EmitCImp.cpp | 44 +- src/V3EmitCInlines.cpp | 6 +- src/V3EmitCMain.cpp | 2 +- src/V3EmitCModel.cpp | 2 +- src/V3EmitCSyms.cpp | 22 +- src/V3EmitV.cpp | 236 ++- src/V3EmitXml.cpp | 62 +- src/V3Expand.cpp | 28 +- src/V3File.h | 20 +- src/V3Gate.cpp | 102 +- src/V3GenClk.cpp | 28 +- src/V3GraphAcyc.cpp | 14 +- src/V3GraphTest.cpp | 24 +- src/V3Hasher.cpp | 152 +- src/V3HierBlock.cpp | 10 +- src/V3Inline.cpp | 84 +- src/V3Inst.cpp | 36 +- src/V3InstrCount.cpp | 28 +- src/V3Life.cpp | 40 +- src/V3LifePost.cpp | 38 +- src/V3LinkCells.cpp | 38 +- src/V3LinkDot.cpp | 200 +- src/V3LinkInc.cpp | 40 +- src/V3LinkJump.cpp | 30 +- src/V3LinkLValue.cpp | 68 +- src/V3LinkParse.cpp | 56 +- src/V3LinkResolve.cpp | 74 +- src/V3Localize.cpp | 16 +- src/V3MergeCond.cpp | 16 +- src/V3Name.cpp | 20 +- src/V3OptionParser.cpp | 16 +- src/V3Order.cpp | 95 +- src/V3OrderGraph.h | 165 +- src/V3Param.cpp | 30 +- src/V3Partition.cpp | 16 +- src/V3PartitionGraph.h | 14 +- src/V3PreProc.cpp | 12 +- src/V3Premit.cpp | 46 +- src/V3ProtectLib.cpp | 8 +- src/V3Randomize.cpp | 14 +- src/V3Reloop.cpp | 12 +- src/V3Scope.cpp | 66 +- src/V3Simulate.h | 72 +- src/V3Slice.cpp | 16 +- src/V3Split.cpp | 116 +- src/V3SplitAs.cpp | 22 +- src/V3SplitVar.cpp | 46 +- src/V3Stats.cpp | 20 +- src/V3Subst.cpp | 24 +- src/V3TSP.cpp | 8 +- src/V3Table.cpp | 16 +- src/V3Task.cpp | 58 +- src/V3Trace.cpp | 46 +- src/V3TraceDecl.cpp | 24 +- src/V3Tristate.cpp | 70 +- src/V3Undriven.cpp | 42 +- src/V3Unknown.cpp | 32 +- src/V3Unroll.cpp | 12 +- src/V3VariableOrder.cpp | 4 +- src/V3Width.cpp | 472 +++-- src/V3WidthCommit.h | 32 +- src/V3WidthSel.cpp | 12 +- src/astgen | 12 +- test_regress/t/t_dist_cppstyle.pl | 66 + 99 files changed, 4454 insertions(+), 4525 deletions(-) create mode 100755 test_regress/t/t_dist_cppstyle.pl diff --git a/include/verilated_fst_sc.h b/include/verilated_fst_sc.h index ae0943d8b..f6546ce84 100644 --- a/include/verilated_fst_sc.h +++ b/include/verilated_fst_sc.h @@ -52,35 +52,36 @@ public: } spTrace()->set_time_resolution(sc_get_time_resolution().to_string()); } - virtual ~VerilatedFstSc() /*override*/ { close(); } + ~VerilatedFstSc() override { close(); } // METHODS /// Called by SystemC simulate() - virtual void cycle(bool delta_cycle) { + void cycle(bool delta_cycle) override { if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); } } // Override VerilatedFstC. Must be called after starting simulation. - // cppcheck-suppress missingOverride // GCC won't accept override - virtual void open(const char* filename) /*override*/ VL_MT_SAFE; + // Note: this is not a virtual function in the base class, so no 'override' + virtual void open(const char* filename) VL_MT_SAFE; private: /// Fake outs for linker #ifdef NC_SYSTEMC // Cadence Incisive has these as abstract functions so we must create them - virtual void set_time_unit(int exponent10_seconds) {} // deprecated + void set_time_unit(int exponent10_seconds) override {} // deprecated #endif - virtual void set_time_unit(double v, sc_time_unit tu) {} // LCOV_EXCL_LINE + void set_time_unit(double v, sc_time_unit tu) override {} // LCOV_EXCL_LINE //-------------------------------------------------- // SystemC 2.1.v1 -#define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name); +#define DECL_TRACE_METHOD_A(tp) \ + void trace(const tp& object, const std::string& name) override; #define DECL_TRACE_METHOD_B(tp) \ - virtual void trace(const tp& object, const std::string& name, int width); + void trace(const tp& object, const std::string& name, int width) override; - virtual void write_comment(const std::string&); - virtual void trace(const unsigned int&, const std::string&, const char**); + void write_comment(const std::string&) override; + void trace(const unsigned int&, const std::string&, const char**) override; // clang-format off // Formatting matches that of sc_trace.h diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h index a32134b23..133f70407 100644 --- a/include/verilated_vcd_sc.h +++ b/include/verilated_vcd_sc.h @@ -55,35 +55,35 @@ public: spTrace()->set_time_resolution(sc_get_time_resolution().to_string()); } /// Destruct, flush, and close the dump - virtual ~VerilatedVcdSc() /*override*/ { close(); } + ~VerilatedVcdSc() override { close(); } // METHODS - for SC kernel // Called by SystemC simulate() - virtual void cycle(bool delta_cycle) { + void cycle(bool delta_cycle) override { if (!delta_cycle) this->dump(sc_time_stamp().to_double()); } // Override VerilatedVcdC. Must be called after starting simulation. - // cppcheck-suppress missingOverride // GCC won't accept override - virtual void open(const char* filename) /*override*/ VL_MT_SAFE; + void open(const char* filename) override VL_MT_SAFE; private: // METHODS - Fake outs for linker #ifdef NC_SYSTEMC // Cadence Incisive has these as abstract functions so we must create them - virtual void set_time_unit(int exponent10_seconds) {} // deprecated + void set_time_unit(int exponent10_seconds) override {} // deprecated #endif - virtual void set_time_unit(double v, sc_time_unit tu) {} // LCOV_EXCL_LINE + void set_time_unit(double v, sc_time_unit tu) override {} // LCOV_EXCL_LINE //-------------------------------------------------- // SystemC 2.1.v1 -#define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name); +#define DECL_TRACE_METHOD_A(tp) \ + void trace(const tp& object, const std::string& name) override; #define DECL_TRACE_METHOD_B(tp) \ - virtual void trace(const tp& object, const std::string& name, int width); + void trace(const tp& object, const std::string& name, int width) override; - virtual void write_comment(const std::string&); - virtual void trace(const unsigned int&, const std::string&, const char**); + void write_comment(const std::string&) override; + void trace(const unsigned int&, const std::string&, const char**) override; // clang-format off // Formatting matches that of sc_trace.h diff --git a/src/V3Active.cpp b/src/V3Active.cpp index fa629c11f..f1b325eac 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -66,8 +66,8 @@ public: : V3GraphVertex{graphp} , m_name{name} , m_type{type} {} - virtual string name() const override { return m_name + " " + typestr(); } - virtual string dotColor() const override { return user() ? "green" : "black"; } + string name() const override { return m_name + " " + typestr(); } + string dotColor() const override { return user() ? "green" : "black"; } virtual int type() const { return m_type; } }; @@ -120,7 +120,7 @@ protected: public: LatchDetectGraph() { clear(); } - virtual ~LatchDetectGraph() override { clear(); } + ~LatchDetectGraph() override { clear(); } // ACCESSORS LatchDetectGraphVertex* currentp() { return m_curVertexp; } void currentp(LatchDetectGraphVertex* vertex) { m_curVertexp = vertex; } @@ -219,7 +219,7 @@ private: m_scopep->addActivep(nodep); } // VISITORS - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { m_scopep = nodep; m_iActivep = nullptr; m_cActivep = nullptr; @@ -227,13 +227,13 @@ private: iterateChildren(nodep); // Don't clear scopep, the namer persists beyond this visit } - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { // Simplify sensitivity list VL_DO_DANGLING(V3Const::constifyExpensiveEdit(nodep), nodep); } //-------------------- - virtual void visit(AstNodeStmt*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeStmt*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // METHODS @@ -275,7 +275,7 @@ public: // CONSTRUCTORS ActiveNamer() = default; - virtual ~ActiveNamer() override = default; + ~ActiveNamer() override = default; void main(AstScope* nodep) { iterate(nodep); } }; @@ -291,13 +291,13 @@ private: // STATE LatchDetectGraph m_graph; // Graph used to detect latches in combo always // VISITORS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { const AstVar* const varp = nodep->varp(); if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()) { m_graph.addAssignment(nodep); } } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { if (!nodep->isBoundsCheck()) { LatchDetectGraphVertex* const parentp = m_graph.currentp(); LatchDetectGraphVertex* const branchp = m_graph.addPathVertex(parentp, "BRANCH", true); @@ -309,7 +309,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -333,7 +333,7 @@ private: const CheckType m_check; // Process type we are checking // VISITORS - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { // Non-blocking assignments are OK in sequential processes if (m_check == CT_SEQ) return; @@ -357,7 +357,7 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstAssign* nodep) override { + void visit(AstAssign* nodep) override { // Blocking assignments are always OK in combinational (and initial/final) processes if (m_check != CT_SEQ) return; @@ -380,7 +380,7 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -407,7 +407,7 @@ private: bool m_itemSequent = false; // Found a SenItem sequential // VISITORS - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { // Create required actives and add to scope UINFO(4, " SCOPE " << nodep << endl); // Clear last scope's names, and collect this scope's existing names @@ -415,10 +415,10 @@ private: m_scopeFinalp = nullptr; iterateChildren(nodep); } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { // Actives are being formed, so we can ignore any already made } - virtual void visit(AstInitialStatic* nodep) override { + void visit(AstInitialStatic* nodep) override { // Relink to IACTIVE, unless already under it UINFO(4, " INITIAL " << nodep << endl); const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL}; @@ -426,7 +426,7 @@ private: nodep->unlinkFrBack(); wantactivep->addStmtsp(nodep); } - virtual void visit(AstInitial* nodep) override { + void visit(AstInitial* nodep) override { // Relink to IACTIVE, unless already under it UINFO(4, " INITIAL " << nodep << endl); const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL}; @@ -434,28 +434,28 @@ private: nodep->unlinkFrBack(); wantactivep->addStmtsp(nodep); } - virtual void visit(AstAssignAlias* nodep) override { + void visit(AstAssignAlias* nodep) override { // Relink to CACTIVE, unless already under it UINFO(4, " ASSIGNW " << nodep << endl); AstActive* const wantactivep = m_namer.getCActive(nodep->fileline()); nodep->unlinkFrBack(); wantactivep->addStmtsp(nodep); } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { // Relink to CACTIVE, unless already under it UINFO(4, " ASSIGNW " << nodep << endl); AstActive* const wantactivep = m_namer.getCActive(nodep->fileline()); nodep->unlinkFrBack(); wantactivep->addStmtsp(nodep); } - virtual void visit(AstCoverToggle* nodep) override { + void visit(AstCoverToggle* nodep) override { // Relink to CACTIVE, unless already under it UINFO(4, " COVERTOGGLE " << nodep << endl); AstActive* const wantactivep = m_namer.getCActive(nodep->fileline()); nodep->unlinkFrBack(); wantactivep->addStmtsp(nodep); } - virtual void visit(AstFinal* nodep) override { + void visit(AstFinal* nodep) override { // Relink to CFUNC for the final UINFO(4, " FINAL " << nodep << endl); if (!nodep->bodysp()) { // Empty, Kill it. @@ -537,7 +537,7 @@ private: ActiveDlyVisitor{nodep, ActiveDlyVisitor::CT_SEQ}; } } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { // Move always to appropriate ACTIVE based on its sense list UINFO(4, " ALW " << nodep << endl); // if (debug() >= 9) nodep->dumpTree(cout, " Alw: "); @@ -549,7 +549,7 @@ private: } visitAlways(nodep, nodep->sensesp(), nodep->keyword()); } - virtual void visit(AstAlwaysPostponed* nodep) override { + void visit(AstAlwaysPostponed* nodep) override { UINFO(4, " ALW " << nodep << endl); if (!nodep->bodysp()) { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); @@ -557,13 +557,13 @@ private: } visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS); } - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlwaysPublic* nodep) override { // Move always to appropriate ACTIVE based on its sense list UINFO(4, " ALWPub " << nodep << endl); // if (debug() >= 9) nodep->dumpTree(cout, " Alw: "); visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS); } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { if (nodep->varrefp()) { if (const AstBasicDType* const basicp = nodep->varrefp()->dtypep()->basicp()) { if (basicp->isEventValue()) { @@ -592,9 +592,9 @@ private: } //-------------------- - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstVarScope*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstVarScope*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index e39742dbd..dc1abe61c 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -52,13 +52,13 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Create required actives and add to module // We can start ordering at a module, or a scope UINFO(4, " MOD " << nodep << endl); iterateChildren(nodep); } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { UINFO(4, " ACTIVE " << nodep << endl); // Remove duplicate clocks and such; sensesp() may change! V3Const::constifyExpensiveEdit(nodep); @@ -101,27 +101,27 @@ private: // No need to do statements under it, they're already moved. // iterateChildren(nodep); } - virtual void visit(AstNodeProcedure* nodep) override { // LCOV_EXCL_LINE + void visit(AstNodeProcedure* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("Node should have been under ACTIVE"); } - virtual void visit(AstAssignAlias* nodep) override { // LCOV_EXCL_LINE + void visit(AstAssignAlias* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("Node should have been under ACTIVE"); } - virtual void visit(AstAssignW* nodep) override { // LCOV_EXCL_LINE + void visit(AstAssignW* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("Node should have been under ACTIVE"); } - virtual void visit(AstAlwaysPublic* nodep) override { // LCOV_EXCL_LINE + void visit(AstAlwaysPublic* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("Node should have been under ACTIVE"); } //-------------------- - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstVarScope*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstVarScope*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ActiveTopVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ActiveTopVisitor() override = default; + ~ActiveTopVisitor() override = default; }; //###################################################################### diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 86e8710a8..59158a07b 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -196,7 +196,7 @@ private: } // VISITORS - virtual void visit(AstIf* nodep) override { + void visit(AstIf* nodep) override { if (nodep->user1SetOnce()) return; if (nodep->uniquePragma() || nodep->unique0Pragma()) { const AstNodeIf* ifp = nodep; @@ -254,7 +254,7 @@ private: } //========== Case assertions - virtual void visit(AstCase* nodep) override { + void visit(AstCase* nodep) override { iterateChildren(nodep); if (!nodep->user1SetOnce()) { bool has_default = false; @@ -323,7 +323,7 @@ private: } //========== Past - virtual void visit(AstPast* nodep) override { + void visit(AstPast* nodep) override { iterateChildren(nodep); uint32_t ticks = 1; if (nodep->ticksp()) { @@ -353,13 +353,13 @@ private: } nodep->replaceWith(inp); } - virtual void visit(AstSampled* nodep) override { + void visit(AstSampled* nodep) override { nodep->replaceWith(nodep->exprp()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); } //========== Statements - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { iterateChildren(nodep); // Replace the special types with standard text if (nodep->displayType() == VDisplayType::DT_INFO) { @@ -410,32 +410,32 @@ private: m_modp->addStmtp(newp); } } - virtual void visit(AstMonitorOff* nodep) override { + void visit(AstMonitorOff* nodep) override { const auto newp = new AstAssign(nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE), new AstConst(nodep->fileline(), AstConst::BitTrue{}, nodep->off())); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstAssert* nodep) override { + void visit(AstAssert* nodep) override { iterateChildren(nodep); newPslAssertion(nodep, nodep->failsp()); } - virtual void visit(AstAssertIntrinsic* nodep) override { + void visit(AstAssertIntrinsic* nodep) override { iterateChildren(nodep); newPslAssertion(nodep, nodep->failsp()); } - virtual void visit(AstCover* nodep) override { + void visit(AstCover* nodep) override { iterateChildren(nodep); newPslAssertion(nodep, nullptr); } - virtual void visit(AstRestrict* nodep) override { + void visit(AstRestrict* nodep) override { iterateChildren(nodep); // IEEE says simulator ignores these VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); VL_RESTORER(m_modPastNum); VL_RESTORER(m_modStrobeNum); @@ -446,7 +446,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { // This code is needed rather than a visitor in V3Begin, // because V3Assert is called before V3Begin VL_RESTORER(m_beginp); @@ -456,12 +456,12 @@ private: } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit AssertVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~AssertVisitor() override { + ~AssertVisitor() override { V3Stats::addStat("Assertions, assert non-immediate statements", m_statAsNotImm); V3Stats::addStat("Assertions, assert immediate statements", m_statAsImm); V3Stats::addStat("Assertions, cover statements", m_statCover); diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 705dfcbb2..e993bd432 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -69,7 +69,7 @@ private: // VISITORS //========== Statements - virtual void visit(AstClocking* nodep) override { + void visit(AstClocking* nodep) override { UINFO(8, " CLOCKING" << nodep << endl); // Store the new default clock, reset on new module m_seniDefaultp = nodep->sensesp(); @@ -81,14 +81,14 @@ private: } VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { iterateAndNextNull(nodep->sensesp()); if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp(); iterateAndNextNull(nodep->bodysp()); m_seniAlwaysp = nullptr; } - virtual void visit(AstNodeCoverOrAssert* nodep) override { + void visit(AstNodeCoverOrAssert* nodep) override { if (nodep->sentreep()) return; // Already processed clearAssertInfo(); // Find Clocking's buried under nodep->exprsp @@ -96,7 +96,7 @@ private: if (!nodep->immediate()) nodep->sentreep(newSenTree(nodep)); clearAssertInfo(); } - virtual void visit(AstFell* nodep) override { + void visit(AstFell* nodep) override { if (nodep->sentreep()) return; // Already processed iterateChildren(nodep); FileLine* const fl = nodep->fileline(); @@ -110,12 +110,12 @@ private: nodep->sentreep(newSenTree(nodep)); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstPast* nodep) override { + void visit(AstPast* nodep) override { if (nodep->sentreep()) return; // Already processed iterateChildren(nodep); nodep->sentreep(newSenTree(nodep)); } - virtual void visit(AstRose* nodep) override { + void visit(AstRose* nodep) override { if (nodep->sentreep()) return; // Already processed iterateChildren(nodep); FileLine* const fl = nodep->fileline(); @@ -129,7 +129,7 @@ private: nodep->sentreep(newSenTree(nodep)); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstStable* nodep) override { + void visit(AstStable* nodep) override { if (nodep->sentreep()) return; // Already processed iterateChildren(nodep); FileLine* const fl = nodep->fileline(); @@ -143,7 +143,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstImplication* nodep) override { + void visit(AstImplication* nodep) override { if (nodep->sentreep()) return; // Already processed FileLine* const fl = nodep->fileline(); @@ -161,7 +161,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstPropClocked* nodep) override { + void visit(AstPropClocked* nodep) override { // No need to iterate the body, once replace will get iterated iterateAndNextNull(nodep->sensesp()); if (m_senip) @@ -183,12 +183,12 @@ private: nodep->replaceWith(blockp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { iterateChildren(nodep); // Reset defaults m_seniDefaultp = nullptr; } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -197,7 +197,7 @@ public: // Process iterate(nodep); } - virtual ~AssertPreVisitor() override = default; + ~AssertPreVisitor() override = default; }; //###################################################################### diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 3615650af..8df86afab 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -52,9 +52,9 @@ protected: public: ASTGEN_MEMBERS_NodeDType; // ACCESSORS - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; virtual void dumpSmall(std::ostream& str) const; - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } /// Require VlUnpacked, instead of [] for POD elements. /// A non-POD object is always compound, but some POD elements /// are compound when methods calls operate on object, or when @@ -72,7 +72,7 @@ public: virtual int widthAlignBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const = 0; - virtual bool maybePointedTo() const override { return true; } + bool maybePointedTo() const override { return true; } // Iff has a non-null refDTypep(), as generic node function virtual AstNodeDType* virtRefDTypep() const { return nullptr; } // Iff has refDTypep(), set as generic node function @@ -143,47 +143,45 @@ protected: public: ASTGEN_MEMBERS_NodeArrayDType; - virtual void dump(std::ostream& str) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual const char* broken() const override { + void dump(std::ostream& str) const override; + void dumpSmall(std::ostream& str) const override; + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstNodeArrayDType* const asamep = static_cast(samep); return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep() && rangenp()->sameTree(asamep->rangenp())); } // HashedDT doesn't recurse, so need to check children - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { const AstNodeArrayDType* const asamep = static_cast(samep); return (asamep && type() == samep->type() && hi() == asamep->hi() && rangenp()->sameTree(asamep->rangenp()) && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable void rangep(AstRange* nodep); // METHODS - virtual AstBasicDType* basicp() const override { + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return elementsConst() * subDTypep()->widthTotalBytes(); } int left() const; @@ -217,30 +215,30 @@ protected: public: ASTGEN_MEMBERS_NodeUOrStructDType; int uniqueNum() const { return m_uniqueNum; } - virtual const char* broken() const override; - virtual void dump(std::ostream& str) const override; - virtual bool isCompound() const override { return false; } // Because don't support unpacked + const char* broken() const override; + void dump(std::ostream& str) const override; + bool isCompound() const override { return false; } // Because don't support unpacked // For basicp() we reuse the size to indicate a "fake" basic type of same size - virtual AstBasicDType* basicp() const override { + AstBasicDType* basicp() const override { return (isFourstate() ? VN_AS(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), BasicDType) : VN_AS(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), BasicDType)); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const override; + int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const override; + int widthTotalBytes() const override; // op1 = members - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { return this == samep; // We don't compare members, require exact equivalence } - virtual string name() const override { return m_name; } - virtual void name(const string& flag) override { m_name = flag; } + string name() const override { return m_name; } + void name(const string& flag) override { m_name = flag; } AstMemberDType* membersp() const { return VN_AS(op1p(), MemberDType); } // op1 = AstMember list @@ -249,7 +247,7 @@ public: // packed() but as don't support unpacked, presently all structs static bool packedUnsup() { return true; } void isFourstate(bool flag) { m_isFourstate = flag; } - virtual bool isFourstate() const override { return m_isFourstate; } + bool isFourstate() const override { return m_isFourstate; } void clearCache() { m_members.clear(); } void repairMemberCache(); AstMemberDType* findMember(const string& name) const { @@ -277,10 +275,10 @@ public: addNOp2p(initp); } ASTGEN_MEMBERS_EnumItem; - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual void name(const string& flag) override { m_name = flag; } + string name() const override { return m_name; } + bool maybePointedTo() const override { return true; } + bool hasDType() const override { return true; } + void name(const string& flag) override { m_name = flag; } AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range for name appending void rangep(AstRange* nodep) { addOp1p((AstNode*)nodep); } AstNode* valuep() const { return op2p(); } // op2 = Value @@ -311,43 +309,41 @@ public: dtypep(dtp); } ASTGEN_MEMBERS_AssocArrayDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists()) || (!m_keyDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); if (m_keyDTypep && m_keyDTypep->clonep()) m_keyDTypep = m_keyDTypep->clonep(); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstAssocArrayDType* const asamep = static_cast(samep); if (!asamep->subDTypep()) return false; if (!asamep->keyDTypep()) return false; return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep()); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* const asamep = static_cast(samep); return type() == samep->type() && asamep->subDTypep() && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } - virtual string prettyDTypeName() const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } - virtual AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); } + string prettyDTypeName() const override; + void dumpSmall(std::ostream& str) const override; + AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - virtual AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; } - virtual void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; } + void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); } // AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); } void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } @@ -355,13 +351,13 @@ public: AstNodeDType* keyChildDTypep() const { return VN_AS(op2p(), NodeDType); } void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); } // METHODS - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } + AstBasicDType* basicp() const override { return nullptr; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + bool isCompound() const override { return true; } }; class AstBasicDType final : public AstNodeDType { // Builtin atomic/vectored data type @@ -404,18 +400,18 @@ private: public: ASTGEN_MEMBERS_BasicDType; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; // width/widthMin/numeric compared elsewhere - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstBasicDType* const sp = static_cast(samep); return m == sp->m; } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { return type() == samep->type() && same(samep); } - virtual string name() const override { return m.m_keyword.ascii(); } - virtual string prettyDTypeName() const override; - virtual const char* broken() const override { + string name() const override { return m.m_keyword.ascii(); } + string prettyDTypeName() const override; + const char* broken() const override { BROKEN_RTN(dtypep() != this); return nullptr; } @@ -430,15 +426,15 @@ public: } } // METHODS - virtual AstBasicDType* basicp() const override { return (AstBasicDType*)this; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + AstBasicDType* basicp() const override { return (AstBasicDType*)this; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const override; + int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const override; - virtual bool isFourstate() const override { return keyword().isFourstate(); } + int widthTotalBytes() const override; + bool isFourstate() const override { return keyword().isFourstate(); } VBasicDTypeKwd keyword() const { // Avoid using - use isSomething accessors instead return m.m_keyword; } @@ -469,7 +465,7 @@ public: bool implicit() const { return keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT; } VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; } void cvtRangeConst(); // Convert to smaller representation - virtual bool isCompound() const override { return isString(); } + bool isCompound() const override { return isString(); } }; class AstBracketArrayDType final : public AstNodeDType { // Associative/Queue/Normal array data type, ie "[dtype_or_expr]" @@ -483,23 +479,23 @@ public: setOp2p(elementsp); // Only for parser } ASTGEN_MEMBERS_BracketArrayDType; - virtual bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } + bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - virtual AstNodeDType* subDTypep() const override { return childDTypep(); } + AstNodeDType* subDTypep() const override { return childDTypep(); } // op2 = Range of variable AstNode* elementsp() const { return op2p(); } // METHODS // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node - virtual bool maybePointedTo() const override { return false; } - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } - virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } - virtual bool isCompound() const override { return true; } + bool maybePointedTo() const override { return false; } + AstBasicDType* basicp() const override { return nullptr; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } + int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } + bool isCompound() const override { return true; } }; class AstClassRefDType final : public AstNodeDType { // Reference to a class @@ -518,31 +514,31 @@ public: // METHODS const char* broken() const override; void cloneRelink() override; - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstClassRefDType* const asamep = static_cast(samep); return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { return this == samep || (type() == samep->type() && same(samep)); } - virtual void dump(std::ostream& str = std::cout) const override; - virtual void dumpSmall(std::ostream& str) const override; + void dump(std::ostream& str = std::cout) const override; + void dumpSmall(std::ostream& str) const override; string name() const override; - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 0; } - virtual int widthTotalBytes() const override { return 0; } - virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } - virtual void virtRefDTypep(AstNodeDType* nodep) override {} - virtual AstNodeDType* subDTypep() const override { return nullptr; } + AstBasicDType* basicp() const override { return nullptr; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return 0; } + int widthTotalBytes() const override { return 0; } + AstNodeDType* virtRefDTypep() const override { return nullptr; } + void virtRefDTypep(AstNodeDType* nodep) override {} + AstNodeDType* subDTypep() const override { return nullptr; } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } AstClass* classp() const { return m_classp; } void classp(AstClass* nodep) { m_classp = nodep; } AstPin* paramsp() const { return VN_AS(op4p(), Pin); } - virtual bool isCompound() const override { return true; } + bool isCompound() const override { return true; } }; class AstConstDType final : public AstNodeDType { // const data type, ie "const some_dtype var_name [2:0]" @@ -559,39 +555,37 @@ public: widthFromSub(subDTypep()); } ASTGEN_MEMBERS_ConstDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstConstDType* const sp = static_cast(samep); return (m_refDTypep == sp->m_refDTypep); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { return skipRefp()->similarDType(samep->skipRefp()); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + bool isCompound() const override { v3fatalSrc("call isCompound on subdata type, not reference"); return false; } @@ -618,33 +612,31 @@ public: } ASTGEN_MEMBERS_DefImplicitDType; int uniqueNum() const { return m_uniqueNum; } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstDefImplicitDType* const sp = static_cast(samep); return uniqueNum() == sp->uniqueNum(); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { return type() == samep->type() && same(samep); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return dtypep() ? dtypep() : childDTypep(); - } + AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); } void* containerp() const { return m_containerp; } // METHODS // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } - virtual string name() const override { return m_name; } - virtual void name(const string& flag) override { m_name = flag; } - virtual bool isCompound() const override { return false; } + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } + string name() const override { return m_name; } + void name(const string& flag) override { m_name = flag; } + bool isCompound() const override { return false; } }; class AstDynArrayDType final : public AstNodeDType { // Dynamic array data type, ie "[]" @@ -664,44 +656,42 @@ public: dtypep(nullptr); // V3Width will resolve } ASTGEN_MEMBERS_DynArrayDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstAssocArrayDType* const asamep = static_cast(samep); if (!asamep->subDTypep()) return false; return subDTypep() == asamep->subDTypep(); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* const asamep = static_cast(samep); return type() == samep->type() && asamep->subDTypep() && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } - virtual string prettyDTypeName() const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + string prettyDTypeName() const override; + void dumpSmall(std::ostream& str) const override; + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } + AstBasicDType* basicp() const override { return nullptr; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + bool isCompound() const override { return true; } }; class AstEmptyQueueDType final : public AstNodeDType { // For EmptyQueue @@ -711,24 +701,24 @@ public: dtypep(this); } ASTGEN_MEMBERS_EmptyQueueDType; - virtual void dumpSmall(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual bool undead() const override { return true; } - virtual AstNodeDType* subDTypep() const override { return nullptr; } - virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } - virtual void virtRefDTypep(AstNodeDType* nodep) override {} - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstBasicDType* basicp() const override { return nullptr; } + void dumpSmall(std::ostream& str) const override; + bool hasDType() const override { return true; } + bool maybePointedTo() const override { return true; } + bool undead() const override { return true; } + AstNodeDType* subDTypep() const override { return nullptr; } + AstNodeDType* virtRefDTypep() const override { return nullptr; } + void virtRefDTypep(AstNodeDType* nodep) override {} + bool similarDType(AstNodeDType* samep) const override { return this == samep; } + AstBasicDType* basicp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 1; } - virtual int widthTotalBytes() const override { return 1; } - virtual bool isCompound() const override { return false; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return 1; } + int widthTotalBytes() const override { return 1; } + bool isCompound() const override { return false; } }; class AstEnumDType final : public AstNodeDType { // Parents: TYPEDEF/MODULE @@ -749,49 +739,45 @@ public: widthFromSub(subDTypep()); } ASTGEN_MEMBERS_EnumDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } int uniqueNum() const { return m_uniqueNum; } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstEnumDType* const sp = static_cast(samep); return uniqueNum() == sp->uniqueNum(); } - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + bool similarDType(AstNodeDType* samep) const override { return this == samep; } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } // op1 = Data type void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } // op1 = Range of variable - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - virtual string name() const override { return m_name; } - virtual void name(const string& flag) override { m_name = flag; } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + string name() const override { return m_name; } + void name(const string& flag) override { m_name = flag; } AstEnumItem* itemsp() const { return VN_AS(op2p(), EnumItem); } // op2 = AstEnumItem's // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { - return subDTypep()->skipRefToConstp(); - } + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } int itemCount() const { size_t count = 0; for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++; return count; } - virtual bool isCompound() const override { return false; } + bool isCompound() const override { return false; } }; class AstIfaceRefDType final : public AstNodeDType { // Reference to an interface, either for a port, or inside parent cell @@ -819,17 +805,17 @@ public: , m_modportName{modport} {} ASTGEN_MEMBERS_IfaceRefDType; // METHODS - virtual const char* broken() const override; - virtual void dump(std::ostream& str = std::cout) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual void cloneRelink() override; - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual int widthAlignBytes() const override { return 1; } - virtual int widthTotalBytes() const override { return 1; } + const char* broken() const override; + void dump(std::ostream& str = std::cout) const override; + void dumpSmall(std::ostream& str) const override; + void cloneRelink() override; + AstBasicDType* basicp() const override { return nullptr; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + bool similarDType(AstNodeDType* samep) const override { return this == samep; } + int widthAlignBytes() const override { return 1; } + int widthTotalBytes() const override { return 1; } FileLine* modportFileline() const { return m_modportFileline; } string cellName() const { return m_cellName; } void cellName(const string& name) { m_cellName = name; } @@ -844,7 +830,7 @@ public: AstModport* modportp() const { return m_modportp; } void modportp(AstModport* modportp) { m_modportp = modportp; } bool isModport() { return !m_modportName.empty(); } - virtual bool isCompound() const override { return true; } // But not relevant + bool isCompound() const override { return true; } // But not relevant }; class AstMemberDType final : public AstNodeDType { // A member of a struct/union @@ -872,49 +858,45 @@ public: widthFromSub(subDTypep()); } ASTGEN_MEMBERS_MemberDType; - virtual string name() const override { return m_name; } // * = Var name - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { + string name() const override { return m_name; } // * = Var name + bool hasDType() const override { return true; } + bool maybePointedTo() const override { return true; } + const char* broken() const override { BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + bool similarDType(AstNodeDType* samep) const override { return this == samep; } // // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { - return subDTypep()->skipRefToConstp(); - } - virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); } + AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } // METHODS - virtual void name(const string& name) override { m_name = name; } - virtual void tag(const string& text) override { m_tag = text; } - virtual string tag() const override { return m_tag; } + void name(const string& name) override { m_name = name; } + void tag(const string& text) override { m_tag = text; } + string tag() const override { return m_tag; } int lsb() const { return m_lsb; } void lsb(int lsb) { m_lsb = lsb; } - virtual bool isCompound() const override { + bool isCompound() const override { v3fatalSrc("call isCompound on subdata type, not reference"); return false; } @@ -935,35 +917,31 @@ public: dtypep(nullptr); // V3Width will resolve } ASTGEN_MEMBERS_ParamTypeDType; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return dtypep() ? dtypep() : childDTypep(); - } - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const override { - return subDTypep()->skipRefToConstp(); - } - virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } - virtual bool similarDType(AstNodeDType* samep) const override { + AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); } + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); } + AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + bool similarDType(AstNodeDType* samep) const override { const AstParamTypeDType* const sp = static_cast(samep); return type() == samep->type() && sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()); } - virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } + int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } // METHODS - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual void name(const string& flag) override { m_name = flag; } + string name() const override { return m_name; } + bool maybePointedTo() const override { return true; } + bool hasDType() const override { return true; } + void name(const string& flag) override { m_name = flag; } VVarType varType() const { return m_varType; } // * = Type of variable bool isParam() const { return true; } bool isGParam() const { return (varType() == VVarType::GPARAM); } - virtual bool isCompound() const override { + bool isCompound() const override { v3fatalSrc("call isCompound on subdata type, not reference"); return false; } @@ -978,16 +956,16 @@ public: ASTGEN_MEMBERS_ParseTypeDType; AstNodeDType* dtypep() const { return nullptr; } // METHODS - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstBasicDType* basicp() const override { return nullptr; } - virtual AstNodeDType* skipRefp() const override { return nullptr; } + bool similarDType(AstNodeDType* samep) const override { return this == samep; } + AstBasicDType* basicp() const override { return nullptr; } + AstNodeDType* skipRefp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 0; } - virtual int widthTotalBytes() const override { return 0; } - virtual bool isCompound() const override { + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return 0; } + int widthTotalBytes() const override { return 0; } + bool isCompound() const override { v3fatalSrc("call isCompound on subdata type, not reference"); return false; } @@ -1012,50 +990,48 @@ public: dtypep(dtp); } ASTGEN_MEMBERS_QueueDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstQueueDType* const asamep = static_cast(samep); if (!asamep->subDTypep()) return false; return (subDTypep() == asamep->subDTypep()); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { const AstQueueDType* const asamep = static_cast(samep); return type() == samep->type() && asamep->subDTypep() && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); } - virtual void dumpSmall(std::ostream& str) const override; - virtual string prettyDTypeName() const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + void dumpSmall(std::ostream& str) const override; + string prettyDTypeName() const override; + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNode* boundp() const { return op2p(); } // op2 = Bound, nullptr = none void boundp(AstNode* nodep) { setNOp2p(nodep); } inline int boundConst() const; - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const override { return nullptr; } + AstBasicDType* basicp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + bool isCompound() const override { return true; } }; class AstRefDType final : public AstNodeDType { private: @@ -1085,24 +1061,24 @@ public: // METHODS const char* broken() const override; void cloneRelink() override; - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstRefDType* const asamep = static_cast(samep); return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep && m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep); } - virtual bool similarDType(AstNodeDType* samep) const override { + bool similarDType(AstNodeDType* samep) const override { return skipRefp()->similarDType(samep->skipRefp()); } - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } - virtual string prettyDTypeName() const override { + void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } + string prettyDTypeName() const override { return subDTypep() ? subDTypep()->name() : prettyName(); } - virtual AstBasicDType* basicp() const override { + AstBasicDType* basicp() const override { return subDTypep() ? subDTypep()->basicp() : nullptr; } AstNodeDType* subDTypep() const override; - virtual AstNodeDType* skipRefp() const override { + AstNodeDType* skipRefp() const override { // Skip past both the Ref and the Typedef if (subDTypep()) { return subDTypep()->skipRefp(); @@ -1111,7 +1087,7 @@ public: return nullptr; } } - virtual AstNodeDType* skipRefToConstp() const override { + AstNodeDType* skipRefToConstp() const override { if (subDTypep()) { return subDTypep()->skipRefToConstp(); } else { @@ -1119,7 +1095,7 @@ public: return nullptr; } } - virtual AstNodeDType* skipRefToEnump() const override { + AstNodeDType* skipRefToEnump() const override { if (subDTypep()) { return subDTypep()->skipRefToEnump(); } else { @@ -1127,23 +1103,23 @@ public: return nullptr; } } - virtual int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } - virtual void name(const string& flag) override { m_name = flag; } + int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } + int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } + void name(const string& flag) override { m_name = flag; } // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } AstTypedef* typedefp() const { return m_typedefp; } void typedefp(AstTypedef* nodep) { m_typedefp = nodep; } AstNodeDType* refDTypep() const { return m_refDTypep; } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return refDTypep(); } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return refDTypep(); } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } AstNode* typeofp() const { return op2p(); } AstNode* classOrPackageOpp() const { return op3p(); } AstPin* paramsp() const { return VN_AS(op4p(), Pin); } - virtual bool isCompound() const override { + bool isCompound() const override { v3fatalSrc("call isCompound on subdata type, not reference"); return false; } @@ -1161,35 +1137,33 @@ public: dtypep(nullptr); // V3Width will resolve } ASTGEN_MEMBERS_UnsizedArrayDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } bool same(const AstNode* samep) const override; bool similarDType(AstNodeDType* samep) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + void dumpSmall(std::ostream& str) const override; + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } - virtual bool isCompound() const override { return true; } + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } + bool isCompound() const override { return true; } }; class AstVoidDType final : public AstNodeDType { // For e.g. a function returning void @@ -1199,24 +1173,24 @@ public: dtypep(this); } ASTGEN_MEMBERS_VoidDType; - virtual void dumpSmall(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual bool undead() const override { return true; } - virtual AstNodeDType* subDTypep() const override { return nullptr; } - virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } - virtual void virtRefDTypep(AstNodeDType* nodep) override {} - virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } - virtual AstBasicDType* basicp() const override { return nullptr; } + void dumpSmall(std::ostream& str) const override; + bool hasDType() const override { return true; } + bool maybePointedTo() const override { return true; } + bool undead() const override { return true; } + AstNodeDType* subDTypep() const override { return nullptr; } + AstNodeDType* virtRefDTypep() const override { return nullptr; } + void virtRefDTypep(AstNodeDType* nodep) override {} + bool similarDType(AstNodeDType* samep) const override { return this == samep; } + AstBasicDType* basicp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { return 1; } - virtual int widthTotalBytes() const override { return 1; } - virtual bool isCompound() const override { return false; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return 1; } + int widthTotalBytes() const override { return 1; } + bool isCompound() const override { return false; } }; class AstWildcardArrayDType final : public AstNodeDType { // Wildcard index type associative array data type, ie "some_dtype var_name [*]" @@ -1231,39 +1205,33 @@ public: dtypep(nullptr); // V3Width will resolve } ASTGEN_MEMBERS_WildcardArrayDType; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } bool same(const AstNode* samep) const override; bool similarDType(AstNodeDType* samep) const override; - virtual void dumpSmall(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + void dumpSmall(std::ostream& str) const override; + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const override { - return m_refDTypep ? m_refDTypep : childDTypep(); - } + AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const override { - return sizeof(std::map); - } - virtual int widthTotalBytes() const override { - return sizeof(std::map); - } - virtual bool isCompound() const override { return true; } + AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + int widthAlignBytes() const override { return sizeof(std::map); } + int widthTotalBytes() const override { return sizeof(std::map); } + bool isCompound() const override { return true; } }; // === AstNodeArrayDType === @@ -1275,8 +1243,8 @@ public: inline AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep); inline AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep); ASTGEN_MEMBERS_PackArrayDType; - virtual string prettyDTypeName() const override; - virtual bool isCompound() const override { return false; } + string prettyDTypeName() const override; + bool isCompound() const override { return false; } }; class AstUnpackArrayDType final : public AstNodeArrayDType { // Array data type, ie "some_dtype var_name [2:0]" @@ -1304,15 +1272,15 @@ public: widthFromSub(subDTypep()); } ASTGEN_MEMBERS_UnpackArrayDType; - virtual string prettyDTypeName() const override; - virtual bool same(const AstNode* samep) const override { + string prettyDTypeName() const override; + bool same(const AstNode* samep) const override { const AstUnpackArrayDType* const sp = static_cast(samep); return m_isCompound == sp->m_isCompound; } // Outer dimension comes first. The first element is this node. std::vector unpackDimensions(); void isCompound(bool flag) { m_isCompound = flag; } - virtual bool isCompound() const override { return m_isCompound; } + bool isCompound() const override { return m_isCompound; } }; // === AstNodeUOrStructDType === @@ -1322,7 +1290,7 @@ public: AstStructDType(FileLine* fl, VSigning numericUnpack) : ASTGEN_SUPER_StructDType(fl, numericUnpack) {} ASTGEN_MEMBERS_StructDType; - virtual string verilogKwd() const override { return "struct"; } + string verilogKwd() const override { return "struct"; } }; class AstUnionDType final : public AstNodeUOrStructDType { public: @@ -1331,7 +1299,7 @@ public: AstUnionDType(FileLine* fl, VSigning numericUnpack) : ASTGEN_SUPER_UnionDType(fl, numericUnpack) {} ASTGEN_MEMBERS_UnionDType; - virtual string verilogKwd() const override { return "union"; } + string verilogKwd() const override { return "union"; } }; #endif // Guard diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index 78360c3c2..498fbce3b 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -46,8 +46,8 @@ protected: public: ASTGEN_MEMBERS_NodeMath; // METHODS - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } + void dump(std::ostream& str) const override; + bool hasDType() const override { return true; } virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV // For documentation on emitC format see EmitCFunc::emitOpName virtual string emitC() = 0; @@ -87,8 +87,8 @@ public: // Signed flavor of nodes with both flavors? virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode*) const override { return true; } }; class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop { // Binary math with commutative properties @@ -123,7 +123,7 @@ public: AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression void bitp(AstNode* nodep) { setOp2p(nodep); } int bitConst() const; - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } }; class AstNodeStream VL_NOT_FINAL : public AstNodeBiop { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() @@ -143,13 +143,13 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_NodeSystemBiop; - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } - virtual bool doubleFlavor() const override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } + bool doubleFlavor() const override { return true; } }; class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath { // Quaternary math @@ -185,8 +185,8 @@ public: virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode*) const override { return true; } }; class AstNodeTermop VL_NOT_FINAL : public AstNodeMath { // Terminal operator -- a operator with no "inputs" @@ -200,7 +200,7 @@ public: // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst void iterateChildren(VNVisitor& v) {} - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; }; class AstNodeTriop VL_NOT_FINAL : public AstNodeMath { // Trinary math @@ -221,7 +221,7 @@ public: void rhsp(AstNode* nodep) { return setOp2p(nodep); } void thsp(AstNode* nodep) { return setOp3p(nodep); } // METHODS - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; // Set out to evaluation of a AstConst'ed virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) @@ -232,8 +232,8 @@ public: virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode*) const override { return true; } }; class AstNodeCond VL_NOT_FINAL : public AstNodeTriop { protected: @@ -248,21 +248,21 @@ protected: public: ASTGEN_MEMBERS_NodeCond; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override; + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override; AstNode* condp() const { return op1p(); } // op1 = Condition AstNode* expr1p() const { return op2p(); } // op2 = If true... AstNode* expr2p() const { return op3p(); } // op3 = If false... - virtual string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; } - virtual string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; } - virtual bool cleanOut() const override { return false; } // clean if e1 & e2 clean - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } // Propagates up - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; } + string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; } + bool cleanOut() const override { return false; } // clean if e1 & e2 clean + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return false; } + bool cleanThs() const override { return false; } // Propagates up + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool sizeMattersThs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_BRANCH; } virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0; }; class AstNodeUniop VL_NOT_FINAL : public AstNodeMath { @@ -279,7 +279,7 @@ public: AstNode* lhsp() const { return op1p(); } void lhsp(AstNode* nodep) { return setOp1p(nodep); } // METHODS - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; // Set out to evaluation of a AstConst'ed lhs virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; virtual bool cleanLhs() const = 0; @@ -288,8 +288,8 @@ public: // Signed flavor of nodes with both flavors? virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode*) const override { return true; } }; class AstNodeSystemUniop VL_NOT_FINAL : public AstNodeUniop { public: @@ -298,11 +298,11 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_NodeSystemUniop; - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } - virtual bool doubleFlavor() const override { return true; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL_TRIG; } + bool doubleFlavor() const override { return true; } }; class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath { // An AstVarRef or AstVarXRef @@ -331,13 +331,13 @@ protected: public: ASTGEN_MEMBERS_NodeVarRef; - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } - virtual const char* broken() const override; - virtual int instrCount() const override { return widthInstrs(); } - virtual void cloneRelink() override; - virtual string name() const override { return m_name; } // * = Var name - virtual void name(const string& name) override { m_name = name; } + void dump(std::ostream& str) const override; + bool hasDType() const override { return true; } + const char* broken() const override; + int instrCount() const override { return widthInstrs(); } + void cloneRelink() override; + string name() const override { return m_name; } // * = Var name + void name(const string& name) override { m_name = name; } VAccess access() const { return m_access; } void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -372,11 +372,11 @@ public: public: ASTGEN_MEMBERS_AddrOfCFunc; - virtual void cloneRelink() override; - virtual const char* broken() const override; - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } + void cloneRelink() override; + const char* broken() const override; + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } AstCFunc* funcp() const { return m_funcp; } }; class AstCMath final : public AstNodeMath { @@ -394,12 +394,12 @@ public: } inline AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true); ASTGEN_MEMBERS_CMath; - virtual bool isGateOptimizable() const override { return m_pure; } - virtual bool isPredictOptimizable() const override { return m_pure; } - virtual bool cleanOut() const override { return m_cleanOut; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return m_pure; } + bool isPredictOptimizable() const override { return m_pure; } + bool cleanOut() const override { return m_cleanOut; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool same(const AstNode* /*samep*/) const override { return true; } void addBodysp(AstNode* nodep) { addNOp1p(nodep); } AstNode* bodysp() const { return op1p(); } // op1 = expressions to print bool pure() const { return m_pure; } @@ -415,13 +415,13 @@ public: setNOp1p(defaultp); } ASTGEN_MEMBERS_ConsAssoc; - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "'{}"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* defaultp() const { return op1p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConsDynArray final : public AstNodeMath { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} @@ -434,14 +434,14 @@ public: setNOp2p(rhsp); } ASTGEN_MEMBERS_ConsDynArray; - virtual string emitVerilog() override { return "'{%l, %r}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "'{%l, %r}"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* lhsp() const { return op1p(); } // op1 = expression AstNode* rhsp() const { return op2p(); } // op2 = expression - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConsQueue final : public AstNodeMath { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} @@ -454,14 +454,14 @@ public: setNOp2p(rhsp); } ASTGEN_MEMBERS_ConsQueue; - virtual string emitVerilog() override { return "'{%l, %r}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "'{%l, %r}"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* lhsp() const { return op1p(); } // op1 = expression AstNode* rhsp() const { return op2p(); } // op2 = expression - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConsWildcard final : public AstNodeMath { // Construct a wildcard assoc array and return object, '{} @@ -473,13 +473,13 @@ public: setNOp1p(defaultp); } ASTGEN_MEMBERS_ConsWildcard; - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "'{}"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* defaultp() const { return op1p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConst final : public AstNodeMath { // A constant @@ -595,20 +595,20 @@ public: initWithNumber(); } ASTGEN_MEMBERS_Const; - virtual string name() const override { return num().ascii(); } // * = Value + string name() const override { return num().ascii(); } // * = Value const V3Number& num() const { return m_num; } // * = Value V3Number& num() { return m_num; } // * = Value uint32_t toUInt() const { return num().toUInt(); } int32_t toSInt() const { return num().toSInt(); } uint64_t toUQuad() const { return num().toUQuad(); } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* samep) const override { + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool same(const AstNode* samep) const override { const AstConst* const sp = static_cast(samep); return num().isCaseEq(sp->num()); } - virtual int instrCount() const override { return widthInstrs(); } + int instrCount() const override { return widthInstrs(); } bool isEqAllOnes() const { return num().isEqAllOnes(width()); } bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); } // Parse string and create appropriate type of AstConst. @@ -620,10 +620,10 @@ public: explicit AstEmptyQueue(FileLine* fl) : ASTGEN_SUPER_EmptyQueue(fl) {} ASTGEN_MEMBERS_EmptyQueue; - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitVerilog() override { return "{}"; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool cleanOut() const override { return true; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitVerilog() override { return "{}"; } + bool same(const AstNode* /*samep*/) const override { return true; } + bool cleanOut() const override { return true; } }; class AstEnumItemRef final : public AstNodeMath { private: @@ -637,21 +637,21 @@ public: dtypeFrom(m_itemp); } ASTGEN_MEMBERS_EnumItemRef; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return itemp()->name(); } - virtual int instrCount() const override { return 0; } + void dump(std::ostream& str) const override; + string name() const override { return itemp()->name(); } + int instrCount() const override { return 0; } const char* broken() const override; - virtual void cloneRelink() override { + void cloneRelink() override { if (m_itemp->clonep()) m_itemp = m_itemp->clonep(); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstEnumItemRef* const sp = static_cast(samep); return itemp() == sp->itemp(); } AstEnumItem* itemp() const { return m_itemp; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } }; @@ -672,10 +672,10 @@ public: void addStmtsp(AstNode* nodep) { addOp1p(nodep); } AstNode* resultp() const { return op2p(); } // METHODS - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode*) const override { return true; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool same(const AstNode*) const override { return true; } }; class AstFError final : public AstNodeMath { public: @@ -685,20 +685,18 @@ public: setOp2p(strp); } ASTGEN_MEMBERS_FError; - virtual string emitVerilog() override { return "%f$ferror(%l, %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } + string emitVerilog() override { return "%f$ferror(%l, %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering + int instrCount() const override { return widthInstrs() * 64; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering void filep(AstNode* nodep) { setOp1p(nodep); } AstNode* filep() const { return op1p(); } void strp(AstNode* nodep) { setOp2p(nodep); } AstNode* strp() const { return op2p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstFRead final : public AstNodeMath { // Parents: expr @@ -715,15 +713,15 @@ public: setNOp4p(countp); } ASTGEN_MEMBERS_FRead; - virtual string verilogKwd() const override { return "$fread"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$fread"; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: makes output + bool cleanOut() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* memp() const { return op1p(); } void memp(AstNode* nodep) { setOp1p(nodep); } AstNode* filep() const { return op2p(); } @@ -742,16 +740,16 @@ public: setNOp2p(filep); } ASTGEN_MEMBERS_FRewind; - virtual string verilogKwd() const override { return "$frewind"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$frewind"; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool cleanOut() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; @@ -770,16 +768,16 @@ public: setNOp2p(filep); } ASTGEN_MEMBERS_FScanF; - virtual string name() const override { return m_text; } - virtual string verilogKwd() const override { return "$fscanf"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* samep) const override { + string name() const override { return m_text; } + string verilogKwd() const override { return "$fscanf"; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: makes output + bool cleanOut() const override { return false; } + bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output @@ -802,15 +800,15 @@ public: setNOp4p(operation); } ASTGEN_MEMBERS_FSeek; - virtual string verilogKwd() const override { return "$fseek"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$fseek"; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: makes output + bool cleanOut() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNode* nodep) { setOp2p(nodep); } AstNode* offset() const { return op3p(); } @@ -827,16 +825,16 @@ public: setNOp2p(filep); } ASTGEN_MEMBERS_FTell; - virtual string verilogKwd() const override { return "$ftell"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$ftell"; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool cleanOut() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; @@ -850,15 +848,15 @@ public: addOp1p(exprp); } ASTGEN_MEMBERS_Fell; - virtual string emitVerilog() override { return "$fell(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "$fell(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstGatePin final : public AstNodeMath { // Possibly expand a gate primitive input pin value to match the range of the gate primitive @@ -869,9 +867,9 @@ public: setOp2p((AstNode*)rangep); } ASTGEN_MEMBERS_GatePin; - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } + string emitVerilog() override { return "%l"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } AstNode* exprp() const { return op1p(); } // op1 = Pin expression AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Range of pin }; @@ -886,18 +884,18 @@ public: setOp2p(rhs); } ASTGEN_MEMBERS_Implication; - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs(); } AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } void lhsp(AstNode* nodep) { return setOp1p(nodep); } void rhsp(AstNode* nodep) { return setOp2p(nodep); } AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain void sentreep(AstSenTree* sentreep) { addOp4p((AstNode*)sentreep); } // op4 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstInside final : public AstNodeMath { public: @@ -911,9 +909,9 @@ public: AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with // op2 = RHS, possibly a list of expr or AstInsideRange AstNode* itemsp() const { return op2p(); } - virtual string emitVerilog() override { return "%l inside { %r }"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } // NA + string emitVerilog() override { return "%l inside { %r }"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } // NA }; class AstInsideRange final : public AstNodeMath { public: @@ -925,9 +923,9 @@ public: ASTGEN_MEMBERS_InsideRange; AstNode* lhsp() const { return op1p(); } // op1 = LHS AstNode* rhsp() const { return op2p(); } // op2 = RHS - virtual string emitVerilog() override { return "[%l:%r]"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } // NA + string emitVerilog() override { return "[%l:%r]"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } // NA // Create AstAnd(AstGte(...), AstLte(...)) AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp); }; @@ -945,14 +943,14 @@ public: , m_name{name} , m_index(index) {} ASTGEN_MEMBERS_LambdaArgRef; - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual string emitVerilog() override { return name(); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - virtual string name() const override { return m_name; } // * = Var name - virtual void name(const string& name) override { m_name = name; } + bool same(const AstNode* /*samep*/) const override { return true; } + string emitVerilog() override { return name(); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool hasDType() const override { return true; } + int instrCount() const override { return widthInstrs(); } + string name() const override { return m_name; } // * = Var name + void name(const string& name) override { m_name = name; } bool index() const { return m_index; } }; class AstMemberSel final : public AstNodeMath { @@ -978,15 +976,13 @@ public: ASTGEN_MEMBERS_MemberSel; void cloneRelink() override; const char* broken() const override; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return true; - } // dtype comparison does it - virtual int instrCount() const override { return widthInstrs(); } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool same(const AstNode* samep) const override { return true; } // dtype comparison does it + int instrCount() const override { return widthInstrs(); } AstNode* fromp() const { return op1p(); } // op1 = Extracting what (nullptr=TBD during parsing) @@ -1005,11 +1001,11 @@ public: setNOp1p(rhsp); } ASTGEN_MEMBERS_NewCopy; - virtual string emitVerilog() override { return "new"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "new"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* rhsp() const { return op1p(); } }; class AstNewDynamic final : public AstNodeMath { @@ -1024,11 +1020,11 @@ public: setNOp2p(rhsp); } ASTGEN_MEMBERS_NewDynamic; - virtual string emitVerilog() override { return "new"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "new"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* sizep() const { return op1p(); } AstNode* rhsp() const { return op2p(); } }; @@ -1043,16 +1039,16 @@ public: addNOp2p(ticksp); } ASTGEN_MEMBERS_Past; - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstNode* ticksp() const { return op2p(); } // op2 = ticks or nullptr means 1 AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain void sentreep(AstSenTree* sentreep) { addOp4p((AstNode*)sentreep); } // op4 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstPatMember final : public AstNodeMath { // Verilog '{a} or '{a{b}} @@ -1067,12 +1063,12 @@ public: addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); } ASTGEN_MEMBERS_PatMember; - virtual string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs() * 2; } - virtual void dump(std::ostream& str = std::cout) const override; + string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs() * 2; } + void dump(std::ostream& str = std::cout) const override; // op1 = expression to assign or another AstPattern (list if replicated) AstNode* lhssp() const { return op1p(); } AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) @@ -1090,12 +1086,12 @@ public: addNOp2p(itemsp); } ASTGEN_MEMBERS_Pattern; - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } @@ -1122,22 +1118,22 @@ public: setNOp1p(seedp); } ASTGEN_MEMBERS_Rand; - virtual string emitVerilog() override { + string emitVerilog() override { return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)") : (m_urandom ? "%f$urandom()" : "%f$random()"); } - virtual string emitC() override { + string emitC() override { return m_reset ? "VL_RAND_RESET_%nq(%nw, %P)" : seedp() ? (urandom() ? "VL_URANDOM_SEEDED_%nq%lq(%li)" : "VL_RANDOM_SEEDED_%nq%lq(%li)") : isWide() ? "VL_RANDOM_%nq(%nw, %P)" // : "VL_RANDOM_%nq()"; } - virtual bool cleanOut() const override { return false; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool cleanOut() const override { return false; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_PLI; } + bool same(const AstNode* /*samep*/) const override { return true; } bool combinable(const AstRand* samep) const { return !seedp() && !samep->seedp() && reset() == samep->reset() && urandom() == samep->urandom(); @@ -1156,15 +1152,15 @@ public: addOp1p(exprp); } ASTGEN_MEMBERS_Rose; - virtual string emitVerilog() override { return "$rose(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "$rose(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstSScanF final : public AstNodeMath { // Parents: expr @@ -1181,16 +1177,16 @@ public: setOp2p(fromp); } ASTGEN_MEMBERS_SScanF; - virtual string name() const override { return m_text; } - virtual string verilogKwd() const override { return "$sscanf"; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: makes output - virtual bool cleanOut() const override { return false; } - virtual bool same(const AstNode* samep) const override { + string name() const override { return m_text; } + string verilogKwd() const override { return "$sscanf"; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: makes output + bool cleanOut() const override { return false; } + bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output @@ -1210,13 +1206,13 @@ public: addOp1p(exprp); } ASTGEN_MEMBERS_Sampled; - virtual string emitVerilog() override { return "$sampled(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return 0; } + string emitVerilog() override { return "$sampled(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return 0; } AstNode* exprp() const { return op1p(); } // op1 = expression - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstScopeName final : public AstNodeMath { // For display %m and DPI context imports @@ -1236,14 +1232,14 @@ public: dtypeSetUInt64(); } ASTGEN_MEMBERS_ScopeName; - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { return (m_dpiExport == static_cast(samep)->m_dpiExport && m_forFormat == static_cast(samep)->m_forFormat); } - virtual string emitVerilog() override { return ""; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; + string emitVerilog() override { return ""; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + void dump(std::ostream& str = std::cout) const override; AstText* scopeAttrp() const { return VN_AS(op1p(), Text); } void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } AstText* scopeEntrp() const { return VN_AS(op2p(), Text); } @@ -1276,15 +1272,15 @@ public: setOp3p(valuep); } ASTGEN_MEMBERS_SetAssoc; - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "'{}"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* lhsp() const { return op1p(); } AstNode* keyp() const { return op2p(); } AstNode* valuep() const { return op3p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstSetWildcard final : public AstNodeMath { // Set a wildcard assoc array element and return object, '{} @@ -1298,15 +1294,15 @@ public: setOp3p(valuep); } ASTGEN_MEMBERS_SetWildcard; - virtual string emitVerilog() override { return "'{}"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "'{}"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } AstNode* lhsp() const { return op1p(); } AstNode* keyp() const { return op2p(); } AstNode* valuep() const { return op3p(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstStable final : public AstNodeMath { // Verilog $stable @@ -1318,15 +1314,15 @@ public: addOp1p(exprp); } ASTGEN_MEMBERS_Stable; - virtual string emitVerilog() override { return "$stable(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "$stable(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstSystemF final : public AstNodeMath { // $system used as function @@ -1336,16 +1332,16 @@ public: setOp1p(lhsp); } ASTGEN_MEMBERS_SystemF; - virtual string verilogKwd() const override { return "$system"; } - virtual string emitVerilog() override { return verilogKwd(); } - virtual string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$system"; } + string emitVerilog() override { return verilogKwd(); } + string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool cleanOut() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* lhsp() const { return op1p(); } }; class AstTestPlusArgs final : public AstNodeMath { @@ -1357,13 +1353,13 @@ public: setOp1p(searchp); } ASTGEN_MEMBERS_TestPlusArgs; - virtual string verilogKwd() const override { return "$test$plusargs"; } - virtual string emitVerilog() override { return verilogKwd(); } - virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$test$plusargs"; } + string emitVerilog() override { return verilogKwd(); } + string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool cleanOut() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* searchp() const { return op1p(); } // op1 = Search expression void searchp(AstNode* nodep) { setOp1p(nodep); } }; @@ -1376,17 +1372,17 @@ public: addNOp1p(exprsp); } ASTGEN_MEMBERS_UCFunc; - virtual bool cleanOut() const override { return false; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isSubstOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isSubstOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_PLI; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstUnbounded final : public AstNodeMath { // A $ in the parser, used for unbounded and queues @@ -1397,9 +1393,9 @@ public: dtypeSetSigned32(); } ASTGEN_MEMBERS_Unbounded; - virtual string emitVerilog() override { return "$"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } + string emitVerilog() override { return "$"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } }; class AstValuePlusArgs final : public AstNodeMath { // Parents: expr @@ -1411,14 +1407,14 @@ public: setOp2p(outp); } ASTGEN_MEMBERS_ValuePlusArgs; - virtual string verilogKwd() const override { return "$value$plusargs"; } - virtual string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return !outp(); } - virtual bool cleanOut() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$value$plusargs"; } + string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return !outp(); } + bool cleanOut() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* searchp() const { return op1p(); } // op1 = Search expression void searchp(AstNode* nodep) { setOp1p(nodep); } AstNode* outp() const { return op2p(); } // op2 = Expressions to output @@ -1436,20 +1432,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_BufIf1; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstBufIf1(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opBufIf1(lhs, rhs); } - virtual string emitVerilog() override { return "bufif(%r,%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "bufif(%r,%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstCastDynamic final : public AstNodeBiop { // Verilog $cast used as a function @@ -1463,21 +1459,21 @@ public: AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_CastDynamic; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstCastDynamic(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() override { return "%f$cast(%r, %l)"; } - virtual string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 20; } - virtual bool isPure() const override { return true; } + string emitVerilog() override { return "%f$cast(%r, %l)"; } + string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 20; } + bool isPure() const override { return true; } AstNode* fromp() const { return lhsp(); } AstNode* top() const { return rhsp(); } }; @@ -1492,25 +1488,25 @@ public: dtypeSetUInt32(); } ASTGEN_MEMBERS_CompareNN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCompareNN(lhs, rhs, m_ignoreCase); } - virtual string name() const override { return m_ignoreCase ? "icompare" : "compare"; } - virtual string emitVerilog() override { + string name() const override { return m_ignoreCase ? "icompare" : "compare"; } + string emitVerilog() override { return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))"; } - virtual string emitC() override { + string emitC() override { return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstConcat final : public AstNodeBiop { // If you're looking for {#{}}, see AstReplicate @@ -1523,20 +1519,20 @@ public: } } ASTGEN_MEMBERS_Concat; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstConcat(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() override { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + string emitVerilog() override { return "%f{%l, %k%r}"; } + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opConcat(lhs, rhs); } - virtual string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } + string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 2; } }; class AstConcatN final : public AstNodeBiop { // String concatenate @@ -1546,21 +1542,21 @@ public: dtypeSetString(); } ASTGEN_MEMBERS_ConcatN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstConcatN(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() override { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + string emitVerilog() override { return "%f{%l, %k%r}"; } + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opConcatN(lhs, rhs); } - virtual string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; class AstDiv final : public AstNodeBiop { public: @@ -1569,20 +1565,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Div; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDiv(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opDiv(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } - virtual string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } + string emitVerilog() override { return "%k(%l %f/ %r)"; } + string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } }; class AstDivD final : public AstNodeBiop { public: @@ -1591,22 +1587,22 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_DivD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDivD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opDivD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "/"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f/ %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "/"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL_DIV; } + bool doubleFlavor() const override { return true; } }; class AstDivS final : public AstNodeBiop { public: @@ -1615,21 +1611,21 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_DivS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDivS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opDivS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } - virtual string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f/ %r)"; } + string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } + bool signedFlavor() const override { return true; } }; class AstEqWild final : public AstNodeBiop { // Note wildcard operator rhs differs from lhs @@ -1639,45 +1635,45 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_EqWild; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqWild(this->fileline(), lhsp, rhsp); } static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEqWild/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opWildEq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f==? %r)"; } - virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f==? %r)"; } + string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "=="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstFGetS final : public AstNodeBiop { public: AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_FGetS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstFGetS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$fgets(%l,%r)"; } - virtual string emitC() override { + string emitVerilog() override { return "%f$fgets(%l,%r)"; } + string emitC() override { return strgp()->dtypep()->basicp()->isString() ? "VL_FGETS_NI(%li, %ri)" : "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 64; } AstNode* strgp() const { return lhsp(); } AstNode* filep() const { return rhsp(); } }; @@ -1686,26 +1682,24 @@ public: AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_FUngetC; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstFUngetC(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() override { return "%f$ungetc(%r, %l)"; } + string emitVerilog() override { return "%f$ungetc(%r, %l)"; } // Non-existent filehandle returns EOF - virtual string emitC() override { + string emitC() override { return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 64; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } AstNode* charp() const { return rhsp(); } }; @@ -1717,21 +1711,21 @@ public: dtypeSetBitSized(8, VSigning::UNSIGNED); } ASTGEN_MEMBERS_GetcN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGetcN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGetcN(lhs, rhs); } - virtual string name() const override { return "getc"; } - virtual string emitVerilog() override { return "%k(%l.getc(%r))"; } - virtual string emitC() override { return "VL_GETC_N(%li,%ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string name() const override { return "getc"; } + string emitVerilog() override { return "%k(%l.getc(%r))"; } + string emitC() override { return "VL_GETC_N(%li,%ri)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstGetcRefN final : public AstNodeBiop { // Verilog string[#] on the left-hand-side of assignment @@ -1742,20 +1736,20 @@ public: dtypeSetBitSized(8, VSigning::UNSIGNED); } ASTGEN_MEMBERS_GetcRefN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGetcRefN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%k%l[%r]"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k%l[%r]"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstGt final : public AstNodeBiop { public: @@ -1764,20 +1758,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_Gt; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGt(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGt(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ">"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f> %r)"; } + string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ">"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstGtD final : public AstNodeBiop { public: @@ -1786,22 +1780,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_GtD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGtD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f> %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return ">"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstGtN final : public AstNodeBiop { public: @@ -1810,22 +1804,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_GtN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGtN(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f> %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return ">"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; class AstGtS final : public AstNodeBiop { public: @@ -1834,21 +1828,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_GtS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGtS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f> %r)"; } - virtual string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f> %r)"; } + string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool signedFlavor() const override { return true; } }; class AstGte final : public AstNodeBiop { public: @@ -1857,20 +1851,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_Gte; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGte(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGte(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ">="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f>= %r)"; } + string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ">="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstGteD final : public AstNodeBiop { public: @@ -1879,22 +1873,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_GteD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGteD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f>= %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return ">="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstGteN final : public AstNodeBiop { public: @@ -1903,22 +1897,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_GteN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGteN(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return ">="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f>= %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return ">="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; class AstGteS final : public AstNodeBiop { public: @@ -1927,21 +1921,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_GteS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGteS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } - virtual string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f>= %r)"; } + string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool signedFlavor() const override { return true; } }; class AstLogAnd final : public AstNodeBiop { public: @@ -1950,21 +1944,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LogAnd; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogAnd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogAnd(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f&& %r)"; } - virtual string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "&&"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + string emitVerilog() override { return "%k(%l %f&& %r)"; } + string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "&&"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } }; class AstLogIf final : public AstNodeBiop { public: @@ -1973,21 +1967,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LogIf; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogIf(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogIf(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f-> %r)"; } - virtual string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "->"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + string emitVerilog() override { return "%k(%l %f-> %r)"; } + string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "->"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } }; class AstLogOr final : public AstNodeBiop { // LOGOR with optional side effects @@ -2001,27 +1995,27 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LogOr; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogOr(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogOr(lhs, rhs); } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstLogOr* const sp = static_cast(samep); return m_sideEffect == sp->m_sideEffect; } - virtual void dump(std::ostream& str = std::cout) const override; - virtual string emitVerilog() override { return "%k(%l %f|| %r)"; } - virtual string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "||"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } - virtual bool isPure() const override { return !m_sideEffect; } + void dump(std::ostream& str = std::cout) const override; + string emitVerilog() override { return "%k(%l %f|| %r)"; } + string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "||"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + bool isPure() const override { return !m_sideEffect; } void sideEffect(bool flag) { m_sideEffect = flag; } bool sideEffect() const { return m_sideEffect; } }; @@ -2032,20 +2026,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_Lt; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLt(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLt(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "<"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f< %r)"; } + string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "<"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstLtD final : public AstNodeBiop { public: @@ -2054,22 +2048,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LtD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLtD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f< %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "<"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstLtN final : public AstNodeBiop { public: @@ -2078,22 +2072,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LtN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLtN(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f< %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "<"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; class AstLtS final : public AstNodeBiop { public: @@ -2102,21 +2096,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LtS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLtS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f< %r)"; } - virtual string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f< %r)"; } + string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool signedFlavor() const override { return true; } }; class AstLte final : public AstNodeBiop { public: @@ -2125,20 +2119,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_Lte; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLte(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLte(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "<="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f<= %r)"; } + string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "<="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstLteD final : public AstNodeBiop { public: @@ -2147,22 +2141,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LteD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLteD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f<= %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "<="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstLteN final : public AstNodeBiop { public: @@ -2171,22 +2165,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LteN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLteN(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "<="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f<= %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "<="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; class AstLteS final : public AstNodeBiop { public: @@ -2195,21 +2189,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LteS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLteS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } - virtual string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f<= %r)"; } + string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool signedFlavor() const override { return true; } }; class AstModDiv final : public AstNodeBiop { public: @@ -2218,20 +2212,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_ModDiv; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstModDiv(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opModDiv(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } - virtual string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } + string emitVerilog() override { return "%k(%l %f%% %r)"; } + string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } }; class AstModDivS final : public AstNodeBiop { public: @@ -2240,21 +2234,21 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_ModDivS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstModDivS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opModDivS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } - virtual string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f%% %r)"; } + string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; } + bool signedFlavor() const override { return true; } }; class AstNeqWild final : public AstNodeBiop { public: @@ -2263,20 +2257,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_NeqWild; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqWild(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opWildNeq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f!=? %r)"; } - virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f!=? %r)"; } + string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "!="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstPow final : public AstNodeBiop { public: @@ -2285,21 +2279,21 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Pow; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPow(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPow(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + string emitVerilog() override { return "%k(%l %f** %r)"; } + string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + bool emitCheckMaxWords() override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } }; class AstPowD final : public AstNodeBiop { public: @@ -2308,21 +2302,21 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_PowD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { return "pow(%li,%ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f** %r)"; } + string emitC() override { return "pow(%li,%ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; } + bool doubleFlavor() const override { return true; } }; class AstPowSS final : public AstNodeBiop { public: @@ -2331,24 +2325,22 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_PowSS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowSS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowSS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { - return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; - } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f** %r)"; } + string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; } + bool emitCheckMaxWords() override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + bool signedFlavor() const override { return true; } }; class AstPowSU final : public AstNodeBiop { public: @@ -2357,24 +2349,22 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_PowSU; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowSU(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowSU(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { - return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; - } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f** %r)"; } + string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; } + bool emitCheckMaxWords() override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + bool signedFlavor() const override { return true; } }; class AstPowUS final : public AstNodeBiop { public: @@ -2383,24 +2373,22 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_PowUS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowUS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowUS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f** %r)"; } - virtual string emitC() override { - return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; - } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f** %r)"; } + string emitC() override { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; } + bool emitCheckMaxWords() override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; } + bool signedFlavor() const override { return true; } }; class AstReplicate final : public AstNodeBiop { // Also used as a "Uniop" flavor of Concat, e.g. "{a}" @@ -2417,20 +2405,20 @@ public: AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount) : AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {} ASTGEN_MEMBERS_Replicate; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstReplicate(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opRepl(lhs, rhs); } - virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } - virtual string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } + string emitVerilog() override { return "%f{%r{%k%l}}"; } + string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 2; } }; class AstReplicateN final : public AstNodeBiop { // String replicate @@ -2442,21 +2430,21 @@ public: AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount) : AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {} ASTGEN_MEMBERS_ReplicateN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstReplicateN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opReplN(lhs, rhs); } - virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } - virtual string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%f{%r{%k%l}}"; } + string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 2; } + bool stringFlavor() const override { return true; } }; class AstShiftL final : public AstNodeBiop { public: @@ -2465,22 +2453,22 @@ public: if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } ASTGEN_MEMBERS_ShiftL; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftL(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opShiftL(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f<< %r)"; } - virtual string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { + string emitVerilog() override { return "%k(%l %f<< %r)"; } + string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } }; class AstShiftR final : public AstNodeBiop { public: @@ -2489,23 +2477,23 @@ public: if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } ASTGEN_MEMBERS_ShiftR; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftR(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opShiftR(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f>> %r)"; } - virtual string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { + string emitVerilog() override { return "%k(%l %f>> %r)"; } + string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } // LHS size might be > output size, so don't want to force size - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstShiftRS final : public AstNodeBiop { // Shift right with sign extension, >>> operator @@ -2517,21 +2505,21 @@ public: if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED); } ASTGEN_MEMBERS_ShiftRS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftRS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opShiftRS(lhs, rhs, lhsp()->widthMinV()); } - virtual string emitVerilog() override { return "%k(%l %f>>> %r)"; } - virtual string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f>>> %r)"; } + string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool signedFlavor() const override { return true; } }; class AstSub final : public AstNodeBiop { public: @@ -2540,20 +2528,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Sub; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstSub(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opSub(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f- %r)"; } - virtual string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } + string emitVerilog() override { return "%k(%l %f- %r)"; } + string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "-"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } }; class AstSubD final : public AstNodeBiop { public: @@ -2562,22 +2550,22 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_SubD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstSubD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opSubD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f- %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f- %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "-"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstURandomRange final : public AstNodeBiop { // $urandom_range @@ -2587,22 +2575,22 @@ public: dtypeSetUInt32(); // Says IEEE } ASTGEN_MEMBERS_URandomRange; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstURandomRange(fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$urandom_range(%l, %r)"; } - virtual string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } + string emitVerilog() override { return "%f$urandom_range(%l, %r)"; } + string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_PLI; } }; // === AstNodeBiCom === @@ -2613,22 +2601,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_Eq; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEq(this->fileline(), lhsp, rhsp); } static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEq/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opEq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f== %r)"; } - virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f== %r)"; } + string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "=="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstEqCase final : public AstNodeBiCom { public: @@ -2637,20 +2625,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_EqCase; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqCase(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCaseEq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f=== %r)"; } - virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f=== %r)"; } + string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "=="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstEqD final : public AstNodeBiCom { public: @@ -2659,22 +2647,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_EqD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opEqD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f== %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f== %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "=="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstEqN final : public AstNodeBiCom { public: @@ -2683,22 +2671,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_EqN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opEqN(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f== %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "=="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f== %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "=="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; class AstLogEq final : public AstNodeBiCom { public: @@ -2707,21 +2695,21 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LogEq; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogEq(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogEq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f<-> %r)"; } - virtual string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "<->"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + string emitVerilog() override { return "%k(%l %f<-> %r)"; } + string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "<->"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } }; class AstNeq final : public AstNodeBiCom { public: @@ -2730,20 +2718,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_Neq; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeq(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opNeq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } - virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f!= %r)"; } + string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "!="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstNeqCase final : public AstNodeBiCom { public: @@ -2752,20 +2740,20 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_NeqCase; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqCase(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCaseNeq(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f!== %r)"; } - virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f!== %r)"; } + string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "!="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstNeqD final : public AstNodeBiCom { public: @@ -2774,22 +2762,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_NeqD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opNeqD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f!= %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "!="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstNeqN final : public AstNodeBiCom { public: @@ -2798,22 +2786,22 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_NeqN; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opNeqN(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "!="; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_STR; } - virtual bool stringFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f!= %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "!="; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_STR; } + bool stringFlavor() const override { return true; } }; // === AstNodeBiComAsv === @@ -2824,20 +2812,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Add; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAdd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAdd(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } - virtual string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "+"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } + string emitVerilog() override { return "%k(%l %f+ %r)"; } + string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "+"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } }; class AstAddD final : public AstNodeBiComAsv { public: @@ -2846,22 +2834,22 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_AddD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAddD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAddD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "+"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f+ %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "+"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstAnd final : public AstNodeBiComAsv { public: @@ -2870,20 +2858,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_And; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAnd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAnd(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f& %r)"; } - virtual string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "&"; } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f& %r)"; } + string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "&"; } + bool cleanOut() const override { V3ERROR_NA_RETURN(false); } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstMul final : public AstNodeBiComAsv { public: @@ -2892,21 +2880,21 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Mul; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMul(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opMul(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f* %r)"; } - virtual string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "*"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } + string emitVerilog() override { return "%k(%l %f* %r)"; } + string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "*"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } }; class AstMulD final : public AstNodeBiComAsv { public: @@ -2915,22 +2903,22 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_MulD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMulD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opMulD(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f* %r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "*"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f* %r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "*"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstMulS final : public AstNodeBiComAsv { public: @@ -2939,23 +2927,23 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_MulS; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMulS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opMulS(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f* %r)"; } - virtual string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } - virtual bool signedFlavor() const override { return true; } + string emitVerilog() override { return "%k(%l %f* %r)"; } + string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + string emitSimpleOperator() override { return ""; } + bool emitCheckMaxWords() override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; } + bool signedFlavor() const override { return true; } }; class AstOr final : public AstNodeBiComAsv { public: @@ -2964,20 +2952,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Or; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstOr(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opOr(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f| %r)"; } - virtual string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "|"; } - virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f| %r)"; } + string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "|"; } + bool cleanOut() const override { V3ERROR_NA_RETURN(false); } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; class AstXor final : public AstNodeBiComAsv { public: @@ -2986,20 +2974,20 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Xor; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstXor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opXor(lhs, rhs); } - virtual string emitVerilog() override { return "%k(%l %f^ %r)"; } - virtual string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() override { return "^"; } - virtual bool cleanOut() const override { return false; } // Lclean && Rclean - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } + string emitVerilog() override { return "%k(%l %f^ %r)"; } + string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } + string emitSimpleOperator() override { return "^"; } + bool cleanOut() const override { return false; } // Lclean && Rclean + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } }; // === AstNodeSel === @@ -3024,25 +3012,23 @@ public: init(fromp); } ASTGEN_MEMBERS_ArraySel; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstArraySel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; /* How can from be a const? */ } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { return "%li%k[%ri]"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { - return true; - } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "%k(%l%f[%r])"; } + string emitC() override { return "%li%k[%ri]"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign + bool isPredictOptimizable() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return widthInstrs(); } // Special operators // Return base var (or const) nodep dereferences static AstNode* baseFromp(AstNode* nodep, bool overMembers); @@ -3064,25 +3050,23 @@ public: init(fromp); } ASTGEN_MEMBERS_AssocSel; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssocSel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { return "%li%k[%ri]"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { - return true; - } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "%k(%l%f[%r])"; } + string emitC() override { return "%li%k[%ri]"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign + bool isPredictOptimizable() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return widthInstrs(); } }; class AstWildcardSel final : public AstNodeSel { // Parents: math|stmt @@ -3101,25 +3085,23 @@ public: init(fromp); } ASTGEN_MEMBERS_WildcardSel; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstWildcardSel{this->fileline(), lhsp, rhsp}; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { return "%li%k[%ri]"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool isGateOptimizable() const override { - return true; - } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + string emitVerilog() override { return "%k(%l%f[%r])"; } + string emitC() override { return "%li%k[%ri]"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign + bool isPredictOptimizable() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return widthInstrs(); } }; class AstWordSel final : public AstNodeSel { // Select a single word from a multi-word wide value @@ -3129,22 +3111,22 @@ public: dtypeSetUInt32(); // Always used on WData arrays so returns edata size } ASTGEN_MEMBERS_WordSel; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstWordSel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override { + void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%k(%l%f[%r])"; } - virtual string emitC() override { + string emitVerilog() override { return "%k(%l%f[%r])"; } + string emitC() override { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } }; // === AstNodeStream === @@ -3154,20 +3136,20 @@ public: AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_StreamL; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstStreamL(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() override { return "%f{ << %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + string emitVerilog() override { return "%f{ << %r %k{%l} }"; } + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opStreamL(lhs, rhs); } - virtual string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } + string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 2; } }; class AstStreamR final : public AstNodeStream { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() @@ -3175,20 +3157,20 @@ public: AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_StreamR; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstStreamR(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() override { return "%f{ >> %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + string emitVerilog() override { return "%f{ >> %r %k{%l} }"; } + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAssign(lhs); } - virtual string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } + string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 2; } }; // === AstNodeSystemBiop === @@ -3197,28 +3179,28 @@ public: AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_Atan2D; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAtan2D(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.setDouble(std::atan2(lhs.toDouble(), rhs.toDouble())); } - virtual string emitVerilog() override { return "%f$atan2(%l,%r)"; } - virtual string emitC() override { return "atan2(%li,%ri)"; } + string emitVerilog() override { return "%f$atan2(%l,%r)"; } + string emitC() override { return "atan2(%li,%ri)"; } }; class AstHypotD final : public AstNodeSystemBiop { public: AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_HypotD; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstHypotD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.setDouble(std::hypot(lhs.toDouble(), rhs.toDouble())); } - virtual string emitVerilog() override { return "%f$hypot(%l,%r)"; } - virtual string emitC() override { return "hypot(%li,%ri)"; } + string emitVerilog() override { return "%f$hypot(%l,%r)"; } + string emitC() override { return "hypot(%li,%ri)"; } }; // === AstNodeQuadop === @@ -3233,22 +3215,22 @@ public: AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p, AstNode* ctrl3p) : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {} ASTGEN_MEMBERS_CountBits; - virtual void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1, - const V3Number& ctrl2, const V3Number& ctrl3) override { + void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1, + const V3Number& ctrl2, const V3Number& ctrl3) override { out.opCountBits(expr, ctrl1, ctrl2, ctrl3); } - virtual string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; } - virtual string emitC() override { return ""; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool cleanFhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual bool sizeMattersFhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } + string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; } + string emitC() override { return ""; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool cleanThs() const override { return true; } + bool cleanFhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool sizeMattersThs() const override { return false; } + bool sizeMattersFhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 16; } }; // === AstNodeTermop === @@ -3261,14 +3243,14 @@ public: dtypeSetUInt64(); } ASTGEN_MEMBERS_Time; - virtual string emitVerilog() override { return "%f$time"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_TIME; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; + string emitVerilog() override { return "%f$time"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_TIME; } + bool same(const AstNode* /*samep*/) const override { return true; } + void dump(std::ostream& str = std::cout) const override; void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -3281,14 +3263,14 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_TimeD; - virtual string emitVerilog() override { return "%f$realtime"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_TIME; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; + string emitVerilog() override { return "%f$realtime"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_TIME; } + bool same(const AstNode* /*samep*/) const override { return true; } + void dump(std::ostream& str = std::cout) const override; void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -3304,20 +3286,20 @@ public: AstPostAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {} ASTGEN_MEMBERS_PostAdd; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() override { return "%k(%r++)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } + string emitVerilog() override { return "%k(%r++)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool cleanThs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + bool sizeMattersThs() const override { return true; } }; class AstPostSub final : public AstNodeTriop { // Post-decrement/subtract @@ -3329,20 +3311,20 @@ public: AstPostSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {} ASTGEN_MEMBERS_PostSub; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() override { return "%k(%r--)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } + string emitVerilog() override { return "%k(%r--)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool cleanThs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + bool sizeMattersThs() const override { return true; } }; class AstPreAdd final : public AstNodeTriop { // Pre-increment/add @@ -3354,20 +3336,20 @@ public: AstPreAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {} ASTGEN_MEMBERS_PreAdd; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() override { return "%k(++%r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } + string emitVerilog() override { return "%k(++%r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool cleanThs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + bool sizeMattersThs() const override { return true; } }; class AstPreSub final : public AstNodeTriop { // Pre-decrement/subtract @@ -3379,20 +3361,20 @@ public: AstPreSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {} ASTGEN_MEMBERS_PreSub; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() override { return "%k(--%r)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return false; } - virtual bool cleanThs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } - virtual bool sizeMattersRhs() const override { return true; } - virtual bool sizeMattersThs() const override { return true; } + string emitVerilog() override { return "%k(--%r)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return false; } + bool cleanThs() const override { return false; } + bool sizeMattersLhs() const override { return true; } + bool sizeMattersRhs() const override { return true; } + bool sizeMattersThs() const override { return true; } }; class AstPutcN final : public AstNodeTriop { // Verilog string.putc() @@ -3402,21 +3384,21 @@ public: dtypeSetString(); } ASTGEN_MEMBERS_PutcN; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { out.opPutcN(lhs, rhs, ths); } - virtual string name() const override { return "putc"; } - virtual string emitVerilog() override { return "%k(%l.putc(%r,%t))"; } - virtual string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } + string name() const override { return "putc"; } + string emitVerilog() override { return "%k(%l.putc(%r,%t))"; } + string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool cleanThs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool sizeMattersThs() const override { return false; } }; class AstSel final : public AstNodeTriop { // Multiple bit range extraction @@ -3441,28 +3423,26 @@ public: dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED); } ASTGEN_MEMBERS_Sel; - virtual void dump(std::ostream& str) const override; - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, - const V3Number& width) override { + void dump(std::ostream& str) const override; + void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, + const V3Number& width) override { out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt()); } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { return widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%lw, %P, %li, %ri)" : isWide() ? "VL_SEL_%nq%lq%rq%tq(%nw,%lw, %P, %li, %ri, %ti)" : "VL_SEL_%nq%lq%rq%tq(%lw, %P, %li, %ri, %ti)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual bool same(const AstNode*) const override { return true; } - virtual int instrCount() const override { - return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); - } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool cleanThs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool sizeMattersThs() const override { return false; } + bool same(const AstNode*) const override { return true; } + int instrCount() const override { return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); } AstNode* fromp() const { return op1p(); } // op1 = Extracting what (nullptr=TBD during parsing) @@ -3489,22 +3469,22 @@ public: new AstConst(fl, declRange.elements())) , m_declRange{declRange} {} ASTGEN_MEMBERS_SliceSel; - virtual void dump(std::ostream& str) const override; - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, - const V3Number& width) override { + void dump(std::ostream& str) const override; + void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, + const V3Number& width) override { V3ERROR_NA; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } - virtual bool same(const AstNode*) const override { return true; } - virtual int instrCount() const override { return 10; } // Removed before matters + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool cleanRhs() const override { return true; } + bool cleanThs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool sizeMattersThs() const override { return false; } + bool same(const AstNode*) const override { return true; } + int instrCount() const override { return 10; } // Removed before matters AstNode* fromp() const { return op1p(); } // op1 = Extracting what (nullptr=TBD during parsing) @@ -3521,21 +3501,21 @@ public: dtypeSetString(); } ASTGEN_MEMBERS_SubstrN; - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) override { + void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, + const V3Number& ths) override { out.opSubstrN(lhs, rhs, ths); } - virtual string name() const override { return "substr"; } - virtual string emitVerilog() override { return "%k(%l.substr(%r,%t))"; } - virtual string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; } - virtual string emitSimpleOperator() override { return ""; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool cleanRhs() const override { return true; } - virtual bool cleanThs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool sizeMattersRhs() const override { return false; } - virtual bool sizeMattersThs() const override { return false; } + string name() const override { return "substr"; } + string emitVerilog() override { return "%k(%l.substr(%r,%t))"; } + string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; } + string emitSimpleOperator() override { return ""; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool cleanRhs() const override { return true; } + bool cleanThs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool sizeMattersRhs() const override { return false; } + bool sizeMattersThs() const override { return false; } }; // === AstNodeCond === @@ -3547,7 +3527,7 @@ public: AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : ASTGEN_SUPER_Cond(fl, condp, expr1p, expr2p) {} ASTGEN_MEMBERS_Cond; - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { + AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { return new AstCond(this->fileline(), condp, expr1p, expr2p); } }; @@ -3559,7 +3539,7 @@ public: AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : ASTGEN_SUPER_CondBound(fl, condp, expr1p, expr2p) {} ASTGEN_MEMBERS_CondBound; - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { + AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { return new AstCondBound(this->fileline(), condp, expr1p, expr2p); } }; @@ -3579,10 +3559,8 @@ public: fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32(); } ASTGEN_MEMBERS_AtoN; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opAtoN(lhs, m_fmt); - } - virtual string name() const override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAtoN(lhs, m_fmt); } + string name() const override { switch (m_fmt) { case ATOI: return "atoi"; case ATOHEX: return "atohex"; @@ -3592,8 +3570,8 @@ public: default: V3ERROR_NA; } } - virtual string emitVerilog() override { return "%l." + name() + "()"; } - virtual string emitC() override { + string emitVerilog() override { return "%l." + name() + "()"; } + string emitC() override { switch (m_fmt) { case ATOI: return "VL_ATOI_N(%li, 10)"; case ATOHEX: return "VL_ATOI_N(%li, 16)"; @@ -3603,9 +3581,9 @@ public: default: V3ERROR_NA; } } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } FmtType format() const { return m_fmt; } }; class AstBitsToRealD final : public AstNodeUniop { @@ -3615,15 +3593,13 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_BitsToRealD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opBitsToRealD(lhs); - } - virtual string emitVerilog() override { return "%f$bitstoreal(%l)"; } - virtual string emitC() override { return "VL_CVT_D_Q(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters - virtual int instrCount() const override { return INSTR_COUNT_DBL; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opBitsToRealD(lhs); } + string emitVerilog() override { return "%f$bitstoreal(%l)"; } + string emitC() override { return "VL_CVT_D_Q(%li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } // Eliminated before matters + bool sizeMattersLhs() const override { return false; } // Eliminated before matters + int instrCount() const override { return INSTR_COUNT_DBL; } }; class AstCCast final : public AstNodeUniop { // Cast to C-based data type @@ -3645,16 +3621,16 @@ public: m_size = width(); } ASTGEN_MEMBERS_CCast; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } - virtual string emitVerilog() override { return "%f$_CAST(%l)"; } - virtual string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast - virtual bool same(const AstNode* samep) const override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } + string emitVerilog() override { return "%f$_CAST(%l)"; } + string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast + bool same(const AstNode* samep) const override { return size() == static_cast(samep)->size(); } - virtual void dump(std::ostream& str = std::cout) const override; + void dump(std::ostream& str = std::cout) const override; // int size() const { return m_size; } }; @@ -3665,13 +3641,13 @@ public: dtypeSetSigned32(); } ASTGEN_MEMBERS_CLog2; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); } - virtual string emitVerilog() override { return "%f$clog2(%l)"; } - virtual string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); } + string emitVerilog() override { return "%f$clog2(%l)"; } + string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 16; } }; class AstCountOnes final : public AstNodeUniop { // Number of bits set in vector @@ -3679,15 +3655,13 @@ public: AstCountOnes(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CountOnes(fl, lhsp) {} ASTGEN_MEMBERS_CountOnes; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opCountOnes(lhs); - } - virtual string emitVerilog() override { return "%f$countones(%l)"; } - virtual string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCountOnes(lhs); } + string emitVerilog() override { return "%f$countones(%l)"; } + string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 16; } }; class AstCvtPackString final : public AstNodeUniop { // Convert to Verilator Packed String (aka verilog "string") @@ -3697,13 +3671,13 @@ public: dtypeSetString(); } ASTGEN_MEMBERS_CvtPackString; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$_CAST(%l)"; } - virtual string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + string emitVerilog() override { return "%f$_CAST(%l)"; } + string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstExtend final : public AstNodeUniop { // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width() @@ -3715,15 +3689,15 @@ public: dtypeSetLogicSized(width, VSigning::UNSIGNED); } ASTGEN_MEMBERS_Extend; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } + string emitVerilog() override { return "%l"; } + string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; // Because the EXTEND operator self-casts } - virtual int instrCount() const override { return 0; } + int instrCount() const override { return 0; } }; class AstExtendS final : public AstNodeUniop { // Expand a value into a wider entity by sign extension. Width is implied from nodep->width() @@ -3736,34 +3710,32 @@ public: dtypeSetLogicSized(width, VSigning::UNSIGNED); } ASTGEN_MEMBERS_ExtendS; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opExtendS(lhs, lhsp()->widthMinV()); } - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { + string emitVerilog() override { return "%l"; } + string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; // Because the EXTEND operator self-casts } - virtual int instrCount() const override { return 0; } - virtual bool signedFlavor() const override { return true; } + int instrCount() const override { return 0; } + bool signedFlavor() const override { return true; } }; class AstFEof final : public AstNodeUniop { public: AstFEof(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_FEof(fl, lhsp) {} ASTGEN_MEMBERS_FEof; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$feof(%l)"; } - virtual string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 16; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering + void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + string emitVerilog() override { return "%f$feof(%l)"; } + string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 16; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } }; class AstFGetC final : public AstNodeUniop { @@ -3771,17 +3743,15 @@ public: AstFGetC(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_FGetC(fl, lhsp) {} ASTGEN_MEMBERS_FGetC; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%f$fgetc(%l)"; } + void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + string emitVerilog() override { return "%f$fgetc(%l)"; } // Non-existent filehandle returns EOF - virtual string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 64; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering + string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 64; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } }; class AstISToRD final : public AstNodeUniop { @@ -3792,14 +3762,14 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_ISToRD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); } - virtual string emitVerilog() override { return "%f$itor($signed(%l))"; } - virtual string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; } - virtual bool emitCheckMaxWords() override { return true; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); } + string emitVerilog() override { return "%f$itor($signed(%l))"; } + string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; } + bool emitCheckMaxWords() override { return true; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } }; class AstIToRD final : public AstNodeUniop { // $itor where lhs is unsigned @@ -3809,13 +3779,13 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_IToRD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); } - virtual string emitVerilog() override { return "%f$itor(%l)"; } - virtual string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); } + string emitVerilog() override { return "%f$itor(%l)"; } + string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } }; class AstIsUnbounded final : public AstNodeUniop { // True if is unmbounded ($) @@ -3825,15 +3795,15 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_IsUnbounded; - virtual void numberOperate(V3Number& out, const V3Number&) override { + void numberOperate(V3Number& out, const V3Number&) override { // Any constant isn't unbounded out.setZero(); } - virtual string emitVerilog() override { return "%f$isunbounded(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } + string emitVerilog() override { return "%f$isunbounded(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } }; class AstIsUnknown final : public AstNodeUniop { // True if any unknown bits @@ -3843,14 +3813,12 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_IsUnknown; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opIsUnknown(lhs); - } - virtual string emitVerilog() override { return "%f$isunknown(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIsUnknown(lhs); } + string emitVerilog() override { return "%f$isunknown(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } }; class AstLenN final : public AstNodeUniop { // Length of a string @@ -3860,12 +3828,12 @@ public: dtypeSetSigned32(); } ASTGEN_MEMBERS_LenN; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); } - virtual string emitVerilog() override { return "%f(%l)"; } - virtual string emitC() override { return "VL_LEN_IN(%li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); } + string emitVerilog() override { return "%f(%l)"; } + string emitC() override { return "VL_LEN_IN(%li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } }; class AstLogNot final : public AstNodeUniop { public: @@ -3874,13 +3842,13 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_LogNot; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } - virtual string emitVerilog() override { return "%f(! %l)"; } - virtual string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } - virtual string emitSimpleOperator() override { return "!"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } + string emitVerilog() override { return "%f(! %l)"; } + string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } + string emitSimpleOperator() override { return "!"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } }; class AstNegate final : public AstNodeUniop { public: @@ -3889,13 +3857,13 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Negate; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); } - virtual string emitVerilog() override { return "%f(- %l)"; } - virtual string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); } + string emitVerilog() override { return "%f(- %l)"; } + string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; } + string emitSimpleOperator() override { return "-"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return true; } }; class AstNegateD final : public AstNodeUniop { public: @@ -3904,15 +3872,15 @@ public: dtypeSetDouble(); } ASTGEN_MEMBERS_NegateD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); } - virtual string emitVerilog() override { return "%f(- %l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { return "-"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } - virtual bool doubleFlavor() const override { return true; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); } + string emitVerilog() override { return "%f(- %l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { return "-"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } + bool doubleFlavor() const override { return true; } }; class AstNot final : public AstNodeUniop { public: @@ -3921,13 +3889,13 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Not; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); } - virtual string emitVerilog() override { return "%f(~ %l)"; } - virtual string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; } - virtual string emitSimpleOperator() override { return "~"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return true; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); } + string emitVerilog() override { return "%f(~ %l)"; } + string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; } + string emitSimpleOperator() override { return "~"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return true; } }; class AstNullCheck final : public AstNodeUniop { // Return LHS after checking that LHS is non-null @@ -3938,17 +3906,15 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_NullCheck; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual int instrCount() const override { return 1; } // Rarely executes - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual bool same(const AstNode* samep) const override { - return fileline() == samep->fileline(); - } + void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + int instrCount() const override { return 1; } // Rarely executes + string emitVerilog() override { return "%l"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } }; class AstOneHot final : public AstNodeUniop { // True if only single bit set in vector @@ -3958,13 +3924,13 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_OneHot; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } - virtual string emitVerilog() override { return "%f$onehot(%l)"; } - virtual string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 4; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } + string emitVerilog() override { return "%f$onehot(%l)"; } + string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 4; } }; class AstOneHot0 final : public AstNodeUniop { // True if only single bit, or no bits set in vector @@ -3974,13 +3940,13 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_OneHot0; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } - virtual string emitVerilog() override { return "%f$onehot0(%l)"; } - virtual string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 3; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } + string emitVerilog() override { return "%f$onehot0(%l)"; } + string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return widthInstrs() * 3; } }; class AstRToIRoundS final : public AstNodeUniop { // Convert real to integer, with arbitrary sized output (not just "integer" format) @@ -3990,17 +3956,15 @@ public: dtypeSetSigned32(); } ASTGEN_MEMBERS_RToIRoundS; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opRToIRoundS(lhs); - } - virtual string emitVerilog() override { return "%f$rtoi_rounded(%l)"; } - virtual string emitC() override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIRoundS(lhs); } + string emitVerilog() override { return "%f$rtoi_rounded(%l)"; } + string emitC() override { return isWide() ? "VL_RTOIROUND_%nq_D(%nw, %P, %li)" : "VL_RTOIROUND_%nq_D(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_DBL; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return INSTR_COUNT_DBL; } }; class AstRToIS final : public AstNodeUniop { // $rtoi(lhs) @@ -4010,13 +3974,13 @@ public: dtypeSetSigned32(); } ASTGEN_MEMBERS_RToIS; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); } - virtual string emitVerilog() override { return "%f$rtoi(%l)"; } - virtual string emitC() override { return "VL_RTOI_I_D(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters - virtual int instrCount() const override { return INSTR_COUNT_DBL; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); } + string emitVerilog() override { return "%f$rtoi(%l)"; } + string emitC() override { return "VL_RTOI_I_D(%li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } // Eliminated before matters + bool sizeMattersLhs() const override { return false; } // Eliminated before matters + int instrCount() const override { return INSTR_COUNT_DBL; } }; class AstRealToBits final : public AstNodeUniop { public: @@ -4025,15 +3989,13 @@ public: dtypeSetUInt64(); } ASTGEN_MEMBERS_RealToBits; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opRealToBits(lhs); - } - virtual string emitVerilog() override { return "%f$realtobits(%l)"; } - virtual string emitC() override { return "VL_CVT_Q_D(%li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters - virtual int instrCount() const override { return INSTR_COUNT_DBL; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRealToBits(lhs); } + string emitVerilog() override { return "%f$realtobits(%l)"; } + string emitC() override { return "VL_CVT_Q_D(%li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } // Eliminated before matters + bool sizeMattersLhs() const override { return false; } // Eliminated before matters + int instrCount() const override { return INSTR_COUNT_DBL; } }; class AstRedAnd final : public AstNodeUniop { public: @@ -4042,12 +4004,12 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_RedAnd; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } - virtual string emitVerilog() override { return "%f(& %l)"; } - virtual string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } + string emitVerilog() override { return "%f(& %l)"; } + string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } }; class AstRedOr final : public AstNodeUniop { public: @@ -4056,12 +4018,12 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_RedOr; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } - virtual string emitVerilog() override { return "%f(| %l)"; } - virtual string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } + string emitVerilog() override { return "%f(| %l)"; } + string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } }; class AstRedXor final : public AstNodeUniop { public: @@ -4070,16 +4032,16 @@ public: dtypeSetBit(); } ASTGEN_MEMBERS_RedXor; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } - virtual string emitVerilog() override { return "%f(^ %l)"; } - virtual string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } + string emitVerilog() override { return "%f(^ %l)"; } + string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { const int w = lhsp()->width(); return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16); } - virtual bool sizeMattersLhs() const override { return false; } - virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } + bool sizeMattersLhs() const override { return false; } + int instrCount() const override { return 1 + V3Number::log2b(width()); } }; class AstSigned final : public AstNodeUniop { // $signed(lhs) @@ -4090,16 +4052,16 @@ public: "not coded to create after dtypes resolved"); } ASTGEN_MEMBERS_Signed; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); out.isSigned(false); } - virtual string emitVerilog() override { return "%f$signed(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters - virtual int instrCount() const override { return 0; } + string emitVerilog() override { return "%f$signed(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } // Eliminated before matters + bool sizeMattersLhs() const override { return true; } // Eliminated before matters + int instrCount() const override { return 0; } }; class AstTimeImport final : public AstNodeUniop { // Take a constant that represents a time and needs conversion based on time units @@ -4108,13 +4070,13 @@ public: AstTimeImport(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_TimeImport(fl, lhsp) {} ASTGEN_MEMBERS_TimeImport; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } - virtual string emitVerilog() override { return "%l"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } - virtual bool sizeMattersLhs() const override { return false; } - virtual void dump(std::ostream& str = std::cout) const override; + void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + string emitVerilog() override { return "%l"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } + bool sizeMattersLhs() const override { return false; } + void dump(std::ostream& str = std::cout) const override; void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -4126,14 +4088,12 @@ public: dtypeSetString(); } ASTGEN_MEMBERS_ToLowerN; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opToLowerN(lhs); - } - virtual string emitVerilog() override { return "%l.tolower()"; } - virtual string emitC() override { return "VL_TOLOWER_NN(%li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToLowerN(lhs); } + string emitVerilog() override { return "%l.tolower()"; } + string emitC() override { return "VL_TOLOWER_NN(%li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } }; class AstToUpperN final : public AstNodeUniop { // string.toupper() @@ -4143,14 +4103,12 @@ public: dtypeSetString(); } ASTGEN_MEMBERS_ToUpperN; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { - out.opToUpperN(lhs); - } - virtual string emitVerilog() override { return "%l.toupper()"; } - virtual string emitC() override { return "VL_TOUPPER_NN(%li)"; } - virtual bool cleanOut() const override { return true; } - virtual bool cleanLhs() const override { return true; } - virtual bool sizeMattersLhs() const override { return false; } + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opToUpperN(lhs); } + string emitVerilog() override { return "%l.toupper()"; } + string emitC() override { return "VL_TOUPPER_NN(%li)"; } + bool cleanOut() const override { return true; } + bool cleanLhs() const override { return true; } + bool sizeMattersLhs() const override { return false; } }; class AstUnsigned final : public AstNodeUniop { // $unsigned(lhs) @@ -4161,16 +4119,16 @@ public: "not coded to create after dtypes resolved"); } ASTGEN_MEMBERS_Unsigned; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); out.isSigned(false); } - virtual string emitVerilog() override { return "%f$unsigned(%l)"; } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return false; } - virtual bool cleanLhs() const override { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters - virtual int instrCount() const override { return 0; } + string emitVerilog() override { return "%f$unsigned(%l)"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return false; } + bool cleanLhs() const override { return false; } // Eliminated before matters + bool sizeMattersLhs() const override { return true; } // Eliminated before matters + int instrCount() const override { return 0; } }; // === AstNodeSystemUniop === @@ -4179,198 +4137,198 @@ public: AstAcosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AcosD(fl, lhsp) {} ASTGEN_MEMBERS_AcosD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::acos(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$acos(%l)"; } - virtual string emitC() override { return "acos(%li)"; } + string emitVerilog() override { return "%f$acos(%l)"; } + string emitC() override { return "acos(%li)"; } }; class AstAcoshD final : public AstNodeSystemUniop { public: AstAcoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AcoshD(fl, lhsp) {} ASTGEN_MEMBERS_AcoshD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::acosh(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$acosh(%l)"; } - virtual string emitC() override { return "acosh(%li)"; } + string emitVerilog() override { return "%f$acosh(%l)"; } + string emitC() override { return "acosh(%li)"; } }; class AstAsinD final : public AstNodeSystemUniop { public: AstAsinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AsinD(fl, lhsp) {} ASTGEN_MEMBERS_AsinD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::asin(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$asin(%l)"; } - virtual string emitC() override { return "asin(%li)"; } + string emitVerilog() override { return "%f$asin(%l)"; } + string emitC() override { return "asin(%li)"; } }; class AstAsinhD final : public AstNodeSystemUniop { public: AstAsinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AsinhD(fl, lhsp) {} ASTGEN_MEMBERS_AsinhD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::asinh(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$asinh(%l)"; } - virtual string emitC() override { return "asinh(%li)"; } + string emitVerilog() override { return "%f$asinh(%l)"; } + string emitC() override { return "asinh(%li)"; } }; class AstAtanD final : public AstNodeSystemUniop { public: AstAtanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AtanD(fl, lhsp) {} ASTGEN_MEMBERS_AtanD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::atan(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$atan(%l)"; } - virtual string emitC() override { return "atan(%li)"; } + string emitVerilog() override { return "%f$atan(%l)"; } + string emitC() override { return "atan(%li)"; } }; class AstAtanhD final : public AstNodeSystemUniop { public: AstAtanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_AtanhD(fl, lhsp) {} ASTGEN_MEMBERS_AtanhD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::atanh(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$atanh(%l)"; } - virtual string emitC() override { return "atanh(%li)"; } + string emitVerilog() override { return "%f$atanh(%l)"; } + string emitC() override { return "atanh(%li)"; } }; class AstCeilD final : public AstNodeSystemUniop { public: AstCeilD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CeilD(fl, lhsp) {} ASTGEN_MEMBERS_CeilD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::ceil(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$ceil(%l)"; } - virtual string emitC() override { return "ceil(%li)"; } + string emitVerilog() override { return "%f$ceil(%l)"; } + string emitC() override { return "ceil(%li)"; } }; class AstCosD final : public AstNodeSystemUniop { public: AstCosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CosD(fl, lhsp) {} ASTGEN_MEMBERS_CosD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::cos(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$cos(%l)"; } - virtual string emitC() override { return "cos(%li)"; } + string emitVerilog() override { return "%f$cos(%l)"; } + string emitC() override { return "cos(%li)"; } }; class AstCoshD final : public AstNodeSystemUniop { public: AstCoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CoshD(fl, lhsp) {} ASTGEN_MEMBERS_CoshD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::cosh(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$cosh(%l)"; } - virtual string emitC() override { return "cosh(%li)"; } + string emitVerilog() override { return "%f$cosh(%l)"; } + string emitC() override { return "cosh(%li)"; } }; class AstExpD final : public AstNodeSystemUniop { public: AstExpD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_ExpD(fl, lhsp) {} ASTGEN_MEMBERS_ExpD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::exp(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$exp(%l)"; } - virtual string emitC() override { return "exp(%li)"; } + string emitVerilog() override { return "%f$exp(%l)"; } + string emitC() override { return "exp(%li)"; } }; class AstFloorD final : public AstNodeSystemUniop { public: AstFloorD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_FloorD(fl, lhsp) {} ASTGEN_MEMBERS_FloorD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::floor(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$floor(%l)"; } - virtual string emitC() override { return "floor(%li)"; } + string emitVerilog() override { return "%f$floor(%l)"; } + string emitC() override { return "floor(%li)"; } }; class AstLog10D final : public AstNodeSystemUniop { public: AstLog10D(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_Log10D(fl, lhsp) {} ASTGEN_MEMBERS_Log10D; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::log10(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$log10(%l)"; } - virtual string emitC() override { return "log10(%li)"; } + string emitVerilog() override { return "%f$log10(%l)"; } + string emitC() override { return "log10(%li)"; } }; class AstLogD final : public AstNodeSystemUniop { public: AstLogD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_LogD(fl, lhsp) {} ASTGEN_MEMBERS_LogD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::log(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$ln(%l)"; } - virtual string emitC() override { return "log(%li)"; } + string emitVerilog() override { return "%f$ln(%l)"; } + string emitC() override { return "log(%li)"; } }; class AstSinD final : public AstNodeSystemUniop { public: AstSinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SinD(fl, lhsp) {} ASTGEN_MEMBERS_SinD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::sin(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$sin(%l)"; } - virtual string emitC() override { return "sin(%li)"; } + string emitVerilog() override { return "%f$sin(%l)"; } + string emitC() override { return "sin(%li)"; } }; class AstSinhD final : public AstNodeSystemUniop { public: AstSinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SinhD(fl, lhsp) {} ASTGEN_MEMBERS_SinhD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::sinh(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$sinh(%l)"; } - virtual string emitC() override { return "sinh(%li)"; } + string emitVerilog() override { return "%f$sinh(%l)"; } + string emitC() override { return "sinh(%li)"; } }; class AstSqrtD final : public AstNodeSystemUniop { public: AstSqrtD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SqrtD(fl, lhsp) {} ASTGEN_MEMBERS_SqrtD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::sqrt(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$sqrt(%l)"; } - virtual string emitC() override { return "sqrt(%li)"; } + string emitVerilog() override { return "%f$sqrt(%l)"; } + string emitC() override { return "sqrt(%li)"; } }; class AstTanD final : public AstNodeSystemUniop { public: AstTanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_TanD(fl, lhsp) {} ASTGEN_MEMBERS_TanD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::tan(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$tan(%l)"; } - virtual string emitC() override { return "tan(%li)"; } + string emitVerilog() override { return "%f$tan(%l)"; } + string emitC() override { return "tan(%li)"; } }; class AstTanhD final : public AstNodeSystemUniop { public: AstTanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_TanhD(fl, lhsp) {} ASTGEN_MEMBERS_TanhD; - virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(std::tanh(lhs.toDouble())); } - virtual string emitVerilog() override { return "%f$tanh(%l)"; } - virtual string emitC() override { return "tanh(%li)"; } + string emitVerilog() override { return "%f$tanh(%l)"; } + string emitC() override { return "tanh(%li)"; } }; // === AstNodeVarRef === @@ -4385,16 +4343,16 @@ public: // This form only allowed post-link (see above) inline AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access); ASTGEN_MEMBERS_VarRef; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; bool same(const AstNode* samep) const override; inline bool same(const AstVarRef* samep) const; inline bool sameNoLvalue(AstVarRef* samep) const; - virtual int instrCount() const override { + int instrCount() const override { return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1); } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } }; class AstVarXRef final : public AstNodeVarRef { // A VarRef to something in another module before AstScope. @@ -4408,16 +4366,16 @@ public: , m_dotted{dotted} {} inline AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access); ASTGEN_MEMBERS_VarXRef; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; string dotted() const { return m_dotted; } void dotted(const string& dotted) { m_dotted = dotted; } string inlinedDots() const { return m_inlinedDots; } void inlinedDots(const string& flag) { m_inlinedDots = flag; } - virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } - virtual string emitC() override { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode* samep) const override { + string emitVerilog() override { V3ERROR_NA_RETURN(""); } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode* samep) const override { const AstVarXRef* asamep = static_cast(samep); return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp() && name() == asamep->name() && dotted() == asamep->dotted()); diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index da62b28d3..e3d56b736 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -47,9 +47,9 @@ protected: public: ASTGEN_MEMBERS_NodeBlock; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } // * = Block name - virtual void name(const string& name) override { m_name = name; } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } // * = Block name + void name(const string& name) override { m_name = name; } // op1 = Statements AstNode* stmtsp() const { return op1p(); } // op1 = List of statements void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } @@ -112,14 +112,12 @@ protected: public: ASTGEN_MEMBERS_NodeFTask; - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool maybePointedTo() const override { return true; } - virtual bool isGateOptimizable() const override { - return !((m_dpiExport || m_dpiImport) && !m_pure); - } + void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } // * = Var name + bool maybePointedTo() const override { return true; } + bool isGateOptimizable() const override { return !((m_dpiExport || m_dpiImport) && !m_pure); } // {AstFunc only} op1 = Range output variable - virtual void name(const string& name) override { m_name = name; } + void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } void cname(const string& cname) { m_cname = cname; } // op1 = Output variable (functions only, nullptr for tasks) @@ -194,9 +192,9 @@ public: : AstNode{t, fl} , m_name{name} {} ASTGEN_MEMBERS_NodeFile; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } + bool same(const AstNode* /*samep*/) const override { return true; } void tblockp(AstTextBlock* tblockp) { setOp1p((AstNode*)tblockp); } AstTextBlock* tblockp() { return VN_AS(op1p(), TextBlock); } }; @@ -237,9 +235,9 @@ protected: public: ASTGEN_MEMBERS_NodeModule; - virtual void dump(std::ostream& str) const override; - virtual bool maybePointedTo() const override { return true; } - virtual string name() const override { return m_name; } + void dump(std::ostream& str) const override; + bool maybePointedTo() const override { return true; } + string name() const override { return m_name; } virtual bool timescaleMatters() const = 0; AstNode* stmtsp() const { return op2p(); } // op2 = List of statements AstActive* activesp() const { return VN_AS(op3p(), Active); } // op3 = List of i/sblocks @@ -248,8 +246,8 @@ public: void addStmtp(AstNode* nodep) { addNOp2p(nodep); } void addActivep(AstNode* nodep) { addOp3p(nodep); } // ACCESSORS - virtual void name(const string& name) override { m_name = name; } - virtual string origName() const override { return m_origName; } + void name(const string& name) override { m_name = name; } + string origName() const override { return m_origName; } string someInstanceName() const { return m_someInstanceName; } void someInstanceName(const string& name) { m_someInstanceName = name; } bool inLibrary() const { return m_inLibrary; } @@ -299,7 +297,7 @@ public: void thsp(AstNode* nodep) { return setOp3p(nodep); } void attrp(AstAttrOf* nodep) { return setOp4p(reinterpret_cast(nodep)); } // METHODS - virtual bool same(const AstNode*) const override { return true; } + bool same(const AstNode*) const override { return true; } }; class AstNodeProcedure VL_NOT_FINAL : public AstNode { // IEEE procedure: initial, final, always @@ -312,7 +310,7 @@ protected: public: ASTGEN_MEMBERS_NodeProcedure; // METHODS - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate void addStmtp(AstNode* nodep) { addOp2p(nodep); } bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } @@ -325,7 +323,7 @@ protected: public: ASTGEN_MEMBERS_NodeRange; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; }; class AstNodeStmt VL_NOT_FINAL : public AstNode { // Statement -- anything that's directly under a function @@ -340,11 +338,11 @@ public: // METHODS bool isStatement() const { return m_statement; } // Really a statement void statement(bool flag) { m_statement = flag; } - virtual void addNextStmt(AstNode* newp, - AstNode* belowp) override; // Stop statement searchback here - virtual void addBeforeStmt(AstNode* newp, - AstNode* belowp) override; // Stop statement searchback here - virtual void dump(std::ostream& str = std::cout) const override; + void addNextStmt(AstNode* newp, + AstNode* belowp) override; // Stop statement searchback here + void addBeforeStmt(AstNode* newp, + AstNode* belowp) override; // Stop statement searchback here + void dump(std::ostream& str = std::cout) const override; }; class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt { protected: @@ -369,11 +367,11 @@ public: void addTimingControlp(AstNode* const np) { addNOp3p(np); } void rhsp(AstNode* np) { setOp1p(np); } void lhsp(AstNode* np) { setOp2p(np); } - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } virtual bool cleanRhs() const { return true; } - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode*) const override { return true; } - virtual string verilogKwd() const override { return "="; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode*) const override { return true; } + string verilogKwd() const override { return "="; } virtual bool brokeLhsMustBeLvalue() const = 0; }; class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt { @@ -391,19 +389,19 @@ protected: public: ASTGEN_MEMBERS_NodeCCall; - virtual void dump(std::ostream& str = std::cout) const override; - virtual void cloneRelink() override; - virtual const char* broken() const override; - virtual int instrCount() const override { return INSTR_COUNT_CALL; } - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str = std::cout) const override; + void cloneRelink() override; + const char* broken() const override; + int instrCount() const override { return INSTR_COUNT_CALL; } + bool same(const AstNode* samep) const override { const AstNodeCCall* const asamep = static_cast(samep); return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes()); } AstNode* exprsp() const { return op2p(); } // op2 = expressions to print - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override; - virtual bool isOutputter() const override { return !isPure(); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override; + bool isOutputter() const override { return !isPure(); } AstCFunc* funcp() const { return m_funcp; } void funcp(AstCFunc* funcp) { m_funcp = funcp; } void argTypes(const string& str) { m_argTypes = str; } @@ -422,7 +420,7 @@ protected: public: ASTGEN_MEMBERS_NodeCase; - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } + int instrCount() const override { return INSTR_COUNT_BRANCH; } AstNode* exprp() const { return op1p(); } // op1 = case condition AstCaseItem* itemsp() const { return VN_AS(op2p(), CaseItem); @@ -448,10 +446,10 @@ public: addNOp4p(passsp); } ASTGEN_MEMBERS_NodeCoverOrAssert; - virtual string name() const override { return m_name; } // * = Var name - virtual bool same(const AstNode* samep) const override { return samep->name() == name(); } - virtual void name(const string& name) override { m_name = name; } - virtual void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } // * = Var name + bool same(const AstNode* samep) const override { return samep->name() == name(); } + void name(const string& name) override { m_name = name; } + void dump(std::ostream& str = std::cout) const override; AstNode* propp() const { return op1p(); } // op1 = property AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain @@ -482,19 +480,17 @@ protected: public: ASTGEN_MEMBERS_NodeFTaskRef; - virtual const char* broken() const override; - virtual void cloneRelink() override; - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool isGateOptimizable() const override { - return m_taskp && m_taskp->isGateOptimizable(); - } + const char* broken() const override; + void cloneRelink() override; + void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } // * = Var name + bool isGateOptimizable() const override { return m_taskp && m_taskp->isGateOptimizable(); } string dotted() const { return m_dotted; } // * = Scope name or "" string inlinedDots() const { return m_inlinedDots; } void inlinedDots(const string& flag) { m_inlinedDots = flag; } AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable void taskp(AstNodeFTask* taskp) { m_taskp = taskp; } - virtual void name(const string& name) override { m_name = name; } + void name(const string& name) override { m_name = name; } void dotted(const string& name) { m_dotted = name; } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } @@ -527,9 +523,9 @@ public: AstNode* condp() const { return op2p(); } // op2 = condition to continue AstNode* incsp() const { return op3p(); } // op3 = increment statements AstNode* bodysp() const { return op4p(); } // op4 = body of loop - virtual bool isGateOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_BRANCH; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { private: @@ -552,10 +548,10 @@ public: void condp(AstNode* newp) { setOp1p(newp); } void addIfsp(AstNode* newp) { addOp2p(newp); } void addElsesp(AstNode* newp) { addOp3p(newp); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isGateDedupable() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isGateDedupable() const override { return true; } + int instrCount() const override { return INSTR_COUNT_BRANCH; } + bool same(const AstNode* /*samep*/) const override { return true; } void branchPred(VBranchPred flag) { m_branchPred = flag; } VBranchPred branchPred() const { return m_branchPred; } void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; } @@ -578,12 +574,12 @@ public: setNOp4p(msbp); } ASTGEN_MEMBERS_NodeReadWriteMem; - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* samep) const override { + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* samep) const override { return isHex() == static_cast(samep)->isHex(); } bool isHex() const { return m_isHex; } @@ -605,8 +601,8 @@ protected: public: ASTGEN_MEMBERS_NodeText; - virtual void dump(std::ostream& str = std::cout) const override; - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str = std::cout) const override; + bool same(const AstNode* samep) const override { const AstNodeText* asamep = static_cast(samep); return text() == asamep->text(); } @@ -643,8 +639,8 @@ public: UASSERT(sensesp, "Sensesp required arg"); } ASTGEN_MEMBERS_Active; - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } + void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } const char* broken() const override; void cloneRelink() override; // Statements are broken into pieces, as some must come before others. @@ -672,8 +668,8 @@ public: setNOp1p(exprp); } ASTGEN_MEMBERS_Arg; - virtual string name() const override { return m_name; } // * = Pin name, ""=go by number - virtual void name(const string& name) override { m_name = name; } + string name() const override { return m_name; } // * = Pin name, ""=go by number + void name(const string& name) override { m_name = name; } void exprp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expression connected to pin, nullptr if unconnected AstNode* exprp() const { return op1p(); } @@ -694,7 +690,7 @@ public: AstNode* fromp() const { return op1p(); } AstNode* dimp() const { return op2p(); } VAttrType attrType() const { return m_attrType; } - virtual void dump(std::ostream& str = std::cout) const override; + void dump(std::ostream& str = std::cout) const override; }; class AstBind final : public AstNode { // Parents: MODULE @@ -710,8 +706,8 @@ public: } ASTGEN_MEMBERS_Bind; // ACCESSORS - virtual string name() const override { return m_name; } // * = Bind Target name - virtual void name(const string& name) override { m_name = name; } + string name() const override { return m_name; } // * = Bind Target name + void name(const string& name) override { m_name = name; } AstNode* cellsp() const { return op1p(); } // op1 = cells }; class AstCFunc final : public AstNode { @@ -779,12 +775,12 @@ public: m_dpiTraceInit = false; } ASTGEN_MEMBERS_CFunc; - virtual string name() const override { return m_name; } + string name() const override { return m_name; } const char* broken() const override; void cloneRelink() override; - virtual bool maybePointedTo() const override { return true; } - virtual void dump(std::ostream& str = std::cout) const override; - virtual bool same(const AstNode* samep) const override { + bool maybePointedTo() const override { return true; } + void dump(std::ostream& str = std::cout) const override; + bool same(const AstNode* samep) const override { const AstCFunc* const asamep = static_cast(samep); return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid()) && (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits()) @@ -792,8 +788,8 @@ public: && (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name())); } // - virtual void name(const string& name) override { m_name = name; } - virtual int instrCount() const override { + void name(const string& name) override { m_name = name; } + int instrCount() const override { return dpiImportPrototype() ? v3Global.opt.instrCountDpi() : 0; } VBoolOrUnknown isConst() const { return m_isConst; } @@ -883,8 +879,8 @@ public: , m_useType{useType} , m_name{name} {} ASTGEN_MEMBERS_CUse; - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } + void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } VUseType useType() const { return m_useType; } }; class AstCaseItem final : public AstNode { @@ -899,7 +895,7 @@ public: addNOp2p(bodysp); } ASTGEN_MEMBERS_CaseItem; - virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } + int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions AstNode* bodysp() const { return op2p(); } // op2 = what to do void condsp(AstNode* nodep) { setOp1p(nodep); } @@ -922,7 +918,7 @@ public: dtypeFrom(dtp); } ASTGEN_MEMBERS_Cast; - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } virtual string emitVerilog() { return "((%d)'(%l))"; } virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } virtual bool cleanLhs() const { return true; } @@ -930,7 +926,7 @@ public: AstNode* lhsp() const { return op1p(); } AstNode* fromp() const { return lhsp(); } void lhsp(AstNode* nodep) { setOp1p(nodep); } - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_AS(op2p(), NodeDType); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } }; @@ -996,13 +992,13 @@ public: } ASTGEN_MEMBERS_Cell; // No cloneRelink, we presume cloneee's want the same module linkages - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; const char* broken() const override; - virtual bool maybePointedTo() const override { return true; } + bool maybePointedTo() const override { return true; } // ACCESSORS - virtual string name() const override { return m_name; } // * = Cell name - virtual void name(const string& name) override { m_name = name; } - virtual string origName() const override { return m_origName; } // * = Original name + string name() const override { return m_name; } // * = Cell name + void name(const string& name) override { m_name = name; } + string origName() const override { return m_origName; } // * = Original name void origName(const string& name) { m_origName = name; } string modName() const { return m_modName; } // * = Instance name void modName(const string& name) { m_modName = name; } @@ -1038,7 +1034,7 @@ public: } ASTGEN_MEMBERS_CellArrayRef; // ACCESSORS - virtual string name() const override { return m_name; } // * = Array name + string name() const override { return m_name; } // * = Array name AstNode* selp() const { return op1p(); } // op1 = Select expression }; class AstCellInline final : public AstNode { @@ -1061,12 +1057,12 @@ public: , m_origModName{origModName} , m_timeunit{timeunit} {} ASTGEN_MEMBERS_CellInline; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; const char* broken() const override; // ACCESSORS - virtual string name() const override { return m_name; } // * = Cell name + string name() const override { return m_name; } // * = Cell name string origModName() const { return m_origModName; } // * = modp()->origName() before inlining - virtual void name(const string& name) override { m_name = name; } + void name(const string& name) override { m_name = name; } void scopep(AstScope* scp) { m_scopep = scp; } AstScope* scopep() const { return m_scopep; } void timeunit(const VTimescale& flag) { m_timeunit = flag; } @@ -1085,7 +1081,7 @@ public: } ASTGEN_MEMBERS_CellRef; // ACCESSORS - virtual string name() const override { return m_name; } // * = Array name + string name() const override { return m_name; } // * = Array name AstNode* cellp() const { return op1p(); } // op1 = Cell AstNode* exprp() const { return op2p(); } // op2 = Expression }; @@ -1098,8 +1094,8 @@ public: setNOp2p(classOrPkgsp); // Only for parser } ASTGEN_MEMBERS_ClassExtends; - virtual bool hasDType() const override { return true; } - virtual string verilogKwd() const override { return "extends"; } + bool hasDType() const override { return true; } + string verilogKwd() const override { return "extends"; } AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNode* classOrPkgsp() const { return op2p(); } @@ -1120,21 +1116,21 @@ public: } ASTGEN_MEMBERS_ClassOrPackageRef; // METHODS - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists()); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_classOrPackageNodep && m_classOrPackageNodep->clonep()) { m_classOrPackageNodep = m_classOrPackageNodep->clonep(); } } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { return (m_classOrPackageNodep == static_cast(samep)->m_classOrPackageNodep); } - virtual void dump(std::ostream& str = std::cout) const override; - virtual string name() const override { return m_name; } // * = Var name + void dump(std::ostream& str = std::cout) const override; + string name() const override { return m_name; } // * = Var name AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } AstNodeModule* classOrPackagep() const; @@ -1169,9 +1165,9 @@ class AstConstPool final : public AstNode { public: explicit AstConstPool(FileLine* fl); ASTGEN_MEMBERS_ConstPool; - virtual bool maybePointedTo() const override { return true; } + bool maybePointedTo() const override { return true; } const char* broken() const override; - virtual void cloneRelink() override { V3ERROR_NA; } + void cloneRelink() override { V3ERROR_NA; } AstModule* modp() const { return m_modp; } // Find a table (unpacked array) within the constant pool which is initialized with the @@ -1201,9 +1197,9 @@ public: , m_path{path} { setOp1p(rhsp); } - virtual string name() const override { return m_name; } // * = Scope name + string name() const override { return m_name; } // * = Scope name ASTGEN_MEMBERS_DefParam; - virtual bool same(const AstNode*) const override { return true; } + bool same(const AstNode*) const override { return true; } AstNode* rhsp() const { return op1p(); } // op1 = Assign from string path() const { return m_path; } }; @@ -1224,7 +1220,7 @@ public: if (!packageOrClassp) return rhsp; return new AstDot(fl, true, packageOrClassp, rhsp); } - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; AstNode* lhsp() const { return op1p(); } void rhsp(AstNode* nodep) { setOp2p(nodep); } AstNode* rhsp() const { return op2p(); } @@ -1243,8 +1239,8 @@ public: , m_name{vname} , m_cname{cname} {} ASTGEN_MEMBERS_DpiExport; - virtual string name() const override { return m_name; } - virtual void name(const string& name) override { m_name = name; } + string name() const override { return m_name; } + void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } void cname(const string& cname) { m_cname = cname; } }; @@ -1257,24 +1253,20 @@ private: public: inline AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp); ASTGEN_MEMBERS_ElabDisplay; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!fmtp()); return nullptr; } - virtual string verilogKwd() const override { - return (string("$") + string(displayType().ascii())); - } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* samep) const override { + string verilogKwd() const override { return (string("$") + string(displayType().ascii())); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: $display makes output + bool isUnlikely() const override { return true; } + bool same(const AstNode* samep) const override { return displayType() == static_cast(samep)->displayType(); } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } + int instrCount() const override { return INSTR_COUNT_PLI; } VDisplayType displayType() const { return m_displayType; } void displayType(VDisplayType type) { m_displayType = type; } void fmtp(AstSFormatF* nodep) { addOp1p((AstNode*)nodep); } // op1 = To-String formatter @@ -1286,7 +1278,7 @@ public: explicit AstEmpty(FileLine* fl) : ASTGEN_SUPER_Empty(fl) {} ASTGEN_MEMBERS_Empty; - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstExecGraph final : public AstNode { // For parallel execution, this node contains a dependency graph. Each @@ -1303,11 +1295,11 @@ public: explicit AstExecGraph(FileLine* fl, const string& name); ASTGEN_MEMBERS_ExecGraph; ~AstExecGraph() override; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!m_depGraphp); return nullptr; } - virtual string name() const override { return m_name; } + string name() const override { return m_name; } V3Graph* depGraphp() { return m_depGraphp; } const V3Graph* depGraphp() const { return m_depGraphp; } // op1: The mtask bodies @@ -1346,11 +1338,11 @@ public: addNOp1p(defaultp); } ASTGEN_MEMBERS_InitArray; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; const char* broken() const override; void cloneRelink() override; - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { + bool hasDType() const override { return true; } + bool same(const AstNode* samep) const override { // Only works if exact same children, instead should override comparison // of children list, and instead use map-vs-map key/value compare return m_map == static_cast(samep)->m_map; @@ -1375,8 +1367,8 @@ public: addOp1p(valuep); } ASTGEN_MEMBERS_InitItem; - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return false; } // See valuep()'s dtype instead + bool maybePointedTo() const override { return true; } + bool hasDType() const override { return false; } // See valuep()'s dtype instead AstNode* valuep() const { return op1p(); } // op1 = Value void valuep(AstNode* nodep) { addOp1p(nodep); } }; @@ -1388,7 +1380,7 @@ public: AstIntfRef(FileLine* fl, const string& name) : ASTGEN_SUPER_IntfRef(fl) , m_name{name} {} - virtual string name() const override { return m_name; } + string name() const override { return m_name; } ASTGEN_MEMBERS_IntfRef; }; class AstMTaskBody final : public AstNode { @@ -1400,7 +1392,7 @@ public: explicit AstMTaskBody(FileLine* fl) : ASTGEN_SUPER_MTaskBody(fl) {} ASTGEN_MEMBERS_MTaskBody; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!m_execMTaskp); return nullptr; } @@ -1415,7 +1407,7 @@ public: } ExecMTask* execMTaskp() const { return m_execMTaskp; } void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; } - virtual void dump(std::ostream& str = std::cout) const override; + void dump(std::ostream& str = std::cout) const override; }; class AstModport final : public AstNode { // A modport in an interface @@ -1427,8 +1419,8 @@ public: , m_name{name} { addNOp1p(varsp); } - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } + string name() const override { return m_name; } + bool maybePointedTo() const override { return true; } ASTGEN_MEMBERS_Modport; AstNode* varsp() const { return op1p(); } // op1 = List of Vars }; @@ -1449,8 +1441,8 @@ public: ASTGEN_MEMBERS_ModportFTaskRef; const char* broken() const override; void cloneRelink() override; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } bool isImport() const { return !m_export; } bool isExport() const { return m_export; } AstNodeFTask* ftaskp() const { return m_ftaskp; } // [After Link] Pointer to variable @@ -1472,8 +1464,8 @@ public: ASTGEN_MEMBERS_ModportVarRef; const char* broken() const override; void cloneRelink() override; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } void direction(const VDirection& flag) { m_direction = flag; } VDirection direction() const { return m_direction; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -1501,9 +1493,9 @@ public: AstNetlist(); ASTGEN_MEMBERS_Netlist; const char* broken() const override; - virtual void cloneRelink() override { V3ERROR_NA; } - virtual string name() const override { return "$root"; } - virtual void dump(std::ostream& str) const override; + void cloneRelink() override { V3ERROR_NA; } + string name() const override { return "$root"; } + void dump(std::ostream& str) const override; AstNodeModule* modulesp() const { // op1 = List of modules return VN_AS(op1p(), NodeModule); } @@ -1553,8 +1545,8 @@ public: ASTGEN_MEMBERS_PackageExport; const char* broken() const override; void cloneRelink() override; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -1579,8 +1571,8 @@ public: ASTGEN_MEMBERS_PackageImport; const char* broken() const override; void cloneRelink() override; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } + void dump(std::ostream& str) const override; + string name() const override { return m_name; } AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -1604,13 +1596,13 @@ public: setNOp2p((AstNode*)ftaskrefp); } ASTGEN_MEMBERS_ParseRef; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str) const override; + string name() const override { return m_name; } // * = Var name + bool same(const AstNode* samep) const override { const AstParseRef* const asamep = static_cast(samep); return (expect() == asamep->expect() && m_name == asamep->m_name); } - virtual void name(const string& name) override { m_name = name; } + void name(const string& name) override { m_name = name; } VParseRefExp expect() const { return m_expect; } void expect(VParseRefExp exp) { m_expect = exp; } // op1 = Components @@ -1637,10 +1629,10 @@ public: } inline AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp); ASTGEN_MEMBERS_Pin; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; const char* broken() const override; - virtual string name() const override { return m_name; } // * = Pin name, ""=go by number - virtual void name(const string& name) override { m_name = name; } + string name() const override { return m_name; } // * = Pin name, ""=go by number + void name(const string& name) override { m_name = name; } string prettyOperatorName() const override; bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked int pinNum() const { return m_pinNum; } @@ -1668,7 +1660,7 @@ public: , m_pinNum{pinnum} , m_name{name} {} ASTGEN_MEMBERS_Port; - virtual string name() const override { return m_name; } // * = Port name + string name() const override { return m_name; } // * = Port name int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation AstNode* exprp() const { return op1p(); } // op1 = Expression connected to port }; @@ -1683,8 +1675,8 @@ public: , m_pragType{pragType} {} ASTGEN_MEMBERS_Pragma; VPragmaType pragType() const { return m_pragType; } // *=type of the pragma - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* samep) const override { + bool isPredictOptimizable() const override { return false; } + bool same(const AstNode* samep) const override { return pragType() == static_cast(samep)->pragType(); } }; @@ -1700,7 +1692,7 @@ public: addOp3p(propp); } ASTGEN_MEMBERS_PropClocked; - virtual bool hasDType() const override { + bool hasDType() const override { return true; } // Used under Cover, which expects a bool child AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } // op1 = Sensitivity list @@ -1718,7 +1710,7 @@ public: setOp1p(lhsp); } ASTGEN_MEMBERS_Pull; - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { return direction() == static_cast(samep)->direction(); } void lhsp(AstNode* np) { setOp1p(np); } @@ -1758,13 +1750,13 @@ public: addNOp2p(nullptr); } ASTGEN_MEMBERS_SFormatF; - virtual string name() const override { return m_text; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { + string name() const override { return m_text; } + int instrCount() const override { return INSTR_COUNT_PLI; } + bool hasDType() const override { return true; } + bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } - virtual string verilogKwd() const override { return "$sformatf"; } + string verilogKwd() const override { return "$sformatf"; } void addExprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display @@ -1800,12 +1792,12 @@ public: , m_aboveCellp{aboveCellp} , m_modp{modp} {} ASTGEN_MEMBERS_Scope; - virtual void cloneRelink() override; - virtual const char* broken() const override; - virtual bool maybePointedTo() const override { return true; } - virtual string name() const override { return m_name; } // * = Scope name - virtual void name(const string& name) override { m_name = name; } - virtual void dump(std::ostream& str) const override; + void cloneRelink() override; + const char* broken() const override; + bool maybePointedTo() const override { return true; } + string name() const override { return m_name; } // * = Scope name + void name(const string& name) override { m_name = name; } + void dump(std::ostream& str) const override; string nameDotless() const; string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); } AstNodeModule* modp() const { return m_modp; } @@ -1829,8 +1821,8 @@ public: addNOp2p(elementsp); } ASTGEN_MEMBERS_SelLoopVars; - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool maybePointedTo() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } + bool maybePointedTo() const override { return false; } AstNode* fromp() const { return op1p(); } void fromp(AstNode* nodep) { setOp1p(nodep); } AstNode* elementsp() const { return op2p(); } @@ -1867,8 +1859,8 @@ public: : ASTGEN_SUPER_SenItem(fl) , m_edgeType{VEdgeType::ET_NEVER} {} ASTGEN_MEMBERS_SenItem; - virtual void dump(std::ostream& str) const override; - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str) const override; + bool same(const AstNode* samep) const override { return edgeType() == static_cast(samep)->edgeType(); } VEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge @@ -1901,8 +1893,8 @@ public: addNOp1p(sensesp); } ASTGEN_MEMBERS_SenTree; - virtual void dump(std::ostream& str) const override; - virtual bool maybePointedTo() const override { return true; } + void dump(std::ostream& str) const override; + bool maybePointedTo() const override { return true; } bool isMulti() const { return m_multi; } // op1 = Sensitivity list AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } @@ -1935,7 +1927,7 @@ public: ASTGEN_MEMBERS_StrengthSpec; VStrength strength0() { return m_s0; } VStrength strength1() { return m_s1; } - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; }; class AstTopScope final : public AstNode { // A singleton, held under the top level AstModule. Holds the top level AstScope, @@ -1950,7 +1942,7 @@ class AstTopScope final : public AstNode { public: ASTGEN_MEMBERS_TopScope; - virtual bool maybePointedTo() const override { return true; } + bool maybePointedTo() const override { return true; } AstSenTree* senTreesp() const { return VN_AS(op1p(), SenTree); } void addSenTreep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } AstScope* scopep() const { return VN_AS(op2p(), Scope); } @@ -1969,14 +1961,14 @@ class AstTypeTable final : public AstNode { public: explicit AstTypeTable(FileLine* fl); ASTGEN_MEMBERS_TypeTable; - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { + bool maybePointedTo() const override { return true; } + const char* broken() const override { BROKEN_RTN(m_emptyQueuep && !m_emptyQueuep->brokeExists()); BROKEN_RTN(m_queueIndexp && !m_queueIndexp->brokeExists()); BROKEN_RTN(m_voidp && !m_voidp->brokeExists()); return nullptr; } - virtual void cloneRelink() override { V3ERROR_NA; } + void cloneRelink() override { V3ERROR_NA; } AstNodeDType* typesp() const { return VN_AS(op1p(), NodeDType); } // op1 = List of dtypes void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); } AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd); @@ -1990,7 +1982,7 @@ public: AstVoidDType* findVoidDType(FileLine* fl); void clearCache(); void repairCache(); - virtual void dump(std::ostream& str = std::cout) const override; + void dump(std::ostream& str = std::cout) const override; }; class AstTypedef final : public AstNode { private: @@ -2007,8 +1999,8 @@ public: dtypep(nullptr); // V3Width will resolve } ASTGEN_MEMBERS_Typedef; - virtual void dump(std::ostream& str) const override; - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + void dump(std::ostream& str) const override; + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } @@ -2016,14 +2008,14 @@ public: void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse // METHODS - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual void name(const string& flag) override { m_name = flag; } + string name() const override { return m_name; } + bool maybePointedTo() const override { return true; } + bool hasDType() const override { return true; } + void name(const string& flag) override { m_name = flag; } bool attrPublic() const { return m_attrPublic; } void attrPublic(bool flag) { m_attrPublic = flag; } - virtual void tag(const string& text) override { m_tag = text; } - virtual string tag() const override { return m_tag; } + void tag(const string& text) override { m_tag = text; } + string tag() const override { return m_tag; } }; class AstTypedefFwd final : public AstNode { // Forward declaration of a type; stripped after netlist parsing is complete @@ -2036,8 +2028,8 @@ public: , m_name{name} {} ASTGEN_MEMBERS_TypedefFwd; // METHODS - virtual string name() const override { return m_name; } - virtual bool maybePointedTo() const override { return true; } + string name() const override { return m_name; } + bool maybePointedTo() const override { return true; } }; class AstUdpTable final : public AstNode { public: @@ -2057,7 +2049,7 @@ public: : ASTGEN_SUPER_UdpTableLine(fl) , m_text{text} {} ASTGEN_MEMBERS_UdpTableLine; - virtual string name() const override { return m_text; } + string name() const override { return m_text; } string text() const { return m_text; } }; class AstUnlinkedRef final : public AstNode { @@ -2073,7 +2065,7 @@ public: } ASTGEN_MEMBERS_UnlinkedRef; // ACCESSORS - virtual string name() const override { return m_name; } // * = Var name + string name() const override { return m_name; } // * = Var name AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef }; @@ -2232,11 +2224,11 @@ public: m_declKwd = examplep->declKwd(); } ASTGEN_MEMBERS_Var; - virtual void dump(std::ostream& str) const override; - virtual string name() const override { return m_name; } // * = Var name - virtual bool hasDType() const override { return true; } - virtual bool maybePointedTo() const override { return true; } - virtual string origName() const override { return m_origName; } // * = Original name + void dump(std::ostream& str) const override; + string name() const override { return m_name; } // * = Var name + bool hasDType() const override { return true; } + bool maybePointedTo() const override { return true; } + string origName() const override { return m_origName; } // * = Original name void origName(const string& name) { m_origName = name; } VVarType varType() const { return m_varType; } // * = Type of variable void direction(const VDirection& flag) { @@ -2269,7 +2261,7 @@ public: string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc string vlPropDecl(const string& propName) const; // Return VerilatorVarProps declaration void combineType(VVarType type); - virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } // op2 = Net delay @@ -2340,9 +2332,9 @@ public: bool isForceable() const { return m_isForceable; } void setForceable() { m_isForceable = true; } // METHODS - virtual void name(const string& name) override { m_name = name; } - virtual void tag(const string& text) override { m_tag = text; } - virtual string tag() const override { return m_tag; } + void name(const string& name) override { m_name = name; } + void tag(const string& text) override { m_tag = text; } + string tag() const override { return m_tag; } bool isAnsi() const { return m_ansi; } bool isContinuously() const { return m_isContinuously; } bool isDeclTyped() const { return m_declTyped; } @@ -2406,7 +2398,7 @@ public: bool attrSplitVar() const { return m_attrSplitVar; } bool attrIsolateAssign() const { return m_attrIsolateAssign; } VVarAttrClocker attrClocker() const { return m_attrClocker; } - virtual string verilogKwd() const override; + string verilogKwd() const override; void lifetime(const VLifetime& flag) { m_lifetime = flag; } VLifetime lifetime() const { return m_lifetime; } void propagateAttrFrom(AstVar* fromp) { @@ -2469,22 +2461,22 @@ public: dtypeFrom(varp); } ASTGEN_MEMBERS_VarScope; - virtual void cloneRelink() override { + void cloneRelink() override { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); UASSERT(m_scopep->clonep(), "No clone cross link: " << this); m_scopep = m_scopep->clonep(); } } - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(m_varp && !m_varp->brokeExists()); BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); return nullptr; } - virtual bool maybePointedTo() const override { return true; } - virtual string name() const override { return scopep()->name() + "->" + varp()->name(); } - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } + bool maybePointedTo() const override { return true; } + string name() const override { return scopep()->name() + "->" + varp()->name(); } + void dump(std::ostream& str) const override; + bool hasDType() const override { return true; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable AstScope* scopep() const { return m_scopep; } // Pointer to scope it's under void scopep(AstScope* nodep) { m_scopep = nodep; } @@ -2510,7 +2502,7 @@ public: , m_generate{generate} , m_implied{implied} {} ASTGEN_MEMBERS_Begin; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; // op1p is statements in NodeBlock AstNode* genforp() const { return op2p(); } // op2 = GENFOR, if applicable, // might NOT be a GenFor, as loop unrolling replaces with Begin @@ -2530,7 +2522,7 @@ public: AstFork(FileLine* fl, const string& name, AstNode* stmtsp) : ASTGEN_SUPER_Fork(fl, name, stmtsp) {} ASTGEN_MEMBERS_Fork; - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; VJoinType joinType() const { return m_joinType; } void joinType(const VJoinType& flag) { m_joinType = flag; } }; @@ -2544,7 +2536,7 @@ public: addNOp1p(fvarsp); } ASTGEN_MEMBERS_Func; - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } }; class AstTask final : public AstNodeFTask { // A task inside a module @@ -2569,7 +2561,7 @@ public: , m_source{false} , m_support{false} {} ASTGEN_MEMBERS_CFile; - virtual void dump(std::ostream& str = std::cout) const override; + void dump(std::ostream& str = std::cout) const override; bool slow() const { return m_slow; } void slow(bool flag) { m_slow = flag; } bool source() const { return m_source; } @@ -2584,7 +2576,7 @@ public: AstVFile(FileLine* fl, const string& name) : ASTGEN_SUPER_VFile(fl, name) {} ASTGEN_MEMBERS_VFile; - virtual void dump(std::ostream& str = std::cout) const override; + void dump(std::ostream& str = std::cout) const override; }; // === AstNodeModule === @@ -2602,12 +2594,12 @@ public: AstClass(FileLine* fl, const string& name) : ASTGEN_SUPER_Class(fl, name) {} ASTGEN_MEMBERS_Class; - virtual string verilogKwd() const override { return "class"; } - virtual bool maybePointedTo() const override { return true; } - virtual void dump(std::ostream& str) const override; + string verilogKwd() const override { return "class"; } + bool maybePointedTo() const override { return true; } + void dump(std::ostream& str) const override; const char* broken() const override; void cloneRelink() override; - virtual bool timescaleMatters() const override { return false; } + bool timescaleMatters() const override { return false; } // op1/op2/op3 in AstNodeModule AstClassPackage* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; } @@ -2640,10 +2632,10 @@ public: AstClassPackage(FileLine* fl, const string& name) : ASTGEN_SUPER_ClassPackage(fl, name) {} ASTGEN_MEMBERS_ClassPackage; - virtual string verilogKwd() const override { return "classpackage"; } - virtual const char* broken() const override; - virtual void cloneRelink() override; - virtual bool timescaleMatters() const override { return false; } + string verilogKwd() const override { return "classpackage"; } + const char* broken() const override; + void cloneRelink() override; + bool timescaleMatters() const override { return false; } AstClass* classp() const { return m_classp; } void classp(AstClass* classp) { m_classp = classp; } }; @@ -2655,8 +2647,8 @@ public: ASTGEN_MEMBERS_Iface; // Interfaces have `timescale applicability but lots of code seems to // get false warnings if we enable this - virtual string verilogKwd() const override { return "interface"; } - virtual bool timescaleMatters() const override { return false; } + string verilogKwd() const override { return "interface"; } + bool timescaleMatters() const override { return false; } }; class AstModule final : public AstNodeModule { // A module declaration @@ -2667,8 +2659,8 @@ public: : ASTGEN_SUPER_Module(fl, name) , m_isProgram{program} {} ASTGEN_MEMBERS_Module; - virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; } - virtual bool timescaleMatters() const override { return true; } + string verilogKwd() const override { return m_isProgram ? "program" : "module"; } + bool timescaleMatters() const override { return true; } }; class AstNotFoundModule final : public AstNodeModule { // A missing module declaration @@ -2676,8 +2668,8 @@ public: AstNotFoundModule(FileLine* fl, const string& name) : ASTGEN_SUPER_NotFoundModule(fl, name) {} ASTGEN_MEMBERS_NotFoundModule; - virtual string verilogKwd() const override { return "/*not-found-*/ module"; } - virtual bool timescaleMatters() const override { return false; } + string verilogKwd() const override { return "/*not-found-*/ module"; } + bool timescaleMatters() const override { return false; } }; class AstPackage final : public AstNodeModule { // A package declaration @@ -2685,8 +2677,8 @@ public: AstPackage(FileLine* fl, const string& name) : ASTGEN_SUPER_Package(fl, name) {} ASTGEN_MEMBERS_Package; - virtual string verilogKwd() const override { return "package"; } - virtual bool timescaleMatters() const override { return !isDollarUnit(); } + string verilogKwd() const override { return "package"; } + bool timescaleMatters() const override { return !isDollarUnit(); } static string dollarUnitName() { return AstNode::encodeName("$unit"); } bool isDollarUnit() const { return name() == dollarUnitName(); } }; @@ -2696,8 +2688,8 @@ public: AstPrimitive(FileLine* fl, const string& name) : ASTGEN_SUPER_Primitive(fl, name) {} ASTGEN_MEMBERS_Primitive; - virtual string verilogKwd() const override { return "primitive"; } - virtual bool timescaleMatters() const override { return false; } + string verilogKwd() const override { return "primitive"; } + bool timescaleMatters() const override { return false; } }; // === AstNodePreSel === @@ -2755,7 +2747,7 @@ public: } ASTGEN_MEMBERS_Always; // - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list void sensesp(AstSenTree* nodep) { setOp1p(nodep); } VAlwaysKwd keyword() const { return m_keyword; } @@ -2818,10 +2810,10 @@ public: ASTGEN_MEMBERS_BracketRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node - virtual bool maybePointedTo() const override { return false; } + bool maybePointedTo() const override { return false; } AstNode* elementsp() const { return op1p(); } }; class AstRange final : public AstNodeRange { @@ -2851,9 +2843,9 @@ public: } int elementsConst() const { return hiConst() - loConst() + 1; } bool littleEndian() const { return leftConst() < rightConst(); } - virtual void dump(std::ostream& str) const override; + void dump(std::ostream& str) const override; virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstUnsizedRange final : public AstNodeRange { // Unsized range specification, for open arrays @@ -2863,7 +2855,7 @@ public: ASTGEN_MEMBERS_UnsizedRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[]"; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstWildcardRange final : public AstNodeRange { // Wildcard range specification, for wildcard index type associative arrays @@ -2873,7 +2865,7 @@ public: ASTGEN_MEMBERS_WildcardRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[*]"; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; // === AstNodeStmt === @@ -2887,7 +2879,7 @@ public: addNOp2p(bodysp); } ASTGEN_MEMBERS_AlwaysPublic; - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } // AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate @@ -2901,8 +2893,8 @@ public: explicit AstBreak(FileLine* fl) : ASTGEN_SUPER_Break(fl) {} ASTGEN_MEMBERS_Break; - virtual string verilogKwd() const override { return "break"; } - virtual bool isBrancher() const override { + string verilogKwd() const override { return "break"; } + bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -2929,14 +2921,14 @@ public: addNOp2p(pinsp); } ASTGEN_MEMBERS_CMethodHard; - virtual string name() const override { return m_name; } // * = Var name - virtual bool hasDType() const override { return true; } - virtual void name(const string& name) override { m_name = name; } - virtual bool same(const AstNode* samep) const override { + string name() const override { return m_name; } // * = Var name + bool hasDType() const override { return true; } + void name(const string& name) override { m_name = name; } + bool same(const AstNode* samep) const override { const AstCMethodHard* asamep = static_cast(samep); return (m_name == asamep->m_name); } - virtual bool isPure() const override { return m_pure; } + bool isPure() const override { return m_pure; } void pure(bool flag) { m_pure = flag; } void makeStatement() { statement(true); @@ -2957,9 +2949,9 @@ public: addNOp1p((AstNode*)exprsp); } ASTGEN_MEMBERS_CReset; - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } AstVarRef* varrefp() const { return VN_AS(op1p(), VarRef); } // op1 = varref to reset }; class AstCReturn final : public AstNodeStmt { @@ -2972,8 +2964,8 @@ public: setOp1p(lhsp); } ASTGEN_MEMBERS_CReturn; - virtual int instrCount() const override { return widthInstrs(); } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return widthInstrs(); } + bool same(const AstNode* /*samep*/) const override { return true; } // AstNode* lhsp() const { return op1p(); } }; @@ -2986,9 +2978,9 @@ public: } inline AstCStmt(FileLine* fl, const string& textStmt); ASTGEN_MEMBERS_CStmt; - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool same(const AstNode* /*samep*/) const override { return true; } void addBodysp(AstNode* nodep) { addNOp1p(nodep); } AstNode* bodysp() const { return op1p(); } // op1 = expressions to print }; @@ -3004,10 +2996,10 @@ public: ASTGEN_MEMBERS_ChangeDet; AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual int instrCount() const override { return widthInstrs() * 2; } // xor, or/logor - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + int instrCount() const override { return widthInstrs() * 2; } // xor, or/logor + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstComment final : public AstNodeStmt { // Some comment to put into the output stream @@ -3022,10 +3014,8 @@ public: , m_showAt{showAt} , m_name{name} {} ASTGEN_MEMBERS_Comment; - virtual string name() const override { return m_name; } // * = Text - virtual bool same(const AstNode* samep) const override { - return true; - } // Ignore name in comments + string name() const override { return m_name; } // * = Text + bool same(const AstNode* samep) const override { return true; } // Ignore name in comments virtual bool showAt() const { return m_showAt; } }; class AstContinue final : public AstNodeStmt { @@ -3033,8 +3023,8 @@ public: explicit AstContinue(FileLine* fl) : ASTGEN_SUPER_Continue(fl) {} ASTGEN_MEMBERS_Continue; - virtual string verilogKwd() const override { return "continue"; } - virtual bool isBrancher() const override { + string verilogKwd() const override { return "continue"; } + bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -3060,19 +3050,19 @@ public: , m_linescov{linescov} , m_offset{offset} {} ASTGEN_MEMBERS_CoverDecl; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing v3fatalSrc("dataDeclp should point to real data, not be a list"); } return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } - virtual bool maybePointedTo() const override { return true; } + void dump(std::ostream& str) const override; + int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } + bool maybePointedTo() const override { return true; } void binNum(int flag) { m_binNum = flag; } int binNum() const { return m_binNum; } int offset() const { return m_offset; } @@ -3082,12 +3072,12 @@ public: const string& hier() const { return m_hier; } void hier(const string& flag) { m_hier = flag; } void comment(const string& flag) { m_text = flag; } - virtual bool same(const AstNode* samep) const override { + bool same(const AstNode* samep) const override { const AstCoverDecl* const asamep = static_cast(samep); return (fileline() == asamep->fileline() && linescov() == asamep->linescov() && hier() == asamep->hier() && comment() == asamep->comment()); } - virtual bool isPredictOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } void dataDeclp(AstCoverDecl* nodep) { m_dataDeclp = nodep; } // dataDecl nullptr means "use this one", but often you want "this" to // indicate to get data from here @@ -3105,21 +3095,21 @@ public: : ASTGEN_SUPER_CoverInc(fl) , m_declp{declp} {} ASTGEN_MEMBERS_CoverInc; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!declp()->brokeExists()); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_declp->clonep()) m_declp = m_declp->clonep(); } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str) const override; + int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } + bool same(const AstNode* samep) const override { return declp() == static_cast(samep)->declp(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isOutputter() const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isOutputter() const override { return true; } // but isPure() true AstCoverDecl* declp() const { return m_declp; } // Where defined }; @@ -3135,11 +3125,11 @@ public: setOp3p(changep); } ASTGEN_MEMBERS_CoverToggle; - virtual int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return true; } - virtual bool isOutputter() const override { + int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } + bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return true; } + bool isOutputter() const override { return false; // Though the AstCoverInc under this is an outputter } // but isPure() true @@ -3157,7 +3147,7 @@ public: setNOp2p(stmtsp); } ASTGEN_MEMBERS_Delay; - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } // AstNode* lhsp() const { return op1p(); } // op1 = delay value void lhsp(AstNode* nodep) { setOp1p(nodep); } @@ -3172,9 +3162,9 @@ public: : ASTGEN_SUPER_Disable(fl) , m_name{name} {} ASTGEN_MEMBERS_Disable; - virtual string name() const override { return m_name; } // * = Block name - virtual void name(const string& flag) override { m_name = flag; } - virtual bool isBrancher() const override { + string name() const override { return m_name; } // * = Block name + void name(const string& flag) override { m_name = flag; } + bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -3208,26 +3198,24 @@ public: setNOp3p(filep); } ASTGEN_MEMBERS_Display; - virtual void dump(std::ostream& str) const override; - virtual const char* broken() const override { + void dump(std::ostream& str) const override; + const char* broken() const override { BROKEN_RTN(!fmtp()); return nullptr; } - virtual string verilogKwd() const override { + string verilogKwd() const override { return (filep() ? string("$f") + string(displayType().ascii()) : string("$") + string(displayType().ascii())); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* samep) const override { + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: $display makes output + bool isUnlikely() const override { return true; } + bool same(const AstNode* samep) const override { return displayType() == static_cast(samep)->displayType(); } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } + int instrCount() const override { return INSTR_COUNT_PLI; } VDisplayType displayType() const { return m_displayType; } void displayType(VDisplayType type) { m_displayType = type; } // * = Add a newline for $display @@ -3256,12 +3244,12 @@ public: setNOp1p(exprp); } ASTGEN_MEMBERS_DumpCtl; - virtual string verilogKwd() const override { return ctlType().ascii(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isOutputter() const override { return true; } + string verilogKwd() const override { return ctlType().ascii(); } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isOutputter() const override { return true; } virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } VDumpCtlType ctlType() const { return m_ctlType; } AstNode* exprp() const { return op1p(); } // op2 = Expressions to output void exprp(AstNode* nodep) { setOp1p(nodep); } @@ -3275,12 +3263,12 @@ public: setNOp2p(stmtsp); } ASTGEN_MEMBERS_EventControl; - virtual string verilogKwd() const override { return "@(%l) %r"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return false; } - virtual int instrCount() const override { return 0; } + string verilogKwd() const override { return "@(%l) %r"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return false; } + int instrCount() const override { return 0; } AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } AstNode* stmtsp() const { return op2p(); } }; @@ -3293,13 +3281,13 @@ public: setNOp2p(filep); } ASTGEN_MEMBERS_FClose; - virtual string verilogKwd() const override { return "$fclose"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$fclose"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; @@ -3312,13 +3300,13 @@ public: setNOp2p(filep); } ASTGEN_MEMBERS_FFlush; - virtual string verilogKwd() const override { return "$fflush"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$fflush"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; @@ -3332,13 +3320,13 @@ public: setOp3p(modep); } ASTGEN_MEMBERS_FOpen; - virtual string verilogKwd() const override { return "$fopen"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$fopen"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op1p(); } AstNode* filenamep() const { return op2p(); } AstNode* modep() const { return op3p(); } @@ -3352,13 +3340,13 @@ public: setOp2p(filenamep); } ASTGEN_MEMBERS_FOpenMcd; - virtual string verilogKwd() const override { return "$fopen"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$fopen"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* filep() const { return op1p(); } AstNode* filenamep() const { return op2p(); } }; @@ -3367,17 +3355,13 @@ public: explicit AstFinish(FileLine* fl) : ASTGEN_SUPER_Finish(fl) {} ASTGEN_MEMBERS_Finish; - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual int instrCount() const override { return 0; } // Rarely executes - virtual bool same(const AstNode* samep) const override { - return fileline() == samep->fileline(); - } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: $display makes output + bool isUnlikely() const override { return true; } + int instrCount() const override { return 0; } // Rarely executes + bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } }; class AstForeach final : public AstNodeStmt { public: @@ -3389,9 +3373,9 @@ public: ASTGEN_MEMBERS_Foreach; AstNode* arrayp() const { return op1p(); } // op1 = array and index vars AstNode* bodysp() const { return op4p(); } // op4 = body of loop - virtual bool isGateOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_BRANCH; } + bool same(const AstNode* /*samep*/) const override { return true; } bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } }; class AstJumpBlock final : public AstNodeStmt { @@ -3407,12 +3391,12 @@ public: : ASTGEN_SUPER_JumpBlock(fl) { addNOp1p(stmtsp); } - virtual const char* broken() const override; - virtual void cloneRelink() override; + const char* broken() const override; + void cloneRelink() override; ASTGEN_MEMBERS_JumpBlock; - virtual int instrCount() const override { return 0; } - virtual bool maybePointedTo() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return 0; } + bool maybePointedTo() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } // op1 = Statements AstNode* stmtsp() const { return op1p(); } // op1 = List of statements void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } @@ -3437,13 +3421,13 @@ public: ASTGEN_MEMBERS_JumpGo; const char* broken() const override; void cloneRelink() override; - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str) const override; + int instrCount() const override { return INSTR_COUNT_BRANCH; } + bool same(const AstNode* samep) const override { return labelp() == static_cast(samep)->labelp(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isBrancher() const override { + bool isGateOptimizable() const override { return false; } + bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } AstJumpLabel* labelp() const { return m_labelp; } @@ -3459,18 +3443,18 @@ public: : ASTGEN_SUPER_JumpLabel(fl) , m_blockp{blockp} {} ASTGEN_MEMBERS_JumpLabel; - virtual bool maybePointedTo() const override { return true; } - virtual const char* broken() const override { + bool maybePointedTo() const override { return true; } + const char* broken() const override { BROKEN_RTN(!blockp()->brokeExistsAbove()); BROKEN_RTN(blockp()->labelp() != this); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_blockp->clonep()) m_blockp = m_blockp->clonep(); } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 0; } - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str) const override; + int instrCount() const override { return 0; } + bool same(const AstNode* samep) const override { return blockp() == static_cast(samep)->blockp(); } AstJumpBlock* blockp() const { return m_blockp; } @@ -3483,15 +3467,13 @@ public: : ASTGEN_SUPER_MonitorOff(fl) , m_off{off} {} ASTGEN_MEMBERS_MonitorOff; - virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; } - virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt - virtual bool isPredictOptimizable() const override { - return false; - } // Though deleted before opt - virtual bool isPure() const override { return false; } // Though deleted before opt - virtual bool isOutputter() const override { return true; } // Though deleted before opt - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* samep) const override { + string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; } + bool isGateOptimizable() const override { return false; } // Though deleted before opt + bool isPredictOptimizable() const override { return false; } // Though deleted before opt + bool isPure() const override { return false; } // Though deleted before opt + bool isOutputter() const override { return true; } // Though deleted before opt + int instrCount() const override { return INSTR_COUNT_PLI; } + bool same(const AstNode* samep) const override { return m_off == static_cast(samep)->m_off; } bool off() const { return m_off; } @@ -3504,15 +3486,15 @@ public: explicit AstPrintTimeScale(FileLine* fl) : ASTGEN_SUPER_PrintTimeScale(fl) {} ASTGEN_MEMBERS_PrintTimeScale; - virtual void name(const string& name) override { m_name = name; } - virtual string name() const override { return m_name; } // * = Var name - virtual void dump(std::ostream& str) const override; - virtual string verilogKwd() const override { return "$printtimescale"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } + void name(const string& name) override { m_name = name; } + string name() const override { return m_name; } // * = Var name + void dump(std::ostream& str) const override; + string verilogKwd() const override { return "$printtimescale"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + int instrCount() const override { return INSTR_COUNT_PLI; } void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -3536,11 +3518,9 @@ public: ASTGEN_MEMBERS_Repeat; AstNode* countp() const { return op2p(); } // op2 = condition to continue AstNode* bodysp() const { return op3p(); } // op3 = body of loop - virtual bool isGateOptimizable() const override { - return false; - } // Not relevant - converted to FOR - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } // Not relevant - converted to FOR + int instrCount() const override { return INSTR_COUNT_BRANCH; } + bool same(const AstNode* /*samep*/) const override { return true; } bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } }; class AstReturn final : public AstNodeStmt { @@ -3550,9 +3530,9 @@ public: setNOp1p(lhsp); } ASTGEN_MEMBERS_Return; - virtual string verilogKwd() const override { return "return"; } + string verilogKwd() const override { return "return"; } AstNode* lhsp() const { return op1p(); } - virtual bool isBrancher() const override { + bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -3573,18 +3553,18 @@ public: setOp3p(lhsp); } ASTGEN_MEMBERS_SFormat; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!fmtp()); return nullptr; } - virtual string verilogKwd() const override { return "$sformat"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return true; } - virtual bool isPure() const override { return true; } - virtual bool isOutputter() const override { return false; } + string verilogKwd() const override { return "$sformat"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return true; } + bool isPure() const override { return true; } + bool isOutputter() const override { return false; } virtual bool cleanOut() const { return false; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + int instrCount() const override { return INSTR_COUNT_PLI; } + bool same(const AstNode* /*samep*/) const override { return true; } void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } AstNode* lhsp() const { return op3p(); } @@ -3595,17 +3575,13 @@ public: AstStop(FileLine* fl, bool maybe) : ASTGEN_SUPER_Stop(fl) {} ASTGEN_MEMBERS_Stop; - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { - return false; - } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const override { return true; } - virtual int instrCount() const override { return 0; } // Rarely executes - virtual bool same(const AstNode* samep) const override { - return fileline() == samep->fileline(); - } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering + bool isOutputter() const override { return true; } // SPECIAL: $display makes output + bool isUnlikely() const override { return true; } + int instrCount() const override { return 0; } // Rarely executes + bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } }; class AstSysFuncAsTask final : public AstNodeStmt { // Call what is normally a system function (with a return) in a non-return context @@ -3617,13 +3593,13 @@ public: addNOp1p(exprsp); } ASTGEN_MEMBERS_SysFuncAsTask; - virtual string verilogKwd() const override { return ""; } - virtual bool isGateOptimizable() const override { return true; } - virtual bool isPredictOptimizable() const override { return true; } - virtual bool isPure() const override { return true; } - virtual bool isOutputter() const override { return false; } - virtual int instrCount() const override { return 0; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return ""; } + bool isGateOptimizable() const override { return true; } + bool isPredictOptimizable() const override { return true; } + bool isPure() const override { return true; } + bool isOutputter() const override { return false; } + int instrCount() const override { return 0; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval }; @@ -3636,14 +3612,12 @@ public: addNOp1p(exprsp); } ASTGEN_MEMBERS_SysIgnore; - virtual string verilogKwd() const override { return "$ignored"; } - virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt - virtual bool isPredictOptimizable() const override { - return false; - } // Though deleted before opt - virtual bool isPure() const override { return false; } // Though deleted before opt - virtual bool isOutputter() const override { return true; } // Though deleted before opt - virtual int instrCount() const override { return INSTR_COUNT_PLI; } + string verilogKwd() const override { return "$ignored"; } + bool isGateOptimizable() const override { return false; } // Though deleted before opt + bool isPredictOptimizable() const override { return false; } // Though deleted before opt + bool isPure() const override { return false; } // Though deleted before opt + bool isOutputter() const override { return true; } // Though deleted before opt + int instrCount() const override { return INSTR_COUNT_PLI; } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output }; @@ -3655,13 +3629,13 @@ public: setOp1p(lhsp); } ASTGEN_MEMBERS_SystemT; - virtual string verilogKwd() const override { return "$system"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool isUnlikely() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + string verilogKwd() const override { return "$system"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool isUnlikely() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } AstNode* lhsp() const { return op1p(); } }; class AstTimeFormat final : public AstNodeStmt { @@ -3676,12 +3650,12 @@ public: setOp4p(widthp); } ASTGEN_MEMBERS_TimeFormat; - virtual string verilogKwd() const override { return "$timeformat"; } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual int instrCount() const override { return INSTR_COUNT_PLI; } + string verilogKwd() const override { return "$timeformat"; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + int instrCount() const override { return INSTR_COUNT_PLI; } AstNode* unitsp() const { return op1p(); } AstNode* precisionp() const { return op2p(); } AstNode* suffixp() const { return op3p(); } @@ -3718,13 +3692,13 @@ public: dtypeFrom(valuep); addNOp1p(valuep); } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 100; } // Large... + void dump(std::ostream& str) const override; + int instrCount() const override { return 100; } // Large... ASTGEN_MEMBERS_TraceDecl; - virtual string name() const override { return m_showname; } - virtual bool maybePointedTo() const override { return true; } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { return false; } + string name() const override { return m_showname; } + bool maybePointedTo() const override { return true; } + bool hasDType() const override { return true; } + bool same(const AstNode* samep) const override { return false; } string showname() const { return m_showname; } // * = Var name // Details on what we're tracing uint32_t code() const { return m_code; } @@ -3758,22 +3732,22 @@ public: addOp2p(declp->valuep()->cloneTree(true)); } ASTGEN_MEMBERS_TraceInc; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_RTN(!declp()->brokeExists()); return nullptr; } - virtual void cloneRelink() override { + void cloneRelink() override { if (m_declp->clonep()) m_declp = m_declp->clonep(); } - virtual void dump(std::ostream& str) const override; - virtual int instrCount() const override { return 10 + 2 * INSTR_COUNT_LD; } - virtual bool hasDType() const override { return true; } - virtual bool same(const AstNode* samep) const override { + void dump(std::ostream& str) const override; + int instrCount() const override { return 10 + 2 * INSTR_COUNT_LD; } + bool hasDType() const override { return true; } + bool same(const AstNode* samep) const override { return declp() == static_cast(samep)->declp(); } - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isOutputter() const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isOutputter() const override { return true; } // but isPure() true // op1 = Statements before the value AstNode* precondsp() const { return op1p(); } @@ -3790,7 +3764,7 @@ public: : ASTGEN_SUPER_TracePopNamePrefix(fl) , m_count{count} {} ASTGEN_MEMBERS_TracePopNamePrefix; - virtual bool same(const AstNode* samep) const override { return false; } + bool same(const AstNode* samep) const override { return false; } unsigned count() const { return m_count; } }; class AstTracePushNamePrefix final : public AstNodeStmt { @@ -3800,7 +3774,7 @@ public: : ASTGEN_SUPER_TracePushNamePrefix(fl) , m_prefix{prefix} {} ASTGEN_MEMBERS_TracePushNamePrefix; - virtual bool same(const AstNode* samep) const override { return false; } + bool same(const AstNode* samep) const override { return false; } string prefix() const { return m_prefix; } }; class AstUCStmt final : public AstNodeStmt { @@ -3812,11 +3786,11 @@ public: } ASTGEN_MEMBERS_UCStmt; AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - virtual bool isGateOptimizable() const override { return false; } - virtual bool isPredictOptimizable() const override { return false; } - virtual bool isPure() const override { return false; } - virtual bool isOutputter() const override { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + bool isPredictOptimizable() const override { return false; } + bool isPure() const override { return false; } + bool isOutputter() const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } }; class AstWait final : public AstNodeStmt { public: @@ -3853,13 +3827,13 @@ public: void addPrecondsp(AstNode* newp) { addOp1p(newp); } void addBodysp(AstNode* newp) { addOp3p(newp); } void addIncsp(AstNode* newp) { addOp4p(newp); } - virtual bool isGateOptimizable() const override { return false; } - virtual int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool isGateOptimizable() const override { return false; } + int instrCount() const override { return INSTR_COUNT_BRANCH; } + bool same(const AstNode* /*samep*/) const override { return true; } // Stop statement searchback here - virtual void addBeforeStmt(AstNode* newp, AstNode* belowp) override; + void addBeforeStmt(AstNode* newp, AstNode* belowp) override; // Stop statement searchback here - virtual void addNextStmt(AstNode* newp, AstNode* belowp) override; + void addNextStmt(AstNode* newp, AstNode* belowp) override; bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } }; class AstWith final : public AstNodeStmt { @@ -3878,9 +3852,9 @@ public: addNOp3p(exprp); } ASTGEN_MEMBERS_With; - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool hasDType() const override { return true; } - virtual const char* broken() const override { + bool same(const AstNode* /*samep*/) const override { return true; } + bool hasDType() const override { return true; } + const char* broken() const override { BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype return nullptr; @@ -3903,7 +3877,7 @@ public: addNOp2p(exprp); } ASTGEN_MEMBERS_WithParse; - virtual bool same(const AstNode* /*samep*/) const override { return true; } + bool same(const AstNode* /*samep*/) const override { return true; } // AstNode* funcrefp() const { return op1p(); } AstNode* exprp() const { return op2p(); } @@ -3917,10 +3891,10 @@ public: dtypeFrom(lhsp); } ASTGEN_MEMBERS_Assign; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssign(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const override { return true; } + bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignAlias final : public AstNodeAssign { // Like AstAssignW, but a true bidirect interconnection alias @@ -3929,22 +3903,20 @@ public: AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp) : ASTGEN_SUPER_AssignAlias(fl, (AstNode*)lhsp, (AstNode*)rhsp) {} ASTGEN_MEMBERS_AssignAlias; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { - V3ERROR_NA_RETURN(nullptr); - } - virtual bool brokeLhsMustBeLvalue() const override { return false; } + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { V3ERROR_NA_RETURN(nullptr); } + bool brokeLhsMustBeLvalue() const override { return false; } }; class AstAssignDly final : public AstNodeAssign { public: AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp, timingControlp) {} ASTGEN_MEMBERS_AssignDly; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignDly(this->fileline(), lhsp, rhsp); } - virtual bool isGateOptimizable() const override { return false; } - virtual string verilogKwd() const override { return "<="; } - virtual bool brokeLhsMustBeLvalue() const override { return true; } + bool isGateOptimizable() const override { return false; } + string verilogKwd() const override { return "<="; } + bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignForce final : public AstNodeAssign { // Procedural 'force' statement @@ -3952,10 +3924,10 @@ public: AstAssignForce(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignForce(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_AssignForce; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignForce{this->fileline(), lhsp, rhsp}; } - virtual bool brokeLhsMustBeLvalue() const override { return true; } + bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignPost final : public AstNodeAssign { // Like Assign, but predelayed assignment requiring special order handling @@ -3963,10 +3935,10 @@ public: AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignPost(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_AssignPost; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignPost(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const override { return true; } + bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignPre final : public AstNodeAssign { // Like Assign, but predelayed assignment requiring special order handling @@ -3974,10 +3946,10 @@ public: AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignPre(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_AssignPre; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignPre(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const override { return true; } + bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignVarScope final : public AstNodeAssign { // Assign two VarScopes to each other @@ -3987,10 +3959,10 @@ public: dtypeFrom(rhsp); } ASTGEN_MEMBERS_AssignVarScope; - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignVarScope(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const override { return false; } + bool brokeLhsMustBeLvalue() const override { return false; } }; class AstAssignW final : public AstNodeAssign { // Like assign, but wire/assign's in verilog, the only setting of the specified variable @@ -4000,10 +3972,10 @@ public: ASTGEN_MEMBERS_AssignW; AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); } void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignW(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const override { return true; } + bool brokeLhsMustBeLvalue() const override { return true; } AstAlways* convertToAlways() { AstNode* const lhs1p = lhsp()->unlinkFrBack(); AstNode* const rhs1p = rhsp()->unlinkFrBack(); @@ -4041,7 +4013,7 @@ public: setOp1p(fromp); } ASTGEN_MEMBERS_CMethodCall; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_BASE_RTN(AstNodeCCall::broken()); BROKEN_RTN(!fromp()); return nullptr; @@ -4060,7 +4032,7 @@ public: : ASTGEN_SUPER_CNew(fl, funcp, argsp) { statement(false); } - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } ASTGEN_MEMBERS_CNew; }; @@ -4082,10 +4054,8 @@ public: : ASTGEN_SUPER_Case(fl, exprp, casesp) , m_casex{casex} {} ASTGEN_MEMBERS_Case; - virtual string verilogKwd() const override { - return casez() ? "casez" : casex() ? "casex" : "case"; - } - virtual bool same(const AstNode* samep) const override { + string verilogKwd() const override { return casez() ? "casez" : casex() ? "casex" : "case"; } + bool same(const AstNode* samep) const override { return m_casex == static_cast(samep)->m_casex; } bool casex() const { return m_casex == VCaseType::CT_CASEX; } @@ -4163,7 +4133,7 @@ public: AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) : ASTGEN_SUPER_FuncRef(fl, false, name, pinsp) {} ASTGEN_MEMBERS_FuncRef; - virtual bool hasDType() const override { return true; } + bool hasDType() const override { return true; } }; class AstMethodCall final : public AstNodeFTaskRef { // A reference to a member task (or function) @@ -4182,13 +4152,13 @@ public: setOp2p(fromp); } ASTGEN_MEMBERS_MethodCall; - virtual const char* broken() const override { + const char* broken() const override { BROKEN_BASE_RTN(AstNodeFTaskRef::broken()); BROKEN_RTN(!fromp()); return nullptr; } - virtual void dump(std::ostream& str) const override; - virtual bool hasDType() const override { return true; } + void dump(std::ostream& str) const override; + bool hasDType() const override { return true; } void makeStatement() { statement(true); dtypeSetVoid(); @@ -4208,9 +4178,9 @@ public: : ASTGEN_SUPER_New(fl, false, "new", pinsp) {} ASTGEN_MEMBERS_New; virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* /*samep*/) const override { return true; } - virtual bool hasDType() const override { return true; } - virtual int instrCount() const override { return widthInstrs(); } + bool same(const AstNode* /*samep*/) const override { return true; } + bool hasDType() const override { return true; } + int instrCount() const override { return widthInstrs(); } }; class AstTaskRef final : public AstNodeFTaskRef { // A reference to a task @@ -4263,8 +4233,8 @@ public: AstNode* msbp) : ASTGEN_SUPER_ReadMem(fl, hex, filenamep, memp, lsbp, msbp) {} ASTGEN_MEMBERS_ReadMem; - virtual string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); } - virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; } + string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); } + const char* cFuncPrefixp() const override { return "VL_READMEM_"; } }; class AstWriteMem final : public AstNodeReadWriteMem { public: @@ -4272,8 +4242,8 @@ public: AstNode* msbp) : ASTGEN_SUPER_WriteMem(fl, hex, filenamep, memp, lsbp, msbp) {} ASTGEN_MEMBERS_WriteMem; - virtual string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); } - virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } + string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); } + const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } }; // === AstNodeText === @@ -4282,48 +4252,48 @@ public: AstScCtor(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScCtor(fl, textp) {} ASTGEN_MEMBERS_ScCtor; - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } }; class AstScDtor final : public AstNodeText { public: AstScDtor(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScDtor(fl, textp) {} ASTGEN_MEMBERS_ScDtor; - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } }; class AstScHdr final : public AstNodeText { public: AstScHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScHdr(fl, textp) {} ASTGEN_MEMBERS_ScHdr; - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } }; class AstScImp final : public AstNodeText { public: AstScImp(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScImp(fl, textp) {} ASTGEN_MEMBERS_ScImp; - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } }; class AstScImpHdr final : public AstNodeText { public: AstScImpHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScImpHdr(fl, textp) {} ASTGEN_MEMBERS_ScImpHdr; - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } }; class AstScInt final : public AstNodeText { public: AstScInt(FileLine* fl, const string& textp) : ASTGEN_SUPER_ScInt(fl, textp) {} ASTGEN_MEMBERS_ScInt; - virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const override { return true; } + bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + bool isOutputter() const override { return true; } }; // === AstNodeSimpleText === diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 4dd3d6e77..d891a46c4 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -564,11 +564,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const { return dpiTypesToStringConverter{}.convert(this); } else { class converter final : public dpiTypesToStringConverter { - virtual string bitLogicVector(const AstVar* varp, bool isBit) const override { + string bitLogicVector(const AstVar* varp, bool isBit) const override { return string(varp->isReadOnly() ? "const " : "") + dpiTypesToStringConverter::bitLogicVector(varp, isBit) + '*'; } - virtual string primitive(const AstVar* varp) const override { + string primitive(const AstVar* varp) const override { string type = dpiTypesToStringConverter::primitive(varp); if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) { if (!varp->isWritable() && varp->basicp()->keyword() != VBasicDTypeKwd::STRING) @@ -600,16 +600,16 @@ string AstVar::dpiTmpVarType(const string& varName) const { return ""; } } - virtual string openArray(const AstVar* varp) const override { + string openArray(const AstVar* varp) const override { return dpiTypesToStringConverter::openArray(varp) + ' ' + m_name + arraySuffix(varp, 0); } - virtual string bitLogicVector(const AstVar* varp, bool isBit) const override { + string bitLogicVector(const AstVar* varp, bool isBit) const override { string type = dpiTypesToStringConverter::bitLogicVector(varp, isBit); type += ' ' + m_name + arraySuffix(varp, varp->widthWords()); return type; } - virtual string primitive(const AstVar* varp) const override { + string primitive(const AstVar* varp) const override { string type = dpiTypesToStringConverter::primitive(varp); if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) { if (!varp->isWritable() && varp->basicp()->keyword() == VBasicDTypeKwd::CHANDLE) diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 6a40e1233..9f65dd79a 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -120,14 +120,14 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; iterateChildren(nodep); } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { UINFO(8, " " << nodep << endl); // Rename it if (m_unnamedScope != "") { @@ -162,7 +162,7 @@ private: m_ftaskp = nullptr; } } - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { // Begin blocks were only useful in variable creation, change names and delete UINFO(8, " " << nodep << endl); VL_RESTORER(m_displayScope); @@ -191,7 +191,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (m_unnamedScope != "") { // Rename it nodep->name(dot(m_unnamedScope, nodep->name())); @@ -200,7 +200,7 @@ private: liftNode(nodep); } } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { if (m_unnamedScope != "") { // Rename it nodep->name(dot(m_unnamedScope, nodep->name())); @@ -209,7 +209,7 @@ private: liftNode(nodep); } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { UINFO(8, " CELL " << nodep << endl); if (m_namedScope != "") { m_statep->userMarkChanged(nodep); @@ -222,14 +222,14 @@ private: } iterateChildren(nodep); } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { UINFO(9, " VARXREF " << nodep << endl); if (m_namedScope != "" && nodep->inlinedDots() == "" && !m_ftaskp) { nodep->inlinedDots(m_namedScope); UINFO(9, " rescope to " << nodep << endl); } } - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { // If there's a %m in the display text, we add a special node that will contain the name() // Similar code in V3Inline if (nodep->user1SetOnce()) return; // Don't double-add text's @@ -244,13 +244,13 @@ private: } iterateChildren(nodep); } - virtual void visit(AstCoverDecl* nodep) override { + void visit(AstCoverDecl* nodep) override { // Don't need to fix path in coverage statements, they're not under // any BEGINs, but V3Coverage adds them all under the module itself. iterateChildren(nodep); } // VISITORS - LINT CHECK - virtual void visit(AstIf* nodep) override { // not AstNodeIf; other types not covered + void visit(AstIf* nodep) override { // not AstNodeIf; other types not covered // Check IFDEPTH warning - could be in other transform files if desire VL_RESTORER(m_ifDepth); if (m_ifDepth == -1 || v3Global.opt.ifDepth() < 1) { // Turned off @@ -264,7 +264,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -272,7 +272,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~BeginVisitor() override = default; + ~BeginVisitor() override = default; }; //###################################################################### @@ -285,21 +285,21 @@ private: // AstNodeFTask::user1p // Node replaced, rename it // VISITORS - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { if (nodep->taskp()->user1()) { // It was converted UINFO(9, " relinkFTask " << nodep << endl); nodep->name(nodep->taskp()->name()); } iterateChildren(nodep); } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (nodep->varp()->user1()) { // It was converted UINFO(9, " relinVarRef " << nodep << endl); nodep->name(nodep->varp()->name()); } iterateChildren(nodep); } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { // May have changed cell names // TypeTable is always after all modules, so names are stable UINFO(8, " IFACEREFDTYPE " << nodep << endl); @@ -308,12 +308,12 @@ private: iterateChildren(nodep); } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS BeginRelinkVisitor(AstNetlist* nodep, BeginState*) { iterate(nodep); } - virtual ~BeginRelinkVisitor() override = default; + ~BeginRelinkVisitor() override = default; }; //###################################################################### diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index 51c749eb4..eed4e49fc 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -63,7 +63,7 @@ private: } // VISITORS - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { UINFO(4, " IF: " << nodep << endl); VL_RESTORER(m_likely); VL_RESTORER(m_unlikely); @@ -87,17 +87,17 @@ private: } // else leave unknown } } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { checkUnlikely(nodep); nodep->funcp()->user1Inc(); iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { checkUnlikely(nodep); m_cfuncsp.push_back(nodep); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { checkUnlikely(nodep); iterateChildren(nodep); } @@ -116,7 +116,7 @@ public: iterateChildren(nodep); calc_tasks(); } - virtual ~BranchVisitor() override = default; + ~BranchVisitor() override = default; }; //###################################################################### diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 6f1f906e8..75fb8c356 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -214,27 +214,27 @@ private: } return false; } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { processAndIterate(nodep); UASSERT_OBJ(!(v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue() && VN_IS(nodep->lhsp(), NodeVarRef) && !VN_AS(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()), nodep, "Assignment LHS is not an lvalue"); } - virtual void visit(AstRelease* nodep) override { + void visit(AstRelease* nodep) override { processAndIterate(nodep); UASSERT_OBJ(!(v3Global.assertDTypesResolved() && VN_IS(nodep->lhsp(), NodeVarRef) && !VN_AS(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()), nodep, "Release LHS is not an lvalue"); } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { VL_RESTORER(m_inScope); { m_inScope = true; processAndIterate(nodep); } } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { processAndIterate(nodep); // m_inScope because some Vars have initial variable references without scopes // This might false fire with some debug flags, as not certain we don't have temporary @@ -252,7 +252,7 @@ private: } } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { UASSERT_OBJ(!m_cfuncp, nodep, "Nested AstCFunc"); m_cfuncp = nodep; m_localVars.clear(); @@ -270,7 +270,7 @@ private: m_cfuncp = nullptr; } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { // Each branch is a separate local variable scope pushLocalScope(); processEnter(nodep); @@ -288,21 +288,21 @@ private: processExit(nodep); popLocalScope(); } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { // For local variable checking act as if any statement introduces a new scope. // This is aggressive but conservatively correct. pushLocalScope(); processAndIterate(nodep); popLocalScope(); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { processAndIterate(nodep); if (m_cfuncp) { m_localVars.insert(nodep); m_localsStack.back().insert(nodep); } } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // Process not just iterate processAndIterate(nodep); } @@ -310,7 +310,7 @@ private: public: // CONSTRUCTORS explicit BrokenCheckVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~BrokenCheckVisitor() override = default; + ~BrokenCheckVisitor() override = default; }; //###################################################################### diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 2d301567e..5bf6bfe69 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -57,7 +57,7 @@ class CUseVisitor final : public VNVisitor { } // VISITORS - virtual void visit(AstClassRefDType* nodep) override { + void visit(AstClassRefDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once if (!m_impOnly) addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name()); // Need to include extends() when we implement, but no need for pointers to know @@ -67,17 +67,17 @@ class CUseVisitor final : public VNVisitor { iterateChildren(nodep->classp()); // This also gets all extend classes } } - virtual void visit(AstNodeDType* nodep) override { + void visit(AstNodeDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once if (nodep->virtRefDTypep()) iterate(nodep->virtRefDTypep()); if (nodep->virtRefDType2p()) iterate(nodep->virtRefDType2p()); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { if (nodep->user1SetOnce()) return; // Process once if (nodep->dtypep() && !nodep->dtypep()->user1()) iterate(nodep->dtypep()); iterateChildren(nodep); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { if (nodep->user1SetOnce()) return; // Process once // Currently no IMP_INCLUDE because we include __Syms which has them all addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->modp()->name()); @@ -90,7 +90,7 @@ public: : m_modp(modp) { iterate(modp); } - virtual ~CUseVisitor() override = default; + ~CUseVisitor() override = default; VL_UNCOPYABLE(CUseVisitor); }; diff --git a/src/V3Case.cpp b/src/V3Case.cpp index c8a2e639f..58a160301 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -59,7 +59,7 @@ private: // METHODS VL_DEBUG_FUNC; // Declare debug() - virtual void visit(AstNodeCase* nodep) override { + void visit(AstNodeCase* nodep) override { if (VN_IS(nodep, Case) && VN_AS(nodep, Case)->casex()) { nodep->v3warn(CASEX, "Suggest casez (with ?'s) in place of casex (with X's)"); } @@ -86,7 +86,7 @@ private: m_caseExprp = nullptr; } } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { // See also neverItem if (m_caseExprp && nodep->num().isFourState()) { if (VN_IS(m_caseExprp, GenCase)) { @@ -107,12 +107,12 @@ private: } } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit CaseLintVisitor(AstNodeCase* nodep) { iterate(nodep); } - virtual ~CaseLintVisitor() override = default; + ~CaseLintVisitor() override = default; }; //###################################################################### @@ -493,7 +493,7 @@ private: } // VISITORS - virtual void visit(AstCase* nodep) override { + void visit(AstCase* nodep) override { V3Case::caseLint(nodep); iterateChildren(nodep); if (debug() >= 9) nodep->dumpTree(cout, " case_old: "); @@ -510,7 +510,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { if (VN_IS(nodep, Always)) m_alwaysp = nodep; iterateChildren(nodep); } @@ -521,7 +521,7 @@ public: for (auto& itr : m_valueItem) itr = nullptr; iterate(nodep); } - virtual ~CaseVisitor() override { + ~CaseVisitor() override { V3Stats::addStat("Optimizations, Cases parallelized", m_statCaseFast); V3Stats::addStat("Optimizations, Cases complex", m_statCaseSlow); } diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index fa5b748e9..5d39416bf 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -111,25 +111,25 @@ private: } // VISITORS - virtual void visit(AstNodeUniop* nodep) override { + void visit(AstNodeUniop* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1()); if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp()); } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1()); if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp()); if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp()); } - virtual void visit(AstNodeTriop* nodep) override { + void visit(AstNodeTriop* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1()); if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp()); if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp()); if (nodep->sizeMattersThs()) ensureCast(nodep->thsp()); } - virtual void visit(AstNodeQuadop* nodep) override { + void visit(AstNodeQuadop* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1() | nodep->fhsp()->user1()); @@ -138,12 +138,12 @@ private: if (nodep->sizeMattersThs()) ensureCast(nodep->thsp()); if (nodep->sizeMattersFhs()) ensureCast(nodep->fhsp()); } - virtual void visit(AstCCast* nodep) override { + void visit(AstCCast* nodep) override { iterateChildren(nodep); ensureLower32Cast(nodep); nodep->user1(1); } - virtual void visit(AstNegate* nodep) override { + void visit(AstNegate* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1()); if (nodep->lhsp()->widthMin() == 1) { @@ -155,7 +155,7 @@ private: ensureCast(nodep->lhsp()); } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { const AstNode* const backp = nodep->backp(); if (nodep->access().isReadOnly() && !VN_IS(backp, CCast) && VN_IS(backp, NodeMath) && !VN_IS(backp, ArraySel) && !VN_IS(backp, RedXor) && backp->width() @@ -166,7 +166,7 @@ private: } nodep->user1(1); } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { // Constants are of unknown size if smaller than 33 bits, because // we're too lazy to wrap every constant in the universe in // ((IData)#). @@ -174,29 +174,29 @@ private: } // Null dereference protection - virtual void visit(AstNullCheck* nodep) override { + void visit(AstNullCheck* nodep) override { iterateChildren(nodep); nodep->user1(nodep->lhsp()->user1()); } - virtual void visit(AstCMethodCall* nodep) override { + void visit(AstCMethodCall* nodep) override { iterateChildren(nodep); ensureNullChecked(nodep->fromp()); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { iterateChildren(nodep); ensureNullChecked(nodep->fromp()); } // NOPs - virtual void visit(AstVar*) override {} + void visit(AstVar*) override {} //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit CastVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~CastVisitor() override = default; + ~CastVisitor() override = default; }; //###################################################################### diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 56e26ebe8..6a6323a15 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -67,9 +67,9 @@ public: , m_srcDomainSet{false} , m_dstDomainSet{false} , m_asyncPath{false} {} - virtual ~CdcEitherVertex() override = default; + ~CdcEitherVertex() override = default; // ACCESSORS - virtual FileLine* fileline() const override { return nodep()->fileline(); } + FileLine* fileline() const override { return nodep()->fileline(); } AstScope* scopep() const { return m_scopep; } AstNode* nodep() const { return m_nodep; } AstSenTree* srcDomainp() const { return m_srcDomainp; } @@ -93,11 +93,11 @@ public: CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : CdcEitherVertex{graphp, scopep, varScp} , m_varScp{varScp} {} - virtual ~CdcVarVertex() override = default; + ~CdcVarVertex() override = default; // ACCESSORS AstVarScope* varScp() const { return m_varScp; } - virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } - virtual string dotColor() const override { + string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } + string dotColor() const override { return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue"; } int cntAsyncRst() const { return m_cntAsyncRst; } @@ -118,12 +118,10 @@ public: srcDomainp(sensenodep); dstDomainp(sensenodep); } - virtual ~CdcLogicVertex() override = default; + ~CdcLogicVertex() override = default; // ACCESSORS - virtual string name() const override { - return (cvtToHex(nodep()) + "@" + scopep()->prettyName()); - } - virtual string dotColor() const override { return hazard() ? "black" : "yellow"; } + string name() const override { return (cvtToHex(nodep()) + "@" + scopep()->prettyName()); } + string dotColor() const override { return hazard() ? "black" : "yellow"; } bool hazard() const { return m_hazard; } void setHazard(AstNode* nodep) { m_hazard = true; @@ -144,7 +142,7 @@ private: std::ofstream* const m_ofp = nullptr; // Output file string m_prefix; - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { *m_ofp << m_prefix; if (nodep->user3()) { *m_ofp << " %%"; @@ -171,7 +169,7 @@ public: , m_prefix{prefix} { iterate(nodep); } - virtual ~CdcDumpVisitor() override = default; + ~CdcDumpVisitor() override = default; }; //###################################################################### @@ -181,7 +179,7 @@ private: int m_maxLineno = 0; size_t m_maxFilenameLen = 0; - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); // Keeping line+filename lengths separate is much faster than calling ascii().length() if (nodep->fileline()->lineno() >= m_maxLineno) { @@ -195,7 +193,7 @@ private: public: // CONSTRUCTORS explicit CdcWidthVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~CdcWidthVisitor() override = default; + ~CdcWidthVisitor() override = default; // ACCESSORS int maxWidth() const { size_t width = 1; @@ -628,21 +626,21 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; m_logicVertexp = nullptr; iterateChildren(nodep); m_scopep = nullptr; } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { // Create required blocks and add to module UINFO(4, " BLOCK " << nodep << endl); AstNode::user2ClearTree(); @@ -654,7 +652,7 @@ private: m_domainp = nullptr; AstNode::user2ClearTree(); } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { if (m_scopep) { UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block"); AstVarScope* const varscp = nodep->varScopep(); @@ -682,53 +680,53 @@ private: } } } - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { m_inDly = true; iterateChildren(nodep); m_inDly = false; } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { m_inSenItem = true; iterateChildren(nodep); m_inSenItem = false; } - virtual void visit(AstAlways* nodep) override { iterateNewStmt(nodep); } - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlways* nodep) override { iterateNewStmt(nodep); } + void visit(AstAlwaysPublic* nodep) override { // CDC doesn't care about public variables } - virtual void visit(AstCFunc* nodep) override { iterateNewStmt(nodep); } - virtual void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); } - virtual void visit(AstAssignW* nodep) override { iterateNewStmt(nodep); } + void visit(AstCFunc* nodep) override { iterateNewStmt(nodep); } + void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); } + void visit(AstAssignW* nodep) override { iterateNewStmt(nodep); } // Math that shouldn't cause us to clear hazard - virtual void visit(AstConst*) override {} - virtual void visit(AstReplicate* nodep) override { iterateChildren(nodep); } - virtual void visit(AstConcat* nodep) override { iterateChildren(nodep); } - virtual void visit(AstNot* nodep) override { iterateChildren(nodep); } - virtual void visit(AstSel* nodep) override { + void visit(AstConst*) override {} + void visit(AstReplicate* nodep) override { iterateChildren(nodep); } + void visit(AstConcat* nodep) override { iterateChildren(nodep); } + void visit(AstNot* nodep) override { iterateChildren(nodep); } + void visit(AstSel* nodep) override { if (!VN_IS(nodep->lsbp(), Const)) setNodeHazard(nodep); iterateChildren(nodep); } - virtual void visit(AstNodeSel* nodep) override { + void visit(AstNodeSel* nodep) override { if (!VN_IS(nodep->bitp(), Const)) setNodeHazard(nodep); iterateChildren(nodep); } // Ignores - virtual void visit(AstInitial*) override {} - virtual void visit(AstInitialAutomatic*) override {} - virtual void visit(AstInitialStatic*) override {} - virtual void visit(AstTraceDecl*) override {} - virtual void visit(AstCoverToggle*) override {} - virtual void visit(AstNodeDType*) override {} + void visit(AstInitial*) override {} + void visit(AstInitialAutomatic*) override {} + void visit(AstInitialStatic*) override {} + void visit(AstTraceDecl*) override {} + void visit(AstCoverToggle*) override {} + void visit(AstNodeDType*) override {} //-------------------- // Default - virtual void visit(AstNodeMath* nodep) override { + void visit(AstNodeMath* nodep) override { setNodeHazard(nodep); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -754,7 +752,7 @@ public: *m_ofp << '\n'; } } - virtual ~CdcVisitor() override { + ~CdcVisitor() override { if (m_ofp) VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } }; diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 32bf3d4c5..f99b40284 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -155,13 +155,13 @@ private: m_state.m_numStmts += initp->nodeCount() + m_varEqnp->widthWords(); } - virtual void visit(AstBasicDType*) override { // + void visit(AstBasicDType*) override { // newChangeDet(); } - virtual void visit(AstPackArrayDType*) override { // + void visit(AstPackArrayDType*) override { // newChangeDet(); } - virtual void visit(AstUnpackArrayDType* nodep) override { + void visit(AstUnpackArrayDType* nodep) override { for (int index = 0; index < nodep->elementsConst(); ++index) { VL_RESTORER(m_varEqnp); VL_RESTORER(m_newLvEqnp); @@ -181,7 +181,7 @@ private: } } } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { if (nodep->packedUnsup()) { newChangeDet(); } else { @@ -191,7 +191,7 @@ private: << m_vscp->varp()->prettyNameQ()); } } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); if (debug()) nodep->dumpTree(cout, "-DETECTARRAY-general-"); m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable" @@ -231,7 +231,7 @@ public: m_newLvEqnp->deleteTree(); m_newRvEqnp->deleteTree(); } - virtual ~ChangedInsertVisitor() override = default; + ~ChangedInsertVisitor() override = default; VL_UNCOPYABLE(ChangedInsertVisitor); }; diff --git a/src/V3Class.cpp b/src/V3Class.cpp index 94f513802..52a7c0f1f 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -49,7 +49,7 @@ private: // METHODS VL_DEBUG_FUNC; // Declare debug() - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { if (nodep->user1SetOnce()) return; // Move this class nodep->name(m_prefix + nodep->name()); @@ -100,7 +100,7 @@ private: } nodep->repairCache(); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule) VL_RESTORER(m_prefix); { @@ -109,7 +109,7 @@ private: } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { iterateChildren(nodep); if (m_packageScopep) { if (m_ftaskp && m_ftaskp->lifetime().isStatic()) { @@ -127,12 +127,12 @@ private: } } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { iterateChildren(nodep); nodep->varp()->user1p(nodep); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { VL_RESTORER(m_ftaskp); { m_ftaskp = nodep; @@ -142,7 +142,7 @@ private: } } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { iterateChildren(nodep); // Don't move now, or wouldn't keep interating the class // TODO move function statics only @@ -150,14 +150,14 @@ private: // m_toScopeMoves.push_back(std::make_pair(nodep, m_classScopep)); //} } - virtual void visit(AstInitial* nodep) override { + void visit(AstInitial* nodep) override { // But not AstInitialAutomatic, which remains under the class iterateChildren(nodep); if (m_packageScopep) { m_toScopeMoves.emplace_back(std::make_pair(nodep, m_packageScopep)); } } - virtual void visit(AstInitialStatic* nodep) override { + void visit(AstInitialStatic* nodep) override { // But not AstInitialAutomatic, which remains under the class iterateChildren(nodep); if (m_packageScopep) { @@ -165,14 +165,14 @@ private: } } - virtual void visit(AstNodeMath* nodep) override {} // Short circuit - virtual void visit(AstNodeStmt* nodep) override {} // Short circuit - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath* nodep) override {} // Short circuit + void visit(AstNodeStmt* nodep) override {} // Short circuit + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ClassVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ClassVisitor() override { + ~ClassVisitor() override { for (auto moved : m_toScopeMoves) { AstNode* const nodep = moved.first; AstScope* const scopep = moved.second; diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 3cca98d7f..64fa0dcba 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -173,64 +173,64 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; iterateChildren(nodep); } } - virtual void visit(AstNodeUniop* nodep) override { + void visit(AstNodeUniop* nodep) override { iterateChildren(nodep); computeCppWidth(nodep); if (nodep->cleanLhs()) ensureClean(nodep->lhsp()); setClean(nodep, nodep->cleanOut()); } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { operandBiop(nodep); setClean(nodep, nodep->cleanOut()); } - virtual void visit(AstAnd* nodep) override { + void visit(AstAnd* nodep) override { operandBiop(nodep); setClean(nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp())); } - virtual void visit(AstXor* nodep) override { + void visit(AstXor* nodep) override { operandBiop(nodep); setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp())); } - virtual void visit(AstOr* nodep) override { + void visit(AstOr* nodep) override { operandBiop(nodep); setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp())); } - virtual void visit(AstNodeQuadop* nodep) override { + void visit(AstNodeQuadop* nodep) override { operandQuadop(nodep); setClean(nodep, nodep->cleanOut()); } - virtual void visit(AstNodeMath* nodep) override { + void visit(AstNodeMath* nodep) override { iterateChildren(nodep); computeCppWidth(nodep); setClean(nodep, nodep->cleanOut()); } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { iterateChildren(nodep); computeCppWidth(nodep); if (nodep->cleanRhs()) ensureClean(nodep->rhsp()); } - virtual void visit(AstText* nodep) override { // + void visit(AstText* nodep) override { // setClean(nodep, true); } - virtual void visit(AstScopeName* nodep) override { // + void visit(AstScopeName* nodep) override { // setClean(nodep, true); } - virtual void visit(AstCNew* nodep) override { + void visit(AstCNew* nodep) override { iterateChildren(nodep); setClean(nodep, true); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { operandTriop(nodep); setClean(nodep, nodep->cleanOut()); } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { iterateChildren(nodep); computeCppWidth(nodep); setClean(nodep, false); @@ -238,69 +238,69 @@ private: if (!VN_IS(nodep->backp(), And)) insertClean(nodep); ensureCleanAndNext(nodep->bodysp()); } - virtual void visit(AstTraceDecl* nodep) override { + void visit(AstTraceDecl* nodep) override { // No cleaning, or would loose pointer to enum iterateChildren(nodep); } - virtual void visit(AstTraceInc* nodep) override { + void visit(AstTraceInc* nodep) override { iterateChildren(nodep); ensureCleanAndNext(nodep->valuep()); } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { // No cleaning, or would loose pointer to enum iterateChildren(nodep); } - virtual void visit(AstParamTypeDType* nodep) override { + void visit(AstParamTypeDType* nodep) override { // No cleaning, or would loose pointer to enum iterateChildren(nodep); } // Control flow operators - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { iterateChildren(nodep); ensureClean(nodep->condp()); setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p())); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { iterateChildren(nodep); ensureClean(nodep->condp()); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { iterateChildren(nodep); ensureClean(nodep->condp()); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { iterateChildren(nodep); ensureCleanAndNext(nodep->exprsp()); setClean(nodep, true); // generates a string, so not relevant } - virtual void visit(AstUCStmt* nodep) override { + void visit(AstUCStmt* nodep) override { iterateChildren(nodep); ensureCleanAndNext(nodep->bodysp()); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); ensureCleanAndNext(nodep->argsp()); setClean(nodep, true); } - virtual void visit(AstCMethodHard* nodep) override { + void visit(AstCMethodHard* nodep) override { iterateChildren(nodep); ensureCleanAndNext(nodep->pinsp()); setClean(nodep, true); } - virtual void visit(AstWith* nodep) override { + void visit(AstWith* nodep) override { iterateChildren(nodep); ensureCleanAndNext(nodep->exprp()); setClean(nodep, true); } - virtual void visit(AstIntfRef* nodep) override { + void visit(AstIntfRef* nodep) override { iterateChildren(nodep); setClean(nodep, true); // generates a string, so not relevant } //-------------------- // Default: Just iterate - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); computeCppWidth(nodep); } @@ -308,7 +308,7 @@ private: public: // CONSTRUCTORS explicit CleanVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~CleanVisitor() override = default; + ~CleanVisitor() override = default; }; //###################################################################### diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index f750d2059..95e10270d 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -242,7 +242,7 @@ private: } // VISITORS - virtual void visit(AstTopScope* nodep) override { + void visit(AstTopScope* nodep) override { UINFO(4, " TOPSCOPE " << nodep << endl); m_topScopep = nodep; m_scopep = nodep->scopep(); @@ -277,7 +277,7 @@ private: m_topScopep = nullptr; m_scopep = nullptr; } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // UINFO(4, " MOD " << nodep << endl); VL_RESTORER(m_modp); { @@ -285,7 +285,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { // UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; iterateChildren(nodep); @@ -296,14 +296,14 @@ private: } m_scopep = nullptr; } - virtual void visit(AstNodeProcedure* nodep) override { + void visit(AstNodeProcedure* nodep) override { if (AstNode* const stmtsp = nodep->bodysp()) { stmtsp->unlinkFrBackWithNext(); nodep->addNextHere(stmtsp); } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstCoverToggle* nodep) override { + void visit(AstCoverToggle* nodep) override { // nodep->dumpTree(cout, "ct:"); // COVERTOGGLE(INC, ORIG, CHANGE) -> // IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; } @@ -320,7 +320,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { iterateChildren(nodep); // Link to global function if (nodep->isFinal()) { @@ -329,7 +329,7 @@ private: m_finalFuncp->addStmtsp(callp); } } - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { // Delete it later; Actives still pointing to it nodep->unlinkFrBack(); pushDeletep(nodep); @@ -343,7 +343,7 @@ private: void addToInitial(AstNode* stmtsp) { m_initFuncp->addStmtsp(stmtsp); // add to top level function } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { // Careful if adding variables here, ACTIVES can be under other ACTIVES // Need to save and restore any member state in AstUntilStable block if (!m_topScopep || !nodep->stmtsp()) { @@ -411,7 +411,7 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - virtual void visit(AstExecGraph* nodep) override { + void visit(AstExecGraph* nodep) override { VL_RESTORER(m_mtaskBodyp); for (m_mtaskBodyp = nodep->mTaskBodiesp(); m_mtaskBodyp; m_mtaskBodyp = VN_AS(m_mtaskBodyp->nextp(), MTaskBody)) { @@ -427,7 +427,7 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -437,7 +437,7 @@ public: // easily without iterating through the tree. nodep->evalp(m_evalFuncp); } - virtual ~ClockVisitor() override = default; + ~ClockVisitor() override = default; }; //###################################################################### diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index 8fa0edbeb..e372629d0 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -180,32 +180,32 @@ class CombineVisitor final : VNVisitor { } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Gather functions and references iterateChildrenConst(nodep); // Combine functions process(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UASSERT_OBJ(!m_modp, nodep, "Should not nest"); m_modp = nodep; iterateChildrenConst(nodep); m_modp = nullptr; } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { iterateChildrenConst(nodep); if (nodep->dontCombine()) return; auto& coll = nodep->slow() ? m_cfuncs(m_modp).m_slow : m_cfuncs(m_modp).m_fast; coll.emplace_back(nodep); } - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { iterateChildrenConst(nodep); AstCFunc* const funcp = nodep->funcp(); if (funcp->dontCombine()) return; m_callSites(funcp).emplace_back(nodep); } - virtual void visit(AstAddrOfCFunc* nodep) override { + void visit(AstAddrOfCFunc* nodep) override { iterateChildrenConst(nodep); if (nodep->funcp()->dontCombine()) return; // LCOV_EXCL_START @@ -217,7 +217,7 @@ class CombineVisitor final : VNVisitor { } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } + void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } // CONSTRUCTORS explicit CombineVisitor(AstNetlist* nodep) { iterate(nodep); } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 2c5f10f7b..ba3b75edb 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -417,14 +417,12 @@ class ConstBitOpTreeVisitor final : public VNVisitor { } // VISITORS - virtual void visit(AstNode* nodep) override { - CONST_BITOP_SET_FAILED("Hit unexpected op", nodep); - } - virtual void visit(AstCCast* nodep) override { + void visit(AstNode* nodep) override { CONST_BITOP_SET_FAILED("Hit unexpected op", nodep); } + void visit(AstCCast* nodep) override { iterateChildren(nodep); if (m_leafp) m_leafp->updateBitRange(nodep); } - virtual void visit(AstShiftR* nodep) override { + void visit(AstShiftR* nodep) override { CONST_BITOP_RETURN_IF(!m_leafp, nodep); AstConst* const constp = VN_CAST(nodep->rhsp(), Const); CONST_BITOP_RETURN_IF(!constp, nodep->rhsp()); @@ -434,7 +432,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor { m_leafp->updateBitRange(nodep); m_lsb -= constp->toUInt(); } - virtual void visit(AstNot* nodep) override { + void visit(AstNot* nodep) override { CONST_BITOP_RETURN_IF(nodep->widthMin() != 1, nodep); AstNode* lhsp = nodep->lhsp(); AstCCast* const castp = VN_CAST(lhsp, CCast); @@ -449,7 +447,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor { if (!isXorTree()) m_polarity = !m_polarity; if (m_leafp && castp) m_leafp->updateBitRange(castp); } - virtual void visit(AstWordSel* nodep) override { + void visit(AstWordSel* nodep) override { CONST_BITOP_RETURN_IF(!m_leafp, nodep); AstConst* const constp = VN_CAST(nodep->bitp(), Const); CONST_BITOP_RETURN_IF(!constp, nodep->rhsp()); @@ -457,17 +455,17 @@ class ConstBitOpTreeVisitor final : public VNVisitor { m_leafp->wordIdx(constp->toSInt()); iterate(nodep->fromp()); } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { CONST_BITOP_RETURN_IF(!m_leafp, nodep); m_leafp->setLeaf(nodep); m_leafp->polarity(m_polarity); } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { CONST_BITOP_RETURN_IF(!m_leafp, nodep); m_leafp->setLeaf(nodep); } - virtual void visit(AstRedXor* nodep) override { + void visit(AstRedXor* nodep) override { Restorer restorer{*this}; CONST_BITOP_RETURN_IF(!VN_IS(m_rootp, Xor), nodep); AstNode* lhsp = nodep->lhsp(); @@ -514,7 +512,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor { } } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { if (VN_IS(nodep, And) && isConst(nodep->lhsp(), 1)) { // 1 & _ // Always reach past a plain making AND Restorer restorer{*this}; @@ -2252,11 +2250,11 @@ private: //---------------------------------------- // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. That's faster iterateChildrenBackwards(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; @@ -2264,7 +2262,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // No ASSIGNW removals under funcs, we've long eliminated INITIALs // (We should perhaps rename the assignw's to just assigns) VL_RESTORER(m_wremove); @@ -2273,7 +2271,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { // No ASSIGNW removals under scope, we've long eliminated INITIALs VL_RESTORER(m_wremove); VL_RESTORER(m_scopep); @@ -2370,17 +2368,17 @@ private: } // Special cases - virtual void visit(AstConst*) override {} // Already constant + void visit(AstConst*) override {} // Already constant - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { if (m_params) { iterateAndNextNull(nodep->paramsp()); } else { iterateChildren(nodep); } } - virtual void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); } - virtual void visit(AstPin* nodep) override { iterateChildren(nodep); } + void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); } + void visit(AstPin* nodep) override { iterateChildren(nodep); } void replaceLogEq(AstLogEq* nodep) { // LOGEQ(a,b) => AstLogAnd{AstLogOr{AstLogNot{a},b},AstLogOr{AstLogNot{b},a}} @@ -2562,7 +2560,7 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstAttrOf* nodep) override { + void visit(AstAttrOf* nodep) override { VL_RESTORER(m_attrp); { m_attrp = nodep; @@ -2570,7 +2568,7 @@ private: } } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { iterateAndNextNull(nodep->bitp()); if (VN_IS(nodep->bitp(), Const) && VN_IS(nodep->fromp(), VarRef) @@ -2596,7 +2594,7 @@ private: } m_selp = nullptr; } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { iterateChildren(nodep); UASSERT_OBJ(nodep->varp(), nodep, "Not linked"); bool did = false; @@ -2650,7 +2648,7 @@ private: << nodep->varp()->prettyNameQ()); } } - virtual void visit(AstEnumItemRef* nodep) override { + void visit(AstEnumItemRef* nodep) override { iterateChildren(nodep); UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); bool did = false; @@ -2675,7 +2673,7 @@ private: } } - // virtual void visit(AstCvtPackString* nodep) override { + // void visit(AstCvtPackString* nodep) override { // Not constant propagated (for today) because AstNodeMath::isOpaque is set // Someday if lower is constant, convert to quoted "string". @@ -2683,7 +2681,7 @@ private: // Only one if it's not in a list return (!nodep->nextp() && nodep->backp()->nextp() != nodep); } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { iterateChildren(nodep); if (m_doNConst && (VN_IS(nodep->sensp(), Const) || VN_IS(nodep->sensp(), EnumItemRef) @@ -2750,7 +2748,7 @@ private: } }; - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { iterateChildren(nodep); if (m_doExpensive) { // cout<dumpTree(cout, "ssin: "); @@ -2834,17 +2832,17 @@ private: //----- // Zero elimination - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { iterateChildren(nodep); if (m_doNConst && replaceNodeAssign(nodep)) return; } - virtual void visit(AstAssignAlias* nodep) override { + void visit(AstAssignAlias* nodep) override { // Don't perform any optimizations, keep the alias around } - virtual void visit(AstAssignVarScope* nodep) override { + void visit(AstAssignVarScope* nodep) override { // Don't perform any optimizations, the node won't be linked yet } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { iterateChildren(nodep); if (m_doNConst && replaceNodeAssign(nodep)) return; AstNodeVarRef* const varrefp = VN_CAST( @@ -2871,7 +2869,7 @@ private: varrefp->varp()->valuep(initvaluep); } } - virtual void visit(AstRelease* nodep) override { + void visit(AstRelease* nodep) override { if (AstConcat* const concatp = VN_CAST(nodep->lhsp(), Concat)) { FileLine* const flp = nodep->fileline(); AstRelease* const newLp = new AstRelease{flp, concatp->lhsp()->unlinkFrBack()}; @@ -2884,7 +2882,7 @@ private: } } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { iterateChildren(nodep); if (m_doNConst) { if (const AstConst* const constp = VN_CAST(nodep->condp(), Const)) { @@ -2968,7 +2966,7 @@ private: } } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { // DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2)) iterateChildren(nodep); if (stmtDisplayDisplay(nodep)) return; @@ -3022,7 +3020,7 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return true; } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { // Substitute constants into displays. The main point of this is to // simplify assertion methodologies which call functions with display's. // This eliminates a pile of wide temps, and makes the C a whole lot more readable. @@ -3089,17 +3087,17 @@ private: } } - virtual void visit(AstFuncRef* nodep) override { + void visit(AstFuncRef* nodep) override { iterateChildren(nodep); if (m_params) { // Only parameters force us to do constant function call propagation replaceWithSimulation(nodep); } } - virtual void visit(AstArg* nodep) override { + void visit(AstArg* nodep) override { // replaceWithSimulation on the Arg's parent FuncRef replaces these iterateChildren(nodep); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { const bool oldHasJumpDelay = m_hasJumpDelay; m_hasJumpDelay = false; { iterateChildren(nodep); } @@ -3125,22 +3123,22 @@ private: } } } - virtual void visit(AstInitArray* nodep) override { iterateChildren(nodep); } - virtual void visit(AstInitItem* nodep) override { iterateChildren(nodep); } - virtual void visit(AstUnbounded* nodep) override { iterateChildren(nodep); } + void visit(AstInitArray* nodep) override { iterateChildren(nodep); } + void visit(AstInitItem* nodep) override { iterateChildren(nodep); } + void visit(AstUnbounded* nodep) override { iterateChildren(nodep); } // These are converted by V3Param. Don't constify as we don't want the // from() VARREF to disappear, if any. // If output of a presel didn't get consted, chances are V3Param didn't visit properly - virtual void visit(AstNodePreSel*) override {} + void visit(AstNodePreSel*) override {} // Ignored, can eliminate early - virtual void visit(AstSysIgnore* nodep) override { + void visit(AstSysIgnore* nodep) override { iterateChildren(nodep); if (m_doNConst) VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } // Simplify - virtual void visit(AstBasicDType* nodep) override { + void visit(AstBasicDType* nodep) override { iterateChildren(nodep); nodep->cvtRangeConst(); } @@ -3148,11 +3146,11 @@ private: //----- // Jump elimination - virtual void visit(AstDelay* nodep) override { + void visit(AstDelay* nodep) override { iterateChildren(nodep); m_hasJumpDelay = true; } - virtual void visit(AstJumpGo* nodep) override { + void visit(AstJumpGo* nodep) override { iterateChildren(nodep); // Jump to label where label immediately follows label is not useful if (nodep->labelp() == VN_CAST(nodep->nextp(), JumpLabel)) { @@ -3183,7 +3181,7 @@ private: m_hasJumpDelay = true; } - virtual void visit(AstJumpBlock* nodep) override { + void visit(AstJumpBlock* nodep) override { // Because JumpLabels disable many optimizations, // remove JumpLabels that are not pointed to by any AstJumpGos // Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this @@ -3537,7 +3535,7 @@ private: // Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101 //----- - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // Default: Just iterate if (m_required) { if (VN_IS(nodep, NodeDType) || VN_IS(nodep, Range) || VN_IS(nodep, SliceSel)) { @@ -3584,7 +3582,7 @@ public: } // clang-format on } - virtual ~ConstVisitor() override { + ~ConstVisitor() override { if (m_doCpp) { if (m_globalPass) { V3Stats::addStat("Optimizations, Const bit op reduction", m_statBitOpReduction); diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index e03be42d4..a5e8b1dc3 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -209,7 +209,7 @@ private: } // VISITORS - BOTH - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { const AstNodeModule* const origModp = m_modp; VL_RESTORER(m_modp); VL_RESTORER(m_state); @@ -227,9 +227,9 @@ private: } } - virtual void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); } - virtual void visit(AstWhile* nodep) override { iterateProcedure(nodep); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); } + void visit(AstWhile* nodep) override { iterateProcedure(nodep); } + void visit(AstNodeFTask* nodep) override { if (!nodep->dpiImport()) iterateProcedure(nodep); } void iterateProcedure(AstNode* nodep) { @@ -258,7 +258,7 @@ private: } // VISITORS - TOGGLE COVERAGE - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { iterateChildren(nodep); if (m_modp && !m_inToggleOff && !m_state.m_inModOff && nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) { @@ -383,7 +383,7 @@ private: // VISITORS - LINE COVERAGE // Note not AstNodeIf; other types don't get covered - virtual void visit(AstIf* nodep) override { + void visit(AstIf* nodep) override { UINFO(4, " IF: " << nodep << endl); if (m_state.m_on) { // An else-if. When we iterate the if, use "elsif" marking @@ -460,7 +460,7 @@ private: } UINFO(9, " done HANDLE " << m_state.m_handle << " for " << nodep << endl); } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { // We don't add an explicit "default" coverage if not provided, // as we already have a warning when there is no default. UINFO(4, " CASEI: " << nodep << endl); @@ -479,7 +479,7 @@ private: } } } - virtual void visit(AstCover* nodep) override { + void visit(AstCover* nodep) override { UINFO(4, " COVER: " << nodep << endl); VL_RESTORER(m_state); { @@ -495,11 +495,11 @@ private: } } } - virtual void visit(AstStop* nodep) override { + void visit(AstStop* nodep) override { UINFO(4, " STOP: " << nodep << endl); m_state.m_on = false; } - virtual void visit(AstPragma* nodep) override { + void visit(AstPragma* nodep) override { if (nodep->pragType() == VPragmaType::COVERAGE_BLOCK_OFF) { // Skip all NEXT nodes under this block, and skip this if/case branch UINFO(4, " OFF: h" << m_state.m_handle << " " << nodep << endl); @@ -510,7 +510,7 @@ private: lineTrack(nodep); } } - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { // Record the hierarchy of any named begins, so we can apply to user // coverage points. This is because there may be cov points inside // generate blocks; each point should get separate consideration. @@ -529,7 +529,7 @@ private: } // VISITORS - BOTH - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); lineTrack(nodep); } @@ -537,7 +537,7 @@ private: public: // CONSTRUCTORS explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); } - virtual ~CoverageVisitor() override = default; + ~CoverageVisitor() override = default; }; //###################################################################### diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index 1b16971d6..b0d081a1d 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -88,24 +88,24 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Find all Coverage's iterateChildren(nodep); // Simplify detectDuplicates(); } - virtual void visit(AstCoverToggle* nodep) override { + void visit(AstCoverToggle* nodep) override { m_toggleps.push_back(nodep); iterateChildren(nodep); } //-------------------- - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~CoverageJoinVisitor() override { + ~CoverageJoinVisitor() override { V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins); } }; diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 5c6c11fb4..0d41429cd 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -102,7 +102,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { if (m_modp) m_modp->user1Inc(); // e.g. Class under Package VL_RESTORER(m_modp); { @@ -120,12 +120,12 @@ private: } } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { iterateChildren(nodep); checkAll(nodep); if (nodep->scopep()) nodep->scopep()->user1Inc(); } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { iterateChildren(nodep); checkAll(nodep); if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc(); @@ -136,14 +136,14 @@ private: m_scopesp.push_back(nodep); } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { iterateChildren(nodep); checkAll(nodep); m_cellsp.push_back(nodep); nodep->modp()->user1Inc(); } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { // Note NodeAssign skips calling this in some cases iterateChildren(nodep); checkAll(nodep); @@ -155,7 +155,7 @@ private: if (nodep->varp()) nodep->varp()->user1Inc(); if (nodep->classOrPackagep()) nodep->classOrPackagep()->user1Inc(); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); checkAll(nodep); if (nodep->classOrPackagep()) { @@ -166,11 +166,11 @@ private: } } } - virtual void visit(AstMethodCall* nodep) override { + void visit(AstMethodCall* nodep) override { iterateChildren(nodep); checkAll(nodep); } - virtual void visit(AstRefDType* nodep) override { + void visit(AstRefDType* nodep) override { iterateChildren(nodep); checkDType(nodep); checkAll(nodep); @@ -184,7 +184,7 @@ private: } } } - virtual void visit(AstClassRefDType* nodep) override { + void visit(AstClassRefDType* nodep) override { iterateChildren(nodep); checkDType(nodep); checkAll(nodep); @@ -197,12 +197,12 @@ private: } if (nodep->classp()) nodep->classp()->user1Inc(); } - virtual void visit(AstNodeDType* nodep) override { + void visit(AstNodeDType* nodep) override { iterateChildren(nodep); checkDType(nodep); checkAll(nodep); } - virtual void visit(AstEnumItemRef* nodep) override { + void visit(AstEnumItemRef* nodep) override { iterateChildren(nodep); checkAll(nodep); if (nodep->classOrPackagep()) { @@ -214,13 +214,13 @@ private: } checkAll(nodep); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { iterateChildren(nodep); if (nodep->varp()) nodep->varp()->user1Inc(); if (nodep->fromp()->dtypep()) nodep->fromp()->dtypep()->user1Inc(); // classref checkAll(nodep); } - virtual void visit(AstModport* nodep) override { + void visit(AstModport* nodep) override { iterateChildren(nodep); if (m_elimCells) { if (!nodep->varsp()) { @@ -230,14 +230,14 @@ private: } checkAll(nodep); } - virtual void visit(AstSelLoopVars* nodep) override { + void visit(AstSelLoopVars* nodep) override { // Var under a SelLoopVars means we haven't called V3Width to remove them yet VL_RESTORER(m_selloopvarsp); m_selloopvarsp = nodep; iterateChildren(nodep); checkAll(nodep); } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { iterateChildren(nodep); if (m_elimCells && !nodep->attrPublic()) { VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); @@ -248,20 +248,20 @@ private: // Normal modules may disappear, e.g. if they are parameterized then removed if (nodep->attrPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc(); } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { iterateChildren(nodep); checkAll(nodep); if (nodep->scopep()) nodep->scopep()->user1Inc(); if (mightElimVar(nodep->varp())) m_vscsp.push_back(nodep); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { iterateChildren(nodep); checkAll(nodep); if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc(); if (m_selloopvarsp) nodep->user1Inc(); if (mightElimVar(nodep)) m_varsp.push_back(nodep); } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // See if simple assignments to variables may be eliminated because // that variable is never used. // Similar code in V3Life @@ -284,7 +284,7 @@ private: } //----- - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { if (nodep->isOutputter()) m_sideEffect = true; iterateChildren(nodep); checkAll(nodep); @@ -446,7 +446,7 @@ public: // We may have removed some datatypes, cleanup nodep->typeTablep()->repairCache(); } - virtual ~DeadVisitor() override = default; + ~DeadVisitor() override = default; }; //###################################################################### diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index ce06a16a2..f7d928d33 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -365,24 +365,24 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // VV***** We reset all userp() on the netlist m_modVarMap.clear(); iterateChildren(nodep); } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UINFO(4, " MOD " << nodep << endl); AstNode::user3ClearTree(); iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { VL_RESTORER(m_cfuncp); { m_cfuncp = nodep; iterateChildren(nodep); } } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { m_activep = nodep; VL_RESTORER(m_inInitial); { @@ -392,7 +392,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { m_inDly = true; m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe nullptr. @@ -426,7 +426,7 @@ private: m_nextDlyp = nullptr; } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (!nodep->user2Inc()) { // Not done yet if (m_inDly && nodep->access().isWriteOrRW()) { UINFO(4, "AssignDlyVar: " << nodep << endl); @@ -488,18 +488,18 @@ private: } } - virtual void visit(AstNodeReadWriteMem* nodep) override { + void visit(AstNodeReadWriteMem* nodep) override { VL_RESTORER(m_ignoreBlkAndNBlk); m_ignoreBlkAndNBlk = true; // $readmem/$writemem often used in mem models // so we will suppress BLKANDNBLK warnings iterateChildren(nodep); } - virtual void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE + void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc( "For statements should have been converted to while statements in V3Begin"); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { VL_RESTORER(m_inLoop); { m_inLoop = true; @@ -508,12 +508,12 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit DelayedVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~DelayedVisitor() override { + ~DelayedVisitor() override { V3Stats::addStat("Optimizations, Delayed shared-sets", m_statSharedSet); } }; diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index 7b81e22ca..f370c6d09 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -73,7 +73,7 @@ private: } // VISITORS - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { VL_RESTORER(m_cfuncp); VL_RESTORER(m_mtaskbodyp); { @@ -85,7 +85,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstMTaskBody* nodep) override { + void visit(AstMTaskBody* nodep) override { VL_RESTORER(m_cfuncp); VL_RESTORER(m_mtaskbodyp); { @@ -106,7 +106,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); } else { @@ -114,8 +114,8 @@ private: } } // Operators - virtual void visit(AstNodeTermop* nodep) override {} - virtual void visit(AstNodeMath* nodep) override { + void visit(AstNodeTermop* nodep) override {} + void visit(AstNodeMath* nodep) override { // We have some operator defines that use 2 parens, so += 2. { VL_RESTORER(m_depth); @@ -142,19 +142,19 @@ private: m_cfuncp->isStatic(false); } } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { needNonStaticFunc(nodep); iterateChildren(nodep); } - virtual void visit(AstUCStmt* nodep) override { + void visit(AstUCStmt* nodep) override { needNonStaticFunc(nodep); visitStmt(nodep); } //-------------------- // Default: Just iterate - virtual void visit(AstVar*) override {} // Don't hit varrefs under vars - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't hit varrefs under vars + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -162,7 +162,7 @@ public: : m_tempNames{"__Vdeeptemp"} { iterate(nodep); } - virtual ~DepthVisitor() override = default; + ~DepthVisitor() override = default; }; //###################################################################### diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 22da37e91..c4cde8287 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -71,7 +71,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UINFO(4, " MOD " << nodep << endl); VL_RESTORER(m_modp); { @@ -80,7 +80,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // We recurse into this. VL_RESTORER(m_depth); VL_RESTORER(m_cfuncp); @@ -106,7 +106,7 @@ private: } m_depth--; } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); } else { @@ -114,15 +114,15 @@ private: } } - virtual void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNodeMath*) override {} // Accelerate //-------------------- - virtual void visit(AstVar*) override {} // Don't hit varrefs under vars - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't hit varrefs under vars + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit DepthBlockVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~DepthBlockVisitor() override = default; + ~DepthBlockVisitor() override = default; }; //###################################################################### diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 4fe90837f..544bac417 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -185,11 +185,11 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { nodep->dpiExportTriggerp(nullptr); iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; @@ -199,17 +199,17 @@ private: makePublicFuncWrappers(); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { m_scopep = nodep; iterateChildren(nodep); m_scopep = nullptr; } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { // Delete the varscope when we're finished nodep->unlinkFrBack(); pushDeletep(nodep); } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { iterateChildren(nodep); if (!nodep->varScopep()) { UASSERT_OBJ(nodep->varp()->isFuncLocal(), nodep, @@ -233,7 +233,7 @@ private: nodep->varScopep(nullptr); UINFO(9, " refout " << nodep << " selfPtr=" << nodep->selfPointer() << endl); } - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { // UINFO(9, " " << nodep << endl); iterateChildren(nodep); // Convert the hierch name @@ -243,9 +243,9 @@ private: // Can't do this, as we may have more calls later // nodep->funcp()->scopep(nullptr); } - virtual void visit(AstCMethodCall* nodep) override { iterateChildren(nodep); } - virtual void visit(AstCNew* nodep) override { iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCMethodCall* nodep) override { iterateChildren(nodep); } + void visit(AstCNew* nodep) override { iterateChildren(nodep); } + void visit(AstCFunc* nodep) override { VL_RESTORER(m_funcp); if (!nodep->user1()) { // Static functions should have been moved under the corresponding AstClassPackage @@ -268,13 +268,13 @@ private: } } } - virtual void visit(AstVar*) override {} - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit DescopeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~DescopeVisitor() override = default; + ~DescopeVisitor() override = default; }; //###################################################################### diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 2451cfdfc..ca293eef1 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -110,7 +110,7 @@ public: // CONSTRUCTORS EmitCBaseVisitor() = default; - virtual ~EmitCBaseVisitor() override = default; + ~EmitCBaseVisitor() override = default; }; #endif // guard diff --git a/src/V3EmitCConstInit.h b/src/V3EmitCConstInit.h index 6c02bf099..9c0960180 100644 --- a/src/V3EmitCConstInit.h +++ b/src/V3EmitCConstInit.h @@ -45,7 +45,7 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitor { protected: // VISITORS - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { VL_RESTORER(m_inUnpacked); VL_RESTORER(m_unpackedWord); m_inUnpacked = true; @@ -94,11 +94,11 @@ protected: } } - virtual void visit(AstInitItem* nodep) override { // LCOV_EXCL_START + void visit(AstInitItem* nodep) override { // LCOV_EXCL_START nodep->v3fatal("Handled by AstInitArray"); } // LCOV_EXCL_STOP - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { const V3Number& num = nodep->num(); UASSERT_OBJ(!num.isFourState(), nodep, "4-state value in constant pool"); const AstNodeDType* const dtypep = nodep->dtypep(); @@ -145,7 +145,7 @@ protected: } // Default - virtual void visit(AstNode* nodep) override { // LCOV_EXCL_START + void visit(AstNode* nodep) override { // LCOV_EXCL_START nodep->v3fatalSrc("Unknown node type reached EmitCConstInit: " << nodep->prettyTypeName()); } // LCOV_EXCL_STOP }; diff --git a/src/V3EmitCConstPool.cpp b/src/V3EmitCConstPool.cpp index 2fd22ccc4..d813fc955 100644 --- a/src/V3EmitCConstPool.cpp +++ b/src/V3EmitCConstPool.cpp @@ -100,7 +100,7 @@ class EmitCConstPool final : public EmitCConstInit { } // VISITORS - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { m_outFileSize += nodep->num().isString() ? 10 : nodep->isWide() ? nodep->widthWords() : 1; EmitCConstInit::visit(nodep); } diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 27af5ad6a..71d636cf9 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -70,17 +70,17 @@ class EmitCLazyDecls final : public VNVisitor { } // VISITORS - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { lazyDeclare(nodep->funcp()); iterateChildren(nodep); } - virtual void visit(AstAddrOfCFunc* nodep) override { + void visit(AstAddrOfCFunc* nodep) override { lazyDeclare(nodep->funcp()); iterateChildren(nodep); } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { AstVar* const varp = nodep->varp(); // Only constant pool symbols are lazy declared for now ... if (EmitCBaseVisitor::isConstPoolMod(EmitCParentModule::get(varp))) { @@ -88,7 +88,7 @@ class EmitCLazyDecls final : public VNVisitor { } } - virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } + void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } VL_DEBUG_FUNC; @@ -213,7 +213,7 @@ public: // VISITORS using EmitCConstInit::visit; - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { VL_RESTORER(m_useSelfForThis); VL_RESTORER(m_cfuncp); m_cfuncp = nodep; @@ -281,12 +281,12 @@ public: if (nodep->ifdef() != "") puts("#endif // " + nodep->ifdef() + "\n"); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { UASSERT_OBJ(m_cfuncp, nodep, "Cannot emit non-local variable"); emitVarDecl(nodep); } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { bool paren = true; bool decind = false; bool rhs = true; @@ -368,8 +368,8 @@ public: if (decind) ofp()->blockDec(); puts(";\n"); } - virtual void visit(AstAlwaysPublic*) override {} - virtual void visit(AstAssocSel* nodep) override { + void visit(AstAlwaysPublic*) override {} + void visit(AstAssocSel* nodep) override { iterateAndNextNull(nodep->fromp()); putbs(".at("); AstAssocArrayDType* const adtypep = VN_AS(nodep->fromp()->dtypep(), AssocArrayDType); @@ -381,7 +381,7 @@ public: } puts(")"); } - virtual void visit(AstWildcardSel* nodep) override { + void visit(AstWildcardSel* nodep) override { iterateAndNextNull(nodep->fromp()); putbs(".at("); AstWildcardArrayDType* const adtypep = VN_AS(nodep->fromp()->dtypep(), WildcardArrayDType); @@ -389,7 +389,7 @@ public: iterateAndNextNull(nodep->bitp()); puts(")"); } - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { const AstCFunc* const funcp = nodep->funcp(); const AstNodeModule* const funcModp = EmitCParentModule::get(funcp); if (funcp->dpiImportPrototype()) { @@ -415,7 +415,7 @@ public: } emitCCallArgs(nodep, nodep->selfPointerProtect(m_useSelfForThis)); } - virtual void visit(AstCMethodCall* nodep) override { + void visit(AstCMethodCall* nodep) override { const AstCFunc* const funcp = nodep->funcp(); UASSERT_OBJ(!funcp->isLoose(), nodep, "Loose method called via AstCMethodCall"); iterate(nodep->fromp()); @@ -423,7 +423,7 @@ public: puts(funcp->nameProtect()); emitCCallArgs(nodep, ""); } - virtual void visit(AstCNew* nodep) override { + void visit(AstCNew* nodep) override { bool comma = false; puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">("); puts("vlSymsp"); // TODO make this part of argsp, and eliminate when unnecessary @@ -435,7 +435,7 @@ public: } puts(")"); } - virtual void visit(AstCMethodHard* nodep) override { + void visit(AstCMethodHard* nodep) override { iterate(nodep->fromp()); puts("."); puts(nodep->name()); @@ -457,8 +457,8 @@ public: UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType), nodep, "Statement of non-void data type"); } - virtual void visit(AstLambdaArgRef* nodep) override { putbs(nodep->nameProtect()); } - virtual void visit(AstWith* nodep) override { + void visit(AstLambdaArgRef* nodep) override { putbs(nodep->nameProtect()); } + void visit(AstWith* nodep) override { // With uses a C++11 lambda putbs("[=]("); if (auto* const argrefp = nodep->indexArgRefp()) { @@ -473,11 +473,11 @@ public: iterateAndNextNull(nodep->exprp()); puts("; }\n"); } - virtual void visit(AstNodeCase* nodep) override { // LCOV_EXCL_LINE + void visit(AstNodeCase* nodep) override { // LCOV_EXCL_LINE // In V3Case... nodep->v3fatalSrc("Case statements should have been reduced out"); } - virtual void visit(AstComment* nodep) override { + void visit(AstComment* nodep) override { string at; if (nodep->showAt()) { at = " at " + nodep->fileline()->ascii(); @@ -489,7 +489,7 @@ public: } iterateChildren(nodep); } - virtual void visit(AstCoverDecl* nodep) override { + void visit(AstCoverDecl* nodep) override { puts("vlSelf->__vlCoverInsert("); // As Declared in emitCoverageDecl puts("&(vlSymsp->__Vcoverage["); puts(cvtToStr(nodep->dataDeclThisp()->binNum())); @@ -517,7 +517,7 @@ public: putsQuoted(nodep->linescov()); puts(");\n"); } - virtual void visit(AstCoverInc* nodep) override { + void visit(AstCoverInc* nodep) override { if (v3Global.opt.threads()) { puts("vlSymsp->__Vcoverage["); puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum())); @@ -528,17 +528,17 @@ public: puts("]);\n"); } } - virtual void visit(AstCReturn* nodep) override { + void visit(AstCReturn* nodep) override { puts("return ("); iterateAndNextNull(nodep->lhsp()); puts(");\n"); } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { string text = nodep->fmtp()->text(); if (nodep->addNewline()) text += "\n"; displayNode(nodep, nodep->fmtp()->scopeNamep(), text, nodep->fmtp()->exprsp(), false); } - virtual void visit(AstDumpCtl* nodep) override { + void visit(AstDumpCtl* nodep) override { switch (nodep->ctlType()) { case VDumpCtlType::FILE: puts("vlSymsp->_vm_contextp__->dumpfile("); @@ -577,7 +577,7 @@ public: default: nodep->v3fatalSrc("Bad case, unexpected " << nodep->ctlType().ascii()); } } - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { // For use under AstCCalls for dpiImports. ScopeNames under // displays are handled in AstDisplay if (!nodep->dpiExport()) { @@ -586,20 +586,20 @@ public: putbs("(&(vlSymsp->" + protect("__Vscope_" + scope) + "))"); } } - virtual void visit(AstSFormat* nodep) override { + void visit(AstSFormat* nodep) override { displayNode(nodep, nodep->fmtp()->scopeNamep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp(), false); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { displayNode(nodep, nodep->scopeNamep(), nodep->text(), nodep->exprsp(), false); } - virtual void visit(AstFScanF* nodep) override { + void visit(AstFScanF* nodep) override { displayNode(nodep, nullptr, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstSScanF* nodep) override { + void visit(AstSScanF* nodep) override { displayNode(nodep, nullptr, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstValuePlusArgs* nodep) override { + void visit(AstValuePlusArgs* nodep) override { puts("VL_VALUEPLUSARGS_IN"); emitIQW(nodep->outp()); puts("("); @@ -611,19 +611,19 @@ public: iterateAndNextNull(nodep->outp()); puts(")"); } - virtual void visit(AstTestPlusArgs* nodep) override { + void visit(AstTestPlusArgs* nodep) override { puts("VL_TESTPLUSARGS_I("); emitCvtPackStr(nodep->searchp()); puts(")"); } - virtual void visit(AstFError* nodep) override { + void visit(AstFError* nodep) override { puts("VL_FERROR_IN("); iterateAndNextNull(nodep->filep()); putbs(", "); iterateAndNextNull(nodep->strp()); puts(")"); } - virtual void visit(AstFGetS* nodep) override { + void visit(AstFGetS* nodep) override { checkMaxWords(nodep); emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); } @@ -636,7 +636,7 @@ public: << " bits exceeds hardcoded limit VL_VALUE_STRING_MAX_WORDS in verilatedos.h"); } } - virtual void visit(AstFOpen* nodep) override { + void visit(AstFOpen* nodep) override { iterateAndNextNull(nodep->filep()); puts(" = VL_FOPEN_NN("); emitCvtPackStr(nodep->filenamep()); @@ -646,13 +646,13 @@ public: emitCvtPackStr(nodep->modep()); puts(");\n"); } - virtual void visit(AstFOpenMcd* nodep) override { + void visit(AstFOpenMcd* nodep) override { iterateAndNextNull(nodep->filep()); puts(" = VL_FOPEN_MCD_N("); emitCvtPackStr(nodep->filenamep()); puts(");\n"); } - virtual void visit(AstNodeReadWriteMem* nodep) override { + void visit(AstNodeReadWriteMem* nodep) override { puts(nodep->cFuncPrefixp()); puts("N("); puts(nodep->isHex() ? "true" : "false"); @@ -701,14 +701,14 @@ public: } puts(");\n"); } - virtual void visit(AstFClose* nodep) override { + void visit(AstFClose* nodep) override { puts("VL_FCLOSE_I("); iterateAndNextNull(nodep->filep()); puts("); "); iterateAndNextNull(nodep->filep()); // For safety, so user doesn't later WRITE with it. puts(" = 0;\n"); } - virtual void visit(AstFFlush* nodep) override { + void visit(AstFFlush* nodep) override { if (!nodep->filep()) { puts("Verilated::runFlushCallbacks();\n"); } else { @@ -719,7 +719,7 @@ public: puts("); }\n"); } } - virtual void visit(AstFSeek* nodep) override { + void visit(AstFSeek* nodep) override { puts("(VL_FSEEK_I("); iterateAndNextNull(nodep->filep()); puts(","); @@ -728,17 +728,17 @@ public: iterateAndNextNull(nodep->operation()); puts(") == -1 ? -1 : 0)"); } - virtual void visit(AstFTell* nodep) override { + void visit(AstFTell* nodep) override { puts("VL_FTELL_I("); iterateAndNextNull(nodep->filep()); puts(")"); } - virtual void visit(AstFRewind* nodep) override { + void visit(AstFRewind* nodep) override { puts("(VL_FSEEK_I("); iterateAndNextNull(nodep->filep()); puts(", 0, 0) == -1 ? -1 : 0)"); } - virtual void visit(AstFRead* nodep) override { + void visit(AstFRead* nodep) override { puts("VL_FREAD_I("); puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width putbs(","); @@ -781,12 +781,12 @@ public: } puts(")"); } - virtual void visit(AstSysFuncAsTask* nodep) override { + void visit(AstSysFuncAsTask* nodep) override { if (!nodep->lhsp()->isWide()) puts("(void)"); iterateAndNextNull(nodep->lhsp()); if (!nodep->lhsp()->isWide()) puts(";"); } - virtual void visit(AstSystemT* nodep) override { + void visit(AstSystemT* nodep) override { puts("(void)VL_SYSTEM_I"); emitIQW(nodep->lhsp()); puts("("); @@ -798,7 +798,7 @@ public: iterateAndNextNull(nodep->lhsp()); puts(");\n"); } - virtual void visit(AstSystemF* nodep) override { + void visit(AstSystemF* nodep) override { puts("VL_SYSTEM_I"); emitIQW(nodep->lhsp()); puts("("); @@ -810,20 +810,20 @@ public: iterateAndNextNull(nodep->lhsp()); puts(")"); } - virtual void visit(AstJumpBlock* nodep) override { + void visit(AstJumpBlock* nodep) override { nodep->labelNum(++m_labelNum); puts("{\n"); // Make it visually obvious label jumps outside these iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->endStmtsp()); puts("}\n"); } - virtual void visit(AstJumpGo* nodep) override { + void visit(AstJumpGo* nodep) override { puts("goto __Vlabel" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n"); } - virtual void visit(AstJumpLabel* nodep) override { + void visit(AstJumpLabel* nodep) override { puts("__Vlabel" + cvtToStr(nodep->blockp()->labelNum()) + ": ;\n"); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { iterateAndNextNull(nodep->precondsp()); puts("while ("); iterateAndNextNull(nodep->condp()); @@ -833,7 +833,7 @@ public: iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop puts("}\n"); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { puts("if ("); if (!nodep->branchPred().unknown()) { puts(nodep->branchPred().ascii()); @@ -857,7 +857,7 @@ public: } } } - virtual void visit(AstExprStmt* nodep) override { + void visit(AstExprStmt* nodep) override { // GCC allows compound statements in expressions, but this is not standard. // So we use an immediate-evaluation lambda and comma operator putbs("([&]() {\n"); @@ -866,7 +866,7 @@ public: iterateAndNextNull(nodep->resultp()); puts(")"); } - virtual void visit(AstStop* nodep) override { + void visit(AstStop* nodep) override { puts("VL_STOP_MT("); putsQuoted(protect(nodep->fileline()->filename())); puts(", "); @@ -874,38 +874,38 @@ public: puts(", \"\""); puts(");\n"); } - virtual void visit(AstFinish* nodep) override { + void visit(AstFinish* nodep) override { puts("VL_FINISH_MT("); putsQuoted(protect(nodep->fileline()->filename())); puts(", "); puts(cvtToStr(nodep->fileline()->lineno())); puts(", \"\");\n"); } - virtual void visit(AstPrintTimeScale* nodep) override { + void visit(AstPrintTimeScale* nodep) override { puts("VL_PRINTTIMESCALE("); putsQuoted(protect(nodep->name())); puts(", "); putsQuoted(nodep->timeunit().ascii()); puts(", vlSymsp->_vm_contextp__);\n"); } - virtual void visit(AstRand* nodep) override { + void visit(AstRand* nodep) override { emitOpName(nodep, nodep->emitC(), nodep->seedp(), nullptr, nullptr); } - virtual void visit(AstTime* nodep) override { + void visit(AstTime* nodep) override { puts("VL_TIME_UNITED_Q("); if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time has no units"); puts(cvtToStr(nodep->timeunit().multiplier() / v3Global.rootp()->timeprecision().multiplier())); puts(")"); } - virtual void visit(AstTimeD* nodep) override { + void visit(AstTimeD* nodep) override { puts("VL_TIME_UNITED_D("); if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$realtime has no units"); puts(cvtToStr(nodep->timeunit().multiplier() / v3Global.rootp()->timeprecision().multiplier())); puts(")"); } - virtual void visit(AstTimeFormat* nodep) override { + void visit(AstTimeFormat* nodep) override { puts("VL_TIMEFORMAT_IINI("); iterateAndNextNull(nodep->unitsp()); puts(", "); @@ -916,7 +916,7 @@ public: iterateAndNextNull(nodep->widthp()); puts(", vlSymsp->_vm_contextp__);\n"); } - virtual void visit(AstNodeSimpleText* nodep) override { + void visit(AstNodeSimpleText* nodep) override { const string text = m_inUC && m_useSelfForThis ? VString::replaceWord(nodep->text(), "this", "vlSelf") : nodep->text(); @@ -926,29 +926,29 @@ public: ofp()->putsNoTracking(text); } } - virtual void visit(AstTextBlock* nodep) override { + void visit(AstTextBlock* nodep) override { visit(static_cast(nodep)); for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) { iterate(childp); if (nodep->commas() && childp->nextp()) puts(", "); } } - virtual void visit(AstCStmt* nodep) override { + void visit(AstCStmt* nodep) override { putbs(""); iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstCMath* nodep) override { + void visit(AstCMath* nodep) override { putbs(""); iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstUCStmt* nodep) override { + void visit(AstUCStmt* nodep) override { VL_RESTORER(m_inUC); m_inUC = true; putsDecoration(ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n")); iterateAndNextNull(nodep->bodysp()); puts("\n"); } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { VL_RESTORER(m_inUC); m_inUC = true; puts("\n"); @@ -958,10 +958,10 @@ public: } // Operators - virtual void visit(AstNodeTermop* nodep) override { + void visit(AstNodeTermop* nodep) override { emitOpName(nodep, nodep->emitC(), nullptr, nullptr, nullptr); } - virtual void visit(AstNodeUniop* nodep) override { + void visit(AstNodeUniop* nodep) override { if (nodep->emitCheckMaxWords() && (nodep->widthWords() > VL_MULS_MAX_WORDS || nodep->lhsp()->widthWords() > VL_MULS_MAX_WORDS)) { @@ -981,7 +981,7 @@ public: emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nullptr, nullptr); } } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { if (nodep->emitCheckMaxWords() && nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3warn( E_UNSUPPORTED, @@ -1001,11 +1001,11 @@ public: emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); } } - virtual void visit(AstNodeTriop* nodep) override { + void visit(AstNodeTriop* nodep) override { UASSERT_OBJ(!emitSimpleOk(nodep), nodep, "Triop cannot be described in a simple way"); emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nodep->thsp()); } - virtual void visit(AstRedXor* nodep) override { + void visit(AstRedXor* nodep) override { if (nodep->lhsp()->isWide()) { visit(static_cast(nodep)); } else { @@ -1021,7 +1021,7 @@ public: puts(")"); } } - virtual void visit(AstCCast* nodep) override { + void visit(AstCCast* nodep) override { // Extending a value of the same word width is just a NOP. if (nodep->size() <= VL_IDATASIZE) { puts("(IData)("); @@ -1031,7 +1031,7 @@ public: iterateAndNextNull(nodep->lhsp()); puts(")"); } - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { // Widths match up already, so we'll just use C++'s operator w/o any temps. if (nodep->expr1p()->isWide()) { emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p()); @@ -1045,12 +1045,12 @@ public: puts(")"); } } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { iterateAndNextNull(nodep->fromp()); putbs("->"); puts(nodep->varp()->nameProtect()); } - virtual void visit(AstNullCheck* nodep) override { + void visit(AstNullCheck* nodep) override { puts("VL_NULL_CHECK("); iterateAndNextNull(nodep->lhsp()); puts(", "); @@ -1059,17 +1059,17 @@ public: puts(cvtToStr(nodep->fileline()->lineno())); puts(")"); } - virtual void visit(AstNewCopy* nodep) override { + void visit(AstNewCopy* nodep) override { puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">("); puts("*"); // i.e. make into a reference iterateAndNextNull(nodep->rhsp()); puts(")"); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { // Note ASSIGN checks for this on a LHS emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp()); } - virtual void visit(AstReplicate* nodep) override { + void visit(AstReplicate* nodep) override { if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) { UASSERT_OBJ((static_cast(VN_AS(nodep->rhsp(), Const)->toUInt()) * nodep->lhsp()->widthMin()) @@ -1088,7 +1088,7 @@ public: emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); } } - virtual void visit(AstStreamL* nodep) override { + void visit(AstStreamL* nodep) override { // Attempt to use a "fast" stream function for slice size = power of 2 if (!nodep->isWide()) { const uint32_t isPow2 = VN_AS(nodep->rhsp(), Const)->num().countOnes() == 1; @@ -1110,14 +1110,14 @@ public: emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)", nodep->lhsp(), nodep->rhsp(), nullptr); } - virtual void visit(AstCastDynamic* nodep) override { + void visit(AstCastDynamic* nodep) override { putbs("VL_CAST_DYNAMIC("); iterateAndNextNull(nodep->lhsp()); puts(", "); iterateAndNextNull(nodep->rhsp()); puts(")"); } - virtual void visit(AstCountBits* nodep) override { + void visit(AstCountBits* nodep) override { putbs("VL_COUNTBITS_"); emitIQW(nodep->lhsp()); puts("("); @@ -1137,9 +1137,9 @@ public: iterateAndNextNull(nodep->fhsp()); puts(")"); } - virtual void visit(AstInitItem* nodep) override { iterateChildren(nodep); } + void visit(AstInitItem* nodep) override { iterateChildren(nodep); } // Terminals - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { const AstVar* const varp = nodep->varp(); const AstNodeModule* const varModp = EmitCParentModule::get(varp); if (isConstPoolMod(varModp)) { @@ -1156,14 +1156,14 @@ public: } puts(nodep->varp()->nameProtect()); } - virtual void visit(AstAddrOfCFunc* nodep) override { + void visit(AstAddrOfCFunc* nodep) override { // Note: Can be thought to handle more, but this is all that is needed right now const AstCFunc* const funcp = nodep->funcp(); UASSERT_OBJ(funcp->isLoose(), nodep, "Cannot take address of non-loose method"); puts("&"); puts(funcNameProtect(funcp)); } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { if (m_emitConstInit) { EmitCConstInit::visit(nodep); } else if (nodep->isWide()) { @@ -1176,12 +1176,12 @@ public: } // - virtual void visit(AstMTaskBody* nodep) override { + void visit(AstMTaskBody* nodep) override { VL_RESTORER(m_useSelfForThis); m_useSelfForThis = true; iterateChildrenConst(nodep); } - virtual void visit(AstConsAssoc* nodep) override { + void visit(AstConsAssoc* nodep) override { putbs(nodep->dtypep()->cType("", false, false)); puts("()"); if (nodep->defaultp()) { @@ -1190,7 +1190,7 @@ public: puts(")"); } } - virtual void visit(AstSetAssoc* nodep) override { + void visit(AstSetAssoc* nodep) override { iterateAndNextNull(nodep->lhsp()); putbs(".set("); iterateAndNextNull(nodep->keyp()); @@ -1199,7 +1199,7 @@ public: iterateAndNextNull(nodep->valuep()); puts(")"); } - virtual void visit(AstConsWildcard* nodep) override { + void visit(AstConsWildcard* nodep) override { putbs(nodep->dtypep()->cType("", false, false)); puts("()"); if (nodep->defaultp()) { @@ -1208,7 +1208,7 @@ public: puts(")"); } } - virtual void visit(AstSetWildcard* nodep) override { + void visit(AstSetWildcard* nodep) override { iterateAndNextNull(nodep->lhsp()); putbs(".set("); iterateAndNextNull(nodep->keyp()); @@ -1217,7 +1217,7 @@ public: iterateAndNextNull(nodep->valuep()); puts(")"); } - virtual void visit(AstConsDynArray* nodep) override { + void visit(AstConsDynArray* nodep) override { putbs(nodep->dtypep()->cType("", false, false)); if (!nodep->lhsp()) { puts("()"); @@ -1232,7 +1232,7 @@ public: puts(")"); } } - virtual void visit(AstConsQueue* nodep) override { + void visit(AstConsQueue* nodep) override { putbs(nodep->dtypep()->cType("", false, false)); if (!nodep->lhsp()) { puts("()"); @@ -1247,22 +1247,22 @@ public: puts(")"); } } - virtual void visit(AstCReset* nodep) override { + void visit(AstCReset* nodep) override { AstVar* const varp = nodep->varrefp()->varp(); emitVarReset(varp); } - virtual void visit(AstExecGraph* nodep) override { + void visit(AstExecGraph* nodep) override { // The location of the AstExecGraph within the containing AstCFunc is where we want to // invoke the graph and wait for it to complete. Emitting the children does just that. UASSERT_OBJ(!nodep->mTaskBodiesp(), nodep, "These should have been lowered"); iterateChildrenConst(nodep); } - virtual void visit(AstChangeDet* nodep) override { // + void visit(AstChangeDet* nodep) override { // m_blkChangeDetVec.push_back(nodep); } // Default - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { puts(string("\n???? // ") + nodep->prettyTypeName() + "\n"); iterateChildren(nodep); // LCOV_EXCL_START @@ -1280,7 +1280,7 @@ public: m_trackText = trackText; iterate(nodep); } - virtual ~EmitCFunc() override = default; + ~EmitCFunc() override = default; }; #endif // guard diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index a32f261d0..2a5c7985b 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -326,7 +326,7 @@ class EmitCHeader final : public EmitCConstInit { // Close output file VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } - virtual ~EmitCHeader() override = default; + ~EmitCHeader() override = default; public: static void main(const AstNodeModule* modp) { EmitCHeader emitCHeader(modp); } diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 988a8b7fd..cced5d818 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -68,59 +68,59 @@ class EmitCGatherDependencies final : VNVisitor { } // VISITORS - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { addSelfDependency(nodep->selfPointer(), nodep->funcp()); iterateChildrenConst(nodep); } - virtual void visit(AstCNew* nodep) override { + void visit(AstCNew* nodep) override { addDTypeDependency(nodep->dtypep()); iterateChildrenConst(nodep); } - virtual void visit(AstCMethodCall* nodep) override { + void visit(AstCMethodCall* nodep) override { addDTypeDependency(nodep->fromp()->dtypep()); iterateChildrenConst(nodep); } - virtual void visit(AstNewCopy* nodep) override { + void visit(AstNewCopy* nodep) override { addDTypeDependency(nodep->dtypep()); iterateChildrenConst(nodep); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { addDTypeDependency(nodep->fromp()->dtypep()); iterateChildrenConst(nodep); } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { addSelfDependency(nodep->selfPointer(), nodep->varp()); iterateChildrenConst(nodep); } - virtual void visit(AstCoverDecl* nodep) override { + void visit(AstCoverDecl* nodep) override { addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstCoverInc* nodep) override { + void visit(AstCoverInc* nodep) override { addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstDumpCtl* nodep) override { + void visit(AstDumpCtl* nodep) override { addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstPrintTimeScale* nodep) override { + void visit(AstPrintTimeScale* nodep) override { addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstTimeFormat* nodep) override { + void visit(AstTimeFormat* nodep) override { addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstNodeSimpleText* nodep) override { + void visit(AstNodeSimpleText* nodep) override { if (nodep->text().find("vlSymsp") != string::npos) addSymsDependency(); iterateChildrenConst(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } + void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } // CONSTRUCTOR explicit EmitCGatherDependencies(AstCFunc* cfuncp) { @@ -512,7 +512,7 @@ class EmitCImp final : EmitCFunc { } // VISITORS - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (splitNeeded()) { // Splitting file, so using parallel build. v3Global.useParallelBuild(true); @@ -544,7 +544,7 @@ class EmitCImp final : EmitCFunc { // Emit implementations of all AstCFunc emitCFuncImp(modp); } - virtual ~EmitCImp() override = default; + ~EmitCImp() override = default; public: static void main(const AstNodeModule* modp, bool slow, std::deque& cfilesr) { @@ -823,7 +823,7 @@ class EmitCTrace final : EmitCFunc { // VISITORS using EmitCFunc::visit; // Suppress hidden overloaded virtual function warning - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (!nodep->isTrace()) return; if (nodep->slow() != m_slow) return; @@ -838,17 +838,17 @@ class EmitCTrace final : EmitCFunc { EmitCFunc::visit(nodep); } - virtual void visit(AstTracePushNamePrefix* nodep) override { + void visit(AstTracePushNamePrefix* nodep) override { puts("tracep->pushNamePrefix("); putsQuoted(VIdProtect::protectWordsIf(nodep->prefix(), nodep->protect())); puts(");\n"); } - virtual void visit(AstTracePopNamePrefix* nodep) override { // + void visit(AstTracePopNamePrefix* nodep) override { // puts("tracep->popNamePrefix("); puts(cvtToStr(nodep->count())); puts(");\n"); } - virtual void visit(AstTraceDecl* nodep) override { + void visit(AstTraceDecl* nodep) override { const int enumNum = emitTraceDeclDType(nodep->dtypep()); if (nodep->arrayRange().ranged()) { puts("for (int i = 0; i < " + cvtToStr(nodep->arrayRange().elements()) + "; ++i) {\n"); @@ -859,7 +859,7 @@ class EmitCTrace final : EmitCFunc { puts("\n"); } } - virtual void visit(AstTraceInc* nodep) override { + void visit(AstTraceInc* nodep) override { if (nodep->declp()->arrayRange().ranged()) { // It traces faster if we unroll the loop for (int i = 0; i < nodep->declp()->arrayRange().elements(); i++) { @@ -883,7 +883,7 @@ class EmitCTrace final : EmitCFunc { // Close output file VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } - virtual ~EmitCTrace() override = default; + ~EmitCTrace() override = default; public: static void main(AstNodeModule* modp, bool slow, std::deque& cfilesr) { diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index f9a667e25..36b92ffec 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -32,18 +32,18 @@ class EmitCInlines final : EmitCBaseVisitor { // METHODS // VISITORS - virtual void visit(AstCNew* nodep) override { + void visit(AstCNew* nodep) override { if (v3Global.opt.savable()) v3warn(E_UNSUPPORTED, "Unsupported: --savable with dynamic new"); iterateChildren(nodep); } - virtual void visit(AstDumpCtl* nodep) override { + void visit(AstDumpCtl* nodep) override { if (v3Global.opt.trace()) v3Global.needTraceDumper(true); iterateChildren(nodep); } //--------------------------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: explicit EmitCInlines(AstNetlist* nodep) { iterate(nodep); } diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp index be04510aa..10314155f 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -32,7 +32,7 @@ class EmitCMain final : EmitCBaseVisitor { // VISITORS // This visitor doesn't really iterate, but exist to appease base class - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } // LCOV_EXCL_LINE + void visit(AstNode* nodep) override { iterateChildren(nodep); } // LCOV_EXCL_LINE public: // CONSTRUCTORS diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp index c8dc7b521..2c2239306 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -190,7 +190,7 @@ class EmitCModel final : public EmitCFunc { + "C* tfp, int levels, int options = 0);\n"); if (optSystemC()) { puts("/// SC tracing; avoid overloaded virtual function lint warning\n"); - puts("virtual void trace(sc_trace_file* tfp) const override { " + puts("void trace(sc_trace_file* tfp) const override { " "::sc_core::sc_module::trace(tfp); }\n"); } } diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 2bff31190..deff75056 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -258,7 +258,7 @@ class EmitCSyms final : EmitCBaseVisitor { } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Collect list of scopes iterateChildren(nodep); varsExpand(); @@ -280,8 +280,8 @@ class EmitCSyms final : EmitCBaseVisitor { if (!m_dpiHdrOnly) emitDpiImp(); } } - virtual void visit(AstConstPool* nodep) override {} // Ignore - virtual void visit(AstNodeModule* nodep) override { + void visit(AstConstPool* nodep) override {} // Ignore + void visit(AstNodeModule* nodep) override { nameCheck(nodep); VL_RESTORER(m_modp); { @@ -289,7 +289,7 @@ class EmitCSyms final : EmitCBaseVisitor { iterateChildren(nodep); } } - virtual void visit(AstCellInline* nodep) override { + void visit(AstCellInline* nodep) override { if (v3Global.opt.vpi()) { const string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE"; @@ -300,7 +300,7 @@ class EmitCSyms final : EmitCBaseVisitor { std::make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type))); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { if (VN_IS(m_modp, Class)) return; // The ClassPackage is what is visible nameCheck(nodep); @@ -315,7 +315,7 @@ class EmitCSyms final : EmitCBaseVisitor { timeunit, type))); } } - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { const string name = nodep->scopeSymName(); // UINFO(9,"scnameins sp "<name()<<" sp "<scopePrettySymName() // <<" ss"<isSigUserRdPublic() && !m_cfuncp) m_modVars.emplace_back(std::make_pair(m_modp, nodep)); } - virtual void visit(AstCoverDecl* nodep) override { + void visit(AstCoverDecl* nodep) override { // Assign numbers to all bins, so we know how big of an array to use if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for nodep->binNum(m_coverBins++); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { nameCheck(nodep); if (nodep->dpiImportPrototype() || nodep->dpiExportDispatcher()) m_dpis.push_back(nodep); VL_RESTORER(m_cfuncp); @@ -360,8 +360,8 @@ class EmitCSyms final : EmitCBaseVisitor { } //--------------------------------------- - virtual void visit(AstConst*) override {} - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstConst*) override {} + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: explicit EmitCSyms(AstNetlist* nodep, bool dpiHdrOnly) diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 1bd2c3a47..76144011b 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -53,14 +53,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } // VISITORS - virtual void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); } + void visit(AstNodeModule* nodep) override { putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n"); iterateChildrenConst(nodep); putqs(nodep, "end" + nodep->verilogKwd() + "\n"); } - virtual void visit(AstPort* nodep) override {} - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstPort* nodep) override {} + void visit(AstNodeFTask* nodep) override { putfs(nodep, nodep->isFunction() ? "function" : "task"); puts(" "); puts(nodep->prettyName()); @@ -70,7 +70,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { putfs(nodep, nodep->isFunction() ? "endfunction\n" : "endtask\n"); } - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { if (nodep->name() == "") { putbs("begin\n"); } else { @@ -79,7 +79,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateChildrenConst(nodep); puts("end\n"); } - virtual void visit(AstFork* nodep) override { + void visit(AstFork* nodep) override { if (nodep->name() == "") { putbs("fork\n"); } else { @@ -89,19 +89,19 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(nodep->joinType().verilogKwd()); puts("\n"); } - virtual void visit(AstFinal* nodep) override { + void visit(AstFinal* nodep) override { putfs(nodep, "final begin\n"); iterateChildrenConst(nodep); putqs(nodep, "end\n"); } - virtual void visit(AstInitial* nodep) override { + void visit(AstInitial* nodep) override { putfs(nodep, "initial begin\n"); iterateChildrenConst(nodep); putqs(nodep, "end\n"); } - virtual void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); } - virtual void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); } - virtual void visit(AstAlways* nodep) override { + void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); } + void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); } + void visit(AstAlways* nodep) override { putfs(nodep, "always "); if (m_sensesp) { iterateAndNextConstNull(m_sensesp); @@ -113,7 +113,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->bodysp()); putqs(nodep, "end\n"); } - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlwaysPublic* nodep) override { putfs(nodep, "/*verilator public_flat_rw "); if (m_sensesp) { iterateAndNextConstNull(m_sensesp); @@ -125,43 +125,43 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->bodysp()); putqs(nodep, "*/\n"); } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { if (VN_IS(nodep, AssignForce)) puts("force "); iterateAndNextConstNull(nodep->lhsp()); putfs(nodep, " " + nodep->verilogKwd() + " "); iterateAndNextConstNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { iterateAndNextConstNull(nodep->lhsp()); putfs(nodep, " <= "); iterateAndNextConstNull(nodep->rhsp()); puts(";\n"); } - virtual void visit(AstAssignAlias* nodep) override { + void visit(AstAssignAlias* nodep) override { putbs("alias "); iterateAndNextConstNull(nodep->lhsp()); putfs(nodep, " = "); iterateAndNextConstNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { putfs(nodep, "assign "); iterateAndNextConstNull(nodep->lhsp()); putbs(" = "); iterateAndNextConstNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstRelease* nodep) override { + void visit(AstRelease* nodep) override { puts("release "); iterateAndNextConstNull(nodep->lhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstBreak*) override { + void visit(AstBreak*) override { putbs("break"); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { // AstSenItem is called for dumping in isolation by V3Order putfs(nodep, "@("); for (AstNode* expp = nodep->sensesp(); expp; expp = expp->nextp()) { @@ -170,13 +170,13 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts(")"); } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { putfs(nodep, ""); puts(nodep->edgeType().verilogKwd()); if (nodep->sensp()) puts(" "); iterateChildrenConst(nodep); } - virtual void visit(AstNodeCase* nodep) override { + void visit(AstNodeCase* nodep) override { putfs(nodep, ""); if (const AstCase* const casep = VN_CAST(nodep, Case)) { if (casep->priorityPragma()) puts("priority "); @@ -197,7 +197,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->itemsp()); putqs(nodep, "endcase\n"); } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { if (nodep->condsp()) { iterateAndNextConstNull(nodep->condsp()); } else { @@ -207,17 +207,17 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->bodysp()); putqs(nodep, "end\n"); } - virtual void visit(AstComment* nodep) override { + void visit(AstComment* nodep) override { puts(std::string{"// "} + nodep->name() + "\n"); iterateChildrenConst(nodep); } - virtual void visit(AstContinue*) override { + void visit(AstContinue*) override { putbs("continue"); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstCoverDecl*) override {} // N/A - virtual void visit(AstCoverInc*) override {} // N/A - virtual void visit(AstCoverToggle*) override {} // N/A + void visit(AstCoverDecl*) override {} // N/A + void visit(AstCoverInc*) override {} // N/A + void visit(AstCoverToggle*) override {} // N/A void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, const string& text, AstNode* exprsp) { @@ -234,26 +234,26 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts(");\n"); } - virtual void visit(AstDisable* nodep) override { putbs("disable " + nodep->name() + ";\n"); } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisable* nodep) override { putbs("disable " + nodep->name() + ";\n"); } + void visit(AstDisplay* nodep) override { visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } - virtual void visit(AstElabDisplay* nodep) override { + void visit(AstElabDisplay* nodep) override { visitNodeDisplay(nodep, nullptr, nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } - virtual void visit(AstFScanF* nodep) override { + void visit(AstFScanF* nodep) override { visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp()); } - virtual void visit(AstSScanF* nodep) override { + void visit(AstSScanF* nodep) override { visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp()); } - virtual void visit(AstSFormat* nodep) override { + void visit(AstSFormat* nodep) override { visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { visitNodeDisplay(nodep, nullptr, nodep->text(), nodep->exprsp()); } - virtual void visit(AstFOpen* nodep) override { + void visit(AstFOpen* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); iterateAndNextConstNull(nodep->filenamep()); @@ -261,36 +261,34 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->modep()); puts(");\n"); } - virtual void visit(AstFOpenMcd* nodep) override { + void visit(AstFOpenMcd* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); iterateAndNextConstNull(nodep->filenamep()); puts(");\n"); } - virtual void visit(AstFClose* nodep) override { + void visit(AstFClose* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); if (nodep->filep()) iterateAndNextConstNull(nodep->filep()); puts(");\n"); } - virtual void visit(AstFFlush* nodep) override { + void visit(AstFFlush* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); if (nodep->filep()) iterateAndNextConstNull(nodep->filep()); puts(");\n"); } - virtual void visit(AstJumpBlock* nodep) override { + void visit(AstJumpBlock* nodep) override { putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n"); if (nodep->stmtsp()) iterateAndNextConstNull(nodep->stmtsp()); puts("end\n"); } - virtual void visit(AstJumpGo* nodep) override { + void visit(AstJumpGo* nodep) override { putbs("disable label" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n"); } - virtual void visit(AstJumpLabel* nodep) override { - putbs("// " + cvtToStr(nodep->blockp()) + ":\n"); - } - virtual void visit(AstNodeReadWriteMem* nodep) override { + void visit(AstJumpLabel* nodep) override { putbs("// " + cvtToStr(nodep->blockp()) + ":\n"); } + void visit(AstNodeReadWriteMem* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); if (nodep->filenamep()) iterateAndNextConstNull(nodep->filenamep()); @@ -306,17 +304,17 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts(");\n"); } - virtual void visit(AstSysFuncAsTask* nodep) override { + void visit(AstSysFuncAsTask* nodep) override { iterateAndNextConstNull(nodep->lhsp()); puts(";\n"); } - virtual void visit(AstSysIgnore* nodep) override { + void visit(AstSysIgnore* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); iterateAndNextConstNull(nodep->exprsp()); puts(");\n"); } - virtual void visit(AstNodeFor* nodep) override { + void visit(AstNodeFor* nodep) override { putfs(nodep, "for ("); { VL_RESTORER(m_suppressSemi); @@ -331,14 +329,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->bodysp()); putqs(nodep, "end\n"); } - virtual void visit(AstRepeat* nodep) override { + void visit(AstRepeat* nodep) override { putfs(nodep, "repeat ("); iterateAndNextConstNull(nodep->countp()); puts(") begin\n"); iterateAndNextConstNull(nodep->bodysp()); putfs(nodep, "end\n"); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { iterateAndNextConstNull(nodep->precondsp()); putfs(nodep, "while ("); iterateAndNextConstNull(nodep->condp()); @@ -348,7 +346,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->precondsp()); // Need to recompute before next loop putfs(nodep, "end\n"); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { putfs(nodep, ""); if (const AstIf* const ifp = VN_CAST(nodep, If)) { if (ifp->priorityPragma()) puts("priority "); @@ -366,7 +364,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } putqs(nodep, "end\n"); } - virtual void visit(AstPast* nodep) override { + void visit(AstPast* nodep) override { putfs(nodep, "$past("); iterateAndNextConstNull(nodep->exprp()); if (nodep->ticksp()) { @@ -375,21 +373,21 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts(")"); } - virtual void visit(AstReturn* nodep) override { + void visit(AstReturn* nodep) override { putfs(nodep, "return "); iterateAndNextConstNull(nodep->lhsp()); puts(";\n"); } - virtual void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); } - virtual void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); } - virtual void visit(AstNodeSimpleText* nodep) override { + void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); } + void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); } + void visit(AstNodeSimpleText* nodep) override { if (nodep->tracking() || m_trackText) { puts(nodep->text()); } else { putsNoTracking(nodep->text()); } } - virtual void visit(AstTextBlock* nodep) override { + void visit(AstTextBlock* nodep) override { visit(static_cast(nodep)); { VL_RESTORER(m_suppressSemi); @@ -400,23 +398,23 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } } } - virtual void visit(AstScopeName* nodep) override {} - virtual void visit(AstCStmt* nodep) override { + void visit(AstScopeName* nodep) override {} + void visit(AstCStmt* nodep) override { putfs(nodep, "$_CSTMT("); iterateAndNextConstNull(nodep->bodysp()); puts(");\n"); } - virtual void visit(AstCMath* nodep) override { + void visit(AstCMath* nodep) override { putfs(nodep, "$_CMATH("); iterateAndNextConstNull(nodep->bodysp()); puts(");\n"); } - virtual void visit(AstUCStmt* nodep) override { + void visit(AstUCStmt* nodep) override { putfs(nodep, "$c("); iterateAndNextConstNull(nodep->bodysp()); puts(");\n"); } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { putfs(nodep, "$c("); iterateAndNextConstNull(nodep->bodysp()); puts(")"); @@ -481,25 +479,23 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } } - virtual void visit(AstNodeTermop* nodep) override { - emitVerilogFormat(nodep, nodep->emitVerilog()); - } - virtual void visit(AstNodeUniop* nodep) override { + void visit(AstNodeTermop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog()); } + void visit(AstNodeUniop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp()); } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp()); } - virtual void visit(AstNodeTriop* nodep) override { + void visit(AstNodeTriop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp()); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { iterate(nodep->fromp()); puts("."); puts(nodep->prettyName()); } - virtual void visit(AstAttrOf* nodep) override { + void visit(AstAttrOf* nodep) override { putfs(nodep, "$_ATTROF("); iterateAndNextConstNull(nodep->fromp()); if (nodep->dimp()) { @@ -508,7 +504,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts(")"); } - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { putfs(nodep, "'{"); int comma = 0; const auto& mapr = nodep->map(); @@ -521,7 +517,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts("}"); } - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { putbs("("); iterateAndNextConstNull(nodep->condp()); putfs(nodep, " ? "); @@ -530,7 +526,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->expr2p()); puts(")"); } - virtual void visit(AstRange* nodep) override { + void visit(AstRange* nodep) override { puts("["); if (VN_IS(nodep->leftp(), Const) && VN_IS(nodep->rightp(), Const)) { // Looks nicer if we print [1:0] rather than [32'sh1:32sh0] @@ -545,7 +541,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts("]"); } } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { iterateAndNextConstNull(nodep->fromp()); puts("["); if (VN_IS(nodep->lsbp(), Const)) { @@ -569,18 +565,18 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts("]"); } - virtual void visit(AstSliceSel* nodep) override { + void visit(AstSliceSel* nodep) override { iterateAndNextConstNull(nodep->fromp()); puts(cvtToStr(nodep->declRange())); } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { putfs(nodep, "typedef "); iterateAndNextConstNull(nodep->dtypep()); puts(" "); puts(nodep->prettyName()); puts(";\n"); } - virtual void visit(AstBasicDType* nodep) override { + void visit(AstBasicDType* nodep) override { if (nodep->isSigned()) putfs(nodep, "signed "); putfs(nodep, nodep->prettyName()); if (nodep->rangep()) { @@ -593,15 +589,15 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(":0] "); } } - virtual void visit(AstConstDType* nodep) override { + void visit(AstConstDType* nodep) override { putfs(nodep, "const "); iterate(nodep->subDTypep()); } - virtual void visit(AstNodeArrayDType* nodep) override { + void visit(AstNodeArrayDType* nodep) override { iterate(nodep->subDTypep()); iterateAndNextConstNull(nodep->rangep()); } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { puts(nodep->verilogKwd() + " "); if (nodep->packed()) puts("packed "); puts("\n"); @@ -609,12 +605,12 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->membersp()); puts("}"); } - virtual void visit(AstMemberDType* nodep) override { + void visit(AstMemberDType* nodep) override { iterate(nodep->subDTypep()); puts(" "); puts(nodep->name()); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { if (nodep->dotted() != "") { putfs(nodep, nodep->dotted()); puts("."); @@ -626,14 +622,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->pinsp()); puts(")"); } - virtual void visit(AstArg* nodep) override { iterateAndNextConstNull(nodep->exprp()); } - virtual void visit(AstPrintTimeScale* nodep) override { + void visit(AstArg* nodep) override { iterateAndNextConstNull(nodep->exprp()); } + void visit(AstPrintTimeScale* nodep) override { puts(nodep->verilogKwd()); puts(";\n"); } // Terminals - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (nodep->varScopep()) { putfs(nodep, nodep->varScopep()->prettyName()); } else { @@ -649,7 +645,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } } } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { putfs(nodep, nodep->dotted()); puts("."); if (nodep->varp()) { @@ -658,12 +654,12 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts(nodep->prettyName()); } } - virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); } + void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); } // Just iterate - virtual void visit(AstTopScope* nodep) override { iterateChildrenConst(nodep); } - virtual void visit(AstScope* nodep) override { iterateChildrenConst(nodep); } - virtual void visit(AstVar* nodep) override { + void visit(AstTopScope* nodep) override { iterateChildrenConst(nodep); } + void visit(AstScope* nodep) override { iterateChildrenConst(nodep); } + void visit(AstVar* nodep) override { if (nodep->isIO()) { putfs(nodep, nodep->verilogKwd()); puts(" "); @@ -691,21 +687,21 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { } puts(m_suppressVarSemi ? "\n" : ";\n"); } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { m_sensesp = nodep->sensesp(); iterateAndNextConstNull(nodep->stmtsp()); m_sensesp = nullptr; } - virtual void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); } - virtual void visit(AstVarScope*) override {} - virtual void visit(AstNodeText*) override {} - virtual void visit(AstTraceDecl*) override {} - virtual void visit(AstTraceInc*) override {} + void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); } + void visit(AstVarScope*) override {} + void visit(AstNodeText*) override {} + void visit(AstTraceDecl*) override {} + void visit(AstTraceInc*) override {} // NOPs - virtual void visit(AstPragma*) override {} - virtual void visit(AstCell*) override {} // Handled outside the Visit class + void visit(AstPragma*) override {} + void visit(AstCell*) override {} // Handled outside the Visit class // Default - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { puts(std::string{"\n???? // "} + nodep->prettyTypeName() + "\n"); iterateChildrenConst(nodep); // Not v3fatalSrc so we keep processing @@ -720,7 +716,7 @@ public: explicit EmitVBaseVisitor(bool suppressUnknown, AstSenTree* domainp) : m_suppressUnknown{suppressUnknown} , m_sensesp{domainp} {} - virtual ~EmitVBaseVisitor() override = default; + ~EmitVBaseVisitor() override = default; }; //###################################################################### @@ -731,11 +727,11 @@ class EmitVFileVisitor final : public EmitVBaseVisitor { V3OutFile* m_ofp; // METHODS V3OutFile* ofp() const { return m_ofp; } - virtual void puts(const string& str) override { ofp()->puts(str); } - virtual void putbs(const string& str) override { ofp()->putbs(str); } - virtual void putfs(AstNode*, const string& str) override { putbs(str); } - virtual void putqs(AstNode*, const string& str) override { putbs(str); } - virtual void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); } + void puts(const string& str) override { ofp()->puts(str); } + void putbs(const string& str) override { ofp()->putbs(str); } + void putfs(AstNode*, const string& str) override { putbs(str); } + void putqs(AstNode*, const string& str) override { putbs(str); } + void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); } public: EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText, bool suppressUnknown) @@ -744,7 +740,7 @@ public: m_trackText = trackText; iterate(nodep); } - virtual ~EmitVFileVisitor() override = default; + ~EmitVFileVisitor() override = default; }; //###################################################################### @@ -754,11 +750,11 @@ class EmitVStreamVisitor final : public EmitVBaseVisitor { // MEMBERS std::ostream& m_os; // METHODS - virtual void putsNoTracking(const string& str) override { m_os << str; } - virtual void puts(const string& str) override { putsNoTracking(str); } - virtual void putbs(const string& str) override { puts(str); } - virtual void putfs(AstNode*, const string& str) override { putbs(str); } - virtual void putqs(AstNode*, const string& str) override { putbs(str); } + void putsNoTracking(const string& str) override { m_os << str; } + void puts(const string& str) override { putsNoTracking(str); } + void putbs(const string& str) override { puts(str); } + void putfs(AstNode*, const string& str) override { putbs(str); } + void putqs(AstNode*, const string& str) override { putbs(str); } public: EmitVStreamVisitor(const AstNode* nodep, std::ostream& os) @@ -766,7 +762,7 @@ public: , m_os(os) { // Need () or GCC 4.8 false warning iterate(const_cast(nodep)); } - virtual ~EmitVStreamVisitor() override = default; + ~EmitVStreamVisitor() override = default; }; //###################################################################### @@ -779,7 +775,7 @@ class EmitVPrefixedFormatter final : public V3OutFormatter { int m_column = 0; // Rough location; need just zero or non-zero FileLine* m_prefixFl; // METHODS - virtual void putcOutput(char chr) override { + void putcOutput(char chr) override { if (chr == '\n') { m_column = 0; m_os << chr; @@ -796,7 +792,7 @@ class EmitVPrefixedFormatter final : public V3OutFormatter { } } - virtual void putsOutput(const char* strg) override { + void putsOutput(const char* strg) override { for (const char* cp = strg; *cp; cp++) putcOutput(*cp); } @@ -812,7 +808,7 @@ public: m_prefixFl = v3Global.rootp()->fileline(); // NETLIST's fileline instead of nullptr to // avoid nullptr checks } - virtual ~EmitVPrefixedFormatter() override { + ~EmitVPrefixedFormatter() override { if (m_column) puts("\n"); } }; @@ -822,13 +818,13 @@ class EmitVPrefixedVisitor final : public EmitVBaseVisitor { EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the // inheritance is another unused V3OutFormatter) // METHODS - virtual void putsNoTracking(const string& str) override { m_formatter.putsNoTracking(str); } - virtual void puts(const string& str) override { m_formatter.puts(str); } + void putsNoTracking(const string& str) override { m_formatter.putsNoTracking(str); } + void puts(const string& str) override { m_formatter.puts(str); } // We don't use m_formatter's putbs because the tokens will change filelines // and insert returns at the proper locations - virtual void putbs(const string& str) override { m_formatter.puts(str); } - virtual void putfs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, false); } - virtual void putqs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, true); } + void putbs(const string& str) override { m_formatter.puts(str); } + void putfs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, false); } + void putqs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, true); } void putfsqs(AstNode* nodep, const string& str, bool quiet) { if (m_formatter.prefixFl() != nodep->fileline()) { m_formatter.prefixFl(nodep->fileline()); @@ -846,7 +842,7 @@ public: if (user3mark) VNUser3InUse::check(); iterate(const_cast(nodep)); } - virtual ~EmitVPrefixedVisitor() override = default; + ~EmitVPrefixedVisitor() override = default; }; //###################################################################### diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index 933f27079..bac6b6791 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -101,11 +101,11 @@ class EmitXmlFileVisitor final : public VNVisitor { } // VISITORS - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { outputTag(nodep, "contassign"); // IEEE: vpiContAssign outputChildrenEnd(nodep, "contassign"); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { outputTag(nodep, "instance"); // IEEE: vpiInstance puts(" defName="); putsQuoted(nodep->modName()); // IEEE vpiDefName @@ -113,7 +113,7 @@ class EmitXmlFileVisitor final : public VNVisitor { putsQuoted(nodep->origName()); outputChildrenEnd(nodep, "instance"); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { outputTag(nodep, "if"); puts(">\n"); iterateAndNextNull(nodep->op1p()); @@ -127,7 +127,7 @@ class EmitXmlFileVisitor final : public VNVisitor { } puts("\n"); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { outputTag(nodep, "while"); puts(">\n"); puts("\n"); @@ -150,19 +150,19 @@ class EmitXmlFileVisitor final : public VNVisitor { } puts("\n"); } - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { puts("\n"); iterateChildren(nodep); puts("\n"); } - virtual void visit(AstConstPool* nodep) override { + void visit(AstConstPool* nodep) override { if (!v3Global.opt.xmlOnly()) { puts("\n"); iterateChildren(nodep); puts("\n"); } } - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { puts("\n"); const auto& mapr = nodep->map(); for (const auto& itr : mapr) { @@ -174,7 +174,7 @@ class EmitXmlFileVisitor final : public VNVisitor { } puts("\n"); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { outputTag(nodep, ""); puts(" origName="); putsQuoted(nodep->origName()); @@ -184,7 +184,7 @@ class EmitXmlFileVisitor final : public VNVisitor { if (nodep->modPublic()) puts(" public=\"true\""); outputChildrenEnd(nodep, ""); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { const VVarType typ = nodep->varType(); const string kw = nodep->verilogKwd(); const string vt = nodep->dtypep()->name(); @@ -222,7 +222,7 @@ class EmitXmlFileVisitor final : public VNVisitor { if (nodep->attrSFormat()) puts(" sformat=\"true\""); outputChildrenEnd(nodep, ""); } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { // What we call a pin in verilator is a port in the IEEE spec. outputTag(nodep, "port"); // IEEE: vpiPort if (nodep->modVarp()->isIO()) { @@ -232,12 +232,12 @@ class EmitXmlFileVisitor final : public VNVisitor { // Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?) outputChildrenEnd(nodep, "port"); } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { outputTag(nodep, ""); puts(" edgeType=\"" + cvtToStr(nodep->edgeType().ascii()) + "\""); // IEEE vpiTopModule outputChildrenEnd(nodep, ""); } - virtual void visit(AstModportVarRef* nodep) override { + void visit(AstModportVarRef* nodep) override { // Dump direction for Modport references const string kw = nodep->direction().xmlKwd(); outputTag(nodep, ""); @@ -245,13 +245,13 @@ class EmitXmlFileVisitor final : public VNVisitor { putsQuoted(kw); outputChildrenEnd(nodep, ""); } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { outputTag(nodep, ""); puts(" dotted="); putsQuoted(nodep->dotted()); outputChildrenEnd(nodep, ""); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { outputTag(nodep, ""); puts(" func="); putsQuoted(nodep->funcp()->name()); @@ -259,7 +259,7 @@ class EmitXmlFileVisitor final : public VNVisitor { } // Data types - virtual void visit(AstBasicDType* nodep) override { + void visit(AstBasicDType* nodep) override { outputTag(nodep, "basicdtype"); if (nodep->isRanged()) { puts(" left=\"" + cvtToStr(nodep->left()) + "\""); @@ -268,7 +268,7 @@ class EmitXmlFileVisitor final : public VNVisitor { if (nodep->isSigned()) { puts(" signed=\"true\""); } puts("/>\n"); } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { string mpn; outputTag(nodep, ""); if (nodep->isModport()) mpn = nodep->modportName(); @@ -276,19 +276,19 @@ class EmitXmlFileVisitor final : public VNVisitor { putsQuoted(mpn); outputChildrenEnd(nodep, ""); } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { outputTag(nodep, ""); puts(" displaytype="); putsQuoted(nodep->verilogKwd()); outputChildrenEnd(nodep, ""); } - virtual void visit(AstElabDisplay* nodep) override { + void visit(AstElabDisplay* nodep) override { outputTag(nodep, ""); puts(" displaytype="); putsQuoted(nodep->verilogKwd()); outputChildrenEnd(nodep, ""); } - virtual void visit(AstExtend* nodep) override { + void visit(AstExtend* nodep) override { outputTag(nodep, ""); puts(" width="); putsQuoted(cvtToStr(nodep->width())); @@ -296,7 +296,7 @@ class EmitXmlFileVisitor final : public VNVisitor { putsQuoted(cvtToStr(nodep->lhsp()->widthMinV())); outputChildrenEnd(nodep, ""); } - virtual void visit(AstExtendS* nodep) override { + void visit(AstExtendS* nodep) override { outputTag(nodep, ""); puts(" width="); putsQuoted(cvtToStr(nodep->width())); @@ -306,7 +306,7 @@ class EmitXmlFileVisitor final : public VNVisitor { } // Default - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { outputTag(nodep, ""); outputChildrenEnd(nodep, ""); } @@ -316,7 +316,7 @@ public: : m_ofp{ofp} { iterate(nodep); } - virtual ~EmitXmlFileVisitor() override = default; + ~EmitXmlFileVisitor() override = default; }; //###################################################################### @@ -333,11 +333,11 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Children are iterated backwards to ensure correct compilation order iterateChildrenBackwards(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Only list modules and interfaces // Assumes modules and interfaces list is already sorted level wise if (!nodep->dead() && (VN_IS(nodep, Module) || VN_IS(nodep, Iface)) @@ -346,7 +346,7 @@ private: } } //----- - virtual void visit(AstNode*) override { + void visit(AstNode*) override { // All modules are present at root so no need to iterate on children } @@ -364,7 +364,7 @@ public: } m_os << "\n"; } - virtual ~ModuleFilesXmlVisitor() override = default; + ~ModuleFilesXmlVisitor() override = default; }; //###################################################################### @@ -381,9 +381,9 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstConstPool*) override {} + void visit(AstConstPool*) override {} - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { if (nodep->level() >= 0 && nodep->level() <= 2) { // ==2 because we don't add wrapper when in XML mode m_os << "\n"; @@ -402,7 +402,7 @@ private: m_os << "\n"; } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { if (nodep->modp()->dead()) return; if (!m_hasChildren) m_os << ">\n"; m_os << "fileline()->xmlDetailedLocation() << " name=\"" << nodep->name() @@ -422,7 +422,7 @@ private: m_hasChildren = true; } //----- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -431,7 +431,7 @@ public: // Operate on whole netlist nodep->accept(*this); } - virtual ~HierCellsXmlVisitor() override = default; + ~HierCellsXmlVisitor() override = default; }; //###################################################################### diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 6e8e2c1ec..85635e31a 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -313,7 +313,7 @@ private: } // VISITORS - virtual void visit(AstExtend* nodep) override { + void visit(AstExtend* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->isWide()) { @@ -339,7 +339,7 @@ private: } } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); // Remember, Sel's may have non-integer rhs, so need to optimize for that! @@ -628,7 +628,7 @@ private: } } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->isWide()) { @@ -665,7 +665,7 @@ private: return true; } - virtual void visit(AstReplicate* nodep) override { + void visit(AstReplicate* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->isWide()) { @@ -750,10 +750,10 @@ private: VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } } - virtual void visit(AstEq* nodep) override { visitEqNeq(nodep); } - virtual void visit(AstNeq* nodep) override { visitEqNeq(nodep); } + void visit(AstEq* nodep) override { visitEqNeq(nodep); } + void visit(AstNeq* nodep) override { visitEqNeq(nodep); } - virtual void visit(AstRedOr* nodep) override { + void visit(AstRedOr* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); FileLine* const fl = nodep->fileline(); @@ -775,7 +775,7 @@ private: VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } } - virtual void visit(AstRedAnd* nodep) override { + void visit(AstRedAnd* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); FileLine* const fl = nodep->fileline(); @@ -805,7 +805,7 @@ private: VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep); } } - virtual void visit(AstRedXor* nodep) override { + void visit(AstRedXor* nodep) override { if (nodep->user1SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->lhsp()->isWide()) { @@ -825,7 +825,7 @@ private: // which the inlined function does nicely. } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (nodep->user1SetOnce()) return; // Process once if (!nodep->isStatement()) { iterateChildren(nodep); @@ -835,7 +835,7 @@ private: iterateChildren(nodep); m_stmtp = nullptr; } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { if (nodep->user1SetOnce()) return; // Process once m_stmtp = nodep; iterateChildren(nodep); @@ -876,13 +876,13 @@ private: } //-------------------- - virtual void visit(AstVar*) override {} // Don't hit varrefs under vars - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't hit varrefs under vars + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ExpandVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ExpandVisitor() override { + ~ExpandVisitor() override { V3Stats::addStat("Optimizations, expand wides", m_statWides); V3Stats::addStat("Optimizations, expand wide words", m_statWideWords); V3Stats::addStat("Optimizations, expand limited", m_statWideLimited); diff --git a/src/V3File.h b/src/V3File.h index 95b29eb8d..38f4dc6ff 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -206,7 +206,7 @@ public: V3OutFile(V3OutFile&&) = delete; V3OutFile& operator=(V3OutFile&&) = delete; - virtual ~V3OutFile() override; + ~V3OutFile() override; void putsForceIncs(); private: @@ -216,11 +216,11 @@ private: } // CALLBACKS - virtual void putcOutput(char chr) override { + void putcOutput(char chr) override { m_bufferp->at(m_usedBytes++) = chr; if (VL_UNLIKELY(m_usedBytes >= WRITE_BUFFER_SIZE_BYTES)) writeBlock(); } - virtual void putsOutput(const char* str) override { + void putsOutput(const char* str) override { std::size_t len = strlen(str); std::size_t availableBytes = WRITE_BUFFER_SIZE_BYTES - m_usedBytes; while (VL_UNLIKELY(len >= availableBytes)) { @@ -246,7 +246,7 @@ public: : V3OutFile{filename, V3OutFormatter::LA_C} { resetPrivate(); } - virtual ~V3OutCFile() override = default; + ~V3OutCFile() override = default; virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); } virtual void putsIntTopInclude() { putsForceIncs(); } virtual void putsGuard(); @@ -270,9 +270,9 @@ class V3OutScFile final : public V3OutCFile { public: explicit V3OutScFile(const string& filename) : V3OutCFile{filename} {} - virtual ~V3OutScFile() override = default; - virtual void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); } - virtual void putsIntTopInclude() override { + ~V3OutScFile() override = default; + void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); } + void putsIntTopInclude() override { putsForceIncs(); puts("#include \"systemc.h\"\n"); puts("#include \"verilated_sc.h\"\n"); @@ -283,7 +283,7 @@ class V3OutVFile final : public V3OutFile { public: explicit V3OutVFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_VERILOG} {} - virtual ~V3OutVFile() override = default; + ~V3OutVFile() override = default; virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); } }; @@ -293,7 +293,7 @@ public: : V3OutFile{filename, V3OutFormatter::LA_XML} { blockIndent(2); } - virtual ~V3OutXmlFile() override = default; + ~V3OutXmlFile() override = default; virtual void putsHeader() { puts("\n"); } }; @@ -301,7 +301,7 @@ class V3OutMkFile final : public V3OutFile { public: explicit V3OutMkFile(const string& filename) : V3OutFile{filename, V3OutFormatter::LA_MK} {} - virtual ~V3OutMkFile() override = default; + ~V3OutMkFile() override = default; virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); } // No automatic indentation yet. void puts(const char* strg) { putsNoTracking(strg); } diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index f7c9ed428..c65e1d3fe 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -79,9 +79,9 @@ public: GateEitherVertex(V3Graph* graphp, AstScope* scopep) : V3GraphVertex{graphp} , m_scopep{scopep} {} - virtual ~GateEitherVertex() override = default; + ~GateEitherVertex() override = default; // ACCESSORS - virtual string dotStyle() const override { return m_consumed ? "" : "dotted"; } + string dotStyle() const override { return m_consumed ? "" : "dotted"; } AstScope* scopep() const { return m_scopep; } bool reducible() const { return m_reducible; } bool dedupable() const { return m_dedupable; } @@ -137,11 +137,11 @@ public: GateVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : GateEitherVertex{graphp, scopep} , m_varScp{varScp} {} - virtual ~GateVarVertex() override = default; + ~GateVarVertex() override = default; // ACCESSORS AstVarScope* varScp() const { return m_varScp; } - virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } - virtual string dotColor() const override { return "blue"; } + string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); } + string dotColor() const override { return "blue"; } bool isTop() const { return m_isTop; } void setIsTop() { m_isTop = true; } bool isClock() const { return m_isClock; } @@ -162,7 +162,7 @@ public: setIsClock(); } } - virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) override { + VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) override { return v.visit(this, vu); } }; @@ -178,17 +178,15 @@ public: , m_nodep{nodep} , m_activep{activep} , m_slow{slow} {} - virtual ~GateLogicVertex() override = default; + ~GateLogicVertex() override = default; // ACCESSORS - virtual string name() const override { - return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); - } - virtual string dotColor() const override { return "purple"; } - virtual FileLine* fileline() const override { return nodep()->fileline(); } + string name() const override { return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); } + string dotColor() const override { return "purple"; } + FileLine* fileline() const override { return nodep()->fileline(); } AstNode* nodep() const { return m_nodep; } AstActive* activep() const { return m_activep; } bool slow() const { return m_slow; } - virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) override { + VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser{0}) override { return v.visit(this, vu); } }; @@ -217,7 +215,7 @@ private: } } // VISITORS - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { ++m_ops; iterateChildren(nodep); // We only allow a LHS ref for the var being set, and a RHS ref for @@ -243,7 +241,7 @@ private: m_rhsVarRefs.push_back(nodep); } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { m_substTreep = nodep->rhsp(); if (!VN_IS(nodep->lhsp(), NodeVarRef)) { clearSimple("ASSIGN(non-VARREF)"); @@ -264,7 +262,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // *** Special iterator if (!m_isSimple) return; // Fastpath if (++m_ops > v3Global.opt.gateStmts()) clearSimple("--gate-stmts exceeded"); @@ -294,7 +292,7 @@ public: } if (debug() >= 9 && !m_isSimple) nodep->dumpTree(cout, " gate!Ok: "); } - virtual ~GateOkVisitor() override = default; + ~GateOkVisitor() override = default; // PUBLIC METHODS bool isSimple() const { return m_isSimple; } AstNode* substTree() const { return m_substTreep; } @@ -413,7 +411,7 @@ private: void decomposeClkVectors(); // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { iterateChildren(nodep); // if (debug() > 6) m_graph.dump(); if (debug() > 6) m_graph.dumpDotFilePrefixed("gate_pre"); @@ -445,7 +443,7 @@ private: // Rewrite assignments consumedMove(); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; @@ -453,14 +451,14 @@ private: iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; m_logicVertexp = nullptr; iterateChildren(nodep); m_scopep = nullptr; } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { // Create required blocks and add to module UINFO(4, " BLOCK " << nodep << endl); m_activeReducible = !(nodep->hasClocked()); // Seq logic outputs aren't reducible @@ -471,7 +469,7 @@ private: m_activep = nullptr; m_activeReducible = true; } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { if (m_scopep) { UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block"); AstVarScope* const varscp = nodep->varScopep(); @@ -499,17 +497,17 @@ private: } } } - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlwaysPublic* nodep) override { VL_RESTORER(m_inSlow); { m_inSlow = true; iterateNewStmt(nodep, "AlwaysPublic", nullptr); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { iterateNewStmt(nodep, "User C Function", "User C Function"); } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { m_inSenItem = true; if (m_logicVertexp) { // Already under logic; presumably a SenGate iterateChildren(nodep); @@ -518,7 +516,7 @@ private: } m_inSenItem = false; } - virtual void visit(AstNodeProcedure* nodep) override { + void visit(AstNodeProcedure* nodep) override { VL_RESTORER(m_inSlow); { m_inSlow = VN_IS(nodep, Initial) || VN_IS(nodep, Final); @@ -526,23 +524,23 @@ private: nullptr); } } - virtual void visit(AstAssignAlias* nodep) override { // + void visit(AstAssignAlias* nodep) override { // iterateNewStmt(nodep, nullptr, nullptr); } - virtual void visit(AstAssignW* nodep) override { // + void visit(AstAssignW* nodep) override { // iterateNewStmt(nodep, nullptr, nullptr); } - virtual void visit(AstCoverToggle* nodep) override { + void visit(AstCoverToggle* nodep) override { iterateNewStmt(nodep, "CoverToggle", "CoverToggle"); } - virtual void visit(AstTraceDecl* nodep) override { + void visit(AstTraceDecl* nodep) override { VL_RESTORER(m_inSlow); { m_inSlow = true; iterateNewStmt(nodep, "Tracing", "Tracing"); } } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { UASSERT_OBJ(!(VN_IS(nodep->backp(), NodeAssign) && VN_AS(nodep->backp(), NodeAssign)->lhsp() == nodep), nodep, "Concat on LHS of assignment; V3Const should have deleted it"); @@ -550,7 +548,7 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); if (nodep->isOutputter() && m_logicVertexp) m_logicVertexp->setConsumed("outputter"); } @@ -558,7 +556,7 @@ private: public: // CONSTRUCTORS explicit GateVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~GateVisitor() override { + ~GateVisitor() override { V3Stats::addStat("Optimizations, Gate sigs deleted", m_statSigs); V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs); V3Stats::addStat("Optimizations, Gate sigs deduped", m_statDedupLogic); @@ -810,7 +808,7 @@ private: public: GateDedupeHash() = default; - virtual ~GateDedupeHash() override { + ~GateDedupeHash() override { if (v3Global.opt.debugCheck()) check(); } @@ -836,7 +834,7 @@ public: } // Callback from V3DupFinder::findDuplicate - virtual bool isSame(AstNode* node1p, AstNode* node2p) override { + bool isSame(AstNode* node1p, AstNode* node2p) override { // Assignment may have been hashReplaced, if so consider non-match (effectively removed) if (isReplaced(node1p) || isReplaced(node2p)) { // UINFO(9, "isSame hit on replaced "<<(void*)node1p<<" "<<(void*)node2p<elsesp()) { // we're under an always, this is the first IF, and there's no else @@ -945,16 +943,16 @@ private: } } - virtual void visit(AstComment*) override {} // NOP + void visit(AstComment*) override {} // NOP //-------------------- - virtual void visit(AstNode*) override { // + void visit(AstNode*) override { // m_dedupable = false; } public: // CONSTRUCTORS GateDedupeVarVisitor() = default; - virtual ~GateDedupeVarVisitor() override = default; + ~GateDedupeVarVisitor() override = default; // PUBLIC METHODS AstNodeVarRef* findDupe(AstNode* nodep, AstVarScope* consumerVarScopep, AstActive* activep) { m_assignp = nullptr; @@ -1043,7 +1041,7 @@ private: GateDedupeVarVisitor m_varVisitor; // Looks for a dupe of the logic int m_depth = 0; // Iteration depth - virtual VNUser visit(GateVarVertex* vvertexp, VNUser) override { + VNUser visit(GateVarVertex* vvertexp, VNUser) override { // Check that we haven't been here before if (m_depth > GATE_DEDUP_MAX_DEPTH) return VNUser{0}; // Break loops; before user2 set so hit this vertex later @@ -1105,7 +1103,7 @@ private: // Given iterated logic, starting at vu which was consumer's GateVarVertex // Returns a varref that has the same logic input; or nullptr if none - virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override { + VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override { lvertexp->iterateInEdges(*this); const GateVarVertex* const consumerVvertexpp @@ -1185,7 +1183,7 @@ private: } } - virtual VNUser visit(GateVarVertex* vvertexp, VNUser) override { + VNUser visit(GateVarVertex* vvertexp, VNUser) override { for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep;) { V3GraphEdge* oldedgep = edgep; edgep = edgep->inNextp(); // for recursive since the edge could be deleted @@ -1259,7 +1257,7 @@ private: } return VNUser{0}; } - virtual VNUser visit(GateLogicVertex*, VNUser) override { // + VNUser visit(GateLogicVertex*, VNUser) override { // return VNUser{0}; } @@ -1297,7 +1295,7 @@ private: bool m_found = false; // Offset found // VISITORS - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { UINFO(9, "CLK DECOMP Concat search var (off = " << m_offset << ") - " << nodep << endl); if (nodep->varScopep() == m_vscp && !nodep->user2() && !m_found) { // A concatenation may use the same var multiple times @@ -1309,18 +1307,18 @@ private: } m_offset += nodep->dtypep()->width(); } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { UINFO(9, "CLK DECOMP Concat search (off = " << m_offset << ") - " << nodep << endl); iterate(nodep->rhsp()); iterate(nodep->lhsp()); } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS GateConcatVisitor() = default; - virtual ~GateConcatVisitor() override = default; + ~GateConcatVisitor() override = default; // PUBLIC METHODS bool concatOffset(AstConcat* concatp, AstVarScope* vscp, int& offsetr) { m_vscp = vscp; @@ -1360,7 +1358,7 @@ private: int m_total_seen_clk_vectors = 0; int m_total_decomposed_clk_vectors = 0; - virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) override { + VNUser visit(GateVarVertex* vvertexp, VNUser vu) override { // Check that we haven't been here before AstVarScope* const vsp = vvertexp->varScp(); if (vsp->user2SetOnce()) return VNUser{0}; @@ -1377,7 +1375,7 @@ private: return VNUser{0}; // Unused } - virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override { + VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override { const GateClkDecompState* const currState = reinterpret_cast(vu.c()); int clk_offset = currState->m_offset; if (const AstAssignW* const assignp = VN_CAST(lvertexp->nodep(), AssignW)) { @@ -1444,7 +1442,7 @@ private: public: explicit GateClkDecompGraphVisitor(V3Graph* graphp) : GateGraphBaseVisitor{graphp} {} - virtual ~GateClkDecompGraphVisitor() override { + ~GateClkDecompGraphVisitor() override { V3Stats::addStat("Optimizations, Clocker seen vectors", m_total_seen_clk_vectors); V3Stats::addStat("Optimizations, Clocker decomposed vectors", m_total_decomposed_clk_vectors); diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index dd3985b6f..40327384b 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -90,7 +90,7 @@ private: } // VISITORS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // Consumption/generation of a variable, if (m_activep && !nodep->user3SetOnce()) { AstVarScope* const vscp = nodep->varScopep(); @@ -105,14 +105,14 @@ private: } } } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { m_activep = nodep; iterate(nodep->sensesp()); m_activep = nullptr; } //----- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -120,7 +120,7 @@ public: : m_topModp{topModp} { iterate(nodep); } - virtual ~GenClkRenameVisitor() override = default; + ~GenClkRenameVisitor() override = default; }; //###################################################################### @@ -139,7 +139,7 @@ private: AstNodeModule* m_topModp = nullptr; // Top module // VISITORS - virtual void visit(AstTopScope* nodep) override { + void visit(AstTopScope* nodep) override { { const VNUser1InUse user1InUse; iterateChildren(nodep); @@ -148,14 +148,14 @@ private: // See rename, it does some AstNode::userClearTree()'s GenClkRenameVisitor{nodep, m_topModp}; } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Only track the top scopes, not lower level functions if (nodep->isTop()) { m_topModp = nodep; iterateChildren(nodep); } } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); if (!nodep->funcp()->entryPoint()) { // Enter the function and trace it @@ -163,7 +163,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (!m_tracingCall && !nodep->entryPoint()) { // Only consider logic within a CFunc when looking // at the call to it, and not when scanning whatever @@ -175,7 +175,7 @@ private: } //---- - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // Consumption/generation of a variable, AstVarScope* const vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); @@ -190,13 +190,13 @@ private: vscp->circular(true); } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // UINFO(8, "ASS " << nodep << endl); m_assignp = nodep; iterateChildren(nodep); m_assignp = nullptr; } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { UINFO(8, "ACTIVE " << nodep << endl); m_activep = nodep; UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked"); @@ -206,13 +206,13 @@ private: } //----- - virtual void visit(AstVar*) override {} // Don't want varrefs under it - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't want varrefs under it + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit GenClkReadVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~GenClkReadVisitor() override = default; + ~GenClkReadVisitor() override = default; }; //###################################################################### diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 0df758ed1..00ab8564f 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -42,13 +42,13 @@ public: GraphAcycVertex(V3Graph* graphp, V3GraphVertex* origVertexp) : V3GraphVertex{graphp} , m_origVertexp{origVertexp} {} - virtual ~GraphAcycVertex() override = default; + ~GraphAcycVertex() override = default; V3GraphVertex* origVertexp() const { return m_origVertexp; } void setDelete() { m_deleted = true; } bool isDelete() const { return m_deleted; } - virtual string name() const override { return m_origVertexp->name(); } - virtual string dotColor() const override { return m_origVertexp->dotColor(); } - virtual FileLine* fileline() const override { return m_origVertexp->fileline(); } + string name() const override { return m_origVertexp->name(); } + string dotColor() const override { return m_origVertexp->dotColor(); } + FileLine* fileline() const override { return m_origVertexp->fileline(); } }; //-------------------------------------------------------------------- @@ -67,11 +67,9 @@ public: GraphAcycEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = false) : V3GraphEdge{graphp, fromp, top, weight, cutable} {} - virtual ~GraphAcycEdge() override = default; + ~GraphAcycEdge() override = default; // yellow=we might still cut it, else oldEdge: yellowGreen=made uncutable, red=uncutable - virtual string dotColor() const override { - return (cutable() ? "yellow" : origEdgep()->dotColor()); - } + string dotColor() const override { return (cutable() ? "yellow" : origEdgep()->dotColor()); } }; //-------------------------------------------------------------------- diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index 757c7ff70..40f847e0e 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -56,18 +56,18 @@ public: V3GraphTestVertex(V3Graph* graphp, const string& name) : V3GraphVertex{graphp} , m_name{name} {} - virtual ~V3GraphTestVertex() override = default; + ~V3GraphTestVertex() override = default; // ACCESSORS - virtual string name() const override { return m_name; } + string name() const override { return m_name; } }; class V3GraphTestVarVertex final : public V3GraphTestVertex { public: V3GraphTestVarVertex(V3Graph* graphp, const string& name) : V3GraphTestVertex{graphp, name} {} - virtual ~V3GraphTestVarVertex() override = default; + ~V3GraphTestVarVertex() override = default; // ACCESSORS - virtual string dotColor() const override { return "blue"; } + string dotColor() const override { return "blue"; } }; //###################################################################### @@ -76,8 +76,8 @@ public: class V3GraphTestStrong final : public V3GraphTest { public: - virtual string name() override { return "strong"; } - virtual void runTest() override { + string name() override { return "strong"; } + void runTest() override { V3Graph* gp = &m_graph; // Verify we break edges at a good point // A simple alg would make 3 breaks, below only requires b->i to break @@ -114,8 +114,8 @@ public: class V3GraphTestAcyc final : public V3GraphTest { public: - virtual string name() override { return "acyc"; } - virtual void runTest() override { + string name() override { return "acyc"; } + void runTest() override { V3Graph* gp = &m_graph; // Verify we break edges at a good point // A simple alg would make 3 breaks, below only requires b->i to break @@ -142,8 +142,8 @@ public: class V3GraphTestVars final : public V3GraphTest { public: - virtual string name() override { return "vars"; } - virtual void runTest() override { + string name() override { return "vars"; } + void runTest() override { V3Graph* gp = &m_graph; V3GraphTestVertex* clk = new V3GraphTestVarVertex(gp, "$clk"); @@ -268,8 +268,8 @@ class V3GraphTestImport final : public V3GraphTest { #endif public: - virtual string name() override { return "import"; } - virtual void runTest() override { + string name() override { return "import"; } + void runTest() override { V3Graph* const gp = &m_graph; dotImport(); dump(); diff --git a/src/V3Hasher.cpp b/src/V3Hasher.cpp index 53a276c89..7a2f7d78d 100644 --- a/src/V3Hasher.cpp +++ b/src/V3Hasher.cpp @@ -80,7 +80,7 @@ private: //------------------------------------------------------------ // AstNode - Warns to help find missing cases - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { #if VL_DEBUG UINFO(0, "%Warning: Hashing node as AstNode: " << nodep << endl); #endif @@ -89,93 +89,93 @@ private: //------------------------------------------------------------ // AstNodeDType - virtual void visit(AstNodeArrayDType* nodep) override { + void visit(AstNodeArrayDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { iterateNull(nodep->virtRefDTypep()); m_hash += nodep->left(); m_hash += nodep->right(); }); } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, false, [=]() { // m_hash += nodep->uniqueNum(); }); } - virtual void visit(AstParamTypeDType* nodep) override { + void visit(AstParamTypeDType* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); m_hash += nodep->varType(); }); } - virtual void visit(AstMemberDType* nodep) override { + void visit(AstMemberDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstDefImplicitDType* nodep) override { + void visit(AstDefImplicitDType* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->uniqueNum(); }); } - virtual void visit(AstAssocArrayDType* nodep) override { + void visit(AstAssocArrayDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { iterateNull(nodep->virtRefDTypep()); iterateNull(nodep->virtRefDType2p()); }); } - virtual void visit(AstDynArrayDType* nodep) override { + void visit(AstDynArrayDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->virtRefDTypep()); }); } - virtual void visit(AstUnsizedArrayDType* nodep) override { + void visit(AstUnsizedArrayDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->virtRefDTypep()); }); } - virtual void visit(AstWildcardArrayDType* nodep) override { + void visit(AstWildcardArrayDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->virtRefDTypep()); }); } - virtual void visit(AstBasicDType* nodep) override { + void visit(AstBasicDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { m_hash += nodep->keyword(); m_hash += nodep->nrange().left(); m_hash += nodep->nrange().right(); }); } - virtual void visit(AstConstDType* nodep) override { + void visit(AstConstDType* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // iterateNull(nodep->virtRefDTypep()); }); } - virtual void visit(AstClassRefDType* nodep) override { + void visit(AstClassRefDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->classp()); }); } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->cellp()); }); } - virtual void visit(AstQueueDType* nodep) override { + void visit(AstQueueDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->virtRefDTypep()); }); } - virtual void visit(AstRefDType* nodep) override { + void visit(AstRefDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { m_hash += nodep->name(); iterateNull(nodep->typedefp()); iterateNull(nodep->refDTypep()); }); } - virtual void visit(AstVoidDType* nodep) override { + void visit(AstVoidDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstEnumDType* nodep) override { + void visit(AstEnumDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, false, [=]() { // m_hash += nodep->uniqueNum(); }); @@ -183,23 +183,23 @@ private: //------------------------------------------------------------ // AstNodeMath - virtual void visit(AstNodeMath* nodep) override { + void visit(AstNodeMath* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->num().toHash(); }); } - virtual void visit(AstNullCheck* nodep) override { + void visit(AstNullCheck* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstCCast* nodep) override { + void visit(AstCCast* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->size(); }); } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { if (nodep->varScopep()) { iterateNull(nodep->varScopep()); @@ -209,28 +209,28 @@ private: } }); } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { iterateNull(nodep->varp()); m_hash += nodep->dotted(); }); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstFScanF* nodep) override { + void visit(AstFScanF* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->text(); }); } - virtual void visit(AstSScanF* nodep) override { + void visit(AstSScanF* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->text(); }); } - virtual void visit(AstAddrOfCFunc* nodep) override { + void visit(AstAddrOfCFunc* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // iterateNull(nodep->funcp()); }); @@ -238,56 +238,56 @@ private: //------------------------------------------------------------ // AstNodeStmt - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstNodeText* nodep) override { + void visit(AstNodeText* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // m_hash += nodep->text(); }); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->funcp()); }); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { iterateNull(nodep->taskp()); iterateNull(nodep->classOrPackagep()); }); } - virtual void visit(AstCMethodHard* nodep) override { + void visit(AstCMethodHard* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstCoverInc* nodep) override { + void visit(AstCoverInc* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->declp()); }); } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // m_hash += nodep->displayType(); }); } - virtual void visit(AstMonitorOff* nodep) override { + void visit(AstMonitorOff* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // m_hash += nodep->off(); }); } - virtual void visit(AstJumpGo* nodep) override { + void visit(AstJumpGo* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->labelp()); }); } - virtual void visit(AstTraceInc* nodep) override { + void visit(AstTraceInc* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // iterateNull(nodep->declp()); }); } - virtual void visit(AstNodeCoverOrAssert* nodep) override { + void visit(AstNodeCoverOrAssert* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); @@ -295,62 +295,62 @@ private: //------------------------------------------------------------ // AstNode direct descendents - virtual void visit(AstNodeRange* nodep) override { + void visit(AstNodeRange* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [=]() { // m_hash += nodep->origName(); }); } - virtual void visit(AstNodePreSel* nodep) override { + void visit(AstNodePreSel* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstClassExtends* nodep) override { + void visit(AstClassExtends* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstSelLoopVars* nodep) override { + void visit(AstSelLoopVars* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstDefParam* nodep) override { + void visit(AstDefParam* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstArg* nodep) override { + void visit(AstArg* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstParseRef* nodep) override { + void visit(AstParseRef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->expect(); m_hash += nodep->name(); }); } - virtual void visit(AstClassOrPackageRef* nodep) override { + void visit(AstClassOrPackageRef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // iterateNull(nodep->classOrPackageNodep()); }); } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->edgeType(); }); } - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->text(); }); } - virtual void visit(AstElabDisplay* nodep) override { + void visit(AstElabDisplay* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->displayType(); }); } - virtual void visit(AstInitItem* nodep) override { + void visit(AstInitItem* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { if (const AstAssocArrayDType* const dtypep = VN_CAST(nodep->dtypep(), AssocArrayDType)) { if (nodep->defaultp()) { m_hash @@ -376,22 +376,22 @@ private: }); } } - virtual void visit(AstPragma* nodep) override { + void visit(AstPragma* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->pragType(); }); } - virtual void visit(AstAttrOf* nodep) override { + void visit(AstAttrOf* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->attrType(); }); } - virtual void visit(AstNodeFile* nodep) override { + void visit(AstNodeFile* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // // We might be in a recursive function, if so on *second* call // here we need to break what would be an infinite loop. @@ -402,90 +402,90 @@ private: m_hash += nodep->isLoose(); }); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); m_hash += nodep->varType(); }); } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [=]() { m_hash += nodep->name(); iterateNull(nodep->aboveScopep()); }); } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { iterateNull(nodep->varp()); iterateNull(nodep->scopep()); }); } - virtual void visit(AstEnumItem* nodep) override { + void visit(AstEnumItem* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstTypedefFwd* nodep) override { + void visit(AstTypedefFwd* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // iterateNull(nodep->sensesp()); }); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); iterateNull(nodep->modp()); }); } - virtual void visit(AstCellInline* nodep) override { + void visit(AstCellInline* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); iterateNull(nodep->scopep()); }); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstModport* nodep) override { + void visit(AstModport* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstModportVarRef* nodep) override { + void visit(AstModportVarRef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); iterateNull(nodep->varp()); }); } - virtual void visit(AstModportFTaskRef* nodep) override { + void visit(AstModportFTaskRef* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); iterateNull(nodep->ftaskp()); }); } - virtual void visit(AstMTaskBody* nodep) override { + void visit(AstMTaskBody* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstNodeProcedure* nodep) override { + void visit(AstNodeProcedure* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {}); } - virtual void visit(AstNodeBlock* nodep) override { + void visit(AstNodeBlock* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { // m_hash += nodep->name(); }); } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { m_hash += nodep->name(); m_hash += nodep->pinNum(); @@ -504,7 +504,7 @@ public: iterate(const_cast(nodep)); } V3Hash finalHash() const { return m_hash; } - virtual ~HasherVisitor() override = default; + ~HasherVisitor() override = default; }; //###################################################################### diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index e7ac8dd9b..7a1b07057 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -250,7 +250,7 @@ class HierBlockUsageCollectVisitor final : public VNVisitor { ModuleSet m_referred; // Modules that have hier_block pragma V3HierBlock::GParams m_gparams; // list of variables that is VVarType::GPARAM - virtual void visit(AstModule* nodep) override { + void visit(AstModule* nodep) override { // Don't visit twice if (nodep->user1SetOnce()) return; UINFO(5, "Checking " << nodep->prettyNameQ() << " from " @@ -277,7 +277,7 @@ class HierBlockUsageCollectVisitor final : public VNVisitor { } m_gparams = prevGParams; } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { // Visit used module here to know that the module is hier_block or not. // This visitor behaves almost depth first search if (AstModule* const modp = VN_CAST(nodep->modp(), Module)) { @@ -287,15 +287,15 @@ class HierBlockUsageCollectVisitor final : public VNVisitor { // Nothing to do for interface because hierarchical block does not exist // beyond interface. } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (m_modp && m_modp->hierBlock() && nodep->isIfaceRef() && !nodep->isIfaceParent()) { nodep->v3error("Modport cannot be used at the hierarchical block boundary"); } if (nodep->isGParam() && nodep->overriddenParam()) m_gparams.push_back(nodep); } - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: HierBlockUsageCollectVisitor(V3HierBlockPlan* planp, AstNetlist* netlist) diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 40f54dcce..277531647 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -112,7 +112,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UASSERT_OBJ(!m_modp, nodep, "Unsupported: Nested modules"); m_modp = nodep; m_allMods.push_back(nodep); @@ -130,19 +130,19 @@ private: iterateChildren(nodep); m_modp = nullptr; } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { // TODO allow inlining of modules that have classes // (Probably wait for new inliner scheme) cantInline("class", true); iterateChildren(nodep); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { m_moduleState(nodep->modp()).m_cellRefs++; m_moduleState(m_modp).m_childCells.push_back(nodep); m_instances[m_modp][nodep->modp()]++; iterateChildren(nodep); } - virtual void visit(AstPragma* nodep) override { + void visit(AstPragma* nodep) override { if (nodep->pragType() == VPragmaType::INLINE_MODULE) { if (!m_modp) { nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE @@ -162,28 +162,28 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { // Remove link. V3LinkDot will reestablish it after inlining. nodep->varp(nullptr); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { // Remove link. V3LinkDot will reestablish it after inlining. // MethodCalls not currently supported by inliner, so keep linked if (!nodep->classOrPackagep() && !VN_IS(nodep, MethodCall)) nodep->taskp(nullptr); iterateChildren(nodep); } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { m_modp->user4Inc(); // statement count iterateChildren(nodep); } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // Don't count assignments, as they'll likely flatten out // Still need to iterate though to nullify VarXRefs const int oldcnt = m_modp->user4(); iterateChildren(nodep); m_modp->user4(oldcnt); } - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Build ModuleState, user2, and user4 for all modules. // Also build m_allMods and m_instances. iterateChildren(nodep); @@ -226,7 +226,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { if (m_modp) m_modp->user4Inc(); // Inc statement count iterateChildren(nodep); } @@ -237,7 +237,7 @@ public: : m_moduleState{moduleState} { iterate(nodep); } - virtual ~InlineMarkVisitor() override { + ~InlineMarkVisitor() override { V3Stats::addStat("Optimizations, Inline unsupported", m_statUnsup); } }; @@ -260,7 +260,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstCellInline* nodep) override { + void visit(AstCellInline* nodep) override { // Inlined cell under the inline cell, need to move to avoid conflicts nodep->unlinkFrBack(); m_modp->addInlinesp(nodep); @@ -270,20 +270,20 @@ private: // Do CellInlines under this, but don't move them iterateChildren(nodep); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { // Cell under the inline cell, need to rename to avoid conflicts nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); iterateChildren(nodep); } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); iterateChildren(nodep); } - virtual void visit(AstModule* nodep) override { + void visit(AstModule* nodep) override { m_renamedInterfaces.clear(); iterateChildren(nodep); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (nodep->user2p()) { // Make an assignment, so we'll trace it properly // user2p is either a const or a var. @@ -360,17 +360,17 @@ private: if (debug() >= 9) nodep->dumpTree(cout, "varchanged:"); if (debug() >= 9 && nodep->valuep()) nodep->valuep()->dumpTree(cout, "varchangei:"); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { // Function under the inline cell, need to rename to avoid conflicts nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); iterateChildren(nodep); } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { // Typedef under the inline cell, need to rename to avoid conflicts nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); iterateChildren(nodep); } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (nodep->varp()->user2p() // It's being converted to an alias. && !nodep->varp()->user3() // Don't constant propagate aliases (we just made) @@ -388,7 +388,7 @@ private: } nodep->name(nodep->varp()->name()); } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { // Track what scope it was originally under so V3LinkDot can resolve it nodep->inlinedDots(VString::dot(m_cellp->name(), ".", nodep->inlinedDots())); for (string tryname = nodep->dotted(); true;) { @@ -406,7 +406,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { // Track what scope it was originally under so V3LinkDot can resolve it nodep->inlinedDots(VString::dot(m_cellp->name(), ".", nodep->inlinedDots())); if (m_renamedInterfaces.count(nodep->dotted())) { @@ -417,9 +417,9 @@ private: } // Not needed, as V3LinkDot doesn't care about typedefs - // virtual void visit(AstRefDType* nodep) override {} + // void visit(AstRefDType* nodep) override {} - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { // If there's a %m in the display text, we add a special node that will contain the name() // Similar code in V3Begin // To keep correct visual order, must add before other Text's @@ -435,12 +435,12 @@ private: if (afterp) nodep->scopeEntrp(afterp); iterateChildren(nodep); } - virtual void visit(AstCoverDecl* nodep) override { + void visit(AstCoverDecl* nodep) override { // Fix path in coverage statements nodep->hier(VString::dot(m_cellp->prettyName(), ".", nodep->hier())); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -449,7 +449,7 @@ public: , m_cellp{cellp} { iterate(cloneModp); } - virtual ~InlineRelinkVisitor() override = default; + ~InlineRelinkVisitor() override = default; }; //###################################################################### @@ -576,13 +576,13 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. Required! iterateAndNextConstNullBackwards(nodep->modulesp()); // Clean up AstIfaceRefDType references iterateChildren(nodep->typeTablep()); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UASSERT_OBJ(!m_modp, nodep, "Unsupported: Nested modules"); m_modp = nodep; // Iterate the stored cells directly to reduce traversal @@ -592,7 +592,7 @@ private: m_moduleState(nodep).m_childCells.clear(); m_modp = nullptr; } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { if (nodep->user5()) { // The cell has been removed so let's make sure we don't leave a reference to it // This dtype may still be in use by the AstAssignVarScope created earlier @@ -602,15 +602,15 @@ private: } //-------------------- - virtual void visit(AstCell* nodep) override { // LCOV_EXCL_START + void visit(AstCell* nodep) override { // LCOV_EXCL_START nodep->v3fatal("Traversal should have been short circuited"); } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { nodep->v3fatal("Traversal should have been short circuited"); } // LCOV_EXCL_STOP - virtual void visit(AstNodeFile*) override {} // Accelerate - virtual void visit(AstNodeDType*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeFile*) override {} // Accelerate + void visit(AstNodeDType*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -618,7 +618,7 @@ public: : m_moduleState{moduleState} { iterate(nodep); } - virtual ~InlineVisitor() override { + ~InlineVisitor() override { V3Stats::addStat("Optimizations, Inlined instances", m_statCells); } }; @@ -639,8 +639,8 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); } - virtual void visit(AstCell* nodep) override { + void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); } + void visit(AstCell* nodep) override { VL_RESTORER(m_scope); if (m_scope.empty()) { m_scope = nodep->name(); @@ -673,7 +673,7 @@ private: iterateChildren(modp); } } - virtual void visit(AstAssignVarScope* nodep) override { + void visit(AstAssignVarScope* nodep) override { // Reference const AstVarRef* const reflp = VN_CAST(nodep->lhsp(), VarRef); // What the reference refers to @@ -698,14 +698,14 @@ private: cellp->addIntfRefp(new AstIntfRef(varlp->fileline(), alias)); } //-------------------- - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNodeStmt*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNodeStmt*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit InlineIntfRefVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~InlineIntfRefVisitor() override = default; + ~InlineIntfRefVisitor() override = default; }; //###################################################################### diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index e66936eec..adca8b9da 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -49,7 +49,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { UINFO(4, " CELL " << nodep << endl); m_cellp = nodep; // VV***** We reset user1p() on each cell!!! @@ -57,7 +57,7 @@ private: iterateChildren(nodep); m_cellp = nullptr; } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { // PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input) // or ASSIGNW(expr,VARXREF(p)) (if sub's output) UINFO(4, " PIN " << nodep << endl); @@ -116,7 +116,7 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstUdpTable* nodep) override { + void visit(AstUdpTable* nodep) override { if (!v3Global.opt.bboxUnsup()) { // If we support primitives, update V3Undriven to remove special case nodep->v3warn(E_UNSUPPORTED, "Unsupported: Verilog 1995 UDP Tables. " @@ -125,17 +125,17 @@ private: } // Save some time - virtual void visit(AstNodeMath*) override {} - virtual void visit(AstNodeAssign*) override {} - virtual void visit(AstAlways*) override {} + void visit(AstNodeMath*) override {} + void visit(AstNodeAssign*) override {} + void visit(AstAlways*) override {} //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit InstVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~InstVisitor() override = default; + ~InstVisitor() override = default; }; //###################################################################### @@ -149,15 +149,15 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (VN_IS(nodep->dtypep(), IfaceRefDType)) { UINFO(8, " dm-1-VAR " << nodep << endl); insert(nodep); } iterateChildren(nodep); } - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // METHODS @@ -181,7 +181,7 @@ public: // CONSTRUCTORS InstDeModVarVisitor() = default; - virtual ~InstDeModVarVisitor() override = default; + ~InstDeModVarVisitor() override = default; void main(AstNodeModule* nodep) { UINFO(8, " dmMODULE " << nodep << endl); m_modVarNameMap.clear(); @@ -203,7 +203,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (VN_IS(nodep->dtypep(), UnpackArrayDType) && VN_IS(VN_AS(nodep->dtypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) { UINFO(8, " dv-vec-VAR " << nodep << endl); @@ -239,7 +239,7 @@ private: iterateChildren(nodep); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { UINFO(4, " CELL " << nodep << endl); // Find submodule vars UASSERT_OBJ(nodep->modp(), nodep, "Unlinked"); @@ -316,7 +316,7 @@ private: } } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { // Any non-direct pins need reconnection with a part-select if (!nodep->exprp()) return; // No-connect if (m_cellRangep) { @@ -478,13 +478,13 @@ private: } //-------------------- - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit InstDeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~InstDeVisitor() override = default; + ~InstDeVisitor() override = default; }; //###################################################################### diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index d0ec37562..41a0e9ef2 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -75,7 +75,7 @@ public: , m_osp{osp} { if (nodep) iterate(nodep); } - virtual ~InstrCountVisitor() override = default; + ~InstrCountVisitor() override = default; // METHODS uint32_t instrCount() const { return m_instrCount; } @@ -117,7 +117,7 @@ private: } // VISITORS - virtual void visit(AstNodeSel* nodep) override { + void visit(AstNodeSel* nodep) override { // This covers both AstArraySel and AstWordSel // // If some vector is a bazillion dwords long, and we're selecting 1 @@ -128,7 +128,7 @@ private: const VisitBase vb{this, nodep}; iterateAndNextNull(nodep->bitp()); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { // Similar to AstNodeSel above, a small select into a large vector // is not expensive. Count the cost of the AstSel itself (scales with // its width) and the cost of the lsbp() and widthp() nodes, but not @@ -137,13 +137,13 @@ private: iterateAndNextNull(nodep->lsbp()); iterateAndNextNull(nodep->widthp()); } - virtual void visit(AstSliceSel* nodep) override { // LCOV_EXCL_LINE + void visit(AstSliceSel* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("AstSliceSel unhandled"); } - virtual void visit(AstMemberSel* nodep) override { // LCOV_EXCL_LINE + void visit(AstMemberSel* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("AstMemberSel unhandled"); } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { // Nop. // // Ignore concat. The problem with counting concat is that when we @@ -163,7 +163,7 @@ private: // the widths of the operands (ignored here). markCost(nodep); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { const VisitBase vb{this, nodep}; iterateAndNextNull(nodep->condp()); const uint32_t savedCount = m_instrCount; @@ -188,7 +188,7 @@ private: if (nodep->ifsp()) nodep->ifsp()->user4(0); // Don't dump it } } - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { // Just like if/else above, the ternary operator only evaluates // one of the two expressions, so only count the max. const VisitBase vb{this, nodep}; @@ -213,7 +213,7 @@ private: if (nodep->expr2p()) nodep->expr2p()->user4(0); // Don't dump it } } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { // You'd think that the OrderLogicVertex's would be disjoint trees // of stuff in the AST, but it isn't so: V3Order makes an // OrderLogicVertex for each ACTIVE, and then also makes an @@ -229,14 +229,14 @@ private: markCost(nodep); UASSERT_OBJ(nodep == m_startNodep, nodep, "Multiple actives, or not start node"); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { const VisitBase vb{this, nodep}; iterateChildren(nodep); m_tracingCall = true; iterate(nodep->funcp()); UASSERT_OBJ(!m_tracingCall, nodep, "visit(AstCFunc) should have cleared m_tracingCall."); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // Don't count a CFunc other than by tracing a call or counting it // from the root UASSERT_OBJ(m_tracingCall || nodep == m_startNodep, nodep, @@ -249,7 +249,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { const VisitBase vb{this, nodep}; iterateChildren(nodep); } @@ -276,12 +276,12 @@ public: UASSERT_OBJ(osp, nodep, "Don't call if not dumping"); if (nodep) iterate(nodep); } - virtual ~InstrCountDumpVisitor() override = default; + ~InstrCountDumpVisitor() override = default; private: // METHODS string indent() const { return string(m_depth, ':') + " "; } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { ++m_depth; if (unsigned costPlus1 = nodep->user4()) { *m_osp << " " << indent() << "cost " << std::setw(6) << std::left << (costPlus1 - 1) diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 482a4d301..d33a47291 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -291,7 +291,7 @@ private: } // VISITORS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // Consumption/generation of a variable, // it's used so can't elim assignment before this use. UASSERT_OBJ(nodep->varScopep(), nodep, "nullptr"); @@ -305,7 +305,7 @@ private: VL_DO_DANGLING(m_lifep->varUsageReplace(vscp, nodep), nodep); } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // Collect any used variables first, as lhs may also be on rhs // Similar code in V3Dead const uint64_t lastEdit = AstNode::editCountGbl(); // When it was last edited @@ -325,13 +325,13 @@ private: iterateAndNextNull(nodep->lhsp()); } } - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { // Don't treat as normal assign; V3Life doesn't understand time sense iterateChildren(nodep); } //---- Track control flow changes - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); // Condition is part of PREVIOUS block iterateAndNextNull(nodep->condp()); @@ -357,7 +357,7 @@ private: VL_DO_DANGLING(delete elseLifep, elseLifep); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { // While's are a problem, as we don't allow loops in the graph. We // may go around the cond/body multiple times. Thus a // lifelication just in the body is ok, but we can't delete an @@ -386,7 +386,7 @@ private: VL_DO_DANGLING(delete condLifep, condLifep); VL_DO_DANGLING(delete bodyLifep, bodyLifep); } - virtual void visit(AstJumpBlock* nodep) override { + void visit(AstJumpBlock* nodep) override { // As with While's we can't predict if a JumpGo will kill us or not // It's worse though as an IF(..., JUMPGO) may change the control flow. // Just don't optimize blocks with labels; they're rare - so far. @@ -404,7 +404,7 @@ private: bodyLifep->lifeToAbove(); VL_DO_DANGLING(delete bodyLifep, bodyLifep); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { // UINFO(4, " CCALL " << nodep << endl); iterateChildren(nodep); // Enter the function and trace it @@ -414,7 +414,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // UINFO(4, " CFUNC " << nodep << endl); if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; @@ -423,17 +423,17 @@ private: } iterateChildren(nodep); } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment iterateChildren(nodep); } - virtual void visit(AstCMath* nodep) override { + void visit(AstCMath* nodep) override { m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment iterateChildren(nodep); } - virtual void visit(AstVar*) override {} // Don't want varrefs under it - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't want varrefs under it + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -446,7 +446,7 @@ public: if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = nullptr); } } - virtual ~LifeVisitor() override { + ~LifeVisitor() override { if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = nullptr); } VL_UNCOPYABLE(LifeVisitor); @@ -462,20 +462,20 @@ private: LifeState* const m_statep; // Current state // VISITORS - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (nodep->entryPoint()) { // Usage model 1: Simulate all C code, doing lifetime analysis LifeVisitor{nodep, m_statep}; } } - virtual void visit(AstNodeProcedure* nodep) override { + void visit(AstNodeProcedure* nodep) override { // Usage model 2: Cleanup basic blocks LifeVisitor{nodep, m_statep}; } - virtual void visit(AstVar*) override {} // Accelerate - virtual void visit(AstNodeStmt*) override {} // Accelerate - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Accelerate + void visit(AstNodeStmt*) override {} // Accelerate + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -483,7 +483,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~LifeTopVisitor() override = default; + ~LifeTopVisitor() override = default; }; //###################################################################### diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index da18dec1b..ce750f4f8 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -54,7 +54,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { const AstVarScope* const vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (AstVarScope* const newvscp = reinterpret_cast(vscp->user4p())) { @@ -64,11 +64,11 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Only track the top scopes, not lower level functions if (nodep->isTop()) iterateChildren(nodep); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); if (!nodep->funcp()->entryPoint()) { // Enter the function and trace it @@ -76,23 +76,23 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstExecGraph* nodep) override { + void visit(AstExecGraph* nodep) override { // Can just iterate across the MTask bodies in any order. Order // isn't important for LifePostElimVisitor's simple substitution. iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; iterateChildren(nodep); } - virtual void visit(AstVar*) override {} // Don't want varrefs under it - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't want varrefs under it + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LifePostElimVisitor(AstTopScope* nodep) { iterate(nodep); } - virtual ~LifePostElimVisitor() override = default; + ~LifePostElimVisitor() override = default; }; //###################################################################### @@ -250,7 +250,7 @@ private: } // VISITORS - virtual void visit(AstTopScope* nodep) override { + void visit(AstTopScope* nodep) override { AstNode::user4ClearTree(); // user4p() used on entire tree // First, build maps of every location (mtask and sequence @@ -274,7 +274,7 @@ private: // Replace any node4p varscopes with the new scope LifePostElimVisitor{nodep}; } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // Consumption/generation of a variable, const AstVarScope* const vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); @@ -283,14 +283,14 @@ private: if (nodep->access().isWriteOrRW()) m_writes[vscp].insert(loc); if (nodep->access().isReadOrRW()) m_reads[vscp].insert(loc); } - virtual void visit(AstAssignPre* nodep) override { + void visit(AstAssignPre* nodep) override { // Do not record varrefs within assign pre. // // The pre-assignment into the dly var should not count as its // first write; we only want to consider reads and writes that // would still happen if the dly var were eliminated. } - virtual void visit(AstAssignPost* nodep) override { + void visit(AstAssignPost* nodep) override { // Don't record ASSIGNPOST in the read/write maps, record them in a // separate map if (const AstVarRef* const rhsp = VN_CAST(nodep->rhsp(), VarRef)) { @@ -302,11 +302,11 @@ private: m_assignposts[dlyVarp] = LifePostLocation(loc, nodep); } } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Only track the top scopes, not lower level functions if (nodep->isTop()) iterateChildren(nodep); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); if (!nodep->funcp()->entryPoint()) { // Enter the function and trace it @@ -314,7 +314,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstExecGraph* nodep) override { + void visit(AstExecGraph* nodep) override { // Treat the ExecGraph like a call to each mtask body UASSERT_OBJ(!m_mtasksGraphp, nodep, "Cannot handle more than one AstExecGraph"); m_mtasksGraphp = nodep->depGraphp(); @@ -327,19 +327,19 @@ private: } m_execMTaskp = nullptr; } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; iterateChildren(nodep); } //----- - virtual void visit(AstVar*) override {} // Don't want varrefs under it - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't want varrefs under it + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LifePostDlyVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LifePostDlyVisitor() override { + ~LifePostDlyVisitor() override { V3Stats::addStat("Optimizations, Lifetime postassign deletions", m_statAssnDel); } }; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 03703c2c8..393013026 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -45,8 +45,8 @@ class LinkCellsGraph final : public V3Graph { public: LinkCellsGraph() = default; - virtual ~LinkCellsGraph() override = default; - virtual void loopsMessageCb(V3GraphVertex* vertexp) override; + ~LinkCellsGraph() override = default; + void loopsMessageCb(V3GraphVertex* vertexp) override; }; class LinkCellsVertex final : public V3GraphVertex { @@ -56,12 +56,12 @@ public: LinkCellsVertex(V3Graph* graphp, AstNodeModule* modp) : V3GraphVertex{graphp} , m_modp{modp} {} - virtual ~LinkCellsVertex() override = default; + ~LinkCellsVertex() override = default; AstNodeModule* modp() const { return m_modp; } - virtual string name() const override { return modp()->name(); } - virtual FileLine* fileline() const override { return modp()->fileline(); } + string name() const override { return modp()->name(); } + FileLine* fileline() const override { return modp()->fileline(); } // Recursive modules get space for maximum recursion - virtual uint32_t rankAdder() const override { + uint32_t rankAdder() const override { return m_modp->recursiveClone() ? (1 + v3Global.opt.moduleRecursionDepth()) : 1; } }; @@ -70,8 +70,8 @@ class LibraryVertex final : public V3GraphVertex { public: explicit LibraryVertex(V3Graph* graphp) : V3GraphVertex{graphp} {} - virtual ~LibraryVertex() override = default; - virtual string name() const override { return "*LIBRARY*"; } + ~LibraryVertex() override = default; + string name() const override { return "*LIBRARY*"; } }; void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) { @@ -161,7 +161,7 @@ private: } // VISITs - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { AstNode::user1ClearTree(); readModNames(); iterateChildren(nodep); @@ -181,8 +181,8 @@ private: << "' was not found in design."); } } - virtual void visit(AstConstPool* nodep) override {} - virtual void visit(AstNodeModule* nodep) override { + void visit(AstConstPool* nodep) override {} + void visit(AstNodeModule* nodep) override { // Module: Pick up modnames, so we can resolve cells later VL_RESTORER(m_modp); { @@ -227,7 +227,7 @@ private: } } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { // Cell: Resolve its filename. If necessary, parse it. UINFO(4, "Link IfaceRef: " << nodep << endl); // Use findIdUpward instead of findIdFlat; it doesn't matter for now @@ -246,14 +246,14 @@ private: // Note cannot do modport resolution here; modports are allowed underneath generates } - virtual void visit(AstPackageImport* nodep) override { + void visit(AstPackageImport* nodep) override { // Package Import: We need to do the package before the use of a package iterateChildren(nodep); UASSERT_OBJ(nodep->packagep(), nodep, "Unlinked package"); // Parser should set packagep new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false); } - virtual void visit(AstBind* nodep) override { + void visit(AstBind* nodep) override { // Bind: Has cells underneath that need to be put into the new // module, and cells which need resolution // TODO this doesn't allow bind to dotted hier names, that would require @@ -275,7 +275,7 @@ private: pushDeletep(nodep->unlinkFrBack()); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { // Cell: Resolve its filename. If necessary, parse it. // Execute only once. Complication is that cloning may result in // user1 being set (for pre-clone) so check if user1() matches the @@ -452,14 +452,14 @@ private: UINFO(4, " Link Cell done: " << nodep << endl); } - virtual void visit(AstRefDType* nodep) override { + void visit(AstRefDType* nodep) override { iterateChildren(nodep); for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) { pinp->param(true); if (pinp->name() == "") pinp->name("__paramNumber" + cvtToStr(pinp->pinNum())); } } - virtual void visit(AstClassOrPackageRef* nodep) override { + void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); // Inside a class, an extends or reference to another class // Note we don't add a V3GraphEdge{vertex(m_modp), vertex(nodep->classOrPackagep()} @@ -471,7 +471,7 @@ private: } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } // METHODS void readModNames() { @@ -528,7 +528,7 @@ public: } iterate(nodep); } - virtual ~LinkCellsVisitor() override = default; + ~LinkCellsVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 6a85a0ff4..4168a0b83 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -81,25 +81,25 @@ class LinkNodeMatcherClass final : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); } + bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); } }; class LinkNodeMatcherFTask final : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); } + bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); } }; class LinkNodeMatcherModport final : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Modport); } + bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Modport); } }; class LinkNodeMatcherVar final : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const override { + bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Var) || VN_IS(nodep, LambdaArgRef); } }; class LinkNodeMatcherVarIO final : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const override { + bool nodeMatch(const AstNode* nodep) const override { const AstVar* const varp = VN_CAST(nodep, Var); if (!varp) return false; return varp->isIO(); @@ -107,7 +107,7 @@ public: }; class LinkNodeMatcherVarParam final : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const override { + bool nodeMatch(const AstNode* nodep) const override { const AstVar* const varp = VN_CAST(nodep, Var); if (!varp) return false; return varp->isParam(); @@ -742,7 +742,7 @@ class LinkDotFindVisitor final : public VNVisitor { } // VISITs - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Process $unit or other packages // Not needed - dotted references not allowed from inside packages // for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); @@ -770,9 +770,9 @@ class LinkDotFindVisitor final : public VNVisitor { m_curSymp = m_modSymp = nullptr; } } - virtual void visit(AstTypeTable*) override {} - virtual void visit(AstConstPool*) override {} - virtual void visit(AstNodeModule* nodep) override { + void visit(AstTypeTable*) override {} + void visit(AstConstPool*) override {} + void visit(AstNodeModule* nodep) override { // Called on top module from Netlist, other modules from the cell creating them, // and packages UINFO(8, " " << nodep << endl); @@ -839,7 +839,7 @@ class LinkDotFindVisitor final : public VNVisitor { UINFO(5, "Module not under any CELL or top - dead module: " << nodep << endl); } } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit"); UINFO(8, " " << nodep << endl); VL_RESTORER(m_scope); @@ -871,12 +871,12 @@ class LinkDotFindVisitor final : public VNVisitor { if (!m_explicitNew && m_statep->forPrimary()) makeImplicitNew(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UASSERT_OBJ(m_statep->forScopeCreation(), nodep, "Scopes should only exist right after V3Scope"); // Ignored. Processed in next step } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { UINFO(5, " CELL under " << m_scope << " is " << nodep << endl); // Process XREFs/etc inside pins if (nodep->recursive() && m_inRecursion) return; @@ -911,7 +911,7 @@ class LinkDotFindVisitor final : public VNVisitor { if (nodep->modp()) iterate(nodep->modp()); } } - virtual void visit(AstCellInline* nodep) override { + void visit(AstCellInline* nodep) override { UINFO(5, " CELLINLINE under " << m_scope << " is " << nodep << endl); VSymEnt* aboveSymp = m_curSymp; // If baz__DOT__foo__DOT__bar, we need to find baz__DOT__foo and add bar to it. @@ -931,11 +931,11 @@ class LinkDotFindVisitor final : public VNVisitor { m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name()); } } - virtual void visit(AstDefParam* nodep) override { + void visit(AstDefParam* nodep) override { nodep->user1p(m_curSymp); iterateChildren(nodep); } - virtual void visit(AstNodeBlock* nodep) override { + void visit(AstNodeBlock* nodep) override { UINFO(5, " " << nodep << endl); if (nodep->name() == "" && nodep->unnamed()) { // Unnamed blocks are only important when they contain var @@ -967,7 +967,7 @@ class LinkDotFindVisitor final : public VNVisitor { } } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { // NodeTask: Remember its name for later resolution UINFO(5, " " << nodep << endl); UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Function/Task not under module?"); @@ -1040,7 +1040,7 @@ class LinkDotFindVisitor final : public VNVisitor { m_ftaskp = nullptr; } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { // Var: Remember its name for later resolution UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?"); iterateChildren(nodep); @@ -1173,18 +1173,18 @@ class LinkDotFindVisitor final : public VNVisitor { } } } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); } - virtual void visit(AstTypedefFwd* nodep) override { + void visit(AstTypedefFwd* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); iterateChildren(nodep); // No need to insert, only the real typedef matters, but need to track for errors nodep->user1p(m_curSymp); } - virtual void visit(AstParamTypeDType* nodep) override { + void visit(AstParamTypeDType* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); @@ -1195,11 +1195,11 @@ class LinkDotFindVisitor final : public VNVisitor { symp->exported(false); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist UASSERT_OBJ(!m_statep->forScopeCreation(), nodep, "No CFuncs expected in tree yet"); } - virtual void visit(AstEnumItem* nodep) override { + void visit(AstEnumItem* nodep) override { // EnumItem: Remember its name for later resolution iterateChildren(nodep); // Find under either a task or the module's vars @@ -1238,7 +1238,7 @@ class LinkDotFindVisitor final : public VNVisitor { } if (ins) m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_classOrPackagep); } - virtual void visit(AstPackageImport* nodep) override { + void visit(AstPackageImport* nodep) override { UINFO(4, " Link: " << nodep << endl); VSymEnt* const srcp = m_statep->getNodeSym(nodep->packagep()); if (nodep->name() == "*") { @@ -1256,7 +1256,7 @@ class LinkDotFindVisitor final : public VNVisitor { UINFO(9, " Link Done: " << nodep << endl); // No longer needed, but can't delete until any multi-instantiated modules are expanded } - virtual void visit(AstPackageExport* nodep) override { + void visit(AstPackageExport* nodep) override { UINFO(9, " Link: " << nodep << endl); VSymEnt* const srcp = m_statep->getNodeSym(nodep->packagep()); if (nodep->name() != "*") { @@ -1270,13 +1270,13 @@ class LinkDotFindVisitor final : public VNVisitor { UINFO(9, " Link Done: " << nodep << endl); // No longer needed, but can't delete until any multi-instantiated modules are expanded } - virtual void visit(AstPackageExportStarStar* nodep) override { + void visit(AstPackageExportStarStar* nodep) override { UINFO(4, " Link: " << nodep << endl); m_curSymp->exportStarStar(m_statep->symsp()); // No longer needed, but can't delete until any multi-instantiated modules are expanded } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { // Symbol table needs nodep->name() as the index variable's name VL_RESTORER(m_curSymp); VSymEnt* const oldCurSymp = m_curSymp; @@ -1327,7 +1327,7 @@ class LinkDotFindVisitor final : public VNVisitor { } } - virtual void visit(AstWithParse* nodep) override { + void visit(AstWithParse* nodep) override { // Change WITHPARSE(FUNCREF, equation) to FUNCREF(WITH(equation)) const auto funcrefp = VN_AS(nodep->funcrefp(), NodeFTaskRef); UASSERT_OBJ(funcrefp, nodep, "'with' only can operate on a function/task"); @@ -1355,7 +1355,7 @@ class LinkDotFindVisitor final : public VNVisitor { nodep->replaceWith(funcrefp->unlinkFrBack()); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstWith* nodep) override { + void visit(AstWith* nodep) override { // Symbol table needs nodep->name() as the index variable's name // Iteration will pickup the AstVar we made under AstWith VL_RESTORER(m_curSymp); @@ -1373,7 +1373,7 @@ class LinkDotFindVisitor final : public VNVisitor { } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1383,7 +1383,7 @@ public: iterate(rootp); } - virtual ~LinkDotFindVisitor() override = default; + ~LinkDotFindVisitor() override = default; }; //====================================================================== @@ -1425,9 +1425,9 @@ private: } // VISITs - virtual void visit(AstTypeTable*) override {} - virtual void visit(AstConstPool*) override {} - virtual void visit(AstNodeModule* nodep) override { + void visit(AstTypeTable*) override {} + void visit(AstConstPool*) override {} + void visit(AstNodeModule* nodep) override { UINFO(5, " " << nodep << endl); if (nodep->dead() || !nodep->user4()) { UINFO(4, "Mark dead module " << nodep << endl); @@ -1444,7 +1444,7 @@ private: m_modp = nullptr; } } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { // Pin: Link to submodule's port // Deal with implicit definitions - do before Resolve visitor as may // be referenced above declaration @@ -1453,7 +1453,7 @@ private: pinImplicitExprRecurse(nodep->exprp()); } } - virtual void visit(AstDefParam* nodep) override { + void visit(AstDefParam* nodep) override { iterateChildren(nodep); nodep->v3warn(DEFPARAM, "defparam is deprecated (IEEE 1800-2017 C.4.1)\n" << nodep->warnMore() @@ -1475,7 +1475,7 @@ private: } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPort* nodep) override { + void visit(AstPort* nodep) override { // Port: Stash the pin number // Need to set pin numbers after varnames are created // But before we do the final resolution based on names @@ -1508,14 +1508,14 @@ private: // Ports not needed any more VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { // Deal with implicit definitions // We used to nodep->allowImplicit() here, but it turns out // normal "assigns" can also make implicit wires. Yuk. pinImplicitExprRecurse(nodep->lhsp()); iterateChildren(nodep); } - virtual void visit(AstAssignAlias* nodep) override { + void visit(AstAssignAlias* nodep) override { // tran gates need implicit creation // As VarRefs don't exist in forPrimary, sanity check UASSERT_OBJ(!m_statep->forPrimary(), nodep, "Assign aliases unexpected pre-dot"); @@ -1527,13 +1527,13 @@ private: } iterateChildren(nodep); } - virtual void visit(AstImplicit* nodep) override { + void visit(AstImplicit* nodep) override { // Unsupported gates need implicit creation pinImplicitExprRecurse(nodep); // We're done with implicit gates VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstClassOrPackageRef* nodep) override { + void visit(AstClassOrPackageRef* nodep) override { if (auto* const fwdp = VN_CAST(nodep->classOrPackageNodep(), TypedefFwd)) { // Relink forward definitions to the "real" definition VSymEnt* const foundp = m_statep->getNodeSym(fwdp)->findIdFallback(fwdp->name()); @@ -1555,7 +1555,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstTypedefFwd* nodep) override { + void visit(AstTypedefFwd* nodep) override { VSymEnt* const foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->name()); if (!foundp && v3Global.opt.pedantic()) { // We only check it was ever really defined in pedantic mode, as it @@ -1570,7 +1570,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1579,7 +1579,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(rootp); } - virtual ~LinkDotParamVisitor() override = default; + ~LinkDotParamVisitor() override = default; }; //====================================================================== @@ -1594,12 +1594,12 @@ class LinkDotScopeVisitor final : public VNVisitor { static int debug() { return LinkDotState::debug(); } // VISITs - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Recurse..., backward as must do packages before using packages iterateChildrenBackwards(nodep); } - virtual void visit(AstConstPool*) override {} - virtual void visit(AstScope* nodep) override { + void visit(AstConstPool*) override {} + void visit(AstScope* nodep) override { UINFO(8, " SCOPE " << nodep << endl); UASSERT_OBJ(m_statep->forScopeCreation(), nodep, "Scopes should only exist right after V3Scope"); @@ -1611,7 +1611,7 @@ class LinkDotScopeVisitor final : public VNVisitor { m_modSymp = nullptr; m_scopep = nullptr; } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { if (!nodep->varp()->isFuncLocal() && !nodep->varp()->isClassMember()) { VSymEnt* const varSymp = m_statep->insertSym(m_modSymp, nodep->varp()->name(), nodep, nullptr); @@ -1649,22 +1649,22 @@ class LinkDotScopeVisitor final : public VNVisitor { } } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { VSymEnt* const symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, nullptr); symp->fallbackp(m_modSymp); // No recursion, we don't want to pick up variables } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { VSymEnt* const symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, nullptr); symp->fallbackp(m_modSymp); // No recursion, we don't want to pick up variables } - virtual void visit(AstWith* nodep) override { + void visit(AstWith* nodep) override { VSymEnt* const symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, nullptr); symp->fallbackp(m_modSymp); // No recursion, we don't want to pick up variables } - virtual void visit(AstAssignAlias* nodep) override { + void visit(AstAssignAlias* nodep) override { // Track aliases created by V3Inline; if we get a VARXREF(aliased_from) // we'll need to replace it with a VARXREF(aliased_to) if (debug() >= 9) nodep->dumpTree(cout, "- alias: "); @@ -1674,7 +1674,7 @@ class LinkDotScopeVisitor final : public VNVisitor { fromVscp->user2p(toVscp); iterateChildren(nodep); } - virtual void visit(AstAssignVarScope* nodep) override { + void visit(AstAssignVarScope* nodep) override { UINFO(5, "ASSIGNVARSCOPE " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, "- avs: "); VSymEnt* rhsSymp; @@ -1734,9 +1734,9 @@ class LinkDotScopeVisitor final : public VNVisitor { } // For speed, don't recurse things that can't have scope // Note we allow AstNodeStmt's as generates may be under them - virtual void visit(AstCell*) override {} - virtual void visit(AstVar*) override {} - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstCell*) override {} + void visit(AstVar*) override {} + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1745,7 +1745,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(rootp); } - virtual ~LinkDotScopeVisitor() override = default; + ~LinkDotScopeVisitor() override = default; }; //====================================================================== @@ -1760,7 +1760,7 @@ class LinkDotIfaceVisitor final : public VNVisitor { static int debug() { return LinkDotState::debug(); } // VISITs - virtual void visit(AstModport* nodep) override { + void visit(AstModport* nodep) override { // Modport: Remember its name for later resolution UINFO(5, " fiv: " << nodep << endl); VL_RESTORER(m_curSymp); @@ -1772,7 +1772,7 @@ class LinkDotIfaceVisitor final : public VNVisitor { iterateChildren(nodep); } } - virtual void visit(AstModportFTaskRef* nodep) override { + void visit(AstModportFTaskRef* nodep) override { UINFO(5, " fif: " << nodep << endl); iterateChildren(nodep); if (nodep->isExport()) nodep->v3warn(E_UNSUPPORTED, "Unsupported: modport export"); @@ -1795,7 +1795,7 @@ class LinkDotIfaceVisitor final : public VNVisitor { VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstModportVarRef* nodep) override { + void visit(AstModportVarRef* nodep) override { UINFO(5, " fiv: " << nodep << endl); iterateChildren(nodep); VSymEnt* const symp = m_curSymp->findIdFallback(nodep->name()); @@ -1820,7 +1820,7 @@ class LinkDotIfaceVisitor final : public VNVisitor { VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1830,7 +1830,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(nodep); } - virtual ~LinkDotIfaceVisitor() override = default; + ~LinkDotIfaceVisitor() override = default; }; void LinkDotState::computeIfaceModSyms() { @@ -2005,13 +2005,13 @@ private: } // VISITs - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Recurse..., backward as must do packages before using packages iterateChildrenBackwards(nodep); } - virtual void visit(AstTypeTable*) override {} - virtual void visit(AstConstPool*) override {} - virtual void visit(AstNodeModule* nodep) override { + void visit(AstTypeTable*) override {} + void visit(AstConstPool*) override {} + void visit(AstNodeModule* nodep) override { if (nodep->dead()) return; checkNoDot(nodep); UINFO(8, " " << nodep << endl); @@ -2025,7 +2025,7 @@ private: m_modp = nullptr; m_ds.m_dotSymp = m_curSymp = m_modSymp = nullptr; } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UINFO(8, " " << nodep << endl); VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); @@ -2036,14 +2036,14 @@ private: m_ds.m_dotSymp = m_curSymp = m_modSymp = nullptr; } } - virtual void visit(AstCellInline* nodep) override { + void visit(AstCellInline* nodep) override { checkNoDot(nodep); if (m_statep->forScopeCreation() && !v3Global.opt.vpi()) { nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { // Cell: Recurse inside or cleanup not founds checkNoDot(nodep); AstNode::user5ClearTree(); @@ -2072,7 +2072,7 @@ private: // Parent module inherits child's publicity // This is done bottom up in the LinkBotupVisitor stage } - virtual void visit(AstClassRefDType* nodep) override { + void visit(AstClassRefDType* nodep) override { // Cell: Recurse inside or cleanup not founds checkNoDot(nodep); AstNode::user5ClearTree(); @@ -2089,7 +2089,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { // Pin: Link to submodule's port checkNoDot(nodep); iterateChildren(nodep); @@ -2130,7 +2130,7 @@ private: } // Early return() above when deleted } - virtual void visit(AstDot* nodep) override { + void visit(AstDot* nodep) override { // Legal under a DOT: AstDot, AstParseRef, AstPackageRef, AstNodeSel // also a DOT can be part of an expression, but only above plus // AstFTaskRef are legal children @@ -2239,7 +2239,7 @@ private: m_ds.m_dotp = lastStates.m_dotp; } } - virtual void visit(AstParseRef* nodep) override { + void visit(AstParseRef* nodep) override { if (nodep->user3SetOnce()) return; UINFO(9, " linkPARSEREF " << m_ds.ascii() << " n=" << nodep << endl); // m_curSymp is symbol table of outer expression @@ -2538,7 +2538,7 @@ private: } if (start) m_ds = lastStates; } - virtual void visit(AstClassOrPackageRef* nodep) override { + void visit(AstClassOrPackageRef* nodep) override { // Class: Recurse inside or cleanup not founds // checkNoDot not appropriate, can be under a dot AstNode::user5ClearTree(); @@ -2559,7 +2559,7 @@ private: } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // VarRef: Resolve its reference // ParseRefs are used the first pass (forPrimary) so we shouldn't get can't find // errors here now that we have a VarRef. @@ -2581,7 +2581,7 @@ private: } } } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { // VarRef: Resolve its reference // We always link even if varp() is set, because the module we choose may change // due to creating new modules, flattening, etc. @@ -2661,18 +2661,18 @@ private: } } } - virtual void visit(AstEnumDType* nodep) override { + void visit(AstEnumDType* nodep) override { iterateChildren(nodep); AstRefDType* const refdtypep = VN_CAST(nodep->subDTypep(), RefDType); if (refdtypep && (nodep == refdtypep->subDTypep())) { refdtypep->v3error("Self-referential enumerated type definition"); } } - virtual void visit(AstEnumItemRef* nodep) override { + void visit(AstEnumItemRef* nodep) override { // EnumItemRef may be under a dot. Should already be resolved. iterateChildren(nodep); } - virtual void visit(AstMethodCall* nodep) override { + void visit(AstMethodCall* nodep) override { // Created here so should already be resolved. VL_RESTORER(m_ds); { @@ -2680,7 +2680,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { checkNoDot(nodep); iterateChildren(nodep); if (m_statep->forPrimary() && nodep->isIO() && !m_ftaskp && !nodep->user4()) { @@ -2688,7 +2688,7 @@ private: "Input/output/inout does not appear in port list: " << nodep->prettyNameQ()); } } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { if (nodep->user3SetOnce()) return; UINFO(8, " " << nodep << endl); UINFO(8, " " << m_ds.ascii() << endl); @@ -2854,7 +2854,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstSelBit* nodep) override { + void visit(AstSelBit* nodep) override { if (nodep->user3SetOnce()) return; iterateAndNextNull(nodep->fromp()); if (m_ds.m_dotPos @@ -2882,7 +2882,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstNodePreSel* nodep) override { + void visit(AstNodePreSel* nodep) override { // Excludes simple AstSelBit, see above if (nodep->user3SetOnce()) return; if (m_ds.m_dotPos @@ -2901,11 +2901,11 @@ private: iterateAndNextNull(nodep->attrp()); } } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { // checkNoDot not appropriate, can be under a dot iterateChildren(nodep); } - virtual void visit(AstNodeBlock* nodep) override { + void visit(AstNodeBlock* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); VSymEnt* const oldCurSymp = m_curSymp; @@ -2919,7 +2919,7 @@ private: m_ds.m_dotSymp = m_curSymp = oldCurSymp; UINFO(5, " cur=se" << cvtToHex(m_curSymp) << endl); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); if (nodep->isExternDef()) { @@ -2941,7 +2941,7 @@ private: m_ds.m_dotSymp = m_curSymp = oldCurSymp; m_ftaskp = nullptr; } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); VSymEnt* const oldCurSymp = m_curSymp; @@ -2951,7 +2951,7 @@ private: } m_ds.m_dotSymp = m_curSymp = oldCurSymp; } - virtual void visit(AstWith* nodep) override { + void visit(AstWith* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); VSymEnt* const oldCurSymp = m_curSymp; @@ -2961,12 +2961,12 @@ private: } m_ds.m_dotSymp = m_curSymp = oldCurSymp; } - virtual void visit(AstLambdaArgRef* nodep) override { + void visit(AstLambdaArgRef* nodep) override { UINFO(5, " " << nodep << endl); // No checknodot(nodep), visit(AstScope) will check for LambdaArgRef iterateChildren(nodep); } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); VL_RESTORER(m_curSymp); @@ -3041,7 +3041,7 @@ private: } } } - virtual void visit(AstRefDType* nodep) override { + void visit(AstRefDType* nodep) override { // Resolve its reference if (nodep->user3SetOnce()) return; if (AstNode* const cpackagep = nodep->classOrPackageOpp()) { @@ -3112,7 +3112,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstDpiExport* nodep) override { + void visit(AstDpiExport* nodep) override { // AstDpiExport: Make sure the function referenced exists, then dump it iterateChildren(nodep); checkNoDot(nodep); @@ -3130,35 +3130,35 @@ private: } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPackageImport* nodep) override { + void visit(AstPackageImport* nodep) override { // No longer needed checkNoDot(nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPackageExport* nodep) override { + void visit(AstPackageExport* nodep) override { // No longer needed checkNoDot(nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPackageExportStarStar* nodep) override { + void visit(AstPackageExportStarStar* nodep) override { // No longer needed checkNoDot(nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstCellRef* nodep) override { + void visit(AstCellRef* nodep) override { UINFO(5, " AstCellRef: " << nodep << " " << m_ds.ascii() << endl); iterateChildren(nodep); } - virtual void visit(AstCellArrayRef* nodep) override { + void visit(AstCellArrayRef* nodep) override { UINFO(5, " AstCellArrayRef: " << nodep << " " << m_ds.ascii() << endl); // Expression already iterated } - virtual void visit(AstUnlinkedRef* nodep) override { + void visit(AstUnlinkedRef* nodep) override { UINFO(5, " AstCellArrayRef: " << nodep << " " << m_ds.ascii() << endl); // No need to iterate, if we have a UnlinkedVarXRef, we're already done } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { checkNoDot(nodep); iterateChildren(nodep); } @@ -3170,7 +3170,7 @@ public: UINFO(4, __FUNCTION__ << ": " << endl); iterate(rootp); } - virtual ~LinkDotResolveVisitor() override = default; + ~LinkDotResolveVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index 66dcbf8e1..a19b1e282 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -89,12 +89,12 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modIncrementsNum); m_modIncrementsNum = 0; iterateChildren(nodep); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { // Special, as statements need to be put in different places // Preconditions insert first just before themselves (the normal // rule for other statement types) @@ -111,7 +111,7 @@ private: // Done the loop m_insStmtp = nullptr; // Next thing should be new statement } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { // Special, as statements need to be put in different places // Body insert just before themselves m_insStmtp = nullptr; // First thing should be new statement @@ -119,7 +119,7 @@ private: // Done the loop m_insStmtp = nullptr; // Next thing should be new statement } - virtual void visit(AstJumpBlock* nodep) override { + void visit(AstJumpBlock* nodep) override { // Special, as statements need to be put in different places // Body insert just before themselves m_insStmtp = nullptr; // First thing should be new statement @@ -127,7 +127,7 @@ private: // Done the loop m_insStmtp = nullptr; // Next thing should be new statement } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { m_insStmtp = nodep; iterateAndNextNull(nodep->condp()); m_insStmtp = nullptr; @@ -135,7 +135,7 @@ private: iterateAndNextNull(nodep->elsesp()); m_insStmtp = nullptr; } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { m_insMode = IM_BEFORE; { VL_RESTORER(m_unsupportedHere); @@ -145,11 +145,11 @@ private: m_insStmtp = nullptr; // Next thing should be new statement iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE + void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc( "For statements should have been converted to while statements in V3Begin.cpp"); } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -165,11 +165,11 @@ private: UINFO(9, "Marking unsupported " << nodep << endl); iterateChildren(nodep); } - virtual void visit(AstLogAnd* nodep) override { unsupported_visit(nodep); } - virtual void visit(AstLogOr* nodep) override { unsupported_visit(nodep); } - virtual void visit(AstLogEq* nodep) override { unsupported_visit(nodep); } - virtual void visit(AstLogIf* nodep) override { unsupported_visit(nodep); } - virtual void visit(AstNodeCond* nodep) override { unsupported_visit(nodep); } + void visit(AstLogAnd* nodep) override { unsupported_visit(nodep); } + void visit(AstLogOr* nodep) override { unsupported_visit(nodep); } + void visit(AstLogEq* nodep) override { unsupported_visit(nodep); } + void visit(AstLogIf* nodep) override { unsupported_visit(nodep); } + void visit(AstNodeCond* nodep) override { unsupported_visit(nodep); } void prepost_visit(AstNodeTriop* nodep) { // Check if we are underneath a statement if (!m_insStmtp) { @@ -257,17 +257,17 @@ private: nodep->replaceWith(new AstVarRef(varrefp->fileline(), varp, VAccess::WRITE)); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } - virtual void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } - virtual void visit(AstPreSub* nodep) override { prepost_visit(nodep); } - virtual void visit(AstPostSub* nodep) override { prepost_visit(nodep); } - virtual void visit(AstGenFor* nodep) override { iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } + void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } + void visit(AstPreSub* nodep) override { prepost_visit(nodep); } + void visit(AstPostSub* nodep) override { prepost_visit(nodep); } + void visit(AstGenFor* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LinkIncVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LinkIncVisitor() override = default; + ~LinkIncVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 9b85ac6f6..ef40653a8 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -122,7 +122,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { if (nodep->dead()) return; VL_RESTORER(m_modp); VL_RESTORER(m_modRepeatNum); @@ -132,12 +132,12 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { m_ftaskp = nodep; iterateChildren(nodep); m_ftaskp = nullptr; } - virtual void visit(AstNodeBlock* nodep) override { + void visit(AstNodeBlock* nodep) override { UINFO(8, " " << nodep << endl); VL_RESTORER(m_inFork); m_blockStack.push_back(nodep); @@ -147,7 +147,7 @@ private: } m_blockStack.pop_back(); } - virtual void visit(AstRepeat* nodep) override { + void visit(AstRepeat* nodep) override { // So later optimizations don't need to deal with them, // REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- } // Note var can be signed or unsigned based on original number. @@ -175,7 +175,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstWait* nodep) override { + void visit(AstWait* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait statements"); // Statements we'll just execute immediately; equivalent to if they followed this if (AstNode* const bodysp = nodep->bodysp()) { @@ -186,7 +186,7 @@ private: } VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { // Don't need to track AstRepeat/AstFor as they have already been converted VL_RESTORER(m_loopp); VL_RESTORER(m_loopInc); @@ -200,14 +200,14 @@ private: iterateAndNextNull(nodep->incsp()); } } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { VL_RESTORER(m_loopp); { m_loopp = nodep; iterateAndNextNull(nodep->bodysp()); } } - virtual void visit(AstReturn* nodep) override { + void visit(AstReturn* nodep) override { iterateChildren(nodep); const AstFunc* const funcp = VN_CAST(m_ftaskp, Func); if (m_inFork) { @@ -235,7 +235,7 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstBreak* nodep) override { + void visit(AstBreak* nodep) override { iterateChildren(nodep); if (!m_loopp) { nodep->v3error("break isn't underneath a loop"); @@ -247,7 +247,7 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstContinue* nodep) override { + void visit(AstContinue* nodep) override { iterateChildren(nodep); if (!m_loopp) { nodep->v3error("continue isn't underneath a loop"); @@ -260,7 +260,7 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstDisable* nodep) override { + void visit(AstDisable* nodep) override { UINFO(8, " DISABLE " << nodep << endl); iterateChildren(nodep); AstNodeBlock* blockp = nullptr; @@ -285,16 +285,16 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); // if (debug() >= 9) { UINFO(0, "\n"); beginp->dumpTree(cout, " labelo: "); } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true); } - virtual void visit(AstConst*) override {} - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstConst*) override {} + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LinkJumpVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LinkJumpVisitor() override = default; + ~LinkJumpVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index a05407d37..0925b89c3 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -46,7 +46,7 @@ private: // VISITs // Result handing - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { // VarRef: LValue its reference if (m_setRefLvalue != VAccess::NOCHANGE) nodep->access(m_setRefLvalue); if (nodep->varp()) { @@ -65,7 +65,7 @@ private: } // Nodes that start propagating down lvalues - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { if (nodep->modVarp() && nodep->modVarp()->isWritable()) { // When the varref's were created, we didn't know the I/O state // Now that we do, and it's from a output, we know it's a lvalue @@ -76,7 +76,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setContinuously); { @@ -92,7 +92,7 @@ private: iterateAndNextNull(nodep->rhsp()); } } - virtual void visit(AstRelease* nodep) override { + void visit(AstRelease* nodep) override { VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setContinuously); { @@ -101,7 +101,7 @@ private: iterateAndNextNull(nodep->lhsp()); } } - virtual void visit(AstCastDynamic* nodep) override { + void visit(AstCastDynamic* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::NOCHANGE; @@ -110,7 +110,7 @@ private: iterateAndNextNull(nodep->top()); } } - virtual void visit(AstFOpen* nodep) override { + void visit(AstFOpen* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -120,7 +120,7 @@ private: iterateAndNextNull(nodep->modep()); } } - virtual void visit(AstFOpenMcd* nodep) override { + void visit(AstFOpenMcd* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -129,14 +129,14 @@ private: iterateAndNextNull(nodep->filenamep()); } } - virtual void visit(AstFClose* nodep) override { + void visit(AstFClose* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } - virtual void visit(AstFError* nodep) override { + void visit(AstFError* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -144,21 +144,21 @@ private: iterateAndNextNull(nodep->strp()); } } - virtual void visit(AstFFlush* nodep) override { + void visit(AstFFlush* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } - virtual void visit(AstFGetC* nodep) override { + void visit(AstFGetC* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } - virtual void visit(AstFGetS* nodep) override { + void visit(AstFGetS* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -166,7 +166,7 @@ private: iterateAndNextNull(nodep->strgp()); } } - virtual void visit(AstFRead* nodep) override { + void visit(AstFRead* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -174,7 +174,7 @@ private: iterateAndNextNull(nodep->filep()); } } - virtual void visit(AstFScanF* nodep) override { + void visit(AstFScanF* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -182,33 +182,33 @@ private: iterateAndNextNull(nodep->exprsp()); } } - virtual void visit(AstFUngetC* nodep) override { + void visit(AstFUngetC* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->filep()); } } - virtual void visit(AstSScanF* nodep) override { + void visit(AstSScanF* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->exprsp()); } } - virtual void visit(AstSysIgnore* nodep) override { + void visit(AstSysIgnore* nodep) override { // Can't know if lvalue or not; presume so as stricter VL_RESTORER(m_setRefLvalue); iterateChildren(nodep); } - virtual void visit(AstRand* nodep) override { + void visit(AstRand* nodep) override { VL_RESTORER(m_setRefLvalue); { if (!nodep->urandom()) m_setRefLvalue = VAccess::WRITE; iterateAndNextNull(nodep->seedp()); } } - virtual void visit(AstReadMem* nodep) override { + void visit(AstReadMem* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -219,14 +219,14 @@ private: iterateAndNextNull(nodep->msbp()); } } - virtual void visit(AstTestPlusArgs* nodep) override { + void visit(AstTestPlusArgs* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::NOCHANGE; iterateAndNextNull(nodep->searchp()); } } - virtual void visit(AstValuePlusArgs* nodep) override { + void visit(AstValuePlusArgs* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::NOCHANGE; @@ -235,7 +235,7 @@ private: iterateAndNextNull(nodep->outp()); } } - virtual void visit(AstSFormat* nodep) override { + void visit(AstSFormat* nodep) override { VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = VAccess::WRITE; @@ -254,13 +254,13 @@ private: iterateAndNextNull(nodep->thsp()); } } - virtual void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } - virtual void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } - virtual void visit(AstPreSub* nodep) override { prepost_visit(nodep); } - virtual void visit(AstPostSub* nodep) override { prepost_visit(nodep); } + void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } + void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } + void visit(AstPreSub* nodep) override { prepost_visit(nodep); } + void visit(AstPostSub* nodep) override { prepost_visit(nodep); } // Nodes that change LValue state - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { VL_RESTORER(m_setRefLvalue); { iterateAndNextNull(nodep->lhsp()); @@ -270,7 +270,7 @@ private: iterateAndNextNull(nodep->thsp()); } } - virtual void visit(AstNodeSel* nodep) override { + void visit(AstNodeSel* nodep) override { VL_RESTORER(m_setRefLvalue); { // Only set lvalues on the from iterateAndNextNull(nodep->lhsp()); @@ -278,14 +278,14 @@ private: iterateAndNextNull(nodep->rhsp()); } } - virtual void visit(AstCellArrayRef* nodep) override { + void visit(AstCellArrayRef* nodep) override { VL_RESTORER(m_setRefLvalue); { // selp is not an lvalue m_setRefLvalue = VAccess::NOCHANGE; iterateAndNextNull(nodep->selp()); } } - virtual void visit(AstNodePreSel* nodep) override { + void visit(AstNodePreSel* nodep) override { VL_RESTORER(m_setRefLvalue); { // Only set lvalues on the from iterateAndNextNull(nodep->fromp()); @@ -294,12 +294,12 @@ private: iterateAndNextNull(nodep->thsp()); } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { m_ftaskp = nodep; iterateChildren(nodep); m_ftaskp = nullptr; } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { AstNode* pinp = nodep->pinsp(); const AstNodeFTask* const taskp = nodep->taskp(); // We'll deal with mismatching pins later @@ -321,7 +321,7 @@ private: } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -329,7 +329,7 @@ public: : m_setRefLvalue{start} { iterate(nodep); } - virtual ~LinkLValueVisitor() override = default; + ~LinkLValueVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index af7185f60..2a4ce4bc0 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -122,7 +122,7 @@ private: } // VISITs - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { if (!nodep->user1SetOnce()) { // Process only once. V3Config::applyFTask(m_modp, nodep); cleanFileline(nodep); @@ -139,7 +139,7 @@ private: } } } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); UINFO(5, " " << nodep << endl); @@ -150,20 +150,20 @@ private: } } } - virtual void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); } - virtual void visit(AstEnumDType* nodep) override { + void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); } + void visit(AstEnumDType* nodep) override { if (nodep->name() == "") { nodep->name(nameFromTypedef(nodep)); // Might still remain "" } visitIterateNodeDType(nodep); } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { if (nodep->name() == "") { nodep->name(nameFromTypedef(nodep)); // Might still remain "" } visitIterateNodeDType(nodep); } - virtual void visit(AstEnumItem* nodep) override { + void visit(AstEnumItem* nodep) override { // Expand ranges cleanFileline(nodep); iterateChildren(nodep); @@ -198,7 +198,7 @@ private: } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { cleanFileline(nodep); if (nodep->lifetime().isNone()) { if (m_ftaskp) { @@ -296,7 +296,7 @@ private: } } - virtual void visit(AstAttrOf* nodep) override { + void visit(AstAttrOf* nodep) override { cleanFileline(nodep); iterateChildren(nodep); if (nodep->attrType() == VAttrType::DT_PUBLIC) { @@ -365,7 +365,7 @@ private: } } - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlwaysPublic* nodep) override { // AlwaysPublic was attached under a var, but it's a statement that should be // at the same level as the var cleanFileline(nodep); @@ -381,7 +381,7 @@ private: } } - virtual void visit(AstDefImplicitDType* nodep) override { + void visit(AstDefImplicitDType* nodep) override { cleanFileline(nodep); UINFO(8, " DEFIMPLICIT " << nodep << endl); // Must remember what names we've already created, and combine duplicates @@ -422,7 +422,7 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { // FOREACH(array, loopvars, body) UINFO(9, "FOREACH " << nodep << endl); // Separate iteration vars from base from variable @@ -457,7 +457,7 @@ private: iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { V3Config::applyModule(nodep); VL_RESTORER(m_modp); @@ -490,16 +490,16 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeProcedure* nodep) override { visitIterateNoValueMod(nodep); } - virtual void visit(AstAlways* nodep) override { + void visit(AstNodeProcedure* nodep) override { visitIterateNoValueMod(nodep); } + void visit(AstAlways* nodep) override { VL_RESTORER(m_inAlways); m_inAlways = true; visitIterateNoValueMod(nodep); } - virtual void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); } - virtual void visit(AstRestrict* nodep) override { visitIterateNoValueMod(nodep); } + void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); } + void visit(AstRestrict* nodep) override { visitIterateNoValueMod(nodep); } - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { V3Config::applyCoverageBlock(m_modp, nodep); cleanFileline(nodep); const AstNode* const backp = nodep->backp(); @@ -525,7 +525,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstGenCase* nodep) override { + void visit(AstGenCase* nodep) override { ++m_genblkNum; cleanFileline(nodep); { @@ -536,7 +536,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstGenIf* nodep) override { + void visit(AstGenIf* nodep) override { cleanFileline(nodep); const bool nestedIf = (VN_IS(nodep->backp(), Begin) && nestedIfBegin(VN_CAST(nodep->backp(), Begin))); @@ -551,39 +551,39 @@ private: iterateChildren(nodep); } } - virtual void visit(AstCase* nodep) override { + void visit(AstCase* nodep) override { V3Config::applyCase(nodep); cleanFileline(nodep); iterateChildren(nodep); } - virtual void visit(AstPrintTimeScale* nodep) override { + void visit(AstPrintTimeScale* nodep) override { // Inlining may change hierarchy, so just save timescale where needed cleanFileline(nodep); iterateChildren(nodep); nodep->name(m_modp->name()); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTime* nodep) override { + void visit(AstTime* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTimeD* nodep) override { + void visit(AstTimeD* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTimeImport* nodep) override { + void visit(AstTimeImport* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstEventControl* nodep) override { + void visit(AstEventControl* nodep) override { cleanFileline(nodep); iterateChildren(nodep); AstAlways* const alwaysp = VN_CAST(nodep->backp(), Always); @@ -605,7 +605,7 @@ private: } } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // Default: Just iterate cleanFileline(nodep); iterateChildren(nodep); @@ -614,7 +614,7 @@ private: public: // CONSTRUCTORS explicit LinkParseVisitor(AstNetlist* rootp) { iterate(rootp); } - virtual ~LinkParseVisitor() override = default; + ~LinkParseVisitor() override = default; }; //###################################################################### diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index f1b859b51..c7dc0ef6f 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -62,7 +62,7 @@ private: // TODO: Most of these visitors are here for historical reasons. // TODO: ExpectDecriptor can move to data type resolution, and the rest // TODO: could move to V3LinkParse to get them out of the way of elaboration - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Module: Create sim table for entire module and iterate UINFO(8, "MODULE " << nodep << endl); if (nodep->dead()) return; @@ -74,14 +74,14 @@ private: iterateChildren(nodep); } } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { VL_RESTORER(m_classp); { m_classp = nodep; iterateChildren(nodep); } } - virtual void visit(AstInitialAutomatic* nodep) override { + void visit(AstInitialAutomatic* nodep) override { iterateChildren(nodep); // Initial assignments under function/tasks can just be simple // assignments without the initial @@ -89,13 +89,13 @@ private: VL_DO_DANGLING(nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()), nodep); } } - virtual void visit(AstNodeCoverOrAssert* nodep) override { + void visit(AstNodeCoverOrAssert* nodep) override { if (m_assertp) nodep->v3error("Assert not allowed under another assert"); m_assertp = nodep; iterateChildren(nodep); m_assertp = nullptr; } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { iterateChildren(nodep); if (m_classp && !nodep->isParam()) nodep->varType(VVarType::MEMBER); if (m_ftaskp) nodep->funcLocal(true); @@ -105,13 +105,13 @@ private: } } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { // VarRef: Resolve its reference if (nodep->varp()) nodep->varp()->usedParam(true); iterateChildren(nodep); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { // NodeTask: Remember its name for later resolution if (m_underGenerate) nodep->underGenerate(true); // Remember the existing symbol table scope @@ -139,14 +139,14 @@ private: m_ftaskp = nullptr; if (nodep->dpiExport()) nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); if (nodep->taskp() && (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) { nodep->scopeNamep(new AstScopeName{nodep->fileline(), false}); } } - virtual void visit(AstSenItem* nodep) override { + void visit(AstSenItem* nodep) override { // Remove bit selects, and bark if it's not a simple variable iterateChildren(nodep); if (nodep->isClocked()) { @@ -214,7 +214,7 @@ private: } } - virtual void visit(AstNodePreSel* nodep) override { + void visit(AstNodePreSel* nodep) override { if (!nodep->attrp()) { iterateChildren(nodep); // Constification may change the fromp() to a constant, which will lose the @@ -249,7 +249,7 @@ private: } } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { // Move default caseItems to the bottom of the list // That saves us from having to search each case list twice, for non-defaults and defaults iterateChildren(nodep); @@ -261,7 +261,7 @@ private: } } - virtual void visit(AstPragma* nodep) override { + void visit(AstPragma* nodep) override { if (nodep->pragType() == VPragmaType::HIER_BLOCK) { UASSERT_OBJ(m_modp, nodep, "HIER_BLOCK not under a module"); // If this is hierarchical mode which is to lib-create, @@ -411,39 +411,39 @@ private: if (filep && filep->varp()) filep->varp()->attrFileDescr(true); } - virtual void visit(AstFOpen* nodep) override { + void visit(AstFOpen* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFOpenMcd* nodep) override { + void visit(AstFOpenMcd* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFClose* nodep) override { + void visit(AstFClose* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFError* nodep) override { + void visit(AstFError* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFEof* nodep) override { + void visit(AstFEof* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFRead* nodep) override { + void visit(AstFRead* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFScanF* nodep) override { + void visit(AstFScanF* nodep) override { iterateChildren(nodep); expectFormat(nodep, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstSScanF* nodep) override { + void visit(AstSScanF* nodep) override { iterateChildren(nodep); expectFormat(nodep, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { iterateChildren(nodep); // Cleanup old-school displays without format arguments if (!nodep->hasFormat()) { @@ -466,7 +466,7 @@ private: } } - virtual void visit(AstUdpTable* nodep) override { + void visit(AstUdpTable* nodep) override { UINFO(5, "UDPTABLE " << nodep << endl); if (!v3Global.opt.bboxUnsup()) { // We don't warn until V3Inst, so that UDPs that are in libraries and @@ -497,49 +497,49 @@ private: } } - virtual void visit(AstScCtor* nodep) override { + void visit(AstScCtor* nodep) override { // Constructor info means the module must remain public m_modp->modPublic(true); iterateChildren(nodep); } - virtual void visit(AstScDtor* nodep) override { + void visit(AstScDtor* nodep) override { // Destructor info means the module must remain public m_modp->modPublic(true); iterateChildren(nodep); } - virtual void visit(AstScInt* nodep) override { + void visit(AstScInt* nodep) override { // Special class info means the module must remain public m_modp->modPublic(true); iterateChildren(nodep); } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { // LinkDot checked modports, now remove references to them // Keeping them later caused problems with InstDeArray, // as it needed to make new modport arrays and such nodep->modportp(nullptr); iterateChildren(nodep); } - // virtual void visit(AstModport* nodep) override { ... } + // void visit(AstModport* nodep) override { ... } // We keep Modport's themselves around for XML dump purposes - virtual void visit(AstGenFor* nodep) override { + void visit(AstGenFor* nodep) override { VL_RESTORER(m_underGenerate); m_underGenerate = true; iterateChildren(nodep); } - virtual void visit(AstGenIf* nodep) override { + void visit(AstGenIf* nodep) override { VL_RESTORER(m_underGenerate); m_underGenerate = true; iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LinkResolveVisitor(AstNetlist* rootp) { iterate(rootp); } - virtual ~LinkResolveVisitor() override = default; + ~LinkResolveVisitor() override = default; }; //###################################################################### @@ -556,29 +556,29 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITs - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. iterateChildrenBackwards(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; iterateChildren(nodep); } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { // Parent module inherits child's publicity if (nodep->modp()->modPublic()) m_modp->modPublic(true); //** No iteration for speed } - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LinkBotupVisitor(AstNetlist* rootp) { iterate(rootp); } - virtual ~LinkBotupVisitor() override = default; + ~LinkBotupVisitor() override = default; }; //###################################################################### diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 27d652110..9a9bf51db 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -123,12 +123,12 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { iterateChildrenConst(nodep); moveVarScopes(); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { UINFO(4, " CFUNC " << nodep << endl); VL_RESTORER(m_cfuncp); VL_RESTORER(m_nodeDepth); @@ -140,12 +140,12 @@ private: } } - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { m_cfuncp->user1(true); // Mark caller as not a leaf function iterateChildrenConst(nodep); } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // Analyze RHS first so "a = a + 1" is detected as a read before write iterate(nodep->rhsp()); // For now we only consider an assignment that is directly under the function, (in @@ -163,7 +163,7 @@ private: iterate(nodep->lhsp()); } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { if (!nodep->varp()->isPrimaryIO() // Not an IO the user wants to interact with && !nodep->varp()->isSigPublic() // Not something the user wants to interact with && !nodep->varp()->isFuncLocal() // Not already a function local (e.g.: argument) @@ -177,7 +177,7 @@ private: // No iterate; Don't want varrefs under it (e.g.: in child dtype?) } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { UASSERT_OBJ(m_cfuncp, nodep, "AstVarRef not under function"); AstVarScope* const varScopep = nodep->varScopep(); @@ -201,7 +201,7 @@ private: // No iterate; Don't want varrefs under it (e.g.: in child dtype?) } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { ++m_nodeDepth; iterateChildrenConst(nodep); --m_nodeDepth; @@ -210,7 +210,7 @@ private: public: // CONSTRUCTORS explicit LocalizeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LocalizeVisitor() override { + ~LocalizeVisitor() override { V3Stats::addStat("Optimizations, Vars localized", m_statLocVars); } }; diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index bb3389861..3dd8fe02e 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -823,7 +823,7 @@ private: } // VISITORS - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { if (AstNode* const condp = (*m_stmtPropertiesp)(nodep).m_condp) { // Check if mergeable if (!checkOrMakeMergeable(nodep)) return; @@ -836,7 +836,7 @@ private: } } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { // Check if mergeable if (!checkOrMakeMergeable(nodep)) { // If not mergeable, try to merge the branches @@ -850,25 +850,25 @@ private: addToList(nodep, nodep->condp()); } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (m_mgFirstp && addIfHelpfulElseEndMerge(nodep)) return; iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // Merge function body if (nodep->stmtsp()) process(nodep->stmtsp()); } // For speed, only iterate what is necessary. - virtual void visit(AstNetlist* nodep) override { iterateAndNextNull(nodep->modulesp()); } - virtual void visit(AstNodeModule* nodep) override { iterateAndNextNull(nodep->stmtsp()); } - virtual void visit(AstNode* nodep) override {} + void visit(AstNetlist* nodep) override { iterateAndNextNull(nodep->modulesp()); } + void visit(AstNodeModule* nodep) override { iterateAndNextNull(nodep->stmtsp()); } + void visit(AstNode* nodep) override {} public: // CONSTRUCTORS explicit MergeCondVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~MergeCondVisitor() override { + ~MergeCondVisitor() override { V3Stats::addStat("Optimizations, MergeCond merges", m_statMerges); V3Stats::addStat("Optimizations, MergeCond merged items", m_statMergedItems); V3Stats::addStat("Optimizations, MergeCond longest merge", m_statLongestList); diff --git a/src/V3Name.cpp b/src/V3Name.cpp index 9c3b422c8..ca8fde8f1 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -68,7 +68,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; @@ -76,44 +76,44 @@ private: } } // Add __PVT__ to names of local signals - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { // Don't iterate... Don't need temps for RANGES under the Var. rename(nodep, ((!m_modp || !m_modp->isTop()) && !nodep->isSigPublic() && !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers && !nodep->isTemp())); // Don't bother to rename internal signals } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (!nodep->user1()) { iterateChildren(nodep); rename(nodep, false); } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (nodep->varp()) { iterate(nodep->varp()); nodep->name(nodep->varp()->name()); } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { if (!nodep->user1()) { rename(nodep, (!nodep->modp()->modPublic() && !VN_IS(nodep->modp(), ClassPackage))); iterateChildren(nodep); } } - virtual void visit(AstMemberDType* nodep) override { + void visit(AstMemberDType* nodep) override { if (!nodep->user1()) { rename(nodep, false); iterateChildren(nodep); } } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { if (!nodep->user1()) { rename(nodep, false); iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { if (!nodep->user1SetOnce()) { if (nodep->aboveScopep()) iterate(nodep->aboveScopep()); if (nodep->aboveCellp()) iterate(nodep->aboveCellp()); @@ -130,12 +130,12 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit NameVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~NameVisitor() override = default; + ~NameVisitor() override = default; }; //###################################################################### diff --git a/src/V3OptionParser.cpp b/src/V3OptionParser.cpp index 8035916e7..1a1f7d84a 100644 --- a/src/V3OptionParser.cpp +++ b/src/V3OptionParser.cpp @@ -39,12 +39,12 @@ struct V3OptionParser::Impl { class ActionBase VL_NOT_FINAL : public ActionIfs { bool m_undocumented = false; // This option is not documented public: - virtual bool isValueNeeded() const override final { return MODE == en::VALUE; } - virtual bool isFOnOffAllowed() const override final { return MODE == en::FONOFF; } - virtual bool isOnOffAllowed() const override final { return MODE == en::ONOFF; } - virtual bool isPartialMatchAllowed() const override final { return ALLOW_PARTIAL_MATCH; } - virtual bool isUndocumented() const override { return m_undocumented; } - virtual void undocumented() override { m_undocumented = true; } + bool isValueNeeded() const override final { return MODE == en::VALUE; } + bool isFOnOffAllowed() const override final { return MODE == en::FONOFF; } + bool isOnOffAllowed() const override final { return MODE == en::ONOFF; } + bool isPartialMatchAllowed() const override final { return ALLOW_PARTIAL_MATCH; } + bool isUndocumented() const override { return m_undocumented; } + void undocumented() override { m_undocumented = true; } }; // Actual action classes @@ -78,7 +78,7 @@ struct V3OptionParser::Impl { public: \ explicit className(type* valp) \ : m_valp(valp) {} \ - virtual void exec(const char* optp, const char* argp) override { body; } \ + void exec(const char* optp, const char* argp) override { body; } \ } V3OPTION_PARSER_DEF_ACT_CLASS(ActionSet, bool, *m_valp = true, en::NONE); @@ -104,7 +104,7 @@ V3OPTION_PARSER_DEF_ACT_CLASS(ActionOnOff, VOptionBool, m_valp->setTrueOrFalse(! using CbType = std::function; \ explicit className(CbType cb) \ : m_cb(std::move(cb)) {} \ - virtual void exec(const char* optp, const char* argp) override { body; } \ + void exec(const char* optp, const char* argp) override { body; } \ } V3OPTION_PARSER_DEF_ACT_CB_CLASS(ActionCbCall, void(void), m_cb(), en::NONE); diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 74e4aaf0a..3c0aee447 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -157,7 +157,7 @@ static bool isClockerAssignment(AstNodeAssign* nodep) { private: // METHODS VL_DEBUG_FUNC; // Declare debug() - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { if (const AstVarRef* const varrefp = VN_CAST(nodep->lhsp(), VarRef)) { if (varrefp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { m_clkAss = true; @@ -166,8 +166,8 @@ static bool isClockerAssignment(AstNodeAssign* nodep) { } iterateChildren(nodep->rhsp()); } - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } } visitor; visitor.iterate(nodep); return visitor.m_clkAss; @@ -212,7 +212,7 @@ class OrderClkMarkVisitor final : public VNVisitor { // METHODS VL_DEBUG_FUNC; // Declare debug() - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { m_hasClk = false; m_inAss = true; m_childClkWidth = 0; @@ -236,7 +236,7 @@ class OrderClkMarkVisitor final : public VNVisitor { } } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (m_inAss && nodep->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { if (m_inClocked) { nodep->v3warn(CLKDATA, @@ -249,7 +249,7 @@ class OrderClkMarkVisitor final : public VNVisitor { } } } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { if (m_inAss) { iterateAndNextNull(nodep->lhsp()); const int lw = m_childClkWidth; @@ -258,20 +258,20 @@ class OrderClkMarkVisitor final : public VNVisitor { m_childClkWidth = lw + rw; // Pass up } } - virtual void visit(AstNodeSel* nodep) override { + void visit(AstNodeSel* nodep) override { if (m_inAss) { iterateChildren(nodep); // Pass up result width if (m_childClkWidth > nodep->width()) m_childClkWidth = nodep->width(); } } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { if (m_inAss) { iterateChildren(nodep); if (m_childClkWidth > nodep->width()) m_childClkWidth = nodep->width(); } } - virtual void visit(AstReplicate* nodep) override { + void visit(AstReplicate* nodep) override { if (m_inAss) { iterateChildren(nodep); if (VN_IS(nodep->rhsp(), Const)) { @@ -281,12 +281,12 @@ class OrderClkMarkVisitor final : public VNVisitor { } } } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { m_inClocked = nodep->hasClocked(); iterateChildren(nodep); m_inClocked = false; } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } // CONSTRUCTORS explicit OrderClkMarkVisitor(AstNode* nodep) { @@ -295,7 +295,7 @@ class OrderClkMarkVisitor final : public VNVisitor { iterate(nodep); } while (m_newClkMarked); } - virtual ~OrderClkMarkVisitor() override = default; + ~OrderClkMarkVisitor() override = default; public: static void process(AstNetlist* nodep) { OrderClkMarkVisitor{nodep}; } @@ -416,19 +416,19 @@ class OrderBuildVisitor final : public VNVisitor { } // VISITORS - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { // This should only find the global AstSenTrees under the AstTopScope, which we ignore // here. We visit AstSenTrees separately when encountering the AstActive that references // them. UASSERT_OBJ(!m_scopep, nodep, "AstSenTrees should have been made global in V3ActiveTop"); } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UASSERT_OBJ(!m_scopep, nodep, "Should not nest"); m_scopep = nodep; iterateChildren(nodep); m_scopep = nullptr; } - virtual void visit(AstActive* nodep) override { + void visit(AstActive* nodep) override { UASSERT_OBJ(!nodep->sensesStorep(), nodep, "AstSenTrees should have been made global in V3ActiveTop"); UASSERT_OBJ(m_scopep, nodep, "AstActive not under AstScope"); @@ -460,7 +460,7 @@ class OrderBuildVisitor final : public VNVisitor { m_activeSenVxp = nullptr; m_domainp = nullptr; } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { // As we explicitly not visit (see ignored nodes below) any subtree that is not relevant // for ordering, we should be able to assert this: UASSERT_OBJ(m_scopep, nodep, "AstVarRef not under scope"); @@ -635,7 +635,7 @@ class OrderBuildVisitor final : public VNVisitor { } } } - virtual void visit(AstDpiExportUpdated* nodep) override { + void visit(AstDpiExportUpdated* nodep) override { // This is under a logic block (AstAlways) sensitive to a change in the DPI export trigger. // We just need to add an edge to the enclosing logic vertex (the vertex for the // AstAlways). @@ -645,7 +645,7 @@ class OrderBuildVisitor final : public VNVisitor { nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { // Calls to 'context' imported DPI function may call DPI exported functions if (m_dpiExportTriggerVxp && nodep->funcp()->dpiImportWrapper() && nodep->funcp()->dpiContext()) { @@ -656,45 +656,45 @@ class OrderBuildVisitor final : public VNVisitor { } //--- Logic akin to SystemVerilog Processes (AstNodeProcedure) - virtual void visit(AstInitial* nodep) override { // + void visit(AstInitial* nodep) override { // iterateLogic(nodep); } - virtual void visit(AstInitialAutomatic* nodep) override { // + void visit(AstInitialAutomatic* nodep) override { // iterateLogic(nodep); } - virtual void visit(AstInitialStatic* nodep) override { // + void visit(AstInitialStatic* nodep) override { // iterateLogic(nodep); } - virtual void visit(AstAlways* nodep) override { // + void visit(AstAlways* nodep) override { // iterateLogic(nodep); } - virtual void visit(AstAlwaysPost* nodep) override { + void visit(AstAlwaysPost* nodep) override { UASSERT_OBJ(!m_inPost, nodep, "Should not nest"); m_inPost = true; iterateLogic(nodep); m_inPost = false; } - virtual void visit(AstAlwaysPostponed* nodep) override { + void visit(AstAlwaysPostponed* nodep) override { UASSERT_OBJ(!m_inPostponed, nodep, "Should not nest"); m_inPostponed = true; iterateLogic(nodep); m_inPostponed = false; } - virtual void visit(AstFinal* nodep) override { // LCOV_EXCL_START + void visit(AstFinal* nodep) override { // LCOV_EXCL_START nodep->v3fatalSrc("AstFinal should have been removed already"); } // LCOV_EXCL_STOP //--- Logic akin go SystemVerilog continuous assignments - virtual void visit(AstAssignAlias* nodep) override { // + void visit(AstAssignAlias* nodep) override { // iterateLogic(nodep); } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { UASSERT_OBJ(!m_inClkAss, nodep, "Should not nest"); m_inClkAss = isClockerAssignment(nodep); iterateLogic(nodep); m_inClkAss = false; } - virtual void visit(AstAssignPre* nodep) override { + void visit(AstAssignPre* nodep) override { UASSERT_OBJ(!m_inClkAss && !m_inPre, nodep, "Should not nest"); m_inClkAss = isClockerAssignment(nodep); m_inPre = true; @@ -702,7 +702,7 @@ class OrderBuildVisitor final : public VNVisitor { m_inPre = false; m_inClkAss = false; } - virtual void visit(AstAssignPost* nodep) override { + void visit(AstAssignPost* nodep) override { UASSERT_OBJ(!m_inClkAss && !m_inPost, nodep, "Should not nest"); m_inClkAss = isClockerAssignment(nodep); m_inPost = true; @@ -712,21 +712,21 @@ class OrderBuildVisitor final : public VNVisitor { } //--- Verilator concoctions - virtual void visit(AstAlwaysPublic* nodep) override { // + void visit(AstAlwaysPublic* nodep) override { // iterateLogic(nodep); } - virtual void visit(AstCoverToggle* nodep) override { // + void visit(AstCoverToggle* nodep) override { // iterateLogic(nodep); } //--- Ignored nodes - virtual void visit(AstVar*) override {} - virtual void visit(AstVarScope* nodep) override {} - virtual void visit(AstCell*) override {} // Only interested in the respective AstScope - virtual void visit(AstTypeTable*) override {} - virtual void visit(AstConstPool*) override {} - virtual void visit(AstClass*) override {} - virtual void visit(AstCFunc*) override { + void visit(AstVar*) override {} + void visit(AstVarScope* nodep) override {} + void visit(AstCell*) override {} // Only interested in the respective AstScope + void visit(AstTypeTable*) override {} + void visit(AstConstPool*) override {} + void visit(AstClass*) override {} + void visit(AstCFunc*) override { // Calls to DPI exports handled with AstCCall. /* verilator public */ functions are // ignored for now (and hence potentially mis-ordered), but could use the same or // similar mechanism as DPI exports. Every other impure function (including those @@ -734,7 +734,7 @@ class OrderBuildVisitor final : public VNVisitor { } //--- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } // CONSTRUCTOR explicit OrderBuildVisitor(AstNetlist* nodep) { @@ -981,15 +981,14 @@ public: : m_pomGraphp{pomGraphp} , m_pomWaitingp{pomWaitingp} {} // METHODS - virtual OrderMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex*, - const AstScope* scopep, - const AstSenTree* domainp) override { + OrderMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex*, + const AstScope* scopep, const AstSenTree* domainp) override { OrderMoveVertex* const resultp = new OrderMoveVertex(m_pomGraphp, lvertexp); resultp->domScopep(OrderMoveDomScope::findCreate(domainp, scopep)); resultp->m_pomWaitingE.pushBack(*m_pomWaitingp, resultp); return resultp; } - virtual void freeVertexp(OrderMoveVertex* freeMep) override { + void freeVertexp(OrderMoveVertex* freeMep) override { freeMep->m_pomWaitingE.unlink(*m_pomWaitingp, freeMep); freeMep->unlinkDelete(m_pomGraphp); } @@ -1005,18 +1004,14 @@ class OrderMTaskMoveVertexMaker final public: explicit OrderMTaskMoveVertexMaker(V3Graph* pomGraphp) : m_pomGraphp{pomGraphp} {} - virtual MTaskMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, - const OrderEitherVertex* varVertexp, - const AstScope* scopep, - const AstSenTree* domainp) override { + MTaskMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex* varVertexp, + const AstScope* scopep, const AstSenTree* domainp) override { // Exclude initial/settle logic from the mtasks graph. // We'll output time-zero logic separately. if (domainp->hasInitial() || domainp->hasSettle()) return nullptr; return new MTaskMoveVertex(m_pomGraphp, lvertexp, varVertexp, scopep, domainp); } - virtual void freeVertexp(MTaskMoveVertex* freeMep) override { - freeMep->unlinkDelete(m_pomGraphp); - } + void freeVertexp(MTaskMoveVertex* freeMep) override { freeMep->unlinkDelete(m_pomGraphp); } private: VL_UNCOPYABLE(OrderMTaskMoveVertexMaker); diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 2fb8c33ab..08c0a54e8 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -112,9 +112,9 @@ inline bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) { class OrderGraph final : public V3Graph { public: OrderGraph() = default; - virtual ~OrderGraph() override = default; + ~OrderGraph() override = default; // Methods - virtual void loopsVertexCb(V3GraphVertex* vertexp) override; + void loopsVertexCb(V3GraphVertex* vertexp) override; }; //###################################################################### @@ -136,12 +136,12 @@ public: : V3GraphVertex{graphp} , m_scopep{scopep} , m_domainp{domainp} {} - virtual ~OrderEitherVertex() override = default; - virtual OrderEitherVertex* clone(V3Graph* graphp) const override = 0; + ~OrderEitherVertex() override = default; + OrderEitherVertex* clone(V3Graph* graphp) const override = 0; // Methods virtual OrderVEdgeType type() const = 0; virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex - virtual string dotName() const override { return cvtToHex(m_scopep) + "_"; } + string dotName() const override { return cvtToHex(m_scopep) + "_"; } // ACCESSORS void domainp(AstSenTree* domainp) { m_domainp = domainp; } AstScope* scopep() const { return m_scopep; } @@ -159,16 +159,16 @@ public: : OrderEitherVertex{graphp, nullptr, domainp} { isFromInput(true); // By definition } - virtual ~OrderInputsVertex() override = default; - virtual OrderInputsVertex* clone(V3Graph* graphp) const override { + ~OrderInputsVertex() override = default; + OrderInputsVertex* clone(V3Graph* graphp) const override { return new OrderInputsVertex(graphp, *this); } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_INPUTS; } - virtual string name() const override { return "*INPUTS*"; } - virtual string dotColor() const override { return "green"; } - virtual string dotName() const override { return ""; } - virtual string dotShape() const override { return "invhouse"; } - virtual bool domainMatters() override { return false; } + OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_INPUTS; } + string name() const override { return "*INPUTS*"; } + string dotColor() const override { return "green"; } + string dotName() const override { return ""; } + string dotShape() const override { return "invhouse"; } + bool domainMatters() override { return false; } }; class OrderLogicVertex final : public OrderEitherVertex { @@ -183,20 +183,18 @@ public: OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstNode* nodep) : OrderEitherVertex{graphp, scopep, domainp} , m_nodep{nodep} {} - virtual ~OrderLogicVertex() override = default; - virtual OrderLogicVertex* clone(V3Graph* graphp) const override { + ~OrderLogicVertex() override = default; + OrderLogicVertex* clone(V3Graph* graphp) const override { return new OrderLogicVertex(graphp, *this); } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_LOGIC; } - virtual bool domainMatters() override { return true; } + OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_LOGIC; } + bool domainMatters() override { return true; } // ACCESSORS - virtual string name() const override { + string name() const override { return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName())); } AstNode* nodep() const { return m_nodep; } - virtual string dotShape() const override { - return VN_IS(m_nodep, Active) ? "doubleoctagon" : "rect"; - } + string dotShape() const override { return VN_IS(m_nodep, Active) ? "doubleoctagon" : "rect"; } }; class OrderVarVertex VL_NOT_FINAL : public OrderEitherVertex { @@ -214,17 +212,17 @@ public: OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderEitherVertex{graphp, scopep, nullptr} , m_varScp{varScp} {} - virtual ~OrderVarVertex() override = default; - virtual OrderVarVertex* clone(V3Graph* graphp) const override = 0; - virtual OrderVEdgeType type() const override = 0; - virtual FileLine* fileline() const override { return varScp()->fileline(); } + ~OrderVarVertex() override = default; + OrderVarVertex* clone(V3Graph* graphp) const override = 0; + OrderVEdgeType type() const override = 0; + FileLine* fileline() const override { return varScp()->fileline(); } // ACCESSORS AstVarScope* varScp() const { return m_varScp; } void isClock(bool flag) { m_isClock = flag; } bool isClock() const { return m_isClock; } void isDelayed(bool flag) { m_isDelayed = flag; } bool isDelayed() const { return m_isDelayed; } - virtual string dotShape() const override { return "ellipse"; } + string dotShape() const override { return "ellipse"; } }; class OrderVarStdVertex final : public OrderVarVertex { @@ -234,16 +232,14 @@ class OrderVarStdVertex final : public OrderVarVertex { public: OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarStdVertex() override = default; - virtual OrderVarStdVertex* clone(V3Graph* graphp) const override { + ~OrderVarStdVertex() override = default; + OrderVarStdVertex* clone(V3Graph* graphp) const override { return new OrderVarStdVertex(graphp, *this); } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARSTD; } - virtual string name() const override { - return (cvtToHex(varScp()) + "\\n " + varScp()->name()); - } - virtual string dotColor() const override { return "grey"; } - virtual bool domainMatters() override { return true; } + OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARSTD; } + string name() const override { return (cvtToHex(varScp()) + "\\n " + varScp()->name()); } + string dotColor() const override { return "grey"; } + bool domainMatters() override { return true; } }; class OrderVarPreVertex final : public OrderVarVertex { OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old) @@ -252,16 +248,14 @@ class OrderVarPreVertex final : public OrderVarVertex { public: OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarPreVertex() override = default; - virtual OrderVarPreVertex* clone(V3Graph* graphp) const override { + ~OrderVarPreVertex() override = default; + OrderVarPreVertex* clone(V3Graph* graphp) const override { return new OrderVarPreVertex(graphp, *this); } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPRE; } - virtual string name() const override { - return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name()); - } - virtual string dotColor() const override { return "green"; } - virtual bool domainMatters() override { return false; } + OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPRE; } + string name() const override { return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name()); } + string dotColor() const override { return "green"; } + bool domainMatters() override { return false; } }; class OrderVarPostVertex final : public OrderVarVertex { OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old) @@ -270,16 +264,14 @@ class OrderVarPostVertex final : public OrderVarVertex { public: OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual OrderVarPostVertex* clone(V3Graph* graphp) const override { + OrderVarPostVertex* clone(V3Graph* graphp) const override { return new OrderVarPostVertex(graphp, *this); } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPOST; } - virtual ~OrderVarPostVertex() override = default; - virtual string name() const override { - return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); - } - virtual string dotColor() const override { return "red"; } - virtual bool domainMatters() override { return false; } + OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPOST; } + ~OrderVarPostVertex() override = default; + string name() const override { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); } + string dotColor() const override { return "red"; } + bool domainMatters() override { return false; } }; class OrderVarPordVertex final : public OrderVarVertex { OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old) @@ -288,16 +280,14 @@ class OrderVarPordVertex final : public OrderVarVertex { public: OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) : OrderVarVertex{graphp, scopep, varScp} {} - virtual ~OrderVarPordVertex() override = default; - virtual OrderVarPordVertex* clone(V3Graph* graphp) const override { + ~OrderVarPordVertex() override = default; + OrderVarPordVertex* clone(V3Graph* graphp) const override { return new OrderVarPordVertex(graphp, *this); } - virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPORD; } - virtual string name() const override { - return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name()); - } - virtual string dotColor() const override { return "blue"; } - virtual bool domainMatters() override { return false; } + OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPORD; } + string name() const override { return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name()); } + string dotColor() const override { return "blue"; } + bool domainMatters() override { return false; } }; //###################################################################### @@ -324,28 +314,28 @@ public: , m_logicp{logicp} , m_state{POM_WAIT} , m_domScopep{nullptr} {} - virtual ~OrderMoveVertex() override = default; - virtual OrderMoveVertex* clone(V3Graph* graphp) const override { + ~OrderMoveVertex() override = default; + OrderMoveVertex* clone(V3Graph* graphp) const override { v3fatalSrc("Unsupported"); return nullptr; } // METHODS virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; } - virtual string dotColor() const override { + string dotColor() const override { if (logicp()) { return logicp()->dotColor(); } else { return ""; } } - virtual FileLine* fileline() const override { + FileLine* fileline() const override { if (logicp()) { return logicp()->fileline(); } else { return nullptr; } } - virtual string name() const override { + string name() const override { string nm; if (VL_UNCOVERABLE(!logicp())) { // Avoid crash when debugging nm = "nul"; // LCOV_EXCL_LINE @@ -394,20 +384,20 @@ public: , m_domainp{domainp} { UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n"); } - virtual ~MTaskMoveVertex() override = default; - virtual MTaskMoveVertex* clone(V3Graph* graphp) const override { + ~MTaskMoveVertex() override = default; + MTaskMoveVertex* clone(V3Graph* graphp) const override { v3fatalSrc("Unsupported"); return nullptr; } virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; } - virtual string dotColor() const override { + string dotColor() const override { if (logicp()) { return logicp()->dotColor(); } else { return "yellow"; } } - virtual string name() const override { + string name() const override { string nm; if (logicp()) { nm = logicp()->name(); @@ -439,10 +429,9 @@ public: OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = false) : V3GraphEdge{graphp, fromp, top, weight, cutable} {} - virtual ~OrderEdge() override = default; + ~OrderEdge() override = default; virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; } - virtual OrderEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const override { + OrderEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const override { return new OrderEdge(graphp, fromp, top, *this); } // When ordering combo blocks with stronglyConnected, follow edges not @@ -466,14 +455,14 @@ class OrderComboCutEdge final : public OrderEdge { public: OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {} - virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_COMBOCUT; } - virtual ~OrderComboCutEdge() override = default; - virtual OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const override { + OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_COMBOCUT; } + ~OrderComboCutEdge() override = default; + OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, + V3GraphVertex* top) const override { return new OrderComboCutEdge(graphp, fromp, top, *this); } - virtual string dotColor() const override { return "yellowGreen"; } - virtual bool followComboConnected() const override { return true; } + string dotColor() const override { return "yellowGreen"; } + bool followComboConnected() const override { return true; } }; class OrderPostCutEdge final : public OrderEdge { @@ -487,14 +476,14 @@ class OrderPostCutEdge final : public OrderEdge { public: OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {} - virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_POSTCUT; } - virtual ~OrderPostCutEdge() override = default; - virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const override { + OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_POSTCUT; } + ~OrderPostCutEdge() override = default; + OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, + V3GraphVertex* top) const override { return new OrderPostCutEdge(graphp, fromp, top, *this); } - virtual string dotColor() const override { return "PaleGreen"; } - virtual bool followComboConnected() const override { return false; } + string dotColor() const override { return "PaleGreen"; } + bool followComboConnected() const override { return false; } }; class OrderPreCutEdge final : public OrderEdge { @@ -508,14 +497,14 @@ class OrderPreCutEdge final : public OrderEdge { public: OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : OrderEdge{graphp, fromp, top, WEIGHT_PRE, CUTABLE} {} - virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_PRECUT; } - virtual OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const override { + OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_PRECUT; } + OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, + V3GraphVertex* top) const override { return new OrderPreCutEdge(graphp, fromp, top, *this); } - virtual ~OrderPreCutEdge() override = default; - virtual string dotColor() const override { return "khaki"; } - virtual bool followComboConnected() const override { return false; } + ~OrderPreCutEdge() override = default; + string dotColor() const override { return "khaki"; } + bool followComboConnected() const override { return false; } }; #endif // Guard diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 01807114f..3a21266fc 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -977,7 +977,7 @@ class ParamVisitor final : public VNVisitor { } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { if (nodep->recursiveClone()) nodep->dead(true); // Fake, made for recursive elimination if (nodep->dead()) return; // Marked by LinkDot (and above) @@ -995,14 +995,14 @@ class ParamVisitor final : public VNVisitor { } } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { visitCellOrClassRef(nodep, VN_IS(nodep->modp(), Iface)); } - virtual void visit(AstClassRefDType* nodep) override { visitCellOrClassRef(nodep, false); } - virtual void visit(AstClassOrPackageRef* nodep) override { visitCellOrClassRef(nodep, false); } + void visit(AstClassRefDType* nodep) override { visitCellOrClassRef(nodep, false); } + void visit(AstClassOrPackageRef* nodep) override { visitCellOrClassRef(nodep, false); } // Make sure all parameters are constantified - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (nodep->user5SetOnce()) return; // Process once iterateChildren(nodep); if (nodep->isParam()) { @@ -1015,7 +1015,7 @@ class ParamVisitor final : public VNVisitor { } } // Make sure varrefs cause vars to constify before things above - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // Might jump across functions, so beware if ever add a m_funcp if (nodep->varp()) iterate(nodep->varp()); } @@ -1036,7 +1036,7 @@ class ParamVisitor final : public VNVisitor { } return false; } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { // Check to see if the scope is just an interface because interfaces are special const string dotted = nodep->dotted(); if (!dotted.empty() && nodep->varp() && nodep->varp()->isParam()) { @@ -1082,7 +1082,7 @@ class ParamVisitor final : public VNVisitor { nodep->varp(nullptr); // Needs relink, as may remove pointed-to var } - virtual void visit(AstUnlinkedRef* nodep) override { + void visit(AstUnlinkedRef* nodep) override { AstVarXRef* const varxrefp = VN_CAST(nodep->op1p(), VarXRef); AstNodeFTaskRef* const taskrefp = VN_CAST(nodep->op1p(), NodeFTaskRef); if (varxrefp) { @@ -1103,7 +1103,7 @@ class ParamVisitor final : public VNVisitor { nodep->replaceWith(nodep->op1p()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstCellArrayRef* nodep) override { + void visit(AstCellArrayRef* nodep) override { V3Const::constifyParamsEdit(nodep->selp()); if (const AstConst* const constp = VN_CAST(nodep->selp(), Const)) { const string index = AstNode::encodeNumber(constp->toSInt()); @@ -1122,7 +1122,7 @@ class ParamVisitor final : public VNVisitor { } // Generate Statements - virtual void visit(AstGenIf* nodep) override { + void visit(AstGenIf* nodep) override { UINFO(9, " GENIF " << nodep << endl); iterateAndNextNull(nodep->condp()); // We suppress errors when widthing params since short-circuiting in @@ -1149,7 +1149,7 @@ class ParamVisitor final : public VNVisitor { //! @todo Unlike generated IF, we don't have to worry about short-circuiting the conditional //! expression, since this is currently restricted to simple comparisons. If we ever do //! move to more generic constant expressions, such code will be needed here. - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { if (nodep->genforp()) { AstGenFor* const forp = VN_AS(nodep->genforp(), GenFor); UASSERT_OBJ(forp, nodep, "Non-GENFOR under generate-for BEGIN"); @@ -1181,10 +1181,10 @@ class ParamVisitor final : public VNVisitor { iterateChildren(nodep); } } - virtual void visit(AstGenFor* nodep) override { // LCOV_EXCL_LINE + void visit(AstGenFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("GENFOR should have been wrapped in BEGIN"); } - virtual void visit(AstGenCase* nodep) override { + void visit(AstGenCase* nodep) override { UINFO(9, " GENCASE " << nodep << endl); AstNode* keepp = nullptr; iterateAndNextNull(nodep->exprp()); @@ -1235,7 +1235,7 @@ class ParamVisitor final : public VNVisitor { VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1272,7 +1272,7 @@ public: for (AstNodeModule* const modp : modps) netlistp->addModulep(modp); } } - virtual ~ParamVisitor() override = default; + ~ParamVisitor() override = default; VL_UNCOPYABLE(ParamVisitor); }; diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index a2978e93a..f3ffaf56b 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -253,7 +253,7 @@ public: m_vertices.splice(m_vertices.end(), otherp->m_vertices); m_cost += otherp->m_cost; } - virtual const VxList* vertexListp() const override { return &m_vertices; } + const VxList* vertexListp() const override { return &m_vertices; } static uint64_t incGeneration() { static uint64_t s_generation = 0; ++s_generation; @@ -263,10 +263,10 @@ public: // Use this instead of pointer-compares to compare LogicMTasks. Avoids // nondeterministic output. Also name mtasks based on this number in // the final C++ output. - virtual uint32_t id() const override { return m_serialId; } + uint32_t id() const override { return m_serialId; } void id(uint32_t id) { m_serialId = id; } // Abstract cost of every logic mtask - virtual uint32_t cost() const override { return m_cost; } + uint32_t cost() const override { return m_cost; } void setCost(uint32_t cost) { m_cost = cost; } // For tests only uint32_t stepCost() const { return stepCost(m_cost); } static uint32_t stepCost(uint32_t cost) { @@ -319,7 +319,7 @@ public: void checkRelativesCp(GraphWay way) const; - virtual string name() const override { + string name() const override { // Display forward and reverse critical path costs. This gives a quick // read on whether graph partitioning looks reasonable or bad. std::ostringstream out; @@ -1850,7 +1850,7 @@ private: // METHODS VL_DEBUG_FUNC; - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (!m_tracingCall) return; m_tracingCall = false; if (nodep->dpiImportWrapper()) { @@ -1861,19 +1861,19 @@ private: } iterateChildren(nodep); } - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); // Enter the function and trace it m_tracingCall = true; iterate(nodep->funcp()); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit DpiImportCallVisitor(AstNode* nodep) { iterate(nodep); } bool hasDpiHazard() const { return m_hasDpiHazard; } - virtual ~DpiImportCallVisitor() override = default; + ~DpiImportCallVisitor() override = default; private: VL_UNCOPYABLE(DpiImportCallVisitor); diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h index b0eac05d3..d8ed603af 100644 --- a/src/V3PartitionGraph.h +++ b/src/V3PartitionGraph.h @@ -32,7 +32,7 @@ class AbstractMTask VL_NOT_FINAL : public V3GraphVertex { public: explicit AbstractMTask(V3Graph* graphp) : V3GraphVertex{graphp} {} - virtual ~AbstractMTask() override = default; + ~AbstractMTask() override = default; virtual uint32_t id() const = 0; virtual uint32_t cost() const = 0; }; @@ -44,12 +44,12 @@ public: // CONSTRUCTORS explicit AbstractLogicMTask(V3Graph* graphp) : AbstractMTask{graphp} {} - virtual ~AbstractLogicMTask() override = default; + ~AbstractLogicMTask() override = default; // METHODS // Set of logic vertices in this mtask. Order is not significant. virtual const VxList* vertexListp() const = 0; - virtual uint32_t id() const override = 0; // Unique id of this mtask. - virtual uint32_t cost() const override = 0; + uint32_t id() const override = 0; // Unique id of this mtask. + uint32_t cost() const override = 0; }; class ExecMTask final : public AbstractMTask { @@ -72,10 +72,10 @@ public: , m_bodyp{bodyp} , m_id{id} {} AstMTaskBody* bodyp() const { return m_bodyp; } - virtual uint32_t id() const override { return m_id; } + uint32_t id() const override { return m_id; } uint32_t priority() const { return m_priority; } void priority(uint32_t pri) { m_priority = pri; } - virtual uint32_t cost() const override { return m_cost; } + uint32_t cost() const override { return m_cost; } void cost(uint32_t cost) { m_cost = cost; } void predictStart(uint64_t time) { m_predictStart = time; } uint64_t predictStart() const { return m_predictStart; } @@ -85,7 +85,7 @@ public: // If this MTask maps to a C function, this should be the name return std::string{"__Vmtask"} + "__" + cvtToStr(m_id); } - virtual string name() const override { return std::string{"mt"} + cvtToStr(id()); } + string name() const override { return std::string{"mt"} + cvtToStr(id()); } string hashName() const { return m_hashName; } void hashName(const string& name) { m_hashName = name; } void dump(std::ostream& str) const { diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 0cf66dc24..684733a6e 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -250,13 +250,13 @@ public: void candidateDefines(VSpellCheck* spellerp) override; // METHODS, callbacks - virtual void comment(const string& text) override; // Comment detected (if keepComments==2) - virtual void include(const string& filename) override; // Request a include file be processed - virtual void undef(const string& name) override; + void comment(const string& text) override; // Comment detected (if keepComments==2) + void include(const string& filename) override; // Request a include file be processed + void undef(const string& name) override; virtual void undefineall(); - virtual void define(FileLine* fl, const string& name, const string& value, - const string& params, bool cmdline) override; - virtual string removeDefines(const string& text) override; // Remove defines in a text string + void define(FileLine* fl, const string& name, const string& value, const string& params, + bool cmdline) override; + string removeDefines(const string& text) override; // Remove defines in a text string // CONSTRUCTORS V3PreProcImp() { diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index e10f13458..842b8d720 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -151,11 +151,11 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UINFO(4, " MOD " << nodep << endl); iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { VL_RESTORER(m_cfuncp); { m_cfuncp = nodep; @@ -167,7 +167,7 @@ private: m_assignLhs = false; if (m_cfuncp) m_stmtp = nodep; } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { UINFO(4, " WHILE " << nodep << endl); startStatement(nodep); iterateAndNextNull(nodep->precondsp()); @@ -180,7 +180,7 @@ private: iterateAndNextNull(nodep->incsp()); m_stmtp = nullptr; } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { startStatement(nodep); { bool noopt = false; @@ -207,7 +207,7 @@ private: m_assignLhs = false; m_stmtp = nullptr; } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -217,7 +217,7 @@ private: iterateChildren(nodep); m_stmtp = nullptr; } - virtual void visit(AstTraceInc* nodep) override { + void visit(AstTraceInc* nodep) override { startStatement(nodep); m_inTracep = nodep; iterateChildren(nodep); @@ -271,31 +271,31 @@ private: iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstShiftL* nodep) override { visitShift(nodep); } - virtual void visit(AstShiftR* nodep) override { visitShift(nodep); } - virtual void visit(AstShiftRS* nodep) override { visitShift(nodep); } + void visit(AstShiftL* nodep) override { visitShift(nodep); } + void visit(AstShiftR* nodep) override { visitShift(nodep); } + void visit(AstShiftRS* nodep) override { visitShift(nodep); } // Operators - virtual void visit(AstNodeTermop* nodep) override { + void visit(AstNodeTermop* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstNodeUniop* nodep) override { + void visit(AstNodeUniop* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstRand* nodep) override { + void visit(AstRand* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { iterateAndNextNull(nodep->fromp()); { // Only the 'from' is part of the assignment LHS VL_RESTORER(m_assignLhs); @@ -305,7 +305,7 @@ private: } checkNode(nodep); } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { iterateAndNextNull(nodep->fromp()); { // Only the 'from' is part of the assignment LHS VL_RESTORER(m_assignLhs); @@ -314,7 +314,7 @@ private: } checkNode(nodep); } - virtual void visit(AstAssocSel* nodep) override { + void visit(AstAssocSel* nodep) override { iterateAndNextNull(nodep->fromp()); { // Only the 'from' is part of the assignment LHS VL_RESTORER(m_assignLhs); @@ -323,11 +323,11 @@ private: } checkNode(nodep); } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { iterateChildren(nodep); if (nodep->expr1p()->isWide() && !VN_IS(nodep->condp(), Const) && !VN_IS(nodep->condp(), VarRef)) { @@ -339,7 +339,7 @@ private: } // Autoflush - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { startStatement(nodep); iterateChildren(nodep); m_stmtp = nullptr; @@ -356,7 +356,7 @@ private: } } } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { iterateChildren(nodep); // Any strings sent to a display must be var of string data type, // to avoid passing a pointer to a temporary. @@ -370,8 +370,8 @@ private: //-------------------- // Default: Just iterate - virtual void visit(AstVar*) override {} // Don't hit varrefs under vars - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Don't hit varrefs under vars + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index c9a7acf9b..21abed5a7 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -64,7 +64,7 @@ private: bool m_hasClk = false; // True if the top module has sequential logic // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { m_vfilep = new AstVFile{nodep->fileline(), v3Global.opt.makeDir() + "/" + m_libName + ".sv"}; nodep->addFilesp(m_vfilep); @@ -74,7 +74,7 @@ private: iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { if (!nodep->isTop()) { return; } else { @@ -422,7 +422,7 @@ private: m_cfilep->tblockp(txtp); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (!nodep->isIO()) return; if (nodep->direction() == VDirection::INPUT) { if (nodep->isUsedClock() || nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) { @@ -439,7 +439,7 @@ private: } } - virtual void visit(AstNode*) override {} + void visit(AstNode*) override {} string cInputConnection(AstVar* varp) { return V3Task::assignDpiToInternal("handlep__V->" + varp->name(), varp); diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 0ac20c3b7..448623a08 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -82,7 +82,7 @@ private: } // VISITORS - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { iterateChildren(nodep); if (nodep->extendsp()) { // Save pointer to derived class @@ -90,7 +90,7 @@ private: m_baseToDerivedMap[basep].insert(nodep); } } - virtual void visit(AstMethodCall* nodep) override { + void visit(AstMethodCall* nodep) override { iterateChildren(nodep); if (nodep->name() != "randomize") return; if (const AstClassRefDType* const classRefp @@ -100,7 +100,7 @@ private: markMembers(classp); } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -108,7 +108,7 @@ public: iterate(nodep); markAllDerived(); } - virtual ~RandomizeMarkVisitor() override = default; + ~RandomizeMarkVisitor() override = default; }; //###################################################################### @@ -199,7 +199,7 @@ private: } // VISITORS - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { iterateChildren(nodep); if (!nodep->user1()) return; // Doesn't need randomize, or already processed UINFO(9, "Define randomize() for " << nodep << endl); @@ -241,12 +241,12 @@ private: } nodep->user1(false); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit RandomizeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~RandomizeVisitor() override = default; + ~RandomizeVisitor() override = default; }; //###################################################################### diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 19a4363ca..e163bdf8c 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -151,7 +151,7 @@ private: } // VISITORS - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { VL_RESTORER(m_cfuncp); { m_cfuncp = nodep; @@ -159,7 +159,7 @@ private: mergeEnd(); // Finish last pending merge, if any } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { if (!m_cfuncp) return; // Left select WordSel or ArraySel @@ -250,14 +250,14 @@ private: UINFO(9, "Start merge i=" << lindex << " o=" << m_mgOffset << nodep << endl); } //-------------------- - virtual void visit(AstVar*) override {} // Accelerate - virtual void visit(AstNodeMath*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar*) override {} // Accelerate + void visit(AstNodeMath*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ReloopVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ReloopVisitor() override { + ~ReloopVisitor() override { V3Stats::addStat("Optimizations, Reloops", m_statReloops); V3Stats::addStat("Optimizations, Reloop iterations", m_statReItems); } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index e39c1aa93..0c4bad466 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -81,7 +81,7 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { AstNodeModule* const modp = nodep->topModulep(); if (!modp) { nodep->v3error("No top level module found"); @@ -93,7 +93,7 @@ private: iterate(modp); cleanupVarRefs(); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { // Create required blocks and add to module string scopename; if (!m_aboveScopep) { @@ -144,7 +144,7 @@ private: // ***Note m_scopep is passed back to the caller of the routine (above) } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { // Create required blocks and add to module VL_RESTORER(m_scopep); VL_RESTORER(m_aboveCellp); @@ -177,13 +177,13 @@ private: iterateChildren(nodep); } } - virtual void visit(AstCellInline* nodep) override { // + void visit(AstCellInline* nodep) override { // nodep->scopep(m_scopep); } - virtual void visit(AstActive* nodep) override { // LCOV_EXCL_LINE + void visit(AstActive* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("Actives now made after scoping"); } - virtual void visit(AstNodeProcedure* nodep) override { + void visit(AstNodeProcedure* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); @@ -191,7 +191,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAssignAlias* nodep) override { + void visit(AstAssignAlias* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); @@ -199,7 +199,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAssignVarScope* nodep) override { + void visit(AstAssignVarScope* nodep) override { // Copy under the scope but don't recurse UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); @@ -207,7 +207,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); @@ -215,7 +215,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlwaysPublic* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); @@ -223,7 +223,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstCoverToggle* nodep) override { + void visit(AstCoverToggle* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); @@ -231,7 +231,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { // Add to list of blocks under this scope UINFO(4, " CFUNC " << nodep << endl); AstCFunc* const clonep = nodep->cloneTree(false); @@ -241,7 +241,7 @@ private: // We iterate under the *clone* iterateChildren(clonep); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { // Add to list of blocks under this scope UINFO(4, " FTASK " << nodep << endl); AstNodeFTask* clonep; @@ -257,7 +257,7 @@ private: // We iterate under the *clone* iterateChildren(clonep); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { // Make new scope variable if (!nodep->user1p()) { AstVarScope* const varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep); @@ -275,7 +275,7 @@ private: m_scopep->addVarp(varscp); } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // VarRef needs to point to VarScope // Make sure variable has made user1p. UASSERT_OBJ(nodep->varp(), nodep, "Unlinked"); @@ -289,7 +289,7 @@ private: m_varRefScopes.emplace(nodep, m_scopep); } } - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { // If there's a %m in the display text, we add a special node that will contain the name() const string prefix = std::string{"__DOT__"} + m_scopep->name(); // TOP and above will be the user's name(). @@ -305,17 +305,17 @@ private: if (afterp) nodep->scopeEntrp(afterp); iterateChildren(nodep); } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { // Scope that was made by this module for different cell; // Want to ignore blocks under it, so just do nothing } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ScopeVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ScopeVisitor() override = default; + ~ScopeVisitor() override = default; }; //###################################################################### @@ -330,7 +330,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { // Want to ignore blocks under it VL_RESTORER(m_scopep); { @@ -351,20 +351,20 @@ private: } } - virtual void visit(AstNodeProcedure* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstAssignAlias* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstAssignVarScope* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstAssignW* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstAlwaysPublic* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstCoverToggle* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstNodeFTask* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstCFunc* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstNodeProcedure* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstAssignAlias* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstAssignVarScope* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstAssignW* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstAlwaysPublic* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstCoverToggle* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstNodeFTask* nodep) override { movedDeleteOrIterate(nodep); } + void visit(AstCFunc* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { // The crossrefs are dealt with in V3LinkDot nodep->varp(nullptr); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { // The crossrefs are dealt with in V3LinkDot UINFO(9, " Old pkg-taskref " << nodep << endl); if (nodep->classOrPackagep()) { @@ -380,7 +380,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstModportFTaskRef* nodep) override { + void visit(AstModportFTaskRef* nodep) override { // The modport persists only for xml dump // The crossrefs are dealt with in V3LinkDot nodep->ftaskp(nullptr); @@ -388,12 +388,12 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ScopeCleanupVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ScopeCleanupVisitor() override = default; + ~ScopeCleanupVisitor() override = default; }; //###################################################################### diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 17f22e127..98d44a3c8 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -397,15 +397,15 @@ private: } // VISITORS - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { if (jumpingOver(nodep)) return; checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstSenTree* nodep) override { + void visit(AstSenTree* nodep) override { // Sensitivities aren't inputs per se; we'll keep our tree under the same sens. } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate UASSERT_OBJ(nodep->varp(), nodep, "Unlinked"); @@ -473,7 +473,7 @@ private: } } } - virtual void visit(AstVarXRef* nodep) override { + void visit(AstVarXRef* nodep) override { if (jumpingOver(nodep)) return; if (m_scoped) { badNodeType(nodep); @@ -483,7 +483,7 @@ private: "allowed in constant functions"); } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { if (jumpingOver(nodep)) return; if (!m_params) { badNodeType(nodep); @@ -503,7 +503,7 @@ private: checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { if (jumpingOver(nodep)) return; UINFO(5, " IF " << nodep << endl); checkNodeInfo(nodep); @@ -520,15 +520,15 @@ private: } } } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { checkNodeInfo(nodep); if (!m_checkOnly && optimizable()) newValue(nodep, nodep); } - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { checkNodeInfo(nodep); if (!m_checkOnly && optimizable()) newValue(nodep, nodep); } - virtual void visit(AstEnumItemRef* nodep) override { + void visit(AstEnumItemRef* nodep) override { checkNodeInfo(nodep); UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); if (!m_checkOnly && optimizable()) { @@ -541,7 +541,7 @@ private: } } } - virtual void visit(AstNodeUniop* nodep) override { + void visit(AstNodeUniop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -549,7 +549,7 @@ private: nodep->numberOperate(newConst(nodep)->num(), fetchConst(nodep->lhsp())->num()); } } - virtual void visit(AstNodeBiop* nodep) override { + void visit(AstNodeBiop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -558,7 +558,7 @@ private: fetchConst(nodep->rhsp())->num()); } } - virtual void visit(AstNodeTriop* nodep) override { + void visit(AstNodeTriop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -568,7 +568,7 @@ private: fetchConst(nodep->thsp())->num()); } } - virtual void visit(AstNodeQuadop* nodep) override { + void visit(AstNodeQuadop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -579,7 +579,7 @@ private: fetchConst(nodep->fhsp())->num()); } } - virtual void visit(AstLogAnd* nodep) override { + void visit(AstLogAnd* nodep) override { // Need to short circuit if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -597,7 +597,7 @@ private: } } } - virtual void visit(AstLogOr* nodep) override { + void visit(AstLogOr* nodep) override { // Need to short circuit if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -615,7 +615,7 @@ private: } } } - virtual void visit(AstLogIf* nodep) override { + void visit(AstLogIf* nodep) override { // Need to short circuit, same as (!A || B) if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -635,7 +635,7 @@ private: } } } - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { // We could use above visit(AstNodeTriop), but need to do short circuiting. // It's also slower even O(n^2) to evaluate both sides when we // really only need to evaluate one side. @@ -755,7 +755,7 @@ private: } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -795,7 +795,7 @@ private: } m_inDlyAssign = false; } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { checkNodeInfo(nodep); iterateChildren(nodep); if (AstInitArray* const initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) { @@ -812,11 +812,11 @@ private: clearOptimizable(nodep, "Array select of non-array"); } } - virtual void visit(AstBegin* nodep) override { + void visit(AstBegin* nodep) override { checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstNodeCase* nodep) override { + void visit(AstNodeCase* nodep) override { if (jumpingOver(nodep)) return; UINFO(5, " CASE " << nodep << endl); checkNodeInfo(nodep); @@ -854,20 +854,20 @@ private: } } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { // Real handling is in AstNodeCase if (jumpingOver(nodep)) return; checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstComment*) override {} + void visit(AstComment*) override {} - virtual void visit(AstJumpBlock* nodep) override { + void visit(AstJumpBlock* nodep) override { if (jumpingOver(nodep)) return; iterateChildren(nodep); } - virtual void visit(AstJumpGo* nodep) override { + void visit(AstJumpGo* nodep) override { if (jumpingOver(nodep)) return; checkNodeInfo(nodep); if (!m_checkOnly) { @@ -875,7 +875,7 @@ private: m_jumpp = nodep; } } - virtual void visit(AstJumpLabel* nodep) override { + void visit(AstJumpLabel* nodep) override { // This only supports forward jumps. That's all we make at present, // AstJumpGo::broken uses brokeExistsBelow() to check this. if (jumpingOver(nodep)) return; @@ -886,7 +886,7 @@ private: m_jumpp = nullptr; } } - virtual void visit(AstStop* nodep) override { + void visit(AstStop* nodep) override { if (jumpingOver(nodep)) return; if (m_params) { // This message seems better than an obscure $stop // The spec says $stop is just ignored, it seems evil to ignore assertions @@ -897,7 +897,7 @@ private: checkNodeInfo(nodep); } - virtual void visit(AstNodeFor* nodep) override { + void visit(AstNodeFor* nodep) override { // Doing lots of Whiles is slow, so only for parameters UINFO(5, " FOR " << nodep << endl); if (!m_params) { @@ -929,7 +929,7 @@ private: } } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { // Doing lots of Whiles is slow, so only for parameters if (jumpingOver(nodep)) return; UINFO(5, " WHILE " << nodep << endl); @@ -969,7 +969,7 @@ private: } } - virtual void visit(AstFuncRef* nodep) override { + void visit(AstFuncRef* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate UINFO(5, " FUNCREF " << nodep << endl); @@ -1041,7 +1041,7 @@ private: } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (jumpingOver(nodep)) return; if (!m_params) { badNodeType(nodep); @@ -1049,12 +1049,12 @@ private: } } - virtual void visit(AstScopeName* nodep) override { + void visit(AstScopeName* nodep) override { if (jumpingOver(nodep)) return; // Ignore } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -1108,7 +1108,7 @@ private: } } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate // We ignore isPredictOptimizable as $display is often in constant @@ -1133,7 +1133,7 @@ private: // These types are definitely not reducible // AstCoverInc, AstFinish, // AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { if (jumpingOver(nodep)) return; badNodeType(nodep); } @@ -1188,7 +1188,7 @@ public: setMode(false /*scoped*/, false /*checking*/, true /*params*/); mainGuts(nodep); } - virtual ~SimulateVisitor() override { + ~SimulateVisitor() override { for (const auto& pair : m_constps) { for (AstConst* const constp : pair.second) { delete constp; } } diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index b143373f2..c5a993e75 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -128,7 +128,7 @@ class SliceVisitor final : public VNVisitor { return newp; } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // Called recursively on newly created assignments if (!nodep->user1() && !VN_IS(nodep, AssignAlias)) { nodep->user1(true); @@ -162,7 +162,7 @@ class SliceVisitor final : public VNVisitor { } } - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { UASSERT_OBJ(!m_assignp, nodep, "Array initialization should have been removed earlier"); } @@ -221,17 +221,17 @@ class SliceVisitor final : public VNVisitor { iterateChildren(nodep); } } - virtual void visit(AstEq* nodep) override { expandBiOp(nodep); } - virtual void visit(AstNeq* nodep) override { expandBiOp(nodep); } - virtual void visit(AstEqCase* nodep) override { expandBiOp(nodep); } - virtual void visit(AstNeqCase* nodep) override { expandBiOp(nodep); } + void visit(AstEq* nodep) override { expandBiOp(nodep); } + void visit(AstNeq* nodep) override { expandBiOp(nodep); } + void visit(AstEqCase* nodep) override { expandBiOp(nodep); } + void visit(AstNeqCase* nodep) override { expandBiOp(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit SliceVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~SliceVisitor() override = default; + ~SliceVisitor() override = default; }; //###################################################################### diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 83dc6ac5b..3e9f4e9ec 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -103,14 +103,12 @@ protected: SplitNodeVertex(V3Graph* graphp, AstNode* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~SplitNodeVertex() override = default; + ~SplitNodeVertex() override = default; // ACCESSORS // Do not make accessor for nodep(), It may change due to // reordering a lower block, but we don't repair it - virtual string name() const override { - return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); - } - virtual FileLine* fileline() const override { return nodep()->fileline(); } + string name() const override { return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); } + FileLine* fileline() const override { return nodep()->fileline(); } public: virtual AstNode* nodep() const { return m_nodep; } @@ -120,34 +118,34 @@ class SplitPliVertex final : public SplitNodeVertex { public: explicit SplitPliVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitPliVertex() override = default; - virtual string name() const override { return "*PLI*"; } - virtual string dotColor() const override { return "green"; } + ~SplitPliVertex() override = default; + string name() const override { return "*PLI*"; } + string dotColor() const override { return "green"; } }; class SplitLogicVertex final : public SplitNodeVertex { public: SplitLogicVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitLogicVertex() override = default; - virtual string dotColor() const override { return "yellow"; } + ~SplitLogicVertex() override = default; + string dotColor() const override { return "yellow"; } }; class SplitVarStdVertex final : public SplitNodeVertex { public: SplitVarStdVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitVarStdVertex() override = default; - virtual string dotColor() const override { return "skyblue"; } + ~SplitVarStdVertex() override = default; + string dotColor() const override { return "skyblue"; } }; class SplitVarPostVertex final : public SplitNodeVertex { public: SplitVarPostVertex(V3Graph* graphp, AstNode* nodep) : SplitNodeVertex{graphp, nodep} {} - virtual ~SplitVarPostVertex() override = default; - virtual string name() const override { return string("POST ") + SplitNodeVertex::name(); } - virtual string dotColor() const override { return "CadetBlue"; } + ~SplitVarPostVertex() override = default; + string name() const override { return string("POST ") + SplitNodeVertex::name(); } + string dotColor() const override { return "CadetBlue"; } }; //###################################################################### @@ -161,7 +159,7 @@ protected: SplitEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = CUTABLE) : V3GraphEdge{graphp, fromp, top, weight, cutable} {} - virtual ~SplitEdge() override = default; + ~SplitEdge() override = default; public: // Iterator for graph functions @@ -180,7 +178,7 @@ public: if (!oedgep) v3fatalSrc("Following edge of non-SplitEdge type"); return (!oedgep->ignoreThisStep()); } - virtual string dotStyle() const override { + string dotStyle() const override { return ignoreThisStep() ? "dotted" : V3GraphEdge::dotStyle(); } }; @@ -190,36 +188,36 @@ class SplitPostEdge final : public SplitEdge { public: SplitPostEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitPostEdge() override = default; - virtual bool followScoreboard() const override { return false; } - virtual string dotColor() const override { return "khaki"; } + ~SplitPostEdge() override = default; + bool followScoreboard() const override { return false; } + string dotColor() const override { return "khaki"; } }; class SplitLVEdge final : public SplitEdge { public: SplitLVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitLVEdge() override = default; - virtual bool followScoreboard() const override { return true; } - virtual string dotColor() const override { return "yellowGreen"; } + ~SplitLVEdge() override = default; + bool followScoreboard() const override { return true; } + string dotColor() const override { return "yellowGreen"; } }; class SplitRVEdge final : public SplitEdge { public: SplitRVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitRVEdge() override = default; - virtual bool followScoreboard() const override { return true; } - virtual string dotColor() const override { return "green"; } + ~SplitRVEdge() override = default; + bool followScoreboard() const override { return true; } + string dotColor() const override { return "green"; } }; struct SplitScorebdEdge : public SplitEdge { public: SplitScorebdEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} - virtual ~SplitScorebdEdge() override = default; - virtual bool followScoreboard() const override { return true; } - virtual string dotColor() const override { return "blue"; } + ~SplitScorebdEdge() override = default; + bool followScoreboard() const override { return true; } + string dotColor() const override { return "blue"; } }; struct SplitStrictEdge : public SplitEdge { @@ -228,9 +226,9 @@ struct SplitStrictEdge : public SplitEdge { public: SplitStrictEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL, NOT_CUTABLE} {} - virtual ~SplitStrictEdge() override = default; - virtual bool followScoreboard() const override { return true; } - virtual string dotColor() const override { return "blue"; } + ~SplitStrictEdge() override = default; + bool followScoreboard() const override { return true; } + string dotColor() const override { return "blue"; } }; //###################################################################### @@ -259,7 +257,7 @@ protected: // CONSTRUCTORS public: SplitReorderBaseVisitor() { scoreboardClear(); } - virtual ~SplitReorderBaseVisitor() override = default; + ~SplitReorderBaseVisitor() override = default; // METHODS protected: @@ -335,19 +333,19 @@ protected: virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) = 0; // VISITORS - virtual void visit(AstAlways* nodep) override = 0; - virtual void visit(AstNodeIf* nodep) override = 0; + void visit(AstAlways* nodep) override = 0; + void visit(AstNodeIf* nodep) override = 0; // We don't do AstNodeFor/AstWhile loops, due to the standard question // of what is before vs. after - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { m_inDly = true; UINFO(4, " ASSIGNDLY " << nodep << endl); iterateChildren(nodep); m_inDly = false; } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (!m_stmtStackps.empty()) { AstVarScope* const vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Not linked"); @@ -410,7 +408,7 @@ protected: } } - virtual void visit(AstJumpGo* nodep) override { + void visit(AstJumpGo* nodep) override { // Jumps will disable reordering at all levels // This is overly pessimistic; we could treat jumps as barriers, and // reorder everything between jumps/labels, however jumps are rare @@ -422,7 +420,7 @@ protected: //-------------------- // Default - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // **** SPECIAL default type that sets PLI_ORDERING if (!m_stmtStackps.empty() && !nodep->isPure()) { UINFO(9, " NotSplittable " << nodep << endl); @@ -439,11 +437,11 @@ class ReorderVisitor final : public SplitReorderBaseVisitor { // CONSTRUCTORS public: explicit ReorderVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ReorderVisitor() override = default; + ~ReorderVisitor() override = default; // METHODS protected: - virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) override { + void makeRvalueEdges(SplitVarStdVertex* vstdp) override { for (SplitLogicVertex* vxp : m_stmtStackps) new SplitRVEdge(&m_graph, vxp, vstdp); } @@ -599,7 +597,7 @@ protected: firstp->user3p(oldBlockUser3); } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { UINFO(4, " ALW " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, " alwIn:: "); scoreboardClear(); @@ -607,7 +605,7 @@ protected: if (debug() >= 9) nodep->dumpTree(cout, " alwOut: "); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); iterateAndNextNull(nodep->condp()); processBlock(nodep->ifsp()); @@ -636,7 +634,7 @@ public: // Visit through *nodep and map each AstNodeIf within to the set of // colors it will participate in. Also find the whole set of colors. explicit IfColorVisitor(AstAlways* nodep) { iterate(nodep); } - virtual ~IfColorVisitor() override = default; + ~IfColorVisitor() override = default; // METHODS const ColorSet& colors() const { return m_colors; } @@ -663,13 +661,13 @@ private: } protected: - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { m_ifStack.push_back(nodep); trackNode(nodep); iterateChildren(nodep); m_ifStack.pop_back(); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { trackNode(nodep); iterateChildren(nodep); } @@ -701,7 +699,7 @@ public: UINFO(6, " splitting always " << nodep << endl); } - virtual ~EmitSplitVisitor() override = default; + ~EmitSplitVisitor() override = default; // METHODS void go() { @@ -732,7 +730,7 @@ protected: return new AstSplitPlaceholder(m_origAlwaysp->fileline()); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // Anything that's not an if/else we assume is a leaf // (that is, something we won't split.) Don't visit further // into the leaf. @@ -754,7 +752,7 @@ protected: m_addAfter[color] = clonedp; } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { const ColorSet& colors = m_ifColorp->colors(nodep); using CloneMap = std::unordered_map; CloneMap clones; @@ -798,17 +796,17 @@ class RemovePlaceholdersVisitor final : public VNVisitor { // CONSTRUCTORS RemovePlaceholdersVisitor() = default; - virtual ~RemovePlaceholdersVisitor() override = default; + ~RemovePlaceholdersVisitor() override = default; // VISITORS - virtual void visit(AstSplitPlaceholder* nodep) override { pushDeletep(nodep->unlinkFrBack()); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstSplitPlaceholder* nodep) override { pushDeletep(nodep->unlinkFrBack()); } + void visit(AstNodeIf* nodep) override { VL_RESTORER(m_isPure); m_isPure = true; iterateChildren(nodep); if (!nodep->ifsp() && !nodep->elsesp() && m_isPure) pushDeletep(nodep->unlinkFrBack()); } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { VL_RESTORER(m_isPure); m_isPure = true; iterateChildren(nodep); @@ -828,7 +826,7 @@ class RemovePlaceholdersVisitor final : public VNVisitor { } } } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { m_isPure &= nodep->isPure(); iterateChildren(nodep); // must visit regardless of m_isPure to remove placeholders } @@ -875,13 +873,11 @@ public: } } - virtual ~SplitVisitor() override { - V3Stats::addStat("Optimizations, Split always", m_statSplits); - } + ~SplitVisitor() override { V3Stats::addStat("Optimizations, Split always", m_statSplits); } // METHODS protected: - virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) override { + void makeRvalueEdges(SplitVarStdVertex* vstdp) override { // Each 'if' depends on rvalues in its own conditional ONLY, // not rvalues in the if/else bodies. for (auto it = m_stmtStackps.cbegin(); it != m_stmtStackps.cend(); ++it) { @@ -956,7 +952,7 @@ protected: if (debug() >= 9) m_graph.dumpDotFilePrefixed("splitg_colored", false); } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { // build the scoreboard scoreboardClear(); scanBlock(nodep->bodysp()); @@ -988,7 +984,7 @@ protected: emitSplit.go(); } } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); m_curIfConditional = nodep; iterateAndNextNull(nodep->condp()); diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index ebdac1d7a..d22429f93 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -49,17 +49,17 @@ private: AstVarScope* m_splitVscp = nullptr; // Variable we want to split // METHODS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (nodep->access().isWriteOrRW() && !m_splitVscp && nodep->varp()->attrIsolateAssign()) { m_splitVscp = nodep->varScopep(); } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit SplitAsFindVisitor(AstAlways* nodep) { iterate(nodep); } - virtual ~SplitAsFindVisitor() override = default; + ~SplitAsFindVisitor() override = default; // METHODS AstVarScope* splitVscp() const { return m_splitVscp; } }; @@ -76,7 +76,7 @@ private: bool m_matches = false; // Statement below has matching lvalue reference // METHODS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (nodep->access().isWriteOrRW()) { if (nodep->varScopep() == m_splitVscp) { UINFO(6, " CL VAR " << nodep << endl); @@ -84,7 +84,7 @@ private: } } } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -110,7 +110,7 @@ private: m_keepStmt = oldKeep || m_keepStmt; UINFO(9, " upKeep=" << m_keepStmt << " STMT " << nodep << endl); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -119,7 +119,7 @@ public: , m_modeMatch{modeMatch} { iterate(nodep); } - virtual ~SplitAsCleanVisitor() override = default; + ~SplitAsCleanVisitor() override = default; }; //###################################################################### @@ -154,7 +154,7 @@ private: } } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { // Are there any lvalue references below this? // There could be more than one. So, we process the first one found first. const AstVarScope* lastSplitVscp = nullptr; @@ -179,13 +179,13 @@ private: } // Speedup; no always under math - virtual void visit(AstNodeMath*) override {} - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeMath*) override {} + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit SplitAsVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~SplitAsVisitor() override { + ~SplitAsVisitor() override { V3Stats::addStat("Optimizations, isolate_assignments blocks", m_statSplits); } }; diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 7ca9464d0..47dc0e006 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -362,10 +362,10 @@ public: void remove(AstNode* nodep) { struct Visitor : public VNVisitor { RefsInModule& m_parent; - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } - virtual void visit(AstVar* nodep) override { m_parent.m_vars.erase(nodep); } - virtual void visit(AstVarRef* nodep) override { m_parent.m_refs.erase(nodep); } - virtual void visit(AstSel* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstVar* nodep) override { m_parent.m_vars.erase(nodep); } + void visit(AstVarRef* nodep) override { m_parent.m_refs.erase(nodep); } + void visit(AstSel* nodep) override { m_parent.m_sels.erase(nodep); iterateChildren(nodep); } @@ -456,8 +456,8 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { return refp; } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeModule* nodep) override { UINFO(4, "Start checking " << nodep->prettyNameQ() << "\n"); if (!VN_IS(nodep, Module)) { UINFO(4, "Skip " << nodep->prettyNameQ() << "\n"); @@ -471,9 +471,9 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { split(); m_modp = nullptr; } - virtual void visit(AstNodeStmt* nodep) override { setContextAndIterateChildren(nodep); } - virtual void visit(AstCell* nodep) override { setContextAndIterateChildren(nodep); } - virtual void visit(AstAlways* nodep) override { + void visit(AstNodeStmt* nodep) override { setContextAndIterateChildren(nodep); } + void visit(AstCell* nodep) override { setContextAndIterateChildren(nodep); } + void visit(AstAlways* nodep) override { if (nodep->sensesp()) { // When visiting sensitivity list, always is the context setContextAndIterate(nodep, nodep->sensesp()); } @@ -481,7 +481,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { iterate(bodysp); } }; - virtual void visit(AstAlwaysPublic* nodep) override { + void visit(AstAlwaysPublic* nodep) override { if (nodep->sensesp()) { // When visiting sensitivity list, always is the context setContextAndIterate(nodep, nodep->sensesp()); } @@ -489,7 +489,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { iterate(bodysp); } } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { VL_RESTORER(m_contextp); { m_contextp = nodep; @@ -524,7 +524,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { } } } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { UINFO(5, nodep->modVarp()->prettyNameQ() << " pin \n"); AstNode* const exprp = nodep->exprp(); if (!exprp) return; // Not connected pin @@ -538,7 +538,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { m_foundTargetVar.clear(); } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { UASSERT_OBJ(!m_inFTask, nodep, "Nested func/task"); if (!cannotSplitTaskReason(nodep)) { m_inFTask = nodep; @@ -546,7 +546,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { m_inFTask = nullptr; } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (!nodep->attrSplitVar()) return; // Nothing to do if (!cannotSplitReason(nodep)) { m_refs.registerVar(nodep); @@ -554,18 +554,18 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { } m_refsForPackedSplit[m_modp].add(nodep); } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (!nodep->varp()->attrSplitVar()) return; // Nothing to do if (m_refs.tryAdd(m_contextp, nodep, m_inFTask)) { m_foundTargetVar.insert(nodep->varp()); } m_refsForPackedSplit[m_modp].add(nodep); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { if (VN_IS(nodep->fromp(), VarRef)) m_refsForPackedSplit[m_modp].add(nodep); iterateChildren(nodep); } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { if (AstVarRef* const refp = isTargetVref(nodep->fromp())) { const AstConst* const indexp = VN_CAST(nodep->bitp(), Const); if (indexp) { // OK @@ -585,7 +585,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { iterateChildren(nodep); } } - virtual void visit(AstSliceSel* nodep) override { + void visit(AstSliceSel* nodep) override { if (AstVarRef* const refp = isTargetVref(nodep->fromp())) { const AstUnpackArrayDType* const dtypep = VN_AS(refp->varp()->dtypep()->skipRefp(), UnpackArrayDType); @@ -966,10 +966,10 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { int m_numSplit = 0; // Total number of split variables // key:variable to be split. value:location where the variable is referenced. std::map m_refs; - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { if (!cannotSplitTaskReason(nodep)) iterateChildren(nodep); } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { if (!nodep->attrSplitVar()) return; // Nothing to do if (const char* const reason = cannotSplitReason(nodep, true)) { warnNoSplit(nodep, nodep, reason); @@ -979,7 +979,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { if (inserted) UINFO(3, nodep->prettyNameQ() << " is added to candidate list.\n"); } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { AstVar* const varp = nodep->varp(); visit(varp); const auto refit = m_refs.find(varp); @@ -993,7 +993,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { UINFO(5, varp->prettyName() << " Entire bit of [" << basicp->lo() << "+:" << varp->width() << "] \n"); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { const AstVarRef* const vrefp = VN_CAST(nodep->fromp(), VarRef); if (!vrefp) { iterateChildren(nodep); @@ -1032,7 +1032,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl { iterateChildren(nodep); } } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } // Extract necessary bit range from a newly created variable to meet ref static AstNode* extractBits(const PackedVarRefEntry& ref, const SplitNewVar& var, diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 11512254d..01d3ec2f2 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -76,7 +76,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { allNodes(nodep); if (!m_fast) { // Count all CFuncs below this module @@ -85,7 +85,7 @@ private: // Else we recursively trace fast CFuncs from the top _eval // func, see visit(AstNetlist*) } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); if (m_counting && nodep->dtypep()) { @@ -111,7 +111,7 @@ private: } } } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); if (m_counting) { @@ -120,7 +120,7 @@ private: } } } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { UINFO(4, " IF i=" << m_instrs << " " << nodep << endl); allNodes(nodep); // Condition is part of cost allocated to PREVIOUS block @@ -166,9 +166,9 @@ private: } } // While's we assume evaluate once. - // virtual void visit(AstWhile* nodep) override { + // void visit(AstWhile* nodep) override { - virtual void visit(AstNodeCCall* nodep) override { + void visit(AstNodeCCall* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); if (m_fast && !nodep->funcp()->entryPoint()) { @@ -177,7 +177,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { if (m_fast) { if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; @@ -189,11 +189,11 @@ private: iterateChildrenConst(nodep); } } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); } - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { if (m_fast && nodep->evalp()) { m_instrs = 0; m_counting = true; @@ -219,7 +219,7 @@ public: // Process iterate(nodep); } - virtual ~StatsVisitor() override { + ~StatsVisitor() override { // Done. Publish statistics V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr); V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast); diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index ce43a7fd0..eda173f78 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -189,7 +189,7 @@ private: return reinterpret_cast(nodep->varp()->user1p()); // Might be nullptr } // VISITORS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { const SubstVarEntry* const entryp = findEntryp(nodep); if (entryp) { // Don't sweat it. We assign a new temp variable for every new assignment, @@ -204,8 +204,8 @@ private: } } } - virtual void visit(AstConst*) override {} // Accelerate - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstConst*) override {} // Accelerate + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -214,7 +214,7 @@ public: UINFO(9, " SubstUseVisitor " << origStep << " " << nodep << endl); iterate(nodep); } - virtual ~SubstUseVisitor() override = default; + ~SubstUseVisitor() override = default; // METHODS bool ok() const { return m_ok; } }; @@ -258,7 +258,7 @@ private: inline bool isSubstVar(AstVar* nodep) { return nodep->isStatementTemp() && !nodep->noSubst(); } // VISITORS - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { m_ops = 0; m_assignStep++; iterateAndNextNull(nodep->rhsp()); @@ -304,7 +304,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); ++m_statSubsts; } - virtual void visit(AstWordSel* nodep) override { + void visit(AstWordSel* nodep) override { iterate(nodep->rhsp()); AstVarRef* const varrefp = VN_CAST(nodep->lhsp(), VarRef); const AstConst* const constp = VN_CAST(nodep->rhsp(), Const); @@ -329,7 +329,7 @@ private: iterate(nodep->lhsp()); } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { // Any variable if (nodep->access().isWriteOrRW()) { m_assignStep++; @@ -357,16 +357,16 @@ private: } } } - virtual void visit(AstVar*) override {} - virtual void visit(AstConst*) override {} - virtual void visit(AstModule* nodep) override { + void visit(AstVar*) override {} + void visit(AstConst*) override {} + void visit(AstModule* nodep) override { ++m_ops; if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA; iterateChildren(nodep); // Reduce peak memory usage by reclaiming the edited AstNodes doDeletes(); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { m_ops++; if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA; iterateChildren(nodep); @@ -375,7 +375,7 @@ private: public: // CONSTRUCTORS explicit SubstVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~SubstVisitor() override { + ~SubstVisitor() override { V3Stats::addStat("Optimizations, Substituted temps", m_statSubsts); for (SubstVarEntry* ip : m_entryps) { ip->deleteUnusedAssign(); diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 27d877369..c89e1f3b9 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -61,7 +61,7 @@ public: TspVertexTmpl(V3Graph* graphp, const T_Key& k) : V3GraphVertex{graphp} , m_key{k} {} - virtual ~TspVertexTmpl() override = default; + ~TspVertexTmpl() override = default; const T_Key& key() const { return m_key; } private: @@ -84,7 +84,7 @@ public: // CONSTRUCTORS TspGraphTmpl() : V3Graph{} {} - virtual ~TspGraphTmpl() override = default; + ~TspGraphTmpl() override = default; // METHODS void addVertex(const T_Key& key) { @@ -542,8 +542,8 @@ public: : m_xpos{xpos} , m_ypos{ypos} , m_serial{++s_serialNext} {} - virtual ~TspTestState() override = default; - virtual int cost(const TspStateBase* otherp) const override { + ~TspTestState() override = default; + int cost(const TspStateBase* otherp) const override { return cost(dynamic_cast(otherp)); } static unsigned diff(unsigned a, unsigned b) { diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 8829e9cbf..76fcb3711 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -59,12 +59,12 @@ class TableSimulateVisitor final : public SimulateVisitor { public: ///< Call other-this function on all new var references - virtual void varRefCb(AstVarRef* nodep) override; + void varRefCb(AstVarRef* nodep) override; // CONSTRUCTORS explicit TableSimulateVisitor(TableVisitor* cbthis) : m_cbthis{cbthis} {} - virtual ~TableSimulateVisitor() override = default; + ~TableSimulateVisitor() override = default; }; //###################################################################### @@ -379,8 +379,8 @@ private: } // VISITORS - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); VL_RESTORER(m_modTables); { @@ -389,20 +389,20 @@ private: iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; iterateChildren(nodep); m_scopep = nullptr; } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { UINFO(4, " ALWAYS " << nodep << endl); if (treeTest(nodep)) { // Well, then, I'll be a memory hog. replaceWithTable(nodep); } } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // It's nearly impossible to have a large enough assign to make this worthwhile // For now we won't bother. // Accelerated: no iterate @@ -411,7 +411,7 @@ private: public: // CONSTRUCTORS explicit TableVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~TableVisitor() override { // + ~TableVisitor() override { // V3Stats::addStat("Optimizations, Tables created", m_statTablesCre); } }; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index c736bb86b..c298f8ed4 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -47,7 +47,7 @@ class TaskBaseVertex VL_NOT_FINAL : public V3GraphVertex { public: explicit TaskBaseVertex(V3Graph* graphp) : V3GraphVertex{graphp} {} - virtual ~TaskBaseVertex() override = default; + ~TaskBaseVertex() override = default; bool pure() const { return m_impurep == nullptr; } AstNode* impureNode() const { return m_impurep; } void impure(AstNode* nodep) { m_impurep = nodep; } @@ -64,10 +64,10 @@ public: TaskFTaskVertex(V3Graph* graphp, AstNodeFTask* nodep) : TaskBaseVertex{graphp} , m_nodep{nodep} {} - virtual ~TaskFTaskVertex() override = default; + ~TaskFTaskVertex() override = default; AstNodeFTask* nodep() const { return m_nodep; } - virtual string name() const override { return nodep()->name(); } - virtual string dotColor() const override { return pure() ? "black" : "red"; } + string name() const override { return nodep()->name(); } + string dotColor() const override { return pure() ? "black" : "red"; } AstCFunc* cFuncp() const { return m_cFuncp; } void cFuncp(AstCFunc* nodep) { m_cFuncp = nodep; } }; @@ -77,17 +77,17 @@ class TaskCodeVertex final : public TaskBaseVertex { public: explicit TaskCodeVertex(V3Graph* graphp) : TaskBaseVertex{graphp} {} - virtual ~TaskCodeVertex() override = default; - virtual string name() const override { return "*CODE*"; } - virtual string dotColor() const override { return "green"; } + ~TaskCodeVertex() override = default; + string name() const override { return "*CODE*"; } + string dotColor() const override { return "green"; } }; class TaskEdge final : public V3GraphEdge { public: TaskEdge(V3Graph* graphp, TaskBaseVertex* fromp, TaskBaseVertex* top) : V3GraphEdge{graphp, fromp, top, 1, false} {} - virtual ~TaskEdge() override = default; - virtual string dotLabel() const override { return "w" + cvtToStr(weight()); } + ~TaskEdge() override = default; + string dotLabel() const override { return "w" + cvtToStr(weight()); } }; //###################################################################### @@ -166,7 +166,7 @@ private: } // VISITORS - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { // Each FTask is unique per-scope, so AstNodeFTaskRefs do not need // pointers to what scope the FTask is to be invoked under. // However, to create variables, we need to track the scopes involved. @@ -186,12 +186,12 @@ private: } iterateChildren(nodep); } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { m_assignwp = nodep; VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. m_assignwp = nullptr; } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { // Includes handling AstMethodCall, AstNew if (m_assignwp) { // Wire assigns must become always statements to deal with insertion @@ -204,7 +204,7 @@ private: UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked task"); new TaskEdge(&m_callGraph, m_curVxp, getFTaskVertex(nodep->taskp())); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { UINFO(9, " TASK " << nodep << endl); { VL_RESTORER(m_curVxp); @@ -221,7 +221,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstPragma* nodep) override { + void visit(AstPragma* nodep) override { if (nodep->pragType() == VPragmaType::NO_INLINE_TASK) { // Just mark for the next steps, and we're done with it. m_curVxp->noInline(true); @@ -230,17 +230,17 @@ private: iterateChildren(nodep); } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { iterateChildren(nodep); nodep->user4p(m_curVxp); // Remember what task it's under } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { iterateChildren(nodep); if (nodep->varp()->user4u().toGraphVertex() != m_curVxp) { if (m_curVxp->pure() && !nodep->varp()->isXTemp()) m_curVxp->impure(nodep); } } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { // Move initial statements into the constructor m_initialps.clear(); m_ctorp = nullptr; @@ -264,12 +264,12 @@ private: m_ctorp = nullptr; m_classp = nullptr; } - virtual void visit(AstInitialAutomatic* nodep) override { + void visit(AstInitialAutomatic* nodep) override { m_initialps.push_back(nodep); iterateChildren(nodep); } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -283,7 +283,7 @@ public: m_callGraph.removeRedundantEdgesSum(&TaskEdge::followAlwaysTrue); m_callGraph.dumpDotFilePrefixed("task_call"); } - virtual ~TaskStateVisitor() override = default; + ~TaskStateVisitor() override = default; VL_UNCOPYABLE(TaskStateVisitor); }; @@ -1366,7 +1366,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); VL_RESTORER(m_modNCalls); { @@ -1376,13 +1376,13 @@ private: iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { m_scopep = nodep; m_insStmtp = nullptr; iterateChildren(nodep); m_scopep = nullptr; } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { // Includes handling AstMethodCall, AstNew UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked?"); iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs @@ -1436,7 +1436,7 @@ private: // Visit nodes that normal iteration won't find if (visitp) iterateAndNextNull(visitp); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { UINFO(4, " visitFTask " << nodep << endl); VL_RESTORER(m_insMode); VL_RESTORER(m_insStmtp); @@ -1504,7 +1504,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { // Special, as statements need to be put in different places // Preconditions insert first just before themselves (the normal // rule for other statement types) @@ -1521,11 +1521,11 @@ private: // Done the loop m_insStmtp = nullptr; // Next thing should be new statement } - virtual void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE + void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc( "For statements should have been converted to while statements in V3Begin.cpp"); } - virtual void visit(AstNodeStmt* nodep) override { + void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -1536,7 +1536,7 @@ private: m_insStmtp = nullptr; // Next thing should be new statement } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1544,7 +1544,7 @@ public: : m_statep{statep} { iterate(nodep); } - virtual ~TaskVisitor() override = default; + ~TaskVisitor() override = default; }; //###################################################################### diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 9a1fe1e3c..c98a120a3 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -73,20 +73,20 @@ public: m_activityCode = code; m_slow = false; } - virtual ~TraceActivityVertex() override = default; + ~TraceActivityVertex() override = default; // ACCESSORS AstNode* insertp() const { if (!m_insertp) v3fatalSrc("Null insertp; probably called on a special always/slow."); return m_insertp; } - virtual string name() const override { + string name() const override { if (activityAlways()) { return "*ALWAYS*"; } else { return std::string{slow() ? "*SLOW* " : ""} + insertp()->name(); } } - virtual string dotColor() const override { return slow() ? "yellowGreen" : "green"; } + string dotColor() const override { return slow() ? "yellowGreen" : "green"; } int32_t activityCode() const { return m_activityCode; } bool activityAlways() const { return activityCode() == ACTIVITY_ALWAYS; } bool activitySlow() const { return activityCode() == ACTIVITY_SLOW; } @@ -104,12 +104,12 @@ public: TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TraceCFuncVertex() override = default; + ~TraceCFuncVertex() override = default; // ACCESSORS AstCFunc* nodep() const { return m_nodep; } - virtual string name() const override { return nodep()->name(); } - virtual string dotColor() const override { return "yellow"; } - virtual FileLine* fileline() const override { return nodep()->fileline(); } + string name() const override { return nodep()->name(); } + string dotColor() const override { return "yellow"; } + FileLine* fileline() const override { return nodep()->fileline(); } }; class TraceTraceVertex final : public V3GraphVertex { @@ -121,12 +121,12 @@ public: TraceTraceVertex(V3Graph* graphp, AstTraceDecl* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TraceTraceVertex() override = default; + ~TraceTraceVertex() override = default; // ACCESSORS AstTraceDecl* nodep() const { return m_nodep; } - virtual string name() const override { return nodep()->name(); } - virtual string dotColor() const override { return "red"; } - virtual FileLine* fileline() const override { return nodep()->fileline(); } + string name() const override { return nodep()->name(); } + string dotColor() const override { return "red"; } + FileLine* fileline() const override { return nodep()->fileline(); } TraceTraceVertex* duplicatep() const { return m_duplicatep; } void duplicatep(TraceTraceVertex* dupp) { UASSERT_OBJ(!duplicatep(), nodep(), "Assigning duplicatep() to already duplicated node"); @@ -141,12 +141,12 @@ public: TraceVarVertex(V3Graph* graphp, AstVarScope* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TraceVarVertex() override = default; + ~TraceVarVertex() override = default; // ACCESSORS AstVarScope* nodep() const { return m_nodep; } - virtual string name() const override { return nodep()->name(); } - virtual string dotColor() const override { return "skyblue"; } - virtual FileLine* fileline() const override { return nodep()->fileline(); } + string name() const override { return nodep()->name(); } + string dotColor() const override { return "skyblue"; } + FileLine* fileline() const override { return nodep()->fileline(); } }; //###################################################################### @@ -796,7 +796,7 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { m_code = 1; // Multiple TopScopes will require fixing how code#s // are assigned as duplicate varscopes must result in the same tracing code#. @@ -811,11 +811,11 @@ private: // Create the trace functions and insert them into the tree createTraceFunctions(); } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { if (nodep->isTop()) m_topModp = nodep; iterateChildren(nodep); } - virtual void visit(AstCCall* nodep) override { + void visit(AstCCall* nodep) override { UINFO(8, " CCALL " << nodep << endl); if (!m_finding && !nodep->user2()) { // See if there are other calls in same statement list; @@ -834,7 +834,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) override { + void visit(AstCFunc* nodep) override { UINFO(8, " CFUNC " << nodep << endl); V3GraphVertex* const funcVtxp = getCFuncVertexp(nodep); if (!m_finding) { // If public, we need a unique activity code to allow for sets @@ -851,7 +851,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstTraceDecl* nodep) override { + void visit(AstTraceDecl* nodep) override { UINFO(8, " TRACE " << nodep << endl); if (!m_finding) { V3GraphVertex* const vertexp = new TraceTraceVertex(&m_graph, nodep); @@ -863,7 +863,7 @@ private: m_tracep = nullptr; } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (m_tracep) { UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?"); UASSERT_OBJ(nodep->access().isReadOnly(), nodep, "Lvalue in trace? Should be const."); @@ -888,7 +888,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -896,7 +896,7 @@ public: : m_alwaysVtxp{new TraceActivityVertex{&m_graph, TraceActivityVertex::ACTIVITY_ALWAYS}} { iterate(nodep); } - virtual ~TraceVisitor() override { + ~TraceVisitor() override { V3Stats::addStat("Tracing, Unique traced signals", m_statUniqSigs); V3Stats::addStat("Tracing, Unique trace codes", m_statUniqCodes); } diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 8268ec487..4c8cae3a8 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -241,7 +241,7 @@ private: } // VISITORS - virtual void visit(AstScope* nodep) override { + void visit(AstScope* nodep) override { UASSERT_OBJ(!m_currScopep, nodep, "Should not nest"); UASSERT_OBJ(m_subFuncps.empty(), nodep, "Should not nest"); UASSERT_OBJ(m_signals.empty(), nodep, "Should not nest"); @@ -330,7 +330,7 @@ private: m_scopeSubFuncps.emplace(scopeName, std::move(m_subFuncps)); } } - virtual void visit(AstVarScope* nodep) override { + void visit(AstVarScope* nodep) override { UASSERT_OBJ(m_currScopep, nodep, "AstVarScope not under AstScope"); // Prefilter - things that get added to m_vscps will either get traced or get a comment as @@ -345,13 +345,13 @@ private: } // VISITORS - Data types when tracing - virtual void visit(AstConstDType* nodep) override { + void visit(AstConstDType* nodep) override { if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump()); } - virtual void visit(AstRefDType* nodep) override { + void visit(AstRefDType* nodep) override { if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump()); } - virtual void visit(AstUnpackArrayDType* nodep) override { + void visit(AstUnpackArrayDType* nodep) override { // Note more specific dtypes above if (m_traVscp) { if (static_cast(nodep->arrayUnpackedElements()) > v3Global.opt.traceMaxArray()) { @@ -386,7 +386,7 @@ private: } } } - virtual void visit(AstPackArrayDType* nodep) override { + void visit(AstPackArrayDType* nodep) override { if (m_traVscp) { if (!v3Global.opt.traceStructs()) { // Everything downstream is packed, so deal with as one trace unit. @@ -412,7 +412,7 @@ private: } } } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { if (m_traVscp) { if (nodep->packed() && !v3Global.opt.traceStructs()) { // Everything downstream is packed, so deal with as one trace unit @@ -449,7 +449,7 @@ private: } } } - virtual void visit(AstBasicDType* nodep) override { + void visit(AstBasicDType* nodep) override { if (m_traVscp) { if (nodep->isString()) { addIgnore("Unsupported: strings"); @@ -458,15 +458,15 @@ private: } } } - virtual void visit(AstEnumDType* nodep) override { iterate(nodep->skipRefp()); } - virtual void visit(AstNodeDType*) override { + void visit(AstEnumDType* nodep) override { iterate(nodep->skipRefp()); } + void visit(AstNodeDType*) override { // Note more specific dtypes above if (!m_traVscp) return; addIgnore("Unsupported: data type"); } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -513,7 +513,7 @@ public: AstCFunc* const topFuncp = m_topFuncps.front(); topFuncp->name("trace_init_top"); } - virtual ~TraceDeclVisitor() override { + ~TraceDeclVisitor() override { V3Stats::addStat("Tracing, Traced signals", m_statSigs); V3Stats::addStat("Tracing, Ignored signals", m_statIgnSigs); } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 733d4ad74..5a04e135e 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -118,17 +118,17 @@ public: TristateVertex(V3Graph* graphp, AstNode* nodep) : V3GraphVertex{graphp} , m_nodep{nodep} {} - virtual ~TristateVertex() override = default; + ~TristateVertex() override = default; // ACCESSORS AstNode* nodep() const { return m_nodep; } const AstVar* varp() const { return VN_CAST(nodep(), Var); } - virtual string name() const override { + string name() const override { return ((isTristate() ? "tri\\n" : feedsTri() ? "feed\\n" : "-\\n") + (nodep()->prettyTypeName() + " " + cvtToHex(nodep()))); } - virtual string dotColor() const override { + string dotColor() const override { return (varp() ? (isTristate() ? "darkblue" : feedsTri() ? "blue" : "lightblue") @@ -136,7 +136,7 @@ public: : feedsTri() ? "green" : "lightgreen")); } - virtual FileLine* fileline() const override { return nodep()->fileline(); } + FileLine* fileline() const override { return nodep()->fileline(); } void isTristate(bool flag) { m_isTristate = flag; } bool isTristate() const { return m_isTristate; } void feedsTri(bool flag) { m_feedsTri = flag; } @@ -312,7 +312,7 @@ class TristatePinVisitor final : public TristateBaseVisitor { TristateGraph& m_tgraph; const bool m_lvalue; // Flip to be an LVALUE // VISITORS - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { UASSERT_OBJ(!nodep->access().isRW(), nodep, "Tristate unexpected on R/W access flip"); if (m_lvalue && !nodep->access().isWriteOrRW()) { UINFO(9, " Flip-to-LValue " << nodep << endl); @@ -325,17 +325,17 @@ class TristatePinVisitor final : public TristateBaseVisitor { m_tgraph.setTristate(nodep->varp()); } } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { // Doesn't work because we'd set lvalue on the array index's var UASSERT_OBJ(!m_lvalue, nodep, "ArraySel conversion to output, under tristate node"); iterateChildren(nodep); } - virtual void visit(AstSliceSel* nodep) override { + void visit(AstSliceSel* nodep) override { // Doesn't work because we'd set lvalue on the array index's var UASSERT_OBJ(!m_lvalue, nodep, "SliceSel conversion to output, under tristate node"); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -344,7 +344,7 @@ public: , m_lvalue{lvalue} { iterate(nodep); } - virtual ~TristatePinVisitor() override = default; + ~TristatePinVisitor() override = default; }; //###################################################################### @@ -778,7 +778,7 @@ class TristateVisitor final : public TristateBaseVisitor { } // VISITORS - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { UINFO(9, dbgState() << nodep << endl); if (m_graphing) { if (!m_alhs && nodep->num().hasZ()) m_tgraph.setTristate(nodep); @@ -811,7 +811,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstCond* nodep) override { + void visit(AstCond* nodep) override { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { @@ -856,7 +856,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { @@ -895,7 +895,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { @@ -941,7 +941,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstBufIf1* nodep) override { + void visit(AstBufIf1* nodep) override { // For BufIf1, the enable is the LHS expression iterateChildren(nodep); UINFO(9, dbgState() << nodep << endl); @@ -1025,8 +1025,8 @@ class TristateVisitor final : public TristateBaseVisitor { expr2p->user1p(nullptr); } } - virtual void visit(AstAnd* nodep) override { visitAndOr(nodep, true); } - virtual void visit(AstOr* nodep) override { visitAndOr(nodep, false); } + void visit(AstAnd* nodep) override { visitAndOr(nodep, true); } + void visit(AstOr* nodep) override { visitAndOr(nodep, false); } void visitAssign(AstNodeAssign* nodep) { if (m_graphing) { @@ -1065,8 +1065,8 @@ class TristateVisitor final : public TristateBaseVisitor { m_alhs = false; } } - virtual void visit(AstAssignW* nodep) override { visitAssign(nodep); } - virtual void visit(AstAssign* nodep) override { visitAssign(nodep); } + void visit(AstAssignW* nodep) override { visitAssign(nodep); } + void visit(AstAssign* nodep) override { visitAssign(nodep); } void visitCaseEq(AstNodeBiop* nodep, bool neq) { if (m_graphing) { @@ -1136,12 +1136,12 @@ class TristateVisitor final : public TristateBaseVisitor { return; } } - virtual void visit(AstEqCase* nodep) override { visitCaseEq(nodep, false); } - virtual void visit(AstNeqCase* nodep) override { visitCaseEq(nodep, true); } - virtual void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } - virtual void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } + void visit(AstEqCase* nodep) override { visitCaseEq(nodep, false); } + void visit(AstNeqCase* nodep) override { visitCaseEq(nodep, true); } + void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } + void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } - virtual void visit(AstCountBits* nodep) override { + void visit(AstCountBits* nodep) override { std::array dropop; dropop[0] = VN_IS(nodep->rhsp(), Const) && VN_AS(nodep->rhsp(), Const)->num().isAnyZ(); dropop[1] = VN_IS(nodep->thsp(), Const) && VN_AS(nodep->thsp(), Const)->num().isAnyZ(); @@ -1201,7 +1201,7 @@ class TristateVisitor final : public TristateBaseVisitor { iterateChildren(nodep); } } - virtual void visit(AstPull* nodep) override { + void visit(AstPull* nodep) override { UINFO(9, dbgState() << nodep << endl); AstVarRef* varrefp = nullptr; if (VN_IS(nodep->lhsp(), VarRef)) { @@ -1276,7 +1276,7 @@ class TristateVisitor final : public TristateBaseVisitor { // __out(to-resolver-only) // const inout Spec says illegal // const output Unsupported; Illegal? - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { if (m_graphing) { if (nodep->user2() & U2_GRAPHING) return; // This pin is already expanded nodep->user2(U2_GRAPHING); @@ -1445,7 +1445,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { UINFO(9, dbgState() << nodep << endl); if (m_graphing) { if (nodep->access().isWriteOrRW()) associateLogic(nodep, nodep->varp()); @@ -1477,7 +1477,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { iterateChildren(nodep); UINFO(9, dbgState() << nodep << endl); if (m_graphing) { @@ -1510,7 +1510,7 @@ class TristateVisitor final : public TristateBaseVisitor { } } - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UINFO(8, nodep << endl); VL_RESTORER(m_modp); VL_RESTORER(m_graphing); @@ -1546,29 +1546,29 @@ class TristateVisitor final : public TristateBaseVisitor { m_tgraph.clear(); // Recursion not supported } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { // don't deal with classes } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { // don't deal with functions } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { // don't deal with casez compare '???? values iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { VL_RESTORER(m_cellp); m_cellp = nodep; m_alhs = false; iterateChildren(nodep); } - virtual void visit(AstNetlist* nodep) override { iterateChildrenBackwards(nodep); } + void visit(AstNetlist* nodep) override { iterateChildrenBackwards(nodep); } // Default: Just iterate - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); checkUnhandled(nodep); } @@ -1579,7 +1579,7 @@ public: m_tgraph.clear(); iterate(nodep); } - virtual ~TristateVisitor() override { + ~TristateVisitor() override { V3Stats::addStat("Tristate, Tristate resolved nets", m_statTriSigs); } }; diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 4f6374cde..1cf0f125d 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -294,7 +294,7 @@ private: } // VISITORS - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { // For assigns and non-combo always, do just usr==1, to look // for module-wide undriven etc. @@ -315,15 +315,15 @@ private: // Discover variables used in bit definitions, etc iterateChildren(nodep); } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { // Arrays are rarely constant assigned, so for now we punt and do all entries iterateChildren(nodep); } - virtual void visit(AstSliceSel* nodep) override { + void visit(AstSliceSel* nodep) override { // Arrays are rarely constant assigned, so for now we punt and do all entries iterateChildren(nodep); } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { AstNodeVarRef* const varrefp = VN_CAST(nodep->fromp(), NodeVarRef); AstConst* const constp = VN_CAST(nodep->lsbp(), Const); if (varrefp && constp && !constp->num().isFourState()) { @@ -347,7 +347,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { // Any variable if (nodep->access().isWriteOrRW() && !VN_IS(nodep, VarXRef)) { // Ignore interface variables and similar ugly items @@ -388,7 +388,7 @@ private: } // Don't know what black boxed calls do, assume in+out - virtual void visit(AstSysIgnore* nodep) override { + void visit(AstSysIgnore* nodep) override { VL_RESTORER(m_inBBox); { m_inBBox = true; @@ -396,28 +396,28 @@ private: } } - virtual void visit(AstAssign* nodep) override { + void visit(AstAssign* nodep) override { VL_RESTORER(m_inProcAssign); { m_inProcAssign = true; iterateChildren(nodep); } } - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { VL_RESTORER(m_inProcAssign); { m_inProcAssign = true; iterateChildren(nodep); } } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { VL_RESTORER(m_inContAssign); { m_inContAssign = true; iterateChildren(nodep); } } - virtual void visit(AstAlways* nodep) override { + void visit(AstAlways* nodep) override { VL_RESTORER(m_alwaysCombp); { AstNode::user2ClearTree(); @@ -432,37 +432,37 @@ private: } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { VL_RESTORER(m_taskp); { m_taskp = nodep; iterateChildren(nodep); } } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { VL_RESTORER(m_inInoutPin); m_inInoutPin = nodep->modVarp()->isInoutish(); iterateChildren(nodep); } // Until we support tables, primitives will have undriven and unused I/Os - virtual void visit(AstPrimitive*) override {} + void visit(AstPrimitive*) override {} // Coverage artifacts etc shouldn't count as a sink - virtual void visit(AstCoverDecl*) override {} - virtual void visit(AstCoverInc*) override {} - virtual void visit(AstCoverToggle*) override {} - virtual void visit(AstTraceDecl*) override {} - virtual void visit(AstTraceInc*) override {} + void visit(AstCoverDecl*) override {} + void visit(AstCoverInc*) override {} + void visit(AstCoverToggle*) override {} + void visit(AstTraceDecl*) override {} + void visit(AstTraceInc*) override {} // iterate - virtual void visit(AstConst* nodep) override {} - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstConst* nodep) override {} + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit UndrivenVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~UndrivenVisitor() override { + ~UndrivenVisitor() override { for (UndrivenVarEntry* ip : m_entryps[1]) ip->reportViolations(); for (int usr = 1; usr < 3; ++usr) { for (UndrivenVarEntry* ip : m_entryps[usr]) delete ip; diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 5d027a135..bd91ad005 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -138,7 +138,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { UINFO(4, " MOD " << nodep << endl); VL_RESTORER(m_modp); VL_RESTORER(m_constXCvt); @@ -153,21 +153,21 @@ private: iterateChildren(nodep); } } - virtual void visit(AstAssignDly* nodep) override { + void visit(AstAssignDly* nodep) override { VL_RESTORER(m_assigndlyp); { m_assigndlyp = nodep; VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. } } - virtual void visit(AstAssignW* nodep) override { + void visit(AstAssignW* nodep) override { VL_RESTORER(m_assignwp); { m_assignwp = nodep; VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. } } - virtual void visit(AstCaseItem* nodep) override { + void visit(AstCaseItem* nodep) override { VL_RESTORER(m_constXCvt); { m_constXCvt = false; // Avoid losing the X's in casex @@ -176,7 +176,7 @@ private: iterateAndNextNull(nodep->bodysp()); } } - virtual void visit(AstNodeDType* nodep) override { + void visit(AstNodeDType* nodep) override { VL_RESTORER(m_constXCvt); { m_constXCvt = false; // Avoid losing the X's in casex @@ -255,11 +255,11 @@ private: } } - virtual void visit(AstEqCase* nodep) override { visitEqNeqCase(nodep); } - virtual void visit(AstNeqCase* nodep) override { visitEqNeqCase(nodep); } - virtual void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } - virtual void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } - virtual void visit(AstIsUnknown* nodep) override { + void visit(AstEqCase* nodep) override { visitEqNeqCase(nodep); } + void visit(AstNeqCase* nodep) override { visitEqNeqCase(nodep); } + void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } + void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } + void visit(AstIsUnknown* nodep) override { iterateChildren(nodep); // Ahh, we're two state, so this is easy UINFO(4, " ISUNKNOWN->0 " << nodep << endl); @@ -267,7 +267,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstCountBits* nodep) override { + void visit(AstCountBits* nodep) override { // Ahh, we're two state, so this is easy std::array dropop; dropop[0] = VN_IS(nodep->rhsp(), Const) && VN_AS(nodep->rhsp(), Const)->num().isAnyX(); @@ -303,7 +303,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { if (m_constXCvt && nodep->num().isFourState()) { UINFO(4, " CONST4 " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, " Const_old: "); @@ -364,7 +364,7 @@ private: } } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { iterateChildren(nodep); if (!nodep->user1SetOnce()) { // Guard against reading/writing past end of bit vector array @@ -411,7 +411,7 @@ private: // visit(AstSliceSel) not needed as its bounds are constant and checked // in V3Width. - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { iterateChildren(nodep); if (!nodep->user1SetOnce()) { if (debug() == 9) nodep->dumpTree(cout, "-in: "); @@ -482,7 +482,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -491,7 +491,7 @@ public: , m_xrandNames{"__Vxrand"} { iterate(nodep); } - virtual ~UnknownVisitor() override { // + ~UnknownVisitor() override { // V3Stats::addStat("Unknowns, variables created", m_statUnkVars); } }; diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 0b47ce518..8c9bf96dd 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -371,7 +371,7 @@ private: return true; } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { iterateChildren(nodep); if (m_varModeCheck || m_varModeReplace) { } else { @@ -406,7 +406,7 @@ private: } } } - virtual void visit(AstGenFor* nodep) override { + void visit(AstGenFor* nodep) override { if (!m_generate || m_varModeReplace) { iterateChildren(nodep); } // else V3Param will recursively call each for loop to be unrolled for us @@ -433,7 +433,7 @@ private: } } } - virtual void visit(AstNodeFor* nodep) override { + void visit(AstNodeFor* nodep) override { if (m_generate) { // Ignore for's when expanding genfor's iterateChildren(nodep); } else { @@ -441,7 +441,7 @@ private: } } - virtual void visit(AstVarRef* nodep) override { + void visit(AstVarRef* nodep) override { if (m_varModeCheck && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp && nodep->access().isWriteOrRW()) { UINFO(8, " Itervar assigned to: " << nodep << endl); @@ -458,7 +458,7 @@ private: //-------------------- // Default: Just iterate - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { if (m_varModeCheck && nodep == m_ignoreIncp) { // Ignore subtree that is the increment } else { @@ -469,7 +469,7 @@ private: public: // CONSTRUCTORS UnrollVisitor() { init(false, ""); } - virtual ~UnrollVisitor() override { + ~UnrollVisitor() override { V3Stats::addStatSum("Optimizations, Unrolled Loops", m_statLoops); V3Stats::addStatSum("Optimizations, Unrolled Iterations", m_statIters); } diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp index d3ea7aa3d..5bd51933d 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -51,12 +51,12 @@ public: } ~VarTspSorter() override = default; // METHODS - virtual bool operator<(const TspStateBase& other) const override { + bool operator<(const TspStateBase& other) const override { return operator<(static_cast(other)); } bool operator<(const VarTspSorter& other) const { return m_serial < other.m_serial; } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } - virtual int cost(const TspStateBase* otherp) const override { + int cost(const TspStateBase* otherp) const override { return cost(static_cast(otherp)); } int cost(const VarTspSorter* otherp) const { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6a303ee0b..57fad0d7f 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -250,123 +250,119 @@ private: // _Ox=anything // Widths: 1 bit out, lhs 1 bit; Real: converts via compare with 0 - virtual void visit(AstLogNot* nodep) override { visit_log_not(nodep); } + void visit(AstLogNot* nodep) override { visit_log_not(nodep); } // Widths: 1 bit out, lhs 1 bit, rhs 1 bit; Real: converts via compare with 0 - virtual void visit(AstLogAnd* nodep) override { visit_log_and_or(nodep); } - virtual void visit(AstLogOr* nodep) override { visit_log_and_or(nodep); } - virtual void visit(AstLogEq* nodep) override { + void visit(AstLogAnd* nodep) override { visit_log_and_or(nodep); } + void visit(AstLogOr* nodep) override { visit_log_and_or(nodep); } + void visit(AstLogEq* nodep) override { // Conversion from real not in IEEE, but a fallout visit_log_and_or(nodep); } - virtual void visit(AstLogIf* nodep) override { + void visit(AstLogIf* nodep) override { // Conversion from real not in IEEE, but a fallout visit_log_and_or(nodep); } // Widths: 1 bit out, Any width lhs - virtual void visit(AstRedAnd* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstRedOr* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstRedXor* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstOneHot* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstOneHot0* nodep) override { visit_red_and_or(nodep); } - virtual void visit(AstIsUnknown* nodep) override { + void visit(AstRedAnd* nodep) override { visit_red_and_or(nodep); } + void visit(AstRedOr* nodep) override { visit_red_and_or(nodep); } + void visit(AstRedXor* nodep) override { visit_red_and_or(nodep); } + void visit(AstOneHot* nodep) override { visit_red_and_or(nodep); } + void visit(AstOneHot0* nodep) override { visit_red_and_or(nodep); } + void visit(AstIsUnknown* nodep) override { visit_red_unknown(nodep); // Allow real } // These have different node types, as they operate differently // Must add to case statement below, // Widths: 1 bit out, lhs width == rhs width. real if lhs|rhs real - virtual void visit(AstEq* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstNeq* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGt* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGte* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLt* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLte* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGtS* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGteS* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLtS* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLteS* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstEqCase* nodep) override { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstNeqCase* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstEq* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstNeq* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstGt* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstGte* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstLt* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstLte* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstGtS* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstGteS* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstLtS* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstLteS* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstEqCase* nodep) override { visit_cmp_eq_gt(nodep, true); } + void visit(AstNeqCase* nodep) override { visit_cmp_eq_gt(nodep, true); } // ... These comparisons don't allow reals - virtual void visit(AstEqWild* nodep) override { visit_cmp_eq_gt(nodep, false); } - virtual void visit(AstNeqWild* nodep) override { visit_cmp_eq_gt(nodep, false); } + void visit(AstEqWild* nodep) override { visit_cmp_eq_gt(nodep, false); } + void visit(AstNeqWild* nodep) override { visit_cmp_eq_gt(nodep, false); } // ... Real compares - virtual void visit(AstEqD* nodep) override { visit_cmp_real(nodep); } - virtual void visit(AstNeqD* nodep) override { visit_cmp_real(nodep); } - virtual void visit(AstLtD* nodep) override { visit_cmp_real(nodep); } - virtual void visit(AstLteD* nodep) override { visit_cmp_real(nodep); } - virtual void visit(AstGtD* nodep) override { visit_cmp_real(nodep); } - virtual void visit(AstGteD* nodep) override { visit_cmp_real(nodep); } + void visit(AstEqD* nodep) override { visit_cmp_real(nodep); } + void visit(AstNeqD* nodep) override { visit_cmp_real(nodep); } + void visit(AstLtD* nodep) override { visit_cmp_real(nodep); } + void visit(AstLteD* nodep) override { visit_cmp_real(nodep); } + void visit(AstGtD* nodep) override { visit_cmp_real(nodep); } + void visit(AstGteD* nodep) override { visit_cmp_real(nodep); } // ... String compares - virtual void visit(AstEqN* nodep) override { visit_cmp_string(nodep); } - virtual void visit(AstNeqN* nodep) override { visit_cmp_string(nodep); } - virtual void visit(AstLtN* nodep) override { visit_cmp_string(nodep); } - virtual void visit(AstLteN* nodep) override { visit_cmp_string(nodep); } - virtual void visit(AstGtN* nodep) override { visit_cmp_string(nodep); } - virtual void visit(AstGteN* nodep) override { visit_cmp_string(nodep); } + void visit(AstEqN* nodep) override { visit_cmp_string(nodep); } + void visit(AstNeqN* nodep) override { visit_cmp_string(nodep); } + void visit(AstLtN* nodep) override { visit_cmp_string(nodep); } + void visit(AstLteN* nodep) override { visit_cmp_string(nodep); } + void visit(AstGtN* nodep) override { visit_cmp_string(nodep); } + void visit(AstGteN* nodep) override { visit_cmp_string(nodep); } // Widths: out width = lhs width = rhs width // Signed: Output signed iff LHS & RHS signed. // Real: Not allowed - virtual void visit(AstAnd* nodep) override { visit_boolmath_and_or(nodep); } - virtual void visit(AstOr* nodep) override { visit_boolmath_and_or(nodep); } - virtual void visit(AstXor* nodep) override { visit_boolmath_and_or(nodep); } - virtual void visit(AstBufIf1* nodep) override { + void visit(AstAnd* nodep) override { visit_boolmath_and_or(nodep); } + void visit(AstOr* nodep) override { visit_boolmath_and_or(nodep); } + void visit(AstXor* nodep) override { visit_boolmath_and_or(nodep); } + void visit(AstBufIf1* nodep) override { visit_boolmath_and_or(nodep); } // Signed behavior changing in 3.814 // Width: Max(Lhs,Rhs) sort of. // Real: If either side real // Signed: If both sides real - virtual void visit(AstAdd* nodep) override { visit_add_sub_replace(nodep, true); } - virtual void visit(AstSub* nodep) override { visit_add_sub_replace(nodep, true); } - virtual void visit(AstDiv* nodep) override { visit_add_sub_replace(nodep, true); } - virtual void visit(AstMul* nodep) override { visit_add_sub_replace(nodep, true); } + void visit(AstAdd* nodep) override { visit_add_sub_replace(nodep, true); } + void visit(AstSub* nodep) override { visit_add_sub_replace(nodep, true); } + void visit(AstDiv* nodep) override { visit_add_sub_replace(nodep, true); } + void visit(AstMul* nodep) override { visit_add_sub_replace(nodep, true); } // These can't promote to real - virtual void visit(AstModDiv* nodep) override { visit_add_sub_replace(nodep, false); } - virtual void visit(AstModDivS* nodep) override { visit_add_sub_replace(nodep, false); } - virtual void visit(AstMulS* nodep) override { visit_add_sub_replace(nodep, false); } - virtual void visit(AstDivS* nodep) override { visit_add_sub_replace(nodep, false); } + void visit(AstModDiv* nodep) override { visit_add_sub_replace(nodep, false); } + void visit(AstModDivS* nodep) override { visit_add_sub_replace(nodep, false); } + void visit(AstMulS* nodep) override { visit_add_sub_replace(nodep, false); } + void visit(AstDivS* nodep) override { visit_add_sub_replace(nodep, false); } // Widths: out width = lhs width, but upper matters // Signed: Output signed iff LHS signed; unary operator // Unary promote to real - virtual void visit(AstNegate* nodep) override { visit_negate_not(nodep, true); } + void visit(AstNegate* nodep) override { visit_negate_not(nodep, true); } // Unary never real - virtual void visit(AstNot* nodep) override { visit_negate_not(nodep, false); } + void visit(AstNot* nodep) override { visit_negate_not(nodep, false); } // Real: inputs and output real - virtual void visit(AstAddD* nodep) override { visit_real_add_sub(nodep); } - virtual void visit(AstSubD* nodep) override { visit_real_add_sub(nodep); } - virtual void visit(AstDivD* nodep) override { visit_real_add_sub(nodep); } - virtual void visit(AstMulD* nodep) override { visit_real_add_sub(nodep); } - virtual void visit(AstPowD* nodep) override { visit_real_add_sub(nodep); } - virtual void visit(AstNodeSystemBiop* nodep) override { visit_real_add_sub(nodep); } + void visit(AstAddD* nodep) override { visit_real_add_sub(nodep); } + void visit(AstSubD* nodep) override { visit_real_add_sub(nodep); } + void visit(AstDivD* nodep) override { visit_real_add_sub(nodep); } + void visit(AstMulD* nodep) override { visit_real_add_sub(nodep); } + void visit(AstPowD* nodep) override { visit_real_add_sub(nodep); } + void visit(AstNodeSystemBiop* nodep) override { visit_real_add_sub(nodep); } // Real: Output real - virtual void visit(AstNegateD* nodep) override { visit_real_neg_ceil(nodep); } - virtual void visit(AstNodeSystemUniop* nodep) override { visit_real_neg_ceil(nodep); } + void visit(AstNegateD* nodep) override { visit_real_neg_ceil(nodep); } + void visit(AstNodeSystemUniop* nodep) override { visit_real_neg_ceil(nodep); } // Widths: out signed/unsigned width = lhs width, input un|signed - virtual void visit(AstSigned* nodep) override { - visit_signed_unsigned(nodep, VSigning::SIGNED); - } - virtual void visit(AstUnsigned* nodep) override { - visit_signed_unsigned(nodep, VSigning::UNSIGNED); - } + void visit(AstSigned* nodep) override { visit_signed_unsigned(nodep, VSigning::SIGNED); } + void visit(AstUnsigned* nodep) override { visit_signed_unsigned(nodep, VSigning::UNSIGNED); } // Widths: Output width from lhs, rhs<33 bits // Signed: If lhs signed - virtual void visit(AstShiftL* nodep) override { visit_shift(nodep); } - virtual void visit(AstShiftR* nodep) override { visit_shift(nodep); } + void visit(AstShiftL* nodep) override { visit_shift(nodep); } + void visit(AstShiftR* nodep) override { visit_shift(nodep); } // ShiftRS converts to ShiftR, but not vice-versa - virtual void visit(AstShiftRS* nodep) override { visit_shift(nodep); } + void visit(AstShiftRS* nodep) override { visit_shift(nodep); } //======== // Widths: Output real, input integer signed - virtual void visit(AstBitsToRealD* nodep) override { visit_Or_Lu64(nodep); } + void visit(AstBitsToRealD* nodep) override { visit_Or_Lu64(nodep); } // Widths: Output integer signed, input real - virtual void visit(AstRToIS* nodep) override { visit_Os32_Lr(nodep); } - virtual void visit(AstRToIRoundS* nodep) override { + void visit(AstRToIS* nodep) override { visit_Os32_Lr(nodep); } + void visit(AstRToIRoundS* nodep) override { // Only created here, size comes from upper expression if (m_vup->prelim()) { // First stage evaluation iterateCheckReal(nodep, "LHS", nodep->lhsp(), BOTH); @@ -375,11 +371,11 @@ private: } // Widths: Output integer unsigned, input real - virtual void visit(AstRealToBits* nodep) override { visit_Ou64_Lr(nodep); } + void visit(AstRealToBits* nodep) override { visit_Ou64_Lr(nodep); } // Output integer, input string - virtual void visit(AstLenN* nodep) override { visit_Os32_string(nodep); } - virtual void visit(AstPutcN* nodep) override { + void visit(AstLenN* nodep) override { visit_Os32_string(nodep); } + void visit(AstPutcN* nodep) override { // CALLER: str.putc() UASSERT_OBJ(nodep->rhsp() && nodep->thsp(), nodep, "For ternary ops only!"); if (m_vup && m_vup->prelim()) { @@ -391,7 +387,7 @@ private: // AstAssign } } - virtual void visit(AstGetcN* nodep) override { + void visit(AstGetcN* nodep) override { // CALLER: str.getc() UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup && m_vup->prelim()) { @@ -401,7 +397,7 @@ private: nodep->dtypeSetBitSized(8, VSigning::UNSIGNED); } } - virtual void visit(AstGetcRefN* nodep) override { + void visit(AstGetcRefN* nodep) override { // CALLER: str.getc() UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup && m_vup->prelim()) { @@ -411,7 +407,7 @@ private: nodep->dtypeSetBitSized(8, VSigning::UNSIGNED); } } - virtual void visit(AstSubstrN* nodep) override { + void visit(AstSubstrN* nodep) override { // CALLER: str.substr() UASSERT_OBJ(nodep->rhsp() && nodep->thsp(), nodep, "For ternary ops only!"); if (m_vup && m_vup->prelim()) { @@ -422,7 +418,7 @@ private: nodep->dtypeSetString(); } } - virtual void visit(AstCompareNN* nodep) override { + void visit(AstCompareNN* nodep) override { // CALLER: str.compare(), str.icompare() // Widths: 32 bit out UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); @@ -433,7 +429,7 @@ private: nodep->dtypeSetSigned32(); } } - virtual void visit(AstAtoN* nodep) override { + void visit(AstAtoN* nodep) override { // CALLER: str.atobin(), atoi(), atohex(), atooct(), atoreal() // Width: 64bit floating point for atoreal(), 32bit out for the others if (m_vup->prelim()) { @@ -448,13 +444,13 @@ private: } // Widths: Constant, terminal - virtual void visit(AstTime* nodep) override { nodep->dtypeSetUInt64(); } - virtual void visit(AstTimeD* nodep) override { nodep->dtypeSetDouble(); } - virtual void visit(AstScopeName* nodep) override { + void visit(AstTime* nodep) override { nodep->dtypeSetUInt64(); } + void visit(AstTimeD* nodep) override { nodep->dtypeSetDouble(); } + void visit(AstScopeName* nodep) override { nodep->dtypeSetUInt64(); // A pointer, but not that it matters } - virtual void visit(AstNodeCond* nodep) override { + void visit(AstNodeCond* nodep) override { // op = cond ? expr1 : expr2 // See IEEE-2012 11.4.11 and Table 11-21. // LHS is self-determined @@ -496,7 +492,7 @@ private: EXTEND_EXP); } } - virtual void visit(AstConcat* nodep) override { + void visit(AstConcat* nodep) override { // Real: Not allowed (assumed) // Signed: unsigned output, input either (assumed) // IEEE-2012 Table 11-21, and 11.8.1: @@ -579,7 +575,7 @@ private: } } } - virtual void visit(AstConcatN* nodep) override { + void visit(AstConcatN* nodep) override { // String concatenate. // Already did AstConcat simplifications if (m_vup->prelim()) { @@ -595,7 +591,7 @@ private: } } } - virtual void visit(AstDelay* nodep) override { + void visit(AstDelay* nodep) override { if (VN_IS(m_procedurep, Final)) { nodep->v3error("Delays are not legal in final blocks (IEEE 1800-2017 9.2.3)"); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); @@ -611,7 +607,7 @@ private: nodep->v3warn(STMTDLY, "Unsupported: Ignoring delay on this delayed statement."); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } - virtual void visit(AstFork* nodep) override { + void visit(AstFork* nodep) override { if (VN_IS(m_ftaskp, Func) && !nodep->joinType().joinNone()) { nodep->v3error("Only fork .. join_none is legal in functions. " "(IEEE 1800-2017 13.4.4)"); @@ -633,27 +629,27 @@ private: // TBD might support only normal join, if so complain about other join flavors } } - virtual void visit(AstDisableFork* nodep) override { + void visit(AstDisableFork* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: disable fork statements"); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstWaitFork* nodep) override { + void visit(AstWaitFork* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait fork statements"); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstToLowerN* nodep) override { + void visit(AstToLowerN* nodep) override { if (m_vup->prelim()) { iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); nodep->dtypeSetString(); } } - virtual void visit(AstToUpperN* nodep) override { + void visit(AstToUpperN* nodep) override { if (m_vup->prelim()) { iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); nodep->dtypeSetString(); } } - virtual void visit(AstReplicate* nodep) override { + void visit(AstReplicate* nodep) override { // IEEE-2012 Table 11-21: // LHS, RHS is self-determined // width: value(LHS) * width(RHS) @@ -714,7 +710,7 @@ private: } } } - virtual void visit(AstReplicateN* nodep) override { + void visit(AstReplicateN* nodep) override { // Replicate with string if (m_vup->prelim()) { iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); @@ -741,7 +737,7 @@ private: } } } - virtual void visit(AstNodeStream* nodep) override { + void visit(AstNodeStream* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); @@ -774,7 +770,7 @@ private: } } } - virtual void visit(AstRange* nodep) override { + void visit(AstRange* nodep) override { // Real: Not allowed // Signed: unsigned output, input either // Convert all range values to constants @@ -800,7 +796,7 @@ private: } } - virtual void visit(AstSel* nodep) override { + void visit(AstSel* nodep) override { // Signed: always unsigned; Real: Not allowed // LSB is self-determined (IEEE 2012 11.5.1) // We also use SELs to shorten a signed constant etc, in this case they are signed. @@ -907,7 +903,7 @@ private: } } - virtual void visit(AstArraySel* nodep) override { + void visit(AstArraySel* nodep) override { // Signed/Real: Output signed iff LHS signed/real; binary operator // Note by contrast, bit extract selects are unsigned // LSB is self-determined (IEEE 2012 11.5.1) @@ -969,7 +965,7 @@ private: } } - virtual void visit(AstAssocSel* nodep) override { + void visit(AstAssocSel* nodep) override { // Signed/Real: Output type based on array-declared type; binary operator if (m_vup->prelim()) { const AstNodeDType* const fromDtp = nodep->fromp()->dtypep()->skipRefp(); @@ -984,7 +980,7 @@ private: } } - virtual void visit(AstWildcardSel* nodep) override { + void visit(AstWildcardSel* nodep) override { // Signed/Real: Output type based on array-declared type; binary operator if (m_vup->prelim()) { const AstNodeDType* const fromDtp = nodep->fromp()->dtypep()->skipRefp(); @@ -1005,7 +1001,7 @@ private: } } - virtual void visit(AstSliceSel* nodep) override { + void visit(AstSliceSel* nodep) override { // Always creates as output an unpacked array if (m_vup->prelim()) { userIterateAndNext(nodep->fromp(), WidthVP(SELF, BOTH).p()); @@ -1049,7 +1045,7 @@ private: } } - virtual void visit(AstSelBit* nodep) override { + void visit(AstSelBit* nodep) override { // Just a quick check as after V3Param these nodes instead are AstSel's userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel @@ -1063,7 +1059,7 @@ private: } nodep->v3fatalSrc("AstSelBit should disappear after widthSel"); } - virtual void visit(AstSelExtract* nodep) override { + void visit(AstSelExtract* nodep) override { // Just a quick check as after V3Param these nodes instead are AstSel's userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel @@ -1077,7 +1073,7 @@ private: } nodep->v3fatalSrc("AstSelExtract should disappear after widthSel"); } - virtual void visit(AstSelPlus* nodep) override { + void visit(AstSelPlus* nodep) override { userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel @@ -1090,7 +1086,7 @@ private: } nodep->v3fatalSrc("AstSelPlus should disappear after widthSel"); } - virtual void visit(AstSelMinus* nodep) override { + void visit(AstSelMinus* nodep) override { userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel @@ -1104,13 +1100,13 @@ private: nodep->v3fatalSrc("AstSelMinus should disappear after widthSel"); } - virtual void visit(AstExtend* nodep) override { + void visit(AstExtend* nodep) override { // Only created by this process, so we know width from here down is correct. } - virtual void visit(AstExtendS* nodep) override { + void visit(AstExtendS* nodep) override { // Only created by this process, so we know width from here down is correct. } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { // The node got setup with the signed/real state of the node. // However a later operation may have changed the node->signed w/o changing // the number's sign. So we don't: nodep->dtypeChgSigned(nodep->num().isSigned()); @@ -1126,20 +1122,20 @@ private: // We don't size the constant until we commit the widths, as need parameters // to remain unsized, and numbers to remain unsized to avoid backp() warnings } - virtual void visit(AstEmptyQueue* nodep) override { + void visit(AstEmptyQueue* nodep) override { nodep->dtypeSetEmptyQueue(); if (!VN_IS(nodep->backp(), Assign)) { nodep->v3warn(E_UNSUPPORTED, "Unsupported/Illegal: empty queue ('{}') in this context"); } } - virtual void visit(AstFell* nodep) override { + void visit(AstFell* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeSetBit(); } } - virtual void visit(AstPast* nodep) override { + void visit(AstPast* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeFrom(nodep->exprp()); @@ -1163,28 +1159,28 @@ private: } } } - virtual void visit(AstRose* nodep) override { + void visit(AstRose* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeSetBit(); } } - virtual void visit(AstSampled* nodep) override { + void visit(AstSampled* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeFrom(nodep->exprp()); } } - virtual void visit(AstStable* nodep) override { + void visit(AstStable* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeSetBit(); } } - virtual void visit(AstImplication* nodep) override { + void visit(AstImplication* nodep) override { if (m_vup->prelim()) { iterateCheckBool(nodep, "LHS", nodep->lhsp(), BOTH); iterateCheckBool(nodep, "RHS", nodep->rhsp(), BOTH); @@ -1192,7 +1188,7 @@ private: } } - virtual void visit(AstRand* nodep) override { + void visit(AstRand* nodep) override { if (m_vup->prelim()) { if (nodep->urandom()) { nodep->dtypeSetUInt32(); // Says the spec @@ -1202,7 +1198,7 @@ private: if (nodep->seedp()) iterateCheckSigned32(nodep, "seed", nodep->seedp(), BOTH); } } - virtual void visit(AstURandomRange* nodep) override { + void visit(AstURandomRange* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetUInt32(); // Says the spec AstNodeDType* const expDTypep = nodep->findUInt32DType(); @@ -1212,7 +1208,7 @@ private: iterateCheck(nodep, "RHS", nodep->rhsp(), SELF, FINAL, expDTypep, EXTEND_EXP); } } - virtual void visit(AstUnbounded* nodep) override { + void visit(AstUnbounded* nodep) override { nodep->dtypeSetSigned32(); // Used in int context if (VN_IS(nodep->backp(), IsUnbounded)) return; // Ok, leave if (VN_IS(nodep->backp(), BracketArrayDType)) return; // Ok, leave @@ -1230,13 +1226,13 @@ private: } nodep->v3warn(E_UNSUPPORTED, "Unsupported/illegal unbounded ('$') in this context."); } - virtual void visit(AstIsUnbounded* nodep) override { + void visit(AstIsUnbounded* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); nodep->dtypeSetBit(); } } - virtual void visit(AstUCFunc* nodep) override { + void visit(AstUCFunc* nodep) override { // Give it the size the user wants. if (m_vup && m_vup->prelim()) { nodep->dtypeSetLogicUnsized(32, 1, VSigning::UNSIGNED); // We don't care @@ -1251,10 +1247,10 @@ private: } } } - virtual void visit(AstCLog2* nodep) override { + void visit(AstCLog2* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); } } - virtual void visit(AstPow* nodep) override { + void visit(AstPow* nodep) override { // Pow is special, output sign only depends on LHS sign, but // function result depends on both signs // RHS is self-determined (IEEE) @@ -1298,25 +1294,25 @@ private: } } } - virtual void visit(AstPowSU* nodep) override { + void visit(AstPowSU* nodep) override { // POWSU/SS/US only created here, dtype already determined, so // nothing to do in this function userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->rhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstPowSS* nodep) override { + void visit(AstPowSS* nodep) override { // POWSU/SS/US only created here, dtype already determined, so // nothing to do in this function userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->rhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstPowUS* nodep) override { + void visit(AstPowUS* nodep) override { // POWSU/SS/US only created here, dtype already determined, so // nothing to do in this function userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->rhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstCountBits* nodep) override { + void visit(AstCountBits* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); @@ -1328,7 +1324,7 @@ private: VSigning::UNSIGNED); // Spec doesn't indicate if an integer } } - virtual void visit(AstCountOnes* nodep) override { + void visit(AstCountOnes* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); // If it's a 32 bit number, we need a 6 bit number as we need to return '32'. @@ -1337,12 +1333,12 @@ private: VSigning::UNSIGNED); // Spec doesn't indicate if an integer } } - virtual void visit(AstCvtPackString* nodep) override { + void visit(AstCvtPackString* nodep) override { // Opaque returns, so arbitrary userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); // Type set in constructor } - virtual void visit(AstTimeImport* nodep) override { + void visit(AstTimeImport* nodep) override { // LHS is a real number in seconds // Need to round to time units and precision userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); @@ -1357,14 +1353,14 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstEventControl* nodep) override { + void visit(AstEventControl* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: event control statement in this location\n" << nodep->warnMore() << "... Suggest have one event control statement " << "per procedure, at the top of the procedure"); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstAttrOf* nodep) override { + void visit(AstAttrOf* nodep) override { VL_RESTORER(m_attrp); m_attrp = nodep; userIterateAndNext(nodep->fromp(), WidthVP(SELF, BOTH).p()); @@ -1497,16 +1493,16 @@ private: } } } - virtual void visit(AstPull* nodep) override { + void visit(AstPull* nodep) override { // May have select underneath, let seek natural size userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstText* nodep) override { + void visit(AstText* nodep) override { // Only used in CStmts which don't care.... } // DTYPES - virtual void visit(AstNodeArrayDType* nodep) override { + void visit(AstNodeArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed if (nodep->subDTypep() == nodep->basicp()) { // Innermost dimension @@ -1537,7 +1533,7 @@ private: } UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstAssocArrayDType* nodep) override { + void visit(AstAssocArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1545,7 +1541,7 @@ private: nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstBracketArrayDType* nodep) override { + void visit(AstBracketArrayDType* nodep) override { // Type inserted only because parser didn't know elementsp() type // Resolve elementsp's type userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); @@ -1574,14 +1570,14 @@ private: // visit VL_DO_DANGLING(userIterate(newp, nullptr), newp); } - virtual void visit(AstDynArrayDType* nodep) override { + void visit(AstDynArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstQueueDType* nodep) override { + void visit(AstQueueDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1591,12 +1587,12 @@ private: } UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstVoidDType* nodep) override { + void visit(AstVoidDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed nodep->dtypep(nodep); UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstUnsizedArrayDType* nodep) override { + void visit(AstUnsizedArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1604,7 +1600,7 @@ private: nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstWildcardArrayDType* nodep) override { + void visit(AstWildcardArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1612,7 +1608,7 @@ private: nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstBasicDType* nodep) override { + void visit(AstBasicDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed if (nodep->generic()) return; // Already perfect if (nodep->rangep()) { @@ -1635,7 +1631,7 @@ private: // dtype Instead for now doing this in V3WidthCommit UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstConstDType* nodep) override { + void visit(AstConstDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1644,7 +1640,7 @@ private: nodep->widthFromSub(nodep->subDTypep()); UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstRefDType* nodep) override { + void visit(AstRefDType* nodep) override { if (nodep->doingWidth()) { // Early exit if have circular parameter definition nodep->v3error("Typedef's type is circular: " << nodep->prettyName()); nodep->dtypeSetBit(); @@ -1682,7 +1678,7 @@ private: UINFO(4, "dtWidthed " << nodep << endl); nodep->doingWidth(false); } - virtual void visit(AstTypedef* nodep) override { + void visit(AstTypedef* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed if (auto* const refp = checkRefToTypedefRecurse(nodep, nodep)) { nodep->v3error("Typedef has self-reference: " << nodep->prettyNameQ() << '\n' @@ -1698,13 +1694,13 @@ private: nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); userIterateChildren(nodep, nullptr); } - virtual void visit(AstParamTypeDType* nodep) override { + void visit(AstParamTypeDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); userIterateChildren(nodep, nullptr); nodep->widthFromSub(nodep->subDTypep()); } - virtual void visit(AstCastDynamic* nodep) override { + void visit(AstCastDynamic* nodep) override { nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); AstNodeDType* const toDtp = nodep->top()->dtypep()->skipRefToEnump(); @@ -1779,7 +1775,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); userIterate(newp, m_vup); } - virtual void visit(AstCastParse* nodep) override { + void visit(AstCastParse* nodep) override { // nodep->dtp could be data type, or a primary_constant // Don't iterate lhsp, will deal with that once convert the type V3Const::constifyParamsEdit(nodep->dtp()); // itemp may change @@ -1796,7 +1792,7 @@ private: nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); } } - virtual void visit(AstCast* nodep) override { + void visit(AstCast* nodep) override { nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); if (m_vup->prelim()) { // if (debug()) nodep->dumpTree(cout, " CastPre: "); @@ -1883,7 +1879,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstCastSize* nodep) override { + void visit(AstCastSize* nodep) override { // IEEE: Signedness of result is same as self-determined signedness // However, the result is same as BITSEL, so we do not sign extend the LHS UASSERT_OBJ(VN_IS(nodep->rhsp(), Const), nodep, "Unsupported: Non-const cast of size"); @@ -1943,7 +1939,7 @@ private: VL_DANGLING(underp); } } - virtual void visit(AstVar* nodep) override { + void visit(AstVar* nodep) override { // if (debug()) nodep->dumpTree(cout, " InitPre: "); // Must have deterministic constant width // We can't skip this step when width()!=0, as creating a AstVar @@ -2055,7 +2051,7 @@ private: nodep->didWidth(true); nodep->doingWidth(false); } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { if (nodep->didWidth()) return; if (!nodep->varp()) { if (m_paramsOnly && VN_IS(nodep, VarXRef)) { @@ -2092,7 +2088,7 @@ private: nodep->didWidth(true); } - virtual void visit(AstEnumDType* nodep) override { + void visit(AstEnumDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5, " ENUMDTYPE " << nodep << endl); nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -2156,7 +2152,7 @@ private: num.opAdd(one, constp->num()); } } - virtual void visit(AstEnumItem* nodep) override { + void visit(AstEnumItem* nodep) override { UINFO(5, " ENUMITEM " << nodep << endl); AstNodeDType* const vdtypep = m_vup->dtypep(); UASSERT_OBJ(vdtypep, nodep, "ENUMITEM not under ENUM"); @@ -2170,7 +2166,7 @@ private: EXTEND_EXP); } } - virtual void visit(AstEnumItemRef* nodep) override { + void visit(AstEnumItemRef* nodep) override { if (!nodep->itemp()->didWidth()) { // We need to do the whole enum en-mass AstNode* enump = nodep->itemp(); @@ -2183,7 +2179,7 @@ private: } nodep->dtypeFrom(nodep->itemp()); } - virtual void visit(AstConsAssoc* nodep) override { + void visit(AstConsAssoc* nodep) override { // Type computed when constructed here auto* const vdtypep = VN_AS(m_vup->dtypep()->skipRefp(), AssocArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsAssoc requires assoc upper parent data type"); @@ -2195,7 +2191,7 @@ private: } } } - virtual void visit(AstSetAssoc* nodep) override { + void visit(AstSetAssoc* nodep) override { // Type computed when constructed here auto* const vdtypep = VN_AS(m_vup->dtypep()->skipRefp(), AssocArrayDType); UASSERT_OBJ(vdtypep, nodep, "SetsAssoc requires assoc upper parent data type"); @@ -2208,7 +2204,7 @@ private: EXTEND_EXP); } } - virtual void visit(AstConsWildcard* nodep) override { + void visit(AstConsWildcard* nodep) override { // Type computed when constructed here auto* const vdtypep = VN_AS(m_vup->dtypep()->skipRefp(), WildcardArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsWildcard requires wildcard upper parent data type"); @@ -2220,7 +2216,7 @@ private: } } } - virtual void visit(AstSetWildcard* nodep) override { + void visit(AstSetWildcard* nodep) override { // Type computed when constructed here auto* const vdtypep = VN_AS(m_vup->dtypep()->skipRefp(), WildcardArrayDType); UASSERT_OBJ(vdtypep, nodep, "SetWildcard requires wildcard upper parent data type"); @@ -2233,7 +2229,7 @@ private: EXTEND_EXP); } } - virtual void visit(AstConsDynArray* nodep) override { + void visit(AstConsDynArray* nodep) override { // Type computed when constructed here AstDynArrayDType* const vdtypep = VN_AS(m_vup->dtypep()->skipRefp(), DynArrayDType); UASSERT_OBJ(vdtypep, nodep, "ConsDynArray requires queue upper parent data type"); @@ -2265,7 +2261,7 @@ private: nodep->dtypeFrom(vdtypep); } } - virtual void visit(AstConsQueue* nodep) override { + void visit(AstConsQueue* nodep) override { // Type computed when constructed here AstQueueDType* const vdtypep = VN_AS(m_vup->dtypep()->skipRefp(), QueueDType); UASSERT_OBJ(vdtypep, nodep, "ConsQueue requires queue upper parent data type"); @@ -2297,10 +2293,10 @@ private: nodep->dtypeFrom(vdtypep); } } - virtual void visit(AstInitItem* nodep) override { // + void visit(AstInitItem* nodep) override { // userIterateChildren(nodep, m_vup); } - virtual void visit(AstInitArray* nodep) override { + void visit(AstInitArray* nodep) override { // InitArray has type of the array; children are array values if (m_vup->prelim()) { // First stage evaluation AstNodeDType* const vdtypep = m_vup->dtypeNullp(); @@ -2315,7 +2311,7 @@ private: } } } - virtual void visit(AstInside* nodep) override { + void visit(AstInside* nodep) override { userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // Prelim may cause the node to get replaced @@ -2374,14 +2370,14 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstInsideRange* nodep) override { + void visit(AstInsideRange* nodep) override { // Just do each side; AstInside will rip these nodes out later userIterateAndNext(nodep->lhsp(), m_vup); userIterateAndNext(nodep->rhsp(), m_vup); nodep->dtypeFrom(nodep->lhsp()); } - virtual void visit(AstIfaceRefDType* nodep) override { + void visit(AstIfaceRefDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5, " IFACEREF " << nodep << endl); userIterateChildren(nodep, m_vup); @@ -2389,7 +2385,7 @@ private: nodep->widthForce(1, 1); // Not really relevant UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5, " NODECLASS " << nodep << endl); // if (debug() >= 9) nodep->dumpTree("-class-in--"); @@ -2424,7 +2420,7 @@ private: nodep->widthForce(width, width); // Signing stays as-is, as parsed from declaration // if (debug() >= 9) nodep->dumpTree("-class-out-"); } - virtual void visit(AstClass* nodep) override { + void visit(AstClass* nodep) override { if (nodep->didWidthAndSet()) return; // Must do extends first, as we may in functions under this class // start following a tree of extends that takes us to other classes @@ -2432,37 +2428,37 @@ private: userIterateChildren(nodep, nullptr); // First size all members nodep->repairCache(); } - virtual void visit(AstClassRefDType* nodep) override { + void visit(AstClassRefDType* nodep) override { if (nodep->didWidthAndSet()) return; // TODO this maybe eventually required to properly resolve members, // though causes problems with t_class_forward.v, so for now avoided // userIterateChildren(nodep->classp(), nullptr); } - virtual void visit(AstClassOrPackageRef* nodep) override { + void visit(AstClassOrPackageRef* nodep) override { if (nodep->didWidthAndSet()) return; userIterateChildren(nodep, nullptr); } - virtual void visit(AstDot* nodep) override { + void visit(AstDot* nodep) override { // We can only reach this from constify called during V3Param (so before linkDotParam) // ... #(Cls#(...)::...) ... // ^^~~~ this is our DOT nodep->v3warn(E_UNSUPPORTED, "dotted expressions in parameters\n" << nodep->warnMore() << "... Suggest use a typedef"); } - virtual void visit(AstClassExtends* nodep) override { + void visit(AstClassExtends* nodep) override { if (nodep->didWidthAndSet()) return; if (VN_IS(nodep->childDTypep(), ClassRefDType)) { nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->childDTypep())); } } - virtual void visit(AstMemberDType* nodep) override { + void visit(AstMemberDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); // The member itself, not subDtype nodep->widthFromSub(nodep->subDTypep()); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { UINFO(5, " MEMBERSEL " << nodep << endl); if (debug() >= 9) nodep->dumpTree("-mbs-in: "); userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); @@ -2565,12 +2561,12 @@ private: return false; } - virtual void visit(AstCMethodHard* nodep) override { + void visit(AstCMethodHard* nodep) override { // Never created before V3Width, so no need to redo it UASSERT_OBJ(nodep->dtypep(), nodep, "CMETHODCALLs should have already been sized"); } - virtual void visit(AstMethodCall* nodep) override { + void visit(AstMethodCall* nodep) override { UINFO(5, " METHODCALL " << nodep << endl); if (nodep->didWidth()) return; if (debug() >= 9) nodep->dumpTree("-mts-in: "); @@ -3418,7 +3414,7 @@ private: } } - virtual void visit(AstNew* nodep) override { + void visit(AstNew* nodep) override { if (nodep->didWidth()) return; AstClassRefDType* const refp = m_vup ? VN_CAST(m_vup->dtypeNullSkipRefp(), ClassRefDType) : nullptr; @@ -3444,7 +3440,7 @@ private: userIterate(nodep->taskp(), nullptr); processFTaskRefArgs(nodep); } - virtual void visit(AstNewCopy* nodep) override { + void visit(AstNewCopy* nodep) override { if (nodep->didWidthAndSet()) return; AstClassRefDType* const refp = VN_CAST(m_vup->dtypeNullSkipRefp(), ClassRefDType); if (!refp) { // e.g. int a = new; @@ -3459,7 +3455,7 @@ private: << nodep->rhsp()->dtypep()->prettyTypeName() << "'"); } } - virtual void visit(AstNewDynamic* nodep) override { + void visit(AstNewDynamic* nodep) override { if (nodep->didWidthAndSet()) return; AstDynArrayDType* const adtypep = VN_CAST(m_vup->dtypeNullSkipRefp(), DynArrayDType); if (!adtypep) { // e.g. int a = new; @@ -3483,7 +3479,7 @@ private: } } - virtual void visit(AstPattern* nodep) override { + void visit(AstPattern* nodep) override { if (nodep->didWidthAndSet()) return; UINFO(9, "PATTERN " << nodep << endl); if (nodep->childDTypep()) { // data_type '{ pattern } @@ -3919,7 +3915,7 @@ private: return valuep; } - virtual void visit(AstPatMember* nodep) override { + void visit(AstPatMember* nodep) override { AstNodeDType* const vdtypep = m_vup->dtypeNullp(); UASSERT_OBJ(vdtypep, nodep, "Pattern member type not assigned by AstPattern visitor"); nodep->dtypep(vdtypep); @@ -3953,7 +3949,7 @@ private: return times; } - virtual void visit(AstPropClocked* nodep) override { + void visit(AstPropClocked* nodep) override { if (m_vup->prelim()) { // First stage evaluation iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); userIterateAndNext(nodep->sensesp(), nullptr); @@ -3968,7 +3964,7 @@ private: //-------------------- // Top levels - virtual void visit(AstNodeCase* nodep) override { + void visit(AstNodeCase* nodep) override { // IEEE-2012 12.5: // Width: MAX(expr, all items) // Signed: Only if expr, and all items signed @@ -4014,7 +4010,7 @@ private: } } } - virtual void visit(AstNodeFor* nodep) override { + void visit(AstNodeFor* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->initsp(), nullptr); iterateCheckBool(nodep, "For Test Condition", nodep->condp(), @@ -4022,12 +4018,12 @@ private: if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), nullptr); userIterateAndNext(nodep->incsp(), nullptr); } - virtual void visit(AstRepeat* nodep) override { + void visit(AstRepeat* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->countp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->bodysp(), nullptr); } - virtual void visit(AstWhile* nodep) override { + void visit(AstWhile* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->precondsp(), nullptr); iterateCheckBool(nodep, "For Test Condition", nodep->condp(), @@ -4035,7 +4031,7 @@ private: userIterateAndNext(nodep->bodysp(), nullptr); userIterateAndNext(nodep->incsp(), nullptr); } - virtual void visit(AstNodeIf* nodep) override { + void visit(AstNodeIf* nodep) override { assertAtStatement(nodep); // if (debug()) nodep->dumpTree(cout, " IfPre: "); if (!VN_IS(nodep, GenIf)) { // for m_paramsOnly @@ -4045,13 +4041,13 @@ private: iterateCheckBool(nodep, "If", nodep->condp(), BOTH); // it's like an if() condition. // if (debug()) nodep->dumpTree(cout, " IfOut: "); } - virtual void visit(AstExprStmt* nodep) override { + void visit(AstExprStmt* nodep) override { userIterateAndNext(nodep->stmtsp(), nullptr); // expected result is same as parent's expected result userIterateAndNext(nodep->resultp(), m_vup); nodep->dtypeFrom(nodep->resultp()); } - virtual void visit(AstForeach* nodep) override { + void visit(AstForeach* nodep) override { const AstSelLoopVars* const loopsp = VN_CAST(nodep->arrayp(), SelLoopVars); UASSERT_OBJ(loopsp, nodep, "No loop variables under foreach"); // if (debug()) nodep->dumpTree(cout, "-foreach-old: "); @@ -4214,7 +4210,7 @@ private: return newp; } - virtual void visit(AstNodeAssign* nodep) override { + void visit(AstNodeAssign* nodep) override { // IEEE-2012 10.7, 11.8.2, 11.8.3, 11.5: (Careful of 11.8.1 which is // only one step; final dtype depends on assign LHS.) // Determine RHS type width and signing @@ -4288,13 +4284,13 @@ private: } } - virtual void visit(AstRelease* nodep) override { + void visit(AstRelease* nodep) override { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); UASSERT_OBJ(nodep->lhsp()->dtypep(), nodep, "How can LValue be untyped?"); UASSERT_OBJ(nodep->lhsp()->dtypep()->widthSized(), nodep, "How can LValue be unsized?"); } - virtual void visit(AstSFormatF* nodep) override { + void visit(AstSFormatF* nodep) override { // Excludes NodeDisplay, see below if (m_vup && !m_vup->prelim()) return; // Can be called as statement or function // Just let all arguments seek their natural sizes @@ -4427,13 +4423,13 @@ private: nodep->text(newFormat); UINFO(9, " Display out " << nodep->text() << endl); } - virtual void visit(AstDisplay* nodep) override { + void visit(AstDisplay* nodep) override { assertAtStatement(nodep); if (nodep->filep()) iterateCheckFileDesc(nodep, nodep->filep(), BOTH); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstElabDisplay* nodep) override { + void visit(AstElabDisplay* nodep) override { assertAtStatement(nodep); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); @@ -4451,28 +4447,28 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - virtual void visit(AstDumpCtl* nodep) override { + void visit(AstDumpCtl* nodep) override { assertAtStatement(nodep); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstFOpen* nodep) override { + void visit(AstFOpen* nodep) override { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) assertAtStatement(nodep); iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->modep(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstFOpenMcd* nodep) override { + void visit(AstFOpenMcd* nodep) override { assertAtStatement(nodep); iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstFClose* nodep) override { + void visit(AstFClose* nodep) override { assertAtStatement(nodep); iterateCheckFileDesc(nodep, nodep->filep(), BOTH); } - virtual void visit(AstFError* nodep) override { + void visit(AstFError* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); // We only support string types, not packed array @@ -4480,51 +4476,51 @@ private: nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFEof* nodep) override { + void visit(AstFEof* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFFlush* nodep) override { + void visit(AstFFlush* nodep) override { assertAtStatement(nodep); if (nodep->filep()) iterateCheckFileDesc(nodep, nodep->filep(), BOTH); } - virtual void visit(AstFRewind* nodep) override { + void visit(AstFRewind* nodep) override { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } - virtual void visit(AstFTell* nodep) override { + void visit(AstFTell* nodep) override { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } - virtual void visit(AstFSeek* nodep) override { + void visit(AstFSeek* nodep) override { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); iterateCheckSigned32(nodep, "$fseek offset", nodep->offset(), BOTH); iterateCheckSigned32(nodep, "$fseek operation", nodep->operation(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } - virtual void visit(AstFGetC* nodep) override { + void visit(AstFGetC* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 8, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFGetS* nodep) override { + void visit(AstFGetS* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->strgp(), WidthVP(SELF, BOTH).p()); } } - virtual void visit(AstFUngetC* nodep) override { + void visit(AstFUngetC* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); iterateCheckSigned32(nodep, "$fungetc character", nodep->charp(), BOTH); nodep->dtypeSetLogicUnsized(32, 8, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFRead* nodep) override { + void visit(AstFRead* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return userIterateAndNext(nodep->memp(), WidthVP(SELF, BOTH).p()); @@ -4537,38 +4533,38 @@ private: } } } - virtual void visit(AstFScanF* nodep) override { + void visit(AstFScanF* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->exprsp(), WidthVP(SELF, BOTH).p()); } } - virtual void visit(AstSScanF* nodep) override { + void visit(AstSScanF* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return userIterateAndNext(nodep->fromp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->exprsp(), WidthVP(SELF, BOTH).p()); } } - virtual void visit(AstSysIgnore* nodep) override { + void visit(AstSysIgnore* nodep) override { userIterateAndNext(nodep->exprsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstSystemF* nodep) override { + void visit(AstSystemF* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); nodep->dtypeSetSigned32(); // Spec says integer return } } - virtual void visit(AstSysFuncAsTask* nodep) override { + void visit(AstSysFuncAsTask* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstSystemT* nodep) override { + void visit(AstSystemT* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstNodeReadWriteMem* nodep) override { + void visit(AstNodeReadWriteMem* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->memp(), WidthVP(SELF, BOTH).p()); @@ -4600,53 +4596,53 @@ private: userIterateAndNext(nodep->lsbp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->msbp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstTestPlusArgs* nodep) override { + void visit(AstTestPlusArgs* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->searchp(), WidthVP{SELF, BOTH}.p()); nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstValuePlusArgs* nodep) override { + void visit(AstValuePlusArgs* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->searchp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->outp(), WidthVP(SELF, BOTH).p()); nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstTimeFormat* nodep) override { + void visit(AstTimeFormat* nodep) override { assertAtStatement(nodep); iterateCheckSigned32(nodep, "units", nodep->unitsp(), BOTH); iterateCheckSigned32(nodep, "precision", nodep->precisionp(), BOTH); iterateCheckString(nodep, "suffix", nodep->suffixp(), BOTH); iterateCheckSigned32(nodep, "width", nodep->widthp(), BOTH); } - virtual void visit(AstUCStmt* nodep) override { + void visit(AstUCStmt* nodep) override { // Just let all arguments seek their natural sizes assertAtStatement(nodep); userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstAssert* nodep) override { + void visit(AstAssert* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. userIterateAndNext(nodep->passsp(), nullptr); userIterateAndNext(nodep->failsp(), nullptr); } - virtual void visit(AstAssertIntrinsic* nodep) override { + void visit(AstAssertIntrinsic* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. userIterateAndNext(nodep->passsp(), nullptr); userIterateAndNext(nodep->failsp(), nullptr); } - virtual void visit(AstCover* nodep) override { + void visit(AstCover* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. userIterateAndNext(nodep->passsp(), nullptr); } - virtual void visit(AstRestrict* nodep) override { + void visit(AstRestrict* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. } - virtual void visit(AstPin* nodep) override { + void visit(AstPin* nodep) override { // if (debug()) nodep->dumpTree(cout, "- PinPre: "); // TOP LEVEL NODE if (nodep->modVarp() && nodep->modVarp()->isGParam()) { @@ -4771,7 +4767,7 @@ private: } // if (debug()) nodep->dumpTree(cout, "- PinOut: "); } - virtual void visit(AstCell* nodep) override { + void visit(AstCell* nodep) override { VL_RESTORER(m_cellp); m_cellp = nodep; if (!m_paramsOnly) { @@ -4788,7 +4784,7 @@ private: } userIterateAndNext(nodep->paramsp(), nullptr); } - virtual void visit(AstGatePin* nodep) override { + void visit(AstGatePin* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); @@ -4812,7 +4808,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { // Grab width from the output variable (if it's a function) if (nodep->didWidth()) return; if (nodep->doingWidth()) { @@ -4854,7 +4850,7 @@ private: // func } } - virtual void visit(AstReturn* nodep) override { + void visit(AstReturn* nodep) override { // IEEE: Assignment-like context assertAtStatement(nodep); if (!m_funcp) { @@ -4872,7 +4868,7 @@ private: } } - virtual void visit(AstFuncRef* nodep) override { + void visit(AstFuncRef* nodep) override { visit(static_cast(nodep)); nodep->dtypeFrom(nodep->taskp()); // if (debug()) nodep->dumpTree(cout, " FuncOut: "); @@ -5042,7 +5038,7 @@ private: } } } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign // Function hasn't been widthed, so make it so. UINFO(5, " FTASKREF " << nodep << endl); @@ -5053,13 +5049,13 @@ private: processFTaskRefArgs(nodep); nodep->didWidth(true); } - virtual void visit(AstNodeProcedure* nodep) override { + void visit(AstNodeProcedure* nodep) override { assertAtStatement(nodep); m_procedurep = nodep; userIterateChildren(nodep, nullptr); m_procedurep = nullptr; } - virtual void visit(AstWith* nodep) override { + void visit(AstWith* nodep) override { // Should otherwise be underneath a method call AstNodeDType* const vdtypep = m_vup->dtypeNullSkipRefp(); { @@ -5077,7 +5073,7 @@ private: nodep->dtypep()); } } - virtual void visit(AstLambdaArgRef* nodep) override { + void visit(AstLambdaArgRef* nodep) override { UASSERT_OBJ(m_withp, nodep, "LambdaArgRef not underneath 'with' lambda"); if (nodep->index()) { nodep->dtypeFrom(m_withp->indexArgRefp()); @@ -5085,21 +5081,21 @@ private: nodep->dtypeFrom(m_withp->valueArgRefp()); } } - virtual void visit(AstNetlist* nodep) override { + void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. That's faster userIterateChildrenBackwards(nodep, nullptr); } //-------------------- // Default - virtual void visit(AstNodeMath* nodep) override { + void visit(AstNodeMath* nodep) override { if (!nodep->didWidth()) { nodep->v3fatalSrc( "Visit function missing? Widthed function missing for math node: " << nodep); } userIterateChildren(nodep, nullptr); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { // Default: Just iterate UASSERT_OBJ(!m_vup, nodep, "Visit function missing? Widthed expectation for this node: " << nodep); @@ -5121,7 +5117,7 @@ private: iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP); } } - virtual void visit(AstIToRD* nodep) override { + void visit(AstIToRD* nodep) override { // Real: Output real // LHS presumed self-determined, then coerced to real if (m_vup->prelim()) { // First stage evaluation @@ -5135,7 +5131,7 @@ private: } } } - virtual void visit(AstISToRD* nodep) override { + void visit(AstISToRD* nodep) override { // Real: Output real // LHS presumed self-determined, then coerced to real if (m_vup->prelim()) { // First stage evaluation @@ -6726,7 +6722,7 @@ public: AstNode* mainAcceptEdit(AstNode* nodep) { return userIterateSubtreeReturnEdits(nodep, WidthVP(SELF, BOTH).p()); } - virtual ~WidthVisitor() override = default; + ~WidthVisitor() override = default; }; //###################################################################### diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 5b784387d..fb883a256 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -45,18 +45,18 @@ private: } // VISITORS - virtual void visit(AstSigned* nodep) override { + void visit(AstSigned* nodep) override { VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); } - virtual void visit(AstUnsigned* nodep) override { + void visit(AstUnsigned* nodep) override { VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); } - virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS WidthRemoveVisitor() = default; - virtual ~WidthRemoveVisitor() override = default; + ~WidthRemoveVisitor() override = default; AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } }; @@ -151,7 +151,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) override { + void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); { m_modp = nodep; @@ -159,7 +159,7 @@ private: editDType(nodep); } } - virtual void visit(AstConst* nodep) override { + void visit(AstConst* nodep) override { UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); iterate(nodep->dtypep()); // Do datatype first if (AstConst* const newp = newIfConstCommitSize(nodep)) { @@ -172,15 +172,15 @@ private: } editDType(nodep); } - virtual void visit(AstNodeDType* nodep) override { // + void visit(AstNodeDType* nodep) override { // visitIterateNodeDType(nodep); } - virtual void visit(AstNodeUOrStructDType* nodep) override { + void visit(AstNodeUOrStructDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); nodep->clearCache(); } - virtual void visit(AstParamTypeDType* nodep) override { + void visit(AstParamTypeDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); // Move to type table as all dtype pointers must resolve there @@ -199,7 +199,7 @@ private: nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep())); nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p())); } - virtual void visit(AstNodeFTask* nodep) override { + void visit(AstNodeFTask* nodep) override { iterateChildren(nodep); editDType(nodep); if (nodep->classMethod() && nodep->pureVirtual() && VN_IS(m_modp, Class) @@ -208,28 +208,28 @@ private: "Illegal to have 'pure virtual' in non-virtual class (IEEE 1800-2017 8.21)"); } } - virtual void visit(AstNodeVarRef* nodep) override { + void visit(AstNodeVarRef* nodep) override { iterateChildren(nodep); editDType(nodep); classEncapCheck(nodep, nodep->varp(), VN_CAST(nodep->classOrPackagep(), Class)); } - virtual void visit(AstNodeFTaskRef* nodep) override { + void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); editDType(nodep); classEncapCheck(nodep, nodep->taskp(), VN_CAST(nodep->classOrPackagep(), Class)); } - virtual void visit(AstMemberSel* nodep) override { + void visit(AstMemberSel* nodep) override { iterateChildren(nodep); editDType(nodep); if (auto* const classrefp = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType)) { classEncapCheck(nodep, nodep->varp(), classrefp->classp()); } // else might be struct, etc } - virtual void visit(AstNodePreSel* nodep) override { // LCOV_EXCL_LINE + void visit(AstNodePreSel* nodep) override { // LCOV_EXCL_LINE // This check could go anywhere after V3Param nodep->v3fatalSrc("Presels should have been removed before this point"); } - virtual void visit(AstNode* nodep) override { + void visit(AstNode* nodep) override { iterateChildren(nodep); editDType(nodep); } @@ -243,7 +243,7 @@ public: // Don't want to repairCache, as all needed nodes have been added back in // a repair would prevent dead nodes from being detected } - virtual ~WidthCommitVisitor() override = default; + ~WidthCommitVisitor() override = default; }; //###################################################################### diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 19392df58..222f69c5b 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -202,7 +202,7 @@ private: // VISITORS // If adding new visitors, ensure V3Width's visit(TYPE) calls into here - virtual void visit(AstSelBit* nodep) override { + void visit(AstSelBit* nodep) override { // Select of a non-width specified part of an array, i.e. "array[2]" // This select style has a lsb and msb (no user specified width) UINFO(6, "SELBIT " << nodep << endl); @@ -330,7 +330,7 @@ private: } if (!rhsp->backp()) VL_DO_DANGLING(pushDeletep(rhsp), rhsp); } - virtual void visit(AstSelExtract* nodep) override { + void visit(AstSelExtract* nodep) override { // Select of a range specified part of an array, i.e. "array[2:3]" // SELEXTRACT(from,msb,lsb) -> SEL(from, lsb, 1+msb-lsb) // This select style has a (msb or lsb) and width @@ -584,13 +584,13 @@ private: if (!rhsp->backp()) VL_DO_DANGLING(pushDeletep(rhsp), rhsp); if (!widthp->backp()) VL_DO_DANGLING(pushDeletep(widthp), widthp); } - virtual void visit(AstSelPlus* nodep) override { replaceSelPlusMinus(nodep); } - virtual void visit(AstSelMinus* nodep) override { replaceSelPlusMinus(nodep); } + void visit(AstSelPlus* nodep) override { replaceSelPlusMinus(nodep); } + void visit(AstSelMinus* nodep) override { replaceSelPlusMinus(nodep); } // If adding new visitors, ensure V3Width's visit(TYPE) calls into here //-------------------- // Default - virtual void visit(AstNode* nodep) override { // LCOV_EXCL_LINE + void visit(AstNode* nodep) override { // LCOV_EXCL_LINE // See notes above; we never iterate nodep->v3fatalSrc("Shouldn't iterate in V3WidthSel"); } @@ -598,7 +598,7 @@ private: public: // CONSTRUCTORS WidthSelVisitor() = default; - virtual ~WidthSelVisitor() override = default; + ~WidthSelVisitor() override = default; AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } }; diff --git a/src/astgen b/src/astgen index 02d8d06d6..98d0750fe 100755 --- a/src/astgen +++ b/src/astgen @@ -468,7 +468,7 @@ class Cpt: if len(out_for_type_sc) > 0: # Short-circuited types self.print( " // Generated by astgen with short-circuiting\n" + - " virtual void visit(Ast" + node.name + + " void visit(Ast" + node.name + "* nodep) override {\n" + " iterateAndNextNull(nodep->lhsp());\n" + "".join(out_for_type_sc)) @@ -481,10 +481,12 @@ class Cpt: elif len(out_for_type) > 0: # Other types with something to print skip = node.name in self.tree_skip_visit gen = "Gen" if skip else "" + virtual = "virtual " if skip else "" override = "" if skip else " override" self.print( - " // Generated by astgen\n" + " virtual void visit" + - gen + "(Ast" + node.name + "* nodep)" + override + " {\n" + + " // Generated by astgen\n" + " " + virtual + + "void visit" + gen + "(Ast" + node.name + "* nodep)" + + override + " {\n" + ("" if skip else " iterateChildren(nodep);\n") + ''.join(out_for_type) + " }\n") @@ -751,8 +753,8 @@ def write_macros(filename): if node.isLeaf: emitBlock('''\ - virtual void accept(VNVisitor& v) override {{ v.visit(this); }} - virtual AstNode* clone() override {{ return new Ast{t}(*this); }} + void accept(VNVisitor& v) override {{ v.visit(this); }} + AstNode* clone() override {{ return new Ast{t}(*this); }} ''', t=node.name) diff --git a/test_regress/t/t_dist_cppstyle.pl b/test_regress/t/t_dist_cppstyle.pl new file mode 100755 index 000000000..a54fef2dd --- /dev/null +++ b/test_regress/t/t_dist_cppstyle.pl @@ -0,0 +1,66 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Primitive C++ style checker +# +# Copyright 2022 by Geza Lore. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(dist => 1); + +my $root = ".."; + +### Must trim output before and after our file list +my %files = %{get_source_files($root)}; + +foreach my $file (sort keys %files) { + my $filename = "$root/$file"; + next if !-f $filename; # git file might be deleted but not yet staged + next unless $file =~ /\.(h|c|cpp)(\.in)?$/; + next if $file =~ /gtkwave/; + + my $contents = file_contents($filename); + + checkPattern($filename, $contents, + qr/virtual[^{};]+override/, + "'virtual' keyword is redundant on 'override' method"); +} + +ok(1); +1; + +sub get_source_files { + my $root = shift; + my $git_files = `cd $root && git ls-files`; + print "MF $git_files\n" if $Self->{verbose}; + my %files; + foreach my $file (split /\s+/, $git_files) { + next if $file eq ''; + $files{$file} |= 1; + } + return \%files; +} + +sub checkPattern { + my $filename = shift; + my $contents = shift; + my $pattern = shift; + my $message = shift; + + my $offset = 0; + my $buffer = $contents; + while ($buffer =~ s/.*?^[^\/]*($pattern)//sm) { + my $lineno = offset_to_lineno($contents, $offset + $-[1]); + $offset += $+[1]; + error("$filename:$lineno: $message"); + } +} + +sub offset_to_lineno { + my $contents = shift; + my $offset = shift; + my $count = (substr $contents, 0, $offset) =~ tr/\n//; + return $count + 1; +} From 38a8d7fb2edf0f31604fef0d8dd99d30553732b2 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 16 Sep 2022 13:17:38 +0100 Subject: [PATCH 41/75] Remove redundant 'inline' keywords from definitions Also add checks to t/t_dist_cppstyle --- include/verilated.cpp | 29 ++-- include/verilated.h | 18 +-- include/verilated_dpi.cpp | 2 +- include/verilated_fst_c.h | 16 +-- include/verilated_fst_sc.h | 3 +- include/verilated_funcs.h | 2 +- include/verilated_imp.h | 6 +- include/verilated_profiler.h | 7 +- include/verilated_threads.h | 14 +- include/verilated_trace.h | 34 ++--- include/verilated_vcd_c.cpp | 6 +- include/verilated_vcd_c.h | 18 +-- include/verilated_vcd_sc.h | 3 +- include/verilated_vpi.cpp | 2 +- include/verilatedos.h | 6 +- src/V3Ast.cpp | 3 +- src/V3Ast.h | 214 +++++++++++++++--------------- src/V3AstInlines.h | 63 ++++----- src/V3AstNodeDType.h | 14 +- src/V3AstNodeMath.h | 5 +- src/V3AstNodes.cpp | 7 + src/V3AstUserAllocator.h | 4 +- src/V3Broken.cpp | 4 +- src/V3CCtors.cpp | 2 +- src/V3Config.cpp | 2 +- src/V3Error.h | 6 +- src/V3File.cpp | 8 +- src/V3FileLine.h | 12 +- src/V3Graph.h | 6 +- src/V3GraphAcyc.cpp | 2 +- src/V3GraphAlg.h | 4 +- src/V3Hash.h | 2 +- src/V3LangCode.h | 6 +- src/V3Life.cpp | 6 +- src/V3LinkDot.cpp | 2 +- src/V3Options.h | 16 +-- src/V3Order.cpp | 6 +- src/V3OrderGraph.h | 6 +- src/V3PreLex.h | 4 +- src/V3String.cpp | 12 +- src/V3Subst.cpp | 2 +- src/V3TSP.cpp | 6 +- test_regress/t/TestVpi.h | 2 +- test_regress/t/t_dist_cppstyle.pl | 20 ++- test_regress/t/t_extend_class_c.h | 2 +- 45 files changed, 305 insertions(+), 309 deletions(-) diff --git a/include/verilated.cpp b/include/verilated.cpp index ee5090507..1b5dab84b 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -1003,22 +1003,22 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA } } -static inline bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE { +static bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE { if (VL_LIKELY(fp)) { return std::feof(fp) ? true : false; // true : false to prevent MSVC++ warning } else { return floc < 0; } } -static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE { +static void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE { if (VL_LIKELY(fp)) { std::fgetc(fp); } else { floc -= 8; } } -static inline int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp, - const std::string& fstr) VL_MT_SAFE { +static int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp, + const std::string& fstr) VL_MT_SAFE { // Get a character without advancing if (VL_LIKELY(fp)) { const int data = std::fgetc(fp); @@ -1035,17 +1035,16 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp, } } } -static inline void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp, - const std::string& fstr) VL_MT_SAFE { +static void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp, + const std::string& fstr) VL_MT_SAFE { while (true) { const int c = _vl_vsss_peek(fp, floc, fromp, fstr); if (c == EOF || !std::isspace(c)) return; _vl_vsss_advance(fp, floc); } } -static inline void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp, - const std::string& fstr, char* tmpp, - const char* acceptp) VL_MT_SAFE { +static void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp, const std::string& fstr, + char* tmpp, const char* acceptp) VL_MT_SAFE { // Read into tmp, consisting of characters from acceptp list char* cp = tmpp; while (true) { @@ -1059,9 +1058,8 @@ static inline void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp, *cp++ = '\0'; // VL_DBG_MSGF(" _read got='"<>= 1) { VL_ASSIGNBIT_WI(lsb, owp, ld & 1); } } -static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, - size_t posstart, size_t posend) VL_MT_SAFE { +static void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, + size_t posstart, size_t posend) VL_MT_SAFE { // Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits. int lsb = 0; for (int i = 0, pos = static_cast(posend) - 1; diff --git a/include/verilated.h b/include/verilated.h index 5700e67be..ed7f7955a 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -274,7 +274,7 @@ protected: public: /// Returns the VerilatedContext this model is instantiated under /// Used to get to e.g. simulation time via contextp()->time() - inline VerilatedContext* contextp() const { return &m_context; } + VerilatedContext* contextp() const { return &m_context; } /// Returns the hierarchical name of this module instance. virtual const char* hierName() const = 0; /// Returns the name of this model (the name of the generated model class). @@ -457,9 +457,9 @@ public: VerilatedCovContext* coveragep() VL_MT_SAFE; /// Set debug level /// Debug is currently global, but for forward compatibility have a per-context method - static void debug(int val) VL_MT_SAFE; + static inline void debug(int val) VL_MT_SAFE; /// Return debug level - static int debug() VL_MT_SAFE; + static inline int debug() VL_MT_SAFE; /// Set current number of errors/assertions void errorCount(int val) VL_MT_SAFE; /// Increment current number of errors/assertions @@ -521,7 +521,7 @@ public: /// /// * Else, time comes from the legacy 'double sc_time_stamp()' which /// must be a function defined by the user's wrapper. - uint64_t time() const VL_MT_SAFE; + inline uint64_t time() const VL_MT_SAFE; /// Set current simulation time. See time() for side effect details void time(uint64_t value) VL_MT_SAFE { m_s.m_time = value; } /// Advance current simulation time. See time() for side effect details @@ -652,13 +652,13 @@ public: // But internals only - called from VerilatedModule's const char* name() const { return m_namep; } const char* identifier() const { return m_identifierp; } int8_t timeunit() const { return m_timeunit; } - inline VerilatedSyms* symsp() const { return m_symsp; } + VerilatedSyms* symsp() const { return m_symsp; } VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT; VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; } void scopeDump() const; void* exportFindError(int funcnum) const; static void* exportFindNullError(int funcnum) VL_MT_SAFE; - static inline void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE { + static void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE { if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum); if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) { // m_callbacksp must be declared, as Max'es are > 0 @@ -727,7 +727,7 @@ public: /// Return debug level /// When multithreaded this may not immediately react to another thread /// changing the level (no mutex) - static inline int debug() VL_MT_SAFE { return s_debug; } + static int debug() VL_MT_SAFE { return s_debug; } #else /// Return constant 0 debug level, so C++'s optimizer rips up static constexpr int debug() VL_PURE { return 0; } @@ -933,8 +933,8 @@ private: #endif }; -inline void VerilatedContext::debug(int val) VL_MT_SAFE { Verilated::debug(val); } -inline int VerilatedContext::debug() VL_MT_SAFE { return Verilated::debug(); } +void VerilatedContext::debug(int val) VL_MT_SAFE { Verilated::debug(val); } +int VerilatedContext::debug() VL_MT_SAFE { return Verilated::debug(); } //========================================================================= // Data Types diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index caa72af85..7f68e1bad 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -181,7 +181,7 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w //====================================================================== // Open array internals -static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) { +static const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) { if (VL_UNLIKELY(!h)) { VL_FATAL_MT(__FILE__, __LINE__, "", "%%Error: DPI svOpenArrayHandle function called with nullptr handle"); diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index 73c821a60..8b33b4855 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -161,13 +161,13 @@ class VerilatedFstBuffer VL_NOT_FINAL { // Implementations of duck-typed methods for VerilatedTraceBuffer. These are // called from only one place (the full* methods), so always inline them. - VL_ATTR_ALWINLINE inline void emitBit(uint32_t code, CData newval); - VL_ATTR_ALWINLINE inline void emitCData(uint32_t code, CData newval, int bits); - VL_ATTR_ALWINLINE inline void emitSData(uint32_t code, SData newval, int bits); - VL_ATTR_ALWINLINE inline void emitIData(uint32_t code, IData newval, int bits); - VL_ATTR_ALWINLINE inline void emitQData(uint32_t code, QData newval, int bits); - VL_ATTR_ALWINLINE inline void emitWData(uint32_t code, const WData* newvalp, int bits); - VL_ATTR_ALWINLINE inline void emitDouble(uint32_t code, double newval); + VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval); + VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits); + VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits); + VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits); + VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits); + VL_ATTR_ALWINLINE void emitWData(uint32_t code, const WData* newvalp, int bits); + VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval); }; //============================================================================= @@ -232,7 +232,7 @@ public: } // Internal class access - inline VerilatedFst* spTrace() { return &m_sptrace; } + VerilatedFst* spTrace() { return &m_sptrace; } }; #endif // guard diff --git a/include/verilated_fst_sc.h b/include/verilated_fst_sc.h index f6546ce84..f5aaa305c 100644 --- a/include/verilated_fst_sc.h +++ b/include/verilated_fst_sc.h @@ -75,8 +75,7 @@ private: //-------------------------------------------------- // SystemC 2.1.v1 -#define DECL_TRACE_METHOD_A(tp) \ - void trace(const tp& object, const std::string& name) override; +#define DECL_TRACE_METHOD_A(tp) void trace(const tp& object, const std::string& name) override; #define DECL_TRACE_METHOD_B(tp) \ void trace(const tp& object, const std::string& name, int width) override; diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h index 8bcef8019..8f5027f96 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -282,7 +282,7 @@ inline uint64_t vl_time_stamp64() { # endif #endif -inline uint64_t VerilatedContext::time() const VL_MT_SAFE { +uint64_t VerilatedContext::time() const VL_MT_SAFE { // When using non-default context, fastest path is return time if (VL_LIKELY(m_s.m_time)) return m_s.m_time; #if defined(SYSTEMC_VERSION) || (!defined(VL_TIME_CONTEXT) && !defined(VL_NO_LEGACY)) diff --git a/include/verilated_imp.h b/include/verilated_imp.h index d55c7b228..cc1971d04 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -356,7 +356,7 @@ public: // But only for verilated*.cpp } } } - inline FILE* fdToFp(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) { + FILE* fdToFp(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) { const VerilatedLockGuard lock{m_fdMutex}; const VerilatedFpList fdlist = fdToFpList(fdi); if (VL_UNLIKELY(fdlist.size() != 1)) return nullptr; @@ -466,7 +466,7 @@ public: // There's often many more scopes than userdata's and thus having a ~48byte // per map overhead * N scopes would take much more space and cache thrashing. // As scopep's are pointers, this implicitly handles multiple Context's - static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE { + static void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE { const VerilatedLockGuard lock{s().m_userMapMutex}; const auto it = s().m_userMap.find(std::make_pair(scopep, userKey)); if (it != s().m_userMap.end()) { @@ -475,7 +475,7 @@ public: s().m_userMap.emplace(std::make_pair(scopep, userKey), userData); } } - static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE { + static void* userFind(const void* scopep, void* userKey) VL_MT_SAFE { const VerilatedLockGuard lock{s().m_userMapMutex}; const auto& it = vlstd::as_const(s().m_userMap).find(std::make_pair(scopep, userKey)); if (VL_UNLIKELY(it == s().m_userMap.end())) return nullptr; diff --git a/include/verilated_profiler.h b/include/verilated_profiler.h index a237ee5cf..5ddf3b0d9 100644 --- a/include/verilated_profiler.h +++ b/include/verilated_profiler.h @@ -45,8 +45,7 @@ class VlThreadPool; //============================================================================= // Return high-precision counter for profiling, or 0x0 if not available -VL_ATTR_ALWINLINE -inline QData VL_CPU_TICK() { +VL_ATTR_ALWINLINE QData VL_CPU_TICK() { uint64_t val; VL_GET_CPU_TICK(val); return val; @@ -171,9 +170,9 @@ public: // METHODS // Is profiling enabled - inline bool enabled() const { return m_enabled; } + bool enabled() const { return m_enabled; } // Append a trace record to the trace buffer of the current thread - static inline VlExecutionRecord& addRecord() { + static VlExecutionRecord& addRecord() { t_trace.emplace_back(); return t_trace.back(); } diff --git a/include/verilated_threads.h b/include/verilated_threads.h index 59658bf20..b595c1bca 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -103,7 +103,7 @@ public: // Upstream mtasks must call this when they complete. // Returns true when the current MTaskVertex becomes ready to execute, // false while it's still waiting on more dependencies. - inline bool signalUpstreamDone(bool evenCycle) { + bool signalUpstreamDone(bool evenCycle) { if (evenCycle) { const uint32_t upstreamDepsDone = 1 + m_upstreamDepsDone.fetch_add(1, std::memory_order_release); @@ -116,11 +116,11 @@ public: return (upstreamDepsDone_prev == 1); } } - inline bool areUpstreamDepsDone(bool evenCycle) const { + bool areUpstreamDepsDone(bool evenCycle) const { const uint32_t target = evenCycle ? m_upstreamDepCount : 0; return m_upstreamDepsDone.load(std::memory_order_acquire) == target; } - inline void waitUntilUpstreamDone(bool evenCycle) const { + void waitUntilUpstreamDone(bool evenCycle) const { unsigned ct = 0; while (VL_UNLIKELY(!areUpstreamDepsDone(evenCycle))) { VL_CPU_RELAX(); @@ -171,7 +171,7 @@ public: // METHODS template - inline void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) { + void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) { // Spin for a while, waiting for new data if VL_CONSTEXPR_CXX17 (SpinWait) { for (unsigned i = 0; i < VL_LOCK_SPINS; ++i) { @@ -191,7 +191,7 @@ public: m_ready.erase(m_ready.begin()); m_ready_size.fetch_sub(1, std::memory_order_relaxed); } - inline void addTask(VlExecFnp fnp, VlSelfP selfp, bool evenCycle = false) + void addTask(VlExecFnp fnp, VlSelfP selfp, bool evenCycle = false) VL_MT_SAFE_EXCLUDES(m_mutex) { bool notify; { @@ -223,8 +223,8 @@ public: ~VlThreadPool() override; // METHODS - inline int numThreads() const { return m_workers.size(); } - inline VlWorkerThread* workerp(int index) { + int numThreads() const { return m_workers.size(); } + VlWorkerThread* workerp(int index) { assert(index >= 0); assert(index < m_workers.size()); return m_workers[index]; diff --git a/include/verilated_trace.h b/include/verilated_trace.h index 03ca2ba2c..151d2c9f2 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -318,8 +318,8 @@ protected: void flushBase(); #ifdef VL_THREADED - inline bool offload() const { return m_offload; } - inline bool parallel() const { return m_parallel; } + bool offload() const { return m_offload; } + bool parallel() const { return m_parallel; } #else static constexpr bool offload() { return false; } static constexpr bool parallel() { return false; } @@ -425,7 +425,7 @@ public: // duck-typed void emitWData(uint32_t code, const WData* newvalp, int bits) = 0; // duck-typed void emitDouble(uint32_t code, double newval) = 0; - VL_ATTR_ALWINLINE inline uint32_t* oldp(uint32_t code) { return m_sigs_oldvalp + code; } + VL_ATTR_ALWINLINE uint32_t* oldp(uint32_t code) { return m_sigs_oldvalp + code; } // Write to previous value buffer value and emit trace entry. void fullBit(uint32_t* oldp, CData newval); @@ -441,27 +441,27 @@ public: // thread and are called chg*Impl // Check previous dumped value of signal. If changed, then emit trace entry - VL_ATTR_ALWINLINE inline void chgBit(uint32_t* oldp, CData newval) { + VL_ATTR_ALWINLINE void chgBit(uint32_t* oldp, CData newval) { const uint32_t diff = *oldp ^ newval; if (VL_UNLIKELY(diff)) fullBit(oldp, newval); } - VL_ATTR_ALWINLINE inline void chgCData(uint32_t* oldp, CData newval, int bits) { + VL_ATTR_ALWINLINE void chgCData(uint32_t* oldp, CData newval, int bits) { const uint32_t diff = *oldp ^ newval; if (VL_UNLIKELY(diff)) fullCData(oldp, newval, bits); } - VL_ATTR_ALWINLINE inline void chgSData(uint32_t* oldp, SData newval, int bits) { + VL_ATTR_ALWINLINE void chgSData(uint32_t* oldp, SData newval, int bits) { const uint32_t diff = *oldp ^ newval; if (VL_UNLIKELY(diff)) fullSData(oldp, newval, bits); } - VL_ATTR_ALWINLINE inline void chgIData(uint32_t* oldp, IData newval, int bits) { + VL_ATTR_ALWINLINE void chgIData(uint32_t* oldp, IData newval, int bits) { const uint32_t diff = *oldp ^ newval; if (VL_UNLIKELY(diff)) fullIData(oldp, newval, bits); } - VL_ATTR_ALWINLINE inline void chgQData(uint32_t* oldp, QData newval, int bits) { + VL_ATTR_ALWINLINE void chgQData(uint32_t* oldp, QData newval, int bits) { const uint64_t diff = *reinterpret_cast(oldp) ^ newval; if (VL_UNLIKELY(diff)) fullQData(oldp, newval, bits); } - VL_ATTR_ALWINLINE inline void chgWData(uint32_t* oldp, const WData* newvalp, int bits) { + VL_ATTR_ALWINLINE void chgWData(uint32_t* oldp, const WData* newvalp, int bits) { for (int i = 0; i < (bits + 31) / 32; ++i) { if (VL_UNLIKELY(oldp[i] ^ newvalp[i])) { fullWData(oldp, newvalp, bits); @@ -469,7 +469,7 @@ public: } } } - VL_ATTR_ALWINLINE inline void chgDouble(uint32_t* oldp, double newval) { + VL_ATTR_ALWINLINE void chgDouble(uint32_t* oldp, double newval) { // cppcheck-suppress invalidPointerCast if (VL_UNLIKELY(*reinterpret_cast(oldp) != newval)) fullDouble(oldp, newval); } @@ -498,48 +498,48 @@ public: // Hot path internal interface to Verilator generated code // Offloaded tracing. Just dump everything in the offload buffer - inline void chgBit(uint32_t code, CData newval) { + void chgBit(uint32_t code, CData newval) { m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_BIT_0 | newval; m_offloadBufferWritep[1] = code; m_offloadBufferWritep += 2; VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp);); } - inline void chgCData(uint32_t code, CData newval, int bits) { + void chgCData(uint32_t code, CData newval, int bits) { m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_CDATA; m_offloadBufferWritep[1] = code; m_offloadBufferWritep[2] = newval; m_offloadBufferWritep += 3; VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp);); } - inline void chgSData(uint32_t code, SData newval, int bits) { + void chgSData(uint32_t code, SData newval, int bits) { m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_SDATA; m_offloadBufferWritep[1] = code; m_offloadBufferWritep[2] = newval; m_offloadBufferWritep += 3; VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp);); } - inline void chgIData(uint32_t code, IData newval, int bits) { + void chgIData(uint32_t code, IData newval, int bits) { m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_IDATA; m_offloadBufferWritep[1] = code; m_offloadBufferWritep[2] = newval; m_offloadBufferWritep += 3; VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp);); } - inline void chgQData(uint32_t code, QData newval, int bits) { + void chgQData(uint32_t code, QData newval, int bits) { m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_QDATA; m_offloadBufferWritep[1] = code; *reinterpret_cast(m_offloadBufferWritep + 2) = newval; m_offloadBufferWritep += 4; VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp);); } - inline void chgWData(uint32_t code, const WData* newvalp, int bits) { + void chgWData(uint32_t code, const WData* newvalp, int bits) { m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_WDATA; m_offloadBufferWritep[1] = code; m_offloadBufferWritep += 2; for (int i = 0; i < (bits + 31) / 32; ++i) { *m_offloadBufferWritep++ = newvalp[i]; } VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp);); } - inline void chgDouble(uint32_t code, double newval) { + void chgDouble(uint32_t code, double newval) { m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_DOUBLE; m_offloadBufferWritep[1] = code; // cppcheck-suppress invalidPointerCast diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index ed36e6583..2d0cc57f0 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -632,10 +632,10 @@ void VerilatedVcd::commitTraceBuffer(VerilatedVcd::Buffer* bufp) { //============================================================================= // Trace rendering primitives -static inline void -VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) VL_ATTR_NO_SANITIZE_ALIGN; +static void VerilatedVcdCCopyAndAppendNewLine(char* writep, + const char* suffixp) VL_ATTR_NO_SANITIZE_ALIGN; -static inline void VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) { +static void VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) { // Copy the whole suffix (this avoid having hard to predict branches which // helps a lot). Note: The maximum length of the suffix is // VL_TRACE_MAX_VCD_CODE_SIZE + 2 == 7, but we unroll this here for speed. diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 9079ef926..2967225b1 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -73,7 +73,7 @@ private: void bufferResize(size_t minsize); void bufferFlush() VL_MT_UNSAFE_ONE; - inline void bufferCheck() { + void bufferCheck() { // Flush the write buffer if there's not enough space left for new information // We only call this once per vector, so we need enough slop for a very wide "b###" line if (VL_UNLIKELY(m_writep > m_wrFlushp)) bufferFlush(); @@ -210,13 +210,13 @@ class VerilatedVcdBuffer VL_NOT_FINAL { // Implementation of VerilatedTraceBuffer interface // Implementations of duck-typed methods for VerilatedTraceBuffer. These are // called from only one place (the full* methods), so always inline them. - VL_ATTR_ALWINLINE inline void emitBit(uint32_t code, CData newval); - VL_ATTR_ALWINLINE inline void emitCData(uint32_t code, CData newval, int bits); - VL_ATTR_ALWINLINE inline void emitSData(uint32_t code, SData newval, int bits); - VL_ATTR_ALWINLINE inline void emitIData(uint32_t code, IData newval, int bits); - VL_ATTR_ALWINLINE inline void emitQData(uint32_t code, QData newval, int bits); - VL_ATTR_ALWINLINE inline void emitWData(uint32_t code, const WData* newvalp, int bits); - VL_ATTR_ALWINLINE inline void emitDouble(uint32_t code, double newval); + VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval); + VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits); + VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits); + VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits); + VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits); + VL_ATTR_ALWINLINE void emitWData(uint32_t code, const WData* newvalp, int bits); + VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval); }; //============================================================================= @@ -313,7 +313,7 @@ public: } // Internal class access - inline VerilatedVcd* spTrace() { return &m_sptrace; } + VerilatedVcd* spTrace() { return &m_sptrace; } }; #endif // guard diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h index 133f70407..c0ba6e528 100644 --- a/include/verilated_vcd_sc.h +++ b/include/verilated_vcd_sc.h @@ -77,8 +77,7 @@ private: //-------------------------------------------------- // SystemC 2.1.v1 -#define DECL_TRACE_METHOD_A(tp) \ - void trace(const tp& object, const std::string& name) override; +#define DECL_TRACE_METHOD_A(tp) void trace(const tp& object, const std::string& name) override; #define DECL_TRACE_METHOD_B(tp) \ void trace(const tp& object, const std::string& name, int width) override; diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index ff2d25c27..be58390ed 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -114,7 +114,7 @@ public: static VerilatedVpio* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(h)); } - inline vpiHandle castVpiHandle() { return reinterpret_cast(this); } + vpiHandle castVpiHandle() { return reinterpret_cast(this); } // ACCESSORS virtual const char* name() const { return ""; } virtual const char* fullname() const { return ""; } diff --git a/include/verilatedos.h b/include/verilatedos.h index 12763f815..c84e13ef0 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -39,7 +39,7 @@ #ifdef __GNUC__ # define VL_ATTR_ALIGNED(alignment) __attribute__((aligned(alignment))) -# define VL_ATTR_ALWINLINE __attribute__((always_inline)) +# define VL_ATTR_ALWINLINE __attribute__((always_inline)) inline # define VL_ATTR_NOINLINE __attribute__((noinline)) # define VL_ATTR_COLD __attribute__((cold)) # define VL_ATTR_HOT __attribute__((hot)) @@ -548,8 +548,8 @@ struct reverse_wrapper { explicit reverse_wrapper(const T& a_v) : m_v(a_v) {} - inline auto begin() -> decltype(m_v.rbegin()) { return m_v.rbegin(); } - inline auto end() -> decltype(m_v.rend()) { return m_v.rend(); } + auto begin() -> decltype(m_v.rbegin()) { return m_v.rbegin(); } + auto end() -> decltype(m_v.rend()) { return m_v.rend(); } }; // C++20's std::ranges::reverse_view diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 3bc1325bc..4a516e6be 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -212,8 +212,7 @@ string AstNode::prettyTypeName() const { //###################################################################### // Insertion -inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int lineno, - bool next) { +void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int lineno, bool next) { #ifdef VL_DEBUG // Called on all major tree changers. // Only for use for those really nasty bugs relating to internals diff --git a/src/V3Ast.h b/src/V3Ast.h index ff3cce31b..90a203042 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -93,11 +93,11 @@ public: // const char* ascii() const {...}; enum en m_e; // cppcheck-suppress uninitVar // responsibility of each subclass - inline VNType() = default; + VNType() = default; // cppcheck-suppress noExplicitConstructor - inline VNType(en _e) + VNType(en _e) : m_e{_e} {} - explicit inline VNType(int _e) + explicit VNType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; @@ -116,12 +116,12 @@ public: static const char* const names[] = {"NONE", "VAUTOM", "VSTATIC"}; return names[m_e]; } - inline VLifetime() + VLifetime() : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor - inline VLifetime(en _e) + VLifetime(en _e) : m_e{_e} {} - explicit inline VLifetime(int _e) + explicit VLifetime(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool isNone() const { return m_e == NONE; } @@ -157,12 +157,12 @@ public: static const char* const names[] = {"[RV] <-", "[LV] =>", "[LV] <=>", "--"}; return names[m_e]; } - inline VAccess() + VAccess() : m_e{READ} {} // cppcheck-suppress noExplicitConstructor - inline VAccess(en _e) + VAccess(en _e) : m_e{_e} {} - explicit inline VAccess(int _e) + explicit VAccess(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } VAccess invert() const { @@ -194,19 +194,19 @@ public: static const char* const names[] = {"UNSIGNED", "SIGNED", "NOSIGN"}; return names[m_e]; } - inline VSigning() + VSigning() : m_e{UNSIGNED} {} // cppcheck-suppress noExplicitConstructor - inline VSigning(en _e) + VSigning(en _e) : m_e{_e} {} - static inline VSigning fromBool(bool isSigned) { // Factory method + static VSigning fromBool(bool isSigned) { // Factory method return isSigned ? VSigning{SIGNED} : VSigning{UNSIGNED}; } - explicit inline VSigning(int _e) + explicit VSigning(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } - inline bool isSigned() const { return m_e == SIGNED; } - inline bool isNosign() const { return m_e == NOSIGN; } + bool isSigned() const { return m_e == SIGNED; } + bool isNosign() const { return m_e == NOSIGN; } // No isUnsigned() as it's ambiguous if NOSIGN should be included or not. }; inline bool operator==(const VSigning& lhs, const VSigning& rhs) { return lhs.m_e == rhs.m_e; } @@ -234,12 +234,12 @@ public: ENUM_SIZE }; enum en m_e; - inline VPragmaType() + VPragmaType() : m_e{ILLEGAL} {} // cppcheck-suppress noExplicitConstructor - inline VPragmaType(en _e) + VPragmaType(en _e) : m_e{_e} {} - explicit inline VPragmaType(int _e) + explicit VPragmaType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; @@ -322,12 +322,12 @@ public: } return false; } - inline VEdgeType() + VEdgeType() : m_e{ET_ILLEGAL} {} // cppcheck-suppress noExplicitConstructor - inline VEdgeType(en _e) + VEdgeType(en _e) : m_e{_e} {} - explicit inline VEdgeType(int _e) + explicit VEdgeType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; @@ -403,12 +403,12 @@ public: // clang-format on return names[m_e]; } - inline VAttrType() + VAttrType() : m_e{ILLEGAL} {} // cppcheck-suppress noExplicitConstructor - inline VAttrType(en _e) + VAttrType(en _e) : m_e{_e} {} - explicit inline VAttrType(int _e) + explicit VAttrType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; @@ -470,12 +470,12 @@ public: UASSERT(0 == std::strcmp(VBasicDTypeKwd{_ENUM_MAX}.dpiType(), " MAX"), "SelfTest: Enum mismatch"); } - inline VBasicDTypeKwd() + VBasicDTypeKwd() : m_e{UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - inline VBasicDTypeKwd(en _e) + VBasicDTypeKwd(en _e) : m_e{_e} {} - explicit inline VBasicDTypeKwd(int _e) + explicit VBasicDTypeKwd(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } int width() const { @@ -574,12 +574,12 @@ class VDirection final { public: enum en : uint8_t { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF }; enum en m_e; - inline VDirection() + VDirection() : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor - inline VDirection(en _e) + VDirection(en _e) : m_e{_e} {} - explicit inline VDirection(int _e) + explicit VDirection(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { @@ -620,12 +620,12 @@ public: enum en : uint8_t { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VBoolOrUnknown() + VBoolOrUnknown() : m_e{BU_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - inline VBoolOrUnknown(en _e) + VBoolOrUnknown(en _e) : m_e{_e} {} - explicit inline VBoolOrUnknown(int _e) + explicit VBoolOrUnknown(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning const char* ascii() const { static const char* const names[] = {"FALSE", "TRUE", "UNK"}; @@ -659,12 +659,12 @@ public: enum en : uint8_t { JOIN = 0, JOIN_ANY = 1, JOIN_NONE = 2 }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VJoinType() + VJoinType() : m_e{JOIN} {} // cppcheck-suppress noExplicitConstructor - inline VJoinType(en _e) + VJoinType(en _e) : m_e{_e} {} - explicit inline VJoinType(int _e) + explicit VJoinType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning const char* ascii() const { static const char* const names[] = {"JOIN", "JOIN_ANY", "JOIN_NONE"}; @@ -712,12 +712,12 @@ public: MEMBER }; enum en m_e; - inline VVarType() + VVarType() : m_e{UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - inline VVarType(en _e) + VVarType(en _e) : m_e{_e} {} - explicit inline VVarType(int _e) + explicit VVarType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { @@ -764,12 +764,12 @@ public: enum en : uint8_t { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VBranchPred() + VBranchPred() : m_e{BP_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - inline VBranchPred(en _e) + VBranchPred(en _e) : m_e{_e} {} - explicit inline VBranchPred(int _e) + explicit VBranchPred(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool unknown() const { return m_e == BP_UNKNOWN; } @@ -805,12 +805,12 @@ public: enum en : uint8_t { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* - inline VVarAttrClocker() + VVarAttrClocker() : m_e{CLOCKER_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - inline VVarAttrClocker(en _e) + VVarAttrClocker(en _e) : m_e{_e} {} - explicit inline VVarAttrClocker(int _e) + explicit VVarAttrClocker(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool unknown() const { return m_e == CLOCKER_UNKNOWN; } @@ -847,12 +847,12 @@ class VAlwaysKwd final { public: enum en : uint8_t { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB }; enum en m_e; - inline VAlwaysKwd() + VAlwaysKwd() : m_e{ALWAYS} {} // cppcheck-suppress noExplicitConstructor - inline VAlwaysKwd(en _e) + VAlwaysKwd(en _e) : m_e{_e} {} - explicit inline VAlwaysKwd(int _e) + explicit VAlwaysKwd(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { @@ -870,12 +870,12 @@ class VCaseType final { public: enum en : uint8_t { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE }; enum en m_e; - inline VCaseType() + VCaseType() : m_e{CT_CASE} {} // cppcheck-suppress noExplicitConstructor - inline VCaseType(en _e) + VCaseType(en _e) : m_e{_e} {} - explicit inline VCaseType(int _e) + explicit VCaseType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; @@ -903,7 +903,7 @@ public: // cppcheck-suppress noExplicitConstructor VDisplayType(en _e) : m_e{_e} {} - explicit inline VDisplayType(int _e) + explicit VDisplayType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool addNewline() const { return m_e != DT_WRITE; } @@ -926,12 +926,12 @@ class VDumpCtlType final { public: enum en : uint8_t { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON }; enum en m_e; - inline VDumpCtlType() + VDumpCtlType() : m_e{ON} {} // cppcheck-suppress noExplicitConstructor - inline VDumpCtlType(en _e) + VDumpCtlType(en _e) : m_e{_e} {} - explicit inline VDumpCtlType(int _e) + explicit VDumpCtlType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { @@ -956,12 +956,12 @@ public: PX_TEXT // Unknown ID component }; enum en m_e; - inline VParseRefExp() + VParseRefExp() : m_e{PX_NONE} {} // cppcheck-suppress noExplicitConstructor - inline VParseRefExp(en _e) + VParseRefExp(en _e) : m_e{_e} {} - explicit inline VParseRefExp(int _e) + explicit VParseRefExp(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { @@ -986,9 +986,9 @@ public: enum en m_e; // cppcheck-suppress noExplicitConstructor - inline VStrength(en strengthLevel) + VStrength(en strengthLevel) : m_e(strengthLevel) {} - explicit inline VStrength(int _e) + explicit VStrength(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } @@ -1080,12 +1080,12 @@ public: INT_FWD_CLASS, // Interface (.h) needs a forward class declaration }; enum en m_e; - inline VUseType() + VUseType() : m_e{IMP_FWD_CLASS} {} // cppcheck-suppress noExplicitConstructor - inline VUseType(en _e) + VUseType(en _e) : m_e{_e} {} - explicit inline VUseType(int _e) + explicit VUseType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; } bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; } @@ -1309,23 +1309,23 @@ class VNVisitor VL_NOT_FINAL : public VNDeleter { public: /// Call visit()s on nodep - void iterate(AstNode* nodep); + inline void iterate(AstNode* nodep); /// Call visit()s on nodep - void iterateNull(AstNode* nodep); + inline void iterateNull(AstNode* nodep); /// Call visit()s on nodep's children - void iterateChildren(AstNode* nodep); + inline void iterateChildren(AstNode* nodep); /// Call visit()s on nodep's children in backp() order - void iterateChildrenBackwards(AstNode* nodep); + inline void iterateChildrenBackwards(AstNode* nodep); /// Call visit()s on const nodep's children - void iterateChildrenConst(AstNode* nodep); + inline void iterateChildrenConst(AstNode* nodep); /// Call visit()s on nodep (maybe nullptr) and nodep's nextp() list - void iterateAndNextNull(AstNode* nodep); + inline void iterateAndNextNull(AstNode* nodep); /// Call visit()s on const nodep (maybe nullptr) and nodep's nextp() list - void iterateAndNextConstNull(AstNode* nodep); + inline void iterateAndNextConstNull(AstNode* nodep); /// Call visit()s on const nodep (maybe nullptr) and nodep's nextp() list, in reverse order - void iterateAndNextConstNullBackwards(AstNode* nodep); + inline void iterateAndNextConstNullBackwards(AstNode* nodep); /// Return edited nodep; see comments in V3Ast.cpp - AstNode* iterateSubtreeReturnEdits(AstNode* nodep); + inline AstNode* iterateSubtreeReturnEdits(AstNode* nodep); virtual void visit(AstNode* nodep) = 0; #include "V3Ast__gen_visitor_decls.h" // From ./astgen @@ -1353,7 +1353,7 @@ protected: public: VNRelinker() = default; - void relink(AstNode* newp); + inline void relink(AstNode* newp); AstNode* oldp() const { return m_oldp; } void dump(std::ostream& str = std::cout) const; }; @@ -1525,7 +1525,7 @@ protected: public: // ACCESSORS - inline VNType type() const { return m_type; } + VNType type() const { return m_type; } const char* typeName() const { return type().ascii(); } // See also prettyTypeName AstNode* nextp() const { return m_nextp; } AstNode* backp() const { return m_backp; } @@ -1607,8 +1607,8 @@ public: virtual string prettyOperatorName() const { return "operator " + prettyTypeName(); } FileLine* fileline() const { return m_fileline; } void fileline(FileLine* fl) { m_fileline = fl; } - bool width1() const; - int widthInstrs() const; + inline bool width1() const; + inline int widthInstrs() const; void didWidth(bool flag) { m_flags.didWidth = flag; } bool didWidth() const { return m_flags.didWidth; } bool didWidthAndSet() { @@ -1622,17 +1622,17 @@ public: void protect(bool flag) { m_flags.protect = flag; } // TODO stomp these width functions out, and call via dtypep() instead - int width() const; - int widthMin() const; + inline int width() const; + inline int widthMin() const; int widthMinV() const { return v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); } int widthWords() const { return VL_WORDS_I(width()); } bool isQuad() const { return (width() > VL_IDATASIZE && width() <= VL_QUADSIZE); } bool isWide() const { return (width() > VL_QUADSIZE); } - bool isDouble() const; - bool isSigned() const; - bool isString() const; + inline bool isDouble() const; + inline bool isSigned() const; + inline bool isString() const; // clang-format off VNUser user1u() const { @@ -1716,11 +1716,11 @@ public: // ACCESSORS for specific types // Alas these can't be virtual or they break when passed a nullptr - bool isZero() const; - bool isOne() const; - bool isNeqZero() const; - bool isAllOnes() const; - bool isAllOnesV() const; // Verilog width rules apply + inline bool isZero() const; + inline bool isOne() const; + inline bool isNeqZero() const; + inline bool isAllOnes() const; + inline bool isAllOnesV() const; // Verilog width rules apply // METHODS - data type changes especially for initial creation void dtypep(AstNodeDType* nodep) { @@ -1832,9 +1832,9 @@ public: } AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable? - bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p? + inline bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p? // Does tree of this == node2p?, not allowing non-isGateOptimizable - bool sameGateTree(const AstNode* node2p) const; + inline bool sameGateTree(const AstNode* node2p) const; void deleteTree(); // Always deletes the next link void checkTree(); // User Interface version void checkIter() const; @@ -1932,7 +1932,7 @@ private: public: // For use via the VN_IS macro only template - inline static bool privateIs(const AstNode* nodep) { + static bool privateIs(const AstNode* nodep) { static_assert(!uselessCast(), "Unnecessary VN_IS, node known to have target type."); static_assert(!impossibleCast(), "Unnecessary VN_IS, node cannot be this type."); return nodep && privateTypeTest(nodep); @@ -1940,14 +1940,14 @@ public: // For use via the VN_CAST macro only template - inline static T* privateCast(AstNode* nodep) { + static T* privateCast(AstNode* nodep) { static_assert(!uselessCast(), "Unnecessary VN_CAST, node known to have target type."); static_assert(!impossibleCast(), "Unnecessary VN_CAST, node cannot be this type."); return nodep && privateTypeTest(nodep) ? reinterpret_cast(nodep) : nullptr; } template - inline static const T* privateCast(const AstNode* nodep) { + static const T* privateCast(const AstNode* nodep) { static_assert(!uselessCast(), "Unnecessary VN_CAST, node known to have target type."); static_assert(!impossibleCast(), "Unnecessary VN_CAST, node cannot be this type."); @@ -1956,7 +1956,7 @@ public: // For use via the VN_AS macro only template - inline static T* privateAs(AstNode* nodep) { + static T* privateAs(AstNode* nodep) { static_assert(!uselessCast(), "Unnecessary VN_AS, node known to have target type."); static_assert(!impossibleCast(), "Unnecessary VN_AS, node cannot be this type."); UASSERT_OBJ(!nodep || privateTypeTest(nodep), nodep, @@ -1965,7 +1965,7 @@ public: return reinterpret_cast(nodep); } template - inline static const T* privateAs(const AstNode* nodep) { + static const T* privateAs(const AstNode* nodep) { static_assert(!uselessCast(), "Unnecessary VN_AS, node known to have target type."); static_assert(!impossibleCast(), "Unnecessary VN_AS, node cannot be this type."); UASSERT_OBJ(!nodep || privateTypeTest(nodep), nodep, @@ -2172,7 +2172,7 @@ void AstNode::foreachImpl(ConstCorrectAstNode* nodep, const std::function constexpr int prefetchDistance = 2; // Grow stack to given size - const auto grow = [&](size_t size) VL_ATTR_ALWINLINE { + const auto grow = [&](size_t size) { const ptrdiff_t occupancy = topp - basep; stack.resize(size); basep = stack.data() + prefetchDistance; @@ -2188,7 +2188,7 @@ void AstNode::foreachImpl(ConstCorrectAstNode* nodep, const std::function for (int i = -prefetchDistance; i; ++i) basep[i] = nodep; // Visit given node, enqueue children for traversal - const auto visit = [&](Node* currp) VL_ATTR_ALWINLINE { + const auto visit = [&](Node* currp) { // Type test this node if (AstNode::privateTypeTest(currp)) { // Call the client function @@ -2253,7 +2253,7 @@ bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, constexpr int prefetchDistance = 2; // Grow stack to given size - const auto grow = [&](size_t size) VL_ATTR_ALWINLINE { + const auto grow = [&](size_t size) { const ptrdiff_t occupancy = topp - basep; stack.resize(size); basep = stack.data() + prefetchDistance; @@ -2269,7 +2269,7 @@ bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, for (int i = -prefetchDistance; i; ++i) basep[i] = nodep; // Visit given node, enqueue children for traversal, return true if result determined. - const auto visit = [&](Node* currp) VL_ATTR_ALWINLINE { + const auto visit = [&](Node* currp) { // Type test this node if (AstNode::privateTypeTest(currp)) { // Call the client function @@ -2322,7 +2322,7 @@ inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) { } return os; } -inline void VNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } +void VNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } //###################################################################### @@ -2369,25 +2369,25 @@ struct std::equal_to> final { //###################################################################### // Inline VNVisitor METHODS -inline void VNVisitor::iterate(AstNode* nodep) { nodep->accept(*this); } -inline void VNVisitor::iterateNull(AstNode* nodep) { +void VNVisitor::iterate(AstNode* nodep) { nodep->accept(*this); } +void VNVisitor::iterateNull(AstNode* nodep) { if (VL_LIKELY(nodep)) nodep->accept(*this); } -inline void VNVisitor::iterateChildren(AstNode* nodep) { nodep->iterateChildren(*this); } -inline void VNVisitor::iterateChildrenBackwards(AstNode* nodep) { +void VNVisitor::iterateChildren(AstNode* nodep) { nodep->iterateChildren(*this); } +void VNVisitor::iterateChildrenBackwards(AstNode* nodep) { nodep->iterateChildrenBackwards(*this); } -inline void VNVisitor::iterateChildrenConst(AstNode* nodep) { nodep->iterateChildrenConst(*this); } -inline void VNVisitor::iterateAndNextNull(AstNode* nodep) { +void VNVisitor::iterateChildrenConst(AstNode* nodep) { nodep->iterateChildrenConst(*this); } +void VNVisitor::iterateAndNextNull(AstNode* nodep) { if (VL_LIKELY(nodep)) nodep->iterateAndNext(*this); } -inline void VNVisitor::iterateAndNextConstNullBackwards(AstNode* nodep) { +void VNVisitor::iterateAndNextConstNullBackwards(AstNode* nodep) { if (VL_LIKELY(nodep)) nodep->iterateListBackwards(*this); } -inline void VNVisitor::iterateAndNextConstNull(AstNode* nodep) { +void VNVisitor::iterateAndNextConstNull(AstNode* nodep) { if (VL_LIKELY(nodep)) nodep->iterateAndNextConst(*this); } -inline AstNode* VNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) { +AstNode* VNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) { return nodep->iterateSubtreeReturnEdits(*this); } diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index d532feb01..9ffb7fa5c 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -25,71 +25,56 @@ //###################################################################### // Inline METHODS -inline AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); } -inline AstNode* AstNode::addNextNull(AstNode* newp) { return addNextNull(this, newp); } -inline void AstNode::addPrev(AstNode* newp) { +AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); } +AstNode* AstNode::addNextNull(AstNode* newp) { return addNextNull(this, newp); } +void AstNode::addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); } -inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } -inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } -inline bool AstNode::width1() const { // V3Const uses to know it can optimize +int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } +int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } +bool AstNode::width1() const { // V3Const uses to know it can optimize return dtypep() && dtypep()->width() == 1; } -inline int AstNode::widthInstrs() const { +int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); } -inline bool AstNode::isDouble() const { +bool AstNode::isDouble() const { return dtypep() && VN_IS(dtypep(), BasicDType) && VN_AS(dtypep(), BasicDType)->isDouble(); } -inline bool AstNode::isString() const { +bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); } -inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); } +bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); } -inline bool AstNode::isZero() const { +bool AstNode::isZero() const { return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqZero()); } -inline bool AstNode::isNeqZero() const { +bool AstNode::isNeqZero() const { return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNeqZero()); } -inline bool AstNode::isOne() const { - return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqOne()); -} -inline bool AstNode::isAllOnes() const { +bool AstNode::isOne() const { return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqOne()); } +bool AstNode::isAllOnes() const { return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnes()); } -inline bool AstNode::isAllOnesV() const { +bool AstNode::isAllOnesV() const { return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnesV()); } -inline bool AstNode::sameTree(const AstNode* node2p) const { +bool AstNode::sameTree(const AstNode* node2p) const { return sameTreeIter(this, node2p, true, false); } -inline bool AstNode::sameGateTree(const AstNode* node2p) const { +bool AstNode::sameGateTree(const AstNode* node2p) const { return sameTreeIter(this, node2p, true, true); } -inline void AstNodeVarRef::varp(AstVar* varp) { - m_varp = varp; - dtypeFrom(varp); -} - -inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); } - -inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); } -inline int AstNodeArrayDType::left() const { return rangep()->leftConst(); } -inline int AstNodeArrayDType::right() const { return rangep()->rightConst(); } -inline int AstNodeArrayDType::hi() const { return rangep()->hiConst(); } -inline int AstNodeArrayDType::lo() const { return rangep()->loConst(); } -inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); } -inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right()}; } - -inline void AstIfaceRefDType::cloneRelink() { - if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep(); - if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep(); - if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); -} +void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); } +int AstNodeArrayDType::left() const { return rangep()->leftConst(); } +int AstNodeArrayDType::right() const { return rangep()->rightConst(); } +int AstNodeArrayDType::hi() const { return rangep()->hiConst(); } +int AstNodeArrayDType::lo() const { return rangep()->loConst(); } +int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); } +VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right()}; } AstRange::AstRange(FileLine* fl, int left, int right) : ASTGEN_SUPER_Range(fl) { diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 8df86afab..02d45f31e 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -172,7 +172,7 @@ public: AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable - void rangep(AstRange* nodep); + inline void rangep(AstRange* nodep); // METHODS AstBasicDType* basicp() const override { return subDTypep()->basicp(); @@ -184,12 +184,12 @@ public: int widthTotalBytes() const override { return elementsConst() * subDTypep()->widthTotalBytes(); } - int left() const; - int right() const; - int hi() const; - int lo() const; - int elementsConst() const; - VNumRange declRange() const; + inline int left() const; + inline int right() const; + inline int hi() const; + inline int lo() const; + inline int elementsConst() const; + inline VNumRange declRange() const; }; class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType { // A struct or union; common handling diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index 498fbce3b..14e9bd2ab 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -341,7 +341,10 @@ public: VAccess access() const { return m_access; } void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable - void varp(AstVar* varp); + void varp(AstVar* varp) { + m_varp = varp; + dtypeFrom((AstNode*)varp); + } AstVarScope* varScopep() const { return m_varScopep; } void varScopep(AstVarScope* varscp) { m_varScopep = varscp; } string selfPointer() const { return m_selfPointer; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index d891a46c4..5bbc6bf42 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -683,6 +683,8 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) { return nullptr; } +bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); } + class AstNodeDType::CTypeRecursed final { public: string m_type; // The base type, e.g.: "Foo_t"s @@ -1490,6 +1492,11 @@ void AstIfaceRefDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "iface"; } +void AstIfaceRefDType::cloneRelink() { + if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep(); + if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep(); + if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); +} void AstInitArray::dump(std::ostream& str) const { this->AstNode::dump(str); int n = 0; diff --git a/src/V3AstUserAllocator.h b/src/V3AstUserAllocator.h index 478c31dfa..1a7f55a46 100644 --- a/src/V3AstUserAllocator.h +++ b/src/V3AstUserAllocator.h @@ -35,7 +35,7 @@ class AstUserAllocatorBase VL_NOT_FINAL { private: std::vector m_allocated; - inline T_Data* getUserp(const T_Node* nodep) const { + T_Data* getUserp(const T_Node* nodep) const { if VL_CONSTEXPR_CXX17 (T_UserN == 1) { const VNUser user = nodep->user1u(); return user.to(); @@ -54,7 +54,7 @@ private: } } - inline void setUserp(T_Node* nodep, T_Data* userp) const { + void setUserp(T_Node* nodep, T_Data* userp) const { if VL_CONSTEXPR_CXX17 (T_UserN == 1) { nodep->user1u(VNUser{userp}); } else if VL_CONSTEXPR_CXX17 (T_UserN == 2) { diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 75fb8c356..dd4978eca 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -132,8 +132,8 @@ private: public: // METHODS void clear() { m_linkable.clear(); } - inline void addLinkable(const AstNode* nodep) { m_linkable.emplace(nodep); } - inline bool isLinkable(const AstNode* nodep) const { return m_linkable.count(nodep) != 0; } + void addLinkable(const AstNode* nodep) { m_linkable.emplace(nodep); } + bool isLinkable(const AstNode* nodep) const { return m_linkable.count(nodep) != 0; } } s_linkableTable; bool V3Broken::isLinkable(const AstNode* nodep) { return s_linkableTable.isLinkable(nodep); } diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index f28e959fc..090009c24 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -44,7 +44,7 @@ private: public: // cppcheck-suppress noExplicitConstructor - inline VCtorType(en _e) + VCtorType(en _e) : m_e{_e} {} bool isClass() const { return m_e == CLASS; } bool isCoverage() const { return m_e == COVERAGE; } diff --git a/src/V3Config.cpp b/src/V3Config.cpp index 5961bf7d0..f716bba2b 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -309,7 +309,7 @@ public: if (lineMatch(lineno, VPragmaType::FULL_CASE)) nodep->fullPragma(true); if (lineMatch(lineno, VPragmaType::PARALLEL_CASE)) nodep->parallelPragma(true); } - inline void applyIgnores(FileLine* filelinep) { + void applyIgnores(FileLine* filelinep) { // HOT routine, called each parsed token line of this filename if (m_lastIgnore.lineno != filelinep->lineno()) { // UINFO(9, " ApplyIgnores for " << filelinep->ascii() << endl); diff --git a/src/V3Error.h b/src/V3Error.h index 077260995..e977a5feb 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -142,13 +142,13 @@ public: }; // clang-format on enum en m_e; - inline V3ErrorCode() + V3ErrorCode() : m_e{EC_MIN} {} // cppcheck-suppress noExplicitConstructor - inline V3ErrorCode(en _e) + V3ErrorCode(en _e) : m_e{_e} {} explicit V3ErrorCode(const char* msgp); // Matching code or ERROR - explicit inline V3ErrorCode(int _e) + explicit V3ErrorCode(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { diff --git a/src/V3File.cpp b/src/V3File.cpp index c4adf58bc..b8c8e6ad6 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -146,7 +146,7 @@ V3FileDependImp dependImp; // Depend implementation class //###################################################################### // V3FileDependImp -inline void V3FileDependImp::writeDepend(const string& filename) { +void V3FileDependImp::writeDepend(const string& filename) { const std::unique_ptr ofp{V3File::new_ofstream(filename)}; if (ofp->fail()) v3fatal("Can't write " << filename); @@ -171,7 +171,7 @@ inline void V3FileDependImp::writeDepend(const string& filename) { } } -inline std::vector V3FileDependImp::getAllDeps() const { +std::vector V3FileDependImp::getAllDeps() const { std::vector r; for (const auto& itr : m_filenameList) { if (!itr.target() && itr.exists()) r.push_back(itr.filename()); @@ -179,7 +179,7 @@ inline std::vector V3FileDependImp::getAllDeps() const { return r; } -inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) { +void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) { const std::unique_ptr ofp{V3File::new_ofstream(filename)}; if (ofp->fail()) v3fatal("Can't write " << filename); @@ -214,7 +214,7 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm } } -inline bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) { +bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) { const std::unique_ptr ifp{V3File::new_ifstream_nodepend(filename)}; if (ifp->fail()) { UINFO(2, " --check-times failed: no input " << filename << endl); diff --git a/src/V3FileLine.h b/src/V3FileLine.h index f16bc5bca..892fb97bd 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -247,7 +247,11 @@ public: // OPERATORS void v3errorEnd(std::ostringstream& str, const string& extra = ""); - void v3errorEndFatal(std::ostringstream& str) VL_ATTR_NORETURN; + void v3errorEndFatal(std::ostringstream& str) VL_ATTR_NORETURN { + v3errorEnd(str); + assert(0); // LCOV_EXCL_LINE + VL_UNREACHABLE + } /// When building an error, prefix for printing continuation lines /// e.g. information referring to the same FileLine as before string warnMore() const; @@ -286,10 +290,4 @@ private: }; std::ostream& operator<<(std::ostream& os, FileLine* fileline); -inline void FileLine::v3errorEndFatal(std::ostringstream& str) { - v3errorEnd(str); - assert(0); // LCOV_EXCL_LINE - VL_UNREACHABLE -} - #endif // Guard diff --git a/src/V3Graph.h b/src/V3Graph.h index a18fb5dfc..9d6b9ea06 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -54,12 +54,12 @@ public: // // an array dimension or loop bound. }; enum en m_e; - inline GraphWay() + GraphWay() : m_e{FORWARD} {} // cppcheck-suppress noExplicitConstructor - inline constexpr GraphWay(en _e) + constexpr GraphWay(en _e) : m_e{_e} {} - explicit inline constexpr GraphWay(int _e) + explicit constexpr GraphWay(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 00ab8564f..8860a5479 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -121,7 +121,7 @@ private: void placeTryEdge(V3GraphEdge* edgep); bool placeIterate(GraphAcycVertex* vertexp, uint32_t currentRank); - inline bool origFollowEdge(V3GraphEdge* edgep) { + bool origFollowEdge(V3GraphEdge* edgep) { return (edgep->weight() && (m_origEdgeFuncp)(edgep)); } V3GraphEdge* edgeFromEdge(V3GraphEdge* oldedgep, V3GraphVertex* fromp, V3GraphVertex* top) { diff --git a/src/V3GraphAlg.h b/src/V3GraphAlg.h index 2cc4ce9b5..6441b2cca 100644 --- a/src/V3GraphAlg.h +++ b/src/V3GraphAlg.h @@ -38,9 +38,7 @@ protected: , m_edgeFuncp{edgeFuncp} {} ~GraphAlg() = default; // METHODS - inline bool followEdge(V3GraphEdge* edgep) { - return (edgep->weight() && (m_edgeFuncp)(edgep)); - } + bool followEdge(V3GraphEdge* edgep) { return (edgep->weight() && (m_edgeFuncp)(edgep)); } }; //============================================================================ diff --git a/src/V3Hash.h b/src/V3Hash.h index 13f86dd6d..c5dd1b631 100644 --- a/src/V3Hash.h +++ b/src/V3Hash.h @@ -26,7 +26,7 @@ class V3Hash final { uint32_t m_value; // The 32-bit hash value. - inline static uint32_t combine(uint32_t a, uint32_t b) { + static uint32_t combine(uint32_t a, uint32_t b) { return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); } diff --git a/src/V3LangCode.h b/src/V3LangCode.h index 0565a948d..1d2d70326 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -55,13 +55,13 @@ public: bool legal() const { return m_e != L_ERROR; } // enum en m_e; - inline V3LangCode() + V3LangCode() : m_e{L_ERROR} {} // cppcheck-suppress noExplicitConstructor - inline V3LangCode(en _e) + V3LangCode(en _e) : m_e{_e} {} explicit V3LangCode(const char* textp); - explicit inline V3LangCode(int _e) + explicit V3LangCode(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; diff --git a/src/V3Life.cpp b/src/V3Life.cpp index d33a47291..5ae48ebd4 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -94,18 +94,18 @@ public: consumed(); } ~LifeVarEntry() = default; - inline void simpleAssign(AstNodeAssign* assp) { // New simple A=.... assignment + void simpleAssign(AstNodeAssign* assp) { // New simple A=.... assignment m_assignp = assp; m_constp = nullptr; m_everSet = true; if (VN_IS(assp->rhsp(), Const)) m_constp = VN_AS(assp->rhsp(), Const); } - inline void complexAssign() { // A[x]=... or some complicated assignment + void complexAssign() { // A[x]=... or some complicated assignment m_assignp = nullptr; m_constp = nullptr; m_everSet = true; } - inline void consumed() { // Rvalue read of A + void consumed() { // Rvalue read of A m_assignp = nullptr; } AstNodeAssign* assignp() const { return m_assignp; } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 4168a0b83..2825daaf7 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1966,7 +1966,7 @@ private: nodep->v3error("Illegal call of a task as a function: " << nodep->prettyNameQ()); } } - inline void checkNoDot(AstNode* nodep) { + void checkNoDot(AstNode* nodep) { if (VL_UNLIKELY(m_ds.m_dotPos != DP_NONE)) { // UINFO(9, "ds=" << m_ds.ascii() << endl); nodep->v3error("Syntax Error: Not expecting " << nodep->type() << " under a " diff --git a/src/V3Options.h b/src/V3Options.h index 028171c5a..6c0eea7fe 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -39,12 +39,12 @@ class VOptionBool final { public: enum en : uint8_t { OPT_DEFAULT_FALSE = 0, OPT_DEFAULT_TRUE, OPT_TRUE, OPT_FALSE }; enum en m_e; - inline VOptionBool() + VOptionBool() : m_e{OPT_DEFAULT_FALSE} {} // cppcheck-suppress noExplicitConstructor - inline VOptionBool(en _e) + VOptionBool(en _e) : m_e{_e} {} - explicit inline VOptionBool(int _e) + explicit VOptionBool(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; } @@ -78,12 +78,12 @@ public: enum : uint8_t { TS_DEFAULT = TS_1PS }; enum en m_e; // CONSTRUCTOR - inline VTimescale() + VTimescale() : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor - inline VTimescale(en _e) + VTimescale(en _e) : m_e{_e} {} - explicit inline VTimescale(int _e) + explicit VTimescale(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning // Construct from string VTimescale(const string& value, bool& badr); @@ -131,9 +131,9 @@ class TraceFormat final { public: enum en : uint8_t { VCD = 0, FST } m_e; // cppcheck-suppress noExplicitConstructor - inline TraceFormat(en _e = VCD) + TraceFormat(en _e = VCD) : m_e{_e} {} - explicit inline TraceFormat(int _e) + explicit TraceFormat(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool fst() const { return m_e == FST; } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 3c0aee447..539d6b6fa 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -816,7 +816,7 @@ public: OrderMoveDomScope::DomScopeMap OrderMoveDomScope::s_dsMap; -inline std::ostream& operator<<(std::ostream& lhs, const OrderMoveDomScope& rhs) { +std::ostream& operator<<(std::ostream& lhs, const OrderMoveDomScope& rhs) { lhs << rhs.name(); return lhs; } @@ -1349,7 +1349,7 @@ public: // OrderMoveDomScope methods // Check the domScope is on ready list, add if not -inline void OrderMoveDomScope::ready(OrderProcess* opp) { +void OrderMoveDomScope::ready(OrderProcess* opp) { if (!m_onReadyList) { m_onReadyList = true; m_readyDomScopeE.pushBack(opp->m_pomReadyDomScope, this); @@ -1357,7 +1357,7 @@ inline void OrderMoveDomScope::ready(OrderProcess* opp) { } // Mark one vertex as finished, remove from ready list if done -inline void OrderMoveDomScope::movedVertex(OrderProcess* opp, OrderMoveVertex* vertexp) { +void OrderMoveDomScope::movedVertex(OrderProcess* opp, OrderMoveVertex* vertexp) { UASSERT_OBJ(m_onReadyList, vertexp, "Moving vertex from ready when nothing was on que as ready."); if (m_readyVertices.empty()) { // Else more work to get to later diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 08c0a54e8..127253002 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -87,12 +87,12 @@ struct OrderVEdgeType { return names[m_e]; } enum en m_e; - inline OrderVEdgeType() + OrderVEdgeType() : m_e{VERTEX_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - inline OrderVEdgeType(en _e) + OrderVEdgeType(en _e) : m_e{_e} {} - explicit inline OrderVEdgeType(int _e) + explicit OrderVEdgeType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; diff --git a/src/V3PreLex.h b/src/V3PreLex.h index 804b29e86..8ce783957 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -143,7 +143,7 @@ public: ~VPreStream() { lexStreamDepthAdd(-1); } private: - void lexStreamDepthAdd(int delta); + inline void lexStreamDepthAdd(int delta); }; //====================================================================== @@ -237,6 +237,6 @@ private: void scanSwitchStream(VPreStream* streamp); }; -inline void VPreStream::lexStreamDepthAdd(int delta) { m_lexp->streamDepthAdd(delta); } +void VPreStream::lexStreamDepthAdd(int delta) { m_lexp->streamDepthAdd(delta); } #endif // Guard diff --git a/src/V3String.cpp b/src/V3String.cpp index 1a42ee2e7..54fcfac07 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -31,7 +31,7 @@ std::map VName::s_dehashMap; // Wildcard // Double procedures, inlined, unrolls loop much better -inline bool VString::wildmatchi(const char* s, const char* p) { +bool VString::wildmatchi(const char* s, const char* p) { for (; *p; s++, p++) { if (*p != '*') { if (((*s) != (*p)) && *p != '?') return false; @@ -193,13 +193,11 @@ static const uint32_t sha256K[] 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; -static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) VL_ATTR_ALWINLINE; -static inline uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) { - return lhs >> rhs | lhs << (32 - rhs); -} +VL_ATTR_ALWINLINE +static uint32_t shaRotr32(uint32_t lhs, uint32_t rhs) { return lhs >> rhs | lhs << (32 - rhs); } -static inline void sha256Block(uint32_t* h, const uint32_t* chunk) VL_ATTR_ALWINLINE; -static inline void sha256Block(uint32_t* h, const uint32_t* chunk) { +VL_ATTR_ALWINLINE +static void sha256Block(uint32_t* h, const uint32_t* chunk) { uint32_t ah[8]; const uint32_t* p = chunk; diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index eda173f78..d671e23f3 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -255,7 +255,7 @@ private: return entryp; } } - inline bool isSubstVar(AstVar* nodep) { return nodep->isStatementTemp() && !nodep->noSubst(); } + bool isSubstVar(AstVar* nodep) { return nodep->isStatementTemp() && !nodep->noSubst(); } // VISITORS void visit(AstNodeAssign* nodep) override { diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index c89e1f3b9..26055725d 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -122,7 +122,7 @@ public: (new V3GraphEdge(this, tp, fp, cost))->user(userValue); } - inline static uint32_t getEdgeId(const V3GraphEdge* edgep) { + static uint32_t getEdgeId(const V3GraphEdge* edgep) { return static_cast(edgep->user()); } @@ -138,7 +138,7 @@ private: // We will keep sorted lists of edges as vectors using EdgeList = std::vector; - inline static bool edgeCmp(const V3GraphEdge* ap, const V3GraphEdge* bp) { + static bool edgeCmp(const V3GraphEdge* ap, const V3GraphEdge* bp) { // We pre-computed these when adding the edge to sort first by cost, then by identity return ap->user() > bp->user(); } @@ -150,7 +150,7 @@ private: } }; - inline static Vertex* castVertexp(V3GraphVertex* vxp) { return static_cast(vxp); } + static Vertex* castVertexp(V3GraphVertex* vxp) { return static_cast(vxp); } public: // From *this, populate *mstp with the minimum spanning tree. diff --git a/test_regress/t/TestVpi.h b/test_regress/t/TestVpi.h index 389707823..40734b7c6 100644 --- a/test_regress/t/TestVpi.h +++ b/test_regress/t/TestVpi.h @@ -29,7 +29,7 @@ public: , m_freeit(true) {} ~TestVpiHandle() { release(); } operator vpiHandle() const { return m_handle; } - inline TestVpiHandle& operator=(vpiHandle h) { + TestVpiHandle& operator=(vpiHandle h) { release(); m_handle = h; return *this; diff --git a/test_regress/t/t_dist_cppstyle.pl b/test_regress/t/t_dist_cppstyle.pl index a54fef2dd..7a8f23e5d 100755 --- a/test_regress/t/t_dist_cppstyle.pl +++ b/test_regress/t/t_dist_cppstyle.pl @@ -24,8 +24,22 @@ foreach my $file (sort keys %files) { my $contents = file_contents($filename); checkPattern($filename, $contents, - qr/virtual[^{};]+override/, + qr/[^\/]*virtual[^{};]+override/, "'virtual' keyword is redundant on 'override' method"); + + checkPattern($filename, $contents, + qr/ \s*(\w+ )*\s*(inline) [^;]+?\([^;]*?\)[^;]+?(?:{|:|=\s*default)/, + "'inline' keyword is redundant on method definitions inside classes"); + + checkPattern($filename, $contents, + qr/(?\n)inline \S+ [^;:(]+::[^;:(]+\([^;]*\)[^;]+{/, + "Use 'inline' only on declaration inside classes (except for template specializatoins)"); + + if ($file =~ /\.(c|cpp)/) { + checkPattern($filename, $contents, + qr/(\w+\s+)*(inline)/, + "'inline' keyword is on functions defined in .cpp files"); + } } ok(1); @@ -51,8 +65,8 @@ sub checkPattern { my $offset = 0; my $buffer = $contents; - while ($buffer =~ s/.*?^[^\/]*($pattern)//sm) { - my $lineno = offset_to_lineno($contents, $offset + $-[1]); + while ($buffer =~ s/.*?^($pattern)//sm) { + my $lineno = offset_to_lineno($contents, $offset + $-[-1]); $offset += $+[1]; error("$filename:$lineno: $message"); } diff --git a/test_regress/t/t_extend_class_c.h b/test_regress/t/t_extend_class_c.h index c5e98001b..a1cdd58dc 100644 --- a/test_regress/t/t_extend_class_c.h +++ b/test_regress/t/t_extend_class_c.h @@ -13,5 +13,5 @@ public: ~t_extend_class_c() = default; // METHODS // This function will be called from a instance created in Verilog - inline uint32_t my_math(uint32_t in) { return in + 1; } + uint32_t my_math(uint32_t in) { return in + 1; } }; From d6bfb37e6a51693953ed0cffcdae2e642e589cc9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 17 Sep 2022 07:47:06 -0400 Subject: [PATCH 42/75] Docker: Use 22.04 --- ci/docker/buildenv/Dockerfile | 2 +- ci/docker/buildenv/README.rst | 2 +- ci/docker/run/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/docker/buildenv/Dockerfile b/ci/docker/buildenv/Dockerfile index 7e6682357..7adf4b3d2 100644 --- a/ci/docker/buildenv/Dockerfile +++ b/ci/docker/buildenv/Dockerfile @@ -6,7 +6,7 @@ # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive \ diff --git a/ci/docker/buildenv/README.rst b/ci/docker/buildenv/README.rst index 5e7110c84..3ff025fc9 100644 --- a/ci/docker/buildenv/README.rst +++ b/ci/docker/buildenv/README.rst @@ -8,7 +8,7 @@ Verilator build. It uses the following parameters: - Source revision (default: master) -- Compiler (GCC 9.3.0, clang 10.0.0, default: 9.3.0) +- Compiler (GCC 10.3.0, clang 10.0.0, default: 10.3.0) The container is published as ``verilator/verilator-buildenv`` on `docker hub diff --git a/ci/docker/run/Dockerfile b/ci/docker/run/Dockerfile index 18c40483f..fa5c98519 100644 --- a/ci/docker/run/Dockerfile +++ b/ci/docker/run/Dockerfile @@ -6,7 +6,7 @@ # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -FROM ubuntu:20.04 +FROM ubuntu:22.04 RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive \ From a548a77f268313ccc4b6b9d4cd3402492a4d93ec Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 17 Sep 2022 07:58:56 -0400 Subject: [PATCH 43/75] Merge branch 'develop-v5' into master: Changes file --- docs/CONTRIBUTORS | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 83ab9f830..7a800bab7 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -90,6 +90,7 @@ Nathan Kohagen Nathan Myers Patrick Stewart Paul Wright +Pawel Sagan Peter Horvath Peter Monsson Philipp Wagner From 80b73859a2b0b30cd5729431a4554a0dd14069f5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 17 Sep 2022 08:00:40 -0400 Subject: [PATCH 44/75] Commentary: Some fixes from 'develop-v5' --- bin/verilator | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/verilator b/bin/verilator index 852ad516c..b6495eee5 100755 --- a/bin/verilator +++ b/bin/verilator @@ -344,7 +344,7 @@ detailed descriptions of these arguments. --lint-only Lint, but do not make output --make Generate scripts for specified build tool -MAKEFLAGS Arguments to pass to make during --build - --main Generate C++ main() + --main Generate C++ main() file --max-num-width Maximum number width (default: 64K) --Mdir Name of output object directory --MMD Create .d dependency files @@ -356,6 +356,7 @@ detailed descriptions of these arguments. -O Selectable optimizations -o Name of final executable --no-order-clock-delay Disable ordering clock enable assignments + --no-verilate Skip Verilation, only compile previously Verilated code --output-split Split .cpp files into pieces --output-split-cfuncs Split model functions --output-split-ctrace Split tracing functions From 11b0d36ba2e56b985d983008308d2c2d2e5f8d62 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 17 Sep 2022 08:17:22 -0400 Subject: [PATCH 45/75] Merge cleanups from 'develop-v5'. No functional change --- src/V3OrderGraph.h | 2 +- src/verilog.y | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index 127253002..fb1fa67dc 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -1,6 +1,6 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* -// DESCRIPTION: Verilator: Block code ordering +// DESCRIPTION: Verilator: Ordering constraint graph // // Code available from: https://verilator.org // diff --git a/src/verilog.y b/src/verilog.y index 3eba4ed3b..c6a7048de 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -302,11 +302,12 @@ int V3ParseGrammar::s_modTypeImpNum = 0; #define APPLY_STRENGTH_TO_LIST(beginp, strengthSpecNodep, typeToCast) \ { \ - if (AstStrengthSpec* specp = VN_CAST(strengthSpecNodep, StrengthSpec)) \ + if (AstStrengthSpec* specp = VN_CAST(strengthSpecNodep, StrengthSpec)) { \ for (auto* nodep = beginp; nodep; nodep = nodep->nextp()) { \ auto* const assignp = VN_AS(nodep, typeToCast); \ assignp->strengthSpecp(nodep == beginp ? specp : specp->cloneTree(false)); \ } \ + } \ } static void ERRSVKWD(FileLine* fileline, const string& tokname) { From 79be097e346ce6d5babeb079ed33068dbe4ce8ea Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 17 Sep 2022 08:17:47 -0400 Subject: [PATCH 46/75] Sort -V env variable output --- src/V3Options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 10d83bd1b..644ea6961 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1758,9 +1758,9 @@ void V3Options::showVersion(bool verbose) { cout << " SYSTEMC_ARCH = " << V3Os::getenvStr("SYSTEMC_ARCH", "") << endl; cout << " SYSTEMC_INCLUDE = " << V3Os::getenvStr("SYSTEMC_INCLUDE", "") << endl; cout << " SYSTEMC_LIBDIR = " << V3Os::getenvStr("SYSTEMC_LIBDIR", "") << endl; - cout << " VERILATOR_ROOT = " << V3Os::getenvStr("VERILATOR_ROOT", "") << endl; - // wrapper uses this: + // wrapper uses VERILATOR_BIN cout << " VERILATOR_BIN = " << V3Os::getenvStr("VERILATOR_BIN", "") << endl; + cout << " VERILATOR_ROOT = " << V3Os::getenvStr("VERILATOR_ROOT", "") << endl; cout << endl; cout << "Features (based on environment or compiled-in support):\n"; From 7d88e63babd05a0de1095b2e37084dc530c4ba5d Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 17 Sep 2022 13:48:51 +0100 Subject: [PATCH 47/75] astgen: generate type specific addNext, remove astNextNull Generate type specific static overloads of Ast::addNext, which return the correct sub-type of the 'this' they were invoked on. Also remove AstNode::addNextNull, which is now only used in the parser, implement in verilog.y directly as a template function. --- src/V3Ast.cpp | 6 -- src/V3Ast.h | 21 ++-- src/V3AstInlines.h | 7 -- src/V3Begin.cpp | 6 +- src/V3Coverage.cpp | 2 +- src/V3Descope.cpp | 6 +- src/V3LinkParse.cpp | 18 ++-- src/V3ParseGrammar.cpp | 9 +- src/V3Slice.cpp | 2 +- src/V3Task.cpp | 6 +- src/V3Unroll.cpp | 6 +- src/V3VariableOrder.cpp | 2 +- src/astgen | 1 + src/verilog.y | 210 +++++++++++++++++++++------------------- 14 files changed, 142 insertions(+), 160 deletions(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 4a516e6be..24c4d0e12 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -272,12 +272,6 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { return nodep; } -template <> -AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) { - if (!newp) return nodep; - return addNext(nodep, newp); -} - void AstNode::addNextHere(AstNode* newp) { // Add to m_nextp on exact node passed, not at the end. // This could be at head, tail, or both (single) diff --git a/src/V3Ast.h b/src/V3Ast.h index 90a203042..87349cc68 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1797,19 +1797,9 @@ public: "'T_NodeNext' must be a subtype of 'T_NodeResult'"); return static_cast(addNext(nodep, newp)); } - // Returns nodep, adds newp (maybe nullptr) to end of nodep's list - template - static T_NodeResult* addNextNull(T_NodeResult* nodep, T_NodeNext* newp) { - static_assert(std::is_base_of::value, - "'T_NodeResult' must be a subtype of AstNode"); - static_assert(std::is_base_of::value, - "'T_NodeNext' must be a subtype of 'T_NodeResult'"); - return static_cast(addNextNull(nodep, newp)); - } inline AstNode* addNext(AstNode* newp); - inline AstNode* addNextNull(AstNode* newp); - void addNextHere(AstNode* newp); // Insert newp at this->nextp inline void addPrev(AstNode* newp); + void addNextHere(AstNode* newp); // Insert newp at this->nextp void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node AstNode* unlinkFrBack(VNRelinker* linkerp @@ -2100,8 +2090,13 @@ public: // Forward declarations of specializations defined in V3Ast.cpp template <> AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp); -template <> -AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp); + +// Inline method implementations +AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); } +void AstNode::addPrev(AstNode* newp) { + replaceWith(newp); + newp->addNext(this); +} // Specialisations of privateTypeTest #include "V3Ast__gen_impl.h" // From ./astgen diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 9ffb7fa5c..2deceda22 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -25,13 +25,6 @@ //###################################################################### // Inline METHODS -AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); } -AstNode* AstNode::addNextNull(AstNode* newp) { return addNextNull(this, newp); } -void AstNode::addPrev(AstNode* newp) { - replaceWith(newp); - newp->addNext(this); -} - int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; } int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; } bool AstNode::width1() const { // V3Const uses to know it can optimize diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 9f65dd79a..c9ceec09e 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -177,11 +177,7 @@ private: AstNode* addsp = nullptr; if (AstNode* const stmtsp = nodep->stmtsp()) { stmtsp->unlinkFrBackWithNext(); - if (addsp) { - addsp = addsp->addNextNull(stmtsp); - } else { - addsp = stmtsp; - } + addsp = AstNode::addNext(addsp, stmtsp); } if (addsp) { nodep->replaceWith(addsp); diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index a5e8b1dc3..04266c492 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -134,7 +134,7 @@ private: incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::WRITE), new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::READ), new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1))); - incp->addNext(assp); + AstNode::addNext(incp, assp); } return incp; } diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 544bac417..835294f74 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -139,14 +139,14 @@ private: UINFO(6, " at " << newfuncp->argTypes() << " und " << funcp->argTypes() << endl); funcp->declPrivate(true); - AstNode* argsp = nullptr; + AstVarRef* argsp = nullptr; for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* const portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn()) { - AstNode* const newp = new AstVarRef( + AstVarRef* const newp = new AstVarRef( portp->fileline(), portp, portp->isWritable() ? VAccess::WRITE : VAccess::READ); - argsp = argsp ? argsp->addNextNull(newp) : newp; + argsp = AstNode::addNext(argsp, newp); } } } diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 2a4ce4bc0..b0a8e4001 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -177,21 +177,17 @@ private: const int right = nodep->rangep()->rightConst(); const int increment = (left > right) ? -1 : 1; int offset_from_init = 0; - AstNode* addp = nullptr; + AstEnumItem* addp = nullptr; + FileLine* const flp = nodep->fileline(); for (int i = left; i != (right + increment); i += increment, offset_from_init++) { const string name = nodep->name() + cvtToStr(i); AstNode* valuep = nullptr; if (nodep->valuep()) { - valuep = new AstAdd( - nodep->fileline(), nodep->valuep()->cloneTree(true), - new AstConst(nodep->fileline(), AstConst::Unsized32(), offset_from_init)); - } - AstNode* const newp = new AstEnumItem(nodep->fileline(), name, nullptr, valuep); - if (addp) { - addp = addp->addNextNull(newp); - } else { - addp = newp; + valuep + = new AstAdd(flp, nodep->valuep()->cloneTree(true), + new AstConst(flp, AstConst::Unsized32(), offset_from_init)); } + addp = AstNode::addNext(addp, new AstEnumItem{flp, name, nullptr, valuep}); } nodep->replaceWith(addp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -372,7 +368,7 @@ private: iterateChildren(nodep); if (m_varp) { nodep->unlinkFrBack(); - m_varp->addNext(nodep); + AstNode::addNext(m_varp, nodep); // lvalue is true, because we know we have a verilator public_flat_rw // but someday we may be more general const bool lvalue = m_varp->isSigUserRWPublic(); diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 66670338e..5655a1d96 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -76,7 +76,6 @@ AstArg* V3ParseGrammar::argWrapList(AstNode* nodep) { AstNode* const nextp = nodep->nextp(); AstNode* const exprp = nodep->unlinkFrBack(); nodep = nextp; - // addNext can handle nulls: outp = AstNode::addNext(outp, new AstArg(exprp->fileline(), "", exprp)); } VL_DO_DANGLING(tempp->deleteTree(), tempp); @@ -204,15 +203,17 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, } if (GRAMMARP->m_varDecl == VVarType::SUPPLY0) { - nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0)); + AstNode::addNext( + nodep, V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 0)); } if (GRAMMARP->m_varDecl == VVarType::SUPPLY1) { - nodep->addNext(V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); + AstNode::addNext( + nodep, V3ParseGrammar::createSupplyExpr(fileline, nodep->name(), 1)); } if (VN_IS(dtypep, ParseTypeDType)) { // Parser needs to know what is a type AstNode* const newp = new AstTypedefFwd(fileline, name); - nodep->addNext(newp); + AstNode::addNext(nodep, newp); SYMP->reinsert(newp); } // Don't set dtypep in the ranging; diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index c5a993e75..f362c3cb7 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -147,7 +147,7 @@ class SliceVisitor final : public VNVisitor { cloneAndSel(nodep->rhsp(), elements, offset)), NodeAssign); if (debug() >= 9) newp->dumpTree(cout, "-new "); - newlistp = AstNode::addNextNull(newlistp, newp); + newlistp = AstNode::addNext(newlistp, newp); } if (debug() >= 9) nodep->dumpTree(cout, " Deslice-Dn: "); nodep->replaceWith(newlistp); diff --git a/src/V3Task.cpp b/src/V3Task.cpp index c298f8ed4..0ab7392fd 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -496,7 +496,7 @@ private: // Put assignment in FRONT of all other statements if (AstNode* const afterp = beginp->nextp()) { afterp->unlinkFrBackWithNext(); - assp->addNext(afterp); + AstNode::addNext(assp, afterp); } beginp->addNext(assp); } @@ -819,7 +819,7 @@ private: AstVarRef* const refp = new AstVarRef(portp->fileline(), outvscp, portp->isWritable() ? VAccess::WRITE : VAccess::READ); - argnodesp = argnodesp->addNextNull(refp); + argnodesp = argnodesp->addNext(refp); if (portp->isNonOutput()) { std::string frName @@ -847,7 +847,7 @@ private: outvscp->varp()->protect(false); AstVarRef* const refp = new AstVarRef( portp->fileline(), outvscp, portp->isWritable() ? VAccess::WRITE : VAccess::READ); - argnodesp = argnodesp->addNextNull(refp); + argnodesp = argnodesp->addNext(refp); } { // Call the user function diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 8c9bf96dd..1efbef18b 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -279,15 +279,15 @@ private: } if (precondsp) { precondsp->unlinkFrBackWithNext(); - stmtsp = AstNode::addNextNull(stmtsp, precondsp); + stmtsp = AstNode::addNext(stmtsp, precondsp); } if (bodysp) { bodysp->unlinkFrBackWithNext(); - stmtsp = AstNode::addNextNull(stmtsp, bodysp); // Maybe null if no body + stmtsp = AstNode::addNext(stmtsp, bodysp); // Maybe null if no body } if (incp && !VN_IS(nodep, GenFor)) { // Generates don't need to increment loop index incp->unlinkFrBackWithNext(); - stmtsp = AstNode::addNextNull(stmtsp, incp); // Maybe null if no body + stmtsp = AstNode::addNext(stmtsp, incp); // Maybe null if no body } // Mark variable to disable some later warnings m_forVarp->usedLoopIdx(true); diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp index 5bd51933d..53e53788e 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -186,7 +186,7 @@ class VariableOrder final { for (; it != varps.cend(); ++it) firstp->addNext(*it); if (AstNode* const stmtsp = modp->stmtsp()) { stmtsp->unlinkFrBackWithNext(); - firstp->addNext(stmtsp); + AstNode::addNext(firstp, stmtsp); } modp->addStmtp(firstp); } diff --git a/src/astgen b/src/astgen index 98d0750fe..19a6d0b19 100755 --- a/src/astgen +++ b/src/astgen @@ -748,6 +748,7 @@ def write_macros(filename): return static_cast(AstNode::cloneTree(cloneNext)); }} Ast{t}* clonep() const {{ return static_cast(AstNode::clonep()); }} + Ast{t}* addNext(Ast{t}* nodep) {{ return static_cast(AstNode::addNext(this, nodep)); }} ''', t=node.name) diff --git a/src/verilog.y b/src/verilog.y index c6a7048de..4d3c38bc3 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -139,7 +139,7 @@ public: } AstDisplay* createDisplayError(FileLine* fileline) { AstDisplay* nodep = new AstDisplay(fileline, VDisplayType::DT_ERROR, "", nullptr, nullptr); - nodep->addNext(new AstStop(fileline, true)); + AstNode::addNext(nodep, new AstStop(fileline, true)); return nodep; } AstNode* createGatePin(AstNode* exprp) { @@ -330,6 +330,12 @@ static void UNSUPREAL(FileLine* fileline) { void yyerror(const char* errmsg) { PARSEP->bisonLastFileline()->v3error(errmsg); } +template +static T_Node* addNextNull(T_Node* nodep, T_Next* nextp) { + if (!nextp) return nodep; + return AstNode::addNext(nodep, nextp); +} + //====================================================================== class AstSenTree; @@ -1138,7 +1144,7 @@ package_itemListE: // IEEE: [{ package_item }] package_itemList: // IEEE: { package_item } package_item { $$ = $1; } - | package_itemList package_item { $$ = $1->addNextNull($2); } + | package_itemList package_item { $$ = addNextNull($1, $2); } ; package_item: // ==IEEE: package_item @@ -1167,7 +1173,7 @@ package_or_generate_item_declaration: // ==IEEE: package_or_generate_i package_import_declarationList: package_import_declaration { $$ = $1; } - | package_import_declarationList package_import_declaration { $$ = $1->addNextNull($2); } + | package_import_declarationList package_import_declaration { $$ = addNextNull($1, $2); } ; package_import_declaration: // ==IEEE: package_import_declaration @@ -1176,7 +1182,7 @@ package_import_declaration: // ==IEEE: package_import_declaration package_import_itemList: package_import_item { $$ = $1; } - | package_import_itemList ',' package_import_item { $$ = $1->addNextNull($3); } + | package_import_itemList ',' package_import_item { $$ = addNextNull($1, $3); } ; package_import_item: // ==IEEE: package_import_item @@ -1204,7 +1210,7 @@ package_export_declaration: // IEEE: package_export_declaration package_export_itemList: package_export_item { $$ = $1; } - | package_export_itemList ',' package_export_item { $$ = $1->addNextNull($3); } + | package_export_itemList ',' package_export_item { $$ = addNextNull($1, $3); } ; package_export_item: // ==IEEE: package_export_item @@ -1261,7 +1267,7 @@ modFront: importsAndParametersE: // IEEE: common part of module_declaration, interface_declaration, program_declaration // // { package_import_declaration } [ parameter_port_list ] parameter_port_listE { $$ = $1; } - | package_import_declarationList parameter_port_listE { $$ = $1->addNextNull($2); } + | package_import_declarationList parameter_port_listE { $$ = addNextNull($1, $2); } ; udpFront: @@ -1332,12 +1338,12 @@ portsStarE: // IEEE: .* + list_of_ports + list_of_port_decla list_of_portsE: // IEEE: list_of_ports + list_of_port_declarations portAndTagE { $$ = $1; } - | list_of_portsE ',' portAndTagE { $$ = $1->addNextNull($3); } + | list_of_portsE ',' portAndTagE { $$ = addNextNull($1, $3); } ; list_of_ports: // IEEE: list_of_ports + list_of_port_declarations portAndTag { $$ = $1; } - | list_of_portsE ',' portAndTagE { $$ = $1->addNextNull($3); } + | list_of_portsE ',' portAndTagE { $$ = addNextNull($1, $3); } ; portAndTagE: @@ -1375,11 +1381,11 @@ port: // ==IEEE: port portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE { $$ = $3; VARDECL(IFACEREF); VARIO(NONE); VARDTYPE(new AstIfaceRefDType($2,"",*$2)); - $$->addNextNull(VARDONEP($$,$4,$5)); } + addNextNull($$, VARDONEP($$,$4,$5)); } | portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE { $$ = $5; VARDECL(IFACEREF); VARIO(NONE); VARDTYPE(new AstIfaceRefDType($2, $4, "", *$2, *$4)); - $$->addNextNull(VARDONEP($$,$6,$7)); } + addNextNull($$, VARDONEP($$,$6,$7)); } | portDirNetE yINTERFACE portSig rangeListE sigAttrListE { $$ = nullptr; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } | portDirNetE yINTERFACE '.' idAny/*modport*/ portSig rangeListE sigAttrListE @@ -1430,29 +1436,29 @@ port: // ==IEEE: port //UNSUP { UNSUP } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE - { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); } + { $$=$3; VARDTYPE($2); addNextNull($$, VARDONEP($$,$4,$5)); } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE - { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } + { $$=$4; VARDTYPE($3); addNextNull($$, VARDONEP($$,$5,$6)); } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE - { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } + { $$=$4; VARDTYPE($3); addNextNull($$, VARDONEP($$,$5,$6)); } | portDirNetE signing portSig variable_dimensionListE sigAttrListE { $$=$3; VARDTYPE_NDECL(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2)); - $$->addNextNull(VARDONEP($$, $4, $5)); } + addNextNull($$, VARDONEP($$, $4, $5)); } | portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE_NDECL(GRAMMARP->addRange( new AstBasicDType{$3->fileline(), LOGIC_IMPLICIT, $2}, $3, true)); - $$->addNextNull(VARDONEP($$, $5, $6)); } + addNextNull($$, VARDONEP($$, $5, $6)); } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE - { $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); } + { $$=$2; /*VARDTYPE-same*/ addNextNull($$, VARDONEP($$,$3,$4)); } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$3; VARDTYPE($2); if (AstVar* vp = VARDONEP($$, $4, $5)) { $$->addNextNull(vp); vp->valuep($7); } } + { $$=$3; VARDTYPE($2); if (AstVar* vp = VARDONEP($$, $4, $5)) { addNextNull($$, vp); vp->valuep($7); } } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$4; VARDTYPE($3); if (AstVar* vp = VARDONEP($$, $5, $6)) { $$->addNextNull(vp); vp->valuep($8); } } + { $$=$4; VARDTYPE($3); if (AstVar* vp = VARDONEP($$, $5, $6)) { addNextNull($$, vp); vp->valuep($8); } } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$4; VARDTYPE($3); if (AstVar* vp = VARDONEP($$, $5, $6)) { $$->addNextNull(vp); vp->valuep($8); } } + { $$=$4; VARDTYPE($3); if (AstVar* vp = VARDONEP($$, $5, $6)) { addNextNull($$, vp); vp->valuep($8); } } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$=$2; /*VARDTYPE-same*/ if (AstVar* vp = VARDONEP($$, $3, $4)) { $$->addNextNull(vp); vp->valuep($6); } } + { $$=$2; /*VARDTYPE-same*/ if (AstVar* vp = VARDONEP($$, $3, $4)) { addNextNull($$, vp); vp->valuep($6); } } ; portDirNetE: // IEEE: part of port, optional net type and/or direction @@ -1507,7 +1513,7 @@ interface_itemListE: interface_itemList: interface_item { $$ = $1; } - | interface_itemList interface_item { $$ = $1->addNextNull($2); } + | interface_itemList interface_item { $$ = addNextNull($1, $2); } ; interface_item: // IEEE: interface_item + non_port_interface_item @@ -1555,7 +1561,7 @@ anonymous_program_itemListE: // IEEE: { anonymous_program_item } anonymous_program_itemList: // IEEE: { anonymous_program_item } anonymous_program_item { $$ = $1; } - | anonymous_program_itemList anonymous_program_item { $$ = $1->addNextNull($2); } + | anonymous_program_itemList anonymous_program_item { $$ = addNextNull($1, $2); } ; anonymous_program_item: // ==IEEE: anonymous_program_item @@ -1602,7 +1608,7 @@ program_itemListE: // ==IEEE: [{ program_item }] program_itemList: // ==IEEE: { program_item } program_item { $$ = $1; } - | program_itemList program_item { $$ = $1->addNextNull($2); } + | program_itemList program_item { $$ = addNextNull($1, $2); } ; program_item: // ==IEEE: program_item @@ -1642,7 +1648,7 @@ modport_declaration: // ==IEEE: modport_declaration modport_itemList: // IEEE: part of modport_declaration modport_item { $$ = $1; } - | modport_itemList ',' modport_item { $$ = $1->addNextNull($3); } + | modport_itemList ',' modport_item { $$ = addNextNull($1, $3); } ; modport_item: // ==IEEE: modport_item @@ -1653,7 +1659,7 @@ modport_item: // ==IEEE: modport_item modportPortsDeclList: modportPortsDecl { $$ = $1; } - | modportPortsDeclList ',' modportPortsDecl { $$ = $1->addNextNull($3); } + | modportPortsDeclList ',' modportPortsDecl { $$ = addNextNull($1, $3); } ; // IEEE: modport_ports_declaration + modport_simple_ports_declaration @@ -2004,7 +2010,7 @@ struct_unionDecl: // IEEE: part of data_type struct_union_memberList: // IEEE: { struct_union_member } struct_union_member { $$ = $1; } - | struct_union_memberList struct_union_member { $$ = $1->addNextNull($2); } + | struct_union_memberList struct_union_member { $$ = addNextNull($1, $2); } ; struct_union_member: // ==IEEE: struct_union_member @@ -2017,7 +2023,7 @@ struct_union_member: // ==IEEE: struct_union_member list_of_member_decl_assignments: // Derived from IEEE: list_of_variable_decl_assignments member_decl_assignment { $$ = $1; } - | list_of_member_decl_assignments ',' member_decl_assignment { $$ = $1->addNextNull($3); } + | list_of_member_decl_assignments ',' member_decl_assignment { $$ = addNextNull($1, $3); } ; member_decl_assignment: // Derived from IEEE: variable_decl_assignment @@ -2050,7 +2056,7 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assi list_of_variable_decl_assignments: // ==IEEE: list_of_variable_decl_assignments variable_decl_assignment { $$ = $1; } - | list_of_variable_decl_assignments ',' variable_decl_assignment { $$ = VN_CAST($1->addNextNull($3), Var); } + | list_of_variable_decl_assignments ',' variable_decl_assignment { $$ = addNextNull($1, $3); } ; variable_decl_assignment: // ==IEEE: variable_decl_assignment @@ -2080,7 +2086,7 @@ list_of_tf_variable_identifiers: // ==IEEE: list_of_tf_variable_identifie tf_variable_identifier: // IEEE: part of list_of_tf_variable_identifiers id variable_dimensionListE sigAttrListE exprEqE { $$ = VARDONEA($1,*$1, $2, $3); - if ($4) $$->addNext(new AstAssign($4->fileline(), new AstVarRef($1, *$1, VAccess::WRITE), $4)); } + if ($4) AstNode::addNext($$, new AstAssign($4->fileline(), new AstVarRef($1, *$1, VAccess::WRITE), $4)); } ; variable_declExpr: // IEEE: part of variable_decl_assignment - rhs of expr @@ -2096,7 +2102,7 @@ variable_dimensionListE: // IEEE: variable_dimension + empty variable_dimensionList: // IEEE: variable_dimension + empty variable_dimension { $$ = $1; } - | variable_dimensionList variable_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); } + | variable_dimensionList variable_dimension { $$ = $1->addNext($2); } ; variable_dimension: // ==IEEE: variable_dimension @@ -2173,7 +2179,7 @@ enum_base_typeE: // IEEE: enum_base_type enum_nameList: enum_name_declaration { $$ = $1; } - | enum_nameList ',' enum_name_declaration { $$ = $1->addNextNull($3); } + | enum_nameList ',' enum_name_declaration { $$ = addNextNull($1, $3); } ; enum_name_declaration: // ==IEEE: enum_name_declaration @@ -2364,7 +2370,7 @@ dtypeAttrListE: dtypeAttrList: dtypeAttr { $$ = $1; } - | dtypeAttrList dtypeAttr { $$ = $1->addNextNull($2); } + | dtypeAttrList dtypeAttr { $$ = addNextNull($1, $2); } ; dtypeAttr: @@ -2385,7 +2391,7 @@ module_itemListE: // IEEE: Part of module_declaration module_itemList: // IEEE: Part of module_declaration module_item { $$ = $1; } - | module_itemList module_item { $$ = $1->addNextNull($2); } + | module_itemList module_item { $$ = addNextNull($1, $2); } ; module_item: // ==IEEE: module_item @@ -2573,7 +2579,7 @@ genItemOrBegin: // Not in IEEE, but our begin isn't under genera genItemList: ~c~genItemOrBegin { $$ = $1; } - | ~c~genItemList ~c~genItemOrBegin { $$ = $1->addNextNull($2); } + | ~c~genItemList ~c~genItemOrBegin { $$ = addNextNull($1, $2); } ; //UNSUPc_genItemList: // (for checkers) @@ -2641,7 +2647,7 @@ loop_generate_construct: // ==IEEE: loop_generate_construct genvar_initialization: // ==IEEE: genvar_initialization varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); } | yGENVAR genvar_identifierDecl '=' constExpr - { $$ = $2; $2->addNext(new AstAssign($3, new AstVarRef($2->fileline(), $2, VAccess::WRITE), $4)); } + { $$ = $2; AstNode::addNext($$, new AstAssign($3, new AstVarRef($2->fileline(), $2, VAccess::WRITE), $4)); } ; genvar_iteration: // ==IEEE: genvar_iteration @@ -2763,7 +2769,7 @@ netSig: // IEEE: net_decl_assignment - one element from auto* const assignp = new AstAssignW{$3, new AstVarRef{$1, *$1, VAccess::WRITE}, $4}; if (GRAMMARP->m_netStrengthp) assignp->strengthSpecp(GRAMMARP->m_netStrengthp->cloneTree(false)); if ($$->delayp()) assignp->addTimingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3 - $$->addNext(assignp); } | netId variable_dimensionList sigAttrListE + AstNode::addNext($$, assignp); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } ; @@ -2779,7 +2785,7 @@ sigAttrListE: sigAttrList: sigAttr { $$ = $1; } - | sigAttrList sigAttr { $$ = $1->addNextNull($2); } + | sigAttrList sigAttr { $$ = addNextNull($1, $2); } ; sigAttr: @@ -2806,7 +2812,7 @@ rangeListE: // IEEE: [{packed_dimension}] rangeList: // IEEE: {packed_dimension} anyrange { $$ = $1; } - | rangeList anyrange { $$ = $1; $1->addNext($2); } + | rangeList anyrange { $$ = $1->addNext($2); } ; //UNSUPbit_selectE: // IEEE: constant_bit_select (IEEE included empty) @@ -2828,7 +2834,7 @@ packed_dimensionListE: // IEEE: [{ packed_dimension }] packed_dimensionList: // IEEE: { packed_dimension } packed_dimension { $$ = $1; } - | packed_dimensionList packed_dimension { $$ = VN_CAST($1->addNext($2), NodeRange); } + | packed_dimensionList packed_dimension { $$ = $1->addNext($2); } ; packed_dimension: // ==IEEE: packed_dimension @@ -2857,7 +2863,7 @@ param_assignment: // ==IEEE: param_assignment list_of_param_assignments: // ==IEEE: list_of_param_assignments param_assignment { $$ = $1; } - | list_of_param_assignments ',' param_assignment { $$ = $1; $1->addNext($3); } + | list_of_param_assignments ',' param_assignment { $$ = $1->addNext($3); } ; type_assignment: // ==IEEE: type_assignment @@ -2868,7 +2874,7 @@ type_assignment: // ==IEEE: type_assignment list_of_type_assignments: // ==IEEE: list_of_type_assignments type_assignment { $$ = $1; } - | list_of_type_assignments ',' type_assignment { $$ = $1; $1->addNext($3); } + | list_of_type_assignments ',' type_assignment { $$ = $1->addNext($3); } ; list_of_defparam_assignments: //== IEEE: list_of_defparam_assignments @@ -2948,7 +2954,7 @@ instRangeListE: instRangeList: instRange { $$ = $1; } - | instRangeList instRange { $$ = VN_CAST($1->addNextNull($2), Range); } + | instRangeList instRange { $$ = addNextNull($1, $2); } ; instRange: @@ -2968,12 +2974,12 @@ cellpinList: cellparamItList: // IEEE: list_of_parameter_assignmente cellparamItemE { $$ = $1; } - | cellparamItList ',' cellparamItemE { $$ = VN_CAST($1->addNextNull($3), Pin); } + | cellparamItList ',' cellparamItemE { $$ = addNextNull($1, $3); } ; cellpinItList: // IEEE: list_of_port_connections cellpinItemE { $$ = $1; } - | cellpinItList ',' cellpinItemE { $$ = VN_CAST($1->addNextNull($3), Pin); } + | cellpinItList ',' cellpinItemE { $$ = addNextNull($1, $3); } ; cellparamItemE: // IEEE: named_parameter_assignment + empty @@ -3051,11 +3057,11 @@ event_control: // ==IEEE: event_control event_expression: // IEEE: event_expression - split over several //UNSUP // Below are all removed senitem { $$ = $1; } - | event_expression yOR senitem { $$ = VN_CAST($1->addNextNull($3), SenItem); } - | event_expression ',' senitem { $$ = VN_CAST($1->addNextNull($3), SenItem); } /* Verilog 2001 */ + | event_expression yOR senitem { $$ = addNextNull($1, $3); } + | event_expression ',' senitem { $$ = addNextNull($1, $3); } /* Verilog 2001 */ //UNSUP // Above are all removed, replace with: //UNSUP ev_expr { $$ = $1; } - //UNSUP event_expression ',' ev_expr %prec yOR { $$ = VN_CAST($1->addNextNull($3), SenItem); } + //UNSUP event_expression ',' ev_expr %prec yOR { $$ = addNextNull($1, $3); } ; senitem: // IEEE: part of event_expression, non-'OR' ',' terms @@ -3167,7 +3173,7 @@ par_blockFrontPreId: // IEEE: part of par_block/stmt with leading id blockDeclStmtList: // IEEE: { block_item_declaration } { statement or null } // // The spec seems to suggest a empty declaration isn't ok, but most simulators take it block_item_declarationList { $$ = $1; } - | block_item_declarationList stmtList { $$ = $1->addNextNull($2); } + | block_item_declarationList stmtList { $$ = addNextNull($1, $2); } | stmtList { $$ = $1; } ; @@ -3178,7 +3184,7 @@ blockDeclStmtListE: // IEEE: [ { block_item_declaration } { statemen block_item_declarationList: // IEEE: [ block_item_declaration ] block_item_declaration { $$ = $1; } - | block_item_declarationList block_item_declaration { $$ = $1->addNextNull($2); } + | block_item_declarationList block_item_declaration { $$ = addNextNull($1, $2); } ; block_item_declaration: // ==IEEE: block_item_declaration @@ -3189,7 +3195,7 @@ block_item_declaration: // ==IEEE: block_item_declaration stmtList: stmtBlock { $$ = $1; } - | stmtList stmtBlock { $$ = $2 ? $1->addNext($2) : $1; } + | stmtList stmtBlock { $$ = addNextNull($1, $2); } ; stmt: // IEEE: statement_or_null == function_statement_or_null @@ -3488,23 +3494,23 @@ case_itemList: // IEEE: { case_item + ... } caseCondList colon stmtBlock { $$ = new AstCaseItem{$2, $1, $3}; } | yDEFAULT colon stmtBlock { $$ = new AstCaseItem{$1, nullptr, $3}; } | yDEFAULT stmtBlock { $$ = new AstCaseItem{$1, nullptr, $2}; } - | case_itemList caseCondList colon stmtBlock { $$ = $1; $1->addNext(new AstCaseItem{$3, $2, $4}); } - | case_itemList yDEFAULT stmtBlock { $$ = $1; $1->addNext(new AstCaseItem{$2, nullptr, $3}); } - | case_itemList yDEFAULT colon stmtBlock { $$ = $1; $1->addNext(new AstCaseItem{$2, nullptr, $4}); } + | case_itemList caseCondList colon stmtBlock { $$ = $1->addNext(new AstCaseItem{$3, $2, $4}); } + | case_itemList yDEFAULT stmtBlock { $$ = $1->addNext(new AstCaseItem{$2, nullptr, $3}); } + | case_itemList yDEFAULT colon stmtBlock { $$ = $1->addNext(new AstCaseItem{$2, nullptr, $4}); } ; case_inside_itemList: // IEEE: { case_inside_item + open_range_list ... } open_range_list colon stmtBlock { $$ = new AstCaseItem{$2, $1, $3}; } | yDEFAULT colon stmtBlock { $$ = new AstCaseItem{$1, nullptr, $3}; } | yDEFAULT stmtBlock { $$ = new AstCaseItem{$1, nullptr, $2}; } - | case_inside_itemList open_range_list colon stmtBlock { $$ = $1; $1->addNext(new AstCaseItem{$3, $2, $4}); } - | case_inside_itemList yDEFAULT stmtBlock { $$ = $1; $1->addNext(new AstCaseItem{$2, nullptr, $3}); } - | case_inside_itemList yDEFAULT colon stmtBlock { $$ = $1; $1->addNext(new AstCaseItem{$2, nullptr, $4}); } + | case_inside_itemList open_range_list colon stmtBlock { $$ = $1->addNext(new AstCaseItem{$3, $2, $4}); } + | case_inside_itemList yDEFAULT stmtBlock { $$ = $1->addNext(new AstCaseItem{$2, nullptr, $3}); } + | case_inside_itemList yDEFAULT colon stmtBlock { $$ = $1->addNext(new AstCaseItem{$2, nullptr, $4}); } ; open_range_list: // ==IEEE: open_range_list + open_value_range open_value_range { $$ = $1; } - | open_range_list ',' open_value_range { $$ = $1; $1->addNext($3); } + | open_range_list ',' open_value_range { $$ = $1->addNext($3); } ; open_value_range: // ==IEEE: open_value_range @@ -3523,7 +3529,7 @@ value_range: // ==IEEE: value_range caseCondList: // IEEE: part of case_item expr { $$ = $1; } - | caseCondList ',' expr { $$ = $1; $1->addNext($3); } + | caseCondList ',' expr { $$ = $1->addNext($3); } ; patternNoExpr: // IEEE: pattern **Excluding Expr* @@ -3540,7 +3546,7 @@ patternNoExpr: // IEEE: pattern **Excluding Expr* patternList: // IEEE: part of pattern patternOne { $$ = $1; } - | patternList ',' patternOne { $$ = $1->addNextNull($3); } + | patternList ',' patternOne { $$ = addNextNull($1, $3); } ; patternOne: // IEEE: part of pattern @@ -3552,7 +3558,7 @@ patternOne: // IEEE: part of pattern patternMemberList: // IEEE: part of pattern and assignment_pattern patternMemberOne { $$ = $1; } - | patternMemberList ',' patternMemberOne { $$ = $1->addNextNull($3); } + | patternMemberList ',' patternMemberOne { $$ = addNextNull($1, $3); } ; patternMemberOne: // IEEE: part of pattern and assignment_pattern @@ -3634,7 +3640,7 @@ for_stepE: // IEEE: for_step + empty for_step: // IEEE: for_step for_step_assignment { $$ = $1; } - | for_step ',' for_step_assignment { $$ = AstNode::addNextNull($1, $3); } + | for_step ',' for_step_assignment { $$ = addNextNull($1, $3); } ; for_step_assignment: // ==IEEE: for_step_assignment @@ -3653,7 +3659,7 @@ for_step_assignment: // ==IEEE: for_step_assignment loop_variables: // IEEE: loop_variables parseRefBase { $$ = $1; } - | loop_variables ',' parseRefBase { $$ = $1; $$->addNext($3); } + | loop_variables ',' parseRefBase { $$ = $1->addNext($3); } | ',' parseRefBase { $$ = new AstEmpty{$1}; $$->addNext($2); } ; @@ -4009,7 +4015,7 @@ exprOrDataType: // expr | data_type: combined to prevent conflic //UNSUPexprOrDataTypeList: //UNSUP exprOrDataType { $$ = $1; } -//UNSUP | exprOrDataTypeList ',' exprOrDataType { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | exprOrDataTypeList ',' exprOrDataType { $$ = addNextNull($1, $3); } //UNSUP ; list_of_argumentsE: // IEEE: [list_of_arguments] @@ -4018,7 +4024,7 @@ list_of_argumentsE: // IEEE: [list_of_arguments] { if (VN_IS($1, Arg) && VN_CAST($1, Arg)->emptyConnectNoNext()) { $1->deleteTree(); $$ = nullptr; // Mis-created when have 'func()' } else { $$ = $1; } } - | argsExprListE ',' argsDottedList { $$ = $1->addNextNull($3); } + | argsExprListE ',' argsDottedList { $$ = addNextNull($1, $3); } ; task_declaration: // ==IEEE: task_declaration @@ -4160,20 +4166,20 @@ fIdScoped: // IEEE: part of function_body_declaration/task_ ; tfGuts: - '(' tf_port_listE ')' ';' tfBodyE { $$ = $2->addNextNull($5); } + '(' tf_port_listE ')' ';' tfBodyE { $$ = addNextNull($2, $5); } | ';' tfBodyE { $$ = $2; } ; tfBodyE: // IEEE: part of function_body_declaration/task_body_declaration /* empty */ { $$ = nullptr; } | tf_item_declarationList { $$ = $1; } - | tf_item_declarationList stmtList { $$ = $1->addNextNull($2); } + | tf_item_declarationList stmtList { $$ = addNextNull($1, $2); } | stmtList { $$ = $1; } ; tf_item_declarationList: tf_item_declaration { $$ = $1; } - | tf_item_declarationList tf_item_declaration { $$ = $1->addNextNull($2); } + | tf_item_declarationList tf_item_declaration { $$ = addNextNull($1, $2); } ; tf_item_declaration: // ==IEEE: tf_item_declaration @@ -4196,7 +4202,7 @@ tf_port_listE: // IEEE: tf_port_list + empty tf_port_listList: // IEEE: part of tf_port_list tf_port_item { $$ = $1; } - | tf_port_listList ',' tf_port_item { $$ = $1->addNextNull($3); } + | tf_port_listList ',' tf_port_item { $$ = addNextNull($1, $3); } ; tf_port_item: // ==IEEE: tf_port_item @@ -4629,7 +4635,7 @@ exprStrText: cStrList: exprStrText { $$ = $1; } - | exprStrText ',' cStrList { $$ = $1; $1->addNext($3); } + | exprStrText ',' cStrList { $$ = $1->addNext($3); } ; cateList: @@ -4645,20 +4651,20 @@ exprListE: exprList: expr { $$ = $1; } - | exprList ',' expr { $$ = $1; $1->addNext($3); } + | exprList ',' expr { $$ = $1->addNext($3); } ; exprDispList: // exprList for within $display expr { $$ = $1; } - | exprDispList ',' expr { $$ = $1; $1->addNext($3); } + | exprDispList ',' expr { $$ = $1->addNext($3); } // // ,, creates a space in $display | exprDispList ',' /*empty*/ - { $$ = $1; $1->addNext(new AstConst($2, AstConst::VerilogStringLiteral(), " ")); } + { $$ = $1->addNext(new AstConst($2, AstConst::VerilogStringLiteral(), " ")); } ; vrdList: idClassSel { $$ = $1; } - | vrdList ',' idClassSel { $$ = $1; $1->addNext($3); } + | vrdList ',' idClassSel { $$ = $1->addNext($3); } ; commaVRDListE: @@ -4678,7 +4684,7 @@ argsExprListE: // IEEE: part of list_of_arguments //UNSUPpev_argsExprListE: // IEEE: part of list_of_arguments - pev_expr at bottom //UNSUP pev_argsExprOneE { $$ = $1; } -//UNSUP | pev_argsExprListE ',' pev_argsExprOneE { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | pev_argsExprListE ',' pev_argsExprOneE { $$ = addNextNull($1, $3); } //UNSUP ; argsExprOneE: // IEEE: part of list_of_arguments @@ -4693,12 +4699,12 @@ argsExprOneE: // IEEE: part of list_of_arguments argsDottedList: // IEEE: part of list_of_arguments argsDotted { $$ = $1; } - | argsDottedList ',' argsDotted { $$ = $1->addNextNull($3); } + | argsDottedList ',' argsDotted { $$ = addNextNull($1, $3); } ; //UNSUPpev_argsDottedList: // IEEE: part of list_of_arguments - pev_expr at bottom //UNSUP pev_argsDotted { $$ = $1; } -//UNSUP | pev_argsDottedList ',' pev_argsDotted { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | pev_argsDottedList ',' pev_argsDotted { $$ = addNextNull($1, $3); } //UNSUP ; argsDotted: // IEEE: part of list_of_arguments @@ -4988,7 +4994,7 @@ combinational_body: // IEEE: combinational_body + sequential_body tableEntryList: // IEEE: { combinational_entry | sequential_entry } tableEntry { $$ = $1; } - | tableEntryList tableEntry { $$ = $1->addNextNull($2); } + | tableEntryList tableEntry { $$ = addNextNull($1, $2); } ; tableEntry: // IEEE: combinational_entry + sequential_entry @@ -5084,7 +5090,7 @@ variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variable_l //UNSUPvariable_lvalueList: // IEEE: part of variable_lvalue: variable_lvalue { ',' variable_lvalue } //UNSUP variable_lvalue { $$ = $1; } -//UNSUP | variable_lvalueList ',' variable_lvalue { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | variable_lvalueList ',' variable_lvalue { $$ = addNextNull($1, $3); } //UNSUP ; // VarRef to dotted, and/or arrayed, and/or bit-ranged variable @@ -5162,9 +5168,9 @@ idArrayedForeach: // IEEE: id + select (under foreach expression) // // IEEE: loop_variables (under foreach expression) // // To avoid conflicts we allow expr as first element, must post-check | idArrayed '[' expr ',' loop_variables ']' - { $3 = AstNode::addNextNull($3, $5); $$ = new AstSelLoopVars($2, $1, $3); } + { $3 = addNextNull($3, $5); $$ = new AstSelLoopVars($2, $1, $3); } | idArrayed '[' ',' loop_variables ']' - { $4 = AstNode::addNextNull(static_cast(new AstEmpty{$3}), $4); $$ = new AstSelLoopVars($2, $1, $4); } + { $4 = addNextNull(static_cast(new AstEmpty{$3}), $4); $$ = new AstSelLoopVars($2, $1, $4); } ; // VarRef without any dots or vectorizaion @@ -5243,7 +5249,7 @@ clocking_declaration: // IEEE: clocking_declaration (INCOMPLE //UNSUPclocking_itemList: // IEEE: [ clocking_item ] //UNSUP clocking_item { $$ = $1; } -//UNSUP | clocking_itemList clocking_item { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | clocking_itemList clocking_item { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPclocking_item: // ==IEEE: clocking_item @@ -5548,7 +5554,7 @@ property_spec: // IEEE: property_spec //UNSUPproperty_case_itemList: // IEEE: {property_case_item} //UNSUP property_case_item { $$ = $1; } -//UNSUP | property_case_itemList ',' property_case_item { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | property_case_itemList ',' property_case_item { $$ = addNextNull($1, $3); } //UNSUP ; //UNSUPproperty_case_item: // ==IEEE: property_case_item @@ -5805,7 +5811,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPcoverage_spec_or_optionList: // IEEE: {coverage_spec_or_option} //UNSUP coverage_spec_or_option { $$ = $1; } -//UNSUP | coverage_spec_or_optionList coverage_spec_or_option { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | coverage_spec_or_optionList coverage_spec_or_option { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPcoverage_spec_or_option: // ==IEEE: coverage_spec_or_option @@ -5846,7 +5852,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPbins_or_optionsList: // IEEE: { bins_or_options ';' } //UNSUP bins_or_options ';' { $$ = $1; } -//UNSUP | bins_or_optionsList bins_or_options ';' { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | bins_or_optionsList bins_or_options ';' { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPbins_or_options: // ==IEEE: bins_or_options @@ -5882,7 +5888,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPcovergroup_range_list: // ==IEEE: covergroup_range_list //UNSUP covergroup_value_range { $$ = $1; } -//UNSUP | covergroup_range_list ',' covergroup_value_range { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | covergroup_range_list ',' covergroup_value_range { $$ = addNextNull($1, $3); } //UNSUP ; //UNSUPtrans_list: // ==IEEE: trans_list @@ -5909,7 +5915,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPrepeat_range: // ==IEEE: repeat_range //UNSUP cgexpr { $$ = $1; } -//UNSUP | cgexpr ':' cgexpr { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | cgexpr ':' cgexpr { $$ = addNextNull($1, $3); } //UNSUP ; //UNSUPcover_cross: // ==IEEE: cover_cross @@ -5918,13 +5924,13 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUP ; //UNSUPlist_of_cross_items: // ==IEEE: list_of_cross_items -//UNSUP cross_item ',' cross_item { $$ = AstNode::addNextNull($1, $3); } +//UNSUP cross_item ',' cross_item { $$ = addNextNull($1, $3); } //UNSUP | cross_item ',' cross_item ',' cross_itemList { } //UNSUP ; //UNSUPcross_itemList: // IEEE: part of list_of_cross_items //UNSUP cross_item { $$ = nullptr; } -//UNSUP | cross_itemList ',' cross_item { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | cross_itemList ',' cross_item { $$ = addNextNull($1, $3); } //UNSUP ; //UNSUPcross_item: // ==IEEE: cross_item @@ -5940,7 +5946,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPcross_body_itemSemiList: // IEEE: part of cross_body //UNSUP cross_body_item ';' { $$ = $1; } -//UNSUP | cross_body_itemSemiList cross_body_item ';' { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | cross_body_itemSemiList cross_body_item ';' { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPcross_body_item: // ==IEEE: cross_body_item @@ -6020,7 +6026,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPproductionList: // IEEE: production+ //UNSUP production { $$ = $1; } -//UNSUP | productionList production { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | productionList production { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPproduction: // ==IEEE: production @@ -6036,7 +6042,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPrs_ruleList: // IEEE: rs_rule+ part of production //UNSUP rs_rule { $$ = $1; } -//UNSUP | rs_ruleList '|' rs_rule { $$ = AstNode::addNextNull($1, $3); } +//UNSUP | rs_ruleList '|' rs_rule { $$ = addNextNull($1, $3); } //UNSUP ; //UNSUPrs_rule: // ==IEEE: rs_rule @@ -6064,7 +6070,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPrs_code_blockItemList: // IEEE: part of rs_code_block //UNSUP rs_code_blockItem { $$ = $1; } -//UNSUP | rs_code_blockItemList rs_code_blockItem { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | rs_code_blockItemList rs_code_blockItem { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPrs_code_blockItem: // IEEE: part of rs_code_block @@ -6074,7 +6080,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPrs_prodList: // IEEE: rs_prod+ //UNSUP rs_prod { $$ = $1; } -//UNSUP | rs_prodList rs_prod { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | rs_prodList rs_prod { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPrs_prod: // ==IEEE: rs_prod @@ -6091,7 +6097,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPproduction_itemList: // IEEE: production_item+ //UNSUP production_item { $$ = $1; } -//UNSUP | production_itemList production_item { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | production_itemList production_item { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPproduction_item: // ==IEEE: production_item @@ -6101,7 +6107,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPrs_case_itemList: // IEEE: rs_case_item+ //UNSUP rs_case_item { $$ = $1; } -//UNSUP | rs_case_itemList rs_case_item { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | rs_case_itemList rs_case_item { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPrs_case_item: // ==IEEE: rs_case_item @@ -6137,7 +6143,7 @@ complex_pexpr: // IEEE: part of property_expr, see comments there //UNSUPchecker_or_generate_itemList: // IEEE: { checker_or_generate_itemList } //UNSUP checker_or_generate_item { $$ = $1; } -//UNSUP | checker_or_generate_itemList checker_or_generate_item { $$ = AstNode::addNextNull($1, $2); } +//UNSUP | checker_or_generate_itemList checker_or_generate_item { $$ = addNextNull($1, $2); } //UNSUP ; //UNSUPchecker_or_generate_item: // ==IEEE: checker_or_generate_item @@ -6256,7 +6262,7 @@ classImplementsE: // IEEE: part of class_declaration classImplementsList: // IEEE: part of class_declaration // // All 1800-2012 class_typeExtImpList { $$ = nullptr; BBUNSUP($1, "Unsupported: implements class"); } - | classImplementsList ',' class_typeExtImpList { $$ = AstNode::addNextNull($1, $3); } + | classImplementsList ',' class_typeExtImpList { $$ = addNextNull($1, $3); } ; class_typeExtImpList: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]" @@ -6383,7 +6389,7 @@ class_itemListE: class_itemList: class_item { $$ = $1; } - | class_itemList class_item { $$ = AstNode::addNextNull($1, $2); } + | class_itemList class_item { $$ = addNextNull($1, $2); } ; class_item: // ==IEEE: class_item @@ -6468,7 +6474,7 @@ constraint_block: // ==IEEE: constraint_block constraint_block_itemList: // IEEE: { constraint_block_item } constraint_block_item { $$ = $1; } - | constraint_block_itemList constraint_block_item { $$ = AstNode::addNextNull($1, $2); } + | constraint_block_itemList constraint_block_item { $$ = addNextNull($1, $2); } ; constraint_block_item: // ==IEEE: constraint_block_item @@ -6479,7 +6485,7 @@ constraint_block_item: // ==IEEE: constraint_block_item solve_before_list: // ==IEEE: solve_before_list constraint_primary { $$ = $1; } - | solve_before_list ',' constraint_primary { $$ = AstNode::addNextNull($1, $3); } + | solve_before_list ',' constraint_primary { $$ = addNextNull($1, $3); } ; constraint_primary: // ==IEEE: constraint_primary @@ -6490,7 +6496,7 @@ constraint_primary: // ==IEEE: constraint_primary constraint_expressionList: // ==IEEE: { constraint_expression } constraint_expression { $$ = $1; } - | constraint_expressionList constraint_expression { $$ = AstNode::addNextNull($1, $2); } + | constraint_expressionList constraint_expression { $$ = addNextNull($1, $2); } ; constraint_expression: // ==IEEE: constraint_expression @@ -6518,7 +6524,7 @@ constraint_set: // ==IEEE: constraint_set dist_list: // ==IEEE: dist_list dist_item { $$ = $1; } - | dist_list ',' dist_item { $$ = AstNode::addNextNull($1, $3); } + | dist_list ',' dist_item { $$ = addNextNull($1, $3); } ; dist_item: // ==IEEE: dist_item + dist_weight From 8da261f30253501b8f48f6f9f691fd633ba535ac Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 18 Sep 2022 10:19:15 -0400 Subject: [PATCH 48/75] Tests: Rename to avoid dash. --- test_regress/t/t_flag_build_jobs_bad.out | 1 + 1 file changed, 1 insertion(+) create mode 100644 test_regress/t/t_flag_build_jobs_bad.out diff --git a/test_regress/t/t_flag_build_jobs_bad.out b/test_regress/t/t_flag_build_jobs_bad.out new file mode 100644 index 000000000..341b1b979 --- /dev/null +++ b/test_regress/t/t_flag_build_jobs_bad.out @@ -0,0 +1 @@ +%Error: --build-jobs requires a non-negative integer, but '-1' was passed From 8dae4ad93a0932d6c8c8031937fe0d09d716e5ac Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 18 Sep 2022 10:19:15 -0400 Subject: [PATCH 49/75] Tests: Rename to avoid dash. --- test_regress/t/t_flag_build_jobs_bad.pl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100755 test_regress/t/t_flag_build_jobs_bad.pl diff --git a/test_regress/t/t_flag_build_jobs_bad.pl b/test_regress/t/t_flag_build_jobs_bad.pl new file mode 100755 index 000000000..8432e74c6 --- /dev/null +++ b/test_regress/t/t_flag_build_jobs_bad.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +top_filename("t/t_flag_werror.v"); + +lint( + fails => 1, + verilator_flags => [qw(--build-jobs -1 --build)], + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; From fc4ffd454ebe77217283b2b61478493602fde3f3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sun, 18 Sep 2022 10:32:43 -0400 Subject: [PATCH 50/75] Rename --bin to --build-dep-bin. --- Changes | 1 + bin/verilator | 2 +- docs/guide/exe_verilator.rst | 16 +++++++++------- src/V3EmitMk.cpp | 2 +- src/V3File.cpp | 2 +- src/V3Options.cpp | 2 +- src/V3Options.h | 6 +++--- src/Verilator.cpp | 4 ++-- test_regress/t/t_flag_build-jobs_bad.out | 1 - ...build-jobs_bad.pl => t_flag_build_dep_bin.pl} | 10 ++++------ test_regress/t/t_flag_build_dep_bin.v | 8 ++++++++ 11 files changed, 31 insertions(+), 23 deletions(-) delete mode 100644 test_regress/t/t_flag_build-jobs_bad.out rename test_regress/t/{t_flag_build-jobs_bad.pl => t_flag_build_dep_bin.pl} (75%) create mode 100644 test_regress/t/t_flag_build_dep_bin.v diff --git a/Changes b/Changes index d0f057a5e..ed4497f7f 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,7 @@ Verilator 4.227 devel * Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro] * Add --main to generate main() C++ (previously was experimental only). +* Rename --bin to --build-dep-bin. * Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic] * Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] * Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk] diff --git a/bin/verilator b/bin/verilator index b6495eee5..45de10206 100755 --- a/bin/verilator +++ b/bin/verilator @@ -282,8 +282,8 @@ detailed descriptions of these arguments. --autoflush Flush streams after all $displays --bbox-sys Blackbox unknown $system calls --bbox-unsup Blackbox unsupported language features - --bin Override Verilator binary --build Build model executable/library after Verilation + --build-dep-bin Override build dependency Verilator binary --build-jobs Parallelism for --build --cc Create C++ output --cdc Clock domain crossing analysis diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index cf7690a14..daf2fc5f3 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -115,13 +115,6 @@ Summary: Using this argument will likely cause incorrect simulation. -.. option:: --bin - - Rarely needed. Override the default filename for Verilator itself. - When a dependency (.d) file is created, this filename will become a - source dependency, such that a change in this binary will have make - rebuild the output files. - .. option:: --build After generating the SystemC/C++ code, Verilator will invoke the @@ -129,6 +122,15 @@ Summary: is also used). Verilator manages the build itself, and for this --build requires GNU Make to be available on the platform. +.. option:: --build-dep-bin + + Rarely needed. When a dependency (.d) file is created, this filename + will become a source dependency, such that a change in this binary will + have make rebuild the output files. Defaults to the full path to the + Verilator binary. + + This option was named `--bin` prior to version 4.228. + .. option:: --build-jobs [] Specify the level of parallelism for :vlopt:`--build`. If zero, uses the diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index e4db53ede..726cd96cd 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -292,7 +292,7 @@ class EmitMkHierVerilation final { of.puts("# Verilation of hierarchical blocks are executed in this directory\n"); of.puts("VM_HIER_RUN_DIR := " + cwd + "\n"); of.puts("# Common options for hierarchical blocks\n"); - const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.bin()); + const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.buildDepBin()); const string verilator_wrapper = V3Os::filenameDir(fullpath_bin) + "/verilator"; of.puts("VM_HIER_VERILATOR := " + verilator_wrapper + "\n"); of.puts("VM_HIER_INPUT_FILES := \\\n"); diff --git a/src/V3File.cpp b/src/V3File.cpp index b8c8e6ad6..96386cbc4 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -154,7 +154,7 @@ void V3FileDependImp::writeDepend(const string& filename) { if (i.target()) *ofp << i.filename() << " "; } *ofp << " : "; - *ofp << v3Global.opt.bin(); + *ofp << v3Global.opt.buildDepBin(); *ofp << " "; for (const DependFile& i : m_filenameList) { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 644ea6961..64ca9e861 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1005,8 +1005,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char m_bboxUnsup = flag; FileLine::globalWarnOff(V3ErrorCode::E_UNSUPPORTED, true); }); - DECL_OPTION("-bin", Set, &m_bin); DECL_OPTION("-build", Set, &m_build); + DECL_OPTION("-build-dep-bin", Set, &m_buildDepBin); DECL_OPTION("-build-jobs", CbVal, [this, fl](const char* valp) { int val = std::atoi(valp); if (val < 0) { diff --git a/src/V3Options.h b/src/V3Options.h index 6c0eea7fe..4149eb75e 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -320,7 +320,7 @@ private: int m_compLimitMembers = 64; // compiler selection; number of members in struct before make anon array int m_compLimitParens = 240; // compiler selection; number of nested parens - string m_bin; // main switch: --bin {binary} + string m_buildDepBin; // main switch: --build-dep-bin {filename} string m_exeName; // main switch: -o {name} string m_flags; // main switch: -f {name} string m_l2Name; // main switch: --l2name; "" for top-module's name @@ -419,7 +419,6 @@ public: bool makePhony() const { return m_makePhony; } bool preprocNoLine() const { return m_preprocNoLine; } bool underlineZero() const { return m_underlineZero; } - string bin() const { return m_bin; } string flags() const { return m_flags; } bool systemC() const { return m_systemC; } bool savable() const { return m_savable; } @@ -431,6 +430,8 @@ public: bool bboxSys() const { return m_bboxSys; } bool bboxUnsup() const { return m_bboxUnsup; } bool build() const { return m_build; } + string buildDepBin() const { return m_buildDepBin; } + void buildDepBin(const string& flag) { m_buildDepBin = flag; } bool cdc() const { return m_cdc; } bool cmake() const { return m_cmake; } bool context() const { return m_context; } @@ -631,7 +632,6 @@ public: // Return options for child hierarchical blocks when forTop==false, otherwise returns args for // the top module. string allArgsStringForHierBlock(bool forTop) const; - void bin(const string& flag) { m_bin = flag; } void parseOpts(FileLine* fl, int argc, char** argv); void parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv); void parseOptsFile(FileLine* fl, const string& filename, bool rel); diff --git a/src/Verilator.cpp b/src/Verilator.cpp index ffd438ca9..9eb120d86 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -563,7 +563,7 @@ static void verilate(const string& argString) { UINFO(1, "Option --verilate: Start Verilation\n"); // Can we skip doing everything if times are ok? - V3File::addSrcDepend(v3Global.opt.bin()); + V3File::addSrcDepend(v3Global.opt.buildDepBin()); if (v3Global.opt.skipIdentical().isTrue() && V3File::checkTimes(v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "__verFiles.dat", @@ -714,7 +714,7 @@ int main(int argc, char** argv, char** /*env*/) { V3PreShell::boot(); // Command option parsing - v3Global.opt.bin(argv[0]); + v3Global.opt.buildDepBin(argv[0]); const string argString = V3Options::argString(argc - 1, argv + 1); v3Global.opt.parseOpts(new FileLine{FileLine::commandLineFilename()}, argc - 1, argv + 1); diff --git a/test_regress/t/t_flag_build-jobs_bad.out b/test_regress/t/t_flag_build-jobs_bad.out deleted file mode 100644 index 341b1b979..000000000 --- a/test_regress/t/t_flag_build-jobs_bad.out +++ /dev/null @@ -1 +0,0 @@ -%Error: --build-jobs requires a non-negative integer, but '-1' was passed diff --git a/test_regress/t/t_flag_build-jobs_bad.pl b/test_regress/t/t_flag_build_dep_bin.pl similarity index 75% rename from test_regress/t/t_flag_build-jobs_bad.pl rename to test_regress/t/t_flag_build_dep_bin.pl index 8432e74c6..13eaa6fe3 100755 --- a/test_regress/t/t_flag_build-jobs_bad.pl +++ b/test_regress/t/t_flag_build_dep_bin.pl @@ -10,13 +10,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(vlt => 1); -top_filename("t/t_flag_werror.v"); - -lint( - fails => 1, - verilator_flags => [qw(--build-jobs -1 --build)], - expect_filename => $Self->{golden_filename}, +compile( + v_flags2 => ['--build-dep-bin', 'path_to_exe'], ); +file_grep("$Self->{obj_dir}/$Self->{VM_PREFIX}__ver.d", qr/path_to_exe/); + ok(1); 1; diff --git a/test_regress/t/t_flag_build_dep_bin.v b/test_regress/t/t_flag_build_dep_bin.v new file mode 100644 index 000000000..a56f76564 --- /dev/null +++ b/test_regress/t/t_flag_build_dep_bin.v @@ -0,0 +1,8 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2005 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); +endmodule From fe2a1e1749fc432095d70959faaa8b2c6a7b61ec Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Mon, 19 Sep 2022 10:54:20 +0200 Subject: [PATCH 51/75] Remove assignments with strengths weaker than strongest non-tristate RHS (#3629) --- src/V3Tristate.cpp | 179 ++++++++++++------ ...pl => t_strength_assignments_constants.pl} | 0 ...s.v => t_strength_assignments_constants.v} | 0 ...gn.pl => t_strength_strongest_constant.pl} | 0 ...sign.v => t_strength_strongest_constant.v} | 19 +- .../t/t_strength_strongest_non_tristate.pl | 21 ++ .../t/t_strength_strongest_non_tristate.v | 35 ++++ 7 files changed, 189 insertions(+), 65 deletions(-) rename test_regress/t/{t_strength_assignments.pl => t_strength_assignments_constants.pl} (100%) rename test_regress/t/{t_strength_assignments.v => t_strength_assignments_constants.v} (100%) rename test_regress/t/{t_weak_nor_strong_assign.pl => t_strength_strongest_constant.pl} (100%) rename test_regress/t/{t_weak_nor_strong_assign.v => t_strength_strongest_constant.v} (50%) create mode 100755 test_regress/t/t_strength_strongest_non_tristate.pl create mode 100644 test_regress/t/t_strength_strongest_non_tristate.v diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 5a04e135e..f88908f62 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -57,11 +57,16 @@ // // // Another thing done in this phase is signal strength handling. -// Currently they are only supported in assignments and only in case when the strongest assignment -// has constant with all bits equal on the RHS. It is the case when they can be statically -// resolved. +// Currently they are only supported in assignments and gates parsed as assignments (see verilog.y) +// and only in case when the strongest assignment has RHS marked as non-tristate. It is the case +// when they can be statically resolved. +// If the RHS is equal to z, that assignment has to be skipped. Since the value may be not known at +// verilation time, cases with tristates on RHS can't be handled statically. // -// Static resolution is done in the following way: +// Static resolution is split into 2 parts. +// First part can be done before tristate propagation. It is about removing assignments that are +// weaker or equally strong as the strongest assignment with constant on RHS that has all bits +// the same (equal to 0 or 1). It is done in the following way: // - The assignment of value 0 (size may be greater than 1), that has greatest strength (the // one corresponding to 0) of all other assignments of 0, has to be found. // - The same is done for value '1 and strength corresponding to value 1. @@ -72,16 +77,19 @@ // both strengths non-greater that the one was found, because they are weaker no matter what is on // RHS. // -// All assignments that are stronger than the one with strongest constant are left as they are. +// Second part of static resolution is done after tristate propagation. +// At that moment it is known that some expressions can't be equal to z. The exact value is +// unknown (except the ones with constants that were handled before), so weaker of both strengths +// has to be taken into account. All weaker assignments can be safely removed. It is done in +// similar way to the first part: +// - The assignment with non-tristate RHS with the greatest weaker strength has to be found. +// - Then all not stronger assignments can be removed. +// +// All assignments that are stronger than the strongest with non-tristate RHS are left as they are. // // There is a possible problem with equally strong assignments, because multiple assignments with // the same strength, but different values should result in x value, but these values are // unsupported. -// -// Singal strength can also be used in simple logic gates parsed as assignments (see verilog.y), -// but these gates are then either removed (if they are weaker than the strongest constant) or -// handled as the gates witout signal strengths are handled now. In other words, gate with greater -// strength won't properly overwrite weaker driver. //************************************************************************* #include "config_build.h" @@ -269,6 +277,18 @@ public: void associate(AstNode* fromp, AstNode* top) { new V3GraphEdge(&m_graph, makeVertex(fromp), makeVertex(top), 1); } + void deleteVerticesFromSubtreeRecurse(AstNode* nodep) { + if (!nodep) return; + // Skip vars, because they may be connected to more than one varref + if (!VN_IS(nodep, Var)) { + TristateVertex* const vertexp = reinterpret_cast(nodep->user5p()); + if (vertexp) vertexp->unlinkDelete(&m_graph); + } + deleteVerticesFromSubtreeRecurse(nodep->op1p()); + deleteVerticesFromSubtreeRecurse(nodep->op2p()); + deleteVerticesFromSubtreeRecurse(nodep->op3p()); + deleteVerticesFromSubtreeRecurse(nodep->op4p()); + } void setTristate(AstNode* nodep) { makeVertex(nodep)->isTristate(true); } bool isTristate(AstNode* nodep) { const TristateVertex* const vertexp = reinterpret_cast(nodep->user5p()); @@ -715,64 +735,93 @@ class TristateVisitor final : public TristateBaseVisitor { return assignmentOfValueOnAllBits(*maxIt, value) ? *maxIt : nullptr; } - void removeWeakerAssignments(Assigns& assigns) { + bool isAssignmentNotStrongerThanStrength(AstAssignW* assignp, uint8_t strength) { + // If the value of the RHS is known and has all bits equal, only strength corresponding to + // its value is taken into account. In opposite case, both strengths are compared. + const uint8_t strength0 = getStrength(assignp, 0); + const uint8_t strength1 = getStrength(assignp, 1); + return (strength0 <= strength && strength1 <= strength) + || (strength0 <= strength && assignmentOfValueOnAllBits(assignp, 0)) + || (strength1 <= strength && assignmentOfValueOnAllBits(assignp, 1)); + } + + void removeNotStrongerAssignments(Assigns& assigns, AstAssignW* strongestp, + uint8_t greatestKnownStrength) { // Weaker assignments are these assignments that can't change the final value of the net. - // If the value of the RHS is known, only strength corresponding to its value is taken into - // account. Assignments of constants that have bits both 0 and 1 are skipped here, because - // it would involve handling parts of bits separately. - - // First, the strongest assignment, that has value on the RHS consisting of only 1 or only - // 0, has to be found. - AstAssignW* const strongest0p = getStrongestAssignmentOfValue(assigns, 0); - AstAssignW* const strongest1p = getStrongestAssignmentOfValue(assigns, 1); - AstAssignW* strongestp = nullptr; - uint8_t greatestKnownStrength = 0; - const auto getIfStrongest = [&](AstAssignW* const strongestCandidatep, bool value) { - if (!strongestCandidatep) return; - uint8_t strength = getStrength(strongestCandidatep, value); - if (strength >= greatestKnownStrength) { - greatestKnownStrength = strength; - strongestp = strongestCandidatep; + // They can be safely removed. Assignments of the same strength are also removed, because + // duplicates aren't needed. One problem is with 2 assignments of different values and + // equal strengths. It should result in assignment of x value, but these values aren't + // supported now. + auto removedIt = std::remove_if(assigns.begin(), assigns.end(), [&](AstAssignW* assignp) { + if (assignp == strongestp) return false; + if (isAssignmentNotStrongerThanStrength(assignp, greatestKnownStrength)) { + // Vertices corresponding to nodes from removed assignment's subtree have to be + // removed. + m_tgraph.deleteVerticesFromSubtreeRecurse(assignp); + VL_DO_DANGLING(pushDeletep(assignp->unlinkFrBack()), assignp); + return true; } - }; - getIfStrongest(strongest0p, 0); - getIfStrongest(strongest1p, 1); + return false; + }); + assigns.erase(removedIt, assigns.end()); + } - if (strongestp) { - // Then all weaker assignments can be safely removed. - // Assignments of the same strength are also removed, because duplicates aren't needed. - // One problem is with 2 assignments of different values and equal strengths. It should - // result in assignment of x value, but these values aren't supported now. - auto removedIt - = std::remove_if(assigns.begin(), assigns.end(), [&](AstAssignW* assignp) { - if (assignp == strongestp) return false; - const uint8_t strength0 = getStrength(assignp, 0); - const uint8_t strength1 = getStrength(assignp, 1); - const bool toRemove = (strength0 <= greatestKnownStrength - && strength1 <= greatestKnownStrength) - || (strength0 <= greatestKnownStrength - && assignmentOfValueOnAllBits(assignp, 0)) - || (strength1 <= greatestKnownStrength - && assignmentOfValueOnAllBits(assignp, 1)); - if (toRemove) { - // Don't propagate tristate if its assignment is removed. - TristateVertex* const vertexp - = reinterpret_cast(assignp->rhsp()->user5p()); - if (vertexp) vertexp->isTristate(false); - VL_DO_DANGLING(pushDeletep(assignp->unlinkFrBack()), assignp); - return true; - } - return false; - }); - assigns.erase(removedIt, assigns.end()); + void removeAssignmentsNotStrongerThanUniformConstant() { + // If a stronger assignment of a constant with all bits equal to the same + // value (0 or 1), is found, all weaker assignments can be safely removed. + for (auto& varpAssigns : m_assigns) { + Assigns& assigns = varpAssigns.second; + if (assigns.size() > 1) { + AstAssignW* const strongest0p = getStrongestAssignmentOfValue(assigns, 0); + AstAssignW* const strongest1p = getStrongestAssignmentOfValue(assigns, 1); + AstAssignW* strongestp = nullptr; + uint8_t greatestKnownStrength = 0; + const auto getIfStrongest + = [&](AstAssignW* const strongestCandidatep, bool value) { + if (!strongestCandidatep) return; + uint8_t strength = getStrength(strongestCandidatep, value); + if (strength >= greatestKnownStrength) { + greatestKnownStrength = strength; + strongestp = strongestCandidatep; + } + }; + getIfStrongest(strongest0p, 0); + getIfStrongest(strongest1p, 1); + + if (strongestp) { + removeNotStrongerAssignments(assigns, strongestp, greatestKnownStrength); + } + } } } - void resolveMultipleNetAssignments() { + void removeAssignmentsNotStrongerThanNonTristate() { + // Similar function as removeAssignmentsNotStrongerThanUniformConstant, but here the + // assignments that have strength not stronger than the strongest assignment with + // non-tristate RHS are removed. Strengths are compared according to their smaller values, + // because the values of RHSs are unknown. (Assignments not stronger than strongest + // constant are already removed.) for (auto& varpAssigns : m_assigns) { - if (varpAssigns.second.size() > 1) { - // first the static resolution is tried - removeWeakerAssignments(varpAssigns.second); + Assigns& assigns = varpAssigns.second; + if (assigns.size() > 1) { + auto maxIt = std::max_element( + assigns.begin(), assigns.end(), [&](AstAssignW* ap, AstAssignW* bp) { + if (m_tgraph.isTristate(ap)) return !m_tgraph.isTristate(bp); + if (m_tgraph.isTristate(bp)) return false; + const uint8_t minStrengthA + = std::min(getStrength(ap, 0), getStrength(ap, 1)); + const uint8_t minStrengthB + = std::min(getStrength(bp, 0), getStrength(bp, 1)); + return minStrengthA < minStrengthB; + }); + // If RHSs of all assignments are tristate, 1st element is returned, so it is + // needed to check if it is non-tristate. + AstAssignW* const strongestp = m_tgraph.isTristate(*maxIt) ? nullptr : *maxIt; + if (strongestp) { + uint8_t greatestKnownStrength + = std::min(getStrength(strongestp, 0), getStrength(strongestp, 1)); + removeNotStrongerAssignments(assigns, strongestp, greatestKnownStrength); + } } } } @@ -1534,10 +1583,14 @@ class TristateVisitor final : public TristateBaseVisitor { iterateChildren(nodep); m_graphing = false; } - // resolve multiple net assignments and signal strengths - resolveMultipleNetAssignments(); + // Remove all assignments not stronger than the strongest uniform constant + removeAssignmentsNotStrongerThanUniformConstant(); // Use graph to find tristate signals m_tgraph.graphWalk(nodep); + + // Remove all assignments not stronger than the strongest non-tristate RHS + removeAssignmentsNotStrongerThanNonTristate(); + // Build the LHS drivers map for this module iterateChildren(nodep); // Insert new logic for all tristates diff --git a/test_regress/t/t_strength_assignments.pl b/test_regress/t/t_strength_assignments_constants.pl similarity index 100% rename from test_regress/t/t_strength_assignments.pl rename to test_regress/t/t_strength_assignments_constants.pl diff --git a/test_regress/t/t_strength_assignments.v b/test_regress/t/t_strength_assignments_constants.v similarity index 100% rename from test_regress/t/t_strength_assignments.v rename to test_regress/t/t_strength_assignments_constants.v diff --git a/test_regress/t/t_weak_nor_strong_assign.pl b/test_regress/t/t_strength_strongest_constant.pl similarity index 100% rename from test_regress/t/t_weak_nor_strong_assign.pl rename to test_regress/t/t_strength_strongest_constant.pl diff --git a/test_regress/t/t_weak_nor_strong_assign.v b/test_regress/t/t_strength_strongest_constant.v similarity index 50% rename from test_regress/t/t_weak_nor_strong_assign.v rename to test_regress/t/t_strength_strongest_constant.v index a3811ca71..d8fec7098 100644 --- a/test_regress/t/t_weak_nor_strong_assign.v +++ b/test_regress/t/t_strength_strongest_constant.v @@ -4,15 +4,30 @@ // any use, without warranty, 2022 by Antmicro Ltd. // SPDX-License-Identifier: CC0-1.0 -module t (/*AUTOARG*/); +module t (clk1, clk2); + input wire clk1; + input wire clk2; + wire a; nor (pull0, weak1) n1(a, 0, 0); assign (strong0, weak1) a = 0; + wire [1:0] b; + assign (weak0, supply1) b = '1; + assign b = clk1 ? '0 : 'z; + + wire c = 1; + assign (weak0, pull1) c = clk1 & clk2; + always begin - if (!a) begin + if (!a && b === '1 && c) begin $write("*-* All Finished *-*\n"); $finish; end + else begin + $write("Error: a = %b, b = %b, c = %b ", a, b, c); + $write("expected: a = 0, b = 11, c = 1\n"); + $stop; + end end endmodule diff --git a/test_regress/t/t_strength_strongest_non_tristate.pl b/test_regress/t/t_strength_strongest_non_tristate.pl new file mode 100755 index 000000000..f5e338520 --- /dev/null +++ b/test_regress/t/t_strength_strongest_non_tristate.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_strongest_non_tristate.v b/test_regress/t/t_strength_strongest_non_tristate.v new file mode 100644 index 000000000..5c3c64c86 --- /dev/null +++ b/test_regress/t/t_strength_strongest_non_tristate.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (clk1, clk2); + input wire clk1; + input wire clk2; + + wire (weak0, weak1) a = 0; + assign (strong0, supply1) a = clk1; + assign (pull0, pull1) a = 1; + + wire b; + xor (strong0, strong1) (b, clk1, clk2); + and (weak0, pull1) (b, clk1, clk2); + + wire [7:0] c; + assign (supply0, strong1) c = clk1 ? '1 : '0; + assign (weak0, supply1) c = '0; + assign (weak0, pull1) c = 'z; + + always begin + if (a === clk1 && b === clk1 ^ clk2 && c[0] === clk1) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else begin + $write("Error: a = %b, b = %b, c[0] = %b, ", a, b, c[0]); + $write("expected: a = %b, b = %b, c[0] = %b\n", clk1, clk1 ^ clk2, clk1); + $stop; + end + end +endmodule From bba800f2d6cbfe9e3e1cbb6bcb6a1130a11bd987 Mon Sep 17 00:00:00 2001 From: Yu-Sheng Lin Date: Wed, 21 Sep 2022 04:45:09 +0800 Subject: [PATCH 52/75] Fix calling trace() after open() segfault (#3610) (#3627) --- docs/CONTRIBUTORS | 1 + src/V3EmitCModel.cpp | 5 ++++ test_regress/t/t_trace_open_wrong_order.cpp | 25 +++++++++++++++++ test_regress/t/t_trace_open_wrong_order.pl | 30 +++++++++++++++++++++ test_regress/t/t_trace_open_wrong_order.v | 8 ++++++ 5 files changed, 69 insertions(+) create mode 100644 test_regress/t/t_trace_open_wrong_order.cpp create mode 100755 test_regress/t/t_trace_open_wrong_order.pl create mode 100644 test_regress/t/t_trace_open_wrong_order.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 7a800bab7..7a5f72934 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -130,5 +130,6 @@ Yoda Lee Yossi Nivin Yuri Victorovich Yutetsu TAKATSUKASA +Yu-Sheng Lin Yves Mathieu Zhanglei Wang diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp index 2c2239306..2daf8c4cf 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -552,6 +552,11 @@ class EmitCModel final : public EmitCFunc { "elaboration.\");\n"); puts(/**/ "}"); } + puts(/**/ "if (tfp->isOpen()) {\n"); + puts(/****/ "vl_fatal(__FILE__, __LINE__, __FILE__,\"'" + topClassName() + + +"::trace()' shall not be called after '" + v3Global.opt.traceClassBase() + + "C::open()'.\");\n"); + puts(/**/ "}\n"); puts(/**/ "if (false && levels && options) {} // Prevent unused\n"); puts(/**/ "tfp->spTrace()->addModel(this);\n"); puts(/**/ "tfp->spTrace()->addInitCb(&" + protect("trace_init") + ", &(vlSymsp->TOP));\n"); diff --git a/test_regress/t/t_trace_open_wrong_order.cpp b/test_regress/t/t_trace_open_wrong_order.cpp new file mode 100644 index 000000000..4faa6dd5b --- /dev/null +++ b/test_regress/t/t_trace_open_wrong_order.cpp @@ -0,0 +1,25 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +// +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Yu-Sheng Lin. +// SPDX-License-Identifier: CC0-1.0 + +#include +#include + +#include "Vt_trace_open_wrong_order.h" +using namespace std; + +int main(int argc, char** argv) { + VerilatedContext ctx; + VerilatedVcdC tfp; + Vt_trace_open_wrong_order dut; + ctx.traceEverOn(true); + tfp.open("dump.vcd"); // Error! shall put to the next line! + dut.trace(&tfp, 99); // Error! + tfp.dump(0); + tfp.close(); + return 0; +} diff --git a/test_regress/t/t_trace_open_wrong_order.pl b/test_regress/t/t_trace_open_wrong_order.pl new file mode 100755 index 000000000..a7c8b6c51 --- /dev/null +++ b/test_regress/t/t_trace_open_wrong_order.pl @@ -0,0 +1,30 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Yu-Sheng Lin. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +if ($Self->{vlt_all}) { + compile( + verilator_flags2 => ["--cc --trace --exe $Self->{t_dir}/$Self->{name}.cpp"], + make_top_shell => 0, + make_main => 0, + ); +} else { + compile( + ); +} + +execute( + fails => 1 + ); +file_grep($Self->{run_log_filename}, qr/::trace\(\)' shall not be called after 'VerilatedVcdC::open\(\)'/i); + +ok(1); +1; diff --git a/test_regress/t/t_trace_open_wrong_order.v b/test_regress/t/t_trace_open_wrong_order.v new file mode 100644 index 000000000..60a7504fd --- /dev/null +++ b/test_regress/t/t_trace_open_wrong_order.v @@ -0,0 +1,8 @@ +// DESCRIPTION: Verilator: Verilog dummy test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Yu-Sheng Lin. +// SPDX-License-Identifier: CC0-1.0 + +module t(input clk); +endmodule From fc3ce29845fd7e4afe76ef3a661e047fbd301c55 Mon Sep 17 00:00:00 2001 From: Mariusz Glebocki Date: Tue, 20 Sep 2022 22:46:47 +0200 Subject: [PATCH 53/75] Improve Verilation memory by reducing V3Number size (#3521) --- include/verilatedos.h | 1 + src/V3Number.cpp | 269 +++++++++++++------------ src/V3Number.h | 452 +++++++++++++++++++++++++++++++++--------- src/V3StdFuture.h | 30 +++ 4 files changed, 532 insertions(+), 220 deletions(-) create mode 100644 src/V3StdFuture.h diff --git a/include/verilatedos.h b/include/verilatedos.h index c84e13ef0..c5677b992 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -563,6 +563,7 @@ template T const& as_const(T& v) { return v; } + }; // namespace vlstd //========================================================================= diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 81b059442..7459ce773 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -44,7 +44,7 @@ constexpr int MAX_SPRINTF_DOUBLE_SIZE "Number operation called with same source and dest") #define NUM_ASSERT_LOGIC_ARGS1(arg1) \ - UASSERT((!(arg1).isDouble() && !(arg1).isString()), \ + UASSERT(((arg1).dataType() == V3NumberData::V3NumberDataType::LOGIC), \ "Number operation called with non-logic (double or string) argument: '" << (arg1) \ << '"') #define NUM_ASSERT_LOGIC_ARGS2(arg1, arg2) \ @@ -79,8 +79,10 @@ void V3Number::v3errorEnd(std::ostringstream& str) const { nsstr << str.str(); if (m_nodep) { m_nodep->v3errorEnd(nsstr); - } else { + } else if (m_fileline) { m_fileline->v3errorEnd(nsstr); + } else { + V3Error::v3errorEnd(nsstr); } } @@ -96,13 +98,11 @@ void V3Number::v3errorEndFatal(std::ostringstream& str) const { V3Number::V3Number(VerilogStringLiteral, AstNode* nodep, const string& str) { // Create a number using a verilog string as the value, thus 8 bits per character. - // cppcheck bug - doesn't see init() resets these - // cppcheck: Member variable 'm_sized/m_width' is not initialized in the constructor - init(nodep, str.length() * 8); - m_fromString = true; + init(nodep, std::max(str.length() * 8, 1)); + m_data.m_fromString = true; for (unsigned pos = 0; pos < str.length(); ++pos) { const int topos = str.length() - 1 - pos; - ValueAndX& v = m_value[topos / 4]; + ValueAndX& v = m_data.num()[topos / 4]; for (int bit = 0; bit < 8; ++bit) { if (str[pos] & (1UL << bit)) { v.m_value |= (1UL << (bit + (topos % 4) * 8)); } } @@ -112,7 +112,7 @@ V3Number::V3Number(VerilogStringLiteral, AstNode* nodep, const string& str) { V3Number::V3Number(AstNode* nodep, const AstNodeDType* nodedtypep) { if (nodedtypep->isString()) { - init(nodep, 0); + init(nodep); setString(""); } else if (nodedtypep->isDouble()) { init(nodep, 64); @@ -124,6 +124,7 @@ V3Number::V3Number(AstNode* nodep, const AstNodeDType* nodedtypep) { void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) { init(nodep, 0); + m_data.setLogic(); m_fileline = fl; const char* value_startp = sourcep; for (const char* cp = sourcep; *cp; cp++) { @@ -172,35 +173,35 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) base = 'd'; } - for (int i = 0; i < words(); ++i) m_value[i] = {0, 0}; + for (int i = 0; i < words(); ++i) m_data.num()[i] = {0, 0}; // Special SystemVerilog unsized constructs if (base == '0') { + width(1, false); // So we extend it setBit(0, 0); - width(1, false); // So we extend it - m_autoExtend = true; + m_data.m_autoExtend = true; } else if (base == '1') { + width(1, false); // So we extend it setBit(0, 1); - width(1, false); // So we extend it - m_autoExtend = true; + m_data.m_autoExtend = true; } else if (tolower(base) == 'z') { + width(1, false); // So we extend it setBit(0, 'z'); - width(1, false); // So we extend it - m_autoExtend = true; + m_data.m_autoExtend = true; } else if (tolower(base) == 'x') { - setBit(0, 'x'); width(1, false); // So we extend it - m_autoExtend = true; + setBit(0, 'x'); + m_data.m_autoExtend = true; } // Otherwise... - else if (!m_sized) { + else if (!sized()) { width(32, false); // Says IEEE 1800-2012 5.7.1 if (unbased) isSigned(true); // Also says the spec. } // Ignore leading blanks while (*value_startp == '_' || isspace(*value_startp)) value_startp++; - if (!*value_startp && !m_autoExtend) { + if (!*value_startp && !m_data.m_autoExtend) { v3error("Number is missing value digits: " << sourcep); } @@ -229,7 +230,7 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) if (olen <= 7) { // 10000000 fits in 32 bits, so ok // Constants are common, so for speed avoid wide math until we need it val = val * 10 + (*cp - '0'); - m_value[0].m_value = val; + m_data.num()[0].m_value = val; } else { // Wide; all previous digits are already in m_value[0] // this = (this * 10)/*product*/ + (*cp-'0')/*addend*/ // Assumed rare; lots of optimizations are possible here @@ -237,12 +238,12 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl) const V3Number ten(this, width() + 4, 10); const V3Number addend(this, width(), (*cp - '0')); product.opMul(*this, ten); - this->opAdd(product, addend); + opAdd(product, addend); if (product.bitsValue(width(), 4)) { // Overflowed static int warned = 0; v3error("Too many digits for " << width() << " bit number: " << sourcep << '\n' - << ((!m_sized && !warned++) ? ( + << ((!sized() && !warned++) ? ( V3Error::warnMore() + "... As that number was unsized" + " ('d...) it is limited to 32 bits (IEEE 1800-2017 " "5.7.1)\n" @@ -387,72 +388,72 @@ int V3Number::log2b(uint32_t num) { // Setters V3Number& V3Number::setZero() { - for (int i = 0; i < words(); i++) m_value[i] = {0, 0}; + for (int i = 0; i < words(); i++) m_data.num()[i] = {0, 0}; return *this; } V3Number& V3Number::setQuad(uint64_t value) { - for (int i = 0; i < words(); i++) m_value[i] = {0, 0}; - m_value[0].m_value = value & 0xffffffffULL; - if (width() > 32) m_value[1].m_value = (value >> 32ULL) & 0xffffffffULL; + for (int i = 0; i < words(); i++) m_data.num()[i] = {0, 0}; + m_data.num()[0].m_value = value & 0xffffffffULL; + if (width() > 32) m_data.num()[1].m_value = (value >> 32ULL) & 0xffffffffULL; opCleanThis(); return *this; } V3Number& V3Number::setLong(uint32_t value) { - for (int i = 0; i < words(); i++) m_value[i] = {0, 0}; - m_value[0].m_value = value; + for (int i = 0; i < words(); i++) m_data.num()[i] = {0, 0}; + m_data.num()[0].m_value = value; opCleanThis(); return *this; } V3Number& V3Number::setLongS(int32_t value) { - for (int i = 0; i < words(); i++) m_value[i] = {0, 0}; + for (int i = 0; i < words(); i++) m_data.num()[i] = {0, 0}; union { uint32_t u; int32_t s; } u; u.s = value; if (u.s) {} - m_value[0].m_value = u.u; + m_data.num()[0].m_value = u.u; opCleanThis(); return *this; } V3Number& V3Number::setDouble(double value) { if (VL_UNCOVERABLE(width() != 64)) v3fatalSrc("Real operation on wrong sized number"); - m_double = true; + m_data.setDouble(); union { double d; uint32_t u[2]; } u; u.d = value; if (u.d != 0.0) {} - for (int i = 2; i < words(); i++) m_value[i] = {0, 0}; - m_value[0].m_value = u.u[0]; - m_value[1].m_value = u.u[1]; + for (int i = 2; i < words(); i++) m_data.num()[i] = {0, 0}; + m_data.num()[0].m_value = u.u[0]; + m_data.num()[1].m_value = u.u[1]; return *this; } V3Number& V3Number::setSingleBits(char value) { - for (int i = 1 /*upper*/; i < words(); i++) m_value[i] = {0, 0}; - m_value[0] = {(value == '1' || value == 'x' || value == 1 || value == 3), - (value == 'z' || value == 'x' || value == 2 || value == 3)}; + for (int i = 1 /*upper*/; i < words(); i++) m_data.num()[i] = {0, 0}; + m_data.num()[0] = {(value == '1' || value == 'x' || value == 1 || value == 3), + (value == 'z' || value == 'x' || value == 2 || value == 3)}; return *this; } V3Number& V3Number::setAllBits0() { - for (int i = 0; i < words(); i++) m_value[i] = {0, 0}; + for (int i = 0; i < words(); i++) m_data.num()[i] = {0, 0}; return *this; } V3Number& V3Number::setAllBits1() { - for (int i = 0; i < words(); i++) m_value[i] = {~0U, 0}; + for (int i = 0; i < words(); i++) m_data.num()[i] = {~0U, 0}; opCleanThis(); return *this; } V3Number& V3Number::setAllBitsX() { // Use setAllBitsXRemoved if calling this based on a non-X/Z input value such as divide by zero - for (int i = 0; i < words(); i++) m_value[i] = {~0U, ~0U}; + for (int i = 0; i < words(); i++) m_data.num()[i] = {~0U, ~0U}; opCleanThis(); return *this; } V3Number& V3Number::setAllBitsZ() { - for (int i = 0; i < words(); i++) m_value[i] = {0, ~0U}; + for (int i = 0; i < words(); i++) m_data.num()[i] = {0, ~0U}; opCleanThis(); return *this; } @@ -493,7 +494,7 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const { } else if (isString()) { return '"' + toString() + '"'; } else { - if (VL_UNCOVERABLE((m_value[words() - 1].m_value | m_value[words() - 1].m_valueX) + if (VL_UNCOVERABLE((m_data.num()[words() - 1].m_value | m_data.num()[words() - 1].m_valueX) & ~hiWordMask())) { out << "%E-hidden-bits"; // LCOV_EXCL_LINE } @@ -688,7 +689,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { } case 's': { // Spec says always drop leading zeros, this isn't quite right, we space pad. - int bit = this->width() - 1; + int bit = width() - 1; bool start = true; while ((bit % 8) != 7) bit++; for (; bit >= 0; bit -= 8) { @@ -709,7 +710,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { case 'd': { // Unsigned decimal const bool issigned = (code == '~'); if (fmtsize == "") { - const double mantissabits = this->width() - (issigned ? 1 : 0); + const double mantissabits = width() - (issigned ? 1 : 0); // To get the number of digits required, we want to compute // log10(2**mantissabits) and round it up. To be able to handle // a very wide mantissa, we use log2(2**mantissabits)/log2(10), @@ -765,7 +766,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { // 'p' // Packed - converted to another code by V3Width case 'u': { // Packed 2-state for (int i = 0; i < words(); i++) { - const uint32_t v = m_value[i].m_value; + const uint32_t v = m_data.num()[i].m_value; str += static_cast((v >> 0) & 0xff); str += static_cast((v >> 8) & 0xff); str += static_cast((v >> 16) & 0xff); @@ -775,7 +776,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { } case 'z': { // Packed 4-state for (int i = 0; i < words(); i++) { - const ValueAndX v = m_value[i]; + const ValueAndX v = m_data.num()[i]; str += static_cast((v.m_value >> 0) & 0xff); str += static_cast((v.m_value >> 8) & 0xff); str += static_cast((v.m_value >> 16) & 0xff); @@ -872,12 +873,12 @@ uint32_t V3Number::toUInt() const { UASSERT(!isFourState(), "toUInt with 4-state " << *this); // We allow wide numbers that represent values <= 32 bits for (int i = 1; i < words(); ++i) { - if (m_value[i].m_value) { + if (m_data.num()[i].m_value) { v3error("Value too wide for 32-bits expected in this context " << *this); break; } } - return m_value[0].m_value; + return m_data.num()[0].m_value; } double V3Number::toDouble() const { @@ -888,8 +889,8 @@ double V3Number::toDouble() const { double d; uint32_t u[2]; } u; - u.u[0] = m_value[0].m_value; - u.u[1] = m_value[1].m_value; + u.u[0] = m_data.num()[0].m_value; + u.u[1] = m_data.num()[1].m_value; return u.d; } @@ -911,14 +912,14 @@ uint64_t V3Number::toUQuad() const { // We allow wide numbers that represent values <= 64 bits if (isDouble()) return static_cast(toDouble()); for (int i = 2; i < words(); ++i) { - if (m_value[i].m_value) { + if (m_data.num()[i].m_value) { v3error("Value too wide for 64-bits expected in this context " << *this); break; } } if (width() <= 32) return (static_cast(toUInt())); - return ((static_cast(m_value[1].m_value) << 32ULL) - | (static_cast(m_value[0].m_value))); + return ((static_cast(m_data.num()[1].m_value) << 32ULL) + | (static_cast(m_data.num()[0].m_value))); } int64_t V3Number::toSQuad() const { @@ -932,8 +933,8 @@ int64_t V3Number::toSQuad() const { string V3Number::toString() const { UASSERT(!isFourState(), "toString with 4-state " << *this); // Spec says always drop leading zeros, this isn't quite right, we space pad. - if (isString()) return m_stringVal; - int bit = this->width() - 1; + if (isString()) return m_data.str(); + int bit = width() - 1; bool start = true; while ((bit % 8) != 7) bit++; string str; @@ -948,14 +949,18 @@ string V3Number::toString() const { } V3Hash V3Number::toHash() const { - V3Hash hash(m_width); - for (int i = 0; i < words(); ++i) { hash += m_value[i].m_value; } + V3Hash hash{width()}; + if (isString()) { + hash += V3Hash{m_data.str()}; + } else { + for (int i = 0; i < words(); ++i) { hash += m_data.num()[i].m_value; } + } return hash; } uint32_t V3Number::edataWord(int eword) const { UASSERT(!isFourState(), "edataWord with 4-state " << *this); - return m_value[eword].m_value; + return m_data.num()[eword].m_value; } uint8_t V3Number::dataByte(int byte) const { @@ -963,30 +968,34 @@ uint8_t V3Number::dataByte(int byte) const { } bool V3Number::isAllZ() const { + if (isDouble() || isString()) return false; for (int i = 0; i < width(); i++) { if (!bitIsZ(i)) return false; } return true; } bool V3Number::isAllX() const { + if (isDouble() || isString()) return false; uint32_t mask = hiWordMask(); for (int i = words() - 1; i >= 0; --i) { - const ValueAndX v = m_value[i]; + const ValueAndX v = m_data.num()[i]; if ((v.m_value & v.m_valueX) ^ mask) return false; mask = ~0U; } return true; } bool V3Number::isEqZero() const { + if (isString()) return m_data.str().empty(); for (int i = 0; i < words(); i++) { - const ValueAndX v = m_value[i]; + const ValueAndX v = m_data.num()[i]; if (v.m_value || v.m_valueX) return false; } return true; } bool V3Number::isNeqZero() const { + if (isString()) return !m_data.str().empty(); for (int i = 0; i < words(); i++) { - const ValueAndX v = m_value[i]; + const ValueAndX v = m_data.num()[i]; if (v.m_value & ~v.m_valueX) return true; } return false; @@ -998,9 +1007,9 @@ bool V3Number::isBitsZero(int msb, int lsb) const { return true; } bool V3Number::isEqOne() const { - if (m_value[0].m_value != 1 || m_value[0].m_valueX) return false; + if (m_data.num()[0].m_value != 1 || m_data.num()[0].m_valueX) return false; for (int i = 1; i < words(); i++) { - const ValueAndX v = m_value[i]; + const ValueAndX v = m_data.num()[i]; if (v.m_value || v.m_valueX) return false; } return true; @@ -1015,7 +1024,7 @@ bool V3Number::isEqAllOnes(int optwidth) const { bool V3Number::isFourState() const { if (isDouble() || isString()) return false; for (int i = 0; i < words(); ++i) { - if (m_value[i].m_valueX) return true; + if (m_data.num()[i].m_valueX) return true; } return false; } @@ -1036,10 +1045,10 @@ bool V3Number::isAnyZ() const { } bool V3Number::isLtXZ(const V3Number& rhs) const { // Include X/Z in comparisons for sort ordering - for (int bit = 0; bit < std::max(this->width(), rhs.width()); bit++) { - if (this->bitIs1(bit) && rhs.bitIs0(bit)) return true; - if (rhs.bitIs1(bit) && this->bitIs0(bit)) return false; - if (this->bitIsXZ(bit)) return true; + for (int bit = 0; bit < std::max(width(), rhs.width()); bit++) { + if (bitIs1(bit) && rhs.bitIs0(bit)) return true; + if (rhs.bitIs1(bit) && bitIs0(bit)) return false; + if (bitIsXZ(bit)) return true; if (rhs.bitIsXZ(bit)) return false; } return false; @@ -1070,7 +1079,7 @@ int V3Number::widthMin() const { uint32_t V3Number::countBits(const V3Number& ctrl) const { int n = 0; - for (int bit = 0; bit < this->width(); ++bit) { + for (int bit = 0; bit < width(); ++bit) { switch (ctrl.bitIs(0)) { case '0': if (bitIs0(bit)) ++n; @@ -1101,14 +1110,14 @@ uint32_t V3Number::countBits(const V3Number& ctrl1, const V3Number& ctrl2, uint32_t V3Number::countOnes() const { int n = 0; - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (bitIs1(bit)) n++; } return n; } uint32_t V3Number::mostSetBitP1() const { - for (int bit = this->width() - 1; bit >= 0; bit--) { + for (int bit = width() - 1; bit >= 0; bit--) { if (bitIs1(bit)) return bit + 1; } return 0; @@ -1120,7 +1129,7 @@ V3Number& V3Number::opBitsNonX(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIs0(bit) || lhs.bitIs1(bit)) setBit(bit, 1); } return *this; @@ -1130,7 +1139,7 @@ V3Number& V3Number::opBitsOne(const V3Number& lhs) { // 1->1, 0/X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIs1(bit)) setBit(bit, 1); } return *this; @@ -1140,7 +1149,7 @@ V3Number& V3Number::opBitsXZ(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIsXZ(bit)) setBit(bit, 1); } return *this; @@ -1150,7 +1159,7 @@ V3Number& V3Number::opBitsZ(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIsZ(bit)) setBit(bit, 1); } return *this; @@ -1160,7 +1169,7 @@ V3Number& V3Number::opBitsNonZ(const V3Number& lhs) { // 0/1->1, X/Z->0 NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (!lhs.bitIsZ(bit)) setBit(bit, 1); } return *this; @@ -1226,7 +1235,7 @@ V3Number& V3Number::opCountBits(const V3Number& expr, const V3Number& ctrl1, con NUM_ASSERT_OP_ARGS4(expr, ctrl1, ctrl2, ctrl3); NUM_ASSERT_LOGIC_ARGS4(expr, ctrl1, ctrl2, ctrl3); setZero(); - m_value[0].m_value = expr.countBits(ctrl1, ctrl2, ctrl3); + m_data.num()[0].m_value = expr.countBits(ctrl1, ctrl2, ctrl3); opCleanThis(); return *this; } @@ -1235,7 +1244,7 @@ V3Number& V3Number::opCountOnes(const V3Number& lhs) { NUM_ASSERT_LOGIC_ARGS1(lhs); if (lhs.isFourState()) return setAllBitsX(); setZero(); - m_value[0].m_value = lhs.countOnes(); + m_data.num()[0].m_value = lhs.countOnes(); opCleanThis(); return *this; } @@ -1292,7 +1301,7 @@ V3Number& V3Number::opNot(const V3Number& lhs) { NUM_ASSERT_LOGIC_ARGS1(lhs); // op i, L(lhs) bit return setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIs0(bit)) { setBit(bit, 1); } else if (lhs.bitIsXZ(bit)) { @@ -1307,7 +1316,7 @@ V3Number& V3Number::opAnd(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); // i op j, max(L(lhs),L(rhs)) bit return, careful need to X/Z extend. setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIs1(bit) && rhs.bitIs1(bit)) { setBit(bit, 1); } else if (lhs.bitIs0(bit) || rhs.bitIs0(bit)) { // 0 @@ -1323,7 +1332,7 @@ V3Number& V3Number::opOr(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); // i op j, max(L(lhs),L(rhs)) bit return, careful need to X/Z extend. setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIs1(bit) || rhs.bitIs1(bit)) { setBit(bit, 1); } else if (lhs.bitIs0(bit) && rhs.bitIs0(bit)) { @@ -1340,7 +1349,7 @@ V3Number& V3Number::opXor(const V3Number& lhs, const V3Number& rhs) { NUM_ASSERT_OP_ARGS2(lhs, rhs); NUM_ASSERT_LOGIC_ARGS2(lhs, rhs); setZero(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (lhs.bitIs1(bit) && rhs.bitIs0(bit)) { setBit(bit, 1); } else if (lhs.bitIs0(bit) && rhs.bitIs1(bit)) { @@ -1619,9 +1628,9 @@ bool V3Number::isCaseEq(const V3Number& rhs) const { // i op j, 1 bit return, max(L(lhs),L(rhs)) calculation, careful need to X/Z extend. if (isString()) return toString() == rhs.toString(); if (isDouble()) return toDouble() == rhs.toDouble(); - if (this->width() != rhs.width()) return false; + if (width() != rhs.width()) return false; for (int i = 0; i < words(); ++i) { - if (!(m_value[i] == rhs.m_value[i])) return false; + if (!(m_data.num()[i] == rhs.m_data.num()[i])) return false; } return true; } @@ -1754,7 +1763,7 @@ V3Number& V3Number::opShiftR(const V3Number& lhs, const V3Number& rhs) { } const uint32_t rhsval = rhs.toUInt(); if (rhsval < static_cast(lhs.width())) { - for (int bit = 0; bit < this->width(); bit++) setBit(bit, lhs.bitIs(bit + rhsval)); + for (int bit = 0; bit < width(); bit++) setBit(bit, lhs.bitIs(bit + rhsval)); } return *this; } @@ -1768,7 +1777,7 @@ V3Number& V3Number::opShiftRS(const V3Number& lhs, const V3Number& rhs, uint32_t if (rhs.isFourState()) return setAllBitsX(); setZero(); for (int bit = 32; bit < rhs.width(); bit++) { - for (int sbit = 0; sbit < this->width(); sbit++) { + for (int sbit = 0; sbit < width(); sbit++) { setBit(sbit, lhs.bitIs(lbits - 1)); // 0/1/X/Z } if (rhs.bitIs1(lbits - 1)) setAllBits1(); // -1 else 0 @@ -1776,11 +1785,11 @@ V3Number& V3Number::opShiftRS(const V3Number& lhs, const V3Number& rhs, uint32_t } const uint32_t rhsval = rhs.toUInt(); if (rhsval < static_cast(lhs.width())) { - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { setBit(bit, lhs.bitIsExtend(bit + rhsval, lbits)); } } else { - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { setBit(bit, lhs.bitIs(lbits - 1)); // 0/1/X/Z } } @@ -1797,7 +1806,7 @@ V3Number& V3Number::opShiftL(const V3Number& lhs, const V3Number& rhs) { if (rhs.bitIs1(bit)) return *this; // shift of over 2^32 must be zero } const uint32_t rhsval = rhs.toUInt(); - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (bit >= static_cast(rhsval)) setBit(bit, lhs.bitIs(bit - rhsval)); } return *this; @@ -1825,7 +1834,7 @@ V3Number& V3Number::opAdd(const V3Number& lhs, const V3Number& rhs) { setZero(); // Addem int carry = 0; - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { const int sum = ((lhs.bitIs1(bit) ? 1 : 0) + (rhs.bitIs1(bit) ? 1 : 0) + carry); if (sum & 1) setBit(bit, 1); carry = (sum >= 2); @@ -1852,15 +1861,15 @@ V3Number& V3Number::opMul(const V3Number& lhs, const V3Number& rhs) { opCleanThis(); // Mult produces extra bits in result } else { for (int lword = 0; lword < lhs.words(); lword++) { - const uint64_t lwordval = static_cast(lhs.m_value[lword].m_value); + const uint64_t lwordval = static_cast(lhs.m_data.num()[lword].m_value); if (lwordval == 0) continue; for (int rword = 0; rword < rhs.words(); rword++) { - const uint64_t rwordval = static_cast(rhs.m_value[rword].m_value); + const uint64_t rwordval = static_cast(rhs.m_data.num()[rword].m_value); if (rwordval == 0) continue; uint64_t mul = lwordval * rwordval; - for (int qword = lword + rword; qword < this->words(); qword++) { - mul += static_cast(m_value[qword].m_value); - m_value[qword].m_value = (mul & 0xffffffffULL); + for (int qword = lword + rword; qword < words(); qword++) { + mul += static_cast(m_data.num()[qword].m_value); + m_data.num()[qword].m_value = (mul & 0xffffffffULL); mul = (mul >> 32ULL) & 0xffffffffULL; if (mul == 0) break; } @@ -1977,17 +1986,18 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool if (vw == 1) { // Single divisor word breaks rest of algorithm uint64_t k = 0; for (int j = uw - 1; j >= 0; j--) { - const uint64_t unw64 = ((k << 32ULL) + static_cast(lhs.m_value[j].m_value)); - m_value[j].m_value = unw64 / static_cast(rhs.m_value[0].m_value); + const uint64_t unw64 + = ((k << 32ULL) + static_cast(lhs.m_data.num()[j].m_value)); + m_data.num()[j].m_value = unw64 / static_cast(rhs.m_data.num()[0].m_value); k = unw64 - - (static_cast(m_value[j].m_value) - * static_cast(rhs.m_value[0].m_value)); + - (static_cast(m_data.num()[j].m_value) + * static_cast(rhs.m_data.num()[0].m_value)); } UINFO(9, " opmoddiv-1w " << lhs << " " << rhs << " q=" << *this << " rem=0x" << std::hex << k << std::dec << endl); if (is_modulus) { setZero(); - m_value[0].m_value = k; + m_data.num()[0].m_value = k; } opCleanThis(); return *this; @@ -1998,7 +2008,7 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool uint32_t vn[VL_MULS_MAX_WORDS + 1]; // v normalized // Zero for ease of debugging and to save having to zero for shifts - for (int i = 0; i < words; i++) { m_value[i].m_value = 0; } + for (int i = 0; i < words; i++) { m_data.num()[i].m_value = 0; } for (int i = 0; i < words + 1; i++) { un[i] = vn[i] = 0; } // +1 as vn may get extra word // Algorithm requires divisor MSB to be set @@ -2006,22 +2016,22 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool const int s = 31 - ((vmsbp1 - 1) & 31); // shift amount (0...31) const uint32_t shift_mask = s ? 0xffffffff : 0; // otherwise >> 32 won't mask the value for (int i = vw - 1; i > 0; i--) { - vn[i] = (rhs.m_value[i].m_value << s) - | (shift_mask & (rhs.m_value[i - 1].m_value >> (32 - s))); + vn[i] = (rhs.m_data.num()[i].m_value << s) + | (shift_mask & (rhs.m_data.num()[i - 1].m_value >> (32 - s))); } - vn[0] = rhs.m_value[0].m_value << s; + vn[0] = rhs.m_data.num()[0].m_value << s; // Copy and shift dividend by same amount; may set new upper word if (s) { - un[uw] = lhs.m_value[uw - 1].m_value >> (32 - s); + un[uw] = lhs.m_data.num()[uw - 1].m_value >> (32 - s); } else { un[uw] = 0; } for (int i = uw - 1; i > 0; i--) { - un[i] = (lhs.m_value[i].m_value << s) - | (shift_mask & (lhs.m_value[i - 1].m_value >> (32 - s))); + un[i] = (lhs.m_data.num()[i].m_value << s) + | (shift_mask & (lhs.m_data.num()[i - 1].m_value >> (32 - s))); } - un[0] = lhs.m_value[0].m_value << s; + un[0] = lhs.m_data.num()[0].m_value << s; // printf(" un="); for (int i=5; i>=0; i--) printf(" %08x",un[i]); printf("\n"); // printf(" vn="); for (int i=5; i>=0; i--) printf(" %08x",vn[i]); printf("\n"); @@ -2052,11 +2062,11 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool } t = un[j + vw] - k; un[j + vw] = t; - this->m_value[j].m_value = qhat; // Save quotient digit + m_data.num()[j].m_value = qhat; // Save quotient digit if (t < 0) { // Over subtracted; correct by adding back - this->m_value[j].m_value--; + m_data.num()[j].m_value--; k = 0; for (int i = 0; i < vw; i++) { t = static_cast(un[i + j]) + static_cast(vn[i]) + k; @@ -2074,9 +2084,9 @@ V3Number& V3Number::opModDivGuts(const V3Number& lhs, const V3Number& rhs, bool if (is_modulus) { // modulus // Need to reverse normalization on copy to output for (int i = 0; i < vw; i++) { - m_value[i].m_value = (un[i] >> s) | (shift_mask & (un[i + 1] << (32 - s))); + m_data.num()[i].m_value = (un[i] >> s) | (shift_mask & (un[i + 1] << (32 - s))); } - for (int i = vw; i < words; i++) m_value[i].m_value = 0; + for (int i = vw; i < words; i++) m_data.num()[i].m_value = 0; opCleanThis(); UINFO(9, " opmoddiv-mod " << lhs << " " << rhs << " now=" << *this << endl); return *this; @@ -2110,7 +2120,7 @@ V3Number& V3Number::opPow(const V3Number& lhs, const V3Number& rhs, bool lsign, } if (lhs.isEqZero()) return setZero(); setZero(); - m_value[0].m_value = 1; + m_data.num()[0].m_value = 1; V3Number power(&lhs, width()); power.opAssign(lhs); for (int bit = 0; bit < rhs.width(); bit++) { @@ -2122,7 +2132,7 @@ V3Number& V3Number::opPow(const V3Number& lhs, const V3Number& rhs, bool lsign, if (rhs.bitIs1(bit)) { // out *= power V3Number lastOut(&lhs, width()); lastOut.opAssign(*this); - this->opMul(lastOut, power); + opMul(lastOut, power); // UINFO(0, "pow "<width(); bit++) { @@ -2198,14 +2215,14 @@ V3Number& V3Number::opClean(const V3Number& lhs, uint32_t bits) { return opSel(l void V3Number::opCleanThis(bool warnOnTruncation) { // Clean MSB of number NUM_ASSERT_LOGIC_ARGS1(*this); - const ValueAndX v = m_value[words() - 1]; + const ValueAndX v = m_data.num()[words() - 1]; const uint32_t newValueMsb = v.m_value & hiWordMask(); const uint32_t newValueXMsb = v.m_valueX & hiWordMask(); if (warnOnTruncation && (newValueMsb != v.m_value || newValueXMsb != v.m_valueX)) { // Displaying in decimal avoids hiWordMask truncation v3warn(WIDTH, "Value too large for " << width() << " bit number: " << displayed("%d")); } - m_value[words() - 1] = {newValueMsb, newValueXMsb}; + m_data.num()[words() - 1] = {newValueMsb, newValueXMsb}; } V3Number& V3Number::opSel(const V3Number& lhs, const V3Number& msb, const V3Number& lsb) { @@ -2221,7 +2238,7 @@ V3Number& V3Number::opSel(const V3Number& lhs, uint32_t msbval, uint32_t lsbval) NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); int ibit = lsbval; - for (int bit = 0; bit < this->width(); bit++) { + for (int bit = 0; bit < width(); bit++) { if (ibit >= 0 && ibit < lhs.width() && ibit <= static_cast(msbval)) { setBit(bit, lhs.bitIs(ibit)); } else { @@ -2317,21 +2334,17 @@ V3Number& V3Number::opRealToBits(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_DOUBLE_ARGS1(lhs); // Conveniently our internal format is identical so we can copy bits... - if (lhs.width() != 64 || this->width() != 64) { - v3fatalSrc("Real operation on wrong sized number"); - } + if (lhs.width() != 64 || width() != 64) v3fatalSrc("Real operation on wrong sized number"); + m_data.setLogic(); opAssign(lhs); - m_double = false; return *this; } V3Number& V3Number::opBitsToRealD(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); // Conveniently our internal format is identical so we can copy bits... - if (lhs.width() != 64 || this->width() != 64) { - v3fatalSrc("Real operation on wrong sized number"); - } + if (lhs.width() != 64 || width() != 64) v3fatalSrc("Real operation on wrong sized number"); + m_data.setDouble(); opAssign(lhs); - m_double = true; return *this; } V3Number& V3Number::opNegateD(const V3Number& lhs) { diff --git a/src/V3Number.h b/src/V3Number.h index fe2f11c5d..1dbec5d36 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -22,8 +22,10 @@ #include "V3Error.h" #include "V3Hash.h" +#include "V3StdFuture.h" #include +#include #include #include #include @@ -42,8 +44,6 @@ class AstNode; class AstNodeDType; class FileLine; -// Holds a few entries of ValueAndX to avoid dynamic allocation in std::vector for less width of -// constants class V3NumberData final { public: // TYPES @@ -57,53 +57,294 @@ public: } }; + enum class V3NumberDataType : uint8_t { + UNINITIALIZED = 0, + LOGIC = 1, + DOUBLE = 2, + STRING = 3, + }; + friend std::ostream& operator<<(std::ostream& os, const V3NumberDataType& rhs) { + switch (rhs) { + case V3NumberDataType::UNINITIALIZED: return os << "UNINITIALIZED"; + case V3NumberDataType::LOGIC: return os << "LOGIC"; + case V3NumberDataType::DOUBLE: return os << "DOUBLE"; + case V3NumberDataType::STRING: return os << "STRING"; + } + return os; + } + private: + // CONSTANTS + // At least 2 words (64 fourstate bits). 4 words (128 fourstate bits) in most cases, + // i.e. when std::string has 32 bytes. + static constexpr int INLINE_WORDS + = vlstd::max(2UL, vlstd::max(sizeof(std::string) / sizeof(ValueAndX), + sizeof(std::vector) / sizeof(ValueAndX))); + // When m_width > MAX_INLINE_WIDTH number is stored in m_dynamicNumber. + // Otherwise number is stored in m_inlineNumber. + static constexpr int MAX_INLINE_WIDTH = INLINE_WORDS * sizeof(ValueAndX) / 2 * 8; + // MEMBERS - static constexpr size_t m_inlinedSize = 2; // Can hold 64 bit without dynamic allocation - ValueAndX m_inlined[m_inlinedSize]; // Holds the beginning m_inlinedSize words - std::vector m_data; // Holds m_inlinedSize-th word and later + union { + std::array m_inlineNumber; + std::vector m_dynamicNumber; + std::string m_string; + }; + + int m_width = 0; // Width (in bits) as specified/calculated + V3NumberDataType m_type; + +public: + bool m_sized : 1; // True if the user specified the width, else we track it. + bool m_signed : 1; // True if signed value + bool m_isNull : 1; // True if "null" versus normal 0 + bool m_fromString : 1; // True if from string literal + bool m_autoExtend : 1; // True if SystemVerilog extend-to-any-width public: // CONSTRUCTORS - V3NumberData() { - for (size_t i = 0; i < m_inlinedSize; ++i) m_inlined[i] = {0, 0}; + V3NumberData() + : m_type{V3NumberDataType::UNINITIALIZED} + , m_sized{false} + , m_signed{false} + , m_isNull{false} + , m_fromString{false} + , m_autoExtend{false} {} + + ~V3NumberData() { destroyStoredValue(); } + + V3NumberData(const V3NumberData& other) + : m_width{other.m_width} + , m_type{other.m_type} + , m_sized{other.m_sized} + , m_signed{other.m_signed} + , m_isNull{other.m_isNull} + , m_fromString{other.m_fromString} + , m_autoExtend{other.m_autoExtend} { + if (other.isInlineNumber()) { + initInlineNumber(other.m_inlineNumber); + } else if (other.isDynamicNumber()) { + initDynamicNumber(other.m_dynamicNumber); + } else if (other.isString()) { + initString(other.m_string); + } } + V3NumberData& operator=(const V3NumberData& other) { + if (other.isInlineNumber()) { + destroyStoredValue(); + initInlineNumber(other.m_inlineNumber); + } else if (other.isDynamicNumber()) { + reinitWithOrAssignDynamicNumber(other.m_dynamicNumber); + } else if (other.isString()) { + reinitWithOrAssignString(other.m_string); + } else { + destroyStoredValue(); + } + m_width = other.m_width; + m_type = other.m_type; + m_sized = other.m_sized; + m_signed = other.m_signed; + m_isNull = other.m_isNull; + m_fromString = other.m_fromString; + m_autoExtend = other.m_autoExtend; + return *this; + } + + V3NumberData(V3NumberData&& other) + : m_width{other.m_width} + , m_type{other.m_type} + , m_sized{other.m_sized} + , m_signed{other.m_signed} + , m_isNull{other.m_isNull} + , m_fromString{other.m_fromString} + , m_autoExtend{other.m_autoExtend} { + if (other.isInlineNumber()) { + initInlineNumber(other.m_inlineNumber); + } else if (other.isDynamicNumber()) { + initDynamicNumber(std::move(other.m_dynamicNumber)); + } else if (other.isString()) { + initString(std::move(other.m_string)); + } + other.m_type = V3NumberDataType::UNINITIALIZED; + } + + V3NumberData& operator=(V3NumberData&& other) { + if (other.isInlineNumber()) { + destroyStoredValue(); + initInlineNumber(other.m_inlineNumber); + } else if (other.isDynamicNumber()) { + reinitWithOrAssignDynamicNumber(std::move(other.m_dynamicNumber)); + } else if (other.isString()) { + reinitWithOrAssignString(std::move(other.m_string)); + } else { + destroyStoredValue(); + } + m_width = other.m_width; + m_type = other.m_type; + m_sized = other.m_sized; + m_signed = other.m_signed; + m_isNull = other.m_isNull; + m_fromString = other.m_fromString; + m_autoExtend = other.m_autoExtend; + other.m_type = V3NumberDataType::UNINITIALIZED; + return *this; + } + + // ACCESSORS + ValueAndX* num() { + UASSERT(isNumber(), "`num` member accessed when data type is " << m_type); + return isInlineNumber() ? m_inlineNumber.data() : m_dynamicNumber.data(); + } + const ValueAndX* num() const { + UASSERT(isNumber(), "`num` member accessed when data type is " << m_type); + return isInlineNumber() ? m_inlineNumber.data() : m_dynamicNumber.data(); + } + std::string& str() { + UASSERT(isString(), "`str` member accessed when data type is " << m_type); + return m_string; + } + const std::string& str() const { + UASSERT(isString(), "`str` member accessed when data type is " << m_type); + return m_string; + } + + int width() const { return m_width; } + V3NumberDataType type() const { return m_type; } + // METHODS - void ensureSizeAtLeast(size_t s) { - if (VL_UNLIKELY(s > m_data.size() + m_inlinedSize)) m_data.resize(s - m_inlinedSize); + void resize(int bitsCount) { + if (m_width == bitsCount) return; + if (bitsToWords(m_width) == bitsToWords(bitsCount)) { + m_width = bitsCount; + return; + } + if (isDynamicNumber()) { + if (bitsCount > MAX_INLINE_WIDTH) { + m_dynamicNumber.resize(bitsToWords(bitsCount)); + } else { + const auto dynamicBits = std::move(m_dynamicNumber); + destroyDynamicNumber(); + initInlineNumber(); + std::memcpy(m_inlineNumber.data(), dynamicBits.data(), sizeof(m_inlineNumber)); + } + } else if (isInlineNumber()) { + if (bitsCount > MAX_INLINE_WIDTH) { + const auto bits = m_inlineNumber; + initDynamicNumber(bitsToWords(bitsCount)); + std::memcpy(m_dynamicNumber.data(), bits.data(), sizeof(bits)); + } + } + m_width = bitsCount; } - ValueAndX& operator[](size_t idx) { - UDEBUGONLY(UASSERT(idx < m_data.size() + m_inlinedSize, - "idx:" << idx << " size:" << m_data.size() - << " inlinedSize:" << m_inlinedSize);); - return idx >= m_inlinedSize ? m_data[idx - m_inlinedSize] : m_inlined[idx]; + + void setString() { + // If there has been a string already it is kept intact. + if (isString()) return; + if (isDynamicNumber()) destroyDynamicNumber(); + initString(); + m_type = V3NumberDataType::STRING; + } + void setString(std::string&& s) { + reinitWithOrAssignString(std::move(s)); + m_type = V3NumberDataType::STRING; + } + void setString(const std::string& s) { + reinitWithOrAssignString(s); + m_type = V3NumberDataType::STRING; + } + + void setDouble() { + destroyStoredValue(); + if (!isInlineNumber()) initInlineNumber(); + m_type = V3NumberDataType::DOUBLE; + resize(64); + } + + void setLogic() { + if (isString()) destroyString(); + if (!isNumber()) { + if (m_width <= MAX_INLINE_WIDTH) { + initInlineNumber(); + } else { + initDynamicNumber(bitsToWords(m_width)); + } + } + m_type = V3NumberDataType::LOGIC; + resize(m_width); + } + +private: + static constexpr int bitsToWords(int bitsCount) { return (bitsCount + 31) / 32; } + + bool isNumber() const { + return m_type == V3NumberDataType::DOUBLE || m_type == V3NumberDataType::LOGIC; + } + bool isInlineNumber() const { + return (m_width <= MAX_INLINE_WIDTH) + && (m_type == V3NumberDataType::DOUBLE || m_type == V3NumberDataType::LOGIC); + } + bool isDynamicNumber() const { + return (m_width > MAX_INLINE_WIDTH) && (m_type == V3NumberDataType::LOGIC); + } + bool isString() const { return m_type == V3NumberDataType::STRING; } + + template + void initInlineNumber(Args&&... args) { + new (&m_inlineNumber) std::array(std::forward(args)...); + } + template + void initDynamicNumber(Args&&... args) { + new (&m_dynamicNumber) std::vector(std::forward(args)...); + } + template + void initString(Args&&... args) { + new (&m_string) std::string(std::forward(args)...); + } + + void destroyDynamicNumber() { m_dynamicNumber.~vector(); } + void destroyString() { m_string.~string(); } + void destroyStoredValue() { + if (isString()) + destroyString(); + else if (isDynamicNumber()) + destroyDynamicNumber(); + } + + template + void reinitWithOrAssignDynamicNumber(T&& s) { + if (isDynamicNumber()) { + m_dynamicNumber = std::forward(s); + return; + } + if (isString()) destroyString(); + initDynamicNumber(std::forward(s)); + } + template + void reinitWithOrAssignString(T&& s) { + if (isString()) { + m_string = std::forward(s); + return; + } + if (isDynamicNumber()) destroyDynamicNumber(); + initString(std::forward(s)); } - const ValueAndX& operator[](size_t idx) const { return const_cast(*this)[idx]; } }; class V3Number final { // TYPES using ValueAndX = V3NumberData::ValueAndX; + using V3NumberDataType = V3NumberData::V3NumberDataType; + + // MEMBERS + V3NumberData m_data; + AstNode* m_nodep = nullptr; // Parent node + FileLine* m_fileline = nullptr; - // Large 4-state number handling - int m_width; // Width as specified/calculated. - bool m_sized : 1; // True if the user specified the width, else we track it. - bool m_signed : 1; // True if signed value - bool m_double : 1; // True if double real value - bool m_isNull : 1; // True if "null" versus normal 0 - bool m_isString : 1; // True if string - bool m_fromString : 1; // True if from string literal - bool m_autoExtend : 1; // True if SystemVerilog extend-to-any-width - FileLine* m_fileline; - AstNode* m_nodep; // Parent node - V3NumberData m_value; // Value and X/Z information - string m_stringVal; // If isString, the value of the string // METHODS V3Number& setSingleBits(char value); V3Number& setString(const string& str) { - m_isString = true; - m_stringVal = str; + m_data.setString(str); return *this; } void opCleanThis(bool warnOnTruncation = false); @@ -116,10 +357,10 @@ public: V3Number& setLong(uint32_t value); V3Number& setLongS(int32_t value); V3Number& setDouble(double value); - void setBit(int bit, char value) { // Note must be pre-zeroed! - if (bit >= m_width) return; + void setBit(int bit, char value) { // Note: must be initialized as number and pre-zeroed! + if (bit >= m_data.width()) return; const uint32_t mask = (1UL << (bit & 31)); - ValueAndX& v = m_value[bit / 32]; + ValueAndX& v = m_data.num()[bit / 32]; if (value == '0' || value == 0) { v.m_value &= ~mask; v.m_valueX &= ~mask; @@ -137,65 +378,71 @@ public: private: char bitIs(int bit) const { - if (bit >= m_width || bit < 0) { + if (bit >= m_data.width() || bit < 0) { // We never sign extend return '0'; } - const ValueAndX v = m_value[bit / 32]; + const ValueAndX v = m_data.num()[bit / 32]; return ("01zx"[(((v.m_value & (1UL << (bit & 31))) ? 1 : 0) | ((v.m_valueX & (1UL << (bit & 31))) ? 2 : 0))]); } char bitIsExtend(int bit, int lbits) const { // lbits usually = width, but for C optimizations width=32_bits, lbits = 32_or_less if (bit < 0) return '0'; - UASSERT(lbits <= m_width, "Extend of wrong size"); + UASSERT(lbits <= m_data.width(), "Extend of wrong size"); if (bit >= lbits) { bit = lbits ? lbits - 1 : 0; - const ValueAndX v = m_value[bit / 32]; + const ValueAndX v = m_data.num()[bit / 32]; // We do sign extend return ("01zx"[(((v.m_value & (1UL << (bit & 31))) ? 1 : 0) | ((v.m_valueX & (1UL << (bit & 31))) ? 2 : 0))]); } - const ValueAndX v = m_value[bit / 32]; + const ValueAndX v = m_data.num()[bit / 32]; return ("01zx"[(((v.m_value & (1UL << (bit & 31))) ? 1 : 0) | ((v.m_valueX & (1UL << (bit & 31))) ? 2 : 0))]); } public: bool bitIs0(int bit) const { + if (!isNumber()) return false; if (bit < 0) return false; - if (bit >= m_width) return !bitIsXZ(m_width - 1); - const ValueAndX v = m_value[bit / 32]; + if (bit >= m_data.width()) return !bitIsXZ(m_data.width() - 1); + const ValueAndX v = m_data.num()[bit / 32]; return ((v.m_value & (1UL << (bit & 31))) == 0 && !(v.m_valueX & (1UL << (bit & 31)))); } bool bitIs1(int bit) const { + if (!isNumber()) return false; if (bit < 0) return false; - if (bit >= m_width) return false; - const ValueAndX v = m_value[bit / 32]; + if (bit >= m_data.width()) return false; + const ValueAndX v = m_data.num()[bit / 32]; return ((v.m_value & (1UL << (bit & 31))) && !(v.m_valueX & (1UL << (bit & 31)))); } bool bitIs1Extend(int bit) const { + if (!isNumber()) return false; if (bit < 0) return false; - if (bit >= m_width) return bitIs1Extend(m_width - 1); - const ValueAndX v = m_value[bit / 32]; + if (bit >= m_data.width()) return bitIs1Extend(m_data.width() - 1); + const ValueAndX v = m_data.num()[bit / 32]; return ((v.m_value & (1UL << (bit & 31))) && !(v.m_valueX & (1UL << (bit & 31)))); } bool bitIsX(int bit) const { + if (!isNumber()) return false; if (bit < 0) return false; - if (bit >= m_width) return bitIsZ(m_width - 1); - const ValueAndX v = m_value[bit / 32]; + if (bit >= m_data.width()) return bitIsZ(m_data.width() - 1); + const ValueAndX v = m_data.num()[bit / 32]; return ((v.m_value & (1UL << (bit & 31))) && (v.m_valueX & (1UL << (bit & 31)))); } bool bitIsXZ(int bit) const { + if (!isNumber()) return false; if (bit < 0) return false; - if (bit >= m_width) return bitIsXZ(m_width - 1); - const ValueAndX v = m_value[bit / 32]; + if (bit >= m_data.width()) return bitIsXZ(m_data.width() - 1); + const ValueAndX v = m_data.num()[bit / 32]; return ((v.m_valueX & (1UL << (bit & 31)))); } bool bitIsZ(int bit) const { + if (!isNumber()) return false; if (bit < 0) return false; - if (bit >= m_width) return bitIsZ(m_width - 1); - const ValueAndX v = m_value[bit / 32]; + if (bit >= m_data.width()) return bitIsZ(m_data.width() - 1); + const ValueAndX v = m_data.num()[bit / 32]; return ((~v.m_value & (1UL << (bit & 31))) && (v.m_valueX & (1UL << (bit & 31)))); } @@ -217,10 +464,12 @@ private: public: // CONSTRUCTORS explicit V3Number(AstNode* nodep) { init(nodep, 1); } - V3Number(AstNode* nodep, int width) { init(nodep, width); } // 0=unsized + V3Number(AstNode* nodep, int width) { // 0=unsized + init(nodep, width, width > 0); + } V3Number(AstNode* nodep, int width, uint32_t value, bool sized = true) { init(nodep, width, sized); - m_value[0].m_value = value; + m_data.num()[0].m_value = value; opCleanThis(); } // Create from a verilog 32'hxxxx number. @@ -233,15 +482,16 @@ public: V3Number(VerilogStringLiteral, AstNode* nodep, const string& str); class String {}; V3Number(String, AstNode* nodep, const string& value) { - init(nodep, 0); + init(nodep); setString(value); - m_fromString = true; + m_data.m_fromString = true; } class Null {}; V3Number(Null, AstNode* nodep) { - init(nodep, 0); - m_isNull = true; - m_autoExtend = true; + init(nodep); + m_data.setLogic(); + m_data.m_isNull = true; + m_data.m_autoExtend = true; } explicit V3Number(const V3Number* nump, int width = 1) { init(nullptr, width); @@ -249,7 +499,7 @@ public: } V3Number(const V3Number* nump, int width, uint32_t value) { init(nullptr, width); - m_value[0].m_value = value; + m_data.num()[0].m_value = value; opCleanThis(); m_fileline = nump->fileline(); } @@ -259,19 +509,31 @@ public: } V3Number(AstNode* nodep, const AstNodeDType* nodedtypep); + V3Number(const V3Number& other) = default; + V3Number& operator=(const V3Number& other) = default; + + V3Number(V3Number&& other) = default; + V3Number& operator=(V3Number&& other) = default; + + ~V3Number() {} + private: void V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl); - void init(AstNode* nodep, int swidth, bool sized = true) { + void init(AstNode* nodep, int swidth = -1, bool sized = true) { setNames(nodep); - // dtype info does NOT from nodep's dtype; nodep only for error reporting - m_signed = false; - m_double = false; - m_isNull = false; - m_isString = false; - m_autoExtend = false; - m_fromString = false; - width(swidth, sized); - for (int i = 0; i < words(); ++i) m_value[i] = {0, 0}; + if (swidth >= 0) { + if (swidth == 0) { + swidth = 1; + sized = false; + } + m_data.setLogic(); + m_data.resize(swidth); + m_data.m_sized = sized; + for (int i = 0; i < words(); ++i) m_data.num()[i] = {0, 0}; + } else { + m_data.resize(1); + m_data.m_sized = false; + } } void setNames(AstNode* nodep); static string displayPad(size_t fmtsize, char pad, bool left, const string& in); @@ -282,15 +544,8 @@ public: void v3errorEnd(std::ostringstream& sstr) const; void v3errorEndFatal(std::ostringstream& sstr) const VL_ATTR_NORETURN; void width(int width, bool sized = true) { - // Set width. Only set m_width here, as we need to tweak vector size - if (width) { - m_sized = sized; - m_width = width; - } else { - m_sized = false; - m_width = 1; - } - m_value.ensureSizeAtLeast(words()); + m_data.m_sized = sized; + m_data.resize(width); } // SETTERS @@ -305,25 +560,39 @@ public: string ascii(bool prefixed = true, bool cleanVerilog = false) const; string displayed(AstNode* nodep, const string& vformat) const; static bool displayedFmtLegal(char format, bool isScan); // Is this a valid format letter? - int width() const { return m_width; } + int width() const { return m_data.width(); } int widthMin() const; // Minimum width that can represent this number (~== log2(num)+1) - bool sized() const { return m_sized; } - bool autoExtend() const { return m_autoExtend; } - bool isFromString() const { return m_fromString; } + bool sized() const { return m_data.m_sized; } + bool autoExtend() const { return m_data.m_autoExtend; } + bool isFromString() const { return m_data.m_fromString; } + V3NumberDataType dataType() const { return m_data.type(); } + void dataType(V3NumberDataType newType) { + if (dataType() == newType) return; + UASSERT(newType != V3NumberDataType::UNINITIALIZED, "Can't set type to UNINITIALIZED."); + switch (newType) { + case V3NumberDataType::STRING: m_data.setString(); break; + case V3NumberDataType::DOUBLE: m_data.setDouble(); break; + case V3NumberDataType::LOGIC: m_data.setLogic(); break; + case V3NumberDataType::UNINITIALIZED: break; + } + } // Only correct for parsing of numbers from strings, otherwise not used // (use AstConst::isSigned()) - bool isSigned() const { return m_signed; } - // Only correct for parsing of numbers from strings, otherwise not used - // (use AstConst::isSigned()) - bool isDouble() const { return m_double; } - // Only if have 64 bit value loaded, and want to indicate it's real - bool isString() const { return m_isString; } - bool isNegative() const { return bitIs1(width() - 1); } - bool isNull() const { return m_isNull; } + bool isSigned() const { return m_data.m_signed; } + void isSigned(bool ssigned) { m_data.m_signed = ssigned; } + bool isDouble() const { return dataType() == V3NumberDataType::DOUBLE; } + bool isString() const { return dataType() == V3NumberDataType::STRING; } + bool isNumber() const { + return m_data.type() == V3NumberDataType::LOGIC + || m_data.type() == V3NumberDataType::DOUBLE; + } + bool isNegative() const { return !isString() && bitIs1(width() - 1); } + bool isNull() const { return m_data.m_isNull; } bool isFourState() const; bool hasZ() const { + if (isString()) return false; for (int i = 0; i < words(); i++) { - const ValueAndX v = m_value[i]; + const ValueAndX v = m_data.num()[i]; if ((~v.m_value) & v.m_valueX) return true; } return false; @@ -337,11 +606,10 @@ public: bool isEqAllOnes(int optwidth = 0) const; bool isCaseEq(const V3Number& rhs) const; // operator== bool isLtXZ(const V3Number& rhs) const; // operator< with XZ compared - void isSigned(bool ssigned) { m_signed = ssigned; } bool isAnyX() const; bool isAnyXZ() const; bool isAnyZ() const; - bool isMsbXZ() const { return bitIsXZ(m_width - 1); } + bool isMsbXZ() const { return bitIsXZ(m_data.width() - 1); } uint32_t toUInt() const; int32_t toSInt() const; uint64_t toUQuad() const; diff --git a/src/V3StdFuture.h b/src/V3StdFuture.h new file mode 100644 index 000000000..32a4f7539 --- /dev/null +++ b/src/V3StdFuture.h @@ -0,0 +1,30 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Backports of features from future C++ versions +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2022 by Wilson Snyder. This program is free software; you +// can redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#ifndef VERILATOR_V3STDFUTURE_H_ +#define VERILATOR_V3STDFUTURE_H_ + +namespace vlstd { + +// constexpr std::max with arguments passed by value (required by constexpr before C++14) +template +constexpr T max(T a, T b) { + return a > b ? a : b; +} + +}; // namespace vlstd + +#endif // Guard From 5df14627fdb57c29ce8fc5084c1dad61f4c69cc0 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 20 Sep 2022 18:23:44 -0400 Subject: [PATCH 54/75] Fix 32-bit build of previous commit --- src/V3Number.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/V3Number.h b/src/V3Number.h index 1dbec5d36..f149c6ae6 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -77,9 +77,9 @@ private: // CONSTANTS // At least 2 words (64 fourstate bits). 4 words (128 fourstate bits) in most cases, // i.e. when std::string has 32 bytes. - static constexpr int INLINE_WORDS - = vlstd::max(2UL, vlstd::max(sizeof(std::string) / sizeof(ValueAndX), - sizeof(std::vector) / sizeof(ValueAndX))); + static constexpr int INLINE_WORDS = vlstd::max( + static_cast(2), vlstd::max(sizeof(std::string) / sizeof(ValueAndX), + sizeof(std::vector) / sizeof(ValueAndX))); // When m_width > MAX_INLINE_WIDTH number is stored in m_dynamicNumber. // Otherwise number is stored in m_inlineNumber. static constexpr int MAX_INLINE_WIDTH = INLINE_WORDS * sizeof(ValueAndX) / 2 * 8; From 0b07679ff21f2ef0418a4604d69df2579c4360f7 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Wed, 21 Sep 2022 11:54:23 +0200 Subject: [PATCH 55/75] v3errorEnd: look for instance only when warning is not ignored (#3632) This approach reduced total time of V3Undriven stage from 34,2s to 2,5s in design containing almost 400 000 unused variables. Signed-off-by: Kamil Rakoczy --- src/V3Ast.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 24c4d0e12..9b406f816 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -1212,7 +1212,11 @@ void AstNode::v3errorEnd(std::ostringstream& str) const { const_cast(this)->dump(nsstr); nsstr << endl; } - m_fileline->v3errorEnd(nsstr, instanceStr()); + // Don't look for instance name when warning is disabled. + // In case of large number of warnings, this can + // take significant amount of time + m_fileline->v3errorEnd(nsstr, + m_fileline->warnIsOff(V3Error::errorCode()) ? "" : instanceStr()); } } From 0a8cfb8d2c52d8b5faf51870fb89dc749347272f Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Wed, 21 Sep 2022 11:35:03 +0100 Subject: [PATCH 56/75] Put dump file in TEST_OBJ_DIR --- test_regress/t/t_trace_open_wrong_order.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_regress/t/t_trace_open_wrong_order.cpp b/test_regress/t/t_trace_open_wrong_order.cpp index 4faa6dd5b..56dae22c3 100644 --- a/test_regress/t/t_trace_open_wrong_order.cpp +++ b/test_regress/t/t_trace_open_wrong_order.cpp @@ -17,7 +17,7 @@ int main(int argc, char** argv) { VerilatedVcdC tfp; Vt_trace_open_wrong_order dut; ctx.traceEverOn(true); - tfp.open("dump.vcd"); // Error! shall put to the next line! + tfp.open(VL_STRINGIFY(TEST_OBJ_DIR) "/dump.vcd"); // Error! shall put to the next line! dut.trace(&tfp, 99); // Error! tfp.dump(0); tfp.close(); From ce03293128d555b70e2bd5fd33c5dd70c322f79b Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Thu, 15 Sep 2022 19:43:56 +0100 Subject: [PATCH 57/75] Generate AstNode accessors via astgen Introduce the @astgen directives parsed by astgen, currently used for the generation child node (operand) accessors. Please see the updated internal documentation for details. --- docs/internals.rst | 100 +++- src/V3Active.cpp | 14 +- src/V3Assert.cpp | 20 +- src/V3AssertPre.cpp | 2 +- src/V3AstInlines.h | 21 +- src/V3AstNodeDType.h | 149 ++---- src/V3AstNodeMath.h | 469 +++++++---------- src/V3AstNodeOther.h | 1057 ++++++++++++++++----------------------- src/V3AstNodes.cpp | 56 +-- src/V3Begin.cpp | 10 +- src/V3Branch.cpp | 2 +- src/V3Broken.cpp | 4 +- src/V3CCtors.cpp | 6 +- src/V3CUse.cpp | 2 +- src/V3Case.cpp | 10 +- src/V3Changed.cpp | 8 +- src/V3Class.cpp | 16 +- src/V3Clean.cpp | 6 +- src/V3Clock.cpp | 16 +- src/V3Common.cpp | 6 +- src/V3Config.cpp | 4 +- src/V3Const.cpp | 105 ++-- src/V3Coverage.cpp | 46 +- src/V3Delayed.cpp | 8 +- src/V3DepthBlock.cpp | 2 +- src/V3Descope.cpp | 2 +- src/V3EmitCFunc.h | 20 +- src/V3EmitV.cpp | 26 +- src/V3Expand.cpp | 4 +- src/V3Force.cpp | 4 +- src/V3Gate.cpp | 4 +- src/V3GenClk.cpp | 6 +- src/V3Inline.cpp | 30 +- src/V3InstrCount.cpp | 12 +- src/V3Life.cpp | 4 +- src/V3LinkCells.cpp | 4 +- src/V3LinkDot.cpp | 8 +- src/V3LinkInc.cpp | 6 +- src/V3LinkJump.cpp | 14 +- src/V3LinkLevel.cpp | 10 +- src/V3LinkParse.cpp | 4 +- src/V3LinkResolve.cpp | 4 +- src/V3MergeCond.cpp | 16 +- src/V3Order.cpp | 12 +- src/V3Param.cpp | 12 +- src/V3ParseImp.cpp | 2 +- src/V3Partition.cpp | 6 +- src/V3Premit.cpp | 4 +- src/V3ProtectLib.cpp | 66 +-- src/V3Randomize.cpp | 2 +- src/V3Reloop.cpp | 2 +- src/V3Scope.cpp | 30 +- src/V3SenTree.h | 2 +- src/V3Simulate.h | 18 +- src/V3Slice.cpp | 4 +- src/V3Split.cpp | 18 +- src/V3SplitVar.cpp | 10 +- src/V3Stats.cpp | 4 +- src/V3Table.cpp | 8 +- src/V3Task.cpp | 32 +- src/V3Trace.cpp | 12 +- src/V3TraceDecl.cpp | 6 +- src/V3Tristate.cpp | 40 +- src/V3Unknown.cpp | 10 +- src/V3Unroll.cpp | 14 +- src/V3VariableOrder.cpp | 2 +- src/V3Width.cpp | 46 +- src/astgen | 146 +++++- src/bisonpre | 5 +- src/verilog.y | 86 ++-- 70 files changed, 1386 insertions(+), 1530 deletions(-) diff --git a/docs/internals.rst b/docs/internals.rst index c9e00d7dd..c62881026 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -96,10 +96,11 @@ this. Each ``AstNode`` has pointers to up to four children, accessed by the ``op1p`` through ``op4p`` methods. These methods are then abstracted in a specific Ast\* node class to a more specific name. For example with the -``AstIf`` node (for ``if`` statements), ``ifsp`` calls ``op2p`` to give the +``AstIf`` node (for ``if`` statements), ``thensp`` calls ``op2p`` to give the pointer to the AST for the "then" block, while ``elsesp`` calls ``op3p`` to give the pointer to the AST for the "else" block, or NULL if there is not -one. +one. These accessors are automatically generated by ``astgen`` after +parsing the ``@astgen`` directives in the specific ``AstNode`` subclasses. ``AstNode`` has the concept of a next and previous AST - for example the next and previous statements in a block. Pointers to the AST for these @@ -501,22 +502,99 @@ code: The ``astgen`` Script --------------------- -Some of the code implementing passes is extremely repetitive, and must be -implemented for each sub-class of ``AstNode``. However, while repetitive, -there is more variability than can be handled in C++ macros. +The ``astgen`` script is used to generate some of the repetitive C++ code +related to the ``AstNode`` type hierarchy. An example is the abstract ``visit`` +methods in ``VNVisitor``. There are other uses, please see the ``*__gen*`` +files in the bulid directories and the ``astgen`` script itself for details. A +description of the more advanced features of ``astgen`` are provided here. -In Verilator this is implemented by using a script, ``astgen`` to -pre-process the C++ code. For example in ``V3Const.cpp`` this is used to -implement the ``visit()`` functions for each binary operation using the -``TREEOP`` macro. -The original C source code is transformed into C code in the ``obj_opt`` +Generating ``AstNode`` members +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some of the member s of ``AstNode`` sub-classes are generated by ``astgen``. +These are emitted as pre-processor macro definitions, which then need to be +added to the ``AstNode`` sub-classes they correspond to. Specifically ``class +AstFoo`` should contain an instance of ``ASTGEN_MEMBERS_Foo;`` at class scope. +The ``astgen`` script checks and errors if this is not present. The method +generated depends on whether the class is a concrete final class, or an +abstract ``AstNode*`` base-class, and on ``@astgen`` directives present in +comment sections in the body of the ``AstNode`` sub-class definitions. + + +List of ``@astgen`` directives +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``@astgen`` directives in comments contained in the body of ``AstNode`` +sub-class definitions are parsed and contribute to the code generated by +``astgen``. The general syntax is ``@astgen := ``, +where ```` determines what is being defined, and ```` is +a ```` dependent description of the definition. The list of +``@astgen`` directives is as follows: + + +``op`` operand directives +""""""""""""""""""""""""""""" + +The ``op1``, ``op2``, ``op3`` and ``op4`` directives are used to describe the +name and type of the up to 4 child operands of a node. The syntax of the +```` field is `` : ``, where ```` +will be used as the base name of the generated operand accessors, and +```` is one of: + +1. An ``AstNode`` sub-class, defining the operand to be of that type, always + no-null, and with an always null ``nextp()``. That is, the child node is + always present, and is a single ``AstNode`` (as opposed to a list). + +2. ``Optional[]``. This is just like in point 1 above, but + defines the child node to be optional, meaning it may be null. + +3. ``List[AstNode sub-class]`` describes a list operand, which means the child + node may have a non-null ``nextp()`` and in addition the child itself may be + null, representing an empty list. + + +An example of the full syntax of the directive is +``@astgen op1 := lhsp : AstNodeMath``. + +``astnode`` generates accessors for the child nodes based on these directives. +For non-list children, the names of the getter and setter both are that of the +given ````. For list type children, the getter is ````, +and instead of the setter, there an ``add`` method is generated +that appends new nodes (or lists of nodes) to the child list. + +``alias op`` operand alias directives +"""""""""""""""""""""""""""""""""""""""" + +If a super-class already defined a name and type for a child node using the +``op`` directive, but a more appropriate name exists in the context of a +sub-class, then the alias directive can be used to introduce an additional name +for the child node. The is ``alias op := `` where +```` is the new name. ``op`` must have been defined in some +super-class of the current node. + +Example: ``@astgen alias op1 := condp`` + + +Additional features of ``astgen`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In addition to generating ``AstNode`` members as described above, +``astgen`` is also use to handle some of the repetitive implementation code +that is still variable enough not to be handled in C++ macros. + +In particular, ``astgen`` is used to pre-process some of the C++ source +files. For example in ``V3Const.cpp``, it is used to implement the +``visit()`` functions for each binary operation using the ``TREEOP`` macro. + +The original C++ source code is transformed into C++ code in the ``obj_opt`` and ``obj_dbg`` sub-directories (the former for the optimized version of Verilator, the latter for the debug version). So for example ``V3Const.cpp`` into ``V3Const__gen.cpp``. -Visitor Functions ----------------- +Visitor Functions +----------------- Verilator uses the "Visitor" design pattern to implement its refinement and optimization passes. This allows separation of the pass algorithm from the diff --git a/src/V3Active.cpp b/src/V3Active.cpp index f1b325eac..b85de968e 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -216,7 +216,7 @@ private: // METHODS void addActive(AstActive* nodep) { UASSERT_OBJ(m_scopep, nodep, "nullptr scope"); - m_scopep->addActivep(nodep); + m_scopep->addBlocksp(nodep); } // VISITORS void visit(AstScope* nodep) override { @@ -302,7 +302,7 @@ private: LatchDetectGraphVertex* const parentp = m_graph.currentp(); LatchDetectGraphVertex* const branchp = m_graph.addPathVertex(parentp, "BRANCH", true); m_graph.addPathVertex(branchp, "IF"); - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); m_graph.addPathVertex(branchp, "ELSE"); iterateAndNextNull(nodep->elsesp()); m_graph.currentp(parentp); @@ -458,7 +458,7 @@ private: void visit(AstFinal* nodep) override { // Relink to CFUNC for the final UINFO(4, " FINAL " << nodep << endl); - if (!nodep->bodysp()) { // Empty, Kill it. + if (!nodep->stmtsp()) { // Empty, Kill it. VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return; } @@ -471,10 +471,10 @@ private: m_scopeFinalp->isStatic(false); m_scopeFinalp->isLoose(true); m_scopeFinalp->slow(true); - m_namer.scopep()->addActivep(m_scopeFinalp); + m_namer.scopep()->addBlocksp(m_scopeFinalp); } nodep->unlinkFrBack(); - m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext()); + m_scopeFinalp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext()); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -542,7 +542,7 @@ private: UINFO(4, " ALW " << nodep << endl); // if (debug() >= 9) nodep->dumpTree(cout, " Alw: "); - if (!nodep->bodysp()) { + if (!nodep->stmtsp()) { // Empty always. Kill it. VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return; @@ -551,7 +551,7 @@ private: } void visit(AstAlwaysPostponed* nodep) override { UINFO(4, " ALW " << nodep << endl); - if (!nodep->bodysp()) { + if (!nodep->stmtsp()) { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return; } diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 59158a07b..2577963f9 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -70,7 +70,7 @@ private: if (!m_monitorNumVarp) { m_monitorNumVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorNum", nodep->findUInt64DType()}; - v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp); + v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorNumVarp); } const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access); varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); @@ -80,7 +80,7 @@ private: if (!m_monitorOffVarp) { m_monitorOffVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorOff", nodep->findBitDType()}; - v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp); + v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorOffVarp); } const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access); varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp()); @@ -147,7 +147,7 @@ private: selfDestruct = true; } else { // V3Coverage assigned us a bucket to increment. - AstCoverInc* const covincp = VN_AS(snodep->coverincp(), CoverInc); + AstCoverInc* const covincp = VN_AS(snodep->coverincsp(), CoverInc); UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion"); covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace if (message != "") covincp->declp()->comment(message); @@ -209,7 +209,7 @@ private: iterateAndNextNull(ifp->condp()); // Recurse into the true case. - iterateAndNextNull(ifp->ifsp()); + iterateAndNextNull(ifp->thensp()); // If the last else is not an else if, recurse into that too. if (ifp->elsesp() && !nextifp) { // @@ -338,15 +338,15 @@ private: sentreep->unlinkFrBack(); AstAlways* const alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr); - m_modp->addStmtp(alwaysp); + m_modp->addStmtsp(alwaysp); for (uint32_t i = 0; i < ticks; ++i) { AstVar* const outvarp = new AstVar( nodep->fileline(), VVarType::MODULETEMP, "_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep()); - m_modp->addStmtp(outvarp); + m_modp->addStmtsp(outvarp); AstNode* const assp = new AstAssignDly( nodep->fileline(), new AstVarRef(nodep->fileline(), outvarp, VAccess::WRITE), inp); - alwaysp->addStmtp(assp); + alwaysp->addStmtsp(assp); // if (debug() >= 9) assp->dumpTree(cout, "-ass: "); invarp = outvarp; inp = new AstVarRef(nodep->fileline(), invarp, VAccess::READ); @@ -387,7 +387,7 @@ private: stmtsp}; ifp->branchPred(VBranchPred::BP_UNLIKELY); AstNode* const newp = new AstAlwaysPostponed{fl, ifp}; - m_modp->addStmtp(newp); + m_modp->addStmtsp(newp); } else if (nodep->displayType() == VDisplayType::DT_STROBE) { nodep->displayType(VDisplayType::DT_DISPLAY); // Need one-shot @@ -395,7 +395,7 @@ private: const auto varp = new AstVar{fl, VVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++), nodep->findBitDType()}; - m_modp->addStmtp(varp); + m_modp->addStmtsp(varp); // Where $strobe was we do "__Vstrobe = '1;" const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, new AstConst{fl, AstConst::BitTrue{}}}; @@ -407,7 +407,7 @@ private: AstNode* const newp = new AstAlwaysPostponed{fl, ifp}; stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, new AstConst{fl, AstConst::BitFalse{}}}); - m_modp->addStmtp(newp); + m_modp->addStmtsp(newp); } } void visit(AstMonitorOff* nodep) override { diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index e993bd432..cdbcec1a4 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -84,7 +84,7 @@ private: void visit(AstAlways* nodep) override { iterateAndNextNull(nodep->sensesp()); if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp(); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); m_seniAlwaysp = nullptr; } diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 2deceda22..107579b69 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -61,7 +61,6 @@ bool AstNode::sameGateTree(const AstNode* node2p) const { return sameTreeIter(this, node2p, true, true); } -void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); } int AstNodeArrayDType::left() const { return rangep()->leftConst(); } int AstNodeArrayDType::right() const { return rangep()->rightConst(); } int AstNodeArrayDType::hi() const { return rangep()->hiConst(); } @@ -71,13 +70,13 @@ VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right( AstRange::AstRange(FileLine* fl, int left, int right) : ASTGEN_SUPER_Range(fl) { - setOp2p(new AstConst{fl, static_cast(left)}); - setOp3p(new AstConst{fl, static_cast(right)}); + leftp(new AstConst{fl, static_cast(left)}); + rightp(new AstConst{fl, static_cast(right)}); } AstRange::AstRange(FileLine* fl, const VNumRange& range) : ASTGEN_SUPER_Range(fl) { - setOp2p(new AstConst{fl, static_cast(range.left())}); - setOp3p(new AstConst{fl, static_cast(range.right())}); + leftp(new AstConst{fl, static_cast(range.left())}); + rightp(new AstConst{fl, static_cast(range.right())}); } int AstRange::leftConst() const { AstConst* const constp = VN_CAST(leftp(), Const); @@ -97,7 +96,7 @@ AstPin::AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) : ASTGEN_SUPER_Pin(fl) , m_pinNum{pinNum} , m_name{varname->name()} { - setNOp1p(exprp); + this->exprp(exprp); } AstDpiExportUpdated::AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep) @@ -112,7 +111,7 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType : ASTGEN_SUPER_PackArrayDType(fl) { childDTypep(dtp); // Only for parser refDTypep(nullptr); - setOp2p(rangep); + this->rangep(rangep); dtypep(nullptr); // V3Width will resolve const int width = subDTypep()->width() * rangep->elementsConst(); widthForce(width, width); @@ -120,7 +119,7 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep) : ASTGEN_SUPER_PackArrayDType(fl) { refDTypep(dtp); - setOp2p(rangep); + this->rangep(rangep); dtypep(this); const int width = subDTypep()->width() * rangep->elementsConst(); widthForce(width, width); @@ -141,20 +140,20 @@ bool AstActive::hasClocked() const { return m_sensesp->hasClocked(); } AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp) : ASTGEN_SUPER_ElabDisplay(fl) { - setOp1p(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp}); + addFmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp}); m_displayType = dispType; } AstCStmt::AstCStmt(FileLine* fl, const string& textStmt) : ASTGEN_SUPER_CStmt(fl) { - addNOp1p(new AstText{fl, textStmt, true}); + addExprsp(new AstText{fl, textStmt, true}); } AstCMath::AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut) : ASTGEN_SUPER_CMath(fl) , m_cleanOut{cleanOut} , m_pure{true} { - addNOp1p(new AstText{fl, textStmt, true}); + addExprsp(new AstText{fl, textStmt, true}); if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 02d45f31e..c1af84cc3 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -132,11 +132,13 @@ private: }; class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType { // Array data type, ie "some_dtype var_name [2:0]" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: RANGE (array bounds) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width + // @astgen op2 := rangep : Optional[AstRange] // array bounds private: AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) - AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable + + AstNode* rangenp() const { return reinterpret_cast(rangep()); } + protected: AstNodeArrayDType(VNType t, FileLine* fl) : AstNodeDType{t, fl} {} @@ -165,14 +167,10 @@ public: && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } - AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable - inline void rangep(AstRange* nodep); // METHODS AstBasicDType* basicp() const override { return subDTypep()->basicp(); @@ -193,6 +191,7 @@ public: }; class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType { // A struct or union; common handling + // @astgen op1 := membersp : List[AstMemberDType] private: // TYPES using MemberNameMap = std::map; @@ -233,16 +232,11 @@ public: int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... int widthTotalBytes() const override; - // op1 = members bool similarDType(AstNodeDType* samep) const override { return this == samep; // We don't compare members, require exact equivalence } string name() const override { return m_name; } void name(const string& flag) override { m_name = flag; } - AstMemberDType* membersp() const { - return VN_AS(op1p(), MemberDType); - } // op1 = AstMember list - void addMembersp(AstNode* nodep) { addNOp1p(nodep); } bool packed() const { return m_packed; } // packed() but as don't support unpacked, presently all structs static bool packedUnsup() { return true; } @@ -263,33 +257,31 @@ public: // === AstNode === class AstEnumItem final : public AstNode { + // @astgen op1 := rangep : Optional[AstRange] // Range for name appending + // @astgen op2 := valuep : Optional[AstNode] private: string m_name; public: // Parents: ENUM - AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp) + AstEnumItem(FileLine* fl, const string& name, AstRange* rangep, AstNode* valuep) : ASTGEN_SUPER_EnumItem(fl) , m_name{name} { - addNOp1p(rangep); - addNOp2p(initp); + this->rangep(rangep); + this->valuep(valuep); } ASTGEN_MEMBERS_EnumItem; string name() const override { return m_name; } bool maybePointedTo() const override { return true; } bool hasDType() const override { return true; } void name(const string& flag) override { m_name = flag; } - AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range for name appending - void rangep(AstRange* nodep) { addOp1p((AstNode*)nodep); } - AstNode* valuep() const { return op2p(); } // op2 = Value - void valuep(AstNode* nodep) { addOp2p(nodep); } }; // === AstNodeDType === class AstAssocArrayDType final : public AstNodeDType { // Associative array data type, ie "[some_dtype]" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: DTYPE (the key, which remains here as a pointer) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width + // @astgen op2 := keyChildDTypep : AstNodeDType // the key, which remains here as a pointer private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) AstNodeDType* m_keyDTypep; // Keys of this type (after widthing) @@ -335,9 +327,6 @@ public: void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } @@ -347,9 +336,6 @@ public: // AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); } void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } - // op1 = Range of variable - AstNodeDType* keyChildDTypep() const { return VN_AS(op2p(), NodeDType); } - void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); } // METHODS AstBasicDType* basicp() const override { return nullptr; } AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } @@ -361,7 +347,7 @@ public: }; class AstBasicDType final : public AstNodeDType { // Builtin atomic/vectored data type - // Children: RANGE (converted to constant in V3Width) + // @astgen op1 := rangep : Optional[AstRange] // Range of variable private: struct Members { VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type @@ -415,8 +401,6 @@ public: BROKEN_RTN(dtypep() != this); return nullptr; } - AstRange* rangep() const { return VN_AS(op1p(), Range); } // op1 = Range of variable - void rangep(AstRange* nodep) { setNOp1p((AstNode*)nodep); } void setSignedState(const VSigning& signst) { // Note NOSIGN does NOT change the state; this is required by the parser if (signst == VSigning::UNSIGNED) { @@ -470,21 +454,18 @@ public: class AstBracketArrayDType final : public AstNodeDType { // Associative/Queue/Normal array data type, ie "[dtype_or_expr]" // only for early parsing then becomes another data type - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: DTYPE (the key) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width + // @astgen op2 := elementsp : AstNode // ??? key dtype ??? public: - AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* elementsp) + AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* childDTypep, + AstNode* elementsp) : ASTGEN_SUPER_BracketArrayDType(fl) { - setOp1p(dtp); // Only for parser - setOp2p(elementsp); // Only for parser + this->childDTypep(childDTypep); + this->elementsp(elementsp); } ASTGEN_MEMBERS_BracketArrayDType; bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } AstNodeDType* subDTypep() const override { return childDTypep(); } - // op2 = Range of variable - AstNode* elementsp() const { return op2p(); } // METHODS // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node @@ -499,16 +480,16 @@ public: }; class AstClassRefDType final : public AstNodeDType { // Reference to a class - // Children: PINs (for parameter settings) + // @astgen op1 := paramsp: List[AstPin] private: AstClass* m_classp; // data type pointed to, BELOW the AstTypedef AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy public: - AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp) + AstClassRefDType(FileLine* fl, AstClass* classp, AstPin* paramsp) : ASTGEN_SUPER_ClassRefDType(fl) , m_classp{classp} { - dtypep(this); - addNOp4p(paramsp); + this->dtypep(this); + this->addParamsp(paramsp); } ASTGEN_MEMBERS_ClassRefDType; // METHODS @@ -537,13 +518,13 @@ public: void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } AstClass* classp() const { return m_classp; } void classp(AstClass* nodep) { m_classp = nodep; } - AstPin* paramsp() const { return VN_AS(op4p(), Pin); } bool isCompound() const override { return true; } }; class AstConstDType final : public AstNodeDType { // const data type, ie "const some_dtype var_name [2:0]" // ConstDType are removed in V3LinkLValue and become AstVar::isConst. // When more generic types are supported AstConstDType will be propagated further. + // @astgen op1 := childDTypep : Optional[AstNodeDType] private: AstNodeDType* m_refDTypep = nullptr; // Inherit from this base data type public: @@ -571,9 +552,6 @@ public: return skipRefp()->similarDType(samep->skipRefp()); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } @@ -594,6 +572,7 @@ class AstDefImplicitDType final : public AstNodeDType { // For parsing enum/struct/unions that are declared with a variable rather than typedef // This allows "var enum {...} a,b" to share the enum definition for both variables // After link, these become typedefs + // @astgen op1 := childDTypep : Optional[AstNodeDType] private: string m_name; void* m_containerp; // In what scope is the name unique, so we can know what are duplicate @@ -620,9 +599,6 @@ public: return type() == samep->type() && same(samep); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); } void* containerp() const { return m_containerp; } // METHODS @@ -640,7 +616,7 @@ public: }; class AstDynArrayDType final : public AstNodeDType { // Dynamic array data type, ie "[]" - // Children: DTYPE (moved to refDTypep() in V3Width) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width private: AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) public: @@ -677,9 +653,6 @@ public: string prettyDTypeName() const override; void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } @@ -722,19 +695,20 @@ public: }; class AstEnumDType final : public AstNodeDType { // Parents: TYPEDEF/MODULE - // Children: ENUMVALUEs + // @astgen op1 := childDTypep : Optional[AstNodeDType] + // @astgen op2 := itemsp : List[AstEnumItem] private: string m_name; // Name from upper typedef, if any AstNodeDType* m_refDTypep = nullptr; // Elements are of this type after V3Width const int m_uniqueNum = 0; public: - AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp) + AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstEnumItem* itemsp) : ASTGEN_SUPER_EnumDType(fl) , m_uniqueNum{uniqueNumInc()} { childDTypep(dtp); // Only for parser refDTypep(nullptr); - addNOp2p(itemsp); + addItemsp(itemsp); dtypep(nullptr); // V3Width will resolve widthFromSub(subDTypep()); } @@ -754,16 +728,12 @@ public: } bool similarDType(AstNodeDType* samep) const override { return this == samep; } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } // op1 = Data type - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - // op1 = Range of variable AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } string name() const override { return m_name; } void name(const string& flag) override { m_name = flag; } - AstEnumItem* itemsp() const { return VN_AS(op2p(), EnumItem); } // op2 = AstEnumItem's // METHODS AstBasicDType* basicp() const override { return subDTypep()->basicp(); } AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } @@ -835,6 +805,7 @@ public: class AstMemberDType final : public AstNodeDType { // A member of a struct/union // PARENT: AstNodeUOrStructDType + // @astgen op1 := childDTypep : Optional[AstNodeDType] private: AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) string m_name; // Name of variable @@ -869,9 +840,6 @@ public: if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep(); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } @@ -904,6 +872,7 @@ public: class AstParamTypeDType final : public AstNodeDType { // Parents: MODULE // A parameter type statement; much like a var or typedef + // @astgen op1 := childDTypep : Optional[AstNodeDType] private: const VVarType m_varType; // Type of variable (for localparam vs. param) string m_name; // Name of variable @@ -918,9 +887,6 @@ public: } ASTGEN_MEMBERS_ParamTypeDType; AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Type assigning to - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return dtypep() ? dtypep() : childDTypep(); } AstBasicDType* basicp() const override { return subDTypep()->basicp(); } AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } @@ -972,20 +938,21 @@ public: }; class AstQueueDType final : public AstNodeDType { // Queue array data type, ie "[ $ ]" - // Children: DTYPE (moved to refDTypep() in V3Width) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width + // @astgen op2 := boundp : Optional[AstNode] private: AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) public: AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp) : ASTGEN_SUPER_QueueDType(fl) { - setNOp2p(boundp); - childDTypep(dtp); // Only for parser + this->childDTypep(dtp); + this->boundp(boundp); refDTypep(nullptr); dtypep(nullptr); // V3Width will resolve } AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNode* boundp) : ASTGEN_SUPER_QueueDType(fl) { - setNOp2p(boundp); + this->boundp(boundp); refDTypep(dtp); dtypep(dtp); } @@ -1011,13 +978,8 @@ public: void dumpSmall(std::ostream& str) const override; string prettyDTypeName() const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - AstNode* boundp() const { return op2p(); } // op2 = Bound, nullptr = none - void boundp(AstNode* nodep) { setNOp2p(nodep); } inline int boundConst() const; AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } @@ -1034,6 +996,9 @@ public: bool isCompound() const override { return true; } }; class AstRefDType final : public AstNodeDType { + // @astgen op1 := typeofp : AstNode + // @astgen op2 := classOrPackageOpp : Optional[AstNode] + // @astgen op3 := paramsp : List[AstPin] private: // Pre-Width must reference the Typeref, not what it points to, as some child // types like AstBracketArrayType will disappear and can't lose the handle @@ -1046,16 +1011,16 @@ public: AstRefDType(FileLine* fl, const string& name) : ASTGEN_SUPER_RefDType(fl) , m_name{name} {} - AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp) + AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstPin* paramsp) : ASTGEN_SUPER_RefDType(fl) , m_name{name} { - setNOp3p(classOrPackagep); - addNOp4p(paramsp); + this->classOrPackageOpp(classOrPackagep); + addParamsp(paramsp); } class FlagTypeOfExpr {}; // type(expr) for parser only AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp) : ASTGEN_SUPER_RefDType(fl) { - setOp2p(typeofp); + this->typeofp(typeofp); } ASTGEN_MEMBERS_RefDType; // METHODS @@ -1106,7 +1071,6 @@ public: int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } void name(const string& flag) override { m_name = flag; } - // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } AstTypedef* typedefp() const { return m_typedefp; } void typedefp(AstTypedef* nodep) { m_typedefp = nodep; } @@ -1116,9 +1080,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } - AstNode* typeofp() const { return op2p(); } - AstNode* classOrPackageOpp() const { return op3p(); } - AstPin* paramsp() const { return VN_AS(op4p(), Pin); } bool isCompound() const override { v3fatalSrc("call isCompound on subdata type, not reference"); return false; @@ -1126,7 +1087,7 @@ public: }; class AstUnsizedArrayDType final : public AstNodeDType { // Unsized/open-range Array data type, ie "some_dtype var_name []" - // Children: DTYPE (moved to refDTypep() in V3Width) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) public: @@ -1149,9 +1110,6 @@ public: bool similarDType(AstNodeDType* samep) const override; void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } @@ -1194,7 +1152,7 @@ public: }; class AstWildcardArrayDType final : public AstNodeDType { // Wildcard index type associative array data type, ie "some_dtype var_name [*]" - // Children: DTYPE (moved to refDTypep() in V3Width) + // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) public: @@ -1217,9 +1175,6 @@ public: bool similarDType(AstNodeDType* samep) const override; void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } @@ -1237,8 +1192,6 @@ public: // === AstNodeArrayDType === class AstPackArrayDType final : public AstNodeArrayDType { // Packed array data type, ie "some_dtype [2:0] var_name" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: RANGE (array bounds) public: inline AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep); inline AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep); @@ -1248,15 +1201,13 @@ public: }; class AstUnpackArrayDType final : public AstNodeArrayDType { // Array data type, ie "some_dtype var_name [2:0]" - // Children: DTYPE (moved to refDTypep() in V3Width) - // Children: RANGE (array bounds) bool m_isCompound = false; // Non-POD subDType, or parent requires compound public: AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) : ASTGEN_SUPER_UnpackArrayDType(fl) { - childDTypep(dtp); // Only for parser + this->childDTypep(dtp); // Only for parser + this->rangep(rangep); refDTypep(nullptr); - setOp2p((AstNode*)rangep); dtypep(nullptr); // V3Width will resolve // For backward compatibility AstNodeArrayDType and others inherit // width and signing from the subDType/base type @@ -1264,8 +1215,8 @@ public: } AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep) : ASTGEN_SUPER_UnpackArrayDType(fl) { + this->rangep(rangep); refDTypep(dtp); - setOp2p((AstNode*)rangep); dtypep(this); // For backward compatibility AstNodeArrayDType and others inherit // width and signing from the subDType/base type diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index 14e9bd2ab..2d5a6f57f 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -59,23 +59,20 @@ public: bool isOpaque() const { return VN_IS(this, CvtPackString); } }; class AstNodeBiop VL_NOT_FINAL : public AstNodeMath { - // Binary math + // Binary expression + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode protected: - AstNodeBiop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs) + AstNodeBiop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeMath{t, fl} { - setOp1p(lhs); - setOp2p(rhs); + this->lhsp(lhsp); + this->rhsp(rhsp); } public: ASTGEN_MEMBERS_NodeBiop; // Clone single node, just get same type back. virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; - // ACCESSORS - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } // METHODS // Set out to evaluation of a AstConst'ed virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0; @@ -110,18 +107,14 @@ public: }; class AstNodeSel VL_NOT_FINAL : public AstNodeBiop { // Single bit range extraction, perhaps with non-constant selection or array selection + // @astgen alias op1 := fromp // Expression we are indexing into + // @astgen alias op2 := bitp // The index // TOOD: rename to idxp protected: AstNodeSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* bitp) : AstNodeBiop{t, fl, fromp, bitp} {} public: ASTGEN_MEMBERS_NodeSel; - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression - void bitp(AstNode* nodep) { setOp2p(nodep); } int bitConst() const; bool hasDType() const override { return true; } }; @@ -152,26 +145,23 @@ public: bool doubleFlavor() const override { return true; } }; class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath { - // Quaternary math + // 4-ary expression + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode + // @astgen op3 := thsp : AstNode + // @astgen op4 := fhsp : AstNode protected: - AstNodeQuadop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs) + AstNodeQuadop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp, + AstNode* fhsp) : AstNodeMath{t, fl} { - setOp1p(lhs); - setOp2p(rhs); - setOp3p(ths); - setOp4p(fhs); + this->lhsp(lhsp); + this->rhsp(rhsp); + this->thsp(thsp); + this->fhsp(fhsp); } public: ASTGEN_MEMBERS_NodeQuadop; - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - AstNode* thsp() const { return op3p(); } - AstNode* fhsp() const { return op4p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - void thsp(AstNode* nodep) { return setOp3p(nodep); } - void fhsp(AstNode* nodep) { return setOp4p(nodep); } // METHODS // Set out to evaluation of a AstConst'ed virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, @@ -203,23 +193,20 @@ public: void dump(std::ostream& str) const override; }; class AstNodeTriop VL_NOT_FINAL : public AstNodeMath { - // Trinary math + // Ternary expression + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode + // @astgen op3 := thsp : AstNode protected: - AstNodeTriop(VNType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) + AstNodeTriop(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp) : AstNodeMath{t, fl} { - setOp1p(lhs); - setOp2p(rhs); - setOp3p(ths); + this->lhsp(lhsp); + this->rhsp(rhsp); + this->thsp(thsp); } public: ASTGEN_MEMBERS_NodeTriop; - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - AstNode* thsp() const { return op3p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - void thsp(AstNode* nodep) { return setOp3p(nodep); } // METHODS void dump(std::ostream& str) const override; // Set out to evaluation of a AstConst'ed @@ -236,13 +223,16 @@ public: bool same(const AstNode*) const override { return true; } }; class AstNodeCond VL_NOT_FINAL : public AstNodeTriop { + // @astgen alias op1 := condp + // @astgen alias op2 := thenp + // @astgen alias op3 := elsep protected: - AstNodeCond(VNType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : AstNodeTriop{t, fl, condp, expr1p, expr2p} { - if (expr1p) { - dtypeFrom(expr1p); - } else if (expr2p) { - dtypeFrom(expr2p); + AstNodeCond(VNType t, FileLine* fl, AstNode* condp, AstNode* thenp, AstNode* elsep) + : AstNodeTriop{t, fl, condp, thenp, elsep} { + if (thenp) { + dtypeFrom(thenp); + } else if (elsep) { + dtypeFrom(elsep); } } @@ -250,9 +240,6 @@ public: ASTGEN_MEMBERS_NodeCond; void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) override; - AstNode* condp() const { return op1p(); } // op1 = Condition - AstNode* expr1p() const { return op2p(); } // op2 = If true... - AstNode* expr2p() const { return op3p(); } // op3 = If false... string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; } string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; } bool cleanOut() const override { return false; } // clean if e1 & e2 clean @@ -263,21 +250,20 @@ public: bool sizeMattersRhs() const override { return false; } bool sizeMattersThs() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0; + virtual AstNode* cloneType(AstNode* condp, AstNode* thenp, AstNode* elsep) = 0; }; class AstNodeUniop VL_NOT_FINAL : public AstNodeMath { - // Unary math + // Unary expression + // @astgen op1 := lhsp : AstNode protected: AstNodeUniop(VNType t, FileLine* fl, AstNode* lhsp) : AstNodeMath{t, fl} { dtypeFrom(lhsp); - setOp1p(lhsp); + this->lhsp(lhsp); } public: ASTGEN_MEMBERS_NodeUniop; - AstNode* lhsp() const { return op1p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } // METHODS void dump(std::ostream& str) const override; // Set out to evaluation of a AstConst'ed lhs @@ -383,6 +369,7 @@ public: AstCFunc* funcp() const { return m_funcp; } }; class AstCMath final : public AstNodeMath { + // @astgen op1 := exprsp : List[AstNode] // Expressions to print private: const bool m_cleanOut; bool m_pure; // Pure optimizable @@ -392,7 +379,7 @@ public: : ASTGEN_SUPER_CMath(fl) , m_cleanOut{true} , m_pure{false} { - addOp1p(exprsp); + addExprsp(exprsp); dtypeFrom(exprsp); } inline AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true); @@ -403,19 +390,16 @@ public: string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool same(const AstNode* /*samep*/) const override { return true; } - void addBodysp(AstNode* nodep) { addNOp1p(nodep); } - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print bool pure() const { return m_pure; } void pure(bool flag) { m_pure = flag; } }; class AstConsAssoc final : public AstNodeMath { // Construct an assoc array and return object, '{} - // Parents: math - // Children: expression (elements or other queues) + // @astgen op1 := defaultp : Optional[AstNode] public: AstConsAssoc(FileLine* fl, AstNode* defaultp) : ASTGEN_SUPER_ConsAssoc(fl) { - setNOp1p(defaultp); + this->defaultp(defaultp); } ASTGEN_MEMBERS_ConsAssoc; string emitVerilog() override { return "'{}"; } @@ -423,18 +407,17 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* defaultp() const { return op1p(); } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConsDynArray final : public AstNodeMath { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} - // Parents: math - // Children: expression (elements or other queues) + // @astgen op1 := lhsp : Optional[AstNode] + // @astgen op2 := rhsp : Optional[AstNode] public: explicit AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) : ASTGEN_SUPER_ConsDynArray(fl) { - setNOp1p(lhsp); - setNOp2p(rhsp); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_ConsDynArray; string emitVerilog() override { return "'{%l, %r}"; } @@ -442,19 +425,17 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } // op1 = expression - AstNode* rhsp() const { return op2p(); } // op2 = expression bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConsQueue final : public AstNodeMath { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} - // Parents: math - // Children: expression (elements or other queues) + // @astgen op1 := lhsp : Optional[AstNode] + // @astgen op2 := rhsp : Optional[AstNode] public: explicit AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr) : ASTGEN_SUPER_ConsQueue(fl) { - setNOp1p(lhsp); - setNOp2p(rhsp); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_ConsQueue; string emitVerilog() override { return "'{%l, %r}"; } @@ -462,18 +443,15 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } // op1 = expression - AstNode* rhsp() const { return op2p(); } // op2 = expression bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConsWildcard final : public AstNodeMath { // Construct a wildcard assoc array and return object, '{} - // Parents: math - // Children: expression (elements or other queues) + // @astgen op1 := defaultp : Optional[AstNode] public: AstConsWildcard(FileLine* fl, AstNode* defaultp) : ASTGEN_SUPER_ConsWildcard(fl) { - setNOp1p(defaultp); + this->defaultp(defaultp); } ASTGEN_MEMBERS_ConsWildcard; string emitVerilog() override { return "'{}"; } @@ -481,7 +459,6 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* defaultp() const { return op1p(); } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstConst final : public AstNodeMath { @@ -662,18 +639,16 @@ class AstExprStmt final : public AstNodeMath { // Perform a statement, often assignment inside an expression/math node, // the parent gets passed the 'resultp()'. // resultp is evaluated AFTER the statement(s). + // @astgen op1 := stmtsp : List[AstNode] + // @astgen op2 := resultp : AstNode public: AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNode* resultp) : ASTGEN_SUPER_ExprStmt(fl) { - addOp1p(stmtsp); - setOp2p(resultp); // Possibly in future nullptr could mean return rhsp() + addStmtsp(stmtsp); + this->resultp(resultp); dtypeFrom(resultp); } ASTGEN_MEMBERS_ExprStmt; - // ACCESSORS - AstNode* stmtsp() const { return op1p(); } - void addStmtsp(AstNode* nodep) { addOp1p(nodep); } - AstNode* resultp() const { return op2p(); } // METHODS string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -681,11 +656,13 @@ public: bool same(const AstNode*) const override { return true; } }; class AstFError final : public AstNodeMath { + // @astgen op1 := filep : AstNode + // @astgen op2 := strp : AstNode public: AstFError(FileLine* fl, AstNode* filep, AstNode* strp) : ASTGEN_SUPER_FError(fl) { - setOp1p(filep); - setOp2p(strp); + this->filep(filep); + this->strp(strp); } ASTGEN_MEMBERS_FError; string emitVerilog() override { return "%f$ferror(%l, %r)"; } @@ -695,25 +672,20 @@ public: virtual bool sizeMattersLhs() const { return false; } int instrCount() const override { return widthInstrs() * 64; } bool isPure() const override { return false; } // SPECIAL: $display has 'visual' ordering - void filep(AstNode* nodep) { setOp1p(nodep); } - AstNode* filep() const { return op1p(); } - void strp(AstNode* nodep) { setOp2p(nodep); } - AstNode* strp() const { return op2p(); } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstFRead final : public AstNodeMath { - // Parents: expr - // Children: varrefs to load - // Children: file which must be a varref - // Children: low index - // Children: count + // @astgen op1 := memp : AstNode // VarRef for result + // @astgen op2 := filep : AstNode // file (must be a VarRef) + // @astgen op3 := startp : Optional[AstNode] // Offset + // @astgen op4 := countp : Optional[AstNode] // Size public: AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, AstNode* startp, AstNode* countp) : ASTGEN_SUPER_FRead(fl) { - setOp1p(memp); - setOp2p(filep); - setNOp3p(startp); - setNOp4p(countp); + this->memp(memp); + this->filep(filep); + this->startp(startp); + this->countp(countp); } ASTGEN_MEMBERS_FRead; string verilogKwd() const override { return "$fread"; } @@ -725,22 +697,14 @@ public: bool isOutputter() const override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* memp() const { return op1p(); } - void memp(AstNode* nodep) { setOp1p(nodep); } - AstNode* filep() const { return op2p(); } - void filep(AstNode* nodep) { setOp2p(nodep); } - AstNode* startp() const { return op3p(); } - void startp(AstNode* nodep) { setNOp3p(nodep); } - AstNode* countp() const { return op4p(); } - void countp(AstNode* nodep) { setNOp4p(nodep); } }; class AstFRewind final : public AstNodeMath { // Parents: stmtlist - // Children: file which must be a varref + // @astgen op1 := filep : Optional[AstNode] public: AstFRewind(FileLine* fl, AstNode* filep) : ASTGEN_SUPER_FRewind(fl) { - setNOp2p(filep); + this->filep(filep); } ASTGEN_MEMBERS_FRewind; string verilogKwd() const override { return "$frewind"; } @@ -753,13 +717,10 @@ public: bool isUnlikely() const override { return true; } bool cleanOut() const override { return false; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; class AstFScanF final : public AstNodeMath { - // Parents: expr - // Children: file which must be a varref - // Children: varrefs to load + // @astgen op1 := exprsp : List[AstNode] // VarRefs for results + // @astgen op2 := filep : Optional[AstNode] // file (must be a VarRef) private: string m_text; @@ -767,8 +728,8 @@ public: AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp) : ASTGEN_SUPER_FScanF(fl) , m_text{text} { - addNOp1p(exprsp); - setNOp2p(filep); + addExprsp(exprsp); + this->filep(filep); } ASTGEN_MEMBERS_FScanF; string name() const override { return m_text; } @@ -783,24 +744,19 @@ public: bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display void text(const string& text) { m_text = text; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; class AstFSeek final : public AstNodeMath { - // Parents: expr - // Children: file which must be a varref - // Children: offset - // Children: operation + // @astgen op1 := filep : AstNode // file (must be a VarRef) + // @astgen op2 := offset : Optional[AstNode] + // @astgen op3 := operation : Optional[AstNode] public: AstFSeek(FileLine* fl, AstNode* filep, AstNode* offset, AstNode* operation) : ASTGEN_SUPER_FSeek(fl) { - setOp2p(filep); - setNOp3p(offset); - setNOp4p(operation); + this->filep(filep); + this->offset(offset); + this->operation(operation); } ASTGEN_MEMBERS_FSeek; string verilogKwd() const override { return "$fseek"; } @@ -812,20 +768,14 @@ public: bool isOutputter() const override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNode* nodep) { setOp2p(nodep); } - AstNode* offset() const { return op3p(); } - void offset(AstNode* nodep) { setNOp3p(nodep); } - AstNode* operation() const { return op4p(); } - void operation(AstNode* nodep) { setNOp4p(nodep); } }; class AstFTell final : public AstNodeMath { // Parents: stmtlist - // Children: file which must be a varref + // @astgen op1 := filep : AstNode // file (must be a VarRef) public: AstFTell(FileLine* fl, AstNode* filep) : ASTGEN_SUPER_FTell(fl) { - setNOp2p(filep); + this->filep(filep); } ASTGEN_MEMBERS_FTell; string verilogKwd() const override { return "$ftell"; } @@ -838,17 +788,15 @@ public: bool isUnlikely() const override { return true; } bool cleanOut() const override { return false; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; class AstFell final : public AstNodeMath { // Verilog $fell - // Parents: math - // Children: expression + // @astgen op1 := exprp : AstNode + // @astgen op2 := sentreep : Optional[AstSenTree] public: AstFell(FileLine* fl, AstNode* exprp) : ASTGEN_SUPER_Fell(fl) { - addOp1p(exprp); + this->exprp(exprp); } ASTGEN_MEMBERS_Fell; string emitVerilog() override { return "$fell(%l)"; } @@ -856,35 +804,33 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain bool same(const AstNode* /*samep*/) const override { return true; } }; class AstGatePin final : public AstNodeMath { // Possibly expand a gate primitive input pin value to match the range of the gate primitive + // @astgen op1 := exprp : AstNode // Pin expression + // @astgen op2 := rangep : AstRange // Range of pin public: - AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep) + AstGatePin(FileLine* fl, AstNode* exprp, AstRange* rangep) : ASTGEN_SUPER_GatePin(fl) { - setOp1p(lhsp); - setOp2p((AstNode*)rangep); + this->exprp(exprp); + this->rangep(rangep); } ASTGEN_MEMBERS_GatePin; string emitVerilog() override { return "%l"; } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } - AstNode* exprp() const { return op1p(); } // op1 = Pin expression - AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Range of pin }; class AstImplication final : public AstNodeMath { // Verilog |-> |=> - // Parents: math - // Children: expression + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode + // @astgen op3 := sentreep : AstSenTree public: - AstImplication(FileLine* fl, AstNode* lhs, AstNode* rhs) + AstImplication(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_Implication(fl) { - setOp1p(lhs); - setOp2p(rhs); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_Implication; string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -892,40 +838,33 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - void lhsp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain - void sentreep(AstSenTree* sentreep) { addOp4p((AstNode*)sentreep); } // op4 = clock domain bool same(const AstNode* /*samep*/) const override { return true; } }; class AstInside final : public AstNodeMath { + // @astgen op1 := exprp : AstNode + // @astgen op2 := itemsp : List[AstNode] public: AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp) : ASTGEN_SUPER_Inside(fl) { - addOp1p(exprp); - addOp2p(itemsp); + this->exprp(exprp); + this->addItemsp(itemsp); dtypeSetBit(); } ASTGEN_MEMBERS_Inside; - AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with - // op2 = RHS, possibly a list of expr or AstInsideRange - AstNode* itemsp() const { return op2p(); } string emitVerilog() override { return "%l inside { %r }"; } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return false; } // NA }; class AstInsideRange final : public AstNodeMath { + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode public: AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_InsideRange(fl) { - addOp1p(lhsp); - addOp2p(rhsp); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_InsideRange; - AstNode* lhsp() const { return op1p(); } // op1 = LHS - AstNode* rhsp() const { return op2p(); } // op2 = RHS string emitVerilog() override { return "[%l:%r]"; } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return false; } // NA @@ -958,7 +897,7 @@ public: }; class AstMemberSel final : public AstNodeMath { // Parents: math|stmt - // Children: varref|arraysel, math + // @astgen op1 := fromp : AstNode private: // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it string m_name; @@ -967,13 +906,13 @@ public: AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name) : ASTGEN_SUPER_MemberSel(fl) , m_name{name} { - setOp1p(fromp); + this->fromp(fromp); dtypep(nullptr); // V3Width will resolve } AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp) : ASTGEN_SUPER_MemberSel(fl) , m_name{dtp->name()} { - setOp1p(fromp); + this->fromp(fromp); dtypep(dtp); } ASTGEN_MEMBERS_MemberSel; @@ -986,22 +925,18 @@ public: bool cleanOut() const override { return false; } bool same(const AstNode* samep) const override { return true; } // dtype comparison does it int instrCount() const override { return widthInstrs(); } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } AstVar* varp() const { return m_varp; } void varp(AstVar* nodep) { m_varp = nodep; } }; class AstNewCopy final : public AstNodeMath { // New as shallow copy // Parents: math|stmt - // Children: varref|arraysel, math + // @astgen op1 := rhsp : AstNode public: AstNewCopy(FileLine* fl, AstNode* rhsp) : ASTGEN_SUPER_NewCopy(fl) { dtypeFrom(rhsp); // otherwise V3Width will resolve - setNOp1p(rhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_NewCopy; string emitVerilog() override { return "new"; } @@ -1009,18 +944,18 @@ public: bool cleanOut() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* rhsp() const { return op1p(); } }; class AstNewDynamic final : public AstNodeMath { // New for dynamic array // Parents: math|stmt - // Children: varref|arraysel, math + // @astgen op1 := sizep : AstNode + // @astgen op2 := rhsp : Optional[AstNode] public: AstNewDynamic(FileLine* fl, AstNode* sizep, AstNode* rhsp) : ASTGEN_SUPER_NewDynamic(fl) { dtypeFrom(rhsp); // otherwise V3Width will resolve - setNOp1p(sizep); - setNOp2p(rhsp); + this->sizep(sizep); + this->rhsp(rhsp); } ASTGEN_MEMBERS_NewDynamic; string emitVerilog() override { return "new"; } @@ -1028,18 +963,17 @@ public: bool cleanOut() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* sizep() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } }; class AstPast final : public AstNodeMath { // Verilog $past - // Parents: math - // Children: expression + // @astgen op1 := exprp : AstNode + // @astgen op2 := ticksp : Optional[AstNode] + // @astgen op3 := sentreep : Optional[AstSenTree] public: AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp) : ASTGEN_SUPER_Past(fl) { - addOp1p(exprp); - addNOp2p(ticksp); + this->exprp(exprp); + this->ticksp(ticksp); } ASTGEN_MEMBERS_Past; string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -1047,23 +981,25 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstNode* ticksp() const { return op2p(); } // op2 = ticks or nullptr means 1 - AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); } // op4 = clock domain - void sentreep(AstSenTree* sentreep) { addOp4p((AstNode*)sentreep); } // op4 = clock domain bool same(const AstNode* /*samep*/) const override { return true; } }; class AstPatMember final : public AstNodeMath { // Verilog '{a} or '{a{b}} // Parents: AstPattern // Children: expression, AstPattern, replication count + // Expression to assign or another AstPattern (list if replicated) + // @astgen op1 := lhssp : List[AstNode] + // @astgen op2 := keyp : Optional[AstNode] + // @astgen op3 := repp : Optional[AstNode] // replication count, or nullptr for count 1 private: bool m_default = false; public: - AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) + AstPatMember(FileLine* fl, AstNode* lhssp, AstNode* keyp, AstNode* repp) : ASTGEN_SUPER_PatMember(fl) { - addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); + this->addLhssp(lhssp); + this->keyp(keyp); + this->repp(repp); } ASTGEN_MEMBERS_PatMember; string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } @@ -1072,10 +1008,6 @@ public: bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs() * 2; } void dump(std::ostream& str = std::cout) const override; - // op1 = expression to assign or another AstPattern (list if replicated) - AstNode* lhssp() const { return op1p(); } - AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) - AstNode* repp() const { return op3p(); } // op3 = replication count, or nullptr for count 1 bool isDefault() const { return m_default; } void isDefault(bool flag) { m_default = flag; } }; @@ -1083,10 +1015,12 @@ class AstPattern final : public AstNodeMath { // Verilog '{a,b,c,d...} // Parents: AstNodeAssign, AstPattern, ... // Children: expression, AstPattern, AstPatReplicate + // @astgen op1 := childDTypep : Optional[AstNodeDType] + // @astgen op2 := itemsp : List[AstNode] // AstPatReplicate, AstPatMember, etc public: AstPattern(FileLine* fl, AstNode* itemsp) : ASTGEN_SUPER_Pattern(fl) { - addNOp2p(itemsp); + addItemsp(itemsp); } ASTGEN_MEMBERS_Pattern; string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -1096,15 +1030,11 @@ public: int instrCount() const override { return widthInstrs(); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - // op1 = Type assigning to - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - AstNode* itemsp() const { return op2p(); } // op2 = AstPatReplicate, AstPatMember, etc - void addItemsp(AstNode* nodep) { addOp2p(nodep); } }; class AstRand final : public AstNodeMath { // $random/$random(seed) or $urandom/$urandom(seed) // Return a random number, based upon width() + // @astgen op1 := seedp : Optional[AstNode] private: const bool m_urandom = false; // $urandom vs $random const bool m_reset = false; // Random reset, versus always random @@ -1118,7 +1048,7 @@ public: AstRand(FileLine* fl, AstNode* seedp, bool urandom) : ASTGEN_SUPER_Rand(fl) , m_urandom{urandom} { - setNOp1p(seedp); + this->seedp(seedp); } ASTGEN_MEMBERS_Rand; string emitVerilog() override { @@ -1141,18 +1071,17 @@ public: return !seedp() && !samep->seedp() && reset() == samep->reset() && urandom() == samep->urandom(); } - AstNode* seedp() const { return op1p(); } bool reset() const { return m_reset; } bool urandom() const { return m_urandom; } }; class AstRose final : public AstNodeMath { // Verilog $rose - // Parents: math - // Children: expression + // @astgen op1 := exprp : AstNode + // @astgen op2 := sentreep : Optional[AstSenTree] public: AstRose(FileLine* fl, AstNode* exprp) : ASTGEN_SUPER_Rose(fl) { - addOp1p(exprp); + this->exprp(exprp); } ASTGEN_MEMBERS_Rose; string emitVerilog() override { return "$rose(%l)"; } @@ -1160,15 +1089,11 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain bool same(const AstNode* /*samep*/) const override { return true; } }; class AstSScanF final : public AstNodeMath { - // Parents: expr - // Children: file which must be a varref - // Children: varrefs to load + // @astgen op1 := exprsp : List[AstNode] // VarRefs for results + // @astgen op2 := fromp : AstNode private: string m_text; @@ -1176,8 +1101,8 @@ public: AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp) : ASTGEN_SUPER_SScanF(fl) , m_text{text} { - addNOp1p(exprsp); - setOp2p(fromp); + this->addExprsp(exprsp); + this->fromp(fromp); } ASTGEN_MEMBERS_SScanF; string name() const override { return m_text; } @@ -1192,21 +1117,16 @@ public: bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display void text(const string& text) { m_text = text; } - AstNode* fromp() const { return op2p(); } - void fromp(AstNode* nodep) { setOp2p(nodep); } }; class AstSampled final : public AstNodeMath { // Verilog $sampled - // Parents: math - // Children: expression + // @astgen op1 := exprp : AstNode public: AstSampled(FileLine* fl, AstNode* exprp) : ASTGEN_SUPER_Sampled(fl) { - addOp1p(exprp); + this->exprp(exprp); } ASTGEN_MEMBERS_Sampled; string emitVerilog() override { return "$sampled(%l)"; } @@ -1214,13 +1134,13 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return 0; } - AstNode* exprp() const { return op1p(); } // op1 = expression bool same(const AstNode* /*samep*/) const override { return true; } }; class AstScopeName final : public AstNodeMath { // For display %m and DPI context imports // Parents: DISPLAY - // Children: TEXT + // @astgen op1 := scopeAttrp : List[AstText] + // @astgen op2 := scopeEntrp : List[AstText] private: bool m_dpiExport = false; // Is for dpiExport const bool m_forFormat = false; // Is for a format %m @@ -1243,10 +1163,6 @@ public: string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } void dump(std::ostream& str = std::cout) const override; - AstText* scopeAttrp() const { return VN_AS(op1p(), Text); } - void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } - AstText* scopeEntrp() const { return VN_AS(op2p(), Text); } - void scopeEntrp(AstNode* nodep) { addOp2p(nodep); } string scopeSymName() const { // Name for __Vscope variable including children return scopeNameFormatter(scopeAttrp()); } @@ -1266,13 +1182,15 @@ public: class AstSetAssoc final : public AstNodeMath { // Set an assoc array element and return object, '{} // Parents: math - // Children: expression (elements or other queues) + // @astgen op1 := lhsp : AstNode + // @astgen op2 := keyp : Optional[AstNode] + // @astgen op3 := valuep : AstNode public: AstSetAssoc(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep) : ASTGEN_SUPER_SetAssoc(fl) { - setOp1p(lhsp); - setNOp2p(keyp); - setOp3p(valuep); + this->lhsp(lhsp); + this->keyp(keyp); + this->valuep(valuep); } ASTGEN_MEMBERS_SetAssoc; string emitVerilog() override { return "'{}"; } @@ -1280,21 +1198,20 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } - AstNode* keyp() const { return op2p(); } - AstNode* valuep() const { return op3p(); } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstSetWildcard final : public AstNodeMath { // Set a wildcard assoc array element and return object, '{} // Parents: math - // Children: expression (elements or other queues) + // @astgen op1 := lhsp : AstNode + // @astgen op2 := keyp : Optional[AstNode] + // @astgen op3 := valuep : AstNode public: AstSetWildcard(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep) : ASTGEN_SUPER_SetWildcard(fl) { - setOp1p(lhsp); - setNOp2p(keyp); - setOp3p(valuep); + this->lhsp(lhsp); + this->keyp(keyp); + this->valuep(valuep); } ASTGEN_MEMBERS_SetWildcard; string emitVerilog() override { return "'{}"; } @@ -1302,19 +1219,16 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - AstNode* lhsp() const { return op1p(); } - AstNode* keyp() const { return op2p(); } - AstNode* valuep() const { return op3p(); } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstStable final : public AstNodeMath { // Verilog $stable - // Parents: math - // Children: expression + // @astgen op1 := exprp : AstNode + // @astgen op2 := sentreep : Optional[AstSenTree] public: AstStable(FileLine* fl, AstNode* exprp) : ASTGEN_SUPER_Stable(fl) { - addOp1p(exprp); + this->exprp(exprp); } ASTGEN_MEMBERS_Stable; string emitVerilog() override { return "$stable(%l)"; } @@ -1322,17 +1236,15 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - AstNode* exprp() const { return op1p(); } // op1 = expression - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain bool same(const AstNode* /*samep*/) const override { return true; } }; class AstSystemF final : public AstNodeMath { // $system used as function + // @astgen op1 := lhsp : AstNode public: AstSystemF(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SystemF(fl) { - setOp1p(lhsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_SystemF; string verilogKwd() const override { return "$system"; } @@ -1345,15 +1257,14 @@ public: bool isUnlikely() const override { return true; } bool cleanOut() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* lhsp() const { return op1p(); } }; class AstTestPlusArgs final : public AstNodeMath { - // Parents: expr - // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs + // Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs. + // @astgen op1 := searchp : Optional[AstNode] public: AstTestPlusArgs(FileLine* fl, AstNode* searchp) : ASTGEN_SUPER_TestPlusArgs(fl) { - setOp1p(searchp); + this->searchp(searchp); } ASTGEN_MEMBERS_TestPlusArgs; string verilogKwd() const override { return "$test$plusargs"; } @@ -1363,22 +1274,20 @@ public: bool isPredictOptimizable() const override { return false; } bool cleanOut() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* searchp() const { return op1p(); } // op1 = Search expression - void searchp(AstNode* nodep) { setOp1p(nodep); } }; class AstUCFunc final : public AstNodeMath { // User's $c function // Perhaps this should be an AstNodeListop; but there's only one list math right now + // @astgen op1 := exprsp : List[AstNode] // Expressions to print public: AstUCFunc(FileLine* fl, AstNode* exprsp) : ASTGEN_SUPER_UCFunc(fl) { - addNOp1p(exprsp); + this->addExprsp(exprsp); } ASTGEN_MEMBERS_UCFunc; bool cleanOut() const override { return false; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs bool isOutputter() const override { return true; } bool isGateOptimizable() const override { return false; } @@ -1401,13 +1310,14 @@ public: bool cleanOut() const override { return true; } }; class AstValuePlusArgs final : public AstNodeMath { - // Parents: expr - // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs + // Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs. + // @astgen op1 := searchp : Optional[AstNode] + // @astgen op2 := outp : AstNode // VarRef for result public: AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp) : ASTGEN_SUPER_ValuePlusArgs(fl) { - setOp1p(searchp); - setOp2p(outp); + this->searchp(searchp); + this->outp(outp); } ASTGEN_MEMBERS_ValuePlusArgs; string verilogKwd() const override { return "$value$plusargs"; } @@ -1418,10 +1328,6 @@ public: bool isPure() const override { return !outp(); } bool cleanOut() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* searchp() const { return op1p(); } // op1 = Search expression - void searchp(AstNode* nodep) { setOp1p(nodep); } - AstNode* outp() const { return op2p(); } // op2 = Expressions to output - void outp(AstNode* nodep) { setOp2p(nodep); } }; // === AstNodeBiop === @@ -2396,6 +2302,8 @@ public: class AstReplicate final : public AstNodeBiop { // Also used as a "Uniop" flavor of Concat, e.g. "{a}" // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp() + // @astgen alias op1 := srcp + // @astgen alias op2 := countp public: AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_Replicate(fl, lhsp, rhsp) { @@ -3407,8 +3315,9 @@ class AstSel final : public AstNodeTriop { // Multiple bit range extraction // Parents: math|stmt // Children: varref|arraysel, math, constant math - // Tempting to have an access() style method here as LHS selects are quite - // different, but that doesn't play well with V3Inst and bidirects which don't know direction + // @astgen alias op1 := fromp + // @astgen alias op2 := lsbp + // @astgen alias op3 := widthp private: VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid int m_declElWidth; // If a packed array, the number of bits per element @@ -3446,11 +3355,6 @@ public: bool sizeMattersThs() const override { return false; } bool same(const AstNode*) const override { return true; } int instrCount() const override { return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - AstNode* lsbp() const { return op2p(); } // op2 = Msb selection expression - AstNode* widthp() const { return op3p(); } // op3 = Width int widthConst() const { return VN_AS(widthp(), Const)->toSInt(); } int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); } int msbConst() const { return lsbConst() + widthConst() - 1; } @@ -3463,7 +3367,7 @@ public: class AstSliceSel final : public AstNodeTriop { // Multiple array element extraction // Parents: math|stmt - // Children: varref|arraysel, math, constant math + // @astgen alias op1 := fromp private: VNumRange m_declRange; // Range of the 'from' array if isRanged() is set, else invalid public: @@ -3488,9 +3392,6 @@ public: bool sizeMattersThs() const override { return false; } bool same(const AstNode*) const override { return true; } int instrCount() const override { return 10; } // Removed before matters - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods VNumRange& declRange() { return m_declRange; } const VNumRange& declRange() const { return m_declRange; } @@ -3527,11 +3428,11 @@ class AstCond final : public AstNodeCond { // Parents: MATH // Children: MATH public: - AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : ASTGEN_SUPER_Cond(fl, condp, expr1p, expr2p) {} + AstCond(FileLine* fl, AstNode* condp, AstNode* thenp, AstNode* elsep) + : ASTGEN_SUPER_Cond(fl, condp, thenp, elsep) {} ASTGEN_MEMBERS_Cond; - AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { - return new AstCond(this->fileline(), condp, expr1p, expr2p); + AstNode* cloneType(AstNode* condp, AstNode* thenp, AstNode* elsep) override { + return new AstCond(this->fileline(), condp, thenp, elsep); } }; class AstCondBound final : public AstNodeCond { @@ -3539,11 +3440,11 @@ class AstCondBound final : public AstNodeCond { // Parents: MATH // Children: MATH public: - AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : ASTGEN_SUPER_CondBound(fl, condp, expr1p, expr2p) {} + AstCondBound(FileLine* fl, AstNode* condp, AstNode* thenp, AstNode* elsep) + : ASTGEN_SUPER_CondBound(fl, condp, thenp, elsep) {} ASTGEN_MEMBERS_CondBound; - AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { - return new AstCondBound(this->fileline(), condp, expr1p, expr2p); + AstNode* cloneType(AstNode* condp, AstNode* thenp, AstNode* elsep) override { + return new AstCondBound(this->fileline(), condp, thenp, elsep); } }; diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index e3d56b736..12b832507 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -32,8 +32,8 @@ class AstNodeBlock VL_NOT_FINAL : public AstNode { // A Begin/fork block + // @astgen op1 := stmtsp : List[AstNode] // Parents: statement - // Children: statements private: string m_name; // Name of block bool m_unnamed; // Originally unnamed (name change does not affect this) @@ -41,7 +41,7 @@ protected: AstNodeBlock(VNType t, FileLine* fl, const string& name, AstNode* stmtsp) : AstNode{t, fl} , m_name{name} { - addNOp1p(stmtsp); + addStmtsp(stmtsp); m_unnamed = (name == ""); } @@ -50,13 +50,18 @@ public: void dump(std::ostream& str) const override; string name() const override { return m_name; } // * = Block name void name(const string& name) override { m_name = name; } - // op1 = Statements - AstNode* stmtsp() const { return op1p(); } // op1 = List of statements - void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } bool unnamed() const { return m_unnamed; } bool isFirstInMyListOfStatements(AstNode* nodep) const override { return nodep == stmtsp(); } }; class AstNodeFTask VL_NOT_FINAL : public AstNode { + // Output variable in functions, nullptr in tasks + // @astgen op1 := fvarp : Optional[AstNode] + // Class/package scope + // @astgen op2 := classOrPackagep : Optional[AstNode] + // Statements/Ports/Vars + // @astgen op3 := stmtsp : List[AstNode] + // Scope name + // @astgen op4 := scopeNamep : Optional[AstScopeName] private: string m_name; // Name of task string m_cname; // Name of task if DPI import @@ -106,7 +111,7 @@ protected: , m_recursive{false} , m_underGenerate{false} , m_virtual{false} { - addNOp3p(stmtsp); + addStmtsp(stmtsp); cname(name); // Might be overridden by dpi import/export } @@ -120,23 +125,11 @@ public: void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } void cname(const string& cname) { m_cname = cname; } - // op1 = Output variable (functions only, nullptr for tasks) - AstNode* fvarp() const { return op1p(); } - void addFvarp(AstNode* nodep) { addNOp1p(nodep); } bool isFunction() const { return fvarp() != nullptr; } - // op2 = Class/package scope - AstNode* classOrPackagep() const { return op2p(); } - void classOrPackagep(AstNode* nodep) { setNOp2p(nodep); } - // op3 = Statements/Ports/Vars - AstNode* stmtsp() const { return op3p(); } // op3 = List of statements - void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } - // op4 = scope name - AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); } // MORE ACCESSORS void dpiOpenParentInc() { ++m_dpiOpenParent; } void dpiOpenParentClear() { m_dpiOpenParent = 0; } uint64_t dpiOpenParent() const { return m_dpiOpenParent; } - void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } void taskPublic(bool flag) { m_taskPublic = flag; } bool taskPublic() const { return m_taskPublic; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } @@ -184,7 +177,7 @@ public: class AstNodeFile VL_NOT_FINAL : public AstNode { // Emitted Otput file // Parents: NETLIST - // Children: AstTextBlock + // @astgen op1 := tblockp : Optional[AstTextBlock] private: string m_name; ///< Filename public: @@ -195,13 +188,14 @@ public: void dump(std::ostream& str) const override; string name() const override { return m_name; } bool same(const AstNode* /*samep*/) const override { return true; } - void tblockp(AstTextBlock* tblockp) { setOp1p((AstNode*)tblockp); } - AstTextBlock* tblockp() { return VN_AS(op1p(), TextBlock); } }; class AstNodeModule VL_NOT_FINAL : public AstNode { // A module, package, program or interface declaration; // something that can live directly under the TOP, // excluding $unit package stuff + // @astgen op1 := inlinesp : List[AstNode] + // @astgen op2 := stmtsp : List[AstNode] + // @astgen op3 := activesp : List[AstActive] private: string m_name; // Name of the module const string m_origName; // Name of the module, ignoring name() changes, for dot lookup @@ -239,12 +233,6 @@ public: bool maybePointedTo() const override { return true; } string name() const override { return m_name; } virtual bool timescaleMatters() const = 0; - AstNode* stmtsp() const { return op2p(); } // op2 = List of statements - AstActive* activesp() const { return VN_AS(op3p(), Active); } // op3 = List of i/sblocks - // METHODS - void addInlinesp(AstNode* nodep) { addOp1p(nodep); } - void addStmtp(AstNode* nodep) { addNOp2p(nodep); } - void addActivep(AstNode* nodep) { addOp3p(nodep); } // ACCESSORS void name(const string& name) override { m_name = name; } string origName() const override { return m_origName; } @@ -278,42 +266,37 @@ public: }; class AstNodePreSel VL_NOT_FINAL : public AstNode { // Something that becomes an AstSel + // @astgen op1 := fromp : AstNode + // @astgen op2 := rhsp : AstNode + // @astgen op3 := thsp : Optional[AstNode] + // @astgen op4 := attrp : Optional[AstAttrOf] protected: - AstNodePreSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* rhs, AstNode* ths) + AstNodePreSel(VNType t, FileLine* fl, AstNode* fromp, AstNode* rhsp, AstNode* thsp) : AstNode{t, fl} { - setOp1p(fromp); - setOp2p(rhs); - setNOp3p(ths); + this->fromp(fromp); + this->rhsp(rhsp); + this->thsp(thsp); } public: ASTGEN_MEMBERS_NodePreSel; - AstNode* fromp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } - AstNode* thsp() const { return op3p(); } - AstAttrOf* attrp() const { return VN_AS(op4p(), AttrOf); } - void fromp(AstNode* nodep) { return setOp1p(nodep); } - void rhsp(AstNode* nodep) { return setOp2p(nodep); } - void thsp(AstNode* nodep) { return setOp3p(nodep); } - void attrp(AstAttrOf* nodep) { return setOp4p(reinterpret_cast(nodep)); } // METHODS bool same(const AstNode*) const override { return true; } }; class AstNodeProcedure VL_NOT_FINAL : public AstNode { // IEEE procedure: initial, final, always + // @astgen op2 := stmtsp : List[AstNode] // Note: op1 is used in some sub-types only protected: - AstNodeProcedure(VNType t, FileLine* fl, AstNode* bodysp) + AstNodeProcedure(VNType t, FileLine* fl, AstNode* stmtsp) : AstNode{t, fl} { - addNOp2p(bodysp); + addStmtsp(stmtsp); } public: ASTGEN_MEMBERS_NodeProcedure; // METHODS void dump(std::ostream& str) const override; - AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate - void addStmtp(AstNode* nodep) { addOp2p(nodep); } - bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } + bool isJustOneBodyStmt() const { return stmtsp() && !stmtsp()->nextp(); } }; class AstNodeRange VL_NOT_FINAL : public AstNode { // A range, sized or unsized @@ -345,13 +328,17 @@ public: void dump(std::ostream& str = std::cout) const override; }; class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt { + // Iteration is in order, and we want rhsp to be visited first (which is the execution order) + // @astgen op1 := rhsp : AstNode + // @astgen op2 := lhsp : AstNode + // @astgen op3 := timingControlp : Optional[AstNode] protected: AstNodeAssign(VNType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* timingControlp = nullptr) : AstNodeStmt{t, fl} { - setOp1p(rhsp); - setOp2p(lhsp); - addNOp3p(timingControlp); + this->rhsp(rhsp); + this->lhsp(lhsp); + this->timingControlp(timingControlp); dtypeFrom(lhsp); } @@ -359,14 +346,6 @@ public: ASTGEN_MEMBERS_NodeAssign; // Clone single node, just get same type back. virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; - // So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2 - AstNode* rhsp() const { return op1p(); } // op1 = Assign from - AstNode* lhsp() const { return op2p(); } // op2 = Assign to - // op3 = Timing controls (delays, event controls) - AstNode* timingControlp() const { return op3p(); } - void addTimingControlp(AstNode* const np) { addNOp3p(np); } - void rhsp(AstNode* np) { setOp1p(np); } - void lhsp(AstNode* np) { setOp2p(np); } bool hasDType() const override { return true; } virtual bool cleanRhs() const { return true; } int instrCount() const override { return widthInstrs(); } @@ -376,6 +355,8 @@ public: }; class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt { // A call of a C++ function, perhaps a AstCFunc or perhaps globally named + // @astgen op2 := argsp : List[AstNode] // Note: op1 used by some sub-types only + // // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. AstCFunc* m_funcp; string m_argTypes; @@ -384,7 +365,7 @@ protected: AstNodeCCall(VNType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) : AstNodeStmt{t, fl, true} , m_funcp{funcp} { - addNOp2p(argsp); + addArgsp(argsp); } public: @@ -397,7 +378,6 @@ public: const AstNodeCCall* const asamep = static_cast(samep); return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes()); } - AstNode* exprsp() const { return op2p(); } // op2 = expressions to print bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool isPure() const override; @@ -406,34 +386,29 @@ public: void funcp(AstCFunc* funcp) { m_funcp = funcp; } void argTypes(const string& str) { m_argTypes = str; } string argTypes() const { return m_argTypes; } - // op1p reserved for AstCMethodCall - AstNode* argsp() const { return op2p(); } - void addArgsp(AstNode* nodep) { addOp2p(nodep); } }; class AstNodeCase VL_NOT_FINAL : public AstNodeStmt { + // @astgen op1 := exprp : AstNode // Condition (scurtinee) expression + // @astgen op2 := itemsp : List[AstCaseItem] + // @astgen op3 := notParallelp : List[AstNode] // assertion code for non-full case's protected: - AstNodeCase(VNType t, FileLine* fl, AstNode* exprp, AstNode* casesp) + AstNodeCase(VNType t, FileLine* fl, AstNode* exprp, AstCaseItem* itemsp) : AstNodeStmt{t, fl} { - setOp1p(exprp); - addNOp2p(casesp); + this->exprp(exprp); + this->addItemsp(itemsp); } public: ASTGEN_MEMBERS_NodeCase; int instrCount() const override { return INSTR_COUNT_BRANCH; } - AstNode* exprp() const { return op1p(); } // op1 = case condition - AstCaseItem* itemsp() const { - return VN_AS(op2p(), CaseItem); - } // op2 = list of case expressions - AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's - void addItemsp(AstNode* nodep) { addOp2p(nodep); } - void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } }; class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt { // Cover or Assert // Parents: {statement list} - // Children: expression, report string -private: + // @astgen op1 := propp : AstNode + // @astgen op2 := sentreep : Optional[AstSenTree] + // op3 used by some sub-types only + // @astgen op4 := passsp: List[AstNode] // Statments when propp is passing/truthly const bool m_immediate; // Immediate assertion/cover string m_name; // Name to report public: @@ -442,22 +417,23 @@ public: : AstNodeStmt{t, fl} , m_immediate{immediate} , m_name{name} { - addOp1p(propp); - addNOp4p(passsp); + this->propp(propp); + this->addPasssp(passsp); } ASTGEN_MEMBERS_NodeCoverOrAssert; string name() const override { return m_name; } // * = Var name bool same(const AstNode* samep) const override { return samep->name() == name(); } void name(const string& name) override { m_name = name; } void dump(std::ostream& str = std::cout) const override; - AstNode* propp() const { return op1p(); } // op1 = property - AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); } // op2 = clock domain - void sentreep(AstSenTree* sentreep) { addOp2p((AstNode*)sentreep); } // op2 = clock domain - AstNode* passsp() const { return op4p(); } // op4 = statements (assert/cover passes) bool immediate() const { return m_immediate; } }; class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt { // A reference to a task (or function) + // @astgen op1 := namep : AstNode + // op2 used by some sub-types only + // @astgen op3 := pinsp : List[AstNode] + // @astgen op4 := scopeNamep : Optional[AstScopeName] + // // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. private: AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced @@ -469,13 +445,13 @@ private: protected: AstNodeFTaskRef(VNType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp) : AstNodeStmt{t, fl, statement} { - setOp1p(namep); - addNOp3p(pinsp); + this->namep(namep); + this->addPinsp(pinsp); } AstNodeFTaskRef(VNType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp) : AstNodeStmt{t, fl, statement} , m_name{name} { - addNOp3p(pinsp); + this->addPinsp(pinsp); } public: @@ -496,58 +472,46 @@ public: void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } bool pli() const { return m_pli; } void pli(bool flag) { m_pli = flag; } - // op1 = namep - AstNode* namep() const { return op1p(); } - // op2 = reserved for AstMethodCall - // op3 = Pin interconnection list - AstNode* pinsp() const { return op3p(); } - void addPinsp(AstNode* nodep) { addOp3p(nodep); } - // op4 = scope tracking - AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); } - void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } }; class AstNodeFor VL_NOT_FINAL : public AstNodeStmt { + // @astgen op1 := initsp : List[AstNode] + // @astgen op2 := condp : AstNode + // @astgen op3 := incsp : List[AstNode] + // @astgen op4 := stmtsp : List[AstNode] protected: AstNodeFor(VNType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, - AstNode* bodysp) + AstNode* stmtsp) : AstNodeStmt{t, fl} { - addNOp1p(initsp); - setOp2p(condp); - addNOp3p(incsp); - addNOp4p(bodysp); + this->addInitsp(initsp); + this->condp(condp); + this->addIncsp(incsp); + this->addStmtsp(stmtsp); } public: ASTGEN_MEMBERS_NodeFor; - AstNode* initsp() const { return op1p(); } // op1 = initial statements - AstNode* condp() const { return op2p(); } // op2 = condition to continue - AstNode* incsp() const { return op3p(); } // op3 = increment statements - AstNode* bodysp() const { return op4p(); } // op4 = body of loop bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } bool same(const AstNode* /*samep*/) const override { return true; } }; class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { + // @astgen op1 := condp : AstNode + // @astgen op2 := thensp : List[AstNode] + // @astgen op3 := elsesp : List[AstNode] private: VBranchPred m_branchPred; // Branch prediction as taken/untaken? bool m_isBoundsCheck; // True if this if node was inserted for array bounds checking protected: - AstNodeIf(VNType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) + AstNodeIf(VNType t, FileLine* fl, AstNode* condp, AstNode* thensp, AstNode* elsesp) : AstNodeStmt{t, fl} { - setOp1p(condp); - addNOp2p(ifsp); - addNOp3p(elsesp); + this->condp(condp); + this->addThensp(thensp); + this->addElsesp(elsesp); isBoundsCheck(false); } public: ASTGEN_MEMBERS_NodeIf; - AstNode* condp() const { return op1p(); } // op1 = condition - AstNode* ifsp() const { return op2p(); } // op2 = list of true statements - AstNode* elsesp() const { return op3p(); } // op3 = list of false statements - void condp(AstNode* newp) { setOp1p(newp); } - void addIfsp(AstNode* newp) { addOp2p(newp); } - void addElsesp(AstNode* newp) { addOp3p(newp); } bool isGateOptimizable() const override { return false; } bool isGateDedupable() const override { return true; } int instrCount() const override { return INSTR_COUNT_BRANCH; } @@ -557,21 +521,25 @@ public: void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; } bool isBoundsCheck() const { return m_isBoundsCheck; } bool isFirstInMyListOfStatements(AstNode* n) const override { - return n == ifsp() || n == elsesp(); + return n == thensp() || n == elsesp(); } }; class AstNodeReadWriteMem VL_NOT_FINAL : public AstNodeStmt { -private: + // @astgen op1 := filenamep : AstNode + // @astgen op2 := memp : AstNode + // @astgen op3 := lsbp : Optional[AstNode] + // @astgen op4 := msbp : Optional[AstNode] + const bool m_isHex; // readmemh, not readmemb public: AstNodeReadWriteMem(VNType t, FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp) : AstNodeStmt(t, fl) , m_isHex(hex) { - setOp1p(filenamep); - setOp2p(memp); - setNOp3p(lsbp); - setNOp4p(msbp); + this->filenamep(filenamep); + this->memp(memp); + this->lsbp(lsbp); + this->msbp(msbp); } ASTGEN_MEMBERS_NodeReadWriteMem; bool isGateOptimizable() const override { return false; } @@ -583,10 +551,6 @@ public: return isHex() == static_cast(samep)->isHex(); } bool isHex() const { return m_isHex; } - AstNode* filenamep() const { return op1p(); } - AstNode* memp() const { return op2p(); } - AstNode* lsbp() const { return op3p(); } - AstNode* msbp() const { return op4p(); } virtual const char* cFuncPrefixp() const = 0; }; class AstNodeText VL_NOT_FINAL : public AstNode { @@ -626,7 +590,8 @@ public: class AstActive final : public AstNode { // Block of code with sensitivity activation // Parents: MODULE | CFUNC - // Children: SENTREE, statements + // @astgen op1 := sensesStorep : Optional[AstSenTree] // Moved into m_sensesp in V3Active + // @astgen op2 := stmtsp : List[AstNode] // Logic private: string m_name; AstSenTree* m_sensesp; @@ -646,12 +611,6 @@ public: // Statements are broken into pieces, as some must come before others. void sensesp(AstSenTree* nodep) { m_sensesp = nodep; } AstSenTree* sensesp() const { return m_sensesp; } - // op1 = Sensitivity tree, if a clocked block in early stages - void sensesStorep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } - AstSenTree* sensesStorep() const { return VN_AS(op1p(), SenTree); } - // op2 = Combo logic - AstNode* stmtsp() const { return op2p(); } - void addStmtsp(AstNode* nodep) { addOp2p(nodep); } // METHODS inline bool hasInitial() const; inline bool hasSettle() const; @@ -659,42 +618,39 @@ public: }; class AstArg final : public AstNode { // An argument to a function/task -private: + // @astgen op1 := exprp : Optional[AstNode] // nullptr if omitted string m_name; // Pin name, or "" for number based interconnect public: AstArg(FileLine* fl, const string& name, AstNode* exprp) : ASTGEN_SUPER_Arg(fl) , m_name{name} { - setNOp1p(exprp); + this->exprp(exprp); } ASTGEN_MEMBERS_Arg; string name() const override { return m_name; } // * = Pin name, ""=go by number void name(const string& name) override { m_name = name; } - void exprp(AstNode* nodep) { addOp1p(nodep); } - // op1 = Expression connected to pin, nullptr if unconnected - AstNode* exprp() const { return op1p(); } bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } }; class AstAttrOf final : public AstNode { -private: // Return a value of a attribute, for example a LSB or array LSB of a signal + // @astgen op1 := fromp : Optional[AstNode] + // @astgen op2 := dimp : Optional[AstNode] VAttrType m_attrType; // What sort of extraction public: AstAttrOf(FileLine* fl, VAttrType attrtype, AstNode* fromp = nullptr, AstNode* dimp = nullptr) : ASTGEN_SUPER_AttrOf(fl) { - setNOp1p(fromp); - setNOp2p(dimp); + this->fromp(fromp); + this->dimp(dimp); m_attrType = attrtype; } ASTGEN_MEMBERS_AttrOf; - AstNode* fromp() const { return op1p(); } - AstNode* dimp() const { return op2p(); } VAttrType attrType() const { return m_attrType; } void dump(std::ostream& str = std::cout) const override; }; class AstBind final : public AstNode { // Parents: MODULE // Children: CELL + // @astgen op1 := cellsp : List[AstNode] private: string m_name; // Binding to name public: @@ -702,18 +658,21 @@ public: : ASTGEN_SUPER_Bind(fl) , m_name{name} { UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound"); - addNOp1p(cellsp); + this->addCellsp(cellsp); } ASTGEN_MEMBERS_Bind; // ACCESSORS string name() const override { return m_name; } // * = Bind Target name void name(const string& name) override { m_name = name; } - AstNode* cellsp() const { return op1p(); } // op1 = cells }; class AstCFunc final : public AstNode { // C++ function // Parents: MODULE/SCOPE - // Children: VAR/statements + // If adding node accessors, see below emptyBody + // @astgen op1 := argsp : List[AstNode] + // @astgen op2 := initsp : List[AstNode] + // @astgen op3 := stmtsp : List[AstNode] + // @astgen op4 := finalsp : List[AstNode] private: AstScope* m_scopep; string m_name; @@ -850,16 +809,6 @@ public: void dpiImportWrapper(bool flag) { m_dpiImportWrapper = flag; } void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; } bool dpiTraceInit() const { return m_dpiTraceInit; } - // - // If adding node accessors, see below emptyBody - AstNode* argsp() const { return op1p(); } - void addArgsp(AstNode* nodep) { addOp1p(nodep); } - AstNode* initsp() const { return op2p(); } - void addInitsp(AstNode* nodep) { addOp2p(nodep); } - AstNode* stmtsp() const { return op3p(); } - void addStmtsp(AstNode* nodep) { addOp3p(nodep); } - AstNode* finalsp() const { return op4p(); } - void addFinalsp(AstNode* nodep) { addOp4p(nodep); } // Special methods bool emptyBody() const { return argsp() == nullptr && initsp() == nullptr && stmtsp() == nullptr @@ -885,36 +834,33 @@ public: }; class AstCaseItem final : public AstNode { // Single item of a case statement - // Parents: CASE - // condsp Children: MATH (Null condition used for default block) - // bodysp Children: Statements + // @astgen op1 := condsp : List[AstNode] + // @astgen op2 := stmtsp : List[AstNode] public: - AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* bodysp) + AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* stmtsp) : ASTGEN_SUPER_CaseItem(fl) { - addNOp1p(condsp); - addNOp2p(bodysp); + this->addCondsp(condsp); + this->addStmtsp(stmtsp); } ASTGEN_MEMBERS_CaseItem; int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; } - AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions - AstNode* bodysp() const { return op2p(); } // op2 = what to do - void condsp(AstNode* nodep) { setOp1p(nodep); } - void addBodysp(AstNode* newp) { addOp2p(newp); } bool isDefault() const { return condsp() == nullptr; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstCast final : public AstNode { - // Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc + // Cast to appropriate data type + // @astgen op1 := fromp : AstNode + // @astgen op2 := childDTypep : Optional[AstNodeDType] public: - AstCast(FileLine* fl, AstNode* lhsp, VFlagChildDType, AstNodeDType* dtp) + AstCast(FileLine* fl, AstNode* fromp, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER_Cast(fl) { - setOp1p(lhsp); - setOp2p(dtp); + this->fromp(fromp); + this->childDTypep(dtp); dtypeFrom(dtp); } - AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp) + AstCast(FileLine* fl, AstNode* fromp, AstNodeDType* dtp) : ASTGEN_SUPER_Cast(fl) { - setOp1p(lhsp); + this->fromp(fromp); dtypeFrom(dtp); } ASTGEN_MEMBERS_Cast; @@ -923,20 +869,18 @@ public: virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - AstNode* lhsp() const { return op1p(); } - AstNode* fromp() const { return lhsp(); } - void lhsp(AstNode* nodep) { setOp1p(nodep); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeDType* childDTypep() const { return VN_AS(op2p(), NodeDType); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } }; class AstCastParse final : public AstNode { // Cast to appropriate type, where we haven't determined yet what the data type is + // @astgen op1 := lhsp : AstNode + // @astgen op2 := dtp : AstNode public: AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp) : ASTGEN_SUPER_CastParse(fl) { - setOp1p(lhsp); - setOp2p(dtp); + this->lhsp(lhsp); + this->dtp(dtp); } ASTGEN_MEMBERS_CastParse; virtual string emitVerilog() { return "((%d)'(%l))"; } @@ -944,16 +888,16 @@ public: virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - AstNode* lhsp() const { return op1p(); } - AstNode* dtp() const { return op2p(); } }; class AstCastSize final : public AstNode { // Cast to specific size; signed/twostate inherited from lower element per IEEE + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode public: AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp) : ASTGEN_SUPER_CastSize(fl) { - setOp1p(lhsp); - setOp2p((AstNode*)rhsp); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_CastSize; // No hasDType because widthing removes this node before the hasDType check @@ -961,12 +905,13 @@ public: virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } }; class AstCell final : public AstNode { // A instantiation cell or interface call (don't know which until link) -private: + // @astgen op1 := pinsp : List[AstPin] // List of port assignments + // @astgen op2 := paramsp : List[AstPin] // List of parameter assignments + // @astgen op3 := rangep : Optional[AstRange] // Range for arrayed instances + // @astgen op4 := intfRefsp : List[AstIntfRef] // List of interface references FileLine* m_modNameFileline; // Where module the cell instances token was string m_name; // Cell name string m_origName; // Original name before dot addition @@ -986,9 +931,9 @@ public: , m_hasIfaceVar{false} , m_recursive{false} , m_trace{true} { - addNOp1p((AstNode*)pinsp); - addNOp2p((AstNode*)paramsp); - setNOp3p((AstNode*)rangep); + this->addPinsp(pinsp); + this->addParamsp(paramsp); + this->rangep(rangep); } ASTGEN_MEMBERS_Cell; // No cloneRelink, we presume cloneee's want the same module linkages @@ -1003,17 +948,7 @@ public: string modName() const { return m_modName; } // * = Instance name void modName(const string& name) { m_modName = name; } FileLine* modNameFileline() const { return m_modNameFileline; } - AstPin* pinsp() const { return VN_AS(op1p(), Pin); } // op1 = List of cell ports - // op2 = List of parameter #(##) values - AstPin* paramsp() const { return VN_AS(op2p(), Pin); } - // op3 = Range of arrayed instants (nullptr=not ranged) - AstRange* rangep() const { return VN_AS(op3p(), Range); } - // op4 = List of interface references - AstIntfRef* intfRefp() const { return VN_AS(op4p(), IntfRef); } AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated - void addPinsp(AstPin* nodep) { addOp1p((AstNode*)nodep); } - void addParamsp(AstPin* nodep) { addOp2p((AstNode*)nodep); } - void addIntfRefp(AstIntfRef* nodep) { addOp4p((AstNode*)nodep); } void modp(AstNodeModule* nodep) { m_modp = nodep; } bool hasIfaceVar() const { return m_hasIfaceVar; } void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; } @@ -1024,18 +959,17 @@ public: }; class AstCellArrayRef final : public AstNode { // As-of-yet unlinkable reference into an array of cells -private: + // @astgen op1 := selp : List[AstNode] // Select expression string m_name; // Array name public: - AstCellArrayRef(FileLine* fl, const string& name, AstNode* selectExprp) + AstCellArrayRef(FileLine* fl, const string& name, AstNode* selp) : ASTGEN_SUPER_CellArrayRef(fl) , m_name{name} { - addNOp1p(selectExprp); + this->addSelp(selp); } ASTGEN_MEMBERS_CellArrayRef; // ACCESSORS string name() const override { return m_name; } // * = Array name - AstNode* selp() const { return op1p(); } // op1 = Select expression }; class AstCellInline final : public AstNode { // A instantiation cell that was removed by inlining @@ -1070,49 +1004,49 @@ public: }; class AstCellRef final : public AstNode { // As-of-yet unlinkable reference into a cell + // @astgen op1 := cellp : AstNode + // @astgen op2 := exprp : AstNode private: string m_name; // Cell name public: AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp) : ASTGEN_SUPER_CellRef(fl) , m_name{name} { - addNOp1p(cellp); - addNOp2p(exprp); + this->cellp(cellp); + this->exprp(exprp); } ASTGEN_MEMBERS_CellRef; // ACCESSORS string name() const override { return m_name; } // * = Array name - AstNode* cellp() const { return op1p(); } // op1 = Cell - AstNode* exprp() const { return op2p(); } // op2 = Expression }; class AstClassExtends final : public AstNode { // Children: List of AstParseRef for packages/classes // during early parse, then moves to dtype + // @astgen op1 := childDTypep : Optional[AstNodeDType] + // @astgen op2 := classOrPkgsp : Optional[AstNode] public: AstClassExtends(FileLine* fl, AstNode* classOrPkgsp) : ASTGEN_SUPER_ClassExtends(fl) { - setNOp2p(classOrPkgsp); // Only for parser + this->classOrPkgsp(classOrPkgsp); // Only for parser } ASTGEN_MEMBERS_ClassExtends; bool hasDType() const override { return true; } string verilogKwd() const override { return "extends"; } - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - AstNode* classOrPkgsp() const { return op2p(); } AstClass* classp() const; // Class being extended (after link) }; class AstClassOrPackageRef final : public AstNode { + // @astgen op1 := paramsp : List[AstPin] private: string m_name; // Node not NodeModule to appease some early parser usage AstNode* m_classOrPackageNodep; // Package hierarchy public: AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep, - AstNode* paramsp) + AstPin* paramsp) : ASTGEN_SUPER_ClassOrPackageRef(fl) , m_name{name} , m_classOrPackageNodep{classOrPackageNodep} { - addNOp4p(paramsp); + this->addParamsp(paramsp); } ASTGEN_MEMBERS_ClassOrPackageRef; // METHODS @@ -1136,25 +1070,23 @@ public: AstNodeModule* classOrPackagep() const; AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = (AstNode*)nodep; } - AstPin* paramsp() const { return VN_AS(op4p(), Pin); } }; class AstClocking final : public AstNode { // Set default clock region // Parents: MODULE - // Children: Assertions + // @astgen op1 := sensesp : List[AstSenItem] + // @astgen op2 := bodysp : List[AstNode] public: AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp) : ASTGEN_SUPER_Clocking(fl) { - addOp1p((AstNode*)sensesp); - addNOp2p(bodysp); + this->addSensesp(sensesp); + this->addBodysp(bodysp); } ASTGEN_MEMBERS_Clocking; - // op1 = Sensitivity list - AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } - AstNode* bodysp() const { return op2p(); } // op2 = Body }; class AstConstPool final : public AstNode { // Container for const static data + // @astgen op1 := modulep : AstModule // m_modp below TODO: fix this mess std::unordered_multimap m_tables; // Constant tables (unpacked arrays) std::unordered_multimap m_consts; // Constant tables (scalars) AstModule* const m_modp; // The Module holding the Scope below ... @@ -1186,8 +1118,7 @@ public: class AstDefParam final : public AstNode { // A defparam assignment // Parents: MODULE - // Children: math -private: + // @astgen op1 := rhsp : AstNode string m_name; // Name of variable getting set string m_path; // Dotted cellname to set parameter of public: @@ -1195,24 +1126,25 @@ public: : ASTGEN_SUPER_DefParam(fl) , m_name{name} , m_path{path} { - setOp1p(rhsp); + this->rhsp(rhsp); } string name() const override { return m_name; } // * = Scope name ASTGEN_MEMBERS_DefParam; bool same(const AstNode*) const override { return true; } - AstNode* rhsp() const { return op1p(); } // op1 = Assign from string path() const { return m_path; } }; class AstDot final : public AstNode { // A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef // These are eliminated in the link stage + // @astgen op1 := lhsp : AstNode + // @astgen op2 := rhsp : AstNode const bool m_colon; // Is a "::" instead of a "." (lhs must be package/class) public: AstDot(FileLine* fl, bool colon, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_Dot(fl) , m_colon{colon} { - setOp1p(lhsp); - setOp2p(rhsp); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_Dot; // For parser, make only if non-null package @@ -1221,9 +1153,6 @@ public: return new AstDot(fl, true, packageOrClassp, rhsp); } void dump(std::ostream& str) const override; - AstNode* lhsp() const { return op1p(); } - void rhsp(AstNode* nodep) { setOp2p(nodep); } - AstNode* rhsp() const { return op2p(); } bool colon() const { return m_colon; } }; class AstDpiExport final : public AstNode { @@ -1246,7 +1175,7 @@ public: }; class AstElabDisplay final : public AstNode { // Parents: stmtlist - // Children: SFORMATF to generate print string + // @astgen op1 := fmtp : List[AstSFormatF] private: VDisplayType m_displayType; @@ -1269,8 +1198,6 @@ public: int instrCount() const override { return INSTR_COUNT_PLI; } VDisplayType displayType() const { return m_displayType; } void displayType(VDisplayType type) { m_displayType = type; } - void fmtp(AstSFormatF* nodep) { addOp1p((AstNode*)nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } }; class AstEmpty final : public AstNode { // Represents something missing, e.g. a missing argument in FOREACH @@ -1287,7 +1214,10 @@ class AstExecGraph final : public AstNode { // // The AstMTaskBody nodes are also children of this node, so we can visit // them without traversing the graph. -private: + // + // @astgen op1 := mTaskBodiesp : List[AstMTaskBody] + // In later phases, the statements that start the parallel execution + // @astgen op2 := stmtsp : List[AstNode] V3Graph* const m_depGraphp; // contains ExecMTask vertices const string m_name; // Name of this AstExecGraph (for uniqueness at code generation) @@ -1302,22 +1232,17 @@ public: string name() const override { return m_name; } V3Graph* depGraphp() { return m_depGraphp; } const V3Graph* depGraphp() const { return m_depGraphp; } - // op1: The mtask bodies - AstMTaskBody* mTaskBodiesp() const { return VN_AS(op1p(), MTaskBody); } - void addMTaskBodyp(AstMTaskBody* bodyp) { addOp1p((AstNode*)bodyp); } - // op2: In later phases, the statements that start the parallel execution - void addStmtsp(AstNode* stmtp) { addOp2p(stmtp); } }; class AstImplicit final : public AstNode { // Create implicit wires and do nothing else, for gates that are ignored // Parents: MODULE + // @astgen op1 := exprsp : List[AstNode] public: AstImplicit(FileLine* fl, AstNode* exprsp) : ASTGEN_SUPER_Implicit(fl) { - addNOp1p(exprsp); + this->addExprsp(exprsp); } ASTGEN_MEMBERS_Implicit; - AstNode* exprsp() const { return op1p(); } // op1 = Assign from }; class AstInitArray final : public AstNode { // Set a var to a map of values @@ -1325,7 +1250,9 @@ class AstInitArray final : public AstNode { // If default is specified, the vector may be sparse, and not provide each value. // Key values are C++ array style, with lo() at index 0 // Parents: ASTVAR::init() - // Children: AstInitItem + // @astgen op1 := defaultp : Optional[AstNode] // Default, if sparse + // @astgen op2 := initsp : List[AstNode] // Initial value expressions + // public: using KeyItemMap = std::map; @@ -1335,7 +1262,7 @@ public: AstInitArray(FileLine* fl, AstNodeDType* newDTypep, AstNode* defaultp) : ASTGEN_SUPER_InitArray(fl) { dtypep(newDTypep); - addNOp1p(defaultp); + this->defaultp(defaultp); } ASTGEN_MEMBERS_InitArray; void dump(std::ostream& str) const override; @@ -1347,12 +1274,9 @@ public: // of children list, and instead use map-vs-map key/value compare return m_map == static_cast(samep)->m_map; } - AstNode* defaultp() const { return op1p(); } // op1 = Default if sparse - void defaultp(AstNode* newp) { setOp1p(newp); } - AstNode* initsp() const { return op2p(); } // op2 = Initial value expressions void addValuep(AstNode* newp) { addIndexValuep(m_map.size(), newp); } const KeyItemMap& map() const { return m_map; } - AstNode* addIndexValuep(uint64_t index, AstNode* newp); + void addIndexValuep(uint64_t index, AstNode* newp); AstNode* getIndexValuep(uint64_t index) const; AstNode* getIndexDefaultedValuep(uint64_t index) const; }; @@ -1360,17 +1284,16 @@ class AstInitItem final : public AstNode { // Container for a item in an init array // This container is present so that the value underneath may get replaced with a new nodep // and the upper AstInitArray's map will remain correct (pointing to this InitItem) + // @astgen op1 := valuep : AstNode public: // Parents: INITARRAY AstInitItem(FileLine* fl, AstNode* valuep) : ASTGEN_SUPER_InitItem(fl) { - addOp1p(valuep); + this->valuep(valuep); } ASTGEN_MEMBERS_InitItem; bool maybePointedTo() const override { return true; } bool hasDType() const override { return false; } // See valuep()'s dtype instead - AstNode* valuep() const { return op1p(); } // op1 = Value - void valuep(AstNode* nodep) { addOp1p(nodep); } }; class AstIntfRef final : public AstNode { // An interface reference @@ -1385,7 +1308,7 @@ public: }; class AstMTaskBody final : public AstNode { // Hold statements for each MTask -private: + // @astgen op1 := stmtsp : List[AstNode] ExecMTask* m_execMTaskp = nullptr; public: @@ -1396,8 +1319,6 @@ public: BROKEN_RTN(!m_execMTaskp); return nullptr; } - AstNode* stmtsp() const { return op1p(); } - void addStmtsp(AstNode* nodep) { addOp1p(nodep); } void addStmtsFirstp(AstNode* nodep) { if (stmtsp()) { stmtsp()->addHereThisAsNext(nodep); @@ -1411,18 +1332,17 @@ public: }; class AstModport final : public AstNode { // A modport in an interface -private: + // @astgen op1 := varsp : List[AstNode] string m_name; // Name of the modport public: AstModport(FileLine* fl, const string& name, AstNode* varsp) : ASTGEN_SUPER_Modport(fl) , m_name{name} { - addNOp1p(varsp); + this->addVarsp(varsp); } string name() const override { return m_name; } bool maybePointedTo() const override { return true; } ASTGEN_MEMBERS_Modport; - AstNode* varsp() const { return op1p(); } // op1 = List of Vars }; class AstModportFTaskRef final : public AstNode { // An import/export referenced under a modport @@ -1475,7 +1395,10 @@ class AstNetlist final : public AstNode { // All modules are under this single top node. // Parents: none // Children: MODULEs & CFILEs -private: + // @astgen op1 := modulesp : List[AstNodeModule] + // @astgen op2 := filesp : List[AstNodeFile] + // @astgen op3 := miscsp : List[AstNode] + AstTypeTable* const m_typeTablep; // Reference to top type table, for faster lookup AstConstPool* const m_constPoolp; // Reference to constant pool, for faster lookup AstPackage* m_dollarUnitPkgp = nullptr; // $unit @@ -1496,16 +1419,9 @@ public: void cloneRelink() override { V3ERROR_NA; } string name() const override { return "$root"; } void dump(std::ostream& str) const override; - AstNodeModule* modulesp() const { // op1 = List of modules - return VN_AS(op1p(), NodeModule); - } AstNodeModule* topModulep() const { // Top module in hierarchy return modulesp(); // First one in the list, for now } - void addModulep(AstNodeModule* modulep) { addOp1p((AstNode*)modulep); } - AstNodeFile* filesp() const { return VN_AS(op2p(), NodeFile); } // op2 = List of files - void addFilesp(AstNodeFile* filep) { addOp2p((AstNode*)filep); } - void addMiscsp(AstNode* nodep) { addOp3p(nodep); } AstTypeTable* typeTablep() { return m_typeTablep; } void changeRequest(bool specified) { m_changeRequest = specified; } bool changeRequest() const { return m_changeRequest; } @@ -1581,8 +1497,9 @@ class AstParseRef final : public AstNode { // We don't know which at parse time due to bison constraints // The link stages will replace this with AstVarRef, or AstTaskRef, etc. // Parents: math|stmt - // Children: TEXT|DOT|SEL*|TASK|FUNC (or expression under sel) -private: + // @astgen op1 := lhsp : Optional[AstNode] + // @astgen op2 := ftaskrefp : Optional[AstNodeFTaskRef] + VParseRefExp m_expect; // Type we think it should resolve to string m_name; @@ -1592,8 +1509,8 @@ public: : ASTGEN_SUPER_ParseRef(fl) , m_expect{expect} , m_name{name} { - setNOp1p(lhsp); - setNOp2p((AstNode*)ftaskrefp); + this->lhsp(lhsp); + this->ftaskrefp(ftaskrefp); } ASTGEN_MEMBERS_ParseRef; void dump(std::ostream& str) const override; @@ -1605,14 +1522,10 @@ public: void name(const string& name) override { m_name = name; } VParseRefExp expect() const { return m_expect; } void expect(VParseRefExp exp) { m_expect = exp; } - // op1 = Components - AstNode* lhsp() const { return op1p(); } // op1 = List of statements - AstNode* ftaskrefp() const { return op2p(); } // op2 = Function/task reference - // op2 = Function/task reference - void ftaskrefp(AstNodeFTaskRef* nodep) { setNOp2p((AstNode*)nodep); } }; class AstPin final : public AstNode { - // A pin on a cell + // A port or parameter assignment on an instantiaton + // @astgen op1 := exprp : Optional[AstNode] // Expression connected (nullptr if unconnected) private: int m_pinNum; // Pin number string m_name; // Pin name, or "" for number based interconnect @@ -1625,7 +1538,7 @@ public: : ASTGEN_SUPER_Pin(fl) , m_pinNum{pinNum} , m_name{name} { - setNOp1p(exprp); + this->exprp(exprp); } inline AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp); ASTGEN_MEMBERS_Pin; @@ -1636,9 +1549,6 @@ public: string prettyOperatorName() const override; bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked int pinNum() const { return m_pinNum; } - void exprp(AstNode* nodep) { addOp1p(nodep); } - // op1 = Expression connected to pin, nullptr if unconnected - AstNode* exprp() const { return op1p(); } AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable void modVarp(AstVar* nodep) { m_modVarp = nodep; } // [After Link] Pointer to variable @@ -1651,9 +1561,9 @@ public: }; class AstPort final : public AstNode { // A port (in/out/inout) on a module -private: - int m_pinNum; // Pin number - string m_name; // Name of pin + // @astgen op1 := exprp : Optional[AstNode] // Expression connected to port + const int m_pinNum; // Pin number + const string m_name; // Name of pin public: AstPort(FileLine* fl, int pinnum, const string& name) : ASTGEN_SUPER_Port(fl) @@ -1662,10 +1572,8 @@ public: ASTGEN_MEMBERS_Port; string name() const override { return m_name; } // * = Port name int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation - AstNode* exprp() const { return op1p(); } // op1 = Expression connected to port }; class AstPragma final : public AstNode { -private: const VPragmaType m_pragType; // Type of pragma public: // Pragmas don't result in any output code, they're just flags that affect @@ -1684,42 +1592,43 @@ class AstPropClocked final : public AstNode { // A clocked property // Parents: ASSERT|COVER (property) // Children: SENITEM, Properties + // @astgen op1 := sensesp : Optional[AstSenItem] + // @astgen op2 := disablep : Optional[AstNode] + // @astgen op3 := propp : AstNode public: AstPropClocked(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp) : ASTGEN_SUPER_PropClocked(fl) { - addNOp1p((AstNode*)sensesp); - addNOp2p(disablep); - addOp3p(propp); + this->sensesp(sensesp); + this->disablep(disablep); + this->propp(propp); } ASTGEN_MEMBERS_PropClocked; bool hasDType() const override { return true; } // Used under Cover, which expects a bool child - AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } // op1 = Sensitivity list - AstNode* disablep() const { return op2p(); } // op2 = disable - AstNode* propp() const { return op3p(); } // op3 = property }; class AstPull final : public AstNode { -private: - bool m_direction; + // @astgen op1 := lhsp : AstNode + + const bool m_direction; public: AstPull(FileLine* fl, AstNode* lhsp, bool direction) : ASTGEN_SUPER_Pull(fl) , m_direction{direction} { - setOp1p(lhsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_Pull; bool same(const AstNode* samep) const override { return direction() == static_cast(samep)->direction(); } - void lhsp(AstNode* np) { setOp1p(np); } - AstNode* lhsp() const { return op1p(); } // op1 = Assign to uint32_t direction() const { return (uint32_t)m_direction; } }; class AstSFormatF final : public AstNode { // Convert format to string, generally under an AstDisplay or AstSFormat // Also used as "real" function for /*verilator sformat*/ functions + // @astgen op1 := exprsp : List[AstNode] + // @astgen op2 := scopeNamep : Optional[AstScopeName] string m_text; const bool m_hidden; // Under display, etc bool m_hasFormat; // Has format code @@ -1735,8 +1644,7 @@ public: , m_hasFormat{true} , m_missingArgChar{missingArgChar} { dtypeSetString(); - addNOp1p(exprsp); - addNOp2p(nullptr); + addExprsp(exprsp); } AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd', bool hidden = true) @@ -1746,8 +1654,7 @@ public: , m_hasFormat{false} , m_missingArgChar{missingArgChar} { dtypeSetString(); - addNOp1p(exprsp); - addNOp2p(nullptr); + addExprsp(exprsp); } ASTGEN_MEMBERS_SFormatF; string name() const override { return m_text; } @@ -1757,12 +1664,8 @@ public: return text() == static_cast(samep)->text(); } string verilogKwd() const override { return "$sformatf"; } - void addExprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display void text(const string& text) { m_text = text; } - AstScopeName* scopeNamep() const { return VN_AS(op2p(), ScopeName); } - void scopeNamep(AstNode* nodep) { setNOp2p(nodep); } bool formatScopeTracking() const { // Track scopeNamep(); Ok if false positive return (name().find("%m") != string::npos || name().find("%M") != string::npos); } @@ -1777,7 +1680,10 @@ class AstScope final : public AstNode { // A particular usage of a cell // Parents: MODULE // Children: NODEBLOCK -private: + // @astgen op1 := varsp : List[AstVarScope] + // @astgen op2 := blocksp : List[AstNode] // Logic blocks/AstActive/AstCFunc + // @astgen op3 := finalClksp : List[AstNode] + // An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope string m_name; // Name AstScope* const m_aboveScopep; // Scope above this one in the hierarchy (nullptr if top) @@ -1801,12 +1707,6 @@ public: string nameDotless() const; string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); } AstNodeModule* modp() const { return m_modp; } - void addVarp(AstVarScope* nodep) { addOp1p((AstNode*)nodep); } - AstVarScope* varsp() const { return VN_AS(op1p(), VarScope); } // op1 = AstVarScope's - void addActivep(AstNode* nodep) { addOp2p(nodep); } - AstNode* blocksp() const { return op2p(); } // op2 = Block names - void addFinalClkp(AstNode* nodep) { addOp3p(nodep); } - AstNode* finalClksp() const { return op3p(); } // op3 = Final assigns for clock correction AstScope* aboveScopep() const { return m_aboveScopep; } AstCell* aboveCellp() const { return m_aboveCellp; } bool isTop() const { return aboveScopep() == nullptr; } // At top of hierarchy @@ -1814,23 +1714,21 @@ public: class AstSelLoopVars final : public AstNode { // Parser only concept "[id, id, id]" for a foreach statement // Unlike normal selects elements is a list + // @astgen op1 := fromp : AstNode + // @astgen op2 := elementsp : List[AstNode] public: AstSelLoopVars(FileLine* fl, AstNode* fromp, AstNode* elementsp) : ASTGEN_SUPER_SelLoopVars(fl) { - setOp1p(fromp); - addNOp2p(elementsp); + this->fromp(fromp); + this->addElementsp(elementsp); } ASTGEN_MEMBERS_SelLoopVars; bool same(const AstNode* /*samep*/) const override { return true; } bool maybePointedTo() const override { return false; } - AstNode* fromp() const { return op1p(); } - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstNode* elementsp() const { return op2p(); } }; class AstSenItem final : public AstNode { // Parents: SENTREE - // Children: (optional) VARREF -private: + // @astgen op1 := sensp : AstNode // Sensitivity expression VEdgeType m_edgeType; // Edge type public: class Combo {}; // for creator type-overload selection @@ -1838,10 +1736,10 @@ public: class Initial {}; // for creator type-overload selection class Settle {}; // for creator type-overload selection class Never {}; // for creator type-overload selection - AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* varrefp) + AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* senp) : ASTGEN_SUPER_SenItem(fl) , m_edgeType{edgeType} { - setOp1p(varrefp); + this->sensp(senp); } AstSenItem(FileLine* fl, Combo) : ASTGEN_SUPER_SenItem(fl) @@ -1867,11 +1765,8 @@ public: void edgeType(VEdgeType type) { m_edgeType = type; editCountInc(); - } // * = Posedge/negedge - AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized - AstNodeVarRef* varrefp() const { - return VN_CAST(op1p(), NodeVarRef); - } // op1 = Signal sensitized + } + AstNodeVarRef* varrefp() const { return VN_CAST(sensp(), NodeVarRef); } // bool isClocked() const { return edgeType().clockedStmt(); } bool isCombo() const { return edgeType() == VEdgeType::ET_COMBO; } @@ -1882,23 +1777,18 @@ public: bool hasVar() const { return !(isCombo() || isInitial() || isSettle() || isNever()); } }; class AstSenTree final : public AstNode { - // A list of senitems - // Parents: MODULE | SBLOCK - // Children: SENITEM list -private: + // A sensitivity list + // @astgen op1 := sensesp : List[AstSenItem] bool m_multi = false; // Created from combo logic by ORing multiple clock domains public: AstSenTree(FileLine* fl, AstSenItem* sensesp) : ASTGEN_SUPER_SenTree(fl) { - addNOp1p(sensesp); + this->addSensesp(sensesp); } ASTGEN_MEMBERS_SenTree; void dump(std::ostream& str) const override; bool maybePointedTo() const override { return true; } bool isMulti() const { return m_multi; } - // op1 = Sensitivity list - AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); } - void addSensesp(AstSenItem* nodep) { addOp1p(nodep); } void multi(bool flag) { m_multi = true; } // METHODS bool hasClocked() const; // Includes a clocked statement @@ -1930,26 +1820,26 @@ public: void dump(std::ostream& str) const override; }; class AstTopScope final : public AstNode { - // A singleton, held under the top level AstModule. Holds the top level AstScope, - // and after V3ActiveTop, the global list of AstSenTrees (list of unique sensitivity lists). - // Parent: Top level AstModule - // Children: AstSenTree, AstScope + // A singleton, held under the top level AstModule. Holds the top level + // AstScope, and after V3ActiveTop, the global list of AstSenTrees (list of + // unique sensitivity lists). + // + // @astgen op1 := senTreesp : List[AstSenTree] // Globally unique sensitivity lists + // @astgen op2 := scopep : AstScope // The AstScope of the top-leveL + friend class AstNetlist; // Only the AstNetlist can create one AstTopScope(FileLine* fl, AstScope* ascopep) : ASTGEN_SUPER_TopScope(fl) { - addOp2p(ascopep); + this->scopep(ascopep); } public: ASTGEN_MEMBERS_TopScope; bool maybePointedTo() const override { return true; } - AstSenTree* senTreesp() const { return VN_AS(op1p(), SenTree); } - void addSenTreep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); } - AstScope* scopep() const { return VN_AS(op2p(), Scope); } }; class AstTypeTable final : public AstNode { // Container for hash of standard data types - // Children: NODEDTYPEs + // @astgen op1 := typesp : List[AstNodeDType] AstEmptyQueueDType* m_emptyQueuep = nullptr; AstQueueDType* m_queueIndexp = nullptr; AstVoidDType* m_voidp = nullptr; @@ -1969,8 +1859,6 @@ public: return nullptr; } void cloneRelink() override { V3ERROR_NA; } - AstNodeDType* typesp() const { return VN_AS(op1p(), NodeDType); } // op1 = List of dtypes - void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); } AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd); AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width, int widthMin, VSigning numeric); @@ -1985,7 +1873,9 @@ public: void dump(std::ostream& str = std::cout) const override; }; class AstTypedef final : public AstNode { -private: + // @astgen op1 := childDTypep : Optional[AstNodeDType] + // @astgen op4 := attrsp : List[AstNode] // Attributes during early parse + string m_name; bool m_attrPublic = false; string m_tag; // Holds the string of the verilator tag -- used in XML output. @@ -2001,12 +1891,7 @@ public: ASTGEN_MEMBERS_Typedef; void dump(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Type assigning to - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } - AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse // METHODS string name() const override { return m_name; } bool maybePointedTo() const override { return true; } @@ -2032,14 +1917,13 @@ public: bool maybePointedTo() const override { return true; } }; class AstUdpTable final : public AstNode { + // @astgen op1 := linesp : List[AstUdpTableLine] public: - AstUdpTable(FileLine* fl, AstNode* bodysp) + AstUdpTable(FileLine* fl, AstUdpTableLine* linesp) : ASTGEN_SUPER_UdpTable(fl) { - addNOp1p(bodysp); + this->addLinesp(linesp); } ASTGEN_MEMBERS_UdpTable; - // op1 = List of UdpTableLines - AstUdpTableLine* bodysp() const { return VN_AS(op1p(), UdpTableLine); } }; class AstUdpTableLine final : public AstNode { string m_text; @@ -2054,24 +1938,29 @@ public: }; class AstUnlinkedRef final : public AstNode { // As-of-yet unlinkable Ref -private: - string m_name; // Var name + // @astgen op1 := refp : AstNode + // @astgen op2 := cellrefp : AstNode + + string m_name; // Var name // TODO: There is no way to access this, fix or remove public: - AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* crp) + AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* cellrefp) : ASTGEN_SUPER_UnlinkedRef(fl) , m_name{name} { - addNOp1p(refp); - addNOp2p(crp); + this->refp(refp); + this->cellrefp(cellrefp); } ASTGEN_MEMBERS_UnlinkedRef; - // ACCESSORS - string name() const override { return m_name; } // * = Var name - AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef - AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef }; class AstVar final : public AstNode { // A variable (in/out/wire/reg/param) inside a module -private: + // + // @astgen op1 := childDTypep : Optional[AstNodeDType] + // @astgen op2 := delayp : Optional[AstNode] // Net delay + // Initial value that never changes (static const), or constructor argument for + // MTASKSTATE variables + // @astgen op3 := valuep : Optional[AstNode] + // @astgen op4 := attrsp : List[AstNode] // Attributes during early parse + string m_name; // Name of variable string m_origName; // Original name before dot addition string m_tag; // Holds the string of the verilator tag -- used in XML output. @@ -2262,23 +2151,10 @@ public: string vlPropDecl(const string& propName) const; // Return VerilatorVarProps declaration void combineType(VVarType type); AstNodeDType* getChildDTypep() const override { return childDTypep(); } - // op1 = Range of variable - AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); } - // op2 = Net delay - AstNode* delayp() const { return op2p(); } - void delayp(AstNode* const nodep) { setNOp2p(nodep); } AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) AstBasicDType* basicp() const { return subDTypep()->basicp(); } - // op3 = Initial value that never changes (static const), or constructor argument for - // MTASKSTATE variables - AstNode* valuep() const { return op3p(); } - // It's valuep(), not constp(), as may be more complicated than an AstConst - void valuep(AstNode* nodep) { setOp3p(nodep); } - void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } - AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse - void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } void ansi(bool flag) { m_ansi = flag; } void declTyped(bool flag) { m_declTyped = flag; } @@ -2490,8 +2366,8 @@ public: class AstBegin final : public AstNodeBlock { // A Begin/end named block, only exists shortly after parsing until linking // Parents: statement - // Children: statements -private: + // @astgen op2 := genforp : Optional[AstNode] + bool m_generate; // Underneath a generate const bool m_implied; // Not inserted by user public: @@ -2503,10 +2379,6 @@ public: , m_implied{implied} {} ASTGEN_MEMBERS_Begin; void dump(std::ostream& str) const override; - // op1p is statements in NodeBlock - AstNode* genforp() const { return op2p(); } // op2 = GENFOR, if applicable, - // might NOT be a GenFor, as loop unrolling replaces with Begin - void addGenforp(AstGenFor* nodep) { addOp2p((AstNode*)nodep); } void generate(bool flag) { m_generate = flag; } bool generate() const { return m_generate; } bool implied() const { return m_implied; } @@ -2531,9 +2403,9 @@ public: class AstFunc final : public AstNodeFTask { // A function inside a module public: - AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp) + AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarp) : ASTGEN_SUPER_Func(fl, name, stmtp) { - addNOp1p(fvarsp); + this->fvarp(fvarp); } ASTGEN_MEMBERS_Func; bool hasDType() const override { return true; } @@ -2581,6 +2453,7 @@ public: // === AstNodeModule === class AstClass final : public AstNodeModule { + // @astgen op4 := extendsp : Optional[AstClassExtends] // TYPES using MemberNameMap = std::map; // MEMBERS @@ -2600,16 +2473,13 @@ public: const char* broken() const override; void cloneRelink() override; bool timescaleMatters() const override { return false; } - // op1/op2/op3 in AstNodeModule AstClassPackage* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; } - AstNode* membersp() const { return stmtsp(); } // op2 = List of statements + AstNode* membersp() const { return stmtsp(); } void addMembersp(AstNode* nodep) { insertCache(nodep); - addStmtp(nodep); + addStmtsp(nodep); } - AstClassExtends* extendsp() const { return VN_AS(op4p(), ClassExtends); } - void extendsp(AstNode* nodep) { addNOp4p(nodep); } void clearCache() { m_members.clear(); } void repairCache(); AstNode* findMember(const string& name) const { @@ -2737,27 +2607,27 @@ public: // === AstNodeProcedure === class AstAlways final : public AstNodeProcedure { + // @astgen op1 := sensesp : Optional[AstSenTree] // Sensitivity list iff clocked const VAlwaysKwd m_keyword; public: - AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp) - : ASTGEN_SUPER_Always(fl, bodysp) + AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* stmtsp) + : ASTGEN_SUPER_Always(fl, stmtsp) , m_keyword{keyword} { - addNOp1p(sensesp); + this->sensesp(sensesp); } ASTGEN_MEMBERS_Always; // void dump(std::ostream& str) const override; - AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list - void sensesp(AstSenTree* nodep) { setOp1p(nodep); } VAlwaysKwd keyword() const { return m_keyword; } }; class AstAlwaysPost final : public AstNodeProcedure { // Like always but post assignments for memory assignment IFs + // @astgen op1 := sensesp : Optional[AstSenTree] // Sensitivity list iff clocked public: - AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) - : ASTGEN_SUPER_AlwaysPost(fl, bodysp) { - addNOp1p(sensesp); + AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) + : ASTGEN_SUPER_AlwaysPost(fl, stmtsp) { + this->sensesp(sensesp); } ASTGEN_MEMBERS_AlwaysPost; }; @@ -2765,36 +2635,36 @@ class AstAlwaysPostponed final : public AstNodeProcedure { // Like always but postponement scheduling region public: - AstAlwaysPostponed(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_AlwaysPostponed(fl, bodysp) {} + AstAlwaysPostponed(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_AlwaysPostponed(fl, stmtsp) {} ASTGEN_MEMBERS_AlwaysPostponed; }; class AstFinal final : public AstNodeProcedure { public: - AstFinal(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_Final(fl, bodysp) {} + AstFinal(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_Final(fl, stmtsp) {} ASTGEN_MEMBERS_Final; }; class AstInitial final : public AstNodeProcedure { public: - AstInitial(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_Initial(fl, bodysp) {} + AstInitial(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_Initial(fl, stmtsp) {} ASTGEN_MEMBERS_Initial; }; class AstInitialAutomatic final : public AstNodeProcedure { // Automatic variable initialization // That is, it runs every function start, or class construction public: - AstInitialAutomatic(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_InitialAutomatic(fl, bodysp) {} + AstInitialAutomatic(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_InitialAutomatic(fl, stmtsp) {} ASTGEN_MEMBERS_InitialAutomatic; }; class AstInitialStatic final : public AstNodeProcedure { // Static variable initialization // That is, it runs at the beginning of simulation, before 'initial' blocks public: - AstInitialStatic(FileLine* fl, AstNode* bodysp) - : ASTGEN_SUPER_InitialStatic(fl, bodysp) {} + AstInitialStatic(FileLine* fl, AstNode* stmtsp) + : ASTGEN_SUPER_InitialStatic(fl, stmtsp) {} ASTGEN_MEMBERS_InitialStatic; }; @@ -2802,10 +2672,11 @@ public: class AstBracketRange final : public AstNodeRange { // Parser only concept "[lhsp]", a AstUnknownRange, QueueRange or Range, // unknown until lhsp type is determined + // @astgen op1 := elementsp : AstNode public: AstBracketRange(FileLine* fl, AstNode* elementsp) : ASTGEN_SUPER_BracketRange(fl) { - setOp1p(elementsp); + this->elementsp(elementsp); } ASTGEN_MEMBERS_BracketRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } @@ -2814,21 +2685,20 @@ public: // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node bool maybePointedTo() const override { return false; } - AstNode* elementsp() const { return op1p(); } }; class AstRange final : public AstNodeRange { // Range specification, for use under variables and cells + // @astgen op1 := leftp : AstNode + // @astgen op2 := rightp : AstNode public: AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp) : ASTGEN_SUPER_Range(fl) { - setOp2p(leftp); - setOp3p(rightp); + this->leftp(leftp); + this->rightp(rightp); } inline AstRange(FileLine* fl, int left, int right); inline AstRange(FileLine* fl, const VNumRange& range); ASTGEN_MEMBERS_Range; - AstNode* leftp() const { return op2p(); } - AstNode* rightp() const { return op3p(); } inline int leftConst() const; inline int rightConst() const; int hiConst() const { @@ -2872,21 +2742,19 @@ public: class AstAlwaysPublic final : public AstNodeStmt { // "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/ // Body statements are just AstVarRefs to the public signals + // @astgen op1 := sensesp : List[AstSenTree] + // @astgen op2 := stmtsp : List[AstNode] public: - AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp) + AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) : ASTGEN_SUPER_AlwaysPublic(fl) { - addNOp1p(sensesp); - addNOp2p(bodysp); + addSensesp(sensesp); + addStmtsp(stmtsp); } ASTGEN_MEMBERS_AlwaysPublic; bool same(const AstNode* /*samep*/) const override { return true; } - // - AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } // op1 = Sensitivity list - AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate - void addStmtp(AstNode* nodep) { addOp2p(nodep); } // Special accessors - bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } + bool isJustOneBodyStmt() const { return stmtsp() && !stmtsp()->nextp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstBreak final : public AstNodeStmt { public: @@ -2902,6 +2770,8 @@ class AstCMethodHard final : public AstNodeStmt { // A reference to a "C" hardcoded member task (or function) // PARENTS: stmt/math // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. + // @astgen op1 := fromp : AstNode // Subject of method call + // @astgen op2 := pinsp : List[AstNode] // Arguments private: string m_name; // Name of method bool m_pure = false; // Pure optimizable @@ -2910,15 +2780,16 @@ public: AstNode* pinsp = nullptr) : ASTGEN_SUPER_CMethodHard(fl, false) , m_name{name} { - setOp1p(fromp); + // TODO: this constructor is exactly the same as the other, bar the ignored tag argument + this->fromp(fromp); + this->addPinsp(pinsp); dtypep(nullptr); // V3Width will resolve - addNOp2p(pinsp); } AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp = nullptr) : ASTGEN_SUPER_CMethodHard(fl, false) , m_name{name} { - setOp1p(fromp); - addNOp2p(pinsp); + this->fromp(fromp); + this->addPinsp(pinsp); } ASTGEN_MEMBERS_CMethodHard; string name() const override { return m_name; } // * = Var name @@ -2934,68 +2805,58 @@ public: statement(true); dtypeSetVoid(); } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } - AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list - void addPinsp(AstNode* nodep) { addOp2p(nodep); } }; class AstCReset final : public AstNodeStmt { // Reset variable at startup + // @astgen op1 := varrefp : AstVarRef public: - AstCReset(FileLine* fl, AstVarRef* exprsp) + AstCReset(FileLine* fl, AstVarRef* varrefp) : ASTGEN_SUPER_CReset(fl) { - addNOp1p((AstNode*)exprsp); + this->varrefp(varrefp); } ASTGEN_MEMBERS_CReset; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool same(const AstNode* /*samep*/) const override { return true; } - AstVarRef* varrefp() const { return VN_AS(op1p(), VarRef); } // op1 = varref to reset }; class AstCReturn final : public AstNodeStmt { // C++ return from a function - // Parents: CFUNC/statement - // Children: Math + // @astgen op1 := lhsp : AstNode public: AstCReturn(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_CReturn(fl) { - setOp1p(lhsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_CReturn; int instrCount() const override { return widthInstrs(); } bool same(const AstNode* /*samep*/) const override { return true; } - // - AstNode* lhsp() const { return op1p(); } }; class AstCStmt final : public AstNodeStmt { // Emit C statement + // @astgen op1 := exprsp : List[AstNode] public: AstCStmt(FileLine* fl, AstNode* exprsp) : ASTGEN_SUPER_CStmt(fl) { - addNOp1p(exprsp); + this->addExprsp(exprsp); } inline AstCStmt(FileLine* fl, const string& textStmt); ASTGEN_MEMBERS_CStmt; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool same(const AstNode* /*samep*/) const override { return true; } - void addBodysp(AstNode* nodep) { addNOp1p(nodep); } - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print }; class AstChangeDet final : public AstNodeStmt { // A comparison to determine change detection, common & must be fast. + // @astgen op1 := lhsp : Optional[AstNode] + // @astgen op2 := rhsp : Optional[AstNode] public: // Null lhs+rhs used to indicate change needed with no spec vars AstChangeDet(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_ChangeDet(fl) { - setNOp1p(lhsp); - setNOp2p(rhsp); + this->lhsp(lhsp); + this->rhsp(rhsp); } ASTGEN_MEMBERS_ChangeDet; - AstNode* lhsp() const { return op1p(); } - AstNode* rhsp() const { return op2p(); } bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } int instrCount() const override { return widthInstrs() * 2; } // xor, or/logor @@ -3004,8 +2865,6 @@ public: class AstComment final : public AstNodeStmt { // Some comment to put into the output stream // Parents: {statement list} - // Children: none -private: const bool m_showAt; // Show "at " const string m_name; // Text of comment public: @@ -3116,13 +2975,15 @@ public: class AstCoverToggle final : public AstNodeStmt { // Toggle analysis of given signal // Parents: MODULE - // Children: AstCoverInc, orig var, change det var + // @astgen op1 := incp : AstCoverInc + // @astgen op2 := origp : AstNode + // @astgen op3 := changep : AstNode public: AstCoverToggle(FileLine* fl, AstCoverInc* incp, AstNode* origp, AstNode* changep) : ASTGEN_SUPER_CoverToggle(fl) { - setOp1p(incp); - setOp2p(origp); - setOp3p(changep); + this->incp(incp); + this->origp(origp); + this->changep(changep); } ASTGEN_MEMBERS_CoverToggle; int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } @@ -3133,26 +2994,19 @@ public: return false; // Though the AstCoverInc under this is an outputter } // but isPure() true - AstCoverInc* incp() const { return VN_AS(op1p(), CoverInc); } - void incp(AstCoverInc* nodep) { setOp1p(nodep); } - AstNode* origp() const { return op2p(); } - AstNode* changep() const { return op3p(); } }; class AstDelay final : public AstNodeStmt { // Delay statement + // @astgen op1 := lhsp : AstNode // Delay value + // @astgen op2 := stmtsp : List[AstNode] // Statements under delay public: AstDelay(FileLine* fl, AstNode* lhsp, AstNode* stmtsp) : ASTGEN_SUPER_Delay(fl) { - setOp1p(lhsp); - setNOp2p(stmtsp); + this->lhsp(lhsp); + this->addStmtsp(stmtsp); } ASTGEN_MEMBERS_Delay; bool same(const AstNode* /*samep*/) const override { return true; } - // - AstNode* lhsp() const { return op1p(); } // op1 = delay value - void lhsp(AstNode* nodep) { setOp1p(nodep); } - void stmtsp(AstNode* nodep) { setOp2p(nodep); } // op2 = statements under delay - AstNode* stmtsp() const { return op2p(); } }; class AstDisable final : public AstNodeStmt { private: @@ -3177,8 +3031,8 @@ public: }; class AstDisplay final : public AstNodeStmt { // Parents: stmtlist - // Children: file which must be a varref - // Children: SFORMATF to generate print string + // @astgen op1 := fmtp : AstSFormatF + // @astgen op2 := filep : Optional[AstNode] // file (must be a VarRef) private: VDisplayType m_displayType; @@ -3187,15 +3041,15 @@ public: AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER_Display(fl) , m_displayType{dispType} { - setOp1p(new AstSFormatF{fl, text, true, exprsp, missingArgChar}); - setNOp3p(filep); + this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar}); + this->filep(filep); } AstDisplay(FileLine* fl, VDisplayType dispType, AstNode* filep, AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER_Display(fl) , m_displayType{dispType} { - setOp1p(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp, missingArgChar}); - setNOp3p(filep); + this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp, missingArgChar}); + this->filep(filep); } ASTGEN_MEMBERS_Display; void dump(std::ostream& str) const override; @@ -3220,10 +3074,6 @@ public: void displayType(VDisplayType type) { m_displayType = type; } // * = Add a newline for $display bool addNewline() const { return displayType().addNewline(); } - void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } - AstNode* filep() const { return op3p(); } - void filep(AstNodeVarRef* nodep) { setNOp3p((AstNode*)nodep); } }; class AstDpiExportUpdated final : public AstNodeStmt { // Denotes that the referenced variable may have been updated via a DPI Export @@ -3235,13 +3085,13 @@ public: class AstDumpCtl final : public AstNodeStmt { // $dumpon etc // Parents: expr - // Child: expr based on type of control statement + // @astgen op1 := exprp : Optional[AstNode] // Expression based on type of control statement const VDumpCtlType m_ctlType; // Type of operation public: AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = nullptr) : ASTGEN_SUPER_DumpCtl(fl) , m_ctlType{ctlType} { - setNOp1p(exprp); + this->exprp(exprp); } ASTGEN_MEMBERS_DumpCtl; string verilogKwd() const override { return ctlType().ascii(); } @@ -3251,16 +3101,16 @@ public: virtual bool cleanOut() const { return true; } bool same(const AstNode* /*samep*/) const override { return true; } VDumpCtlType ctlType() const { return m_ctlType; } - AstNode* exprp() const { return op1p(); } // op2 = Expressions to output - void exprp(AstNode* nodep) { setOp1p(nodep); } }; class AstEventControl final : public AstNodeStmt { // Parents: stmtlist + // @astgen op1 := sensesp : Optional[AstSenTree] + // @astgen op2 := stmtsp : List[AstNode] public: AstEventControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp) : ASTGEN_SUPER_EventControl(fl) { - setNOp1p(sensesp); - setNOp2p(stmtsp); + this->sensesp(sensesp); + this->addStmtsp(stmtsp); } ASTGEN_MEMBERS_EventControl; string verilogKwd() const override { return "@(%l) %r"; } @@ -3269,16 +3119,14 @@ public: bool isPure() const override { return false; } bool isOutputter() const override { return false; } int instrCount() const override { return 0; } - AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); } - AstNode* stmtsp() const { return op2p(); } }; class AstFClose final : public AstNodeStmt { // Parents: stmtlist - // Children: file which must be a varref + // @astgen op1 := filep : AstNode // file (must be a VarRef) public: AstFClose(FileLine* fl, AstNode* filep) : ASTGEN_SUPER_FClose(fl) { - setNOp2p(filep); + this->filep(filep); } ASTGEN_MEMBERS_FClose; string verilogKwd() const override { return "$fclose"; } @@ -3288,16 +3136,14 @@ public: bool isOutputter() const override { return true; } bool isUnlikely() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; class AstFFlush final : public AstNodeStmt { // Parents: stmtlist - // Children: file which must be a varref + // @astgen op1 := filep : Optional[AstNode] // file (must be a VarRef) public: AstFFlush(FileLine* fl, AstNode* filep) : ASTGEN_SUPER_FFlush(fl) { - setNOp2p(filep); + this->filep(filep); } ASTGEN_MEMBERS_FFlush; string verilogKwd() const override { return "$fflush"; } @@ -3307,17 +3153,18 @@ public: bool isOutputter() const override { return true; } bool isUnlikely() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op2p(); } - void filep(AstNodeVarRef* nodep) { setNOp2p((AstNode*)nodep); } }; class AstFOpen final : public AstNodeStmt { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) + // @astgen op1 := filep : AstNode + // @astgen op2 := filenamep : AstNode + // @astgen op3 := modep : AstNode public: AstFOpen(FileLine* fl, AstNode* filep, AstNode* filenamep, AstNode* modep) : ASTGEN_SUPER_FOpen(fl) { - setOp1p(filep); - setOp2p(filenamep); - setOp3p(modep); + this->filep(filep); + this->filenamep(filenamep); + this->modep(modep); } ASTGEN_MEMBERS_FOpen; string verilogKwd() const override { return "$fopen"; } @@ -3327,17 +3174,16 @@ public: bool isOutputter() const override { return true; } bool isUnlikely() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op1p(); } - AstNode* filenamep() const { return op2p(); } - AstNode* modep() const { return op3p(); } }; class AstFOpenMcd final : public AstNodeStmt { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) + // @astgen op1 := filep : AstNode + // @astgen op2 := filenamep : AstNode public: AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep) : ASTGEN_SUPER_FOpenMcd(fl) { - setOp1p(filep); - setOp2p(filenamep); + this->filep(filep); + this->filenamep(filenamep); } ASTGEN_MEMBERS_FOpenMcd; string verilogKwd() const override { return "$fopen"; } @@ -3347,8 +3193,6 @@ public: bool isOutputter() const override { return true; } bool isUnlikely() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* filep() const { return op1p(); } - AstNode* filenamep() const { return op2p(); } }; class AstFinish final : public AstNodeStmt { public: @@ -3364,24 +3208,26 @@ public: bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } }; class AstForeach final : public AstNodeStmt { + // @astgen op1 := arrayp : AstNode + // @astgen op2 := stmtsp : List[AstNode] public: - AstForeach(FileLine* fl, AstNode* arrayp, AstNode* bodysp) + AstForeach(FileLine* fl, AstNode* arrayp, AstNode* stmtsp) : ASTGEN_SUPER_Foreach(fl) { - setOp1p(arrayp); - addNOp4p(bodysp); + this->arrayp(arrayp); + this->addStmtsp(stmtsp); } ASTGEN_MEMBERS_Foreach; - AstNode* arrayp() const { return op1p(); } // op1 = array and index vars - AstNode* bodysp() const { return op4p(); } // op4 = body of loop bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } bool same(const AstNode* /*samep*/) const override { return true; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstJumpBlock final : public AstNodeStmt { // Block of code including a JumpGo and JumpLabel // Parents: {statement list} // Children: {statement list, with JumpGo and JumpLabel below} + // @astgen op1 := stmtsp : List[AstNode] + // @astgen op2 := endStmtsp : List[AstNode] private: AstJumpLabel* m_labelp = nullptr; // [After V3Jump] Pointer to declaration int m_labelNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment @@ -3389,7 +3235,7 @@ public: // After construction must call ->labelp to associate with appropriate label AstJumpBlock(FileLine* fl, AstNode* stmtsp) : ASTGEN_SUPER_JumpBlock(fl) { - addNOp1p(stmtsp); + this->addStmtsp(stmtsp); } const char* broken() const override; void cloneRelink() override; @@ -3397,11 +3243,6 @@ public: int instrCount() const override { return 0; } bool maybePointedTo() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - // op1 = Statements - AstNode* stmtsp() const { return op1p(); } // op1 = List of statements - void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } - AstNode* endStmtsp() const { return op2p(); } // op1 = List of end-of-block - void addEndStmtsp(AstNode* nodep) { addNOp2p(nodep); } int labelNum() const { return m_labelNum; } void labelNum(int flag) { m_labelNum = flag; } AstJumpLabel* labelp() const { return m_labelp; } @@ -3500,57 +3341,57 @@ public: }; class AstRelease final : public AstNodeStmt { // Procedural 'release' statement + // @astgen op1 := lhsp : AstNode public: AstRelease(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_Release(fl) { - setOp1p(lhsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_Release; - AstNode* lhsp() const { return op1p(); } }; class AstRepeat final : public AstNodeStmt { + // @astgen op1 := countp : AstNode + // @astgen op2 := stmtsp : List[AstNode] public: - AstRepeat(FileLine* fl, AstNode* countp, AstNode* bodysp) + AstRepeat(FileLine* fl, AstNode* countp, AstNode* stmtsp) : ASTGEN_SUPER_Repeat(fl) { - setOp2p(countp); - addNOp3p(bodysp); + this->countp(countp); + this->addStmtsp(stmtsp); } ASTGEN_MEMBERS_Repeat; - AstNode* countp() const { return op2p(); } // op2 = condition to continue - AstNode* bodysp() const { return op3p(); } // op3 = body of loop bool isGateOptimizable() const override { return false; } // Not relevant - converted to FOR int instrCount() const override { return INSTR_COUNT_BRANCH; } bool same(const AstNode* /*samep*/) const override { return true; } - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstReturn final : public AstNodeStmt { + // @astgen op1 := lhsp : Optional[AstNode] public: explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr) : ASTGEN_SUPER_Return(fl) { - setNOp1p(lhsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_Return; string verilogKwd() const override { return "return"; } - AstNode* lhsp() const { return op1p(); } bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; class AstSFormat final : public AstNodeStmt { // Parents: statement container - // Children: string to load - // Children: SFORMATF to generate print string + // @astgen op1 := fmtp : AstSFormatF + // @astgen op2 := lhsp : AstNode public: AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER_SFormat(fl) { - setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); - setOp3p(lhsp); + this->fmtp(new AstSFormatF{fl, text, true, exprsp, missingArgChar}); + this->lhsp(lhsp); } AstSFormat(FileLine* fl, AstNode* lhsp, AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER_SFormat(fl) { - setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); - setOp3p(lhsp); + this->fmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp, missingArgChar}); + this->lhsp(lhsp); } ASTGEN_MEMBERS_SFormat; const char* broken() const override { @@ -3565,10 +3406,6 @@ public: virtual bool cleanOut() const { return false; } int instrCount() const override { return INSTR_COUNT_PLI; } bool same(const AstNode* /*samep*/) const override { return true; } - void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter - AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); } - AstNode* lhsp() const { return op3p(); } - void lhsp(AstNode* nodep) { setOp3p(nodep); } }; class AstStop final : public AstNodeStmt { public: @@ -3585,12 +3422,11 @@ public: }; class AstSysFuncAsTask final : public AstNodeStmt { // Call what is normally a system function (with a return) in a non-return context - // Parents: stmtlist - // Children: a system function + // @astgen op1 := lhsp : AstNode public: - AstSysFuncAsTask(FileLine* fl, AstNode* exprsp) + AstSysFuncAsTask(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SysFuncAsTask(fl) { - addNOp1p(exprsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_SysFuncAsTask; string verilogKwd() const override { return ""; } @@ -3600,16 +3436,13 @@ public: bool isOutputter() const override { return false; } int instrCount() const override { return 0; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval - void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval }; class AstSysIgnore final : public AstNodeStmt { - // Parents: stmtlist - // Children: varrefs or exprs + // @astgen op1 := exprsp : List[AstNode] // Expressions to output (???) public: AstSysIgnore(FileLine* fl, AstNode* exprsp) : ASTGEN_SUPER_SysIgnore(fl) { - addNOp1p(exprsp); + this->addExprsp(exprsp); } ASTGEN_MEMBERS_SysIgnore; string verilogKwd() const override { return "$ignored"; } @@ -3618,15 +3451,14 @@ public: bool isPure() const override { return false; } // Though deleted before opt bool isOutputter() const override { return true; } // Though deleted before opt int instrCount() const override { return INSTR_COUNT_PLI; } - AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output - void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output }; class AstSystemT final : public AstNodeStmt { // $system used as task + // @astgen op1 := lhsp : AstNode public: AstSystemT(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER_SystemT(fl) { - setOp1p(lhsp); + this->lhsp(lhsp); } ASTGEN_MEMBERS_SystemT; string verilogKwd() const override { return "$system"; } @@ -3636,18 +3468,21 @@ public: bool isOutputter() const override { return true; } bool isUnlikely() const override { return true; } bool same(const AstNode* /*samep*/) const override { return true; } - AstNode* lhsp() const { return op1p(); } }; class AstTimeFormat final : public AstNodeStmt { // Parents: stmtlist + // @astgen op1 := unitsp : AstNode + // @astgen op2 := precisionp : AstNode + // @astgen op3 := suffixp : AstNode + // @astgen op4 := widthp : AstNode public: AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp, AstNode* widthp) : ASTGEN_SUPER_TimeFormat(fl) { - setOp1p(unitsp); - setOp2p(precisionp); - setOp3p(suffixp); - setOp4p(widthp); + this->unitsp(unitsp); + this->precisionp(precisionp); + this->suffixp(suffixp); + this->widthp(widthp); } ASTGEN_MEMBERS_TimeFormat; string verilogKwd() const override { return "$timeformat"; } @@ -3656,16 +3491,12 @@ public: bool isPure() const override { return false; } bool isOutputter() const override { return true; } int instrCount() const override { return INSTR_COUNT_PLI; } - AstNode* unitsp() const { return op1p(); } - AstNode* precisionp() const { return op2p(); } - AstNode* suffixp() const { return op3p(); } - AstNode* widthp() const { return op4p(); } }; class AstTraceDecl final : public AstNodeStmt { // Trace point declaration // Separate from AstTraceInc; as a declaration can't be deleted // Parents: {statement list} - // Children: expression being traced + // @astgen op1 := valuep : AstNode // Expressio being traced private: uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines const string m_showname; // Name of variable @@ -3690,7 +3521,7 @@ public: , m_declKwd{varp->declKwd()} , m_declDirection{varp->declDirection()} { dtypeFrom(valuep); - addNOp1p(valuep); + this->valuep(valuep); } void dump(std::ostream& str) const override; int instrCount() const override { return 100; } // Large... @@ -3709,13 +3540,11 @@ public: VVarType varType() const { return m_varType; } VBasicDTypeKwd declKwd() const { return m_declKwd; } VDirection declDirection() const { return m_declDirection; } - AstNode* valuep() const { return op1p(); } }; class AstTraceInc final : public AstNodeStmt { // Trace point dump - // Parents: {statement list} - // Children: op1: things to emit before this node, - // op2: expression being traced (from decl) + // @astgen op1 := precondsp : List[AstNode] // Statements to emit before this node + // @astgen op2 := valuep : AstNode // Expression being traced (from decl) private: AstTraceDecl* m_declp; // Pointer to declaration @@ -3729,7 +3558,8 @@ public: , m_full{full} , m_baseCode{baseCode} { dtypeFrom(declp); - addOp2p(declp->valuep()->cloneTree(true)); + this->valuep( + declp->valuep()->cloneTree(true)); // TODO: maybe use reference to TraceDecl instead? } ASTGEN_MEMBERS_TraceInc; const char* broken() const override { @@ -3749,10 +3579,6 @@ public: bool isPredictOptimizable() const override { return false; } bool isOutputter() const override { return true; } // but isPure() true - // op1 = Statements before the value - AstNode* precondsp() const { return op1p(); } - void addPrecondsp(AstNode* newp) { addOp1p(newp); } - AstNode* valuep() const { return op2p(); } AstTraceDecl* declp() const { return m_declp; } bool full() const { return m_full; } uint32_t baseCode() const { return m_baseCode; } @@ -3779,13 +3605,13 @@ public: }; class AstUCStmt final : public AstNodeStmt { // User $c statement + // @astgen op1 := exprsp : List[AstNode] public: AstUCStmt(FileLine* fl, AstNode* exprsp) : ASTGEN_SUPER_UCStmt(fl) { - addNOp1p(exprsp); + this->addExprsp(exprsp); } ASTGEN_MEMBERS_UCStmt; - AstNode* bodysp() const { return op1p(); } // op1 = expressions to print bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool isPure() const override { return false; } @@ -3793,15 +3619,16 @@ public: bool same(const AstNode* /*samep*/) const override { return true; } }; class AstWait final : public AstNodeStmt { + // @astgen op1 := condp : AstNode + // @astgen op2 := stmtsp : List[AstNode] public: - AstWait(FileLine* fl, AstNode* condp, AstNode* bodysp) + AstWait(FileLine* fl, AstNode* condp, AstNode* stmtsp) : ASTGEN_SUPER_Wait(fl) { - setOp2p(condp); - addNOp3p(bodysp); + this->condp(condp); + this->addStmtsp(stmtsp); } ASTGEN_MEMBERS_Wait; - AstNode* bodysp() const { return op3p(); } // op3 = body of loop - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstWaitFork final : public AstNodeStmt { // A "wait fork" statement @@ -3811,22 +3638,18 @@ public: ASTGEN_MEMBERS_WaitFork; }; class AstWhile final : public AstNodeStmt { + // @astgen op1 := precondsp : List[AstNode] + // @astgen op2 := condp : AstNode + // @astgen op3 := stmtsp : List[AstNode] + // @astgen op4 := incsp : List[AstNode] public: - AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp = nullptr, AstNode* incsp = nullptr) + AstWhile(FileLine* fl, AstNode* condp, AstNode* stmtsp = nullptr, AstNode* incsp = nullptr) : ASTGEN_SUPER_While(fl) { - setOp2p(condp); - addNOp3p(bodysp); - addNOp4p(incsp); + this->condp(condp); + this->addStmtsp(stmtsp); + this->addIncsp(incsp); } ASTGEN_MEMBERS_While; - // op1 = prepare statements for condition (exec every loop) - AstNode* precondsp() const { return op1p(); } - AstNode* condp() const { return op2p(); } // op2 = condition to continue - AstNode* bodysp() const { return op3p(); } // op3 = body of loop - AstNode* incsp() const { return op4p(); } // op4 = increment (if from a FOR loop) - void addPrecondsp(AstNode* newp) { addOp1p(newp); } - void addBodysp(AstNode* newp) { addOp3p(newp); } - void addIncsp(AstNode* newp) { addOp4p(newp); } bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } bool same(const AstNode* /*samep*/) const override { return true; } @@ -3834,7 +3657,7 @@ public: void addBeforeStmt(AstNode* newp, AstNode* belowp) override; // Stop statement searchback here void addNextStmt(AstNode* newp, AstNode* belowp) override; - bool isFirstInMyListOfStatements(AstNode* n) const override { return n == bodysp(); } + bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstWith final : public AstNodeStmt { // Used as argument to method, then to AstCMethodHard @@ -3843,13 +3666,16 @@ class AstWith final : public AstNodeStmt { // Children: LambdaArgRef that declares the item variable // Children: LambdaArgRef that declares the item.index variable // Children: math (equation establishing the with) + // @astgen op1 := indexArgRefp : AstLambdaArgRef + // @astgen op2 := valueArgRefp : AstLambdaArgRef + // @astgen op3 := exprp : AstNode public: AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp, AstNode* exprp) : ASTGEN_SUPER_With(fl) { - addOp1p((AstNode*)indexArgRefp); - addOp2p((AstNode*)valueArgRefp); - addNOp3p(exprp); + this->indexArgRefp(indexArgRefp); + this->valueArgRefp(valueArgRefp); + this->exprp(exprp); } ASTGEN_MEMBERS_With; bool same(const AstNode* /*samep*/) const override { return true; } @@ -3859,28 +3685,23 @@ public: BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype return nullptr; } - // - AstLambdaArgRef* indexArgRefp() const { return VN_AS(op1p(), LambdaArgRef); } - AstLambdaArgRef* valueArgRefp() const { return VN_AS(op2p(), LambdaArgRef); } - AstNode* exprp() const { return op3p(); } }; class AstWithParse final : public AstNodeStmt { // In early parse, FUNC(index) WITH equation-using-index // Replaced with AstWith // Parents: math|stmt // Children: funcref, math + // @astgen op1 := funcrefp : AstNode + // @astgen op2 := exprp : Optional[AstNode] public: AstWithParse(FileLine* fl, bool stmt, AstNode* funcrefp, AstNode* exprp) : ASTGEN_SUPER_WithParse(fl) { statement(stmt); - setOp1p(funcrefp); - addNOp2p(exprp); + this->funcrefp(funcrefp); + this->exprp(exprp); } ASTGEN_MEMBERS_WithParse; bool same(const AstNode* /*samep*/) const override { return true; } - // - AstNode* funcrefp() const { return op1p(); } - AstNode* exprp() const { return op2p(); } }; // === AstNodeAssign === @@ -3966,12 +3787,11 @@ public: }; class AstAssignW final : public AstNodeAssign { // Like assign, but wire/assign's in verilog, the only setting of the specified variable + // @astgen op4 := strengthSpecp : Optional[AstStrengthSpec] public: AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_AssignW(fl, lhsp, rhsp) {} ASTGEN_MEMBERS_AssignW; - AstStrengthSpec* strengthSpecp() const { return VN_AS(op4p(), StrengthSpec); } - void strengthSpecp(AstStrengthSpec* const strengthSpecp) { setOp4p((AstNode*)strengthSpecp); } AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignW(this->fileline(), lhsp, rhsp); } @@ -4006,11 +3826,11 @@ public: class AstCMethodCall final : public AstNodeCCall { // C++ method call // Parents: Anything above a statement - // Children: Args to the function + // @astgen op1 := fromp : AstNode public: AstCMethodCall(FileLine* fl, AstNode* fromp, AstCFunc* funcp, AstNode* argsp = nullptr) : ASTGEN_SUPER_CMethodCall(fl, funcp, argsp) { - setOp1p(fromp); + this->fromp(fromp); } ASTGEN_MEMBERS_CMethodCall; const char* broken() const override { @@ -4018,10 +3838,6 @@ public: BROKEN_RTN(!fromp()); return nullptr; } - AstNode* fromp() const { - return op1p(); - } // op1 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp1p(nodep); } }; class AstCNew final : public AstNodeCCall { // C++ new() call @@ -4040,8 +3856,6 @@ public: class AstCase final : public AstNodeCase { // Case statement // Parents: {statement list} - // exprp Children: MATHs - // casesp Children: CASEITEMs private: VCaseType m_casex; // 0=case, 1=casex, 2=casez bool m_fullPragma = false; // Synthesis full_case @@ -4050,8 +3864,8 @@ private: bool m_unique0Pragma = false; // unique0 case bool m_priorityPragma = false; // priority case public: - AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp) - : ASTGEN_SUPER_Case(fl, exprp, casesp) + AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstCaseItem* itemsp) + : ASTGEN_SUPER_Case(fl, exprp, itemsp) , m_casex{casex} {} ASTGEN_MEMBERS_Case; string verilogKwd() const override { return casez() ? "casez" : casex() ? "casex" : "case"; } @@ -4077,44 +3891,41 @@ public: class AstGenCase final : public AstNodeCase { // Generate Case statement // Parents: {statement list} - // exprp Children: MATHs - // casesp Children: CASEITEMs public: - AstGenCase(FileLine* fl, AstNode* exprp, AstNode* casesp) - : ASTGEN_SUPER_GenCase(fl, exprp, casesp) {} + AstGenCase(FileLine* fl, AstNode* exprp, AstCaseItem* itemsp) + : ASTGEN_SUPER_GenCase(fl, exprp, itemsp) {} ASTGEN_MEMBERS_GenCase; }; // === AstNodeCoverOrAssert === class AstAssert final : public AstNodeCoverOrAssert { + // @astgen op3 := failsp: List[AstNode] // Statments when propp is failing/falsey public: ASTGEN_MEMBERS_Assert; AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, const string& name = "") : ASTGEN_SUPER_Assert(fl, propp, passsp, immediate, name) { - addNOp3p(failsp); + this->addFailsp(failsp); } - AstNode* failsp() const { return op3p(); } // op3 = if assertion fails }; class AstAssertIntrinsic final : public AstNodeCoverOrAssert { // A $cast or other compiler inserted assert, that must run even without --assert option + // @astgen op3 := failsp: List[AstNode] // Statments when propp is failing/falsey public: ASTGEN_MEMBERS_AssertIntrinsic; AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate, const string& name = "") : ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, immediate, name) { - addNOp3p(failsp); + this->addFailsp(failsp); } - AstNode* failsp() const { return op3p(); } // op3 = if assertion fails }; class AstCover final : public AstNodeCoverOrAssert { + // @astgen op3 := coverincsp: List[AstNode] // Coverage node public: ASTGEN_MEMBERS_Cover; AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate, const string& name = "") : ASTGEN_SUPER_Cover(fl, propp, stmtsp, immediate, name) {} - AstNode* coverincp() const { return op3p(); } // op3 = coverage node - void coverincp(AstCoverInc* nodep) { addOp3p(nodep); } // op3 = coverage node virtual bool immediate() const { return false; } }; class AstRestrict final : public AstNodeCoverOrAssert { @@ -4140,16 +3951,18 @@ class AstMethodCall final : public AstNodeFTaskRef { // PARENTS: stmt/math // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it + // @astgen op2 := fromp : AstNode + // public: AstMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, AstNode* pinsp) : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { - setOp2p(fromp); + this->fromp(fromp); dtypep(nullptr); // V3Width will resolve } AstMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) { - setOp2p(fromp); + this->fromp(fromp); } ASTGEN_MEMBERS_MethodCall; const char* broken() const override { @@ -4163,10 +3976,6 @@ public: statement(true); dtypeSetVoid(); } - AstNode* fromp() const { - return op2p(); - } // op2 = Extracting what (nullptr=TBD during parsing) - void fromp(AstNode* nodep) { setOp2p(nodep); } }; class AstNew final : public AstNodeFTaskRef { // New as constructor @@ -4197,16 +4006,16 @@ public: // === AstNodeFor === class AstGenFor final : public AstNodeFor { public: - AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) - : ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, bodysp) {} + AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* stmtsp) + : ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, stmtsp) {} ASTGEN_MEMBERS_GenFor; }; // === AstNodeIf === class AstGenIf final : public AstNodeIf { public: - AstGenIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) - : ASTGEN_SUPER_GenIf(fl, condp, ifsp, elsesp) {} + AstGenIf(FileLine* fl, AstNode* condp, AstNode* thensp, AstNode* elsesp) + : ASTGEN_SUPER_GenIf(fl, condp, thensp, elsesp) {} ASTGEN_MEMBERS_GenIf; }; class AstIf final : public AstNodeIf { @@ -4215,8 +4024,8 @@ private: bool m_unique0Pragma = false; // unique0 case bool m_priorityPragma = false; // priority case public: - AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp = nullptr, AstNode* elsesp = nullptr) - : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) {} + AstIf(FileLine* fl, AstNode* condp, AstNode* thensp = nullptr, AstNode* elsesp = nullptr) + : ASTGEN_SUPER_If(fl, condp, thensp, elsesp) {} ASTGEN_MEMBERS_If; bool uniquePragma() const { return m_uniquePragma; } void uniquePragma(bool flag) { m_uniquePragma = flag; } @@ -4304,7 +4113,7 @@ public: ASTGEN_MEMBERS_Text; }; class AstTextBlock final : public AstNodeSimpleText { -private: + // @astgen op1 := nodesp : List[AstNode] bool m_commas; // Comma separate emitted children public: explicit AstTextBlock(FileLine* fl, const string& textp = "", bool tracking = false, @@ -4314,10 +4123,8 @@ public: ASTGEN_MEMBERS_TextBlock; void commas(bool flag) { m_commas = flag; } bool commas() const { return m_commas; } - AstNode* nodesp() const { return op1p(); } - void addNodep(AstNode* nodep) { addOp1p(nodep); } void addText(FileLine* fl, const string& textp, bool tracking = false) { - addNodep(new AstText(fl, textp, tracking)); + addNodesp(new AstText(fl, textp, tracking)); } }; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 5bbc6bf42..172b4cec1 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -188,8 +188,8 @@ void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthForce(rangep->elementsConst(), rangep->elementsConst()); // Maybe unknown if parameters underneath it } - setNOp1p(rangep); - dtypep(this); + this->rangep(rangep); + this->dtypep(this); } void AstBasicDType::cvtRangeConst() { @@ -660,25 +660,15 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) { } else { return nullptr; } - } else if (VN_IS(nodep, VarRef)) { - if (VN_AS(nodep, VarRef)->varp()->isSc()) { - return VN_AS(nodep, VarRef)->varp(); + } else if (AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) { + if (vrefp->varp()->isSc()) { + return vrefp->varp(); } else { return nullptr; } - } else if (VN_IS(nodep, ArraySel)) { - if (nodep->op1p()) { - if (AstVar* p = scVarRecurse(nodep->op1p())) return p; - } - if (nodep->op2p()) { - if (AstVar* p = scVarRecurse(nodep->op2p())) return p; - } - if (nodep->op3p()) { - if (AstVar* p = scVarRecurse(nodep->op3p())) return p; - } - if (nodep->op4p()) { - if (AstVar* p = scVarRecurse(nodep->op4p())) return p; - } + } else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) { + if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p; + if (AstVar* const p = scVarRecurse(arraySelp->bitp())) return p; } return nullptr; } @@ -1070,8 +1060,8 @@ AstConstPool::AstConstPool(FileLine* fl) : ASTGEN_SUPER_ConstPool(fl) , m_modp{new AstModule(fl, "@CONST-POOL@")} , m_scopep{new AstScope(fl, m_modp, "@CONST-POOL@", nullptr, nullptr)} { - addOp1p(m_modp); - m_modp->addStmtp(m_scopep); + this->modulep(m_modp); + m_modp->addStmtsp(m_scopep); } const char* AstConstPool::broken() const { BROKEN_RTN(m_modp && !m_modp->brokeExists()); @@ -1085,9 +1075,9 @@ AstVarScope* AstConstPool::createNewEntry(const string& name, AstNode* initp) { varp->isConst(true); varp->isStatic(true); varp->valuep(initp->cloneTree(false)); - m_modp->addStmtp(varp); + m_modp->addStmtsp(varp); AstVarScope* const varScopep = new AstVarScope(fl, m_scopep, varp); - m_scopep->addVarp(varScopep); + m_scopep->addVarsp(varScopep); return varScopep; } @@ -1233,7 +1223,7 @@ void AstWhile::addBeforeStmt(AstNode* newp, AstNode* belowp) { } else if (belowp == condp()) { // Goes before condition, IE in preconditions addPrecondsp(newp); - } else if (belowp == bodysp()) { + } else if (belowp == stmtsp()) { // Was first statement in body, so new front belowp->addHereThisAsNext(newp); } else { @@ -1250,12 +1240,12 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) { belowp->addNextHere(newp); } else if (belowp == condp()) { // Becomes first statement in body, body may have been empty - if (bodysp()) { - bodysp()->addHereThisAsNext(newp); + if (stmtsp()) { + stmtsp()->addHereThisAsNext(newp); } else { - addBodysp(newp); + addStmtsp(newp); } - } else if (belowp == bodysp()) { + } else if (belowp == stmtsp()) { // Next statement in body belowp->addNextHere(newp); } else { @@ -1521,19 +1511,15 @@ void AstInitArray::cloneRelink() { if (it->second->clonep()) it->second = it->second->clonep(); } } -AstNode* AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) { - // Returns old value, caller must garbage collect - AstNode* oldp = nullptr; +void AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) { const auto it = m_map.find(index); if (it != m_map.end()) { - oldp = it->second->valuep(); it->second->valuep(newp); } else { AstInitItem* const itemp = new AstInitItem(fileline(), newp); m_map.emplace(index, itemp); - addOp2p(itemp); + addInitsp(itemp); } - return oldp; } AstNode* AstInitArray::getIndexValuep(uint64_t index) const { const auto it = m_map.find(index); @@ -1808,7 +1794,7 @@ AstPackage* AstNetlist::dollarUnitPkgAddp() { m_dollarUnitPkgp->inLibrary(true); m_dollarUnitPkgp->modTrace(false); // may reconsider later m_dollarUnitPkgp->internal(true); - addModulep(m_dollarUnitPkgp); + addModulesp(m_dollarUnitPkgp); } return m_dollarUnitPkgp; } @@ -1816,7 +1802,7 @@ void AstNetlist::createTopScope(AstScope* scopep) { UASSERT(scopep, "Must not be nullptr"); UASSERT_OBJ(!m_topScopep, scopep, "TopScope already exits"); m_topScopep = new AstTopScope{scopep->modp()->fileline(), scopep}; - scopep->modp()->addStmtp(v3Global.rootp()->topScopep()); + scopep->modp()->addStmtsp(v3Global.rootp()->topScopep()); } void AstNodeModule::dump(std::ostream& str) const { this->AstNode::dump(str); diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index c9ceec09e..1f5abb9ce 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -115,7 +115,7 @@ private: } } else { // Move to module - m_modp->addStmtp(nodep); + m_modp->addStmtsp(nodep); } } @@ -214,7 +214,7 @@ private: UINFO(8, " rename to " << nodep->name() << endl); // Move to module nodep->unlinkFrBack(); - m_modp->addStmtp(nodep); + m_modp->addStmtsp(nodep); } iterateChildren(nodep); } @@ -233,10 +233,10 @@ private: const string scname = nodep->forFormat() ? m_displayScope : m_namedScope; if (!scname.empty()) { // To keep correct visual order, must add before other Text's - AstNode* const afterp = nodep->scopeAttrp(); + AstText* const afterp = nodep->scopeAttrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname}); - if (afterp) nodep->scopeAttrp(afterp); + nodep->addScopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname}); + if (afterp) nodep->addScopeAttrp(afterp); } iterateChildren(nodep); } diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index eed4e49fc..8cd525687 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -70,7 +70,7 @@ private: { // Do if reset(); - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); const int ifLikely = m_likely; const int ifUnlikely = m_unlikely; // Do else diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index dd4978eca..2be4316d6 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -275,9 +275,9 @@ private: pushLocalScope(); processEnter(nodep); processAndIterate(nodep->condp()); - if (AstNode* const ifsp = nodep->ifsp()) { + if (AstNode* const thensp = nodep->thensp()) { pushLocalScope(); - processAndIterateList(ifsp); + processAndIterateList(thensp); popLocalScope(); } if (AstNode* const elsesp = nodep->elsesp()) { diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index 090009c24..e37b4e884 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -77,7 +77,7 @@ private: if (!preventUnusedStmt.empty()) { funcp->addStmtsp(new AstCStmt{m_modp->fileline(), preventUnusedStmt}); } - m_modp->addStmtp(funcp); + m_modp->addStmtsp(funcp); m_numStmts = 0; return funcp; } @@ -136,7 +136,7 @@ void V3CCtors::evalAsserts() { funcp->isLoose(true); funcp->slow(false); funcp->ifdef("VL_DEBUG"); - modp->addStmtp(funcp); + modp->addStmtsp(funcp); for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) { if (AstVar* const varp = VN_CAST(np, Var)) { if (varp->isPrimaryInish() && !varp->isSc()) { @@ -209,7 +209,7 @@ void V3CCtors::cctorsAll() { // If can be referred to by base pointer, need virtual delete funcp->isVirtual(classp->isExtended()); funcp->slow(false); - modp->addStmtp(funcp); + modp->addStmtsp(funcp); } } } diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 5bf6bfe69..adc33fccd 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -51,7 +51,7 @@ class CUseVisitor final : public VNVisitor { void addNewUse(AstNode* nodep, VUseType useType, const string& name) { if (m_didUse.emplace(useType, name).second) { AstCUse* const newp = new AstCUse{nodep->fileline(), useType, name}; - m_modp->addStmtp(newp); + m_modp->addStmtsp(newp); UINFO(8, "Insert " << newp << endl); } } diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 58a160301..d469978e2 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -245,7 +245,7 @@ private: // Convert valueItem from AstCaseItem* to the expression // Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch for (uint32_t i = 0; i < numCases; ++i) { - m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->bodysp(); + m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->stmtsp(); } return true; // All is fine } @@ -346,7 +346,7 @@ private: itemp = VN_AS(itemp->nextp(), CaseItem)) { if (!itemp->condsp()) { // Default clause. Just make true, we'll optimize it away later - itemp->condsp(new AstConst(itemp->fileline(), AstConst::BitTrue())); + itemp->addCondsp(new AstConst(itemp->fileline(), AstConst::BitTrue())); hadDefault = true; } else { // Expressioned clause @@ -397,7 +397,7 @@ private: } } // Replace expression in tree - itemp->condsp(ifexprp); + itemp->addCondsp(ifexprp); } } VL_DO_DANGLING(cexprp->deleteTree(), cexprp); @@ -420,7 +420,7 @@ private: AstIf* itemnextp = nullptr; for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp = VN_AS(itemp->nextp(), CaseItem)) { - AstNode* const istmtsp = itemp->bodysp(); // Maybe null -- no action. + AstNode* const istmtsp = itemp->stmtsp(); // Maybe null -- no action. if (istmtsp) istmtsp->unlinkFrBackWithNext(); // Expressioned clause AstNode* const ifexprp = itemp->condsp()->unlinkFrBack(); @@ -452,7 +452,7 @@ private: if (itemnextp) { itemnextp->addElsesp(newp); } else { - groupnextp->addIfsp(newp); // First in a new group + groupnextp->addThensp(newp); // First in a new group } itemnextp = newp; } diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index f99b40284..067d0d0a7 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -67,7 +67,7 @@ public: m_tlChgFuncp->isStatic(false); m_tlChgFuncp->isLoose(true); m_tlChgFuncp->declPrivate(true); - m_scopetopp->addActivep(m_tlChgFuncp); + m_scopetopp->addBlocksp(m_tlChgFuncp); // Each change detection function needs at least one AstChangeDet // to ensure that V3EmitC outputs the necessary code. maybeCreateMidChg(); @@ -86,7 +86,7 @@ public: m_chgFuncp->isStatic(false); m_chgFuncp->isLoose(true); m_chgFuncp->declPrivate(true); - m_scopetopp->addActivep(m_chgFuncp); + m_scopetopp->addBlocksp(m_chgFuncp); // Add a top call to it AstCCall* const callp = new AstCCall{m_scopetopp->fileline(), m_chgFuncp}; @@ -218,9 +218,9 @@ public: // CHANGEDET(VARREF(_last), VARREF(var)) AstVar* const newvarp = new AstVar{varp->fileline(), VVarType::MODULETEMP, newvarname, varp}; - m_state.m_topModp->addStmtp(newvarp); + m_state.m_topModp->addStmtsp(newvarp); m_newvscp = new AstVarScope{m_vscp->fileline(), m_state.m_scopetopp, newvarp}; - m_state.m_scopetopp->addVarp(m_newvscp); + m_state.m_scopetopp->addVarsp(m_newvscp); m_varEqnp = new AstVarRef{m_vscp->fileline(), m_vscp, VAccess::READ}; m_newLvEqnp = new AstVarRef{m_vscp->fileline(), m_newvscp, VAccess::WRITE}; diff --git a/src/V3Class.cpp b/src/V3Class.cpp index 52a7c0f1f..f89be682d 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -54,7 +54,7 @@ private: // Move this class nodep->name(m_prefix + nodep->name()); nodep->unlinkFrBack(); - v3Global.rootp()->addModulep(nodep); + v3Global.rootp()->addModulesp(nodep); // Make containing package // Note origName is the same as the class origName so errors look correct AstClassPackage* const packagep @@ -62,7 +62,7 @@ private: packagep->name(nodep->name() + "__Vclpkg"); nodep->classOrPackagep(packagep); packagep->classp(nodep); - v3Global.rootp()->addModulep(packagep); + v3Global.rootp()->addModulesp(packagep); // Add package to hierarchy AstCell* const cellp = new AstCell{packagep->fileline(), packagep->fileline(), @@ -72,7 +72,7 @@ private: nullptr, nullptr}; cellp->modp(packagep); - v3Global.rootp()->topModulep()->addStmtp(cellp); + v3Global.rootp()->topModulep()->addStmtsp(cellp); // Find class's scope // Alternative would be to move this and related to V3Scope const AstScope* classScopep = nullptr; @@ -85,7 +85,7 @@ private: AstScope* const scopep = new AstScope{nodep->fileline(), packagep, classScopep->name(), classScopep->aboveScopep(), classScopep->aboveCellp()}; - packagep->addStmtp(scopep); + packagep->addStmtsp(scopep); // Iterate VL_RESTORER(m_prefix); VL_RESTORER(m_classPackagep); @@ -178,15 +178,15 @@ public: AstScope* const scopep = moved.second; UINFO(9, "moving " << nodep << " to " << scopep << endl); if (VN_IS(nodep, NodeFTask)) { - scopep->addActivep(nodep->unlinkFrBack()); + scopep->addBlocksp(nodep->unlinkFrBack()); } else if (VN_IS(nodep, Var)) { AstVarScope* const vscp = VN_AS(nodep->user1p(), VarScope); vscp->scopep(scopep); vscp->unlinkFrBack(); - scopep->addVarp(vscp); + scopep->addVarsp(vscp); } else if (VN_IS(nodep, Initial) || VN_IS(nodep, InitialStatic)) { nodep->unlinkFrBack(); - scopep->addActivep(nodep); + scopep->addBlocksp(nodep); } else { nodep->v3fatalSrc("Bad case"); } @@ -196,7 +196,7 @@ public: AstNodeModule* const modp = moved.second; UINFO(9, "moving " << nodep << " to " << modp << endl); nodep->unlinkFrBack(); - modp->addStmtp(nodep); + modp->addStmtsp(nodep); } } }; diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 64fa0dcba..7817304a2 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -236,7 +236,7 @@ private: setClean(nodep, false); // We always clean, as we don't trust those pesky users. if (!VN_IS(nodep->backp(), And)) insertClean(nodep); - ensureCleanAndNext(nodep->bodysp()); + ensureCleanAndNext(nodep->exprsp()); } void visit(AstTraceDecl* nodep) override { // No cleaning, or would loose pointer to enum @@ -259,7 +259,7 @@ private: void visit(AstNodeCond* nodep) override { iterateChildren(nodep); ensureClean(nodep->condp()); - setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p())); + setClean(nodep, isClean(nodep->thenp()) && isClean(nodep->elsep())); } void visit(AstWhile* nodep) override { iterateChildren(nodep); @@ -276,7 +276,7 @@ private: } void visit(AstUCStmt* nodep) override { iterateChildren(nodep); - ensureCleanAndNext(nodep->bodysp()); + ensureCleanAndNext(nodep->exprsp()); } void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index 95e10270d..ed6f5cc1f 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -102,10 +102,10 @@ private: AstVar* const newvarp = new AstVar(vscp->fileline(), VVarType::MODULETEMP, newvarname, VFlagLogicPacked{}, 1); newvarp->noReset(true); // Reset by below assign - m_modp->addStmtp(newvarp); + m_modp->addStmtsp(newvarp); AstVarScope* const newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp); vscp->user1p(newvscp); - m_scopep->addVarp(newvscp); + m_scopep->addVarsp(newvscp); // Add init AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, VAccess::READ); if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp); @@ -202,7 +202,7 @@ private: funcp->slow(slow); funcp->isConst(false); funcp->declPrivate(true); - m_topScopep->scopep()->addActivep(funcp); + m_topScopep->scopep()->addBlocksp(funcp); return funcp; } void splitCheck(AstCFunc* ofuncp) { @@ -229,7 +229,7 @@ private: funcp->isStatic(false); funcp->isLoose(true); funcp->slow(ofuncp->slow()); - m_topScopep->scopep()->addActivep(funcp); + m_topScopep->scopep()->addBlocksp(funcp); // AstCCall* const callp = new AstCCall{funcp->fileline(), funcp}; ofuncp->addStmtsp(callp); @@ -297,7 +297,7 @@ private: m_scopep = nullptr; } void visit(AstNodeProcedure* nodep) override { - if (AstNode* const stmtsp = nodep->bodysp()) { + if (AstNode* const stmtsp = nodep->stmtsp()) { stmtsp->unlinkFrBackWithNext(); nodep->addNextHere(stmtsp); } @@ -316,7 +316,7 @@ private: // We could add another IF to detect posedges, and only increment if so. // It's another whole branch though versus a potential memory miss. // We'll go with the miss. - newp->addIfsp(new AstAssign(nodep->fileline(), changeWrp, origp->cloneTree(false))); + newp->addThensp(new AstAssign(nodep->fileline(), changeWrp, origp->cloneTree(false))); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -367,7 +367,7 @@ private: m_mtaskBodyp->addStmtsp(m_lastIfp); } // Move statements to if - m_lastIfp->addIfsp(stmtsp); + m_lastIfp->addThensp(stmtsp); } else if (nodep->hasInitial() || nodep->hasSettle()) { nodep->v3fatalSrc("MTask should not include initial/settle logic."); } else { @@ -393,7 +393,7 @@ private: addToEvalLoop(m_lastIfp); } // Move statements to if - m_lastIfp->addIfsp(stmtsp); + m_lastIfp->addThensp(stmtsp); } else if (nodep->hasInitial()) { // Don't need to: clearLastSen();, as we're adding it to different cfunc // Move statements to function diff --git a/src/V3Common.cpp b/src/V3Common.cpp index 76521a3fd..f64018c5b 100644 --- a/src/V3Common.cpp +++ b/src/V3Common.cpp @@ -43,7 +43,7 @@ static void makeVlToString(AstClass* nodep) { AstNode* const exprp = new AstCMath{nodep->fileline(), "obj ? obj->to_string() : \"null\"", 0}; exprp->dtypeSetString(); funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp}); - nodep->addStmtp(funcp); + nodep->addStmtsp(funcp); } static void makeToString(AstClass* nodep) { AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "to_string", nullptr, "std::string"}; @@ -54,7 +54,7 @@ static void makeToString(AstClass* nodep) { = new AstCMath{nodep->fileline(), R"(std::string{"'{"} + to_string_middle() + "}")", 0}; exprp->dtypeSetString(); funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp}); - nodep->addStmtp(funcp); + nodep->addStmtsp(funcp); } static void makeToStringMiddle(AstClass* nodep) { AstCFunc* const funcp @@ -96,7 +96,7 @@ static void makeToStringMiddle(AstClass* nodep) { funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt}); } funcp->addStmtsp(new AstCStmt{nodep->fileline(), "return out;\n"}); - nodep->addStmtp(funcp); + nodep->addStmtsp(funcp); } //###################################################################### diff --git a/src/V3Config.cpp b/src/V3Config.cpp index f716bba2b..5c6d77acf 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -193,11 +193,11 @@ public: const VPragmaType type = m_inlineValue ? VPragmaType::INLINE_MODULE : VPragmaType::NO_INLINE_MODULE; AstNode* const nodep = new AstPragma(modp->fileline(), type); - modp->addStmtp(nodep); + modp->addStmtsp(nodep); } for (const auto& itr : m_modPragmas) { AstNode* const nodep = new AstPragma{modp->fileline(), itr}; - modp->addStmtp(nodep); + modp->addStmtsp(nodep); } } diff --git a/src/V3Const.cpp b/src/V3Const.cpp index ba3b75edb..b94f49373 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -1042,20 +1042,19 @@ private: // as high as possible, which is usally the right choice, except for this. AstNodeCond* const condp = VN_CAST(nodep->rhsp(), NodeCond); if (!condp) return false; - if (!VN_IS(condp->expr1p(), Const) && !VN_IS(condp->expr2p(), Const)) return false; + if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false; AstConst* const maskp = VN_CAST(nodep->lhsp(), Const); if (!maskp) return false; UINFO(4, "AND(CONSTm, CONDcond(c, i, e))->CONDcond(c, AND(m,i), AND(m, e)) " << nodep << endl); - AstNodeCond* const newp = static_cast( - condp->cloneType(condp->condp()->unlinkFrBack(), - new AstAnd(nodep->fileline(), maskp->cloneTree(false), - condp->expr1p()->unlinkFrBack()), - new AstAnd(nodep->fileline(), maskp->cloneTree(false), - condp->expr2p()->unlinkFrBack()))); + AstNodeCond* const newp = static_cast(condp->cloneType( + condp->condp()->unlinkFrBack(), + new AstAnd(nodep->fileline(), maskp->cloneTree(false), condp->thenp()->unlinkFrBack()), + new AstAnd(nodep->fileline(), maskp->cloneTree(false), + condp->elsep()->unlinkFrBack()))); newp->dtypeFrom(nodep); - newp->expr1p()->dtypeFrom(nodep); // As And might have been to change widths - newp->expr2p()->dtypeFrom(nodep); + newp->thenp()->dtypeFrom(nodep); // As And might have been to change widths + newp->elsep()->dtypeFrom(nodep); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); return true; @@ -1443,19 +1442,19 @@ private: } } bool ifSameAssign(const AstNodeIf* nodep) { - const AstNodeAssign* const ifp = VN_CAST(nodep->ifsp(), NodeAssign); - const AstNodeAssign* const elsep = VN_CAST(nodep->elsesp(), NodeAssign); - if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement - if (!elsep || elsep->nextp()) return false; - if (ifp->type() != elsep->type()) return false; // Can't mix an assigndly and an assign - if (!ifp->lhsp()->sameGateTree(elsep->lhsp())) return false; - if (!ifp->rhsp()->gateTree()) return false; - if (!elsep->rhsp()->gateTree()) return false; + const AstNodeAssign* const thensp = VN_CAST(nodep->thensp(), NodeAssign); + const AstNodeAssign* const elsesp = VN_CAST(nodep->elsesp(), NodeAssign); + if (!thensp || thensp->nextp()) return false; // Must be SINGLE statement + if (!elsesp || elsesp->nextp()) return false; + if (thensp->type() != elsesp->type()) return false; // Can't mix an assigndly with assign + if (!thensp->lhsp()->sameGateTree(elsesp->lhsp())) return false; + if (!thensp->rhsp()->gateTree()) return false; + if (!elsesp->rhsp()->gateTree()) return false; return true; } bool operandIfIf(const AstNodeIf* nodep) { if (nodep->elsesp()) return false; - const AstNodeIf* const lowerIfp = VN_CAST(nodep->ifsp(), NodeIf); + const AstNodeIf* const lowerIfp = VN_CAST(nodep->thensp(), NodeIf); if (!lowerIfp || lowerIfp->nextp()) return false; if (nodep->type() != lowerIfp->type()) return false; if (afterComment(lowerIfp->elsesp())) return false; @@ -2097,8 +2096,8 @@ private: AstVar* const temp2p = new AstVar(sel2p->fileline(), VVarType::BLOCKTEMP, m_concswapNames.get(sel2p), VFlagLogicPacked(), msb2 - lsb2 + 1); - m_modp->addStmtp(temp1p); - m_modp->addStmtp(temp2p); + m_modp->addStmtsp(temp1p); + m_modp->addStmtsp(temp2p); AstNodeAssign* const asn1ap = VN_AS(nodep->cloneType( new AstVarRef(sel1p->fileline(), temp1p, VAccess::WRITE), sel1p), @@ -2862,7 +2861,7 @@ private: varrefp->unlinkFrBack(); AstInitial* const newinitp = new AstInitial( nodep->fileline(), new AstAssign(nodep->fileline(), varrefp, exprp)); - m_modp->addStmtp(newinitp); + m_modp->addStmtsp(newinitp); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); // Set the initial value right in the variable so we can constant propagate AstNode* const initvaluep = exprp->cloneTree(false); @@ -2892,7 +2891,7 @@ private: keepp = nodep->elsesp(); } else if (!m_doV || constp->isNeqZero()) { // Might be X in Verilog UINFO(4, "IF(!0,{x},{any}) => {x}: " << nodep << endl); - keepp = nodep->ifsp(); + keepp = nodep->thensp(); } else { UINFO(4, "IF condition is X, retaining: " << nodep << endl); return; @@ -2904,7 +2903,7 @@ private: nodep->unlinkFrBack(); } VL_DO_DANGLING(nodep->deleteTree(), nodep); - } else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) { + } else if (!afterComment(nodep->thensp()) && !afterComment(nodep->elsesp())) { if (!isTreePureRecurse(nodep->condp())) { // Condition has side effect - leave - perhaps in // future simplify to remove all but side effect terms @@ -2912,27 +2911,27 @@ private: // Empty block, remove it VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - } else if (!afterComment(nodep->ifsp())) { + } else if (!afterComment(nodep->thensp())) { UINFO(4, "IF({x}) nullptr {...} => IF(NOT{x}}: " << nodep << endl); AstNode* const condp = nodep->condp(); AstNode* const elsesp = nodep->elsesp(); condp->unlinkFrBackWithNext(); elsesp->unlinkFrBackWithNext(); - if (nodep->ifsp()) { // Must have been comment - nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); + if (nodep->thensp()) { // Must have been comment + nodep->thensp()->unlinkFrBackWithNext()->deleteTree(); } nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible - nodep->addIfsp(elsesp); + nodep->addThensp(elsesp); } else if (((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1) || VN_IS(nodep->condp(), LogNot)) - && nodep->ifsp() && nodep->elsesp()) { + && nodep->thensp() && nodep->elsesp()) { UINFO(4, "IF(NOT {x}) => IF(x) swapped if/else" << nodep << endl); AstNode* const condp = VN_AS(nodep->condp(), NodeUniop)->lhsp()->unlinkFrBackWithNext(); - AstNode* const ifsp = nodep->ifsp()->unlinkFrBackWithNext(); + AstNode* const thensp = nodep->thensp()->unlinkFrBackWithNext(); AstNode* const elsesp = nodep->elsesp()->unlinkFrBackWithNext(); - AstIf* const ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp); + AstIf* const ifp = new AstIf(nodep->fileline(), condp, elsesp, thensp); ifp->branchPred(nodep->branchPred().invert()); nodep->replaceWith(ifp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -2940,25 +2939,25 @@ private: UINFO( 4, "IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})\n"); - AstNodeAssign* const ifp = VN_AS(nodep->ifsp(), NodeAssign); - AstNodeAssign* const elsep = VN_AS(nodep->elsesp(), NodeAssign); - ifp->unlinkFrBack(); + AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign); + AstNodeAssign* const elsesp = VN_AS(nodep->elsesp(), NodeAssign); + thensp->unlinkFrBack(); AstNode* const condp = nodep->condp()->unlinkFrBack(); - AstNode* const truep = ifp->rhsp()->unlinkFrBack(); - AstNode* const falsep = elsep->rhsp()->unlinkFrBack(); - ifp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep)); - nodep->replaceWith(ifp); + AstNode* const truep = thensp->rhsp()->unlinkFrBack(); + AstNode* const falsep = elsesp->rhsp()->unlinkFrBack(); + thensp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep)); + nodep->replaceWith(thensp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } else if (false // Disabled, as vpm assertions are faster // without due to short-circuiting && operandIfIf(nodep)) { UINFO(9, "IF({a}) IF({b}) => IF({a} && {b})" << endl); - AstNodeIf* const lowerIfp = VN_AS(nodep->ifsp(), NodeIf); + AstNodeIf* const lowerIfp = VN_AS(nodep->thensp(), NodeIf); AstNode* const condp = nodep->condp()->unlinkFrBack(); - AstNode* const lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext(); + AstNode* const lowerThensp = lowerIfp->thensp()->unlinkFrBackWithNext(); AstNode* const lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext(); nodep->condp(new AstLogAnd(lowerIfp->fileline(), condp, lowerCondp)); - lowerIfp->replaceWith(lowerIfsp); + lowerIfp->replaceWith(lowerThensp); VL_DO_DANGLING(lowerIfp->deleteTree(), lowerIfp); } else if (operandBoolShift(nodep->condp())) { replaceBoolShift(nodep->condp()); @@ -3015,8 +3014,10 @@ private: pformatp->text(pformatp->text() + nformatp->text()); if (!prevp->addNewline() && nodep->addNewline()) pformatp->text(pformatp->text() + "\n"); if (nformatp->exprsp()) pformatp->addExprsp(nformatp->exprsp()->unlinkFrBackWithNext()); - if (nformatp->scopeNamep()) - pformatp->scopeNamep(nformatp->scopeNamep()->unlinkFrBackWithNext()); + if (AstScopeName* const scopeNamep = nformatp->scopeNamep()) { + scopeNamep->unlinkFrBackWithNext(); + pformatp->scopeNamep(scopeNamep); + } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); return true; } @@ -3300,19 +3301,19 @@ private: TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b) // Trinary ops // Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump! - TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)"); - TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)"); - TREEOPA("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)"); - TREEOPA("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)"); - TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)"); + TREEOP ("AstNodeCond{$condp.isZero, $thenp, $elsep}", "replaceWChild(nodep,$elsep)"); + TREEOP ("AstNodeCond{$condp.isNeqZero, $thenp, $elsep}", "replaceWChild(nodep,$thenp)"); + TREEOPA("AstNodeCond{$condp.isZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$elsep)"); + TREEOPA("AstNodeCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)"); + TREEOP ("AstNodeCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)"); // This visit function here must allow for short-circuiting. TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)"); TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)"); - TREEOP ("AstCond{$condp.castNot, $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}"); - TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b - TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b - TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstLogOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a||b - TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstLogAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&&b + TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->op1p(), $elsep, $thenp}"); + TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b + TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b + TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isAllOnes}", "AstLogOr {AstNot{$condp}, $thenp}"); // a?b:1 == ~a||b + TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isZero, $elsep}", "AstLogAnd{AstNot{$condp}, $elsep}"); // a?0:b == ~a&&b TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())"); // Prefer constants on left, since that often needs a shift, it lets // constant red remove the shift diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 04266c492..1a87bb02f 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -119,7 +119,7 @@ private: AstCoverDecl* const declp = new AstCoverDecl(fl, page, comment, linescov, offset); declp->hier(hier); - m_modp->addStmtp(declp); + m_modp->addStmtsp(declp); UINFO(9, "new " << declp << endl); AstCoverInc* const incp = new AstCoverInc(fl, declp); @@ -128,7 +128,7 @@ private: incp->findUInt32DType()); varp->trace(true); varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); - m_modp->addStmtp(varp); + m_modp->addStmtsp(varp); UINFO(5, "New coverage trace: " << varp << endl); AstAssign* const assp = new AstAssign( incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::WRITE), @@ -245,11 +245,11 @@ private: = newCoverInc(nodep->fileline(), "", "v_line", "block", linesCov(m_state, nodep), 0, traceNameForLine(nodep, "block")); if (AstNodeProcedure* const itemp = VN_CAST(nodep, NodeProcedure)) { - itemp->addStmtp(newp); + itemp->addStmtsp(newp); } else if (AstNodeFTask* const itemp = VN_CAST(nodep, NodeFTask)) { itemp->addStmtsp(newp); } else if (AstWhile* const itemp = VN_CAST(nodep, While)) { - itemp->addBodysp(newp); + itemp->addStmtsp(newp); } else { nodep->v3fatalSrc("Bad node type"); } @@ -283,7 +283,7 @@ private: AstVar* const chgVarp = new AstVar(nodep->fileline(), VVarType::MODULETEMP, newvarname, nodep); chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); - m_modp->addStmtp(chgVarp); + m_modp->addStmtsp(chgVarp); // Create bucket for each dimension * bit. // This is necessarily an O(n^2) expansion, which is why @@ -304,7 +304,7 @@ private: newCoverInc(varp->fileline(), "", "v_toggle", varp->name() + above.m_comment, "", 0, ""), above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true)); - m_modp->addStmtp(newp); + m_modp->addStmtsp(newp); } void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration @@ -388,7 +388,7 @@ private: if (m_state.m_on) { // An else-if. When we iterate the if, use "elsif" marking const bool elsif - = nodep->ifsp() && VN_IS(nodep->elsesp(), If) && !nodep->elsesp()->nextp(); + = nodep->thensp() && VN_IS(nodep->elsesp(), If) && !nodep->elsesp()->nextp(); if (elsif) VN_AS(nodep->elsesp(), If)->user1(true); const bool first_elsif = !nodep->user1() && elsif; const bool cont_elsif = nodep->user1() && elsif; @@ -403,7 +403,7 @@ private: CheckState elseState; { createHandle(nodep); - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); lineTrack(nodep); ifState = m_state; } @@ -422,9 +422,9 @@ private: // Normal if. Linecov shows what's inside the if (not condition that is // always executed) UINFO(4, " COVER-branch: " << nodep << endl); - nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_branch", "if", - linesCov(ifState, nodep), 0, - traceNameForLine(nodep, "if"))); + nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_branch", "if", + linesCov(ifState, nodep), 0, + traceNameForLine(nodep, "if"))); // The else has a column offset of 1 to uniquify it relative to the if // As "if" and "else" are more than one character wide, this won't overlap // another token @@ -436,18 +436,18 @@ private: else if (first_elsif || cont_elsif) { UINFO(4, " COVER-elsif: " << nodep << endl); if (ifState.lineCoverageOn(nodep)) { - nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif", - linesCov(ifState, nodep), 0, - traceNameForLine(nodep, "elsif"))); + nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "elsif", + linesCov(ifState, nodep), 0, + traceNameForLine(nodep, "elsif"))); } // and we don't insert the else as the child if-else will do so } else { // Cover as separate blocks (not a branch as is not two-legged) if (ifState.lineCoverageOn(nodep)) { UINFO(4, " COVER-half-if: " << nodep << endl); - nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if", - linesCov(ifState, nodep), 0, - traceNameForLine(nodep, "if"))); + nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "if", + linesCov(ifState, nodep), 0, + traceNameForLine(nodep, "if"))); } if (elseState.lineCoverageOn(nodep)) { UINFO(4, " COVER-half-el: " << nodep << endl); @@ -468,11 +468,11 @@ private: VL_RESTORER(m_state); { createHandle(nodep); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); if (m_state.lineCoverageOn(nodep)) { // if the case body didn't disable it lineTrack(nodep); UINFO(4, " COVER: " << nodep << endl); - nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case", + nodep->addStmtsp(newCoverInc(nodep->fileline(), "", "v_line", "case", linesCov(m_state, nodep), 0, traceNameForLine(nodep, "case"))); } @@ -486,12 +486,12 @@ private: m_state.m_on = true; // Always do cover blocks, even if there's a $stop createHandle(nodep); iterateChildren(nodep); - if (!nodep->coverincp() && v3Global.opt.coverageUser()) { + if (!nodep->coverincsp() && v3Global.opt.coverageUser()) { // Note the name may be overridden by V3Assert processing lineTrack(nodep); - nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover", - linesCov(m_state, nodep), 0, - m_beginHier + "_vlCoverageUserTrace")); + nodep->addCoverincsp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover", + linesCov(m_state, nodep), 0, + m_beginHier + "_vlCoverageUserTrace")); } } } diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index f7d928d33..f95ad8f0d 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -153,13 +153,13 @@ private: varp = new AstVar(oldvarscp->fileline(), VVarType::BLOCKTEMP, name, VFlagBitPacked(), width); } - addmodp->addStmtp(varp); + addmodp->addStmtsp(varp); m_modVarMap.emplace(std::make_pair(addmodp, name), varp); } AstVarScope* const varscp = new AstVarScope(oldvarscp->fileline(), oldvarscp->scopep(), varp); - oldvarscp->scopep()->addVarp(varscp); + oldvarscp->scopep()->addVarsp(varscp); return varscp; } @@ -356,11 +356,11 @@ private: postLogicp = new AstIf(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, VAccess::READ)); UINFO(9, " Created " << postLogicp << endl); - finalp->addStmtp(postLogicp); + finalp->addStmtsp(postLogicp); finalp->user3p(setvscp); // Remember IF's vset variable finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it } - postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp)); + postLogicp->addThensp(new AstAssign(nodep->fileline(), selectsp, valreadp)); return newlhsp; } diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index c4cde8287..89bd99669 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -57,7 +57,7 @@ private: funcp->isStatic(m_cfuncp->isStatic()); funcp->isLoose(m_cfuncp->isLoose()); funcp->addStmtsp(nodep); - scopep->addActivep(funcp); + scopep->addBlocksp(funcp); // Call sub function at the point where the body was removed from AstCCall* const callp = new AstCCall(nodep->fileline(), funcp); if (VN_IS(m_modp, Class)) { diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index 835294f74..fbf39da8b 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -257,7 +257,7 @@ private: // If it's under a scope, move it up to the top if (m_scopep) { nodep->unlinkFrBack(); - m_modp->addStmtp(nodep); + m_modp->addStmtsp(nodep); if (nodep->funcPublic()) { // There may be multiple public functions by the same name; diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 71d636cf9..47c219da6 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -828,7 +828,7 @@ public: puts("while ("); iterateAndNextNull(nodep->condp()); puts(") {\n"); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->incsp()); iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop puts("}\n"); @@ -842,7 +842,7 @@ public: iterateAndNextNull(nodep->condp()); if (!nodep->branchPred().unknown()) puts(")"); puts(") {\n"); - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); puts("}"); if (!nodep->elsesp()) { puts("\n"); @@ -935,17 +935,17 @@ public: } void visit(AstCStmt* nodep) override { putbs(""); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->exprsp()); } void visit(AstCMath* nodep) override { putbs(""); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->exprsp()); } void visit(AstUCStmt* nodep) override { VL_RESTORER(m_inUC); m_inUC = true; putsDecoration(ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n")); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->exprsp()); puts("\n"); } void visit(AstUCFunc* nodep) override { @@ -953,7 +953,7 @@ public: m_inUC = true; puts("\n"); putsDecoration(ifNoProtect("// $c function at " + nodep->fileline()->ascii() + "\n")); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->exprsp()); puts("\n"); } @@ -1033,15 +1033,15 @@ public: } void visit(AstNodeCond* nodep) override { // Widths match up already, so we'll just use C++'s operator w/o any temps. - if (nodep->expr1p()->isWide()) { - emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p()); + if (nodep->thenp()->isWide()) { + emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->thenp(), nodep->elsep()); } else { putbs("("); iterateAndNextNull(nodep->condp()); putbs(" ? "); - iterateAndNextNull(nodep->expr1p()); + iterateAndNextNull(nodep->thenp()); putbs(" : "); - iterateAndNextNull(nodep->expr2p()); + iterateAndNextNull(nodep->elsep()); puts(")"); } } diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 76144011b..9e7d015da 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -110,7 +110,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->sensesp()); } putbs(" begin\n"); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->stmtsp()); putqs(nodep, "end\n"); } void visit(AstAlwaysPublic* nodep) override { @@ -122,7 +122,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->sensesp()); } putqs(nodep, " "); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->stmtsp()); putqs(nodep, "*/\n"); } void visit(AstNodeAssign* nodep) override { @@ -204,7 +204,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { putbs("default"); } putfs(nodep, ": begin "); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->stmtsp()); putqs(nodep, "end\n"); } void visit(AstComment* nodep) override { @@ -326,14 +326,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { iterateAndNextConstNull(nodep->incsp()); } puts(") begin\n"); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->stmtsp()); putqs(nodep, "end\n"); } void visit(AstRepeat* nodep) override { putfs(nodep, "repeat ("); iterateAndNextConstNull(nodep->countp()); puts(") begin\n"); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->stmtsp()); putfs(nodep, "end\n"); } void visit(AstWhile* nodep) override { @@ -341,7 +341,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { putfs(nodep, "while ("); iterateAndNextConstNull(nodep->condp()); puts(") begin\n"); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->stmtsp()); iterateAndNextConstNull(nodep->incsp()); iterateAndNextConstNull(nodep->precondsp()); // Need to recompute before next loop putfs(nodep, "end\n"); @@ -356,7 +356,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { puts("if ("); iterateAndNextConstNull(nodep->condp()); puts(") begin\n"); - iterateAndNextConstNull(nodep->ifsp()); + iterateAndNextConstNull(nodep->thensp()); if (nodep->elsesp()) { putqs(nodep, "end\n"); putqs(nodep, "else begin\n"); @@ -401,22 +401,22 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { void visit(AstScopeName* nodep) override {} void visit(AstCStmt* nodep) override { putfs(nodep, "$_CSTMT("); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->exprsp()); puts(");\n"); } void visit(AstCMath* nodep) override { putfs(nodep, "$_CMATH("); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->exprsp()); puts(");\n"); } void visit(AstUCStmt* nodep) override { putfs(nodep, "$c("); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->exprsp()); puts(");\n"); } void visit(AstUCFunc* nodep) override { putfs(nodep, "$c("); - iterateAndNextConstNull(nodep->bodysp()); + iterateAndNextConstNull(nodep->exprsp()); puts(")"); } @@ -521,9 +521,9 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { putbs("("); iterateAndNextConstNull(nodep->condp()); putfs(nodep, " ? "); - iterateAndNextConstNull(nodep->expr1p()); + iterateAndNextConstNull(nodep->thenp()); putbs(" : "); - iterateAndNextConstNull(nodep->expr2p()); + iterateAndNextConstNull(nodep->elsep()); puts(")"); } void visit(AstRange* nodep) override { diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 85635e31a..9eea581ae 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -306,8 +306,8 @@ private: for (int w = 0; w < nodep->widthWords(); ++w) { addWordAssign(nodep, w, new AstCond{fl, rhsp->condp()->cloneTree(true), - newAstWordSelClone(rhsp->expr1p(), w), - newAstWordSelClone(rhsp->expr2p(), w)}); + newAstWordSelClone(rhsp->thenp(), w), + newAstWordSelClone(rhsp->elsep(), w)}); } return true; } diff --git a/src/V3Force.cpp b/src/V3Force.cpp index ea4c61a02..446869208 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -109,7 +109,7 @@ class ForceConvertVisitor final : public VNVisitor { new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Initial{}}}}; activep->sensesStorep(activep->sensesp()); activep->addStmtsp(new AstInitial{flp, assignp}); - vscp->scopep()->addActivep(activep); + vscp->scopep()->addBlocksp(activep); } { // Add the combinational override @@ -127,7 +127,7 @@ class ForceConvertVisitor final : public VNVisitor { new AstSenTree{flp, new AstSenItem{flp, AstSenItem::Combo{}}}}; activep->sensesStorep(activep->sensesp()); activep->addStmtsp(new AstAssignW{flp, lhsp, rhsp}); - vscp->scopep()->addActivep(activep); + vscp->scopep()->addBlocksp(activep); } } }; diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index c65e1d3fe..c4695ec28 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -921,7 +921,7 @@ private: if (m_dedupable) { if (!m_always) { m_always = true; - iterateAndNextNull(alwaysp->bodysp()); + iterateAndNextNull(alwaysp->stmtsp()); } else { m_dedupable = false; } @@ -936,7 +936,7 @@ private: if (m_always && !m_ifCondp && !ifp->elsesp()) { // we're under an always, this is the first IF, and there's no else m_ifCondp = ifp->condp(); - iterateAndNextNull(ifp->ifsp()); + iterateAndNextNull(ifp->thensp()); } else { m_dedupable = false; } diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 40327384b..d6d4d11f5 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -76,13 +76,13 @@ private: // ASSIGN(VARREF(inpclk), VARREF(var)) AstVar* const newvarp = new AstVar(varp->fileline(), VVarType::MODULETEMP, newvarname, varp); - m_topModp->addStmtp(newvarp); + m_topModp->addStmtsp(newvarp); AstVarScope* const newvscp = new AstVarScope(vscp->fileline(), m_scopetopp, newvarp); - m_scopetopp->addVarp(newvscp); + m_scopetopp->addVarsp(newvscp); AstAssign* const asninitp = new AstAssign( vscp->fileline(), new AstVarRef(vscp->fileline(), newvscp, VAccess::WRITE), new AstVarRef(vscp->fileline(), vscp, VAccess::READ)); - m_scopetopp->addFinalClkp(asninitp); + m_scopetopp->addFinalClksp(asninitp); // vscp->user2p(newvscp); } diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 277531647..cacca2901 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -294,15 +294,15 @@ private: UASSERT_OBJ(exprconstp || exprvarrefp, nodep, "Unknown interconnect type; pinReconnectSimple should have cleared up"); if (exprconstp) { - m_modp->addStmtp(new AstAssignW(flp, new AstVarRef(flp, nodep, VAccess::WRITE), - exprconstp->cloneTree(false))); + m_modp->addStmtsp(new AstAssignW(flp, new AstVarRef(flp, nodep, VAccess::WRITE), + exprconstp->cloneTree(false))); } else if (nodep->user3()) { // Public variable at the lower module end - we need to make sure we propagate // the logic changes up and down; if we aliased, we might // remove the change detection on the output variable. UINFO(9, "public pin assign: " << exprvarrefp << endl); UASSERT_OBJ(!nodep->isNonOutput(), nodep, "Outputs only - inputs use AssignAlias"); - m_modp->addStmtp( + m_modp->addStmtsp( new AstAssignW(flp, new AstVarRef(flp, exprvarrefp->varp(), VAccess::WRITE), new AstVarRef(flp, nodep, VAccess::READ))); } else if (nodep->isSigPublic() && VN_IS(nodep->dtypep(), UnpackArrayDType)) { @@ -310,11 +310,11 @@ private: // instead of aliased, because otherwise it will pass V3Slice and invalid // code will be emitted. UINFO(9, "assign to public and unpacked: " << nodep << endl); - m_modp->addStmtp( + m_modp->addStmtsp( new AstAssignW{flp, new AstVarRef{flp, nodep, VAccess::WRITE}, new AstVarRef{flp, exprvarrefp->varp(), VAccess::READ}}); } else if (nodep->isIfaceRef()) { - m_modp->addStmtp( + m_modp->addStmtsp( new AstAssignVarScope(flp, new AstVarRef(flp, nodep, VAccess::WRITE), new AstVarRef(flp, exprvarrefp->varp(), VAccess::READ))); FileLine* const flbp = exprvarrefp->varp()->fileline(); @@ -323,7 +323,7 @@ private: } else { // Do to inlining child's variable now within the same // module, so a AstVarRef not AstVarXRef below - m_modp->addStmtp( + m_modp->addStmtsp( new AstAssignAlias(flp, new AstVarRef(flp, nodep, VAccess::WRITE), new AstVarRef(flp, exprvarrefp->varp(), VAccess::READ))); FileLine* const flbp = exprvarrefp->varp()->fileline(); @@ -423,16 +423,16 @@ private: // If there's a %m in the display text, we add a special node that will contain the name() // Similar code in V3Begin // To keep correct visual order, must add before other Text's - AstNode* afterp = nodep->scopeAttrp(); + AstText* afterp = nodep->scopeAttrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeAttrp( + nodep->addScopeAttrp( new AstText{nodep->fileline(), std::string{"__DOT__"} + m_cellp->name()}); - if (afterp) nodep->scopeAttrp(afterp); + if (afterp) nodep->addScopeAttrp(afterp); afterp = nodep->scopeEntrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeEntrp( + nodep->addScopeEntrp( new AstText{nodep->fileline(), std::string{"__DOT__"} + m_cellp->name()}); - if (afterp) nodep->scopeEntrp(afterp); + if (afterp) nodep->addScopeEntrp(afterp); iterateChildren(nodep); } void visit(AstCoverDecl* nodep) override { @@ -566,7 +566,7 @@ private: // Move statements under the module we are inlining into if (AstNode* const stmtsp = newmodp->stmtsp()) { stmtsp->unlinkFrBackWithNext(); - m_modp->addStmtp(stmtsp); + m_modp->addStmtsp(stmtsp); } // Clear any leftover ports, etc VL_DO_DANGLING(newmodp->deleteTree(), newmodp); @@ -649,7 +649,7 @@ private: } if (VN_IS(nodep->modp(), Iface)) { - nodep->addIntfRefp(new AstIntfRef{nodep->fileline(), m_scope}); + nodep->addIntfRefsp(new AstIntfRef{nodep->fileline(), m_scope}); } { AstNodeModule* const modp = nodep->modp(); @@ -666,7 +666,7 @@ private: if ((cellp = VN_CAST(fromVarp->user1p(), Cell)) || (cellp = irdtp->cellp())) { varp->user1p(cellp); const string alias = m_scope + "__DOT__" + pinp->name(); - cellp->addIntfRefp(new AstIntfRef(pinp->fileline(), alias)); + cellp->addIntfRefsp(new AstIntfRef(pinp->fileline(), alias)); } } @@ -695,7 +695,7 @@ private: string alias; if (!m_scope.empty()) alias = m_scope + "__DOT__"; alias += varlp->name(); - cellp->addIntfRefp(new AstIntfRef(varlp->fileline(), alias)); + cellp->addIntfRefsp(new AstIntfRef(varlp->fileline(), alias)); } //-------------------- void visit(AstNodeMath*) override {} // Accelerate diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 41a0e9ef2..4a394fe80 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -170,7 +170,7 @@ private: UINFO(8, "ifsp:\n"); m_instrCount = 0; - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); uint32_t ifCount = m_instrCount; if (nodep->branchPred().unlikely()) ifCount = 0; @@ -185,7 +185,7 @@ private: if (nodep->elsesp()) nodep->elsesp()->user4(0); // Don't dump it } else { m_instrCount = savedCount + elseCount; - if (nodep->ifsp()) nodep->ifsp()->user4(0); // Don't dump it + if (nodep->thensp()) nodep->thensp()->user4(0); // Don't dump it } } void visit(AstNodeCond* nodep) override { @@ -197,20 +197,20 @@ private: UINFO(8, "?\n"); m_instrCount = 0; - iterateAndNextNull(nodep->expr1p()); + iterateAndNextNull(nodep->thenp()); const uint32_t ifCount = m_instrCount; UINFO(8, ":\n"); m_instrCount = 0; - iterateAndNextNull(nodep->expr2p()); + iterateAndNextNull(nodep->elsep()); const uint32_t elseCount = m_instrCount; if (ifCount < elseCount) { m_instrCount = savedCount + elseCount; - if (nodep->expr1p()) nodep->expr1p()->user4(0); // Don't dump it + if (nodep->thenp()) nodep->thenp()->user4(0); // Don't dump it } else { m_instrCount = savedCount + ifCount; - if (nodep->expr2p()) nodep->expr2p()->user4(0); // Don't dump it + if (nodep->elsep()) nodep->elsep()->user4(0); // Don't dump it } } void visit(AstActive* nodep) override { diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 5ae48ebd4..62459ba84 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -340,7 +340,7 @@ private: LifeBlock* const elseLifep = new LifeBlock(prevLifep, m_statep); { m_lifep = ifLifep; - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); } { m_lifep = elseLifep; @@ -375,7 +375,7 @@ private: } { m_lifep = bodyLifep; - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->incsp()); } m_lifep = prevLifep; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 393013026..5057a4090 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -268,7 +268,7 @@ private: { m_modp = modp; // Important that this adds to end, as next iterate assumes does all cells - modp->addStmtp(cellsp); + modp->addStmtsp(cellsp); iterateAndNextNull(cellsp); } } @@ -321,7 +321,7 @@ private: otherModp->recursiveClone(true); // user1 etc will retain its pre-clone value cellmodp->user2p(otherModp); - v3Global.rootp()->addModulep(otherModp); + v3Global.rootp()->addModulesp(otherModp); new V3GraphEdge(&m_graph, vertex(cellmodp), vertex(otherModp), 1, false); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 2825daaf7..57f9fca83 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -994,7 +994,7 @@ class LinkDotFindVisitor final : public VNVisitor { if (!nodep->isExternDef()) { // Move it to proper spot under the target class nodep->unlinkFrBack(); - classp->addStmtp(nodep); + classp->addStmtsp(nodep); nodep->isExternDef(true); // So we check there's a matching extern nodep->classOrPackagep()->unlinkFrBack()->deleteTree(); } @@ -1030,7 +1030,7 @@ class LinkDotFindVisitor final : public VNVisitor { newvarp->funcReturn(true); newvarp->trace(false); // Not user visible newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); - nodep->addFvarp(newvarp); + nodep->fvarp(newvarp); // Explicit insert required, as the var name shadows the upper level's task name m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, nullptr /*classOrPackagep*/); @@ -1938,7 +1938,7 @@ private: VFlagLogicPacked{}, 1); newp->trace(modp->modTrace()); nodep->varp(newp); - modp->addStmtp(newp); + modp->addStmtsp(newp); // Link it to signal list, must add the variable under the module; // current scope might be lower now m_statep->insertSym(moduleSymp, newp->name(), newp, nullptr /*classOrPackagep*/); @@ -3097,7 +3097,7 @@ private: nodep->classOrPackagep(foundp->classOrPackagep()); } } else if (AstClass* const defp = foundp ? VN_AS(foundp->nodep(), Class) : nullptr) { - AstNode* const paramsp = nodep->paramsp(); + AstPin* const paramsp = nodep->paramsp(); if (paramsp) paramsp->unlinkFrBackWithNext(); AstClassRefDType* const newp = new AstClassRefDType{nodep->fileline(), defp, paramsp}; diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index a19b1e282..d0e852849 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -106,7 +106,7 @@ private: iterateAndNextNull(nodep->condp()); // Body insert just before themselves m_insStmtp = nullptr; // First thing should be new statement - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->incsp()); // Done the loop m_insStmtp = nullptr; // Next thing should be new statement @@ -131,7 +131,7 @@ private: m_insStmtp = nodep; iterateAndNextNull(nodep->condp()); m_insStmtp = nullptr; - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); iterateAndNextNull(nodep->elsesp()); m_insStmtp = nullptr; } @@ -143,7 +143,7 @@ private: iterateAndNextNull(nodep->condsp()); } m_insStmtp = nullptr; // Next thing should be new statement - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); } void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc( diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index ef40653a8..2c5802704 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -69,7 +69,7 @@ private: underp = VN_AS(nodep, NodeFTask)->stmtsp(); } else if (VN_IS(nodep, Foreach)) { if (endOfIter) { - underp = VN_AS(nodep, Foreach)->bodysp(); + underp = VN_AS(nodep, Foreach)->stmtsp(); } else { underp = nodep; under_and_next = false; // IE we skip the entire foreach @@ -78,7 +78,7 @@ private: if (endOfIter) { // Note we jump to end of bodysp; a FOR loop has its // increment under incsp() which we don't skip - underp = VN_AS(nodep, While)->bodysp(); + underp = VN_AS(nodep, While)->stmtsp(); } else { underp = nodep; under_and_next = false; // IE we skip the entire while @@ -157,7 +157,7 @@ private: AstVar* const varp = new AstVar(nodep->fileline(), VVarType::BLOCKTEMP, name, nodep->findSigned32DType()); varp->usedLoopIdx(true); - m_modp->addStmtp(varp); + m_modp->addStmtsp(varp); AstNode* initsp = new AstAssign( nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::WRITE), countp); AstNode* const decp = new AstAssign( @@ -167,7 +167,7 @@ private: AstNode* const zerosp = new AstConst(nodep->fileline(), AstConst::Signed32(), 0); AstNode* const condp = new AstGtS( nodep->fileline(), new AstVarRef(nodep->fileline(), varp, VAccess::READ), zerosp); - AstNode* const bodysp = nodep->bodysp(); + AstNode* const bodysp = nodep->stmtsp(); if (bodysp) bodysp->unlinkFrBackWithNext(); AstNode* newp = new AstWhile(nodep->fileline(), condp, bodysp, decp); initsp = initsp->addNext(newp); @@ -178,7 +178,7 @@ private: void visit(AstWait* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait statements"); // Statements we'll just execute immediately; equivalent to if they followed this - if (AstNode* const bodysp = nodep->bodysp()) { + if (AstNode* const bodysp = nodep->stmtsp()) { bodysp->unlinkFrBackWithNext(); nodep->replaceWith(bodysp); } else { @@ -195,7 +195,7 @@ private: m_loopInc = false; iterateAndNextNull(nodep->precondsp()); iterateAndNextNull(nodep->condp()); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); m_loopInc = true; iterateAndNextNull(nodep->incsp()); } @@ -204,7 +204,7 @@ private: VL_RESTORER(m_loopp); { m_loopp = nodep; - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); } } void visit(AstReturn* nodep) override { diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 3e9130ed3..9c88973f6 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -76,7 +76,7 @@ void V3LinkLevel::modSortByLevel() { UINFO(9, "modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666 for (AstNodeModule* nodep : mods) nodep->unlinkFrBack(); UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work"); - for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulep(nodep); + for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulesp(nodep); UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666 V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } @@ -154,7 +154,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { newmodp->modPublic(true); newmodp->protect(false); newmodp->timeunit(oldmodp->timeunit()); - rootp->addModulep(newmodp); + rootp->addModulesp(newmodp); // TODO the module creation above could be done after linkcells, but // the rest must be done after data type resolution @@ -170,7 +170,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { // with module names/"v" modp->name(), modp->name(), nullptr, nullptr, nullptr); cellp->modp(modp); - newmodp->addStmtp(cellp); + newmodp->addStmtsp(cellp); } } @@ -213,7 +213,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { (!v3Global.opt.l2Name().empty() ? v3Global.opt.l2Name() : oldmodp->name()), oldmodp->name(), nullptr, nullptr, nullptr); cellp->modp(oldmodp); - newmodp->addStmtp(cellp); + newmodp->addStmtsp(cellp); // Add pins for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { @@ -229,7 +229,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { AstVar* const varp = oldvarp->cloneTree(false); varp->name(name); varp->protect(false); - newmodp->addStmtp(varp); + newmodp->addStmtsp(varp); varp->sigPublic(true); // User needs to be able to get to it... if (oldvarp->isIO()) { oldvarp->primaryIO(false); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index b0a8e4001..1fff33a56 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -372,7 +372,7 @@ private: // lvalue is true, because we know we have a verilator public_flat_rw // but someday we may be more general const bool lvalue = m_varp->isSigUserRWPublic(); - nodep->addStmtp( + nodep->addStmtsp( new AstVarRef(nodep->fileline(), m_varp, lvalue ? VAccess::WRITE : VAccess::READ)); } } @@ -596,7 +596,7 @@ private: sensesp->unlinkFrBackWithNext(); alwaysp->sensesp(sensesp); } - if (nodep->stmtsp()) alwaysp->addStmtp(nodep->stmtsp()->unlinkFrBackWithNext()); + if (nodep->stmtsp()) alwaysp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext()); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index c7dc0ef6f..d5157b0c9 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -86,7 +86,7 @@ private: // Initial assignments under function/tasks can just be simple // assignments without the initial if (m_ftaskp) { - VL_DO_DANGLING(nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()), nodep); + VL_DO_DANGLING(nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext()), nodep); } } void visit(AstNodeCoverOrAssert* nodep) override { @@ -483,7 +483,7 @@ private: } varoutp = varp; // Tie off - m_modp->addStmtp( + m_modp->addStmtsp( new AstAssignW(varp->fileline(), new AstVarRef(varp->fileline(), varp, VAccess::WRITE), new AstConst(varp->fileline(), AstConst::BitFalse()))); diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 3dd8fe02e..1f99e4570 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -565,7 +565,7 @@ private: return false; } if (const AstNodeCond* const condp = VN_CAST(nodep, NodeCond)) { - return yieldsOneOrZero(condp->expr1p()) && yieldsOneOrZero(condp->expr2p()); + return yieldsOneOrZero(condp->thenp()) && yieldsOneOrZero(condp->elsep()); } if (const AstCCast* const castp = VN_CAST(nodep, CCast)) { // Cast never sign extends @@ -593,7 +593,7 @@ private: return new AstConst{rhsp->fileline(), AstConst::BitTrue{}, condTrue}; } else if (const AstNodeCond* const condp = extractCondFromRhs(rhsp)) { AstNode* const resp - = condTrue ? condp->expr1p()->unlinkFrBack() : condp->expr2p()->unlinkFrBack(); + = condTrue ? condp->thenp()->unlinkFrBack() : condp->elsep()->unlinkFrBack(); if (condp == rhsp) return resp; if (const AstAnd* const andp = VN_CAST(rhsp, And)) { UASSERT_OBJ(andp->rhsp() == condp, rhsp, "Should not try to fold this"); @@ -676,7 +676,7 @@ private: // Construct the new RHSs and add to branches thenp->rhsp(foldAndUnlink(rhsp, true)); elsep->rhsp(foldAndUnlink(rhsp, false)); - resultp->addIfsp(thenp); + resultp->addThensp(thenp); resultp->addElsesp(elsep); // Cleanup VL_DO_DANGLING(rhsp->deleteTree(), rhsp); @@ -684,8 +684,8 @@ private: AstNodeIf* const ifp = VN_AS(currp, NodeIf); UASSERT_OBJ(ifp, currp, "Must be AstNodeIf"); // Move branch contents under new if - if (AstNode* const listp = ifp->ifsp()) { - resultp->addIfsp(listp->unlinkFrBackWithNext()); + if (AstNode* const listp = ifp->thensp()) { + resultp->addThensp(listp->unlinkFrBackWithNext()); } if (AstNode* const listp = ifp->elsesp()) { resultp->addElsesp(listp->unlinkFrBackWithNext()); @@ -695,7 +695,7 @@ private: } } while (nextp); // Merge the branches of the resulting AstIf after re-analysis - if (resultp->ifsp()) m_workQueuep->push(resultp->ifsp()); + if (resultp->thensp()) m_workQueuep->push(resultp->thensp()); if (resultp->elsesp()) m_workQueuep->push(resultp->elsesp()); } else if (AstNodeIf* const ifp = VN_CAST(m_mgFirstp, NodeIf)) { // There was nothing to merge this AstNodeIf with, so try to merge its branches. @@ -711,7 +711,7 @@ private: AstNode::user2ClearTree(); // Merge recursively within the branches of an un-merged AstNodeIF if (recursivep) { - iterateAndNextNull(recursivep->ifsp()); + iterateAndNextNull(recursivep->thensp()); iterateAndNextNull(recursivep->elsesp()); // Close a pending merge to ensure merge state is // reset as expected at the end of this function @@ -840,7 +840,7 @@ private: // Check if mergeable if (!checkOrMakeMergeable(nodep)) { // If not mergeable, try to merge the branches - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); iterateAndNextNull(nodep->elsesp()); return; } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 539d6b6fa..5bbb46a68 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -1789,7 +1789,7 @@ void OrderProcess::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d << " s=" << cvtToHex(scopep) << " " << lvertexp << endl); AstActive* const newActivep = processMoveOneLogic(lvertexp, m_pomNewFuncp /*ref*/, m_pomNewStmts /*ref*/); - if (newActivep) m_scopetop.addActivep(newActivep); + if (newActivep) m_scopetop.addBlocksp(newActivep); processMoveDoneOne(vertexp); } @@ -1811,7 +1811,7 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp, // procedures. Everything else is handled in one go AstNodeProcedure* const procp = VN_CAST(nodep, NodeProcedure); if (procp && !v3Global.opt.profCFuncs()) { - nodep = procp->bodysp(); + nodep = procp->stmtsp(); pushDeletep(procp); } @@ -1831,7 +1831,7 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp, newFuncpr->isLoose(true); newStmtsr = 0; if (domainp->hasInitial() || domainp->hasSettle()) newFuncpr->slow(true); - scopep->addActivep(newFuncpr); + scopep->addBlocksp(newFuncpr); // Create top call to it AstCCall* const callp = new AstCCall(nodep->fileline(), newFuncpr); // Where will we be adding the call? @@ -1886,7 +1886,7 @@ void OrderProcess::processMTasksInitial(InitialLogicE logic_type) { } AstActive* const newActivep = processMoveOneLogic(initp, initCFunc /*ref*/, initStmts /*ref*/); - if (newActivep) m_scopetop.addActivep(newActivep); + if (newActivep) m_scopetop.addBlocksp(newActivep); } } @@ -1966,7 +1966,7 @@ void OrderProcess::processMTasks() { // of the MTask graph. FileLine* const rootFlp = v3Global.rootp()->fileline(); AstExecGraph* const execGraphp = new AstExecGraph{rootFlp, "eval"}; - m_scopetop.addActivep(execGraphp); + m_scopetop.addBlocksp(execGraphp); // Create CFuncs and bodies for each MTask. GraphStream emit_mtasks(&mtasks); @@ -2018,7 +2018,7 @@ void OrderProcess::processMTasks() { const MTaskState& fromState = mtaskStates[fromp->id()]; new V3GraphEdge(depGraphp, fromState.m_execMTaskp, state.m_execMTaskp, 1); } - execGraphp->addMTaskBodyp(bodyp); + execGraphp->addMTaskBodiesp(bodyp); } } diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 3a21266fc..4c372895e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -1132,7 +1132,7 @@ class ParamVisitor final : public VNVisitor { // NOT recurse the body. V3Const::constifyGenerateParamsEdit(nodep->condp()); // condp may change if (const AstConst* const constp = VN_CAST(nodep->condp(), Const)) { - if (AstNode* const keepp = (constp->isZero() ? nodep->elsesp() : nodep->ifsp())) { + if (AstNode* const keepp = (constp->isZero() ? nodep->elsesp() : nodep->thensp())) { keepp->unlinkFrBackWithNext(); nodep->replaceWith(keepp); } else { @@ -1150,9 +1150,7 @@ class ParamVisitor final : public VNVisitor { //! expression, since this is currently restricted to simple comparisons. If we ever do //! move to more generic constant expressions, such code will be needed here. void visit(AstBegin* nodep) override { - if (nodep->genforp()) { - AstGenFor* const forp = VN_AS(nodep->genforp(), GenFor); - UASSERT_OBJ(forp, nodep, "Non-GENFOR under generate-for BEGIN"); + if (AstGenFor* const forp = VN_AS(nodep->genforp(), GenFor)) { // We should have a GENFOR under here. We will be replacing the begin, // so process here rather than at the generate to avoid iteration problems UINFO(9, " BEGIN " << nodep << endl); @@ -1211,7 +1209,7 @@ class ParamVisitor final : public VNVisitor { if (const AstConst* const ccondp = VN_CAST(ep, Const)) { V3Number match(nodep, 1); match.opEq(ccondp->num(), exprp->num()); - if (!keepp && match.isNeqZero()) keepp = itemp->bodysp(); + if (!keepp && match.isNeqZero()) keepp = itemp->stmtsp(); } else { itemp->v3error("Generate Case item does not evaluate to constant"); } @@ -1222,7 +1220,7 @@ class ParamVisitor final : public VNVisitor { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp = VN_AS(itemp->nextp(), CaseItem)) { if (itemp->isDefault()) { - if (!keepp) keepp = itemp->bodysp(); + if (!keepp) keepp = itemp->stmtsp(); } } // Replace @@ -1269,7 +1267,7 @@ public: }); // Re-insert modules - for (AstNodeModule* const modp : modps) netlistp->addModulep(modp); + for (AstNodeModule* const modp : modps) netlistp->addModulesp(modp); } } ~ParamVisitor() override = default; diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 37da5a1fc..db0a0f422 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -283,7 +283,7 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i if (errmsg != "") return; // Threw error already // Create fake node for later error reporting AstNodeModule* const nodep = new AstNotFoundModule(fileline, modname); - v3Global.rootp()->addModulep(nodep); + v3Global.rootp()->addModulesp(nodep); return; } diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index f3ffaf56b..ea3855ddd 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -3051,7 +3051,7 @@ static void addMTaskToFunction(const ThreadSchedule& schedule, const uint32_t th AstVar* const varp = new AstVar(fl, VVarType::MODULETEMP, name, mtaskStateDtypep); varp->valuep(new AstConst(fl, nDependencies)); varp->protect(false); // Do not protect as we still have references in AstText - modp->addStmtp(varp); + modp->addStmtsp(varp); // For now, reference is still via text bashing addStrStmt("vlSelf->" + name + +".waitUntilUpstreamDone(even_cycle);\n"); } @@ -3112,7 +3112,7 @@ static const std::vector createThreadFunctions(const ThreadSchedule& const uint32_t threadId = schedule.threadId(thread.front()); const string name{"__Vthread__" + tag + "__" + cvtToStr(threadId)}; AstCFunc* const funcp = new AstCFunc(fl, name, nullptr, "void"); - modp->addStmtp(funcp); + modp->addStmtsp(funcp); funcps.push_back(funcp); funcp->isStatic(true); // Uses void self pointer, so static and hand rolled funcp->isLoose(true); @@ -3140,7 +3140,7 @@ static const std::vector createThreadFunctions(const ThreadSchedule& = new AstVar(fl, VVarType::MODULETEMP, "__Vm_mtaskstate_final", mtaskStateDtypep); varp->valuep(new AstConst(fl, funcps.size())); varp->protect(false); // Do not protect as we still have references in AstText - modp->addStmtp(varp); + modp->addStmtsp(varp); return funcps; } diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 842b8d720..54b1324c4 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -176,7 +176,7 @@ private: iterateAndNextNull(nodep->condp()); m_inWhilep = nullptr; startStatement(nodep); - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->incsp()); m_stmtp = nullptr; } @@ -329,7 +329,7 @@ private: } void visit(AstNodeCond* nodep) override { iterateChildren(nodep); - if (nodep->expr1p()->isWide() && !VN_IS(nodep->condp(), Const) + if (nodep->thenp()->isWide() && !VN_IS(nodep->condp(), Const) && !VN_IS(nodep->condp(), VarRef)) { // We're going to need the expression several times in the expanded code, // so might as well make it a common expression diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 21abed5a7..734695c2f 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -95,7 +95,7 @@ private: } void addComment(AstTextBlock* txtp, FileLine* fl, const string& comment) { - txtp->addNodep(new AstComment{fl, comment}); + txtp->addNodesp(new AstComment{fl, comment}); } void hashComment(AstTextBlock* txtp, FileLine* fl) { @@ -143,7 +143,7 @@ private: // Module declaration m_modPortsp = new AstTextBlock{fl, "module " + m_libName + " (\n", false, true}; - txtp->addNodep(m_modPortsp); + txtp->addNodesp(m_modPortsp); txtp->addText(fl, ");\n\n"); // Timescale @@ -177,7 +177,7 @@ private: "(\n", false, true}; m_comboPortsp->addText(fl, "chandle handle__V\n"); - txtp->addNodep(m_comboPortsp); + txtp->addNodesp(m_comboPortsp); txtp->addText(fl, ");\n\n"); seqComment(txtp, fl); if (m_hasClk) { @@ -187,7 +187,7 @@ private: "(\n", false, true}; m_seqPortsp->addText(fl, "chandle handle__V\n"); - txtp->addNodep(m_seqPortsp); + txtp->addNodesp(m_seqPortsp); txtp->addText(fl, ");\n\n"); } comboIgnoreComment(txtp, fl); @@ -197,7 +197,7 @@ private: "(\n", false, true}; m_comboIgnorePortsp->addText(fl, "chandle handle__V\n"); - txtp->addNodep(m_comboIgnorePortsp); + txtp->addNodesp(m_comboIgnorePortsp); txtp->addText(fl, ");\n\n"); finalComment(txtp, fl); @@ -227,17 +227,17 @@ private: txtp->addText(fl, "\n"); m_comboDeclsp = new AstTextBlock{fl}; - txtp->addNodep(m_comboDeclsp); + txtp->addNodesp(m_comboDeclsp); m_seqDeclsp = new AstTextBlock{fl}; - txtp->addNodep(m_seqDeclsp); + txtp->addNodesp(m_seqDeclsp); m_tmpDeclsp = new AstTextBlock{fl}; - txtp->addNodep(m_tmpDeclsp); + txtp->addNodesp(m_tmpDeclsp); // CPP hash value addComment(txtp, fl, "Hash value to make sure this file and the corresponding"); addComment(txtp, fl, "library agree"); m_hashValuep = new AstTextBlock{fl, "localparam int protectlib_hash__V = 32'd"}; - txtp->addNodep(m_hashValuep); + txtp->addNodesp(m_hashValuep); txtp->addText(fl, "\n"); // Initial @@ -256,7 +256,7 @@ private: + m_libName + "_protectlib_combo_update(\n", false, true}; m_comboParamsp->addText(fl, "handle__V\n"); - txtp->addNodep(m_comboParamsp); + txtp->addNodesp(m_comboParamsp); txtp->addText(fl, ");\n"); txtp->addText(fl, "end\n\n"); @@ -264,21 +264,21 @@ private: if (m_hasClk) { addComment(txtp, fl, "Evaluate clock edges"); m_clkSensp = new AstTextBlock{fl, "always @(", false, true}; - txtp->addNodep(m_clkSensp); + txtp->addNodesp(m_clkSensp); txtp->addText(fl, ") begin\n"); m_comboIgnoreParamsp = new AstTextBlock{fl, m_libName + "_protectlib_combo_ignore(\n", false, true}; m_comboIgnoreParamsp->addText(fl, "handle__V\n"); - txtp->addNodep(m_comboIgnoreParamsp); + txtp->addNodesp(m_comboIgnoreParamsp); txtp->addText(fl, ");\n"); m_seqParamsp = new AstTextBlock{ fl, "last_seq_seqnum__V <= " + m_libName + "_protectlib_seq_update(\n", false, true}; m_seqParamsp->addText(fl, "handle__V\n"); - txtp->addNodep(m_seqParamsp); + txtp->addNodesp(m_seqParamsp); txtp->addText(fl, ");\n"); m_nbAssignsp = new AstTextBlock{fl}; - txtp->addNodep(m_nbAssignsp); + txtp->addNodesp(m_nbAssignsp); txtp->addText(fl, "end\n\n"); } @@ -288,13 +288,13 @@ private: if (m_hasClk) { m_seqAssignsp = new AstTextBlock{fl, "if (last_seq_seqnum__V > " "last_combo_seqnum__V) begin\n"}; - txtp->addNodep(m_seqAssignsp); + txtp->addNodesp(m_seqAssignsp); m_comboAssignsp = new AstTextBlock{fl, "end\nelse begin\n"}; - txtp->addNodep(m_comboAssignsp); + txtp->addNodesp(m_comboAssignsp); txtp->addText(fl, "end\n"); } else { m_comboAssignsp = new AstTextBlock{fl, ""}; - txtp->addNodep(m_comboAssignsp); + txtp->addNodesp(m_comboAssignsp); } txtp->addText(fl, "end\n\n"); @@ -341,7 +341,7 @@ private: + "_protectlib_check_hash" "(int protectlib_hash__V) {\n"); m_cHashValuep = new AstTextBlock{fl, "const int expected_hash__V = "}; - txtp->addNodep(m_cHashValuep); + txtp->addNodesp(m_cHashValuep); txtp->addText(fl, /**/ "if (protectlib_hash__V != expected_hash__V) {\n"); txtp->addText(fl, /****/ "fprintf(stderr, \"%%Error: cannot use " + m_libName + " library, " @@ -364,13 +364,13 @@ private: m_cComboParamsp = new AstTextBlock{ fl, "long long " + m_libName + "_protectlib_combo_update(\n", false, true}; m_cComboParamsp->addText(fl, "void* vhandlep__V\n"); - txtp->addNodep(m_cComboParamsp); + txtp->addNodesp(m_cComboParamsp); txtp->addText(fl, ")\n"); m_cComboInsp = new AstTextBlock{fl, "{\n"}; castPtr(fl, m_cComboInsp); - txtp->addNodep(m_cComboInsp); + txtp->addNodesp(m_cComboInsp); m_cComboOutsp = new AstTextBlock{fl, "handlep__V->eval();\n"}; - txtp->addNodep(m_cComboOutsp); + txtp->addNodesp(m_cComboOutsp); txtp->addText(fl, "return handlep__V->m_seqnum++;\n"); txtp->addText(fl, "}\n\n"); @@ -379,13 +379,13 @@ private: m_cSeqParamsp = new AstTextBlock{ fl, "long long " + m_libName + "_protectlib_seq_update(\n", false, true}; m_cSeqParamsp->addText(fl, "void* vhandlep__V\n"); - txtp->addNodep(m_cSeqParamsp); + txtp->addNodesp(m_cSeqParamsp); txtp->addText(fl, ")\n"); m_cSeqClksp = new AstTextBlock{fl, "{\n"}; castPtr(fl, m_cSeqClksp); - txtp->addNodep(m_cSeqClksp); + txtp->addNodesp(m_cSeqClksp); m_cSeqOutsp = new AstTextBlock{fl, "handlep__V->eval();\n"}; - txtp->addNodep(m_cSeqOutsp); + txtp->addNodesp(m_cSeqOutsp); txtp->addText(fl, "return handlep__V->m_seqnum++;\n"); txtp->addText(fl, "}\n\n"); } @@ -394,7 +394,7 @@ private: m_cIgnoreParamsp = new AstTextBlock{ fl, "void " + m_libName + "_protectlib_combo_ignore(\n", false, true}; m_cIgnoreParamsp->addText(fl, "void* vhandlep__V\n"); - txtp->addNodep(m_cIgnoreParamsp); + txtp->addNodesp(m_cIgnoreParamsp); txtp->addText(fl, ")\n"); txtp->addText(fl, "{ }\n\n"); @@ -448,7 +448,7 @@ private: void handleClock(AstVar* varp) { FileLine* const fl = varp->fileline(); handleInput(varp); - m_seqPortsp->addNodep(varp->cloneTree(false)); + m_seqPortsp->addNodesp(varp->cloneTree(false)); if (m_hasClk) { m_seqParamsp->addText(fl, varp->name() + "\n"); m_clkSensp->addText(fl, "posedge " + varp->name() + " or negedge " + varp->name()); @@ -460,30 +460,30 @@ private: void handleDataInput(AstVar* varp) { FileLine* const fl = varp->fileline(); handleInput(varp); - m_comboPortsp->addNodep(varp->cloneTree(false)); + m_comboPortsp->addNodesp(varp->cloneTree(false)); m_comboParamsp->addText(fl, varp->name() + "\n"); - m_comboIgnorePortsp->addNodep(varp->cloneTree(false)); + m_comboIgnorePortsp->addNodesp(varp->cloneTree(false)); if (m_hasClk) m_comboIgnoreParamsp->addText(fl, varp->name() + "\n"); m_cComboParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); m_cComboInsp->addText(fl, cInputConnection(varp)); m_cIgnoreParamsp->addText(fl, varp->dpiArgType(true, false) + "\n"); } - void handleInput(AstVar* varp) { m_modPortsp->addNodep(varp->cloneTree(false)); } + void handleInput(AstVar* varp) { m_modPortsp->addNodesp(varp->cloneTree(false)); } static void addLocalVariable(AstTextBlock* textp, AstVar* varp, const char* suffix) { AstVar* const newVarp = new AstVar{varp->fileline(), VVarType::VAR, varp->name() + suffix, varp->dtypep()}; - textp->addNodep(newVarp); + textp->addNodesp(newVarp); } void handleOutput(AstVar* varp) { FileLine* const fl = varp->fileline(); - m_modPortsp->addNodep(varp->cloneTree(false)); - m_comboPortsp->addNodep(varp->cloneTree(false)); + m_modPortsp->addNodesp(varp->cloneTree(false)); + m_comboPortsp->addNodesp(varp->cloneTree(false)); m_comboParamsp->addText(fl, varp->name() + "_combo__V\n"); if (m_hasClk) { - m_seqPortsp->addNodep(varp->cloneTree(false)); + m_seqPortsp->addNodesp(varp->cloneTree(false)); m_seqParamsp->addText(fl, varp->name() + "_tmp__V\n"); } diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 448623a08..7efc30c0f 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -144,7 +144,7 @@ private: varp->isStatic(true); varp->valuep(initp); // Add to root, as don't know module we are in, and aids later structure sharing - v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp); + v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp); UASSERT_OBJ(nodep->itemsp(), nodep, "Enum without items"); for (AstEnumItem* itemp = nodep->itemsp(); itemp; itemp = VN_AS(itemp->nextp(), EnumItem)) { diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index e163bdf8c..4e8690b3e 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -114,7 +114,7 @@ private: AstWhile* const whilep = new AstWhile(fl, condp, nullptr, incp); initp->addNext(whilep); bodyp->replaceWith(initp); - whilep->addBodysp(bodyp); + whilep->addStmtsp(bodyp); // Replace constant index with new loop index AstNode* const offsetp diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 0c4bad466..8077d2959 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -135,7 +135,7 @@ private: if (m_modp->isTop()) { v3Global.rootp()->createTopScope(m_scopep); } else { - m_modp->addStmtp(m_scopep); + m_modp->addStmtsp(m_scopep); } // Copy blocks into this scope @@ -188,7 +188,7 @@ private: UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } void visit(AstAssignAlias* nodep) override { @@ -196,7 +196,7 @@ private: UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } void visit(AstAssignVarScope* nodep) override { @@ -204,7 +204,7 @@ private: UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } void visit(AstAssignW* nodep) override { @@ -212,7 +212,7 @@ private: UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } void visit(AstAlwaysPublic* nodep) override { @@ -220,7 +220,7 @@ private: UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } void visit(AstCoverToggle* nodep) override { @@ -228,7 +228,7 @@ private: UINFO(4, " Move " << nodep << endl); AstNode* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); iterateChildren(clonep); // We iterate under the *clone* } void visit(AstCFunc* nodep) override { @@ -236,7 +236,7 @@ private: UINFO(4, " CFUNC " << nodep << endl); AstCFunc* const clonep = nodep->cloneTree(false); nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); clonep->scopep(m_scopep); // We iterate under the *clone* iterateChildren(clonep); @@ -253,7 +253,7 @@ private: clonep = nodep->cloneTree(false); } nodep->user2p(clonep); - m_scopep->addActivep(clonep); + m_scopep->addBlocksp(clonep); // We iterate under the *clone* iterateChildren(clonep); } @@ -272,7 +272,7 @@ private: } UASSERT_OBJ(m_scopep, nodep, "No scope for var"); m_varScopes.emplace(std::make_pair(nodep, m_scopep), varscp); - m_scopep->addVarp(varscp); + m_scopep->addVarsp(varscp); } } void visit(AstVarRef* nodep) override { @@ -295,14 +295,14 @@ private: // TOP and above will be the user's name(). // Note 'TOP.' is stripped by scopePrettyName // To keep correct visual order, must add before other Text's - AstNode* afterp = nodep->scopeAttrp(); + AstText* afterp = nodep->scopeAttrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeAttrp(new AstText(nodep->fileline(), prefix)); - if (afterp) nodep->scopeAttrp(afterp); + nodep->addScopeAttrp(new AstText(nodep->fileline(), prefix)); + if (afterp) nodep->addScopeAttrp(afterp); afterp = nodep->scopeEntrp(); if (afterp) afterp->unlinkFrBackWithNext(); - nodep->scopeEntrp(new AstText(nodep->fileline(), prefix)); - if (afterp) nodep->scopeEntrp(afterp); + nodep->addScopeEntrp(new AstText(nodep->fileline(), prefix)); + if (afterp) nodep->addScopeEntrp(afterp); iterateChildren(nodep); } void visit(AstScope* nodep) override { diff --git a/src/V3SenTree.h b/src/V3SenTree.h index c140580a0..636476b6f 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -64,7 +64,7 @@ public: // Not found, create a new one AstSenTree* const newSenTreep = senTreep->cloneTree(false); - m_topScopep->addSenTreep(newSenTreep); + m_topScopep->addSenTreesp(newSenTreep); m_trees.emplace(*newSenTreep); return newSenTreep; } diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 98d44a3c8..ee4b23caf 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -513,7 +513,7 @@ private: iterateAndNextNull(nodep->condp()); if (optimizable()) { if (fetchConst(nodep->condp())->num().isNeqZero()) { - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); } else { iterateAndNextNull(nodep->elsesp()); } @@ -647,11 +647,11 @@ private: iterate(nodep->condp()); if (optimizable()) { if (fetchConst(nodep->condp())->num().isNeqZero()) { - iterate(nodep->expr1p()); - newValue(nodep, fetchValue(nodep->expr1p())); + iterate(nodep->thenp()); + newValue(nodep, fetchValue(nodep->thenp())); } else { - iterate(nodep->expr2p()); - newValue(nodep, fetchValue(nodep->expr2p())); + iterate(nodep->elsep()); + newValue(nodep, fetchValue(nodep->elsep())); } } } @@ -835,7 +835,7 @@ private: V3Number match{nodep, 1}; match.opEq(fetchConst(nodep->exprp())->num(), fetchConst(ep)->num()); if (match.isNeqZero()) { - iterateAndNextNull(itemp->bodysp()); + iterateAndNextNull(itemp->stmtsp()); hit = true; } } @@ -847,7 +847,7 @@ private: itemp = VN_AS(itemp->nextp(), CaseItem)) { if (hit) break; if (!hit && itemp->isDefault()) { - iterateAndNextNull(itemp->bodysp()); + iterateAndNextNull(itemp->stmtsp()); hit = true; } } @@ -917,7 +917,7 @@ private: if (!fetchConst(nodep->condp())->num().isNeqZero()) { // break; } - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->incsp()); if (loops++ > unrollCount() * 16) { clearOptimizable(nodep, "Loop unrolling took too long; probably this is an" @@ -952,7 +952,7 @@ private: if (!fetchConst(nodep->condp())->num().isNeqZero()) { // break; } - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); if (jumpingOver(nodep)) break; iterateAndNextNull(nodep->incsp()); if (jumpingOver(nodep)) break; diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index f362c3cb7..cd977626f 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -101,8 +101,8 @@ class SliceVisitor final : public VNVisitor { } else if (AstNodeCond* const snodep = VN_CAST(nodep, NodeCond)) { UINFO(9, " cloneCond(" << elements << "," << offset << ") " << nodep << endl); return snodep->cloneType(snodep->condp()->cloneTree(false), - cloneAndSel(snodep->expr1p(), elements, offset), - cloneAndSel(snodep->expr2p(), elements, offset)); + cloneAndSel(snodep->thenp(), elements, offset), + cloneAndSel(snodep->elsep(), elements, offset)); } else if (const AstSliceSel* const snodep = VN_CAST(nodep, SliceSel)) { UINFO(9, " cloneSliceSel(" << elements << "," << offset << ") " << nodep << endl); const int leOffset = (snodep->declRange().lo() diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 3e9f4e9ec..b3fd07314 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -601,14 +601,14 @@ protected: UINFO(4, " ALW " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, " alwIn:: "); scoreboardClear(); - processBlock(nodep->bodysp()); + processBlock(nodep->stmtsp()); if (debug() >= 9) nodep->dumpTree(cout, " alwOut: "); } void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); iterateAndNextNull(nodep->condp()); - processBlock(nodep->ifsp()); + processBlock(nodep->thensp()); processBlock(nodep->elsesp()); } @@ -713,14 +713,14 @@ public: // Put a placeholder node into stmtp to track our position. // We'll strip these out after the blocks are fully cloned. AstSplitPlaceholder* const placeholderp = makePlaceholderp(); - alwaysp->addStmtp(placeholderp); + alwaysp->addStmtsp(placeholderp); m_addAfter[color] = placeholderp; m_newBlocksp->push_back(alwaysp); } // Scan the body of the always. We'll handle if/else // specially, everything else is a leaf node that we can // just clone into one of the split always blocks. - iterateAndNextNull(m_origAlwaysp->bodysp()); + iterateAndNextNull(m_origAlwaysp->stmtsp()); } protected: @@ -776,7 +776,7 @@ protected: m_addAfter[color] = if_placeholderp; } - iterateAndNextNull(nodep->ifsp()); + iterateAndNextNull(nodep->thensp()); for (const auto& color : colors) m_addAfter[color] = clones[color]->elsesp(); @@ -804,7 +804,7 @@ class RemovePlaceholdersVisitor final : public VNVisitor { VL_RESTORER(m_isPure); m_isPure = true; iterateChildren(nodep); - if (!nodep->ifsp() && !nodep->elsesp() && m_isPure) pushDeletep(nodep->unlinkFrBack()); + if (!nodep->thensp() && !nodep->elsesp() && m_isPure) pushDeletep(nodep->unlinkFrBack()); } void visit(AstAlways* nodep) override { VL_RESTORER(m_isPure); @@ -812,7 +812,7 @@ class RemovePlaceholdersVisitor final : public VNVisitor { iterateChildren(nodep); if (m_isPure) { bool emptyOrCommentOnly = true; - for (AstNode* bodysp = nodep->bodysp(); bodysp; bodysp = bodysp->nextp()) { + for (AstNode* bodysp = nodep->stmtsp(); bodysp; bodysp = bodysp->nextp()) { // If this always block contains only AstComment, remove here. // V3Gate will remove anyway. if (!VN_IS(bodysp, Comment)) { @@ -955,7 +955,7 @@ protected: void visit(AstAlways* nodep) override { // build the scoreboard scoreboardClear(); - scanBlock(nodep->bodysp()); + scanBlock(nodep->stmtsp()); if (m_noReorderWhy != "") { // We saw a jump or something else rare that we don't handle. @@ -989,7 +989,7 @@ protected: m_curIfConditional = nodep; iterateAndNextNull(nodep->condp()); m_curIfConditional = nullptr; - scanBlock(nodep->ifsp()); + scanBlock(nodep->thensp()); scanBlock(nodep->elsesp()); } diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 47dc0e006..502058e37 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -191,16 +191,16 @@ struct SplitVarImpl { template void insertBeginCore(T_ALWAYSLIKE* ap, AstNodeStmt* stmtp, AstNodeModule* modp) { - if (ap->isJustOneBodyStmt() && ap->bodysp() == stmtp) { + if (ap->isJustOneBodyStmt() && ap->stmtsp() == stmtp) { stmtp->unlinkFrBack(); // Insert begin-end because temp value may be inserted to this block later. const std::string name = "__VsplitVarBlk" + cvtToStr(modp->user1Inc(1)); - ap->addStmtp(new AstBegin{ap->fileline(), name, stmtp}); + ap->addStmtsp(new AstBegin{ap->fileline(), name, stmtp}); } } void insertBeginCore(AstInitial* initp, AstNodeStmt* stmtp, AstNodeModule* modp) { - if (initp->isJustOneBodyStmt() && initp->bodysp() == stmtp) { + if (initp->isJustOneBodyStmt() && initp->stmtsp() == stmtp) { stmtp->unlinkFrBack(); // Insert begin-end because temp value may be inserted to this block later. FileLine* const fl = initp->fileline(); @@ -477,7 +477,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { if (nodep->sensesp()) { // When visiting sensitivity list, always is the context setContextAndIterate(nodep, nodep->sensesp()); } - for (AstNode* bodysp = nodep->bodysp(); bodysp; bodysp = bodysp->nextp()) { + for (AstNode* bodysp = nodep->stmtsp(); bodysp; bodysp = bodysp->nextp()) { iterate(bodysp); } }; @@ -485,7 +485,7 @@ class SplitUnpackedVarVisitor final : public VNVisitor, public SplitVarImpl { if (nodep->sensesp()) { // When visiting sensitivity list, always is the context setContextAndIterate(nodep, nodep->sensesp()); } - for (AstNode* bodysp = nodep->bodysp(); bodysp; bodysp = bodysp->nextp()) { + for (AstNode* bodysp = nodep->stmtsp(); bodysp; bodysp = bodysp->nextp()) { iterate(bodysp); } } diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 01d3ec2f2..5ec58dfdc 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -141,7 +141,7 @@ private: { m_counting = false; m_instrs = 0.0; - iterateAndNextConstNull(nodep->ifsp()); + iterateAndNextConstNull(nodep->thensp()); ifInstrs = m_instrs; } } @@ -158,7 +158,7 @@ private: // Now collect the stats if (m_counting) { if (ifInstrs >= elseInstrs) { - iterateAndNextConstNull(nodep->ifsp()); + iterateAndNextConstNull(nodep->thensp()); } else { iterateAndNextConstNull(nodep->elsesp()); } diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 76fcb3711..1e829f32e 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -253,9 +253,9 @@ private: AstVar* const indexVarp = new AstVar{fl, VVarType::BLOCKTEMP, "__Vtableidx" + cvtToStr(m_modTables), VFlagBitPacked{}, static_cast(m_inWidthBits)}; - m_modp->addStmtp(indexVarp); + m_modp->addStmtsp(indexVarp); AstVarScope* const indexVscp = new AstVarScope{indexVarp->fileline(), m_scopep, indexVarp}; - m_scopep->addVarp(indexVscp); + m_scopep->addVarsp(indexVscp); // The 'output assigned' table builder TableBuilder outputAssignedTableBuilder{fl}; @@ -274,8 +274,8 @@ private: // Link it in. // Keep sensitivity list, but delete all else - nodep->bodysp()->unlinkFrBackWithNext()->deleteTree(); - nodep->addStmtp(stmtsp); + nodep->stmtsp()->unlinkFrBackWithNext()->deleteTree(); + nodep->addStmtsp(stmtsp); if (debug() >= 6) nodep->dumpTree(cout, " table_new: "); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 0ab7392fd..332550798 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -250,7 +250,7 @@ private: } UASSERT_OBJ(m_ctorp, nodep, "class constructor missing"); // LinkDot always makes it for (AstInitialAutomatic* initialp : m_initialps) { - if (AstNode* const newp = initialp->bodysp()) { + if (AstNode* const newp = initialp->stmtsp()) { newp->unlinkFrBackWithNext(); if (!m_ctorp->stmtsp()) { m_ctorp->addStmtsp(newp); @@ -371,7 +371,7 @@ private: newvarp->funcLocal(true); funcp->addInitsp(newvarp); AstVarScope* const newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp); - m_scopep->addVarp(newvscp); + m_scopep->addVarsp(newvscp); return newvscp; } AstVarScope* createInputVar(AstCFunc* funcp, const string& name, VBasicDTypeKwd kwd) { @@ -381,7 +381,7 @@ private: newvarp->direction(VDirection::INPUT); funcp->addArgsp(newvarp); AstVarScope* const newvscp = new AstVarScope(funcp->fileline(), m_scopep, newvarp); - m_scopep->addVarp(newvscp); + m_scopep->addVarsp(newvscp); return newvscp; } AstVarScope* createVarScope(AstVar* invarp, const string& name) { @@ -397,9 +397,9 @@ private: = new AstVar{invarp->fileline(), VVarType::BLOCKTEMP, name, invarp}; newvarp->funcLocal(false); newvarp->propagateAttrFrom(invarp); - m_modp->addStmtp(newvarp); + m_modp->addStmtsp(newvarp); AstVarScope* const newvscp = new AstVarScope{newvarp->fileline(), m_scopep, newvarp}; - m_scopep->addVarp(newvscp); + m_scopep->addVarsp(newvscp); return newvscp; } } @@ -766,7 +766,7 @@ private: funcp->protect(false); funcp->cname(nodep->cname()); // Add DPI Export to top, since it's a global function - m_topScopep->scopep()->addActivep(funcp); + m_topScopep->scopep()->addBlocksp(funcp); { // Create dispatch wrapper // Note this function may dispatch to myfunc on a different class. @@ -855,9 +855,9 @@ private: // doesn't rip up the variables on us args += ");\n"; AstCStmt* const newp = new AstCStmt(nodep->fileline(), "(*__Vcb)("); - newp->addBodysp(argnodesp); + newp->addExprsp(argnodesp); VL_DANGLING(argnodesp); - newp->addBodysp(new AstText(nodep->fileline(), args, true)); + newp->addExprsp(new AstText(nodep->fileline(), args, true)); funcp->addStmtsp(newp); } @@ -899,7 +899,7 @@ private: funcp->protect(false); funcp->pure(nodep->pure()); // Add DPI Import to top, since it's a global function - m_topScopep->scopep()->addActivep(funcp); + m_topScopep->scopep()->addBlocksp(funcp); makePortList(nodep, funcp); return funcp; } @@ -1064,9 +1064,9 @@ private: FileLine* const fl = m_topScopep->fileline(); AstVar* const varp = new AstVar{fl, VVarType::VAR, "__Vdpi_export_trigger", VFlagBitPacked{}, 1}; - m_topScopep->scopep()->modp()->addStmtp(varp); + m_topScopep->scopep()->modp()->addStmtsp(varp); dpiExportTriggerp = new AstVarScope{fl, m_topScopep->scopep(), varp}; - m_topScopep->scopep()->addVarp(dpiExportTriggerp); + m_topScopep->scopep()->addVarsp(dpiExportTriggerp); v3Global.rootp()->dpiExportTriggerp(dpiExportTriggerp); } return dpiExportTriggerp; @@ -1134,7 +1134,7 @@ private: AstVarScope* rtnvscp = nullptr; if (rtnvarp) { rtnvscp = new AstVarScope(rtnvarp->fileline(), m_scopep, rtnvarp); - m_scopep->addVarp(rtnvscp); + m_scopep->addVarsp(rtnvscp); rtnvarp->user2p(rtnvscp); } @@ -1228,7 +1228,7 @@ private: } AstVarScope* const newvscp = new AstVarScope{portp->fileline(), m_scopep, portp}; - m_scopep->addVarp(newvscp); + m_scopep->addVarsp(newvscp); portp->user2p(newvscp); } } @@ -1314,9 +1314,9 @@ private: new AstVarRef{fl, dpiExportTriggerp, VAccess::READ}}}, nullptr}; for (AstVarScope* const varScopep : writtenps) { - alwaysp->addStmtp(new AstDpiExportUpdated{fl, varScopep}); + alwaysp->addStmtsp(new AstDpiExportUpdated{fl, varScopep}); } - m_scopep->addActivep(alwaysp); + m_scopep->addBlocksp(alwaysp); } } @@ -1516,7 +1516,7 @@ private: iterateAndNextNull(nodep->condp()); // Body insert just before themselves m_insStmtp = nullptr; // First thing should be new statement - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->incsp()); // Done the loop m_insStmtp = nullptr; // Next thing should be new statement diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index c98a120a3..328e913ad 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -454,9 +454,9 @@ private: v3Global.rootp()->typeTablep()->addTypesp(newArrDtp); AstVar* const newvarp = new AstVar(flp, VVarType::MODULETEMP, "__Vm_traceActivity", newArrDtp); - m_topModp->addStmtp(newvarp); + m_topModp->addStmtsp(newvarp); AstVarScope* const newvscp = new AstVarScope(flp, m_topScopep, newvarp); - m_topScopep->addVarp(newvscp); + m_topScopep->addVarsp(newvscp); m_activityVscp = newvscp; // Insert activity setters @@ -493,7 +493,7 @@ private: funcp->slow(full); funcp->isStatic(isTopFunc); // Add it to top scope - m_topScopep->addActivep(funcp); + m_topScopep->addBlocksp(funcp); const auto addInitStr = [funcp, flp](const string& str) -> void { funcp->addInitsp(new AstCStmt(flp, str)); }; @@ -676,7 +676,7 @@ private: // Add TraceInc node AstTraceInc* const incp = new AstTraceInc(declp->fileline(), declp, /* full: */ false, baseCode); - ifp->addIfsp(incp); + ifp->addThensp(incp); subStmts += incp->nodeCount(); // Track partitioning @@ -698,7 +698,7 @@ private: cleanupFuncp->slow(false); cleanupFuncp->isStatic(true); cleanupFuncp->isLoose(true); - m_topScopep->addActivep(cleanupFuncp); + m_topScopep->addBlocksp(cleanupFuncp); cleanupFuncp->addInitsp(new AstCStmt(fl, voidSelfAssign(m_topModp))); cleanupFuncp->addInitsp(new AstCStmt(fl, symClassAssign())); @@ -755,7 +755,7 @@ private: m_regFuncp->slow(true); m_regFuncp->isStatic(false); m_regFuncp->isLoose(true); - m_topScopep->addActivep(m_regFuncp); + m_topScopep->addBlocksp(m_regFuncp); // Create the full dump functions, also allocates signal numbers createFullTraceFunction(traces, nFullCodes, m_parallelism); diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 4c8cae3a8..9df50a158 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -162,7 +162,7 @@ private: funcp->isStatic(false); funcp->isLoose(true); funcp->slow(true); - topScopep->addActivep(funcp); + topScopep->addBlocksp(funcp); return funcp; } @@ -303,8 +303,8 @@ private: scopeName = scopeName.substr(0, lastDot + 1); const size_t scopeLen = scopeName.length(); - UASSERT_OBJ(cellp->intfRefp(), cellp, "Interface without tracing reference"); - for (AstIntfRef *irp = cellp->intfRefp(), *nextIrp; irp; irp = nextIrp) { + UASSERT_OBJ(cellp->intfRefsp(), cellp, "Interface without tracing reference"); + for (AstIntfRef *irp = cellp->intfRefsp(), *nextIrp; irp; irp = nextIrp) { nextIrp = VN_AS(irp->nextp(), IntfRef); const string irpName = irp->prettyName(); diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index f88908f62..613983a02 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -422,7 +422,7 @@ class TristateVisitor final : public TristateBaseVisitor { "Unsupported: Creating tristate signal not underneath a module: " << nodep->prettyNameQ()); } else { - m_modp->addStmtp(newp); + m_modp->addStmtsp(newp); } } void associateLogic(AstNode* fromp, AstNode* top) { @@ -554,7 +554,7 @@ class TristateVisitor final : public TristateBaseVisitor { AstNode* const newp = new AstAssignW(varp->fileline(), varrefp, constp); UINFO(9, " newoev " << newp << endl); varrefp->user1p(newAllZerosOrOnes(varp, false)); - nodep->addStmtp(newp); + nodep->addStmtsp(newp); mapInsertLhsVarRef(varrefp); // insertTristates will convert // // to a varref to the __out# variable } @@ -627,7 +627,7 @@ class TristateVisitor final : public TristateBaseVisitor { lhsp->name() + "__out" + cvtToStr(m_unique), VFlagBitPacked(), w); // 2-state ok; sep enable UINFO(9, " newout " << newlhsp << endl); - nodep->addStmtp(newlhsp); + nodep->addStmtsp(newlhsp); refp->varp(newlhsp); // assign the new var to the varref refp->name(newlhsp->name()); @@ -636,13 +636,13 @@ class TristateVisitor final : public TristateBaseVisitor { lhsp->name() + "__en" + cvtToStr(m_unique++), VFlagBitPacked(), w); // 2-state ok UINFO(9, " newenp " << newenp << endl); - nodep->addStmtp(newenp); + nodep->addStmtsp(newenp); AstNode* const enassp = new AstAssignW( refp->fileline(), new AstVarRef(refp->fileline(), newenp, VAccess::WRITE), getEnp(refp)); UINFO(9, " newass " << enassp << endl); - nodep->addStmtp(enassp); + nodep->addStmtsp(enassp); // now append this driver to the driver logic. AstNode* const ref1p = new AstVarRef(refp->fileline(), newlhsp, VAccess::READ); @@ -675,7 +675,7 @@ class TristateVisitor final : public TristateBaseVisitor { VL_DO_DANGLING(undrivenp->deleteTree(), undrivenp); } if (envarp) { - nodep->addStmtp(new AstAssignW( + nodep->addStmtsp(new AstAssignW( enp->fileline(), new AstVarRef(envarp->fileline(), envarp, VAccess::WRITE), enp)); } // __out (child) or (parent) = drive-value expression @@ -683,7 +683,7 @@ class TristateVisitor final : public TristateBaseVisitor { lhsp->fileline(), new AstVarRef(lhsp->fileline(), lhsp, VAccess::WRITE), orp); assp->user2(U2_BOTH); // Don't process further; already resolved if (debug() >= 9) assp->dumpTree(cout, "-lhsp-eqn: "); - nodep->addStmtp(assp); + nodep->addStmtsp(assp); } void addToAssignmentList(AstAssignW* nodep) { @@ -864,11 +864,11 @@ class TristateVisitor final : public TristateBaseVisitor { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { - associateLogic(nodep, nodep->expr1p()); - associateLogic(nodep, nodep->expr2p()); + associateLogic(nodep, nodep->thenp()); + associateLogic(nodep, nodep->elsep()); } else { - associateLogic(nodep->expr1p(), nodep); - associateLogic(nodep->expr2p(), nodep); + associateLogic(nodep->thenp(), nodep); + associateLogic(nodep->elsep(), nodep); } } else { if (m_alhs && nodep->user1p()) { @@ -887,20 +887,20 @@ class TristateVisitor final : public TristateBaseVisitor { condp->v3warn(E_UNSUPPORTED, "Unsupported: don't know how to deal with " "tristate logic in the conditional expression"); } - AstNode* const expr1p = nodep->expr1p(); - AstNode* const expr2p = nodep->expr2p(); - if (expr1p->user1p() || expr2p->user1p()) { // else no tristates + AstNode* const thenp = nodep->thenp(); + AstNode* const elsep = nodep->elsep(); + if (thenp->user1p() || elsep->user1p()) { // else no tristates m_tgraph.didProcess(nodep); - AstNode* const en1p = getEnp(expr1p); - AstNode* const en2p = getEnp(expr2p); + AstNode* const en1p = getEnp(thenp); + AstNode* const en2p = getEnp(elsep); // The output enable of a cond is a cond of the output enable of the // two expressions with the same conditional. AstNode* const enp = new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p); UINFO(9, " newcond " << enp << endl); nodep->user1p(enp); // propagate up COND(lhsp->enable, rhsp->enable) - expr1p->user1p(nullptr); - expr2p->user1p(nullptr); + thenp->user1p(nullptr); + elsep->user1p(nullptr); } } } @@ -1391,7 +1391,7 @@ class TristateVisitor final : public TristateBaseVisitor { UINFO(9, " newpin " << enpinp << endl); enpinp->user2(U2_BOTH); // don't iterate the pin later nodep->addNextHere(enpinp); - m_modp->addStmtp(enVarp); + m_modp->addStmtsp(enVarp); enrefp = new AstVarRef(nodep->fileline(), enVarp, VAccess::READ); UINFO(9, " newvrf " << enrefp << endl); if (debug() >= 9) enpinp->dumpTree(cout, "-pin-ena: "); @@ -1608,7 +1608,7 @@ class TristateVisitor final : public TristateBaseVisitor { void visit(AstCaseItem* nodep) override { // don't deal with casez compare '???? values - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); } void visit(AstCell* nodep) override { diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index bd91ad005..df468c70f 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -120,7 +120,7 @@ private: } else { AstVar* const varp = new AstVar(fl, VVarType::MODULETEMP, m_lvboundNames.get(prep), prep->dtypep()); - m_modp->addStmtp(varp); + m_modp->addStmtsp(varp); AstNode* const abovep = prep->backp(); // Grab above point before we replace 'prep' prep->replaceWith(new AstVarRef(fl, varp, VAccess::WRITE)); AstIf* const newp = new AstIf( @@ -173,7 +173,7 @@ private: m_constXCvt = false; // Avoid losing the X's in casex iterateAndNextNull(nodep->condsp()); m_constXCvt = true; - iterateAndNextNull(nodep->bodysp()); + iterateAndNextNull(nodep->stmtsp()); } } void visit(AstNodeDType* nodep) override { @@ -353,9 +353,9 @@ private: // Add inits in front of other statement. // In the future, we should stuff the initp into the module's constructor. AstNode* const afterp = m_modp->stmtsp()->unlinkFrBackWithNext(); - m_modp->addStmtp(newvarp); - m_modp->addStmtp(newinitp); - m_modp->addStmtp(afterp); + m_modp->addStmtsp(newvarp); + m_modp->addStmtsp(newinitp); + m_modp->addStmtsp(afterp); if (debug() >= 9) newref1p->dumpTree(cout, " _new: "); if (debug() >= 9) newvarp->dumpTree(cout, " _new: "); if (debug() >= 9) newinitp->dumpTree(cout, " _new: "); diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 1efbef18b..2ffef6176 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -387,21 +387,21 @@ private: if (nodep->backp()->nextp() == nodep) initp = nodep->backp(); // Grab assignment AstNode* incp = nullptr; // Should be last statement - AstNode* bodysp = nodep->bodysp(); + AstNode* stmtsp = nodep->stmtsp(); if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp()); // cppcheck-suppress duplicateCondition if (nodep->incsp()) { incp = nodep->incsp(); } else { - for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} + for (incp = nodep->stmtsp(); incp && incp->nextp(); incp = incp->nextp()) {} if (incp) VL_DO_DANGLING(V3Const::constifyEdit(incp), incp); // Again, as may have changed - bodysp = nodep->bodysp(); - for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} - if (incp == bodysp) bodysp = nullptr; + stmtsp = nodep->stmtsp(); + for (incp = nodep->stmtsp(); incp && incp->nextp(); incp = incp->nextp()) {} + if (incp == stmtsp) stmtsp = nullptr; } // And check it - if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, bodysp)) { + if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, stmtsp)) { VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement } } @@ -426,7 +426,7 @@ private: // deleted by V3Const. VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } else if (forUnrollCheck(nodep, nodep->initsp(), nullptr, nodep->condp(), - nodep->incsp(), nodep->bodysp())) { + nodep->incsp(), nodep->stmtsp())) { VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement } else { nodep->v3error("For loop doesn't have genvar index, or is malformed"); diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp index 53e53788e..ad98ec081 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -188,7 +188,7 @@ class VariableOrder final { stmtsp->unlinkFrBackWithNext(); AstNode::addNext(firstp, stmtsp); } - modp->addStmtp(firstp); + modp->addStmtsp(firstp); } } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 57fad0d7f..c2f77042d 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -462,22 +462,22 @@ private: iterateCheckBool(nodep, "Conditional Test", nodep->condp(), BOTH); // Determine sub expression widths only relying on what's in the subops // CONTEXT determined, but need data type for pattern assignments - userIterateAndNext(nodep->expr1p(), WidthVP(m_vup->dtypeNullp(), PRELIM).p()); - userIterateAndNext(nodep->expr2p(), WidthVP(m_vup->dtypeNullp(), PRELIM).p()); + userIterateAndNext(nodep->thenp(), WidthVP(m_vup->dtypeNullp(), PRELIM).p()); + userIterateAndNext(nodep->elsep(), WidthVP(m_vup->dtypeNullp(), PRELIM).p()); // Calculate width of this expression. // First call (prelim()) m_vup->width() is probably zero, so we'll return // the size of this subexpression only. // Second call (final()) m_vup->width() is probably the expression size, so // the expression includes the size of the output too. - if (nodep->expr1p()->isDouble() || nodep->expr2p()->isDouble()) { + if (nodep->thenp()->isDouble() || nodep->elsep()->isDouble()) { nodep->dtypeSetDouble(); - } else if (nodep->expr1p()->isString() || nodep->expr2p()->isString()) { + } else if (nodep->thenp()->isString() || nodep->elsep()->isString()) { nodep->dtypeSetString(); } else { - const int width = std::max(nodep->expr1p()->width(), nodep->expr2p()->width()); + const int width = std::max(nodep->thenp()->width(), nodep->elsep()->width()); const int mwidth - = std::max(nodep->expr1p()->widthMin(), nodep->expr2p()->widthMin()); - const bool issigned = nodep->expr1p()->isSigned() && nodep->expr2p()->isSigned(); + = std::max(nodep->thenp()->widthMin(), nodep->elsep()->widthMin()); + const bool issigned = nodep->thenp()->isSigned() && nodep->elsep()->isSigned(); nodep->dtypeSetLogicUnsized(width, mwidth, VSigning::fromBool(issigned)); } } @@ -486,9 +486,9 @@ private: AstNodeDType* const subDTypep = expDTypep; nodep->dtypeFrom(expDTypep); // Error report and change sizes for suboperands of this node. - iterateCheck(nodep, "Conditional True", nodep->expr1p(), CONTEXT, FINAL, subDTypep, + iterateCheck(nodep, "Conditional True", nodep->thenp(), CONTEXT, FINAL, subDTypep, EXTEND_EXP); - iterateCheck(nodep, "Conditional False", nodep->expr2p(), CONTEXT, FINAL, subDTypep, + iterateCheck(nodep, "Conditional False", nodep->elsep(), CONTEXT, FINAL, subDTypep, EXTEND_EXP); } } @@ -1834,7 +1834,7 @@ private: castSized(nodep, nodep->fromp(), width); // Note castSized might modify nodep->fromp() } else { - iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, fromDtp, EXTEND_EXP, + iterateCheck(nodep, "value", nodep->fromp(), SELF, FINAL, fromDtp, EXTEND_EXP, false); } if (basicp->isDouble() && !nodep->fromp()->isDouble()) { @@ -1866,14 +1866,14 @@ private: << toDtp->prettyDTypeNameQ()); } if (!newp) newp = nodep->fromp()->unlinkFrBack(); - nodep->lhsp(newp); + nodep->fromp(newp); // if (debug()) nodep->dumpTree(cout, " CastOut: "); // if (debug()) nodep->backp()->dumpTree(cout, " CastOutUpUp: "); } if (m_vup->final()) { - iterateCheck(nodep, "value", nodep->lhsp(), SELF, FINAL, nodep->lhsp()->dtypep(), + iterateCheck(nodep, "value", nodep->fromp(), SELF, FINAL, nodep->fromp()->dtypep(), EXTEND_EXP, false); - AstNode* const underp = nodep->lhsp()->unlinkFrBack(); + AstNode* const underp = nodep->fromp()->unlinkFrBack(); // if (debug()) underp->dumpTree(cout, " CastRep: "); nodep->replaceWith(underp); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -3972,7 +3972,7 @@ private: userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); for (AstCaseItem *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = VN_AS(itemp->nextp(), CaseItem); // Prelim may cause the node to get replaced - if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->bodysp(), nullptr); + if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->stmtsp(), nullptr); for (AstNode *nextcp, *condp = itemp->condsp(); condp; condp = nextcp) { nextcp = condp->nextp(); // Prelim may cause the node to get replaced VL_DO_DANGLING(userIterate(condp, WidthVP(CONTEXT, PRELIM).p()), condp); @@ -4015,27 +4015,27 @@ private: userIterateAndNext(nodep->initsp(), nullptr); iterateCheckBool(nodep, "For Test Condition", nodep->condp(), BOTH); // it's like an if() condition. - if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), nullptr); + if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->stmtsp(), nullptr); userIterateAndNext(nodep->incsp(), nullptr); } void visit(AstRepeat* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->countp(), WidthVP(SELF, BOTH).p()); - userIterateAndNext(nodep->bodysp(), nullptr); + userIterateAndNext(nodep->stmtsp(), nullptr); } void visit(AstWhile* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->precondsp(), nullptr); iterateCheckBool(nodep, "For Test Condition", nodep->condp(), BOTH); // it's like an if() condition. - userIterateAndNext(nodep->bodysp(), nullptr); + userIterateAndNext(nodep->stmtsp(), nullptr); userIterateAndNext(nodep->incsp(), nullptr); } void visit(AstNodeIf* nodep) override { assertAtStatement(nodep); // if (debug()) nodep->dumpTree(cout, " IfPre: "); if (!VN_IS(nodep, GenIf)) { // for m_paramsOnly - userIterateAndNext(nodep->ifsp(), nullptr); + userIterateAndNext(nodep->thensp(), nullptr); userIterateAndNext(nodep->elsesp(), nullptr); } iterateCheckBool(nodep, "If", nodep->condp(), BOTH); // it's like an if() condition. @@ -4056,7 +4056,7 @@ private: UASSERT_OBJ(fromp->dtypep(), fromp, "Missing data type"); AstNodeDType* fromDtp = fromp->dtypep()->skipRefp(); // Split into for loop - AstNode* bodyp = nodep->bodysp(); // Might be null + AstNode* bodyp = nodep->stmtsp(); // Might be null if (bodyp) bodyp->unlinkFrBackWithNext(); // We record where the body needs to eventually go with bodyPointp // (Can't use bodyp as might be null) @@ -4348,8 +4348,8 @@ private: argp->unlinkFrBack(&handle); AstCMath* const newp = new AstCMath(nodep->fileline(), "VL_TO_STRING(", 0, true); - newp->addBodysp(argp); - newp->addBodysp(new AstText(nodep->fileline(), ")", true)); + newp->addExprsp(argp); + newp->addExprsp(new AstText(nodep->fileline(), ")", true)); newp->dtypeSetString(); newp->pure(true); newp->protect(false); @@ -6356,7 +6356,7 @@ private: varp->isStatic(true); varp->valuep(initp); // Add to root, as don't know module we are in, and aids later structure sharing - v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp); + v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp); // Element 0 is a non-index and has speced values initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0)); for (unsigned i = 1; i < msbdim + 1; ++i) { @@ -6421,7 +6421,7 @@ private: varp->isStatic(true); varp->valuep(initp); // Add to root, as don't know module we are in, and aids later structure sharing - v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(varp); + v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp); // Default for all unspecified values if (attrType == VAttrType::ENUM_NAME) { diff --git a/src/astgen b/src/astgen index 19a6d0b19..56956768d 100755 --- a/src/astgen +++ b/src/astgen @@ -24,6 +24,8 @@ class Node: self._file = file # File this class is defined in self._lineno = lineno # Line this class is defined on self._ordIdx = None # Ordering index of this class + self._arity = -1 # Arity of node + self._ops = {} # Operands of node @property def name(self): @@ -33,6 +35,10 @@ class Node: def superClass(self): return self._superClass + @property + def isRoot(self): + return self.superClass is None + @property def isCompleted(self): return isinstance(self._subClasses, tuple) @@ -50,6 +56,20 @@ class Node: assert not self.isCompleted self._subClasses.append(subClass) + def addOp(self, n, name, monad, kind): + assert 1 <= n <= 4 + self._ops[n] = (name, monad, kind) + self._arity = max(self._arity, n) + + def getOp(self, n): + assert 1 <= n <= 4 + op = self._ops.get(n, None) + if op is not None: + return op + if not self.isRoot: + return self.superClass.getOp(n) + return None + # Computes derived properties over entire class hierarchy. # No more changes to the hierarchy are allowed once this was called def complete(self, typeId=0, ordIdx=0): @@ -62,6 +82,11 @@ class Node: self._ordIdx = ordIdx ordIdx = ordIdx + 1 + if self.isRoot: + self._arity = 0 + else: + self._arity = max(self._arity, self._superClass.arity) + # Leaves if self.isLeaf: self._typeId = typeId @@ -78,11 +103,6 @@ class Node: assert self.isCompleted return self._subClasses - @property - def isRoot(self): - assert self.isCompleted - return self.superClass is None - @property def isLeaf(self): assert self.isCompleted @@ -140,6 +160,11 @@ class Node: assert self.isCompleted return self._ordIdx + @property + def arity(self): + assert self.isCompleted + return self._arity + def isSubClassOf(self, other): assert self.isCompleted if self is other: @@ -495,6 +520,25 @@ class Cpt: ###################################################################### +def partitionAndStrip(string, separator): + return map(lambda _: _.strip(), string.partition(separator)) + + +def parseOpType(string): + match = re.match(r'^(\w+)\[(\w+)\]$', string) + if match: + monad, kind = match.groups() + if monad not in ("Optional", "List"): + return None + kind = parseOpType(kind) + if not kind or kind[0]: + return None + return monad, kind[1] + if re.match(r'^Ast(\w+)$', string): + return "", string[3:] + return None + + def read_types(filename): hasErrors = False @@ -539,12 +583,65 @@ def read_types(filename): node = Node(classn, superClass, filename, lineno) superClass.addSubClass(node) Nodes[classn] = node - if not node: continue if re.match(r'^\s*ASTGEN_MEMBERS_' + node.name + ';', line): hasAstgenMembers = True + match = re.match(r'^\s*//\s*@astgen\s+(.*)$', line) + if match: + decl = re.sub(r'//.*$', '', match.group(1)) + what, sep, rest = partitionAndStrip(decl, ":=") + what = re.sub(r'\s+', ' ', what) + if not sep: + error( + lineno, + "Malformed '@astgen' directive (expecting ' := '): " + + decl) + elif what in ("op1", "op2", "op3", "op4"): + n = int(what[-1]) + ident, sep, kind = partitionAndStrip(rest, ":") + ident = ident.strip() + if not sep or not re.match(r'^\w+$', ident): + error( + lineno, "Malformed '@astgen " + what + + "' directive (expecting '" + what + + " := : ': " + decl) + else: + kind = parseOpType(kind) + if not kind: + error( + lineno, "Bad type for '@astgen " + what + + "' (expecting Ast*, Optional[Ast*], or List[Ast*]):" + + decl) + elif node.getOp(n) is not None: + error( + lineno, "Already defined " + what + " for " + + node.name) + else: + node.addOp(n, ident, *kind) + elif what in ("alias op1", "alias op2", "alias op3", + "alias op4"): + n = int(what[-1]) + ident = rest.strip() + if not re.match(r'^\w+$', ident): + error( + lineno, "Malformed '@astgen " + what + + "' directive (expecting '" + what + + " := ': " + decl) + else: + op = node.getOp(n) + if op is None: + error(lineno, + "Alaised op" + str(n) + " is not defined") + else: + node.addOp(n, ident, *op[1:]) + else: + line = re.sub(r'//.*$', '', line) + if re.match(r'.*[Oo]p[1-9].*', line): + error(lineno, + "Use generated accessors to access op operands") + checkFinishedNode(node) if hasErrors: sys.exit("%Error: Stopping due to errors reported above") @@ -614,6 +711,7 @@ def write_report(filename): fh.write("\nClasses:\n") for node in SortedNodes: fh.write(" class Ast%-17s\n" % node.name) + fh.write(" arity: {}\n".format(node.arity)) fh.write(" parent: ") for superClass in node.allSuperClasses: if not superClass.isRoot: @@ -759,6 +857,42 @@ def write_macros(filename): ''', t=node.name) + for n in (1, 2, 3, 4): + op = node.getOp(n) + if not op: + continue + name, monad, kind = op + retrieve = ("VN_AS(op{n}p(), {kind})" if kind != "Node" else + "op{n}p()").format(n=n, kind=kind) + if monad == "List": + emitBlock('''\ + Ast{kind}* {name}() const {{ return {retrieve}; }} + void add{Name}(Ast{kind}* nodep) {{ addNOp{n}p(reinterpret_cast(nodep)); }} + ''', + kind=kind, + name=name, + Name=name[0].upper() + name[1:], + n=n, + retrieve=retrieve) + elif monad == "Optional": + emitBlock('''\ + Ast{kind}* {name}() const {{ return {retrieve}; }} + void {name}(Ast{kind}* nodep) {{ setNOp{n}p(reinterpret_cast(nodep)); }} + ''', + kind=kind, + name=name, + n=n, + retrieve=retrieve) + else: + emitBlock('''\ + Ast{kind}* {name}() const {{ return {retrieve}; }} + void {name}(Ast{kind}* nodep) {{ setOp{n}p(reinterpret_cast(nodep)); }} + ''', + kind=kind, + name=name, + n=n, + retrieve=retrieve) + fh.write( " static_assert(true, \"\")\n") # Swallowing the semicolon diff --git a/src/bisonpre b/src/bisonpre index e03a7e41e..c60e3575d 100755 --- a/src/bisonpre +++ b/src/bisonpre @@ -391,9 +391,8 @@ def clean_input(filename, outname): if not re.match(r'^\s*$', line): sys.exit( "%Error: " + filename + ":" + str(lineno) + ": Need " + - needmore + - " more blank lines to keep line numbers are constant\n" - ) + str(needmore) + + " more blank lines to keep line numbers constant\n") needmore -= 1 else: lines.append(line) diff --git a/src/verilog.y b/src/verilog.y index 4d3c38bc3..c2b17e25c 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1068,6 +1068,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) // Blank lines for type insertion // Blank lines for type insertion // Blank lines for type insertion +// Blank lines for type insertion %start source_text @@ -1092,8 +1093,8 @@ description: // ==IEEE: description | interface_declaration { } | program_declaration { } | package_declaration { } - | package_item { if ($1) PARSEP->unitPackage($1->fileline())->addStmtp($1); } - | bind_directive { if ($1) PARSEP->unitPackage($1->fileline())->addStmtp($1); } + | package_item { if ($1) PARSEP->unitPackage($1->fileline())->addStmtsp($1); } + | bind_directive { if ($1) PARSEP->unitPackage($1->fileline())->addStmtsp($1); } // unsupported // IEEE: config_declaration // // Verilator only | yaT_RESETALL { } // Else, under design, and illegal based on IEEE 22.3 @@ -1119,7 +1120,7 @@ timeunits_declaration: // ==IEEE: timeunits_declaration package_declaration: // ==IEEE: package_declaration packageFront package_itemListE yENDPACKAGE endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc - if ($2) $1->addStmtp($2); + if ($2) $1->addStmtsp($2); GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($4,$1,$4); } @@ -1132,7 +1133,7 @@ packageFront: $$->lifetime($2); $$->modTrace(GRAMMARP->allTracingOn($$->fileline())); $$->timeunit(PARSEP->timeLastUnit()); - PARSEP->rootp()->addModulep($$); + PARSEP->rootp()->addModulesp($$); SYMP->pushNew($$); GRAMMARP->m_modp = $$; } ; @@ -1228,18 +1229,18 @@ module_declaration: // ==IEEE: module_declaration modFront importsAndParametersE portsStarE ';' /*cont*/ module_itemListE yENDMODULE endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc - if ($2) $1->addStmtp($2); - if ($3) $1->addStmtp($3); - if ($5) $1->addStmtp($5); + if ($2) $1->addStmtsp($2); + if ($3) $1->addStmtsp($3); + if ($5) $1->addStmtsp($5); GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } | udpFront parameter_port_listE portsStarE ';' /*cont*/ module_itemListE yENDPRIMITIVE endLabelE { $1->modTrace(false); // Stash for implicit wires, etc - if ($2) $1->addStmtp($2); - if ($3) $1->addStmtp($3); - if ($5) $1->addStmtp($5); + if ($2) $1->addStmtsp($2); + if ($3) $1->addStmtsp($3); + if ($5) $1->addStmtsp($5); GRAMMARP->m_tracingParse = true; GRAMMARP->m_modp = nullptr; SYMP->popScope($1); @@ -1259,7 +1260,7 @@ modFront: $$->modTrace(GRAMMARP->allTracingOn($$->fileline())); $$->timeunit(PARSEP->timeLastUnit()); $$->unconnectedDrive(PARSEP->unconnectedDrive()); - PARSEP->rootp()->addModulep($$); + PARSEP->rootp()->addModulesp($$); SYMP->pushNew($$); GRAMMARP->m_modp = $$; } ; @@ -1275,9 +1276,9 @@ udpFront: { $$ = new AstPrimitive($3, *$3); $$->inLibrary(true); $$->lifetime($2); $$->modTrace(false); - $$->addStmtp(new AstPragma($3, VPragmaType::INLINE_MODULE)); + $$->addStmtsp(new AstPragma($3, VPragmaType::INLINE_MODULE)); GRAMMARP->m_tracingParse = false; - PARSEP->rootp()->addModulep($$); + PARSEP->rootp()->addModulesp($$); SYMP->pushNew($$); } ; @@ -1489,9 +1490,9 @@ interface_declaration: // IEEE: interface_declaration + interface_nonan // // timeunits_delcarationE is instead in interface_item intFront importsAndParametersE portsStarE ';' interface_itemListE yENDINTERFACE endLabelE - { if ($2) $1->addStmtp($2); - if ($3) $1->addStmtp($3); - if ($5) $1->addStmtp($5); + { if ($2) $1->addStmtsp($2); + if ($3) $1->addStmtsp($3); + if ($5) $1->addStmtsp($5); SYMP->popScope($1); } | yEXTERN intFront parameter_port_listE portsStarE ';' { BBUNSUP($1, "Unsupported: extern interface"); } @@ -1502,7 +1503,7 @@ intFront: { $$ = new AstIface($3, *$3); $$->inLibrary(true); $$->lifetime($2); - PARSEP->rootp()->addModulep($$); + PARSEP->rootp()->addModulesp($$); SYMP->pushNew($$); } ; @@ -1578,9 +1579,9 @@ program_declaration: // IEEE: program_declaration + program_nonansi_h pgmFront parameter_port_listE portsStarE ';' /*cont*/ program_itemListE yENDPROGRAM endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc - if ($2) $1->addStmtp($2); - if ($3) $1->addStmtp($3); - if ($5) $1->addStmtp($5); + if ($2) $1->addStmtsp($2); + if ($3) $1->addStmtsp($3); + if ($5) $1->addStmtsp($5); GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } @@ -1596,7 +1597,7 @@ pgmFront: $$->inLibrary(PARSEP->inLibrary() || $$->fileline()->celldefineOn()); $$->modTrace(GRAMMARP->allTracingOn($$->fileline())); $$->timeunit(PARSEP->timeLastUnit()); - PARSEP->rootp()->addModulep($$); + PARSEP->rootp()->addModulesp($$); SYMP->pushNew($$); GRAMMARP->m_modp = $$; } ; @@ -2008,12 +2009,13 @@ struct_unionDecl: // IEEE: part of data_type { $$ = $5; $$->addMembersp($6); SYMP->popScope($$); } ; -struct_union_memberList: // IEEE: { struct_union_member } +struct_union_memberList: // IEEE: { struct_union_member } struct_union_member { $$ = $1; } + | struct_union_memberList struct_union_member { $$ = addNextNull($1, $2); } ; -struct_union_member: // ==IEEE: struct_union_member +struct_union_member: // ==IEEE: struct_union_member // // UNSUP random_qualifer not propagagted until have randomize support random_qualifierE data_type_or_void /*mid*/ { GRAMMARP->m_memDTypep = $2; } // As a list follows, need to attach this dtype to each member. @@ -2021,7 +2023,7 @@ struct_union_member: // ==IEEE: struct_union_member | vlTag { $$ = nullptr; } ; -list_of_member_decl_assignments: // Derived from IEEE: list_of_variable_decl_assignments +list_of_member_decl_assignments: // Derived from IEEE: list_of_variable_decl_assignments member_decl_assignment { $$ = $1; } | list_of_member_decl_assignments ',' member_decl_assignment { $$ = addNextNull($1, $3); } ; @@ -2177,17 +2179,17 @@ enum_base_typeE: // IEEE: enum_base_type $$ = GRAMMARP->createArray(refp, $3, true); } ; -enum_nameList: +enum_nameList: enum_name_declaration { $$ = $1; } | enum_nameList ',' enum_name_declaration { $$ = addNextNull($1, $3); } ; -enum_name_declaration: // ==IEEE: enum_name_declaration +enum_name_declaration: // ==IEEE: enum_name_declaration idAny/*enum_identifier*/ enumNameRangeE enumNameStartE { $$ = new AstEnumItem($1, *$1, $2, $3); } ; -enumNameRangeE: // IEEE: second part of enum_name_declaration +enumNameRangeE: // IEEE: second part of enum_name_declaration /* empty */ { $$ = nullptr; } | '[' intnumAsConst ']' @@ -2472,7 +2474,7 @@ continuous_assign: // IEEE: continuous_assign if ($3) for (auto* nodep = $$; nodep; nodep = nodep->nextp()) { auto* const assignp = VN_AS(nodep, NodeAssign); - assignp->addTimingControlp(nodep == $$ ? $3 : $3->cloneTree(false)); + assignp->timingControlp(nodep == $$ ? $3 : $3->cloneTree(false)); } } ; @@ -2634,7 +2636,7 @@ loop_generate_construct: // ==IEEE: loop_generate_construct } // Statements are under 'genforp' as cells under this // for loop won't get an extra layer of hierarchy tacked on - blkp->addGenforp(new AstGenFor($1, initp, $5, $7, lowerNoBegp)); + blkp->genforp(new AstGenFor($1, initp, $5, $7, lowerNoBegp)); $$ = blkp; VL_DO_DANGLING(lowerBegp->deleteTree(), lowerBegp); } @@ -2679,12 +2681,12 @@ genvar_iteration: // ==IEEE: genvar_iteration new AstConst{$2, AstConst::StringToParse{}, "'b1"}}}; } ; -case_generate_itemListE: // IEEE: [{ case_generate_itemList }] +case_generate_itemListE: // IEEE: [{ case_generate_itemList }] /* empty */ { $$ = nullptr; } | case_generate_itemList { $$ = $1; } ; -case_generate_itemList: // IEEE: { case_generate_itemList } +case_generate_itemList: // IEEE: { case_generate_itemList } ~c~case_generate_item { $$ = $1; } | ~c~case_generate_itemList ~c~case_generate_item { $$ = $1; $1->addNext($2); } ; @@ -2693,7 +2695,7 @@ case_generate_itemList: // IEEE: { case_generate_itemList } //UNSUP BISONPRE_COPY(case_generate_itemList,{s/~c~/c_/g}) // {copied} //UNSUP ; -case_generate_item: // ==IEEE: case_generate_item +case_generate_item: // ==IEEE: case_generate_item caseCondList colon generate_block_or_null { $$ = new AstCaseItem{$2, $1, $3}; } | yDEFAULT colon generate_block_or_null { $$ = new AstCaseItem{$1, nullptr, $3}; } | yDEFAULT generate_block_or_null { $$ = new AstCaseItem{$1, nullptr, $2}; } @@ -2768,7 +2770,7 @@ netSig: // IEEE: net_decl_assignment - one element from { $$ = VARDONEA($1, *$1, nullptr, $2); auto* const assignp = new AstAssignW{$3, new AstVarRef{$1, *$1, VAccess::WRITE}, $4}; if (GRAMMARP->m_netStrengthp) assignp->strengthSpecp(GRAMMARP->m_netStrengthp->cloneTree(false)); - if ($$->delayp()) assignp->addTimingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3 + if ($$->delayp()) assignp->timingControlp($$->delayp()->unlinkFrBack()); // IEEE 1800-2017 10.3.3 AstNode::addNext($$, assignp); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } ; @@ -4110,19 +4112,19 @@ funcId: // IEEE: function_data_type_or_implicit // // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID /**/ fIdScoped { $$ = $1; - $$->addFvarp(new AstBasicDType($1, LOGIC_IMPLICIT)); + $$->fvarp(new AstBasicDType($1, LOGIC_IMPLICIT)); SYMP->pushNewUnderNodeOrCurrent($$, $1); } | signingE rangeList fIdScoped { $$ = $3; - $$->addFvarp(GRAMMARP->addRange(new AstBasicDType($3, LOGIC_IMPLICIT, $1), $2,true)); + $$->fvarp(GRAMMARP->addRange(new AstBasicDType($3, LOGIC_IMPLICIT, $1), $2,true)); SYMP->pushNewUnderNodeOrCurrent($$, $3); } | signing fIdScoped { $$ = $2; - $$->addFvarp(new AstBasicDType($2, LOGIC_IMPLICIT, $1)); + $$->fvarp(new AstBasicDType($2, LOGIC_IMPLICIT, $1)); SYMP->pushNewUnderNodeOrCurrent($$, $2); } | data_type fIdScoped { $$ = $2; - $$->addFvarp($1); + $$->fvarp($1); SYMP->pushNewUnderNodeOrCurrent($$, $2); } // // To verilator tasks are the same as void functions (we separately detect time passing) | yVOID taskId @@ -4992,12 +4994,12 @@ combinational_body: // IEEE: combinational_body + sequential_body yTABLE tableEntryList yENDTABLE { $$ = new AstUdpTable($1,$2); } ; -tableEntryList: // IEEE: { combinational_entry | sequential_entry } +tableEntryList: // IEEE: { combinational_entry | sequential_entry } tableEntry { $$ = $1; } | tableEntryList tableEntry { $$ = addNextNull($1, $2); } ; -tableEntry: // IEEE: combinational_entry + sequential_entry +tableEntry: // IEEE: combinational_entry + sequential_entry yaTABLELINE { $$ = new AstUdpTableLine($1,*$1); } | error { $$ = nullptr; } ; @@ -6227,14 +6229,14 @@ classVirtualE: | yVIRTUAL__CLASS { $$ = true; } ; -classExtendsE: // IEEE: part of class_declaration +classExtendsE: // IEEE: part of class_declaration // // The classExtendsE rule relys on classFront having the // // new class scope correct via classFront /* empty */ { $$ = nullptr; $$ = nullptr; } | yEXTENDS classExtendsList { $$ = $2; $$ = $2; } ; -classExtendsList: // IEEE: part of class_declaration +classExtendsList: // IEEE: part of class_declaration classExtendsOne { $$ = $1; $$ = $1; } | classExtendsList ',' classExtendsOne { $$ = $3; $$ = $3; @@ -6242,7 +6244,7 @@ classExtendsList: // IEEE: part of class_declaration "and unsupported for interface classes."); } ; -classExtendsOne: // IEEE: part of class_declaration +classExtendsOne: // IEEE: part of class_declaration class_typeExtImpList { $$ = new AstClassExtends($1->fileline(), $1); $$ = $1; } From 9949a6cd172a8fcbbc3c56be71015add60a5689f Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Wed, 21 Sep 2022 15:24:17 +0100 Subject: [PATCH 58/75] Generate AstGen::checkTreeiter to enforce Ast op*p use Use astgen to generate a more thorough version of AstNode::checkTree, which checks that operands are or consistent structure and type, as described in the @astgen op directives. Also change checkTree to always run when --debug-check is given. Fix discovered fallout. --- src/V3Ast.cpp | 39 +++------------------- src/V3Ast.h | 7 ++-- src/V3AstInlines.h | 4 +-- src/V3AstNodeDType.h | 4 +-- src/V3AstNodeMath.h | 4 +-- src/V3AstNodeOther.h | 8 +++-- src/astgen | 79 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 97 insertions(+), 48 deletions(-) diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 9b406f816..99f8096d0 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -999,43 +999,12 @@ bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ig //====================================================================== // Debugging -void AstNode::checkTreeIter(AstNode* backp) { +void AstNode::checkTreeIter(const AstNode* backp) const { // private: Check a tree and children UASSERT_OBJ(backp == this->backp(), this, "Back node inconsistent"); - if (VN_IS(this, NodeTermop) || VN_IS(this, NodeVarRef)) { - // Termops have a short-circuited iterateChildren, so check usage - UASSERT_OBJ(!(op1p() || op2p() || op3p() || op4p()), this, - "Terminal operation with non-terminals"); - } - if (m_op1p) m_op1p->checkTreeIterList(this); - if (m_op2p) m_op2p->checkTreeIterList(this); - if (m_op3p) m_op3p->checkTreeIterList(this); - if (m_op4p) m_op4p->checkTreeIterList(this); -} - -void AstNode::checkTreeIterList(AstNode* backp) { - // private: Check a (possible) list of nodes, this is always the head of the list - // Audited to make sure this is never nullptr - AstNode* const headp = this; - const AstNode* tailp = this; - for (AstNode* nodep = headp; nodep; nodep = nodep->nextp()) { - nodep->checkTreeIter(backp); - UASSERT_OBJ(headp == this || !nextp(), this, - "Headtailp should be null in middle of lists"); - tailp = nodep; - backp = nodep; - } - UASSERT_OBJ(headp->m_headtailp == tailp, headp, "Tail in headtailp is inconsistent"); - UASSERT_OBJ(tailp->m_headtailp == headp, tailp, "Head in headtailp is inconsistent"); -} - -void AstNode::checkTree() { - if (!debug()) return; - if (this->backp()) { - // Linked tree- check only the passed node - this->checkTreeIter(this->backp()); - } else { - this->checkTreeIterList(this->backp()); + switch (this->type()) { +#include "V3Ast__gen_op_checks.h" + default: VL_UNREACHABLE; // LCOV_EXCL_LINE } } diff --git a/src/V3Ast.h b/src/V3Ast.h index 87349cc68..a945ea6a2 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1470,8 +1470,7 @@ class AstNode VL_NOT_FINAL { private: AstNode* cloneTreeIter(); AstNode* cloneTreeIterList(); - void checkTreeIter(AstNode* backp); - void checkTreeIterList(AstNode* backp); + void checkTreeIter(const AstNode* backp) const; bool gateTreeIter() const; static bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext, bool gateOnly); @@ -1826,7 +1825,9 @@ public: // Does tree of this == node2p?, not allowing non-isGateOptimizable inline bool sameGateTree(const AstNode* node2p) const; void deleteTree(); // Always deletes the next link - void checkTree(); // User Interface version + void checkTree() const { + if (v3Global.opt.debugCheck()) checkTreeIter(backp()); + } void checkIter() const; void dumpPtrs(std::ostream& os = std::cout) const; void dumpTree(std::ostream& os = std::cout, const string& indent = " ", diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 107579b69..198ed0ec5 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -101,10 +101,10 @@ AstPin::AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) AstDpiExportUpdated::AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep) : ASTGEN_SUPER_DpiExportUpdated(fl) { - addOp1p(new AstVarRef{fl, varScopep, VAccess::WRITE}); + this->varRefp(new AstVarRef{fl, varScopep, VAccess::WRITE}); } -AstVarScope* AstDpiExportUpdated::varScopep() const { return VN_AS(op1p(), VarRef)->varScopep(); } +AstVarScope* AstDpiExportUpdated::varScopep() const { return varRefp()->varScopep(); } AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index c1af84cc3..4da216427 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -281,7 +281,7 @@ public: class AstAssocArrayDType final : public AstNodeDType { // Associative array data type, ie "[some_dtype]" // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width - // @astgen op2 := keyChildDTypep : AstNodeDType // the key, which remains here as a pointer + // @astgen op2 := keyChildDTypep : Optional[AstNodeDType] private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) AstNodeDType* m_keyDTypep; // Keys of this type (after widthing) @@ -996,7 +996,7 @@ public: bool isCompound() const override { return true; } }; class AstRefDType final : public AstNodeDType { - // @astgen op1 := typeofp : AstNode + // @astgen op1 := typeofp : Optional[AstNode] // @astgen op2 := classOrPackageOpp : Optional[AstNode] // @astgen op3 := paramsp : List[AstPin] private: diff --git a/src/V3AstNodeMath.h b/src/V3AstNodeMath.h index 2d5a6f57f..977a49b96 100644 --- a/src/V3AstNodeMath.h +++ b/src/V3AstNodeMath.h @@ -187,7 +187,6 @@ protected: public: ASTGEN_MEMBERS_NodeTermop; // Know no children, and hot function, so skip iterator for speed - // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst void iterateChildren(VNVisitor& v) {} void dump(std::ostream& str) const override; @@ -339,7 +338,6 @@ public: AstNodeModule* classOrPackagep() const { return m_classOrPackagep; } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; } // Know no children, and hot function, so skip iterator for speed - // See checkTreeIter also that asserts no children // cppcheck-suppress functionConst void iterateChildren(VNVisitor& v) {} }; @@ -825,7 +823,7 @@ class AstImplication final : public AstNodeMath { // Verilog |-> |=> // @astgen op1 := lhsp : AstNode // @astgen op2 := rhsp : AstNode - // @astgen op3 := sentreep : AstSenTree + // @astgen op3 := sentreep : Optional[AstSenTree] public: AstImplication(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER_Implication(fl) { diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 12b832507..c386496ed 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -429,7 +429,7 @@ public: }; class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt { // A reference to a task (or function) - // @astgen op1 := namep : AstNode + // @astgen op1 := namep : Optional[AstNode] // op2 used by some sub-types only // @astgen op3 := pinsp : List[AstNode] // @astgen op4 := scopeNamep : Optional[AstScopeName] @@ -1728,7 +1728,7 @@ public: }; class AstSenItem final : public AstNode { // Parents: SENTREE - // @astgen op1 := sensp : AstNode // Sensitivity expression + // @astgen op1 := sensp : Optional[AstNode] // Sensitivity expression VEdgeType m_edgeType; // Edge type public: class Combo {}; // for creator type-overload selection @@ -3077,6 +3077,7 @@ public: }; class AstDpiExportUpdated final : public AstNodeStmt { // Denotes that the referenced variable may have been updated via a DPI Export + // @astgen op1 := varRefp : AstVarRef public: inline AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep); ASTGEN_MEMBERS_DpiExportUpdated; @@ -3496,7 +3497,8 @@ class AstTraceDecl final : public AstNodeStmt { // Trace point declaration // Separate from AstTraceInc; as a declaration can't be deleted // Parents: {statement list} - // @astgen op1 := valuep : AstNode // Expressio being traced + // Expression being traced - Moved to AstTraceInc by V3Trace + // @astgen op1 := valuep : Optional[AstNode] private: uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines const string m_showname; // Name of variable diff --git a/src/astgen b/src/astgen index 56956768d..7b95c081b 100755 --- a/src/astgen +++ b/src/astgen @@ -904,6 +904,84 @@ def write_macros(filename): fh.write("\n") +def write_op_checks(filename): + with open_file(filename) as fh: + + indent = "" + + def emitBlock(pattern, **fmt): + fh.write(textwrap.indent(textwrap.dedent(pattern), indent).format(**fmt)) + + for node in SortedNodes: + if not node.isLeaf: + continue + + emitBlock('''\ + case VNType::at{nodeName}: {{ + const Ast{nodeName}* const currp = static_cast(this); + ''', + nodeName=node.name) + indent = " " + for n in range(1, 5): + op = node.getOp(n) + emitBlock("// Checking op{n}p\n",n=n) + if op: + name, monad, kind = op + if not monad: + emitBlock('''\ + UASSERT_OBJ(currp->{opName}(), currp, "Ast{nodeName} must have non nullptr {opName}()"); + UASSERT_OBJ(!currp->{opName}()->nextp(), currp, "Ast{nodeName}::{opName}() cannot have a non nullptr nextp()"); + currp->{opName}()->checkTreeIter(currp); + ''', + n=n, + nodeName=node.name, + opName=name) + elif monad == "Optional": + emitBlock('''\ + if (Ast{kind}* const opp = currp->{opName}()) {{ + UASSERT_OBJ(!currp->{opName}()->nextp(), currp, "Ast{nodeName}::{opName}() cannot have a non nullptr nextp()"); + opp->checkTreeIter(currp); + }} + ''', + n=n, + nodeName=node.name, + opName=name, + kind=kind) + elif monad == "List": + emitBlock('''\ + if (const Ast{kind}* const headp = currp->{opName}()) {{ + const AstNode* backp = currp; + const Ast{kind}* tailp = headp; + const Ast{kind}* opp = headp; + do {{ + opp->checkTreeIter(backp); + UASSERT_OBJ(opp == headp || !opp->nextp() || !opp->m_headtailp, opp, "Headtailp should be null in middle of lists"); + backp = tailp = opp; + opp = {next}; + }} while (opp); + UASSERT_OBJ(headp->m_headtailp == tailp, headp, "Tail in headtailp is inconsistent"); + UASSERT_OBJ(tailp->m_headtailp == headp, tailp, "Head in headtailp is inconsistent"); + }} + ''', + n=n, + nodeName=node.name, + opName=name, + kind=kind, +next = "VN_AS(opp->nextp(), {kind})".format(kind=kind) if kind != "Node" else "opp->nextp()" +) + else: + sys.exit("Unknown operand type") + else: + emitBlock('''\ + UASSERT_OBJ(!currp->op{n}p(), currp, "Ast{nodeName} does not use op{n}p()"); + ''', n=n, nodeName=node.name) + indent = "" + emitBlock('''\ + break; + }} + ''') + + ###################################################################### # main @@ -1005,6 +1083,7 @@ if Args.classes: write_types("V3Ast__gen_types.h") write_yystype("V3Ast__gen_yystype.h") write_macros("V3Ast__gen_macros.h") + write_op_checks("V3Ast__gen_op_checks.h") for cpt in Args.infiles: if not re.search(r'.cpp$', cpt): From 12093e6939a13107a040e5eafa789c459d2f28d9 Mon Sep 17 00:00:00 2001 From: github action Date: Wed, 21 Sep 2022 19:22:15 +0000 Subject: [PATCH 59/75] Apply 'make format' --- src/astgen | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/astgen b/src/astgen index 7b95c081b..c1d571ecd 100755 --- a/src/astgen +++ b/src/astgen @@ -910,7 +910,9 @@ def write_op_checks(filename): indent = "" def emitBlock(pattern, **fmt): - fh.write(textwrap.indent(textwrap.dedent(pattern), indent).format(**fmt)) + fh.write( + textwrap.indent(textwrap.dedent(pattern), + indent).format(**fmt)) for node in SortedNodes: if not node.isLeaf: @@ -924,7 +926,7 @@ def write_op_checks(filename): indent = " " for n in range(1, 5): op = node.getOp(n) - emitBlock("// Checking op{n}p\n",n=n) + emitBlock("// Checking op{n}p\n", n=n) if op: name, monad, kind = op if not monad: @@ -967,14 +969,17 @@ def write_op_checks(filename): nodeName=node.name, opName=name, kind=kind, -next = "VN_AS(opp->nextp(), {kind})".format(kind=kind) if kind != "Node" else "opp->nextp()" -) + next="VN_AS(opp->nextp(), {kind})".format( + kind=kind) + if kind != "Node" else "opp->nextp()") else: sys.exit("Unknown operand type") else: emitBlock('''\ UASSERT_OBJ(!currp->op{n}p(), currp, "Ast{nodeName} does not use op{n}p()"); - ''', n=n, nodeName=node.name) + ''', + n=n, + nodeName=node.name) indent = "" emitBlock('''\ break; From 63c694f65f5ca2135432ff5d1ab2eba170f8bd31 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sun, 18 Sep 2022 20:53:42 +0100 Subject: [PATCH 60/75] Streamline dump control options - Rename `--dump-treei` option to `--dumpi-tree`, which itself is now a special case of `--dumpi-` where tag can be a magic word, or a filename - Control dumping via static `dump*()` functions, analogous to `debug()` - Make dumping independent of the value of `debug()` (so dumping always works even without the debug flag) - Add separate `--dumpi-graph` for dumping V3Graphs, which is again a special case of `--dumpi-` - Alias `--dump-` to `--dumpi- 3` as before --- bin/verilator | 9 ++-- docs/guide/exe_verilator.rst | 45 +++++++++++----- src/V3Active.cpp | 21 +++----- src/V3ActiveTop.cpp | 5 +- src/V3Assert.cpp | 4 +- src/V3AssertPre.cpp | 5 +- src/V3Ast.cpp | 6 ++- src/V3Begin.cpp | 5 +- src/V3Branch.cpp | 3 +- src/V3Broken.cpp | 2 + src/V3CCtors.cpp | 2 + src/V3CUse.cpp | 4 +- src/V3Case.cpp | 6 +-- src/V3Cast.cpp | 5 +- src/V3Cdc.cpp | 13 +++-- src/V3Changed.cpp | 4 +- src/V3Class.cpp | 5 +- src/V3Clean.cpp | 5 +- src/V3Clock.cpp | 5 +- src/V3Combine.cpp | 5 +- src/V3Common.cpp | 4 +- src/V3Config.cpp | 2 + src/V3Const.cpp | 12 ++--- src/V3Coverage.cpp | 5 +- src/V3CoverageJoin.cpp | 5 +- src/V3Dead.cpp | 14 ++--- src/V3Delayed.cpp | 5 +- src/V3Depth.cpp | 5 +- src/V3DepthBlock.cpp | 5 +- src/V3Descope.cpp | 5 +- src/V3DupFinder.cpp | 6 +-- src/V3DupFinder.h | 1 - src/V3EmitCConstInit.h | 1 - src/V3EmitCConstPool.cpp | 3 +- src/V3EmitCFunc.h | 3 -- src/V3EmitCHeaders.cpp | 3 +- src/V3EmitCImp.cpp | 2 + src/V3EmitCInlines.cpp | 2 + src/V3EmitCMain.cpp | 2 + src/V3EmitCMake.cpp | 7 +-- src/V3EmitCModel.cpp | 4 +- src/V3EmitCSyms.cpp | 2 + src/V3EmitMk.cpp | 4 +- src/V3EmitV.cpp | 3 +- src/V3EmitXml.cpp | 5 +- src/V3Error.cpp | 5 +- src/V3Error.h | 48 +++++++++++++---- src/V3Expand.cpp | 5 +- src/V3File.cpp | 3 +- src/V3FileLine.cpp | 8 +-- src/V3FileLine.h | 1 - src/V3Force.cpp | 4 +- src/V3Gate.cpp | 34 +++++------- src/V3GenClk.cpp | 14 ++--- src/V3Graph.cpp | 7 +-- src/V3Graph.h | 3 -- src/V3GraphAcyc.cpp | 16 +++--- src/V3GraphAlg.cpp | 3 +- src/V3GraphPathChecker.h | 1 - src/V3GraphTest.cpp | 20 +++---- src/V3Hasher.cpp | 3 +- src/V3Hasher.h | 1 - src/V3HierBlock.cpp | 3 +- src/V3HierBlock.h | 2 - src/V3Inline.cpp | 13 ++--- src/V3Inst.cpp | 14 ++--- src/V3InstrCount.cpp | 5 +- src/V3Life.cpp | 7 ++- src/V3LifePost.cpp | 8 ++- src/V3LinkCells.cpp | 6 +-- src/V3LinkDot.cpp | 67 +++++++++++++---------- src/V3LinkDot.h | 27 ++-------- src/V3LinkInc.cpp | 6 +-- src/V3LinkJump.cpp | 6 +-- src/V3LinkLValue.cpp | 7 ++- src/V3LinkLevel.cpp | 6 ++- src/V3LinkParse.cpp | 6 +-- src/V3LinkResolve.cpp | 10 ++-- src/V3Localize.cpp | 6 +-- src/V3MergeCond.cpp | 5 +- src/V3Name.cpp | 6 +-- src/V3Number.cpp | 2 + src/V3Options.cpp | 71 +++++++++++-------------- src/V3Options.h | 22 ++++---- src/V3Order.cpp | 40 +++++--------- src/V3Os.cpp | 8 ++- src/V3Param.cpp | 7 ++- src/V3ParseGrammar.cpp | 2 + src/V3ParseImp.cpp | 8 +-- src/V3ParseImp.h | 21 ++------ src/V3ParseSym.h | 7 ++- src/V3Partition.cpp | 20 +++---- src/V3Partition.h | 1 - src/V3PreLex.h | 5 +- src/V3PreLex.l | 7 +-- src/V3PreProc.cpp | 17 ++---- src/V3PreProc.h | 8 +-- src/V3PreShell.cpp | 14 +---- src/V3Premit.cpp | 6 +-- src/V3ProtectLib.cpp | 2 + src/V3Randomize.cpp | 8 ++- src/V3Reloop.cpp | 5 +- src/V3Scope.cpp | 6 +-- src/V3Simulate.h | 2 +- src/V3Slice.cpp | 6 +-- src/V3Split.cpp | 24 ++++----- src/V3SplitAs.cpp | 5 +- src/V3SplitVar.cpp | 8 +-- src/V3Stats.cpp | 3 +- src/V3StatsReport.cpp | 2 + src/V3String.cpp | 9 +++- src/V3Subst.cpp | 15 ++---- src/V3SymTable.h | 20 ++++--- src/V3TSP.cpp | 16 +++--- src/V3Table.cpp | 5 +- src/V3Task.cpp | 7 +-- src/V3Trace.cpp | 11 ++-- src/V3TraceDecl.cpp | 5 +- src/V3Tristate.cpp | 9 ++-- src/V3Undriven.cpp | 5 +- src/V3Unknown.cpp | 5 +- src/V3Unroll.cpp | 5 +- src/V3VariableOrder.cpp | 4 +- src/V3Width.cpp | 15 ++---- src/V3Width.h | 1 - src/V3WidthCommit.h | 5 +- src/V3WidthSel.cpp | 3 +- src/Verilator.cpp | 4 +- src/VlcMain.cpp | 6 ++- src/VlcPoint.h | 2 + src/VlcTest.h | 2 + test_regress/driver.pl | 2 +- test_regress/t/t_debug_emitv.pl | 2 +- test_regress/t/t_debug_emitv_addrids.pl | 2 +- test_regress/t/t_dotfiles.pl | 2 +- 135 files changed, 565 insertions(+), 589 deletions(-) diff --git a/bin/verilator b/bin/verilator index 45de10206..4c9e08209 100755 --- a/bin/verilator +++ b/bin/verilator @@ -309,10 +309,13 @@ detailed descriptions of these arguments. +define+= Set preprocessor define --dpi-hdr-only Only produce the DPI header file --dump-defines Show preprocessor defines with -E - --dump-tree Enable dumping .tree files + --dump-graph Enable dumping V3Graphs to .dot + --dump-tree Enable dumping Ast .tree files --dump-tree-addrids Use short identifiers instead of addresses - --dump-treei Enable dumping .tree files at a level - --dump-treei- Enable dumping .tree file at a source file at a level + --dump- Enable dumping everything in source file + --dumpi-graph Enable dumping V3Graphs to .dot files at level + --dumpi-tree Enable dumping Ast .tree files at level + --dumpi- Enable dumping everything in source file at level -E Preprocess, but do not compile --error-limit Abort after this number of errors --exe Link to create executable diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index daf2fc5f3..a54510df4 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -266,8 +266,8 @@ Summary: generally is a less-optimized binary with symbols present (so GDB can be used on it). * Enable debugging messages (equivalent to :vlopt:`--debugi 3 <--debugi>`). * Enable internal assertions (equivalent to :vlopt:`--debug-check`). - * Enable intermediate form dump files (equivalent to :vlopt:`--dump-treei 3 - <--dump-treei>`). + * Enable intermediate form dump files (equivalent to :vlopt:`--dumpi-tree 3 + <--dumpi-tree>`). * Leak to make node numbers unique (equivalent to :vlopt:`--debug-leak <--no-debug-leak>`. * Call abort() instead of exit() if there are any errors (so GDB can see @@ -358,26 +358,21 @@ Summary: touch foo.v ; verilator -E --dump-defines foo.v +.. option:: --dump-graph + + Rarely needed. Enable dumping V3Graph .dot debug files with dumping + level 3. Before Verilator 4.228, :vlopt:`--dump-tree` used + to include this option. + .. option:: --dump-tree - Rarely needed. Enable writing .tree debug files with dumping level 3, + Rarely needed. Enable dumping Ast .tree debug files with dumping level 3, which dumps the standard critical stages. For details on the format see the Verilator Internals manual. :vlopt:`--dump-tree` is enabled automatically with :vlopt:`--debug`, so :vlopt:`--debug --no-dump-tree <--dump-tree>` may be useful if the dump files are large and not desired. -.. option:: --dump-treei - -.. option:: --dump-treei- - - Rarely needed - for developer use. Set internal tree dumping level - globally to a specific dumping level or set the specified Verilator - source file to the specified tree dumping level (e.g. - :vlopt:`--dump-treei-V3Order 9 <--dump-treei>`). Level 0 disables dumps - and is equivalent to :vlopt:`--no-dump-tree <--dump-tree>`. Level 9 - enables dumping of every stage. - .. option:: --dump-tree-addrids Rarely needed - for developer use. Replace AST node addresses with @@ -387,6 +382,28 @@ Summary: by a newly allocated node after a node with the same address has been dumped then freed. +.. option:: --dump- + + Rarely needed - for developer use. Enable all dumping in the given + source file at level 3. + +.. option:: --dumpi-graph + + Rarely needed - for developer use. Set internal V3Graph dumping level + globally to the specified value. + +.. option:: --dumpi-tree + + Rarely needed - for developer use. Set internal Ast dumping level + globally to the specified value. + +.. option:: --dumpi- + + Rarely needed - for developer use. Set the dumping level in the + specified Verilator source file to the specified value (e.g. + :vlopt:`--dumpi-V3Order 9`). Level 0 disables dumps and is equivalent + to :vlopt:`--no-dump-`. Level 9 enables dumping of everything. + .. option:: -E Preprocess the source code, but do not compile, similar to C++ diff --git a/src/V3Active.cpp b/src/V3Active.cpp index b85de968e..ac8080eb1 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -38,6 +38,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //***** See below for main transformation engine //###################################################################### @@ -79,8 +81,6 @@ protected: LatchDetectGraphVertex* m_curVertexp = nullptr; // Current latch detection graph vertex std::vector m_outputs; // Vector of lvalues encountered on this pass - VL_DEBUG_FUNC; // Declare debug() - static LatchDetectGraphVertex* castVertexp(void* vertexp) { return reinterpret_cast(vertexp); } @@ -183,7 +183,7 @@ public: << " (not all control paths of combinational always assign a value)\n" << nodep->warnMore() << "... Suggest use of always_latch for intentional latches"); - if (debug() >= 9) dumpDotFilePrefixed("latch_" + vrp->name()); + if (dumpGraph() >= 9) dumpDotFilePrefixed("latch_" + vrp->name()); } vertp->user(false); // Clear again (see above) vrp->varp()->isLatched(latch_detected); @@ -198,12 +198,7 @@ public: //###################################################################### // Collect existing active names -class ActiveBaseVisitor VL_NOT_FINAL : public VNVisitor { -protected: - VL_DEBUG_FUNC; // Declare debug() -}; - -class ActiveNamer final : public ActiveBaseVisitor { +class ActiveNamer final : public VNVisitor { private: // STATE AstScope* m_scopep = nullptr; // Current scope to add statement to @@ -282,7 +277,7 @@ public: //###################################################################### // Latch checking visitor -class ActiveLatchCheckVisitor final : public ActiveBaseVisitor { +class ActiveLatchCheckVisitor final : public VNVisitor { private: // NODE STATE // Input: @@ -324,7 +319,7 @@ public: //###################################################################### // Replace unsupported non-blocking assignments with blocking assignments -class ActiveDlyVisitor final : public ActiveBaseVisitor { +class ActiveDlyVisitor final : public VNVisitor { public: enum CheckType : uint8_t { CT_SEQ, CT_COMB, CT_INITIAL }; @@ -394,7 +389,7 @@ public: //###################################################################### // Active class functions -class ActiveVisitor final : public ActiveBaseVisitor { +class ActiveVisitor final : public VNVisitor { private: // NODE STATE // Each call to V3Const::constify @@ -608,5 +603,5 @@ public: void V3Active::activeAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ActiveVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("active", 0, dumpTree() >= 3); } diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index dc1abe61c..eefa36685 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -33,6 +33,8 @@ #include "V3Global.h" #include "V3SenTree.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Active class functions @@ -49,7 +51,6 @@ private: SenTreeFinder m_finder; // Find global sentree's / add them under the AstTopScope // METHODS - VL_DEBUG_FUNC; // Declare debug() // VISITORS void visit(AstNodeModule* nodep) override { @@ -130,5 +131,5 @@ public: void V3ActiveTop::activeTopAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ActiveTopVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("activetop", 0, dumpTree() >= 3); } diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 2577963f9..c15cd269d 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -23,6 +23,8 @@ #include "V3Global.h" #include "V3Stats.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Assert class functions @@ -475,5 +477,5 @@ public: void V3Assert::assertAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { AssertVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("assert", 0, dumpTree() >= 3); } diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index cdbcec1a4..bb0ae8b27 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -25,6 +25,8 @@ #include "V3Ast.h" #include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Assert class functions @@ -45,7 +47,6 @@ private: AstNode* m_disablep = nullptr; // Last disable // METHODS - VL_DEBUG_FUNC; // Declare debug() AstSenTree* newSenTree(AstNode* nodep) { // Create sentree based on clocked or default clock @@ -206,5 +207,5 @@ public: void V3AssertPre::assertPreAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { AssertPreVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("assertpre", 0, dumpTree() >= 3); } diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 99f8096d0..8f7b102ef 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -28,6 +28,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //====================================================================== // Statics @@ -1120,7 +1122,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo if (logsp->fail()) v3fatal("Can't write " << filename); *logsp << "Verilator Tree Dump (format 0x3900) from to \n"; - if (editCountGbl() == editCountLast() && !(v3Global.opt.dumpTree() >= 9)) { + if (editCountGbl() == editCountLast() && ::dumpTree() < 9) { *logsp << '\n'; *logsp << "No changes since last dump!\n"; } else { @@ -1130,7 +1132,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo } } if (doDump && v3Global.opt.debugEmitV()) V3EmitV::debugEmitV(filename + ".v"); - if (doCheck && (v3Global.opt.debugCheck() || v3Global.opt.dumpTree())) { + if (doCheck && (v3Global.opt.debugCheck() || ::dumpTree())) { // Error check checkTree(); // Broken isn't part of check tree because it can munge iterp's diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 1f5abb9ce..4cdb480e6 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -35,6 +35,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class BeginState final { @@ -70,7 +72,6 @@ private: int m_ifDepth = 0; // Current if depth // METHODS - VL_DEBUG_FUNC; // Declare debug() string dot(const string& a, const string& b) { if (a == "") return b; @@ -322,5 +323,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) { { BeginVisitor{nodep, &state}; } if (state.anyFuncInBegin()) { BeginRelinkVisitor{nodep, &state}; } } // Destruct before checking - V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("begin", 0, dumpTree() >= 3); } diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index 8cd525687..0cf4acda9 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -33,6 +33,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Branch state, as a visitor of each AstNode @@ -49,7 +51,6 @@ private: std::vector m_cfuncsp; // List of all tasks // METHODS - VL_DEBUG_FUNC; // Declare debug() void reset() { m_likely = false; diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index 2be4316d6..d039e593b 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -36,6 +36,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Generation counter for AstNode::m_brokenState diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index e37b4e884..bd8aa3e3a 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -35,6 +35,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + class VCtorType final { public: enum en : uint8_t { MODULE, CLASS, COVERAGE }; diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index adc33fccd..11eb84957 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -32,6 +32,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Visit within a module all nodes and data types they reference, finding @@ -106,5 +108,5 @@ void V3CUse::cUseAll() { // for each output file and put under that CUseVisitor{modp}; } - V3Global::dumpCheckGlobalTree("cuse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("cuse", 0, dumpTree() >= 3); } diff --git a/src/V3Case.cpp b/src/V3Case.cpp index d469978e2..258f76e0d 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -45,6 +45,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + #define CASE_OVERLAP_WIDTH 16 // Maximum width we can check for overlaps in #define CASE_BARF 999999 // Magic width when non-constant #define CASE_ENCODER_GROUP_DEPTH 8 // Levels of priority to be ORed together in top IF tree @@ -57,7 +59,6 @@ private: = nullptr; // Under a CASE value node, if so the relevant case statement // METHODS - VL_DEBUG_FUNC; // Declare debug() void visit(AstNodeCase* nodep) override { if (VN_IS(nodep, Case) && VN_AS(nodep, Case)->casex()) { @@ -138,7 +139,6 @@ private: std::array m_valueItem; // METHODS - VL_DEBUG_FUNC; // Declare debug() bool isCaseTreeFast(AstCase* nodep) { int width = 0; @@ -533,7 +533,7 @@ public: void V3Case::caseAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { CaseVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("case", 0, dumpTree() >= 3); } void V3Case::caseLint(AstNodeCase* nodep) { UINFO(4, __FUNCTION__ << ": " << endl); diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index 5d39416bf..0ab4f4202 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -47,6 +47,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Cast state, as a visitor of each AstNode @@ -60,7 +62,6 @@ private: // STATE // METHODS - VL_DEBUG_FUNC; // Declare debug() void insertCast(AstNode* nodep, int needsize) { // We'll insert ABOVE passed node UINFO(4, " NeedCast " << nodep << endl); @@ -205,5 +206,5 @@ public: void V3Cast::castAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { CastVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("cast", 0, dumpTree() >= 3); } diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 6a6323a15..dc1e5a3e3 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -38,13 +38,14 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + constexpr int CDC_WEIGHT_ASYNC = 0x1000; // Weight for edges that feed async logic //###################################################################### class CdcBaseVisitor VL_NOT_FINAL : public VNVisitor { public: - VL_DEBUG_FUNC; // Declare debug() }; //###################################################################### @@ -323,13 +324,11 @@ private: void analyze() { UINFO(3, __FUNCTION__ << ": " << endl); - // if (debug() > 6) m_graph.dump(); - if (debug() > 6) m_graph.dumpDotFilePrefixed("cdc_pre"); + if (dumpGraph() > 6) m_graph.dumpDotFilePrefixed("cdc_pre"); + // This will MAX across edge weights + m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // - m_graph.removeRedundantEdges( - &V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights - // - m_graph.dumpDotFilePrefixed("cdc_simp"); + if (dumpGraph() >= 3) m_graph.dumpDotFilePrefixed("cdc_simp"); // analyzeReset(); } diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 067d0d0a7..41652250f 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -36,6 +36,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class ChangedState final { @@ -252,5 +254,5 @@ void V3Changed::changedAll(AstNetlist* nodep) { } }); - V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("changed", 0, dumpTree() >= 3); } diff --git a/src/V3Class.cpp b/src/V3Class.cpp index f89be682d..810fe95d7 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -28,6 +28,8 @@ #include "V3Ast.h" #include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class ClassVisitor final : public VNVisitor { @@ -47,7 +49,6 @@ private: std::vector> m_toPackageMoves; // METHODS - VL_DEBUG_FUNC; // Declare debug() void visit(AstClass* nodep) override { if (nodep->user1SetOnce()) return; @@ -207,5 +208,5 @@ public: void V3Class::classAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ClassVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("class", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("class", 0, dumpTree() >= 3); } diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 7817304a2..cd9c96d7d 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -33,6 +33,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Clean state, as a visitor of each AstNode @@ -54,7 +56,6 @@ private: const AstNodeModule* m_modp = nullptr; // METHODS - VL_DEBUG_FUNC; // Declare debug() // Width resetting int cppWidth(AstNode* nodep) { @@ -317,5 +318,5 @@ public: void V3Clean::cleanAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { CleanVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("clean", 0, dumpTree() >= 3); } diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index ed6f5cc1f..af7f6dd79 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -37,6 +37,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Convert every WRITE AstVarRef to a READ ref @@ -88,7 +90,6 @@ private: AstMTaskBody* m_mtaskBodyp = nullptr; // Current mtask body // METHODS - VL_DEBUG_FUNC; // Declare debug() AstVarScope* getCreateLastClk(AstVarScope* vscp) { if (vscp->user1p()) return static_cast(vscp->user1p()); @@ -446,5 +447,5 @@ public: void V3Clock::clockAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ClockVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("clock", 0, dumpTree() >= 3); } diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index e372629d0..7d61aae35 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -33,6 +33,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + class CombineVisitor final : VNVisitor { // NODE STATE // AstNodeModule::user1() List of AstCFuncs in this module (via m_cfuncs) @@ -57,7 +59,6 @@ class CombineVisitor final : VNVisitor { VDouble0 m_cfuncsCombined; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() void removeEmptyFunctions(std::list& funcps) { for (funcit_t it = funcps.begin(), nit; it != funcps.end(); it = nit) { @@ -235,5 +236,5 @@ public: void V3Combine::combineAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); CombineVisitor::apply(nodep); - V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("combine", 0, dumpTree() >= 3); } diff --git a/src/V3Common.cpp b/src/V3Common.cpp index f64018c5b..9961585b9 100644 --- a/src/V3Common.cpp +++ b/src/V3Common.cpp @@ -29,6 +29,8 @@ #include "V3EmitCBase.h" #include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Common component builders @@ -117,5 +119,5 @@ void V3Common::commonAll() { makeToStringMiddle(classp); } } - V3Global::dumpCheckGlobalTree("common", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("common", 0, dumpTree() >= 3); } diff --git a/src/V3Config.cpp b/src/V3Config.cpp index 5c6d77acf..abfd4f295 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -27,6 +27,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Resolve wildcards in files, modules, ftasks or variables diff --git a/src/V3Const.cpp b/src/V3Const.cpp index b94f49373..f091e04bc 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -37,6 +37,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Utilities @@ -350,7 +352,6 @@ class ConstBitOpTreeVisitor final : public VNVisitor { std::vector> m_varInfos; // VarInfo for each variable, [0] is nullptr // METHODS - VL_DEBUG_FUNC; // Declare debug() bool isAndTree() const { return VN_IS(m_rootp, And); } bool isOrTree() const { return VN_IS(m_rootp, Or); } @@ -893,7 +894,6 @@ private: V3UniqueNames m_concswapNames; // For generating unique temporary variable names // METHODS - VL_DEBUG_FUNC; // Declare debug() bool operandConst(AstNode* nodep) { return VN_IS(nodep, Const); } bool operandAsvConst(const AstNode* nodep) { @@ -3664,7 +3664,7 @@ void V3Const::constifyAllLint(AstNetlist* nodep) { ConstVisitor visitor{ConstVisitor::PROC_V_WARN, /* globalPass: */ true}; (void)visitor.mainAcceptEdit(nodep); } // Destruct before checking - V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("const", 0, dumpTree() >= 3); } void V3Const::constifyCpp(AstNetlist* nodep) { @@ -3673,7 +3673,7 @@ void V3Const::constifyCpp(AstNetlist* nodep) { ConstVisitor visitor{ConstVisitor::PROC_CPP, /* globalPass: */ true}; (void)visitor.mainAcceptEdit(nodep); } // Destruct before checking - V3Global::dumpCheckGlobalTree("const_cpp", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("const_cpp", 0, dumpTree() >= 3); } AstNode* V3Const::constifyEdit(AstNode* nodep) { @@ -3697,7 +3697,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) { ConstVisitor visitor{ConstVisitor::PROC_LIVE, /* globalPass: */ true}; (void)visitor.mainAcceptEdit(nodep); } // Destruct before checking - V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("const", 0, dumpTree() >= 3); } void V3Const::constifyAll(AstNetlist* nodep) { @@ -3707,7 +3707,7 @@ void V3Const::constifyAll(AstNetlist* nodep) { ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE, /* globalPass: */ true}; (void)visitor.mainAcceptEdit(nodep); } // Destruct before checking - V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("const", 0, dumpTree() >= 3); } AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) { diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 1a87bb02f..324e6f7a4 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -35,6 +35,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Coverage state, as a visitor of each AstNode @@ -86,7 +88,6 @@ private: m_handleLines; // All line numbers for a given m_stateHandle // METHODS - VL_DEBUG_FUNC; // Declare debug() const char* varIgnoreToggle(AstVar* nodep) { // Return true if this shouldn't be traced @@ -546,5 +547,5 @@ public: void V3Coverage::coverage(AstNetlist* rootp) { UINFO(2, __FUNCTION__ << ": " << endl); { CoverageVisitor{rootp}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("coverage", 0, dumpTree() >= 3); } diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index b0d081a1d..d5571a7a7 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -28,6 +28,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // CoverageJoin state, as a visitor of each AstNode @@ -42,7 +44,6 @@ private: VDouble0 m_statToggleJoins; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() void detectDuplicates() { UINFO(9, "Finding duplicates\n"); @@ -116,5 +117,5 @@ public: void V3CoverageJoin::coverageJoin(AstNetlist* rootp) { UINFO(2, __FUNCTION__ << ": " << endl); { CoverageJoinVisitor{rootp}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("coveragejoin", 0, dumpTree() >= 3); } diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 0d41429cd..83ecf5ffa 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -44,6 +44,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Dead state, as a visitor of each AstNode @@ -78,7 +80,6 @@ private: bool m_sideEffect = false; // Side effects discovered in assign RHS // METHODS - VL_DEBUG_FUNC; // Declare debug() void checkAll(AstNode* nodep) { if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves @@ -455,30 +456,29 @@ public: void V3Dead::deadifyModules(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DeadVisitor{nodep, false, false, false, false}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("deadModules", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("deadModules", 0, dumpTree() >= 6); } void V3Dead::deadifyDTypes(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DeadVisitor{nodep, false, true, false, false}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("deadDtypes", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("deadDtypes", 0, dumpTree() >= 3); } void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DeadVisitor{nodep, false, true, true, false}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, - v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, dumpTree() >= 3); } void V3Dead::deadifyAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DeadVisitor{nodep, true, true, false, true}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("deadAll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("deadAll", 0, dumpTree() >= 3); } void V3Dead::deadifyAllScoped(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DeadVisitor{nodep, true, true, true, true}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("deadAllScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("deadAllScoped", 0, dumpTree() >= 3); } diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index f95ad8f0d..6a4e89ed8 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -61,6 +61,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Delayed state, as a visitor of each AstNode @@ -102,7 +104,6 @@ private: std::unordered_map m_scopeVecMap; // Next var number for each scope // METHODS - VL_DEBUG_FUNC; // Declare debug() void markVarUsage(AstNodeVarRef* nodep, bool blocking) { // Ignore if warning is disabled on this reference (used by V3Force). @@ -524,5 +525,5 @@ public: void V3Delayed::delayedAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DelayedVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("delayed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("delayed", 0, dumpTree() >= 3); } diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index f370c6d09..489d36b7d 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -34,6 +34,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class DepthVisitor final : public VNVisitor { @@ -49,7 +51,6 @@ private: V3UniqueNames m_tempNames; // For generating unique temporary variable names // METHODS - VL_DEBUG_FUNC; // Declare debug() void createDeepTemp(AstNode* nodep) { UINFO(6, " Deep " << nodep << endl); @@ -171,5 +172,5 @@ public: void V3Depth::depthAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DepthVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("depth", 0, dumpTree() >= 6); } diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 89bd99669..9399e78e0 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -31,6 +31,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class DepthBlockVisitor final : public VNVisitor { @@ -44,7 +46,6 @@ private: int m_deepNum = 0; // How many functions made // METHODS - VL_DEBUG_FUNC; // Declare debug() AstCFunc* createDeepFunc(AstNode* nodep) { VNRelinker relinkHandle; @@ -131,5 +132,5 @@ public: void V3DepthBlock::depthBlockAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DepthBlockVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("deepblock", 0, dumpTree() >= 3); } diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index fbf39da8b..b93c0b947 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -33,6 +33,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class DescopeVisitor final : public VNVisitor { @@ -53,7 +55,6 @@ private: FuncMmap m_modFuncs; // Name of public functions added // METHODS - VL_DEBUG_FUNC; // Declare debug() static bool modIsSingleton(AstNodeModule* modp) { // True iff there's exactly one instance of this module in the design (including top). @@ -283,5 +284,5 @@ public: void V3Descope::descopeAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { DescopeVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("descope", 0, dumpTree() >= 3); } diff --git a/src/V3DupFinder.cpp b/src/V3DupFinder.cpp index 17c498646..70647a1d1 100644 --- a/src/V3DupFinder.cpp +++ b/src/V3DupFinder.cpp @@ -28,6 +28,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // V3DupFinder class functions @@ -98,7 +100,5 @@ void V3DupFinder::dumpFile(const string& filename, bool tree) { } void V3DupFinder::dumpFilePrefixed(const string& nameComment, bool tree) { - if (v3Global.opt.dumpTree()) { // - dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree); - } + if (dump()) dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree); } diff --git a/src/V3DupFinder.h b/src/V3DupFinder.h index 3853fa35f..9bc8df81b 100644 --- a/src/V3DupFinder.h +++ b/src/V3DupFinder.h @@ -59,7 +59,6 @@ public: } // METHODS - VL_DEBUG_FUNC; // Declare debug() // Expose minimal set of superclass interface using Super::begin; diff --git a/src/V3EmitCConstInit.h b/src/V3EmitCConstInit.h index 9c0960180..fbcac4c16 100644 --- a/src/V3EmitCConstInit.h +++ b/src/V3EmitCConstInit.h @@ -32,7 +32,6 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitor { uint32_t m_unpackedWord = 0; // METHODS - VL_DEBUG_FUNC; // Declare debug() uint32_t tabModulus(AstNodeDType* dtypep) { const uint32_t elemBytes = dtypep->widthTotalBytes(); diff --git a/src/V3EmitCConstPool.cpp b/src/V3EmitCConstPool.cpp index d813fc955..672d2cabb 100644 --- a/src/V3EmitCConstPool.cpp +++ b/src/V3EmitCConstPool.cpp @@ -27,6 +27,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Const pool emitter @@ -38,7 +40,6 @@ class EmitCConstPool final : public EmitCConstInit { VDouble0 m_constsEmitted; // METHODS - VL_DEBUG_FUNC; // Declare debug() V3OutCFile* newOutCFile() const { const string fileName = v3Global.opt.makeDir() + "/" + topClassName() + "__ConstPool_" diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h index 47c219da6..7a9abae9f 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -90,8 +90,6 @@ class EmitCLazyDecls final : public VNVisitor { void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } - VL_DEBUG_FUNC; - public: explicit EmitCLazyDecls(EmitCBaseVisitor& emitter) : m_emitter(emitter) {} @@ -154,7 +152,6 @@ protected: public: // METHODS - VL_DEBUG_FUNC; // Declare debug() // ACCESSORS void splitSizeInc(int count) { m_splitSize += count; } diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index 2a5c7985b..6e1a541db 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -24,12 +24,13 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Internal EmitC implementation class EmitCHeader final : public EmitCConstInit { // METHODS - VL_DEBUG_FUNC; // Declare debug() void decorateFirst(bool& first, const string& str) { if (first) { diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index cced5d818..c01594c13 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -28,6 +28,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Visitor that gathers the headers required by an AstCFunc diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index 36b92ffec..24556fd5f 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -24,6 +24,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class EmitCInlines final : EmitCBaseVisitor { diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp index 10314155f..a4f95f486 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -25,6 +25,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class EmitCMain final : EmitCBaseVisitor { diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index c053cc45a..d72f6a863 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -26,13 +26,14 @@ #include -//###################################################################### -// Emit statements +VL_DEFINE_DEBUG_FUNCTIONS; + +// ###################################################################### +// Emit statements class CMakeEmitter final { // METHODS - VL_DEBUG_FUNC; // Declare debug() // STATIC FUNCTIONS diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp index 2daf8c4cf..52141a109 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -26,6 +26,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + class EmitCModel final : public EmitCFunc { // TYPES using CFuncVector = std::vector; @@ -34,8 +36,6 @@ class EmitCModel final : public EmitCFunc { V3UniqueNames m_uniqueNames; // For generating unique file names // METHODS - VL_DEBUG_FUNC; - CFuncVector findFuncps(std::function cb) { CFuncVector funcps; for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) { diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index deff75056..d826bf692 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -27,6 +27,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Symbol table emitting diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 726cd96cd..c05f02af8 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -24,13 +24,14 @@ #include "V3HierBlock.h" #include "V3Os.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Emit statements and math operators class EmitMk final { public: // METHODS - VL_DEBUG_FUNC; // Declare debug() void putMakeClassEntry(V3OutMkFile& of, const string& name) { of.puts("\t" + V3Os::filenameNonDirExt(name) + " \\\n"); @@ -399,7 +400,6 @@ public: V3OutMkFile of(m_makefile); emit(of); } - VL_DEBUG_FUNC; // Declare debug() }; //###################################################################### diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 9e7d015da..624fc3f19 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -26,6 +26,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Emit statements and math operators @@ -36,7 +38,6 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor { AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE // METHODS - VL_DEBUG_FUNC; // Declare debug() virtual void puts(const string& str) = 0; virtual void putbs(const string& str) = 0; diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index bac6b6791..89690d6de 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -26,6 +26,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Emit statements and math operators @@ -39,7 +41,6 @@ class EmitXmlFileVisitor final : public VNVisitor { uint64_t m_id = 0; // METHODS - VL_DEBUG_FUNC; // Declare debug() // Outfile methods V3OutFile* ofp() const { return m_ofp; } @@ -330,7 +331,6 @@ private: std::deque m_nodeModules; // METHODS - VL_DEBUG_FUNC; // Declare debug() // VISITORS void visit(AstNetlist* nodep) override { @@ -378,7 +378,6 @@ private: bool m_hasChildren = false; // METHODS - VL_DEBUG_FUNC; // Declare debug() // VISITORS void visit(AstConstPool*) override {} diff --git a/src/V3Error.cpp b/src/V3Error.cpp index 4912e67b4..54b61132d 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -20,6 +20,7 @@ # include "V3Ast.h" # include "V3Global.h" # include "V3Stats.h" +VL_DEFINE_DEBUG_FUNCTIONS; #endif // clang-format on @@ -275,8 +276,10 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& extra) { s_tellManual = 2; } #ifndef V3ERROR_NO_GLOBAL_ - if (debug()) { + if (dumpTree()) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree", 990)); + } + if (debug()) { if (s_errorExitCb) s_errorExitCb(); V3Stats::statsFinalAll(v3Global.rootp()); V3Stats::statsReport(); diff --git a/src/V3Error.h b/src/V3Error.h index e977a5feb..b538c250d 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -317,7 +318,6 @@ public: }; // Global versions, so that if the class doesn't define a operator, we get the functions anyways. -inline int debug() { return V3Error::debugDefault(); } inline void v3errorEnd(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr); } inline void v3errorEndFatal(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr); @@ -412,19 +412,47 @@ inline void v3errorEndFatal(std::ostringstream& sstr) { V3ERROR_NA; \ return value -/// Declare a convenience debug() routine that may be added to any class in -/// Verilator so that --debugi- will work to control UINFOs in -/// that class: -#define VL_DEBUG_FUNC \ - static int debug() { \ +// Helper macros for VL_DEFINE_DEBUG_FUNCTIONS +#define VL_DEFINE_DEBUG(name) \ + VL_ATTR_UNUSED static int debug##name() { \ static int level = -1; \ if (VL_UNLIKELY(level < 0)) { \ - const int debugSrcLevel = v3Global.opt.debugSrcLevel(__FILE__); \ - if (!v3Global.opt.available()) return debugSrcLevel; \ - level = debugSrcLevel; \ + std::string tag{VL_STRINGIFY(name)}; \ + tag[0] = std::tolower(tag[0]); \ + const unsigned debugTag = v3Global.opt.debugLevel(tag); \ + const unsigned debugSrc = v3Global.opt.debugSrcLevel(__FILE__); \ + const unsigned debugLevel = debugTag >= debugSrc ? debugTag : debugSrc; \ + if (!v3Global.opt.available()) return static_cast(debugLevel); \ + level = static_cast(debugLevel); \ } \ return level; \ - } + } \ + static_assert(true, "") + +#define VL_DEFINE_DUMP(name) \ + VL_ATTR_UNUSED static int dump##name() { \ + static int level = -1; \ + if (VL_UNLIKELY(level < 0)) { \ + std::string tag{VL_STRINGIFY(name)}; \ + tag[0] = std::tolower(tag[0]); \ + const unsigned dumpTag = v3Global.opt.dumpLevel(tag); \ + const unsigned dumpSrc = v3Global.opt.dumpSrcLevel(__FILE__); \ + const unsigned dumpLevel = dumpTag >= dumpSrc ? dumpTag : dumpSrc; \ + if (!v3Global.opt.available()) return static_cast(dumpLevel); \ + level = static_cast(dumpLevel); \ + } \ + return level; \ + } \ + static_assert(true, "") + +// Define debug*() and dump*() routines. This needs to be added to every compilation unit so that +// --debugi- and --dumpi- can be used to control debug prints and dumping +#define VL_DEFINE_DEBUG_FUNCTIONS \ + VL_DEFINE_DEBUG(); /* Define 'int debug()' */ \ + VL_DEFINE_DUMP(); /* Define 'int dump()' */ \ + VL_DEFINE_DUMP(Graph); /* Define 'int dumpGraph()' */ \ + VL_DEFINE_DUMP(Tree); /* Define 'int dumpTree()' */ \ + static_assert(true, "") //---------------------------------------------------------------------- diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 9eea581ae..7bba5f825 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -37,6 +37,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Expand state, as a visitor of each AstNode @@ -53,7 +55,6 @@ private: VDouble0 m_statWideLimited; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() bool doExpand(AstNode* nodep) { ++m_statWides; @@ -898,5 +899,5 @@ public: void V3Expand::expandAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ExpandVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("expand", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("expand", 0, dumpTree() >= 3); } diff --git a/src/V3File.cpp b/src/V3File.cpp index 96386cbc4..a8e23182a 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -56,6 +56,8 @@ #endif // clang-format on +VL_DEFINE_DEBUG_FUNCTIONS; + // If change this code, run a test with the below size set very small // #define INFILTER_IPC_BUFSIZ 16 constexpr int INFILTER_IPC_BUFSIZ = (64 * 1024); // For debug, try this as a small number @@ -346,7 +348,6 @@ class VInFilterImp final { private: // METHODS - VL_DEBUG_FUNC; // Declare debug() bool readContents(const string& filename, StrList& outl) { if (m_pid) { diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 93940bac6..b313b2063 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -33,6 +33,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // FileLineSingleton class functions @@ -83,12 +85,6 @@ void FileLineSingleton::fileNameNumMapDumpXml(std::ostream& os) { //###################################################################### // VFileContents class functions -int VFileContent::debug() { - static int level = -1; - if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__); - return level; -} - void VFileContent::pushText(const string& text) { if (m_lines.size() == 0) { m_lines.emplace_back(""); // no such thing as line [0] diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 892fb97bd..e3cd40fc4 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -77,7 +77,6 @@ public: void pushText(const string& text); // Add arbitrary text (need not be line-by-line) string getLine(int lineno) const; string ascii() const { return "ct" + cvtToStr(m_id); } - static int debug(); }; std::ostream& operator<<(std::ostream& os, VFileContent* contentp); diff --git a/src/V3Force.cpp b/src/V3Force.cpp index 446869208..bebf210ac 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -46,6 +46,8 @@ #include "V3Error.h" #include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Convert force/release statements and signals marked 'forceable' @@ -305,5 +307,5 @@ void V3Force::forceAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); if (!v3Global.hasForceableSignals()) return; ForceConvertVisitor::apply(nodep); - V3Global::dumpCheckGlobalTree("force", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("force", 0, dumpTree() >= 3); } diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index c4695ec28..6829d55ee 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -39,6 +39,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + class GateDedupeVarVisitor; using GateVarRefList = std::list; @@ -47,13 +49,6 @@ constexpr int GATE_DEDUP_MAX_DEPTH = 20; //###################################################################### -class GateBaseVisitor VL_NOT_FINAL : public VNVisitor { -public: - VL_DEBUG_FUNC; // Declare debug() -}; - -//###################################################################### - class GateLogicVertex; class GateVarVertex; class GateGraphBaseVisitor VL_NOT_FINAL { @@ -64,7 +59,6 @@ public: virtual ~GateGraphBaseVisitor() = default; virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu = VNUser{0}) = 0; virtual VNUser visit(GateVarVertex* vertexp, VNUser vu = VNUser{0}) = 0; - VL_DEBUG_FUNC; // Declare debug() }; //###################################################################### @@ -194,7 +188,7 @@ public: //###################################################################### // Is this a simple math expression with a single input and single output? -class GateOkVisitor final : public GateBaseVisitor { +class GateOkVisitor final : public VNVisitor { private: // RETURN STATE bool m_isSimple = true; // Set false when we know it isn't simple @@ -309,7 +303,7 @@ static void eliminate(AstNode* logicp, // ###################################################################### // Gate class functions -class GateVisitor final : public GateBaseVisitor { +class GateVisitor final : public VNVisitor { private: // NODE STATE // Entire netlist: @@ -413,13 +407,12 @@ private: // VISITORS void visit(AstNetlist* nodep) override { iterateChildren(nodep); - // if (debug() > 6) m_graph.dump(); - if (debug() > 6) m_graph.dumpDotFilePrefixed("gate_pre"); + if (dumpGraph() >= 3) m_graph.dumpDotFilePrefixed("gate_pre"); warnSignals(); // Before loss of sync/async pointers // Decompose clock vectors -- need to do this before removing redundant edges decomposeClkVectors(); m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue); - m_graph.dumpDotFilePrefixed("gate_simp"); + if (dumpGraph() >= 6) m_graph.dumpDotFilePrefixed("gate_simp"); // Find gate interconnect and optimize m_graph.userClearVertices(); // vertex->user(): bool. Indicates we've set it as consumed // Get rid of buffers first, @@ -431,15 +424,15 @@ private: // Remove redundant logic if (v3Global.opt.fDedupe()) { dedupe(); - if (debug() >= 6) m_graph.dumpDotFilePrefixed("gate_dedup"); + if (dumpGraph() >= 6) m_graph.dumpDotFilePrefixed("gate_dedup"); } if (v3Global.opt.fAssemble()) { mergeAssigns(); - if (debug() >= 6) m_graph.dumpDotFilePrefixed("gate_assm"); + if (dumpGraph() >= 6) m_graph.dumpDotFilePrefixed("gate_assm"); } // Consumption warnings consumedMark(); - m_graph.dumpDotFilePrefixed("gate_opt"); + if (dumpGraph() >= 3) m_graph.dumpDotFilePrefixed("gate_opt"); // Rewrite assignments consumedMove(); } @@ -780,8 +773,6 @@ private: V3DupFinder m_dupFinder; // Duplicate finder for rhs of assigns std::unordered_set m_nodeDeleteds; // Any node in this hash was deleted - VL_DEBUG_FUNC; // Declare debug() - bool same(AstNode* node1p, AstNode* node2p) { // Regarding the complexity of this funcition 'same': // Applying this comparison function to a a set of n trees pairwise is O(n^2) in the @@ -886,7 +877,7 @@ public: //###################################################################### // Have we seen the rhs of this assign before? -class GateDedupeVarVisitor final : public GateBaseVisitor { +class GateDedupeVarVisitor final : public VNVisitor { // Given a node, it is visited to try to find the AstNodeAssign under // it that can used for dedupe. // Right now, only the following node trees are supported for dedupe. @@ -1070,7 +1061,6 @@ private: const GateLogicVertex* const consumeVertexp = static_cast(outedgep->top()); AstNode* const consumerp = consumeVertexp->nodep(); - // if (debug() >= 9) m_graphp->dumpDotFilePrefixed("gate_preelim"); UINFO(9, "elim src vtx" << lvertexp << " node " << lvertexp->nodep() << endl); UINFO(9, @@ -1286,7 +1276,7 @@ void GateVisitor::mergeAssigns() { //###################################################################### // Find a var's offset in a concatenation -class GateConcatVisitor final : public GateBaseVisitor { +class GateConcatVisitor final : public VNVisitor { private: // STATE const AstVarScope* m_vscp = nullptr; // Varscope we're trying to find @@ -1482,5 +1472,5 @@ void GateVisitor::decomposeClkVectors() { void V3Gate::gateAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { const GateVisitor visitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("gate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("gate", 0, dumpTree() >= 3); } diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index d6d4d11f5..d4b507238 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -27,18 +27,12 @@ #include "V3Ast.h" #include "V3Global.h" -//###################################################################### -// GenClk state, as a visitor of each AstNode - -class GenClkBaseVisitor VL_NOT_FINAL : public VNVisitor { -protected: - VL_DEBUG_FUNC; // Declare debug() -}; +VL_DEFINE_DEBUG_FUNCTIONS; //###################################################################### // GenClk Read -class GenClkRenameVisitor final : public GenClkBaseVisitor { +class GenClkRenameVisitor final : public VNVisitor { private: // NODE STATE // Cleared on top scope @@ -126,7 +120,7 @@ public: //###################################################################### // GenClk Read -class GenClkReadVisitor final : public GenClkBaseVisitor { +class GenClkReadVisitor final : public VNVisitor { private: // NODE STATE // Cleared on top scope @@ -221,5 +215,5 @@ public: void V3GenClk::genClkAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { GenClkReadVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("genclk", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("genclk", 0, dumpTree() >= 3); } diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index fe0be1cf6..faffb7b41 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -28,8 +28,7 @@ #include #include -int V3Graph::s_debug = 0; -int V3Graph::debug() { return std::max(V3Error::debugDefault(), s_debug); } +VL_DEFINE_DEBUG_FUNCTIONS; //###################################################################### //###################################################################### @@ -312,9 +311,7 @@ void V3Graph::dumpEdge(std::ostream& os, V3GraphVertex* vertexp, V3GraphEdge* ed } void V3Graph::dumpDotFilePrefixed(const string& nameComment, bool colorAsSubgraph) const { - if (v3Global.opt.dumpTree()) { - dumpDotFile(v3Global.debugFilename(nameComment) + ".dot", colorAsSubgraph); - } + dumpDotFile(v3Global.debugFilename(nameComment) + ".dot", colorAsSubgraph); } //! Variant of dumpDotFilePrefixed without --dump option check diff --git a/src/V3Graph.h b/src/V3Graph.h index 9d6b9ea06..8190e946e 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -81,7 +81,6 @@ class V3Graph VL_NOT_FINAL { private: // MEMBERS V3List m_vertices; // All vertices - static int s_debug; protected: friend class V3GraphVertex; @@ -92,12 +91,10 @@ protected: void dumpEdge(std::ostream& os, V3GraphVertex* vertexp, V3GraphEdge* edgep); void verticesUnlink() { m_vertices.reset(); } // ACCESSORS - static int debug(); public: V3Graph(); virtual ~V3Graph(); - static void debug(int level) { s_debug = level; } virtual string dotRankDir() const { return "TB"; } // rankdir for dot plotting // METHODS diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 8860a5479..016c6930b 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -24,6 +24,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### //###################################################################### // Algorithms - acyclic @@ -104,8 +106,6 @@ private: m_origEdgeFuncp; // Function that says we follow this edge (in original graph) uint32_t m_placeStep = 0; // Number that user() must be equal to to indicate processing - static int debug() { return V3Graph::debug(); } - // METHODS void buildGraph(V3Graph* origGraphp); void buildGraphIterate(V3GraphVertex* overtexp, GraphAcycVertex* avertexp); @@ -544,28 +544,28 @@ void GraphAcyc::main() { // edges (and thus can't represent loops - if we did the unbreakable // marking right, anyways) buildGraph(m_origGraphp); - if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_pre"); + if (dumpGraph() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_pre"); // Perform simple optimizations before any cuttings simplify(false); - if (debug() >= 5) m_breakGraph.dumpDotFilePrefixed("acyc_simp"); + if (dumpGraph() >= 5) m_breakGraph.dumpDotFilePrefixed("acyc_simp"); UINFO(4, " Cutting trivial loops\n"); simplify(true); - if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_mid"); + if (dumpGraph() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_mid"); UINFO(4, " Ranking\n"); m_breakGraph.rank(&V3GraphEdge::followNotCutable); - if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_rank"); + if (dumpGraph() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_rank"); UINFO(4, " Placement\n"); place(); - if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_place"); + if (dumpGraph() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_place"); UINFO(4, " Final Ranking\n"); // Only needed to assert there are no loops in completed graph m_breakGraph.rank(&V3GraphEdge::followAlwaysTrue); - if (debug() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_done"); + if (dumpGraph() >= 6) m_breakGraph.dumpDotFilePrefixed("acyc_done"); } void V3Graph::acyclic(V3EdgeFuncP edgeFuncp) { diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index c5e7dcec9..0e5042b5a 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -27,6 +27,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### //###################################################################### // Algorithms - weakly connected components @@ -120,7 +122,6 @@ public: } private: - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(GraphAlgRemoveTransitiveEdges); }; diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index 06be17d4f..b919c7869 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -56,7 +56,6 @@ private: void initHalfCriticalPaths(GraphWay way, bool checkOnly); void incGeneration() { ++m_generation; } - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(GraphPathChecker); }; diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index 40f847e0e..3fdb8dfe7 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -20,6 +20,8 @@ #include "V3Global.h" #include "V3Graph.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### //###################################################################### // Test class @@ -34,14 +36,14 @@ protected: virtual string name() = 0; // Name of the test // Utilities - void dump() { - if (debug() >= 9) m_graph.dumpDotFilePrefixed("v3graphtest_" + name()); + void dumpSelf() { + if (dumpGraph() >= 9) m_graph.dumpDotFilePrefixed("v3graphtest_" + name()); } public: V3GraphTest() = default; virtual ~V3GraphTest() = default; - VL_DEBUG_FUNC; // Declare debug() + void run() { runTest(); } }; @@ -101,7 +103,7 @@ public: new V3GraphEdge(gp, g3, q, 2, true); gp->stronglyConnected(&V3GraphEdge::followAlwaysTrue); - dump(); + dumpSelf(); UASSERT(i->color() != a->color() && a->color() != g2->color() && g2->color() != q->color(), "SelfTest: Separate colors not assigned"); @@ -136,7 +138,7 @@ public: gp->acyclic(&V3GraphEdge::followAlwaysTrue); gp->order(); - dump(); + dumpSelf(); } }; @@ -253,7 +255,7 @@ public: gp->acyclic(&V3GraphEdge::followAlwaysTrue); gp->order(); - dump(); + dumpSelf(); } }; @@ -272,11 +274,11 @@ public: void runTest() override { V3Graph* const gp = &m_graph; dotImport(); - dump(); + dumpSelf(); gp->acyclic(&V3GraphEdge::followAlwaysTrue); - dump(); + dumpSelf(); gp->rank(&V3GraphEdge::followAlwaysTrue); - dump(); + dumpSelf(); } }; diff --git a/src/V3Hasher.cpp b/src/V3Hasher.cpp index 7a2f7d78d..97fef5716 100644 --- a/src/V3Hasher.cpp +++ b/src/V3Hasher.cpp @@ -21,6 +21,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Visitor that computes node hashes @@ -35,7 +37,6 @@ private: const bool m_cacheInUser4; // Use user4 to cache each V3Hash? // METHODS - VL_DEBUG_FUNC; // Declare debug() V3Hash hashNodeAndIterate(AstNode* nodep, bool hashDType, bool hashChildren, std::function&& f) { diff --git a/src/V3Hasher.h b/src/V3Hasher.h index 9944f84b1..823a1a074 100644 --- a/src/V3Hasher.h +++ b/src/V3Hasher.h @@ -40,7 +40,6 @@ public: ~V3Hasher() = default; // METHODS - VL_DEBUG_FUNC; // Declare debug() // Compute hash of node. This method caches the hash in the node's user4(). V3Hash operator()(AstNode* nodep) const; diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index 7a1b07057..a5f2fa38a 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -86,6 +86,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + static string V3HierCommandArgsFileName(const string& prefix, bool forCMake) { return v3Global.opt.makeDir() + "/" + prefix + (forCMake ? "_hierCMakeArgs.f" : "_hierMkArgs.f"); @@ -302,7 +304,6 @@ public: : m_planp{planp} { iterateChildren(netlist); } - VL_DEBUG_FUNC; // Declare debug() }; //###################################################################### diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index b4fe14374..7526423d5 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -67,7 +67,6 @@ public: : m_modp{modp} , m_gparams{gparams} {} ~V3HierBlock(); - VL_DEBUG_FUNC; // Declare debug() void addParent(V3HierBlock* parentp) { m_parents.insert(parentp); } void addChild(V3HierBlock* childp) { m_children.insert(childp); } @@ -107,7 +106,6 @@ public: using iterator = HierMap::iterator; using const_iterator = HierMap::const_iterator; using HierVector = std::vector; - VL_DEBUG_FUNC; // Declare debug() void add(const AstNodeModule* modp, const std::vector& gparams); void registerUsage(const AstNodeModule* parentp, const AstNodeModule* childp); diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index cacca2901..cad404fbc 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -40,6 +40,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + // CONFIG static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can always inline it @@ -95,7 +97,6 @@ private: std::unordered_map m_instances; // METHODS - VL_DEBUG_FUNC; // Declare debug() void cantInline(const char* reason, bool hard) { if (hard) { if (m_modp->user2() != CIL_NOTHARD) { @@ -256,9 +257,6 @@ private: AstNodeModule* const m_modp; // Current module const AstCell* const m_cellp; // Cell being cloned - // METHODS - VL_DEBUG_FUNC; // Declare debug() - // VISITORS void visit(AstCellInline* nodep) override { // Inlined cell under the inline cell, need to move to avoid conflicts @@ -478,8 +476,6 @@ private: VDouble0 m_statCells; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() - void inlineCell(AstCell* nodep) { UINFO(5, " Inline CELL " << nodep << endl); @@ -635,9 +631,6 @@ private: string m_scope; // Scope name - // METHODS - VL_DEBUG_FUNC; // Declare debug() - // VISITORS void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); } void visit(AstCell* nodep) override { @@ -734,5 +727,5 @@ void V3Inline::inlineAll(AstNetlist* nodep) { } { InlineIntfRefVisitor{nodep}; } - V3Global::dumpCheckGlobalTree("inline", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("inline", 0, dumpTree() >= 3); } diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index adca8b9da..328318dc5 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -32,6 +32,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Inst state, as a visitor of each AstNode @@ -45,9 +47,6 @@ private: // STATE AstCell* m_cellp = nullptr; // Current cell - // METHODS - VL_DEBUG_FUNC; // Declare debug() - // VISITORS void visit(AstCell* nodep) override { UINFO(4, " CELL " << nodep << endl); @@ -146,8 +145,6 @@ private: // STATE std::map m_modVarNameMap; // Per module, name of cloned variables - VL_DEBUG_FUNC; // Declare debug() - // VISITORS void visit(AstVar* nodep) override { if (VN_IS(nodep->dtypep(), IfaceRefDType)) { @@ -200,8 +197,6 @@ private: int m_instSelNum = 0; // Current instantiation count 0..N-1 InstDeModVarVisitor m_deModVars; // State of variables for current cell module - VL_DEBUG_FUNC; // Declare debug() - // VISITORS void visit(AstVar* nodep) override { if (VN_IS(nodep->dtypep(), UnpackArrayDType) @@ -492,7 +487,6 @@ public: class InstStatic final { private: - VL_DEBUG_FUNC; // Declare debug() InstStatic() = default; // Static class static AstNode* extendOrSel(FileLine* fl, AstNode* rhsp, AstNode* cmpWidthp) { @@ -622,11 +616,11 @@ void V3Inst::checkOutputShort(AstPin* nodep) { void V3Inst::instAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { InstVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("inst", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("inst", 0, dumpTree() >= 3); } void V3Inst::dearrayAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { InstDeVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("dearray", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("dearray", 0, dumpTree() >= 6); } diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 4a394fe80..1f2cc3a9b 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -24,6 +24,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + /// Estimate the instruction cost for executing all logic within and below /// a given AST node. Note this estimates the number of instructions we'll /// execute, not the number we'll generate. That is, for conditionals, @@ -254,7 +256,6 @@ private: iterateChildren(nodep); } - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(InstrCountVisitor); }; @@ -290,7 +291,7 @@ private: } --m_depth; } - VL_DEBUG_FUNC; // Declare debug() + VL_UNCOPYABLE(InstrCountDumpVisitor); }; diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 62459ba84..534c5afca 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -36,6 +36,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Structure for global state @@ -129,8 +131,6 @@ class LifeBlock final { LifeBlock* const m_aboveLifep; // Upper life, or nullptr LifeState* const m_statep; // Current global state - VL_DEBUG_FUNC; // Declare debug() - public: LifeBlock(LifeBlock* aboveLifep, LifeState* statep) : m_aboveLifep{aboveLifep} // Null if top @@ -284,7 +284,6 @@ private: LifeBlock* m_lifep; // Current active lifetime map for current scope // METHODS - VL_DEBUG_FUNC; // Declare debug() void setNoopt() { m_noopt = true; m_lifep->clear(); @@ -495,5 +494,5 @@ void V3Life::lifeAll(AstNetlist* nodep) { LifeState state; LifeTopVisitor{nodep, &state}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("life", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("life", 0, dumpTree() >= 3); } diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index ce750f4f8..63758d067 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -38,6 +38,8 @@ #include // for std::unique_ptr -> auto_ptr or unique_ptr #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // LifePost class functions @@ -50,8 +52,6 @@ private: // AstVarScope::user4p() -> AstVarScope*, If set, replace this // varscope with specified new one // STATE - // METHODS - VL_DEBUG_FUNC; // Declare debug() // VISITORS void visit(AstVarRef* nodep) override { @@ -157,8 +157,6 @@ private: std::unique_ptr m_checker; // METHODS - VL_DEBUG_FUNC; // Declare debug() - bool before(const LifeLocation& a, const LifeLocation& b) { if (a.mtaskp == b.mtaskp) return a.sequence < b.sequence; return m_checker->pathExistsFrom(a.mtaskp, b.mtaskp); @@ -351,5 +349,5 @@ void V3LifePost::lifepostAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); // Mark redundant AssignPost { LifePostDlyVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("life_post", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("life_post", 0, dumpTree() >= 3); } diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index 5057a4090..c92a41a10 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -39,6 +39,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Graph subclasses @@ -118,8 +120,6 @@ private: std::unordered_set m_declfnWarned; // Files we issued DECLFILENAME on string m_origTopModuleName; // original name of the top module - VL_DEBUG_FUNC; // Declare debug() - // METHODS V3GraphVertex* vertex(AstNodeModule* nodep) { // Return corresponding vertex for this module @@ -167,7 +167,7 @@ private: iterateChildren(nodep); // Find levels in graph m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); - m_graph.dumpDotFilePrefixed("linkcells"); + if (dumpGraph()) m_graph.dumpDotFilePrefixed("linkcells"); m_graph.rank(); for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { if (const LinkCellsVertex* const vvertexp = dynamic_cast(itp)) { diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 57f9fca83..75681218f 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -76,8 +76,10 @@ #include #include -//###################################################################### -// Matcher classes (for suggestion matching) +VL_DEFINE_DEBUG_FUNCTIONS; + +// ###################################################################### +// Matcher classes (for suggestion matching) class LinkNodeMatcherClass final : public VNodeMatcher { public: @@ -162,14 +164,14 @@ private: public: // METHODS - VL_DEBUG_FUNC; // Declare debug() - void dump(const string& nameComment = "linkdot", bool force = false) { - if (debug() >= 6 || force) { + + void dumpSelf(const string& nameComment = "linkdot", bool force = false) { + if (dump() >= 6 || force) { const string filename = v3Global.debugFilename(nameComment) + ".txt"; const std::unique_ptr logp{V3File::new_ofstream(filename)}; if (logp->fail()) v3fatal("Can't write " << filename); std::ostream& os = *logp; - m_syms.dump(os); + m_syms.dumpSelf(os); bool first = true; for (int samn = 0; samn < SAMN__MAX; ++samn) { if (!m_scopeAliasMap[samn].empty()) { @@ -191,9 +193,9 @@ public: } void preErrorDump() { static bool diddump = false; - if (!diddump && v3Global.opt.dumpTree()) { + if (!diddump && dumpTree()) { diddump = true; - dump("linkdot-preerr", true); + dumpSelf("linkdot-preerr", true); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("linkdot-preerr.tree")); } } @@ -726,8 +728,6 @@ class LinkDotFindVisitor final : public VNVisitor { int m_modWithNum = 0; // With block number, 0=none seen // METHODS - static int debug() { return LinkDotState::debug(); } - void makeImplicitNew(AstClass* nodep) { AstFunc* const newp = new AstFunc(nodep->fileline(), "new", nullptr, nullptr); newp->isConstructor(true); @@ -1400,8 +1400,6 @@ private: LinkDotState* const m_statep; // State to pass between visitors, including symbol table AstNodeModule* m_modp = nullptr; // Current module - static int debug() { return LinkDotState::debug(); } - void pinImplicitExprRecurse(AstNode* nodep) { // Under a pin, Check interconnect expression for a pin reference or a concat. // Create implicit variable as needed @@ -1591,8 +1589,6 @@ class LinkDotScopeVisitor final : public VNVisitor { const AstScope* m_scopep = nullptr; // The current scope VSymEnt* m_modSymp = nullptr; // Symbol entry for current module - static int debug() { return LinkDotState::debug(); } - // VISITs void visit(AstNetlist* nodep) override { // Recurse..., backward as must do packages before using packages @@ -1756,9 +1752,6 @@ class LinkDotIfaceVisitor final : public VNVisitor { LinkDotState* const m_statep; // State to pass between visitors, including symbol table VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert - // METHODS - static int debug() { return LinkDotState::debug(); } - // VISITs void visit(AstModport* nodep) override { // Modport: Remember its name for later resolution @@ -1906,8 +1899,6 @@ private: } } m_ds; // State to preserve across recursions - static int debug() { return LinkDotState::debug(); } - // METHODS - Variables void createImplicitVar(VSymEnt* /*lookupSymp*/, AstVarRef* nodep, AstNodeModule* modp, VSymEnt* moduleSymp, bool noWarn) { @@ -3176,21 +3167,19 @@ public: //###################################################################### // Link class functions -int V3LinkDot::debug() { return LinkDotState::debug(); } - void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { - if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { + if (debug() >= 5 || dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot.tree")); } LinkDotState state(rootp, step); const LinkDotFindVisitor visitor{rootp, &state}; - if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { + if (debug() >= 5 || dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-find.tree")); } if (step == LDS_PRIMARY || step == LDS_PARAMED) { // Initial link stage, resolve parameters const LinkDotParamVisitor visitors{rootp, &state}; - if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { + if (debug() >= 5 || dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-param.tree")); } } else if (step == LDS_ARRAYED) { @@ -3199,16 +3188,40 @@ void V3LinkDot::linkDotGuts(AstNetlist* rootp, VLinkDotStep step) { // process AstScope's. This needs to be separate pass after whole hierarchy graph created. const LinkDotScopeVisitor visitors{rootp, &state}; v3Global.assertScoped(true); - if (LinkDotState::debug() >= 5 || v3Global.opt.dumpTree() >= 9) { + if (debug() >= 5 || dumpTree() >= 9) { v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("prelinkdot-scoped.tree")); } } else { v3fatalSrc("Bad case"); } - state.dump(); + state.dumpSelf(); state.computeIfaceModSyms(); state.computeIfaceVarSyms(); state.computeScopeAliases(); - state.dump(); + state.dumpSelf(); { LinkDotResolveVisitor{rootp, &state}; } } + +void V3LinkDot::linkDotPrimary(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + linkDotGuts(nodep, LDS_PRIMARY); + V3Global::dumpCheckGlobalTree("linkdot", 0, dumpTree() >= 6); +} + +void V3LinkDot::linkDotParamed(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + linkDotGuts(nodep, LDS_PARAMED); + V3Global::dumpCheckGlobalTree("linkdotparam", 0, dumpTree() >= 3); +} + +void V3LinkDot::linkDotArrayed(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + linkDotGuts(nodep, LDS_ARRAYED); + V3Global::dumpCheckGlobalTree("linkdot", 0, dumpTree() >= 6); +} + +void V3LinkDot::linkDotScope(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + linkDotGuts(nodep, LDS_SCOPED); + V3Global::dumpCheckGlobalTree("linkdot", 0, dumpTree() >= 3); +} diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index 260c8cbcf..428f18904 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -28,32 +28,13 @@ enum VLinkDotStep : uint8_t { LDS_PRIMARY, LDS_PARAMED, LDS_ARRAYED, LDS_SCOPED }; class V3LinkDot final { -private: - static int debug(); static void linkDotGuts(AstNetlist* rootp, VLinkDotStep step); public: - static void linkDotPrimary(AstNetlist* nodep) { - UINFO(2, __FUNCTION__ << ": " << endl); - linkDotGuts(nodep, LDS_PRIMARY); - V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); - } - static void linkDotParamed(AstNetlist* nodep) { - UINFO(2, __FUNCTION__ << ": " << endl); - linkDotGuts(nodep, LDS_PARAMED); - V3Global::dumpCheckGlobalTree("linkdotparam", 0, - v3Global.opt.dumpTreeLevel(__FILE__) >= 3); - } - static void linkDotArrayed(AstNetlist* nodep) { - UINFO(2, __FUNCTION__ << ": " << endl); - linkDotGuts(nodep, LDS_ARRAYED); - V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); - } - static void linkDotScope(AstNetlist* nodep) { - UINFO(2, __FUNCTION__ << ": " << endl); - linkDotGuts(nodep, LDS_SCOPED); - V3Global::dumpCheckGlobalTree("linkdot", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); - } + static void linkDotPrimary(AstNetlist* nodep); + static void linkDotParamed(AstNetlist* nodep); + static void linkDotArrayed(AstNetlist* nodep); + static void linkDotScope(AstNetlist* nodep); }; #endif // Guard diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index d0e852849..91bfbe530 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -46,6 +46,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class LinkIncVisitor final : public VNVisitor { @@ -64,8 +66,6 @@ private: bool m_unsupportedHere = false; // Used to detect where it's not supported yet // METHODS - VL_DEBUG_FUNC; // Declare debug() - void insertBeforeStmt(AstNode* nodep, AstNode* newp) { // Return node that must be visited, if any // See also AstNode::addBeforeStmt; this predates that function @@ -276,5 +276,5 @@ public: void V3LinkInc::linkIncrements(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { LinkIncVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("linkinc", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("linkinc", 0, dumpTree() >= 3); } diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 2c5802704..5243ed1cb 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -40,6 +40,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class LinkJumpVisitor final : public VNVisitor { @@ -54,8 +56,6 @@ private: std::vector m_blockStack; // All begin blocks above current node // METHODS - VL_DEBUG_FUNC; // Declare debug() - AstJumpLabel* findAddLabel(AstNode* nodep, bool endOfIter) { // Put label under given node, and if WHILE optionally at end of iteration UINFO(4, "Create label for " << nodep << endl); @@ -303,5 +303,5 @@ public: void V3LinkJump::linkJump(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { LinkJumpVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("linkjump", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("linkjump", 0, dumpTree() >= 3); } diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 0925b89c3..d0e01d997 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -28,6 +28,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Link state, as a visitor of each AstNode @@ -41,9 +43,6 @@ private: VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments AstNodeFTask* m_ftaskp = nullptr; // Function or task we're inside - // METHODS - VL_DEBUG_FUNC; // Declare debug() - // VISITs // Result handing void visit(AstNodeVarRef* nodep) override { @@ -338,7 +337,7 @@ public: void V3LinkLValue::linkLValue(AstNetlist* nodep) { UINFO(4, __FUNCTION__ << ": " << endl); { LinkLValueVisitor{nodep, VAccess::NOCHANGE}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("linklvalue", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("linklvalue", 0, dumpTree() >= 6); } void V3LinkLValue::linkLValueSet(AstNode* nodep) { // Called by later link functions when it is known a node needs diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 9c88973f6..cdb9b19c8 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -31,6 +31,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Levelizing class functions @@ -78,7 +80,7 @@ void V3LinkLevel::modSortByLevel() { UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work"); for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulesp(nodep); UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666 - V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("cells", false, dumpTree() >= 3); } void V3LinkLevel::timescaling(const ModVec& mods) { @@ -174,7 +176,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { } } - V3Global::dumpCheckGlobalTree("wraptop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("wraptop", 0, dumpTree() >= 6); } void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 1fff33a56..43ade69e9 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -32,6 +32,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Link state, as a visitor of each AstNode @@ -62,8 +64,6 @@ private: VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime // METHODS - VL_DEBUG_FUNC; // Declare debug() - void cleanFileline(AstNode* nodep) { if (!nodep->user2SetOnce()) { // Process once // We make all filelines unique per AstNode. This allows us to @@ -619,5 +619,5 @@ public: void V3LinkParse::linkParse(AstNetlist* rootp) { UINFO(4, __FUNCTION__ << ": " << endl); { LinkParseVisitor{rootp}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("linkparse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("linkparse", 0, dumpTree() >= 6); } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index d5157b0c9..9e314992a 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -36,6 +36,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Link state, as a visitor of each AstNode @@ -55,9 +57,6 @@ private: int m_senitemCvtNum = 0; // Temporary signal counter bool m_underGenerate = false; // Under GenFor/GenIf - // METHODS - VL_DEBUG_FUNC; // Declare debug() - // VISITs // TODO: Most of these visitors are here for historical reasons. // TODO: ExpectDecriptor can move to data type resolution, and the rest @@ -552,9 +551,6 @@ private: // STATE AstNodeModule* m_modp = nullptr; // Current module - // METHODS - VL_DEBUG_FUNC; // Declare debug() - // VISITs void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. @@ -590,5 +586,5 @@ void V3LinkResolve::linkResolve(AstNetlist* rootp) { const LinkResolveVisitor visitor{rootp}; LinkBotupVisitor{rootp}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("linkresolve", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("linkresolve", 0, dumpTree() >= 6); } diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 9a9bf51db..0d5977dcc 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -34,6 +34,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // LocalizeVisitor @@ -62,8 +64,6 @@ private: std::vector m_varScopeps; // List of variables to consider for localization // METHODS - VL_DEBUG_FUNC; // Declare debug() - bool isOptimizable(AstVarScope* nodep) { return !nodep->user1() || // Not marked as not optimizable, or ... (nodep->varp()->varType() == VVarType::BLOCKTEMP @@ -221,5 +221,5 @@ public: void V3Localize::localizeAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { LocalizeVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("localize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("localize", 0, dumpTree() >= 6); } diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 1f99e4570..6103c62b1 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -87,6 +87,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + namespace { //###################################################################### @@ -455,7 +457,6 @@ private: StmtPropertiesAllocator* m_stmtPropertiesp = nullptr; // METHODS - VL_DEBUG_FUNC; // Declare debug() // Function that processes a whole sub-tree void process(AstNode* nodep) { @@ -883,5 +884,5 @@ public: void V3MergeCond::mergeAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { MergeCondVisitor{nodep}; } - V3Global::dumpCheckGlobalTree("merge_cond", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("merge_cond", 0, dumpTree() >= 6); } diff --git a/src/V3Name.cpp b/src/V3Name.cpp index ca8fde8f1..8cb27838d 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -28,6 +28,8 @@ #include "V3Global.h" #include "V3LanguageWords.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Name state, as a visitor of each AstNode @@ -44,8 +46,6 @@ private: const AstNodeModule* m_modp = nullptr; // METHODS - VL_DEBUG_FUNC; // Declare debug() - void rename(AstNode* nodep, bool addPvt) { if (!nodep->user1()) { // Not already done if (addPvt) { @@ -144,5 +144,5 @@ public: void V3Name::nameAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { NameVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("name", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("name", 0, dumpTree() >= 6); } diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 7459ce773..3dcfc88e2 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -27,6 +27,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + constexpr int MAX_SPRINTF_DOUBLE_SIZE = 1100; // Maximum characters with a sprintf %e/%f/%g (really 1079) diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 64ca9e861..4456f601e 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include "config_rev.h" @@ -51,6 +52,8 @@ #endif // clang-format on +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // V3 Internal state @@ -1061,7 +1064,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-debug", CbCall, [this]() { setDebugMode(3); }); DECL_OPTION("-debugi", CbVal, [this](int v) { setDebugMode(v); }); DECL_OPTION("-debugi-", CbPartialMatchVal, [this](const char* optp, const char* valp) { - setDebugSrcLevel(optp, std::atoi(valp)); + m_debugLevel[optp] = std::atoi(valp); }); DECL_OPTION("-debug-abort", CbCall, V3Error::vlAbort) @@ -1082,15 +1085,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char DECL_OPTION("-debug-sigsegv", CbCall, throwSigsegv).undocumented(); // See also --debug-abort DECL_OPTION("-decoration", OnOff, &m_decoration); DECL_OPTION("-dpi-hdr-only", OnOff, &m_dpiHdrOnly); - DECL_OPTION("-dump-defines", OnOff, &m_dumpDefines); - DECL_OPTION("-dump-tree", CbOnOff, - [this](bool flag) { m_dumpTree = flag ? 3 : 0; }); // Also see --dump-treei - DECL_OPTION("-dump-tree-addrids", OnOff, &m_dumpTreeAddrids); - DECL_OPTION("-dump-treei", Set, &m_dumpTree); - DECL_OPTION("-dump-treei-", CbPartialMatchVal, [this](const char* optp, const char* valp) { - setDumpTreeLevel(optp, std::atoi(valp)); + DECL_OPTION("-dump-", CbPartialMatch, [this](const char* optp) { m_dumpLevel[optp] = 3; }); + DECL_OPTION("-no-dump-", CbPartialMatch, [this](const char* optp) { m_dumpLevel[optp] = 0; }); + DECL_OPTION("-dumpi-", CbPartialMatchVal, [this](const char* optp, const char* valp) { + m_dumpLevel[optp] = std::atoi(valp); }); - DECL_OPTION("-E", Set, &m_preprocOnly); DECL_OPTION("-error-limit", CbVal, static_cast(&V3Error::errorLimit)); DECL_OPTION("-exe", OnOff, &m_exe); @@ -1795,52 +1794,42 @@ V3Options::~V3Options() { VL_DO_CLEAR(delete m_impp, m_impp = nullptr); } void V3Options::setDebugMode(int level) { V3Error::debugDefault(level); - if (!m_dumpTree) m_dumpTree = 3; // Don't override if already set. + if (!m_dumpLevel.count("tree")) m_dumpLevel["tree"] = 3; // Don't override if already set. m_stats = true; m_debugCheck = true; cout << "Starting " << version() << endl; } -void V3Options::setDebugSrcLevel(const string& srcfile, int level) { - const auto iter = m_debugSrcs.find(srcfile); - if (iter != m_debugSrcs.end()) { - iter->second = level; - } else { - m_debugSrcs.emplace(srcfile, level); - } +unsigned V3Options::debugLevel(const string& tag) const { + const auto iter = m_debugLevel.find(tag); + return iter != m_debugLevel.end() ? iter->second : V3Error::debugDefault(); } -int V3Options::debugSrcLevel(const string& srcfile_path, int default_level) { +unsigned V3Options::debugSrcLevel(const string& srcfile_path) const { // For simplicity, calling functions can just use __FILE__ for srcfile. - // That means though we need to cleanup the filename from ../Foo.cpp -> Foo - const string srcfile = V3Os::filenameNonDirExt(srcfile_path); - const auto iter = m_debugSrcs.find(srcfile); - if (iter != m_debugSrcs.end()) { - return iter->second; - } else { - return default_level; - } + // That means we need to strip the filenames: ../Foo.cpp -> Foo + return debugLevel(V3Os::filenameNonDirExt(srcfile_path)); } -void V3Options::setDumpTreeLevel(const string& srcfile, int level) { - const auto iter = m_dumpTrees.find(srcfile); - if (iter != m_dumpTrees.end()) { - iter->second = level; - } else { - m_dumpTrees.emplace(srcfile, level); - } +unsigned V3Options::dumpLevel(const string& tag) const { + const auto iter = m_dumpLevel.find(tag); + return iter != m_dumpLevel.end() ? iter->second : 0; } -int V3Options::dumpTreeLevel(const string& srcfile_path) { +unsigned V3Options::dumpSrcLevel(const string& srcfile_path) const { // For simplicity, calling functions can just use __FILE__ for srcfile. - // That means though we need to cleanup the filename from ../Foo.cpp -> Foo - const string srcfile = V3Os::filenameNonDirExt(srcfile_path); - const auto iter = m_dumpTrees.find(srcfile); - if (iter != m_dumpTrees.end()) { - return iter->second; - } else { - return m_dumpTree; + // That means we need to strip the filenames: ../Foo.cpp -> Foo + return dumpLevel(V3Os::filenameNonDirExt(srcfile_path)); +} + +bool V3Options::dumpTreeAddrids() const { + static int level = -1; + if (VL_UNLIKELY(level < 0)) { + const unsigned value = dumpLevel("tree-addrids"); + if (!available()) return value > 0; + level = static_cast(value); } + return level > 0; } void V3Options::optimize(int level) { diff --git a/src/V3Options.h b/src/V3Options.h index 4149eb75e..353370b7f 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -188,7 +188,7 @@ class V3Options final { public: private: // TYPES - using DebugSrcMap = std::map; + using DebugLevelMap = std::map; // MEMBERS (general options) V3OptionsImp* m_impp; // Slow hidden options @@ -206,8 +206,8 @@ private: V3StringSet m_noClockers; // argument: Verilog -noclk signals V3StringList m_vFiles; // argument: Verilog files to read V3StringList m_forceIncs; // argument: -FI - DebugSrcMap m_debugSrcs; // argument: --debugi-= - DebugSrcMap m_dumpTrees; // argument: --dump-treei-= + DebugLevelMap m_debugLevel; // argument: --debugi- + DebugLevelMap m_dumpLevel; // argument: --dumpi- std::map m_parameters; // Parameters std::map m_hierBlocks; // main switch: --hierarchical-block @@ -238,8 +238,6 @@ private: bool m_debugSelfTest = false; // main switch: --debug-self-test bool m_decoration = true; // main switch: --decoration bool m_dpiHdrOnly = false; // main switch: --dpi-hdr-only - bool m_dumpDefines = false; // main switch: --dump-defines - bool m_dumpTreeAddrids = false; // main switch: --dump-tree-addrids bool m_exe = false; // main switch: --exe bool m_flatten = false; // main switch: --flatten bool m_hierarchical = false; // main switch: --hierarchical @@ -286,7 +284,6 @@ private: int m_buildJobs = -1; // main switch: --build-jobs, -j int m_convergeLimit = 100; // main switch: --converge-limit int m_coverageMaxWidth = 256; // main switch: --coverage-max-width - int m_dumpTree = 0; // main switch: --dump-tree int m_expandLimit = 64; // main switch: --expand-limit int m_gateStmts = 100; // main switch: --gate-stmts int m_hierChild = 0; // main switch: --hierarchical-child @@ -395,10 +392,10 @@ public: V3Options(); ~V3Options(); void setDebugMode(int level); - void setDebugSrcLevel(const string& srcfile, int level); - int debugSrcLevel(const string& srcfile_path, int default_level = V3Error::debugDefault()); - void setDumpTreeLevel(const string& srcfile, int level); - int dumpTreeLevel(const string& srcfile_path); + unsigned debugLevel(const string& tag) const; + unsigned debugSrcLevel(const string& srcfile_path) const; + unsigned dumpLevel(const string& tag) const; + unsigned dumpSrcLevel(const string& srcfile_path) const; // METHODS void addCppFile(const string& filename); @@ -452,7 +449,7 @@ public: bool debugSelfTest() const { return m_debugSelfTest; } bool decoration() const { return m_decoration; } bool dpiHdrOnly() const { return m_dpiHdrOnly; } - bool dumpDefines() const { return m_dumpDefines; } + bool dumpDefines() const { return m_dumpLevel.count("defines") && m_dumpLevel.at("defines"); } bool exe() const { return m_exe; } bool flatten() const { return m_flatten; } bool gmake() const { return m_gmake; } @@ -493,8 +490,7 @@ public: int buildJobs() const { return m_buildJobs; } int convergeLimit() const { return m_convergeLimit; } int coverageMaxWidth() const { return m_coverageMaxWidth; } - int dumpTree() const { return m_dumpTree; } - bool dumpTreeAddrids() const { return m_dumpTreeAddrids; } + bool dumpTreeAddrids() const; int expandLimit() const { return m_expandLimit; } int gateStmts() const { return m_gateStmts; } int ifDepth() const { return m_ifDepth; } diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 5bbb46a68..471012b73 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -107,6 +107,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Utilities @@ -156,7 +158,6 @@ static bool isClockerAssignment(AstNodeAssign* nodep) { bool m_clkAss = false; // There is signals marked as clocker in the assignment private: // METHODS - VL_DEBUG_FUNC; // Declare debug() void visit(AstNodeAssign* nodep) override { if (const AstVarRef* const varrefp = VN_CAST(nodep->lhsp(), VarRef)) { if (varrefp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { @@ -210,7 +211,6 @@ class OrderClkMarkVisitor final : public VNVisitor { int m_childClkWidth = 0; // If in hasClk, width of clock signal in child // METHODS - VL_DEBUG_FUNC; // Declare debug() void visit(AstNodeAssign* nodep) override { m_hasClk = false; @@ -394,7 +394,6 @@ class OrderBuildVisitor final : public VNVisitor { bool m_inPostponed = false; // Underneath AstAlwaysPostponed // METHODS - VL_DEBUG_FUNC; // Declare debug() void iterateLogic(AstNode* nodep) { UASSERT_OBJ(!m_logicVxp, nodep, "Should not nest"); @@ -738,9 +737,6 @@ class OrderBuildVisitor final : public VNVisitor { // CONSTRUCTOR explicit OrderBuildVisitor(AstNetlist* nodep) { - // Enable debugging (3 is default if global debug; we want acyc debugging) - if (debug()) m_graphp->debug(5); - // Add edges from the InputVertex to all top level input signal VarStdVertex for (AstVarScope* vscp = nodep->topScopep()->scopep()->varsp(); vscp; vscp = VN_AS(vscp->nextp(), VarScope)) { @@ -1078,7 +1074,6 @@ class OrderProcess final : VNDeleter { std::array m_statCut; // Count of each edge type cut // METHODS - VL_DEBUG_FUNC; // Declare debug() void process(); void processCircular(); @@ -2027,7 +2022,7 @@ void OrderProcess::processMTasks() { void OrderProcess::process() { // Dump data - m_graph.dumpDotFilePrefixed("orderg_pre"); + if (dumpGraph()) m_graph.dumpDotFilePrefixed("orderg_pre"); // Break cycles. Each strongly connected subgraph (including cutable // edges) will have its own color, and corresponds to a loop in the @@ -2035,12 +2030,12 @@ void OrderProcess::process() { // edges are actually still there, just with weight 0). UINFO(2, " Acyclic & Order...\n"); m_graph.acyclic(&V3GraphEdge::followAlwaysTrue); - m_graph.dumpDotFilePrefixed("orderg_acyc"); + if (dumpGraph()) m_graph.dumpDotFilePrefixed("orderg_acyc"); // Assign ranks so we know what to follow // Then, sort vertices and edges by that ordering m_graph.order(); - m_graph.dumpDotFilePrefixed("orderg_order"); + if (dumpGraph()) m_graph.dumpDotFilePrefixed("orderg_order"); // This finds everything that can be traced from an input (which by // definition are the source clocks). After this any vertex which was @@ -2054,19 +2049,17 @@ void OrderProcess::process() { // Assign logic vertices to new domains UINFO(2, " Domains...\n"); processDomains(); - m_graph.dumpDotFilePrefixed("orderg_domain"); + if (dumpGraph()) m_graph.dumpDotFilePrefixed("orderg_domain"); - if (debug() && v3Global.opt.dumpTree()) processEdgeReport(); + if (dump()) processEdgeReport(); if (!v3Global.opt.mtasks()) { UINFO(2, " Construct Move Graph...\n"); processMoveBuildGraph(); - if (debug() >= 4) { - m_pomGraph.dumpDotFilePrefixed( - "ordermv_start"); // Different prefix (ordermv) as it's not the same graph - } + // Different prefix (ordermv) as it's not the same graph + if (dumpGraph() >= 4) m_pomGraph.dumpDotFilePrefixed("ordermv_start"); m_pomGraph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); - if (debug() >= 4) m_pomGraph.dumpDotFilePrefixed("ordermv_simpl"); + if (dumpGraph() >= 4) m_pomGraph.dumpDotFilePrefixed("ordermv_simpl"); UINFO(2, " Move...\n"); processMove(); @@ -2080,14 +2073,7 @@ void OrderProcess::process() { processSensitive(); // must be after processDomains // Dump data - m_graph.dumpDotFilePrefixed("orderg_done"); - if (false && debug()) { - const string dfilename - = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_INT_order"; - const std::unique_ptr logp{V3File::new_ofstream(dfilename)}; - if (logp->fail()) v3fatal("Can't write " << dfilename); - m_graph.dump(*logp); - } + if (dumpGraph()) m_graph.dumpDotFilePrefixed("orderg_done"); } //###################################################################### @@ -2101,8 +2087,6 @@ void V3Order::orderAll(AstNetlist* netlistp) { std::unique_ptr orderGraph = OrderBuildVisitor::process(netlistp); // Order the netlist OrderProcess::main(netlistp, *orderGraph); - // Reset debug level - orderGraph->debug(V3Error::debugDefault()); // Dump tree - V3Global::dumpCheckGlobalTree("order", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("order", 0, dumpTree() >= 3); } diff --git a/src/V3Os.cpp b/src/V3Os.cpp index 2abc200c0..32d78f09c 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -29,8 +29,13 @@ #include "verilatedos.h" // Limited V3 headers here - this is a base class for Vlc etc -#include "V3String.h" #include "V3Os.h" +#include "V3String.h" + +#ifndef V3ERROR_NO_GLOBAL_ +#include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; +#endif #include #include // PATH_MAX (especially on FreeBSD) @@ -38,6 +43,7 @@ #include #include #include + #include #include diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 4c372895e..e4719d3f3 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -65,6 +65,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Hierarchical block and parameter db (modules without parameter is also handled) @@ -88,7 +90,6 @@ class ParameterizedHierBlocks final { m_modParams; // Parameter variables of hierarchical blocks // METHODS - VL_DEBUG_FUNC; // Declare debug() public: ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep) { @@ -270,7 +271,6 @@ class ParamProcessor final { std::map m_defaultParameterValues; // METHODS - VL_DEBUG_FUNC; // Declare debug() static void makeSmallNames(AstNodeModule* modp) { std::vector usedLetter; @@ -888,7 +888,6 @@ class ParamVisitor final : public VNVisitor { std::unordered_map> m_parentps; // METHODS - VL_DEBUG_FUNC; // Declare debug() void visitCells(AstNodeModule* nodep) { UASSERT_OBJ(!m_iterateModule, nodep, "Should not nest"); @@ -1280,5 +1279,5 @@ public: void V3Param::param(AstNetlist* rootp) { UINFO(2, __FUNCTION__ << ": " << endl); { ParamVisitor{rootp}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("param", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("param", 0, dumpTree() >= 6); } diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 5655a1d96..984544d82 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -18,6 +18,8 @@ #include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict +VL_DEFINE_DEBUG_FUNCTIONS; + //====================================================================== // The guts come from bison output diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index db0a0f422..cb26c7026 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -38,6 +38,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //====================================================================== // Globals @@ -58,7 +60,7 @@ V3ParseImp::~V3ParseImp() { if (debug() >= 9) { UINFO(0, "~V3ParseImp\n"); - symp()->dump(cout, "-vpi: "); + symp()->dumpSelf(cout, "-vpi: "); } } @@ -497,7 +499,7 @@ void V3ParseImp::tokenPipelineSym() { const VSymEnt* foundp; if (const VSymEnt* const look_underp = V3ParseImp::parsep()->symp()->nextId()) { UINFO(7, " tokenPipelineSym: next id lookup forced under " << look_underp << endl); - // if (debug() >= 7) V3ParseImp::parsep()->symp()->dump(cout, " -symtree: "); + // if (debug() >= 7) V3ParseImp::parsep()->symp()->dumpSelf(cout, " -symtree: "); foundp = look_underp->findIdFallback(*(yylval.strp)); // "consume" it. Must set again if want another token under temp scope V3ParseImp::parsep()->symp()->nextId(nullptr); @@ -505,7 +507,7 @@ void V3ParseImp::tokenPipelineSym() { UINFO(7, " tokenPipelineSym: find upward " << V3ParseImp::parsep()->symp()->symCurrentp() << " for '" << *(yylval.strp) << "'" << endl); - // if (debug()>=9) V3ParseImp::parsep()->symp()->symCurrentp()->dump(cout, + // if (debug()>=9) V3ParseImp::parsep()->symp()->symCurrentp()->dumpSelf(cout, // " -findtree: ", true); foundp = V3ParseImp::parsep()->symp()->symCurrentp()->findIdFallback(*(yylval.strp)); } diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 54a241365..54c4ab080 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -161,25 +161,10 @@ class V3ParseImp final { VTimescale m_timeLastUnit; // Last `timescale's unit public: + VL_DEFINE_DEBUG_FUNCTIONS; // Note these are an exception to using the filename as the debug type - static int debugBison() { - static int level = -1; - if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("bison"); - return level; - } - static int debugFlex() { - static int level = -1; - if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("flex"); - return level; - } - static int debug() { - static int level = -1; - if (VL_UNLIKELY(level < 0)) { - level = std::max(std::max(debugBison(), debugFlex()), - v3Global.opt.debugSrcLevel("V3ParseImp")); - } - return level; - } + VL_DEFINE_DEBUG(Bison); // Define 'unsigned debugBison()' + VL_DEFINE_DEBUG(Flex); // Define 'unsigned debugFlex()' // Functions called by lex rules: int yylexThis(); diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 87edaef5a..b9e0d26e3 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -55,6 +55,9 @@ public: private: // METHODS + + VL_DEFINE_DEBUG_FUNCTIONS; + static VSymEnt* getTable(AstNode* nodep) { UASSERT_OBJ(nodep->user4p(), nodep, "Current symtable not found"); return nodep->user4u().toSymEnt(); @@ -115,7 +118,7 @@ public: if (VL_UNCOVERABLE(symCurrentp()->nodep() != nodep)) { // LCOV_EXCL_START if (debug()) { showUpward(); - dump(cout, "-mism: "); + dumpSelf(cout, "-mism: "); } nodep->v3fatalSrc("Symbols suggest ending " << symCurrentp()->nodep()->prettyTypeName() << " but parser thinks ending " @@ -133,7 +136,7 @@ public: } UINFO(1, "ParseSym Current: " << symCurrentp()->nodep() << endl); } // LCOV_EXCL_STOP - void dump(std::ostream& os, const string& indent = "") { m_syms.dump(os, indent); } + void dumpSelf(std::ostream& os, const string& indent = "") { m_syms.dumpSelf(os, indent); } AstNode* findEntUpward(const string& name) const { // Lookup the given string as an identifier, return type of the id, scanning upward VSymEnt* const foundp = symCurrentp()->findIdFallback(name); diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index ea3855ddd..18952bfe8 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -41,6 +41,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + class LogicMTask; class MTaskEdge; class MergeCandidate; @@ -390,7 +392,6 @@ public: static void dumpCpFilePrefixed(const V3Graph* graphp, const string& nameComment); private: - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(LogicMTask); }; @@ -826,7 +827,6 @@ public: } private: - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(PartParallelismEst); }; @@ -1070,7 +1070,6 @@ public: } private: - VL_DEBUG_FUNC; VL_UNCOPYABLE(PartPropagateCp); }; @@ -1834,7 +1833,6 @@ public: } private: - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(PartContraction); }; @@ -1848,8 +1846,6 @@ private: bool m_hasDpiHazard = false; // Found a DPI import call. bool m_tracingCall = false; // Iterating into a CCall to a CFunc // METHODS - VL_DEBUG_FUNC; - void visit(AstCFunc* nodep) override { if (!m_tracingCall) return; m_tracingCall = false; @@ -2203,7 +2199,6 @@ public: private: VL_UNCOPYABLE(PartFixDataHazards); - VL_DEBUG_FUNC; }; //###################################################################### @@ -2525,7 +2520,7 @@ public: } } - if (debug() >= 4) schedule.dumpDotFilePrefixedAlways(mtaskGraph, "schedule"); + if (dumpGraph() >= 4) schedule.dumpDotFilePrefixedAlways(mtaskGraph, "schedule"); return schedule; } @@ -2583,7 +2578,6 @@ public: } private: - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(PartPackMTasks); }; @@ -2591,7 +2585,7 @@ private: // V3Partition implementation void V3Partition::debugMTaskGraphStats(const V3Graph* graphp, const string& stage) { - if (!debug()) return; + if (!debug() && !dump() && !dumpGraph()) return; UINFO(4, "\n"); UINFO(4, " Stats for " << stage << endl); @@ -2628,7 +2622,7 @@ void V3Partition::debugMTaskGraphStats(const V3Graph* graphp, const string& stag if (mtaskCount < 1000) { string filePrefix("ordermv_"); filePrefix += stage; - if (debug() >= 4) graphp->dumpDotFilePrefixedAlways(filePrefix); + if (dumpGraph() >= 4) graphp->dumpDotFilePrefixedAlways(filePrefix); } // Look only at the cost of each mtask, neglect communication cost. @@ -2729,9 +2723,7 @@ void V3Partition::go(V3Graph* mtasksp) { // For debug: print out the longest critical path. This allows us to // verify that the costs look reasonable, that we aren't combining // nodes that should probably be split, etc. - if (v3Global.opt.dumpTreeLevel(__FILE__) >= 3) { - LogicMTask::dumpCpFilePrefixed(mtasksp, "cp"); - } + if (dump() >= 3) LogicMTask::dumpCpFilePrefixed(mtasksp, "cp"); // Merge nodes that could present data hazards; see comment within. { diff --git a/src/V3Partition.h b/src/V3Partition.h index c358599f4..fc410c5c0 100644 --- a/src/V3Partition.h +++ b/src/V3Partition.h @@ -67,7 +67,6 @@ public: private: static void setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp); - VL_DEBUG_FUNC; // Declare debug() VL_UNCOPYABLE(V3Partition); }; diff --git a/src/V3PreLex.h b/src/V3PreLex.h index 8ce783957..4389c506d 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -225,9 +225,8 @@ public: // Used only by V3PreLex.cpp and V3PreProc.cpp // Called by VPreStream void streamDepthAdd(int delta) { m_streamDepth += delta; } int streamDepth() const { return m_streamDepth; } - /// Utility - static int debug(); - static void debug(int level); + // Utility + static void setYYDebug(bool on); static string cleanDbgStrg(const string& in); private: diff --git a/src/V3PreLex.l b/src/V3PreLex.l index a83a55db9..bc1dda03d 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -462,11 +462,8 @@ void V3PreLex::pushStateIncFilename() { yymore(); } -void V3PreLex::debug(int level) { - yy_flex_debug = level; // Use --debugi-V3PreShell, if level<5 this level is 0 -} -int V3PreLex::debug() { - return yy_flex_debug; } +void V3PreLex::setYYDebug(bool on) { + yy_flex_debug = static_cast(on); } int V3PreLex::lex() { V3PreLex::s_currentLexp = this; // Tell parser where to get/put data diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index 684733a6e..6aadb69f7 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -33,6 +33,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //====================================================================== // Build in LEX script @@ -112,8 +114,6 @@ public: using DefinesMap = std::map; using StrList = VInFilter::StrList; - // debug() -> see V3PreShellImp::debug; use --debugi-V3PreShell - // Defines list DefinesMap m_defines; ///< Map of defines @@ -259,10 +259,7 @@ public: string removeDefines(const string& text) override; // Remove defines in a text string // CONSTRUCTORS - V3PreProcImp() { - m_debug = 0; - m_states.push(ps_TOP); - } + V3PreProcImp() { m_states.push(ps_TOP); } void configure(FileLine* filelinep) { // configure() separate from constructor to avoid calling abstract functions m_preprocp = this; // Silly, but to make code more similar to Verilog-Perl @@ -273,7 +270,6 @@ public: m_lexp->m_keepComments = keepComments(); m_lexp->m_keepWhitespace = keepWhitespace(); m_lexp->m_pedantic = pedantic(); - debug(debug()); // Set lexer debug via V3PreProc::debug() method } ~V3PreProcImp() override { if (m_lexp) VL_DO_CLEAR(delete m_lexp, m_lexp = nullptr); @@ -490,12 +486,6 @@ void V3PreProcImp::comment(const string& text) { //************************************************************************* // VPreProc Methods. -void V3PreProc::debug(int level) { - m_debug = level; - V3PreProcImp* idatap = static_cast(this); - if (idatap->m_lexp) idatap->m_lexp->debug(debug() >= 5 ? debug() : 0); -} - FileLine* V3PreProc::fileline() { const V3PreProcImp* idatap = static_cast(this); return idatap->m_lexp->m_tokFilelinep; @@ -777,6 +767,7 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { void V3PreProcImp::openFile(FileLine*, VInFilter* filterp, const string& filename) { // Open a new file, possibly overriding the current one which is active. if (m_incError) return; + m_lexp->setYYDebug(debug() >= 5); V3File::addSrcDepend(filename); // Read a list with the whole file. diff --git a/src/V3PreProc.h b/src/V3PreProc.h index f446a4f35..a14562a32 100644 --- a/src/V3PreProc.h +++ b/src/V3PreProc.h @@ -39,8 +39,7 @@ class V3PreProc VL_NOT_FINAL { // After creating, call open(), then getline() in a loop. The class will to the rest... protected: - // STATE - int m_debug; // Debugging + VL_DEFINE_DEBUG_FUNCTIONS; public: // CONSTANTS @@ -61,9 +60,6 @@ public: virtual bool isEof() const = 0; // Return true on EOF. virtual void insertUnreadback(const string& text) = 0; - int debug() const { return m_debug; } - void debug(int level); - FileLine* fileline(); ///< File/Line number for last getline call // CONTROL METHODS @@ -99,7 +95,7 @@ public: protected: // CONSTRUCTORS - V3PreProc() { m_debug = 0; } + V3PreProc() {} void configure(FileLine* fl); public: diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index f6e325f29..0502535af 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -28,6 +28,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class V3PreShellImp final { @@ -41,21 +43,11 @@ protected: //--------------------------------------- // METHODS - static int debug(bool reset = false) { - static int level = -1; - if (VL_UNLIKELY(level < 0) || reset) { - level = v3Global.opt.debugSrcLevel(__FILE__); - if (s_preprocp) s_preprocp->debug(debug()); - } - return level; - } - void boot() { // Create the implementation pointer if (!s_preprocp) { FileLine* const cmdfl = new FileLine(FileLine::commandLineFilename()); s_preprocp = V3PreProc::createPreProc(cmdfl); - s_preprocp->debug(debug()); // Default defines FileLine* const prefl = new FileLine(FileLine::builtInFilename()); s_preprocp->defineCmdLine(prefl, "VERILATOR", "1"); // LEAK_OK @@ -88,8 +80,6 @@ protected: bool preproc(FileLine* fl, const string& modname, VInFilter* filterp, V3ParseImp* parsep, const string& errmsg) { // "" for no error - debug(true); // Recheck if debug on - first check was before command line passed - // Preprocess the given module, putting output in vppFilename UINFONL(1, " Preprocessing " << modname << endl); diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 54b1324c4..48f8c5c31 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -36,6 +36,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + constexpr int STATIC_CONST_MIN_WIDTH = 256; // Minimum size to extract to static constant //###################################################################### @@ -62,8 +64,6 @@ private: VDouble0 m_extractedToConstPool; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() - bool assignNoTemp(AstNodeAssign* nodep) { return (VN_IS(nodep->lhsp(), VarRef) && !AstVar::scVarRecurse(nodep->lhsp()) && VN_IS(nodep->rhsp(), Const)); @@ -394,5 +394,5 @@ public: void V3Premit::premitAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { PremitVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("premit", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("premit", 0, dumpTree() >= 3); } diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 734695c2f..7d04a1fc8 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -26,6 +26,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // ProtectLib top-level visitor diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 7efc30c0f..3677a1071 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -31,6 +31,8 @@ #include "V3Ast.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Visitor that marks classes needing a randomize() method @@ -47,8 +49,6 @@ private: BaseToDerivedMap m_baseToDerivedMap; // Mapping from base classes to classes that extend them // METHODS - VL_DEBUG_FUNC; - void markMembers(AstClass* nodep) { for (auto* classp = nodep; classp; classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr) { @@ -127,8 +127,6 @@ private: size_t m_enumValueTabCount = 0; // Number of tables with enum values created // METHODS - VL_DEBUG_FUNC; - AstVar* enumValueTabp(AstEnumDType* nodep) { if (nodep->user2p()) return VN_AS(nodep->user2p(), Var); UINFO(9, "Construct Venumvaltab " << nodep << endl); @@ -258,7 +256,7 @@ void V3Randomize::randomizeNetlist(AstNetlist* nodep) { const RandomizeMarkVisitor markVisitor{nodep}; RandomizeVisitor{nodep}; } - V3Global::dumpCheckGlobalTree("randomize", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("randomize", 0, dumpTree() >= 3); } AstFunc* V3Randomize::newRandomizeFunc(AstClass* nodep) { diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 4e8690b3e..db48e6b2e 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -40,6 +40,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class ReloopVisitor final : public VNVisitor { @@ -66,7 +68,6 @@ private: uint32_t m_mgIndexHi = 0; // Merge range // METHODS - VL_DEBUG_FUNC; // Declare debug() static AstVar* findCreateVarTemp(FileLine* fl, AstCFunc* cfuncp) { AstVar* varp = VN_AS(cfuncp->user1p(), Var); @@ -269,5 +270,5 @@ public: void V3Reloop::reloopAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ReloopVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("reloop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("reloop", 0, dumpTree() >= 6); } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 8077d2959..c0694e2ab 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -34,6 +34,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Scope class functions @@ -62,7 +64,6 @@ private: m_varRefScopes; // Varrefs-in-scopes needing fixup when done // METHODS - VL_DEBUG_FUNC; // Declare debug() void cleanupVarRefs() { for (const auto& itr : m_varRefScopes) { @@ -327,7 +328,6 @@ private: AstScope* m_scopep = nullptr; // Current scope we are building // METHODS - VL_DEBUG_FUNC; // Declare debug() // VISITORS void visit(AstScope* nodep) override { @@ -405,5 +405,5 @@ void V3Scope::scopeAll(AstNetlist* nodep) { const ScopeVisitor visitor{nodep}; ScopeCleanupVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("scope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("scope", 0, dumpTree() >= 3); } diff --git a/src/V3Simulate.h b/src/V3Simulate.h index ee4b23caf..7c70e4ba1 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -115,7 +115,7 @@ private: std::vector m_reclaimValuesp; // List of allocated string numbers // Note level 8&9 include debugging each simulation value - VL_DEBUG_FUNC; // Declare debug() + VL_DEFINE_DEBUG_FUNCTIONS; // Potentially very slow, intended for debugging string prettyNumber(const V3Number* nump, AstNodeDType* dtypep) { diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index cd977626f..57cca7785 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -43,6 +43,8 @@ #include "V3Ast.h" #include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //************************************************************************* class SliceVisitor final : public VNVisitor { @@ -58,8 +60,6 @@ class SliceVisitor final : public VNVisitor { bool m_assignError = false; // True if the current assign already has an error // METHODS - VL_DEBUG_FUNC; // Declare debug() - AstNode* cloneAndSel(AstNode* nodep, int elements, int offset) { // Insert an ArraySel, except for a few special cases const AstUnpackArrayDType* const arrayp @@ -240,5 +240,5 @@ public: void V3Slice::sliceAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { SliceVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("slice", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("slice", 0, dumpTree() >= 3); } diff --git a/src/V3Split.cpp b/src/V3Split.cpp index b3fd07314..e6521ea69 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -93,6 +93,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Support classes @@ -261,8 +263,6 @@ public: // METHODS protected: - VL_DEBUG_FUNC; // Declare debug() - void scoreboardClear() { // VV***** We reset user1p() and user2p on each block!!! m_inDly = false; @@ -450,10 +450,7 @@ protected: UINFO(5, "ReorderBlock " << nodep << endl); m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); - if (debug() >= 9) { - m_graph.dumpDotFilePrefixed("reorderg_nodup", false); - // m_graph.dump(); cout<= 9) m_graph.dumpDotFilePrefixed("reorderg_nodup", false); // Mark all the logic for this step // Vertex::m_user begin: true indicates logic for this step @@ -510,10 +507,10 @@ protected: // And a real ordering to get the statements into something reasonable // We don't care if there's cutable violations here... // Non-cutable violations should be impossible; as those edges are program-order - if (debug() >= 9) m_graph.dumpDotFilePrefixed(string("splitg_preo"), false); + if (dumpGraph() >= 9) m_graph.dumpDotFilePrefixed(string("splitg_preo"), false); m_graph.acyclic(&SplitEdge::followCyclic); m_graph.rank(&SplitEdge::followCyclic); // Or order(), but that's more expensive - if (debug() >= 9) m_graph.dumpDotFilePrefixed(string("splitg_opt"), false); + if (dumpGraph() >= 9) m_graph.dumpDotFilePrefixed(string("splitg_opt"), false); } void reorderBlock(AstNode* nodep) { @@ -672,7 +669,6 @@ protected: iterateChildren(nodep); } - VL_DEBUG_FUNC; // Declare debug() private: VL_UNCOPYABLE(IfColorVisitor); }; @@ -724,8 +720,6 @@ public: } protected: - VL_DEBUG_FUNC; // Declare debug() - AstSplitPlaceholder* makePlaceholderp() { return new AstSplitPlaceholder(m_origAlwaysp->fileline()); } @@ -942,14 +936,14 @@ protected: } } - if (debug() >= 9) m_graph.dumpDotFilePrefixed("splitg_nodup", false); + if (dumpGraph() >= 9) m_graph.dumpDotFilePrefixed("splitg_nodup", false); // Weak coloring to determine what needs to remain grouped // in a single always. This follows all edges excluding: // - those we pruned above // - PostEdges, which are done later m_graph.weaklyConnected(&SplitEdge::followScoreboard); - if (debug() >= 9) m_graph.dumpDotFilePrefixed("splitg_colored", false); + if (dumpGraph() >= 9) m_graph.dumpDotFilePrefixed("splitg_colored", false); } void visit(AstAlways* nodep) override { @@ -1003,10 +997,10 @@ private: void V3Split::splitReorderAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { ReorderVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("reorder", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("reorder", 0, dumpTree() >= 3); } void V3Split::splitAlwaysAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { SplitVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("split", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("split", 0, dumpTree() >= 3); } diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index d22429f93..1d7b4d86d 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -32,12 +32,13 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class SplitAsBaseVisitor VL_NOT_FINAL : public VNVisitor { public: // METHODS - VL_DEBUG_FUNC; // Declare debug() }; //###################################################################### @@ -196,5 +197,5 @@ public: void V3SplitAs::splitAsAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { SplitAsVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("splitas", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("splitas", 0, dumpTree() >= 3); } diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 502058e37..7b82c3f46 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -125,6 +125,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + struct SplitVarImpl { // NODE STATE // AstNodeModule::user1() -> Block number counter for generating unique names @@ -782,7 +784,6 @@ public: V3Stats::addStat("SplitVar, Split unpacked arrays", m_numSplit); } const SplitVarRefsMap& getPackedVarRefs() const { return m_refsForPackedSplit; } - VL_DEBUG_FUNC; // Declare debug() // Check if the passed variable can be split. // Even if this function returns true, the variable may not be split @@ -1243,7 +1244,6 @@ public: } return reason; } - VL_DEBUG_FUNC; // Declare debug() }; const char* SplitVarImpl::cannotSplitPackedVarReason(const AstVar* varp) { @@ -1260,9 +1260,9 @@ void V3SplitVar::splitVariable(AstNetlist* nodep) { const SplitUnpackedVarVisitor visitor{nodep}; refs = visitor.getPackedVarRefs(); } - V3Global::dumpCheckGlobalTree("split_var", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 9); + V3Global::dumpCheckGlobalTree("split_var", 0, dumpTree() >= 9); { SplitPackedVarVisitor{nodep, refs}; } - V3Global::dumpCheckGlobalTree("split_var", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 9); + V3Global::dumpCheckGlobalTree("split_var", 0, dumpTree() >= 9); } bool V3SplitVar::canSplitVar(const AstVar* varp) { diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index 5ec58dfdc..bda08d003 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -28,6 +28,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Stats class functions @@ -61,7 +63,6 @@ private: VDouble0 m_statVarScpBytes; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() void allNodes(AstNode* nodep) { m_instrs += nodep->instrCount(); diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index 85860e43e..03be5d71c 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -27,6 +27,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Stats dumping diff --git a/src/V3String.cpp b/src/V3String.cpp index 54fcfac07..6f4aa473b 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -17,10 +17,15 @@ #include "config_build.h" #include "verilatedos.h" -// Limited V3 headers here - this is a base class for Vlc etc -#include "V3Error.h" #include "V3String.h" +#include "V3Error.h" + +#ifndef V3ERROR_NO_GLOBAL_ +#include "V3Global.h" +VL_DEFINE_DEBUG_FUNCTIONS; +#endif + #include size_t VName::s_minLength = 32; diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index d671e23f3..60a664786 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -34,13 +34,7 @@ #include #include -//###################################################################### -// Common debugging baseclass - -class SubstBaseVisitor VL_NOT_FINAL : public VNVisitor { -public: - VL_DEBUG_FUNC; // Declare debug() -}; +VL_DEFINE_DEBUG_FUNCTIONS; //###################################################################### // Class for each word of a multi-word variable @@ -72,7 +66,6 @@ class SubstVarEntry final { bool m_wordUse = false; // True if any individual word usage SubstVarWord m_whole; // Data for whole vector used at once std::vector m_words; // Data for every word, if multi word variable - static int debug() { return SubstBaseVisitor::debug(); } public: // CONSTRUCTORS @@ -175,7 +168,7 @@ public: // See if any variables have changed value since we determined subst value, // as a visitor of each AstNode -class SubstUseVisitor final : public SubstBaseVisitor { +class SubstUseVisitor final : public VNVisitor { private: // NODE STATE // See SubstVisitor @@ -222,7 +215,7 @@ public: //###################################################################### // Subst state, as a visitor of each AstNode -class SubstVisitor final : public SubstBaseVisitor { +class SubstVisitor final : public VNVisitor { private: // NODE STATE // Passed to SubstUseVisitor @@ -390,5 +383,5 @@ public: void V3Subst::substituteAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { SubstVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("subst", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("subst", 0, dumpTree() >= 3); } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index c1607f5f4..879c898e9 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -53,11 +53,7 @@ class VSymEnt final { bool m_exported; // Allow importing bool m_imported; // Was imported #ifdef VL_DEBUG - static int debug() { - static int level = -1; - if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("V3LinkDot.cpp"); - return level; - } + VL_DEFINE_DEBUG_FUNCTIONS; #else static constexpr int debug() { return 0; } // NOT runtime, too hot of a function #endif @@ -88,7 +84,7 @@ public: } } } - void dump(std::ostream& os, const string& indent = "", int numLevels = 1) const { + void dumpSelf(std::ostream& os, const string& indent = "", int numLevels = 1) const { VSymConstMap doneSyms; dumpIterate(os, doneSyms, indent, numLevels, "TOP"); } @@ -127,7 +123,7 @@ public: << " " << entp->nodep() << endl); if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) { if (!V3Error::errorCount()) { // Else may have just reported warning - if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1); + if (debug() >= 9 || V3Error::debugDefault()) dumpSelf(cout, "- err-dump: ", 1); entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name); } } else { @@ -272,7 +268,7 @@ public: if (scopes == "") scopes = ""; std::cerr << V3Error::warnMore() << "... Known scopes under '" << prettyName << "': " << scopes << endl; - if (debug()) dump(std::cerr, " KnownScope: ", 1); + if (debug()) dumpSelf(std::cerr, " KnownScope: ", 1); } }; @@ -291,6 +287,8 @@ class VSymGraph final { // CONSTRUCTORS VL_UNCOPYABLE(VSymGraph); + VL_DEFINE_DEBUG_FUNCTIONS; + public: explicit VSymGraph(AstNetlist* nodep) { m_symRootp = new VSymEnt(this, nodep); } ~VSymGraph() { @@ -300,7 +298,7 @@ public: // METHODS VSymEnt* rootp() const { return m_symRootp; } // Debug - void dump(std::ostream& os, const string& indent = "") { + void dumpSelf(std::ostream& os, const string& indent = "") { VSymConstMap doneSyms; os << "SymEnt Dump:\n"; m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root"); @@ -316,12 +314,12 @@ public: } } void dumpFilePrefixed(const string& nameComment) { - if (v3Global.opt.dumpTree()) { + if (dumpTree()) { const string filename = v3Global.debugFilename(nameComment) + ".txt"; UINFO(2, "Dumping " << filename << endl); const std::unique_ptr logp{V3File::new_ofstream(filename)}; if (logp->fail()) v3fatal("Can't write " << filename); - dump(*logp, ""); + dumpSelf(*logp, ""); } } diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 26055725d..0e488ca45 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -39,6 +39,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Support classes @@ -47,8 +49,6 @@ static uint32_t edgeIdNext = 0; static void selfTestStates(); static void selfTestString(); - -VL_DEBUG_FUNC; // Declare debug() } // namespace V3TSP // Vertex that tracks a per-vertex key @@ -396,7 +396,7 @@ public: } } void dumpGraphFilePrefixed(const string& nameComment) const { - if (v3Global.opt.dumpTree()) { + if (::dump()) { const string filename = v3Global.debugFilename(nameComment) + ".txt"; const std::unique_ptr logp{V3File::new_ofstream(filename)}; if (logp->fail()) v3fatal("Can't write " << filename); @@ -406,7 +406,7 @@ public: void findEulerTour(std::vector* sortedOutp) { UASSERT(sortedOutp->empty(), "Output graph must start empty"); - if (debug() >= 6) dumpDotFilePrefixed("findEulerTour"); + if (::dumpGraph() >= 6) dumpDotFilePrefixed("findEulerTour"); std::unordered_set markedEdges; // Pick a start node Vertex* const start_vertexp = castVertexp(verticesBeginp()); @@ -464,12 +464,12 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { // Create the minimum spanning tree Graph minGraph; graph.makeMinSpanningTree(&minGraph); - if (debug() >= 6) minGraph.dumpGraphFilePrefixed("minGraph"); + if (dumpGraph() >= 6) minGraph.dumpGraphFilePrefixed("minGraph"); const std::vector oddDegree = minGraph.getOddDegreeKeys(); Graph matching; graph.perfectMatching(oddDegree, &matching); - if (debug() >= 6) matching.dumpGraphFilePrefixed("matching"); + if (dumpGraph() >= 6) matching.dumpGraphFilePrefixed("matching"); // Adds edges to minGraph, the resulting graph will have even number of // edge counts at every vertex: @@ -672,12 +672,12 @@ void V3TSP::selfTestString() { Graph minGraph; graph.makeMinSpanningTree(&minGraph); - if (debug() >= 6) minGraph.dumpGraphFilePrefixed("minGraph"); + if (dumpGraph() >= 6) minGraph.dumpGraphFilePrefixed("minGraph"); const std::vector oddDegree = minGraph.getOddDegreeKeys(); Graph matching; graph.perfectMatching(oddDegree, &matching); - if (debug() >= 6) matching.dumpGraphFilePrefixed("matching"); + if (dumpGraph() >= 6) matching.dumpGraphFilePrefixed("matching"); minGraph.combineGraph(matching); diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 1e829f32e..8ace9f4f3 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -34,6 +34,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Table class functions @@ -169,7 +171,6 @@ private: std::vector m_outVarps; // Output variable list // METHODS - VL_DEBUG_FUNC; // Declare debug() public: void simulateVarRefCb(AstVarRef* nodep) { @@ -430,5 +431,5 @@ void TableSimulateVisitor::varRefCb(AstVarRef* nodep) { void V3Table::tableAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { TableVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("table", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("table", 0, dumpTree() >= 3); } diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 332550798..1dd4c2cd1 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -38,6 +38,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Graph subclasses @@ -281,7 +283,7 @@ public: iterate(nodep); // m_callGraph.removeRedundantEdgesSum(&TaskEdge::followAlwaysTrue); - m_callGraph.dumpDotFilePrefixed("task_call"); + if (dumpGraph()) m_callGraph.dumpDotFilePrefixed("task_call"); } ~TaskStateVisitor() override = default; VL_UNCOPYABLE(TaskStateVisitor); @@ -364,7 +366,6 @@ private: DpiCFuncs m_dpiNames; // Map of all created DPI functions // METHODS - VL_DEBUG_FUNC; // Declare debug() AstVarScope* createFuncVar(AstCFunc* funcp, const string& name, AstVar* examplep) { AstVar* const newvarp = new AstVar(funcp->fileline(), VVarType::BLOCKTEMP, name, examplep); @@ -1814,5 +1815,5 @@ void V3Task::taskAll(AstNetlist* nodep) { TaskStateVisitor visitors{nodep}; const TaskVisitor visitor{nodep, &visitors}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("task", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("task", 0, dumpTree() >= 3); } diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index 328e913ad..b19b1c249 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -50,6 +50,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Graph vertexes @@ -194,7 +196,6 @@ private: using TraceVec = std::multimap; // METHODS - VL_DEBUG_FUNC; // Declare debug() void detectDuplicates() { UINFO(9, "Finding duplicates\n"); @@ -724,11 +725,11 @@ private: detectDuplicates(); // Simplify & optimize the graph - if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_pre"); + if (dumpGraph() >= 6) m_graph.dumpDotFilePrefixed("trace_pre"); graphSimplify(true); - if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_simplified"); + if (dumpGraph() >= 6) m_graph.dumpDotFilePrefixed("trace_simplified"); graphOptimize(); - if (debug() >= 6) m_graph.dumpDotFilePrefixed("trace_optimized"); + if (dumpGraph() >= 6) m_graph.dumpDotFilePrefixed("trace_optimized"); // Create the fine grained activity flags createActivityFlags(); @@ -908,5 +909,5 @@ public: void V3Trace::traceAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { TraceVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("trace", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("trace", 0, dumpTree() >= 3); } diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 9df50a158..41db6e5ab 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -37,6 +37,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Utility class to emit path adjustments @@ -133,7 +135,6 @@ private: VDouble0 m_statIgnSigs; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() const char* vscIgnoreTrace(const AstVarScope* nodep) { // Return true if this shouldn't be traced @@ -525,5 +526,5 @@ public: void V3TraceDecl::traceDeclAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { TraceDeclVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("tracedecl", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("tracedecl", 0, dumpTree() >= 3); } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 613983a02..aafbc0f47 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -106,12 +106,13 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class TristateBaseVisitor VL_NOT_FINAL : public VNVisitor { public: // METHODS - VL_DEBUG_FUNC; // Declare debug() }; //###################################################################### @@ -176,7 +177,6 @@ public: private: // METHODS - VL_DEBUG_FUNC; // Declare debug() TristateVertex* makeVertex(AstNode* nodep) { TristateVertex* vertexp = reinterpret_cast(nodep->user5p()); @@ -264,7 +264,6 @@ public: AstNode::user5ClearTree(); // Wipe all node user5p's that point to vertexes } void graphWalk(AstNodeModule* nodep) { - // if (debug() >= 9) m_graph.dumpDotFilePrefixed("tri_pre__" + nodep->name()); UINFO(9, " Walking " << nodep << endl); for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { graphWalkRecurseFwd(static_cast(itp), 0); @@ -272,7 +271,7 @@ public: for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) { graphWalkRecurseBack(static_cast(itp), 0); } - if (debug() >= 9) m_graph.dumpDotFilePrefixed("tri_pos__" + nodep->name()); + if (dumpGraph() >= 9) m_graph.dumpDotFilePrefixed("tri_pos__" + nodep->name()); } void associate(AstNode* fromp, AstNode* top) { new V3GraphEdge(&m_graph, makeVertex(fromp), makeVertex(top), 1); @@ -1643,5 +1642,5 @@ public: void V3Tristate::tristateAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { TristateVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("tristate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("tristate", 0, dumpTree() >= 3); } diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 1cf0f125d..716005892 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -36,6 +36,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Class for every variable we may process @@ -47,8 +49,6 @@ class UndrivenVarEntry final { enum : uint8_t { FLAG_USED = 0, FLAG_DRIVEN = 1, FLAGS_PER_BIT = 2 }; - VL_DEBUG_FUNC; // Declare debug() - public: // CONSTRUCTORS explicit UndrivenVarEntry(AstVar* varp) @@ -257,7 +257,6 @@ private: const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr // METHODS - VL_DEBUG_FUNC; // Declare debug() UndrivenVarEntry* getEntryp(AstVar* nodep, int which_user) { if (!(which_user == 1 ? nodep->user1p() : nodep->user2p())) { diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index df468c70f..22a10af7d 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -41,6 +41,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### class UnknownVisitor final : public VNVisitor { @@ -64,7 +66,6 @@ private: V3UniqueNames m_xrandNames; // For generating unique temporary variable names // METHODS - VL_DEBUG_FUNC; // Declare debug() void replaceBoundLvalue(AstNode* nodep, AstNode* condp) { // Spec says a out-of-range LHS SEL results in a NOP. @@ -502,5 +503,5 @@ public: void V3Unknown::unknownAll(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { UnknownVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("unknown", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("unknown", 0, dumpTree() >= 3); } diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 2ffef6176..4629f16a5 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -37,6 +37,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Unroll state, as a visitor of each AstNode @@ -57,7 +59,6 @@ private: VDouble0 m_statIters; // Statistic tracking // METHODS - VL_DEBUG_FUNC; // Declare debug() // VISITORS bool cantUnroll(AstNode* nodep, const char* reason) const { @@ -517,5 +518,5 @@ void V3Unroll::unrollAll(AstNetlist* nodep) { UnrollStateful unroller; unroller.unrollAll(nodep); } // Destruct before checking - V3Global::dumpCheckGlobalTree("unroll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("unroll", 0, dumpTree() >= 3); } diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp index ad98ec081..562bc7225 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -34,6 +34,8 @@ #include #include +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Establish mtask variable sort order in mtasks mode @@ -205,5 +207,5 @@ void V3VariableOrder::orderAll() { modp = VN_AS(modp->nextp(), NodeModule)) { VariableOrder::processModule(modp); } - V3Global::dumpCheckGlobalTree("variableorder", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("variableorder", 0, dumpTree() >= 3); } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index c2f77042d..040b5b2bf 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -81,6 +81,8 @@ #define VERILATOR_V3WIDTH_CPP_ #include "V3WidthCommit.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### enum Stage : uint8_t { @@ -236,9 +238,6 @@ private: EXTEND_OFF // No extension }; - // METHODS - static int debug() { return V3Width::debug(); } - // VISITORS // Naming: width_O{outputtype}_L{lhstype}_R{rhstype}_W{widthing}_S{signing} // Where type: @@ -6728,12 +6727,6 @@ public: //###################################################################### // Width class functions -int V3Width::debug() { - static int level = -1; - if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__); - return level; -} - void V3Width::width(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { @@ -6744,7 +6737,7 @@ void V3Width::width(AstNetlist* nodep) { WidthRemoveVisitor rvisitor; (void)rvisitor.mainAcceptEdit(nodep); } // Destruct before checking - V3Global::dumpCheckGlobalTree("width", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("width", 0, dumpTree() >= 3); } //! Single node parameter propagation @@ -6780,5 +6773,5 @@ AstNode* V3Width::widthGenerateParamsEdit( void V3Width::widthCommit(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); { WidthCommitVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("widthcommit", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6); + V3Global::dumpCheckGlobalTree("widthcommit", 0, dumpTree() >= 6); } diff --git a/src/V3Width.h b/src/V3Width.h index 2d6cfb9d7..6a0261d9e 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -27,7 +27,6 @@ class AstNode; class V3Width final { public: - static int debug(); static void width(AstNetlist* nodep); static AstNode* widthParamsEdit(AstNode* nodep); static AstNode* widthGenerateParamsEdit(AstNode* nodep); diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index fb883a256..ca2f9a584 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -35,8 +35,9 @@ /// This step is only called on real V3Width, not intermediate e.g. widthParams class WidthRemoveVisitor final : public VNVisitor { -private: // METHODS + VL_DEFINE_DEBUG_FUNCTIONS; + void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) { UINFO(6, " Replace " << nodep << " w/ " << newp << endl); nodep->replaceWith(newp); @@ -74,6 +75,8 @@ class WidthCommitVisitor final : public VNVisitor { public: // METHODS + VL_DEFINE_DEBUG_FUNCTIONS; + static AstConst* newIfConstCommitSize(AstConst* nodep) { if (((nodep->dtypep()->width() != nodep->num().width()) || !nodep->num().sized()) && !nodep->num().isString()) { // Need to force the number from unsized to sized diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 222f69c5b..174d01a36 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -34,6 +34,8 @@ #include "V3Global.h" #include "V3Width.h" +VL_DEFINE_DEBUG_FUNCTIONS; + //###################################################################### // Width state, as a visitor of each AstNode @@ -47,7 +49,6 @@ private: #define iterateChildren DO_NOT_iterateChildern_IN_V3WidthSel // METHODS - VL_DEBUG_FUNC; // Declare debug() void checkConstantOrReplace(AstNode* nodep, const string& message) { // See also V3Width::checkConstantOrReplace diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 9eb120d86..448bf735d 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -103,6 +103,8 @@ #include +VL_DEFINE_DEBUG_FUNCTIONS; + V3Global v3Global; static void reportStatsIfEnabled() { @@ -607,7 +609,7 @@ static void verilate(const string& argString) { } // Final steps - V3Global::dumpCheckGlobalTree("final", 990, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + V3Global::dumpCheckGlobalTree("final", 990, dumpTree() >= 3); V3Error::abortIfErrors(); diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp index f4f6717ca..5f1b01ec5 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -23,14 +23,18 @@ #include "verilatedos.h" -// Cheat for speed and compile .cpp files into one object +// Cheat for speed and compile .cpp files into one object TODO: Reconsider #define V3ERROR_NO_GLOBAL_ +#include "V3Error.h" +static int debug() { return V3Error::debugDefault(); } #include "V3Error.cpp" #include "V3String.cpp" #define V3OPTION_PARSER_NO_VOPTION_BOOL +// clang-format off #include "V3OptionParser.cpp" #include "V3Os.cpp" #include "VlcTop.cpp" +// clanf-format on #include "VlcOptions.h" #include "VlcTop.h" diff --git a/src/VlcPoint.h b/src/VlcPoint.h index b5c9598fc..1b59b39f2 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -102,6 +102,8 @@ private: std::vector m_points; //< List of all points uint64_t m_numPoints = 0; //< Total unique points + static int debug() { return V3Error::debugDefault(); } + public: // ITERATORS using ByName = NameMap; diff --git a/src/VlcTest.h b/src/VlcTest.h index 2c85950dc..0ceb7d340 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -93,6 +93,8 @@ private: // MEMBERS ByName m_tests; //< List of all tests + static int debug() { return V3Error::debugDefault(); } + public: // ITERATORS using iterator = ByName::iterator; diff --git a/test_regress/driver.pl b/test_regress/driver.pl index fe0bd9498..da738d16a 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -235,7 +235,7 @@ sub parameter { elsif ($param =~ /\.pl/) { push @opt_tests, $param; } - elsif ($param =~ /^-?(-debugi|-dump-treei)/) { + elsif ($param =~ /^-?(-debugi|-dumpi)/) { push @Opt_Driver_Verilator_Flags, $param; $_Parameter_Next_Level = $param; } diff --git a/test_regress/t/t_debug_emitv.pl b/test_regress/t/t_debug_emitv.pl index 863c22c75..91be564c7 100755 --- a/test_regress/t/t_debug_emitv.pl +++ b/test_regress/t/t_debug_emitv.pl @@ -13,7 +13,7 @@ scenarios(vlt => 1); lint( # We also have dump-tree turned on, so hit a lot of AstNode*::dump() functions # Likewise XML - v_flags => ["--lint-only --dump-treei 9 --dump-treei-V3EmitV 9 --debug-emitv"], + v_flags => ["--lint-only --dumpi-tree 9 --dumpi-V3EmitV 9 --debug-emitv"], ); files_identical(glob_one("$Self->{obj_dir}/$Self->{VM_PREFIX}_*_width.tree.v"), $Self->{golden_filename}); diff --git a/test_regress/t/t_debug_emitv_addrids.pl b/test_regress/t/t_debug_emitv_addrids.pl index 40070d6e5..183f2dd13 100755 --- a/test_regress/t/t_debug_emitv_addrids.pl +++ b/test_regress/t/t_debug_emitv_addrids.pl @@ -15,7 +15,7 @@ top_filename("t/t_debug_emitv.v"); lint( # We also have dump-tree turned on, so hit a lot of AstNode*::dump() functions # Likewise XML - v_flags => ["--lint-only --dump-treei 9 --dump-tree-addrids"], + v_flags => ["--lint-only --dumpi-tree 9 --dump-tree-addrids"], ); ok(1); diff --git a/test_regress/t/t_dotfiles.pl b/test_regress/t/t_dotfiles.pl index a9b52715e..9df77e2ca 100755 --- a/test_regress/t/t_dotfiles.pl +++ b/test_regress/t/t_dotfiles.pl @@ -14,7 +14,7 @@ scenarios(vltmt => 1); top_filename("t/t_gen_alw.v"); compile( - v_flags2 => ["--debug --debugi 5"], + v_flags2 => ["--dumpi-graph 6"], threads => 2 ); From 050060b13940e13b24f0b3b4100dc4754146c6b1 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 23 Sep 2022 10:57:01 +0100 Subject: [PATCH 61/75] Make enum constructors and operators constexpr --- src/V3Ast.h | 263 ++++++++++++++++++++++++--------------------- src/V3CCtors.cpp | 2 +- src/V3Error.h | 12 +-- src/V3Global.h | 10 +- src/V3Graph.h | 8 +- src/V3LangCode.h | 4 +- src/V3Options.h | 40 +++---- src/V3OrderGraph.h | 10 +- 8 files changed, 184 insertions(+), 165 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index a945ea6a2..47661d626 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -95,18 +95,18 @@ public: // cppcheck-suppress uninitVar // responsibility of each subclass VNType() = default; // cppcheck-suppress noExplicitConstructor - VNType(en _e) + constexpr VNType(en _e) : m_e{_e} {} explicit VNType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const VNType& lhs, const VNType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VNType& lhs, VNType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VNType::en lhs, const VNType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VNType& lhs, const VNType& rhs) { return lhs.m_e == rhs.m_e; } +constexpr bool operator==(const VNType& lhs, VNType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VNType::en lhs, const VNType& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VNType& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VLifetime final { public: @@ -119,23 +119,25 @@ public: VLifetime() : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor - VLifetime(en _e) + constexpr VLifetime(en _e) : m_e{_e} {} explicit VLifetime(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool isNone() const { return m_e == NONE; } bool isAutomatic() const { return m_e == AUTOMATIC; } bool isStatic() const { return m_e == STATIC; } }; -inline bool operator==(const VLifetime& lhs, const VLifetime& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VLifetime& lhs, VLifetime::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VLifetime::en lhs, const VLifetime& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VLifetime& lhs, const VLifetime& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VLifetime& lhs, VLifetime::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VLifetime::en lhs, const VLifetime& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VAccess final { public: @@ -160,11 +162,11 @@ public: VAccess() : m_e{READ} {} // cppcheck-suppress noExplicitConstructor - VAccess(en _e) + constexpr VAccess(en _e) : m_e{_e} {} explicit VAccess(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } VAccess invert() const { return (m_e == READWRITE) ? VAccess{m_e} : (m_e == WRITE ? VAccess{READ} : VAccess{WRITE}); } @@ -174,12 +176,12 @@ public: bool isWriteOrRW() const { return m_e == WRITE || m_e == READWRITE; } bool isRW() const { return m_e == READWRITE; } }; -inline bool operator==(const VAccess& lhs, const VAccess& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VAccess& lhs, VAccess::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VAccess::en lhs, const VAccess& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VAccess& lhs, const VAccess& rhs) { return lhs.m_e == rhs.m_e; } +constexpr bool operator==(const VAccess& lhs, VAccess::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VAccess::en lhs, const VAccess& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VAccess& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VSigning final { public: @@ -197,26 +199,26 @@ public: VSigning() : m_e{UNSIGNED} {} // cppcheck-suppress noExplicitConstructor - VSigning(en _e) + constexpr VSigning(en _e) : m_e{_e} {} static VSigning fromBool(bool isSigned) { // Factory method return isSigned ? VSigning{SIGNED} : VSigning{UNSIGNED}; } explicit VSigning(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool isSigned() const { return m_e == SIGNED; } bool isNosign() const { return m_e == NOSIGN; } // No isUnsigned() as it's ambiguous if NOSIGN should be included or not. }; -inline bool operator==(const VSigning& lhs, const VSigning& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VSigning& lhs, VSigning::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VSigning::en lhs, const VSigning& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VSigning& lhs, const VSigning& rhs) { return lhs.m_e == rhs.m_e; } +constexpr bool operator==(const VSigning& lhs, VSigning::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VSigning::en lhs, const VSigning& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VSigning& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VPragmaType final { public: @@ -237,19 +239,19 @@ public: VPragmaType() : m_e{ILLEGAL} {} // cppcheck-suppress noExplicitConstructor - VPragmaType(en _e) + constexpr VPragmaType(en _e) : m_e{_e} {} explicit VPragmaType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const VPragmaType& lhs, const VPragmaType& rhs) { +constexpr bool operator==(const VPragmaType& lhs, const VPragmaType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VPragmaType& lhs, VPragmaType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VPragmaType::en lhs, const VPragmaType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VPragmaType& lhs, VPragmaType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VPragmaType::en lhs, const VPragmaType& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VEdgeType final { public: @@ -325,17 +327,19 @@ public: VEdgeType() : m_e{ET_ILLEGAL} {} // cppcheck-suppress noExplicitConstructor - VEdgeType(en _e) + constexpr VEdgeType(en _e) : m_e{_e} {} explicit VEdgeType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const VEdgeType& lhs, const VEdgeType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VEdgeType& lhs, VEdgeType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VEdgeType& lhs, const VEdgeType& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VEdgeType& lhs, VEdgeType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VAttrType final { public: @@ -406,17 +410,19 @@ public: VAttrType() : m_e{ILLEGAL} {} // cppcheck-suppress noExplicitConstructor - VAttrType(en _e) + constexpr VAttrType(en _e) : m_e{_e} {} explicit VAttrType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const VAttrType& lhs, const VAttrType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VAttrType& lhs, VAttrType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VAttrType::en lhs, const VAttrType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VAttrType& lhs, const VAttrType& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VAttrType& lhs, VAttrType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VAttrType::en lhs, const VAttrType& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VBasicDTypeKwd final { public: @@ -473,11 +479,11 @@ public: VBasicDTypeKwd() : m_e{UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - VBasicDTypeKwd(en _e) + constexpr VBasicDTypeKwd(en _e) : m_e{_e} {} explicit VBasicDTypeKwd(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } int width() const { switch (m_e) { case BIT: return 1; // scalar, can't bit extract unless ranged @@ -558,13 +564,13 @@ public: } } }; -inline bool operator==(const VBasicDTypeKwd& lhs, const VBasicDTypeKwd& rhs) { +constexpr bool operator==(const VBasicDTypeKwd& lhs, const VBasicDTypeKwd& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VBasicDTypeKwd& lhs, VBasicDTypeKwd::en rhs) { +constexpr bool operator==(const VBasicDTypeKwd& lhs, VBasicDTypeKwd::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VBasicDTypeKwd::en lhs, const VBasicDTypeKwd& rhs) { +constexpr bool operator==(VBasicDTypeKwd::en lhs, const VBasicDTypeKwd& rhs) { return lhs == rhs.m_e; } @@ -577,11 +583,11 @@ public: VDirection() : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor - VDirection(en _e) + constexpr VDirection(en _e) : m_e{_e} {} explicit VDirection(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"NONE", "INPUT", "OUTPUT", "INOUT", "REF", "CONSTREF"}; return names[m_e]; @@ -605,14 +611,16 @@ public: bool isWritable() const { return m_e == OUTPUT || m_e == INOUT || m_e == REF; } bool isRefOrConstRef() const { return m_e == REF || m_e == CONSTREF; } }; -inline bool operator==(const VDirection& lhs, const VDirection& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VDirection& lhs, VDirection::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VDirection::en lhs, const VDirection& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VDirection& lhs, const VDirection& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VDirection& lhs, VDirection::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VDirection::en lhs, const VDirection& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### /// Boolean or unknown class VBoolOrUnknown final { @@ -623,7 +631,7 @@ public: VBoolOrUnknown() : m_e{BU_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - VBoolOrUnknown(en _e) + constexpr VBoolOrUnknown(en _e) : m_e{_e} {} explicit VBoolOrUnknown(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning @@ -638,13 +646,13 @@ public: bool unknown() const { return m_e == BU_UNKNOWN; } void setTrueOrFalse(bool flag) { m_e = flag ? BU_TRUE : BU_FALSE; } }; -inline bool operator==(const VBoolOrUnknown& lhs, const VBoolOrUnknown& rhs) { +constexpr bool operator==(const VBoolOrUnknown& lhs, const VBoolOrUnknown& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VBoolOrUnknown& lhs, VBoolOrUnknown::en rhs) { +constexpr bool operator==(const VBoolOrUnknown& lhs, VBoolOrUnknown::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VBoolOrUnknown::en lhs, const VBoolOrUnknown& rhs) { +constexpr bool operator==(VBoolOrUnknown::en lhs, const VBoolOrUnknown& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) { @@ -662,7 +670,7 @@ public: VJoinType() : m_e{JOIN} {} // cppcheck-suppress noExplicitConstructor - VJoinType(en _e) + constexpr VJoinType(en _e) : m_e{_e} {} explicit VJoinType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning @@ -678,14 +686,16 @@ public: bool joinAny() const { return m_e == JOIN_ANY; } bool joinNone() const { return m_e == JOIN_NONE; } }; -inline bool operator==(const VJoinType& lhs, const VJoinType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VJoinType& lhs, VJoinType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VJoinType::en lhs, const VJoinType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VJoinType& lhs, const VJoinType& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VJoinType& lhs, VJoinType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VJoinType::en lhs, const VJoinType& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VJoinType& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VVarType final { public: @@ -715,11 +725,11 @@ public: VVarType() : m_e{UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - VVarType(en _e) + constexpr VVarType(en _e) : m_e{_e} {} explicit VVarType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = { "?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1", @@ -750,14 +760,14 @@ public: return (m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP); } }; -inline bool operator==(const VVarType& lhs, const VVarType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VVarType& lhs, VVarType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VVarType::en lhs, const VVarType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VVarType& lhs, const VVarType& rhs) { return lhs.m_e == rhs.m_e; } +constexpr bool operator==(const VVarType& lhs, VVarType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VVarType::en lhs, const VVarType& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VVarType& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VBranchPred final { public: @@ -767,11 +777,11 @@ public: VBranchPred() : m_e{BP_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - VBranchPred(en _e) + constexpr VBranchPred(en _e) : m_e{_e} {} explicit VBranchPred(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool unknown() const { return m_e == BP_UNKNOWN; } bool likely() const { return m_e == BP_LIKELY; } bool unlikely() const { return m_e == BP_UNLIKELY; } @@ -789,16 +799,16 @@ public: return names[m_e]; } }; -inline bool operator==(const VBranchPred& lhs, const VBranchPred& rhs) { +constexpr bool operator==(const VBranchPred& lhs, const VBranchPred& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VBranchPred& lhs, VBranchPred::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VBranchPred::en lhs, const VBranchPred& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VBranchPred& lhs, VBranchPred::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VBranchPred::en lhs, const VBranchPred& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VVarAttrClocker final { public: @@ -808,11 +818,11 @@ public: VVarAttrClocker() : m_e{CLOCKER_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - VVarAttrClocker(en _e) + constexpr VVarAttrClocker(en _e) : m_e{_e} {} explicit VVarAttrClocker(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool unknown() const { return m_e == CLOCKER_UNKNOWN; } VVarAttrClocker invert() const { if (m_e == CLOCKER_YES) { @@ -828,13 +838,13 @@ public: return names[m_e]; } }; -inline bool operator==(const VVarAttrClocker& lhs, const VVarAttrClocker& rhs) { +constexpr bool operator==(const VVarAttrClocker& lhs, const VVarAttrClocker& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VVarAttrClocker& lhs, VVarAttrClocker::en rhs) { +constexpr bool operator==(const VVarAttrClocker& lhs, VVarAttrClocker::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VVarAttrClocker::en lhs, const VVarAttrClocker& rhs) { +constexpr bool operator==(VVarAttrClocker::en lhs, const VVarAttrClocker& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) { @@ -850,21 +860,23 @@ public: VAlwaysKwd() : m_e{ALWAYS} {} // cppcheck-suppress noExplicitConstructor - VAlwaysKwd(en _e) + constexpr VAlwaysKwd(en _e) : m_e{_e} {} explicit VAlwaysKwd(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"always", "always_ff", "always_latch", "always_comb"}; return names[m_e]; } }; -inline bool operator==(const VAlwaysKwd& lhs, const VAlwaysKwd& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VAlwaysKwd& lhs, VAlwaysKwd::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VAlwaysKwd& lhs, const VAlwaysKwd& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VAlwaysKwd& lhs, VAlwaysKwd::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VCaseType final { public: @@ -873,17 +885,19 @@ public: VCaseType() : m_e{CT_CASE} {} // cppcheck-suppress noExplicitConstructor - VCaseType(en _e) + constexpr VCaseType(en _e) : m_e{_e} {} explicit VCaseType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const VCaseType& lhs, const VCaseType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VCaseType& lhs, VCaseType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VCaseType& lhs, const VCaseType& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VCaseType& lhs, VCaseType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VDisplayType final { public: @@ -901,11 +915,11 @@ public: VDisplayType() : m_e{DT_DISPLAY} {} // cppcheck-suppress noExplicitConstructor - VDisplayType(en _e) + constexpr VDisplayType(en _e) : m_e{_e} {} explicit VDisplayType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool addNewline() const { return m_e != DT_WRITE; } bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; } const char* ascii() const { @@ -914,13 +928,13 @@ public: return names[m_e]; } }; -inline bool operator==(const VDisplayType& lhs, const VDisplayType& rhs) { +constexpr bool operator==(const VDisplayType& lhs, const VDisplayType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VDisplayType& lhs, VDisplayType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VDisplayType::en lhs, const VDisplayType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VDisplayType& lhs, VDisplayType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VDisplayType::en lhs, const VDisplayType& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VDumpCtlType final { public: @@ -929,24 +943,24 @@ public: VDumpCtlType() : m_e{ON} {} // cppcheck-suppress noExplicitConstructor - VDumpCtlType(en _e) + constexpr VDumpCtlType(en _e) : m_e{_e} {} explicit VDumpCtlType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"$dumpfile", "$dumpvars", "$dumpall", "$dumpflush", "$dumplimit", "$dumpoff", "$dumpon"}; return names[m_e]; } }; -inline bool operator==(const VDumpCtlType& lhs, const VDumpCtlType& rhs) { +constexpr bool operator==(const VDumpCtlType& lhs, const VDumpCtlType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VDumpCtlType& lhs, VDumpCtlType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VDumpCtlType& lhs, VDumpCtlType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VParseRefExp final { public: @@ -959,26 +973,26 @@ public: VParseRefExp() : m_e{PX_NONE} {} // cppcheck-suppress noExplicitConstructor - VParseRefExp(en _e) + constexpr VParseRefExp(en _e) : m_e{_e} {} explicit VParseRefExp(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"", "$root", "TEXT", "PREDOT"}; return names[m_e]; } }; -inline bool operator==(const VParseRefExp& lhs, const VParseRefExp& rhs) { +constexpr bool operator==(const VParseRefExp& lhs, const VParseRefExp& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VParseRefExp& lhs, VParseRefExp::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VParseRefExp::en lhs, const VParseRefExp& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VParseRefExp& lhs, VParseRefExp::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VParseRefExp::en lhs, const VParseRefExp& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VStrength final { public: @@ -986,28 +1000,29 @@ public: enum en m_e; // cppcheck-suppress noExplicitConstructor - VStrength(en strengthLevel) + constexpr VStrength(en strengthLevel) : m_e(strengthLevel) {} explicit VStrength(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"highz", "small", "medium", "weak", "large", "pull", "strong", "supply"}; return names[m_e]; } }; -inline bool operator==(const VStrength& lhs, const VStrength& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VStrength& lhs, VStrength::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VStrength::en lhs, const VStrength& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VStrength& lhs, const VStrength& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VStrength& lhs, VStrength::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VStrength::en lhs, const VStrength& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VStrength& rhs) { return os << rhs.ascii(); } -//###################################################################### -// VNumRange - Structure containing numeric range information -// See also AstRange, which is a symbolic version of this +// ###################################################################### +// VNumRange - Structure containing numeric range information +// See also AstRange, which is a symbolic version of this class VNumRange final { public: @@ -1083,26 +1098,26 @@ public: VUseType() : m_e{IMP_FWD_CLASS} {} // cppcheck-suppress noExplicitConstructor - VUseType(en _e) + constexpr VUseType(en _e) : m_e{_e} {} explicit VUseType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; } bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; } - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"IMP_INC", "INT_INC", "IMP_FWD", "INT_FWD"}; return names[m_e]; } }; -inline bool operator==(const VUseType& lhs, const VUseType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VUseType& lhs, VUseType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VUseType::en lhs, const VUseType& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VUseType& lhs, const VUseType& rhs) { return lhs.m_e == rhs.m_e; } +constexpr bool operator==(const VUseType& lhs, VUseType::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VUseType::en lhs, const VUseType& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class VBasicTypeKey final { public: diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index bd8aa3e3a..c4af9097e 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -46,7 +46,7 @@ private: public: // cppcheck-suppress noExplicitConstructor - VCtorType(en _e) + constexpr VCtorType(en _e) : m_e{_e} {} bool isClass() const { return m_e == CLASS; } bool isCoverage() const { return m_e == COVERAGE; } diff --git a/src/V3Error.h b/src/V3Error.h index b538c250d..4e1de700c 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -146,12 +146,12 @@ public: V3ErrorCode() : m_e{EC_MIN} {} // cppcheck-suppress noExplicitConstructor - V3ErrorCode(en _e) + constexpr V3ErrorCode(en _e) : m_e{_e} {} explicit V3ErrorCode(const char* msgp); // Matching code or ERROR explicit V3ErrorCode(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { // clang-format off static const char* const names[] = { @@ -221,16 +221,16 @@ public: || m_e == VARHIDDEN); } }; -inline bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) { +constexpr bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; } inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class V3Error final { // Base class for any object that wants debugging and error reporting diff --git a/src/V3Global.h b/src/V3Global.h index 1341332f5..0a50e97b6 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -70,19 +70,19 @@ public: VWidthMinUsage() : m_e{LINT_WIDTH} {} // cppcheck-suppress noExplicitConstructor - VWidthMinUsage(en _e) + constexpr VWidthMinUsage(en _e) : m_e{_e} {} explicit VWidthMinUsage(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) { +constexpr bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VWidthMinUsage& lhs, VWidthMinUsage::en rhs) { +constexpr bool operator==(const VWidthMinUsage& lhs, VWidthMinUsage::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) { +constexpr bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) { return lhs == rhs.m_e; } diff --git a/src/V3Graph.h b/src/V3Graph.h index 8190e946e..0de50222a 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -61,7 +61,7 @@ public: : m_e{_e} {} explicit constexpr GraphWay(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"FORWARD", "REVERSE"}; return names[m_e]; @@ -71,9 +71,9 @@ public: constexpr bool forward() const { return m_e == FORWARD; } constexpr bool reverse() const { return m_e != FORWARD; } }; -inline bool operator==(const GraphWay& lhs, const GraphWay& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const GraphWay& lhs, GraphWay::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(GraphWay::en lhs, const GraphWay& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const GraphWay& lhs, const GraphWay& rhs) { return lhs.m_e == rhs.m_e; } +constexpr bool operator==(const GraphWay& lhs, GraphWay::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(GraphWay::en lhs, const GraphWay& rhs) { return lhs == rhs.m_e; } //============================================================================ diff --git a/src/V3LangCode.h b/src/V3LangCode.h index 1d2d70326..9deef638f 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -58,12 +58,12 @@ public: V3LangCode() : m_e{L_ERROR} {} // cppcheck-suppress noExplicitConstructor - V3LangCode(en _e) + constexpr V3LangCode(en _e) : m_e{_e} {} explicit V3LangCode(const char* textp); explicit V3LangCode(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; //###################################################################### diff --git a/src/V3Options.h b/src/V3Options.h index 353370b7f..782987d46 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -42,24 +42,24 @@ public: VOptionBool() : m_e{OPT_DEFAULT_FALSE} {} // cppcheck-suppress noExplicitConstructor - VOptionBool(en _e) + constexpr VOptionBool(en _e) : m_e{_e} {} explicit VOptionBool(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; } bool isTrue() const { return m_e == OPT_TRUE || m_e == OPT_DEFAULT_TRUE; } bool isSetTrue() const { return m_e == OPT_TRUE; } bool isSetFalse() const { return m_e == OPT_FALSE; } void setTrueOrFalse(bool flag) { m_e = flag ? OPT_TRUE : OPT_FALSE; } }; -inline bool operator==(const VOptionBool& lhs, const VOptionBool& rhs) { +constexpr bool operator==(const VOptionBool& lhs, const VOptionBool& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VOptionBool& lhs, VOptionBool::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VOptionBool::en lhs, const VOptionBool& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VOptionBool& lhs, VOptionBool::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VOptionBool::en lhs, const VOptionBool& rhs) { return lhs == rhs.m_e; } -//###################################################################### +// ###################################################################### class VTimescale final { public: @@ -81,7 +81,7 @@ public: VTimescale() : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor - VTimescale(en _e) + constexpr VTimescale(en _e) : m_e{_e} {} explicit VTimescale(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning @@ -116,26 +116,30 @@ public: return values[m_e]; } }; -inline bool operator==(const VTimescale& lhs, const VTimescale& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const VTimescale& lhs, VTimescale::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(VTimescale::en lhs, const VTimescale& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const VTimescale& lhs, const VTimescale& rhs) { + return lhs.m_e == rhs.m_e; +} +constexpr bool operator==(const VTimescale& lhs, VTimescale::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(VTimescale::en lhs, const VTimescale& rhs) { return lhs == rhs.m_e; } // Comparisons are based on time, not enum values, so seconds > milliseconds -inline bool operator<(const VTimescale& lhs, const VTimescale& rhs) { return lhs.m_e > rhs.m_e; } +constexpr bool operator<(const VTimescale& lhs, const VTimescale& rhs) { + return lhs.m_e > rhs.m_e; +} inline std::ostream& operator<<(std::ostream& os, const VTimescale& rhs) { return os << rhs.ascii(); } -//###################################################################### +// ###################################################################### class TraceFormat final { public: enum en : uint8_t { VCD = 0, FST } m_e; // cppcheck-suppress noExplicitConstructor - TraceFormat(en _e = VCD) + constexpr TraceFormat(en _e = VCD) : m_e{_e} {} explicit TraceFormat(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } bool fst() const { return m_e == FST; } bool vcd() const { return m_e == VCD; } string classBase() const { @@ -147,16 +151,16 @@ public: return names[m_e]; } }; -inline bool operator==(const TraceFormat& lhs, const TraceFormat& rhs) { +constexpr bool operator==(const TraceFormat& lhs, const TraceFormat& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const TraceFormat& lhs, TraceFormat::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(TraceFormat::en lhs, const TraceFormat& rhs) { return lhs == rhs.m_e; } +constexpr bool operator==(const TraceFormat& lhs, TraceFormat::en rhs) { return lhs.m_e == rhs; } +constexpr bool operator==(TraceFormat::en lhs, const TraceFormat& rhs) { return lhs == rhs.m_e; } using V3StringList = std::vector; using V3StringSet = std::set; -//###################################################################### +// ###################################################################### // Information given by --hierarchical-block option class V3HierarchicalBlockOption final { diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index fb1fa67dc..109dfb3cb 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -90,19 +90,19 @@ struct OrderVEdgeType { OrderVEdgeType() : m_e{VERTEX_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor - OrderVEdgeType(en _e) + constexpr OrderVEdgeType(en _e) : m_e{_e} {} explicit OrderVEdgeType(int _e) : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning - operator en() const { return m_e; } + constexpr operator en() const { return m_e; } }; -inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) { +constexpr bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) { return lhs.m_e == rhs.m_e; } -inline bool operator==(const OrderVEdgeType& lhs, OrderVEdgeType::en rhs) { +constexpr bool operator==(const OrderVEdgeType& lhs, OrderVEdgeType::en rhs) { return lhs.m_e == rhs; } -inline bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) { +constexpr bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) { return lhs == rhs.m_e; } From 2f50642ecb8a220cfdaf17cd102361651cdd461c Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Fri, 23 Sep 2022 17:20:24 +0100 Subject: [PATCH 62/75] Exclude VL_DEFINE_DEBUG_FUNCTIONS from code coverage --- nodist/code_coverage.dat | 1 + 1 file changed, 1 insertion(+) diff --git a/nodist/code_coverage.dat b/nodist/code_coverage.dat index bff045d22..5197f226f 100644 --- a/nodist/code_coverage.dat +++ b/nodist/code_coverage.dat @@ -48,6 +48,7 @@ exclude_line_regexp(r'\bNUM_ASSERT') exclude_line_regexp(r'\bERROR_RSVD_WORD') exclude_line_regexp(r'\bV3ERROR_NA') exclude_line_regexp(r'\bUINFO\b') +exclude_line_regexp(r'\bVL_DEFINE_DEBUG_FUNCTIONS\b') # Exclude for branch coverage only exclude_branch_regexp(r'\bdebug\(\)') From 78e659a142ca0a1fe77d78e936c78c6bd3a52a9f Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 24 Sep 2022 16:57:42 +0100 Subject: [PATCH 63/75] Reduce size of FileLine Multiple tricks to reduce the size of class FileLine from 72 to 40 bytes: - Reduce file name index from 32 to 16 bits. This still allows 64K unique input files, which is hopefully enough. - Intern message/warning enable bitset and use a 16-bit index, again allowing 64K unique sets which is hopefully enough. - Put the m_waive flag into the sign bit of one of the line numbers. - Use explicit reference counting to avoid overhead of shared_ptr. Added assertions to ensure interned data fits within it's index space. This saves ~5-10% peak memory consumption at no measurable run-time cost on various designs. --- src/V3FileLine.cpp | 100 ++++++++++++++++++++----------- src/V3FileLine.h | 145 +++++++++++++++++++++++++++++++-------------- src/V3Param.cpp | 2 +- 3 files changed, 167 insertions(+), 80 deletions(-) diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index b313b2063..2e1c76afe 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -31,6 +31,7 @@ #include #include +#include #include VL_DEFINE_DEBUG_FUNCTIONS; @@ -38,7 +39,7 @@ VL_DEFINE_DEBUG_FUNCTIONS; //###################################################################### // FileLineSingleton class functions -string FileLineSingleton::filenameLetters(int fileno) { +string FileLineSingleton::filenameLetters(fileNameIdx_t fileno) { constexpr int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number char out[size]; @@ -60,14 +61,18 @@ string FileLineSingleton::filenameLetters(int fileno) { //! We associate a language with each source file, so we also set the default //! for this. -int FileLineSingleton::nameToNumber(const string& filename) { - const auto it = vlstd::as_const(m_namemap).find(filename); - if (VL_LIKELY(it != m_namemap.end())) return it->second; - const int num = m_names.size(); - m_names.push_back(filename); - m_languages.push_back(V3LangCode::mostRecent()); - m_namemap.emplace(filename, num); - return num; +FileLineSingleton::fileNameIdx_t FileLineSingleton::nameToNumber(const string& filename) { + const auto pair = m_namemap.emplace(filename, 0); + fileNameIdx_t& idx = pair.first->second; + if (pair.second) { + const size_t nextIdx = m_names.size(); + UASSERT(nextIdx <= std::numeric_limits::max(), + "Too many input files (" + cvtToStr(nextIdx) + "+)."); + idx = static_cast(nextIdx); + m_names.push_back(filename); + m_languages.push_back(V3LangCode::mostRecent()); + } + return idx; } //! Support XML output @@ -82,8 +87,46 @@ void FileLineSingleton::fileNameNumMapDumpXml(std::ostream& os) { os << "\n"; } -//###################################################################### -// VFileContents class functions +FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBitSet& bitSet) { + const auto pair = m_internedMsgEnIdxs.emplace(bitSet, 0); + msgEnSetIdx_t& idx = pair.first->second; + if (pair.second) { + const size_t nextIdx = m_internedMsgEns.size(); + UASSERT(nextIdx <= std::numeric_limits::max(), + "Too many unique message enable sets (" + cvtToStr(nextIdx) + "+)."); + idx = static_cast(nextIdx); + m_internedMsgEns.push_back(bitSet); + } + return idx; +} + +FileLineSingleton::msgEnSetIdx_t FileLineSingleton::defaultMsgEnIndex() { + MsgEnBitSet msgEnBitSet; + for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) { + msgEnBitSet.set(i, !V3ErrorCode{i}.defaultsOff()); + } + return addMsgEnBitSet(msgEnBitSet); +} + +FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnSetBit(msgEnSetIdx_t setIdx, + size_t bitIdx, bool value) { + if (msgEn(setIdx).test(bitIdx) == value) return setIdx; + MsgEnBitSet msgEnBitSet{msgEn(setIdx)}; + msgEnBitSet.set(bitIdx, value); + return addMsgEnBitSet(msgEnBitSet); +} + +FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnAnd(msgEnSetIdx_t lhsIdx, + msgEnSetIdx_t rhsIdx) { + MsgEnBitSet msgEnBitSet{msgEn(lhsIdx)}; + msgEnBitSet &= msgEn(rhsIdx); + if (msgEnBitSet == msgEn(lhsIdx)) return lhsIdx; + if (msgEnBitSet == msgEn(rhsIdx)) return rhsIdx; + return addMsgEnBitSet(msgEnBitSet); +} + +// ###################################################################### +// VFileContents class functions void VFileContent::pushText(const string& text) { if (m_lines.size() == 0) { @@ -136,22 +179,17 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp) { return os; } -//###################################################################### -// FileLine class functions +// ###################################################################### +// FileLine class functions -// Sort of a singleton -FileLine::FileLine(FileLine::EmptySecret) { - m_filenameno = singleton().nameToNumber(FileLine::builtInFilename()); - - m_warnOn = 0; - for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code{codei}; - warnOff(code, code.defaultsOff()); - } +FileLine::~FileLine() { + if (m_contentp) VL_DO_DANGLING(m_contentp->refDec(), m_contentp); } void FileLine::newContent() { - m_contentp = std::make_shared(); + if (m_contentp) VL_DO_DANGLING(m_contentp->refDec(), m_contentp); + m_contentp = new VFileContent; + m_contentp->refInc(); m_contentLineno = 1; } @@ -318,24 +356,16 @@ void FileLine::warnStyleOff(bool flag) { } bool FileLine::warnIsOff(V3ErrorCode code) const { - if (!m_warnOn.test(code)) return true; - if (!defaultFileLine().m_warnOn.test(code)) return true; // Global overrides local + if (!msgEn().test(code)) return true; + if (!defaultFileLine().msgEn().test(code)) return true; // Global overrides local // UNOPTFLAT implies UNOPT - if (code == V3ErrorCode::UNOPT && !m_warnOn.test(V3ErrorCode::UNOPTFLAT)) return true; - if ((code.lintError() || code.styleError()) && !m_warnOn.test(V3ErrorCode::I_LINT)) { + if (code == V3ErrorCode::UNOPT && !msgEn().test(V3ErrorCode::UNOPTFLAT)) return true; + if ((code.lintError() || code.styleError()) && !msgEn().test(V3ErrorCode::I_LINT)) { return true; } return false; } -void FileLine::modifyStateInherit(const FileLine* fromp) { - // Any warnings that are off in "from", become off in "this". - for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) { - const V3ErrorCode code{codei}; - if (fromp->warnIsOff(code)) warnOff(code, true); - } -} - void FileLine::v3errorEnd(std::ostringstream& sstr, const string& extra) { std::ostringstream nsstr; if (lastLineno()) nsstr << this; diff --git a/src/V3FileLine.h b/src/V3FileLine.h index e3cd40fc4..c8a44a0bf 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -23,14 +23,17 @@ #include "V3Error.h" #include "V3LangCode.h" +#include #include #include #include #include #include #include +#include +#include -//###################################################################### +// ###################################################################### class FileLine; @@ -39,68 +42,109 @@ class FileLine; //! This singleton class contains tables of data that are unchanging in each //! source file (each with its own unique filename number). class FileLineSingleton final { + friend class FileLine; + + // TYPES + using fileNameIdx_t = uint16_t; // Increase width if 64K input files are not enough + using msgEnSetIdx_t = uint16_t; // Increase width if 64K unique message sets are not enough + using MsgEnBitSet = std::bitset; + // MEMBERS - std::map m_namemap; // filenameno for each filename + std::map m_namemap; // filenameno for each filename std::deque m_names; // filename text for each filenameno std::deque m_languages; // language for each filenameno + + // Map from flag set to the index in m_internedMsgEns for interning + std::unordered_map m_internedMsgEnIdxs; + // Interned message enablement flag sets + std::vector m_internedMsgEns; + // CONSTRUCTORS FileLineSingleton() = default; ~FileLineSingleton() = default; -protected: - friend class FileLine; - int nameToNumber(const string& filename); - string numberToName(int filenameno) const { return m_names[filenameno]; } - V3LangCode numberToLang(int filenameno) const { return m_languages[filenameno]; } - void numberToLang(int filenameno, const V3LangCode& l) { m_languages[filenameno] = l; } + fileNameIdx_t nameToNumber(const string& filename); + string numberToName(fileNameIdx_t filenameno) const { return m_names[filenameno]; } + V3LangCode numberToLang(fileNameIdx_t filenameno) const { return m_languages[filenameno]; } + void numberToLang(fileNameIdx_t filenameno, const V3LangCode& l) { + m_languages[filenameno] = l; + } void clear() { m_namemap.clear(); m_names.clear(); m_languages.clear(); } void fileNameNumMapDumpXml(std::ostream& os); - static string filenameLetters(int fileno); + static string filenameLetters(fileNameIdx_t fileno); + + // Add given bitset to the interned bitsets, return interned index + msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet); + // Add index of default bitset + msgEnSetIdx_t defaultMsgEnIndex(); + // Set bitIdx to value in bitset at interned idnex setIdx, return interned index of result + msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, size_t bitIdx, bool value); + // Return index to intersection set + msgEnSetIdx_t msgEnAnd(msgEnSetIdx_t lhsIdx, msgEnSetIdx_t rhsIdx); + // Retrieve interned bitset at given interned index. The returned reference is not persistent. + const MsgEnBitSet& msgEn(msgEnSetIdx_t idx) const { return m_internedMsgEns.at(idx); } }; -//! All source lines from a file/stream, to enable errors to show sources +// All source lines from a file/stream, to enable errors to show sources class VFileContent final { + friend class FileLine; // MEMBERS int m_id; // Content ID number + // Reference count for sharing (shared_ptr has size overhead that we don't want) + std::atomic m_refCount{0}; std::deque m_lines; // Source text lines -public: VFileContent() { static int s_id = 0; m_id = ++s_id; } ~VFileContent() = default; // METHODS + void refInc() { ++m_refCount; } + void refDec() { + if (!--m_refCount) delete this; + } + +public: void pushText(const string& text); // Add arbitrary text (need not be line-by-line) string getLine(int lineno) const; string ascii() const { return "ct" + cvtToStr(m_id); } }; std::ostream& operator<<(std::ostream& os, VFileContent* contentp); -//! File and line number of an object, mostly for error reporting +// File and line number of an object, mostly for error reporting -//! This class is instantiated for every source code line (potentially -//! millions). To save space, per-file information (e.g. filename, source -//! language is held in tables in the FileLineSingleton class. +// This class is instantiated for every source code line (potentially millions), and instances +// created at any point usually persist until the end of the program. To save space, per-file +// information (e.g. filename, source language) is held in tables in the FileLineSingleton class. +// Similarly, message enablement flags are interned in FileLineSingleton. + +// WARNING: Avoid increasing the size of this class as much as possible. class FileLine final { + // CONSTANTS static constexpr unsigned SHOW_SOURCE_MAX_LENGTH = 400; // Don't show source lines > this long + // TYPES + using fileNameIdx_t = FileLineSingleton::fileNameIdx_t; + using msgEnSetIdx_t = FileLineSingleton::msgEnSetIdx_t; + using MsgEnBitSet = FileLineSingleton::MsgEnBitSet; + // MEMBERS // Columns here means number of chars from beginning (i.e. tabs count as one) + msgEnSetIdx_t m_msgEnIdx = 0; // Message enable bit set (index into interned array) + fileNameIdx_t m_filenameno = 0; // `line corrected filename number + bool m_waive : 1; // Waive warning - pack next to the line number to save 8 bytes of storage + unsigned m_contentLineno : 31; // Line number within source stream int m_firstLineno = 0; // `line corrected token's first line number int m_firstColumn = 0; // `line corrected token's first column number int m_lastLineno = 0; // `line corrected token's last line number int m_lastColumn = 0; // `line corrected token's last column number - int m_filenameno; // `line corrected filename number - int m_contentLineno = 0; // Line number within source stream - std::shared_ptr m_contentp = nullptr; // Source text contents line is within + VFileContent* m_contentp = nullptr; // Source text contents line is within FileLine* m_parent = nullptr; // Parent line that included this line - std::bitset m_warnOn; - bool m_waive = false; // Waive warning protected: // User routines should never need to change line numbers @@ -118,30 +162,38 @@ private: return s; } static FileLine& defaultFileLine() { - static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret()); - return *defFilelinep; + static FileLine s; + return s; } + FileLine() // Only used for defaultFileLine above + : m_msgEnIdx{singleton().defaultMsgEnIndex()} + , m_filenameno{singleton().nameToNumber(FileLine::builtInFilename())} + , m_waive{false} + , m_contentLineno{0} {} + public: explicit FileLine(const string& filename) - : m_filenameno{singleton().nameToNumber(filename)} - , m_warnOn{defaultFileLine().m_warnOn} {} + : m_msgEnIdx{defaultFileLine().m_msgEnIdx} + , m_filenameno{singleton().nameToNumber(filename)} + , m_waive{false} + , m_contentLineno{0} {} explicit FileLine(FileLine* fromp) - : m_firstLineno{fromp->m_firstLineno} + : m_msgEnIdx{fromp->m_msgEnIdx} + , m_filenameno{fromp->m_filenameno} + , m_waive{fromp->m_waive} + , m_contentLineno{fromp->m_contentLineno} + , m_firstLineno{fromp->m_firstLineno} , m_firstColumn{fromp->m_firstColumn} , m_lastLineno{fromp->m_lastLineno} , m_lastColumn{fromp->m_lastColumn} - , m_filenameno{fromp->m_filenameno} - , m_contentLineno{fromp->m_contentLineno} , m_contentp{fromp->m_contentp} - , m_parent{fromp->m_parent} - , m_warnOn{fromp->m_warnOn} - , m_waive{fromp->m_waive} {} - struct EmptySecret {}; // Constructor selection - explicit FileLine(EmptySecret); + , m_parent{fromp->m_parent} { + if (m_contentp) m_contentp->refInc(); + } FileLine* copyOrSameFileLine(); static void deleteAllRemaining(); - ~FileLine() = default; + ~FileLine(); #ifdef VL_LEAK_CHECKS static void* operator new(size_t size); static void operator delete(void* obj, size_t size); @@ -150,7 +202,7 @@ public: void newContent(); void contentLineno(int num) { lineno(num); - m_contentLineno = num; + m_contentLineno = static_cast(num); } void lineno(int num) { m_firstLineno = num; @@ -180,7 +232,7 @@ public: int firstColumn() const { return m_firstColumn; } int lastLineno() const { return m_lastLineno; } int lastColumn() const { return m_lastColumn; } - std::shared_ptr contentp() const { return m_contentp; } + VFileContent* contentp() const { return m_contentp; } // If not otherwise more specific, use last lineno for errors etc, // as the parser errors etc generally make more sense pointing at the last parse point int lineno() const { return m_lastLineno; } @@ -204,22 +256,24 @@ public: string lineDirectiveStrg(int enterExit) const; // Turn on/off warning messages on this line. - void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code, flag); } + void warnOn(V3ErrorCode code, bool flag) { + m_msgEnIdx = singleton().msgEnSetBit(m_msgEnIdx, code, flag); + } void warnOff(V3ErrorCode code, bool flag) { warnOn(code, !flag); } bool warnOff(const string& msg, bool flag); // Returns 1 if ok bool warnIsOff(V3ErrorCode code) const; void warnLintOff(bool flag); void warnStyleOff(bool flag); - void warnStateFrom(const FileLine& from) { m_warnOn = from.m_warnOn; } + void warnStateFrom(const FileLine& from) { m_msgEnIdx = from.m_msgEnIdx; } void warnResetDefault() { warnStateFrom(defaultFileLine()); } bool lastWarnWaived() const { return m_waive; } // Specific flag ACCESSORS/METHODS - bool celldefineOn() const { return m_warnOn.test(V3ErrorCode::I_CELLDEFINE); } + bool celldefineOn() const { return msgEn().test(V3ErrorCode::I_CELLDEFINE); } void celldefineOn(bool flag) { warnOn(V3ErrorCode::I_CELLDEFINE, flag); } - bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); } + bool coverageOn() const { return msgEn().test(V3ErrorCode::I_COVERAGE); } void coverageOn(bool flag) { warnOn(V3ErrorCode::I_COVERAGE, flag); } - bool tracingOn() const { return m_warnOn.test(V3ErrorCode::I_TRACING); } + bool tracingOn() const { return msgEn().test(V3ErrorCode::I_TRACING); } void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING, flag); } // METHODS - Global @@ -238,7 +292,9 @@ public: // METHODS - Called from netlist // Merge warning disables from another fileline - void modifyStateInherit(const FileLine* fromp); + void modifyStateInherit(const FileLine* fromp) { + m_msgEnIdx = singleton().msgEnAnd(m_msgEnIdx, fromp->m_msgEnIdx); + } // Change the current fileline due to actions discovered after parsing // and may have side effects on other nodes sharing this FileLine. // Use only when this is intended @@ -266,7 +322,7 @@ public: bool operator==(const FileLine& rhs) const { return (m_firstLineno == rhs.m_firstLineno && m_firstColumn == rhs.m_firstColumn && m_lastLineno == rhs.m_lastLineno && m_lastColumn == rhs.m_lastColumn - && m_filenameno == rhs.m_filenameno && m_warnOn == rhs.m_warnOn); + && m_filenameno == rhs.m_filenameno && m_msgEnIdx == rhs.m_msgEnIdx); } // Returns -1 if (*this) should come before rhs after sorted. 1 for the opposite case. 0 for // equivalent. @@ -278,14 +334,15 @@ public: return (m_firstColumn < rhs.m_firstColumn) ? -1 : 1; if (m_lastLineno != rhs.m_lastLineno) return (m_lastLineno < rhs.m_lastLineno) ? -1 : 1; if (m_lastColumn != rhs.m_lastColumn) return (m_lastColumn < rhs.m_lastColumn) ? -1 : 1; - for (size_t i = 0; i < m_warnOn.size(); ++i) { - if (m_warnOn[i] != rhs.m_warnOn[i]) return (m_warnOn[i] < rhs.m_warnOn[i]) ? -1 : 1; + for (size_t i = 0; i < msgEn().size(); ++i) { + if (msgEn().test(i) != rhs.msgEn().test(i)) return rhs.msgEn().test(i) ? -1 : 1; } return 0; // (*this) and rhs are equivalent } private: string warnContext(bool secondary) const; + const MsgEnBitSet& msgEn() const { return singleton().msgEn(m_msgEnIdx); } }; std::ostream& operator<<(std::ostream& os, FileLine* fileline); diff --git a/src/V3Param.cpp b/src/V3Param.cpp index e4719d3f3..18dfc06b6 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -101,7 +101,7 @@ public: for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin(); pIt != params.end(); ++pIt) { std::unique_ptr constp{AstConst::parseParamLiteral( - new FileLine(FileLine::EmptySecret()), pIt->second)}; + new FileLine{FileLine::builtInFilename()}, pIt->second)}; UASSERT(constp, pIt->second << " is not a valid parameter literal"); const bool inserted = consts.emplace(pIt->first, std::move(constp)).second; UASSERT(inserted, pIt->first << " is already added"); From 10796457d2d6c408b91d3a2f9b81f95da846f3b3 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 24 Sep 2022 20:44:00 +0100 Subject: [PATCH 64/75] V3Life: don't depend on AstNode::editCountGbl() No functional change intended. --- src/V3Life.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 534c5afca..4a8067189 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -130,6 +130,7 @@ class LifeBlock final { LifeMap m_map; // Current active lifetime map for current scope LifeBlock* const m_aboveLifep; // Upper life, or nullptr LifeState* const m_statep; // Current global state + bool m_replacedVref = false; // Replaced a variable reference since last clearing public: LifeBlock(LifeBlock* aboveLifep, LifeState* statep) @@ -178,6 +179,8 @@ public: m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}}); } } + void clearReplaced() { m_replacedVref = false; } + bool replaced() const { return m_replacedVref; } void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) { // Variable rvalue. If it references a constant, we can replace it const auto it = m_map.find(nodep); @@ -188,6 +191,7 @@ public: // We'll later constant propagate UINFO(4, " replaceconst: " << varrefp << endl); varrefp->replaceWith(constp->cloneTree(false)); + m_replacedVref = true; VL_DO_DANGLING(varrefp->deleteTree(), varrefp); ++m_statep->m_statAssnCon; return; // **DONE, no longer a var reference** @@ -307,10 +311,10 @@ private: void visit(AstNodeAssign* nodep) override { // Collect any used variables first, as lhs may also be on rhs // Similar code in V3Dead - const uint64_t lastEdit = AstNode::editCountGbl(); // When it was last edited m_sideEffect = false; + m_lifep->clearReplaced(); iterateAndNextNull(nodep->rhsp()); - if (lastEdit != AstNode::editCountGbl()) { + if (m_lifep->replaced()) { // We changed something, try to constant propagate, but don't delete the // assignment as we still need nodep to remain. V3Const::constifyEdit(nodep->rhsp()); // rhsp may change From 9a20a258f5e10d3247b15397354b6da93cd97be2 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Sat, 24 Sep 2022 21:18:43 +0100 Subject: [PATCH 65/75] Omit AstNode::m_editCount in release build This is only a debugging aid at this point, so compile out of the release build. This reduces peak memory consumption by 4-5%. We still keep the global counters to detect the tree have changed, to avoid unnecessary dumps. --- src/V3Ast.h | 14 ++++++++++---- src/V3AstNodes.cpp | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/V3Ast.h b/src/V3Ast.h index 47661d626..01a6af34c 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1443,13 +1443,15 @@ class AstNode VL_NOT_FINAL { AstNodeDType* m_dtypep = nullptr; // Data type of output or assignment (etc) AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list FileLine* m_fileline; // Where it was declared +#ifdef VL_DEBUG + // Only keep track of the edit count in the node in the debug build. + // In the release build we will take the space saving instead. uint64_t m_editCount; // When it was last edited +#endif static uint64_t s_editCntGbl; // Global edit counter - // Global edit counter, last value for printing * near node #s - static uint64_t s_editCntLast; + static uint64_t s_editCntLast; // Last committed value of global edit counter - AstNode* m_clonep - = nullptr; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY) + AstNode* m_clonep = nullptr; // Pointer to clone/source of node (only for *LAST* cloneTree()) static int s_cloneCntGbl; // Count of which userp is set // This member ordering both allows 64 bit alignment and puts associated data together @@ -1720,10 +1722,14 @@ public: static void user5ClearTree() { VNUser5InUse::clear(); } // Clear userp()'s across the entire tree // clang-format on +#ifdef VL_DEBUG uint64_t editCount() const { return m_editCount; } void editCountInc() { m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##" } +#else + void editCountInc() { ++s_editCntGbl; } +#endif static uint64_t editCountLast() { return s_editCntLast; } static uint64_t editCountGbl() { return s_editCntGbl; } static void editCountSetLast() { s_editCntLast = editCountGbl(); } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 172b4cec1..af7f7d74c 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1266,10 +1266,10 @@ static std::string nodeAddr(const AstNode* nodep) { } void AstNode::dump(std::ostream& str) const { - str << typeName() << " " - << nodeAddr(this) - //<< " " << nodeAddr(m_backp) + str << typeName() << " " << nodeAddr(this) +#ifdef VL_DEBUG << " = editCountLast()) ? "#>" : ">") +#endif << " {" << fileline()->filenameLetters() << std::dec << fileline()->lastLineno() << fileline()->firstColumnLetters() << "}"; if (user1p()) str << " u1=" << nodeAddr(user1p()); From f96454adccc0c8395d151a54f60d6c2218c88ed0 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Mon, 26 Sep 2022 14:43:09 +0100 Subject: [PATCH 66/75] gitignore .gdb_history --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2bfa23d4b..48859af2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ \#* .#* +.gdb_history .nfs* *~ *.tidy From 4931e48016666438eaa3e1ba604e0796b2a9af6b Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Tue, 27 Sep 2022 03:21:37 +0200 Subject: [PATCH 67/75] Support resolving assignments with equal strengths (#3637) --- src/V3Tristate.cpp | 250 +++++++++++++++----- test_regress/t/t_strength_2_uneq_assign.out | 10 + test_regress/t/t_strength_2_uneq_assign.pl | 19 ++ test_regress/t/t_strength_2_uneq_assign.v | 19 ++ test_regress/t/t_strength_equal_strength.pl | 21 ++ test_regress/t/t_strength_equal_strength.v | 48 ++++ 6 files changed, 309 insertions(+), 58 deletions(-) create mode 100644 test_regress/t/t_strength_2_uneq_assign.out create mode 100755 test_regress/t/t_strength_2_uneq_assign.pl create mode 100644 test_regress/t/t_strength_2_uneq_assign.v create mode 100755 test_regress/t/t_strength_equal_strength.pl create mode 100644 test_regress/t/t_strength_equal_strength.v diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index aafbc0f47..55dddaacc 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -58,10 +58,14 @@ // // Another thing done in this phase is signal strength handling. // Currently they are only supported in assignments and gates parsed as assignments (see verilog.y) -// and only in case when the strongest assignment has RHS marked as non-tristate. It is the case -// when they can be statically resolved. -// If the RHS is equal to z, that assignment has to be skipped. Since the value may be not known at -// verilation time, cases with tristates on RHS can't be handled statically. +// when any of the cases occurs: +// - it is possible to statically resolve all drivers, +// - all assignments that passed the static resolution have symmetric strengths (the same strength +// is related to both 0 and 1 values). +// +// It is possible to statically resolve all drivers when the strongest assignment has RHS marked as +// non-tristate. If the RHS is equal to z, that assignment has to be skipped. Since the value may +// be not known at verilation time, cases with tristates on RHS can't be handled statically. // // Static resolution is split into 2 parts. // First part can be done before tristate propagation. It is about removing assignments that are @@ -85,7 +89,26 @@ // - The assignment with non-tristate RHS with the greatest weaker strength has to be found. // - Then all not stronger assignments can be removed. // -// All assignments that are stronger than the strongest with non-tristate RHS are left as they are. +// All assignments that are stronger than the strongest with non-tristate RHS are then tried to be +// handled dynamically. Currently it is supported only on assignments with symmetric strengths. +// In this case, the exact value of the RHS doesn't matter. It only matters if it equals z or not. +// Such assignments are handled by changing the values to z of these bits that are overwritten by +// stronger assignments. Then all assignments can be aggregated as they would have equal strengths +// (by | on them and their __en expressions). To change the value to z, the RHS should be & with +// negation of __en expression of stronger assignments. Changing RHS's __en expression is not +// needed, because it will be then aggregated with __en expression of stronger assignments using |, +// so & with the negation can be safely skipped. +// So the values of overwritten bits are actually changed to 0, which doesn't affect stronger +// assignments, because | operation was used. +// +// Dynamic handling is implemented in the following way: +// - group the assignments by their strengths, +// - handle assignments of the same strength by aggregating values with | +// - assign results to var__strength and var__strength__en variables +// - aggregate the results: +// orp = orp | (var__strength & ~enp) +// enp = enp | var__strength__en, +// where orp is aggregated value and enp is aggregated __en value. // // There is a possible problem with equally strong assignments, because multiple assignments with // the same strength, but different values should result in x value, but these values are @@ -384,8 +407,15 @@ class TristateVisitor final : public TristateBaseVisitor { const VNUser5InUse m_inuser5; // TYPES - using RefVec = std::vector; - using VarMap = std::unordered_map; + struct RefStrength { + AstVarRef* m_varrefp; + VStrength m_strength; + RefStrength(AstVarRef* varrefp, VStrength strength) + : m_varrefp{varrefp} + , m_strength{strength} {} + }; + using RefStrengthVec = std::vector; + using VarMap = std::unordered_map; using Assigns = std::vector; using VarToAssignsMap = std::map; enum : uint8_t { @@ -403,6 +433,8 @@ class TristateVisitor final : public TristateBaseVisitor { VarToAssignsMap m_assigns; // Assigns in current module int m_unique = 0; bool m_alhs = false; // On LHS of assignment + VStrength m_currentStrength = VStrength::STRONG; // Current strength of assignment, + // Used only on LHS of assignment const AstNode* m_logicp = nullptr; // Current logic being built TristateGraph m_tgraph; // Logic graph @@ -485,11 +517,11 @@ class TristateVisitor final : public TristateBaseVisitor { const auto it = m_lhsmap.find(key); UINFO(9, " mapInsertLhsVarRef " << nodep << endl); if (it == m_lhsmap.end()) { // Not found - RefVec* const refsp = new RefVec; - refsp->push_back(nodep); + RefStrengthVec* const refsp = new RefStrengthVec; + refsp->push_back(RefStrength{nodep, m_currentStrength}); m_lhsmap.emplace(key, refsp); } else { - it->second->push_back(nodep); + it->second->push_back(RefStrength{nodep, m_currentStrength}); } } @@ -567,7 +599,7 @@ class TristateVisitor final : public TristateBaseVisitor { nextit = it; ++nextit; AstVar* const invarp = it->first; - const RefVec* const refsp = it->second; + RefStrengthVec* refsp = it->second; // Figure out if this var needs tristate expanded. if (m_tgraph.isTristate(invarp)) { insertTristatesSignal(nodep, invarp, refsp); @@ -580,8 +612,64 @@ class TristateVisitor final : public TristateBaseVisitor { } } - void insertTristatesSignal(AstNodeModule* nodep, AstVar* const invarp, - const RefVec* const refsp) { + void aggregateTriSameStrength(AstNodeModule* nodep, AstVar* const varp, AstVar* const envarp, + RefStrengthVec::iterator beginStrength, + RefStrengthVec::iterator endStrength) { + // For each driver seperate variables (normal and __en) are created and initialized with + // values. In case of normal variable, the original expression is reused. Their values are + // aggregated using | to form one expression, which are assigned to varp end envarp. + AstNode* orp = nullptr; + AstNode* enp = nullptr; + + for (auto it = beginStrength; it != endStrength; it++) { + AstVarRef* refp = it->m_varrefp; + const int w = varp->width(); + + // create the new lhs driver for this var + AstVar* const newLhsp = new AstVar{varp->fileline(), VVarType::MODULETEMP, + varp->name() + "__out" + cvtToStr(m_unique), + VFlagBitPacked{}, w}; // 2-state ok; sep enable + UINFO(9, " newout " << newLhsp << endl); + nodep->addStmtsp(newLhsp); + refp->varp(newLhsp); // assign the new var to the varref + refp->name(newLhsp->name()); + + // create a new var for this drivers enable signal + AstVar* const newEnLhsp = new AstVar{varp->fileline(), VVarType::MODULETEMP, + varp->name() + "__en" + cvtToStr(m_unique++), + VFlagBitPacked{}, w}; // 2-state ok + UINFO(9, " newenlhsp " << newEnLhsp << endl); + nodep->addStmtsp(newEnLhsp); + + AstNode* const enLhspAssignp = new AstAssignW{ + refp->fileline(), new AstVarRef{refp->fileline(), newEnLhsp, VAccess::WRITE}, + getEnp(refp)}; + UINFO(9, " newenlhspAssignp " << enLhspAssignp << endl); + nodep->addStmtsp(enLhspAssignp); + + // now append this driver to the driver logic. + AstNode* const ref1p = new AstVarRef{refp->fileline(), newLhsp, VAccess::READ}; + AstNode* const ref2p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ}; + AstNode* const andp = new AstAnd{refp->fileline(), ref1p, ref2p}; + + // or this to the others + orp = (!orp) ? andp : new AstOr{refp->fileline(), orp, andp}; + + AstNode* const ref3p = new AstVarRef{refp->fileline(), newEnLhsp, VAccess::READ}; + enp = (!enp) ? ref3p : new AstOr{ref3p->fileline(), enp, ref3p}; + } + AstNode* const assp = new AstAssignW{ + varp->fileline(), new AstVarRef{varp->fileline(), varp, VAccess::WRITE}, orp}; + UINFO(9, " newassp " << assp << endl); + nodep->addStmtsp(assp); + + AstNode* const enAssp = new AstAssignW{ + envarp->fileline(), new AstVarRef{envarp->fileline(), envarp, VAccess::WRITE}, enp}; + UINFO(9, " newenassp " << enAssp << endl); + nodep->addStmtsp(enAssp); + } + + void insertTristatesSignal(AstNodeModule* nodep, AstVar* const invarp, RefStrengthVec* refsp) { UINFO(8, " TRISTATE EXPANDING:" << invarp << endl); ++m_statTriSigs; m_tgraph.didProcess(invarp); @@ -615,76 +703,103 @@ class TristateVisitor final : public TristateBaseVisitor { AstNode* orp = nullptr; AstNode* enp = nullptr; - AstNode* undrivenp = nullptr; + const int w = lhsp->width(); - // loop through the lhs drivers to build the driver resolution logic - for (auto refp : *refsp) { - const int w = lhsp->width(); + std::sort(refsp->begin(), refsp->end(), + [](RefStrength a, RefStrength b) { return a.m_strength > b.m_strength; }); - // create the new lhs driver for this var - AstVar* const newlhsp = new AstVar(lhsp->fileline(), VVarType::MODULETEMP, - lhsp->name() + "__out" + cvtToStr(m_unique), - VFlagBitPacked(), w); // 2-state ok; sep enable - UINFO(9, " newout " << newlhsp << endl); - nodep->addStmtsp(newlhsp); - refp->varp(newlhsp); // assign the new var to the varref - refp->name(newlhsp->name()); + auto beginStrength = refsp->begin(); + while (beginStrength != refsp->end()) { + auto endStrength = beginStrength + 1; + while (endStrength != refsp->end() + && endStrength->m_strength == beginStrength->m_strength) + endStrength++; - // create a new var for this drivers enable signal - AstVar* const newenp = new AstVar(lhsp->fileline(), VVarType::MODULETEMP, - lhsp->name() + "__en" + cvtToStr(m_unique++), - VFlagBitPacked(), w); // 2-state ok - UINFO(9, " newenp " << newenp << endl); - nodep->addStmtsp(newenp); + FileLine* const fl = beginStrength->m_varrefp->fileline(); + const string strengthVarName = lhsp->name() + "__" + beginStrength->m_strength.ascii(); - AstNode* const enassp = new AstAssignW( - refp->fileline(), new AstVarRef(refp->fileline(), newenp, VAccess::WRITE), - getEnp(refp)); - UINFO(9, " newass " << enassp << endl); - nodep->addStmtsp(enassp); + // var__strength variable + AstVar* varStrengthp = new AstVar{fl, VVarType::MODULETEMP, strengthVarName, + VFlagBitPacked{}, w}; // 2-state ok; sep enable; + UINFO(9, " newstrength " << varStrengthp << endl); + nodep->addStmtsp(varStrengthp); - // now append this driver to the driver logic. - AstNode* const ref1p = new AstVarRef(refp->fileline(), newlhsp, VAccess::READ); - AstNode* const ref2p = new AstVarRef(refp->fileline(), newenp, VAccess::READ); - AstNode* const andp = new AstAnd(refp->fileline(), ref1p, ref2p); + // var__strength__en variable + AstVar* enVarStrengthp = new AstVar{fl, VVarType::MODULETEMP, strengthVarName + "__en", + VFlagBitPacked{}, w}; // 2-state ok; + UINFO(9, " newenstrength " << enVarStrengthp << endl); + nodep->addStmtsp(enVarStrengthp); - // or this to the others - orp = (!orp) ? andp : new AstOr(refp->fileline(), orp, andp); + aggregateTriSameStrength(nodep, varStrengthp, enVarStrengthp, beginStrength, + endStrength); - if (envarp) { - AstNode* const ref3p = new AstVarRef(refp->fileline(), newenp, VAccess::READ); - enp = (!enp) ? ref3p : new AstOr(ref3p->fileline(), enp, ref3p); + AstNode* exprCurrentStrengthp; + if (enp) { + // If weaker driver should be overwritten by a stronger, replace its value with z + exprCurrentStrengthp + = new AstAnd{fl, new AstVarRef{fl, varStrengthp, VAccess::READ}, + new AstNot{fl, enp->cloneTree(false)}}; + } else { + exprCurrentStrengthp = new AstVarRef{fl, varStrengthp, VAccess::READ}; } - AstNode* const tmp = new AstNot( - newenp->fileline(), new AstVarRef(newenp->fileline(), newenp, VAccess::READ)); - undrivenp = ((!undrivenp) ? tmp : new AstAnd(refp->fileline(), tmp, undrivenp)); - } - if (!undrivenp) { // No drivers on the bus - undrivenp = newAllZerosOrOnes(invarp, true); + orp = (!orp) ? exprCurrentStrengthp : new AstOr{fl, orp, exprCurrentStrengthp}; + + AstNode* enVarStrengthRefp = new AstVarRef{fl, enVarStrengthp, VAccess::READ}; + + enp = (!enp) ? enVarStrengthRefp : new AstOr{fl, enp, enVarStrengthRefp}; + + beginStrength = endStrength; } + if (!outvarp) { // This is the final pre-forced resolution of the tristate, so we apply // the pull direction to any undriven pins. const AstPull* const pullp = static_cast(lhsp->user3p()); bool pull1 = pullp && pullp->direction() == 1; // Else default is down + + AstNode* undrivenp; + if (envarp) { + undrivenp = new AstNot{envarp->fileline(), + new AstVarRef{envarp->fileline(), envarp, VAccess::READ}}; + } else { + if (enp) { + undrivenp = new AstNot{enp->fileline(), enp}; + } else { + undrivenp = newAllZerosOrOnes(invarp, true); + } + } + undrivenp = new AstAnd{invarp->fileline(), undrivenp, newAllZerosOrOnes(invarp, pull1)}; - orp = new AstOr(invarp->fileline(), orp, undrivenp); - } else { - VL_DO_DANGLING(undrivenp->deleteTree(), undrivenp); + orp = new AstOr{invarp->fileline(), orp, undrivenp}; } + if (envarp) { - nodep->addStmtsp(new AstAssignW( - enp->fileline(), new AstVarRef(envarp->fileline(), envarp, VAccess::WRITE), enp)); + AstAssignW* const enAssp = new AstAssignW{ + enp->fileline(), new AstVarRef{envarp->fileline(), envarp, VAccess::WRITE}, enp}; + if (debug() >= 9) enAssp->dumpTree(cout, "enAssp: "); + nodep->addStmtsp(enAssp); } + // __out (child) or (parent) = drive-value expression - AstNode* const assp = new AstAssignW( - lhsp->fileline(), new AstVarRef(lhsp->fileline(), lhsp, VAccess::WRITE), orp); + AstNode* const assp = new AstAssignW{ + lhsp->fileline(), new AstVarRef{lhsp->fileline(), lhsp, VAccess::WRITE}, orp}; assp->user2(U2_BOTH); // Don't process further; already resolved if (debug() >= 9) assp->dumpTree(cout, "-lhsp-eqn: "); nodep->addStmtsp(assp); } + bool isOnlyAssignmentIsToLhsVar(AstAssignW* const nodep) { + if (AstVarRef* const varRefp = VN_CAST(nodep->lhsp(), VarRef)) { + auto foundIt = m_assigns.find(varRefp->varp()); + if (foundIt != m_assigns.end()) { + auto const& assignsToVar = foundIt->second; + if (assignsToVar.size() == 1 && assignsToVar[0] == nodep) return true; + } + } + return false; + } + void addToAssignmentList(AstAssignW* nodep) { if (AstVarRef* const varRefp = VN_CAST(nodep->lhsp(), VarRef)) { if (varRefp->varp()->isNet()) { @@ -1109,7 +1224,26 @@ class TristateVisitor final : public TristateBaseVisitor { m_tgraph.didProcess(nodep); } m_alhs = true; // And user1p() will indicate tristate equation, if any + if (AstAssignW* const assignWp = VN_CAST(nodep, AssignW)) { + if (AstStrengthSpec* const specp = assignWp->strengthSpecp()) { + if (specp->strength0() != specp->strength1()) { + // Unequal strengths are not a problem if the assignment is the only + // assignment to its variable. Unfortunately, m_assigns map stores only + // assignments to var. Selects are not inserted, so they may be handled + // improperly + if (!isOnlyAssignmentIsToLhsVar(assignWp)) { + assignWp->v3warn( + E_UNSUPPORTED, + "Unsupported: Unable to resolve unequal strength specifier"); + } + } else { + m_currentStrength = specp->strength0(); + } + } + } iterateAndNextNull(nodep->lhsp()); + // back to default strength + m_currentStrength = VStrength::STRONG; m_alhs = false; } } diff --git a/test_regress/t/t_strength_2_uneq_assign.out b/test_regress/t/t_strength_2_uneq_assign.out new file mode 100644 index 000000000..4235b8fb3 --- /dev/null +++ b/test_regress/t/t_strength_2_uneq_assign.out @@ -0,0 +1,10 @@ +%Error-UNSUPPORTED: t/t_strength_2_uneq_assign.v:10:30: Unsupported: Unable to resolve unequal strength specifier + : ... In instance t + 10 | assign (weak0, strong1) a = clk ? 'z : '0; + | ^ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_strength_2_uneq_assign.v:11:30: Unsupported: Unable to resolve unequal strength specifier + : ... In instance t + 11 | assign (strong0, pull1) a = 6'b110001; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_strength_2_uneq_assign.pl b/test_regress/t/t_strength_2_uneq_assign.pl new file mode 100755 index 000000000..19ba90d40 --- /dev/null +++ b/test_regress/t/t_strength_2_uneq_assign.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_2_uneq_assign.v b/test_regress/t/t_strength_2_uneq_assign.v new file mode 100644 index 000000000..2c92a21b1 --- /dev/null +++ b/test_regress/t/t_strength_2_uneq_assign.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (clk); + input clk; + wire [5:0] a; + assign (weak0, strong1) a = clk ? 'z : '0; + assign (strong0, pull1) a = 6'b110001; + initial begin + if (a === 6'b110001) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_strength_equal_strength.pl b/test_regress/t/t_strength_equal_strength.pl new file mode 100755 index 000000000..f5e338520 --- /dev/null +++ b/test_regress/t/t_strength_equal_strength.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2022 by Antmicro Ltd. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_strength_equal_strength.v b/test_regress/t/t_strength_equal_strength.v new file mode 100644 index 000000000..fbbe8bdf1 --- /dev/null +++ b/test_regress/t/t_strength_equal_strength.v @@ -0,0 +1,48 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +interface inter (input logic cond, output wire a); + parameter W; + // Example: + wire (weak0, weak1) [W-1:0] b = '1; + assign (strong0, strong1) b = cond ? 'b0 : 'bz; + + assign a = b[10]; + +endinterface + +module t (clk1, clk2); + input wire clk1; + input wire clk2; + + wire (weak0, weak1) a = 0; + assign (supply0, supply1) a = 1'bz; + assign (pull0, pull1) a = 1; + + wire [2:0] b; + assign b = 3'b101; + assign (supply0, supply1) b = 3'b01z; + + wire c; + and (weak0, weak1) (c, clk1, clk2); + assign (strong0, strong1) c = 'z; + assign (pull0, pull1) c = 0; + + wire d; + inter #(.W(32)) i(.cond(1'b1), .a(d)); + + always begin + if (a === 1 && b === 3'b011 && c === 0 && d === 0) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else begin + $write("Error: a = %b, b = %b, c = %b, d = %b", a, b, c, d); + $write("expected: a = %b, b = %b, c = %b, d = %b\n", clk1, 3'b011, 0, 0); + $stop; + end + end +endmodule From 1b18eee5dc6d785b63627818d90646c18ceae9f5 Mon Sep 17 00:00:00 2001 From: Jake Merdich Date: Tue, 27 Sep 2022 09:11:49 -0400 Subject: [PATCH 68/75] Tests: Fix CCache test not properly skipped (#3643) If the skip condition happens, the rest still runs and it fails. Don't do that. --- docs/CONTRIBUTORS | 1 + test_regress/t/t_ccache_report.pl | 55 ++++++++++++++++--------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 7a5f72934..0c3be357f 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -44,6 +44,7 @@ HyungKi Jeong Iru Cai Ivan Vnučec Iztok Jeras +Jake Merdich James Hanlon James Hutchinson James Pallister diff --git a/test_regress/t/t_ccache_report.pl b/test_regress/t/t_ccache_report.pl index a17c2b02e..790bbf9f0 100755 --- a/test_regress/t/t_ccache_report.pl +++ b/test_regress/t/t_ccache_report.pl @@ -13,36 +13,37 @@ scenarios(vlt => 1); if (!$Self->cfg_with_ccache) { skip("Requires configuring with ccache"); } +else { + top_filename("t_a1_first_cc.v"); -top_filename("t_a1_first_cc.v"); + # This test requires rebuilding the object files to check the ccache log + foreach my $filename (glob("$Self->{obj_dir}/*.o")) { + print "rm $filename\n" if $Self->{verbose}; + unlink $filename; + } -# This test requires rebuilding the object files to check the ccache log -foreach my $filename (glob("$Self->{obj_dir}/*.o")) { - print "rm $filename\n" if $Self->{verbose}; - unlink $filename; + compile( + verilator_flags2 => ['--trace'], + make_flags => "ccache-report" + ); + + my $report = "$Self->{obj_dir}/$Self->{VM_PREFIX}__ccache_report.txt"; + + # We do not actually want to make this test depend on whether the file was + # cached or not, so trim the report to ignore actual caching behaviour + run(cmd => ["sed", "-i", "-e", "'s/ : .*/ : IGNORED/; /|/s/.*/IGNORED/;'", $report]); + files_identical($report, "t/$Self->{name}__ccache_report_initial.out"); + + # Now rebuild again (should be all up to date) + run( + logfile => "$Self->{obj_dir}/rebuild.log", + cmd => ["make", "-C", $Self->{obj_dir}, + "-f", "$Self->{VM_PREFIX}.mk", + $Self->{VM_PREFIX}, "ccache-report"] + ); + + files_identical($report, "t/$Self->{name}__ccache_report_rebuild.out"); } -compile( - verilator_flags2 => ['--trace'], - make_flags => "ccache-report" - ); - -my $report = "$Self->{obj_dir}/$Self->{VM_PREFIX}__ccache_report.txt"; - -# We do not actually want to make this test depend on whether the file was -# cached or not, so trim the report to ignore actual caching behaviour -run(cmd => ["sed", "-i", "-e", "'s/ : .*/ : IGNORED/; /|/s/.*/IGNORED/;'", $report]); -files_identical($report, "t/$Self->{name}__ccache_report_initial.out"); - -# Now rebuild again (should be all up to date) -run( - logfile => "$Self->{obj_dir}/rebuild.log", - cmd => ["make", "-C", $Self->{obj_dir}, - "-f", "$Self->{VM_PREFIX}.mk", - $Self->{VM_PREFIX}, "ccache-report"] - ); - -files_identical($report, "t/$Self->{name}__ccache_report_rebuild.out"); - ok(1); 1; From 1b1907af4995ee5ac0212fc66ccccf72ed4b47c3 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 27 Sep 2022 18:42:03 -0400 Subject: [PATCH 69/75] Tests: Rename some tests --- .../t/{t_write_format_bug.out => t_display_concat2.out} | 0 .../t/{t_write_format_bug.pl => t_display_concat2.pl} | 0 .../t/{t_write_format_bug.v => t_display_concat2.v} | 0 test_regress/t/{t_void_queue_ops.pl => t_queue_void_ops.pl} | 0 test_regress/t/{t_void_queue_ops.v => t_queue_void_ops.v} | 6 ++++++ 5 files changed, 6 insertions(+) rename test_regress/t/{t_write_format_bug.out => t_display_concat2.out} (100%) rename test_regress/t/{t_write_format_bug.pl => t_display_concat2.pl} (100%) rename test_regress/t/{t_write_format_bug.v => t_display_concat2.v} (100%) rename test_regress/t/{t_void_queue_ops.pl => t_queue_void_ops.pl} (100%) rename test_regress/t/{t_void_queue_ops.v => t_queue_void_ops.v} (96%) diff --git a/test_regress/t/t_write_format_bug.out b/test_regress/t/t_display_concat2.out similarity index 100% rename from test_regress/t/t_write_format_bug.out rename to test_regress/t/t_display_concat2.out diff --git a/test_regress/t/t_write_format_bug.pl b/test_regress/t/t_display_concat2.pl similarity index 100% rename from test_regress/t/t_write_format_bug.pl rename to test_regress/t/t_display_concat2.pl diff --git a/test_regress/t/t_write_format_bug.v b/test_regress/t/t_display_concat2.v similarity index 100% rename from test_regress/t/t_write_format_bug.v rename to test_regress/t/t_display_concat2.v diff --git a/test_regress/t/t_void_queue_ops.pl b/test_regress/t/t_queue_void_ops.pl similarity index 100% rename from test_regress/t/t_void_queue_ops.pl rename to test_regress/t/t_queue_void_ops.pl diff --git a/test_regress/t/t_void_queue_ops.v b/test_regress/t/t_queue_void_ops.v similarity index 96% rename from test_regress/t/t_void_queue_ops.v rename to test_regress/t/t_queue_void_ops.v index f618cb876..b3363177c 100644 --- a/test_regress/t/t_void_queue_ops.v +++ b/test_regress/t/t_queue_void_ops.v @@ -1,3 +1,9 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + module t (/*AUTOARG*/ // Inputs From 75a70bee6d98a5f9407d6aea9dcd6c94f20c9a66 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 27 Sep 2022 21:47:45 -0400 Subject: [PATCH 70/75] Update to clang-format-14 on Ubuntu22.04 --- .github/workflows/format.yml | 10 +++++----- Makefile.in | 6 +++--- docs/guide/conf.py | 1 + docs/guide/install.rst | 2 +- examples/xml_py/vl_file_copy | 9 +++++---- examples/xml_py/vl_hier_graph | 9 +++++---- include/verilated_vpi.cpp | 2 +- src/astgen | 2 ++ src/verilog.l | 2 +- src/verilog.y | 4 ++-- test_regress/t/t_trace_two_sc.cpp | 1 + 11 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 1b6662ea0..2b903aa88 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -10,11 +10,11 @@ on: jobs: format: - runs-on: ubuntu-20.04 - name: Ubuntu 20.04 | format + runs-on: ubuntu-22.04 + name: Ubuntu 22.04 | format env: CI_OS_NAME: linux - CI_RUNS_ON: ubuntu-20.04 + CI_RUNS_ON: ubuntu-22.04 CI_COMMIT: ${{ github.sha }} CI_M32: 0 steps: @@ -27,14 +27,14 @@ jobs: CI_BUILD_STAGE_NAME: build run: | bash ci/ci-install.bash && - sudo apt-get install clang-format-11 yapf3 && + sudo apt-get install clang-format-14 yapf3 && git config --global user.email "action@example.com" && git config --global user.name "github action" - name: Format code run: | autoconf && ./configure && - make -j 2 format CLANGFORMAT=clang-format-11 && + make -j 2 format CLANGFORMAT=clang-format-14 && git status - name: Push run: | diff --git a/Makefile.in b/Makefile.in index 08271b047..662a57361 100644 --- a/Makefile.in +++ b/Makefile.in @@ -346,13 +346,13 @@ analyzer-include: format: clang-format yapf format-pl-exec -CLANGFORMAT = clang-format-11 +CLANGFORMAT = clang-format-14 CLANGFORMAT_FLAGS = -i CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* test_regress/t/*.h clang-format: - @$(CLANGFORMAT) --version | egrep 11.0 > /dev/null \ - || echo "*** You are not using clang-format 11.0, indents may differ from master's ***" + @$(CLANGFORMAT) --version | egrep 14.0 > /dev/null \ + || echo "*** You are not using clang-format-14, indents may differ from master's ***" $(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES) PY_PROGRAMS = \ diff --git a/docs/guide/conf.py b/docs/guide/conf.py index 0714e50c7..fb9c66d1a 100644 --- a/docs/guide/conf.py +++ b/docs/guide/conf.py @@ -13,6 +13,7 @@ from datetime import datetime import os import re import sys + sys.path.insert(0, os.path.abspath('./_ext')) import sphinx_rtd_theme # pylint: disable=wrong-import-position, diff --git a/docs/guide/install.rst b/docs/guide/install.rst index b69517076..31d553094 100644 --- a/docs/guide/install.rst +++ b/docs/guide/install.rst @@ -124,7 +124,7 @@ Those developing Verilator itself may also want these (see internals.rst): :: - sudo apt-get install gdb graphviz cmake clang clang-format-11 gprof lcov + sudo apt-get install gdb graphviz cmake clang clang-format-14 gprof lcov sudo apt-get install yapf3 sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe cpan install Pod::Perldoc diff --git a/examples/xml_py/vl_file_copy b/examples/xml_py/vl_file_copy index 5eae927ed..1ff96328e 100755 --- a/examples/xml_py/vl_file_copy +++ b/examples/xml_py/vl_file_copy @@ -16,12 +16,13 @@ from shutil import copy2 class VlFileCopy: + def __init__( - self, - verilator_args, # presently all verilator options are passed-thru - # ideally this script would check against options mentioned in help + self, + verilator_args, # presently all verilator options are passed-thru + # ideally this script would check against options mentioned in help debug=0, - output_dir='copied'): # directory name we output file uses + output_dir='copied'): # directory name we output file uses self.debug = debug diff --git a/examples/xml_py/vl_hier_graph b/examples/xml_py/vl_hier_graph index 359bd5da2..566250226 100755 --- a/examples/xml_py/vl_hier_graph +++ b/examples/xml_py/vl_hier_graph @@ -14,12 +14,13 @@ import xml.etree.ElementTree as ET class VlHierGraph: + def __init__( - self, - verilator_args, # presently all verilator options are passed-thru - # ideally this script would check against options mentioned in help + self, + verilator_args, # presently all verilator options are passed-thru + # ideally this script would check against options mentioned in help debug=0, - output_filename='graph.dot'): # output filename + output_filename='graph.dot'): # output filename self.debug = debug self.next_vertex_number = 0 self.name_to_number = {} diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index be58390ed..56f7d5e42 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -96,7 +96,7 @@ public: *(reinterpret_cast(newp)) = activeMagic(); return newp + 8; } - static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE { + static void operator delete(void* obj, size_t /*size*/) VL_MT_SAFE { uint8_t* const oldp = (static_cast(obj)) - 8; if (VL_UNLIKELY(*(reinterpret_cast(oldp)) != activeMagic())) { VL_FATAL_MT(__FILE__, __LINE__, "", diff --git a/src/astgen b/src/astgen index c1d571ecd..dbe6968e0 100755 --- a/src/astgen +++ b/src/astgen @@ -12,6 +12,7 @@ import textwrap class Node: + def __init__(self, name, superClass, file, lineno): self._name = name self._superClass = superClass @@ -180,6 +181,7 @@ Stages = {} class Cpt: + def __init__(self): self.did_out_tree = False self.in_filename = "" diff --git a/src/verilog.l b/src/verilog.l index 46f612ef4..38adcdc84 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -24,8 +24,8 @@ // clang-format on #include "V3Number.h" -#include "V3ParseImp.h" // Defines YYTYPE; before including bison header #include "V3ParseBison.h" // Generated by bison +#include "V3ParseImp.h" // Defines YYTYPE; before including bison header #define STATE_VERILOG_RECENT S17 // State name for most recent Verilog Version diff --git a/src/verilog.y b/src/verilog.y index c2b17e25c..674f2a3a2 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -23,12 +23,12 @@ #endif // clang-format on #include "V3Ast.h" -#include "V3Global.h" #include "V3Config.h" +#include "V3Global.h" #include "V3ParseImp.h" // Defines YYTYPE; before including bison header -#include #include +#include #include #define YYERROR_VERBOSE 1 // For prior to Bison 3.6 diff --git a/test_regress/t/t_trace_two_sc.cpp b/test_regress/t/t_trace_two_sc.cpp index 118a2d0a1..99f111fe4 100644 --- a/test_regress/t/t_trace_two_sc.cpp +++ b/test_regress/t/t_trace_two_sc.cpp @@ -21,6 +21,7 @@ // General headers #include "verilated.h" + #include "systemc.h" VM_PREFIX* ap; From a999c73ce080c08461d994897c06bd1d7a4bd890 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Wed, 28 Sep 2022 14:41:26 +0100 Subject: [PATCH 71/75] Commentary --- src/V3GraphAlg.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index 0e5042b5a..b74de1351 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -178,7 +178,10 @@ private: std::vector m_callTrace; // List of everything we hit processing so far void main() { - // Use Tarjan's algorithm to find the strongly connected subgraphs. + // Use Pearce's algorithm to color the strongly connected components. For reference see + // "An Improved Algorithm for Finding the Strongly Connected Components of a Directed + // Graph", David J.Pearce, 2005 + // // Node State: // Vertex::user // DFS number indicating possible root of subtree, 0=not iterated // Vertex::color // Output subtree number (fully processed) From f25a9a4c8067a3291c6268a4be7b0acd461d166d Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 28 Sep 2022 19:11:00 -0400 Subject: [PATCH 72/75] examples: Use SC_ZERO_TIME in tracing (#3646) --- examples/make_tracing_sc/sc_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/make_tracing_sc/sc_main.cpp b/examples/make_tracing_sc/sc_main.cpp index 3d3cb1392..a23040a54 100644 --- a/examples/make_tracing_sc/sc_main.cpp +++ b/examples/make_tracing_sc/sc_main.cpp @@ -82,7 +82,7 @@ int sc_main(int argc, char* argv[]) { // You must do one evaluation before enabling waves, in order to allow // SystemC to interconnect everything for testing. - sc_start(1, SC_NS); + sc_start(SC_ZERO_TIME); #if VM_TRACE // If verilator was invoked with --trace argument, From fa4b10b4d9a4513fb8914c5c7af5b6f917b29878 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 30 Sep 2022 23:03:26 -0400 Subject: [PATCH 73/75] Commentary: Changes update --- Changes | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index ed4497f7f..b793b69cb 100644 --- a/Changes +++ b/Changes @@ -19,14 +19,18 @@ Verilator 4.227 devel **Minor:** -* Support IEEE constant signal strengths (#3601). [Ryszard Rozak/Antmicro] +* Support some IEEE signal strengths (#3601) (#3629). [Ryszard Rozak/Antmicro] * Add --main to generate main() C++ (previously was experimental only). +* Add --build-jobs, and rework arguments for -j (#3623). [Kamil Rakoczy] * Rename --bin to --build-dep-bin. +* Rename debug flags --dumpi-tree, --dumpi-graph, etc. [Geza Lore] * Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic] * Fix crash in gate optimization of circular logic (#3543). [Bill Flynn] * Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk] * Fix default --mod-prefix when --prefix is repeated (#3603). [Geza Lore] +* Fix calling trace() after open() segfault (#3610) (#3627). [Yu-Sheng Lin] * Fix typedef'ed class conversion to boolean (#3616). [Aleksander Kiryk] +* Fix Verilation speed when disabled warnings (#3632). [Kamil Rakoczy/Antmicro] Verilator 4.226 2022-08-31 @@ -41,6 +45,7 @@ Verilator 4.226 2022-08-31 * Support $test$plusargs(expr) (#3489). * Rename trace rolloverSize() (#3570). * Improve Verilation speed with --threads on large designs. [Geza Lore] +* Improve Verilation memory by reducing V3Number (#3521). [Mariusz Glebocki/Antmicro] * Fix struct pattern assignment (#2328) (#3517). [Mostafa Gamal] * Fix public combo propagation issues (#2905). [Todd Strader] * Fix incorrect tristate logic (#3399) [shareefj, Vighnesh Iyer] From 5ed882faf2d12535853f17922e7220f5c1368eb2 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 30 Sep 2022 23:41:35 -0400 Subject: [PATCH 74/75] Fix unused compiler warning when not VL_THREADED. --- include/verilated_trace_imp.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/verilated_trace_imp.h b/include/verilated_trace_imp.h index 0663986f1..90dcc2e70 100644 --- a/include/verilated_trace_imp.h +++ b/include/verilated_trace_imp.h @@ -551,15 +551,15 @@ template <> void VerilatedTrace::runOffloadedCallbacks( const std::vector& cbVec) { // Fall back on sequential execution - for (const CallbackRecord& cbr : cbVec) { #ifdef VL_THREADED + for (const CallbackRecord& cbr : cbVec) { Buffer* traceBufferp = getTraceBuffer(); cbr.m_dumpOffloadCb(cbr.m_userp, static_cast(traceBufferp)); commitTraceBuffer(traceBufferp); -#else - VL_FATAL_MT(__FILE__, __LINE__, "", "Unreachable"); -#endif } +#else + if (!cbVec.empty()) VL_FATAL_MT(__FILE__, __LINE__, "", "Unreachable"); +#endif } template <> @@ -586,7 +586,9 @@ void VerilatedTrace::dump(uint64_t timeui) VL_MT_SAFE_EXCLUD if (!preChangeDump()) return; } +#ifdef VL_THREADED uint32_t* bufferp = nullptr; +#endif if (offload()) { #ifdef VL_THREADED // Currently only incremental dumps run on the worker thread From 746c7ea8f786e1183f15c28727cbc0c44e9b556e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 1 Oct 2022 08:28:27 -0400 Subject: [PATCH 75/75] Version bump --- Changes | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index b793b69cb..06ce093d1 100644 --- a/Changes +++ b/Changes @@ -8,7 +8,7 @@ The changes in each Verilator version are described below. The contributors that suggested a given feature are shown in []. Thanks! -Verilator 4.227 devel +Verilator 4.228 2022-10-01 ========================== **Announcement:** diff --git a/configure.ac b/configure.ac index 7caacbd45..35b3fcd01 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,7 @@ # Then 'make maintainer-dist' #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[4.227 devel], +AC_INIT([Verilator],[4.228 2022-10-01], [https://verilator.org], [verilator],[https://verilator.org])