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:
Geza Lore 2020-01-21 19:54:14 -05:00 committed by Wilson Snyder
parent d76b5b7823
commit 220daa5f33
8 changed files with 49 additions and 28 deletions

View File

@ -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

View File

@ -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

View File

@ -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; }

View File

@ -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());

View File

@ -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()) {

View File

@ -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)

View File

@ -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());

View File

@ -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) {