Partial clean up of V3Order. No functional change intended.
This is a partial cleanup of V3Order with the aim of increasing clarity: - Split the initial OrderGraph building and the actual ordering process into separate classes (OrderVisitor -> OrderBuildVisitor + OrderProcess) - Remove all the historical cruft from the graph building phase (now in OrderBuildVisitor), and add more assertions for assumptions. - Change the dot styling of OrderGraph to use shapes and more easily distinguishable colors. - Expand vague comments, remove incorrect comments, and add more. - Replace some old code with cleaner C++11 constructs. - Move code about a bit so logically connected sections are closer to each other, scope some definitions where they are used rather than file scope. - The actual ordering process (now in OrderProcess) is still largely unchanged. The generated code is identical to before (within the limits of the exiting non-determinism).
This commit is contained in:
parent
5515eed0b6
commit
f5a226a183
|
|
@ -1276,9 +1276,9 @@ AstNodeDType* AstNode::findVoidDType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// AstNVisitor
|
// AstNDeleter
|
||||||
|
|
||||||
void AstNVisitor::doDeletes() {
|
void AstNDeleter::doDeletes() {
|
||||||
for (AstNode* nodep : m_deleteps) nodep->deleteTree();
|
for (AstNode* const nodep : m_deleteps) nodep->deleteTree();
|
||||||
m_deleteps.clear();
|
m_deleteps.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
34
src/V3Ast.h
34
src/V3Ast.h
|
|
@ -1251,31 +1251,39 @@ public:
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// AstNVisitor -- Allows new functions to be called on each node
|
// Node deleter, deletes all enqueued AstNode* on destruction, or when
|
||||||
// type without changing the base classes. See "Modern C++ Design".
|
// explicitly told to do so. This is useful when the deletion of removed
|
||||||
|
// nodes needs to be deferred to a later time, because pointers to the
|
||||||
|
// removed nodes might still exist.
|
||||||
|
|
||||||
class AstNVisitor VL_NOT_FINAL {
|
class AstNDeleter VL_NOT_FINAL {
|
||||||
private:
|
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
std::vector<AstNode*> m_deleteps; // Nodes to delete when doDeletes() called
|
std::vector<AstNode*> m_deleteps; // Nodes to delete
|
||||||
protected:
|
|
||||||
friend class AstNode;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
/// At the end of the visitor (or doDeletes()), delete this pushed node
|
|
||||||
/// along with all children and next(s). This is often better to use
|
// Enqueue node for deletion on next 'doDelete' (or destruction)
|
||||||
/// than an immediate deleteTree, as any pointers into this node will
|
|
||||||
/// persist for the lifetime of the visitor
|
|
||||||
void pushDeletep(AstNode* nodep) {
|
void pushDeletep(AstNode* nodep) {
|
||||||
UASSERT_STATIC(nodep, "Cannot delete nullptr node");
|
UASSERT_STATIC(nodep, "Cannot delete nullptr node");
|
||||||
m_deleteps.push_back(nodep);
|
m_deleteps.push_back(nodep);
|
||||||
}
|
}
|
||||||
/// Call deleteTree on all previously pushDeletep()'ed nodes
|
|
||||||
|
// Delete all previously pushed nodes (by callint deleteTree)
|
||||||
void doDeletes();
|
void doDeletes();
|
||||||
|
|
||||||
|
// Do the deletions on destruction
|
||||||
|
virtual ~AstNDeleter() { doDeletes(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// AstNVisitor -- Allows new functions to be called on each node
|
||||||
|
// type without changing the base classes. See "Modern C++ Design".
|
||||||
|
|
||||||
|
class AstNVisitor VL_NOT_FINAL : public AstNDeleter {
|
||||||
|
friend class AstNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~AstNVisitor() { doDeletes(); }
|
|
||||||
/// Call visit()s on nodep
|
/// Call visit()s on nodep
|
||||||
void iterate(AstNode* nodep);
|
void iterate(AstNode* nodep);
|
||||||
/// Call visit()s on nodep
|
/// Call visit()s on nodep
|
||||||
|
|
|
||||||
|
|
@ -2300,9 +2300,9 @@ class AstScope final : public AstNode {
|
||||||
private:
|
private:
|
||||||
// An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope
|
// An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope
|
||||||
string m_name; // Name
|
string m_name; // Name
|
||||||
AstScope* m_aboveScopep; // Scope above this one in the hierarchy (nullptr if top)
|
AstScope* const m_aboveScopep; // Scope above this one in the hierarchy (nullptr if top)
|
||||||
AstCell* m_aboveCellp; // Cell above this in the hierarchy (nullptr if top)
|
AstCell* const m_aboveCellp; // Cell above this in the hierarchy (nullptr if top)
|
||||||
AstNodeModule* m_modp; // Module scope corresponds to
|
AstNodeModule* const m_modp; // Module scope corresponds to
|
||||||
public:
|
public:
|
||||||
AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep,
|
AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep,
|
||||||
AstCell* aboveCellp)
|
AstCell* aboveCellp)
|
||||||
|
|
@ -2321,8 +2321,8 @@ public:
|
||||||
string nameDotless() const;
|
string nameDotless() const;
|
||||||
string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); }
|
string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); }
|
||||||
AstNodeModule* modp() const { return m_modp; }
|
AstNodeModule* modp() const { return m_modp; }
|
||||||
void addVarp(AstNode* nodep) { addOp1p(nodep); }
|
void addVarp(AstVarScope* nodep) { addOp1p((AstNode*)nodep); }
|
||||||
AstNode* varsp() const { return op1p(); } // op1 = AstVarScope's
|
AstVarScope* varsp() const { return VN_AS(op1p(), VarScope); } // op1 = AstVarScope's
|
||||||
void addActivep(AstNode* nodep) { addOp2p(nodep); }
|
void addActivep(AstNode* nodep) { addOp2p(nodep); }
|
||||||
AstNode* blocksp() const { return op2p(); } // op2 = Block names
|
AstNode* blocksp() const { return op2p(); } // op2 = Block names
|
||||||
void addFinalClkp(AstNode* nodep) { addOp3p(nodep); }
|
void addFinalClkp(AstNode* nodep) { addOp3p(nodep); }
|
||||||
|
|
@ -2367,6 +2367,8 @@ public:
|
||||||
: ASTGEN_SUPER_VarScope(fl)
|
: ASTGEN_SUPER_VarScope(fl)
|
||||||
, m_scopep{scopep}
|
, m_scopep{scopep}
|
||||||
, m_varp{varp} {
|
, m_varp{varp} {
|
||||||
|
UASSERT_OBJ(scopep, fl, "Scope must be non-null");
|
||||||
|
UASSERT_OBJ(varp, fl, "Var must be non-null");
|
||||||
m_circular = false;
|
m_circular = false;
|
||||||
m_trace = true;
|
m_trace = true;
|
||||||
dtypeFrom(varp);
|
dtypeFrom(varp);
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,9 @@ public:
|
||||||
if (VN_IS(moved.first, NodeFTask)) {
|
if (VN_IS(moved.first, NodeFTask)) {
|
||||||
moved.second->addActivep(moved.first->unlinkFrBack());
|
moved.second->addActivep(moved.first->unlinkFrBack());
|
||||||
} else if (VN_IS(moved.first, Var)) {
|
} else if (VN_IS(moved.first, Var)) {
|
||||||
AstVarScope* scopep = VN_AS(moved.first->user1p(), VarScope);
|
AstVarScope* const scopep = VN_AS(moved.first->user1p(), VarScope);
|
||||||
moved.second->addVarp(scopep->unlinkFrBack());
|
scopep->unlinkFrBack();
|
||||||
|
moved.second->addVarp(scopep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1286
src/V3Order.cpp
1286
src/V3Order.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -167,6 +167,7 @@ public:
|
||||||
virtual string name() const override { return "*INPUTS*"; }
|
virtual string name() const override { return "*INPUTS*"; }
|
||||||
virtual string dotColor() const override { return "green"; }
|
virtual string dotColor() const override { return "green"; }
|
||||||
virtual string dotName() const override { return ""; }
|
virtual string dotName() const override { return ""; }
|
||||||
|
virtual string dotShape() const override { return "invhouse"; }
|
||||||
virtual bool domainMatters() override { return false; }
|
virtual bool domainMatters() override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -193,7 +194,9 @@ public:
|
||||||
return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName()));
|
return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName()));
|
||||||
}
|
}
|
||||||
AstNode* nodep() const { return m_nodep; }
|
AstNode* nodep() const { return m_nodep; }
|
||||||
virtual string dotColor() const override { return "yellow"; }
|
virtual string dotShape() const override {
|
||||||
|
return VN_IS(m_nodep, Active) ? "doubleoctagon" : "rect";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class OrderVarVertex VL_NOT_FINAL : public OrderEitherVertex {
|
class OrderVarVertex VL_NOT_FINAL : public OrderEitherVertex {
|
||||||
|
|
@ -221,6 +224,7 @@ public:
|
||||||
bool isClock() const { return m_isClock; }
|
bool isClock() const { return m_isClock; }
|
||||||
void isDelayed(bool flag) { m_isDelayed = flag; }
|
void isDelayed(bool flag) { m_isDelayed = flag; }
|
||||||
bool isDelayed() const { return m_isDelayed; }
|
bool isDelayed() const { return m_isDelayed; }
|
||||||
|
virtual string dotShape() const override { return "ellipse"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class OrderVarStdVertex final : public OrderVarVertex {
|
class OrderVarStdVertex final : public OrderVarVertex {
|
||||||
|
|
@ -238,7 +242,7 @@ public:
|
||||||
virtual string name() const override {
|
virtual string name() const override {
|
||||||
return (cvtToHex(varScp()) + "\\n " + varScp()->name());
|
return (cvtToHex(varScp()) + "\\n " + varScp()->name());
|
||||||
}
|
}
|
||||||
virtual string dotColor() const override { return "skyblue"; }
|
virtual string dotColor() const override { return "grey"; }
|
||||||
virtual bool domainMatters() override { return true; }
|
virtual bool domainMatters() override { return true; }
|
||||||
};
|
};
|
||||||
class OrderVarPreVertex final : public OrderVarVertex {
|
class OrderVarPreVertex final : public OrderVarVertex {
|
||||||
|
|
@ -256,7 +260,7 @@ public:
|
||||||
virtual string name() const override {
|
virtual string name() const override {
|
||||||
return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name());
|
return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name());
|
||||||
}
|
}
|
||||||
virtual string dotColor() const override { return "lightblue"; }
|
virtual string dotColor() const override { return "green"; }
|
||||||
virtual bool domainMatters() override { return false; }
|
virtual bool domainMatters() override { return false; }
|
||||||
};
|
};
|
||||||
class OrderVarPostVertex final : public OrderVarVertex {
|
class OrderVarPostVertex final : public OrderVarVertex {
|
||||||
|
|
@ -274,7 +278,7 @@ public:
|
||||||
virtual string name() const override {
|
virtual string name() const override {
|
||||||
return (cvtToHex(varScp()) + " POST\\n " + varScp()->name());
|
return (cvtToHex(varScp()) + " POST\\n " + varScp()->name());
|
||||||
}
|
}
|
||||||
virtual string dotColor() const override { return "CadetBlue"; }
|
virtual string dotColor() const override { return "red"; }
|
||||||
virtual bool domainMatters() override { return false; }
|
virtual bool domainMatters() override { return false; }
|
||||||
};
|
};
|
||||||
class OrderVarPordVertex final : public OrderVarVertex {
|
class OrderVarPordVertex final : public OrderVarVertex {
|
||||||
|
|
@ -292,7 +296,7 @@ public:
|
||||||
virtual string name() const override {
|
virtual string name() const override {
|
||||||
return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name());
|
return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name());
|
||||||
}
|
}
|
||||||
virtual string dotColor() const override { return "NavyBlue"; }
|
virtual string dotColor() const override { return "blue"; }
|
||||||
virtual bool domainMatters() override { return false; }
|
virtual bool domainMatters() override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -307,7 +311,7 @@ class OrderMoveVertex final : public V3GraphVertex {
|
||||||
OrderMoveDomScope* m_domScopep; // Domain/scope list information
|
OrderMoveDomScope* m_domScopep; // Domain/scope list information
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class OrderVisitor;
|
friend class OrderProcess;
|
||||||
friend class OrderMoveVertexMaker;
|
friend class OrderMoveVertexMaker;
|
||||||
// These only contain the "next" item,
|
// These only contain the "next" item,
|
||||||
// for the head of the list, see the same var name under OrderVisitor
|
// for the head of the list, see the same var name under OrderVisitor
|
||||||
|
|
|
||||||
|
|
@ -82,21 +82,24 @@ private:
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
SenTreeFinder()
|
SenTreeFinder()
|
||||||
: m_topScopep{v3Global.rootp()->topScopep()} {
|
: SenTreeFinder(v3Global.rootp()) {}
|
||||||
|
|
||||||
|
explicit SenTreeFinder(AstNetlist* netlistp)
|
||||||
|
: m_topScopep{netlistp->topScopep()} {
|
||||||
// Gather existing global SenTrees
|
// Gather existing global SenTrees
|
||||||
for (AstSenTree* nodep = m_topScopep->senTreesp(); nodep;
|
for (AstNode* nodep = m_topScopep->senTreesp(); nodep; nodep = nodep->nextp()) {
|
||||||
nodep = VN_AS(nodep->nextp(), SenTree)) {
|
m_trees.add(VN_AS(nodep, SenTree));
|
||||||
m_trees.add(nodep);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
|
|
||||||
|
// Return a global AstSenTree that matches given SenTree.
|
||||||
|
// If no such global AstSenTree exists create one and add it to the stored AstTopScope.
|
||||||
AstSenTree* getSenTree(AstSenTree* senTreep) {
|
AstSenTree* getSenTree(AstSenTree* senTreep) {
|
||||||
// Return a global SenTree that matches given SenTree. If no such global
|
|
||||||
// SenTree exists, create one and add it to the stored TopScope.
|
|
||||||
AstSenTree* treep = m_trees.find(senTreep);
|
AstSenTree* treep = m_trees.find(senTreep);
|
||||||
// Not found, form a new one
|
|
||||||
if (!treep) {
|
if (!treep) {
|
||||||
|
// Not found, form a new one
|
||||||
treep = senTreep->cloneTree(false);
|
treep = senTreep->cloneTree(false);
|
||||||
m_topScopep->addSenTreep(treep);
|
m_topScopep->addSenTreep(treep);
|
||||||
UINFO(8, " New SENTREE " << treep << endl);
|
UINFO(8, " New SENTREE " << treep << endl);
|
||||||
|
|
@ -104,6 +107,16 @@ public:
|
||||||
}
|
}
|
||||||
return treep;
|
return treep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the global combinational AstSenTree.
|
||||||
|
// If no such global SenTree exists create one and add it to the stored AstTopScope.
|
||||||
|
AstSenTree* getComb() {
|
||||||
|
FileLine* const fl = m_topScopep->fileline();
|
||||||
|
AstSenTree* const combp = new AstSenTree{fl, new AstSenItem{fl, AstSenItem::Combo()}};
|
||||||
|
AstSenTree* const resultp = getSenTree(combp);
|
||||||
|
VL_DO_DANGLING(combp->deleteTree(), combp); // getSenTree clones, so can delete
|
||||||
|
return resultp;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|
|
||||||
24
src/astgen
24
src/astgen
|
|
@ -362,21 +362,19 @@ def read_types(filename):
|
||||||
match = re.search(r'^\s*(class|struct)\s*(\S+)', line)
|
match = re.search(r'^\s*(class|struct)\s*(\S+)', line)
|
||||||
if match:
|
if match:
|
||||||
classn = match.group(2)
|
classn = match.group(2)
|
||||||
inh = ""
|
|
||||||
match = re.search(r':\s*public\s+(\S+)', line)
|
match = re.search(r':\s*public\s+(\S+)', line)
|
||||||
if match:
|
supern = match.group(1) if match else ""
|
||||||
inh = match.group(1)
|
assert classn != "AstNode" or supern == "", "AstNode can't have a superclass"
|
||||||
# print("class "+classn+" : "+inh)
|
if re.search(r'Ast', supern) or classn == "AstNode":
|
||||||
if classn == "AstNode":
|
if supern == "AstNDeleter":
|
||||||
inh = ""
|
continue
|
||||||
if re.search(r'Ast', inh) or classn == "AstNode":
|
|
||||||
classn = re.sub(r'^Ast', '', classn)
|
classn = re.sub(r'^Ast', '', classn)
|
||||||
inh = re.sub(r'^Ast', '', inh)
|
supern = re.sub(r'^Ast', '', supern)
|
||||||
Classes[classn] = inh
|
Classes[classn] = supern
|
||||||
if inh != '':
|
if supern != '':
|
||||||
if inh not in Children:
|
if supern not in Children:
|
||||||
Children[inh] = {}
|
Children[supern] = {}
|
||||||
Children[inh][classn] = 1
|
Children[supern][classn] = 1
|
||||||
|
|
||||||
|
|
||||||
def read_stages(filename):
|
def read_stages(filename):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue