Internals: Add new VL_RESTORER flavours
Restrict VL_RESTORER to be usable only with trivially copyable types. Introduce VL_RESTORER_COPY and VL_RESTORER_CLEAR, which are more efficient versions usable for non trivially copyable types. VL_RESTORER_COPY semantically behaves the same as VL_RESTORER, but only does one copy at initialization, and on scope exit restores via a move. VL_RESTORER_CLEAR swaps the variable with an new one constructed via the no-args constructor (e.g. empty collection), which does not require any copying at any point. Static assertions enforce picking one of the new flavours when copying might be expensive.
This commit is contained in:
parent
f82f59a024
commit
bbee65ed4b
|
|
@ -1153,12 +1153,11 @@ class AssertVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_modPastNum);
|
VL_RESTORER(m_modPastNum);
|
||||||
VL_RESTORER(m_modStrobeNum);
|
VL_RESTORER(m_modStrobeNum);
|
||||||
VL_RESTORER(m_modExpr2Sen2DelayedAlwaysp);
|
|
||||||
VL_RESTORER(m_finalp);
|
VL_RESTORER(m_finalp);
|
||||||
|
VL_RESTORER_CLEAR(m_modExpr2Sen2DelayedAlwaysp);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_modPastNum = 0;
|
m_modPastNum = 0;
|
||||||
m_modStrobeNum = 0;
|
m_modStrobeNum = 0;
|
||||||
m_modExpr2Sen2DelayedAlwaysp.clear();
|
|
||||||
m_finalp = nullptr;
|
m_finalp = nullptr;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,12 +137,9 @@ class BeginVisitor final : public VNVisitor {
|
||||||
UINFO(8, " rename to " << nodep->name());
|
UINFO(8, " rename to " << nodep->name());
|
||||||
m_statep->userMarkChanged(nodep);
|
m_statep->userMarkChanged(nodep);
|
||||||
}
|
}
|
||||||
VL_RESTORER(m_displayScope);
|
VL_RESTORER_CLEAR(m_displayScope);
|
||||||
VL_RESTORER(m_namedScope);
|
VL_RESTORER_CLEAR(m_namedScope);
|
||||||
VL_RESTORER(m_unnamedScope);
|
VL_RESTORER_CLEAR(m_unnamedScope);
|
||||||
m_displayScope = "";
|
|
||||||
m_namedScope = "";
|
|
||||||
m_unnamedScope = "";
|
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeProcedure* nodep) override {
|
void visit(AstNodeProcedure* nodep) override {
|
||||||
|
|
@ -163,14 +160,13 @@ class BeginVisitor final : public VNVisitor {
|
||||||
// naming; so that any begin's inside the function will rename
|
// naming; so that any begin's inside the function will rename
|
||||||
// inside the function.
|
// inside the function.
|
||||||
// Process children
|
// Process children
|
||||||
VL_RESTORER(m_displayScope);
|
VL_RESTORER_COPY(m_displayScope);
|
||||||
VL_RESTORER(m_ftaskp);
|
VL_RESTORER(m_ftaskp);
|
||||||
VL_RESTORER(m_liftedp);
|
VL_RESTORER(m_liftedp);
|
||||||
VL_RESTORER(m_namedScope);
|
VL_RESTORER_CLEAR(m_namedScope);
|
||||||
VL_RESTORER(m_unnamedScope);
|
VL_RESTORER_CLEAR(m_unnamedScope);
|
||||||
m_displayScope = dot(m_displayScope, nodep->name());
|
m_displayScope = dot(m_displayScope, nodep->name());
|
||||||
m_namedScope = "";
|
|
||||||
m_unnamedScope = "";
|
|
||||||
m_ftaskp = nodep;
|
m_ftaskp = nodep;
|
||||||
m_liftedp = nullptr;
|
m_liftedp = nullptr;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
@ -191,9 +187,9 @@ class BeginVisitor final : public VNVisitor {
|
||||||
void visit(AstGenBlock* nodep) override {
|
void visit(AstGenBlock* nodep) override {
|
||||||
// GenBlocks were only useful in variable creation, change names and delete
|
// GenBlocks were only useful in variable creation, change names and delete
|
||||||
UINFO(8, " " << nodep);
|
UINFO(8, " " << nodep);
|
||||||
VL_RESTORER(m_displayScope);
|
VL_RESTORER_COPY(m_displayScope);
|
||||||
VL_RESTORER(m_namedScope);
|
VL_RESTORER_COPY(m_namedScope);
|
||||||
VL_RESTORER(m_unnamedScope);
|
VL_RESTORER_COPY(m_unnamedScope);
|
||||||
UASSERT_OBJ(!m_keepBegins, nodep, "Should be able to eliminate all AstGenBlock");
|
UASSERT_OBJ(!m_keepBegins, nodep, "Should be able to eliminate all AstGenBlock");
|
||||||
dotNames(nodep->name(), nodep->fileline(), "__BEGIN__");
|
dotNames(nodep->name(), nodep->fileline(), "__BEGIN__");
|
||||||
iterateAndNextNull(nodep->itemsp());
|
iterateAndNextNull(nodep->itemsp());
|
||||||
|
|
@ -227,9 +223,9 @@ class BeginVisitor final : public VNVisitor {
|
||||||
void visit(AstBegin* nodep) override {
|
void visit(AstBegin* nodep) override {
|
||||||
// Begin blocks were only useful in variable creation, change names and delete
|
// Begin blocks were only useful in variable creation, change names and delete
|
||||||
UINFO(8, " " << nodep);
|
UINFO(8, " " << nodep);
|
||||||
VL_RESTORER(m_displayScope);
|
VL_RESTORER_COPY(m_displayScope);
|
||||||
VL_RESTORER(m_namedScope);
|
VL_RESTORER_COPY(m_namedScope);
|
||||||
VL_RESTORER(m_unnamedScope);
|
VL_RESTORER_COPY(m_unnamedScope);
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_keepBegins);
|
VL_RESTORER(m_keepBegins);
|
||||||
m_keepBegins = false;
|
m_keepBegins = false;
|
||||||
|
|
@ -261,9 +257,9 @@ class BeginVisitor final : public VNVisitor {
|
||||||
void visit(AstNodeBlock* nodep) override {
|
void visit(AstNodeBlock* nodep) override {
|
||||||
// Begin/Fork blocks were only useful in variable creation, change names and delete
|
// Begin/Fork blocks were only useful in variable creation, change names and delete
|
||||||
UINFO(8, " " << nodep);
|
UINFO(8, " " << nodep);
|
||||||
VL_RESTORER(m_displayScope);
|
VL_RESTORER_COPY(m_displayScope);
|
||||||
VL_RESTORER(m_namedScope);
|
VL_RESTORER_COPY(m_namedScope);
|
||||||
VL_RESTORER(m_unnamedScope);
|
VL_RESTORER_COPY(m_unnamedScope);
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_keepBegins);
|
VL_RESTORER(m_keepBegins);
|
||||||
m_keepBegins = VN_IS(nodep, Fork);
|
m_keepBegins = VN_IS(nodep, Fork);
|
||||||
|
|
|
||||||
|
|
@ -252,18 +252,15 @@ private:
|
||||||
void visit(AstScope* nodep) override {
|
void visit(AstScope* nodep) override {
|
||||||
VL_RESTORER(m_inScope);
|
VL_RESTORER(m_inScope);
|
||||||
m_inScope = true;
|
m_inScope = true;
|
||||||
VL_RESTORER(m_cFuncNames);
|
VL_RESTORER_CLEAR(m_cFuncNames);
|
||||||
m_cFuncNames.clear();
|
|
||||||
processAndIterate(nodep);
|
processAndIterate(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
VL_RESTORER(m_cFuncNames);
|
VL_RESTORER_CLEAR(m_cFuncNames);
|
||||||
m_cFuncNames.clear();
|
|
||||||
processAndIterate(nodep);
|
processAndIterate(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeUOrStructDType* nodep) override {
|
void visit(AstNodeUOrStructDType* nodep) override {
|
||||||
VL_RESTORER(m_cFuncNames);
|
VL_RESTORER_CLEAR(m_cFuncNames);
|
||||||
m_cFuncNames.clear();
|
|
||||||
processAndIterate(nodep);
|
processAndIterate(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeVarRef* nodep) override {
|
void visit(AstNodeVarRef* nodep) override {
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ class ClassVisitor final : public VNVisitor {
|
||||||
classScopep->aboveScopep(), classScopep->aboveCellp()};
|
classScopep->aboveScopep(), classScopep->aboveCellp()};
|
||||||
packagep->addStmtsp(scopep);
|
packagep->addStmtsp(scopep);
|
||||||
// Iterate
|
// Iterate
|
||||||
VL_RESTORER(m_prefix);
|
VL_RESTORER_CLEAR(m_prefix);
|
||||||
VL_RESTORER(m_classPackagep);
|
VL_RESTORER(m_classPackagep);
|
||||||
VL_RESTORER(m_classScopep);
|
VL_RESTORER(m_classScopep);
|
||||||
VL_RESTORER(m_packageScopep);
|
VL_RESTORER(m_packageScopep);
|
||||||
|
|
@ -129,7 +129,7 @@ class ClassVisitor final : public VNVisitor {
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
// Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule)
|
// Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule)
|
||||||
// Classes are always under a Package (perhaps $unit) or a module
|
// Classes are always under a Package (perhaps $unit) or a module
|
||||||
VL_RESTORER(m_prefix);
|
VL_RESTORER_CLEAR(m_prefix);
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_prefix = nodep->name() + "__03a__03a"; // ::
|
m_prefix = nodep->name() + "__03a__03a"; // ::
|
||||||
|
|
|
||||||
|
|
@ -279,8 +279,8 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
const AstNodeModule* const origModp = m_modp;
|
const AstNodeModule* const origModp = m_modp;
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_state);
|
VL_RESTORER(m_state);
|
||||||
VL_RESTORER(m_exprTempNames);
|
VL_RESTORER_COPY(m_exprTempNames);
|
||||||
VL_RESTORER(m_funcTemps);
|
VL_RESTORER_COPY(m_funcTemps);
|
||||||
createHandle(nodep);
|
createHandle(nodep);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_state.m_inModOff = false; // Haven't made top shell, so tops are real tops
|
m_state.m_inModOff = false; // Haven't made top shell, so tops are real tops
|
||||||
|
|
@ -294,8 +294,8 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
void visit(AstClass* nodep) override {
|
void visit(AstClass* nodep) override {
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_state);
|
VL_RESTORER(m_state);
|
||||||
VL_RESTORER(m_exprTempNames);
|
VL_RESTORER_COPY(m_exprTempNames);
|
||||||
VL_RESTORER(m_funcTemps);
|
VL_RESTORER_COPY(m_funcTemps);
|
||||||
createHandle(nodep);
|
createHandle(nodep);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
// Covergroup declarations are not executable statements; suppress line/expr/toggle
|
// Covergroup declarations are not executable statements; suppress line/expr/toggle
|
||||||
|
|
@ -356,8 +356,8 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
|
|
||||||
void visit(AstNodeFTask* nodep) override {
|
void visit(AstNodeFTask* nodep) override {
|
||||||
VL_RESTORER(m_ftaskp);
|
VL_RESTORER(m_ftaskp);
|
||||||
VL_RESTORER(m_exprTempNames);
|
VL_RESTORER_COPY(m_exprTempNames);
|
||||||
VL_RESTORER(m_funcTemps);
|
VL_RESTORER_COPY(m_funcTemps);
|
||||||
m_ftaskp = nodep;
|
m_ftaskp = nodep;
|
||||||
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -762,7 +762,7 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
void visit(AstGenBlock* nodep) override {
|
void visit(AstGenBlock* nodep) override {
|
||||||
// Similar to AstBegin
|
// Similar to AstBegin
|
||||||
VL_RESTORER(m_beginHier);
|
VL_RESTORER_COPY(m_beginHier);
|
||||||
if (nodep->name() != "") {
|
if (nodep->name() != "") {
|
||||||
m_beginHier = m_beginHier + (m_beginHier != "" ? "__DOT__" : "") + nodep->name();
|
m_beginHier = m_beginHier + (m_beginHier != "" ? "__DOT__" : "") + nodep->name();
|
||||||
}
|
}
|
||||||
|
|
@ -776,7 +776,7 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
// generate blocks; each point should get separate consideration.
|
// generate blocks; each point should get separate consideration.
|
||||||
// (Currently ignored for line coverage, since any generate iteration
|
// (Currently ignored for line coverage, since any generate iteration
|
||||||
// covers the code in that line.)
|
// covers the code in that line.)
|
||||||
VL_RESTORER(m_beginHier);
|
VL_RESTORER_COPY(m_beginHier);
|
||||||
VL_RESTORER(m_inToggleOff);
|
VL_RESTORER(m_inToggleOff);
|
||||||
VL_RESTORER(m_exprStmtsp);
|
VL_RESTORER(m_exprStmtsp);
|
||||||
m_exprStmtsp = nodep;
|
m_exprStmtsp = nodep;
|
||||||
|
|
@ -874,7 +874,7 @@ class CoverageVisitor final : public VNVisitor {
|
||||||
UASSERT_OBJ(m_exprs.empty(), nodep, "unexpected expression coverage garbage");
|
UASSERT_OBJ(m_exprs.empty(), nodep, "unexpected expression coverage garbage");
|
||||||
VL_RESTORER(m_seeking);
|
VL_RESTORER(m_seeking);
|
||||||
VL_RESTORER(m_objective);
|
VL_RESTORER(m_objective);
|
||||||
VL_RESTORER(m_exprs);
|
VL_RESTORER_CLEAR(m_exprs); // Already asserted above it's empty.
|
||||||
|
|
||||||
m_seeking = SEEKING;
|
m_seeking = SEEKING;
|
||||||
m_objective = false;
|
m_objective = false;
|
||||||
|
|
|
||||||
|
|
@ -1727,15 +1727,12 @@ class FunctionalCoverageVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_covergroupp);
|
VL_RESTORER(m_covergroupp);
|
||||||
VL_RESTORER(m_sampleFuncp);
|
VL_RESTORER(m_sampleFuncp);
|
||||||
VL_RESTORER(m_constructorp);
|
VL_RESTORER(m_constructorp);
|
||||||
VL_RESTORER(m_coverpoints);
|
VL_RESTORER_CLEAR(m_coverpoints);
|
||||||
VL_RESTORER(m_coverpointMap);
|
VL_RESTORER_CLEAR(m_coverpointMap);
|
||||||
VL_RESTORER(m_coverCrosses);
|
VL_RESTORER_CLEAR(m_coverCrosses);
|
||||||
m_covergroupp = nodep;
|
m_covergroupp = nodep;
|
||||||
m_sampleFuncp = nullptr;
|
m_sampleFuncp = nullptr;
|
||||||
m_constructorp = nullptr;
|
m_constructorp = nullptr;
|
||||||
m_coverpoints.clear();
|
|
||||||
m_coverpointMap.clear();
|
|
||||||
m_coverCrosses.clear();
|
|
||||||
|
|
||||||
// Extract and store the clocking event from AstCovergroup node
|
// Extract and store the clocking event from AstCovergroup node
|
||||||
// The parser creates this node to preserve the event information
|
// The parser creates this node to preserve the event information
|
||||||
|
|
|
||||||
|
|
@ -1050,8 +1050,7 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
||||||
if (nodep->packed()) puts("packed ");
|
if (nodep->packed()) puts("packed ");
|
||||||
{
|
{
|
||||||
puts("{\n");
|
puts("{\n");
|
||||||
VL_RESTORER(m_packedps);
|
VL_RESTORER_CLEAR(m_packedps);
|
||||||
m_packedps.clear();
|
|
||||||
for (AstMemberDType* itemp = nodep->membersp(); itemp;
|
for (AstMemberDType* itemp = nodep->membersp(); itemp;
|
||||||
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
itemp = VN_AS(itemp->nextp(), MemberDType)) {
|
||||||
iterateConst(itemp);
|
iterateConst(itemp);
|
||||||
|
|
|
||||||
|
|
@ -561,10 +561,9 @@ class ForkVisitor final : public VNVisitor {
|
||||||
// replace body with a call to that task. Returns true iff wrapped.
|
// replace body with a call to that task. Returns true iff wrapped.
|
||||||
bool taskify(AstBegin* beginp) {
|
bool taskify(AstBegin* beginp) {
|
||||||
// Visit statement to gather variables (And recursively process)
|
// Visit statement to gather variables (And recursively process)
|
||||||
VL_RESTORER(m_forkLocalsp);
|
VL_RESTORER_CLEAR(m_forkLocalsp);
|
||||||
VL_RESTORER(m_capturedVarsp);
|
VL_RESTORER(m_capturedVarsp);
|
||||||
VL_RESTORER(m_capturedArgsp);
|
VL_RESTORER(m_capturedArgsp);
|
||||||
m_forkLocalsp.clear();
|
|
||||||
m_capturedVarsp = nullptr;
|
m_capturedVarsp = nullptr;
|
||||||
m_capturedArgsp = nullptr;
|
m_capturedArgsp = nullptr;
|
||||||
iterate(beginp);
|
iterate(beginp);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
|
@ -44,27 +45,90 @@ class V3ThreadPool;
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Restorer
|
// Restorer
|
||||||
|
|
||||||
/// Save a given variable's value on the stack, restoring it at end-of-scope.
|
// For all flavours, 'var' must be a named scalar variable (simple identifier).
|
||||||
// Object must be named, or it will not persist until end-of-scope.
|
|
||||||
// Constructor needs () or GCC 4.8 false warning.
|
// Copy given variable's value on the stack, copy saved value back at end-of-scope.
|
||||||
#define VL_RESTORER(var) const VRestorer<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
// Only usable for trivially copyable types; use VL_RESTORER_COPY/VL_RESTORER_CLEAR for
|
||||||
/// Get the copy of the variable previously saved by VL_RESTORER()
|
// non-trivially copyable types, which are more efficient.
|
||||||
|
#define VL_RESTORER(var) \
|
||||||
|
const VRestorerTrivial<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||||
|
|
||||||
|
// This is the equivalent of VL_RESTORER for non-trivially copyable types. Still more efficient
|
||||||
|
// than VL_RESTORER as uses move to restore.
|
||||||
|
#define VL_RESTORER_COPY(var) \
|
||||||
|
const VRestorerCopy<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||||
|
|
||||||
|
// Swap 'var' with a no-args constructed object of the same type, effectively clearing it, then
|
||||||
|
// swap back at end-of-scope. No copying involved. Use this e.g. for std containers where they
|
||||||
|
// would be .clear()'d right after the VL_RESTORER instance.
|
||||||
|
#define VL_RESTORER_CLEAR(var) \
|
||||||
|
const VRestorerClear<typename std::decay_t<decltype(var)>> restorer_##var(var);
|
||||||
|
|
||||||
|
// Get const reference to the saved copy
|
||||||
#define VL_RESTORER_PREV(var) restorer_##var.saved()
|
#define VL_RESTORER_PREV(var) restorer_##var.saved()
|
||||||
|
|
||||||
// Object used by VL_RESTORER. This object must be an auto variable, not
|
// Implementation of VL_RESTORER
|
||||||
// allocated on the heap or otherwise.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class VRestorer final {
|
class VRestorerTrivial final {
|
||||||
|
static_assert(std::is_trivially_copyable<T>::value,
|
||||||
|
"Use VL_RESTORER_{COPY,CLEAR} for non trivially copyable types");
|
||||||
T& m_ref; // Reference to object we're saving and restoring
|
T& m_ref; // Reference to object we're saving and restoring
|
||||||
const T m_saved; // Value saved, for later restore
|
const T m_saved; // Value saved, for later restore
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit VRestorer(T& permr)
|
explicit VRestorerTrivial(T& val)
|
||||||
: m_ref{permr}
|
: m_ref{val}
|
||||||
, m_saved{permr} {}
|
, m_saved{val} {}
|
||||||
~VRestorer() { m_ref = m_saved; }
|
~VRestorerTrivial() { m_ref = m_saved; }
|
||||||
|
VL_UNCOPYABLE(VRestorerTrivial);
|
||||||
|
// Must be stack allocated
|
||||||
|
void* operator new(size_t) = delete;
|
||||||
|
void operator delete(void*) = delete;
|
||||||
|
|
||||||
|
const T& saved() const { return m_saved; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of VL_RESTORER_COPY
|
||||||
|
template <typename T>
|
||||||
|
class VRestorerCopy final {
|
||||||
|
static_assert(!std::is_trivially_copyable<T>::value,
|
||||||
|
"Use VL_RESTORER for trivially copyable types");
|
||||||
|
T& m_ref; // Reference to object we're saving and restoring
|
||||||
|
T m_saved; // Value saved, for later restore
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VRestorerCopy(T& val)
|
||||||
|
: m_ref{val}
|
||||||
|
, m_saved{val} {}
|
||||||
|
~VRestorerCopy() { m_ref = std::move(m_saved); }
|
||||||
|
VL_UNCOPYABLE(VRestorerCopy);
|
||||||
|
// Must be stack allocated
|
||||||
|
void* operator new(size_t) = delete;
|
||||||
|
void operator delete(void*) = delete;
|
||||||
|
|
||||||
|
const T& saved() const { return m_saved; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation of VL_RESTORER_CLEAR.
|
||||||
|
template <typename T>
|
||||||
|
class VRestorerClear final {
|
||||||
|
static_assert(!std::is_trivially_copyable<T>::value,
|
||||||
|
"Use VL_RESTORER for trivially copyable types");
|
||||||
|
T& m_ref; // Reference to object we're saving and restoring
|
||||||
|
T m_saved{}; // Owns the swapped-out value; starts empty
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VRestorerClear(T& val)
|
||||||
|
: m_ref{val} {
|
||||||
|
std::swap(m_ref, m_saved);
|
||||||
|
}
|
||||||
|
~VRestorerClear() { std::swap(m_ref, m_saved); }
|
||||||
|
VL_UNCOPYABLE(VRestorerClear);
|
||||||
|
// Must be stack allocated
|
||||||
|
void* operator new(size_t) = delete;
|
||||||
|
void operator delete(void*) = delete;
|
||||||
|
|
||||||
const T& saved() const { return m_saved; }
|
const T& saved() const { return m_saved; }
|
||||||
VL_UNCOPYABLE(VRestorer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
|
||||||
|
|
@ -331,12 +331,9 @@ class HierBlockUsageCollectVisitor final : public VNVisitorConst {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a hierarchical block, gather parts
|
// This is a hierarchical block, gather parts
|
||||||
VL_RESTORER(m_params);
|
VL_RESTORER_CLEAR(m_params);
|
||||||
VL_RESTORER(m_typeParams);
|
VL_RESTORER_CLEAR(m_typeParams);
|
||||||
VL_RESTORER(m_childrenp);
|
VL_RESTORER_CLEAR(m_childrenp);
|
||||||
m_params.clear();
|
|
||||||
m_typeParams.clear();
|
|
||||||
m_childrenp.clear();
|
|
||||||
iterateChildrenConst(nodep);
|
iterateChildrenConst(nodep);
|
||||||
// Create the graph vertex for this hier block
|
// Create the graph vertex for this hier block
|
||||||
V3HierBlock* const blockp = new V3HierBlock{m_graphp, nodep, m_params, m_typeParams};
|
V3HierBlock* const blockp = new V3HierBlock{m_graphp, nodep, m_params, m_typeParams};
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class InlineIntfRefVisitor final : public VNVisitor {
|
||||||
// VISITORS
|
// VISITORS
|
||||||
void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); }
|
void visit(AstNetlist* nodep) override { iterateChildren(nodep->topModulep()); }
|
||||||
void visit(AstCell* nodep) override {
|
void visit(AstCell* nodep) override {
|
||||||
VL_RESTORER(m_scope);
|
VL_RESTORER_COPY(m_scope);
|
||||||
if (m_scope.empty()) {
|
if (m_scope.empty()) {
|
||||||
m_scope = nodep->name();
|
m_scope = nodep->name();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,8 @@ class LibMapVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(AstLibrary* nodep) override {
|
void visit(AstLibrary* nodep) override {
|
||||||
VL_RESTORER(m_lib);
|
VL_RESTORER_CLEAR(m_lib);
|
||||||
VL_RESTORER(m_rel);
|
VL_RESTORER_CLEAR(m_rel);
|
||||||
m_lib = nodep->name();
|
m_lib = nodep->name();
|
||||||
m_rel = V3Os::filenameDir(nodep->fileline()->filename());
|
m_rel = V3Os::filenameDir(nodep->fileline()->filename());
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
|
||||||
|
|
@ -157,11 +157,11 @@ class LinkConfigsVisitor final : public VNVisitor {
|
||||||
m_isDefault = true;
|
m_isDefault = true;
|
||||||
iterateAndNextNull(nodep->usep());
|
iterateAndNextNull(nodep->usep());
|
||||||
} else if (nodep->isCell()) {
|
} else if (nodep->isCell()) {
|
||||||
VL_RESTORER(m_cell);
|
VL_RESTORER_CLEAR(m_cell);
|
||||||
m_cell = nodep->cellp()->name();
|
m_cell = nodep->cellp()->name();
|
||||||
iterateAndNextNull(nodep->usep());
|
iterateAndNextNull(nodep->usep());
|
||||||
} else {
|
} else {
|
||||||
VL_RESTORER(m_hierInst);
|
VL_RESTORER_COPY(m_hierInst);
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_dotp);
|
VL_RESTORER(m_dotp);
|
||||||
m_dotp = VN_AS(nodep->cellp(), Dot);
|
m_dotp = VN_AS(nodep->cellp(), Dot);
|
||||||
|
|
|
||||||
|
|
@ -1259,7 +1259,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
const bool standalonePkg
|
const bool standalonePkg
|
||||||
= !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package));
|
= !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package));
|
||||||
const bool doit = (m_modSymp || standalonePkg);
|
const bool doit = (m_modSymp || standalonePkg);
|
||||||
VL_RESTORER(m_scope);
|
VL_RESTORER_COPY(m_scope);
|
||||||
VL_RESTORER(m_classOrPackagep);
|
VL_RESTORER(m_classOrPackagep);
|
||||||
VL_RESTORER(m_modSymp);
|
VL_RESTORER(m_modSymp);
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
|
|
@ -1335,7 +1335,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
void visit(AstClass* nodep) override { // FindVisitor::
|
void visit(AstClass* nodep) override { // FindVisitor::
|
||||||
UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit");
|
UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit");
|
||||||
UINFO(8, " " << nodep);
|
UINFO(8, " " << nodep);
|
||||||
VL_RESTORER(m_scope);
|
VL_RESTORER_COPY(m_scope);
|
||||||
VL_RESTORER(m_classOrPackagep);
|
VL_RESTORER(m_classOrPackagep);
|
||||||
VL_RESTORER(m_modSymp);
|
VL_RESTORER(m_modSymp);
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
|
|
@ -1384,7 +1384,7 @@ class LinkDotFindVisitor final : public VNVisitor {
|
||||||
if (nodep->recursive() && m_inRecursion) return;
|
if (nodep->recursive() && m_inRecursion) return;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
// Recurse in, preserving state
|
// Recurse in, preserving state
|
||||||
VL_RESTORER(m_scope);
|
VL_RESTORER_COPY(m_scope);
|
||||||
VL_RESTORER(m_modSymp);
|
VL_RESTORER(m_modSymp);
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_paramNum);
|
VL_RESTORER(m_paramNum);
|
||||||
|
|
@ -3584,7 +3584,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
|
|
||||||
void symIterateChildren(AstNode* nodep, VSymEnt* symp) {
|
void symIterateChildren(AstNode* nodep, VSymEnt* symp) {
|
||||||
// Iterate children, changing to given context, with restore to old context
|
// Iterate children, changing to given context, with restore to old context
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
m_curSymp = symp;
|
m_curSymp = symp;
|
||||||
m_ds.init(m_curSymp);
|
m_ds.init(m_curSymp);
|
||||||
|
|
@ -3592,7 +3592,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
void symIterateNull(AstNode* nodep, VSymEnt* symp) {
|
void symIterateNull(AstNode* nodep, VSymEnt* symp) {
|
||||||
// Iterate node, changing to given context, with restore to old context
|
// Iterate node, changing to given context, with restore to old context
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
m_curSymp = symp;
|
m_curSymp = symp;
|
||||||
m_ds.init(m_curSymp);
|
m_ds.init(m_curSymp);
|
||||||
|
|
@ -3805,10 +3805,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
LINKDOT_VISIT_START();
|
LINKDOT_VISIT_START();
|
||||||
UINFO(5, indent() << "visit " << nodep);
|
UINFO(5, indent() << "visit " << nodep);
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
VL_RESTORER(m_usedPins);
|
VL_RESTORER_CLEAR(m_usedPins);
|
||||||
VL_RESTORER(m_usedDefParamPins);
|
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||||
m_usedPins.clear();
|
|
||||||
m_usedDefParamPins.clear();
|
|
||||||
UASSERT_OBJ(nodep->modp(), nodep,
|
UASSERT_OBJ(nodep->modp(), nodep,
|
||||||
"Instance has unlinked module"); // V3LinkCell should have errored out
|
"Instance has unlinked module"); // V3LinkCell should have errored out
|
||||||
VL_RESTORER(m_cellp);
|
VL_RESTORER(m_cellp);
|
||||||
|
|
@ -3845,10 +3843,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
LINKDOT_VISIT_START();
|
LINKDOT_VISIT_START();
|
||||||
UINFO(5, indent() << "visit " << nodep);
|
UINFO(5, indent() << "visit " << nodep);
|
||||||
// Can be under dot if called as package::class and that class resolves, so no checkNoDot
|
// Can be under dot if called as package::class and that class resolves, so no checkNoDot
|
||||||
VL_RESTORER(m_usedPins);
|
VL_RESTORER_CLEAR(m_usedPins);
|
||||||
VL_RESTORER(m_usedDefParamPins);
|
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||||
m_usedPins.clear();
|
|
||||||
m_usedDefParamPins.clear();
|
|
||||||
UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class");
|
UASSERT_OBJ(nodep->classp(), nodep, "ClassRef has unlinked class");
|
||||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp() || V3Error::errorCount(), nodep,
|
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp() || V3Error::errorCount(), nodep,
|
||||||
"class reference parameter not removed by V3Param");
|
"class reference parameter not removed by V3Param");
|
||||||
|
|
@ -4753,14 +4749,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
LINKDOT_VISIT_START();
|
LINKDOT_VISIT_START();
|
||||||
UINFO(8, indent() << "visit " << nodep);
|
UINFO(8, indent() << "visit " << nodep);
|
||||||
UINFO(9, indent() << m_ds.ascii());
|
UINFO(9, indent() << m_ds.ascii());
|
||||||
VL_RESTORER(m_usedPins);
|
VL_RESTORER_CLEAR(m_usedPins);
|
||||||
VL_RESTORER(m_usedDefParamPins);
|
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||||
m_usedPins.clear();
|
|
||||||
m_usedDefParamPins.clear();
|
|
||||||
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep,
|
||||||
"class reference parameter not removed by V3Param");
|
"class reference parameter not removed by V3Param");
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
VL_RESTORER(m_pinSymp);
|
VL_RESTORER(m_pinSymp);
|
||||||
|
|
||||||
if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") {
|
if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") {
|
||||||
|
|
@ -4834,7 +4828,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -5054,7 +5048,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
// Created here so should already be resolved.
|
// Created here so should already be resolved.
|
||||||
LINKDOT_VISIT_START();
|
LINKDOT_VISIT_START();
|
||||||
UINFO(5, indent() << "visit " << nodep);
|
UINFO(5, indent() << "visit " << nodep);
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
VL_RESTORER(m_randSymp);
|
VL_RESTORER(m_randSymp);
|
||||||
VL_RESTORER(m_randMethodCallp);
|
VL_RESTORER(m_randMethodCallp);
|
||||||
{
|
{
|
||||||
|
|
@ -5509,7 +5503,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
if (nodep->name() != "") {
|
if (nodep->name() != "") {
|
||||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||||
UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp));
|
UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp));
|
||||||
|
|
@ -5524,7 +5518,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
if (nodep->name() != "") {
|
if (nodep->name() != "") {
|
||||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||||
UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp));
|
UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp));
|
||||||
|
|
@ -5643,7 +5637,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_currentWithp);
|
VL_RESTORER(m_currentWithp);
|
||||||
VL_RESTORER(m_restrictedNamesUsed);
|
VL_RESTORER_COPY(m_restrictedNamesUsed);
|
||||||
{
|
{
|
||||||
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep);
|
||||||
m_currentWithp = nodep;
|
m_currentWithp = nodep;
|
||||||
|
|
@ -5813,7 +5807,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_curSymp);
|
VL_RESTORER(m_curSymp);
|
||||||
VL_RESTORER(m_modSymp);
|
VL_RESTORER(m_modSymp);
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_ifClassImpNames);
|
VL_RESTORER_COPY(m_ifClassImpNames);
|
||||||
VL_RESTORER(m_insideClassExtParam);
|
VL_RESTORER(m_insideClassExtParam);
|
||||||
{
|
{
|
||||||
m_ds.init(m_curSymp);
|
m_ds.init(m_curSymp);
|
||||||
|
|
@ -6169,7 +6163,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
void visit(AstDisable* nodep) override {
|
void visit(AstDisable* nodep) override {
|
||||||
LINKDOT_VISIT_START();
|
LINKDOT_VISIT_START();
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
VL_RESTORER(m_ds);
|
VL_RESTORER_COPY(m_ds);
|
||||||
m_ds.init(m_curSymp);
|
m_ds.init(m_curSymp);
|
||||||
m_ds.m_dotPos = DP_FIRST;
|
m_ds.m_dotPos = DP_FIRST;
|
||||||
m_ds.m_disablep = nodep;
|
m_ds.m_disablep = nodep;
|
||||||
|
|
@ -6249,10 +6243,8 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
UASSERT_OBJ(ifacep, nodep, "Port parameters of AstIfaceRefDType without ifacep()");
|
UASSERT_OBJ(ifacep, nodep, "Port parameters of AstIfaceRefDType without ifacep()");
|
||||||
if (ifacep->dead()) return;
|
if (ifacep->dead()) return;
|
||||||
checkNoDot(nodep);
|
checkNoDot(nodep);
|
||||||
VL_RESTORER(m_usedPins);
|
VL_RESTORER_CLEAR(m_usedPins);
|
||||||
VL_RESTORER(m_usedDefParamPins);
|
VL_RESTORER_CLEAR(m_usedDefParamPins);
|
||||||
m_usedPins.clear();
|
|
||||||
m_usedDefParamPins.clear();
|
|
||||||
VL_RESTORER(m_pinSymp);
|
VL_RESTORER(m_pinSymp);
|
||||||
m_pinSymp = m_statep->getNodeSym(ifacep);
|
m_pinSymp = m_statep->getNodeSym(ifacep);
|
||||||
iterateAndNextNull(nodep->paramsp());
|
iterateAndNextNull(nodep->paramsp());
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
<< nodep->verilogKwd() << "'");
|
<< nodep->verilogKwd() << "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_RESTORER(m_portDups);
|
VL_RESTORER_COPY(m_portDups);
|
||||||
collectPorts(nodep->stmtsp());
|
collectPorts(nodep->stmtsp());
|
||||||
|
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
@ -763,12 +763,12 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_genblkAbove);
|
VL_RESTORER(m_genblkAbove);
|
||||||
VL_RESTORER(m_genblkNum);
|
VL_RESTORER(m_genblkNum);
|
||||||
VL_RESTORER(m_beginDepth);
|
VL_RESTORER(m_beginDepth);
|
||||||
VL_RESTORER(m_implTypedef);
|
|
||||||
VL_RESTORER(m_lifetime);
|
VL_RESTORER(m_lifetime);
|
||||||
VL_RESTORER(m_lifetimeAllowed);
|
VL_RESTORER(m_lifetimeAllowed);
|
||||||
VL_RESTORER(m_moduleWithGenericIface);
|
VL_RESTORER(m_moduleWithGenericIface);
|
||||||
VL_RESTORER(m_randSequenceNum);
|
VL_RESTORER(m_randSequenceNum);
|
||||||
VL_RESTORER(m_valueModp);
|
VL_RESTORER(m_valueModp);
|
||||||
|
VL_RESTORER_CLEAR(m_implTypedef);
|
||||||
|
|
||||||
// Module: Create sim table for entire module and iterate
|
// Module: Create sim table for entire module and iterate
|
||||||
cleanFileline(nodep);
|
cleanFileline(nodep);
|
||||||
|
|
@ -780,7 +780,6 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
m_genblkAbove = 0;
|
m_genblkAbove = 0;
|
||||||
m_genblkNum = 0;
|
m_genblkNum = 0;
|
||||||
m_beginDepth = 0;
|
m_beginDepth = 0;
|
||||||
m_implTypedef.clear();
|
|
||||||
m_valueModp = nodep;
|
m_valueModp = nodep;
|
||||||
m_lifetime = nodep->lifetime().makeImplicit();
|
m_lifetime = nodep->lifetime().makeImplicit();
|
||||||
m_lifetimeAllowed = VN_IS(nodep, Class);
|
m_lifetimeAllowed = VN_IS(nodep, Class);
|
||||||
|
|
@ -797,7 +796,7 @@ class LinkParseVisitor final : public VNVisitor {
|
||||||
"Verilator top-level internals");
|
"Verilator top-level internals");
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_RESTORER(m_portDups);
|
VL_RESTORER_COPY(m_portDups);
|
||||||
collectPorts(nodep->stmtsp());
|
collectPorts(nodep->stmtsp());
|
||||||
|
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class LinkWithVisitor final : public VNVisitor {
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
// Below state needs to be preserved between each module call.
|
// Below state needs to be preserved between each module call.
|
||||||
string m_randcIllegalWhy; // Why randc illegal
|
const char* m_randcIllegalWhyp = nullptr; // Why randc illegal
|
||||||
AstNode* m_randcIllegalp = nullptr; // Node causing randc illegal
|
AstNode* m_randcIllegalp = nullptr; // Node causing randc illegal
|
||||||
AstNodeExpr* m_currentRandomizeSelectp = nullptr; // fromp() of current `randomize()` call
|
AstNodeExpr* m_currentRandomizeSelectp = nullptr; // fromp() of current `randomize()` call
|
||||||
bool m_inRandomizeWith = false; // If in randomize() with (and no other with afterwards)
|
bool m_inRandomizeWith = false; // If in randomize() with (and no other with afterwards)
|
||||||
|
|
@ -49,24 +49,24 @@ class LinkWithVisitor final : public VNVisitor {
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstConstraintBefore* nodep) override {
|
void visit(AstConstraintBefore* nodep) override {
|
||||||
VL_RESTORER(m_randcIllegalWhy);
|
VL_RESTORER(m_randcIllegalWhyp);
|
||||||
VL_RESTORER(m_randcIllegalp);
|
VL_RESTORER(m_randcIllegalp);
|
||||||
m_randcIllegalWhy = "'solve before' (IEEE 1800-2023 18.5.9)";
|
m_randcIllegalWhyp = "'solve before' (IEEE 1800-2023 18.5.9)";
|
||||||
m_randcIllegalp = nodep;
|
m_randcIllegalp = nodep;
|
||||||
iterateChildrenConst(nodep);
|
iterateChildrenConst(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstDist* nodep) override {
|
void visit(AstDist* nodep) override {
|
||||||
VL_RESTORER(m_randcIllegalWhy);
|
VL_RESTORER(m_randcIllegalWhyp);
|
||||||
VL_RESTORER(m_randcIllegalp);
|
VL_RESTORER(m_randcIllegalp);
|
||||||
m_randcIllegalWhy = "'constraint dist' (IEEE 1800-2023 18.5.3)";
|
m_randcIllegalWhyp = "'constraint dist' (IEEE 1800-2023 18.5.3)";
|
||||||
m_randcIllegalp = nodep;
|
m_randcIllegalp = nodep;
|
||||||
iterateChildrenConst(nodep);
|
iterateChildrenConst(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstConstraintExpr* nodep) override {
|
void visit(AstConstraintExpr* nodep) override {
|
||||||
VL_RESTORER(m_randcIllegalWhy);
|
VL_RESTORER(m_randcIllegalWhyp);
|
||||||
VL_RESTORER(m_randcIllegalp);
|
VL_RESTORER(m_randcIllegalp);
|
||||||
if (nodep->isSoft()) {
|
if (nodep->isSoft()) {
|
||||||
m_randcIllegalWhy = "'constraint soft' (IEEE 1800-2023 18.5.13.1)";
|
m_randcIllegalWhyp = "'constraint soft' (IEEE 1800-2023 18.5.13.1)";
|
||||||
m_randcIllegalp = nodep;
|
m_randcIllegalp = nodep;
|
||||||
}
|
}
|
||||||
iterateChildrenConst(nodep);
|
iterateChildrenConst(nodep);
|
||||||
|
|
@ -76,7 +76,7 @@ class LinkWithVisitor final : public VNVisitor {
|
||||||
if (nodep->varp()) { // Else due to dead code, might not have var pointer
|
if (nodep->varp()) { // Else due to dead code, might not have var pointer
|
||||||
if (nodep->varp()->isRandC() && m_randcIllegalp) {
|
if (nodep->varp()->isRandC() && m_randcIllegalp) {
|
||||||
nodep->v3error("Randc variables not allowed in "
|
nodep->v3error("Randc variables not allowed in "
|
||||||
<< m_randcIllegalWhy << '\n'
|
<< m_randcIllegalWhyp << '\n'
|
||||||
<< nodep->warnContextPrimary() << '\n'
|
<< nodep->warnContextPrimary() << '\n'
|
||||||
<< m_randcIllegalp->warnOther()
|
<< m_randcIllegalp->warnOther()
|
||||||
<< "... Location of restricting expression\n"
|
<< "... Location of restricting expression\n"
|
||||||
|
|
|
||||||
|
|
@ -2571,11 +2571,9 @@ class ParamVisitor final : public VNVisitor {
|
||||||
// Iterate the body
|
// Iterate the body
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_ifacePortNames);
|
VL_RESTORER_CLEAR(m_ifacePortNames);
|
||||||
VL_RESTORER(m_ifaceInstCells);
|
VL_RESTORER_CLEAR(m_ifaceInstCells);
|
||||||
m_modp = modp;
|
m_modp = modp;
|
||||||
m_ifacePortNames.clear();
|
|
||||||
m_ifaceInstCells.clear();
|
|
||||||
iterateChildren(modp);
|
iterateChildren(modp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3241,7 +3239,7 @@ class ParamVisitor final : public VNVisitor {
|
||||||
// Note this clears nodep->genforp(), so begin is no longer special
|
// Note this clears nodep->genforp(), so begin is no longer special
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VL_RESTORER(m_generateHierName);
|
VL_RESTORER_COPY(m_generateHierName);
|
||||||
m_generateHierName += "." + nodep->prettyName();
|
m_generateHierName += "." + nodep->prettyName();
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ class RandSequenceVisitor final : public VNVisitor {
|
||||||
m_modp->addStmtsp(taskp);
|
m_modp->addStmtsp(taskp);
|
||||||
|
|
||||||
// Create local (not output) break variable
|
// Create local (not output) break variable
|
||||||
VL_RESTORER(m_localizeRemaps);
|
VL_RESTORER_COPY(m_localizeRemaps);
|
||||||
AstVar* breakVarp = newBreakVar(nodep->fileline(), false);
|
AstVar* breakVarp = newBreakVar(nodep->fileline(), false);
|
||||||
taskp->addStmtsp(breakVarp);
|
taskp->addStmtsp(breakVarp);
|
||||||
|
|
||||||
|
|
@ -417,9 +417,9 @@ class RandSequenceVisitor final : public VNVisitor {
|
||||||
m_rsp = nodep;
|
m_rsp = nodep;
|
||||||
VL_RESTORER(m_startProdp);
|
VL_RESTORER(m_startProdp);
|
||||||
|
|
||||||
VL_RESTORER(m_localizes);
|
VL_RESTORER_COPY(m_localizes);
|
||||||
VL_RESTORER(m_localizeNames);
|
VL_RESTORER_COPY(m_localizeNames);
|
||||||
VL_RESTORER(m_localizeRemaps);
|
VL_RESTORER_COPY(m_localizeRemaps);
|
||||||
findLocalizes(nodep);
|
findLocalizes(nodep);
|
||||||
|
|
||||||
// Find first production
|
// Find first production
|
||||||
|
|
@ -482,7 +482,7 @@ class RandSequenceVisitor final : public VNVisitor {
|
||||||
// TODO we could do this only if break exists in the downstream production,
|
// TODO we could do this only if break exists in the downstream production,
|
||||||
// but as-is we'll optimize it away in most cases anyways
|
// but as-is we'll optimize it away in most cases anyways
|
||||||
VL_RESTORER(m_breakVarp);
|
VL_RESTORER(m_breakVarp);
|
||||||
VL_RESTORER(m_localizeRemaps);
|
VL_RESTORER_COPY(m_localizeRemaps);
|
||||||
m_breakVarp = newBreakVar(nodep->fileline(), true);
|
m_breakVarp = newBreakVar(nodep->fileline(), true);
|
||||||
m_prodFuncp->addStmtsp(m_breakVarp);
|
m_prodFuncp->addStmtsp(m_breakVarp);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -306,10 +306,9 @@ private:
|
||||||
}
|
}
|
||||||
void visit(AstClass* nodep) override {
|
void visit(AstClass* nodep) override {
|
||||||
// Move initial statements into the constructor
|
// Move initial statements into the constructor
|
||||||
VL_RESTORER(m_initialps);
|
VL_RESTORER_CLEAR(m_initialps);
|
||||||
VL_RESTORER(m_ctorp);
|
VL_RESTORER(m_ctorp);
|
||||||
VL_RESTORER(m_classp);
|
VL_RESTORER(m_classp);
|
||||||
m_initialps.clear();
|
|
||||||
m_ctorp = nullptr;
|
m_ctorp = nullptr;
|
||||||
m_classp = nodep;
|
m_classp = nodep;
|
||||||
{ // Find m_initialps, m_ctor
|
{ // Find m_initialps, m_ctor
|
||||||
|
|
|
||||||
|
|
@ -485,7 +485,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
||||||
AstNodeDType* const skipTypep = nodep->skipRefp();
|
AstNodeDType* const skipTypep = nodep->skipRefp();
|
||||||
// offset and direction args added in EmitCImp
|
// offset and direction args added in EmitCImp
|
||||||
std::string callArgs{"tracep, \"" + VIdProtect::protect(m_traName) + "\""};
|
std::string callArgs{"tracep, \"" + VIdProtect::protect(m_traName) + "\""};
|
||||||
VL_RESTORER(m_traName);
|
VL_RESTORER_COPY(m_traName);
|
||||||
FileLine* const flp = skipTypep->fileline();
|
FileLine* const flp = skipTypep->fileline();
|
||||||
|
|
||||||
const DtypeFuncKey dtypeKey{skipTypep, m_traVscp->varp()->varType()};
|
const DtypeFuncKey dtypeKey{skipTypep, m_traVscp->varp()->varType()};
|
||||||
|
|
@ -530,7 +530,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
||||||
void declUnpackedArray(AstUnpackArrayDType* const nodep, bool newFunc) {
|
void declUnpackedArray(AstUnpackArrayDType* const nodep, bool newFunc) {
|
||||||
string prefixName(newFunc ? "name" : m_traName);
|
string prefixName(newFunc ? "name" : m_traName);
|
||||||
|
|
||||||
VL_RESTORER(m_traName);
|
VL_RESTORER_COPY(m_traName);
|
||||||
FileLine* const flp = nodep->fileline();
|
FileLine* const flp = nodep->fileline();
|
||||||
|
|
||||||
addToSubFunc(new AstTracePushPrefix{flp, prefixName, VTracePrefixType::ARRAY_UNPACKED,
|
addToSubFunc(new AstTracePushPrefix{flp, prefixName, VTracePrefixType::ARRAY_UNPACKED,
|
||||||
|
|
@ -568,7 +568,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
||||||
string prefixName(newFunc ? "name" : m_traName);
|
string prefixName(newFunc ? "name" : m_traName);
|
||||||
AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump();
|
AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump();
|
||||||
|
|
||||||
VL_RESTORER(m_traName);
|
VL_RESTORER_COPY(m_traName);
|
||||||
FileLine* const flp = nodep->fileline();
|
FileLine* const flp = nodep->fileline();
|
||||||
|
|
||||||
addToSubFunc(new AstTracePushPrefix{flp, prefixName, VTracePrefixType::ARRAY_PACKED,
|
addToSubFunc(new AstTracePushPrefix{flp, prefixName, VTracePrefixType::ARRAY_PACKED,
|
||||||
|
|
@ -918,7 +918,7 @@ class TraceDeclVisitor final : public VNVisitor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VL_RESTORER(m_traName);
|
VL_RESTORER_COPY(m_traName);
|
||||||
FileLine* const flp = nodep->fileline();
|
FileLine* const flp = nodep->fileline();
|
||||||
|
|
||||||
int nMembers = 0;
|
int nMembers = 0;
|
||||||
|
|
|
||||||
|
|
@ -2191,8 +2191,8 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||||
VL_RESTORER(m_modp);
|
VL_RESTORER(m_modp);
|
||||||
VL_RESTORER(m_graphing);
|
VL_RESTORER(m_graphing);
|
||||||
VL_RESTORER(m_unique);
|
VL_RESTORER(m_unique);
|
||||||
VL_RESTORER(m_lhsmap);
|
VL_RESTORER_CLEAR(m_lhsmap);
|
||||||
VL_RESTORER(m_assigns);
|
VL_RESTORER_CLEAR(m_assigns);
|
||||||
// Not preserved, needs pointer instead: TristateGraph origTgraph = m_tgraph;
|
// Not preserved, needs pointer instead: TristateGraph origTgraph = m_tgraph;
|
||||||
UASSERT_OBJ(m_tgraph.empty(), nodep, "Unsupported: NodeModule under NodeModule");
|
UASSERT_OBJ(m_tgraph.empty(), nodep, "Unsupported: NodeModule under NodeModule");
|
||||||
|
|
||||||
|
|
@ -2201,8 +2201,6 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||||
m_tgraph.clearAndCheck();
|
m_tgraph.clearAndCheck();
|
||||||
m_unique = 0;
|
m_unique = 0;
|
||||||
m_logicp = nullptr;
|
m_logicp = nullptr;
|
||||||
m_lhsmap.clear();
|
|
||||||
m_assigns.clear();
|
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
// Walk the graph, finding all variables and tristate constructs
|
// Walk the graph, finding all variables and tristate constructs
|
||||||
m_graphing = true;
|
m_graphing = true;
|
||||||
|
|
|
||||||
|
|
@ -56,14 +56,12 @@ class UdpVisitor final : public VNVisitor {
|
||||||
VL_RESTORER(m_primp);
|
VL_RESTORER(m_primp);
|
||||||
VL_RESTORER(m_outputInitVerfp);
|
VL_RESTORER(m_outputInitVerfp);
|
||||||
VL_RESTORER(m_isFirstOutput);
|
VL_RESTORER(m_isFirstOutput);
|
||||||
VL_RESTORER(m_inputVars);
|
VL_RESTORER_CLEAR(m_inputVars);
|
||||||
VL_RESTORER(m_outputVars);
|
VL_RESTORER_CLEAR(m_outputVars);
|
||||||
m_outputInitVerfp = nullptr;
|
m_outputInitVerfp = nullptr;
|
||||||
m_primp = nodep;
|
m_primp = nodep;
|
||||||
m_isFirstOutput = false;
|
m_isFirstOutput = false;
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
m_inputVars.clear();
|
|
||||||
m_outputVars.clear();
|
|
||||||
}
|
}
|
||||||
void visit(AstVar* nodep) override {
|
void visit(AstVar* nodep) override {
|
||||||
// Push the input and output vars for primitive.
|
// Push the input and output vars for primitive.
|
||||||
|
|
|
||||||
|
|
@ -7852,7 +7852,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
}
|
}
|
||||||
void visit(AstNodeModule* nodep) override {
|
void visit(AstNodeModule* nodep) override {
|
||||||
assertAtStatement(nodep);
|
assertAtStatement(nodep);
|
||||||
VL_RESTORER(m_insideTempNames);
|
VL_RESTORER_COPY(m_insideTempNames);
|
||||||
if (AstClass* const classp = VN_CAST(nodep, Class)) {
|
if (AstClass* const classp = VN_CAST(nodep, Class)) {
|
||||||
visitClass(classp);
|
visitClass(classp);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class WidthCommitVisitor final : public VNVisitor {
|
||||||
// STATE
|
// STATE
|
||||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||||
AstNodeModule* m_modp = nullptr; // Current module
|
AstNodeModule* m_modp = nullptr; // Current module
|
||||||
std::string m_contNba; // In continuous- or non-blocking assignment
|
const char* m_contNbap = nullptr; // In continuous- or non-blocking assignment
|
||||||
bool m_contReads = false; // Check read continuous automatic variables
|
bool m_contReads = false; // Check read continuous automatic variables
|
||||||
bool m_dynsizedelem = false; // Writing dynamically-sized array element, not the array itself
|
bool m_dynsizedelem = false; // Writing dynamically-sized array element, not the array itself
|
||||||
VMemberMap m_memberMap; // Member names cached for fast lookup
|
VMemberMap m_memberMap; // Member names cached for fast lookup
|
||||||
|
|
@ -148,7 +148,7 @@ private:
|
||||||
void varLifetimeCheck(AstNode* nodep, AstVar* varp) {
|
void varLifetimeCheck(AstNode* nodep, AstVar* varp) {
|
||||||
// Skip if we are under a member select (lhs of a dot)
|
// Skip if we are under a member select (lhs of a dot)
|
||||||
// We don't care about lifetime of anything else than rhs of a dot
|
// We don't care about lifetime of anything else than rhs of a dot
|
||||||
if (!m_underSel && !m_contNba.empty()) {
|
if (!m_underSel && m_contNbap) {
|
||||||
std::string varType;
|
std::string varType;
|
||||||
const AstNodeDType* const varDtp = varp->dtypep()->skipRefp();
|
const AstNodeDType* const varDtp = varp->dtypep()->skipRefp();
|
||||||
if (varp->lifetime().isAutomatic() && !VN_IS(varDtp, IfaceRefDType)
|
if (varp->lifetime().isAutomatic() && !VN_IS(varDtp, IfaceRefDType)
|
||||||
|
|
@ -162,7 +162,7 @@ private:
|
||||||
if (!varType.empty()) {
|
if (!varType.empty()) {
|
||||||
UINFO(1, " Related var dtype: " << varDtp);
|
UINFO(1, " Related var dtype: " << varDtp);
|
||||||
nodep->v3error(varType
|
nodep->v3error(varType
|
||||||
<< " variable not allowed in " << m_contNba
|
<< " variable not allowed in " << m_contNbap
|
||||||
<< " assignment (IEEE 1800-2023 6.21): " << varp->prettyNameQ());
|
<< " assignment (IEEE 1800-2023 6.21): " << varp->prettyNameQ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -419,9 +419,9 @@ private:
|
||||||
void visit(AstAssignCont* nodep) override {
|
void visit(AstAssignCont* nodep) override {
|
||||||
iterateAndNextNull(nodep->timingControlp());
|
iterateAndNextNull(nodep->timingControlp());
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_contNba);
|
VL_RESTORER(m_contNbap);
|
||||||
VL_RESTORER(m_contReads);
|
VL_RESTORER(m_contReads);
|
||||||
m_contNba = "continuous";
|
m_contNbap = "continuous";
|
||||||
m_contReads = true;
|
m_contReads = true;
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
iterateAndNextNull(nodep->rhsp());
|
iterateAndNextNull(nodep->rhsp());
|
||||||
|
|
@ -432,9 +432,9 @@ private:
|
||||||
iterateAndNextNull(nodep->timingControlp());
|
iterateAndNextNull(nodep->timingControlp());
|
||||||
iterateAndNextNull(nodep->rhsp());
|
iterateAndNextNull(nodep->rhsp());
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_contNba);
|
VL_RESTORER(m_contNbap);
|
||||||
VL_RESTORER(m_contReads);
|
VL_RESTORER(m_contReads);
|
||||||
m_contNba = "nonblocking";
|
m_contNbap = "nonblocking";
|
||||||
m_contReads = false;
|
m_contReads = false;
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
}
|
}
|
||||||
|
|
@ -444,9 +444,9 @@ private:
|
||||||
iterateAndNextNull(nodep->timingControlp());
|
iterateAndNextNull(nodep->timingControlp());
|
||||||
iterateAndNextNull(nodep->rhsp());
|
iterateAndNextNull(nodep->rhsp());
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_contNba);
|
VL_RESTORER(m_contNbap);
|
||||||
VL_RESTORER(m_contReads);
|
VL_RESTORER(m_contReads);
|
||||||
m_contNba = "continuous";
|
m_contNbap = "continuous";
|
||||||
m_contReads = false;
|
m_contReads = false;
|
||||||
iterateAndNextNull(nodep->lhsp());
|
iterateAndNextNull(nodep->lhsp());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue