mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 18:13:50 +02:00
Fix V3SplitVar test stability (#2408)
This commit is contained in:
+33
-41
@@ -122,8 +122,6 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include VL_INCLUDE_UNORDERED_SET
|
||||
|
||||
struct SplitVarImpl {
|
||||
static AstNodeAssign* newAssign(FileLine* fileline, AstNode* lhsp, AstNode* rhsp,
|
||||
@@ -228,6 +226,15 @@ const char* const SplitVarImpl::notSplitMsg
|
||||
// AstVarRef -> Create a temporary variable and refer the variable
|
||||
// AstSliceSel -> Create a temporary variable and refer the variable
|
||||
|
||||
// Compare AstNode* to get deterministic ordering when showing messages.
|
||||
struct AstNodeComparator {
|
||||
bool operator()(const AstNode* ap, const AstNode* bp) const {
|
||||
const int lineComp = ap->fileline()->operatorCompare(*bp->fileline());
|
||||
if (lineComp != 0) return lineComp < 0;
|
||||
return ap < bp;
|
||||
}
|
||||
};
|
||||
|
||||
class UnpackRef {
|
||||
// m_nodep is called in this context (AstNodeStmt, AstCell, AstNodeFTask, or AstAlways)
|
||||
AstNode* m_contextp;
|
||||
@@ -277,6 +284,9 @@ public:
|
||||
}
|
||||
bool lvalue() const { return m_lvalue; }
|
||||
bool ftask() const { return m_ftask; }
|
||||
bool operator<(const UnpackRef& other) const {
|
||||
return AstNodeComparator()(m_nodep, other.m_nodep);
|
||||
}
|
||||
};
|
||||
|
||||
class UnpackRefMap {
|
||||
@@ -289,7 +299,7 @@ public:
|
||||
return a.nodep() == b.nodep();
|
||||
}
|
||||
};
|
||||
typedef std::map<AstVar*, vl_unordered_set<UnpackRef, Hash, Compare> > MapType;
|
||||
typedef std::map<AstVar*, std::set<UnpackRef>, AstNodeComparator> MapType;
|
||||
typedef MapType::iterator MapIt;
|
||||
typedef MapType::value_type::second_type::iterator SetIt;
|
||||
|
||||
@@ -336,30 +346,14 @@ public:
|
||||
MapIt end() { return m_map.end(); }
|
||||
};
|
||||
|
||||
// Compare AstNode* to get deterministic ordering when showing messages.
|
||||
struct AstNodeComparator {
|
||||
bool operator()(const AstNode* ap, const AstNode* bp) const {
|
||||
const FileLine* afp = ap->fileline();
|
||||
const FileLine* bfp = bp->fileline();
|
||||
if (afp->firstLineno() != bfp->firstLineno())
|
||||
return afp->firstLineno() < bfp->firstLineno();
|
||||
if (afp->firstColumn() != bfp->firstColumn())
|
||||
return afp->firstColumn() < bfp->firstColumn();
|
||||
// Don't comapre its filename because it is expensive.
|
||||
// Line number and column is practically enough.
|
||||
// The comparison of raw pointer here is just in case.
|
||||
// The comparison of this pointer may differ on different run,
|
||||
// but this is just warning message order. (mostly for CI)
|
||||
// Verilated result is same anyway.
|
||||
return ap < bp;
|
||||
}
|
||||
};
|
||||
|
||||
// Found nodes for SplitPackedVarVisitor
|
||||
struct RefsInModule {
|
||||
std::set<AstVar*> m_vars;
|
||||
std::set<AstVarRef*> m_refs;
|
||||
std::set<AstSel*> m_sels;
|
||||
typedef std::set<AstVar*, AstNodeComparator> VarSet;
|
||||
typedef std::set<AstVarRef*, AstNodeComparator> VarRefSet;
|
||||
typedef std::set<AstSel*, AstNodeComparator> SelSet;
|
||||
VarSet m_vars;
|
||||
VarRefSet m_refs;
|
||||
SelSet m_sels;
|
||||
|
||||
public:
|
||||
void add(AstVar* nodep) { m_vars.insert(nodep); }
|
||||
@@ -381,12 +375,10 @@ public:
|
||||
v.iterate(nodep);
|
||||
}
|
||||
void visit(AstNVisitor* visitor) {
|
||||
for (std::set<AstVar*>::iterator it = m_vars.begin(), it_end = m_vars.end(); it != it_end;
|
||||
++it) {
|
||||
for (VarSet::iterator it = m_vars.begin(), it_end = m_vars.end(); it != it_end; ++it) {
|
||||
visitor->iterate(*it);
|
||||
}
|
||||
for (std::set<AstSel*>::iterator it = m_sels.begin(), it_end = m_sels.end(); it != it_end;
|
||||
++it) {
|
||||
for (SelSet::iterator it = m_sels.begin(), it_end = m_sels.end(); it != it_end; ++it) {
|
||||
// If m_refs includes VarRef from ArraySel, remove it
|
||||
// because the VarRef would not be visited in SplitPackedVarVisitor::visit(AstSel*).
|
||||
if (AstVarRef* refp = VN_CAST((*it)->fromp(), VarRef)) {
|
||||
@@ -399,8 +391,7 @@ public:
|
||||
UASSERT_OBJ(reinterpret_cast<uintptr_t>((*it)->op1p()) != 1, *it, "stale");
|
||||
visitor->iterate(*it);
|
||||
}
|
||||
for (std::set<AstVarRef*>::iterator it = m_refs.begin(), it_end = m_refs.end();
|
||||
it != it_end; ++it) {
|
||||
for (VarRefSet::iterator it = m_refs.begin(), it_end = m_refs.end(); it != it_end; ++it) {
|
||||
UASSERT_OBJ(reinterpret_cast<uintptr_t>((*it)->op1p()) != 1, *it, "stale");
|
||||
visitor->iterate(*it);
|
||||
}
|
||||
@@ -894,15 +885,16 @@ class PackedVarRef {
|
||||
AstBasicDType* m_basicp; // Cache the ptr since varp->dtypep()->basicp() is expensive
|
||||
bool m_dedupDone;
|
||||
static void dedupRefs(std::vector<PackedVarRefEntry>& refs) {
|
||||
vl_unordered_map<AstNode*, size_t> nodes;
|
||||
// Use raw pointer to dedup
|
||||
typedef std::map<AstNode*, size_t, AstNodeComparator> NodeIndices;
|
||||
NodeIndices nodes;
|
||||
for (size_t i = 0; i < refs.size(); ++i) {
|
||||
nodes.insert(std::make_pair(refs[i].nodep(), i));
|
||||
}
|
||||
std::vector<PackedVarRefEntry> vect;
|
||||
vect.reserve(nodes.size());
|
||||
for (vl_unordered_map<AstNode*, size_t>::const_iterator it = nodes.begin(),
|
||||
it_end = nodes.end();
|
||||
it != it_end; ++it) {
|
||||
for (NodeIndices::const_iterator it = nodes.begin(), it_end = nodes.end(); it != it_end;
|
||||
++it) {
|
||||
vect.push_back(refs[it->second]);
|
||||
}
|
||||
refs.swap(vect);
|
||||
@@ -983,11 +975,12 @@ public:
|
||||
};
|
||||
|
||||
class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl {
|
||||
typedef std::map<AstVar*, PackedVarRef, AstNodeComparator> PackedVarRefMap;
|
||||
AstNetlist* m_netp;
|
||||
AstNodeModule* m_modp; // Current module (just for log)
|
||||
int m_numSplit; // Total number of split variables
|
||||
// key:variable to be split. value:location where the variable is referenced.
|
||||
vl_unordered_map<AstVar*, PackedVarRef> m_refs;
|
||||
PackedVarRefMap m_refs;
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
UASSERT_OBJ(m_modp == NULL, m_modp, "Nested module declaration");
|
||||
if (!VN_IS(nodep, Module)) {
|
||||
@@ -1017,7 +1010,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl {
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
AstVar* varp = nodep->varp();
|
||||
visit(varp);
|
||||
vl_unordered_map<AstVar*, PackedVarRef>::iterator refit = m_refs.find(varp);
|
||||
PackedVarRefMap::iterator refit = m_refs.find(varp);
|
||||
if (refit == m_refs.end()) return; // variable without split_var metacomment
|
||||
UASSERT_OBJ(varp->attrSplitVar(), varp, "split_var attribute must be attached");
|
||||
UASSERT_OBJ(!nodep->packagep(), nodep,
|
||||
@@ -1036,7 +1029,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl {
|
||||
}
|
||||
|
||||
AstVar* varp = vrefp->varp();
|
||||
vl_unordered_map<AstVar*, PackedVarRef>::iterator refit = m_refs.find(varp);
|
||||
PackedVarRefMap::iterator refit = m_refs.find(varp);
|
||||
if (refit == m_refs.end()) {
|
||||
iterateChildren(nodep);
|
||||
return; // Variable without split_var metacomment
|
||||
@@ -1198,9 +1191,8 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl {
|
||||
}
|
||||
// Do the actual splitting operation
|
||||
void split() {
|
||||
for (vl_unordered_map<AstVar*, PackedVarRef>::iterator it = m_refs.begin(),
|
||||
it_end = m_refs.end();
|
||||
it != it_end; ++it) {
|
||||
for (PackedVarRefMap::iterator it = m_refs.begin(), it_end = m_refs.end(); it != it_end;
|
||||
++it) {
|
||||
it->second.dedup();
|
||||
AstVar* varp = it->first;
|
||||
UINFO(3, "In module " << m_modp->name() << " var " << varp->prettyNameQ()
|
||||
|
||||
Reference in New Issue
Block a user