Rework Ast hashing to be stable (#2974)

Rework Ast hashing to be stable

Eliminated reliance on pointer values in AstNode hashes in order to make
them stable. This requires moving the sameHash functions into a visitor,
as nodes pointed to via members (and not child nodes) need to be hashed
themselves.

The hashes are now stable (as far as I could test them), and the impact
on verilation time is small enough not to be reliably measurable.
This commit is contained in:
Geza Lore 2021-05-21 14:34:27 +01:00 committed by GitHub
parent fd35492226
commit 8814111724
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 559 additions and 268 deletions

View File

@ -203,6 +203,7 @@ RAW_OBJS = \
V3GraphDfa.o \
V3GraphPathChecker.o \
V3GraphTest.o \
V3Hash.o \
V3Hasher.o \
V3HierBlock.o \
V3Inline.o \

View File

@ -970,20 +970,6 @@ bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ig
&& (ignNext || sameTreeIter(node1p->m_nextp, node2p->m_nextp, false, gateOnly)));
}
//======================================================================
// Static utilities
std::ostream& operator<<(std::ostream& os, const V3Hash& rhs) {
return os << std::hex << std::setw(2) << std::setfill('0') << rhs.depth() << "_"
<< std::setw(6) << std::setfill('0') << rhs.hshval();
}
V3Hash::V3Hash(const string& name) {
uint32_t val = 0;
for (const auto& c : name) val = val * 31 + c;
setBoth(1, val);
}
//======================================================================
// Debugging

View File

@ -1271,6 +1271,8 @@ public:
virtual ~AstNVisitor() { doDeletes(); }
/// Call visit()s on nodep
void iterate(AstNode* nodep);
/// Call visit()s on nodep
void iterateNull(AstNode* nodep);
/// Call visit()s on nodep's children
void iterateChildren(AstNode* nodep);
/// Call visit()s on nodep's children in backp() order
@ -1321,56 +1323,6 @@ inline std::ostream& operator<<(std::ostream& os, const AstNRelinker& rhs) {
return os;
}
//######################################################################
// V3Hash -- Node hashing for V3Combine
class V3Hash final {
// A hash of a tree of nodes, consisting of 8 bits with the number of nodes in the hash
// and 24 bit value hash of relevant information about the node.
// A value of 0 is illegal
uint32_t m_both;
static const uint32_t M24 = ((1 << 24) - 1);
void setBoth(uint32_t depth, uint32_t hshval) {
if (depth == 0) depth = 1;
if (depth > 255) depth = 255;
m_both = (depth << 24) | (hshval & M24);
}
public:
// METHODS
bool isIllegal() const { return m_both == 0; }
uint32_t fullValue() const { return m_both; }
uint32_t depth() const { return (m_both >> 24) & 255; }
uint32_t hshval() const { return m_both & M24; }
// OPERATORS
bool operator==(const V3Hash& rh) const { return m_both == rh.m_both; }
bool operator!=(const V3Hash& rh) const { return m_both != rh.m_both; }
bool operator<(const V3Hash& rh) const { return m_both < rh.m_both; }
// CONSTRUCTORS
class Illegal {}; // for creator type-overload selection
class FullValue {}; // for creator type-overload selection
explicit V3Hash(Illegal) { m_both = 0; }
// Saving and restoring inside a userp
explicit V3Hash(const VNUser& u) { m_both = u.toInt(); }
V3Hash operator+=(const V3Hash& rh) {
setBoth(depth() + rh.depth(), (hshval() * 31 + rh.hshval()));
return *this;
}
// Creating from raw data (sameHash functions)
V3Hash() { setBoth(1, 0); }
explicit V3Hash(uint32_t val) { setBoth(1, val); }
explicit V3Hash(const void* vp) { setBoth(1, cvtToHash(vp)); }
explicit V3Hash(const string& name);
V3Hash(V3Hash h1, V3Hash h2) { setBoth(1, h1.hshval() * 31 + h2.hshval()); }
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3) {
setBoth(1, (h1.hshval() * 31 + h2.hshval()) * 31 + h3.hshval());
}
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3, V3Hash h4) {
setBoth(1, ((h1.hshval() * 31 + h2.hshval()) * 31 + h3.hshval()) * 31 + h4.hshval());
}
};
std::ostream& operator<<(std::ostream& os, const V3Hash& rhs);
//######################################################################
// Callback base class to determine if node matches some formula
@ -1832,9 +1784,6 @@ public:
// statement is unlikely to be taken
virtual bool isUnlikely() const { return false; }
virtual int instrCount() const { return 0; }
virtual V3Hash sameHash() const {
return V3Hash(V3Hash::Illegal()); // Not a node that supports it
}
virtual bool same(const AstNode*) const { return true; }
// Iff has a data type; dtype() must be non null
virtual bool hasDType() const { return false; }
@ -1968,7 +1917,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
};
@ -2002,7 +1950,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
};
@ -2037,7 +1984,6 @@ 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 int instrCount() const override { return widthInstrs(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
};
@ -2076,7 +2022,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
};
@ -2180,7 +2125,6 @@ public:
void thsp(AstNode* nodep) { return setOp3p(nodep); }
void attrp(AstAttrOf* nodep) { return setOp4p((AstNode*)nodep); }
// METHODS
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
};
@ -2242,7 +2186,6 @@ public:
virtual bool hasDType() const override { return true; }
virtual bool cleanRhs() const { return true; }
virtual int instrCount() const override { return widthInstrs(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
virtual string verilogKwd() const override { return "="; }
virtual bool brokeLhsMustBeLvalue() const = 0;
@ -2267,7 +2210,6 @@ public:
AstNode* bodysp() const { return op4p(); } // op4 = body of loop
virtual bool isGateOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountBranch(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -2293,7 +2235,6 @@ public:
virtual bool isGateOptimizable() const override { return false; }
virtual bool isGateDedupable() const override { return true; }
virtual int instrCount() const override { return instrCountBranch(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
void branchPred(VBranchPred flag) { m_branchPred = flag; }
VBranchPred branchPred() const { return m_branchPred; }
@ -2390,7 +2331,6 @@ protected:
public:
ASTNODE_BASE_FUNCS(NodeText)
virtual void dump(std::ostream& str = std::cout) const override;
virtual V3Hash sameHash() const override { return V3Hash(text()); }
virtual bool same(const AstNode* samep) const override {
const AstNodeText* asamep = static_cast<const AstNodeText*>(samep);
return text() == asamep->text();
@ -2511,10 +2451,12 @@ private:
bool m_packed;
bool m_isFourstate;
MemberNameMap m_members;
const int m_uniqueNum;
protected:
AstNodeUOrStructDType(AstType t, FileLine* fl, VSigning numericUnpack)
: AstNodeDType{t, fl} {
: AstNodeDType{t, fl}
, m_uniqueNum{uniqueNumInc()} {
// VSigning::NOSIGN overloaded to indicate not packed
m_packed = (numericUnpack != VSigning::NOSIGN);
m_isFourstate = false; // V3Width computes
@ -2523,6 +2465,7 @@ protected:
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
@ -2601,9 +2544,6 @@ public:
&& rangenp()->sameTree(asamep->rangenp())
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
}
virtual V3Hash sameHash() const override {
return V3Hash(V3Hash(m_refDTypep), V3Hash(hi()), V3Hash(lo()));
}
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
@ -2688,7 +2628,6 @@ public:
virtual void cloneRelink() override;
virtual const char* broken() const override;
virtual int instrCount() const override { return instrCountCall(); }
virtual V3Hash sameHash() const override { return V3Hash(funcp()); }
virtual bool same(const AstNode* samep) const override {
const AstNodeCCall* asamep = static_cast<const AstNodeCCall*>(samep);
return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes());
@ -2983,6 +2922,9 @@ public:
// Inline AstNVisitor METHODS
inline void AstNVisitor::iterate(AstNode* nodep) { nodep->accept(*this); }
inline void AstNVisitor::iterateNull(AstNode* nodep) {
if (VL_LIKELY(nodep)) nodep->accept(*this);
}
inline void AstNVisitor::iterateChildren(AstNode* nodep) { nodep->iterateChildren(*this); }
inline void AstNVisitor::iterateChildrenBackwards(AstNode* nodep) {
nodep->iterateChildrenBackwards(*this);

View File

@ -170,7 +170,6 @@ public:
virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(num().toHash()); }
virtual bool same(const AstNode* samep) const override {
const AstConst* sp = static_cast<const AstConst*>(samep);
return num().isCaseEq(sp->num());
@ -226,7 +225,6 @@ public:
bool littleEndian() const { return leftConst() < rightConst(); }
virtual void dump(std::ostream& str) const override;
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -241,7 +239,6 @@ public:
ASTNODE_NODE_FUNCS(BracketRange)
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual string emitVerilog() { V3ERROR_NA_RETURN(""); }
virtual V3Hash sameHash() const override { return V3Hash(); }
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
@ -257,7 +254,6 @@ public:
ASTNODE_NODE_FUNCS(UnsizedRange)
virtual string emitC() { V3ERROR_NA_RETURN(""); }
virtual string emitVerilog() { return "[]"; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -473,27 +469,27 @@ private:
string m_name;
void* m_containerp; // In what scope is the name unique, so we can know what are duplicate
// definitions (arbitrary value)
int m_uniqueNum;
const int m_uniqueNum;
public:
AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType,
AstNodeDType* dtp)
: ASTGEN_SUPER(fl)
, m_name{name}
, m_containerp{containerp} {
, m_containerp{containerp}
, m_uniqueNum{uniqueNumInc()} {
childDTypep(dtp); // Only for parser
dtypep(nullptr); // V3Width will resolve
m_uniqueNum = uniqueNumInc();
}
ASTNODE_NODE_FUNCS(DefImplicitDType)
int uniqueNum() const { return m_uniqueNum; }
virtual bool same(const AstNode* samep) const override {
const AstDefImplicitDType* sp = static_cast<const AstDefImplicitDType*>(samep);
return m_uniqueNum == sp->m_uniqueNum;
return uniqueNum() == sp->uniqueNum();
}
virtual bool similarDType(AstNodeDType* samep) const override {
return type() == samep->type() && same(samep);
}
virtual V3Hash sameHash() const override { return V3Hash(m_uniqueNum); }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
@ -557,7 +553,6 @@ public:
}
virtual string prettyDTypeName() const override;
virtual void dumpSmall(std::ostream& str) const override;
virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
virtual AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); }
virtual bool isHeavy() const override { return true; }
@ -657,7 +652,6 @@ public:
}
virtual string prettyDTypeName() const override;
virtual void dumpSmall(std::ostream& str) const override;
virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); }
virtual bool isHeavy() const override { return true; }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
@ -775,7 +769,6 @@ public:
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
virtual void dumpSmall(std::ostream& str) const override;
virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
@ -873,9 +866,6 @@ private:
public:
ASTNODE_NODE_FUNCS(BasicDType)
virtual void dump(std::ostream& str) const override;
virtual V3Hash sameHash() const override {
return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi()));
}
// width/widthMin/numeric compared elsewhere
virtual bool same(const AstNode* samep) const override {
const AstBasicDType* sp = static_cast<const AstBasicDType*>(samep);
@ -983,9 +973,6 @@ public:
virtual bool similarDType(AstNodeDType* samep) const override {
return skipRefp()->similarDType(samep->skipRefp());
}
virtual V3Hash sameHash() const override {
return V3Hash(m_refDTypep);
} // node's type() included elsewhere
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
@ -1038,9 +1025,6 @@ public:
virtual bool similarDType(AstNodeDType* samep) const override {
return this == samep || (type() == samep->type() && same(samep));
}
virtual V3Hash sameHash() const override {
return V3Hash(V3Hash(m_classp), V3Hash(m_classOrPackagep));
}
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() : "<unlinked>"; }
@ -1096,7 +1080,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(m_cellp); }
virtual int widthAlignBytes() const override { return 1; }
virtual int widthTotalBytes() const override { return 1; }
FileLine* modportFileline() const { return m_modportFileline; }
@ -1156,7 +1139,6 @@ public:
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
virtual void dumpSmall(std::ostream& str) const override;
virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); }
virtual string prettyDTypeName() const override;
virtual bool isHeavy() const override { return true; }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
@ -1231,9 +1213,6 @@ public:
virtual bool similarDType(AstNodeDType* samep) const override {
return skipRefp()->similarDType(samep->skipRefp());
}
virtual V3Hash sameHash() const override {
return V3Hash(V3Hash(m_typedefp), V3Hash(m_classOrPackagep));
}
virtual void dump(std::ostream& str = std::cout) const override;
virtual string name() const override { return m_name; }
virtual string prettyDTypeName() const override {
@ -1403,7 +1382,6 @@ public:
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const override { return 1; }
virtual int widthTotalBytes() const override { return 1; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool isCompound() const override { return false; }
};
@ -1470,17 +1448,17 @@ class AstEnumDType final : public AstNodeDType {
private:
string m_name; // Name from upper typedef, if any
AstNodeDType* m_refDTypep; // Elements are of this type after V3Width
int m_uniqueNum;
const int m_uniqueNum;
public:
AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp)
: ASTGEN_SUPER(fl) {
: ASTGEN_SUPER(fl)
, m_uniqueNum{uniqueNumInc()} {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
addNOp2p(itemsp);
dtypep(nullptr); // V3Width will resolve
widthFromSub(subDTypep());
m_uniqueNum = uniqueNumInc();
}
ASTNODE_NODE_FUNCS(EnumDType)
virtual const char* broken() const override {
@ -1491,12 +1469,12 @@ public:
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* sp = static_cast<const AstEnumDType*>(samep);
return m_uniqueNum == sp->m_uniqueNum;
return uniqueNum() == sp->uniqueNum();
}
virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
virtual V3Hash sameHash() const override { return V3Hash(m_uniqueNum); }
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Data type
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
@ -1594,7 +1572,6 @@ public:
return true;
} // esp for V3Const::ifSameAssign
virtual bool isPredictOptimizable() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
virtual int instrCount() const override { return widthInstrs(); }
// Special operators
@ -1636,7 +1613,6 @@ public:
return true;
} // esp for V3Const::ifSameAssign
virtual bool isPredictOptimizable() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
virtual int instrCount() const override { return widthInstrs(); }
};
@ -1664,7 +1640,6 @@ public:
virtual bool cleanRhs() const override { return true; }
virtual bool sizeMattersLhs() const override { return false; }
virtual bool sizeMattersRhs() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -1678,7 +1653,6 @@ public:
addNOp2p(elementsp);
}
ASTNODE_NODE_FUNCS(SelLoopVars)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
virtual bool maybePointedTo() const override { return false; }
AstNode* fromp() const { return op1p(); }
@ -1770,7 +1744,6 @@ public:
virtual bool sizeMattersLhs() const override { return false; }
virtual bool sizeMattersRhs() const override { return false; }
virtual bool sizeMattersThs() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
virtual int instrCount() const override {
return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10);
@ -1816,7 +1789,6 @@ public:
virtual bool sizeMattersLhs() const override { return false; }
virtual bool sizeMattersRhs() const override { return false; }
virtual bool sizeMattersThs() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
virtual int instrCount() const override { return 10; } // Removed before matters
AstNode* fromp() const {
@ -1888,7 +1860,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(m_name); }
virtual bool same(const AstNode* samep) const override {
const AstCMethodHard* asamep = static_cast<const AstCMethodHard*>(samep);
return (m_name == asamep->m_name);
@ -2273,7 +2244,6 @@ public:
}
virtual string name() const override { return m_name; } // * = Scope name
ASTNODE_NODE_FUNCS(DefParam)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
AstNode* rhsp() const { return op1p(); } // op1 = Assign from
string path() const { return m_path; }
@ -2410,9 +2380,6 @@ public:
}
ASTNODE_NODE_FUNCS(VarRef)
virtual void dump(std::ostream& str) const override;
virtual V3Hash sameHash() const override {
return V3Hash(V3Hash(varp()->name()), V3Hash(hiernameToProt()));
}
virtual bool same(const AstNode* samep) const override {
return same(static_cast<const AstVarRef*>(samep));
}
@ -2469,7 +2436,6 @@ public:
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return true; }
virtual int instrCount() const override { return widthInstrs(); }
virtual V3Hash sameHash() const override { return V3Hash(V3Hash(varp()), V3Hash(dotted())); }
virtual bool same(const AstNode* samep) const override {
const AstVarXRef* asamep = static_cast<const AstVarXRef*>(samep);
return (hiernameToProt() == asamep->hiernameToProt()
@ -2545,7 +2511,6 @@ public:
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; }
virtual V3Hash sameHash() const override { return V3Hash(); }
void exprp(AstNode* nodep) { addOp1p(nodep); }
// op1 = Expression connected to pin, nullptr if unconnected
AstNode* exprp() const { return op1p(); }
@ -2695,7 +2660,6 @@ public:
}
virtual void dump(std::ostream& str) const override;
virtual string name() const override { return m_name; }
virtual V3Hash sameHash() const override { return V3Hash(m_name); }
virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return false; }
@ -3005,7 +2969,6 @@ public:
ASTNODE_NODE_FUNCS(ParseRef)
virtual void dump(std::ostream& str) const override;
virtual string name() const override { return m_name; } // * = Var name
virtual V3Hash sameHash() const override { return V3Hash(V3Hash(m_expect), V3Hash(m_name)); }
virtual bool same(const AstNode* samep) const override {
const AstParseRef* asamep = static_cast<const AstParseRef*>(samep);
return (expect() == asamep->expect() && m_name == asamep->m_name);
@ -3047,7 +3010,6 @@ public:
return (m_classOrPackageNodep
== static_cast<const AstClassOrPackageRef*>(samep)->m_classOrPackageNodep);
}
virtual V3Hash sameHash() const override { return V3Hash(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; }
@ -3171,7 +3133,6 @@ public:
addNOp2p(exprp);
}
ASTNODE_NODE_FUNCS(WithParse)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
//
AstNode* funcrefp() const { return op1p(); }
@ -3192,7 +3153,6 @@ public:
, m_name{name}
, m_index(index) {}
ASTNODE_NODE_FUNCS(LambdaArgRef)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
virtual string emitVerilog() override { return name(); }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
@ -3220,7 +3180,6 @@ public:
addNOp3p(exprp);
}
ASTNODE_NODE_FUNCS(With)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
virtual bool hasDType() const override { return true; }
virtual const char* broken() const override {
@ -3269,7 +3228,6 @@ public:
, m_edgeType{VEdgeType::ET_NEVER} {}
ASTNODE_NODE_FUNCS(SenItem)
virtual void dump(std::ostream& str) const override;
virtual V3Hash sameHash() const override { return V3Hash(edgeType()); }
virtual bool same(const AstNode* samep) const override {
return edgeType() == static_cast<const AstSenItem*>(samep)->edgeType();
}
@ -3306,7 +3264,6 @@ public:
ASTNODE_NODE_FUNCS(SenTree)
virtual void dump(std::ostream& str) const override;
virtual bool maybePointedTo() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
bool isMulti() const { return m_multi; }
// op1 = Sensitivity list
AstSenItem* sensesp() const { return VN_CAST(op1p(), SenItem); }
@ -3379,7 +3336,6 @@ public:
addNOp2p(bodysp);
}
ASTNODE_NODE_FUNCS(AlwaysPublic)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
//
AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list
@ -3525,7 +3481,6 @@ public:
virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode*) const override { return true; }
};
@ -3543,7 +3498,6 @@ public:
, m_name{name} {}
ASTNODE_NODE_FUNCS(Comment)
virtual string name() const override { return m_name; } // * = Text
virtual V3Hash sameHash() const override { return V3Hash(); } // Ignore name in comments
virtual bool same(const AstNode* samep) const override {
return true;
} // Ignore name in comments
@ -3623,7 +3577,6 @@ 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 V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override {
const AstCoverDecl* asamep = static_cast<const AstCoverDecl*>(samep);
return (fileline() == asamep->fileline() && linescov() == asamep->linescov()
@ -3657,7 +3610,6 @@ public:
}
virtual void dump(std::ostream& str) const override;
virtual int instrCount() const override { return 1 + 2 * instrCountLd(); }
virtual V3Hash sameHash() const override { return V3Hash(declp()); }
virtual bool same(const AstNode* samep) const override {
return declp() == static_cast<const AstCoverInc*>(samep)->declp();
}
@ -3681,7 +3633,6 @@ public:
}
ASTNODE_NODE_FUNCS(CoverToggle)
virtual int instrCount() const override { return 3 + instrCountBranch() + instrCountLd(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return true; }
@ -3703,7 +3654,6 @@ public:
setOp1p(lhsp);
}
ASTNODE_NODE_FUNCS(Delay)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
//
AstNode* lhsp() const { return op1p(); } // op2 = Statements to evaluate
@ -3820,7 +3770,6 @@ public:
ASTNODE_NODE_FUNCS(SFormatF)
virtual string name() const override { return m_text; }
virtual int instrCount() const override { return instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(text()); }
virtual bool hasDType() const override { return true; }
virtual bool same(const AstNode* samep) const override {
return text() == static_cast<const AstSFormatF*>(samep)->text();
@ -3882,7 +3831,6 @@ public:
} // SPECIAL: $display has 'visual' ordering
virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(displayType()); }
virtual bool same(const AstNode* samep) const override {
return displayType() == static_cast<const AstDisplay*>(samep)->displayType();
}
@ -3915,7 +3863,6 @@ public:
virtual bool isPredictOptimizable() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool cleanOut() const { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
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
@ -3949,7 +3896,6 @@ public:
} // SPECIAL: $display has 'visual' ordering
virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(displayType()); }
virtual bool same(const AstNode* samep) const override {
return displayType() == static_cast<const AstElabDisplay*>(samep)->displayType();
}
@ -3988,7 +3934,6 @@ public:
virtual bool isOutputter() const override { return false; }
virtual bool cleanOut() const { return false; }
virtual int instrCount() const override { return instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
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_CAST(op1p(), SFormatF); }
@ -4012,7 +3957,6 @@ public:
virtual bool isPure() const override { return true; }
virtual bool isOutputter() const override { return false; }
virtual int instrCount() const override { return 0; }
virtual V3Hash sameHash() const override { return V3Hash(); }
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
@ -4054,7 +3998,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
@ -4077,7 +4020,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op1p(); }
AstNode* filenamep() const { return op2p(); }
@ -4100,7 +4042,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op1p(); }
AstNode* filenamep() const { return op2p(); }
@ -4121,7 +4062,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
@ -4150,7 +4090,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* memp() const { return op1p(); }
void memp(AstNode* nodep) { setOp1p(nodep); }
@ -4180,7 +4119,6 @@ public:
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual bool cleanOut() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
@ -4204,7 +4142,6 @@ public:
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual bool cleanOut() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
@ -4231,7 +4168,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* filep() const { return op2p(); }
void filep(AstNode* nodep) { setOp2p(nodep); }
@ -4265,7 +4201,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(text()); }
virtual bool same(const AstNode* samep) const override {
return text() == static_cast<const AstFScanF*>(samep)->text();
}
@ -4301,7 +4236,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(text()); }
virtual bool same(const AstNode* samep) const override {
return text() == static_cast<const AstSScanF*>(samep)->text();
}
@ -4332,7 +4266,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override {
return isHex() == static_cast<const AstNodeReadWriteMem*>(samep)->isHex();
}
@ -4380,7 +4313,6 @@ public:
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 instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(m_off); }
virtual bool same(const AstNode* samep) const override {
return m_off == static_cast<const AstMonitorOff*>(samep)->m_off;
}
@ -4401,7 +4333,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* lhsp() const { return op1p(); }
};
@ -4423,7 +4354,6 @@ public:
virtual bool isOutputter() const override { return true; }
virtual bool isUnlikely() const override { return true; }
virtual bool cleanOut() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* lhsp() const { return op1p(); }
};
@ -4445,7 +4375,6 @@ public:
virtual bool isHeavy() const override { return true; }
virtual bool isPredictOptimizable() const override { return false; }
virtual bool cleanOut() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* searchp() const { return op1p(); } // op1 = Search expression
void searchp(AstNode* nodep) { setOp1p(nodep); }
@ -4471,7 +4400,6 @@ public:
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual bool cleanOut() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(text()); }
virtual bool same(const AstNode* samep) const override {
return text() == static_cast<const AstTestPlusArgs*>(samep)->text();
}
@ -4498,7 +4426,6 @@ public:
AstNode* bodysp() const { return op4p(); } // op4 = body of loop
virtual bool isGateOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountBranch(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -4516,7 +4443,6 @@ public:
return false;
} // Not relevant - converted to FOR
virtual int instrCount() const override { return instrCountBranch(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -4550,7 +4476,6 @@ public:
void addIncsp(AstNode* newp) { addOp4p(newp); }
virtual bool isGateOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountBranch(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
// Stop statement searchback here
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp) override;
@ -4564,7 +4489,6 @@ public:
: ASTGEN_SUPER(fl) {}
ASTNODE_NODE_FUNCS(Break)
virtual string verilogKwd() const override { return "break"; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool isBrancher() const override {
return true; // SPECIAL: We don't process code after breaks
}
@ -4576,7 +4500,6 @@ public:
: ASTGEN_SUPER(fl) {}
ASTNODE_NODE_FUNCS(Continue)
virtual string verilogKwd() const override { return "continue"; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool isBrancher() const override {
return true; // SPECIAL: We don't process code after breaks
}
@ -4621,7 +4544,6 @@ public:
}
ASTNODE_NODE_FUNCS(Return)
virtual string verilogKwd() const override { return "return"; }
virtual V3Hash sameHash() const override { return V3Hash(); }
AstNode* lhsp() const { return op1p(); }
virtual bool isBrancher() const override {
return true; // SPECIAL: We don't process code after breaks
@ -4674,7 +4596,6 @@ public:
ASTNODE_NODE_FUNCS(JumpBlock)
virtual int instrCount() const override { return 0; }
virtual bool maybePointedTo() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
// op1 = Statements
AstNode* stmtsp() const { return op1p(); } // op1 = List of statements
@ -4709,7 +4630,6 @@ public:
}
virtual void dump(std::ostream& str) const override;
virtual int instrCount() const override { return 0; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override {
return blockp() == static_cast<const AstJumpLabel*>(samep)->blockp();
}
@ -4737,7 +4657,6 @@ public:
}
virtual void dump(std::ostream& str) const override;
virtual int instrCount() const override { return instrCountBranch(); }
virtual V3Hash sameHash() const override { return V3Hash(labelp()); }
virtual bool same(const AstNode* samep) const override {
return labelp() == static_cast<const AstJumpGo*>(samep)->labelp();
}
@ -4795,7 +4714,6 @@ public:
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual int instrCount() const override { return widthInstrs(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -4815,7 +4733,6 @@ public:
virtual bool cleanOut() const override { return true; }
virtual int instrCount() const override { return widthInstrs(); }
AstNode* defaultp() const { return op1p(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
class AstSetAssoc final : public AstNodeMath {
@ -4838,7 +4755,6 @@ public:
AstNode* lhsp() const { return op1p(); }
AstNode* keyp() const { return op2p(); }
AstNode* valuep() const { return op3p(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -4860,7 +4776,6 @@ public:
virtual int instrCount() const override { return widthInstrs(); }
AstNode* lhsp() const { return op1p(); } // op1 = expression
AstNode* rhsp() const { return op2p(); } // op2 = expression
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -4882,7 +4797,6 @@ public:
virtual int instrCount() const override { return widthInstrs(); }
AstNode* lhsp() const { return op1p(); } // op1 = expression
AstNode* rhsp() const { return op2p(); } // op2 = expression
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -4974,7 +4888,6 @@ public:
ASTNODE_NODE_FUNCS(InitItem)
virtual bool maybePointedTo() const override { return true; }
virtual bool hasDType() const override { return false; } // See valuep()'s dtype instead
virtual V3Hash sameHash() const override { return V3Hash(); }
AstNode* valuep() const { return op1p(); } // op1 = Value
void valuep(AstNode* nodep) { addOp1p(nodep); }
};
@ -5012,7 +4925,6 @@ public:
}
}
virtual bool hasDType() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
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
@ -5061,7 +4973,6 @@ public:
AstNew(FileLine* fl, AstNode* pinsp)
: ASTGEN_SUPER(fl, false, "new", pinsp) {}
ASTNODE_NODE_FUNCS(New)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool cleanOut() const { return true; }
virtual bool same(const AstNode* samep) const override { return true; }
virtual bool hasDType() const override { return true; }
@ -5079,7 +4990,6 @@ public:
setNOp1p(rhsp);
}
ASTNODE_NODE_FUNCS(NewCopy)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual string emitVerilog() override { return "new"; }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return true; }
@ -5100,7 +5010,6 @@ public:
setNOp2p(rhsp);
}
ASTNODE_NODE_FUNCS(NewDynamic)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual string emitVerilog() override { return "new"; }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return true; }
@ -5121,7 +5030,6 @@ public:
, m_pragType{pragType} {}
ASTNODE_NODE_FUNCS(Pragma)
AstPragmaType pragType() const { return m_pragType; } // *=type of the pragma
virtual V3Hash sameHash() const override { return V3Hash(pragType()); }
virtual bool isPredictOptimizable() const override { return false; }
virtual bool same(const AstNode* samep) const override {
return pragType() == static_cast<const AstPragma*>(samep)->pragType();
@ -5145,7 +5053,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual int instrCount() const override { return instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
VTimescale timeunit() const { return m_timeunit; }
};
@ -5163,7 +5070,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(fileline()->lineno()); }
virtual bool same(const AstNode* samep) const override {
return fileline() == samep->fileline();
}
@ -5182,7 +5088,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(fileline()->lineno()); }
virtual bool same(const AstNode* samep) const override {
return fileline() == samep->fileline();
}
@ -5205,7 +5110,6 @@ public:
virtual bool cleanOut() const override { return true; }
virtual bool cleanLhs() const override { return true; }
virtual bool sizeMattersLhs() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(fileline()->lineno()); }
virtual bool same(const AstNode* samep) const override {
return fileline() == samep->fileline();
}
@ -5226,7 +5130,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return false; }
virtual int instrCount() const override { return 0; }
virtual V3Hash sameHash() const override { return V3Hash(); }
AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); }
AstNode* stmtsp() const { return op2p(); }
};
@ -5249,7 +5152,6 @@ public:
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual int instrCount() const override { return instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
AstNode* unitsp() const { return op1p(); }
AstNode* precisionp() const { return op2p(); }
AstNode* suffixp() const { return op3p(); }
@ -5338,7 +5240,6 @@ public:
virtual void dump(std::ostream& str) const override;
virtual int instrCount() const override { return 10 + 2 * instrCountLd(); }
virtual bool hasDType() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(declp()); }
virtual bool same(const AstNode* samep) const override {
return declp() == static_cast<const AstTraceInc*>(samep)->declp();
}
@ -5413,7 +5314,6 @@ public:
AstNode* fromp() const { return op1p(); }
AstNode* dimp() const { return op2p(); }
AstAttrType attrType() const { return m_attrType; }
virtual V3Hash sameHash() const override { return V3Hash(m_attrType); }
virtual void dump(std::ostream& str = std::cout) const override;
};
@ -5432,7 +5332,6 @@ public:
dtypeSetUInt64();
}
ASTNODE_NODE_FUNCS(ScopeName)
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override {
return m_dpiExport == static_cast<const AstScopeName*>(samep)->m_dpiExport;
}
@ -5517,7 +5416,6 @@ public:
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstNode* seedp() const { return op1p(); }
bool reset() const { return m_reset; }
@ -5565,7 +5463,6 @@ public:
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountTime(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
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; }
@ -5587,7 +5484,6 @@ public:
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountTime(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
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; }
@ -5613,7 +5509,6 @@ public:
virtual bool isSubstOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual int instrCount() const override { return instrCountPli(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -6175,7 +6070,6 @@ public:
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 V3Hash sameHash() const override { return V3Hash(size()); }
virtual bool same(const AstNode* samep) const override {
return size() == static_cast<const AstCCast*>(samep)->size();
}
@ -6198,7 +6092,6 @@ public:
virtual bool cleanOut() const override { return true; }
virtual bool cleanLhs() const override { return true; }
virtual bool sizeMattersLhs() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -6241,7 +6134,6 @@ public:
AstNode* filep() const { return op1p(); }
void strp(AstNode* nodep) { setOp2p(nodep); }
AstNode* strp() const { return op2p(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8364,7 +8256,6 @@ public:
AstNode* exprp() const { return op1p(); } // op1 = expression
AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8388,7 +8279,6 @@ public:
AstNode* ticksp() const { return op2p(); } // op2 = ticks or nullptr means 1
AstSenTree* sentreep() const { return VN_CAST(op4p(), SenTree); } // op4 = clock domain
void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8410,7 +8300,6 @@ public:
AstNode* exprp() const { return op1p(); } // op1 = expression
AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8430,7 +8319,6 @@ public:
virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
virtual int instrCount() const override { return 0; }
AstNode* exprp() const { return op1p(); } // op1 = expression
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8452,7 +8340,6 @@ public:
AstNode* exprp() const { return op1p(); } // op1 = expression
AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain
void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8527,7 +8414,6 @@ public:
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
AstSenTree* sentreep() const { return VN_CAST(op4p(), SenTree); } // op4 = clock domain
void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8591,7 +8477,6 @@ public:
}
ASTNODE_BASE_FUNCS(NodeCoverOrAssert)
virtual string name() const override { return m_name; } // * = Var name
virtual V3Hash sameHash() const override { return V3Hash(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;
@ -8750,7 +8635,6 @@ public:
virtual bool isPredictOptimizable() const override { return false; }
virtual bool isPure() const override { return false; }
virtual bool isOutputter() const override { return true; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
@ -8771,7 +8655,6 @@ public:
ASTNODE_BASE_FUNCS(NodeFile)
virtual void dump(std::ostream& str) const override;
virtual string name() const override { return m_name; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
void tblockp(AstTextBlock* tblockp) { setOp1p(tblockp); }
AstTextBlock* tblockp() { return VN_CAST(op1p(), TextBlock); }
@ -8885,7 +8768,6 @@ public:
}
virtual bool maybePointedTo() const override { return true; }
virtual void dump(std::ostream& str = std::cout) const override;
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override {
const AstCFunc* asamep = static_cast<const AstCFunc*>(samep);
return ((funcType() == asamep->funcType()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
@ -9023,7 +8905,6 @@ public:
}
ASTNODE_NODE_FUNCS(CReturn)
virtual int instrCount() const override { return widthInstrs(); }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
//
AstNode* lhsp() const { return op1p(); }
@ -9055,7 +8936,6 @@ public:
virtual bool cleanOut() const override { return m_cleanOut; }
virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual V3Hash sameHash() const override { return V3Hash(); }
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
@ -9073,7 +8953,6 @@ public:
ASTNODE_NODE_FUNCS(CReset)
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
AstVarRef* varrefp() const { return VN_CAST(op1p(), VarRef); } // op1 = varref to reset
};
@ -9092,7 +8971,6 @@ public:
ASTNODE_NODE_FUNCS(CStmt)
virtual bool isGateOptimizable() const override { return false; }
virtual bool isPredictOptimizable() const override { return false; }
virtual V3Hash sameHash() const override { return V3Hash(); }
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

View File

@ -132,8 +132,7 @@ private:
// Remove calls to empty function
UASSERT_OBJ(!oldfuncp->user3(), oldfuncp, "Should not be processed yet");
UINFO(5, " Drop empty CFunc " << std::hex << V3Hash(oldfuncp->user4p()) << " "
<< oldfuncp << endl);
UINFO(5, " Drop empty CFunc " << itr.first << " " << oldfuncp << endl);
oldfuncp->user3SetOnce(); // Mark replaced
m_call.replaceFunc(oldfuncp, nullptr);
oldfuncp->unlinkFrBack();
@ -161,10 +160,8 @@ private:
if (!newfuncp->sameTree(oldfuncp)) continue; // Different functions
// Replace calls to oldfuncp with calls to newfuncp
UINFO(5, " Replace CFunc " << std::hex << V3Hash(newfuncp->user4p()) << " "
<< newfuncp << endl);
UINFO(5, " with " << std::hex << V3Hash(oldfuncp->user4p()) << " "
<< oldfuncp << endl);
UINFO(5, " Replace CFunc " << newIt->first << " " << newfuncp << endl);
UINFO(5, " with " << oldIt->first << " " << oldfuncp << endl);
++m_cfuncsCombined;
oldfuncp->user3SetOnce(); // Mark replaced
m_call.replaceFunc(oldfuncp, newfuncp);

View File

@ -30,11 +30,6 @@
//######################################################################
// V3DupFinder class functions
bool V3DupFinder::sameNodes(AstNode* node1p, AstNode* node2p) {
return m_hasher(node1p) == m_hasher(node2p) // Same hash
&& node1p->sameTree(node2p); // Same tree
}
V3DupFinder::iterator V3DupFinder::findDuplicate(AstNode* nodep, V3DupFinderUserSame* checkp) {
const auto& er = equal_range(m_hasher(nodep));
for (iterator it = er.first; it != er.second; ++it) {

View File

@ -67,10 +67,6 @@ public:
// Insert node into data structure
iterator insert(AstNode* nodep) { return emplace(m_hasher(nodep), nodep); }
// Check if nodes are the same (same as node1p->sameTree(node2p),
// but first checks the hashes are equal for speed)
bool sameNodes(AstNode* node1p, AstNode* node2p);
// Return duplicate, if one was inserted, with optional user check for sameness
iterator findDuplicate(AstNode* nodep, V3DupFinderUserSame* checkp = nullptr);

View File

@ -919,16 +919,28 @@ private:
VL_DEBUG_FUNC; // Declare debug()
bool sameHash(AstNode* node1p, AstNode* node2p) {
return node1p //
&& node2p //
&& !node1p->sameHash().isIllegal() //
&& !node2p->sameHash().isIllegal() //
&& m_dupFinder.sameNodes(node1p, node2p);
}
bool same(AstNode* node1p, AstNode* node2p) {
return node1p == node2p || sameHash(node1p, 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
// number of comparisons (number of pairs). AstNode::sameTree itself, is O(sizeOfTree) in
// the worst case, which happens if the operands of sameTree are indeed identical copies,
// which means this line is O(n^2*sizeOfTree), iff you are comparing identical copies of
// the same tree. In practice the identity comparison over the pointers, and the short
// circuiting in sameTree means that for comparing the same tree instance to itself, or
// trees of different types/shapes is a lot closer to O(1), so this 'same' function is
// Omega(n^2) and O(n^2*sizeOfTree), and in practice as we are mostly comparing the same
// instance to itself or different trees, the complexity should be closer to the lower
// bound.
//
// Also if you see where this 'same' function is used within isSame, it's only ever
// comparing AstActive nodes, which are very likely not to compare equals (and for the
// purposes of V3Gate, we probably only care about them either being identical instances,
// or having the same sensitivities anyway, so if this becomes a problem, it can be
// improved which should also speed things up), and AstNodeMath for if conditions, which
// are hopefully small, and to be safe they should probably be only considered same when
// identical instances (otherwise if writing the condition between 2 ifs don't really
// merge).
return node1p == node2p || (node1p && node1p->sameTree(node2p));
}
public:

27
src/V3Hash.cpp Normal file
View File

@ -0,0 +1,27 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Hash calculation
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2021 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
//
//*************************************************************************
#include "V3Hash.h"
#include <functional>
#include <iomanip>
V3Hash::V3Hash(const std::string& val)
: m_value{static_cast<uint32_t>(std::hash<std::string>{}(val))} {}
std::ostream& operator<<(std::ostream& os, const V3Hash& rhs) {
return os << std::hex << std::setw(8) << std::setfill('0') << rhs.value();
}

65
src/V3Hash.h Normal file
View File

@ -0,0 +1,65 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Hash calculation
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2021 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_V3HASH_H_
#define VERILATOR_V3HASH_H_
#include <cstdint>
#include <string>
//######################################################################
// V3Hash -- Generic hashing
class V3Hash final {
// A 32-bit hash value. A value of 0 is illegal.
uint32_t m_value;
public:
// METHODS
uint32_t value() const { return m_value; }
// OPERATORS
bool operator==(const V3Hash& rh) const { return m_value == rh.m_value; }
bool operator!=(const V3Hash& rh) const { return m_value != rh.m_value; }
bool operator<(const V3Hash& rh) const { return m_value < rh.m_value; }
V3Hash operator+(uint32_t value) const {
const uint64_t prod = (static_cast<uint64_t>(m_value) * 31) + value;
return V3Hash(static_cast<uint32_t>(prod ^ (prod >> 32)));
}
V3Hash operator+(int32_t value) const { return *this + static_cast<uint32_t>(value); }
V3Hash operator+(const V3Hash& that) const { return *this + that.m_value; }
V3Hash& operator+=(const V3Hash& that) {
*this = *this + that.m_value;
return *this;
}
V3Hash& operator+=(uint32_t value) { return *this += V3Hash(value); }
V3Hash& operator+=(int32_t value) { return *this += V3Hash(value); }
V3Hash& operator+=(const std::string& that) { return *this += V3Hash(that); }
// CONSTRUCTORS
V3Hash()
: m_value{1} {}
explicit V3Hash(uint32_t val)
: m_value{val | 1} {}
explicit V3Hash(int32_t val)
: m_value{static_cast<uint32_t>(val)} {}
explicit V3Hash(const std::string& val);
};
std::ostream& operator<<(std::ostream& os, const V3Hash& rhs);
#endif // Guard

View File

@ -1,6 +1,6 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Hashed common code into functions
// DESCRIPTION: Verilator: AstNode hash computation
//
// Code available from: https://verilator.org
//
@ -19,6 +19,8 @@
#include "V3Hasher.h"
#include <functional>
//######################################################################
// Visitor that computes node hashes
@ -29,38 +31,426 @@ private:
// AstUser4InUse in V3Hasher.h
// STATE
V3Hash m_lowerHash; // Hash of the statement we're building
V3Hash m_hash; // Hash value accumulator
const bool m_cacheInUser4; // Use user4 to cache each V3Hash?
// METHODS
VL_DEBUG_FUNC; // Declare debug()
//--------------------
virtual void visit(AstVar*) override {}
virtual void visit(AstTypedef*) override {}
virtual void visit(AstParamTypeDType*) override {}
V3Hash hashNodeAndIterate(AstNode* nodep, bool hashDType, bool hashChildren,
std::function<void()>&& f) {
if (m_cacheInUser4 && nodep->user4()) {
return V3Hash(nodep->user4());
} else {
VL_RESTORER(m_hash);
// Reset accumulator
m_hash = V3Hash(nodep->type()); // Node type
f(); // Node specific hash
if (hashDType && nodep != nodep->dtypep()) iterateNull(nodep->dtypep()); // Node dtype
if (hashChildren) iterateChildrenConst(nodep); // Children
if (m_cacheInUser4) nodep->user4(m_hash.value());
return m_hash;
}
}
// VISITORS
constexpr static bool HASH_DTYPE = true;
constexpr static bool HASH_CHILDREN = true;
// Each visitor below contributes to the hash any node specific content
// that is not dependent on either of the following, as these are
// included by default by hashNode:
// - Node type (as given by AstNode::type())
// - Node dtype (unless !hashDType)
// - child nodes (unless !hashChildren)
//
// The hash must be stable, which means in particular it cannot rely on
// pointer values, or any other value that might differ between separate
// invocations of Verilator over the same design.
//
// Note there is a circularity problem where some child nodes can back
// to their ancestral nodes via member pointers, which can lead to an
// infinite traversal. To break this, nodes that are subject to such
// referencing and represent code which can reasonably be assumed not to
// be equivalent to any other code, are hashed either by name (e.g.:
// AstNodeModule), or by unique identifier (e.g.: AstNodeUOrStructDType).
//------------------------------------------------------------
// AstNode - Warns to help find missing cases
virtual void visit(AstNode* nodep) override {
V3Hash thisHash;
if (!m_cacheInUser4 || !nodep->user4()) {
VL_RESTORER(m_lowerHash);
{
m_lowerHash = nodep->sameHash();
UASSERT_OBJ(!m_lowerHash.isIllegal(), nodep,
"sameHash function undefined (returns 0) for node under CFunc.");
// For identical nodes, the type should be the same thus
// dtypep should be the same too
m_lowerHash = V3Hash(m_lowerHash,
V3Hash(V3Hash(nodep->type() << 6), V3Hash(nodep->dtypep())));
// Now update m_lowerHash for our children's (and next children) contributions
iterateChildrenConst(nodep);
// Store the hash value
if (m_cacheInUser4) { nodep->user4(m_lowerHash.fullValue()); }
thisHash = m_lowerHash;
#if VL_DEBUG
UINFO(0, "%Warning: Hashing node as AstNode: " << nodep);
#endif
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
//------------------------------------------------------------
// AstNodeDType
virtual 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 {
m_hash += hashNodeAndIterate(nodep, false, false, [=]() { //
m_hash += nodep->uniqueNum();
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstDefImplicitDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->uniqueNum();
});
}
virtual void visit(AstAssocArrayDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() {
iterateNull(nodep->virtRefDTypep());
iterateNull(nodep->virtRefDType2p());
});
}
virtual void visit(AstDynArrayDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->virtRefDTypep());
});
}
virtual void visit(AstUnsizedArrayDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->virtRefDTypep());
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
iterateNull(nodep->virtRefDTypep());
});
}
virtual void visit(AstClassRefDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->classp());
});
}
virtual void visit(AstIfaceRefDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->cellp());
});
}
virtual void visit(AstQueueDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->virtRefDTypep());
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstEnumDType* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, false, [=]() { //
m_hash += nodep->uniqueNum();
});
}
//------------------------------------------------------------
// AstNodeMath
virtual void visit(AstNodeMath* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstConst* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->num().toHash();
});
}
virtual void visit(AstNullCheck* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstCCast* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->size();
});
}
virtual void visit(AstVarRef* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {
if (nodep->varScopep()) {
iterateNull(nodep->varScopep());
} else {
iterateNull(nodep->varp());
m_hash += nodep->hiernameToProt();
}
}
// Update what will become the above node's hash
m_lowerHash += m_cacheInUser4 ? V3Hash(nodep->user4()) : thisHash;
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstFScanF* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->text();
});
}
virtual void visit(AstSScanF* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->text();
});
}
virtual void visit(AstTestPlusArgs* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->text();
});
}
//------------------------------------------------------------
// AstNodeStmt
virtual void visit(AstNodeStmt* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstNodeText* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
m_hash += nodep->text();
});
}
virtual void visit(AstNodeCCall* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->funcp());
});
}
virtual void visit(AstNodeFTaskRef* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() {
iterateNull(nodep->taskp());
iterateNull(nodep->classOrPackagep());
});
}
virtual void visit(AstCMethodHard* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstCoverInc* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->declp());
});
}
virtual void visit(AstDisplay* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
m_hash += nodep->displayType();
});
}
virtual void visit(AstMonitorOff* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
m_hash += nodep->off();
});
}
virtual void visit(AstJumpGo* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->labelp());
});
}
virtual void visit(AstTraceInc* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
iterateNull(nodep->declp());
});
}
virtual void visit(AstNodeCoverOrAssert* nodep) override {
m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
//------------------------------------------------------------
// AstNode direct descendents
virtual void visit(AstNodeRange* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstNodeModule* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [=]() {
m_hash += nodep->origName();
m_hash += nodep->hierName();
});
}
virtual void visit(AstNodePreSel* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstClassExtends* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstSelLoopVars* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstDefParam* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstArg* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
iterateNull(nodep->classOrPackageNodep());
});
}
virtual void visit(AstSenItem* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->edgeType();
});
}
virtual void visit(AstSenTree* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstSFormatF* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->text();
});
}
virtual void visit(AstElabDisplay* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->displayType();
});
}
virtual void visit(AstInitItem* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstInitArray* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstPragma* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->pragType();
});
}
virtual void visit(AstAttrOf* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->attrType();
});
}
virtual void visit(AstNodeFile* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstCFunc* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, false, [=]() {
m_hash += nodep->name();
iterateNull(nodep->aboveScopep());
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstTypedef* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstTypedefFwd* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstActive* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
iterateNull(nodep->sensesp());
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {
m_hash += nodep->name();
iterateNull(nodep->scopep());
});
}
virtual void visit(AstNodeFTask* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstModport* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual 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 {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {
m_hash += nodep->name();
iterateNull(nodep->ftaskp());
});
}
virtual void visit(AstNodeProcedure* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
}
virtual void visit(AstNodeBlock* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() { //
m_hash += nodep->name();
});
}
virtual void visit(AstPin* nodep) override {
m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {
m_hash += nodep->name();
m_hash += nodep->pinNum();
});
}
public:
@ -73,7 +463,7 @@ public:
: m_cacheInUser4{false} {
iterate(const_cast<AstNode*>(nodep));
}
V3Hash finalHash() const { return m_lowerHash; }
V3Hash finalHash() const { return m_hash; }
virtual ~HasherVisitor() override = default;
};

View File

@ -25,6 +25,7 @@
#include "V3Error.h"
#include "V3Ast.h"
#include "V3Hash.h"
//============================================================================

View File

@ -883,7 +883,7 @@ string V3Number::toString() const {
return str;
}
uint32_t V3Number::toHash() const { return m_value[0]; }
V3Hash V3Number::toHash() const { return V3Hash(m_width * (m_value[0] | 1)); }
uint32_t V3Number::edataWord(int eword) const {
UASSERT(!isFourState(), "edataWord with 4-state " << *this);

View File

@ -21,6 +21,7 @@
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Hash.h"
#include <cmath>
#include <limits>
@ -298,7 +299,7 @@ public:
string toDecimalS() const; // return ASCII signed decimal number
string toDecimalU() const; // return ASCII unsigned decimal number
double toDouble() const;
uint32_t toHash() const;
V3Hash toHash() const;
uint32_t edataWord(int eword) const;
uint8_t dataByte(int byte) const;
uint32_t countBits(const V3Number& ctrl) const;

View File

@ -88,8 +88,8 @@ private:
iterateChildren(nodep);
V3Hash hash = V3Hasher::uncachedHash(m_cfilep);
m_hashValuep->addText(fl, cvtToStr(hash.fullValue()) + ";\n");
m_cHashValuep->addText(fl, cvtToStr(hash.fullValue()) + "U;\n");
m_hashValuep->addText(fl, cvtToStr(hash.value()) + ";\n");
m_cHashValuep->addText(fl, cvtToStr(hash.value()) + "U;\n");
m_foundTop = true;
}

View File

@ -37,7 +37,7 @@ private:
// TYPES
struct HashSenTree {
size_t operator()(const AstSenTree* kp) const {
return V3Hasher::uncachedHash(kp).fullValue();
return V3Hasher::uncachedHash(kp).value();
}
};