Internals: Restore AstNode naming property. #2133.
The intention was that all subclasses of AstNode which are
intermediate must be abstract as well and called AstNode*. This was
violated recently by 28b9db1903. This
patch restores that property by:
- Renaming AstFile to AstNodeFile
- Introducing AstNodeSimpleText as the common base of AstText and
AstTextBlock, rather than AstTextBlock deriving from AstText.
This commit is contained in:
parent
d76b5b7823
commit
220daa5f33
|
|
@ -11,6 +11,7 @@ Chris Randall
|
||||||
Driss Hafdi
|
Driss Hafdi
|
||||||
Eric Rippey
|
Eric Rippey
|
||||||
Garrett Smith
|
Garrett Smith
|
||||||
|
Geza Lore
|
||||||
Gianfranco Costamagna
|
Gianfranco Costamagna
|
||||||
Howard Su
|
Howard Su
|
||||||
Iztok Jeras
|
Iztok Jeras
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,10 @@ The AST is represented at the top level by the class `AstNode`. This
|
||||||
abstract class has derived classes for the individual components
|
abstract class has derived classes for the individual components
|
||||||
(e.g. `AstGenerate` for a generate block) or groups of components
|
(e.g. `AstGenerate` for a generate block) or groups of components
|
||||||
(e.g. `AstNodeFTask` for functions and tasks, which in turn has `AstFunc`
|
(e.g. `AstNodeFTask` for functions and tasks, which in turn has `AstFunc`
|
||||||
and `AstTask` as derived classes).
|
and `AstTask` as derived classes). An important property of the `AstNode`
|
||||||
|
type hierarchy is that all non-final subclasses of `AstNode` (i.e.: those
|
||||||
|
which themselves have subclasses) must be abstract as well, and be named
|
||||||
|
with the prefix `AstNode*`. The `astgen` (see below) script relies on this.
|
||||||
|
|
||||||
Each `AstNode` has pointers to up to four children, accessed by the `op1p`
|
Each `AstNode` has pointers to up to four children, accessed by the `op1p`
|
||||||
through `op4p` methods. These methods are then abstracted in a specific
|
through `op4p` methods. These methods are then abstracted in a specific
|
||||||
|
|
@ -959,7 +962,8 @@ src/VParseGrammar.y, as this grammar supports the full SystemVerilog
|
||||||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||||
the appropriate rules to src/verilog.y and modify the productions.
|
the appropriate rules to src/verilog.y and modify the productions.
|
||||||
|
|
||||||
. If a new Ast type is needed, add it to V3AstNodes.h.
|
. If a new Ast type is needed, add it to V3AstNodes.h. Follow the convention
|
||||||
|
described above about the AstNode type hierarchy.
|
||||||
|
|
||||||
. Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
. Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
|
||||||
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree
|
||||||
|
|
|
||||||
|
|
@ -6355,24 +6355,31 @@ public:
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Text based nodes
|
// Text based nodes
|
||||||
|
|
||||||
class AstText : public AstNodeText {
|
class AstNodeSimpleText : public AstNodeText {
|
||||||
private:
|
private:
|
||||||
bool m_tracking; // When emit, it's ok to parse the string to do indentation
|
bool m_tracking; // When emit, it's ok to parse the string to do indentation
|
||||||
public:
|
public:
|
||||||
AstText(FileLine* fl, const string& textp, bool tracking=false)
|
AstNodeSimpleText(FileLine* fl, const string& textp, bool tracking=false)
|
||||||
: AstNodeText(fl, textp), m_tracking(tracking) {}
|
: AstNodeText(fl, textp), m_tracking(tracking) {}
|
||||||
ASTNODE_NODE_FUNCS(Text)
|
ASTNODE_BASE_FUNCS(NodeSimpleText)
|
||||||
void tracking(bool flag) { m_tracking = flag; }
|
void tracking(bool flag) { m_tracking = flag; }
|
||||||
bool tracking() const { return m_tracking; }
|
bool tracking() const { return m_tracking; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstTextBlock : public AstText {
|
class AstText : public AstNodeSimpleText {
|
||||||
|
public:
|
||||||
|
AstText(FileLine* fl, const string& textp, bool tracking=false)
|
||||||
|
: AstNodeSimpleText(fl, textp, tracking) {}
|
||||||
|
ASTNODE_NODE_FUNCS(Text)
|
||||||
|
};
|
||||||
|
|
||||||
|
class AstTextBlock : public AstNodeSimpleText {
|
||||||
private:
|
private:
|
||||||
bool m_commas; // Comma separate emitted children
|
bool m_commas; // Comma separate emitted children
|
||||||
public:
|
public:
|
||||||
AstTextBlock(FileLine* fl, const string& textp="", bool tracking=false,
|
AstTextBlock(FileLine* fl, const string& textp="", bool tracking=false,
|
||||||
bool commas=false)
|
bool commas=false)
|
||||||
: AstText(fl, textp, tracking), m_commas(commas) {}
|
: AstNodeSimpleText(fl, textp, tracking), m_commas(commas) {}
|
||||||
ASTNODE_NODE_FUNCS(TextBlock)
|
ASTNODE_NODE_FUNCS(TextBlock)
|
||||||
void commas(bool flag) { m_commas = flag; }
|
void commas(bool flag) { m_commas = flag; }
|
||||||
bool commas() const { return m_commas; }
|
bool commas() const { return m_commas; }
|
||||||
|
|
@ -6457,18 +6464,18 @@ public:
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Emitted file nodes
|
// Emitted file nodes
|
||||||
|
|
||||||
class AstFile : public AstNode {
|
class AstNodeFile : public AstNode {
|
||||||
// Emitted Otput file
|
// Emitted Otput file
|
||||||
// Parents: NETLIST
|
// Parents: NETLIST
|
||||||
// Children: AstTextBlock
|
// Children: AstTextBlock
|
||||||
private:
|
private:
|
||||||
string m_name; ///< Filename
|
string m_name; ///< Filename
|
||||||
public:
|
public:
|
||||||
AstFile(FileLine* fl, const string& name)
|
AstNodeFile(FileLine* fl, const string& name)
|
||||||
: AstNode(fl) {
|
: AstNode(fl) {
|
||||||
m_name = name;
|
m_name = name;
|
||||||
}
|
}
|
||||||
ASTNODE_BASE_FUNCS(File)
|
ASTNODE_BASE_FUNCS(NodeFile)
|
||||||
virtual string name() const { return m_name; }
|
virtual string name() const { return m_name; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||||
virtual bool same(const AstNode* samep) const { return true; }
|
virtual bool same(const AstNode* samep) const { return true; }
|
||||||
|
|
@ -6479,12 +6486,12 @@ public:
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Emit V nodes
|
// Emit V nodes
|
||||||
|
|
||||||
class AstVFile : public AstFile {
|
class AstVFile : public AstNodeFile {
|
||||||
// Verilog output file
|
// Verilog output file
|
||||||
// Parents: NETLIST
|
// Parents: NETLIST
|
||||||
public:
|
public:
|
||||||
AstVFile(FileLine* fl, const string& name)
|
AstVFile(FileLine* fl, const string& name)
|
||||||
: AstFile(fl, name) { }
|
: AstNodeFile(fl, name) { }
|
||||||
ASTNODE_NODE_FUNCS(VFile)
|
ASTNODE_NODE_FUNCS(VFile)
|
||||||
virtual void dump(std::ostream& str=std::cout) const;
|
virtual void dump(std::ostream& str=std::cout) const;
|
||||||
};
|
};
|
||||||
|
|
@ -6492,7 +6499,7 @@ public:
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Emit C nodes
|
// Emit C nodes
|
||||||
|
|
||||||
class AstCFile : public AstFile {
|
class AstCFile : public AstNodeFile {
|
||||||
// C++ output file
|
// C++ output file
|
||||||
// Parents: NETLIST
|
// Parents: NETLIST
|
||||||
private:
|
private:
|
||||||
|
|
@ -6501,7 +6508,7 @@ private:
|
||||||
bool m_support:1; ///< Support file (non systemc)
|
bool m_support:1; ///< Support file (non systemc)
|
||||||
public:
|
public:
|
||||||
AstCFile(FileLine* fl, const string& name)
|
AstCFile(FileLine* fl, const string& name)
|
||||||
: AstFile(fl, name) {
|
: AstNodeFile(fl, name) {
|
||||||
m_slow = false;
|
m_slow = false;
|
||||||
m_source = false;
|
m_source = false;
|
||||||
m_support = false;
|
m_support = false;
|
||||||
|
|
@ -6877,8 +6884,8 @@ public:
|
||||||
AstNodeModule* topModulep() const { // * = Top module in hierarchy (first one added, for now)
|
AstNodeModule* topModulep() const { // * = Top module in hierarchy (first one added, for now)
|
||||||
return VN_CAST(op1p(), NodeModule); }
|
return VN_CAST(op1p(), NodeModule); }
|
||||||
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
|
void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
|
||||||
AstFile* filesp() const { return VN_CAST(op2p(), File);} // op2 = List of files
|
AstNodeFile* filesp() const { return VN_CAST(op2p(), NodeFile); } // op2 = List of files
|
||||||
void addFilesp(AstFile* filep) { addOp2p(filep); }
|
void addFilesp(AstNodeFile* filep) { addOp2p(filep); }
|
||||||
AstNode* miscsp() const { return op3p(); } // op3 = List of dtypes etc
|
AstNode* miscsp() const { return op3p(); } // op3 = List of dtypes etc
|
||||||
void addMiscsp(AstNode* nodep) { addOp3p(nodep); }
|
void addMiscsp(AstNode* nodep) { addOp3p(nodep); }
|
||||||
AstTypeTable* typeTablep() { return m_typeTablep; }
|
AstTypeTable* typeTablep() { return m_typeTablep; }
|
||||||
|
|
|
||||||
|
|
@ -642,7 +642,7 @@ public:
|
||||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
puts(", \"\");\n");
|
puts(", \"\");\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstText* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE {
|
||||||
if (nodep->tracking() || m_trackText) {
|
if (nodep->tracking() || m_trackText) {
|
||||||
puts(nodep->text());
|
puts(nodep->text());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -650,7 +650,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstTextBlock* nodep) VL_OVERRIDE {
|
virtual void visit(AstTextBlock* nodep) VL_OVERRIDE {
|
||||||
visit(VN_CAST(nodep, Text));
|
visit(VN_CAST(nodep, NodeSimpleText));
|
||||||
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
|
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
|
||||||
iterate(childp);
|
iterate(childp);
|
||||||
if (nodep->commas() && childp->nextp()) puts(", ");
|
if (nodep->commas() && childp->nextp()) puts(", ");
|
||||||
|
|
@ -3301,8 +3301,8 @@ void V3EmitC::emitcTrace() {
|
||||||
|
|
||||||
void V3EmitC::emitcFiles() {
|
void V3EmitC::emitcFiles() {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
for (AstFile* filep = v3Global.rootp()->filesp(); filep;
|
for (AstNodeFile* filep = v3Global.rootp()->filesp(); filep;
|
||||||
filep = VN_CAST(filep->nextp(), File)) {
|
filep = VN_CAST(filep->nextp(), NodeFile)) {
|
||||||
AstCFile* cfilep = VN_CAST(filep, CFile);
|
AstCFile* cfilep = VN_CAST(filep, CFile);
|
||||||
if (cfilep && cfilep->tblockp()) {
|
if (cfilep && cfilep->tblockp()) {
|
||||||
V3OutCFile of(cfilep->name());
|
V3OutCFile of(cfilep->name());
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,8 @@ class CMakeEmitter {
|
||||||
|
|
||||||
*of << "\n### Sources...\n";
|
*of << "\n### Sources...\n";
|
||||||
std::vector<string> classes_fast, classes_slow, support_fast, support_slow, global;
|
std::vector<string> classes_fast, classes_slow, support_fast, support_slow, global;
|
||||||
for (AstFile* nodep = v3Global.rootp()->filesp(); nodep;
|
for (AstNodeFile* nodep = v3Global.rootp()->filesp(); nodep;
|
||||||
nodep = VN_CAST(nodep->nextp(), File)) {
|
nodep = VN_CAST(nodep->nextp(), NodeFile)) {
|
||||||
AstCFile* cfilep = VN_CAST(nodep, CFile);
|
AstCFile* cfilep = VN_CAST(nodep, CFile);
|
||||||
if (cfilep && cfilep->source()) {
|
if (cfilep && cfilep->source()) {
|
||||||
if (cfilep->support()) {
|
if (cfilep->support()) {
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,8 @@ public:
|
||||||
else if (support==2 && slow) {
|
else if (support==2 && slow) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (AstFile* nodep = v3Global.rootp()->filesp();
|
for (AstNodeFile* nodep = v3Global.rootp()->filesp();
|
||||||
nodep; nodep = VN_CAST(nodep->nextp(), File)) {
|
nodep; nodep = VN_CAST(nodep->nextp(), NodeFile)) {
|
||||||
AstCFile* cfilep = VN_CAST(nodep, CFile);
|
AstCFile* cfilep = VN_CAST(nodep, CFile);
|
||||||
if (cfilep && cfilep->source()
|
if (cfilep && cfilep->source()
|
||||||
&& cfilep->slow()==(slow!=0)
|
&& cfilep->slow()==(slow!=0)
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
virtual void visit(AstFinish* nodep) VL_OVERRIDE {
|
virtual void visit(AstFinish* nodep) VL_OVERRIDE {
|
||||||
putfs(nodep, "$finish;\n");
|
putfs(nodep, "$finish;\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstText* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE {
|
||||||
if (nodep->tracking() || m_trackText) {
|
if (nodep->tracking() || m_trackText) {
|
||||||
puts(nodep->text());
|
puts(nodep->text());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -363,7 +363,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstTextBlock* nodep) VL_OVERRIDE {
|
virtual void visit(AstTextBlock* nodep) VL_OVERRIDE {
|
||||||
visit(VN_CAST(nodep, Text));
|
visit(VN_CAST(nodep, NodeSimpleText));
|
||||||
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
|
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
|
||||||
iterate(childp);
|
iterate(childp);
|
||||||
if (nodep->commas() && childp->nextp()) puts(", ");
|
if (nodep->commas() && childp->nextp()) puts(", ");
|
||||||
|
|
@ -779,8 +779,8 @@ void V3EmitV::verilogPrefixedTree(AstNode* nodep, std::ostream& os,
|
||||||
|
|
||||||
void V3EmitV::emitvFiles() {
|
void V3EmitV::emitvFiles() {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
for (AstFile* filep = v3Global.rootp()->filesp(); filep;
|
for (AstNodeFile* filep = v3Global.rootp()->filesp(); filep;
|
||||||
filep = VN_CAST(filep->nextp(), File)) {
|
filep = VN_CAST(filep->nextp(), NodeFile)) {
|
||||||
AstVFile* vfilep = VN_CAST(filep, VFile);
|
AstVFile* vfilep = VN_CAST(filep, VFile);
|
||||||
if (vfilep && vfilep->tblockp()) {
|
if (vfilep && vfilep->tblockp()) {
|
||||||
V3OutVFile of(vfilep->name());
|
V3OutVFile of(vfilep->name());
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,15 @@ if (! GetOptions(
|
||||||
|
|
||||||
read_types("$Opt_I[0]/V3Ast.h");
|
read_types("$Opt_I[0]/V3Ast.h");
|
||||||
read_types("$Opt_I[0]/V3AstNodes.h");
|
read_types("$Opt_I[0]/V3AstNodes.h");
|
||||||
|
foreach my $type (sort (keys %Classes)) {
|
||||||
|
# Chekc all leafs are not AstNode* and non-leave are AstNode*
|
||||||
|
my @children = children_of($type);
|
||||||
|
if ($type =~ /^Node/) {
|
||||||
|
@children || die "Error: Final AstNode subclasses must not be named AstNode*: Ast$type"
|
||||||
|
} else {
|
||||||
|
!@children || die "Error: Non-final AstNode subclasses must be named AstNode*: Ast$type"
|
||||||
|
}
|
||||||
|
}
|
||||||
read_stages("$Opt_I[0]/Verilator.cpp");
|
read_stages("$Opt_I[0]/Verilator.cpp");
|
||||||
read_refs(glob("$Opt_I[0]/*.y"), glob("$Opt_I[0]/*.h"), glob("$Opt_I[0]/*.cpp"));
|
read_refs(glob("$Opt_I[0]/*.y"), glob("$Opt_I[0]/*.h"), glob("$Opt_I[0]/*.cpp"));
|
||||||
if ($opt_report) {
|
if ($opt_report) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue