Name temporary variables based on hash of related node.
This improves output stability by removing sequence numbers and hence can improve ccache hit rate. No functional change intended.
This commit is contained in:
parent
5adc856950
commit
00fe36f44c
|
|
@ -2849,7 +2849,6 @@ private:
|
|||
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, ...
|
||||
int m_varNum = 0; // Incrementing variable number
|
||||
int m_typeNum = 0; // Incrementing implicit type number
|
||||
VLifetime m_lifetime; // Lifetime
|
||||
VTimescale m_timeunit; // Global time unit
|
||||
|
|
@ -2890,7 +2889,6 @@ public:
|
|||
void level(int level) { m_level = level; }
|
||||
int level() const { return m_level; }
|
||||
bool isTop() const { return level() == 1; }
|
||||
int varNumGetInc() { return ++m_varNum; }
|
||||
int typeNumGetInc() { return ++m_typeNum; }
|
||||
void modPublic(bool flag) { m_modPublic = flag; }
|
||||
bool modPublic() const { return m_modPublic; }
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "V3Width.h"
|
||||
#include "V3Simulate.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -601,6 +602,9 @@ private:
|
|||
AstNode* m_scopep = nullptr; // Current scope
|
||||
AstAttrOf* m_attrp = nullptr; // Current attribute
|
||||
VDouble0 m_statBitOpReduction; // Ops reduced in ConstBitOpTreeVisitor
|
||||
const bool m_globalPass; // ConstVisitor invoked as a global pass
|
||||
static uint32_t s_globalPassNum; // Counts number of times ConstVisitor invoked as global pass
|
||||
V3UniqueNames m_concswapNames; // For generating unique temporary variable names
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -1762,14 +1766,16 @@ private:
|
|||
newp = AstNode::addNext(newp, asn2ap);
|
||||
} else {
|
||||
UASSERT_OBJ(m_modp, nodep, "Not under module");
|
||||
UASSERT_OBJ(m_globalPass, nodep,
|
||||
"Should not reach here when not invoked on whole AstNetlist");
|
||||
// We could create just one temp variable, but we'll get better optimization
|
||||
// if we make one per term.
|
||||
string name1 = (string("__Vconcswap") + cvtToStr(m_modp->varNumGetInc()));
|
||||
string name2 = (string("__Vconcswap") + cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
|
||||
VFlagLogicPacked(), msb1 - lsb1 + 1);
|
||||
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
|
||||
VFlagLogicPacked(), msb2 - lsb2 + 1);
|
||||
AstVar* const temp1p
|
||||
= new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP,
|
||||
m_concswapNames.get(sel1p), VFlagLogicPacked(), msb1 - lsb1 + 1);
|
||||
AstVar* const temp2p
|
||||
= new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP,
|
||||
m_concswapNames.get(sel2p), VFlagLogicPacked(), msb2 - lsb2 + 1);
|
||||
m_modp->addStmtp(temp1p);
|
||||
m_modp->addStmtp(temp2p);
|
||||
AstNodeAssign* asn1ap
|
||||
|
|
@ -1931,6 +1937,7 @@ private:
|
|||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_concswapNames.reset();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
|
@ -3197,7 +3204,9 @@ public:
|
|||
};
|
||||
|
||||
// CONSTRUCTORS
|
||||
explicit ConstVisitor(ProcMode pmode) {
|
||||
ConstVisitor(ProcMode pmode, bool globalPass)
|
||||
: m_globalPass{globalPass}
|
||||
, m_concswapNames{globalPass ? ("__Vconcswap_" + cvtToStr(s_globalPassNum++)) : ""} {
|
||||
// clang-format off
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true;
|
||||
|
|
@ -3225,6 +3234,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
uint32_t ConstVisitor::s_globalPassNum = 0;
|
||||
|
||||
//######################################################################
|
||||
// Const class functions
|
||||
|
||||
|
|
@ -3237,7 +3248,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
|||
|
||||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthParamsEdit(nodep);
|
||||
ConstVisitor visitor{ConstVisitor::PROC_PARAMS};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_PARAMS, /* globalPass: */ false};
|
||||
if (AstVar* varp = VN_CAST(nodep, Var)) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
|
@ -3267,7 +3278,7 @@ AstNode* V3Const::constifyGenerateParamsEdit(AstNode* nodep) {
|
|||
|
||||
// Make sure we've sized everything first
|
||||
nodep = V3Width::widthGenerateParamsEdit(nodep);
|
||||
ConstVisitor visitor{ConstVisitor::PROC_GENERATE};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_GENERATE, /* globalPass: */ false};
|
||||
if (AstVar* varp = VN_CAST(nodep, Var)) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
|
|
@ -3285,7 +3296,7 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
|
|||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_WARN};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_WARN, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
|
|
@ -3294,14 +3305,14 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
|
|||
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{
|
||||
ConstVisitor visitor{ConstVisitor::PROC_CPP};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_CPP, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const_cpp", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_NOWARN};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_NOWARN, /* globalPass: */ false};
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
return nodep;
|
||||
}
|
||||
|
|
@ -3312,7 +3323,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
|
|||
// IE doesn't prune dead statements, as we need to do some usability checks after this
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{
|
||||
ConstVisitor visitor{ConstVisitor::PROC_LIVE};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_LIVE, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
|
|
@ -3322,14 +3333,14 @@ void V3Const::constifyAll(AstNetlist* nodep) {
|
|||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE};
|
||||
ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE, /* globalPass: */ false};
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
return nodep;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3Depth.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -39,11 +40,11 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstCFunc* m_cfuncp = nullptr; // Current block
|
||||
AstNode* m_stmtp = nullptr; // Current statement
|
||||
int m_depth = 0; // How deep in an expression
|
||||
int m_maxdepth = 0; // Maximum depth in an expression
|
||||
V3UniqueNames m_tempNames; // For generating unique temporary variable names
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -51,10 +52,8 @@ private:
|
|||
void createDeepTemp(AstNode* nodep) {
|
||||
UINFO(6, " Deep " << nodep << endl);
|
||||
// if (debug() >= 9) nodep->dumpTree(cout, "deep:");
|
||||
|
||||
const string newvarname = (string("__Vdeeptemp") + cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* const varp
|
||||
= new AstVar{nodep->fileline(), AstVarType::STMTTEMP, newvarname, nodep->dtypep()};
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), AstVarType::STMTTEMP,
|
||||
m_tempNames.get(nodep), nodep->dtypep()};
|
||||
UASSERT_OBJ(m_cfuncp, nodep, "Deep expression not under a function");
|
||||
m_cfuncp->addInitsp(varp);
|
||||
// Replace node tree with reference to var
|
||||
|
|
@ -70,21 +69,13 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_cfuncp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_cfuncp);
|
||||
{
|
||||
m_cfuncp = nodep;
|
||||
m_depth = 0;
|
||||
m_maxdepth = 0;
|
||||
m_tempNames.reset();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +140,10 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DepthVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
explicit DepthVisitor(AstNetlist* nodep)
|
||||
: m_tempNames{"__Vdeeptemp"} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~DepthVisitor() override = default;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3Premit.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3DupFinder.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -92,17 +92,17 @@ private:
|
|||
// AstNodeMath::user() -> bool. True if iterated already
|
||||
// AstShiftL::user2() -> bool. True if converted to conditional
|
||||
// AstShiftR::user2() -> bool. True if converted to conditional
|
||||
// *::user4() -> See PremitAssignVisitor
|
||||
// *::user3() -> See PremitAssignVisitor
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstCFunc* m_cfuncp = nullptr; // Current block
|
||||
AstNode* m_stmtp = nullptr; // Current statement
|
||||
AstWhile* m_inWhilep = nullptr; // Inside while loop, special statement additions
|
||||
AstTraceInc* m_inTracep = nullptr; // Inside while loop, special statement additions
|
||||
bool m_assignLhs = false; // Inside assignment lhs, don't breakup extracts
|
||||
V3UniqueNames m_tempNames; // For generating unique temporary variable names
|
||||
|
||||
VDouble0 m_extractedToConstPool; // Statistic tracking
|
||||
|
||||
|
|
@ -184,9 +184,8 @@ private:
|
|||
nodep->deleteTree();
|
||||
++m_extractedToConstPool;
|
||||
} else {
|
||||
// Keep as local temporary
|
||||
const string name = string("__Vtemp") + cvtToStr(m_modp->varNumGetInc());
|
||||
varp = new AstVar(fl, AstVarType::STMTTEMP, name, nodep->dtypep());
|
||||
// Keep as local temporary. Name based on hash of node for output stability.
|
||||
varp = new AstVar(fl, AstVarType::STMTTEMP, m_tempNames.get(nodep), nodep->dtypep());
|
||||
m_cfuncp->addInitsp(varp);
|
||||
// Put assignment before the referencing statement
|
||||
insertBeforeStmt(new AstAssign(fl, new AstVarRef(fl, varp, VAccess::WRITE), nodep));
|
||||
|
|
@ -202,16 +201,13 @@ private:
|
|||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
UASSERT_OBJ(m_modp == nullptr, nodep, "Nested modules ?");
|
||||
m_modp = nodep;
|
||||
m_cfuncp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
m_modp = nullptr;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_cfuncp);
|
||||
{
|
||||
m_cfuncp = nodep;
|
||||
m_tempNames.reset();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
|
@ -412,7 +408,10 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit PremitVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
explicit PremitVisitor(AstNetlist* nodep)
|
||||
: m_tempNames{"__Vtemp"} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~PremitVisitor() {
|
||||
V3Stats::addStat("Optimizations, Prelim extracted value to ConstPool",
|
||||
m_extractedToConstPool);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3SplitVar.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm> // sort
|
||||
#include <map>
|
||||
|
|
@ -124,6 +125,10 @@
|
|||
#include <vector>
|
||||
|
||||
struct SplitVarImpl {
|
||||
// NODE STATE
|
||||
// AstNodeModule::user1() -> Block number counter for generating unique names
|
||||
AstUser1InUse m_user1InUse; // Only used in SplitUnpackedVarVisitor
|
||||
|
||||
static AstNodeAssign* newAssign(FileLine* fileline, AstNode* lhsp, AstNode* rhsp,
|
||||
const AstVar* varp) {
|
||||
if (varp->isFuncLocal() || varp->isFuncReturn()) {
|
||||
|
|
@ -184,27 +189,27 @@ struct SplitVarImpl {
|
|||
static const char* cannotSplitPackedVarReason(const AstVar* varp);
|
||||
|
||||
template <class T_ALWAYSLIKE>
|
||||
static void insertBeginCore(T_ALWAYSLIKE* ap, AstNodeStmt* stmtp, AstNodeModule* modp) {
|
||||
void insertBeginCore(T_ALWAYSLIKE* ap, AstNodeStmt* stmtp, AstNodeModule* modp) {
|
||||
if (ap->isJustOneBodyStmt() && ap->bodysp() == stmtp) {
|
||||
stmtp->unlinkFrBack();
|
||||
// Insert begin-end because temp value may be inserted to this block later.
|
||||
const std::string name = "__VsplitVarBlk" + cvtToStr(modp->varNumGetInc());
|
||||
const std::string name = "__VsplitVarBlk" + cvtToStr(modp->user1Inc(1));
|
||||
ap->addStmtp(new AstBegin{ap->fileline(), name, stmtp});
|
||||
}
|
||||
}
|
||||
|
||||
static void insertBeginCore(AstInitial* initp, AstNodeStmt* stmtp, AstNodeModule* modp) {
|
||||
void insertBeginCore(AstInitial* initp, AstNodeStmt* stmtp, AstNodeModule* modp) {
|
||||
if (initp->isJustOneBodyStmt() && initp->bodysp() == stmtp) {
|
||||
stmtp->unlinkFrBack();
|
||||
// Insert begin-end because temp value may be inserted to this block later.
|
||||
FileLine* const fl = initp->fileline();
|
||||
const std::string name = "__VsplitVarBlk" + cvtToStr(modp->varNumGetInc());
|
||||
const std::string name = "__VsplitVarBlk" + cvtToStr(modp->user1Inc(1));
|
||||
initp->replaceWith(new AstInitial{fl, new AstBegin{fl, name, stmtp}});
|
||||
VL_DO_DANGLING(initp->deleteTree(), initp);
|
||||
}
|
||||
}
|
||||
|
||||
static void insertBeginIfNecessary(AstNodeStmt* stmtp, AstNodeModule* modp) {
|
||||
void insertBeginIfNecessary(AstNodeStmt* stmtp, AstNodeModule* modp) {
|
||||
AstNode* const backp = stmtp->backp();
|
||||
if (AstAlways* const ap = VN_CAST(backp, Always)) {
|
||||
insertBeginCore(ap, stmtp, modp);
|
||||
|
|
@ -401,6 +406,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
|
|||
size_t m_numSplit = 0;
|
||||
// List for SplitPackedVarVisitor
|
||||
SplitVarRefsMap m_refsForPackedSplit;
|
||||
V3UniqueNames m_tempNames; // For generating unique temporary variable names
|
||||
|
||||
static AstVarRef* isTargetVref(AstNode* nodep) {
|
||||
if (AstVarRef* const refp = VN_CAST(nodep, VarRef)) {
|
||||
|
|
@ -457,6 +463,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
|
|||
UASSERT_OBJ(!m_modp, m_modp, "Nested module declaration");
|
||||
UASSERT_OBJ(m_refs.empty(), nodep, "The last module didn't finish split()");
|
||||
m_modp = nodep;
|
||||
m_tempNames.reset();
|
||||
iterateChildren(nodep);
|
||||
split();
|
||||
m_modp = nullptr;
|
||||
|
|
@ -593,7 +600,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
static AstNode* toInsertPoint(AstNode* insertp) {
|
||||
AstNode* toInsertPoint(AstNode* insertp) {
|
||||
if (AstNodeStmt* const stmtp = VN_CAST(insertp, NodeStmt)) {
|
||||
if (!stmtp->isStatement()) insertp = stmtp->backp();
|
||||
}
|
||||
|
|
@ -603,8 +610,7 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
|
|||
const std::string& name_prefix, std::vector<AstVar*>& vars,
|
||||
int start_idx, bool lvalue, bool ftask) {
|
||||
FileLine* const fl = nodep->fileline();
|
||||
const std::string name
|
||||
= "__VsplitVar" + cvtToStr(m_modp->varNumGetInc()) + "__" + name_prefix;
|
||||
const std::string name = m_tempNames.get(nodep) + "__" + name_prefix;
|
||||
AstNodeAssign* const assignp = VN_CAST(context, NodeAssign);
|
||||
if (assignp) {
|
||||
// "always_comb a = b;" to "always_comb begin a = b; end" so that local
|
||||
|
|
@ -765,7 +771,8 @@ class SplitUnpackedVarVisitor final : public AstNVisitor, public SplitVarImpl {
|
|||
|
||||
public:
|
||||
explicit SplitUnpackedVarVisitor(AstNetlist* nodep)
|
||||
: m_refs{} {
|
||||
: m_refs{}
|
||||
, m_tempNames{"__VsplitVar"} {
|
||||
iterate(nodep);
|
||||
}
|
||||
~SplitUnpackedVarVisitor() override {
|
||||
|
|
|
|||
|
|
@ -18,22 +18,47 @@
|
|||
|
||||
#ifndef VERILATOR_V3UNIQUENAMES_H_
|
||||
#define VERILATOR_V3UNIQUENAMES_H_
|
||||
|
||||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include "V3Hasher.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class V3UniqueNames final {
|
||||
const std::string m_prefix; // Prefix to attach to all names
|
||||
|
||||
std::unordered_map<std::string, unsigned> m_multiplicity; // Suffix number for given key
|
||||
|
||||
public:
|
||||
// Return argument, appended with a unique suffix each time we are called with the same
|
||||
// argument.
|
||||
V3UniqueNames()
|
||||
: m_prefix{""} {}
|
||||
explicit V3UniqueNames(const std::string& prefix)
|
||||
: m_prefix{prefix} {}
|
||||
|
||||
// Return argument, prepended with the prefix if any, then appended with a unique suffix each
|
||||
// time we are called with the same argument.
|
||||
std::string get(const std::string& name) {
|
||||
const unsigned num = m_multiplicity.emplace(name, 0).first->second++;
|
||||
return name + "__" + cvtToStr(num);
|
||||
std::string result;
|
||||
if (!m_prefix.empty()) {
|
||||
result += m_prefix;
|
||||
result += "_";
|
||||
}
|
||||
result += name;
|
||||
result += "__";
|
||||
result += cvtToStr(num);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return hash of node as string, prepended with the prefix if any, appended with a unique
|
||||
// suffix each time we are called with a node that hashes to the same value.
|
||||
std::string get(const AstNode* nodep) { return get(V3Hasher::uncachedHash(nodep).toString()); }
|
||||
|
||||
// Reset to initial state (as if just constructed)
|
||||
void reset() { m_multiplicity.clear(); }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "V3Ast.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -57,6 +58,8 @@ private:
|
|||
AstAssignDly* m_assigndlyp = nullptr; // Current assignment
|
||||
bool m_constXCvt = false; // Convert X's
|
||||
VDouble0 m_statUnkVars; // Statistic tracking
|
||||
V3UniqueNames m_lvboundNames; // For generating unique temporary variable names
|
||||
V3UniqueNames m_xrandNames; // For generating unique temporary variable names
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -113,11 +116,10 @@ private:
|
|||
UINFO(4, "Edit BOUNDLVALUE " << newp << endl);
|
||||
replaceHandle.relink(newp);
|
||||
} else {
|
||||
const string name = (string("__Vlvbound") + cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name, prep->dtypep());
|
||||
AstVar* const varp
|
||||
= new AstVar(fl, AstVarType::MODULETEMP, m_lvboundNames.get(prep), prep->dtypep());
|
||||
m_modp->addStmtp(varp);
|
||||
|
||||
AstNode* abovep = prep->backp(); // Grab above point before lose it w/ next replace
|
||||
AstNode* const abovep = prep->backp(); // Grab above point before we replace 'prep'
|
||||
prep->replaceWith(new AstVarRef(fl, varp, VAccess::WRITE));
|
||||
AstIf* newp = new AstIf(
|
||||
fl, condp,
|
||||
|
|
@ -142,6 +144,8 @@ private:
|
|||
{
|
||||
m_modp = nodep;
|
||||
m_constXCvt = true;
|
||||
m_lvboundNames.reset();
|
||||
m_xrandNames.reset();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
|
@ -322,15 +326,16 @@ private:
|
|||
// Make a Vxrand variable
|
||||
// We use the special XTEMP type so it doesn't break pure functions
|
||||
UASSERT_OBJ(m_modp, nodep, "X number not under module");
|
||||
const string newvarname = (string("__Vxrand") + cvtToStr(m_modp->varNumGetInc()));
|
||||
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::XTEMP, newvarname,
|
||||
VFlagLogicPacked(), nodep->width());
|
||||
AstVar* const newvarp
|
||||
= new AstVar(nodep->fileline(), AstVarType::XTEMP, m_xrandNames.get(nodep),
|
||||
VFlagLogicPacked(), nodep->width());
|
||||
++m_statUnkVars;
|
||||
AstNRelinker replaceHandle;
|
||||
nodep->unlinkFrBack(&replaceHandle);
|
||||
AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, VAccess::READ);
|
||||
AstNodeVarRef* const newref1p
|
||||
= new AstVarRef(nodep->fileline(), newvarp, VAccess::READ);
|
||||
replaceHandle.relink(newref1p); // Replace const with varref
|
||||
AstInitial* newinitp = new AstInitial(
|
||||
AstInitial* const newinitp = new AstInitial(
|
||||
nodep->fileline(),
|
||||
new AstAssign(
|
||||
nodep->fileline(),
|
||||
|
|
@ -342,7 +347,7 @@ private:
|
|||
nodep->dtypep(), true)))));
|
||||
// Add inits in front of other statement.
|
||||
// In the future, we should stuff the initp into the module's constructor.
|
||||
AstNode* afterp = m_modp->stmtsp()->unlinkFrBackWithNext();
|
||||
AstNode* const afterp = m_modp->stmtsp()->unlinkFrBackWithNext();
|
||||
m_modp->addStmtp(newvarp);
|
||||
m_modp->addStmtp(newinitp);
|
||||
m_modp->addStmtp(afterp);
|
||||
|
|
@ -476,7 +481,11 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit UnknownVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
explicit UnknownVisitor(AstNetlist* nodep)
|
||||
: m_lvboundNames{"__Vlvbound"}
|
||||
, m_xrandNames{"__Vxrand"} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~UnknownVisitor() override { //
|
||||
V3Stats::addStat("Unknowns, variables created", m_statUnkVars);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@
|
|||
<cfunc fl="d60" loc="d,60,4,60,10" name="_sequent__TOP__1">
|
||||
<var fl="d22" loc="d,22,13,22,16" name="__Vdly__t.cyc" dtype_id="3" vartype="integer" origName="__Vdly__t__DOT__cyc"/>
|
||||
<var fl="d23" loc="d,23,9,23,10" name="__Vdly__t.e" dtype_id="2" vartype="my_t" origName="__Vdly__t__DOT__e"/>
|
||||
<var fl="d67" loc="d,67,119,67,123" name="__Vtemp1" dtype_id="4" vartype="string" origName="__Vtemp1"/>
|
||||
<var fl="d77" loc="d,77,119,77,123" name="__Vtemp2" dtype_id="4" vartype="string" origName="__Vtemp2"/>
|
||||
<var fl="d87" loc="d,87,119,87,123" name="__Vtemp3" dtype_id="4" vartype="string" origName="__Vtemp3"/>
|
||||
<var fl="d67" loc="d,67,119,67,123" name="__Vtemp_h########__0" dtype_id="4" vartype="string" origName="__Vtemp_h########__0"/>
|
||||
<var fl="d77" loc="d,77,119,77,123" name="__Vtemp_h########__1" dtype_id="4" vartype="string" origName="__Vtemp_h########__1"/>
|
||||
<var fl="d87" loc="d,87,119,87,123" name="__Vtemp_h########__2" dtype_id="4" vartype="string" origName="__Vtemp_h########__2"/>
|
||||
<assignpre fl="d64" loc="d,64,3,64,4" dtype_id="5">
|
||||
<varref fl="d64" loc="d,64,3,64,4" name="t.e" dtype_id="5"/>
|
||||
<varref fl="d64" loc="d,64,3,64,4" name="__Vdly__t.e" dtype_id="5"/>
|
||||
|
|
@ -93,11 +93,11 @@
|
|||
</ccast>
|
||||
</and>
|
||||
</arraysel>
|
||||
<varref fl="d67" loc="d,67,119,67,123" name="__Vtemp1" dtype_id="4"/>
|
||||
<varref fl="d67" loc="d,67,119,67,123" name="__Vtemp_h########__0" dtype_id="4"/>
|
||||
</assign>
|
||||
<display fl="d67" loc="d,67,38,67,44" displaytype="$write">
|
||||
<sformatf fl="d67" loc="d,67,38,67,44" name="%%Error: t/t_enum_type_methods.v:67: got='%@' exp='E01' " dtype_id="4">
|
||||
<varref fl="d67" loc="d,67,119,67,123" name="__Vtemp1" dtype_id="4"/>
|
||||
<varref fl="d67" loc="d,67,119,67,123" name="__Vtemp_h########__0" dtype_id="4"/>
|
||||
</sformatf>
|
||||
</display>
|
||||
<stop fl="d67" loc="d,67,136,67,141"/>
|
||||
|
|
@ -343,11 +343,11 @@
|
|||
</ccast>
|
||||
</and>
|
||||
</arraysel>
|
||||
<varref fl="d77" loc="d,77,119,77,123" name="__Vtemp2" dtype_id="4"/>
|
||||
<varref fl="d77" loc="d,77,119,77,123" name="__Vtemp_h########__1" dtype_id="4"/>
|
||||
</assign>
|
||||
<display fl="d77" loc="d,77,38,77,44" displaytype="$write">
|
||||
<sformatf fl="d77" loc="d,77,38,77,44" name="%%Error: t/t_enum_type_methods.v:77: got='%@' exp='E03' " dtype_id="4">
|
||||
<varref fl="d77" loc="d,77,119,77,123" name="__Vtemp2" dtype_id="4"/>
|
||||
<varref fl="d77" loc="d,77,119,77,123" name="__Vtemp_h########__1" dtype_id="4"/>
|
||||
</sformatf>
|
||||
</display>
|
||||
<stop fl="d77" loc="d,77,136,77,141"/>
|
||||
|
|
@ -593,11 +593,11 @@
|
|||
</ccast>
|
||||
</and>
|
||||
</arraysel>
|
||||
<varref fl="d87" loc="d,87,119,87,123" name="__Vtemp3" dtype_id="4"/>
|
||||
<varref fl="d87" loc="d,87,119,87,123" name="__Vtemp_h########__2" dtype_id="4"/>
|
||||
</assign>
|
||||
<display fl="d87" loc="d,87,38,87,44" displaytype="$write">
|
||||
<sformatf fl="d87" loc="d,87,38,87,44" name="%%Error: t/t_enum_type_methods.v:87: got='%@' exp='E04' " dtype_id="4">
|
||||
<varref fl="d87" loc="d,87,119,87,123" name="__Vtemp3" dtype_id="4"/>
|
||||
<varref fl="d87" loc="d,87,119,87,123" name="__Vtemp_h########__2" dtype_id="4"/>
|
||||
</sformatf>
|
||||
</display>
|
||||
<stop fl="d87" loc="d,87,136,87,141"/>
|
||||
|
|
@ -845,7 +845,7 @@
|
|||
<cfunc fl="d22" loc="d,22,17,22,18" name="_initial__TOP__2">
|
||||
<var fl="d27" loc="d,27,11,27,14" name="t.all" dtype_id="4" vartype="string" origName="t__DOT__all"/>
|
||||
<var fl="d51" loc="d,51,17,51,18" name="t.unnamedblk1.e" dtype_id="2" vartype="my_t" origName="t__DOT__unnamedblk1__DOT__e"/>
|
||||
<var fl="d48" loc="d,48,123,48,127" name="__Vtemp4" dtype_id="4" vartype="string" origName="__Vtemp4"/>
|
||||
<var fl="d48" loc="d,48,123,48,127" name="__Vtemp_h########__0" dtype_id="4" vartype="string" origName="__Vtemp_h########__0"/>
|
||||
<assign fl="d22" loc="d,22,17,22,18" dtype_id="3">
|
||||
<const fl="d22" loc="d,22,17,22,18" name="32'sh0" dtype_id="7"/>
|
||||
<varref fl="d22" loc="d,22,17,22,18" name="t.cyc" dtype_id="3"/>
|
||||
|
|
@ -1298,11 +1298,11 @@
|
|||
</ccast>
|
||||
</and>
|
||||
</arraysel>
|
||||
<varref fl="d48" loc="d,48,123,48,127" name="__Vtemp4" dtype_id="4"/>
|
||||
<varref fl="d48" loc="d,48,123,48,127" name="__Vtemp_h########__0" dtype_id="4"/>
|
||||
</assign>
|
||||
<display fl="d48" loc="d,48,42,48,48" displaytype="$write">
|
||||
<sformatf fl="d48" loc="d,48,42,48,48" name="%%Error: t/t_enum_type_methods.v:48: got='%@' exp='E03' " dtype_id="4">
|
||||
<varref fl="d48" loc="d,48,123,48,127" name="__Vtemp4" dtype_id="4"/>
|
||||
<varref fl="d48" loc="d,48,123,48,127" name="__Vtemp_h########__0" dtype_id="4"/>
|
||||
</sformatf>
|
||||
</display>
|
||||
<stop fl="d48" loc="d,48,140,48,145"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue