1 // -*- mode: C++; c-file-style: "cc-mode" -*-
2 //*************************************************************************
3 // DESCRIPTION: Verilator: Ast node structure
4 //
5 // Code available from: https://verilator.org
6 //
7 //*************************************************************************
8 //
9 // Copyright 2003-2021 by Wilson Snyder. This program is free software; you
10 // can redistribute it and/or modify it under the terms of either the GNU
11 // Lesser General Public License Version 3 or the Perl Artistic License
12 // Version 2.0.
13 // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
14 //
15 //*************************************************************************
16 
17 #ifndef VERILATOR_V3ASTNODES_H_
18 #define VERILATOR_V3ASTNODES_H_
19 
20 #ifndef VERILATOR_V3AST_H_
21 #error "Use V3Ast.h as the include"
22 #include "V3Ast.h"  // This helps code analysis tools pick up symbols in V3Ast.h
23 #endif
24 
25 //######################################################################
26 // Standard defines for all AstNode final classes
27 
28 #define ASTNODE_NODE_FUNCS_NO_DTOR(name) \
29     virtual void accept(AstNVisitor& v) override { v.visit(this); } \
30     virtual AstNode* clone() override { return new Ast##name(*this); } \
31     static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \
32         return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \
33     } \
34     Ast##name* cloneTree(bool cloneNext) { \
35         return static_cast<Ast##name*>(AstNode::cloneTree(cloneNext)); \
36     } \
37     Ast##name* clonep() const { return static_cast<Ast##name*>(AstNode::clonep()); }
38 
39 #define ASTNODE_NODE_FUNCS(name) \
40     virtual ~Ast##name() override = default; \
41     ASTNODE_NODE_FUNCS_NO_DTOR(name)
42 
43 //######################################################################
44 // Macros generated by 'astgen'
45 
46 #include "V3AstNodes__gen_macros.h"
47 
48 //######################################################################
49 //=== Ast* : Specific types
50 // Netlist interconnect
51 
52 class AstConst final : public AstNodeMath {
53     // A constant
54 private:
55     V3Number m_num;  // Constant value
initWithNumber()56     void initWithNumber() {
57         if (m_num.isDouble()) {
58             dtypeSetDouble();
59         } else if (m_num.isString()) {
60             dtypeSetString();
61         } else {
62             dtypeSetLogicUnsized(m_num.width(), (m_num.sized() ? 0 : m_num.widthMin()),
63                                  VSigning::fromBool(m_num.isSigned()));
64         }
65         m_num.nodep(this);
66     }
67 
68 public:
AstConst(FileLine * fl,const V3Number & num)69     AstConst(FileLine* fl, const V3Number& num)
70         : ASTGEN_SUPER_Const(fl)
71         , m_num(num) {
72         initWithNumber();
73     }
74     class WidthedValue {};  // for creator type-overload selection
AstConst(FileLine * fl,WidthedValue,int width,uint32_t value)75     AstConst(FileLine* fl, WidthedValue, int width, uint32_t value)
76         : ASTGEN_SUPER_Const(fl)
77         , m_num(this, width, value) {
78         initWithNumber();
79     }
80     class DtypedValue {};  // for creator type-overload selection
AstConst(FileLine * fl,DtypedValue,AstNodeDType * nodedtypep,uint32_t value)81     AstConst(FileLine* fl, DtypedValue, AstNodeDType* nodedtypep, uint32_t value)
82         : ASTGEN_SUPER_Const(fl)
83         , m_num(this, nodedtypep->width(), value, nodedtypep->widthSized()) {
84         initWithNumber();
85     }
86     class StringToParse {};  // for creator type-overload selection
AstConst(FileLine * fl,StringToParse,const char * sourcep)87     AstConst(FileLine* fl, StringToParse, const char* sourcep)
88         : ASTGEN_SUPER_Const(fl)
89         , m_num(this, sourcep) {
90         initWithNumber();
91     }
92     class VerilogStringLiteral {};  // for creator type-overload selection
AstConst(FileLine * fl,VerilogStringLiteral,const string & str)93     AstConst(FileLine* fl, VerilogStringLiteral, const string& str)
94         : ASTGEN_SUPER_Const(fl)
95         , m_num(V3Number::VerilogStringLiteral(), this, str) {
96         initWithNumber();
97     }
AstConst(FileLine * fl,uint32_t num)98     AstConst(FileLine* fl, uint32_t num)
99         : ASTGEN_SUPER_Const(fl)
100         , m_num(this, 32, num) {
101         dtypeSetLogicUnsized(m_num.width(), 0, VSigning::UNSIGNED);
102     }
103     class Unsized32 {};  // for creator type-overload selection
AstConst(FileLine * fl,Unsized32,uint32_t num)104     AstConst(FileLine* fl, Unsized32, uint32_t num)  // Unsized 32-bit integer of specified value
105         : ASTGEN_SUPER_Const(fl)
106         , m_num(this, 32, num) {
107         m_num.width(32, false);
108         dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::UNSIGNED);
109     }
110     class Signed32 {};  // for creator type-overload selection
AstConst(FileLine * fl,Signed32,int32_t num)111     AstConst(FileLine* fl, Signed32, int32_t num)  // Signed 32-bit integer of specified value
112         : ASTGEN_SUPER_Const(fl)
113         , m_num(this, 32, num) {
114         m_num.width(32, true);
115         dtypeSetLogicUnsized(32, m_num.widthMin(), VSigning::SIGNED);
116     }
117     class Unsized64 {};  // for creator type-overload selection
AstConst(FileLine * fl,Unsized64,vluint64_t num)118     AstConst(FileLine* fl, Unsized64, vluint64_t num)
119         : ASTGEN_SUPER_Const(fl)
120         , m_num(this, 64, 0) {
121         m_num.setQuad(num);
122         dtypeSetLogicSized(64, VSigning::UNSIGNED);
123     }
124     class SizedEData {};  // for creator type-overload selection
AstConst(FileLine * fl,SizedEData,vluint64_t num)125     AstConst(FileLine* fl, SizedEData, vluint64_t num)
126         : ASTGEN_SUPER_Const(fl)
127         , m_num(this, VL_EDATASIZE, 0) {
128         m_num.setQuad(num);
129         dtypeSetLogicSized(VL_EDATASIZE, VSigning::UNSIGNED);
130     }
131     class RealDouble {};  // for creator type-overload selection
AstConst(FileLine * fl,RealDouble,double num)132     AstConst(FileLine* fl, RealDouble, double num)
133         : ASTGEN_SUPER_Const(fl)
134         , m_num(this, 64) {
135         m_num.setDouble(num);
136         dtypeSetDouble();
137     }
138     class String {};  // for creator type-overload selection
AstConst(FileLine * fl,String,const string & num)139     AstConst(FileLine* fl, String, const string& num)
140         : ASTGEN_SUPER_Const(fl)
141         , m_num(V3Number::String(), this, num) {
142         dtypeSetString();
143     }
144     class BitFalse {};
AstConst(FileLine * fl,BitFalse)145     AstConst(FileLine* fl, BitFalse)  // Shorthand const 0, dtype should be a logic of size 1
146         : ASTGEN_SUPER_Const(fl)
147         , m_num(this, 1, 0) {
148         dtypeSetBit();
149     }
150     // Shorthand const 1 (or with argument 0/1), dtype should be a logic of size 1
151     class BitTrue {};
152     AstConst(FileLine* fl, BitTrue, bool on = true)
ASTGEN_SUPER_Const(fl)153         : ASTGEN_SUPER_Const(fl)
154         , m_num(this, 1, on) {
155         dtypeSetBit();
156     }
157     class Null {};
AstConst(FileLine * fl,Null)158     AstConst(FileLine* fl, Null)
159         : ASTGEN_SUPER_Const(fl)
160         , m_num(V3Number::Null{}, this) {
161         dtypeSetBit();  // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here
162         initWithNumber();
163     }
ASTNODE_NODE_FUNCS(Const)164     ASTNODE_NODE_FUNCS(Const)
165     virtual string name() const override { return num().ascii(); }  // * = Value
num()166     const V3Number& num() const { return m_num; }  // * = Value
num()167     V3Number& num() { return m_num; }  // * = Value
toUInt()168     uint32_t toUInt() const { return num().toUInt(); }
toSInt()169     vlsint32_t toSInt() const { return num().toSInt(); }
toUQuad()170     vluint64_t toUQuad() const { return num().toUQuad(); }
emitVerilog()171     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()172     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()173     virtual bool cleanOut() const override { return true; }
same(const AstNode * samep)174     virtual bool same(const AstNode* samep) const override {
175         const AstConst* const sp = static_cast<const AstConst*>(samep);
176         return num().isCaseEq(sp->num());
177     }
instrCount()178     virtual int instrCount() const override { return widthInstrs(); }
isEqAllOnes()179     bool isEqAllOnes() const { return num().isEqAllOnes(width()); }
isEqAllOnesV()180     bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
181     // Parse string and create appropriate type of AstConst.
182     // May return nullptr on parse failure.
183     static AstConst* parseParamLiteral(FileLine* fl, const string& literal);
184 };
185 
186 class AstEmptyQueue final : public AstNodeMath {
187 public:
AstEmptyQueue(FileLine * fl)188     AstEmptyQueue(FileLine* fl)
189         : ASTGEN_SUPER_EmptyQueue(fl) {}
ASTNODE_NODE_FUNCS(EmptyQueue)190     ASTNODE_NODE_FUNCS(EmptyQueue)
191     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitVerilog()192     virtual string emitVerilog() override { return "{}"; }
same(const AstNode * samep)193     virtual bool same(const AstNode* samep) const override { return true; }
cleanOut()194     virtual bool cleanOut() const override { return true; }
195 };
196 
197 class AstRange final : public AstNodeRange {
198     // Range specification, for use under variables and cells
199 public:
AstRange(FileLine * fl,AstNode * leftp,AstNode * rightp)200     AstRange(FileLine* fl, AstNode* leftp, AstNode* rightp)
201         : ASTGEN_SUPER_Range(fl) {
202         setOp2p(leftp);
203         setOp3p(rightp);
204     }
AstRange(FileLine * fl,int left,int right)205     AstRange(FileLine* fl, int left, int right)
206         : ASTGEN_SUPER_Range(fl) {
207         setOp2p(new AstConst(fl, left));
208         setOp3p(new AstConst(fl, right));
209     }
AstRange(FileLine * fl,const VNumRange & range)210     AstRange(FileLine* fl, const VNumRange& range)
211         : ASTGEN_SUPER_Range(fl) {
212         setOp2p(new AstConst(fl, range.left()));
213         setOp3p(new AstConst(fl, range.right()));
214     }
ASTNODE_NODE_FUNCS(Range)215     ASTNODE_NODE_FUNCS(Range)
216     AstNode* leftp() const { return op2p(); }
rightp()217     AstNode* rightp() const { return op3p(); }
leftConst()218     int leftConst() const {
219         AstConst* const constp = VN_CAST(leftp(), Const);
220         return (constp ? constp->toSInt() : 0);
221     }
rightConst()222     int rightConst() const {
223         AstConst* const constp = VN_CAST(rightp(), Const);
224         return (constp ? constp->toSInt() : 0);
225     }
hiConst()226     int hiConst() const {
227         const int l = leftConst();
228         const int r = rightConst();
229         return l > r ? l : r;
230     }
loConst()231     int loConst() const {
232         const int l = leftConst();
233         const int r = rightConst();
234         return l > r ? r : l;
235     }
elementsConst()236     int elementsConst() const { return hiConst() - loConst() + 1; }
littleEndian()237     bool littleEndian() const { return leftConst() < rightConst(); }
238     virtual void dump(std::ostream& str) const override;
emitC()239     virtual string emitC() { V3ERROR_NA_RETURN(""); }
same(const AstNode * samep)240     virtual bool same(const AstNode* samep) const override { return true; }
241 };
242 
243 class AstBracketRange final : public AstNodeRange {
244     // Parser only concept "[lhsp]", a AstUnknownRange, QueueRange or Range,
245     // unknown until lhsp type is determined
246 public:
AstBracketRange(FileLine * fl,AstNode * elementsp)247     AstBracketRange(FileLine* fl, AstNode* elementsp)
248         : ASTGEN_SUPER_BracketRange(fl) {
249         setOp1p(elementsp);
250     }
ASTNODE_NODE_FUNCS(BracketRange)251     ASTNODE_NODE_FUNCS(BracketRange)
252     virtual string emitC() { V3ERROR_NA_RETURN(""); }
emitVerilog()253     virtual string emitVerilog() { V3ERROR_NA_RETURN(""); }
same(const AstNode * samep)254     virtual bool same(const AstNode* samep) const override { return true; }
255     // Will be removed in V3Width, which relies on this
256     // being a child not a dtype pointed node
maybePointedTo()257     virtual bool maybePointedTo() const override { return false; }
elementsp()258     AstNode* elementsp() const { return op1p(); }
259 };
260 
261 class AstUnsizedRange final : public AstNodeRange {
262     // Unsized range specification, for open arrays
263 public:
AstUnsizedRange(FileLine * fl)264     explicit AstUnsizedRange(FileLine* fl)
265         : ASTGEN_SUPER_UnsizedRange(fl) {}
ASTNODE_NODE_FUNCS(UnsizedRange)266     ASTNODE_NODE_FUNCS(UnsizedRange)
267     virtual string emitC() { V3ERROR_NA_RETURN(""); }
emitVerilog()268     virtual string emitVerilog() { return "[]"; }
same(const AstNode * samep)269     virtual bool same(const AstNode* samep) const override { return true; }
270 };
271 
272 class AstGatePin final : public AstNodeMath {
273     // Possibly expand a gate primitive input pin value to match the range of the gate primitive
274 public:
AstGatePin(FileLine * fl,AstNode * lhsp,AstRange * rangep)275     AstGatePin(FileLine* fl, AstNode* lhsp, AstRange* rangep)
276         : ASTGEN_SUPER_GatePin(fl) {
277         setOp1p(lhsp);
278         setOp2p(rangep);
279     }
ASTNODE_NODE_FUNCS(GatePin)280     ASTNODE_NODE_FUNCS(GatePin)
281     virtual string emitVerilog() override { return "%l"; }
emitC()282     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()283     virtual bool cleanOut() const override { return true; }
exprp()284     AstNode* exprp() const { return op1p(); }  // op1 = Pin expression
rangep()285     AstRange* rangep() const { return VN_AS(op2p(), Range); }  // op2 = Range of pin
286 };
287 
288 //######################################################################
289 // Classes
290 
291 class AstClassPackage final : public AstNodeModule {
292     // The static information portion of a class (treated similarly to a package)
293     AstClass* m_classp
294         = nullptr;  // Class package this is under (weak pointer, hard link is other way)
295 public:
AstClassPackage(FileLine * fl,const string & name)296     AstClassPackage(FileLine* fl, const string& name)
297         : ASTGEN_SUPER_ClassPackage(fl, name) {}
ASTNODE_NODE_FUNCS(ClassPackage)298     ASTNODE_NODE_FUNCS(ClassPackage)
299     virtual string verilogKwd() const override { return "/*class*/package"; }
300     virtual const char* broken() const override;
timescaleMatters()301     virtual bool timescaleMatters() const override { return false; }
classp()302     AstClass* classp() const { return m_classp; }
classp(AstClass * classp)303     void classp(AstClass* classp) { m_classp = classp; }
304 };
305 
306 class AstClass final : public AstNodeModule {
307     // TYPES
308     using MemberNameMap = std::map<const std::string, AstNode*>;
309     // MEMBERS
310     MemberNameMap m_members;  // Members or method children
311     AstClassPackage* m_classOrPackagep = nullptr;  // Class package this is under
312     bool m_virtual = false;  // Virtual class
313     bool m_extended = false;  // Is extension or extended by other classes
314     void insertCache(AstNode* nodep);
315 
316 public:
AstClass(FileLine * fl,const string & name)317     AstClass(FileLine* fl, const string& name)
318         : ASTGEN_SUPER_Class(fl, name) {}
ASTNODE_NODE_FUNCS(Class)319     ASTNODE_NODE_FUNCS(Class)
320     virtual string verilogKwd() const override { return "class"; }
maybePointedTo()321     virtual bool maybePointedTo() const override { return true; }
322     virtual void dump(std::ostream& str) const override;
broken()323     virtual const char* broken() const override {
324         BROKEN_BASE_RTN(AstNodeModule::broken());
325         BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
326         return nullptr;
327     }
timescaleMatters()328     virtual bool timescaleMatters() const override { return false; }
329     // op1/op2/op3 in AstNodeModule
classOrPackagep()330     AstClassPackage* classOrPackagep() const { return m_classOrPackagep; }
classOrPackagep(AstClassPackage * classpackagep)331     void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; }
membersp()332     AstNode* membersp() const { return stmtsp(); }  // op2 = List of statements
addMembersp(AstNode * nodep)333     void addMembersp(AstNode* nodep) {
334         insertCache(nodep);
335         addStmtp(nodep);
336     }
extendsp()337     AstClassExtends* extendsp() const { return VN_AS(op4p(), ClassExtends); }
extendsp(AstNode * nodep)338     void extendsp(AstNode* nodep) { addNOp4p(nodep); }
clearCache()339     void clearCache() { m_members.clear(); }
340     void repairCache();
findMember(const string & name)341     AstNode* findMember(const string& name) const {
342         const auto it = m_members.find(name);
343         return (it == m_members.end()) ? nullptr : it->second;
344     }
isExtended()345     bool isExtended() const { return m_extended; }
isExtended(bool flag)346     void isExtended(bool flag) { m_extended = flag; }
isVirtual()347     bool isVirtual() const { return m_virtual; }
isVirtual(bool flag)348     void isVirtual(bool flag) { m_virtual = flag; }
349     // Return true if this class is an extension of base class (SLOW)
350     // Accepts nullptrs
351     static bool isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp);
352 };
353 
354 class AstClassExtends final : public AstNode {
355     // Children: List of AstParseRef for packages/classes
356     // during early parse, then moves to dtype
357 public:
AstClassExtends(FileLine * fl,AstNode * classOrPkgsp)358     AstClassExtends(FileLine* fl, AstNode* classOrPkgsp)
359         : ASTGEN_SUPER_ClassExtends(fl) {
360         setNOp2p(classOrPkgsp);  // Only for parser
361     }
ASTNODE_NODE_FUNCS(ClassExtends)362     ASTNODE_NODE_FUNCS(ClassExtends)
363     virtual bool hasDType() const override { return true; }
verilogKwd()364     virtual string verilogKwd() const override { return "extends"; }
childDTypep()365     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)366     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
classOrPkgsp()367     AstNode* classOrPkgsp() const { return op2p(); }
368     AstClass* classp() const;  // Class being extended (after link)
369 };
370 
371 //######################################################################
372 //==== Data Types
373 
374 class AstParamTypeDType final : public AstNodeDType {
375     // Parents: MODULE
376     // A parameter type statement; much like a var or typedef
377 private:
378     const AstVarType m_varType;  // Type of variable (for localparam vs. param)
379     string m_name;  // Name of variable
380 public:
AstParamTypeDType(FileLine * fl,AstVarType type,const string & name,VFlagChildDType,AstNodeDType * dtp)381     AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType,
382                       AstNodeDType* dtp)
383         : ASTGEN_SUPER_ParamTypeDType(fl)
384         , m_varType{type}
385         , m_name{name} {
386         childDTypep(dtp);  // Only for parser
387         dtypep(nullptr);  // V3Width will resolve
388     }
ASTNODE_NODE_FUNCS(ParamTypeDType)389     ASTNODE_NODE_FUNCS(ParamTypeDType)
390     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
391     // op1 = Type assigning to
childDTypep()392     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)393     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()394     virtual AstNodeDType* subDTypep() const override {
395         return dtypep() ? dtypep() : childDTypep();
396     }
basicp()397     virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
skipRefp()398     virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); }
skipRefToConstp()399     virtual AstNodeDType* skipRefToConstp() const override {
400         return subDTypep()->skipRefToConstp();
401     }
skipRefToEnump()402     virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
similarDType(AstNodeDType * samep)403     virtual bool similarDType(AstNodeDType* samep) const override {
404         const AstParamTypeDType* const sp = static_cast<const AstParamTypeDType*>(samep);
405         return type() == samep->type() && sp
406                && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp());
407     }
widthAlignBytes()408     virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); }
widthTotalBytes()409     virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); }
410     // METHODS
name()411     virtual string name() const override { return m_name; }
maybePointedTo()412     virtual bool maybePointedTo() const override { return true; }
hasDType()413     virtual bool hasDType() const override { return true; }
name(const string & flag)414     virtual void name(const string& flag) override { m_name = flag; }
varType()415     AstVarType varType() const { return m_varType; }  // * = Type of variable
isParam()416     bool isParam() const { return true; }
isGParam()417     bool isGParam() const { return (varType() == AstVarType::GPARAM); }
isCompound()418     virtual bool isCompound() const override {
419         v3fatalSrc("call isCompound on subdata type, not reference");
420         return false;
421     }
422 };
423 
424 class AstTypedef final : public AstNode {
425 private:
426     string m_name;
427     bool m_attrPublic;
428     string m_tag;  // Holds the string of the verilator tag -- used in XML output.
429 public:
AstTypedef(FileLine * fl,const string & name,AstNode * attrsp,VFlagChildDType,AstNodeDType * dtp)430     AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType,
431                AstNodeDType* dtp)
432         : ASTGEN_SUPER_Typedef(fl)
433         , m_name{name} {
434         childDTypep(dtp);  // Only for parser
435         addAttrsp(attrsp);
436         dtypep(nullptr);  // V3Width will resolve
437         m_attrPublic = false;
438     }
439     ASTNODE_NODE_FUNCS(Typedef)
440     virtual void dump(std::ostream& str) const override;
getChildDTypep()441     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
442     // op1 = Type assigning to
childDTypep()443     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)444     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()445     virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
addAttrsp(AstNode * nodep)446     void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
attrsp()447     AstNode* attrsp() const { return op4p(); }  // op4 = Attributes during early parse
448     // METHODS
name()449     virtual string name() const override { return m_name; }
maybePointedTo()450     virtual bool maybePointedTo() const override { return true; }
hasDType()451     virtual bool hasDType() const override { return true; }
name(const string & flag)452     virtual void name(const string& flag) override { m_name = flag; }
attrPublic()453     bool attrPublic() const { return m_attrPublic; }
attrPublic(bool flag)454     void attrPublic(bool flag) { m_attrPublic = flag; }
tag(const string & text)455     virtual void tag(const string& text) override { m_tag = text; }
tag()456     virtual string tag() const override { return m_tag; }
457 };
458 
459 class AstTypedefFwd final : public AstNode {
460     // Forward declaration of a type; stripped after netlist parsing is complete
461 private:
462     string m_name;
463 
464 public:
AstTypedefFwd(FileLine * fl,const string & name)465     AstTypedefFwd(FileLine* fl, const string& name)
466         : ASTGEN_SUPER_TypedefFwd(fl)
467         , m_name{name} {}
ASTNODE_NODE_FUNCS(TypedefFwd)468     ASTNODE_NODE_FUNCS(TypedefFwd)
469     // METHODS
470     virtual string name() const override { return m_name; }
maybePointedTo()471     virtual bool maybePointedTo() const override { return true; }
472 };
473 
474 class AstDefImplicitDType final : public AstNodeDType {
475     // For parsing enum/struct/unions that are declared with a variable rather than typedef
476     // This allows "var enum {...} a,b" to share the enum definition for both variables
477     // After link, these become typedefs
478 private:
479     string m_name;
480     void* m_containerp;  // In what scope is the name unique, so we can know what are duplicate
481                          // definitions (arbitrary value)
482     const int m_uniqueNum;
483 
484 public:
AstDefImplicitDType(FileLine * fl,const string & name,void * containerp,VFlagChildDType,AstNodeDType * dtp)485     AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType,
486                         AstNodeDType* dtp)
487         : ASTGEN_SUPER_DefImplicitDType(fl)
488         , m_name{name}
489         , m_containerp{containerp}
490         , m_uniqueNum{uniqueNumInc()} {
491         childDTypep(dtp);  // Only for parser
492         dtypep(nullptr);  // V3Width will resolve
493     }
ASTNODE_NODE_FUNCS(DefImplicitDType)494     ASTNODE_NODE_FUNCS(DefImplicitDType)
495     int uniqueNum() const { return m_uniqueNum; }
same(const AstNode * samep)496     virtual bool same(const AstNode* samep) const override {
497         const AstDefImplicitDType* const sp = static_cast<const AstDefImplicitDType*>(samep);
498         return uniqueNum() == sp->uniqueNum();
499     }
similarDType(AstNodeDType * samep)500     virtual bool similarDType(AstNodeDType* samep) const override {
501         return type() == samep->type() && same(samep);
502     }
getChildDTypep()503     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
504     // op1 = Range of variable
childDTypep()505     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)506     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()507     virtual AstNodeDType* subDTypep() const override {
508         return dtypep() ? dtypep() : childDTypep();
509     }
containerp()510     void* containerp() const { return m_containerp; }
511     // METHODS
512     // op1 = Range of variable
dtypeSkipRefp()513     AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); }
basicp()514     virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
skipRefp()515     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()516     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()517     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()518     virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); }
widthTotalBytes()519     virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); }
name()520     virtual string name() const override { return m_name; }
name(const string & flag)521     virtual void name(const string& flag) override { m_name = flag; }
isCompound()522     virtual bool isCompound() const override { return false; }
523 };
524 
525 class AstAssocArrayDType final : public AstNodeDType {
526     // Associative array data type, ie "[some_dtype]"
527     // Children: DTYPE (moved to refDTypep() in V3Width)
528     // Children: DTYPE (the key, which remains here as a pointer)
529 private:
530     AstNodeDType* m_refDTypep;  // Elements of this type (after widthing)
531     AstNodeDType* m_keyDTypep;  // Keys of this type (after widthing)
532 public:
AstAssocArrayDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp,AstNodeDType * keyDtp)533     AstAssocArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeDType* keyDtp)
534         : ASTGEN_SUPER_AssocArrayDType(fl) {
535         childDTypep(dtp);  // Only for parser
536         keyChildDTypep(keyDtp);  // Only for parser
537         refDTypep(nullptr);
538         keyDTypep(nullptr);
539         dtypep(nullptr);  // V3Width will resolve
540     }
ASTNODE_NODE_FUNCS(AssocArrayDType)541     ASTNODE_NODE_FUNCS(AssocArrayDType)
542     virtual const char* broken() const override {
543         BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
544                      || (!m_refDTypep && childDTypep())));
545         BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists())
546                      || (!m_keyDTypep && childDTypep())));
547         return nullptr;
548     }
cloneRelink()549     virtual void cloneRelink() override {
550         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
551         if (m_keyDTypep && m_keyDTypep->clonep()) m_keyDTypep = m_keyDTypep->clonep();
552     }
same(const AstNode * samep)553     virtual bool same(const AstNode* samep) const override {
554         const AstAssocArrayDType* const asamep = static_cast<const AstAssocArrayDType*>(samep);
555         if (!asamep->subDTypep()) return false;
556         if (!asamep->keyDTypep()) return false;
557         return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep());
558     }
similarDType(AstNodeDType * samep)559     virtual bool similarDType(AstNodeDType* samep) const override {
560         const AstAssocArrayDType* const asamep = static_cast<const AstAssocArrayDType*>(samep);
561         return type() == samep->type() && asamep->subDTypep()
562                && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
563     }
564     virtual string prettyDTypeName() const override;
565     virtual void dumpSmall(std::ostream& str) const override;
getChildDTypep()566     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
getChild2DTypep()567     virtual AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); }
568     // op1 = Range of variable
childDTypep()569     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)570     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()571     virtual AstNodeDType* subDTypep() const override {
572         return m_refDTypep ? m_refDTypep : childDTypep();
573     }
refDTypep(AstNodeDType * nodep)574     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()575     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)576     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
virtRefDType2p()577     virtual AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; }
virtRefDType2p(AstNodeDType * nodep)578     virtual void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); }
579     //
keyDTypep()580     AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); }
keyDTypep(AstNodeDType * nodep)581     void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; }
582     // op1 = Range of variable
keyChildDTypep()583     AstNodeDType* keyChildDTypep() const { return VN_AS(op2p(), NodeDType); }
keyChildDTypep(AstNodeDType * nodep)584     void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); }
585     // METHODS
basicp()586     virtual AstBasicDType* basicp() const override { return nullptr; }
skipRefp()587     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()588     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()589     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()590     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
widthTotalBytes()591     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
isCompound()592     virtual bool isCompound() const override { return true; }
593 };
594 
595 class AstBracketArrayDType final : public AstNodeDType {
596     // Associative/Queue/Normal array data type, ie "[dtype_or_expr]"
597     // only for early parsing then becomes another data type
598     // Children: DTYPE (moved to refDTypep() in V3Width)
599     // Children: DTYPE (the key)
600 public:
AstBracketArrayDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp,AstNode * elementsp)601     AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* elementsp)
602         : ASTGEN_SUPER_BracketArrayDType(fl) {
603         setOp1p(dtp);  // Only for parser
604         setOp2p(elementsp);  // Only for parser
605     }
ASTNODE_NODE_FUNCS(BracketArrayDType)606     ASTNODE_NODE_FUNCS(BracketArrayDType)
607     virtual bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); }
608     // op1 = Range of variable
childDTypep()609     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
subDTypep()610     virtual AstNodeDType* subDTypep() const override { return childDTypep(); }
611     // op2 = Range of variable
elementsp()612     AstNode* elementsp() const { return op2p(); }
613     // METHODS
614     // Will be removed in V3Width, which relies on this
615     // being a child not a dtype pointed node
maybePointedTo()616     virtual bool maybePointedTo() const override { return false; }
basicp()617     virtual AstBasicDType* basicp() const override { return nullptr; }
skipRefp()618     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()619     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()620     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()621     virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); }
widthTotalBytes()622     virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); }
isCompound()623     virtual bool isCompound() const override { return true; }
624 };
625 
626 class AstDynArrayDType final : public AstNodeDType {
627     // Dynamic array data type, ie "[]"
628     // Children: DTYPE (moved to refDTypep() in V3Width)
629 private:
630     AstNodeDType* m_refDTypep;  // Elements of this type (after widthing)
631 public:
AstDynArrayDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp)632     AstDynArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
633         : ASTGEN_SUPER_DynArrayDType(fl) {
634         childDTypep(dtp);  // Only for parser
635         refDTypep(nullptr);
636         dtypep(nullptr);  // V3Width will resolve
637     }
AstDynArrayDType(FileLine * fl,AstNodeDType * dtp)638     AstDynArrayDType(FileLine* fl, AstNodeDType* dtp)
639         : ASTGEN_SUPER_DynArrayDType(fl) {
640         refDTypep(dtp);
641         dtypep(nullptr);  // V3Width will resolve
642     }
ASTNODE_NODE_FUNCS(DynArrayDType)643     ASTNODE_NODE_FUNCS(DynArrayDType)
644     virtual const char* broken() const override {
645         BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
646                      || (!m_refDTypep && childDTypep())));
647         return nullptr;
648     }
cloneRelink()649     virtual void cloneRelink() override {
650         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
651     }
same(const AstNode * samep)652     virtual bool same(const AstNode* samep) const override {
653         const AstAssocArrayDType* const asamep = static_cast<const AstAssocArrayDType*>(samep);
654         if (!asamep->subDTypep()) return false;
655         return subDTypep() == asamep->subDTypep();
656     }
similarDType(AstNodeDType * samep)657     virtual bool similarDType(AstNodeDType* samep) const override {
658         const AstAssocArrayDType* const asamep = static_cast<const AstAssocArrayDType*>(samep);
659         return type() == samep->type() && asamep->subDTypep()
660                && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
661     }
662     virtual string prettyDTypeName() const override;
663     virtual void dumpSmall(std::ostream& str) const override;
getChildDTypep()664     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
665     // op1 = Range of variable
childDTypep()666     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)667     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()668     virtual AstNodeDType* subDTypep() const override {
669         return m_refDTypep ? m_refDTypep : childDTypep();
670     }
refDTypep(AstNodeDType * nodep)671     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()672     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)673     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
674     // METHODS
basicp()675     virtual AstBasicDType* basicp() const override { return nullptr; }
skipRefp()676     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()677     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()678     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()679     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
widthTotalBytes()680     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
isCompound()681     virtual bool isCompound() const override { return true; }
682 };
683 
684 class AstPackArrayDType final : public AstNodeArrayDType {
685     // Packed array data type, ie "some_dtype [2:0] var_name"
686     // Children: DTYPE (moved to refDTypep() in V3Width)
687     // Children: RANGE (array bounds)
688 public:
AstPackArrayDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp,AstRange * rangep)689     AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
690         : ASTGEN_SUPER_PackArrayDType(fl) {
691         childDTypep(dtp);  // Only for parser
692         refDTypep(nullptr);
693         setOp2p(rangep);
694         dtypep(nullptr);  // V3Width will resolve
695         const int width = subDTypep()->width() * rangep->elementsConst();
696         widthForce(width, width);
697     }
AstPackArrayDType(FileLine * fl,AstNodeDType * dtp,AstRange * rangep)698     AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
699         : ASTGEN_SUPER_PackArrayDType(fl) {
700         refDTypep(dtp);
701         setOp2p(rangep);
702         dtypep(this);
703         const int width = subDTypep()->width() * rangep->elementsConst();
704         widthForce(width, width);
705     }
706     ASTNODE_NODE_FUNCS(PackArrayDType)
707     virtual string prettyDTypeName() const override;
isCompound()708     virtual bool isCompound() const override { return false; }
709 };
710 
711 class AstUnpackArrayDType final : public AstNodeArrayDType {
712     // Array data type, ie "some_dtype var_name [2:0]"
713     // Children: DTYPE (moved to refDTypep() in V3Width)
714     // Children: RANGE (array bounds)
715     bool m_isCompound = false;  // Non-POD subDType, or parent requires compound
716 public:
AstUnpackArrayDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp,AstRange * rangep)717     AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
718         : ASTGEN_SUPER_UnpackArrayDType(fl) {
719         childDTypep(dtp);  // Only for parser
720         refDTypep(nullptr);
721         setOp2p(rangep);
722         dtypep(nullptr);  // V3Width will resolve
723         // For backward compatibility AstNodeArrayDType and others inherit
724         // width and signing from the subDType/base type
725         widthFromSub(subDTypep());
726     }
AstUnpackArrayDType(FileLine * fl,AstNodeDType * dtp,AstRange * rangep)727     AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
728         : ASTGEN_SUPER_UnpackArrayDType(fl) {
729         refDTypep(dtp);
730         setOp2p(rangep);
731         dtypep(this);
732         // For backward compatibility AstNodeArrayDType and others inherit
733         // width and signing from the subDType/base type
734         widthFromSub(subDTypep());
735     }
736     ASTNODE_NODE_FUNCS(UnpackArrayDType)
737     virtual string prettyDTypeName() const override;
same(const AstNode * samep)738     virtual bool same(const AstNode* samep) const override {
739         const AstUnpackArrayDType* const sp = static_cast<const AstUnpackArrayDType*>(samep);
740         return m_isCompound == sp->m_isCompound;
741     }
742     // Outer dimension comes first. The first element is this node.
743     std::vector<AstUnpackArrayDType*> unpackDimensions();
isCompound(bool flag)744     void isCompound(bool flag) { m_isCompound = flag; }
isCompound()745     virtual bool isCompound() const override { return m_isCompound; }
746 };
747 
748 class AstUnsizedArrayDType final : public AstNodeDType {
749     // Unsized/open-range Array data type, ie "some_dtype var_name []"
750     // Children: DTYPE (moved to refDTypep() in V3Width)
751 private:
752     AstNodeDType* m_refDTypep;  // Elements of this type (after widthing)
753 public:
AstUnsizedArrayDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp)754     AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
755         : ASTGEN_SUPER_UnsizedArrayDType(fl) {
756         childDTypep(dtp);  // Only for parser
757         refDTypep(nullptr);
758         dtypep(nullptr);  // V3Width will resolve
759     }
ASTNODE_NODE_FUNCS(UnsizedArrayDType)760     ASTNODE_NODE_FUNCS(UnsizedArrayDType)
761     virtual const char* broken() const override {
762         BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
763                      || (!m_refDTypep && childDTypep())));
764         return nullptr;
765     }
cloneRelink()766     virtual void cloneRelink() override {
767         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
768     }
same(const AstNode * samep)769     virtual bool same(const AstNode* samep) const override {
770         const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
771         if (!asamep->subDTypep()) return false;
772         return (subDTypep() == asamep->subDTypep());
773     }
similarDType(AstNodeDType * samep)774     virtual bool similarDType(AstNodeDType* samep) const override {
775         const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
776         return type() == samep->type() && asamep->subDTypep()
777                && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
778     }
779     virtual void dumpSmall(std::ostream& str) const override;
getChildDTypep()780     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
781     // op1 = Range of variable
childDTypep()782     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)783     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()784     virtual AstNodeDType* subDTypep() const override {
785         return m_refDTypep ? m_refDTypep : childDTypep();
786     }
refDTypep(AstNodeDType * nodep)787     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()788     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)789     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
790     // METHODS
basicp()791     virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
skipRefp()792     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()793     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()794     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()795     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
widthTotalBytes()796     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
isCompound()797     virtual bool isCompound() const override { return true; }
798 };
799 
800 class AstBasicDType final : public AstNodeDType {
801     // Builtin atomic/vectored data type
802     // Children: RANGE (converted to constant in V3Width)
803 private:
804     struct Members {
805         AstBasicDTypeKwd m_keyword;  // (also in VBasicTypeKey) What keyword created basic type
806         VNumRange m_nrange;  // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword)
807         bool operator==(const Members& rhs) const {
808             return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange;
809         }
810     } m;
811     // See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned)
812 public:
813     AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN)
ASTGEN_SUPER_BasicDType(fl)814         : ASTGEN_SUPER_BasicDType(fl) {
815         init(kwd, signst, 0, -1, nullptr);
816     }
AstBasicDType(FileLine * fl,VFlagLogicPacked,int wantwidth)817     AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth)
818         : ASTGEN_SUPER_BasicDType(fl) {
819         init(AstBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr);
820     }
AstBasicDType(FileLine * fl,VFlagBitPacked,int wantwidth)821     AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth)
822         : ASTGEN_SUPER_BasicDType(fl) {
823         init(AstBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr);
824     }
AstBasicDType(FileLine * fl,AstBasicDTypeKwd kwd,VSigning numer,int wantwidth,int widthmin)825     AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin)
826         : ASTGEN_SUPER_BasicDType(fl) {
827         init(kwd, numer, wantwidth, widthmin, nullptr);
828     }
AstBasicDType(FileLine * fl,AstBasicDTypeKwd kwd,VSigning numer,VNumRange range,int widthmin)829     AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSigning numer, VNumRange range,
830                   int widthmin)
831         : ASTGEN_SUPER_BasicDType(fl) {
832         init(kwd, numer, range.elements(), widthmin, nullptr);
833         m.m_nrange = range;  // as init() presumes lsb==0, but range.lsb() might not be
834     }
835     // See also addRange in verilog.y
836 private:
init(AstBasicDTypeKwd kwd,VSigning numer,int wantwidth,int wantwidthmin,AstRange * rangep)837     void init(AstBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
838               AstRange* rangep) {
839         // wantwidth=0 means figure it out, but if a widthmin is >=0
840         //    we allow width 0 so that {{0{x}},y} works properly
841         // wantwidthmin=-1:  default, use wantwidth if it is non zero
842         m.m_keyword = kwd;
843         // Implicitness: // "parameter X" is implicit and sized from initial
844         // value, "parameter reg x" not
845         if (keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT) {
846             if (rangep || wantwidth) m.m_keyword = AstBasicDTypeKwd::LOGIC;
847         }
848         if (numer == VSigning::NOSIGN) {
849             if (keyword().isSigned()) {
850                 numer = VSigning::SIGNED;
851             } else if (keyword().isUnsigned()) {
852                 numer = VSigning::UNSIGNED;
853             }
854         }
855         numeric(numer);
856         if (!rangep && (wantwidth || wantwidthmin >= 0)) {  // Constant width
857             if (wantwidth > 1) m.m_nrange.init(wantwidth - 1, 0, false);
858             const int wmin = wantwidthmin >= 0 ? wantwidthmin : wantwidth;
859             widthForce(wantwidth, wmin);
860         } else if (!rangep) {  // Set based on keyword properties
861             // V3Width will pull from this width
862             if (keyword().width() > 1 && !isOpaque()) {
863                 m.m_nrange.init(keyword().width() - 1, 0, false);
864             }
865             widthForce(keyword().width(), keyword().width());
866         } else {
867             widthForce(rangep->elementsConst(),
868                        rangep->elementsConst());  // Maybe unknown if parameters underneath it
869         }
870         setNOp1p(rangep);
871         dtypep(this);
872     }
873 
874 public:
875     ASTNODE_NODE_FUNCS(BasicDType)
876     virtual void dump(std::ostream& str) const override;
877     // width/widthMin/numeric compared elsewhere
same(const AstNode * samep)878     virtual bool same(const AstNode* samep) const override {
879         const AstBasicDType* const sp = static_cast<const AstBasicDType*>(samep);
880         return m == sp->m;
881     }
similarDType(AstNodeDType * samep)882     virtual bool similarDType(AstNodeDType* samep) const override {
883         return type() == samep->type() && same(samep);
884     }
name()885     virtual string name() const override { return m.m_keyword.ascii(); }
886     virtual string prettyDTypeName() const override;
broken()887     virtual const char* broken() const override {
888         BROKEN_RTN(dtypep() != this);
889         return nullptr;
890     }
rangep()891     AstRange* rangep() const { return VN_AS(op1p(), Range); }  // op1 = Range of variable
rangep(AstRange * nodep)892     void rangep(AstRange* nodep) { setNOp1p(nodep); }
setSignedState(const VSigning & signst)893     void setSignedState(const VSigning& signst) {
894         // Note NOSIGN does NOT change the state; this is required by the parser
895         if (signst == VSigning::UNSIGNED) {
896             numeric(signst);
897         } else if (signst == VSigning::SIGNED) {
898             numeric(signst);
899         }
900     }
901     // METHODS
basicp()902     virtual AstBasicDType* basicp() const override { return (AstBasicDType*)this; }
skipRefp()903     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()904     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()905     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
906     // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
907     virtual int widthAlignBytes() const override;
908     // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
909     virtual int widthTotalBytes() const override;
isFourstate()910     virtual bool isFourstate() const override { return keyword().isFourstate(); }
keyword()911     AstBasicDTypeKwd keyword() const {  // Avoid using - use isSomething accessors instead
912         return m.m_keyword;
913     }
isBitLogic()914     bool isBitLogic() const { return keyword().isBitLogic(); }
isDouble()915     bool isDouble() const { return keyword().isDouble(); }
isEventValue()916     bool isEventValue() const { return keyword().isEventValue(); }
isOpaque()917     bool isOpaque() const { return keyword().isOpaque(); }
isString()918     bool isString() const { return keyword().isString(); }
isZeroInit()919     bool isZeroInit() const { return keyword().isZeroInit(); }
isRanged()920     bool isRanged() const { return rangep() || m.m_nrange.ranged(); }
isDpiBitVec()921     bool isDpiBitVec() const {  // DPI uses svBitVecVal
922         return keyword() == AstBasicDTypeKwd::BIT && isRanged();
923     }
isDpiLogicVec()924     bool isDpiLogicVec() const {  // DPI uses svLogicVecVal
925         return keyword().isFourstate() && !(keyword() == AstBasicDTypeKwd::LOGIC && !isRanged());
926     }
isDpiPrimitive()927     bool isDpiPrimitive() const {  // DPI uses a primitive type
928         return !isDpiBitVec() && !isDpiLogicVec();
929     }
930     // Generally the lo/hi/left/right funcs should be used instead of nrange()
nrange()931     const VNumRange& nrange() const { return m.m_nrange; }
hi()932     int hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); }
lo()933     int lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); }
elements()934     int elements() const { return (rangep() ? rangep()->elementsConst() : m.m_nrange.elements()); }
left()935     int left() const { return littleEndian() ? lo() : hi(); }  // How to show a declaration
right()936     int right() const { return littleEndian() ? hi() : lo(); }
littleEndian()937     bool littleEndian() const {
938         return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian());
939     }
implicit()940     bool implicit() const { return keyword() == AstBasicDTypeKwd::LOGIC_IMPLICIT; }
declRange()941     VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; }
cvtRangeConst()942     void cvtRangeConst() {  // Convert to smaller representation
943         if (rangep() && VN_IS(rangep()->leftp(), Const) && VN_IS(rangep()->rightp(), Const)) {
944             m.m_nrange = VNumRange{rangep()->leftConst(), rangep()->rightConst()};
945             rangep()->unlinkFrBackWithNext()->deleteTree();
946             rangep(nullptr);
947         }
948     }
isCompound()949     virtual bool isCompound() const override { return isString(); }
950 };
951 
952 class AstConstDType final : public AstNodeDType {
953     // const data type, ie "const some_dtype var_name [2:0]"
954     // ConstDType are removed in V3LinkLValue and become AstVar::isConst.
955     // When more generic types are supported AstConstDType will be propagated further.
956 private:
957     AstNodeDType* m_refDTypep;  // Inherit from this base data type
958 public:
AstConstDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp)959     AstConstDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
960         : ASTGEN_SUPER_ConstDType(fl) {
961         childDTypep(dtp);  // Only for parser
962         refDTypep(nullptr);  // V3Width will resolve
963         dtypep(nullptr);  // V3Width will resolve
964         widthFromSub(subDTypep());
965     }
ASTNODE_NODE_FUNCS(ConstDType)966     ASTNODE_NODE_FUNCS(ConstDType)
967     virtual const char* broken() const override {
968         BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
969                      || (!m_refDTypep && childDTypep())));
970         return nullptr;
971     }
cloneRelink()972     virtual void cloneRelink() override {
973         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
974     }
same(const AstNode * samep)975     virtual bool same(const AstNode* samep) const override {
976         const AstConstDType* const sp = static_cast<const AstConstDType*>(samep);
977         return (m_refDTypep == sp->m_refDTypep);
978     }
similarDType(AstNodeDType * samep)979     virtual bool similarDType(AstNodeDType* samep) const override {
980         return skipRefp()->similarDType(samep->skipRefp());
981     }
getChildDTypep()982     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
983     // op1 = Range of variable
childDTypep()984     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)985     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()986     virtual AstNodeDType* subDTypep() const override {
987         return m_refDTypep ? m_refDTypep : childDTypep();
988     }
refDTypep(AstNodeDType * nodep)989     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()990     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)991     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
992     // METHODS
basicp()993     virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
skipRefp()994     virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); }
skipRefToConstp()995     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()996     virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
widthAlignBytes()997     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
widthTotalBytes()998     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
isCompound()999     virtual bool isCompound() const override {
1000         v3fatalSrc("call isCompound on subdata type, not reference");
1001         return false;
1002     }
1003 };
1004 
1005 class AstClassRefDType final : public AstNodeDType {
1006     // Reference to a class
1007     // Children: PINs (for parameter settings)
1008 private:
1009     AstClass* m_classp;  // data type pointed to, BELOW the AstTypedef
1010     AstNodeModule* m_classOrPackagep = nullptr;  // Package hierarchy
1011 public:
AstClassRefDType(FileLine * fl,AstClass * classp,AstNode * paramsp)1012     AstClassRefDType(FileLine* fl, AstClass* classp, AstNode* paramsp)
1013         : ASTGEN_SUPER_ClassRefDType(fl)
1014         , m_classp{classp} {
1015         dtypep(this);
1016         addNOp4p(paramsp);
1017     }
ASTNODE_NODE_FUNCS(ClassRefDType)1018     ASTNODE_NODE_FUNCS(ClassRefDType)
1019     // METHODS
1020     virtual const char* broken() const override {
1021         BROKEN_RTN(m_classp && !m_classp->brokeExists());
1022         return nullptr;
1023     }
cloneRelink()1024     virtual void cloneRelink() override {
1025         if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep();
1026     }
same(const AstNode * samep)1027     virtual bool same(const AstNode* samep) const override {
1028         const AstClassRefDType* const asamep = static_cast<const AstClassRefDType*>(samep);
1029         return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep);
1030     }
similarDType(AstNodeDType * samep)1031     virtual bool similarDType(AstNodeDType* samep) const override {
1032         return this == samep || (type() == samep->type() && same(samep));
1033     }
1034     virtual void dump(std::ostream& str = std::cout) const override;
1035     virtual void dumpSmall(std::ostream& str) const override;
name()1036     virtual string name() const override { return classp() ? classp()->name() : "<unlinked>"; }
basicp()1037     virtual AstBasicDType* basicp() const override { return nullptr; }
skipRefp()1038     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()1039     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()1040     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()1041     virtual int widthAlignBytes() const override { return 0; }
widthTotalBytes()1042     virtual int widthTotalBytes() const override { return 0; }
virtRefDTypep()1043     virtual AstNodeDType* virtRefDTypep() const override { return nullptr; }
virtRefDTypep(AstNodeDType * nodep)1044     virtual void virtRefDTypep(AstNodeDType* nodep) override {}
subDTypep()1045     virtual AstNodeDType* subDTypep() const override { return nullptr; }
classOrPackagep()1046     AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
classOrPackagep(AstNodeModule * nodep)1047     void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
classp()1048     AstClass* classp() const { return m_classp; }
classp(AstClass * nodep)1049     void classp(AstClass* nodep) { m_classp = nodep; }
paramsp()1050     AstPin* paramsp() const { return VN_AS(op4p(), Pin); }
isCompound()1051     virtual bool isCompound() const override { return true; }
1052 };
1053 
1054 class AstIfaceRefDType final : public AstNodeDType {
1055     // Reference to an interface, either for a port, or inside parent cell
1056 private:
1057     FileLine* m_modportFileline;  // Where modport token was
1058     string m_cellName;  // "" = no cell, such as when connects to 'input' iface
1059     string m_ifaceName;  // Interface name
1060     string m_modportName;  // "" = no modport
1061     AstIface* m_ifacep = nullptr;  // Pointer to interface; note cellp() should override
1062     AstCell* m_cellp = nullptr;  // When exact parent cell known; not a guess
1063     AstModport* m_modportp = nullptr;  // nullptr = unlinked or no modport
1064 public:
AstIfaceRefDType(FileLine * fl,const string & cellName,const string & ifaceName)1065     AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName)
1066         : ASTGEN_SUPER_IfaceRefDType(fl)
1067         , m_modportFileline{nullptr}
1068         , m_cellName{cellName}
1069         , m_ifaceName{ifaceName}
1070         , m_modportName{""} {}
AstIfaceRefDType(FileLine * fl,FileLine * modportFl,const string & cellName,const string & ifaceName,const string & modport)1071     AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName,
1072                      const string& ifaceName, const string& modport)
1073         : ASTGEN_SUPER_IfaceRefDType(fl)
1074         , m_modportFileline{modportFl}
1075         , m_cellName{cellName}
1076         , m_ifaceName{ifaceName}
1077         , m_modportName{modport} {}
1078     ASTNODE_NODE_FUNCS(IfaceRefDType)
1079     // METHODS
1080     virtual const char* broken() const override;
1081     virtual void dump(std::ostream& str = std::cout) const override;
1082     virtual void dumpSmall(std::ostream& str) const override;
1083     virtual void cloneRelink() override;
basicp()1084     virtual AstBasicDType* basicp() const override { return nullptr; }
skipRefp()1085     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
skipRefToConstp()1086     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
skipRefToEnump()1087     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
similarDType(AstNodeDType * samep)1088     virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
widthAlignBytes()1089     virtual int widthAlignBytes() const override { return 1; }
widthTotalBytes()1090     virtual int widthTotalBytes() const override { return 1; }
modportFileline()1091     FileLine* modportFileline() const { return m_modportFileline; }
cellName()1092     string cellName() const { return m_cellName; }
cellName(const string & name)1093     void cellName(const string& name) { m_cellName = name; }
ifaceName()1094     string ifaceName() const { return m_ifaceName; }
ifaceName(const string & name)1095     void ifaceName(const string& name) { m_ifaceName = name; }
modportName()1096     string modportName() const { return m_modportName; }
1097     AstIface* ifaceViaCellp() const;  // Use cellp or ifacep
ifacep()1098     AstIface* ifacep() const { return m_ifacep; }
ifacep(AstIface * nodep)1099     void ifacep(AstIface* nodep) { m_ifacep = nodep; }
cellp()1100     AstCell* cellp() const { return m_cellp; }
cellp(AstCell * nodep)1101     void cellp(AstCell* nodep) { m_cellp = nodep; }
modportp()1102     AstModport* modportp() const { return m_modportp; }
modportp(AstModport * modportp)1103     void modportp(AstModport* modportp) { m_modportp = modportp; }
isModport()1104     bool isModport() { return !m_modportName.empty(); }
isCompound()1105     virtual bool isCompound() const override { return true; }  // But not relevant
1106 };
1107 
1108 class AstQueueDType final : public AstNodeDType {
1109     // Queue array data type, ie "[ $ ]"
1110     // Children: DTYPE (moved to refDTypep() in V3Width)
1111 private:
1112     AstNodeDType* m_refDTypep;  // Elements of this type (after widthing)
1113 public:
AstQueueDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp,AstNode * boundp)1114     AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* boundp)
1115         : ASTGEN_SUPER_QueueDType(fl) {
1116         setNOp2p(boundp);
1117         childDTypep(dtp);  // Only for parser
1118         refDTypep(nullptr);
1119         dtypep(nullptr);  // V3Width will resolve
1120     }
AstQueueDType(FileLine * fl,AstNodeDType * dtp,AstNode * boundp)1121     AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNode* boundp)
1122         : ASTGEN_SUPER_QueueDType(fl) {
1123         setNOp2p(boundp);
1124         refDTypep(dtp);
1125         dtypep(dtp);
1126     }
ASTNODE_NODE_FUNCS(QueueDType)1127     ASTNODE_NODE_FUNCS(QueueDType)
1128     virtual const char* broken() const override {
1129         BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
1130                      || (!m_refDTypep && childDTypep())));
1131         return nullptr;
1132     }
cloneRelink()1133     virtual void cloneRelink() override {
1134         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
1135     }
same(const AstNode * samep)1136     virtual bool same(const AstNode* samep) const override {
1137         const AstQueueDType* const asamep = static_cast<const AstQueueDType*>(samep);
1138         if (!asamep->subDTypep()) return false;
1139         return (subDTypep() == asamep->subDTypep());
1140     }
similarDType(AstNodeDType * samep)1141     virtual bool similarDType(AstNodeDType* samep) const override {
1142         const AstQueueDType* const asamep = static_cast<const AstQueueDType*>(samep);
1143         return type() == samep->type() && asamep->subDTypep()
1144                && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
1145     }
1146     virtual void dumpSmall(std::ostream& str) const override;
1147     virtual string prettyDTypeName() const override;
getChildDTypep()1148     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
1149     // op1 = Range of variable
childDTypep()1150     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)1151     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()1152     virtual AstNodeDType* subDTypep() const override {
1153         return m_refDTypep ? m_refDTypep : childDTypep();
1154     }
refDTypep(AstNodeDType * nodep)1155     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
boundp()1156     AstNode* boundp() const { return op2p(); }  // op2 = Bound, nullptr = none
boundp(AstNode * nodep)1157     void boundp(AstNode* nodep) { setNOp2p(nodep); }
boundConst()1158     int boundConst() const {
1159         AstConst* const constp = VN_CAST(boundp(), Const);
1160         return (constp ? constp->toSInt() : 0);
1161     }
virtRefDTypep()1162     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)1163     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
1164     // METHODS
basicp()1165     virtual AstBasicDType* basicp() const override { return nullptr; }
1166     // cppcheck-suppress csyleCast
skipRefp()1167     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
1168     // cppcheck-suppress csyleCast
skipRefToConstp()1169     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
1170     // cppcheck-suppress csyleCast
skipRefToEnump()1171     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()1172     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
widthTotalBytes()1173     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
isCompound()1174     virtual bool isCompound() const override { return true; }
1175 };
1176 
1177 class AstRefDType final : public AstNodeDType {
1178 private:
1179     // Pre-Width must reference the Typeref, not what it points to, as some child
1180     // types like AstBracketArrayType will disappear and can't lose the handle
1181     AstTypedef* m_typedefp = nullptr;  // referenced type
1182     // Post-width typedefs are removed and point to type directly
1183     AstNodeDType* m_refDTypep = nullptr;  // data type pointed to, BELOW the AstTypedef
1184     string m_name;  // Name of an AstTypedef
1185     AstNodeModule* m_classOrPackagep = nullptr;  // Package hierarchy
1186 public:
AstRefDType(FileLine * fl,const string & name)1187     AstRefDType(FileLine* fl, const string& name)
1188         : ASTGEN_SUPER_RefDType(fl)
1189         , m_name{name} {}
AstRefDType(FileLine * fl,const string & name,AstNode * classOrPackagep,AstNode * paramsp)1190     AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp)
1191         : ASTGEN_SUPER_RefDType(fl)
1192         , m_name{name} {
1193         setNOp3p(classOrPackagep);
1194         addNOp4p(paramsp);
1195     }
1196     class FlagTypeOfExpr {};  // type(expr) for parser only
AstRefDType(FileLine * fl,FlagTypeOfExpr,AstNode * typeofp)1197     AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp)
1198         : ASTGEN_SUPER_RefDType(fl) {
1199         setOp2p(typeofp);
1200     }
ASTNODE_NODE_FUNCS(RefDType)1201     ASTNODE_NODE_FUNCS(RefDType)
1202     // METHODS
1203     virtual const char* broken() const override {
1204         BROKEN_RTN(m_typedefp && !m_typedefp->brokeExists());
1205         BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists());
1206         return nullptr;
1207     }
cloneRelink()1208     virtual void cloneRelink() override {
1209         if (m_typedefp && m_typedefp->clonep()) m_typedefp = m_typedefp->clonep();
1210         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
1211     }
same(const AstNode * samep)1212     virtual bool same(const AstNode* samep) const override {
1213         const AstRefDType* const asamep = static_cast<const AstRefDType*>(samep);
1214         return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep
1215                 && m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep);
1216     }
similarDType(AstNodeDType * samep)1217     virtual bool similarDType(AstNodeDType* samep) const override {
1218         return skipRefp()->similarDType(samep->skipRefp());
1219     }
1220     virtual void dump(std::ostream& str = std::cout) const override;
name()1221     virtual string name() const override { return m_name; }
prettyDTypeName()1222     virtual string prettyDTypeName() const override {
1223         return subDTypep() ? subDTypep()->name() : prettyName();
1224     }
basicp()1225     virtual AstBasicDType* basicp() const override {
1226         return subDTypep() ? subDTypep()->basicp() : nullptr;
1227     }
subDTypep()1228     virtual AstNodeDType* subDTypep() const override {
1229         if (typedefp()) return typedefp()->subDTypep();
1230         return refDTypep();  // Maybe nullptr
1231     }
skipRefp()1232     virtual AstNodeDType* skipRefp() const override {
1233         // Skip past both the Ref and the Typedef
1234         if (subDTypep()) {
1235             return subDTypep()->skipRefp();
1236         } else {
1237             v3fatalSrc("Typedef not linked");
1238             return nullptr;
1239         }
1240     }
skipRefToConstp()1241     virtual AstNodeDType* skipRefToConstp() const override {
1242         if (subDTypep()) {
1243             return subDTypep()->skipRefToConstp();
1244         } else {
1245             v3fatalSrc("Typedef not linked");
1246             return nullptr;
1247         }
1248     }
skipRefToEnump()1249     virtual AstNodeDType* skipRefToEnump() const override {
1250         if (subDTypep()) {
1251             return subDTypep()->skipRefToEnump();
1252         } else {
1253             v3fatalSrc("Typedef not linked");
1254             return nullptr;
1255         }
1256     }
widthAlignBytes()1257     virtual int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); }
widthTotalBytes()1258     virtual int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); }
name(const string & flag)1259     virtual void name(const string& flag) override { m_name = flag; }
1260     // op1 = Range of variable
dtypeSkipRefp()1261     AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
typedefp()1262     AstTypedef* typedefp() const { return m_typedefp; }
typedefp(AstTypedef * nodep)1263     void typedefp(AstTypedef* nodep) { m_typedefp = nodep; }
refDTypep()1264     AstNodeDType* refDTypep() const { return m_refDTypep; }
refDTypep(AstNodeDType * nodep)1265     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()1266     virtual AstNodeDType* virtRefDTypep() const override { return refDTypep(); }
virtRefDTypep(AstNodeDType * nodep)1267     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
classOrPackagep()1268     AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
classOrPackagep(AstNodeModule * nodep)1269     void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
typeofp()1270     AstNode* typeofp() const { return op2p(); }
classOrPackageOpp()1271     AstNode* classOrPackageOpp() const { return op3p(); }
paramsp()1272     AstPin* paramsp() const { return VN_AS(op4p(), Pin); }
isCompound()1273     virtual bool isCompound() const override {
1274         v3fatalSrc("call isCompound on subdata type, not reference");
1275         return false;
1276     }
1277 };
1278 
1279 class AstStructDType final : public AstNodeUOrStructDType {
1280 public:
1281     // VSigning below is mispurposed to indicate if packed or not
AstStructDType(FileLine * fl,VSigning numericUnpack)1282     AstStructDType(FileLine* fl, VSigning numericUnpack)
1283         : ASTGEN_SUPER_StructDType(fl, numericUnpack) {}
ASTNODE_NODE_FUNCS(StructDType)1284     ASTNODE_NODE_FUNCS(StructDType)
1285     virtual string verilogKwd() const override { return "struct"; }
1286 };
1287 
1288 class AstUnionDType final : public AstNodeUOrStructDType {
1289 public:
1290     // UNSUP: bool isTagged;
1291     // VSigning below is mispurposed to indicate if packed or not
AstUnionDType(FileLine * fl,VSigning numericUnpack)1292     AstUnionDType(FileLine* fl, VSigning numericUnpack)
1293         : ASTGEN_SUPER_UnionDType(fl, numericUnpack) {}
ASTNODE_NODE_FUNCS(UnionDType)1294     ASTNODE_NODE_FUNCS(UnionDType)
1295     virtual string verilogKwd() const override { return "union"; }
1296 };
1297 
1298 class AstMemberDType final : public AstNodeDType {
1299     // A member of a struct/union
1300     // PARENT: AstNodeUOrStructDType
1301 private:
1302     AstNodeDType* m_refDTypep;  // Elements of this type (after widthing)
1303     string m_name;  // Name of variable
1304     string m_tag;  // Holds the string of the verilator tag -- used in XML output.
1305     int m_lsb = -1;  // Within this level's packed struct, the LSB of the first bit of the member
1306     // UNSUP: int m_randType;    // Randomization type (IEEE)
1307 public:
AstMemberDType(FileLine * fl,const string & name,VFlagChildDType,AstNodeDType * dtp)1308     AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp)
1309         : ASTGEN_SUPER_MemberDType(fl)
1310         , m_name{name} {
1311         childDTypep(dtp);  // Only for parser
1312         dtypep(nullptr);  // V3Width will resolve
1313         refDTypep(nullptr);
1314     }
AstMemberDType(FileLine * fl,const string & name,AstNodeDType * dtp)1315     AstMemberDType(FileLine* fl, const string& name, AstNodeDType* dtp)
1316         : ASTGEN_SUPER_MemberDType(fl)
1317         , m_name{name} {
1318         UASSERT(dtp, "AstMember created with no dtype");
1319         refDTypep(dtp);
1320         dtypep(this);
1321         widthFromSub(subDTypep());
1322     }
ASTNODE_NODE_FUNCS(MemberDType)1323     ASTNODE_NODE_FUNCS(MemberDType)
1324     virtual string name() const override { return m_name; }  // * = Var name
hasDType()1325     virtual bool hasDType() const override { return true; }
maybePointedTo()1326     virtual bool maybePointedTo() const override { return true; }
getChildDTypep()1327     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
1328     // op1 = Range of variable
childDTypep()1329     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)1330     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()1331     virtual AstNodeDType* subDTypep() const override {
1332         return m_refDTypep ? m_refDTypep : childDTypep();
1333     }
refDTypep(AstNodeDType * nodep)1334     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()1335     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)1336     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
similarDType(AstNodeDType * samep)1337     virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
1338     //
1339     // (Slow) recurse down to find basic data type (Note don't need virtual -
1340     // AstVar isn't a NodeDType)
basicp()1341     virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
1342     // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
dtypeSkipRefp()1343     AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
skipRefp()1344     virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); }
skipRefToConstp()1345     virtual AstNodeDType* skipRefToConstp() const override {
1346         return subDTypep()->skipRefToConstp();
1347     }
skipRefToEnump()1348     virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
1349     // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
widthAlignBytes()1350     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
1351     // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
widthTotalBytes()1352     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
1353     // METHODS
name(const string & name)1354     virtual void name(const string& name) override { m_name = name; }
tag(const string & text)1355     virtual void tag(const string& text) override { m_tag = text; }
tag()1356     virtual string tag() const override { return m_tag; }
lsb()1357     int lsb() const { return m_lsb; }
lsb(int lsb)1358     void lsb(int lsb) { m_lsb = lsb; }
isCompound()1359     virtual bool isCompound() const override {
1360         v3fatalSrc("call isCompound on subdata type, not reference");
1361         return false;
1362     }
1363 };
1364 
1365 class AstEmptyQueueDType final : public AstNodeDType {
1366     // For EmptyQueue
1367 public:
AstEmptyQueueDType(FileLine * fl)1368     explicit AstEmptyQueueDType(FileLine* fl)
1369         : ASTGEN_SUPER_EmptyQueueDType(fl) {
1370         dtypep(this);
1371     }
1372     ASTNODE_NODE_FUNCS(EmptyQueueDType)
1373     virtual void dumpSmall(std::ostream& str) const override;
hasDType()1374     virtual bool hasDType() const override { return true; }
maybePointedTo()1375     virtual bool maybePointedTo() const override { return true; }
subDTypep()1376     virtual AstNodeDType* subDTypep() const override { return nullptr; }
virtRefDTypep()1377     virtual AstNodeDType* virtRefDTypep() const override { return nullptr; }
virtRefDTypep(AstNodeDType * nodep)1378     virtual void virtRefDTypep(AstNodeDType* nodep) override {}
similarDType(AstNodeDType * samep)1379     virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
basicp()1380     virtual AstBasicDType* basicp() const override { return nullptr; }
1381     // cppcheck-suppress csyleCast
skipRefp()1382     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
1383     // cppcheck-suppress csyleCast
skipRefToConstp()1384     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
1385     // cppcheck-suppress csyleCast
skipRefToEnump()1386     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()1387     virtual int widthAlignBytes() const override { return 1; }
widthTotalBytes()1388     virtual int widthTotalBytes() const override { return 1; }
isCompound()1389     virtual bool isCompound() const override { return false; }
1390 };
1391 
1392 class AstVoidDType final : public AstNodeDType {
1393     // For e.g. a function returning void
1394 public:
AstVoidDType(FileLine * fl)1395     explicit AstVoidDType(FileLine* fl)
1396         : ASTGEN_SUPER_VoidDType(fl) {
1397         dtypep(this);
1398     }
1399     ASTNODE_NODE_FUNCS(VoidDType)
1400     virtual void dumpSmall(std::ostream& str) const override;
hasDType()1401     virtual bool hasDType() const override { return true; }
maybePointedTo()1402     virtual bool maybePointedTo() const override { return true; }
subDTypep()1403     virtual AstNodeDType* subDTypep() const override { return nullptr; }
virtRefDTypep()1404     virtual AstNodeDType* virtRefDTypep() const override { return nullptr; }
virtRefDTypep(AstNodeDType * nodep)1405     virtual void virtRefDTypep(AstNodeDType* nodep) override {}
similarDType(AstNodeDType * samep)1406     virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
basicp()1407     virtual AstBasicDType* basicp() const override { return nullptr; }
1408     // cppcheck-suppress csyleCast
skipRefp()1409     virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
1410     // cppcheck-suppress csyleCast
skipRefToConstp()1411     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
1412     // cppcheck-suppress csyleCast
skipRefToEnump()1413     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()1414     virtual int widthAlignBytes() const override { return 1; }
widthTotalBytes()1415     virtual int widthTotalBytes() const override { return 1; }
isCompound()1416     virtual bool isCompound() const override { return false; }
1417 };
1418 
1419 class AstEnumItem final : public AstNode {
1420 private:
1421     string m_name;
1422 
1423 public:
1424     // Parents: ENUM
AstEnumItem(FileLine * fl,const string & name,AstNode * rangep,AstNode * initp)1425     AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp)
1426         : ASTGEN_SUPER_EnumItem(fl)
1427         , m_name{name} {
1428         addNOp1p(rangep);
1429         addNOp2p(initp);
1430     }
ASTNODE_NODE_FUNCS(EnumItem)1431     ASTNODE_NODE_FUNCS(EnumItem)
1432     virtual string name() const override { return m_name; }
maybePointedTo()1433     virtual bool maybePointedTo() const override { return true; }
hasDType()1434     virtual bool hasDType() const override { return true; }
name(const string & flag)1435     virtual void name(const string& flag) override { m_name = flag; }
rangep()1436     AstRange* rangep() const { return VN_AS(op1p(), Range); }  // op1 = Range for name appending
rangep(AstRange * nodep)1437     void rangep(AstRange* nodep) { addOp1p(nodep); }
valuep()1438     AstNode* valuep() const { return op2p(); }  // op2 = Value
valuep(AstNode * nodep)1439     void valuep(AstNode* nodep) { addOp2p(nodep); }
1440 };
1441 
1442 class AstEnumItemRef final : public AstNodeMath {
1443 private:
1444     AstEnumItem* m_itemp;  // [AfterLink] Pointer to item
1445     AstNodeModule* m_classOrPackagep;  // Package hierarchy
1446 public:
AstEnumItemRef(FileLine * fl,AstEnumItem * itemp,AstNodeModule * classOrPackagep)1447     AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* classOrPackagep)
1448         : ASTGEN_SUPER_EnumItemRef(fl)
1449         , m_itemp{itemp}
1450         , m_classOrPackagep{classOrPackagep} {
1451         dtypeFrom(m_itemp);
1452     }
1453     ASTNODE_NODE_FUNCS(EnumItemRef)
1454     virtual void dump(std::ostream& str) const override;
name()1455     virtual string name() const override { return itemp()->name(); }
instrCount()1456     virtual int instrCount() const override { return 0; }
cloneRelink()1457     virtual void cloneRelink() override {
1458         if (m_itemp->clonep()) m_itemp = m_itemp->clonep();
1459     }
same(const AstNode * samep)1460     virtual bool same(const AstNode* samep) const override {
1461         const AstEnumItemRef* const sp = static_cast<const AstEnumItemRef*>(samep);
1462         return itemp() == sp->itemp();
1463     }
itemp()1464     AstEnumItem* itemp() const { return m_itemp; }
emitVerilog()1465     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()1466     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()1467     virtual bool cleanOut() const override { return true; }
classOrPackagep()1468     AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
classOrPackagep(AstNodeModule * nodep)1469     void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
1470 };
1471 
1472 class AstEnumDType final : public AstNodeDType {
1473     // Parents: TYPEDEF/MODULE
1474     // Children: ENUMVALUEs
1475 private:
1476     string m_name;  // Name from upper typedef, if any
1477     AstNodeDType* m_refDTypep;  // Elements are of this type after V3Width
1478     const int m_uniqueNum;
1479 
1480 public:
AstEnumDType(FileLine * fl,VFlagChildDType,AstNodeDType * dtp,AstNode * itemsp)1481     AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp)
1482         : ASTGEN_SUPER_EnumDType(fl)
1483         , m_uniqueNum{uniqueNumInc()} {
1484         childDTypep(dtp);  // Only for parser
1485         refDTypep(nullptr);
1486         addNOp2p(itemsp);
1487         dtypep(nullptr);  // V3Width will resolve
1488         widthFromSub(subDTypep());
1489     }
ASTNODE_NODE_FUNCS(EnumDType)1490     ASTNODE_NODE_FUNCS(EnumDType)
1491     virtual const char* broken() const override {
1492         BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
1493                      || (!m_refDTypep && childDTypep())));
1494         return nullptr;
1495     }
cloneRelink()1496     virtual void cloneRelink() override {
1497         if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
1498     }
uniqueNum()1499     int uniqueNum() const { return m_uniqueNum; }
same(const AstNode * samep)1500     virtual bool same(const AstNode* samep) const override {
1501         const AstEnumDType* const sp = static_cast<const AstEnumDType*>(samep);
1502         return uniqueNum() == sp->uniqueNum();
1503     }
similarDType(AstNodeDType * samep)1504     virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
getChildDTypep()1505     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
childDTypep()1506     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }  // op1 = Data type
childDTypep(AstNodeDType * nodep)1507     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
1508     // op1 = Range of variable
subDTypep()1509     virtual AstNodeDType* subDTypep() const override {
1510         return m_refDTypep ? m_refDTypep : childDTypep();
1511     }
refDTypep(AstNodeDType * nodep)1512     void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
virtRefDTypep()1513     virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
virtRefDTypep(AstNodeDType * nodep)1514     virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
name()1515     virtual string name() const override { return m_name; }
name(const string & flag)1516     virtual void name(const string& flag) override { m_name = flag; }
itemsp()1517     AstEnumItem* itemsp() const { return VN_AS(op2p(), EnumItem); }  // op2 = AstEnumItem's
1518     // METHODS
basicp()1519     virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
skipRefp()1520     virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); }
skipRefToConstp()1521     virtual AstNodeDType* skipRefToConstp() const override {
1522         return subDTypep()->skipRefToConstp();
1523     }
1524     // cppcheck-suppress csyleCast
skipRefToEnump()1525     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()1526     virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
widthTotalBytes()1527     virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
itemCount()1528     int itemCount() const {
1529         size_t count = 0;
1530         for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++;
1531         return count;
1532     }
isCompound()1533     virtual bool isCompound() const override { return false; }
1534 };
1535 
1536 class AstParseTypeDType final : public AstNodeDType {
1537     // Parents: VAR
1538     // During parsing, this indicates the type of a parameter is a "parameter type"
1539     // e.g. the data type is a container of any data type
1540 public:
AstParseTypeDType(FileLine * fl)1541     explicit AstParseTypeDType(FileLine* fl)
1542         : ASTGEN_SUPER_ParseTypeDType(fl) {}
ASTNODE_NODE_FUNCS(ParseTypeDType)1543     ASTNODE_NODE_FUNCS(ParseTypeDType)
1544     AstNodeDType* dtypep() const { return nullptr; }
1545     // METHODS
similarDType(AstNodeDType * samep)1546     virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; }
basicp()1547     virtual AstBasicDType* basicp() const override { return nullptr; }
skipRefp()1548     virtual AstNodeDType* skipRefp() const override { return nullptr; }
1549     // cppcheck-suppress csyleCast
skipRefToConstp()1550     virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
1551     // cppcheck-suppress csyleCast
skipRefToEnump()1552     virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
widthAlignBytes()1553     virtual int widthAlignBytes() const override { return 0; }
widthTotalBytes()1554     virtual int widthTotalBytes() const override { return 0; }
isCompound()1555     virtual bool isCompound() const override {
1556         v3fatalSrc("call isCompound on subdata type, not reference");
1557         return false;
1558     }
1559 };
1560 
1561 //######################################################################
1562 
1563 class AstArraySel final : public AstNodeSel {
1564     // Parents: math|stmt
1565     // Children: varref|arraysel, math
1566 private:
init(AstNode * fromp)1567     void init(AstNode* fromp) {
1568         if (fromp && VN_IS(fromp->dtypep()->skipRefp(), NodeArrayDType)) {
1569             // Strip off array to find what array references
1570             dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), NodeArrayDType)->subDTypep());
1571         }
1572     }
1573 
1574 public:
AstArraySel(FileLine * fl,AstNode * fromp,AstNode * bitp)1575     AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp)
1576         : ASTGEN_SUPER_ArraySel(fl, fromp, bitp) {
1577         init(fromp);
1578     }
AstArraySel(FileLine * fl,AstNode * fromp,int bit)1579     AstArraySel(FileLine* fl, AstNode* fromp, int bit)
1580         : ASTGEN_SUPER_ArraySel(fl, fromp, new AstConst(fl, bit)) {
1581         init(fromp);
1582     }
ASTNODE_NODE_FUNCS(ArraySel)1583     ASTNODE_NODE_FUNCS(ArraySel)
1584     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
1585         return new AstArraySel(this->fileline(), lhsp, rhsp);
1586     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)1587     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
1588         V3ERROR_NA; /* How can from be a const? */
1589     }
emitVerilog()1590     virtual string emitVerilog() override { return "%k(%l%f[%r])"; }
emitC()1591     virtual string emitC() override { return "%li%k[%ri]"; }
cleanOut()1592     virtual bool cleanOut() const override { return true; }
cleanLhs()1593     virtual bool cleanLhs() const override { return false; }
cleanRhs()1594     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()1595     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()1596     virtual bool sizeMattersRhs() const override { return false; }
isGateOptimizable()1597     virtual bool isGateOptimizable() const override {
1598         return true;
1599     }  // esp for V3Const::ifSameAssign
isPredictOptimizable()1600     virtual bool isPredictOptimizable() const override { return true; }
same(const AstNode * samep)1601     virtual bool same(const AstNode* samep) const override { return true; }
instrCount()1602     virtual int instrCount() const override { return widthInstrs(); }
1603     // Special operators
1604     // Return base var (or const) nodep dereferences
1605     static AstNode* baseFromp(AstNode* nodep, bool overMembers);
1606 };
1607 
1608 class AstAssocSel final : public AstNodeSel {
1609     // Parents: math|stmt
1610     // Children: varref|arraysel, math
1611 private:
init(AstNode * fromp)1612     void init(AstNode* fromp) {
1613         if (fromp && VN_IS(fromp->dtypep()->skipRefp(), AssocArrayDType)) {
1614             // Strip off array to find what array references
1615             dtypeFrom(VN_AS(fromp->dtypep()->skipRefp(), AssocArrayDType)->subDTypep());
1616         }
1617     }
1618 
1619 public:
AstAssocSel(FileLine * fl,AstNode * fromp,AstNode * bitp)1620     AstAssocSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
1621         : ASTGEN_SUPER_AssocSel(fl, fromp, bitp) {
1622         init(fromp);
1623     }
ASTNODE_NODE_FUNCS(AssocSel)1624     ASTNODE_NODE_FUNCS(AssocSel)
1625     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
1626         return new AstAssocSel(this->fileline(), lhsp, rhsp);
1627     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)1628     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
1629         V3ERROR_NA;
1630     }
emitVerilog()1631     virtual string emitVerilog() override { return "%k(%l%f[%r])"; }
emitC()1632     virtual string emitC() override { return "%li%k[%ri]"; }
cleanOut()1633     virtual bool cleanOut() const override { return true; }
cleanLhs()1634     virtual bool cleanLhs() const override { return false; }
cleanRhs()1635     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()1636     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()1637     virtual bool sizeMattersRhs() const override { return false; }
isGateOptimizable()1638     virtual bool isGateOptimizable() const override {
1639         return true;
1640     }  // esp for V3Const::ifSameAssign
isPredictOptimizable()1641     virtual bool isPredictOptimizable() const override { return false; }
same(const AstNode * samep)1642     virtual bool same(const AstNode* samep) const override { return true; }
instrCount()1643     virtual int instrCount() const override { return widthInstrs(); }
1644 };
1645 
1646 class AstWordSel final : public AstNodeSel {
1647     // Select a single word from a multi-word wide value
1648 public:
AstWordSel(FileLine * fl,AstNode * fromp,AstNode * bitp)1649     AstWordSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
1650         : ASTGEN_SUPER_WordSel(fl, fromp, bitp) {
1651         dtypeSetUInt32();  // Always used on WData arrays so returns edata size
1652     }
ASTNODE_NODE_FUNCS(WordSel)1653     ASTNODE_NODE_FUNCS(WordSel)
1654     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
1655         return new AstWordSel(this->fileline(), lhsp, rhsp);
1656     }
numberOperate(V3Number & out,const V3Number & from,const V3Number & bit)1657     virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override {
1658         V3ERROR_NA;
1659     }
emitVerilog()1660     virtual string emitVerilog() override { return "%k(%l%f[%r])"; }
emitC()1661     virtual string emitC() override {
1662         return "%li[%ri]";
1663     }  // Not %k, as usually it's a small constant rhsp
cleanOut()1664     virtual bool cleanOut() const override { return true; }
cleanLhs()1665     virtual bool cleanLhs() const override { return true; }
cleanRhs()1666     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()1667     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()1668     virtual bool sizeMattersRhs() const override { return false; }
same(const AstNode * samep)1669     virtual bool same(const AstNode* samep) const override { return true; }
1670 };
1671 
1672 class AstSelLoopVars final : public AstNode {
1673     // Parser only concept "[id, id, id]" for a foreach statement
1674     // Unlike normal selects elements is a list
1675 public:
AstSelLoopVars(FileLine * fl,AstNode * fromp,AstNode * elementsp)1676     AstSelLoopVars(FileLine* fl, AstNode* fromp, AstNode* elementsp)
1677         : ASTGEN_SUPER_SelLoopVars(fl) {
1678         setOp1p(fromp);
1679         addNOp2p(elementsp);
1680     }
ASTNODE_NODE_FUNCS(SelLoopVars)1681     ASTNODE_NODE_FUNCS(SelLoopVars)
1682     virtual bool same(const AstNode* samep) const override { return true; }
maybePointedTo()1683     virtual bool maybePointedTo() const override { return false; }
fromp()1684     AstNode* fromp() const { return op1p(); }
elementsp()1685     AstNode* elementsp() const { return op2p(); }
1686 };
1687 
1688 class AstSelExtract final : public AstNodePreSel {
1689     // Range extraction, gets replaced with AstSel
1690 public:
AstSelExtract(FileLine * fl,AstNode * fromp,AstNode * msbp,AstNode * lsbp)1691     AstSelExtract(FileLine* fl, AstNode* fromp, AstNode* msbp, AstNode* lsbp)
1692         : ASTGEN_SUPER_SelExtract(fl, fromp, msbp, lsbp) {}
ASTNODE_NODE_FUNCS(SelExtract)1693     ASTNODE_NODE_FUNCS(SelExtract)
1694     AstNode* leftp() const { return rhsp(); }
rightp()1695     AstNode* rightp() const { return thsp(); }
1696 };
1697 
1698 class AstSelBit final : public AstNodePreSel {
1699     // Single bit range extraction, perhaps with non-constant selection or array selection
1700     // Gets replaced during link with AstArraySel or AstSel
1701 public:
AstSelBit(FileLine * fl,AstNode * fromp,AstNode * bitp)1702     AstSelBit(FileLine* fl, AstNode* fromp, AstNode* bitp)
1703         : ASTGEN_SUPER_SelBit(fl, fromp, bitp, nullptr) {
1704         UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
1705                     "not coded to create after dtypes resolved");
1706     }
ASTNODE_NODE_FUNCS(SelBit)1707     ASTNODE_NODE_FUNCS(SelBit)
1708     AstNode* bitp() const { return rhsp(); }
1709 };
1710 
1711 class AstSelPlus final : public AstNodePreSel {
1712     // +: range extraction, perhaps with non-constant selection
1713     // Gets replaced during link with AstSel
1714 public:
AstSelPlus(FileLine * fl,AstNode * fromp,AstNode * bitp,AstNode * widthp)1715     AstSelPlus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp)
1716         : ASTGEN_SUPER_SelPlus(fl, fromp, bitp, widthp) {}
ASTNODE_NODE_FUNCS(SelPlus)1717     ASTNODE_NODE_FUNCS(SelPlus)
1718     AstNode* bitp() const { return rhsp(); }
widthp()1719     AstNode* widthp() const { return thsp(); }
1720 };
1721 
1722 class AstSelMinus final : public AstNodePreSel {
1723     // -: range extraction, perhaps with non-constant selection
1724     // Gets replaced during link with AstSel
1725 public:
AstSelMinus(FileLine * fl,AstNode * fromp,AstNode * bitp,AstNode * widthp)1726     AstSelMinus(FileLine* fl, AstNode* fromp, AstNode* bitp, AstNode* widthp)
1727         : ASTGEN_SUPER_SelMinus(fl, fromp, bitp, widthp) {}
ASTNODE_NODE_FUNCS(SelMinus)1728     ASTNODE_NODE_FUNCS(SelMinus)
1729     AstNode* bitp() const { return rhsp(); }
widthp()1730     AstNode* widthp() const { return thsp(); }
1731 };
1732 
1733 class AstSel final : public AstNodeTriop {
1734     // Multiple bit range extraction
1735     // Parents: math|stmt
1736     // Children: varref|arraysel, math, constant math
1737     // Tempting to have an access() style method here as LHS selects are quite
1738     // different, but that doesn't play well with V3Inst and bidirects which don't know direction
1739 private:
1740     VNumRange m_declRange;  // Range of the 'from' array if isRanged() is set, else invalid
1741     int m_declElWidth;  // If a packed array, the number of bits per element
1742 public:
AstSel(FileLine * fl,AstNode * fromp,AstNode * lsbp,AstNode * widthp)1743     AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp)
1744         : ASTGEN_SUPER_Sel(fl, fromp, lsbp, widthp)
1745         , m_declElWidth{1} {
1746         if (VN_IS(widthp, Const)) {
1747             dtypeSetLogicSized(VN_AS(widthp, Const)->toUInt(), VSigning::UNSIGNED);
1748         }
1749     }
AstSel(FileLine * fl,AstNode * fromp,int lsb,int bitwidth)1750     AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth)
1751         : ASTGEN_SUPER_Sel(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth))
1752         , m_declElWidth{1} {
1753         dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED);
1754     }
1755     ASTNODE_NODE_FUNCS(Sel)
1756     virtual void dump(std::ostream& str) const override;
numberOperate(V3Number & out,const V3Number & from,const V3Number & bit,const V3Number & width)1757     virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit,
1758                                const V3Number& width) override {
1759         out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt());
1760     }
emitVerilog()1761     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()1762     virtual string emitC() override {
1763         return widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%lw, %P, %li, %ri)"
1764                : isWide()        ? "VL_SEL_%nq%lq%rq%tq(%nw,%lw, %P, %li, %ri, %ti)"
1765                                  : "VL_SEL_%nq%lq%rq%tq(%lw, %P, %li, %ri, %ti)";
1766     }
cleanOut()1767     virtual bool cleanOut() const override { return false; }
cleanLhs()1768     virtual bool cleanLhs() const override { return true; }
cleanRhs()1769     virtual bool cleanRhs() const override { return true; }
cleanThs()1770     virtual bool cleanThs() const override { return true; }
sizeMattersLhs()1771     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()1772     virtual bool sizeMattersRhs() const override { return false; }
sizeMattersThs()1773     virtual bool sizeMattersThs() const override { return false; }
same(const AstNode *)1774     virtual bool same(const AstNode*) const override { return true; }
instrCount()1775     virtual int instrCount() const override {
1776         return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10);
1777     }
fromp()1778     AstNode* fromp() const {
1779         return op1p();
1780     }  // op1 = Extracting what (nullptr=TBD during parsing)
lsbp()1781     AstNode* lsbp() const { return op2p(); }  // op2 = Msb selection expression
widthp()1782     AstNode* widthp() const { return op3p(); }  // op3 = Width
widthConst()1783     int widthConst() const { return VN_AS(widthp(), Const)->toSInt(); }
lsbConst()1784     int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); }
msbConst()1785     int msbConst() const { return lsbConst() + widthConst() - 1; }
declRange()1786     VNumRange& declRange() { return m_declRange; }
declRange()1787     const VNumRange& declRange() const { return m_declRange; }
declRange(const VNumRange & flag)1788     void declRange(const VNumRange& flag) { m_declRange = flag; }
declElWidth()1789     int declElWidth() const { return m_declElWidth; }
declElWidth(int flag)1790     void declElWidth(int flag) { m_declElWidth = flag; }
1791 };
1792 
1793 class AstSliceSel final : public AstNodeTriop {
1794     // Multiple array element extraction
1795     // Parents: math|stmt
1796     // Children: varref|arraysel, math, constant math
1797 private:
1798     VNumRange m_declRange;  // Range of the 'from' array if isRanged() is set, else invalid
1799 public:
AstSliceSel(FileLine * fl,AstNode * fromp,const VNumRange & declRange)1800     AstSliceSel(FileLine* fl, AstNode* fromp, const VNumRange& declRange)
1801         : ASTGEN_SUPER_SliceSel(fl, fromp, new AstConst(fl, declRange.lo()),
1802                                 new AstConst(fl, declRange.elements()))
1803         , m_declRange{declRange} {}
1804     ASTNODE_NODE_FUNCS(SliceSel)
1805     virtual void dump(std::ostream& str) const override;
numberOperate(V3Number & out,const V3Number & from,const V3Number & lo,const V3Number & width)1806     virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo,
1807                                const V3Number& width) override {
1808         V3ERROR_NA;
1809     }
emitVerilog()1810     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()1811     virtual string emitC() override { V3ERROR_NA_RETURN(""); }  // Removed before EmitC
cleanOut()1812     virtual bool cleanOut() const override { return false; }
cleanLhs()1813     virtual bool cleanLhs() const override { return false; }
cleanRhs()1814     virtual bool cleanRhs() const override { return true; }
cleanThs()1815     virtual bool cleanThs() const override { return true; }
sizeMattersLhs()1816     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()1817     virtual bool sizeMattersRhs() const override { return false; }
sizeMattersThs()1818     virtual bool sizeMattersThs() const override { return false; }
same(const AstNode *)1819     virtual bool same(const AstNode*) const override { return true; }
instrCount()1820     virtual int instrCount() const override { return 10; }  // Removed before matters
fromp()1821     AstNode* fromp() const {
1822         return op1p();
1823     }  // op1 = Extracting what (nullptr=TBD during parsing)
1824     // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods
declRange()1825     VNumRange& declRange() { return m_declRange; }
declRange()1826     const VNumRange& declRange() const { return m_declRange; }
declRange(const VNumRange & flag)1827     void declRange(const VNumRange& flag) { m_declRange = flag; }
1828 };
1829 
1830 class AstMethodCall final : public AstNodeFTaskRef {
1831     // A reference to a member task (or function)
1832     // PARENTS: stmt/math
1833     // Not all calls are statments vs math.  AstNodeStmt needs isStatement() to deal.
1834     // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
1835 public:
AstMethodCall(FileLine * fl,AstNode * fromp,VFlagChildDType,const string & name,AstNode * pinsp)1836     AstMethodCall(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
1837                   AstNode* pinsp)
1838         : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) {
1839         setOp2p(fromp);
1840         dtypep(nullptr);  // V3Width will resolve
1841     }
AstMethodCall(FileLine * fl,AstNode * fromp,const string & name,AstNode * pinsp)1842     AstMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
1843         : ASTGEN_SUPER_MethodCall(fl, false, name, pinsp) {
1844         setOp2p(fromp);
1845     }
ASTNODE_NODE_FUNCS(MethodCall)1846     ASTNODE_NODE_FUNCS(MethodCall)
1847     virtual const char* broken() const override {
1848         BROKEN_BASE_RTN(AstNodeFTaskRef::broken());
1849         BROKEN_RTN(!fromp());
1850         return nullptr;
1851     }
1852     virtual void dump(std::ostream& str) const override;
hasDType()1853     virtual bool hasDType() const override { return true; }
makeStatement()1854     void makeStatement() {
1855         statement(true);
1856         dtypeSetVoid();
1857     }
fromp()1858     AstNode* fromp() const {
1859         return op2p();
1860     }  // op2 = Extracting what (nullptr=TBD during parsing)
fromp(AstNode * nodep)1861     void fromp(AstNode* nodep) { setOp2p(nodep); }
1862 };
1863 
1864 class AstCMethodHard final : public AstNodeStmt {
1865     // A reference to a "C" hardcoded member task (or function)
1866     // PARENTS: stmt/math
1867     // Not all calls are statments vs math.  AstNodeStmt needs isStatement() to deal.
1868 private:
1869     string m_name;  // Name of method
1870     bool m_pure = false;  // Pure optimizable
1871 public:
AstCMethodHard(FileLine * fl,AstNode * fromp,VFlagChildDType,const string & name,AstNode * pinsp)1872     AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name,
1873                    AstNode* pinsp)
1874         : ASTGEN_SUPER_CMethodHard(fl, false)
1875         , m_name{name} {
1876         setOp1p(fromp);
1877         dtypep(nullptr);  // V3Width will resolve
1878         addNOp2p(pinsp);
1879     }
AstCMethodHard(FileLine * fl,AstNode * fromp,const string & name,AstNode * pinsp)1880     AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp)
1881         : ASTGEN_SUPER_CMethodHard(fl, false)
1882         , m_name{name} {
1883         setOp1p(fromp);
1884         addNOp2p(pinsp);
1885     }
ASTNODE_NODE_FUNCS(CMethodHard)1886     ASTNODE_NODE_FUNCS(CMethodHard)
1887     virtual string name() const override { return m_name; }  // * = Var name
hasDType()1888     virtual bool hasDType() const override { return true; }
name(const string & name)1889     virtual void name(const string& name) override { m_name = name; }
same(const AstNode * samep)1890     virtual bool same(const AstNode* samep) const override {
1891         const AstCMethodHard* asamep = static_cast<const AstCMethodHard*>(samep);
1892         return (m_name == asamep->m_name);
1893     }
isPure()1894     virtual bool isPure() const override { return m_pure; }
pure(bool flag)1895     void pure(bool flag) { m_pure = flag; }
makeStatement()1896     void makeStatement() {
1897         statement(true);
1898         dtypeSetVoid();
1899     }
fromp()1900     AstNode* fromp() const {
1901         return op1p();
1902     }  // op1 = Extracting what (nullptr=TBD during parsing)
fromp(AstNode * nodep)1903     void fromp(AstNode* nodep) { setOp1p(nodep); }
pinsp()1904     AstNode* pinsp() const { return op2p(); }  // op2 = Pin interconnection list
addPinsp(AstNode * nodep)1905     void addPinsp(AstNode* nodep) { addOp2p(nodep); }
1906 };
1907 
1908 class AstVar final : public AstNode {
1909     // A variable (in/out/wire/reg/param) inside a module
1910 private:
1911     string m_name;  // Name of variable
1912     string m_origName;  // Original name before dot addition
1913     string m_tag;  // Holds the string of the verilator tag -- used in XML output.
1914     AstVarType m_varType;  // Type of variable
1915     VDirection m_direction;  // Direction input/output etc
1916     VDirection m_declDirection;  // Declared direction input/output etc
1917     AstBasicDTypeKwd m_declKwd;  // Keyword at declaration time
1918     VLifetime m_lifetime;  // Lifetime
1919     VVarAttrClocker m_attrClocker;
1920     MTaskIdSet m_mtaskIds;  // MTaskID's that read or write this var
1921     int m_pinNum = 0;  // For XML, if non-zero the connection pin number
1922     bool m_ansi : 1;  // ANSI port list variable (for dedup check)
1923     bool m_declTyped : 1;  // Declared as type (for dedup check)
1924     bool m_tristate : 1;  // Inout or triwire or trireg
1925     bool m_primaryIO : 1;  // In/out to top level (or directly assigned from same)
1926     bool m_sc : 1;  // SystemC variable
1927     bool m_scClocked : 1;  // SystemC sc_clk<> needed
1928     bool m_scSensitive : 1;  // SystemC sensitive() needed
1929     bool m_sigPublic : 1;  // User C code accesses this signal or is top signal
1930     bool m_sigModPublic : 1;  // User C code accesses this signal and module
1931     bool m_sigUserRdPublic : 1;  // User C code accesses this signal, read only
1932     bool m_sigUserRWPublic : 1;  // User C code accesses this signal, read-write
1933     bool m_usedClock : 1;  // Signal used as a clock
1934     bool m_usedParam : 1;  // Parameter is referenced (on link; later signals not setup)
1935     bool m_usedLoopIdx : 1;  // Variable subject of for unrolling
1936     bool m_funcLocal : 1;  // Local variable for a function
1937     bool m_funcReturn : 1;  // Return variable for a function
1938     bool m_attrClockEn : 1;  // User clock enable attribute
1939     bool m_attrScBv : 1;  // User force bit vector attribute
1940     bool m_attrIsolateAssign : 1;  // User isolate_assignments attribute
1941     bool m_attrSFormat : 1;  // User sformat attribute
1942     bool m_attrSplitVar : 1;  // declared with split_var metacomment
1943     bool m_fileDescr : 1;  // File descriptor
1944     bool m_isRand : 1;  // Random variable
1945     bool m_isConst : 1;  // Table contains constant data
1946     bool m_isStatic : 1;  // Static C variable (for Verilog see instead isAutomatic)
1947     bool m_isPulldown : 1;  // Tri0
1948     bool m_isPullup : 1;  // Tri1
1949     bool m_isIfaceParent : 1;  // dtype is reference to interface present in this module
1950     bool m_isDpiOpenArray : 1;  // DPI import open array
1951     bool m_isHideLocal : 1;  // Verilog local
1952     bool m_isHideProtected : 1;  // Verilog protected
1953     bool m_noReset : 1;  // Do not do automated reset/randomization
1954     bool m_noSubst : 1;  // Do not substitute out references
1955     bool m_overridenParam : 1;  // Overridden parameter by #(...) or defparam
1956     bool m_trace : 1;  // Trace this variable
1957     bool m_isLatched : 1;  // Not assigned in all control paths of combo always
1958 
init()1959     void init() {
1960         m_ansi = false;
1961         m_declTyped = false;
1962         m_tristate = false;
1963         m_primaryIO = false;
1964         m_sc = false;
1965         m_scClocked = false;
1966         m_scSensitive = false;
1967         m_usedClock = false;
1968         m_usedParam = false;
1969         m_usedLoopIdx = false;
1970         m_sigPublic = false;
1971         m_sigModPublic = false;
1972         m_sigUserRdPublic = false;
1973         m_sigUserRWPublic = false;
1974         m_funcLocal = false;
1975         m_funcReturn = false;
1976         m_attrClockEn = false;
1977         m_attrScBv = false;
1978         m_attrIsolateAssign = false;
1979         m_attrSFormat = false;
1980         m_attrSplitVar = false;
1981         m_fileDescr = false;
1982         m_isRand = false;
1983         m_isConst = false;
1984         m_isStatic = false;
1985         m_isPulldown = false;
1986         m_isPullup = false;
1987         m_isIfaceParent = false;
1988         m_isDpiOpenArray = false;
1989         m_isHideLocal = false;
1990         m_isHideProtected = false;
1991         m_noReset = false;
1992         m_noSubst = false;
1993         m_overridenParam = false;
1994         m_trace = false;
1995         m_isLatched = false;
1996         m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN;
1997     }
1998 
1999 public:
AstVar(FileLine * fl,AstVarType type,const string & name,VFlagChildDType,AstNodeDType * dtp)2000     AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
2001         : ASTGEN_SUPER_Var(fl)
2002         , m_name{name}
2003         , m_origName{name} {
2004         init();
2005         combineType(type);
2006         childDTypep(dtp);  // Only for parser
2007         dtypep(nullptr);  // V3Width will resolve
2008         if (dtp->basicp()) {
2009             m_declKwd = dtp->basicp()->keyword();
2010         } else {
2011             m_declKwd = AstBasicDTypeKwd::LOGIC;
2012         }
2013     }
AstVar(FileLine * fl,AstVarType type,const string & name,AstNodeDType * dtp)2014     AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtp)
2015         : ASTGEN_SUPER_Var(fl)
2016         , m_name{name}
2017         , m_origName{name} {
2018         init();
2019         combineType(type);
2020         UASSERT(dtp, "AstVar created with no dtype");
2021         dtypep(dtp);
2022         if (dtp->basicp()) {
2023             m_declKwd = dtp->basicp()->keyword();
2024         } else {
2025             m_declKwd = AstBasicDTypeKwd::LOGIC;
2026         }
2027     }
AstVar(FileLine * fl,AstVarType type,const string & name,VFlagLogicPacked,int wantwidth)2028     AstVar(FileLine* fl, AstVarType type, const string& name, VFlagLogicPacked, int wantwidth)
2029         : ASTGEN_SUPER_Var(fl)
2030         , m_name{name}
2031         , m_origName{name} {
2032         init();
2033         combineType(type);
2034         dtypeSetLogicSized(wantwidth, VSigning::UNSIGNED);
2035         m_declKwd = AstBasicDTypeKwd::LOGIC;
2036     }
AstVar(FileLine * fl,AstVarType type,const string & name,VFlagBitPacked,int wantwidth)2037     AstVar(FileLine* fl, AstVarType type, const string& name, VFlagBitPacked, int wantwidth)
2038         : ASTGEN_SUPER_Var(fl)
2039         , m_name{name}
2040         , m_origName{name} {
2041         init();
2042         combineType(type);
2043         dtypeSetBitSized(wantwidth, VSigning::UNSIGNED);
2044         m_declKwd = AstBasicDTypeKwd::BIT;
2045     }
AstVar(FileLine * fl,AstVarType type,const string & name,AstVar * examplep)2046     AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep)
2047         : ASTGEN_SUPER_Var(fl)
2048         , m_name{name}
2049         , m_origName{name} {
2050         init();
2051         combineType(type);
2052         if (examplep->childDTypep()) childDTypep(examplep->childDTypep()->cloneTree(true));
2053         dtypeFrom(examplep);
2054         m_declKwd = examplep->declKwd();
2055     }
2056     ASTNODE_NODE_FUNCS(Var)
2057     virtual void dump(std::ostream& str) const override;
name()2058     virtual string name() const override { return m_name; }  // * = Var name
hasDType()2059     virtual bool hasDType() const override { return true; }
maybePointedTo()2060     virtual bool maybePointedTo() const override { return true; }
origName()2061     virtual string origName() const override { return m_origName; }  // * = Original name
origName(const string & name)2062     void origName(const string& name) { m_origName = name; }
varType()2063     AstVarType varType() const { return m_varType; }  // * = Type of variable
direction(const VDirection & flag)2064     void direction(const VDirection& flag) {
2065         m_direction = flag;
2066         if (m_direction == VDirection::INOUT) m_tristate = true;
2067     }
direction()2068     VDirection direction() const { return m_direction; }
isIO()2069     bool isIO() const { return m_direction != VDirection::NONE; }
declDirection(const VDirection & flag)2070     void declDirection(const VDirection& flag) { m_declDirection = flag; }
declDirection()2071     VDirection declDirection() const { return m_declDirection; }
varType(AstVarType type)2072     void varType(AstVarType type) { m_varType = type; }
varType2Out()2073     void varType2Out() {
2074         m_tristate = false;
2075         m_direction = VDirection::OUTPUT;
2076     }
varType2In()2077     void varType2In() {
2078         m_tristate = false;
2079         m_direction = VDirection::INPUT;
2080     }
declKwd()2081     AstBasicDTypeKwd declKwd() const { return m_declKwd; }
2082     string scType() const;  // Return SysC type: bool, uint32_t, uint64_t, sc_bv
2083     // Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
2084     string cPubArgType(bool named, bool forReturn) const;
2085     string dpiArgType(bool named, bool forReturn) const;  // Return DPI-C type for argument
2086     string dpiTmpVarType(const string& varName) const;
2087     // Return Verilator internal type for argument: CData, SData, IData, WData
2088     string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "",
2089                      bool asRef = false) const;
2090     string vlEnumType() const;  // Return VerilatorVarType: VLVT_UINT32, etc
2091     string vlEnumDir() const;  // Return VerilatorVarDir: VLVD_INOUT, etc
2092     string vlPropDecl(const string& propName) const;  // Return VerilatorVarProps declaration
2093     void combineType(AstVarType type);
getChildDTypep()2094     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
2095     // op1 = Range of variable
childDTypep()2096     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
dtypeSkipRefp()2097     AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
2098     // (Slow) recurse down to find basic data type (Note don't need virtual -
2099     // AstVar isn't a NodeDType)
basicp()2100     AstBasicDType* basicp() const { return subDTypep()->basicp(); }
2101     // op3 = Initial value that never changes (static const), or constructor argument for
2102     // MTASKSTATE variables
valuep()2103     AstNode* valuep() const { return op3p(); }
2104     // It's valuep(), not constp(), as may be more complicated than an AstConst
valuep(AstNode * nodep)2105     void valuep(AstNode* nodep) { setOp3p(nodep); }
addAttrsp(AstNode * nodep)2106     void addAttrsp(AstNode* nodep) { addNOp4p(nodep); }
attrsp()2107     AstNode* attrsp() const { return op4p(); }  // op4 = Attributes during early parse
childDTypep(AstNodeDType * nodep)2108     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
subDTypep()2109     virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
ansi(bool flag)2110     void ansi(bool flag) { m_ansi = flag; }
declTyped(bool flag)2111     void declTyped(bool flag) { m_declTyped = flag; }
attrClockEn(bool flag)2112     void attrClockEn(bool flag) { m_attrClockEn = flag; }
attrClocker(VVarAttrClocker flag)2113     void attrClocker(VVarAttrClocker flag) { m_attrClocker = flag; }
attrFileDescr(bool flag)2114     void attrFileDescr(bool flag) { m_fileDescr = flag; }
attrScClocked(bool flag)2115     void attrScClocked(bool flag) { m_scClocked = flag; }
attrScBv(bool flag)2116     void attrScBv(bool flag) { m_attrScBv = flag; }
attrIsolateAssign(bool flag)2117     void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
attrSFormat(bool flag)2118     void attrSFormat(bool flag) { m_attrSFormat = flag; }
attrSplitVar(bool flag)2119     void attrSplitVar(bool flag) { m_attrSplitVar = flag; }
usedClock(bool flag)2120     void usedClock(bool flag) { m_usedClock = flag; }
usedParam(bool flag)2121     void usedParam(bool flag) { m_usedParam = flag; }
usedLoopIdx(bool flag)2122     void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
sigPublic(bool flag)2123     void sigPublic(bool flag) { m_sigPublic = flag; }
sigModPublic(bool flag)2124     void sigModPublic(bool flag) { m_sigModPublic = flag; }
sigUserRdPublic(bool flag)2125     void sigUserRdPublic(bool flag) {
2126         m_sigUserRdPublic = flag;
2127         if (flag) sigPublic(true);
2128     }
sigUserRWPublic(bool flag)2129     void sigUserRWPublic(bool flag) {
2130         m_sigUserRWPublic = flag;
2131         if (flag) sigUserRdPublic(true);
2132     }
sc(bool flag)2133     void sc(bool flag) { m_sc = flag; }
scSensitive(bool flag)2134     void scSensitive(bool flag) { m_scSensitive = flag; }
primaryIO(bool flag)2135     void primaryIO(bool flag) { m_primaryIO = flag; }
isRand(bool flag)2136     void isRand(bool flag) { m_isRand = flag; }
isConst(bool flag)2137     void isConst(bool flag) { m_isConst = flag; }
isStatic(bool flag)2138     void isStatic(bool flag) { m_isStatic = flag; }
isIfaceParent(bool flag)2139     void isIfaceParent(bool flag) { m_isIfaceParent = flag; }
funcLocal(bool flag)2140     void funcLocal(bool flag) { m_funcLocal = flag; }
funcReturn(bool flag)2141     void funcReturn(bool flag) { m_funcReturn = flag; }
isDpiOpenArray(bool flag)2142     void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; }
isDpiOpenArray()2143     bool isDpiOpenArray() const { return m_isDpiOpenArray; }
isHideLocal()2144     bool isHideLocal() const { return m_isHideLocal; }
isHideLocal(bool flag)2145     void isHideLocal(bool flag) { m_isHideLocal = flag; }
isHideProtected()2146     bool isHideProtected() const { return m_isHideProtected; }
isHideProtected(bool flag)2147     void isHideProtected(bool flag) { m_isHideProtected = flag; }
noReset(bool flag)2148     void noReset(bool flag) { m_noReset = flag; }
noReset()2149     bool noReset() const { return m_noReset; }
noSubst(bool flag)2150     void noSubst(bool flag) { m_noSubst = flag; }
noSubst()2151     bool noSubst() const { return m_noSubst; }
overriddenParam(bool flag)2152     void overriddenParam(bool flag) { m_overridenParam = flag; }
overriddenParam()2153     bool overriddenParam() const { return m_overridenParam; }
trace(bool flag)2154     void trace(bool flag) { m_trace = flag; }
isLatched(bool flag)2155     void isLatched(bool flag) { m_isLatched = flag; }
2156     // METHODS
name(const string & name)2157     virtual void name(const string& name) override { m_name = name; }
tag(const string & text)2158     virtual void tag(const string& text) override { m_tag = text; }
tag()2159     virtual string tag() const override { return m_tag; }
isAnsi()2160     bool isAnsi() const { return m_ansi; }
isDeclTyped()2161     bool isDeclTyped() const { return m_declTyped; }
isInoutish()2162     bool isInoutish() const { return m_direction.isInoutish(); }
isNonOutput()2163     bool isNonOutput() const { return m_direction.isNonOutput(); }
isReadOnly()2164     bool isReadOnly() const { return m_direction.isReadOnly(); }
isWritable()2165     bool isWritable() const { return m_direction.isWritable(); }
isTristate()2166     bool isTristate() const { return m_tristate; }
isPrimaryIO()2167     bool isPrimaryIO() const { return m_primaryIO; }
isPrimaryInish()2168     bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); }
isIfaceRef()2169     bool isIfaceRef() const { return (varType() == AstVarType::IFACEREF); }
isIfaceParent()2170     bool isIfaceParent() const { return m_isIfaceParent; }
isSignal()2171     bool isSignal() const { return varType().isSignal(); }
isTemp()2172     bool isTemp() const { return varType().isTemp(); }
isToggleCoverable()2173     bool isToggleCoverable() const {
2174         return ((isIO() || isSignal())
2175                 && (isIO() || isBitLogic())
2176                 // Wrapper would otherwise duplicate wrapped module's coverage
2177                 && !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString());
2178     }
isClassMember()2179     bool isClassMember() const { return varType() == AstVarType::MEMBER; }
isStatementTemp()2180     bool isStatementTemp() const { return (varType() == AstVarType::STMTTEMP); }
isXTemp()2181     bool isXTemp() const { return (varType() == AstVarType::XTEMP); }
isParam()2182     bool isParam() const {
2183         return (varType() == AstVarType::LPARAM || varType() == AstVarType::GPARAM);
2184     }
isGParam()2185     bool isGParam() const { return (varType() == AstVarType::GPARAM); }
isGenVar()2186     bool isGenVar() const { return (varType() == AstVarType::GENVAR); }
isBitLogic()2187     bool isBitLogic() const {
2188         AstBasicDType* bdtypep = basicp();
2189         return bdtypep && bdtypep->isBitLogic();
2190     }
isUsedClock()2191     bool isUsedClock() const { return m_usedClock; }
isUsedParam()2192     bool isUsedParam() const { return m_usedParam; }
isUsedLoopIdx()2193     bool isUsedLoopIdx() const { return m_usedLoopIdx; }
isSc()2194     bool isSc() const { return m_sc; }
2195     bool isScQuad() const;
2196     bool isScBv() const;
2197     bool isScUint() const;
2198     bool isScBigUint() const;
isScSensitive()2199     bool isScSensitive() const { return m_scSensitive; }
2200     bool isSigPublic() const;
isSigModPublic()2201     bool isSigModPublic() const { return m_sigModPublic; }
isSigUserRdPublic()2202     bool isSigUserRdPublic() const { return m_sigUserRdPublic; }
isSigUserRWPublic()2203     bool isSigUserRWPublic() const { return m_sigUserRWPublic; }
isTrace()2204     bool isTrace() const { return m_trace; }
isRand()2205     bool isRand() const { return m_isRand; }
isConst()2206     bool isConst() const { return m_isConst; }
isStatic()2207     bool isStatic() const { return m_isStatic; }
isLatched()2208     bool isLatched() const { return m_isLatched; }
isFuncLocal()2209     bool isFuncLocal() const { return m_funcLocal; }
isFuncReturn()2210     bool isFuncReturn() const { return m_funcReturn; }
isPullup()2211     bool isPullup() const { return m_isPullup; }
isPulldown()2212     bool isPulldown() const { return m_isPulldown; }
attrClockEn()2213     bool attrClockEn() const { return m_attrClockEn; }
attrScBv()2214     bool attrScBv() const { return m_attrScBv; }
attrFileDescr()2215     bool attrFileDescr() const { return m_fileDescr; }
attrScClocked()2216     bool attrScClocked() const { return m_scClocked; }
attrSFormat()2217     bool attrSFormat() const { return m_attrSFormat; }
attrSplitVar()2218     bool attrSplitVar() const { return m_attrSplitVar; }
attrIsolateAssign()2219     bool attrIsolateAssign() const { return m_attrIsolateAssign; }
attrClocker()2220     VVarAttrClocker attrClocker() const { return m_attrClocker; }
2221     virtual string verilogKwd() const override;
lifetime(const VLifetime & flag)2222     void lifetime(const VLifetime& flag) { m_lifetime = flag; }
lifetime()2223     VLifetime lifetime() const { return m_lifetime; }
propagateAttrFrom(AstVar * fromp)2224     void propagateAttrFrom(AstVar* fromp) {
2225         // This is getting connected to fromp; keep attributes
2226         // Note the method below too
2227         if (fromp->attrClockEn()) attrClockEn(true);
2228         if (fromp->attrFileDescr()) attrFileDescr(true);
2229         if (fromp->attrIsolateAssign()) attrIsolateAssign(true);
2230     }
gateMultiInputOptimizable()2231     bool gateMultiInputOptimizable() const {
2232         // Ok to gate optimize; must return false if propagateAttrFrom would do anything
2233         return (!attrClockEn() && !isUsedClock());
2234     }
combineType(AstVar * typevarp)2235     void combineType(AstVar* typevarp) {
2236         // This is same as typevarp (for combining input & reg decls)
2237         // "this" is the input var. typevarp is the reg var.
2238         propagateAttrFrom(typevarp);
2239         combineType(typevarp->varType());
2240         if (typevarp->isSigPublic()) sigPublic(true);
2241         if (typevarp->isSigModPublic()) sigModPublic(true);
2242         if (typevarp->isSigUserRdPublic()) sigUserRdPublic(true);
2243         if (typevarp->isSigUserRWPublic()) sigUserRWPublic(true);
2244         if (typevarp->attrScClocked()) attrScClocked(true);
2245     }
inlineAttrReset(const string & name)2246     void inlineAttrReset(const string& name) {
2247         if (direction() == VDirection::INOUT && varType() == AstVarType::WIRE) {
2248             m_varType = AstVarType::TRIWIRE;
2249         }
2250         m_direction = VDirection::NONE;
2251         m_name = name;
2252     }
2253     static AstVar* scVarRecurse(AstNode* nodep);
addProducingMTaskId(int id)2254     void addProducingMTaskId(int id) { m_mtaskIds.insert(id); }
addConsumingMTaskId(int id)2255     void addConsumingMTaskId(int id) { m_mtaskIds.insert(id); }
mtaskIds()2256     const MTaskIdSet& mtaskIds() const { return m_mtaskIds; }
pinNum(int id)2257     void pinNum(int id) { m_pinNum = id; }
pinNum()2258     int pinNum() const { return m_pinNum; }
2259 };
2260 
2261 class AstDefParam final : public AstNode {
2262     // A defparam assignment
2263     // Parents: MODULE
2264     // Children: math
2265 private:
2266     string m_name;  // Name of variable getting set
2267     string m_path;  // Dotted cellname to set parameter of
2268 public:
AstDefParam(FileLine * fl,const string & path,const string & name,AstNode * rhsp)2269     AstDefParam(FileLine* fl, const string& path, const string& name, AstNode* rhsp)
2270         : ASTGEN_SUPER_DefParam(fl) {
2271         setOp1p(rhsp);
2272         m_name = name;
2273         m_path = path;
2274     }
name()2275     virtual string name() const override { return m_name; }  // * = Scope name
ASTNODE_NODE_FUNCS(DefParam)2276     ASTNODE_NODE_FUNCS(DefParam)
2277     virtual bool same(const AstNode*) const override { return true; }
rhsp()2278     AstNode* rhsp() const { return op1p(); }  // op1 = Assign from
path()2279     string path() const { return m_path; }
2280 };
2281 
2282 class AstImplicit final : public AstNode {
2283     // Create implicit wires and do nothing else, for gates that are ignored
2284     // Parents: MODULE
2285 public:
AstImplicit(FileLine * fl,AstNode * exprsp)2286     AstImplicit(FileLine* fl, AstNode* exprsp)
2287         : ASTGEN_SUPER_Implicit(fl) {
2288         addNOp1p(exprsp);
2289     }
ASTNODE_NODE_FUNCS(Implicit)2290     ASTNODE_NODE_FUNCS(Implicit)
2291     AstNode* exprsp() const { return op1p(); }  // op1 = Assign from
2292 };
2293 
2294 class AstScope final : public AstNode {
2295     // A particular usage of a cell
2296     // Parents: MODULE
2297     // Children: NODEBLOCK
2298 private:
2299     // An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope
2300     string m_name;  // Name
2301     AstScope* const m_aboveScopep;  // Scope above this one in the hierarchy (nullptr if top)
2302     AstCell* const m_aboveCellp;  // Cell above this in the hierarchy (nullptr if top)
2303     AstNodeModule* const m_modp;  // Module scope corresponds to
2304 public:
AstScope(FileLine * fl,AstNodeModule * modp,const string & name,AstScope * aboveScopep,AstCell * aboveCellp)2305     AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep,
2306              AstCell* aboveCellp)
2307         : ASTGEN_SUPER_Scope(fl)
2308         , m_name{name}
2309         , m_aboveScopep{aboveScopep}
2310         , m_aboveCellp{aboveCellp}
2311         , m_modp{modp} {}
2312     ASTNODE_NODE_FUNCS(Scope)
2313     virtual void cloneRelink() override;
2314     virtual const char* broken() const override;
maybePointedTo()2315     virtual bool maybePointedTo() const override { return true; }
name()2316     virtual string name() const override { return m_name; }  // * = Scope name
name(const string & name)2317     virtual void name(const string& name) override { m_name = name; }
2318     virtual void dump(std::ostream& str) const override;
2319     string nameDotless() const;
nameVlSym()2320     string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); }
modp()2321     AstNodeModule* modp() const { return m_modp; }
addVarp(AstVarScope * nodep)2322     void addVarp(AstVarScope* nodep) { addOp1p((AstNode*)nodep); }
varsp()2323     AstVarScope* varsp() const { return VN_AS(op1p(), VarScope); }  // op1 = AstVarScope's
addActivep(AstNode * nodep)2324     void addActivep(AstNode* nodep) { addOp2p(nodep); }
blocksp()2325     AstNode* blocksp() const { return op2p(); }  // op2 = Block names
addFinalClkp(AstNode * nodep)2326     void addFinalClkp(AstNode* nodep) { addOp3p(nodep); }
finalClksp()2327     AstNode* finalClksp() const { return op3p(); }  // op3 = Final assigns for clock correction
aboveScopep()2328     AstScope* aboveScopep() const { return m_aboveScopep; }
aboveCellp()2329     AstCell* aboveCellp() const { return m_aboveCellp; }
isTop()2330     bool isTop() const { return aboveScopep() == nullptr; }  // At top of hierarchy
2331 };
2332 
2333 class AstTopScope final : public AstNode {
2334     // A singleton, held under the top level AstModule. Holds the top level AstScope,
2335     // and after V3ActiveTop, the global list of AstSenTrees (list of unique sensitivity lists).
2336     // Parent: Top level AstModule
2337     // Children: AstSenTree, AstScope
2338     friend class AstNetlist;  // Only the AstNetlist can create one
AstTopScope(FileLine * fl,AstScope * ascopep)2339     AstTopScope(FileLine* fl, AstScope* ascopep)
2340         : ASTGEN_SUPER_TopScope(fl) {
2341         addOp2p(ascopep);
2342     }
2343 
2344 public:
ASTNODE_NODE_FUNCS(TopScope)2345     ASTNODE_NODE_FUNCS(TopScope)
2346     virtual bool maybePointedTo() const override { return true; }
senTreesp()2347     AstSenTree* senTreesp() const { return VN_AS(op1p(), SenTree); }
addSenTreep(AstSenTree * nodep)2348     void addSenTreep(AstSenTree* nodep) { addOp1p((AstNode*)nodep); }
scopep()2349     AstScope* scopep() const { return VN_AS(op2p(), Scope); }
2350 };
2351 
2352 class AstVarScope final : public AstNode {
2353     // A particular scoped usage of a variable
2354     // That is, as a module is used under multiple cells, we get a different
2355     // varscope for each var in the module
2356     // Parents: MODULE
2357     // Children: none
2358 private:
2359     AstScope* m_scopep;  // Scope variable is underneath
2360     AstVar* m_varp;  // [AfterLink] Pointer to variable itself
2361     bool m_circular : 1;  // Used in circular ordering dependency, need change detect
2362     bool m_trace : 1;  // Tracing is turned on for this scope
2363 public:
AstVarScope(FileLine * fl,AstScope * scopep,AstVar * varp)2364     AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp)
2365         : ASTGEN_SUPER_VarScope(fl)
2366         , m_scopep{scopep}
2367         , m_varp{varp} {
2368         UASSERT_OBJ(scopep, fl, "Scope must be non-null");
2369         UASSERT_OBJ(varp, fl, "Var must be non-null");
2370         m_circular = false;
2371         m_trace = true;
2372         dtypeFrom(varp);
2373     }
ASTNODE_NODE_FUNCS(VarScope)2374     ASTNODE_NODE_FUNCS(VarScope)
2375     virtual void cloneRelink() override {
2376         if (m_varp && m_varp->clonep()) {
2377             m_varp = m_varp->clonep();
2378             UASSERT(m_scopep->clonep(), "No clone cross link: " << this);
2379             m_scopep = m_scopep->clonep();
2380         }
2381     }
broken()2382     virtual const char* broken() const override {
2383         BROKEN_RTN(m_varp && !m_varp->brokeExists());
2384         BROKEN_RTN(m_scopep && !m_scopep->brokeExists());
2385         return nullptr;
2386     }
maybePointedTo()2387     virtual bool maybePointedTo() const override { return true; }
name()2388     virtual string name() const override { return scopep()->name() + "->" + varp()->name(); }
2389     virtual void dump(std::ostream& str) const override;
hasDType()2390     virtual bool hasDType() const override { return true; }
varp()2391     AstVar* varp() const { return m_varp; }  // [After Link] Pointer to variable
scopep()2392     AstScope* scopep() const { return m_scopep; }  // Pointer to scope it's under
2393     // op1 = Calculation of value of variable, nullptr=complicated
valuep()2394     AstNode* valuep() const { return op1p(); }
valuep(AstNode * valuep)2395     void valuep(AstNode* valuep) { addOp1p(valuep); }
isCircular()2396     bool isCircular() const { return m_circular; }
circular(bool flag)2397     void circular(bool flag) { m_circular = flag; }
isTrace()2398     bool isTrace() const { return m_trace; }
trace(bool flag)2399     void trace(bool flag) { m_trace = flag; }
2400 };
2401 
2402 class AstVarRef final : public AstNodeVarRef {
2403     // A reference to a variable (lvalue or rvalue)
2404 public:
AstVarRef(FileLine * fl,const string & name,const VAccess & access)2405     AstVarRef(FileLine* fl, const string& name, const VAccess& access)
2406         : ASTGEN_SUPER_VarRef(fl, name, nullptr, access) {}
2407     // This form only allowed post-link because output/wire compression may
2408     // lead to deletion of AstVar's
AstVarRef(FileLine * fl,AstVar * varp,const VAccess & access)2409     AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access)
2410         : ASTGEN_SUPER_VarRef(fl, varp->name(), varp, access) {}
2411     // This form only allowed post-link (see above)
AstVarRef(FileLine * fl,AstVarScope * varscp,const VAccess & access)2412     AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access)
2413         : ASTGEN_SUPER_VarRef(fl, varscp->varp()->name(), varscp->varp(), access) {
2414         varScopep(varscp);
2415     }
2416     ASTNODE_NODE_FUNCS(VarRef)
2417     virtual void dump(std::ostream& str) const override;
same(const AstNode * samep)2418     virtual bool same(const AstNode* samep) const override {
2419         return same(static_cast<const AstVarRef*>(samep));
2420     }
same(const AstVarRef * samep)2421     inline bool same(const AstVarRef* samep) const {
2422         if (varScopep()) {
2423             return (varScopep() == samep->varScopep() && access() == samep->access());
2424         } else {
2425             return (selfPointer() == samep->selfPointer()
2426                     && varp()->name() == samep->varp()->name() && access() == samep->access());
2427         }
2428     }
sameNoLvalue(AstVarRef * samep)2429     inline bool sameNoLvalue(AstVarRef* samep) const {
2430         if (varScopep()) {
2431             return (varScopep() == samep->varScopep());
2432         } else {
2433             return (selfPointer() == samep->selfPointer()
2434                     && (!selfPointer().empty() || !samep->selfPointer().empty())
2435                     && varp()->name() == samep->varp()->name());
2436         }
2437     }
instrCount()2438     virtual int instrCount() const override {
2439         return widthInstrs() * (access().isReadOrRW() ? INSTR_COUNT_LD : 1);
2440     }
emitVerilog()2441     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()2442     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()2443     virtual bool cleanOut() const override { return true; }
2444 };
2445 
2446 class AstVarXRef final : public AstNodeVarRef {
2447     // A VarRef to something in another module before AstScope.
2448     // Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
2449 private:
2450     string m_dotted;  // Dotted part of scope the name()'ed reference is under or ""
2451     string m_inlinedDots;  // Dotted hierarchy flattened out
2452 public:
AstVarXRef(FileLine * fl,const string & name,const string & dotted,const VAccess & access)2453     AstVarXRef(FileLine* fl, const string& name, const string& dotted, const VAccess& access)
2454         : ASTGEN_SUPER_VarXRef(fl, name, nullptr, access)
2455         , m_dotted{dotted} {}
AstVarXRef(FileLine * fl,AstVar * varp,const string & dotted,const VAccess & access)2456     AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access)
2457         : ASTGEN_SUPER_VarXRef(fl, varp->name(), varp, access)
2458         , m_dotted{dotted} {
2459         dtypeFrom(varp);
2460     }
2461     ASTNODE_NODE_FUNCS(VarXRef)
2462     virtual void dump(std::ostream& str) const override;
dotted()2463     string dotted() const { return m_dotted; }
dotted(const string & dotted)2464     void dotted(const string& dotted) { m_dotted = dotted; }
inlinedDots()2465     string inlinedDots() const { return m_inlinedDots; }
inlinedDots(const string & flag)2466     void inlinedDots(const string& flag) { m_inlinedDots = flag; }
emitVerilog()2467     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()2468     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()2469     virtual bool cleanOut() const override { return true; }
instrCount()2470     virtual int instrCount() const override { return widthInstrs(); }
same(const AstNode * samep)2471     virtual bool same(const AstNode* samep) const override {
2472         const AstVarXRef* asamep = static_cast<const AstVarXRef*>(samep);
2473         return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp()
2474                 && name() == asamep->name() && dotted() == asamep->dotted());
2475     }
2476 };
2477 
2478 class AstAddrOfCFunc final : public AstNodeMath {
2479     // Get address of CFunc
2480 private:
2481     AstCFunc* m_funcp;  // Pointer to function itself
2482 
2483 public:
AstAddrOfCFunc(FileLine * fl,AstCFunc * funcp)2484     AstAddrOfCFunc(FileLine* fl, AstCFunc* funcp)
2485         : ASTGEN_SUPER_AddrOfCFunc(fl)
2486         , m_funcp{funcp} {
2487         dtypep(findCHandleDType());
2488     }
2489 
2490 public:
2491     ASTNODE_NODE_FUNCS(AddrOfCFunc)
2492     virtual void cloneRelink() override;
2493     virtual const char* broken() const override;
emitVerilog()2494     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()2495     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()2496     virtual bool cleanOut() const override { return true; }
funcp()2497     AstCFunc* funcp() const { return m_funcp; }
2498 };
2499 
2500 class AstPin final : public AstNode {
2501     // A pin on a cell
2502 private:
2503     int m_pinNum;  // Pin number
2504     string m_name;  // Pin name, or "" for number based interconnect
2505     AstVar* m_modVarp = nullptr;  // Input/output this pin connects to on submodule.
2506     AstParamTypeDType* m_modPTypep = nullptr;  // Param type this pin connects to on submodule.
2507     bool m_param = false;  // Pin connects to parameter
2508     bool m_svImplicit = false;  // Pin is SystemVerilog .name'ed
2509 public:
AstPin(FileLine * fl,int pinNum,const string & name,AstNode * exprp)2510     AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
2511         : ASTGEN_SUPER_Pin(fl)
2512         , m_pinNum{pinNum}
2513         , m_name{name} {
2514         setNOp1p(exprp);
2515     }
AstPin(FileLine * fl,int pinNum,AstVarRef * varname,AstNode * exprp)2516     AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp)
2517         : ASTGEN_SUPER_Pin(fl)
2518         , m_pinNum{pinNum}
2519         , m_name{varname->name()} {
2520         setNOp1p(exprp);
2521     }
2522     ASTNODE_NODE_FUNCS(Pin)
2523     virtual void dump(std::ostream& str) const override;
broken()2524     virtual const char* broken() const override {
2525         BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists());
2526         BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists());
2527         return nullptr;
2528     }
name()2529     virtual string name() const override { return m_name; }  // * = Pin name, ""=go by number
name(const string & name)2530     virtual void name(const string& name) override { m_name = name; }
prettyOperatorName()2531     virtual string prettyOperatorName() const override {
2532         return modVarp()
2533                    ? ((modVarp()->direction().isAny() ? modVarp()->direction().prettyName() + " "
2534                                                       : "")
2535                       + "port connection " + modVarp()->prettyNameQ())
2536                    : "port connection";
2537     }
dotStar()2538     bool dotStar() const { return name() == ".*"; }  // Fake name for .* connections until linked
pinNum()2539     int pinNum() const { return m_pinNum; }
exprp(AstNode * nodep)2540     void exprp(AstNode* nodep) { addOp1p(nodep); }
2541     // op1 = Expression connected to pin, nullptr if unconnected
exprp()2542     AstNode* exprp() const { return op1p(); }
modVarp()2543     AstVar* modVarp() const { return m_modVarp; }  // [After Link] Pointer to variable
modVarp(AstVar * nodep)2544     void modVarp(AstVar* nodep) { m_modVarp = nodep; }
2545     // [After Link] Pointer to variable
modPTypep()2546     AstParamTypeDType* modPTypep() const { return m_modPTypep; }
modPTypep(AstParamTypeDType * nodep)2547     void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; }
param()2548     bool param() const { return m_param; }
param(bool flag)2549     void param(bool flag) { m_param = flag; }
svImplicit()2550     bool svImplicit() const { return m_svImplicit; }
svImplicit(bool flag)2551     void svImplicit(bool flag) { m_svImplicit = flag; }
2552 };
2553 
2554 class AstArg final : public AstNode {
2555     // An argument to a function/task
2556 private:
2557     string m_name;  // Pin name, or "" for number based interconnect
2558 public:
AstArg(FileLine * fl,const string & name,AstNode * exprp)2559     AstArg(FileLine* fl, const string& name, AstNode* exprp)
2560         : ASTGEN_SUPER_Arg(fl)
2561         , m_name{name} {
2562         setNOp1p(exprp);
2563     }
ASTNODE_NODE_FUNCS(Arg)2564     ASTNODE_NODE_FUNCS(Arg)
2565     virtual string name() const override { return m_name; }  // * = Pin name, ""=go by number
name(const string & name)2566     virtual void name(const string& name) override { m_name = name; }
exprp(AstNode * nodep)2567     void exprp(AstNode* nodep) { addOp1p(nodep); }
2568     // op1 = Expression connected to pin, nullptr if unconnected
exprp()2569     AstNode* exprp() const { return op1p(); }
emptyConnectNoNext()2570     bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); }
2571 };
2572 
2573 class AstModule final : public AstNodeModule {
2574     // A module declaration
2575 private:
2576     const bool m_isProgram;  // Module represents a program
2577 public:
2578     AstModule(FileLine* fl, const string& name, bool program = false)
ASTGEN_SUPER_Module(fl,name)2579         : ASTGEN_SUPER_Module(fl, name)
2580         , m_isProgram{program} {}
ASTNODE_NODE_FUNCS(Module)2581     ASTNODE_NODE_FUNCS(Module)
2582     virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; }
timescaleMatters()2583     virtual bool timescaleMatters() const override { return true; }
2584 };
2585 
2586 class AstNotFoundModule final : public AstNodeModule {
2587     // A missing module declaration
2588 public:
AstNotFoundModule(FileLine * fl,const string & name)2589     AstNotFoundModule(FileLine* fl, const string& name)
2590         : ASTGEN_SUPER_NotFoundModule(fl, name) {}
ASTNODE_NODE_FUNCS(NotFoundModule)2591     ASTNODE_NODE_FUNCS(NotFoundModule)
2592     virtual string verilogKwd() const override { return "/*not-found-*/ module"; }
timescaleMatters()2593     virtual bool timescaleMatters() const override { return false; }
2594 };
2595 
2596 class AstPackage final : public AstNodeModule {
2597     // A package declaration
2598 public:
AstPackage(FileLine * fl,const string & name)2599     AstPackage(FileLine* fl, const string& name)
2600         : ASTGEN_SUPER_Package(fl, name) {}
ASTNODE_NODE_FUNCS(Package)2601     ASTNODE_NODE_FUNCS(Package)
2602     virtual string verilogKwd() const override { return "package"; }
timescaleMatters()2603     virtual bool timescaleMatters() const override { return !isDollarUnit(); }
dollarUnitName()2604     static string dollarUnitName() { return AstNode::encodeName("$unit"); }
isDollarUnit()2605     bool isDollarUnit() const { return name() == dollarUnitName(); }
2606 };
2607 
2608 class AstPrimitive final : public AstNodeModule {
2609     // A primitive declaration
2610 public:
AstPrimitive(FileLine * fl,const string & name)2611     AstPrimitive(FileLine* fl, const string& name)
2612         : ASTGEN_SUPER_Primitive(fl, name) {}
ASTNODE_NODE_FUNCS(Primitive)2613     ASTNODE_NODE_FUNCS(Primitive)
2614     virtual string verilogKwd() const override { return "primitive"; }
timescaleMatters()2615     virtual bool timescaleMatters() const override { return false; }
2616 };
2617 
2618 class AstPackageExportStarStar final : public AstNode {
2619     // A package export *::* declaration
2620 public:
2621     // cppcheck-suppress noExplicitConstructor
AstPackageExportStarStar(FileLine * fl)2622     AstPackageExportStarStar(FileLine* fl)
2623         : ASTGEN_SUPER_PackageExportStarStar(fl) {}
2624     ASTNODE_NODE_FUNCS(PackageExportStarStar)
2625 };
2626 
2627 class AstPackageExport final : public AstNode {
2628 private:
2629     // A package export declaration
2630     string m_name;
2631     AstPackage* m_packagep;  // Package hierarchy
2632 public:
AstPackageExport(FileLine * fl,AstPackage * packagep,const string & name)2633     AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
2634         : ASTGEN_SUPER_PackageExport(fl)
2635         , m_name{name}
2636         , m_packagep{packagep} {}
ASTNODE_NODE_FUNCS(PackageExport)2637     ASTNODE_NODE_FUNCS(PackageExport)
2638     virtual const char* broken() const override {
2639         BROKEN_RTN(!m_packagep || !m_packagep->brokeExists());
2640         return nullptr;
2641     }
cloneRelink()2642     virtual void cloneRelink() override {
2643         if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep();
2644     }
2645     virtual void dump(std::ostream& str) const override;
name()2646     virtual string name() const override { return m_name; }
packagep()2647     AstPackage* packagep() const { return m_packagep; }
packagep(AstPackage * nodep)2648     void packagep(AstPackage* nodep) { m_packagep = nodep; }
2649 };
2650 
2651 class AstPackageImport final : public AstNode {
2652 private:
2653     // A package import declaration
2654     string m_name;
2655     AstPackage* m_packagep;  // Package hierarchy
2656 public:
AstPackageImport(FileLine * fl,AstPackage * packagep,const string & name)2657     AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name)
2658         : ASTGEN_SUPER_PackageImport(fl)
2659         , m_name{name}
2660         , m_packagep{packagep} {}
ASTNODE_NODE_FUNCS(PackageImport)2661     ASTNODE_NODE_FUNCS(PackageImport)
2662     virtual const char* broken() const override {
2663         BROKEN_RTN(!m_packagep || !m_packagep->brokeExists());
2664         return nullptr;
2665     }
cloneRelink()2666     virtual void cloneRelink() override {
2667         if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep();
2668     }
2669     virtual void dump(std::ostream& str) const override;
name()2670     virtual string name() const override { return m_name; }
packagep()2671     AstPackage* packagep() const { return m_packagep; }
packagep(AstPackage * nodep)2672     void packagep(AstPackage* nodep) { m_packagep = nodep; }
2673 };
2674 
2675 class AstIface final : public AstNodeModule {
2676     // A module declaration
2677 public:
AstIface(FileLine * fl,const string & name)2678     AstIface(FileLine* fl, const string& name)
2679         : ASTGEN_SUPER_Iface(fl, name) {}
ASTNODE_NODE_FUNCS(Iface)2680     ASTNODE_NODE_FUNCS(Iface)
2681     // Interfaces have `timescale applicability but lots of code seems to
2682     // get false warnings if we enable this
2683     virtual bool timescaleMatters() const override { return false; }
2684 };
2685 
2686 class AstMemberSel final : public AstNodeMath {
2687     // Parents: math|stmt
2688     // Children: varref|arraysel, math
2689 private:
2690     // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
2691     string m_name;
2692     AstVar* m_varp = nullptr;  // Post link, variable within class that is target of selection
2693 public:
AstMemberSel(FileLine * fl,AstNode * fromp,VFlagChildDType,const string & name)2694     AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name)
2695         : ASTGEN_SUPER_MemberSel(fl)
2696         , m_name{name} {
2697         setOp1p(fromp);
2698         dtypep(nullptr);  // V3Width will resolve
2699     }
AstMemberSel(FileLine * fl,AstNode * fromp,AstNodeDType * dtp)2700     AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp)
2701         : ASTGEN_SUPER_MemberSel(fl)
2702         , m_name{dtp->name()} {
2703         setOp1p(fromp);
2704         dtypep(dtp);
2705     }
ASTNODE_NODE_FUNCS(MemberSel)2706     ASTNODE_NODE_FUNCS(MemberSel)
2707     virtual void cloneRelink() override {
2708         if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep();
2709     }
broken()2710     virtual const char* broken() const override {
2711         BROKEN_RTN(m_varp && !m_varp->brokeExists());
2712         return nullptr;
2713     }
2714     virtual void dump(std::ostream& str) const override;
name()2715     virtual string name() const override { return m_name; }
emitVerilog()2716     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()2717     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()2718     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)2719     virtual bool same(const AstNode* samep) const override {
2720         return true;
2721     }  // dtype comparison does it
instrCount()2722     virtual int instrCount() const override { return widthInstrs(); }
fromp()2723     AstNode* fromp() const {
2724         return op1p();
2725     }  // op1 = Extracting what (nullptr=TBD during parsing)
fromp(AstNode * nodep)2726     void fromp(AstNode* nodep) { setOp1p(nodep); }
varp()2727     AstVar* varp() const { return m_varp; }
varp(AstVar * nodep)2728     void varp(AstVar* nodep) { m_varp = nodep; }
2729 };
2730 
2731 class AstModportFTaskRef final : public AstNode {
2732     // An import/export referenced under a modport
2733     // The storage for the function itself is inside the
2734     // interface/instantiator, thus this is a reference
2735     // PARENT: AstModport
2736 private:
2737     string m_name;  // Name of the variable referenced
2738     bool m_export;  // Type of the function (import/export)
2739     AstNodeFTask* m_ftaskp = nullptr;  // Link to the function
2740 public:
AstModportFTaskRef(FileLine * fl,const string & name,bool isExport)2741     AstModportFTaskRef(FileLine* fl, const string& name, bool isExport)
2742         : ASTGEN_SUPER_ModportFTaskRef(fl)
2743         , m_name{name}
2744         , m_export{isExport} {}
ASTNODE_NODE_FUNCS(ModportFTaskRef)2745     ASTNODE_NODE_FUNCS(ModportFTaskRef)
2746     virtual const char* broken() const override {
2747         BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists());
2748         return nullptr;
2749     }
2750     virtual void dump(std::ostream& str) const override;
name()2751     virtual string name() const override { return m_name; }
cloneRelink()2752     virtual void cloneRelink() override {
2753         if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep();
2754     }
isImport()2755     bool isImport() const { return !m_export; }
isExport()2756     bool isExport() const { return m_export; }
ftaskp()2757     AstNodeFTask* ftaskp() const { return m_ftaskp; }  // [After Link] Pointer to variable
ftaskp(AstNodeFTask * ftaskp)2758     void ftaskp(AstNodeFTask* ftaskp) { m_ftaskp = ftaskp; }
2759 };
2760 
2761 class AstModportVarRef final : public AstNode {
2762     // A input/output/etc variable referenced under a modport
2763     // The storage for the variable itself is inside the interface, thus this is a reference
2764     // PARENT: AstModport
2765 private:
2766     string m_name;  // Name of the variable referenced
2767     VDirection m_direction;  // Direction of the variable (in/out)
2768     AstVar* m_varp = nullptr;  // Link to the actual Var
2769 public:
AstModportVarRef(FileLine * fl,const string & name,VDirection::en direction)2770     AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction)
2771         : ASTGEN_SUPER_ModportVarRef(fl)
2772         , m_name{name}
2773         , m_direction{direction} {}
ASTNODE_NODE_FUNCS(ModportVarRef)2774     ASTNODE_NODE_FUNCS(ModportVarRef)
2775     virtual const char* broken() const override {
2776         BROKEN_RTN(m_varp && !m_varp->brokeExists());
2777         return nullptr;
2778     }
2779     virtual void dump(std::ostream& str) const override;
cloneRelink()2780     virtual void cloneRelink() override {
2781         if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep();
2782     }
name()2783     virtual string name() const override { return m_name; }
direction(const VDirection & flag)2784     void direction(const VDirection& flag) { m_direction = flag; }
direction()2785     VDirection direction() const { return m_direction; }
varp()2786     AstVar* varp() const { return m_varp; }  // [After Link] Pointer to variable
varp(AstVar * varp)2787     void varp(AstVar* varp) { m_varp = varp; }
2788 };
2789 
2790 class AstModport final : public AstNode {
2791     // A modport in an interface
2792 private:
2793     string m_name;  // Name of the modport
2794 public:
AstModport(FileLine * fl,const string & name,AstNode * varsp)2795     AstModport(FileLine* fl, const string& name, AstNode* varsp)
2796         : ASTGEN_SUPER_Modport(fl)
2797         , m_name{name} {
2798         addNOp1p(varsp);
2799     }
name()2800     virtual string name() const override { return m_name; }
maybePointedTo()2801     virtual bool maybePointedTo() const override { return true; }
ASTNODE_NODE_FUNCS(Modport)2802     ASTNODE_NODE_FUNCS(Modport)
2803     AstNode* varsp() const { return op1p(); }  // op1 = List of Vars
2804 };
2805 
2806 class AstIntfRef final : public AstNode {
2807     // An interface reference
2808 private:
2809     string m_name;  // Name of the reference
2810 public:
AstIntfRef(FileLine * fl,const string & name)2811     AstIntfRef(FileLine* fl, const string& name)
2812         : ASTGEN_SUPER_IntfRef(fl)
2813         , m_name{name} {}
name()2814     virtual string name() const override { return m_name; }
2815     ASTNODE_NODE_FUNCS(IntfRef)
2816 };
2817 
2818 class AstCell final : public AstNode {
2819     // A instantiation cell or interface call (don't know which until link)
2820 private:
2821     FileLine* m_modNameFileline;  // Where module the cell instances token was
2822     string m_name;  // Cell name
2823     string m_origName;  // Original name before dot addition
2824     string m_modName;  // Module the cell instances
2825     AstNodeModule* m_modp = nullptr;  // [AfterLink] Pointer to module instanced
2826     bool m_hasIfaceVar : 1;  // True if a Var has been created for this cell
2827     bool m_recursive : 1;  // Self-recursive module
2828     bool m_trace : 1;  // Trace this cell
2829 public:
AstCell(FileLine * fl,FileLine * mfl,const string & instName,const string & modName,AstPin * pinsp,AstPin * paramsp,AstRange * rangep)2830     AstCell(FileLine* fl, FileLine* mfl, const string& instName, const string& modName,
2831             AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
2832         : ASTGEN_SUPER_Cell(fl)
2833         , m_modNameFileline{mfl}
2834         , m_name{instName}
2835         , m_origName{instName}
2836         , m_modName{modName}
2837         , m_hasIfaceVar{false}
2838         , m_recursive{false}
2839         , m_trace{true} {
2840         addNOp1p(pinsp);
2841         addNOp2p(paramsp);
2842         setNOp3p(rangep);
2843     }
2844     ASTNODE_NODE_FUNCS(Cell)
2845     // No cloneRelink, we presume cloneee's want the same module linkages
2846     virtual void dump(std::ostream& str) const override;
broken()2847     virtual const char* broken() const override {
2848         BROKEN_RTN(m_modp && !m_modp->brokeExists());
2849         return nullptr;
2850     }
maybePointedTo()2851     virtual bool maybePointedTo() const override { return true; }
2852     // ACCESSORS
name()2853     virtual string name() const override { return m_name; }  // * = Cell name
name(const string & name)2854     virtual void name(const string& name) override { m_name = name; }
origName()2855     virtual string origName() const override { return m_origName; }  // * = Original name
origName(const string & name)2856     void origName(const string& name) { m_origName = name; }
modName()2857     string modName() const { return m_modName; }  // * = Instance name
modName(const string & name)2858     void modName(const string& name) { m_modName = name; }
modNameFileline()2859     FileLine* modNameFileline() const { return m_modNameFileline; }
pinsp()2860     AstPin* pinsp() const { return VN_AS(op1p(), Pin); }  // op1 = List of cell ports
2861     // op2 = List of parameter #(##) values
paramsp()2862     AstPin* paramsp() const { return VN_AS(op2p(), Pin); }
2863     // op3 = Range of arrayed instants (nullptr=not ranged)
rangep()2864     AstRange* rangep() const { return VN_AS(op3p(), Range); }
2865     // op4 = List of interface references
intfRefp()2866     AstIntfRef* intfRefp() const { return VN_AS(op4p(), IntfRef); }
modp()2867     AstNodeModule* modp() const { return m_modp; }  // [AfterLink] = Pointer to module instantiated
addPinsp(AstPin * nodep)2868     void addPinsp(AstPin* nodep) { addOp1p(nodep); }
addParamsp(AstPin * nodep)2869     void addParamsp(AstPin* nodep) { addOp2p(nodep); }
addIntfRefp(AstIntfRef * nodep)2870     void addIntfRefp(AstIntfRef* nodep) { addOp4p(nodep); }
modp(AstNodeModule * nodep)2871     void modp(AstNodeModule* nodep) { m_modp = nodep; }
hasIfaceVar()2872     bool hasIfaceVar() const { return m_hasIfaceVar; }
hasIfaceVar(bool flag)2873     void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; }
trace(bool flag)2874     void trace(bool flag) { m_trace = flag; }
isTrace()2875     bool isTrace() const { return m_trace; }
recursive(bool flag)2876     void recursive(bool flag) { m_recursive = flag; }
recursive()2877     bool recursive() const { return m_recursive; }
2878 };
2879 
2880 class AstCellInline final : public AstNode {
2881     // A instantiation cell that was removed by inlining
2882     // For communication between V3Inline and V3LinkDot,
2883     // except for VPI runs where it exists until the end.
2884     // It is augmented with the scope in V3Scope for VPI.
2885     // Children: When 2 levels inlined, other CellInline under this
2886 private:
2887     string m_name;  // Cell name, possibly {a}__DOT__{b}...
2888     const string
2889         m_origModName;  // Original name of the module, ignoring name() changes, for dot lookup
2890     AstScope* m_scopep = nullptr;  // The scope that the cell is inlined into
2891     VTimescale m_timeunit;  // Parent module time unit
2892 public:
AstCellInline(FileLine * fl,const string & name,const string & origModName,const VTimescale & timeunit)2893     AstCellInline(FileLine* fl, const string& name, const string& origModName,
2894                   const VTimescale& timeunit)
2895         : ASTGEN_SUPER_CellInline(fl)
2896         , m_name{name}
2897         , m_origModName{origModName}
2898         , m_timeunit{timeunit} {}
2899     ASTNODE_NODE_FUNCS(CellInline)
2900     virtual void dump(std::ostream& str) const override;
broken()2901     virtual const char* broken() const override {
2902         BROKEN_RTN(m_scopep && !m_scopep->brokeExists());
2903         return nullptr;
2904     }
2905     // ACCESSORS
name()2906     virtual string name() const override { return m_name; }  // * = Cell name
origModName()2907     string origModName() const { return m_origModName; }  // * = modp()->origName() before inlining
name(const string & name)2908     virtual void name(const string& name) override { m_name = name; }
scopep(AstScope * scp)2909     void scopep(AstScope* scp) { m_scopep = scp; }
scopep()2910     AstScope* scopep() const { return m_scopep; }
timeunit(const VTimescale & flag)2911     void timeunit(const VTimescale& flag) { m_timeunit = flag; }
timeunit()2912     VTimescale timeunit() const { return m_timeunit; }
2913 };
2914 
2915 class AstCellRef final : public AstNode {
2916     // As-of-yet unlinkable reference into a cell
2917 private:
2918     string m_name;  // Cell name
2919 public:
AstCellRef(FileLine * fl,const string & name,AstNode * cellp,AstNode * exprp)2920     AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp)
2921         : ASTGEN_SUPER_CellRef(fl)
2922         , m_name{name} {
2923         addNOp1p(cellp);
2924         addNOp2p(exprp);
2925     }
ASTNODE_NODE_FUNCS(CellRef)2926     ASTNODE_NODE_FUNCS(CellRef)
2927     // ACCESSORS
2928     virtual string name() const override { return m_name; }  // * = Array name
cellp()2929     AstNode* cellp() const { return op1p(); }  // op1 = Cell
exprp()2930     AstNode* exprp() const { return op2p(); }  // op2 = Expression
2931 };
2932 
2933 class AstCellArrayRef final : public AstNode {
2934     // As-of-yet unlinkable reference into an array of cells
2935 private:
2936     string m_name;  // Array name
2937 public:
AstCellArrayRef(FileLine * fl,const string & name,AstNode * selectExprp)2938     AstCellArrayRef(FileLine* fl, const string& name, AstNode* selectExprp)
2939         : ASTGEN_SUPER_CellArrayRef(fl)
2940         , m_name{name} {
2941         addNOp1p(selectExprp);
2942     }
ASTNODE_NODE_FUNCS(CellArrayRef)2943     ASTNODE_NODE_FUNCS(CellArrayRef)
2944     // ACCESSORS
2945     virtual string name() const override { return m_name; }  // * = Array name
selp()2946     AstNode* selp() const { return op1p(); }  // op1 = Select expression
2947 };
2948 
2949 class AstUnlinkedRef final : public AstNode {
2950     // As-of-yet unlinkable Ref
2951 private:
2952     string m_name;  // Var name
2953 public:
AstUnlinkedRef(FileLine * fl,AstNode * refp,const string & name,AstNode * crp)2954     AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* crp)
2955         : ASTGEN_SUPER_UnlinkedRef(fl)
2956         , m_name{name} {
2957         addNOp1p(refp);
2958         addNOp2p(crp);
2959     }
ASTNODE_NODE_FUNCS(UnlinkedRef)2960     ASTNODE_NODE_FUNCS(UnlinkedRef)
2961     // ACCESSORS
2962     virtual string name() const override { return m_name; }  // * = Var name
refp()2963     AstNode* refp() const { return op1p(); }  // op1 = VarXRef or AstNodeFTaskRef
cellrefp()2964     AstNode* cellrefp() const { return op2p(); }  // op2 = CellArrayRef or CellRef
2965 };
2966 
2967 class AstBind final : public AstNode {
2968     // Parents: MODULE
2969     // Children: CELL
2970 private:
2971     string m_name;  // Binding to name
2972 public:
AstBind(FileLine * fl,const string & name,AstNode * cellsp)2973     AstBind(FileLine* fl, const string& name, AstNode* cellsp)
2974         : ASTGEN_SUPER_Bind(fl)
2975         , m_name{name} {
2976         UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound");
2977         addNOp1p(cellsp);
2978     }
ASTNODE_NODE_FUNCS(Bind)2979     ASTNODE_NODE_FUNCS(Bind)
2980     // ACCESSORS
2981     virtual string name() const override { return m_name; }  // * = Bind Target name
name(const string & name)2982     virtual void name(const string& name) override { m_name = name; }
cellsp()2983     AstNode* cellsp() const { return op1p(); }  // op1 = cells
2984 };
2985 
2986 class AstPort final : public AstNode {
2987     // A port (in/out/inout) on a module
2988 private:
2989     int m_pinNum;  // Pin number
2990     string m_name;  // Name of pin
2991 public:
AstPort(FileLine * fl,int pinnum,const string & name)2992     AstPort(FileLine* fl, int pinnum, const string& name)
2993         : ASTGEN_SUPER_Port(fl)
2994         , m_pinNum{pinnum}
2995         , m_name{name} {}
ASTNODE_NODE_FUNCS(Port)2996     ASTNODE_NODE_FUNCS(Port)
2997     virtual string name() const override { return m_name; }  // * = Port name
pinNum()2998     int pinNum() const { return m_pinNum; }  // * = Pin number, for order based instantiation
exprp()2999     AstNode* exprp() const { return op1p(); }  // op1 = Expression connected to port
3000 };
3001 
3002 //######################################################################
3003 
3004 class AstParseRef final : public AstNode {
3005     // A reference to a variable, function or task
3006     // We don't know which at parse time due to bison constraints
3007     // The link stages will replace this with AstVarRef, or AstTaskRef, etc.
3008     // Parents: math|stmt
3009     // Children: TEXT|DOT|SEL*|TASK|FUNC (or expression under sel)
3010 private:
3011     VParseRefExp m_expect;  // Type we think it should resolve to
3012     string m_name;
3013 
3014 public:
3015     AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, AstNode* lhsp = nullptr,
3016                 AstNodeFTaskRef* ftaskrefp = nullptr)
ASTGEN_SUPER_ParseRef(fl)3017         : ASTGEN_SUPER_ParseRef(fl)
3018         , m_expect{expect}
3019         , m_name{name} {
3020         setNOp1p(lhsp);
3021         setNOp2p(ftaskrefp);
3022     }
3023     ASTNODE_NODE_FUNCS(ParseRef)
3024     virtual void dump(std::ostream& str) const override;
name()3025     virtual string name() const override { return m_name; }  // * = Var name
same(const AstNode * samep)3026     virtual bool same(const AstNode* samep) const override {
3027         const AstParseRef* const asamep = static_cast<const AstParseRef*>(samep);
3028         return (expect() == asamep->expect() && m_name == asamep->m_name);
3029     }
name(const string & name)3030     virtual void name(const string& name) override { m_name = name; }
expect()3031     VParseRefExp expect() const { return m_expect; }
expect(VParseRefExp exp)3032     void expect(VParseRefExp exp) { m_expect = exp; }
3033     // op1 = Components
lhsp()3034     AstNode* lhsp() const { return op1p(); }  // op1 = List of statements
ftaskrefp()3035     AstNode* ftaskrefp() const { return op2p(); }  // op2 = Function/task reference
ftaskrefp(AstNodeFTaskRef * nodep)3036     void ftaskrefp(AstNodeFTaskRef* nodep) { setNOp2p(nodep); }  // op2 = Function/task reference
3037 };
3038 
3039 class AstClassOrPackageRef final : public AstNode {
3040 private:
3041     string m_name;
3042     // Node not NodeModule to appease some early parser usage
3043     AstNode* m_classOrPackageNodep;  // Package hierarchy
3044 public:
AstClassOrPackageRef(FileLine * fl,const string & name,AstNode * classOrPackageNodep,AstNode * paramsp)3045     AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackageNodep,
3046                          AstNode* paramsp)
3047         : ASTGEN_SUPER_ClassOrPackageRef(fl)
3048         , m_name{name}
3049         , m_classOrPackageNodep{classOrPackageNodep} {
3050         addNOp4p(paramsp);
3051     }
ASTNODE_NODE_FUNCS(ClassOrPackageRef)3052     ASTNODE_NODE_FUNCS(ClassOrPackageRef)
3053     // METHODS
3054     virtual const char* broken() const override {
3055         BROKEN_RTN(m_classOrPackageNodep && !m_classOrPackageNodep->brokeExists());
3056         return nullptr;
3057     }
cloneRelink()3058     virtual void cloneRelink() override {
3059         if (m_classOrPackageNodep && m_classOrPackageNodep->clonep()) {
3060             m_classOrPackageNodep = m_classOrPackageNodep->clonep();
3061         }
3062     }
same(const AstNode * samep)3063     virtual bool same(const AstNode* samep) const override {
3064         return (m_classOrPackageNodep
3065                 == static_cast<const AstClassOrPackageRef*>(samep)->m_classOrPackageNodep);
3066     }
3067     virtual void dump(std::ostream& str = std::cout) const override;
name()3068     virtual string name() const override { return m_name; }  // * = Var name
classOrPackageNodep()3069     AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; }
classOrPackageNodep(AstNode * nodep)3070     void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; }
classOrPackagep()3071     AstNodeModule* classOrPackagep() const { return VN_AS(m_classOrPackageNodep, NodeModule); }
packagep()3072     AstPackage* packagep() const { return VN_AS(classOrPackageNodep(), Package); }
classOrPackagep(AstNodeModule * nodep)3073     void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = nodep; }
paramsp()3074     AstPin* paramsp() const { return VN_AS(op4p(), Pin); }
3075 };
3076 
3077 class AstDot final : public AstNode {
3078     // A dot separating paths in an AstVarXRef, AstFuncRef or AstTaskRef
3079     // These are eliminated in the link stage
3080     const bool m_colon;  // Is a "::" instead of a "." (lhs must be package/class)
3081 public:
AstDot(FileLine * fl,bool colon,AstNode * lhsp,AstNode * rhsp)3082     AstDot(FileLine* fl, bool colon, AstNode* lhsp, AstNode* rhsp)
3083         : ASTGEN_SUPER_Dot(fl)
3084         , m_colon{colon} {
3085         setOp1p(lhsp);
3086         setOp2p(rhsp);
3087     }
ASTNODE_NODE_FUNCS(Dot)3088     ASTNODE_NODE_FUNCS(Dot)
3089     // For parser, make only if non-null package
3090     static AstNode* newIfPkg(FileLine* fl, AstNode* packageOrClassp, AstNode* rhsp) {
3091         if (!packageOrClassp) return rhsp;
3092         return new AstDot(fl, true, packageOrClassp, rhsp);
3093     }
3094     virtual void dump(std::ostream& str) const override;
lhsp()3095     AstNode* lhsp() const { return op1p(); }
rhsp()3096     AstNode* rhsp() const { return op2p(); }
colon()3097     bool colon() const { return m_colon; }
3098 };
3099 
3100 class AstUnbounded final : public AstNodeMath {
3101     // A $ in the parser, used for unbounded and queues
3102     // Due to where is used, treated as Signed32
3103 public:
AstUnbounded(FileLine * fl)3104     explicit AstUnbounded(FileLine* fl)
3105         : ASTGEN_SUPER_Unbounded(fl) {
3106         dtypeSetSigned32();
3107     }
ASTNODE_NODE_FUNCS(Unbounded)3108     ASTNODE_NODE_FUNCS(Unbounded)
3109     virtual string emitVerilog() override { return "$"; }
emitC()3110     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()3111     virtual bool cleanOut() const override { return true; }
3112 };
3113 
3114 //######################################################################
3115 
3116 class AstTask final : public AstNodeFTask {
3117     // A task inside a module
3118 public:
AstTask(FileLine * fl,const string & name,AstNode * stmtp)3119     AstTask(FileLine* fl, const string& name, AstNode* stmtp)
3120         : ASTGEN_SUPER_Task(fl, name, stmtp) {}
3121     ASTNODE_NODE_FUNCS(Task)
3122 };
3123 
3124 class AstFunc final : public AstNodeFTask {
3125     // A function inside a module
3126 public:
AstFunc(FileLine * fl,const string & name,AstNode * stmtp,AstNode * fvarsp)3127     AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarsp)
3128         : ASTGEN_SUPER_Func(fl, name, stmtp) {
3129         addNOp1p(fvarsp);
3130     }
ASTNODE_NODE_FUNCS(Func)3131     ASTNODE_NODE_FUNCS(Func)
3132     virtual bool hasDType() const override { return true; }
3133 };
3134 
3135 class AstTaskRef final : public AstNodeFTaskRef {
3136     // A reference to a task
3137 public:
AstTaskRef(FileLine * fl,AstParseRef * namep,AstNode * pinsp)3138     AstTaskRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
3139         : ASTGEN_SUPER_TaskRef(fl, true, namep, pinsp) {
3140         statement(true);
3141     }
AstTaskRef(FileLine * fl,const string & name,AstNode * pinsp)3142     AstTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
3143         : ASTGEN_SUPER_TaskRef(fl, true, name, pinsp) {}
3144     ASTNODE_NODE_FUNCS(TaskRef)
3145 };
3146 
3147 class AstFuncRef final : public AstNodeFTaskRef {
3148     // A reference to a function
3149 public:
AstFuncRef(FileLine * fl,AstParseRef * namep,AstNode * pinsp)3150     AstFuncRef(FileLine* fl, AstParseRef* namep, AstNode* pinsp)
3151         : ASTGEN_SUPER_FuncRef(fl, false, namep, pinsp) {}
AstFuncRef(FileLine * fl,const string & name,AstNode * pinsp)3152     AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp)
3153         : ASTGEN_SUPER_FuncRef(fl, false, name, pinsp) {}
ASTNODE_NODE_FUNCS(FuncRef)3154     ASTNODE_NODE_FUNCS(FuncRef)
3155     virtual bool hasDType() const override { return true; }
3156 };
3157 
3158 class AstDpiExport final : public AstNode {
3159     // We could put an AstNodeFTaskRef instead of the verilog function name,
3160     // however we're not *calling* it, so that seems somehow wrong.
3161     // (Probably AstNodeFTaskRef should be renamed AstNodeFTaskCall and have-a AstNodeFTaskRef)
3162 private:
3163     string m_name;  // Name of function
3164     string m_cname;  // Name of function on c side
3165 public:
AstDpiExport(FileLine * fl,const string & vname,const string & cname)3166     AstDpiExport(FileLine* fl, const string& vname, const string& cname)
3167         : ASTGEN_SUPER_DpiExport(fl)
3168         , m_name{vname}
3169         , m_cname{cname} {}
ASTNODE_NODE_FUNCS(DpiExport)3170     ASTNODE_NODE_FUNCS(DpiExport)
3171     virtual string name() const override { return m_name; }
name(const string & name)3172     virtual void name(const string& name) override { m_name = name; }
cname()3173     string cname() const { return m_cname; }
cname(const string & cname)3174     void cname(const string& cname) { m_cname = cname; }
3175 };
3176 
3177 class AstWithParse final : public AstNodeStmt {
3178     // In early parse, FUNC(index) WITH equation-using-index
3179     // Replaced with AstWith
3180     // Parents: math|stmt
3181     // Children: funcref, math
3182 public:
AstWithParse(FileLine * fl,bool stmt,AstNode * funcrefp,AstNode * exprp)3183     AstWithParse(FileLine* fl, bool stmt, AstNode* funcrefp, AstNode* exprp)
3184         : ASTGEN_SUPER_WithParse(fl) {
3185         statement(stmt);
3186         setOp1p(funcrefp);
3187         addNOp2p(exprp);
3188     }
ASTNODE_NODE_FUNCS(WithParse)3189     ASTNODE_NODE_FUNCS(WithParse)
3190     virtual bool same(const AstNode* samep) const override { return true; }
3191     //
funcrefp()3192     AstNode* funcrefp() const { return op1p(); }
exprp()3193     AstNode* exprp() const { return op2p(); }
3194 };
3195 
3196 class AstLambdaArgRef final : public AstNodeMath {
3197     // Lambda argument usage
3198     // These are not AstVarRefs because we need to be able to delete/clone lambdas during
3199     // optimizations and AstVar's are painful to remove.
3200 private:
3201     string m_name;  // Name of variable
3202     bool m_index;  // Index, not value
3203 
3204 public:
AstLambdaArgRef(FileLine * fl,const string & name,bool index)3205     AstLambdaArgRef(FileLine* fl, const string& name, bool index)
3206         : ASTGEN_SUPER_LambdaArgRef(fl)
3207         , m_name{name}
3208         , m_index(index) {}
ASTNODE_NODE_FUNCS(LambdaArgRef)3209     ASTNODE_NODE_FUNCS(LambdaArgRef)
3210     virtual bool same(const AstNode* samep) const override { return true; }
emitVerilog()3211     virtual string emitVerilog() override { return name(); }
emitC()3212     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()3213     virtual bool cleanOut() const override { return true; }
hasDType()3214     virtual bool hasDType() const override { return true; }
instrCount()3215     virtual int instrCount() const override { return widthInstrs(); }
name()3216     virtual string name() const override { return m_name; }  // * = Var name
name(const string & name)3217     virtual void name(const string& name) override { m_name = name; }
index()3218     bool index() const { return m_index; }
3219 };
3220 
3221 class AstWith final : public AstNodeStmt {
3222     // Used as argument to method, then to AstCMethodHard
3223     // dtypep() contains the with lambda's return dtype
3224     // Parents: funcref (similar to AstArg)
3225     // Children: LambdaArgRef that declares the item variable
3226     // Children: LambdaArgRef that declares the item.index variable
3227     // Children: math (equation establishing the with)
3228 public:
AstWith(FileLine * fl,AstLambdaArgRef * indexArgRefp,AstLambdaArgRef * valueArgRefp,AstNode * exprp)3229     AstWith(FileLine* fl, AstLambdaArgRef* indexArgRefp, AstLambdaArgRef* valueArgRefp,
3230             AstNode* exprp)
3231         : ASTGEN_SUPER_With(fl) {
3232         addOp1p(indexArgRefp);
3233         addOp2p(valueArgRefp);
3234         addNOp3p(exprp);
3235     }
ASTNODE_NODE_FUNCS(With)3236     ASTNODE_NODE_FUNCS(With)
3237     virtual bool same(const AstNode* samep) const override { return true; }
hasDType()3238     virtual bool hasDType() const override { return true; }
broken()3239     virtual const char* broken() const override {
3240         BROKEN_RTN(!indexArgRefp());  // varp needed to know lambda's arg dtype
3241         BROKEN_RTN(!valueArgRefp());  // varp needed to know lambda's arg dtype
3242         return nullptr;
3243     }
3244     //
indexArgRefp()3245     AstLambdaArgRef* indexArgRefp() const { return VN_AS(op1p(), LambdaArgRef); }
valueArgRefp()3246     AstLambdaArgRef* valueArgRefp() const { return VN_AS(op2p(), LambdaArgRef); }
exprp()3247     AstNode* exprp() const { return op3p(); }
3248 };
3249 
3250 //######################################################################
3251 
3252 class AstSenItem final : public AstNode {
3253     // Parents:  SENTREE
3254     // Children: (optional) VARREF
3255 private:
3256     VEdgeType m_edgeType;  // Edge type
3257 public:
3258     class Combo {};  // for creator type-overload selection
3259     class Illegal {};  // for creator type-overload selection
3260     class Initial {};  // for creator type-overload selection
3261     class Settle {};  // for creator type-overload selection
3262     class Never {};  // for creator type-overload selection
AstSenItem(FileLine * fl,VEdgeType edgeType,AstNode * varrefp)3263     AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* varrefp)
3264         : ASTGEN_SUPER_SenItem(fl)
3265         , m_edgeType{edgeType} {
3266         setOp1p(varrefp);
3267     }
AstSenItem(FileLine * fl,Combo)3268     AstSenItem(FileLine* fl, Combo)
3269         : ASTGEN_SUPER_SenItem(fl)
3270         , m_edgeType{VEdgeType::ET_COMBO} {}
AstSenItem(FileLine * fl,Illegal)3271     AstSenItem(FileLine* fl, Illegal)
3272         : ASTGEN_SUPER_SenItem(fl)
3273         , m_edgeType{VEdgeType::ET_ILLEGAL} {}
AstSenItem(FileLine * fl,Initial)3274     AstSenItem(FileLine* fl, Initial)
3275         : ASTGEN_SUPER_SenItem(fl)
3276         , m_edgeType{VEdgeType::ET_INITIAL} {}
AstSenItem(FileLine * fl,Settle)3277     AstSenItem(FileLine* fl, Settle)
3278         : ASTGEN_SUPER_SenItem(fl)
3279         , m_edgeType{VEdgeType::ET_SETTLE} {}
AstSenItem(FileLine * fl,Never)3280     AstSenItem(FileLine* fl, Never)
3281         : ASTGEN_SUPER_SenItem(fl)
3282         , m_edgeType{VEdgeType::ET_NEVER} {}
3283     ASTNODE_NODE_FUNCS(SenItem)
3284     virtual void dump(std::ostream& str) const override;
same(const AstNode * samep)3285     virtual bool same(const AstNode* samep) const override {
3286         return edgeType() == static_cast<const AstSenItem*>(samep)->edgeType();
3287     }
edgeType()3288     VEdgeType edgeType() const { return m_edgeType; }  // * = Posedge/negedge
edgeType(VEdgeType type)3289     void edgeType(VEdgeType type) {
3290         m_edgeType = type;
3291         editCountInc();
3292     }  // * = Posedge/negedge
sensp()3293     AstNode* sensp() const { return op1p(); }  // op1 = Signal sensitized
varrefp()3294     AstNodeVarRef* varrefp() const {
3295         return VN_CAST(op1p(), NodeVarRef);
3296     }  // op1 = Signal sensitized
3297     //
isClocked()3298     bool isClocked() const { return edgeType().clockedStmt(); }
isCombo()3299     bool isCombo() const { return edgeType() == VEdgeType::ET_COMBO; }
isInitial()3300     bool isInitial() const { return edgeType() == VEdgeType::ET_INITIAL; }
isIllegal()3301     bool isIllegal() const { return edgeType() == VEdgeType::ET_ILLEGAL; }
isSettle()3302     bool isSettle() const { return edgeType() == VEdgeType::ET_SETTLE; }
isNever()3303     bool isNever() const { return edgeType() == VEdgeType::ET_NEVER; }
hasVar()3304     bool hasVar() const { return !(isCombo() || isInitial() || isSettle() || isNever()); }
3305 };
3306 
3307 class AstSenTree final : public AstNode {
3308     // A list of senitems
3309     // Parents:  MODULE | SBLOCK
3310     // Children: SENITEM list
3311 private:
3312     bool m_multi = false;  // Created from combo logic by ORing multiple clock domains
3313 public:
AstSenTree(FileLine * fl,AstSenItem * sensesp)3314     AstSenTree(FileLine* fl, AstSenItem* sensesp)
3315         : ASTGEN_SUPER_SenTree(fl) {
3316         addNOp1p(sensesp);
3317     }
3318     ASTNODE_NODE_FUNCS(SenTree)
3319     virtual void dump(std::ostream& str) const override;
maybePointedTo()3320     virtual bool maybePointedTo() const override { return true; }
isMulti()3321     bool isMulti() const { return m_multi; }
3322     // op1 = Sensitivity list
sensesp()3323     AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); }
addSensesp(AstSenItem * nodep)3324     void addSensesp(AstSenItem* nodep) { addOp1p(nodep); }
multi(bool flag)3325     void multi(bool flag) { m_multi = true; }
3326     // METHODS
3327     bool hasClocked() const;  // Includes a clocked statement
3328     bool hasSettle() const;  // Includes a SETTLE SenItem
3329     bool hasInitial() const;  // Includes a INITIAL SenItem
3330     bool hasCombo() const;  // Includes a COMBO SenItem
3331 };
3332 
3333 class AstFinal final : public AstNodeProcedure {
3334 public:
AstFinal(FileLine * fl,AstNode * bodysp)3335     AstFinal(FileLine* fl, AstNode* bodysp)
3336         : ASTGEN_SUPER_Final(fl, bodysp) {}
3337     ASTNODE_NODE_FUNCS(Final)
3338 };
3339 
3340 class AstInitial final : public AstNodeProcedure {
3341 public:
AstInitial(FileLine * fl,AstNode * bodysp)3342     AstInitial(FileLine* fl, AstNode* bodysp)
3343         : ASTGEN_SUPER_Initial(fl, bodysp) {}
3344     ASTNODE_NODE_FUNCS(Initial)
3345 };
3346 
3347 class AstAlways final : public AstNodeProcedure {
3348     const VAlwaysKwd m_keyword;
3349 
3350 public:
AstAlways(FileLine * fl,VAlwaysKwd keyword,AstSenTree * sensesp,AstNode * bodysp)3351     AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp)
3352         : ASTGEN_SUPER_Always(fl, bodysp)
3353         , m_keyword{keyword} {
3354         addNOp1p(sensesp);
3355     }
3356     ASTNODE_NODE_FUNCS(Always)
3357     //
3358     virtual void dump(std::ostream& str) const override;
sensesp()3359     AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); }  // op1 = Sensitivity list
sensesp(AstSenTree * nodep)3360     void sensesp(AstSenTree* nodep) { setOp1p(nodep); }
keyword()3361     VAlwaysKwd keyword() const { return m_keyword; }
3362 };
3363 
3364 class AstAlwaysPostponed final : public AstNodeProcedure {
3365     // Like always but postponement scheduling region
3366 
3367 public:
AstAlwaysPostponed(FileLine * fl,AstNode * bodysp)3368     AstAlwaysPostponed(FileLine* fl, AstNode* bodysp)
3369         : ASTGEN_SUPER_AlwaysPostponed(fl, bodysp) {}
3370     ASTNODE_NODE_FUNCS(AlwaysPostponed)
3371 };
3372 
3373 class AstAlwaysPost final : public AstNodeProcedure {
3374     // Like always but post assignments for memory assignment IFs
3375 public:
AstAlwaysPost(FileLine * fl,AstSenTree * sensesp,AstNode * bodysp)3376     AstAlwaysPost(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
3377         : ASTGEN_SUPER_AlwaysPost(fl, bodysp) {
3378         addNOp1p(sensesp);
3379     }
3380     ASTNODE_NODE_FUNCS(AlwaysPost)
3381 };
3382 
3383 class AstAlwaysPublic final : public AstNodeStmt {
3384     // "Fake" sensitivity created by /*verilator public_flat_rw @(edgelist)*/
3385     // Body statements are just AstVarRefs to the public signals
3386 public:
AstAlwaysPublic(FileLine * fl,AstSenTree * sensesp,AstNode * bodysp)3387     AstAlwaysPublic(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
3388         : ASTGEN_SUPER_AlwaysPublic(fl) {
3389         addNOp1p(sensesp);
3390         addNOp2p(bodysp);
3391     }
ASTNODE_NODE_FUNCS(AlwaysPublic)3392     ASTNODE_NODE_FUNCS(AlwaysPublic)
3393     virtual bool same(const AstNode* samep) const override { return true; }
3394     //
sensesp()3395     AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); }  // op1 = Sensitivity list
bodysp()3396     AstNode* bodysp() const { return op2p(); }  // op2 = Statements to evaluate
addStmtp(AstNode * nodep)3397     void addStmtp(AstNode* nodep) { addOp2p(nodep); }
3398     // Special accessors
isJustOneBodyStmt()3399     bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); }
3400 };
3401 
3402 class AstAssign final : public AstNodeAssign {
3403 public:
AstAssign(FileLine * fl,AstNode * lhsp,AstNode * rhsp)3404     AstAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
3405         : ASTGEN_SUPER_Assign(fl, lhsp, rhsp) {
3406         dtypeFrom(lhsp);
3407     }
ASTNODE_NODE_FUNCS(Assign)3408     ASTNODE_NODE_FUNCS(Assign)
3409     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3410         return new AstAssign(this->fileline(), lhsp, rhsp);
3411     }
brokeLhsMustBeLvalue()3412     virtual bool brokeLhsMustBeLvalue() const override { return true; }
3413 };
3414 
3415 class AstAssignAlias final : public AstNodeAssign {
3416     // Like AstAssignW, but a true bidirect interconnection alias
3417     // If both sides are wires, there's no LHS vs RHS,
3418 public:
AstAssignAlias(FileLine * fl,AstVarRef * lhsp,AstVarRef * rhsp)3419     AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp)
3420         : ASTGEN_SUPER_AssignAlias(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignAlias)3421     ASTNODE_NODE_FUNCS(AssignAlias)
3422     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3423         V3ERROR_NA_RETURN(nullptr);
3424     }
brokeLhsMustBeLvalue()3425     virtual bool brokeLhsMustBeLvalue() const override { return false; }
3426 };
3427 
3428 class AstAssignDly final : public AstNodeAssign {
3429 public:
AstAssignDly(FileLine * fl,AstNode * lhsp,AstNode * rhsp)3430     AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
3431         : ASTGEN_SUPER_AssignDly(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignDly)3432     ASTNODE_NODE_FUNCS(AssignDly)
3433     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3434         return new AstAssignDly(this->fileline(), lhsp, rhsp);
3435     }
isGateOptimizable()3436     virtual bool isGateOptimizable() const override { return false; }
verilogKwd()3437     virtual string verilogKwd() const override { return "<="; }
brokeLhsMustBeLvalue()3438     virtual bool brokeLhsMustBeLvalue() const override { return true; }
3439 };
3440 
3441 class AstAssignW final : public AstNodeAssign {
3442     // Like assign, but wire/assign's in verilog, the only setting of the specified variable
3443 public:
AstAssignW(FileLine * fl,AstNode * lhsp,AstNode * rhsp)3444     AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
3445         : ASTGEN_SUPER_AssignW(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignW)3446     ASTNODE_NODE_FUNCS(AssignW)
3447     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3448         return new AstAssignW(this->fileline(), lhsp, rhsp);
3449     }
brokeLhsMustBeLvalue()3450     virtual bool brokeLhsMustBeLvalue() const override { return true; }
convertToAlways()3451     AstAlways* convertToAlways() {
3452         AstNode* const lhs1p = lhsp()->unlinkFrBack();
3453         AstNode* const rhs1p = rhsp()->unlinkFrBack();
3454         AstAlways* const newp = new AstAlways(fileline(), VAlwaysKwd::ALWAYS, nullptr,
3455                                               new AstAssign(fileline(), lhs1p, rhs1p));
3456         replaceWith(newp);  // User expected to then deleteTree();
3457         return newp;
3458     }
3459 };
3460 
3461 class AstAssignVarScope final : public AstNodeAssign {
3462     // Assign two VarScopes to each other
3463 public:
AstAssignVarScope(FileLine * fl,AstNode * lhsp,AstNode * rhsp)3464     AstAssignVarScope(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
3465         : ASTGEN_SUPER_AssignVarScope(fl, lhsp, rhsp) {
3466         dtypeFrom(rhsp);
3467     }
ASTNODE_NODE_FUNCS(AssignVarScope)3468     ASTNODE_NODE_FUNCS(AssignVarScope)
3469     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3470         return new AstAssignVarScope(this->fileline(), lhsp, rhsp);
3471     }
brokeLhsMustBeLvalue()3472     virtual bool brokeLhsMustBeLvalue() const override { return false; }
3473 };
3474 
3475 class AstPull final : public AstNode {
3476 private:
3477     bool m_direction;
3478 
3479 public:
AstPull(FileLine * fl,AstNode * lhsp,bool direction)3480     AstPull(FileLine* fl, AstNode* lhsp, bool direction)
3481         : ASTGEN_SUPER_Pull(fl) {
3482         setOp1p(lhsp);
3483         m_direction = direction;
3484     }
ASTNODE_NODE_FUNCS(Pull)3485     ASTNODE_NODE_FUNCS(Pull)
3486     virtual bool same(const AstNode* samep) const override {
3487         return direction() == static_cast<const AstPull*>(samep)->direction();
3488     }
lhsp(AstNode * np)3489     void lhsp(AstNode* np) { setOp1p(np); }
lhsp()3490     AstNode* lhsp() const { return op1p(); }  // op1 = Assign to
direction()3491     uint32_t direction() const { return (uint32_t)m_direction; }
3492 };
3493 
3494 class AstAssignPre final : public AstNodeAssign {
3495     // Like Assign, but predelayed assignment requiring special order handling
3496 public:
AstAssignPre(FileLine * fl,AstNode * lhsp,AstNode * rhsp)3497     AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
3498         : ASTGEN_SUPER_AssignPre(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignPre)3499     ASTNODE_NODE_FUNCS(AssignPre)
3500     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3501         return new AstAssignPre(this->fileline(), lhsp, rhsp);
3502     }
brokeLhsMustBeLvalue()3503     virtual bool brokeLhsMustBeLvalue() const override { return true; }
3504 };
3505 
3506 class AstAssignPost final : public AstNodeAssign {
3507     // Like Assign, but predelayed assignment requiring special order handling
3508 public:
AstAssignPost(FileLine * fl,AstNode * lhsp,AstNode * rhsp)3509     AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
3510         : ASTGEN_SUPER_AssignPost(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(AssignPost)3511     ASTNODE_NODE_FUNCS(AssignPost)
3512     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
3513         return new AstAssignPost(this->fileline(), lhsp, rhsp);
3514     }
brokeLhsMustBeLvalue()3515     virtual bool brokeLhsMustBeLvalue() const override { return true; }
3516 };
3517 
3518 class AstDpiExportUpdated final : public AstNodeStmt {
3519     // Denotes that the referenced variable may have been updated via a DPI Export
3520 public:
AstDpiExportUpdated(FileLine * fl,AstVarScope * varScopep)3521     AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep)
3522         : ASTGEN_SUPER_DpiExportUpdated(fl) {
3523         addOp1p(new AstVarRef{fl, varScopep, VAccess::WRITE});
3524     }
ASTNODE_NODE_FUNCS(DpiExportUpdated)3525     ASTNODE_NODE_FUNCS(DpiExportUpdated)
3526     AstVarScope* varScopep() const { return VN_AS(op1p(), VarRef)->varScopep(); }
3527 };
3528 
3529 class AstExprStmt final : public AstNodeMath {
3530     // Perform a statement, often assignment inside an expression/math node,
3531     // the parent gets passed the 'resultp()'.
3532     // resultp is evaluated AFTER the statement(s).
3533 public:
AstExprStmt(FileLine * fl,AstNode * stmtsp,AstNode * resultp)3534     AstExprStmt(FileLine* fl, AstNode* stmtsp, AstNode* resultp)
3535         : ASTGEN_SUPER_ExprStmt(fl) {
3536         addOp1p(stmtsp);
3537         setOp2p(resultp);  // Possibly in future nullptr could mean return rhsp()
3538         dtypeFrom(resultp);
3539     }
ASTNODE_NODE_FUNCS(ExprStmt)3540     ASTNODE_NODE_FUNCS(ExprStmt)
3541     // ACCESSORS
3542     AstNode* stmtsp() const { return op1p(); }
addStmtsp(AstNode * nodep)3543     void addStmtsp(AstNode* nodep) { addOp1p(nodep); }
resultp()3544     AstNode* resultp() const { return op2p(); }
3545     // METHODS
emitVerilog()3546     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()3547     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()3548     virtual bool cleanOut() const override { return false; }
same(const AstNode *)3549     virtual bool same(const AstNode*) const override { return true; }
3550 };
3551 
3552 class AstComment final : public AstNodeStmt {
3553     // Some comment to put into the output stream
3554     // Parents:  {statement list}
3555     // Children: none
3556 private:
3557     const bool m_showAt;  // Show "at <fileline>"
3558     const string m_name;  // Text of comment
3559 public:
3560     AstComment(FileLine* fl, const string& name, bool showAt = false)
ASTGEN_SUPER_Comment(fl)3561         : ASTGEN_SUPER_Comment(fl)
3562         , m_showAt{showAt}
3563         , m_name{name} {}
ASTNODE_NODE_FUNCS(Comment)3564     ASTNODE_NODE_FUNCS(Comment)
3565     virtual string name() const override { return m_name; }  // * = Text
same(const AstNode * samep)3566     virtual bool same(const AstNode* samep) const override {
3567         return true;
3568     }  // Ignore name in comments
showAt()3569     virtual bool showAt() const { return m_showAt; }
3570 };
3571 
3572 class AstCond final : public AstNodeCond {
3573     // Conditional ?: statement
3574     // Parents:  MATH
3575     // Children: MATH
3576 public:
AstCond(FileLine * fl,AstNode * condp,AstNode * expr1p,AstNode * expr2p)3577     AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
3578         : ASTGEN_SUPER_Cond(fl, condp, expr1p, expr2p) {}
ASTNODE_NODE_FUNCS(Cond)3579     ASTNODE_NODE_FUNCS(Cond)
3580     virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override {
3581         return new AstCond(this->fileline(), condp, expr1p, expr2p);
3582     }
3583 };
3584 
3585 class AstCondBound final : public AstNodeCond {
3586     // Conditional ?: statement, specially made for safety checking of array bounds
3587     // Parents:  MATH
3588     // Children: MATH
3589 public:
AstCondBound(FileLine * fl,AstNode * condp,AstNode * expr1p,AstNode * expr2p)3590     AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
3591         : ASTGEN_SUPER_CondBound(fl, condp, expr1p, expr2p) {}
ASTNODE_NODE_FUNCS(CondBound)3592     ASTNODE_NODE_FUNCS(CondBound)
3593     virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override {
3594         return new AstCondBound(this->fileline(), condp, expr1p, expr2p);
3595     }
3596 };
3597 
3598 class AstCoverDecl final : public AstNodeStmt {
3599     // Coverage analysis point declaration
3600     // Parents:  {statement list}
3601     // Children: none
3602 private:
3603     AstCoverDecl* m_dataDeclp;  // [After V3CoverageJoin] Pointer to duplicate declaration to get
3604                                 // data from instead
3605     string m_page;
3606     string m_text;
3607     string m_hier;
3608     string m_linescov;
3609     int m_offset;  // Offset column numbers to uniq-ify IFs
3610     int m_binNum;  // Set by V3EmitCSyms to tell final V3Emit what to increment
3611 public:
AstCoverDecl(FileLine * fl,const string & page,const string & comment,const string & linescov,int offset)3612     AstCoverDecl(FileLine* fl, const string& page, const string& comment, const string& linescov,
3613                  int offset)
3614         : ASTGEN_SUPER_CoverDecl(fl) {
3615         m_page = page;
3616         m_text = comment;
3617         m_linescov = linescov;
3618         m_offset = offset;
3619         m_binNum = 0;
3620         m_dataDeclp = nullptr;
3621     }
ASTNODE_NODE_FUNCS(CoverDecl)3622     ASTNODE_NODE_FUNCS(CoverDecl)
3623     virtual const char* broken() const override {
3624         BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists());
3625         if (m_dataDeclp && m_dataDeclp->m_dataDeclp) {  // Avoid O(n^2) accessing
3626             v3fatalSrc("dataDeclp should point to real data, not be a list");
3627         }
3628         return nullptr;
3629     }
cloneRelink()3630     virtual void cloneRelink() override {
3631         if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep();
3632     }
3633     virtual void dump(std::ostream& str) const override;
instrCount()3634     virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; }
maybePointedTo()3635     virtual bool maybePointedTo() const override { return true; }
binNum(int flag)3636     void binNum(int flag) { m_binNum = flag; }
binNum()3637     int binNum() const { return m_binNum; }
offset()3638     int offset() const { return m_offset; }
comment()3639     const string& comment() const { return m_text; }  // text to insert in code
linescov()3640     const string& linescov() const { return m_linescov; }
page()3641     const string& page() const { return m_page; }
hier()3642     const string& hier() const { return m_hier; }
hier(const string & flag)3643     void hier(const string& flag) { m_hier = flag; }
comment(const string & flag)3644     void comment(const string& flag) { m_text = flag; }
same(const AstNode * samep)3645     virtual bool same(const AstNode* samep) const override {
3646         const AstCoverDecl* const asamep = static_cast<const AstCoverDecl*>(samep);
3647         return (fileline() == asamep->fileline() && linescov() == asamep->linescov()
3648                 && hier() == asamep->hier() && comment() == asamep->comment());
3649     }
isPredictOptimizable()3650     virtual bool isPredictOptimizable() const override { return false; }
dataDeclp(AstCoverDecl * nodep)3651     void dataDeclp(AstCoverDecl* nodep) { m_dataDeclp = nodep; }
3652     // dataDecl nullptr means "use this one", but often you want "this" to
3653     // indicate to get data from here
dataDeclNullp()3654     AstCoverDecl* dataDeclNullp() const { return m_dataDeclp; }
dataDeclThisp()3655     AstCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; }
3656 };
3657 
3658 class AstCoverInc final : public AstNodeStmt {
3659     // Coverage analysis point; increment coverage count
3660     // Parents:  {statement list}
3661     // Children: none
3662 private:
3663     AstCoverDecl* m_declp;  // [After V3Coverage] Pointer to declaration
3664 public:
AstCoverInc(FileLine * fl,AstCoverDecl * declp)3665     AstCoverInc(FileLine* fl, AstCoverDecl* declp)
3666         : ASTGEN_SUPER_CoverInc(fl)
3667         , m_declp{declp} {}
ASTNODE_NODE_FUNCS(CoverInc)3668     ASTNODE_NODE_FUNCS(CoverInc)
3669     virtual const char* broken() const override {
3670         BROKEN_RTN(!declp()->brokeExists());
3671         return nullptr;
3672     }
cloneRelink()3673     virtual void cloneRelink() override {
3674         if (m_declp->clonep()) m_declp = m_declp->clonep();
3675     }
3676     virtual void dump(std::ostream& str) const override;
instrCount()3677     virtual int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; }
same(const AstNode * samep)3678     virtual bool same(const AstNode* samep) const override {
3679         return declp() == static_cast<const AstCoverInc*>(samep)->declp();
3680     }
isGateOptimizable()3681     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()3682     virtual bool isPredictOptimizable() const override { return false; }
isOutputter()3683     virtual bool isOutputter() const override { return true; }
3684     // but isPure()  true
declp()3685     AstCoverDecl* declp() const { return m_declp; }  // Where defined
3686 };
3687 
3688 class AstCoverToggle final : public AstNodeStmt {
3689     // Toggle analysis of given signal
3690     // Parents:  MODULE
3691     // Children: AstCoverInc, orig var, change det var
3692 public:
AstCoverToggle(FileLine * fl,AstCoverInc * incp,AstNode * origp,AstNode * changep)3693     AstCoverToggle(FileLine* fl, AstCoverInc* incp, AstNode* origp, AstNode* changep)
3694         : ASTGEN_SUPER_CoverToggle(fl) {
3695         setOp1p(incp);
3696         setOp2p(origp);
3697         setOp3p(changep);
3698     }
ASTNODE_NODE_FUNCS(CoverToggle)3699     ASTNODE_NODE_FUNCS(CoverToggle)
3700     virtual int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; }
same(const AstNode * samep)3701     virtual bool same(const AstNode* samep) const override { return true; }
isGateOptimizable()3702     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()3703     virtual bool isPredictOptimizable() const override { return true; }
isOutputter()3704     virtual bool isOutputter() const override {
3705         return false;  // Though the AstCoverInc under this is an outputter
3706     }
3707     // but isPure()  true
incp()3708     AstCoverInc* incp() const { return VN_AS(op1p(), CoverInc); }
incp(AstCoverInc * nodep)3709     void incp(AstCoverInc* nodep) { setOp1p(nodep); }
origp()3710     AstNode* origp() const { return op2p(); }
changep()3711     AstNode* changep() const { return op3p(); }
3712 };
3713 
3714 class AstDelay final : public AstNodeStmt {
3715     // Delay statement
3716 public:
AstDelay(FileLine * fl,AstNode * lhsp)3717     AstDelay(FileLine* fl, AstNode* lhsp)
3718         : ASTGEN_SUPER_Delay(fl) {
3719         setOp1p(lhsp);
3720     }
ASTNODE_NODE_FUNCS(Delay)3721     ASTNODE_NODE_FUNCS(Delay)
3722     virtual bool same(const AstNode* samep) const override { return true; }
3723     //
lhsp()3724     AstNode* lhsp() const { return op1p(); }  // op2 = Statements to evaluate
lhsp(AstNode * nodep)3725     void lhsp(AstNode* nodep) { setOp1p(nodep); }
3726 };
3727 
3728 class AstGenCase final : public AstNodeCase {
3729     // Generate Case statement
3730     // Parents:  {statement list}
3731     // exprp Children:  MATHs
3732     // casesp Children: CASEITEMs
3733 public:
AstGenCase(FileLine * fl,AstNode * exprp,AstNode * casesp)3734     AstGenCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
3735         : ASTGEN_SUPER_GenCase(fl, exprp, casesp) {}
3736     ASTNODE_NODE_FUNCS(GenCase)
3737 };
3738 
3739 class AstCase final : public AstNodeCase {
3740     // Case statement
3741     // Parents:  {statement list}
3742     // exprp Children:  MATHs
3743     // casesp Children: CASEITEMs
3744 private:
3745     VCaseType m_casex;  // 0=case, 1=casex, 2=casez
3746     bool m_fullPragma = false;  // Synthesis full_case
3747     bool m_parallelPragma = false;  // Synthesis parallel_case
3748     bool m_uniquePragma = false;  // unique case
3749     bool m_unique0Pragma = false;  // unique0 case
3750     bool m_priorityPragma = false;  // priority case
3751 public:
AstCase(FileLine * fl,VCaseType casex,AstNode * exprp,AstNode * casesp)3752     AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp)
3753         : ASTGEN_SUPER_Case(fl, exprp, casesp)
3754         , m_casex{casex} {}
ASTNODE_NODE_FUNCS(Case)3755     ASTNODE_NODE_FUNCS(Case)
3756     virtual string verilogKwd() const override {
3757         return casez() ? "casez" : casex() ? "casex" : "case";
3758     }
same(const AstNode * samep)3759     virtual bool same(const AstNode* samep) const override {
3760         return m_casex == static_cast<const AstCase*>(samep)->m_casex;
3761     }
casex()3762     bool casex() const { return m_casex == VCaseType::CT_CASEX; }
casez()3763     bool casez() const { return m_casex == VCaseType::CT_CASEZ; }
caseInside()3764     bool caseInside() const { return m_casex == VCaseType::CT_CASEINSIDE; }
caseSimple()3765     bool caseSimple() const { return m_casex == VCaseType::CT_CASE; }
caseInsideSet()3766     void caseInsideSet() { m_casex = VCaseType::CT_CASEINSIDE; }
fullPragma()3767     bool fullPragma() const { return m_fullPragma; }
fullPragma(bool flag)3768     void fullPragma(bool flag) { m_fullPragma = flag; }
parallelPragma()3769     bool parallelPragma() const { return m_parallelPragma; }
parallelPragma(bool flag)3770     void parallelPragma(bool flag) { m_parallelPragma = flag; }
uniquePragma()3771     bool uniquePragma() const { return m_uniquePragma; }
uniquePragma(bool flag)3772     void uniquePragma(bool flag) { m_uniquePragma = flag; }
unique0Pragma()3773     bool unique0Pragma() const { return m_unique0Pragma; }
unique0Pragma(bool flag)3774     void unique0Pragma(bool flag) { m_unique0Pragma = flag; }
priorityPragma()3775     bool priorityPragma() const { return m_priorityPragma; }
priorityPragma(bool flag)3776     void priorityPragma(bool flag) { m_priorityPragma = flag; }
3777 };
3778 
3779 class AstCaseItem final : public AstNode {
3780     // Single item of a case statement
3781     // Parents:  CASE
3782     // condsp Children: MATH  (Null condition used for default block)
3783     // bodysp Children: Statements
3784 public:
AstCaseItem(FileLine * fl,AstNode * condsp,AstNode * bodysp)3785     AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* bodysp)
3786         : ASTGEN_SUPER_CaseItem(fl) {
3787         addNOp1p(condsp);
3788         addNOp2p(bodysp);
3789     }
ASTNODE_NODE_FUNCS(CaseItem)3790     ASTNODE_NODE_FUNCS(CaseItem)
3791     virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
condsp()3792     AstNode* condsp() const { return op1p(); }  // op1 = list of possible matching expressions
bodysp()3793     AstNode* bodysp() const { return op2p(); }  // op2 = what to do
condsp(AstNode * nodep)3794     void condsp(AstNode* nodep) { setOp1p(nodep); }
addBodysp(AstNode * newp)3795     void addBodysp(AstNode* newp) { addOp2p(newp); }
isDefault()3796     bool isDefault() const { return condsp() == nullptr; }
3797 };
3798 
3799 class AstSFormatF final : public AstNode {
3800     // Convert format to string, generally under an AstDisplay or AstSFormat
3801     // Also used as "real" function for /*verilator sformat*/ functions
3802     string m_text;
3803     const bool m_hidden;  // Under display, etc
3804     bool m_hasFormat;  // Has format code
3805     const char m_missingArgChar;  // Format code when argument without format, 'h'/'o'/'b'
3806     VTimescale m_timeunit;  // Parent module time unit
3807 public:
3808     class NoFormat {};
3809     AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp,
3810                 char missingArgChar = 'd')
ASTGEN_SUPER_SFormatF(fl)3811         : ASTGEN_SUPER_SFormatF(fl)
3812         , m_text{text}
3813         , m_hidden{hidden}
3814         , m_hasFormat{true}
3815         , m_missingArgChar{missingArgChar} {
3816         dtypeSetString();
3817         addNOp1p(exprsp);
3818         addNOp2p(nullptr);
3819     }
3820     AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd',
3821                 bool hidden = true)
ASTGEN_SUPER_SFormatF(fl)3822         : ASTGEN_SUPER_SFormatF(fl)
3823         , m_text{""}
3824         , m_hidden{hidden}
3825         , m_hasFormat{false}
3826         , m_missingArgChar{missingArgChar} {
3827         dtypeSetString();
3828         addNOp1p(exprsp);
3829         addNOp2p(nullptr);
3830     }
ASTNODE_NODE_FUNCS(SFormatF)3831     ASTNODE_NODE_FUNCS(SFormatF)
3832     virtual string name() const override { return m_text; }
instrCount()3833     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
hasDType()3834     virtual bool hasDType() const override { return true; }
same(const AstNode * samep)3835     virtual bool same(const AstNode* samep) const override {
3836         return text() == static_cast<const AstSFormatF*>(samep)->text();
3837     }
verilogKwd()3838     virtual string verilogKwd() const override { return "$sformatf"; }
addExprsp(AstNode * nodep)3839     void addExprsp(AstNode* nodep) { addOp1p(nodep); }  // op1 = Expressions to output
exprsp()3840     AstNode* exprsp() const { return op1p(); }  // op1 = Expressions to output
text()3841     string text() const { return m_text; }  // * = Text to display
text(const string & text)3842     void text(const string& text) { m_text = text; }
scopeNamep()3843     AstScopeName* scopeNamep() const { return VN_AS(op2p(), ScopeName); }
scopeNamep(AstNode * nodep)3844     void scopeNamep(AstNode* nodep) { setNOp2p(nodep); }
formatScopeTracking()3845     bool formatScopeTracking() const {  // Track scopeNamep();  Ok if false positive
3846         return (name().find("%m") != string::npos || name().find("%M") != string::npos);
3847     }
hidden()3848     bool hidden() const { return m_hidden; }
hasFormat(bool flag)3849     void hasFormat(bool flag) { m_hasFormat = flag; }
hasFormat()3850     bool hasFormat() const { return m_hasFormat; }
missingArgChar()3851     char missingArgChar() const { return m_missingArgChar; }
timeunit(const VTimescale & flag)3852     void timeunit(const VTimescale& flag) { m_timeunit = flag; }
timeunit()3853     VTimescale timeunit() const { return m_timeunit; }
3854 };
3855 
3856 class AstDisplay final : public AstNodeStmt {
3857     // Parents: stmtlist
3858     // Children: file which must be a varref
3859     // Children: SFORMATF to generate print string
3860 private:
3861     AstDisplayType m_displayType;
3862 
3863 public:
3864     AstDisplay(FileLine* fl, AstDisplayType dispType, const string& text, AstNode* filep,
3865                AstNode* exprsp, char missingArgChar = 'd')
ASTGEN_SUPER_Display(fl)3866         : ASTGEN_SUPER_Display(fl) {
3867         setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar));
3868         setNOp3p(filep);
3869         m_displayType = dispType;
3870     }
3871     AstDisplay(FileLine* fl, AstDisplayType dispType, AstNode* filep, AstNode* exprsp,
3872                char missingArgChar = 'd')
ASTGEN_SUPER_Display(fl)3873         : ASTGEN_SUPER_Display(fl) {
3874         setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar));
3875         setNOp3p(filep);
3876         m_displayType = dispType;
3877     }
3878     ASTNODE_NODE_FUNCS(Display)
3879     virtual void dump(std::ostream& str) const override;
broken()3880     virtual const char* broken() const override {
3881         BROKEN_RTN(!fmtp());
3882         return nullptr;
3883     }
verilogKwd()3884     virtual string verilogKwd() const override {
3885         return (filep() ? string("$f") + string(displayType().ascii())
3886                         : string("$") + string(displayType().ascii()));
3887     }
isGateOptimizable()3888     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()3889     virtual bool isPredictOptimizable() const override { return false; }
isPure()3890     virtual bool isPure() const override {
3891         return false;
3892     }  // SPECIAL: $display has 'visual' ordering
isOutputter()3893     virtual bool isOutputter() const override { return true; }  // SPECIAL: $display makes output
isUnlikely()3894     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)3895     virtual bool same(const AstNode* samep) const override {
3896         return displayType() == static_cast<const AstDisplay*>(samep)->displayType();
3897     }
instrCount()3898     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
displayType()3899     AstDisplayType displayType() const { return m_displayType; }
displayType(AstDisplayType type)3900     void displayType(AstDisplayType type) { m_displayType = type; }
3901     // * = Add a newline for $display
addNewline()3902     bool addNewline() const { return displayType().addNewline(); }
fmtp(AstSFormatF * nodep)3903     void fmtp(AstSFormatF* nodep) { addOp1p(nodep); }  // op1 = To-String formatter
fmtp()3904     AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); }
filep()3905     AstNode* filep() const { return op3p(); }
filep(AstNodeVarRef * nodep)3906     void filep(AstNodeVarRef* nodep) { setNOp3p(nodep); }
3907 };
3908 
3909 class AstDumpCtl final : public AstNodeStmt {
3910     // $dumpon etc
3911     // Parents: expr
3912     // Child: expr based on type of control statement
3913     const VDumpCtlType m_ctlType;  // Type of operation
3914 public:
3915     AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = nullptr)
ASTGEN_SUPER_DumpCtl(fl)3916         : ASTGEN_SUPER_DumpCtl(fl)
3917         , m_ctlType{ctlType} {
3918         setNOp1p(exprp);
3919     }
ASTNODE_NODE_FUNCS(DumpCtl)3920     ASTNODE_NODE_FUNCS(DumpCtl)
3921     virtual string verilogKwd() const override { return ctlType().ascii(); }
isGateOptimizable()3922     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()3923     virtual bool isPredictOptimizable() const override { return false; }
isOutputter()3924     virtual bool isOutputter() const override { return true; }
cleanOut()3925     virtual bool cleanOut() const { return true; }
same(const AstNode * samep)3926     virtual bool same(const AstNode* samep) const override { return true; }
ctlType()3927     VDumpCtlType ctlType() const { return m_ctlType; }
exprp()3928     AstNode* exprp() const { return op1p(); }  // op2 = Expressions to output
exprp(AstNode * nodep)3929     void exprp(AstNode* nodep) { setOp1p(nodep); }
3930 };
3931 
3932 class AstElabDisplay final : public AstNode {
3933     // Parents: stmtlist
3934     // Children: SFORMATF to generate print string
3935 private:
3936     AstDisplayType m_displayType;
3937 
3938 public:
AstElabDisplay(FileLine * fl,AstDisplayType dispType,AstNode * exprsp)3939     AstElabDisplay(FileLine* fl, AstDisplayType dispType, AstNode* exprsp)
3940         : ASTGEN_SUPER_ElabDisplay(fl) {
3941         setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp));
3942         m_displayType = dispType;
3943     }
ASTNODE_NODE_FUNCS(ElabDisplay)3944     ASTNODE_NODE_FUNCS(ElabDisplay)
3945     virtual const char* broken() const override {
3946         BROKEN_RTN(!fmtp());
3947         return nullptr;
3948     }
verilogKwd()3949     virtual string verilogKwd() const override {
3950         return (string("$") + string(displayType().ascii()));
3951     }
isGateOptimizable()3952     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()3953     virtual bool isPredictOptimizable() const override { return false; }
isPure()3954     virtual bool isPure() const override {
3955         return false;
3956     }  // SPECIAL: $display has 'visual' ordering
isOutputter()3957     virtual bool isOutputter() const override { return true; }  // SPECIAL: $display makes output
isUnlikely()3958     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)3959     virtual bool same(const AstNode* samep) const override {
3960         return displayType() == static_cast<const AstElabDisplay*>(samep)->displayType();
3961     }
instrCount()3962     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
displayType()3963     AstDisplayType displayType() const { return m_displayType; }
displayType(AstDisplayType type)3964     void displayType(AstDisplayType type) { m_displayType = type; }
fmtp(AstSFormatF * nodep)3965     void fmtp(AstSFormatF* nodep) { addOp1p(nodep); }  // op1 = To-String formatter
fmtp()3966     AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); }
3967 };
3968 
3969 class AstSFormat final : public AstNodeStmt {
3970     // Parents: statement container
3971     // Children: string to load
3972     // Children: SFORMATF to generate print string
3973 public:
3974     AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp,
3975                char missingArgChar = 'd')
ASTGEN_SUPER_SFormat(fl)3976         : ASTGEN_SUPER_SFormat(fl) {
3977         setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar));
3978         setOp3p(lhsp);
3979     }
3980     AstSFormat(FileLine* fl, AstNode* lhsp, AstNode* exprsp, char missingArgChar = 'd')
ASTGEN_SUPER_SFormat(fl)3981         : ASTGEN_SUPER_SFormat(fl) {
3982         setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar));
3983         setOp3p(lhsp);
3984     }
ASTNODE_NODE_FUNCS(SFormat)3985     ASTNODE_NODE_FUNCS(SFormat)
3986     virtual const char* broken() const override {
3987         BROKEN_RTN(!fmtp());
3988         return nullptr;
3989     }
verilogKwd()3990     virtual string verilogKwd() const override { return "$sformat"; }
isGateOptimizable()3991     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()3992     virtual bool isPredictOptimizable() const override { return true; }
isPure()3993     virtual bool isPure() const override { return true; }
isOutputter()3994     virtual bool isOutputter() const override { return false; }
cleanOut()3995     virtual bool cleanOut() const { return false; }
instrCount()3996     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
same(const AstNode * samep)3997     virtual bool same(const AstNode* samep) const override { return true; }
fmtp(AstSFormatF * nodep)3998     void fmtp(AstSFormatF* nodep) { addOp1p(nodep); }  // op1 = To-String formatter
fmtp()3999     AstSFormatF* fmtp() const { return VN_AS(op1p(), SFormatF); }
lhsp()4000     AstNode* lhsp() const { return op3p(); }
lhsp(AstNode * nodep)4001     void lhsp(AstNode* nodep) { setOp3p(nodep); }
4002 };
4003 
4004 class AstSysFuncAsTask final : public AstNodeStmt {
4005     // Call what is normally a system function (with a return) in a non-return context
4006     // Parents: stmtlist
4007     // Children: a system function
4008 public:
AstSysFuncAsTask(FileLine * fl,AstNode * exprsp)4009     AstSysFuncAsTask(FileLine* fl, AstNode* exprsp)
4010         : ASTGEN_SUPER_SysFuncAsTask(fl) {
4011         addNOp1p(exprsp);
4012     }
ASTNODE_NODE_FUNCS(SysFuncAsTask)4013     ASTNODE_NODE_FUNCS(SysFuncAsTask)
4014     virtual string verilogKwd() const override { return ""; }
isGateOptimizable()4015     virtual bool isGateOptimizable() const override { return true; }
isPredictOptimizable()4016     virtual bool isPredictOptimizable() const override { return true; }
isPure()4017     virtual bool isPure() const override { return true; }
isOutputter()4018     virtual bool isOutputter() const override { return false; }
instrCount()4019     virtual int instrCount() const override { return 0; }
same(const AstNode * samep)4020     virtual bool same(const AstNode* samep) const override { return true; }
lhsp()4021     AstNode* lhsp() const { return op1p(); }  // op1 = Expressions to eval
lhsp(AstNode * nodep)4022     void lhsp(AstNode* nodep) { addOp1p(nodep); }  // op1 = Expressions to eval
4023 };
4024 
4025 class AstSysIgnore final : public AstNodeStmt {
4026     // Parents: stmtlist
4027     // Children: varrefs or exprs
4028 public:
AstSysIgnore(FileLine * fl,AstNode * exprsp)4029     AstSysIgnore(FileLine* fl, AstNode* exprsp)
4030         : ASTGEN_SUPER_SysIgnore(fl) {
4031         addNOp1p(exprsp);
4032     }
ASTNODE_NODE_FUNCS(SysIgnore)4033     ASTNODE_NODE_FUNCS(SysIgnore)
4034     virtual string verilogKwd() const override { return "$ignored"; }
isGateOptimizable()4035     virtual bool isGateOptimizable() const override { return false; }  // Though deleted before opt
isPredictOptimizable()4036     virtual bool isPredictOptimizable() const override {
4037         return false;
4038     }  // Though deleted before opt
isPure()4039     virtual bool isPure() const override { return false; }  // Though deleted before opt
isOutputter()4040     virtual bool isOutputter() const override { return true; }  // Though deleted before opt
instrCount()4041     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
exprsp()4042     AstNode* exprsp() const { return op1p(); }  // op1 = Expressions to output
exprsp(AstNode * nodep)4043     void exprsp(AstNode* nodep) { addOp1p(nodep); }  // op1 = Expressions to output
4044 };
4045 
4046 class AstFClose final : public AstNodeStmt {
4047     // Parents: stmtlist
4048     // Children: file which must be a varref
4049 public:
AstFClose(FileLine * fl,AstNode * filep)4050     AstFClose(FileLine* fl, AstNode* filep)
4051         : ASTGEN_SUPER_FClose(fl) {
4052         setNOp2p(filep);
4053     }
ASTNODE_NODE_FUNCS(FClose)4054     ASTNODE_NODE_FUNCS(FClose)
4055     virtual string verilogKwd() const override { return "$fclose"; }
isGateOptimizable()4056     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4057     virtual bool isPredictOptimizable() const override { return false; }
isPure()4058     virtual bool isPure() const override { return false; }
isOutputter()4059     virtual bool isOutputter() const override { return true; }
isUnlikely()4060     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)4061     virtual bool same(const AstNode* samep) const override { return true; }
filep()4062     AstNode* filep() const { return op2p(); }
filep(AstNodeVarRef * nodep)4063     void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
4064 };
4065 
4066 class AstFOpen final : public AstNodeStmt {
4067     // Although a system function in IEEE, here a statement which sets the file pointer (MCD)
4068 public:
AstFOpen(FileLine * fl,AstNode * filep,AstNode * filenamep,AstNode * modep)4069     AstFOpen(FileLine* fl, AstNode* filep, AstNode* filenamep, AstNode* modep)
4070         : ASTGEN_SUPER_FOpen(fl) {
4071         setOp1p(filep);
4072         setOp2p(filenamep);
4073         setOp3p(modep);
4074     }
ASTNODE_NODE_FUNCS(FOpen)4075     ASTNODE_NODE_FUNCS(FOpen)
4076     virtual string verilogKwd() const override { return "$fopen"; }
isGateOptimizable()4077     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4078     virtual bool isPredictOptimizable() const override { return false; }
isPure()4079     virtual bool isPure() const override { return false; }
isOutputter()4080     virtual bool isOutputter() const override { return true; }
isUnlikely()4081     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)4082     virtual bool same(const AstNode* samep) const override { return true; }
filep()4083     AstNode* filep() const { return op1p(); }
filenamep()4084     AstNode* filenamep() const { return op2p(); }
modep()4085     AstNode* modep() const { return op3p(); }
4086 };
4087 
4088 class AstFOpenMcd final : public AstNodeStmt {
4089     // Although a system function in IEEE, here a statement which sets the file pointer (MCD)
4090 public:
AstFOpenMcd(FileLine * fl,AstNode * filep,AstNode * filenamep)4091     AstFOpenMcd(FileLine* fl, AstNode* filep, AstNode* filenamep)
4092         : ASTGEN_SUPER_FOpenMcd(fl) {
4093         setOp1p(filep);
4094         setOp2p(filenamep);
4095     }
ASTNODE_NODE_FUNCS(FOpenMcd)4096     ASTNODE_NODE_FUNCS(FOpenMcd)
4097     virtual string verilogKwd() const override { return "$fopen"; }
isGateOptimizable()4098     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4099     virtual bool isPredictOptimizable() const override { return false; }
isPure()4100     virtual bool isPure() const override { return false; }
isOutputter()4101     virtual bool isOutputter() const override { return true; }
isUnlikely()4102     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)4103     virtual bool same(const AstNode* samep) const override { return true; }
filep()4104     AstNode* filep() const { return op1p(); }
filenamep()4105     AstNode* filenamep() const { return op2p(); }
4106 };
4107 
4108 class AstFFlush final : public AstNodeStmt {
4109     // Parents: stmtlist
4110     // Children: file which must be a varref
4111 public:
AstFFlush(FileLine * fl,AstNode * filep)4112     AstFFlush(FileLine* fl, AstNode* filep)
4113         : ASTGEN_SUPER_FFlush(fl) {
4114         setNOp2p(filep);
4115     }
ASTNODE_NODE_FUNCS(FFlush)4116     ASTNODE_NODE_FUNCS(FFlush)
4117     virtual string verilogKwd() const override { return "$fflush"; }
isGateOptimizable()4118     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4119     virtual bool isPredictOptimizable() const override { return false; }
isPure()4120     virtual bool isPure() const override { return false; }
isOutputter()4121     virtual bool isOutputter() const override { return true; }
isUnlikely()4122     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)4123     virtual bool same(const AstNode* samep) const override { return true; }
filep()4124     AstNode* filep() const { return op2p(); }
filep(AstNodeVarRef * nodep)4125     void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
4126 };
4127 
4128 class AstFRead final : public AstNodeMath {
4129     // Parents: expr
4130     // Children: varrefs to load
4131     // Children: file which must be a varref
4132     // Children: low index
4133     // Children: count
4134 public:
AstFRead(FileLine * fl,AstNode * memp,AstNode * filep,AstNode * startp,AstNode * countp)4135     AstFRead(FileLine* fl, AstNode* memp, AstNode* filep, AstNode* startp, AstNode* countp)
4136         : ASTGEN_SUPER_FRead(fl) {
4137         setOp1p(memp);
4138         setOp2p(filep);
4139         setNOp3p(startp);
4140         setNOp4p(countp);
4141     }
ASTNODE_NODE_FUNCS(FRead)4142     ASTNODE_NODE_FUNCS(FRead)
4143     virtual string verilogKwd() const override { return "$fread"; }
emitVerilog()4144     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()4145     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4146     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4147     virtual bool isPredictOptimizable() const override { return false; }
isPure()4148     virtual bool isPure() const override { return false; }  // SPECIAL: has 'visual' ordering
isOutputter()4149     virtual bool isOutputter() const override { return true; }  // SPECIAL: makes output
cleanOut()4150     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)4151     virtual bool same(const AstNode* samep) const override { return true; }
memp()4152     AstNode* memp() const { return op1p(); }
memp(AstNode * nodep)4153     void memp(AstNode* nodep) { setOp1p(nodep); }
filep()4154     AstNode* filep() const { return op2p(); }
filep(AstNode * nodep)4155     void filep(AstNode* nodep) { setOp2p(nodep); }
startp()4156     AstNode* startp() const { return op3p(); }
startp(AstNode * nodep)4157     void startp(AstNode* nodep) { setNOp3p(nodep); }
countp()4158     AstNode* countp() const { return op4p(); }
countp(AstNode * nodep)4159     void countp(AstNode* nodep) { setNOp4p(nodep); }
4160 };
4161 
4162 class AstFRewind final : public AstNodeMath {
4163     // Parents: stmtlist
4164     // Children: file which must be a varref
4165 public:
AstFRewind(FileLine * fl,AstNode * filep)4166     AstFRewind(FileLine* fl, AstNode* filep)
4167         : ASTGEN_SUPER_FRewind(fl) {
4168         setNOp2p(filep);
4169     }
ASTNODE_NODE_FUNCS(FRewind)4170     ASTNODE_NODE_FUNCS(FRewind)
4171     virtual string verilogKwd() const override { return "$frewind"; }
emitVerilog()4172     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()4173     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4174     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4175     virtual bool isPredictOptimizable() const override { return false; }
isPure()4176     virtual bool isPure() const override { return false; }
isOutputter()4177     virtual bool isOutputter() const override { return true; }
isUnlikely()4178     virtual bool isUnlikely() const override { return true; }
cleanOut()4179     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)4180     virtual bool same(const AstNode* samep) const override { return true; }
filep()4181     AstNode* filep() const { return op2p(); }
filep(AstNodeVarRef * nodep)4182     void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
4183 };
4184 
4185 class AstFTell final : public AstNodeMath {
4186     // Parents: stmtlist
4187     // Children: file which must be a varref
4188 public:
AstFTell(FileLine * fl,AstNode * filep)4189     AstFTell(FileLine* fl, AstNode* filep)
4190         : ASTGEN_SUPER_FTell(fl) {
4191         setNOp2p(filep);
4192     }
ASTNODE_NODE_FUNCS(FTell)4193     ASTNODE_NODE_FUNCS(FTell)
4194     virtual string verilogKwd() const override { return "$ftell"; }
emitVerilog()4195     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()4196     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4197     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4198     virtual bool isPredictOptimizable() const override { return false; }
isPure()4199     virtual bool isPure() const override { return false; }
isOutputter()4200     virtual bool isOutputter() const override { return true; }
isUnlikely()4201     virtual bool isUnlikely() const override { return true; }
cleanOut()4202     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)4203     virtual bool same(const AstNode* samep) const override { return true; }
filep()4204     AstNode* filep() const { return op2p(); }
filep(AstNodeVarRef * nodep)4205     void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
4206 };
4207 
4208 class AstFSeek final : public AstNodeMath {
4209     // Parents: expr
4210     // Children: file which must be a varref
4211     // Children: offset
4212     // Children: operation
4213 public:
AstFSeek(FileLine * fl,AstNode * filep,AstNode * offset,AstNode * operation)4214     AstFSeek(FileLine* fl, AstNode* filep, AstNode* offset, AstNode* operation)
4215         : ASTGEN_SUPER_FSeek(fl) {
4216         setOp2p(filep);
4217         setNOp3p(offset);
4218         setNOp4p(operation);
4219     }
ASTNODE_NODE_FUNCS(FSeek)4220     ASTNODE_NODE_FUNCS(FSeek)
4221     virtual string verilogKwd() const override { return "$fseek"; }
emitVerilog()4222     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()4223     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4224     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4225     virtual bool isPredictOptimizable() const override { return false; }
isPure()4226     virtual bool isPure() const override { return false; }  // SPECIAL: has 'visual' ordering
isOutputter()4227     virtual bool isOutputter() const override { return true; }  // SPECIAL: makes output
cleanOut()4228     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)4229     virtual bool same(const AstNode* samep) const override { return true; }
filep()4230     AstNode* filep() const { return op2p(); }
filep(AstNode * nodep)4231     void filep(AstNode* nodep) { setOp2p(nodep); }
offset()4232     AstNode* offset() const { return op3p(); }
offset(AstNode * nodep)4233     void offset(AstNode* nodep) { setNOp3p(nodep); }
operation()4234     AstNode* operation() const { return op4p(); }
operation(AstNode * nodep)4235     void operation(AstNode* nodep) { setNOp4p(nodep); }
4236 };
4237 
4238 class AstFScanF final : public AstNodeMath {
4239     // Parents: expr
4240     // Children: file which must be a varref
4241     // Children: varrefs to load
4242 private:
4243     string m_text;
4244 
4245 public:
AstFScanF(FileLine * fl,const string & text,AstNode * filep,AstNode * exprsp)4246     AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp)
4247         : ASTGEN_SUPER_FScanF(fl)
4248         , m_text{text} {
4249         addNOp1p(exprsp);
4250         setNOp2p(filep);
4251     }
ASTNODE_NODE_FUNCS(FScanF)4252     ASTNODE_NODE_FUNCS(FScanF)
4253     virtual string name() const override { return m_text; }
verilogKwd()4254     virtual string verilogKwd() const override { return "$fscanf"; }
emitVerilog()4255     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()4256     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4257     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4258     virtual bool isPredictOptimizable() const override { return false; }
isPure()4259     virtual bool isPure() const override { return false; }  // SPECIAL: has 'visual' ordering
isOutputter()4260     virtual bool isOutputter() const override { return true; }  // SPECIAL: makes output
cleanOut()4261     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)4262     virtual bool same(const AstNode* samep) const override {
4263         return text() == static_cast<const AstFScanF*>(samep)->text();
4264     }
exprsp()4265     AstNode* exprsp() const { return op1p(); }  // op1 = Expressions to output
exprsp(AstNode * nodep)4266     void exprsp(AstNode* nodep) { addOp1p(nodep); }  // op1 = Expressions to output
text()4267     string text() const { return m_text; }  // * = Text to display
text(const string & text)4268     void text(const string& text) { m_text = text; }
filep()4269     AstNode* filep() const { return op2p(); }
filep(AstNodeVarRef * nodep)4270     void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); }
4271 };
4272 
4273 class AstSScanF final : public AstNodeMath {
4274     // Parents: expr
4275     // Children: file which must be a varref
4276     // Children: varrefs to load
4277 private:
4278     string m_text;
4279 
4280 public:
AstSScanF(FileLine * fl,const string & text,AstNode * fromp,AstNode * exprsp)4281     AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp)
4282         : ASTGEN_SUPER_SScanF(fl)
4283         , m_text{text} {
4284         addNOp1p(exprsp);
4285         setOp2p(fromp);
4286     }
ASTNODE_NODE_FUNCS(SScanF)4287     ASTNODE_NODE_FUNCS(SScanF)
4288     virtual string name() const override { return m_text; }
verilogKwd()4289     virtual string verilogKwd() const override { return "$sscanf"; }
emitVerilog()4290     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()4291     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4292     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4293     virtual bool isPredictOptimizable() const override { return false; }
isPure()4294     virtual bool isPure() const override { return false; }  // SPECIAL: has 'visual' ordering
isOutputter()4295     virtual bool isOutputter() const override { return true; }  // SPECIAL: makes output
cleanOut()4296     virtual bool cleanOut() const override { return false; }
same(const AstNode * samep)4297     virtual bool same(const AstNode* samep) const override {
4298         return text() == static_cast<const AstSScanF*>(samep)->text();
4299     }
exprsp()4300     AstNode* exprsp() const { return op1p(); }  // op1 = Expressions to output
exprsp(AstNode * nodep)4301     void exprsp(AstNode* nodep) { addOp1p(nodep); }  // op1 = Expressions to output
text()4302     string text() const { return m_text; }  // * = Text to display
text(const string & text)4303     void text(const string& text) { m_text = text; }
fromp()4304     AstNode* fromp() const { return op2p(); }
fromp(AstNode * nodep)4305     void fromp(AstNode* nodep) { setOp2p(nodep); }
4306 };
4307 
4308 class AstNodeReadWriteMem VL_NOT_FINAL : public AstNodeStmt {
4309 private:
4310     const bool m_isHex;  // readmemh, not readmemb
4311 public:
AstNodeReadWriteMem(AstType t,FileLine * fl,bool hex,AstNode * filenamep,AstNode * memp,AstNode * lsbp,AstNode * msbp)4312     AstNodeReadWriteMem(AstType t, FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp,
4313                         AstNode* lsbp, AstNode* msbp)
4314         : AstNodeStmt(t, fl)
4315         , m_isHex(hex) {
4316         setOp1p(filenamep);
4317         setOp2p(memp);
4318         setNOp3p(lsbp);
4319         setNOp4p(msbp);
4320     }
isGateOptimizable()4321     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4322     virtual bool isPredictOptimizable() const override { return false; }
isPure()4323     virtual bool isPure() const override { return false; }
isOutputter()4324     virtual bool isOutputter() const override { return true; }
isUnlikely()4325     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)4326     virtual bool same(const AstNode* samep) const override {
4327         return isHex() == static_cast<const AstNodeReadWriteMem*>(samep)->isHex();
4328     }
isHex()4329     bool isHex() const { return m_isHex; }
filenamep()4330     AstNode* filenamep() const { return op1p(); }
memp()4331     AstNode* memp() const { return op2p(); }
lsbp()4332     AstNode* lsbp() const { return op3p(); }
msbp()4333     AstNode* msbp() const { return op4p(); }
4334     virtual const char* cFuncPrefixp() const = 0;
4335 };
4336 
4337 class AstReadMem final : public AstNodeReadWriteMem {
4338 public:
AstReadMem(FileLine * fl,bool hex,AstNode * filenamep,AstNode * memp,AstNode * lsbp,AstNode * msbp)4339     AstReadMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp,
4340                AstNode* msbp)
4341         : ASTGEN_SUPER_ReadMem(fl, hex, filenamep, memp, lsbp, msbp) {}
4342     ASTNODE_NODE_FUNCS(ReadMem);
verilogKwd()4343     virtual string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); }
cFuncPrefixp()4344     virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; }
4345 };
4346 
4347 class AstWriteMem final : public AstNodeReadWriteMem {
4348 public:
AstWriteMem(FileLine * fl,bool hex,AstNode * filenamep,AstNode * memp,AstNode * lsbp,AstNode * msbp)4349     AstWriteMem(FileLine* fl, bool hex, AstNode* filenamep, AstNode* memp, AstNode* lsbp,
4350                 AstNode* msbp)
4351         : ASTGEN_SUPER_WriteMem(fl, hex, filenamep, memp, lsbp, msbp) {}
ASTNODE_NODE_FUNCS(WriteMem)4352     ASTNODE_NODE_FUNCS(WriteMem)
4353     virtual string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); }
cFuncPrefixp()4354     virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; }
4355 };
4356 
4357 class AstMonitorOff final : public AstNodeStmt {
4358     const bool m_off;  // Monitor off.  Using 0=on allows faster init and comparison
4359 
4360 public:
AstMonitorOff(FileLine * fl,bool off)4361     AstMonitorOff(FileLine* fl, bool off)
4362         : ASTGEN_SUPER_MonitorOff(fl)
4363         , m_off{off} {}
ASTNODE_NODE_FUNCS(MonitorOff)4364     ASTNODE_NODE_FUNCS(MonitorOff)
4365     virtual string verilogKwd() const override { return m_off ? "$monitoroff" : "$monitoron"; }
isGateOptimizable()4366     virtual bool isGateOptimizable() const override { return false; }  // Though deleted before opt
isPredictOptimizable()4367     virtual bool isPredictOptimizable() const override {
4368         return false;
4369     }  // Though deleted before opt
isPure()4370     virtual bool isPure() const override { return false; }  // Though deleted before opt
isOutputter()4371     virtual bool isOutputter() const override { return true; }  // Though deleted before opt
instrCount()4372     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
same(const AstNode * samep)4373     virtual bool same(const AstNode* samep) const override {
4374         return m_off == static_cast<const AstMonitorOff*>(samep)->m_off;
4375     }
off()4376     bool off() const { return m_off; }
4377 };
4378 
4379 class AstSystemT final : public AstNodeStmt {
4380     // $system used as task
4381 public:
AstSystemT(FileLine * fl,AstNode * lhsp)4382     AstSystemT(FileLine* fl, AstNode* lhsp)
4383         : ASTGEN_SUPER_SystemT(fl) {
4384         setOp1p(lhsp);
4385     }
ASTNODE_NODE_FUNCS(SystemT)4386     ASTNODE_NODE_FUNCS(SystemT)
4387     virtual string verilogKwd() const override { return "$system"; }
isGateOptimizable()4388     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4389     virtual bool isPredictOptimizable() const override { return false; }
isPure()4390     virtual bool isPure() const override { return false; }
isOutputter()4391     virtual bool isOutputter() const override { return true; }
isUnlikely()4392     virtual bool isUnlikely() const override { return true; }
same(const AstNode * samep)4393     virtual bool same(const AstNode* samep) const override { return true; }
lhsp()4394     AstNode* lhsp() const { return op1p(); }
4395 };
4396 
4397 class AstSystemF final : public AstNodeMath {
4398     // $system used as function
4399 public:
AstSystemF(FileLine * fl,AstNode * lhsp)4400     AstSystemF(FileLine* fl, AstNode* lhsp)
4401         : ASTGEN_SUPER_SystemF(fl) {
4402         setOp1p(lhsp);
4403     }
ASTNODE_NODE_FUNCS(SystemF)4404     ASTNODE_NODE_FUNCS(SystemF)
4405     virtual string verilogKwd() const override { return "$system"; }
emitVerilog()4406     virtual string emitVerilog() override { return verilogKwd(); }
emitC()4407     virtual string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; }
isGateOptimizable()4408     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4409     virtual bool isPredictOptimizable() const override { return false; }
isPure()4410     virtual bool isPure() const override { return false; }
isOutputter()4411     virtual bool isOutputter() const override { return true; }
isUnlikely()4412     virtual bool isUnlikely() const override { return true; }
cleanOut()4413     virtual bool cleanOut() const override { return true; }
same(const AstNode * samep)4414     virtual bool same(const AstNode* samep) const override { return true; }
lhsp()4415     AstNode* lhsp() const { return op1p(); }
4416 };
4417 
4418 class AstValuePlusArgs final : public AstNodeMath {
4419     // Parents: expr
4420     // Child: variable to set.  If nullptr then this is a $test$plusargs instead of $value$plusargs
4421 public:
AstValuePlusArgs(FileLine * fl,AstNode * searchp,AstNode * outp)4422     AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp)
4423         : ASTGEN_SUPER_ValuePlusArgs(fl) {
4424         setOp1p(searchp);
4425         setOp2p(outp);
4426     }
ASTNODE_NODE_FUNCS(ValuePlusArgs)4427     ASTNODE_NODE_FUNCS(ValuePlusArgs)
4428     virtual string verilogKwd() const override { return "$value$plusargs"; }
emitVerilog()4429     virtual string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; }
emitC()4430     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
isGateOptimizable()4431     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4432     virtual bool isPredictOptimizable() const override { return false; }
isPure()4433     virtual bool isPure() const override { return !outp(); }
cleanOut()4434     virtual bool cleanOut() const override { return true; }
same(const AstNode * samep)4435     virtual bool same(const AstNode* samep) const override { return true; }
searchp()4436     AstNode* searchp() const { return op1p(); }  // op1 = Search expression
searchp(AstNode * nodep)4437     void searchp(AstNode* nodep) { setOp1p(nodep); }
outp()4438     AstNode* outp() const { return op2p(); }  // op2 = Expressions to output
outp(AstNode * nodep)4439     void outp(AstNode* nodep) { setOp2p(nodep); }
4440 };
4441 
4442 class AstTestPlusArgs final : public AstNodeMath {
4443     // Parents: expr
4444     // Child: variable to set.  If nullptr then this is a $test$plusargs instead of $value$plusargs
4445 private:
4446     string m_text;
4447 
4448 public:
AstTestPlusArgs(FileLine * fl,const string & text)4449     AstTestPlusArgs(FileLine* fl, const string& text)
4450         : ASTGEN_SUPER_TestPlusArgs(fl)
4451         , m_text{text} {}
ASTNODE_NODE_FUNCS(TestPlusArgs)4452     ASTNODE_NODE_FUNCS(TestPlusArgs)
4453     virtual string name() const override { return m_text; }
verilogKwd()4454     virtual string verilogKwd() const override { return "$test$plusargs"; }
emitVerilog()4455     virtual string emitVerilog() override { return verilogKwd(); }
emitC()4456     virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; }
isGateOptimizable()4457     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4458     virtual bool isPredictOptimizable() const override { return false; }
cleanOut()4459     virtual bool cleanOut() const override { return true; }
same(const AstNode * samep)4460     virtual bool same(const AstNode* samep) const override {
4461         return text() == static_cast<const AstTestPlusArgs*>(samep)->text();
4462     }
text()4463     string text() const { return m_text; }  // * = Text to display
text(const string & text)4464     void text(const string& text) { m_text = text; }
4465 };
4466 
4467 class AstGenFor final : public AstNodeFor {
4468 public:
AstGenFor(FileLine * fl,AstNode * initsp,AstNode * condp,AstNode * incsp,AstNode * bodysp)4469     AstGenFor(FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp)
4470         : ASTGEN_SUPER_GenFor(fl, initsp, condp, incsp, bodysp) {}
4471     ASTNODE_NODE_FUNCS(GenFor)
4472 };
4473 
4474 class AstForeach final : public AstNodeStmt {
4475 public:
AstForeach(FileLine * fl,AstNode * arrayp,AstNode * bodysp)4476     AstForeach(FileLine* fl, AstNode* arrayp, AstNode* bodysp)
4477         : ASTGEN_SUPER_Foreach(fl) {
4478         setOp1p(arrayp);
4479         addNOp4p(bodysp);
4480     }
ASTNODE_NODE_FUNCS(Foreach)4481     ASTNODE_NODE_FUNCS(Foreach)
4482     AstNode* arrayp() const { return op1p(); }  // op1 = array and index vars
bodysp()4483     AstNode* bodysp() const { return op4p(); }  // op4 = body of loop
isGateOptimizable()4484     virtual bool isGateOptimizable() const override { return false; }
instrCount()4485     virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
same(const AstNode * samep)4486     virtual bool same(const AstNode* samep) const override { return true; }
4487 };
4488 
4489 class AstRepeat final : public AstNodeStmt {
4490 public:
AstRepeat(FileLine * fl,AstNode * countp,AstNode * bodysp)4491     AstRepeat(FileLine* fl, AstNode* countp, AstNode* bodysp)
4492         : ASTGEN_SUPER_Repeat(fl) {
4493         setOp2p(countp);
4494         addNOp3p(bodysp);
4495     }
ASTNODE_NODE_FUNCS(Repeat)4496     ASTNODE_NODE_FUNCS(Repeat)
4497     AstNode* countp() const { return op2p(); }  // op2 = condition to continue
bodysp()4498     AstNode* bodysp() const { return op3p(); }  // op3 = body of loop
isGateOptimizable()4499     virtual bool isGateOptimizable() const override {
4500         return false;
4501     }  // Not relevant - converted to FOR
instrCount()4502     virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
same(const AstNode * samep)4503     virtual bool same(const AstNode* samep) const override { return true; }
4504 };
4505 
4506 class AstWait final : public AstNodeStmt {
4507 public:
AstWait(FileLine * fl,AstNode * condp,AstNode * bodysp)4508     AstWait(FileLine* fl, AstNode* condp, AstNode* bodysp)
4509         : ASTGEN_SUPER_Wait(fl) {
4510         setOp2p(condp);
4511         addNOp3p(bodysp);
4512     }
ASTNODE_NODE_FUNCS(Wait)4513     ASTNODE_NODE_FUNCS(Wait)
4514     AstNode* bodysp() const { return op3p(); }  // op3 = body of loop
4515 };
4516 
4517 class AstWhile final : public AstNodeStmt {
4518 public:
4519     AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp = nullptr)
ASTGEN_SUPER_While(fl)4520         : ASTGEN_SUPER_While(fl) {
4521         setOp2p(condp);
4522         addNOp3p(bodysp);
4523         addNOp4p(incsp);
4524     }
ASTNODE_NODE_FUNCS(While)4525     ASTNODE_NODE_FUNCS(While)
4526     // op1 = prepare statements for condition (exec every loop)
4527     AstNode* precondsp() const { return op1p(); }
condp()4528     AstNode* condp() const { return op2p(); }  // op2 = condition to continue
bodysp()4529     AstNode* bodysp() const { return op3p(); }  // op3 = body of loop
incsp()4530     AstNode* incsp() const { return op4p(); }  // op4 = increment (if from a FOR loop)
addPrecondsp(AstNode * newp)4531     void addPrecondsp(AstNode* newp) { addOp1p(newp); }
addBodysp(AstNode * newp)4532     void addBodysp(AstNode* newp) { addOp3p(newp); }
addIncsp(AstNode * newp)4533     void addIncsp(AstNode* newp) { addOp4p(newp); }
isGateOptimizable()4534     virtual bool isGateOptimizable() const override { return false; }
instrCount()4535     virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
same(const AstNode * samep)4536     virtual bool same(const AstNode* samep) const override { return true; }
4537     // Stop statement searchback here
4538     virtual void addBeforeStmt(AstNode* newp, AstNode* belowp) override;
4539     // Stop statement searchback here
4540     virtual void addNextStmt(AstNode* newp, AstNode* belowp) override;
4541 };
4542 
4543 class AstBreak final : public AstNodeStmt {
4544 public:
AstBreak(FileLine * fl)4545     explicit AstBreak(FileLine* fl)
4546         : ASTGEN_SUPER_Break(fl) {}
ASTNODE_NODE_FUNCS(Break)4547     ASTNODE_NODE_FUNCS(Break)
4548     virtual string verilogKwd() const override { return "break"; }
isBrancher()4549     virtual bool isBrancher() const override {
4550         return true;  // SPECIAL: We don't process code after breaks
4551     }
4552 };
4553 
4554 class AstContinue final : public AstNodeStmt {
4555 public:
AstContinue(FileLine * fl)4556     explicit AstContinue(FileLine* fl)
4557         : ASTGEN_SUPER_Continue(fl) {}
ASTNODE_NODE_FUNCS(Continue)4558     ASTNODE_NODE_FUNCS(Continue)
4559     virtual string verilogKwd() const override { return "continue"; }
isBrancher()4560     virtual bool isBrancher() const override {
4561         return true;  // SPECIAL: We don't process code after breaks
4562     }
4563 };
4564 
4565 class AstDisable final : public AstNodeStmt {
4566 private:
4567     string m_name;  // Name of block
4568 public:
AstDisable(FileLine * fl,const string & name)4569     AstDisable(FileLine* fl, const string& name)
4570         : ASTGEN_SUPER_Disable(fl)
4571         , m_name{name} {}
ASTNODE_NODE_FUNCS(Disable)4572     ASTNODE_NODE_FUNCS(Disable)
4573     virtual string name() const override { return m_name; }  // * = Block name
name(const string & flag)4574     virtual void name(const string& flag) override { m_name = flag; }
isBrancher()4575     virtual bool isBrancher() const override {
4576         return true;  // SPECIAL: We don't process code after breaks
4577     }
4578 };
4579 
4580 class AstDisableFork final : public AstNodeStmt {
4581     // A "disable fork" statement
4582 public:
AstDisableFork(FileLine * fl)4583     explicit AstDisableFork(FileLine* fl)
4584         : ASTGEN_SUPER_DisableFork(fl) {}
4585     ASTNODE_NODE_FUNCS(DisableFork)
4586 };
4587 
4588 class AstWaitFork final : public AstNodeStmt {
4589     // A "wait fork" statement
4590 public:
AstWaitFork(FileLine * fl)4591     explicit AstWaitFork(FileLine* fl)
4592         : ASTGEN_SUPER_WaitFork(fl) {}
4593     ASTNODE_NODE_FUNCS(WaitFork)
4594 };
4595 
4596 class AstReturn final : public AstNodeStmt {
4597 public:
4598     explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr)
ASTGEN_SUPER_Return(fl)4599         : ASTGEN_SUPER_Return(fl) {
4600         setNOp1p(lhsp);
4601     }
ASTNODE_NODE_FUNCS(Return)4602     ASTNODE_NODE_FUNCS(Return)
4603     virtual string verilogKwd() const override { return "return"; }
lhsp()4604     AstNode* lhsp() const { return op1p(); }
isBrancher()4605     virtual bool isBrancher() const override {
4606         return true;  // SPECIAL: We don't process code after breaks
4607     }
4608 };
4609 
4610 class AstGenIf final : public AstNodeIf {
4611 public:
AstGenIf(FileLine * fl,AstNode * condp,AstNode * ifsp,AstNode * elsesp)4612     AstGenIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
4613         : ASTGEN_SUPER_GenIf(fl, condp, ifsp, elsesp) {}
4614     ASTNODE_NODE_FUNCS(GenIf)
4615 };
4616 
4617 class AstIf final : public AstNodeIf {
4618 private:
4619     bool m_uniquePragma;  // unique case
4620     bool m_unique0Pragma;  // unique0 case
4621     bool m_priorityPragma;  // priority case
4622 public:
4623     AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp = nullptr)
ASTGEN_SUPER_If(fl,condp,ifsp,elsesp)4624         : ASTGEN_SUPER_If(fl, condp, ifsp, elsesp) {
4625         m_uniquePragma = false;
4626         m_unique0Pragma = false;
4627         m_priorityPragma = false;
4628     }
ASTNODE_NODE_FUNCS(If)4629     ASTNODE_NODE_FUNCS(If)
4630     bool uniquePragma() const { return m_uniquePragma; }
uniquePragma(bool flag)4631     void uniquePragma(bool flag) { m_uniquePragma = flag; }
unique0Pragma()4632     bool unique0Pragma() const { return m_unique0Pragma; }
unique0Pragma(bool flag)4633     void unique0Pragma(bool flag) { m_unique0Pragma = flag; }
priorityPragma()4634     bool priorityPragma() const { return m_priorityPragma; }
priorityPragma(bool flag)4635     void priorityPragma(bool flag) { m_priorityPragma = flag; }
4636 };
4637 
4638 class AstJumpBlock final : public AstNodeStmt {
4639     // Block of code including a JumpGo and JumpLabel
4640     // Parents:  {statement list}
4641     // Children: {statement list, with JumpGo and JumpLabel below}
4642 private:
4643     AstJumpLabel* m_labelp = nullptr;  // [After V3Jump] Pointer to declaration
4644     int m_labelNum = 0;  // Set by V3EmitCSyms to tell final V3Emit what to increment
4645 public:
4646     // After construction must call ->labelp to associate with appropriate label
AstJumpBlock(FileLine * fl,AstNode * stmtsp)4647     AstJumpBlock(FileLine* fl, AstNode* stmtsp)
4648         : ASTGEN_SUPER_JumpBlock(fl) {
4649         addNOp1p(stmtsp);
4650     }
4651     virtual const char* broken() const override;
4652     virtual void cloneRelink() override;
ASTNODE_NODE_FUNCS(JumpBlock)4653     ASTNODE_NODE_FUNCS(JumpBlock)
4654     virtual int instrCount() const override { return 0; }
maybePointedTo()4655     virtual bool maybePointedTo() const override { return true; }
same(const AstNode * samep)4656     virtual bool same(const AstNode* samep) const override { return true; }
4657     // op1 = Statements
stmtsp()4658     AstNode* stmtsp() const { return op1p(); }  // op1 = List of statements
addStmtsp(AstNode * nodep)4659     void addStmtsp(AstNode* nodep) { addNOp1p(nodep); }
endStmtsp()4660     AstNode* endStmtsp() const { return op2p(); }  // op1 = List of end-of-block
addEndStmtsp(AstNode * nodep)4661     void addEndStmtsp(AstNode* nodep) { addNOp2p(nodep); }
labelNum()4662     int labelNum() const { return m_labelNum; }
labelNum(int flag)4663     void labelNum(int flag) { m_labelNum = flag; }
labelp()4664     AstJumpLabel* labelp() const { return m_labelp; }
labelp(AstJumpLabel * labelp)4665     void labelp(AstJumpLabel* labelp) { m_labelp = labelp; }
4666 };
4667 
4668 class AstJumpLabel final : public AstNodeStmt {
4669     // Jump point declaration
4670     // Parents:  {statement list with JumpBlock above}
4671     // Children: none
4672 private:
4673     AstJumpBlock* m_blockp;  // [After V3Jump] Pointer to declaration
4674 public:
AstJumpLabel(FileLine * fl,AstJumpBlock * blockp)4675     AstJumpLabel(FileLine* fl, AstJumpBlock* blockp)
4676         : ASTGEN_SUPER_JumpLabel(fl)
4677         , m_blockp{blockp} {}
ASTNODE_NODE_FUNCS(JumpLabel)4678     ASTNODE_NODE_FUNCS(JumpLabel)
4679     virtual bool maybePointedTo() const override { return true; }
broken()4680     virtual const char* broken() const override {
4681         BROKEN_RTN(!blockp()->brokeExistsAbove());
4682         BROKEN_RTN(blockp()->labelp() != this);
4683         return nullptr;
4684     }
cloneRelink()4685     virtual void cloneRelink() override {
4686         if (m_blockp->clonep()) m_blockp = m_blockp->clonep();
4687     }
4688     virtual void dump(std::ostream& str) const override;
instrCount()4689     virtual int instrCount() const override { return 0; }
same(const AstNode * samep)4690     virtual bool same(const AstNode* samep) const override {
4691         return blockp() == static_cast<const AstJumpLabel*>(samep)->blockp();
4692     }
blockp()4693     AstJumpBlock* blockp() const { return m_blockp; }
4694 };
4695 
4696 class AstJumpGo final : public AstNodeStmt {
4697     // Jump point; branch down to a JumpLabel
4698     // No support for backward jumps at present
4699     // Parents:  {statement list with JumpBlock above}
4700     // Children: none
4701 private:
4702     AstJumpLabel* m_labelp;  // [After V3Jump] Pointer to declaration
4703 public:
AstJumpGo(FileLine * fl,AstJumpLabel * labelp)4704     AstJumpGo(FileLine* fl, AstJumpLabel* labelp)
4705         : ASTGEN_SUPER_JumpGo(fl)
4706         , m_labelp{labelp} {}
4707     ASTNODE_NODE_FUNCS(JumpGo);
broken()4708     virtual const char* broken() const override {
4709         BROKEN_RTN(!labelp()->brokeExistsBelow());
4710         return nullptr;
4711     }
cloneRelink()4712     virtual void cloneRelink() override {
4713         if (m_labelp->clonep()) m_labelp = m_labelp->clonep();
4714     }
4715     virtual void dump(std::ostream& str) const override;
instrCount()4716     virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
same(const AstNode * samep)4717     virtual bool same(const AstNode* samep) const override {
4718         return labelp() == static_cast<const AstJumpGo*>(samep)->labelp();
4719     }
isGateOptimizable()4720     virtual bool isGateOptimizable() const override { return false; }
isBrancher()4721     virtual bool isBrancher() const override {
4722         return true;  // SPECIAL: We don't process code after breaks
4723     }
labelp()4724     AstJumpLabel* labelp() const { return m_labelp; }
4725 };
4726 
4727 class AstChangeXor final : public AstNodeBiComAsv {
4728     // A comparison to determine change detection, common & must be fast.
4729     // Returns 32-bit or 64-bit value where 0 indicates no change.
4730     // Parents: OR or LOGOR
4731     // Children: VARREF
4732 public:
AstChangeXor(FileLine * fl,AstNode * lhsp,AstNode * rhsp)4733     AstChangeXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
4734         : ASTGEN_SUPER_ChangeXor(fl, lhsp, rhsp) {
4735         dtypeSetUInt32();  // Always used on, and returns word entities
4736     }
ASTNODE_NODE_FUNCS(ChangeXor)4737     ASTNODE_NODE_FUNCS(ChangeXor)
4738     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
4739         return new AstChangeXor(this->fileline(), lhsp, rhsp);
4740     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)4741     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
4742         out.opChangeXor(lhs, rhs);
4743     }
emitVerilog()4744     virtual string emitVerilog() override { return "%k(%l %f^ %r)"; }
emitC()4745     virtual string emitC() override { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; }
emitSimpleOperator()4746     virtual string emitSimpleOperator() override { return "^"; }
cleanOut()4747     virtual bool cleanOut() const override { return false; }  // Lclean && Rclean
cleanLhs()4748     virtual bool cleanLhs() const override { return true; }
cleanRhs()4749     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()4750     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()4751     virtual bool sizeMattersRhs() const override { return false; }
instrCount()4752     virtual int instrCount() const override { return widthInstrs(); }
4753 };
4754 
4755 class AstChangeDet final : public AstNodeStmt {
4756     // A comparison to determine change detection, common & must be fast.
4757 public:
4758     // Null lhs+rhs used to indicate change needed with no spec vars
AstChangeDet(FileLine * fl,AstNode * lhsp,AstNode * rhsp)4759     AstChangeDet(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
4760         : ASTGEN_SUPER_ChangeDet(fl) {
4761         setNOp1p(lhsp);
4762         setNOp2p(rhsp);
4763     }
ASTNODE_NODE_FUNCS(ChangeDet)4764     ASTNODE_NODE_FUNCS(ChangeDet)
4765     AstNode* lhsp() const { return op1p(); }
rhsp()4766     AstNode* rhsp() const { return op2p(); }
isGateOptimizable()4767     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()4768     virtual bool isPredictOptimizable() const override { return false; }
instrCount()4769     virtual int instrCount() const override { return widthInstrs() * 2; }  // xor, or/logor
same(const AstNode * samep)4770     virtual bool same(const AstNode* samep) const override { return true; }
4771 };
4772 
4773 class AstConsAssoc final : public AstNodeMath {
4774     // Construct an assoc array and return object, '{}
4775     // Parents: math
4776     // Children: expression (elements or other queues)
4777 public:
AstConsAssoc(FileLine * fl,AstNode * defaultp)4778     AstConsAssoc(FileLine* fl, AstNode* defaultp)
4779         : ASTGEN_SUPER_ConsAssoc(fl) {
4780         setNOp1p(defaultp);
4781     }
ASTNODE_NODE_FUNCS(ConsAssoc)4782     ASTNODE_NODE_FUNCS(ConsAssoc)
4783     virtual string emitVerilog() override { return "'{}"; }
emitC()4784     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()4785     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()4786     virtual bool cleanOut() const override { return true; }
instrCount()4787     virtual int instrCount() const override { return widthInstrs(); }
defaultp()4788     AstNode* defaultp() const { return op1p(); }
same(const AstNode * samep)4789     virtual bool same(const AstNode* samep) const override { return true; }
4790 };
4791 class AstSetAssoc final : public AstNodeMath {
4792     // Set an assoc array element and return object, '{}
4793     // Parents: math
4794     // Children: expression (elements or other queues)
4795 public:
AstSetAssoc(FileLine * fl,AstNode * lhsp,AstNode * keyp,AstNode * valuep)4796     AstSetAssoc(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* valuep)
4797         : ASTGEN_SUPER_SetAssoc(fl) {
4798         setOp1p(lhsp);
4799         setNOp2p(keyp);
4800         setOp3p(valuep);
4801     }
ASTNODE_NODE_FUNCS(SetAssoc)4802     ASTNODE_NODE_FUNCS(SetAssoc)
4803     virtual string emitVerilog() override { return "'{}"; }
emitC()4804     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()4805     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()4806     virtual bool cleanOut() const override { return true; }
instrCount()4807     virtual int instrCount() const override { return widthInstrs(); }
lhsp()4808     AstNode* lhsp() const { return op1p(); }
keyp()4809     AstNode* keyp() const { return op2p(); }
valuep()4810     AstNode* valuep() const { return op3p(); }
same(const AstNode * samep)4811     virtual bool same(const AstNode* samep) const override { return true; }
4812 };
4813 
4814 class AstConsDynArray final : public AstNodeMath {
4815     // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
4816     // Parents: math
4817     // Children: expression (elements or other queues)
4818 public:
4819     explicit AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr)
ASTGEN_SUPER_ConsDynArray(fl)4820         : ASTGEN_SUPER_ConsDynArray(fl) {
4821         setNOp1p(lhsp);
4822         setNOp2p(rhsp);
4823     }
ASTNODE_NODE_FUNCS(ConsDynArray)4824     ASTNODE_NODE_FUNCS(ConsDynArray)
4825     virtual string emitVerilog() override { return "'{%l, %r}"; }
emitC()4826     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()4827     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()4828     virtual bool cleanOut() const override { return true; }
instrCount()4829     virtual int instrCount() const override { return widthInstrs(); }
lhsp()4830     AstNode* lhsp() const { return op1p(); }  // op1 = expression
rhsp()4831     AstNode* rhsp() const { return op2p(); }  // op2 = expression
same(const AstNode * samep)4832     virtual bool same(const AstNode* samep) const override { return true; }
4833 };
4834 
4835 class AstConsQueue final : public AstNodeMath {
4836     // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
4837     // Parents: math
4838     // Children: expression (elements or other queues)
4839 public:
4840     explicit AstConsQueue(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr)
ASTGEN_SUPER_ConsQueue(fl)4841         : ASTGEN_SUPER_ConsQueue(fl) {
4842         setNOp1p(lhsp);
4843         setNOp2p(rhsp);
4844     }
ASTNODE_NODE_FUNCS(ConsQueue)4845     ASTNODE_NODE_FUNCS(ConsQueue)
4846     virtual string emitVerilog() override { return "'{%l, %r}"; }
emitC()4847     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()4848     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()4849     virtual bool cleanOut() const override { return true; }
instrCount()4850     virtual int instrCount() const override { return widthInstrs(); }
lhsp()4851     AstNode* lhsp() const { return op1p(); }  // op1 = expression
rhsp()4852     AstNode* rhsp() const { return op2p(); }  // op2 = expression
same(const AstNode * samep)4853     virtual bool same(const AstNode* samep) const override { return true; }
4854 };
4855 
4856 class AstBegin final : public AstNodeBlock {
4857     // A Begin/end named block, only exists shortly after parsing until linking
4858     // Parents: statement
4859     // Children: statements
4860 private:
4861     bool m_generate;  // Underneath a generate
4862     const bool m_implied;  // Not inserted by user
4863 public:
4864     // Node that simply puts name into the output stream
4865     AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false,
4866              bool implied = false)
ASTGEN_SUPER_Begin(fl,name,stmtsp)4867         : ASTGEN_SUPER_Begin(fl, name, stmtsp)
4868         , m_generate{generate}
4869         , m_implied{implied} {}
4870     ASTNODE_NODE_FUNCS(Begin)
4871     virtual void dump(std::ostream& str) const override;
4872     // op1p is statements in NodeBlock
genforp()4873     AstNode* genforp() const { return op2p(); }  // op2 = GENFOR, if applicable,
4874     // might NOT be a GenFor, as loop unrolling replaces with Begin
addGenforp(AstGenFor * nodep)4875     void addGenforp(AstGenFor* nodep) { addOp2p(nodep); }
generate(bool flag)4876     void generate(bool flag) { m_generate = flag; }
generate()4877     bool generate() const { return m_generate; }
implied()4878     bool implied() const { return m_implied; }
4879 };
4880 
4881 class AstFork final : public AstNodeBlock {
4882     // A fork named block
4883     // Parents: statement
4884     // Children: statements
4885 private:
4886     VJoinType m_joinType;  // Join keyword type
4887 public:
4888     // Node that simply puts name into the output stream
AstFork(FileLine * fl,const string & name,AstNode * stmtsp)4889     AstFork(FileLine* fl, const string& name, AstNode* stmtsp)
4890         : ASTGEN_SUPER_Fork(fl, name, stmtsp) {}
4891     ASTNODE_NODE_FUNCS(Fork)
4892     virtual void dump(std::ostream& str) const override;
joinType()4893     VJoinType joinType() const { return m_joinType; }
joinType(const VJoinType & flag)4894     void joinType(const VJoinType& flag) { m_joinType = flag; }
4895 };
4896 
4897 class AstInside final : public AstNodeMath {
4898 public:
AstInside(FileLine * fl,AstNode * exprp,AstNode * itemsp)4899     AstInside(FileLine* fl, AstNode* exprp, AstNode* itemsp)
4900         : ASTGEN_SUPER_Inside(fl) {
4901         addOp1p(exprp);
4902         addOp2p(itemsp);
4903         dtypeSetBit();
4904     }
ASTNODE_NODE_FUNCS(Inside)4905     ASTNODE_NODE_FUNCS(Inside)
4906     AstNode* exprp() const { return op1p(); }  // op1 = LHS expression to compare with
4907     // op2 = RHS, possibly a list of expr or AstInsideRange
itemsp()4908     AstNode* itemsp() const { return op2p(); }
emitVerilog()4909     virtual string emitVerilog() override { return "%l inside { %r }"; }
emitC()4910     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()4911     virtual bool cleanOut() const override { return false; }  // NA
4912 };
4913 
4914 class AstInsideRange final : public AstNodeMath {
4915 public:
AstInsideRange(FileLine * fl,AstNode * lhsp,AstNode * rhsp)4916     AstInsideRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
4917         : ASTGEN_SUPER_InsideRange(fl) {
4918         addOp1p(lhsp);
4919         addOp2p(rhsp);
4920     }
ASTNODE_NODE_FUNCS(InsideRange)4921     ASTNODE_NODE_FUNCS(InsideRange)
4922     AstNode* lhsp() const { return op1p(); }  // op1 = LHS
rhsp()4923     AstNode* rhsp() const { return op2p(); }  // op2 = RHS
emitVerilog()4924     virtual string emitVerilog() override { return "[%l:%r]"; }
emitC()4925     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()4926     virtual bool cleanOut() const override { return false; }  // NA
4927     // Create AstAnd(AstGte(...), AstLte(...))
4928     AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp);
4929 };
4930 
4931 class AstInitItem final : public AstNode {
4932     // Container for a item in an init array
4933     // This container is present so that the value underneath may get replaced with a new nodep
4934     // and the upper AstInitArray's map will remain correct (pointing to this InitItem)
4935 public:
4936     // Parents: INITARRAY
AstInitItem(FileLine * fl,AstNode * valuep)4937     AstInitItem(FileLine* fl, AstNode* valuep)
4938         : ASTGEN_SUPER_InitItem(fl) {
4939         addOp1p(valuep);
4940     }
ASTNODE_NODE_FUNCS(InitItem)4941     ASTNODE_NODE_FUNCS(InitItem)
4942     virtual bool maybePointedTo() const override { return true; }
hasDType()4943     virtual bool hasDType() const override { return false; }  // See valuep()'s dtype instead
valuep()4944     AstNode* valuep() const { return op1p(); }  // op1 = Value
valuep(AstNode * nodep)4945     void valuep(AstNode* nodep) { addOp1p(nodep); }
4946 };
4947 
4948 class AstInitArray final : public AstNode {
4949     // Set a var to a map of values
4950     // The list of initsp() is not relevant
4951     // If default is specified, the vector may be sparse, and not provide each value.
4952     // Key values are C++ array style, with lo() at index 0
4953     // Parents: ASTVAR::init()
4954     // Children: AstInitItem
4955 public:
4956     using KeyItemMap = std::map<uint32_t, AstInitItem*>;
4957 
4958 private:
4959     KeyItemMap m_map;  // Node value for each array index
4960 public:
AstInitArray(FileLine * fl,AstNodeArrayDType * newDTypep,AstNode * defaultp)4961     AstInitArray(FileLine* fl, AstNodeArrayDType* newDTypep, AstNode* defaultp)
4962         : ASTGEN_SUPER_InitArray(fl) {
4963         dtypep(newDTypep);
4964         addNOp1p(defaultp);
4965     }
4966     ASTNODE_NODE_FUNCS(InitArray)
4967     virtual void dump(std::ostream& str) const override;
broken()4968     virtual const char* broken() const override {
4969         for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
4970             BROKEN_RTN(!it->second);
4971             BROKEN_RTN(!it->second->brokeExists());
4972         }
4973         return nullptr;
4974     }
cloneRelink()4975     virtual void cloneRelink() override {
4976         for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) {
4977             if (it->second->clonep()) it->second = it->second->clonep();
4978         }
4979     }
hasDType()4980     virtual bool hasDType() const override { return true; }
same(const AstNode * samep)4981     virtual bool same(const AstNode* samep) const override {
4982         // Only works if exact same children, instead should override comparison
4983         // of children list, and instead use map-vs-map key/value compare
4984         return m_map == static_cast<const AstInitArray*>(samep)->m_map;
4985     }
defaultp()4986     AstNode* defaultp() const { return op1p(); }  // op1 = Default if sparse
defaultp(AstNode * newp)4987     void defaultp(AstNode* newp) { setOp1p(newp); }
initsp()4988     AstNode* initsp() const { return op2p(); }  // op2 = Initial value expressions
addValuep(AstNode * newp)4989     void addValuep(AstNode* newp) { addIndexValuep(m_map.size(), newp); }
map()4990     const KeyItemMap& map() const { return m_map; }
addIndexValuep(uint32_t index,AstNode * newp)4991     AstNode* addIndexValuep(uint32_t index, AstNode* newp) {
4992         // Returns old value, caller must garbage collect
4993         AstNode* oldp = nullptr;
4994         const auto it = m_map.find(index);
4995         if (it != m_map.end()) {
4996             oldp = it->second->valuep();
4997             it->second->valuep(newp);
4998         } else {
4999             AstInitItem* const itemp = new AstInitItem(fileline(), newp);
5000             m_map.emplace(index, itemp);
5001             addOp2p(itemp);
5002         }
5003         return oldp;
5004     }
getIndexValuep(uint32_t index)5005     AstNode* getIndexValuep(uint32_t index) const {
5006         const auto it = m_map.find(index);
5007         if (it == m_map.end()) {
5008             return nullptr;
5009         } else {
5010             return it->second->valuep();
5011         }
5012     }
getIndexDefaultedValuep(uint32_t index)5013     AstNode* getIndexDefaultedValuep(uint32_t index) const {
5014         AstNode* valuep = getIndexValuep(index);
5015         if (!valuep) valuep = defaultp();
5016         return valuep;
5017     }
5018 };
5019 
5020 class AstNew final : public AstNodeFTaskRef {
5021     // New as constructor
5022     // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it
5023     // Parents: math|stmt
5024     // Children: varref|arraysel, math
5025 public:
AstNew(FileLine * fl,AstNode * pinsp)5026     AstNew(FileLine* fl, AstNode* pinsp)
5027         : ASTGEN_SUPER_New(fl, false, "new", pinsp) {}
ASTNODE_NODE_FUNCS(New)5028     ASTNODE_NODE_FUNCS(New)
5029     virtual bool cleanOut() const { return true; }
same(const AstNode * samep)5030     virtual bool same(const AstNode* samep) const override { return true; }
hasDType()5031     virtual bool hasDType() const override { return true; }
instrCount()5032     virtual int instrCount() const override { return widthInstrs(); }
5033 };
5034 
5035 class AstNewCopy final : public AstNodeMath {
5036     // New as shallow copy
5037     // Parents: math|stmt
5038     // Children: varref|arraysel, math
5039 public:
AstNewCopy(FileLine * fl,AstNode * rhsp)5040     AstNewCopy(FileLine* fl, AstNode* rhsp)
5041         : ASTGEN_SUPER_NewCopy(fl) {
5042         dtypeFrom(rhsp);  // otherwise V3Width will resolve
5043         setNOp1p(rhsp);
5044     }
ASTNODE_NODE_FUNCS(NewCopy)5045     ASTNODE_NODE_FUNCS(NewCopy)
5046     virtual string emitVerilog() override { return "new"; }
emitC()5047     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5048     virtual bool cleanOut() const override { return true; }
same(const AstNode * samep)5049     virtual bool same(const AstNode* samep) const override { return true; }
instrCount()5050     virtual int instrCount() const override { return widthInstrs(); }
rhsp()5051     AstNode* rhsp() const { return op1p(); }
5052 };
5053 
5054 class AstNewDynamic final : public AstNodeMath {
5055     // New for dynamic array
5056     // Parents: math|stmt
5057     // Children: varref|arraysel, math
5058 public:
AstNewDynamic(FileLine * fl,AstNode * sizep,AstNode * rhsp)5059     AstNewDynamic(FileLine* fl, AstNode* sizep, AstNode* rhsp)
5060         : ASTGEN_SUPER_NewDynamic(fl) {
5061         dtypeFrom(rhsp);  // otherwise V3Width will resolve
5062         setNOp1p(sizep);
5063         setNOp2p(rhsp);
5064     }
ASTNODE_NODE_FUNCS(NewDynamic)5065     ASTNODE_NODE_FUNCS(NewDynamic)
5066     virtual string emitVerilog() override { return "new"; }
emitC()5067     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5068     virtual bool cleanOut() const override { return true; }
same(const AstNode * samep)5069     virtual bool same(const AstNode* samep) const override { return true; }
instrCount()5070     virtual int instrCount() const override { return widthInstrs(); }
sizep()5071     AstNode* sizep() const { return op1p(); }
rhsp()5072     AstNode* rhsp() const { return op2p(); }
5073 };
5074 
5075 class AstPragma final : public AstNode {
5076 private:
5077     const AstPragmaType m_pragType;  // Type of pragma
5078 public:
5079     // Pragmas don't result in any output code, they're just flags that affect
5080     // other processing in verilator.
AstPragma(FileLine * fl,AstPragmaType pragType)5081     AstPragma(FileLine* fl, AstPragmaType pragType)
5082         : ASTGEN_SUPER_Pragma(fl)
5083         , m_pragType{pragType} {}
ASTNODE_NODE_FUNCS(Pragma)5084     ASTNODE_NODE_FUNCS(Pragma)
5085     AstPragmaType pragType() const { return m_pragType; }  // *=type of the pragma
isPredictOptimizable()5086     virtual bool isPredictOptimizable() const override { return false; }
same(const AstNode * samep)5087     virtual bool same(const AstNode* samep) const override {
5088         return pragType() == static_cast<const AstPragma*>(samep)->pragType();
5089     }
5090 };
5091 
5092 class AstPrintTimeScale final : public AstNodeStmt {
5093     // Parents: stmtlist
5094     string m_name;  // Parent module name
5095     VTimescale m_timeunit;  // Parent module time unit
5096 public:
AstPrintTimeScale(FileLine * fl)5097     explicit AstPrintTimeScale(FileLine* fl)
5098         : ASTGEN_SUPER_PrintTimeScale(fl) {}
ASTNODE_NODE_FUNCS(PrintTimeScale)5099     ASTNODE_NODE_FUNCS(PrintTimeScale)
5100     virtual void name(const string& name) override { m_name = name; }
name()5101     virtual string name() const override { return m_name; }  // * = Var name
5102     virtual void dump(std::ostream& str) const override;
verilogKwd()5103     virtual string verilogKwd() const override { return "$printtimescale"; }
isGateOptimizable()5104     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5105     virtual bool isPredictOptimizable() const override { return false; }
isPure()5106     virtual bool isPure() const override { return false; }
isOutputter()5107     virtual bool isOutputter() const override { return true; }
instrCount()5108     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
timeunit(const VTimescale & flag)5109     void timeunit(const VTimescale& flag) { m_timeunit = flag; }
timeunit()5110     VTimescale timeunit() const { return m_timeunit; }
5111 };
5112 
5113 class AstStop final : public AstNodeStmt {
5114 public:
AstStop(FileLine * fl,bool maybe)5115     AstStop(FileLine* fl, bool maybe)
5116         : ASTGEN_SUPER_Stop(fl) {}
ASTNODE_NODE_FUNCS(Stop)5117     ASTNODE_NODE_FUNCS(Stop)
5118     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5119     virtual bool isPredictOptimizable() const override { return false; }
isPure()5120     virtual bool isPure() const override {
5121         return false;
5122     }  // SPECIAL: $display has 'visual' ordering
isOutputter()5123     virtual bool isOutputter() const override { return true; }  // SPECIAL: $display makes output
isUnlikely()5124     virtual bool isUnlikely() const override { return true; }
instrCount()5125     virtual int instrCount() const override { return 0; }  // Rarely executes
same(const AstNode * samep)5126     virtual bool same(const AstNode* samep) const override {
5127         return fileline() == samep->fileline();
5128     }
5129 };
5130 
5131 class AstFinish final : public AstNodeStmt {
5132 public:
AstFinish(FileLine * fl)5133     explicit AstFinish(FileLine* fl)
5134         : ASTGEN_SUPER_Finish(fl) {}
ASTNODE_NODE_FUNCS(Finish)5135     ASTNODE_NODE_FUNCS(Finish)
5136     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5137     virtual bool isPredictOptimizable() const override { return false; }
isPure()5138     virtual bool isPure() const override {
5139         return false;
5140     }  // SPECIAL: $display has 'visual' ordering
isOutputter()5141     virtual bool isOutputter() const override { return true; }  // SPECIAL: $display makes output
isUnlikely()5142     virtual bool isUnlikely() const override { return true; }
instrCount()5143     virtual int instrCount() const override { return 0; }  // Rarely executes
same(const AstNode * samep)5144     virtual bool same(const AstNode* samep) const override {
5145         return fileline() == samep->fileline();
5146     }
5147 };
5148 
5149 class AstNullCheck final : public AstNodeUniop {
5150     // Return LHS after checking that LHS is non-null
5151     // Children: VarRef or something returning pointer
5152 public:
AstNullCheck(FileLine * fl,AstNode * lhsp)5153     AstNullCheck(FileLine* fl, AstNode* lhsp)
5154         : ASTGEN_SUPER_NullCheck(fl, lhsp) {
5155         dtypeFrom(lhsp);
5156     }
ASTNODE_NODE_FUNCS(NullCheck)5157     ASTNODE_NODE_FUNCS(NullCheck)
5158     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
instrCount()5159     virtual int instrCount() const override { return 1; }  // Rarely executes
emitVerilog()5160     virtual string emitVerilog() override { return "%l"; }
emitC()5161     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()5162     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()5163     virtual bool cleanOut() const override { return true; }
cleanLhs()5164     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5165     virtual bool sizeMattersLhs() const override { return false; }
same(const AstNode * samep)5166     virtual bool same(const AstNode* samep) const override {
5167         return fileline() == samep->fileline();
5168     }
5169 };
5170 
5171 class AstTimingControl final : public AstNodeStmt {
5172     // Parents: stmtlist
5173 public:
AstTimingControl(FileLine * fl,AstSenTree * sensesp,AstNode * stmtsp)5174     AstTimingControl(FileLine* fl, AstSenTree* sensesp, AstNode* stmtsp)
5175         : ASTGEN_SUPER_TimingControl(fl) {
5176         setNOp1p(sensesp);
5177         setNOp2p(stmtsp);
5178     }
ASTNODE_NODE_FUNCS(TimingControl)5179     ASTNODE_NODE_FUNCS(TimingControl)
5180     virtual string verilogKwd() const override { return "@(%l) %r"; }
isGateOptimizable()5181     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5182     virtual bool isPredictOptimizable() const override { return false; }
isPure()5183     virtual bool isPure() const override { return false; }
isOutputter()5184     virtual bool isOutputter() const override { return false; }
instrCount()5185     virtual int instrCount() const override { return 0; }
sensesp()5186     AstSenTree* sensesp() const { return VN_AS(op1p(), SenTree); }
stmtsp()5187     AstNode* stmtsp() const { return op2p(); }
5188 };
5189 
5190 class AstTimeFormat final : public AstNodeStmt {
5191     // Parents: stmtlist
5192 public:
AstTimeFormat(FileLine * fl,AstNode * unitsp,AstNode * precisionp,AstNode * suffixp,AstNode * widthp)5193     AstTimeFormat(FileLine* fl, AstNode* unitsp, AstNode* precisionp, AstNode* suffixp,
5194                   AstNode* widthp)
5195         : ASTGEN_SUPER_TimeFormat(fl) {
5196         setOp1p(unitsp);
5197         setOp2p(precisionp);
5198         setOp3p(suffixp);
5199         setOp4p(widthp);
5200     }
ASTNODE_NODE_FUNCS(TimeFormat)5201     ASTNODE_NODE_FUNCS(TimeFormat)
5202     virtual string verilogKwd() const override { return "$timeformat"; }
isGateOptimizable()5203     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5204     virtual bool isPredictOptimizable() const override { return false; }
isPure()5205     virtual bool isPure() const override { return false; }
isOutputter()5206     virtual bool isOutputter() const override { return true; }
instrCount()5207     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
unitsp()5208     AstNode* unitsp() const { return op1p(); }
precisionp()5209     AstNode* precisionp() const { return op2p(); }
suffixp()5210     AstNode* suffixp() const { return op3p(); }
widthp()5211     AstNode* widthp() const { return op4p(); }
5212 };
5213 
5214 class AstTraceDecl final : public AstNodeStmt {
5215     // Trace point declaration
5216     // Separate from AstTraceInc; as a declaration can't be deleted
5217     // Parents:  {statement list}
5218     // Children: expression being traced
5219 private:
5220     uint32_t m_code = 0;  // Trace identifier code; converted to ASCII by trace routines
5221     const string m_showname;  // Name of variable
5222     const VNumRange m_bitRange;  // Property of var the trace details
5223     const VNumRange m_arrayRange;  // Property of var the trace details
5224     const uint32_t m_codeInc;  // Code increment
5225     const AstVarType m_varType;  // Type of variable (for localparam vs. param)
5226     const AstBasicDTypeKwd m_declKwd;  // Keyword at declaration time
5227     const VDirection m_declDirection;  // Declared direction input/output etc
5228     const bool m_isScoped;  // Uses run-time scope (for interfaces)
5229 public:
AstTraceDecl(FileLine * fl,const string & showname,AstVar * varp,AstNode * valuep,const VNumRange & bitRange,const VNumRange & arrayRange,bool isScoped)5230     AstTraceDecl(FileLine* fl, const string& showname,
5231                  AstVar* varp,  // For input/output state etc
5232                  AstNode* valuep, const VNumRange& bitRange, const VNumRange& arrayRange,
5233                  bool isScoped)
5234         : ASTGEN_SUPER_TraceDecl(fl)
5235         , m_showname{showname}
5236         , m_bitRange{bitRange}
5237         , m_arrayRange{arrayRange}
5238         , m_codeInc(
5239               ((arrayRange.ranged() ? arrayRange.elements() : 1) * valuep->dtypep()->widthWords()
5240                * (VL_EDATASIZE / 32)))  // A code is always 32-bits
5241         , m_varType{varp->varType()}
5242         , m_declKwd{varp->declKwd()}
5243         , m_declDirection{varp->declDirection()}
5244         , m_isScoped{isScoped} {
5245         dtypeFrom(valuep);
5246         addNOp1p(valuep);
5247     }
instrCount()5248     virtual int instrCount() const override { return 100; }  // Large...
ASTNODE_NODE_FUNCS(TraceDecl)5249     ASTNODE_NODE_FUNCS(TraceDecl)
5250     virtual string name() const override { return m_showname; }
maybePointedTo()5251     virtual bool maybePointedTo() const override { return true; }
hasDType()5252     virtual bool hasDType() const override { return true; }
same(const AstNode * samep)5253     virtual bool same(const AstNode* samep) const override { return false; }
showname()5254     string showname() const { return m_showname; }  // * = Var name
5255     // Details on what we're tracing
code()5256     uint32_t code() const { return m_code; }
code(uint32_t code)5257     void code(uint32_t code) { m_code = code; }
codeInc()5258     uint32_t codeInc() const { return m_codeInc; }
bitRange()5259     const VNumRange& bitRange() const { return m_bitRange; }
arrayRange()5260     const VNumRange& arrayRange() const { return m_arrayRange; }
varType()5261     AstVarType varType() const { return m_varType; }
declKwd()5262     AstBasicDTypeKwd declKwd() const { return m_declKwd; }
declDirection()5263     VDirection declDirection() const { return m_declDirection; }
isScoped()5264     bool isScoped() const { return m_isScoped; }
valuep()5265     AstNode* valuep() const { return op1p(); }
5266 };
5267 
5268 class AstTraceInc final : public AstNodeStmt {
5269     // Trace point dump
5270     // Parents:  {statement list}
5271     // Children: op1: things to emit before this node,
5272     //           op2: expression being traced (from decl)
5273 
5274 private:
5275     AstTraceDecl* m_declp;  // Pointer to declaration
5276     const bool m_full;  // Is this a full vs incremental dump
5277     const uint32_t m_baseCode;  // Trace code base value in function containing this AstTraceInc
5278 
5279 public:
5280     AstTraceInc(FileLine* fl, AstTraceDecl* declp, bool full, uint32_t baseCode = 0)
ASTGEN_SUPER_TraceInc(fl)5281         : ASTGEN_SUPER_TraceInc(fl)
5282         , m_declp{declp}
5283         , m_full{full}
5284         , m_baseCode{baseCode} {
5285         dtypeFrom(declp);
5286         addOp2p(declp->valuep()->cloneTree(true));
5287     }
ASTNODE_NODE_FUNCS(TraceInc)5288     ASTNODE_NODE_FUNCS(TraceInc)
5289     virtual const char* broken() const override {
5290         BROKEN_RTN(!declp()->brokeExists());
5291         return nullptr;
5292     }
cloneRelink()5293     virtual void cloneRelink() override {
5294         if (m_declp->clonep()) m_declp = m_declp->clonep();
5295     }
5296     virtual void dump(std::ostream& str) const override;
instrCount()5297     virtual int instrCount() const override { return 10 + 2 * INSTR_COUNT_LD; }
hasDType()5298     virtual bool hasDType() const override { return true; }
same(const AstNode * samep)5299     virtual bool same(const AstNode* samep) const override {
5300         return declp() == static_cast<const AstTraceInc*>(samep)->declp();
5301     }
isGateOptimizable()5302     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5303     virtual bool isPredictOptimizable() const override { return false; }
isOutputter()5304     virtual bool isOutputter() const override { return true; }
5305     // but isPure()  true
5306     // op1 = Statements before the value
precondsp()5307     AstNode* precondsp() const { return op1p(); }
addPrecondsp(AstNode * newp)5308     void addPrecondsp(AstNode* newp) { addOp1p(newp); }
valuep()5309     AstNode* valuep() const { return op2p(); }
declp()5310     AstTraceDecl* declp() const { return m_declp; }
full()5311     bool full() const { return m_full; }
baseCode()5312     uint32_t baseCode() const { return m_baseCode; }
5313 };
5314 
5315 class AstActive final : public AstNode {
5316     // Block of code with sensitivity activation
5317     // Parents:  MODULE | CFUNC
5318     // Children: SENTREE, statements
5319 private:
5320     string m_name;
5321     AstSenTree* m_sensesp;
5322 
5323 public:
AstActive(FileLine * fl,const string & name,AstSenTree * sensesp)5324     AstActive(FileLine* fl, const string& name, AstSenTree* sensesp)
5325         : ASTGEN_SUPER_Active(fl) {
5326         m_name = name;  // Copy it
5327         UASSERT(sensesp, "Sensesp required arg");
5328         m_sensesp = sensesp;
5329     }
5330     ASTNODE_NODE_FUNCS(Active)
5331     virtual void dump(std::ostream& str = std::cout) const override;
name()5332     virtual string name() const override { return m_name; }
broken()5333     virtual const char* broken() const override {
5334         BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists());
5335         return nullptr;
5336     }
cloneRelink()5337     virtual void cloneRelink() override {
5338         if (m_sensesp->clonep()) {
5339             m_sensesp = m_sensesp->clonep();
5340             UASSERT(m_sensesp, "Bad clone cross link: " << this);
5341         }
5342     }
5343     // Statements are broken into pieces, as some must come before others.
sensesp(AstSenTree * nodep)5344     void sensesp(AstSenTree* nodep) { m_sensesp = nodep; }
sensesp()5345     AstSenTree* sensesp() const { return m_sensesp; }
5346     // op1 = Sensitivity tree, if a clocked block in early stages
sensesStorep(AstSenTree * nodep)5347     void sensesStorep(AstSenTree* nodep) { addOp1p(nodep); }
sensesStorep()5348     AstSenTree* sensesStorep() const { return VN_AS(op1p(), SenTree); }
5349     // op2 = Combo logic
stmtsp()5350     AstNode* stmtsp() const { return op2p(); }
addStmtsp(AstNode * nodep)5351     void addStmtsp(AstNode* nodep) { addOp2p(nodep); }
5352     // METHODS
hasInitial()5353     bool hasInitial() const { return m_sensesp->hasInitial(); }
hasSettle()5354     bool hasSettle() const { return m_sensesp->hasSettle(); }
hasClocked()5355     bool hasClocked() const { return m_sensesp->hasClocked(); }
5356 };
5357 
5358 class AstAttrOf final : public AstNode {
5359 private:
5360     // Return a value of a attribute, for example a LSB or array LSB of a signal
5361     AstAttrType m_attrType;  // What sort of extraction
5362 public:
5363     AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp = nullptr,
5364               AstNode* dimp = nullptr)
ASTGEN_SUPER_AttrOf(fl)5365         : ASTGEN_SUPER_AttrOf(fl) {
5366         setNOp1p(fromp);
5367         setNOp2p(dimp);
5368         m_attrType = attrtype;
5369     }
ASTNODE_NODE_FUNCS(AttrOf)5370     ASTNODE_NODE_FUNCS(AttrOf)
5371     AstNode* fromp() const { return op1p(); }
dimp()5372     AstNode* dimp() const { return op2p(); }
attrType()5373     AstAttrType attrType() const { return m_attrType; }
5374     virtual void dump(std::ostream& str = std::cout) const override;
5375 };
5376 
5377 class AstScopeName final : public AstNodeMath {
5378     // For display %m and DPI context imports
5379     // Parents:  DISPLAY
5380     // Children: TEXT
5381 private:
5382     bool m_dpiExport = false;  // Is for dpiExport
5383     const bool m_forFormat = false;  // Is for a format %m
5384     string scopeNameFormatter(AstText* scopeTextp) const;
5385     string scopePrettyNameFormatter(AstText* scopeTextp) const;
5386 
5387 public:
5388     class ForFormat {};
AstScopeName(FileLine * fl,bool forFormat)5389     AstScopeName(FileLine* fl, bool forFormat)
5390         : ASTGEN_SUPER_ScopeName(fl)
5391         , m_forFormat{forFormat} {
5392         dtypeSetUInt64();
5393     }
ASTNODE_NODE_FUNCS(ScopeName)5394     ASTNODE_NODE_FUNCS(ScopeName)
5395     virtual bool same(const AstNode* samep) const override {
5396         return (m_dpiExport == static_cast<const AstScopeName*>(samep)->m_dpiExport
5397                 && m_forFormat == static_cast<const AstScopeName*>(samep)->m_forFormat);
5398     }
emitVerilog()5399     virtual string emitVerilog() override { return ""; }
emitC()5400     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5401     virtual bool cleanOut() const override { return true; }
5402     virtual void dump(std::ostream& str = std::cout) const override;
scopeAttrp()5403     AstText* scopeAttrp() const { return VN_AS(op1p(), Text); }
scopeAttrp(AstNode * nodep)5404     void scopeAttrp(AstNode* nodep) { addOp1p(nodep); }
scopeEntrp()5405     AstText* scopeEntrp() const { return VN_AS(op2p(), Text); }
scopeEntrp(AstNode * nodep)5406     void scopeEntrp(AstNode* nodep) { addOp2p(nodep); }
scopeSymName()5407     string scopeSymName() const {  // Name for __Vscope variable including children
5408         return scopeNameFormatter(scopeAttrp());
5409     }
scopeDpiName()5410     string scopeDpiName() const {  // Name for DPI import scope
5411         return scopeNameFormatter(scopeEntrp());
5412     }
scopePrettySymName()5413     string scopePrettySymName() const {  // Name for __Vscope variable including children
5414         return scopePrettyNameFormatter(scopeAttrp());
5415     }
scopePrettyDpiName()5416     string scopePrettyDpiName() const {  // Name for __Vscope variable including children
5417         return scopePrettyNameFormatter(scopeEntrp());
5418     }
dpiExport()5419     bool dpiExport() const { return m_dpiExport; }
dpiExport(bool flag)5420     void dpiExport(bool flag) { m_dpiExport = flag; }
forFormat()5421     bool forFormat() const { return m_forFormat; }
5422 };
5423 
5424 class AstUdpTable final : public AstNode {
5425 public:
AstUdpTable(FileLine * fl,AstNode * bodysp)5426     AstUdpTable(FileLine* fl, AstNode* bodysp)
5427         : ASTGEN_SUPER_UdpTable(fl) {
5428         addNOp1p(bodysp);
5429     }
ASTNODE_NODE_FUNCS(UdpTable)5430     ASTNODE_NODE_FUNCS(UdpTable)
5431     // op1 = List of UdpTableLines
5432     AstUdpTableLine* bodysp() const { return VN_AS(op1p(), UdpTableLine); }
5433 };
5434 
5435 class AstUdpTableLine final : public AstNode {
5436     string m_text;
5437 
5438 public:
AstUdpTableLine(FileLine * fl,const string & text)5439     AstUdpTableLine(FileLine* fl, const string& text)
5440         : ASTGEN_SUPER_UdpTableLine(fl)
5441         , m_text{text} {}
ASTNODE_NODE_FUNCS(UdpTableLine)5442     ASTNODE_NODE_FUNCS(UdpTableLine)
5443     virtual string name() const override { return m_text; }
text()5444     string text() const { return m_text; }
5445 };
5446 
5447 //======================================================================
5448 // non-ary ops
5449 
5450 class AstRand final : public AstNodeMath {
5451     // $random/$random(seed) or $urandom/$urandom(seed)
5452     // Return a random number, based upon width()
5453 private:
5454     const bool m_urandom = false;  // $urandom vs $random
5455     const bool m_reset = false;  // Random reset, versus always random
5456 public:
5457     class Reset {};
AstRand(FileLine * fl,Reset,AstNodeDType * dtp,bool reset)5458     AstRand(FileLine* fl, Reset, AstNodeDType* dtp, bool reset)
5459         : ASTGEN_SUPER_Rand(fl)
5460         , m_reset{reset} {
5461         dtypep(dtp);
5462     }
AstRand(FileLine * fl,AstNode * seedp,bool urandom)5463     AstRand(FileLine* fl, AstNode* seedp, bool urandom)
5464         : ASTGEN_SUPER_Rand(fl)
5465         , m_urandom(urandom) {
5466         setNOp1p(seedp);
5467     }
ASTNODE_NODE_FUNCS(Rand)5468     ASTNODE_NODE_FUNCS(Rand)
5469     virtual string emitVerilog() override {
5470         return seedp() ? (m_urandom ? "%f$urandom(%l)" : "%f$random(%l)")
5471                        : (m_urandom ? "%f$urandom()" : "%f$random()");
5472     }
emitC()5473     virtual string emitC() override {
5474         return m_reset    ? "VL_RAND_RESET_%nq(%nw, %P)"
5475                : seedp()  ? "VL_RANDOM_SEEDED_%nq%lq(%li)"
5476                : isWide() ? "VL_RANDOM_%nq(%nw, %P)"  //
5477                           : "VL_RANDOM_%nq()";
5478     }
cleanOut()5479     virtual bool cleanOut() const override { return false; }
isGateOptimizable()5480     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5481     virtual bool isPredictOptimizable() const override { return false; }
instrCount()5482     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
same(const AstNode * samep)5483     virtual bool same(const AstNode* samep) const override { return true; }
combinable(const AstRand * samep)5484     bool combinable(const AstRand* samep) const {
5485         return !seedp() && !samep->seedp() && reset() == samep->reset()
5486                && urandom() == samep->urandom();
5487     }
seedp()5488     AstNode* seedp() const { return op1p(); }
reset()5489     bool reset() const { return m_reset; }
urandom()5490     bool urandom() const { return m_urandom; }
5491 };
5492 
5493 class AstURandomRange final : public AstNodeBiop {
5494     // $urandom_range
5495 public:
AstURandomRange(FileLine * fl,AstNode * lhsp,AstNode * rhsp)5496     explicit AstURandomRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
5497         : ASTGEN_SUPER_URandomRange(fl, lhsp, rhsp) {
5498         dtypeSetUInt32();  // Says IEEE
5499     }
ASTNODE_NODE_FUNCS(URandomRange)5500     ASTNODE_NODE_FUNCS(URandomRange)
5501     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
5502         return new AstURandomRange(fileline(), lhsp, rhsp);
5503     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)5504     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
5505         V3ERROR_NA;
5506     }
emitVerilog()5507     virtual string emitVerilog() override { return "%f$urandom_range(%l, %r)"; }
emitC()5508     virtual string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; }
cleanOut()5509     virtual bool cleanOut() const override { return true; }
cleanLhs()5510     virtual bool cleanLhs() const override { return true; }
cleanRhs()5511     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()5512     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()5513     virtual bool sizeMattersRhs() const override { return false; }
isGateOptimizable()5514     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5515     virtual bool isPredictOptimizable() const override { return false; }
instrCount()5516     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
5517 };
5518 
5519 class AstTime final : public AstNodeTermop {
5520     VTimescale m_timeunit;  // Parent module time unit
5521 public:
AstTime(FileLine * fl,const VTimescale & timeunit)5522     AstTime(FileLine* fl, const VTimescale& timeunit)
5523         : ASTGEN_SUPER_Time(fl)
5524         , m_timeunit{timeunit} {
5525         dtypeSetUInt64();
5526     }
ASTNODE_NODE_FUNCS(Time)5527     ASTNODE_NODE_FUNCS(Time)
5528     virtual string emitVerilog() override { return "%f$time"; }
emitC()5529     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5530     virtual bool cleanOut() const override { return true; }
isGateOptimizable()5531     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5532     virtual bool isPredictOptimizable() const override { return false; }
instrCount()5533     virtual int instrCount() const override { return INSTR_COUNT_TIME; }
same(const AstNode * samep)5534     virtual bool same(const AstNode* samep) const override { return true; }
5535     virtual void dump(std::ostream& str = std::cout) const override;
timeunit(const VTimescale & flag)5536     void timeunit(const VTimescale& flag) { m_timeunit = flag; }
timeunit()5537     VTimescale timeunit() const { return m_timeunit; }
5538 };
5539 
5540 class AstTimeD final : public AstNodeTermop {
5541     VTimescale m_timeunit;  // Parent module time unit
5542 public:
AstTimeD(FileLine * fl,const VTimescale & timeunit)5543     AstTimeD(FileLine* fl, const VTimescale& timeunit)
5544         : ASTGEN_SUPER_TimeD(fl)
5545         , m_timeunit{timeunit} {
5546         dtypeSetDouble();
5547     }
ASTNODE_NODE_FUNCS(TimeD)5548     ASTNODE_NODE_FUNCS(TimeD)
5549     virtual string emitVerilog() override { return "%f$realtime"; }
emitC()5550     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5551     virtual bool cleanOut() const override { return true; }
isGateOptimizable()5552     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()5553     virtual bool isPredictOptimizable() const override { return false; }
instrCount()5554     virtual int instrCount() const override { return INSTR_COUNT_TIME; }
same(const AstNode * samep)5555     virtual bool same(const AstNode* samep) const override { return true; }
5556     virtual void dump(std::ostream& str = std::cout) const override;
timeunit(const VTimescale & flag)5557     void timeunit(const VTimescale& flag) { m_timeunit = flag; }
timeunit()5558     VTimescale timeunit() const { return m_timeunit; }
5559 };
5560 
5561 class AstUCFunc final : public AstNodeMath {
5562     // User's $c function
5563     // Perhaps this should be an AstNodeListop; but there's only one list math right now
5564 public:
AstUCFunc(FileLine * fl,AstNode * exprsp)5565     AstUCFunc(FileLine* fl, AstNode* exprsp)
5566         : ASTGEN_SUPER_UCFunc(fl) {
5567         addNOp1p(exprsp);
5568     }
ASTNODE_NODE_FUNCS(UCFunc)5569     ASTNODE_NODE_FUNCS(UCFunc)
5570     virtual bool cleanOut() const override { return false; }
emitVerilog()5571     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()5572     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
bodysp()5573     AstNode* bodysp() const { return op1p(); }  // op1 = expressions to print
isPure()5574     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()5575     virtual bool isOutputter() const override { return true; }
isGateOptimizable()5576     virtual bool isGateOptimizable() const override { return false; }
isSubstOptimizable()5577     virtual bool isSubstOptimizable() const override { return false; }
isPredictOptimizable()5578     virtual bool isPredictOptimizable() const override { return false; }
instrCount()5579     virtual int instrCount() const override { return INSTR_COUNT_PLI; }
same(const AstNode * samep)5580     virtual bool same(const AstNode* samep) const override { return true; }
5581 };
5582 
5583 //======================================================================
5584 // Unary ops
5585 
5586 class AstNegate final : public AstNodeUniop {
5587 public:
AstNegate(FileLine * fl,AstNode * lhsp)5588     AstNegate(FileLine* fl, AstNode* lhsp)
5589         : ASTGEN_SUPER_Negate(fl, lhsp) {
5590         dtypeFrom(lhsp);
5591     }
ASTNODE_NODE_FUNCS(Negate)5592     ASTNODE_NODE_FUNCS(Negate)
5593     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); }
emitVerilog()5594     virtual string emitVerilog() override { return "%f(- %l)"; }
emitC()5595     virtual string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
emitSimpleOperator()5596     virtual string emitSimpleOperator() override { return "-"; }
cleanOut()5597     virtual bool cleanOut() const override { return false; }
cleanLhs()5598     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()5599     virtual bool sizeMattersLhs() const override { return true; }
5600 };
5601 class AstNegateD final : public AstNodeUniop {
5602 public:
AstNegateD(FileLine * fl,AstNode * lhsp)5603     AstNegateD(FileLine* fl, AstNode* lhsp)
5604         : ASTGEN_SUPER_NegateD(fl, lhsp) {
5605         dtypeSetDouble();
5606     }
ASTNODE_NODE_FUNCS(NegateD)5607     ASTNODE_NODE_FUNCS(NegateD)
5608     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); }
emitVerilog()5609     virtual string emitVerilog() override { return "%f(- %l)"; }
emitC()5610     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()5611     virtual string emitSimpleOperator() override { return "-"; }
cleanOut()5612     virtual bool cleanOut() const override { return true; }
cleanLhs()5613     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()5614     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5615     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()5616     virtual bool doubleFlavor() const override { return true; }
5617 };
5618 class AstRedAnd final : public AstNodeUniop {
5619 public:
AstRedAnd(FileLine * fl,AstNode * lhsp)5620     AstRedAnd(FileLine* fl, AstNode* lhsp)
5621         : ASTGEN_SUPER_RedAnd(fl, lhsp) {
5622         dtypeSetBit();
5623     }
ASTNODE_NODE_FUNCS(RedAnd)5624     ASTNODE_NODE_FUNCS(RedAnd)
5625     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); }
emitVerilog()5626     virtual string emitVerilog() override { return "%f(& %l)"; }
emitC()5627     virtual string emitC() override { return "VL_REDAND_%nq%lq(%lw, %P, %li)"; }
cleanOut()5628     virtual bool cleanOut() const override { return true; }
cleanLhs()5629     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5630     virtual bool sizeMattersLhs() const override { return false; }
5631 };
5632 class AstRedOr final : public AstNodeUniop {
5633 public:
AstRedOr(FileLine * fl,AstNode * lhsp)5634     AstRedOr(FileLine* fl, AstNode* lhsp)
5635         : ASTGEN_SUPER_RedOr(fl, lhsp) {
5636         dtypeSetBit();
5637     }
ASTNODE_NODE_FUNCS(RedOr)5638     ASTNODE_NODE_FUNCS(RedOr)
5639     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); }
emitVerilog()5640     virtual string emitVerilog() override { return "%f(| %l)"; }
emitC()5641     virtual string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; }
cleanOut()5642     virtual bool cleanOut() const override { return true; }
cleanLhs()5643     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5644     virtual bool sizeMattersLhs() const override { return false; }
5645 };
5646 class AstRedXor final : public AstNodeUniop {
5647 public:
AstRedXor(FileLine * fl,AstNode * lhsp)5648     AstRedXor(FileLine* fl, AstNode* lhsp)
5649         : ASTGEN_SUPER_RedXor(fl, lhsp) {
5650         dtypeSetBit();
5651     }
ASTNODE_NODE_FUNCS(RedXor)5652     ASTNODE_NODE_FUNCS(RedXor)
5653     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); }
emitVerilog()5654     virtual string emitVerilog() override { return "%f(^ %l)"; }
emitC()5655     virtual string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; }
cleanOut()5656     virtual bool cleanOut() const override { return false; }
cleanLhs()5657     virtual bool cleanLhs() const override {
5658         const int w = lhsp()->width();
5659         return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16);
5660     }
sizeMattersLhs()5661     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5662     virtual int instrCount() const override { return 1 + V3Number::log2b(width()); }
5663 };
5664 
5665 class AstLenN final : public AstNodeUniop {
5666     // Length of a string
5667 public:
AstLenN(FileLine * fl,AstNode * lhsp)5668     AstLenN(FileLine* fl, AstNode* lhsp)
5669         : ASTGEN_SUPER_LenN(fl, lhsp) {
5670         dtypeSetSigned32();
5671     }
ASTNODE_NODE_FUNCS(LenN)5672     ASTNODE_NODE_FUNCS(LenN)
5673     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); }
emitVerilog()5674     virtual string emitVerilog() override { return "%f(%l)"; }
emitC()5675     virtual string emitC() override { return "VL_LEN_IN(%li)"; }
cleanOut()5676     virtual bool cleanOut() const override { return true; }
cleanLhs()5677     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5678     virtual bool sizeMattersLhs() const override { return false; }
5679 };
5680 class AstLogNot final : public AstNodeUniop {
5681 public:
AstLogNot(FileLine * fl,AstNode * lhsp)5682     AstLogNot(FileLine* fl, AstNode* lhsp)
5683         : ASTGEN_SUPER_LogNot(fl, lhsp) {
5684         dtypeSetBit();
5685     }
ASTNODE_NODE_FUNCS(LogNot)5686     ASTNODE_NODE_FUNCS(LogNot)
5687     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); }
emitVerilog()5688     virtual string emitVerilog() override { return "%f(! %l)"; }
emitC()5689     virtual string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; }
emitSimpleOperator()5690     virtual string emitSimpleOperator() override { return "!"; }
cleanOut()5691     virtual bool cleanOut() const override { return true; }
cleanLhs()5692     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5693     virtual bool sizeMattersLhs() const override { return false; }
5694 };
5695 class AstNot final : public AstNodeUniop {
5696 public:
AstNot(FileLine * fl,AstNode * lhsp)5697     AstNot(FileLine* fl, AstNode* lhsp)
5698         : ASTGEN_SUPER_Not(fl, lhsp) {
5699         dtypeFrom(lhsp);
5700     }
ASTNODE_NODE_FUNCS(Not)5701     ASTNODE_NODE_FUNCS(Not)
5702     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); }
emitVerilog()5703     virtual string emitVerilog() override { return "%f(~ %l)"; }
emitC()5704     virtual string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; }
emitSimpleOperator()5705     virtual string emitSimpleOperator() override { return "~"; }
cleanOut()5706     virtual bool cleanOut() const override { return false; }
cleanLhs()5707     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()5708     virtual bool sizeMattersLhs() const override { return true; }
5709 };
5710 class AstExtend final : public AstNodeUniop {
5711     // Expand a value into a wider entity by 0 extension.  Width is implied from nodep->width()
5712 public:
AstExtend(FileLine * fl,AstNode * lhsp)5713     AstExtend(FileLine* fl, AstNode* lhsp)
5714         : ASTGEN_SUPER_Extend(fl, lhsp) {}
AstExtend(FileLine * fl,AstNode * lhsp,int width)5715     AstExtend(FileLine* fl, AstNode* lhsp, int width)
5716         : ASTGEN_SUPER_Extend(fl, lhsp) {
5717         dtypeSetLogicSized(width, VSigning::UNSIGNED);
5718     }
ASTNODE_NODE_FUNCS(Extend)5719     ASTNODE_NODE_FUNCS(Extend)
5720     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
emitVerilog()5721     virtual string emitVerilog() override { return "%l"; }
emitC()5722     virtual string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; }
cleanOut()5723     virtual bool cleanOut() const override { return true; }
cleanLhs()5724     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5725     virtual bool sizeMattersLhs() const override {
5726         return false;  // Because the EXTEND operator self-casts
5727     }
instrCount()5728     virtual int instrCount() const override { return 0; }
5729 };
5730 class AstExtendS final : public AstNodeUniop {
5731     // Expand a value into a wider entity by sign extension.  Width is implied from nodep->width()
5732 public:
AstExtendS(FileLine * fl,AstNode * lhsp)5733     AstExtendS(FileLine* fl, AstNode* lhsp)
5734         : ASTGEN_SUPER_ExtendS(fl, lhsp) {}
AstExtendS(FileLine * fl,AstNode * lhsp,int width)5735     AstExtendS(FileLine* fl, AstNode* lhsp, int width)
5736         // Important that widthMin be correct, as opExtend requires it after V3Expand
5737         : ASTGEN_SUPER_ExtendS(fl, lhsp) {
5738         dtypeSetLogicSized(width, VSigning::UNSIGNED);
5739     }
ASTNODE_NODE_FUNCS(ExtendS)5740     ASTNODE_NODE_FUNCS(ExtendS)
5741     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5742         out.opExtendS(lhs, lhsp()->widthMinV());
5743     }
emitVerilog()5744     virtual string emitVerilog() override { return "%l"; }
emitC()5745     virtual string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
cleanOut()5746     virtual bool cleanOut() const override { return false; }
cleanLhs()5747     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5748     virtual bool sizeMattersLhs() const override {
5749         return false;  // Because the EXTEND operator self-casts
5750     }
instrCount()5751     virtual int instrCount() const override { return 0; }
signedFlavor()5752     virtual bool signedFlavor() const override { return true; }
5753 };
5754 class AstSigned final : public AstNodeUniop {
5755     // $signed(lhs)
5756 public:
AstSigned(FileLine * fl,AstNode * lhsp)5757     AstSigned(FileLine* fl, AstNode* lhsp)
5758         : ASTGEN_SUPER_Signed(fl, lhsp) {
5759         UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
5760                     "not coded to create after dtypes resolved");
5761     }
ASTNODE_NODE_FUNCS(Signed)5762     ASTNODE_NODE_FUNCS(Signed)
5763     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5764         out.opAssign(lhs);
5765         out.isSigned(false);
5766     }
emitVerilog()5767     virtual string emitVerilog() override { return "%f$signed(%l)"; }
emitC()5768     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5769     virtual bool cleanOut() const override { return false; }
cleanLhs()5770     virtual bool cleanLhs() const override { return false; }  // Eliminated before matters
sizeMattersLhs()5771     virtual bool sizeMattersLhs() const override { return true; }  // Eliminated before matters
instrCount()5772     virtual int instrCount() const override { return 0; }
5773 };
5774 class AstUnsigned final : public AstNodeUniop {
5775     // $unsigned(lhs)
5776 public:
AstUnsigned(FileLine * fl,AstNode * lhsp)5777     AstUnsigned(FileLine* fl, AstNode* lhsp)
5778         : ASTGEN_SUPER_Unsigned(fl, lhsp) {
5779         UASSERT_OBJ(!v3Global.assertDTypesResolved(), this,
5780                     "not coded to create after dtypes resolved");
5781     }
ASTNODE_NODE_FUNCS(Unsigned)5782     ASTNODE_NODE_FUNCS(Unsigned)
5783     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5784         out.opAssign(lhs);
5785         out.isSigned(false);
5786     }
emitVerilog()5787     virtual string emitVerilog() override { return "%f$unsigned(%l)"; }
emitC()5788     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5789     virtual bool cleanOut() const override { return false; }
cleanLhs()5790     virtual bool cleanLhs() const override { return false; }  // Eliminated before matters
sizeMattersLhs()5791     virtual bool sizeMattersLhs() const override { return true; }  // Eliminated before matters
instrCount()5792     virtual int instrCount() const override { return 0; }
5793 };
5794 class AstRToIS final : public AstNodeUniop {
5795     // $rtoi(lhs)
5796 public:
AstRToIS(FileLine * fl,AstNode * lhsp)5797     AstRToIS(FileLine* fl, AstNode* lhsp)
5798         : ASTGEN_SUPER_RToIS(fl, lhsp) {
5799         dtypeSetSigned32();
5800     }
ASTNODE_NODE_FUNCS(RToIS)5801     ASTNODE_NODE_FUNCS(RToIS)
5802     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); }
emitVerilog()5803     virtual string emitVerilog() override { return "%f$rtoi(%l)"; }
emitC()5804     virtual string emitC() override { return "VL_RTOI_I_D(%li)"; }
cleanOut()5805     virtual bool cleanOut() const override { return false; }
cleanLhs()5806     virtual bool cleanLhs() const override { return false; }  // Eliminated before matters
sizeMattersLhs()5807     virtual bool sizeMattersLhs() const override { return false; }  // Eliminated before matters
instrCount()5808     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
5809 };
5810 class AstRToIRoundS final : public AstNodeUniop {
5811     // Convert real to integer, with arbitrary sized output (not just "integer" format)
5812 public:
AstRToIRoundS(FileLine * fl,AstNode * lhsp)5813     AstRToIRoundS(FileLine* fl, AstNode* lhsp)
5814         : ASTGEN_SUPER_RToIRoundS(fl, lhsp) {
5815         dtypeSetSigned32();
5816     }
ASTNODE_NODE_FUNCS(RToIRoundS)5817     ASTNODE_NODE_FUNCS(RToIRoundS)
5818     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5819         out.opRToIRoundS(lhs);
5820     }
emitVerilog()5821     virtual string emitVerilog() override { return "%f$rtoi_rounded(%l)"; }
emitC()5822     virtual string emitC() override {
5823         return isWide() ? "VL_RTOIROUND_%nq_D(%nw, %P, %li)" : "VL_RTOIROUND_%nq_D(%li)";
5824     }
cleanOut()5825     virtual bool cleanOut() const override { return false; }
cleanLhs()5826     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()5827     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5828     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
5829 };
5830 class AstIToRD final : public AstNodeUniop {
5831     // $itor where lhs is unsigned
5832 public:
AstIToRD(FileLine * fl,AstNode * lhsp)5833     AstIToRD(FileLine* fl, AstNode* lhsp)
5834         : ASTGEN_SUPER_IToRD(fl, lhsp) {
5835         dtypeSetDouble();
5836     }
ASTNODE_NODE_FUNCS(IToRD)5837     ASTNODE_NODE_FUNCS(IToRD)
5838     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); }
emitVerilog()5839     virtual string emitVerilog() override { return "%f$itor(%l)"; }
emitC()5840     virtual string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; }
cleanOut()5841     virtual bool cleanOut() const override { return false; }
cleanLhs()5842     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5843     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5844     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
5845 };
5846 class AstISToRD final : public AstNodeUniop {
5847     // $itor where lhs is signed
5848 public:
AstISToRD(FileLine * fl,AstNode * lhsp)5849     AstISToRD(FileLine* fl, AstNode* lhsp)
5850         : ASTGEN_SUPER_ISToRD(fl, lhsp) {
5851         dtypeSetDouble();
5852     }
ASTNODE_NODE_FUNCS(ISToRD)5853     ASTNODE_NODE_FUNCS(ISToRD)
5854     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); }
emitVerilog()5855     virtual string emitVerilog() override { return "%f$itor($signed(%l))"; }
emitC()5856     virtual string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; }
emitCheckMaxWords()5857     virtual bool emitCheckMaxWords() override { return true; }
cleanOut()5858     virtual bool cleanOut() const override { return false; }
cleanLhs()5859     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5860     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5861     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
5862 };
5863 class AstRealToBits final : public AstNodeUniop {
5864 public:
AstRealToBits(FileLine * fl,AstNode * lhsp)5865     AstRealToBits(FileLine* fl, AstNode* lhsp)
5866         : ASTGEN_SUPER_RealToBits(fl, lhsp) {
5867         dtypeSetUInt64();
5868     }
ASTNODE_NODE_FUNCS(RealToBits)5869     ASTNODE_NODE_FUNCS(RealToBits)
5870     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5871         out.opRealToBits(lhs);
5872     }
emitVerilog()5873     virtual string emitVerilog() override { return "%f$realtobits(%l)"; }
emitC()5874     virtual string emitC() override { return "VL_CVT_Q_D(%li)"; }
cleanOut()5875     virtual bool cleanOut() const override { return false; }
cleanLhs()5876     virtual bool cleanLhs() const override { return false; }  // Eliminated before matters
sizeMattersLhs()5877     virtual bool sizeMattersLhs() const override { return false; }  // Eliminated before matters
instrCount()5878     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
5879 };
5880 class AstBitsToRealD final : public AstNodeUniop {
5881 public:
AstBitsToRealD(FileLine * fl,AstNode * lhsp)5882     AstBitsToRealD(FileLine* fl, AstNode* lhsp)
5883         : ASTGEN_SUPER_BitsToRealD(fl, lhsp) {
5884         dtypeSetDouble();
5885     }
ASTNODE_NODE_FUNCS(BitsToRealD)5886     ASTNODE_NODE_FUNCS(BitsToRealD)
5887     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5888         out.opBitsToRealD(lhs);
5889     }
emitVerilog()5890     virtual string emitVerilog() override { return "%f$bitstoreal(%l)"; }
emitC()5891     virtual string emitC() override { return "VL_CVT_D_Q(%li)"; }
cleanOut()5892     virtual bool cleanOut() const override { return false; }
cleanLhs()5893     virtual bool cleanLhs() const override { return false; }  // Eliminated before matters
sizeMattersLhs()5894     virtual bool sizeMattersLhs() const override { return false; }  // Eliminated before matters
instrCount()5895     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
5896 };
5897 
5898 class AstCLog2 final : public AstNodeUniop {
5899 public:
AstCLog2(FileLine * fl,AstNode * lhsp)5900     AstCLog2(FileLine* fl, AstNode* lhsp)
5901         : ASTGEN_SUPER_CLog2(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CLog2)5902     ASTNODE_NODE_FUNCS(CLog2)
5903     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); }
emitVerilog()5904     virtual string emitVerilog() override { return "%f$clog2(%l)"; }
emitC()5905     virtual string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; }
cleanOut()5906     virtual bool cleanOut() const override { return false; }
cleanLhs()5907     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5908     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5909     virtual int instrCount() const override { return widthInstrs() * 16; }
5910 };
5911 class AstCountBits final : public AstNodeQuadop {
5912     // Number of bits set in vector
5913 public:
AstCountBits(FileLine * fl,AstNode * exprp,AstNode * ctrl1p)5914     AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p)
5915         : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl1p->cloneTree(false),
5916                                  ctrl1p->cloneTree(false)) {}
AstCountBits(FileLine * fl,AstNode * exprp,AstNode * ctrl1p,AstNode * ctrl2p)5917     AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p)
5918         : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl2p->cloneTree(false)) {}
AstCountBits(FileLine * fl,AstNode * exprp,AstNode * ctrl1p,AstNode * ctrl2p,AstNode * ctrl3p)5919     AstCountBits(FileLine* fl, AstNode* exprp, AstNode* ctrl1p, AstNode* ctrl2p, AstNode* ctrl3p)
5920         : ASTGEN_SUPER_CountBits(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {}
ASTNODE_NODE_FUNCS(CountBits)5921     ASTNODE_NODE_FUNCS(CountBits)
5922     virtual void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1,
5923                                const V3Number& ctrl2, const V3Number& ctrl3) override {
5924         out.opCountBits(expr, ctrl1, ctrl2, ctrl3);
5925     }
emitVerilog()5926     virtual string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; }
emitC()5927     virtual string emitC() override { return ""; }
cleanOut()5928     virtual bool cleanOut() const override { return false; }
cleanLhs()5929     virtual bool cleanLhs() const override { return true; }
cleanRhs()5930     virtual bool cleanRhs() const override { return true; }
cleanThs()5931     virtual bool cleanThs() const override { return true; }
cleanFhs()5932     virtual bool cleanFhs() const override { return true; }
sizeMattersLhs()5933     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()5934     virtual bool sizeMattersRhs() const override { return false; }
sizeMattersThs()5935     virtual bool sizeMattersThs() const override { return false; }
sizeMattersFhs()5936     virtual bool sizeMattersFhs() const override { return false; }
instrCount()5937     virtual int instrCount() const override { return widthInstrs() * 16; }
5938 };
5939 class AstCountOnes final : public AstNodeUniop {
5940     // Number of bits set in vector
5941 public:
AstCountOnes(FileLine * fl,AstNode * lhsp)5942     AstCountOnes(FileLine* fl, AstNode* lhsp)
5943         : ASTGEN_SUPER_CountOnes(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CountOnes)5944     ASTNODE_NODE_FUNCS(CountOnes)
5945     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5946         out.opCountOnes(lhs);
5947     }
emitVerilog()5948     virtual string emitVerilog() override { return "%f$countones(%l)"; }
emitC()5949     virtual string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; }
cleanOut()5950     virtual bool cleanOut() const override { return false; }
cleanLhs()5951     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()5952     virtual bool sizeMattersLhs() const override { return false; }
instrCount()5953     virtual int instrCount() const override { return widthInstrs() * 16; }
5954 };
5955 class AstIsUnknown final : public AstNodeUniop {
5956     // True if any unknown bits
5957 public:
AstIsUnknown(FileLine * fl,AstNode * lhsp)5958     AstIsUnknown(FileLine* fl, AstNode* lhsp)
5959         : ASTGEN_SUPER_IsUnknown(fl, lhsp) {
5960         dtypeSetBit();
5961     }
ASTNODE_NODE_FUNCS(IsUnknown)5962     ASTNODE_NODE_FUNCS(IsUnknown)
5963     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
5964         out.opIsUnknown(lhs);
5965     }
emitVerilog()5966     virtual string emitVerilog() override { return "%f$isunknown(%l)"; }
emitC()5967     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5968     virtual bool cleanOut() const override { return false; }
cleanLhs()5969     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()5970     virtual bool sizeMattersLhs() const override { return false; }
5971 };
5972 class AstIsUnbounded final : public AstNodeUniop {
5973     // True if is unmbounded ($)
5974 public:
AstIsUnbounded(FileLine * fl,AstNode * lhsp)5975     AstIsUnbounded(FileLine* fl, AstNode* lhsp)
5976         : ASTGEN_SUPER_IsUnbounded(fl, lhsp) {
5977         dtypeSetBit();
5978     }
ASTNODE_NODE_FUNCS(IsUnbounded)5979     ASTNODE_NODE_FUNCS(IsUnbounded)
5980     virtual void numberOperate(V3Number& out, const V3Number&) override {
5981         // Any constant isn't unbounded
5982         out.setZero();
5983     }
emitVerilog()5984     virtual string emitVerilog() override { return "%f$isunbounded(%l)"; }
emitC()5985     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()5986     virtual bool cleanOut() const override { return false; }
cleanLhs()5987     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()5988     virtual bool sizeMattersLhs() const override { return false; }
5989 };
5990 class AstOneHot final : public AstNodeUniop {
5991     // True if only single bit set in vector
5992 public:
AstOneHot(FileLine * fl,AstNode * lhsp)5993     AstOneHot(FileLine* fl, AstNode* lhsp)
5994         : ASTGEN_SUPER_OneHot(fl, lhsp) {
5995         dtypeSetBit();
5996     }
ASTNODE_NODE_FUNCS(OneHot)5997     ASTNODE_NODE_FUNCS(OneHot)
5998     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); }
emitVerilog()5999     virtual string emitVerilog() override { return "%f$onehot(%l)"; }
emitC()6000     virtual string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; }
cleanOut()6001     virtual bool cleanOut() const override { return true; }
cleanLhs()6002     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6003     virtual bool sizeMattersLhs() const override { return false; }
instrCount()6004     virtual int instrCount() const override { return widthInstrs() * 4; }
6005 };
6006 class AstOneHot0 final : public AstNodeUniop {
6007     // True if only single bit, or no bits set in vector
6008 public:
AstOneHot0(FileLine * fl,AstNode * lhsp)6009     AstOneHot0(FileLine* fl, AstNode* lhsp)
6010         : ASTGEN_SUPER_OneHot0(fl, lhsp) {
6011         dtypeSetBit();
6012     }
ASTNODE_NODE_FUNCS(OneHot0)6013     ASTNODE_NODE_FUNCS(OneHot0)
6014     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); }
emitVerilog()6015     virtual string emitVerilog() override { return "%f$onehot0(%l)"; }
emitC()6016     virtual string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; }
cleanOut()6017     virtual bool cleanOut() const override { return true; }
cleanLhs()6018     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6019     virtual bool sizeMattersLhs() const override { return false; }
instrCount()6020     virtual int instrCount() const override { return widthInstrs() * 3; }
6021 };
6022 
6023 class AstCast final : public AstNode {
6024     // Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc
6025 public:
AstCast(FileLine * fl,AstNode * lhsp,VFlagChildDType,AstNodeDType * dtp)6026     AstCast(FileLine* fl, AstNode* lhsp, VFlagChildDType, AstNodeDType* dtp)
6027         : ASTGEN_SUPER_Cast(fl) {
6028         setOp1p(lhsp);
6029         setOp2p(dtp);
6030         dtypeFrom(dtp);
6031     }
AstCast(FileLine * fl,AstNode * lhsp,AstNodeDType * dtp)6032     AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtp)
6033         : ASTGEN_SUPER_Cast(fl) {
6034         setOp1p(lhsp);
6035         dtypeFrom(dtp);
6036     }
ASTNODE_NODE_FUNCS(Cast)6037     ASTNODE_NODE_FUNCS(Cast)
6038     virtual bool hasDType() const override { return true; }
emitVerilog()6039     virtual string emitVerilog() { return "((%d)'(%l))"; }
cleanOut()6040     virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); }
cleanLhs()6041     virtual bool cleanLhs() const { return true; }
sizeMattersLhs()6042     virtual bool sizeMattersLhs() const { return false; }
lhsp()6043     AstNode* lhsp() const { return op1p(); }
fromp()6044     AstNode* fromp() const { return lhsp(); }
lhsp(AstNode * nodep)6045     void lhsp(AstNode* nodep) { setOp1p(nodep); }
getChildDTypep()6046     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
childDTypep()6047     AstNodeDType* childDTypep() const { return VN_AS(op2p(), NodeDType); }
subDTypep()6048     virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
6049 };
6050 
6051 class AstCastDynamic final : public AstNodeBiop {
6052     // Verilog $cast used as a function
6053     // Task usage of $cast is converted during parse to assert($cast(...))
6054     // Parents: MATH
6055     // Children: MATH
6056     // lhsp() is value (we are converting FROM) to match AstCCast etc, this
6057     // is opposite of $cast's order, because the first access is to the
6058     // value reading from.  Suggest use fromp()/top() instead of lhsp/rhsp().
6059 public:
AstCastDynamic(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6060     AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6061         : ASTGEN_SUPER_CastDynamic(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(CastDynamic)6062     ASTNODE_NODE_FUNCS(CastDynamic)
6063     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6064         V3ERROR_NA;
6065     }
cloneType(AstNode * lhsp,AstNode * rhsp)6066     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6067         return new AstCastDynamic(this->fileline(), lhsp, rhsp);
6068     }
emitVerilog()6069     virtual string emitVerilog() override { return "%f$cast(%r, %l)"; }
emitC()6070     virtual string emitC() override { return "VL_DYNAMIC_CAST(%r, %l)"; }
cleanOut()6071     virtual bool cleanOut() const override { return true; }
cleanLhs()6072     virtual bool cleanLhs() const override { return true; }
cleanRhs()6073     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6074     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6075     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6076     virtual int instrCount() const override { return widthInstrs() * 20; }
isPure()6077     virtual bool isPure() const override { return true; }
fromp()6078     AstNode* fromp() const { return lhsp(); }
top()6079     AstNode* top() const { return rhsp(); }
6080 };
6081 
6082 class AstCastParse final : public AstNode {
6083     // Cast to appropriate type, where we haven't determined yet what the data type is
6084 public:
AstCastParse(FileLine * fl,AstNode * lhsp,AstNode * dtp)6085     AstCastParse(FileLine* fl, AstNode* lhsp, AstNode* dtp)
6086         : ASTGEN_SUPER_CastParse(fl) {
6087         setOp1p(lhsp);
6088         setOp2p(dtp);
6089     }
ASTNODE_NODE_FUNCS(CastParse)6090     ASTNODE_NODE_FUNCS(CastParse)
6091     virtual string emitVerilog() { return "((%d)'(%l))"; }
emitC()6092     virtual string emitC() { V3ERROR_NA_RETURN(""); }
cleanOut()6093     virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); }
cleanLhs()6094     virtual bool cleanLhs() const { return true; }
sizeMattersLhs()6095     virtual bool sizeMattersLhs() const { return false; }
lhsp()6096     AstNode* lhsp() const { return op1p(); }
dtp()6097     AstNode* dtp() const { return op2p(); }
6098 };
6099 
6100 class AstCastSize final : public AstNode {
6101     // Cast to specific size; signed/twostate inherited from lower element per IEEE
6102 public:
AstCastSize(FileLine * fl,AstNode * lhsp,AstConst * rhsp)6103     AstCastSize(FileLine* fl, AstNode* lhsp, AstConst* rhsp)
6104         : ASTGEN_SUPER_CastSize(fl) {
6105         setOp1p(lhsp);
6106         setOp2p(rhsp);
6107     }
ASTNODE_NODE_FUNCS(CastSize)6108     ASTNODE_NODE_FUNCS(CastSize)
6109     // No hasDType because widthing removes this node before the hasDType check
6110     virtual string emitVerilog() { return "((%r)'(%l))"; }
cleanOut()6111     virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); }
cleanLhs()6112     virtual bool cleanLhs() const { return true; }
sizeMattersLhs()6113     virtual bool sizeMattersLhs() const { return false; }
lhsp()6114     AstNode* lhsp() const { return op1p(); }
rhsp()6115     AstNode* rhsp() const { return op2p(); }
6116 };
6117 
6118 class AstCCast final : public AstNodeUniop {
6119     // Cast to C-based data type
6120 private:
6121     int m_size;
6122 
6123 public:
6124     AstCCast(FileLine* fl, AstNode* lhsp, int setwidth, int minwidth = -1)
ASTGEN_SUPER_CCast(fl,lhsp)6125         : ASTGEN_SUPER_CCast(fl, lhsp) {
6126         m_size = setwidth;
6127         if (setwidth) {
6128             if (minwidth == -1) minwidth = setwidth;
6129             dtypeSetLogicUnsized(setwidth, minwidth, VSigning::UNSIGNED);
6130         }
6131     }
AstCCast(FileLine * fl,AstNode * lhsp,AstNode * typeFromp)6132     AstCCast(FileLine* fl, AstNode* lhsp, AstNode* typeFromp)
6133         : ASTGEN_SUPER_CCast(fl, lhsp) {
6134         dtypeFrom(typeFromp);
6135         m_size = width();
6136     }
ASTNODE_NODE_FUNCS(CCast)6137     ASTNODE_NODE_FUNCS(CCast)
6138     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); }
emitVerilog()6139     virtual string emitVerilog() override { return "%f$_CAST(%l)"; }
emitC()6140     virtual string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; }
cleanOut()6141     virtual bool cleanOut() const override { return true; }
cleanLhs()6142     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6143     virtual bool sizeMattersLhs() const override { return false; }  // Special cased in V3Cast
same(const AstNode * samep)6144     virtual bool same(const AstNode* samep) const override {
6145         return size() == static_cast<const AstCCast*>(samep)->size();
6146     }
6147     virtual void dump(std::ostream& str = std::cout) const override;
6148     //
size()6149     int size() const { return m_size; }
6150 };
6151 
6152 class AstCvtPackString final : public AstNodeUniop {
6153     // Convert to Verilator Packed String (aka verilog "string")
6154 public:
AstCvtPackString(FileLine * fl,AstNode * lhsp)6155     AstCvtPackString(FileLine* fl, AstNode* lhsp)
6156         : ASTGEN_SUPER_CvtPackString(fl, lhsp) {
6157         dtypeSetString();
6158     }
ASTNODE_NODE_FUNCS(CvtPackString)6159     ASTNODE_NODE_FUNCS(CvtPackString)
6160     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
emitVerilog()6161     virtual string emitVerilog() override { return "%f$_CAST(%l)"; }
emitC()6162     virtual string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; }
cleanOut()6163     virtual bool cleanOut() const override { return true; }
cleanLhs()6164     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6165     virtual bool sizeMattersLhs() const override { return false; }
same(const AstNode * samep)6166     virtual bool same(const AstNode* samep) const override { return true; }
6167 };
6168 
6169 class AstFEof final : public AstNodeUniop {
6170 public:
AstFEof(FileLine * fl,AstNode * lhsp)6171     AstFEof(FileLine* fl, AstNode* lhsp)
6172         : ASTGEN_SUPER_FEof(fl, lhsp) {}
ASTNODE_NODE_FUNCS(FEof)6173     ASTNODE_NODE_FUNCS(FEof)
6174     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
emitVerilog()6175     virtual string emitVerilog() override { return "%f$feof(%l)"; }
emitC()6176     virtual string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
cleanOut()6177     virtual bool cleanOut() const override { return true; }
cleanLhs()6178     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6179     virtual bool sizeMattersLhs() const override { return false; }
instrCount()6180     virtual int instrCount() const override { return widthInstrs() * 16; }
isPure()6181     virtual bool isPure() const override {
6182         return false;
6183     }  // SPECIAL: $display has 'visual' ordering
filep()6184     AstNode* filep() const { return lhsp(); }
6185 };
6186 
6187 class AstFError final : public AstNodeMath {
6188 public:
AstFError(FileLine * fl,AstNode * filep,AstNode * strp)6189     AstFError(FileLine* fl, AstNode* filep, AstNode* strp)
6190         : ASTGEN_SUPER_FError(fl) {
6191         setOp1p(filep);
6192         setOp2p(strp);
6193     }
ASTNODE_NODE_FUNCS(FError)6194     ASTNODE_NODE_FUNCS(FError)
6195     virtual string emitVerilog() override { return "%f$ferror(%l, %r)"; }
emitC()6196     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()6197     virtual bool cleanOut() const override { return true; }
cleanLhs()6198     virtual bool cleanLhs() const { return true; }
sizeMattersLhs()6199     virtual bool sizeMattersLhs() const { return false; }
instrCount()6200     virtual int instrCount() const override { return widthInstrs() * 64; }
isPure()6201     virtual bool isPure() const override {
6202         return false;
6203     }  // SPECIAL: $display has 'visual' ordering
filep(AstNode * nodep)6204     void filep(AstNode* nodep) { setOp1p(nodep); }
filep()6205     AstNode* filep() const { return op1p(); }
strp(AstNode * nodep)6206     void strp(AstNode* nodep) { setOp2p(nodep); }
strp()6207     AstNode* strp() const { return op2p(); }
same(const AstNode * samep)6208     virtual bool same(const AstNode* samep) const override { return true; }
6209 };
6210 
6211 class AstFGetC final : public AstNodeUniop {
6212 public:
AstFGetC(FileLine * fl,AstNode * lhsp)6213     AstFGetC(FileLine* fl, AstNode* lhsp)
6214         : ASTGEN_SUPER_FGetC(fl, lhsp) {}
ASTNODE_NODE_FUNCS(FGetC)6215     ASTNODE_NODE_FUNCS(FGetC)
6216     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
emitVerilog()6217     virtual string emitVerilog() override { return "%f$fgetc(%l)"; }
6218     // Non-existent filehandle returns EOF
emitC()6219     virtual string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
cleanOut()6220     virtual bool cleanOut() const override { return false; }
cleanLhs()6221     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6222     virtual bool sizeMattersLhs() const override { return false; }
instrCount()6223     virtual int instrCount() const override { return widthInstrs() * 64; }
isPure()6224     virtual bool isPure() const override {
6225         return false;
6226     }  // SPECIAL: $display has 'visual' ordering
filep()6227     AstNode* filep() const { return lhsp(); }
6228 };
6229 
6230 class AstFUngetC final : public AstNodeBiop {
6231 public:
AstFUngetC(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6232     AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6233         : ASTGEN_SUPER_FUngetC(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FUngetC)6234     ASTNODE_NODE_FUNCS(FUngetC)
6235     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6236         V3ERROR_NA;
6237     }
cloneType(AstNode * lhsp,AstNode * rhsp)6238     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6239         return new AstFUngetC(this->fileline(), lhsp, rhsp);
6240     }
emitVerilog()6241     virtual string emitVerilog() override { return "%f$ungetc(%r, %l)"; }
6242     // Non-existent filehandle returns EOF
emitC()6243     virtual string emitC() override {
6244         return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)";
6245     }
cleanOut()6246     virtual bool cleanOut() const override { return false; }
cleanLhs()6247     virtual bool cleanLhs() const override { return true; }
cleanRhs()6248     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6249     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6250     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6251     virtual int instrCount() const override { return widthInstrs() * 64; }
isPure()6252     virtual bool isPure() const override {
6253         return false;
6254     }  // SPECIAL: $display has 'visual' ordering
filep()6255     AstNode* filep() const { return lhsp(); }
charp()6256     AstNode* charp() const { return rhsp(); }
6257 };
6258 
6259 class AstNodeSystemUniop VL_NOT_FINAL : public AstNodeUniop {
6260 public:
AstNodeSystemUniop(AstType t,FileLine * fl,AstNode * lhsp)6261     AstNodeSystemUniop(AstType t, FileLine* fl, AstNode* lhsp)
6262         : AstNodeUniop(t, fl, lhsp) {
6263         dtypeSetDouble();
6264     }
ASTNODE_BASE_FUNCS(NodeSystemUniop)6265     ASTNODE_BASE_FUNCS(NodeSystemUniop)
6266     virtual bool cleanOut() const override { return true; }
cleanLhs()6267     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()6268     virtual bool sizeMattersLhs() const override { return false; }
instrCount()6269     virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
doubleFlavor()6270     virtual bool doubleFlavor() const override { return true; }
6271 };
6272 
6273 class AstLogD final : public AstNodeSystemUniop {
6274 public:
AstLogD(FileLine * fl,AstNode * lhsp)6275     AstLogD(FileLine* fl, AstNode* lhsp)
6276         : ASTGEN_SUPER_LogD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(LogD)6277     ASTNODE_NODE_FUNCS(LogD)
6278     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6279         out.setDouble(std::log(lhs.toDouble()));
6280     }
emitVerilog()6281     virtual string emitVerilog() override { return "%f$ln(%l)"; }
emitC()6282     virtual string emitC() override { return "log(%li)"; }
6283 };
6284 class AstLog10D final : public AstNodeSystemUniop {
6285 public:
AstLog10D(FileLine * fl,AstNode * lhsp)6286     AstLog10D(FileLine* fl, AstNode* lhsp)
6287         : ASTGEN_SUPER_Log10D(fl, lhsp) {}
ASTNODE_NODE_FUNCS(Log10D)6288     ASTNODE_NODE_FUNCS(Log10D)
6289     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6290         out.setDouble(std::log10(lhs.toDouble()));
6291     }
emitVerilog()6292     virtual string emitVerilog() override { return "%f$log10(%l)"; }
emitC()6293     virtual string emitC() override { return "log10(%li)"; }
6294 };
6295 
6296 class AstExpD final : public AstNodeSystemUniop {
6297 public:
AstExpD(FileLine * fl,AstNode * lhsp)6298     AstExpD(FileLine* fl, AstNode* lhsp)
6299         : ASTGEN_SUPER_ExpD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(ExpD)6300     ASTNODE_NODE_FUNCS(ExpD)
6301     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6302         out.setDouble(std::exp(lhs.toDouble()));
6303     }
emitVerilog()6304     virtual string emitVerilog() override { return "%f$exp(%l)"; }
emitC()6305     virtual string emitC() override { return "exp(%li)"; }
6306 };
6307 
6308 class AstSqrtD final : public AstNodeSystemUniop {
6309 public:
AstSqrtD(FileLine * fl,AstNode * lhsp)6310     AstSqrtD(FileLine* fl, AstNode* lhsp)
6311         : ASTGEN_SUPER_SqrtD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SqrtD)6312     ASTNODE_NODE_FUNCS(SqrtD)
6313     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6314         out.setDouble(std::sqrt(lhs.toDouble()));
6315     }
emitVerilog()6316     virtual string emitVerilog() override { return "%f$sqrt(%l)"; }
emitC()6317     virtual string emitC() override { return "sqrt(%li)"; }
6318 };
6319 
6320 class AstFloorD final : public AstNodeSystemUniop {
6321 public:
AstFloorD(FileLine * fl,AstNode * lhsp)6322     AstFloorD(FileLine* fl, AstNode* lhsp)
6323         : ASTGEN_SUPER_FloorD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(FloorD)6324     ASTNODE_NODE_FUNCS(FloorD)
6325     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6326         out.setDouble(std::floor(lhs.toDouble()));
6327     }
emitVerilog()6328     virtual string emitVerilog() override { return "%f$floor(%l)"; }
emitC()6329     virtual string emitC() override { return "floor(%li)"; }
6330 };
6331 
6332 class AstCeilD final : public AstNodeSystemUniop {
6333 public:
AstCeilD(FileLine * fl,AstNode * lhsp)6334     AstCeilD(FileLine* fl, AstNode* lhsp)
6335         : ASTGEN_SUPER_CeilD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CeilD)6336     ASTNODE_NODE_FUNCS(CeilD)
6337     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6338         out.setDouble(std::ceil(lhs.toDouble()));
6339     }
emitVerilog()6340     virtual string emitVerilog() override { return "%f$ceil(%l)"; }
emitC()6341     virtual string emitC() override { return "ceil(%li)"; }
6342 };
6343 
6344 class AstSinD final : public AstNodeSystemUniop {
6345 public:
AstSinD(FileLine * fl,AstNode * lhsp)6346     AstSinD(FileLine* fl, AstNode* lhsp)
6347         : ASTGEN_SUPER_SinD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SinD)6348     ASTNODE_NODE_FUNCS(SinD)
6349     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6350         out.setDouble(std::sin(lhs.toDouble()));
6351     }
emitVerilog()6352     virtual string emitVerilog() override { return "%f$sin(%l)"; }
emitC()6353     virtual string emitC() override { return "sin(%li)"; }
6354 };
6355 
6356 class AstCosD final : public AstNodeSystemUniop {
6357 public:
AstCosD(FileLine * fl,AstNode * lhsp)6358     AstCosD(FileLine* fl, AstNode* lhsp)
6359         : ASTGEN_SUPER_CosD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CosD)6360     ASTNODE_NODE_FUNCS(CosD)
6361     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6362         out.setDouble(std::cos(lhs.toDouble()));
6363     }
emitVerilog()6364     virtual string emitVerilog() override { return "%f$cos(%l)"; }
emitC()6365     virtual string emitC() override { return "cos(%li)"; }
6366 };
6367 
6368 class AstTanD final : public AstNodeSystemUniop {
6369 public:
AstTanD(FileLine * fl,AstNode * lhsp)6370     AstTanD(FileLine* fl, AstNode* lhsp)
6371         : ASTGEN_SUPER_TanD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TanD)6372     ASTNODE_NODE_FUNCS(TanD)
6373     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6374         out.setDouble(std::tan(lhs.toDouble()));
6375     }
emitVerilog()6376     virtual string emitVerilog() override { return "%f$tan(%l)"; }
emitC()6377     virtual string emitC() override { return "tan(%li)"; }
6378 };
6379 
6380 class AstAsinD final : public AstNodeSystemUniop {
6381 public:
AstAsinD(FileLine * fl,AstNode * lhsp)6382     AstAsinD(FileLine* fl, AstNode* lhsp)
6383         : ASTGEN_SUPER_AsinD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AsinD)6384     ASTNODE_NODE_FUNCS(AsinD)
6385     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6386         out.setDouble(std::asin(lhs.toDouble()));
6387     }
emitVerilog()6388     virtual string emitVerilog() override { return "%f$asin(%l)"; }
emitC()6389     virtual string emitC() override { return "asin(%li)"; }
6390 };
6391 
6392 class AstAcosD final : public AstNodeSystemUniop {
6393 public:
AstAcosD(FileLine * fl,AstNode * lhsp)6394     AstAcosD(FileLine* fl, AstNode* lhsp)
6395         : ASTGEN_SUPER_AcosD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AcosD)6396     ASTNODE_NODE_FUNCS(AcosD)
6397     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6398         out.setDouble(std::acos(lhs.toDouble()));
6399     }
emitVerilog()6400     virtual string emitVerilog() override { return "%f$acos(%l)"; }
emitC()6401     virtual string emitC() override { return "acos(%li)"; }
6402 };
6403 
6404 class AstAtanD final : public AstNodeSystemUniop {
6405 public:
AstAtanD(FileLine * fl,AstNode * lhsp)6406     AstAtanD(FileLine* fl, AstNode* lhsp)
6407         : ASTGEN_SUPER_AtanD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AtanD)6408     ASTNODE_NODE_FUNCS(AtanD)
6409     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6410         out.setDouble(std::atan(lhs.toDouble()));
6411     }
emitVerilog()6412     virtual string emitVerilog() override { return "%f$atan(%l)"; }
emitC()6413     virtual string emitC() override { return "atan(%li)"; }
6414 };
6415 
6416 class AstSinhD final : public AstNodeSystemUniop {
6417 public:
AstSinhD(FileLine * fl,AstNode * lhsp)6418     AstSinhD(FileLine* fl, AstNode* lhsp)
6419         : ASTGEN_SUPER_SinhD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(SinhD)6420     ASTNODE_NODE_FUNCS(SinhD)
6421     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6422         out.setDouble(std::sinh(lhs.toDouble()));
6423     }
emitVerilog()6424     virtual string emitVerilog() override { return "%f$sinh(%l)"; }
emitC()6425     virtual string emitC() override { return "sinh(%li)"; }
6426 };
6427 
6428 class AstCoshD final : public AstNodeSystemUniop {
6429 public:
AstCoshD(FileLine * fl,AstNode * lhsp)6430     AstCoshD(FileLine* fl, AstNode* lhsp)
6431         : ASTGEN_SUPER_CoshD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CoshD)6432     ASTNODE_NODE_FUNCS(CoshD)
6433     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6434         out.setDouble(std::cosh(lhs.toDouble()));
6435     }
emitVerilog()6436     virtual string emitVerilog() override { return "%f$cosh(%l)"; }
emitC()6437     virtual string emitC() override { return "cosh(%li)"; }
6438 };
6439 
6440 class AstTanhD final : public AstNodeSystemUniop {
6441 public:
AstTanhD(FileLine * fl,AstNode * lhsp)6442     AstTanhD(FileLine* fl, AstNode* lhsp)
6443         : ASTGEN_SUPER_TanhD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TanhD)6444     ASTNODE_NODE_FUNCS(TanhD)
6445     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6446         out.setDouble(std::tanh(lhs.toDouble()));
6447     }
emitVerilog()6448     virtual string emitVerilog() override { return "%f$tanh(%l)"; }
emitC()6449     virtual string emitC() override { return "tanh(%li)"; }
6450 };
6451 
6452 class AstAsinhD final : public AstNodeSystemUniop {
6453 public:
AstAsinhD(FileLine * fl,AstNode * lhsp)6454     AstAsinhD(FileLine* fl, AstNode* lhsp)
6455         : ASTGEN_SUPER_AsinhD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AsinhD)6456     ASTNODE_NODE_FUNCS(AsinhD)
6457     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6458         out.setDouble(std::asinh(lhs.toDouble()));
6459     }
emitVerilog()6460     virtual string emitVerilog() override { return "%f$asinh(%l)"; }
emitC()6461     virtual string emitC() override { return "asinh(%li)"; }
6462 };
6463 
6464 class AstAcoshD final : public AstNodeSystemUniop {
6465 public:
AstAcoshD(FileLine * fl,AstNode * lhsp)6466     AstAcoshD(FileLine* fl, AstNode* lhsp)
6467         : ASTGEN_SUPER_AcoshD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AcoshD)6468     ASTNODE_NODE_FUNCS(AcoshD)
6469     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6470         out.setDouble(std::acosh(lhs.toDouble()));
6471     }
emitVerilog()6472     virtual string emitVerilog() override { return "%f$acosh(%l)"; }
emitC()6473     virtual string emitC() override { return "acosh(%li)"; }
6474 };
6475 
6476 class AstAtanhD final : public AstNodeSystemUniop {
6477 public:
AstAtanhD(FileLine * fl,AstNode * lhsp)6478     AstAtanhD(FileLine* fl, AstNode* lhsp)
6479         : ASTGEN_SUPER_AtanhD(fl, lhsp) {}
ASTNODE_NODE_FUNCS(AtanhD)6480     ASTNODE_NODE_FUNCS(AtanhD)
6481     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6482         out.setDouble(std::atanh(lhs.toDouble()));
6483     }
emitVerilog()6484     virtual string emitVerilog() override { return "%f$atanh(%l)"; }
emitC()6485     virtual string emitC() override { return "atanh(%li)"; }
6486 };
6487 class AstToLowerN final : public AstNodeUniop {
6488     // string.tolower()
6489 public:
AstToLowerN(FileLine * fl,AstNode * lhsp)6490     AstToLowerN(FileLine* fl, AstNode* lhsp)
6491         : ASTGEN_SUPER_ToLowerN(fl, lhsp) {
6492         dtypeSetString();
6493     }
ASTNODE_NODE_FUNCS(ToLowerN)6494     ASTNODE_NODE_FUNCS(ToLowerN)
6495     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6496         out.opToLowerN(lhs);
6497     }
emitVerilog()6498     virtual string emitVerilog() override { return "%l.tolower()"; }
emitC()6499     virtual string emitC() override { return "VL_TOLOWER_NN(%li)"; }
cleanOut()6500     virtual bool cleanOut() const override { return true; }
cleanLhs()6501     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6502     virtual bool sizeMattersLhs() const override { return false; }
6503 };
6504 class AstToUpperN final : public AstNodeUniop {
6505     // string.toupper()
6506 public:
AstToUpperN(FileLine * fl,AstNode * lhsp)6507     AstToUpperN(FileLine* fl, AstNode* lhsp)
6508         : ASTGEN_SUPER_ToUpperN(fl, lhsp) {
6509         dtypeSetString();
6510     }
ASTNODE_NODE_FUNCS(ToUpperN)6511     ASTNODE_NODE_FUNCS(ToUpperN)
6512     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6513         out.opToUpperN(lhs);
6514     }
emitVerilog()6515     virtual string emitVerilog() override { return "%l.toupper()"; }
emitC()6516     virtual string emitC() override { return "VL_TOUPPER_NN(%li)"; }
cleanOut()6517     virtual bool cleanOut() const override { return true; }
cleanLhs()6518     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6519     virtual bool sizeMattersLhs() const override { return false; }
6520 };
6521 class AstTimeImport final : public AstNodeUniop {
6522     // Take a constant that represents a time and needs conversion based on time units
6523     VTimescale m_timeunit;  // Parent module time unit
6524 public:
AstTimeImport(FileLine * fl,AstNode * lhsp)6525     AstTimeImport(FileLine* fl, AstNode* lhsp)
6526         : ASTGEN_SUPER_TimeImport(fl, lhsp) {}
ASTNODE_NODE_FUNCS(TimeImport)6527     ASTNODE_NODE_FUNCS(TimeImport)
6528     virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; }
emitVerilog()6529     virtual string emitVerilog() override { return "%l"; }
emitC()6530     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
cleanOut()6531     virtual bool cleanOut() const override { return false; }
cleanLhs()6532     virtual bool cleanLhs() const override { return false; }
sizeMattersLhs()6533     virtual bool sizeMattersLhs() const override { return false; }
6534     virtual void dump(std::ostream& str = std::cout) const override;
timeunit(const VTimescale & flag)6535     void timeunit(const VTimescale& flag) { m_timeunit = flag; }
timeunit()6536     VTimescale timeunit() const { return m_timeunit; }
6537 };
6538 
6539 class AstAtoN final : public AstNodeUniop {
6540     // string.atoi(), atobin(), atohex(), atooct(), atoireal()
6541 public:
6542     enum FmtType { ATOI = 10, ATOHEX = 16, ATOOCT = 8, ATOBIN = 2, ATOREAL = -1 };
6543 
6544 private:
6545     const FmtType m_fmt;  // Operation type
6546 public:
AstAtoN(FileLine * fl,AstNode * lhsp,FmtType fmt)6547     AstAtoN(FileLine* fl, AstNode* lhsp, FmtType fmt)
6548         : ASTGEN_SUPER_AtoN(fl, lhsp)
6549         , m_fmt{fmt} {
6550         fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32();
6551     }
ASTNODE_NODE_FUNCS(AtoN)6552     ASTNODE_NODE_FUNCS(AtoN)
6553     virtual void numberOperate(V3Number& out, const V3Number& lhs) override {
6554         out.opAtoN(lhs, m_fmt);
6555     }
name()6556     virtual string name() const override {
6557         switch (m_fmt) {
6558         case ATOI: return "atoi";
6559         case ATOHEX: return "atohex";
6560         case ATOOCT: return "atooct";
6561         case ATOBIN: return "atobin";
6562         case ATOREAL: return "atoreal";
6563         default: V3ERROR_NA;
6564         }
6565     }
emitVerilog()6566     virtual string emitVerilog() override { return "%l." + name() + "()"; }
emitC()6567     virtual string emitC() override {
6568         switch (m_fmt) {
6569         case ATOI: return "VL_ATOI_N(%li, 10)";
6570         case ATOHEX: return "VL_ATOI_N(%li, 16)";
6571         case ATOOCT: return "VL_ATOI_N(%li, 8)";
6572         case ATOBIN: return "VL_ATOI_N(%li, 2)";
6573         case ATOREAL: return "std::atof(%li.c_str())";
6574         default: V3ERROR_NA;
6575         }
6576     }
cleanOut()6577     virtual bool cleanOut() const override { return true; }
cleanLhs()6578     virtual bool cleanLhs() const override { return true; }
sizeMattersLhs()6579     virtual bool sizeMattersLhs() const override { return false; }
format()6580     FmtType format() const { return m_fmt; }
6581 };
6582 
6583 //======================================================================
6584 // Binary ops
6585 
6586 class AstLogOr final : public AstNodeBiop {
6587 public:
AstLogOr(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6588     AstLogOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6589         : ASTGEN_SUPER_LogOr(fl, lhsp, rhsp) {
6590         dtypeSetBit();
6591     }
ASTNODE_NODE_FUNCS(LogOr)6592     ASTNODE_NODE_FUNCS(LogOr)
6593     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6594         return new AstLogOr(this->fileline(), lhsp, rhsp);
6595     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6596     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6597         out.opLogOr(lhs, rhs);
6598     }
emitVerilog()6599     virtual string emitVerilog() override { return "%k(%l %f|| %r)"; }
emitC()6600     virtual string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()6601     virtual string emitSimpleOperator() override { return "||"; }
cleanOut()6602     virtual bool cleanOut() const override { return true; }
cleanLhs()6603     virtual bool cleanLhs() const override { return true; }
cleanRhs()6604     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6605     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6606     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6607     virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
6608 };
6609 class AstLogAnd final : public AstNodeBiop {
6610 public:
AstLogAnd(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6611     AstLogAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6612         : ASTGEN_SUPER_LogAnd(fl, lhsp, rhsp) {
6613         dtypeSetBit();
6614     }
ASTNODE_NODE_FUNCS(LogAnd)6615     ASTNODE_NODE_FUNCS(LogAnd)
6616     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6617         return new AstLogAnd(this->fileline(), lhsp, rhsp);
6618     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6619     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6620         out.opLogAnd(lhs, rhs);
6621     }
emitVerilog()6622     virtual string emitVerilog() override { return "%k(%l %f&& %r)"; }
emitC()6623     virtual string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()6624     virtual string emitSimpleOperator() override { return "&&"; }
cleanOut()6625     virtual bool cleanOut() const override { return true; }
cleanLhs()6626     virtual bool cleanLhs() const override { return true; }
cleanRhs()6627     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6628     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6629     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6630     virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
6631 };
6632 class AstLogEq final : public AstNodeBiCom {
6633 public:
AstLogEq(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6634     AstLogEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6635         : ASTGEN_SUPER_LogEq(fl, lhsp, rhsp) {
6636         dtypeSetBit();
6637     }
ASTNODE_NODE_FUNCS(LogEq)6638     ASTNODE_NODE_FUNCS(LogEq)
6639     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6640         return new AstLogEq(this->fileline(), lhsp, rhsp);
6641     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6642     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6643         out.opLogEq(lhs, rhs);
6644     }
emitVerilog()6645     virtual string emitVerilog() override { return "%k(%l %f<-> %r)"; }
emitC()6646     virtual string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()6647     virtual string emitSimpleOperator() override { return "<->"; }
cleanOut()6648     virtual bool cleanOut() const override { return true; }
cleanLhs()6649     virtual bool cleanLhs() const override { return true; }
cleanRhs()6650     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6651     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6652     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6653     virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
6654 };
6655 class AstLogIf final : public AstNodeBiop {
6656 public:
AstLogIf(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6657     AstLogIf(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6658         : ASTGEN_SUPER_LogIf(fl, lhsp, rhsp) {
6659         dtypeSetBit();
6660     }
ASTNODE_NODE_FUNCS(LogIf)6661     ASTNODE_NODE_FUNCS(LogIf)
6662     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6663         return new AstLogIf(this->fileline(), lhsp, rhsp);
6664     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6665     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6666         out.opLogIf(lhs, rhs);
6667     }
emitVerilog()6668     virtual string emitVerilog() override { return "%k(%l %f-> %r)"; }
emitC()6669     virtual string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()6670     virtual string emitSimpleOperator() override { return "->"; }
cleanOut()6671     virtual bool cleanOut() const override { return true; }
cleanLhs()6672     virtual bool cleanLhs() const override { return true; }
cleanRhs()6673     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6674     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6675     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6676     virtual int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
6677 };
6678 class AstOr final : public AstNodeBiComAsv {
6679 public:
AstOr(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6680     AstOr(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6681         : ASTGEN_SUPER_Or(fl, lhsp, rhsp) {
6682         dtypeFrom(lhsp);
6683     }
ASTNODE_NODE_FUNCS(Or)6684     ASTNODE_NODE_FUNCS(Or)
6685     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6686         return new AstOr(this->fileline(), lhsp, rhsp);
6687     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6688     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6689         out.opOr(lhs, rhs);
6690     }
emitVerilog()6691     virtual string emitVerilog() override { return "%k(%l %f| %r)"; }
emitC()6692     virtual string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6693     virtual string emitSimpleOperator() override { return "|"; }
cleanOut()6694     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
cleanLhs()6695     virtual bool cleanLhs() const override { return false; }
cleanRhs()6696     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6697     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6698     virtual bool sizeMattersRhs() const override { return false; }
6699 };
6700 class AstAnd final : public AstNodeBiComAsv {
6701 public:
AstAnd(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6702     AstAnd(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6703         : ASTGEN_SUPER_And(fl, lhsp, rhsp) {
6704         dtypeFrom(lhsp);
6705     }
ASTNODE_NODE_FUNCS(And)6706     ASTNODE_NODE_FUNCS(And)
6707     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6708         return new AstAnd(this->fileline(), lhsp, rhsp);
6709     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6710     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6711         out.opAnd(lhs, rhs);
6712     }
emitVerilog()6713     virtual string emitVerilog() override { return "%k(%l %f& %r)"; }
emitC()6714     virtual string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6715     virtual string emitSimpleOperator() override { return "&"; }
cleanOut()6716     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); }
cleanLhs()6717     virtual bool cleanLhs() const override { return false; }
cleanRhs()6718     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6719     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6720     virtual bool sizeMattersRhs() const override { return false; }
6721 };
6722 class AstXor final : public AstNodeBiComAsv {
6723 public:
AstXor(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6724     AstXor(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6725         : ASTGEN_SUPER_Xor(fl, lhsp, rhsp) {
6726         dtypeFrom(lhsp);
6727     }
ASTNODE_NODE_FUNCS(Xor)6728     ASTNODE_NODE_FUNCS(Xor)
6729     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6730         return new AstXor(this->fileline(), lhsp, rhsp);
6731     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6732     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6733         out.opXor(lhs, rhs);
6734     }
emitVerilog()6735     virtual string emitVerilog() override { return "%k(%l %f^ %r)"; }
emitC()6736     virtual string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6737     virtual string emitSimpleOperator() override { return "^"; }
cleanOut()6738     virtual bool cleanOut() const override { return false; }  // Lclean && Rclean
cleanLhs()6739     virtual bool cleanLhs() const override { return false; }
cleanRhs()6740     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6741     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6742     virtual bool sizeMattersRhs() const override { return false; }
6743 };
6744 class AstEq final : public AstNodeBiCom {
6745 public:
AstEq(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6746     AstEq(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6747         : ASTGEN_SUPER_Eq(fl, lhsp, rhsp) {
6748         dtypeSetBit();
6749     }
ASTNODE_NODE_FUNCS(Eq)6750     ASTNODE_NODE_FUNCS(Eq)
6751     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6752         return new AstEq(this->fileline(), lhsp, rhsp);
6753     }
6754     static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp,
6755                                  AstNode* rhsp);  // Return AstEq/AstEqD
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6756     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6757         out.opEq(lhs, rhs);
6758     }
emitVerilog()6759     virtual string emitVerilog() override { return "%k(%l %f== %r)"; }
emitC()6760     virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6761     virtual string emitSimpleOperator() override { return "=="; }
cleanOut()6762     virtual bool cleanOut() const override { return true; }
cleanLhs()6763     virtual bool cleanLhs() const override { return true; }
cleanRhs()6764     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6765     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6766     virtual bool sizeMattersRhs() const override { return false; }
6767 };
6768 class AstEqD final : public AstNodeBiCom {
6769 public:
AstEqD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6770     AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6771         : ASTGEN_SUPER_EqD(fl, lhsp, rhsp) {
6772         dtypeSetBit();
6773     }
ASTNODE_NODE_FUNCS(EqD)6774     ASTNODE_NODE_FUNCS(EqD)
6775     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6776         return new AstEqD(this->fileline(), lhsp, rhsp);
6777     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6778     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6779         out.opEqD(lhs, rhs);
6780     }
emitVerilog()6781     virtual string emitVerilog() override { return "%k(%l %f== %r)"; }
emitC()6782     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()6783     virtual string emitSimpleOperator() override { return "=="; }
cleanOut()6784     virtual bool cleanOut() const override { return true; }
cleanLhs()6785     virtual bool cleanLhs() const override { return false; }
cleanRhs()6786     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6787     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6788     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6789     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()6790     virtual bool doubleFlavor() const override { return true; }
6791 };
6792 class AstEqN final : public AstNodeBiCom {
6793 public:
AstEqN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6794     AstEqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6795         : ASTGEN_SUPER_EqN(fl, lhsp, rhsp) {
6796         dtypeSetBit();
6797     }
ASTNODE_NODE_FUNCS(EqN)6798     ASTNODE_NODE_FUNCS(EqN)
6799     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6800         return new AstEqN(this->fileline(), lhsp, rhsp);
6801     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6802     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6803         out.opEqN(lhs, rhs);
6804     }
emitVerilog()6805     virtual string emitVerilog() override { return "%k(%l %f== %r)"; }
emitC()6806     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()6807     virtual string emitSimpleOperator() override { return "=="; }
cleanOut()6808     virtual bool cleanOut() const override { return true; }
cleanLhs()6809     virtual bool cleanLhs() const override { return false; }
cleanRhs()6810     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6811     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6812     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6813     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()6814     virtual bool stringFlavor() const override { return true; }
6815 };
6816 class AstNeq final : public AstNodeBiCom {
6817 public:
AstNeq(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6818     AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6819         : ASTGEN_SUPER_Neq(fl, lhsp, rhsp) {
6820         dtypeSetBit();
6821     }
ASTNODE_NODE_FUNCS(Neq)6822     ASTNODE_NODE_FUNCS(Neq)
6823     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6824         return new AstNeq(this->fileline(), lhsp, rhsp);
6825     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6826     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6827         out.opNeq(lhs, rhs);
6828     }
emitVerilog()6829     virtual string emitVerilog() override { return "%k(%l %f!= %r)"; }
emitC()6830     virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6831     virtual string emitSimpleOperator() override { return "!="; }
cleanOut()6832     virtual bool cleanOut() const override { return true; }
cleanLhs()6833     virtual bool cleanLhs() const override { return true; }
cleanRhs()6834     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6835     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6836     virtual bool sizeMattersRhs() const override { return false; }
6837 };
6838 class AstNeqD final : public AstNodeBiCom {
6839 public:
AstNeqD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6840     AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6841         : ASTGEN_SUPER_NeqD(fl, lhsp, rhsp) {
6842         dtypeSetBit();
6843     }
ASTNODE_NODE_FUNCS(NeqD)6844     ASTNODE_NODE_FUNCS(NeqD)
6845     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6846         return new AstNeqD(this->fileline(), lhsp, rhsp);
6847     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6848     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6849         out.opNeqD(lhs, rhs);
6850     }
emitVerilog()6851     virtual string emitVerilog() override { return "%k(%l %f!= %r)"; }
emitC()6852     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()6853     virtual string emitSimpleOperator() override { return "!="; }
cleanOut()6854     virtual bool cleanOut() const override { return true; }
cleanLhs()6855     virtual bool cleanLhs() const override { return false; }
cleanRhs()6856     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6857     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6858     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6859     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()6860     virtual bool doubleFlavor() const override { return true; }
6861 };
6862 class AstNeqN final : public AstNodeBiCom {
6863 public:
AstNeqN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6864     AstNeqN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6865         : ASTGEN_SUPER_NeqN(fl, lhsp, rhsp) {
6866         dtypeSetBit();
6867     }
ASTNODE_NODE_FUNCS(NeqN)6868     ASTNODE_NODE_FUNCS(NeqN)
6869     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6870         return new AstNeqN(this->fileline(), lhsp, rhsp);
6871     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6872     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6873         out.opNeqN(lhs, rhs);
6874     }
emitVerilog()6875     virtual string emitVerilog() override { return "%k(%l %f!= %r)"; }
emitC()6876     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()6877     virtual string emitSimpleOperator() override { return "!="; }
cleanOut()6878     virtual bool cleanOut() const override { return true; }
cleanLhs()6879     virtual bool cleanLhs() const override { return false; }
cleanRhs()6880     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6881     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6882     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6883     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()6884     virtual bool stringFlavor() const override { return true; }
6885 };
6886 class AstLt final : public AstNodeBiop {
6887 public:
AstLt(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6888     AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6889         : ASTGEN_SUPER_Lt(fl, lhsp, rhsp) {
6890         dtypeSetBit();
6891     }
ASTNODE_NODE_FUNCS(Lt)6892     ASTNODE_NODE_FUNCS(Lt)
6893     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6894         return new AstLt(this->fileline(), lhsp, rhsp);
6895     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6896     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6897         out.opLt(lhs, rhs);
6898     }
emitVerilog()6899     virtual string emitVerilog() override { return "%k(%l %f< %r)"; }
emitC()6900     virtual string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6901     virtual string emitSimpleOperator() override { return "<"; }
cleanOut()6902     virtual bool cleanOut() const override { return true; }
cleanLhs()6903     virtual bool cleanLhs() const override { return true; }
cleanRhs()6904     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6905     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6906     virtual bool sizeMattersRhs() const override { return false; }
6907 };
6908 class AstLtD final : public AstNodeBiop {
6909 public:
AstLtD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6910     AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6911         : ASTGEN_SUPER_LtD(fl, lhsp, rhsp) {
6912         dtypeSetBit();
6913     }
ASTNODE_NODE_FUNCS(LtD)6914     ASTNODE_NODE_FUNCS(LtD)
6915     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6916         return new AstLtD(this->fileline(), lhsp, rhsp);
6917     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6918     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6919         out.opLtD(lhs, rhs);
6920     }
emitVerilog()6921     virtual string emitVerilog() override { return "%k(%l %f< %r)"; }
emitC()6922     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()6923     virtual string emitSimpleOperator() override { return "<"; }
cleanOut()6924     virtual bool cleanOut() const override { return true; }
cleanLhs()6925     virtual bool cleanLhs() const override { return false; }
cleanRhs()6926     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6927     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6928     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6929     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()6930     virtual bool doubleFlavor() const override { return true; }
6931 };
6932 class AstLtS final : public AstNodeBiop {
6933 public:
AstLtS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6934     AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6935         : ASTGEN_SUPER_LtS(fl, lhsp, rhsp) {
6936         dtypeSetBit();
6937     }
ASTNODE_NODE_FUNCS(LtS)6938     ASTNODE_NODE_FUNCS(LtS)
6939     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6940         return new AstLtS(this->fileline(), lhsp, rhsp);
6941     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6942     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6943         out.opLtS(lhs, rhs);
6944     }
emitVerilog()6945     virtual string emitVerilog() override { return "%k(%l %f< %r)"; }
emitC()6946     virtual string emitC() override { return "VL_LTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
emitSimpleOperator()6947     virtual string emitSimpleOperator() override { return ""; }
cleanOut()6948     virtual bool cleanOut() const override { return true; }
cleanLhs()6949     virtual bool cleanLhs() const override { return true; }
cleanRhs()6950     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6951     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6952     virtual bool sizeMattersRhs() const override { return false; }
signedFlavor()6953     virtual bool signedFlavor() const override { return true; }
6954 };
6955 class AstLtN final : public AstNodeBiop {
6956 public:
AstLtN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6957     AstLtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6958         : ASTGEN_SUPER_LtN(fl, lhsp, rhsp) {
6959         dtypeSetBit();
6960     }
ASTNODE_NODE_FUNCS(LtN)6961     ASTNODE_NODE_FUNCS(LtN)
6962     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6963         return new AstLtN(this->fileline(), lhsp, rhsp);
6964     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6965     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6966         out.opLtN(lhs, rhs);
6967     }
emitVerilog()6968     virtual string emitVerilog() override { return "%k(%l %f< %r)"; }
emitC()6969     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()6970     virtual string emitSimpleOperator() override { return "<"; }
cleanOut()6971     virtual bool cleanOut() const override { return true; }
cleanLhs()6972     virtual bool cleanLhs() const override { return false; }
cleanRhs()6973     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()6974     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6975     virtual bool sizeMattersRhs() const override { return false; }
instrCount()6976     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()6977     virtual bool stringFlavor() const override { return true; }
6978 };
6979 class AstGt final : public AstNodeBiop {
6980 public:
AstGt(FileLine * fl,AstNode * lhsp,AstNode * rhsp)6981     AstGt(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
6982         : ASTGEN_SUPER_Gt(fl, lhsp, rhsp) {
6983         dtypeSetBit();
6984     }
ASTNODE_NODE_FUNCS(Gt)6985     ASTNODE_NODE_FUNCS(Gt)
6986     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
6987         return new AstGt(this->fileline(), lhsp, rhsp);
6988     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)6989     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
6990         out.opGt(lhs, rhs);
6991     }
emitVerilog()6992     virtual string emitVerilog() override { return "%k(%l %f> %r)"; }
emitC()6993     virtual string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()6994     virtual string emitSimpleOperator() override { return ">"; }
cleanOut()6995     virtual bool cleanOut() const override { return true; }
cleanLhs()6996     virtual bool cleanLhs() const override { return true; }
cleanRhs()6997     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()6998     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()6999     virtual bool sizeMattersRhs() const override { return false; }
7000 };
7001 class AstGtD final : public AstNodeBiop {
7002 public:
AstGtD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7003     AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7004         : ASTGEN_SUPER_GtD(fl, lhsp, rhsp) {
7005         dtypeSetBit();
7006     }
ASTNODE_NODE_FUNCS(GtD)7007     ASTNODE_NODE_FUNCS(GtD)
7008     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7009         return new AstGtD(this->fileline(), lhsp, rhsp);
7010     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7011     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7012         out.opGtD(lhs, rhs);
7013     }
emitVerilog()7014     virtual string emitVerilog() override { return "%k(%l %f> %r)"; }
emitC()7015     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7016     virtual string emitSimpleOperator() override { return ">"; }
cleanOut()7017     virtual bool cleanOut() const override { return true; }
cleanLhs()7018     virtual bool cleanLhs() const override { return false; }
cleanRhs()7019     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7020     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7021     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7022     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()7023     virtual bool doubleFlavor() const override { return true; }
7024 };
7025 class AstGtS final : public AstNodeBiop {
7026 public:
AstGtS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7027     AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7028         : ASTGEN_SUPER_GtS(fl, lhsp, rhsp) {
7029         dtypeSetBit();
7030     }
ASTNODE_NODE_FUNCS(GtS)7031     ASTNODE_NODE_FUNCS(GtS)
7032     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7033         return new AstGtS(this->fileline(), lhsp, rhsp);
7034     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7035     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7036         out.opGtS(lhs, rhs);
7037     }
emitVerilog()7038     virtual string emitVerilog() override { return "%k(%l %f> %r)"; }
emitC()7039     virtual string emitC() override { return "VL_GTS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
emitSimpleOperator()7040     virtual string emitSimpleOperator() override { return ""; }
cleanOut()7041     virtual bool cleanOut() const override { return true; }
cleanLhs()7042     virtual bool cleanLhs() const override { return true; }
cleanRhs()7043     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7044     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7045     virtual bool sizeMattersRhs() const override { return false; }
signedFlavor()7046     virtual bool signedFlavor() const override { return true; }
7047 };
7048 class AstGtN final : public AstNodeBiop {
7049 public:
AstGtN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7050     AstGtN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7051         : ASTGEN_SUPER_GtN(fl, lhsp, rhsp) {
7052         dtypeSetBit();
7053     }
ASTNODE_NODE_FUNCS(GtN)7054     ASTNODE_NODE_FUNCS(GtN)
7055     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7056         return new AstGtN(this->fileline(), lhsp, rhsp);
7057     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7058     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7059         out.opGtN(lhs, rhs);
7060     }
emitVerilog()7061     virtual string emitVerilog() override { return "%k(%l %f> %r)"; }
emitC()7062     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7063     virtual string emitSimpleOperator() override { return ">"; }
cleanOut()7064     virtual bool cleanOut() const override { return true; }
cleanLhs()7065     virtual bool cleanLhs() const override { return false; }
cleanRhs()7066     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7067     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7068     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7069     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()7070     virtual bool stringFlavor() const override { return true; }
7071 };
7072 class AstGte final : public AstNodeBiop {
7073 public:
AstGte(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7074     AstGte(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7075         : ASTGEN_SUPER_Gte(fl, lhsp, rhsp) {
7076         dtypeSetBit();
7077     }
ASTNODE_NODE_FUNCS(Gte)7078     ASTNODE_NODE_FUNCS(Gte)
7079     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7080         return new AstGte(this->fileline(), lhsp, rhsp);
7081     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7082     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7083         out.opGte(lhs, rhs);
7084     }
emitVerilog()7085     virtual string emitVerilog() override { return "%k(%l %f>= %r)"; }
emitC()7086     virtual string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7087     virtual string emitSimpleOperator() override { return ">="; }
cleanOut()7088     virtual bool cleanOut() const override { return true; }
cleanLhs()7089     virtual bool cleanLhs() const override { return true; }
cleanRhs()7090     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7091     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7092     virtual bool sizeMattersRhs() const override { return false; }
7093 };
7094 class AstGteD final : public AstNodeBiop {
7095 public:
AstGteD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7096     AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7097         : ASTGEN_SUPER_GteD(fl, lhsp, rhsp) {
7098         dtypeSetBit();
7099     }
ASTNODE_NODE_FUNCS(GteD)7100     ASTNODE_NODE_FUNCS(GteD)
7101     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7102         return new AstGteD(this->fileline(), lhsp, rhsp);
7103     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7104     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7105         out.opGteD(lhs, rhs);
7106     }
emitVerilog()7107     virtual string emitVerilog() override { return "%k(%l %f>= %r)"; }
emitC()7108     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7109     virtual string emitSimpleOperator() override { return ">="; }
cleanOut()7110     virtual bool cleanOut() const override { return true; }
cleanLhs()7111     virtual bool cleanLhs() const override { return false; }
cleanRhs()7112     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7113     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7114     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7115     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()7116     virtual bool doubleFlavor() const override { return true; }
7117 };
7118 class AstGteS final : public AstNodeBiop {
7119 public:
AstGteS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7120     AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7121         : ASTGEN_SUPER_GteS(fl, lhsp, rhsp) {
7122         dtypeSetBit();
7123     }
ASTNODE_NODE_FUNCS(GteS)7124     ASTNODE_NODE_FUNCS(GteS)
7125     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7126         return new AstGteS(this->fileline(), lhsp, rhsp);
7127     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7128     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7129         out.opGteS(lhs, rhs);
7130     }
emitVerilog()7131     virtual string emitVerilog() override { return "%k(%l %f>= %r)"; }
emitC()7132     virtual string emitC() override { return "VL_GTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
emitSimpleOperator()7133     virtual string emitSimpleOperator() override { return ""; }
cleanOut()7134     virtual bool cleanOut() const override { return true; }
cleanLhs()7135     virtual bool cleanLhs() const override { return true; }
cleanRhs()7136     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7137     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7138     virtual bool sizeMattersRhs() const override { return false; }
signedFlavor()7139     virtual bool signedFlavor() const override { return true; }
7140 };
7141 class AstGteN final : public AstNodeBiop {
7142 public:
AstGteN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7143     AstGteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7144         : ASTGEN_SUPER_GteN(fl, lhsp, rhsp) {
7145         dtypeSetBit();
7146     }
ASTNODE_NODE_FUNCS(GteN)7147     ASTNODE_NODE_FUNCS(GteN)
7148     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7149         return new AstGteN(this->fileline(), lhsp, rhsp);
7150     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7151     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7152         out.opGteN(lhs, rhs);
7153     }
emitVerilog()7154     virtual string emitVerilog() override { return "%k(%l %f>= %r)"; }
emitC()7155     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7156     virtual string emitSimpleOperator() override { return ">="; }
cleanOut()7157     virtual bool cleanOut() const override { return true; }
cleanLhs()7158     virtual bool cleanLhs() const override { return false; }
cleanRhs()7159     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7160     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7161     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7162     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()7163     virtual bool stringFlavor() const override { return true; }
7164 };
7165 class AstLte final : public AstNodeBiop {
7166 public:
AstLte(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7167     AstLte(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7168         : ASTGEN_SUPER_Lte(fl, lhsp, rhsp) {
7169         dtypeSetBit();
7170     }
ASTNODE_NODE_FUNCS(Lte)7171     ASTNODE_NODE_FUNCS(Lte)
7172     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7173         return new AstLte(this->fileline(), lhsp, rhsp);
7174     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7175     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7176         out.opLte(lhs, rhs);
7177     }
emitVerilog()7178     virtual string emitVerilog() override { return "%k(%l %f<= %r)"; }
emitC()7179     virtual string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7180     virtual string emitSimpleOperator() override { return "<="; }
cleanOut()7181     virtual bool cleanOut() const override { return true; }
cleanLhs()7182     virtual bool cleanLhs() const override { return true; }
cleanRhs()7183     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7184     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7185     virtual bool sizeMattersRhs() const override { return false; }
7186 };
7187 class AstLteD final : public AstNodeBiop {
7188 public:
AstLteD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7189     AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7190         : ASTGEN_SUPER_LteD(fl, lhsp, rhsp) {
7191         dtypeSetBit();
7192     }
ASTNODE_NODE_FUNCS(LteD)7193     ASTNODE_NODE_FUNCS(LteD)
7194     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7195         return new AstLteD(this->fileline(), lhsp, rhsp);
7196     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7197     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7198         out.opLteD(lhs, rhs);
7199     }
emitVerilog()7200     virtual string emitVerilog() override { return "%k(%l %f<= %r)"; }
emitC()7201     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7202     virtual string emitSimpleOperator() override { return "<="; }
cleanOut()7203     virtual bool cleanOut() const override { return true; }
cleanLhs()7204     virtual bool cleanLhs() const override { return false; }
cleanRhs()7205     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7206     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7207     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7208     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()7209     virtual bool doubleFlavor() const override { return true; }
7210 };
7211 class AstLteS final : public AstNodeBiop {
7212 public:
AstLteS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7213     AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7214         : ASTGEN_SUPER_LteS(fl, lhsp, rhsp) {
7215         dtypeSetBit();
7216     }
ASTNODE_NODE_FUNCS(LteS)7217     ASTNODE_NODE_FUNCS(LteS)
7218     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7219         return new AstLteS(this->fileline(), lhsp, rhsp);
7220     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7221     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7222         out.opLteS(lhs, rhs);
7223     }
emitVerilog()7224     virtual string emitVerilog() override { return "%k(%l %f<= %r)"; }
emitC()7225     virtual string emitC() override { return "VL_LTES_%nq%lq%rq(%lw, %P, %li, %ri)"; }
emitSimpleOperator()7226     virtual string emitSimpleOperator() override { return ""; }
cleanOut()7227     virtual bool cleanOut() const override { return true; }
cleanLhs()7228     virtual bool cleanLhs() const override { return true; }
cleanRhs()7229     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7230     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7231     virtual bool sizeMattersRhs() const override { return false; }
signedFlavor()7232     virtual bool signedFlavor() const override { return true; }
7233 };
7234 class AstLteN final : public AstNodeBiop {
7235 public:
AstLteN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7236     AstLteN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7237         : ASTGEN_SUPER_LteN(fl, lhsp, rhsp) {
7238         dtypeSetBit();
7239     }
ASTNODE_NODE_FUNCS(LteN)7240     ASTNODE_NODE_FUNCS(LteN)
7241     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7242         return new AstLteN(this->fileline(), lhsp, rhsp);
7243     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7244     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7245         out.opLteN(lhs, rhs);
7246     }
emitVerilog()7247     virtual string emitVerilog() override { return "%k(%l %f<= %r)"; }
emitC()7248     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7249     virtual string emitSimpleOperator() override { return "<="; }
cleanOut()7250     virtual bool cleanOut() const override { return true; }
cleanLhs()7251     virtual bool cleanLhs() const override { return false; }
cleanRhs()7252     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7253     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7254     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7255     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()7256     virtual bool stringFlavor() const override { return true; }
7257 };
7258 class AstShiftL final : public AstNodeBiop {
7259 public:
7260     AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0)
ASTGEN_SUPER_ShiftL(fl,lhsp,rhsp)7261         : ASTGEN_SUPER_ShiftL(fl, lhsp, rhsp) {
7262         if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
7263     }
ASTNODE_NODE_FUNCS(ShiftL)7264     ASTNODE_NODE_FUNCS(ShiftL)
7265     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7266         return new AstShiftL(this->fileline(), lhsp, rhsp);
7267     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7268     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7269         out.opShiftL(lhs, rhs);
7270     }
emitVerilog()7271     virtual string emitVerilog() override { return "%k(%l %f<< %r)"; }
emitC()7272     virtual string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()7273     virtual string emitSimpleOperator() override {
7274         return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : "<<";
7275     }
cleanOut()7276     virtual bool cleanOut() const override { return false; }
cleanLhs()7277     virtual bool cleanLhs() const override { return false; }
cleanRhs()7278     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7279     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7280     virtual bool sizeMattersRhs() const override { return false; }
7281 };
7282 class AstShiftR final : public AstNodeBiop {
7283 public:
7284     AstShiftR(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0)
ASTGEN_SUPER_ShiftR(fl,lhsp,rhsp)7285         : ASTGEN_SUPER_ShiftR(fl, lhsp, rhsp) {
7286         if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
7287     }
ASTNODE_NODE_FUNCS(ShiftR)7288     ASTNODE_NODE_FUNCS(ShiftR)
7289     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7290         return new AstShiftR(this->fileline(), lhsp, rhsp);
7291     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7292     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7293         out.opShiftR(lhs, rhs);
7294     }
emitVerilog()7295     virtual string emitVerilog() override { return "%k(%l %f>> %r)"; }
emitC()7296     virtual string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()7297     virtual string emitSimpleOperator() override {
7298         return (rhsp()->isWide() || rhsp()->isQuad()) ? "" : ">>";
7299     }
cleanOut()7300     virtual bool cleanOut() const override { return false; }
cleanLhs()7301     virtual bool cleanLhs() const override { return true; }
cleanRhs()7302     virtual bool cleanRhs() const override { return true; }
7303     // LHS size might be > output size, so don't want to force size
sizeMattersLhs()7304     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7305     virtual bool sizeMattersRhs() const override { return false; }
7306 };
7307 class AstShiftRS final : public AstNodeBiop {
7308     // Shift right with sign extension, >>> operator
7309     // Output data type's width determines which bit is used for sign extension
7310 public:
7311     AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth = 0)
ASTGEN_SUPER_ShiftRS(fl,lhsp,rhsp)7312         : ASTGEN_SUPER_ShiftRS(fl, lhsp, rhsp) {
7313         // Important that widthMin be correct, as opExtend requires it after V3Expand
7314         if (setwidth) dtypeSetLogicSized(setwidth, VSigning::SIGNED);
7315     }
ASTNODE_NODE_FUNCS(ShiftRS)7316     ASTNODE_NODE_FUNCS(ShiftRS)
7317     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7318         return new AstShiftRS(this->fileline(), lhsp, rhsp);
7319     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7320     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7321         out.opShiftRS(lhs, rhs, lhsp()->widthMinV());
7322     }
emitVerilog()7323     virtual string emitVerilog() override { return "%k(%l %f>>> %r)"; }
emitC()7324     virtual string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitSimpleOperator()7325     virtual string emitSimpleOperator() override { return ""; }
cleanOut()7326     virtual bool cleanOut() const override { return false; }
cleanLhs()7327     virtual bool cleanLhs() const override { return true; }
cleanRhs()7328     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7329     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7330     virtual bool sizeMattersRhs() const override { return false; }
signedFlavor()7331     virtual bool signedFlavor() const override { return true; }
7332 };
7333 class AstAdd final : public AstNodeBiComAsv {
7334 public:
AstAdd(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7335     AstAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7336         : ASTGEN_SUPER_Add(fl, lhsp, rhsp) {
7337         dtypeFrom(lhsp);
7338     }
ASTNODE_NODE_FUNCS(Add)7339     ASTNODE_NODE_FUNCS(Add)
7340     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7341         return new AstAdd(this->fileline(), lhsp, rhsp);
7342     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7343     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7344         out.opAdd(lhs, rhs);
7345     }
emitVerilog()7346     virtual string emitVerilog() override { return "%k(%l %f+ %r)"; }
emitC()7347     virtual string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7348     virtual string emitSimpleOperator() override { return "+"; }
cleanOut()7349     virtual bool cleanOut() const override { return false; }
cleanLhs()7350     virtual bool cleanLhs() const override { return false; }
cleanRhs()7351     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7352     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7353     virtual bool sizeMattersRhs() const override { return true; }
7354 };
7355 class AstAddD final : public AstNodeBiComAsv {
7356 public:
AstAddD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7357     AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7358         : ASTGEN_SUPER_AddD(fl, lhsp, rhsp) {
7359         dtypeSetDouble();
7360     }
ASTNODE_NODE_FUNCS(AddD)7361     ASTNODE_NODE_FUNCS(AddD)
7362     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7363         return new AstAddD(this->fileline(), lhsp, rhsp);
7364     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7365     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7366         out.opAddD(lhs, rhs);
7367     }
emitVerilog()7368     virtual string emitVerilog() override { return "%k(%l %f+ %r)"; }
emitC()7369     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7370     virtual string emitSimpleOperator() override { return "+"; }
cleanOut()7371     virtual bool cleanOut() const override { return true; }
cleanLhs()7372     virtual bool cleanLhs() const override { return false; }
cleanRhs()7373     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7374     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7375     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7376     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()7377     virtual bool doubleFlavor() const override { return true; }
7378 };
7379 class AstSub final : public AstNodeBiop {
7380 public:
AstSub(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7381     AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7382         : ASTGEN_SUPER_Sub(fl, lhsp, rhsp) {
7383         dtypeFrom(lhsp);
7384     }
ASTNODE_NODE_FUNCS(Sub)7385     ASTNODE_NODE_FUNCS(Sub)
7386     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7387         return new AstSub(this->fileline(), lhsp, rhsp);
7388     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7389     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7390         out.opSub(lhs, rhs);
7391     }
emitVerilog()7392     virtual string emitVerilog() override { return "%k(%l %f- %r)"; }
emitC()7393     virtual string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7394     virtual string emitSimpleOperator() override { return "-"; }
cleanOut()7395     virtual bool cleanOut() const override { return false; }
cleanLhs()7396     virtual bool cleanLhs() const override { return false; }
cleanRhs()7397     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7398     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7399     virtual bool sizeMattersRhs() const override { return true; }
7400 };
7401 class AstSubD final : public AstNodeBiop {
7402 public:
AstSubD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7403     AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7404         : ASTGEN_SUPER_SubD(fl, lhsp, rhsp) {
7405         dtypeSetDouble();
7406     }
ASTNODE_NODE_FUNCS(SubD)7407     ASTNODE_NODE_FUNCS(SubD)
7408     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7409         return new AstSubD(this->fileline(), lhsp, rhsp);
7410     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7411     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7412         out.opSubD(lhs, rhs);
7413     }
emitVerilog()7414     virtual string emitVerilog() override { return "%k(%l %f- %r)"; }
emitC()7415     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7416     virtual string emitSimpleOperator() override { return "-"; }
cleanOut()7417     virtual bool cleanOut() const override { return true; }
cleanLhs()7418     virtual bool cleanLhs() const override { return false; }
cleanRhs()7419     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7420     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7421     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7422     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()7423     virtual bool doubleFlavor() const override { return true; }
7424 };
7425 class AstMul final : public AstNodeBiComAsv {
7426 public:
AstMul(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7427     AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7428         : ASTGEN_SUPER_Mul(fl, lhsp, rhsp) {
7429         dtypeFrom(lhsp);
7430     }
ASTNODE_NODE_FUNCS(Mul)7431     ASTNODE_NODE_FUNCS(Mul)
7432     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7433         return new AstMul(this->fileline(), lhsp, rhsp);
7434     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7435     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7436         out.opMul(lhs, rhs);
7437     }
emitVerilog()7438     virtual string emitVerilog() override { return "%k(%l %f* %r)"; }
emitC()7439     virtual string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7440     virtual string emitSimpleOperator() override { return "*"; }
cleanOut()7441     virtual bool cleanOut() const override { return false; }
cleanLhs()7442     virtual bool cleanLhs() const override { return true; }
cleanRhs()7443     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7444     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7445     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7446     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; }
7447 };
7448 class AstMulD final : public AstNodeBiComAsv {
7449 public:
AstMulD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7450     AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7451         : ASTGEN_SUPER_MulD(fl, lhsp, rhsp) {
7452         dtypeSetDouble();
7453     }
ASTNODE_NODE_FUNCS(MulD)7454     ASTNODE_NODE_FUNCS(MulD)
7455     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7456         return new AstMulD(this->fileline(), lhsp, rhsp);
7457     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7458     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7459         out.opMulD(lhs, rhs);
7460     }
emitVerilog()7461     virtual string emitVerilog() override { return "%k(%l %f* %r)"; }
emitC()7462     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7463     virtual string emitSimpleOperator() override { return "*"; }
cleanOut()7464     virtual bool cleanOut() const override { return true; }
cleanLhs()7465     virtual bool cleanLhs() const override { return false; }
cleanRhs()7466     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7467     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7468     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7469     virtual int instrCount() const override { return INSTR_COUNT_DBL; }
doubleFlavor()7470     virtual bool doubleFlavor() const override { return true; }
7471 };
7472 class AstMulS final : public AstNodeBiComAsv {
7473 public:
AstMulS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7474     AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7475         : ASTGEN_SUPER_MulS(fl, lhsp, rhsp) {
7476         dtypeFrom(lhsp);
7477     }
ASTNODE_NODE_FUNCS(MulS)7478     ASTNODE_NODE_FUNCS(MulS)
7479     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7480         return new AstMulS(this->fileline(), lhsp, rhsp);
7481     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7482     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7483         out.opMulS(lhs, rhs);
7484     }
emitVerilog()7485     virtual string emitVerilog() override { return "%k(%l %f* %r)"; }
emitC()7486     virtual string emitC() override { return "VL_MULS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
emitSimpleOperator()7487     virtual string emitSimpleOperator() override { return ""; }
emitCheckMaxWords()7488     virtual bool emitCheckMaxWords() override { return true; }
cleanOut()7489     virtual bool cleanOut() const override { return false; }
cleanLhs()7490     virtual bool cleanLhs() const override { return true; }
cleanRhs()7491     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7492     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7493     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7494     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL; }
signedFlavor()7495     virtual bool signedFlavor() const override { return true; }
7496 };
7497 class AstDiv final : public AstNodeBiop {
7498 public:
AstDiv(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7499     AstDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7500         : ASTGEN_SUPER_Div(fl, lhsp, rhsp) {
7501         dtypeFrom(lhsp);
7502     }
ASTNODE_NODE_FUNCS(Div)7503     ASTNODE_NODE_FUNCS(Div)
7504     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7505         return new AstDiv(this->fileline(), lhsp, rhsp);
7506     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7507     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7508         out.opDiv(lhs, rhs);
7509     }
emitVerilog()7510     virtual string emitVerilog() override { return "%k(%l %f/ %r)"; }
emitC()7511     virtual string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
cleanOut()7512     virtual bool cleanOut() const override { return false; }
cleanLhs()7513     virtual bool cleanLhs() const override { return true; }
cleanRhs()7514     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7515     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7516     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7517     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
7518 };
7519 class AstDivD final : public AstNodeBiop {
7520 public:
AstDivD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7521     AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7522         : ASTGEN_SUPER_DivD(fl, lhsp, rhsp) {
7523         dtypeSetDouble();
7524     }
ASTNODE_NODE_FUNCS(DivD)7525     ASTNODE_NODE_FUNCS(DivD)
7526     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7527         return new AstDivD(this->fileline(), lhsp, rhsp);
7528     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7529     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7530         out.opDivD(lhs, rhs);
7531     }
emitVerilog()7532     virtual string emitVerilog() override { return "%k(%l %f/ %r)"; }
emitC()7533     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7534     virtual string emitSimpleOperator() override { return "/"; }
cleanOut()7535     virtual bool cleanOut() const override { return true; }
cleanLhs()7536     virtual bool cleanLhs() const override { return false; }
cleanRhs()7537     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7538     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7539     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7540     virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV; }
doubleFlavor()7541     virtual bool doubleFlavor() const override { return true; }
7542 };
7543 class AstDivS final : public AstNodeBiop {
7544 public:
AstDivS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7545     AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7546         : ASTGEN_SUPER_DivS(fl, lhsp, rhsp) {
7547         dtypeFrom(lhsp);
7548     }
ASTNODE_NODE_FUNCS(DivS)7549     ASTNODE_NODE_FUNCS(DivS)
7550     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7551         return new AstDivS(this->fileline(), lhsp, rhsp);
7552     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7553     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7554         out.opDivS(lhs, rhs);
7555     }
emitVerilog()7556     virtual string emitVerilog() override { return "%k(%l %f/ %r)"; }
emitC()7557     virtual string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
cleanOut()7558     virtual bool cleanOut() const override { return false; }
cleanLhs()7559     virtual bool cleanLhs() const override { return true; }
cleanRhs()7560     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7561     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7562     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7563     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
signedFlavor()7564     virtual bool signedFlavor() const override { return true; }
7565 };
7566 class AstModDiv final : public AstNodeBiop {
7567 public:
AstModDiv(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7568     AstModDiv(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7569         : ASTGEN_SUPER_ModDiv(fl, lhsp, rhsp) {
7570         dtypeFrom(lhsp);
7571     }
ASTNODE_NODE_FUNCS(ModDiv)7572     ASTNODE_NODE_FUNCS(ModDiv)
7573     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7574         return new AstModDiv(this->fileline(), lhsp, rhsp);
7575     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7576     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7577         out.opModDiv(lhs, rhs);
7578     }
emitVerilog()7579     virtual string emitVerilog() override { return "%k(%l %f%% %r)"; }
emitC()7580     virtual string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; }
cleanOut()7581     virtual bool cleanOut() const override { return false; }
cleanLhs()7582     virtual bool cleanLhs() const override { return true; }
cleanRhs()7583     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7584     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7585     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7586     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
7587 };
7588 class AstModDivS final : public AstNodeBiop {
7589 public:
AstModDivS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7590     AstModDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7591         : ASTGEN_SUPER_ModDivS(fl, lhsp, rhsp) {
7592         dtypeFrom(lhsp);
7593     }
ASTNODE_NODE_FUNCS(ModDivS)7594     ASTNODE_NODE_FUNCS(ModDivS)
7595     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7596         return new AstModDivS(this->fileline(), lhsp, rhsp);
7597     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7598     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7599         out.opModDivS(lhs, rhs);
7600     }
emitVerilog()7601     virtual string emitVerilog() override { return "%k(%l %f%% %r)"; }
emitC()7602     virtual string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; }
cleanOut()7603     virtual bool cleanOut() const override { return false; }
cleanLhs()7604     virtual bool cleanLhs() const override { return true; }
cleanRhs()7605     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7606     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7607     virtual bool sizeMattersRhs() const override { return true; }
instrCount()7608     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_DIV; }
signedFlavor()7609     virtual bool signedFlavor() const override { return true; }
7610 };
7611 class AstPow final : public AstNodeBiop {
7612 public:
AstPow(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7613     AstPow(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7614         : ASTGEN_SUPER_Pow(fl, lhsp, rhsp) {
7615         dtypeFrom(lhsp);
7616     }
ASTNODE_NODE_FUNCS(Pow)7617     ASTNODE_NODE_FUNCS(Pow)
7618     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7619         return new AstPow(this->fileline(), lhsp, rhsp);
7620     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7621     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7622         out.opPow(lhs, rhs);
7623     }
emitVerilog()7624     virtual string emitVerilog() override { return "%k(%l %f** %r)"; }
emitC()7625     virtual string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
emitCheckMaxWords()7626     virtual bool emitCheckMaxWords() override { return true; }
cleanOut()7627     virtual bool cleanOut() const override { return false; }
cleanLhs()7628     virtual bool cleanLhs() const override { return true; }
cleanRhs()7629     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7630     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7631     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7632     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
7633 };
7634 class AstPowD final : public AstNodeBiop {
7635 public:
AstPowD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7636     AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7637         : ASTGEN_SUPER_PowD(fl, lhsp, rhsp) {
7638         dtypeSetDouble();
7639     }
ASTNODE_NODE_FUNCS(PowD)7640     ASTNODE_NODE_FUNCS(PowD)
7641     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7642         return new AstPowD(this->fileline(), lhsp, rhsp);
7643     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7644     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7645         out.opPowD(lhs, rhs);
7646     }
emitVerilog()7647     virtual string emitVerilog() override { return "%k(%l %f** %r)"; }
emitC()7648     virtual string emitC() override { return "pow(%li,%ri)"; }
cleanOut()7649     virtual bool cleanOut() const override { return false; }
cleanLhs()7650     virtual bool cleanLhs() const override { return false; }
cleanRhs()7651     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()7652     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7653     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7654     virtual int instrCount() const override { return INSTR_COUNT_DBL_DIV * 5; }
doubleFlavor()7655     virtual bool doubleFlavor() const override { return true; }
7656 };
7657 class AstPowSU final : public AstNodeBiop {
7658 public:
AstPowSU(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7659     AstPowSU(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7660         : ASTGEN_SUPER_PowSU(fl, lhsp, rhsp) {
7661         dtypeFrom(lhsp);
7662     }
ASTNODE_NODE_FUNCS(PowSU)7663     ASTNODE_NODE_FUNCS(PowSU)
7664     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7665         return new AstPowSU(this->fileline(), lhsp, rhsp);
7666     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7667     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7668         out.opPowSU(lhs, rhs);
7669     }
emitVerilog()7670     virtual string emitVerilog() override { return "%k(%l %f** %r)"; }
emitC()7671     virtual string emitC() override {
7672         return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)";
7673     }
emitCheckMaxWords()7674     virtual bool emitCheckMaxWords() override { return true; }
cleanOut()7675     virtual bool cleanOut() const override { return false; }
cleanLhs()7676     virtual bool cleanLhs() const override { return true; }
cleanRhs()7677     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7678     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7679     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7680     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
signedFlavor()7681     virtual bool signedFlavor() const override { return true; }
7682 };
7683 class AstPowSS final : public AstNodeBiop {
7684 public:
AstPowSS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7685     AstPowSS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7686         : ASTGEN_SUPER_PowSS(fl, lhsp, rhsp) {
7687         dtypeFrom(lhsp);
7688     }
ASTNODE_NODE_FUNCS(PowSS)7689     ASTNODE_NODE_FUNCS(PowSS)
7690     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7691         return new AstPowSS(this->fileline(), lhsp, rhsp);
7692     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7693     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7694         out.opPowSS(lhs, rhs);
7695     }
emitVerilog()7696     virtual string emitVerilog() override { return "%k(%l %f** %r)"; }
emitC()7697     virtual string emitC() override {
7698         return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)";
7699     }
emitCheckMaxWords()7700     virtual bool emitCheckMaxWords() override { return true; }
cleanOut()7701     virtual bool cleanOut() const override { return false; }
cleanLhs()7702     virtual bool cleanLhs() const override { return true; }
cleanRhs()7703     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7704     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7705     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7706     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
signedFlavor()7707     virtual bool signedFlavor() const override { return true; }
7708 };
7709 class AstPowUS final : public AstNodeBiop {
7710 public:
AstPowUS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7711     AstPowUS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7712         : ASTGEN_SUPER_PowUS(fl, lhsp, rhsp) {
7713         dtypeFrom(lhsp);
7714     }
ASTNODE_NODE_FUNCS(PowUS)7715     ASTNODE_NODE_FUNCS(PowUS)
7716     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7717         return new AstPowUS(this->fileline(), lhsp, rhsp);
7718     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7719     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7720         out.opPowUS(lhs, rhs);
7721     }
emitVerilog()7722     virtual string emitVerilog() override { return "%k(%l %f** %r)"; }
emitC()7723     virtual string emitC() override {
7724         return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)";
7725     }
emitCheckMaxWords()7726     virtual bool emitCheckMaxWords() override { return true; }
cleanOut()7727     virtual bool cleanOut() const override { return false; }
cleanLhs()7728     virtual bool cleanLhs() const override { return true; }
cleanRhs()7729     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7730     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7731     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7732     virtual int instrCount() const override { return widthInstrs() * INSTR_COUNT_INT_MUL * 10; }
signedFlavor()7733     virtual bool signedFlavor() const override { return true; }
7734 };
7735 class AstPreAdd final : public AstNodeTriop {
7736     // Pre-increment/add
7737     // Parents:  MATH
7738     // Children: lhsp: AstConst (1) as currently support only ++ not +=
7739     // Children: rhsp: tree with AstVarRef that is value to read before operation
7740     // Children: thsp: tree with AstVarRef LValue that is stored after operation
7741 public:
AstPreAdd(FileLine * fl,AstNode * lhsp,AstNode * rhsp,AstNode * thsp)7742     AstPreAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
7743         : ASTGEN_SUPER_PreAdd(fl, lhsp, rhsp, thsp) {}
ASTNODE_NODE_FUNCS(PreAdd)7744     ASTNODE_NODE_FUNCS(PreAdd)
7745     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
7746                                const V3Number& ths) override {
7747         V3ERROR_NA;  // Need to modify lhs
7748     }
emitVerilog()7749     virtual string emitVerilog() override { return "%k(++%r)"; }
emitC()7750     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7751     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()7752     virtual bool cleanOut() const override { return false; }
cleanLhs()7753     virtual bool cleanLhs() const override { return false; }
cleanRhs()7754     virtual bool cleanRhs() const override { return false; }
cleanThs()7755     virtual bool cleanThs() const override { return false; }
sizeMattersLhs()7756     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7757     virtual bool sizeMattersRhs() const override { return true; }
sizeMattersThs()7758     virtual bool sizeMattersThs() const override { return true; }
7759 };
7760 class AstPreSub final : public AstNodeTriop {
7761     // Pre-decrement/subtract
7762     // Parents:  MATH
7763     // Children: lhsp: AstConst (1) as currently support only -- not -=
7764     // Children: rhsp: tree with AstVarRef that is value to read before operation
7765     // Children: thsp: tree with AstVarRef LValue that is stored after operation
7766 public:
AstPreSub(FileLine * fl,AstNode * lhsp,AstNode * rhsp,AstNode * thsp)7767     AstPreSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
7768         : ASTGEN_SUPER_PreSub(fl, lhsp, rhsp, thsp) {}
ASTNODE_NODE_FUNCS(PreSub)7769     ASTNODE_NODE_FUNCS(PreSub)
7770     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
7771                                const V3Number& ths) override {
7772         V3ERROR_NA;  // Need to modify lhs
7773     }
emitVerilog()7774     virtual string emitVerilog() override { return "%k(--%r)"; }
emitC()7775     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7776     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()7777     virtual bool cleanOut() const override { return false; }
cleanLhs()7778     virtual bool cleanLhs() const override { return false; }
cleanRhs()7779     virtual bool cleanRhs() const override { return false; }
cleanThs()7780     virtual bool cleanThs() const override { return false; }
sizeMattersLhs()7781     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7782     virtual bool sizeMattersRhs() const override { return true; }
sizeMattersThs()7783     virtual bool sizeMattersThs() const override { return true; }
7784 };
7785 class AstPostAdd final : public AstNodeTriop {
7786     // Post-increment/add
7787     // Parents:  MATH
7788     // Children: lhsp: AstConst (1) as currently support only ++ not +=
7789     // Children: rhsp: tree with AstVarRef that is value to read before operation
7790     // Children: thsp: tree with AstVarRef LValue that is stored after operation
7791 public:
AstPostAdd(FileLine * fl,AstNode * lhsp,AstNode * rhsp,AstNode * thsp)7792     AstPostAdd(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
7793         : ASTGEN_SUPER_PostAdd(fl, lhsp, rhsp, thsp) {}
ASTNODE_NODE_FUNCS(PostAdd)7794     ASTNODE_NODE_FUNCS(PostAdd)
7795     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
7796                                const V3Number& ths) override {
7797         V3ERROR_NA;  // Need to modify lhs
7798     }
emitVerilog()7799     virtual string emitVerilog() override { return "%k(%r++)"; }
emitC()7800     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7801     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()7802     virtual bool cleanOut() const override { return false; }
cleanLhs()7803     virtual bool cleanLhs() const override { return false; }
cleanRhs()7804     virtual bool cleanRhs() const override { return false; }
cleanThs()7805     virtual bool cleanThs() const override { return false; }
sizeMattersLhs()7806     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7807     virtual bool sizeMattersRhs() const override { return true; }
sizeMattersThs()7808     virtual bool sizeMattersThs() const override { return true; }
7809 };
7810 class AstPostSub final : public AstNodeTriop {
7811     // Post-decrement/subtract
7812     // Parents:  MATH
7813     // Children: lhsp: AstConst (1) as currently support only -- not -=
7814     // Children: rhsp: tree with AstVarRef that is value to read before operation
7815     // Children: thsp: tree with AstVarRef LValue that is stored after operation
7816 public:
AstPostSub(FileLine * fl,AstNode * lhsp,AstNode * rhsp,AstNode * thsp)7817     AstPostSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* thsp)
7818         : ASTGEN_SUPER_PostSub(fl, lhsp, rhsp, thsp) {}
ASTNODE_NODE_FUNCS(PostSub)7819     ASTNODE_NODE_FUNCS(PostSub)
7820     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
7821                                const V3Number& ths) override {
7822         V3ERROR_NA;  // Need to modify lhs
7823     }
emitVerilog()7824     virtual string emitVerilog() override { return "%k(%r--)"; }
emitC()7825     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()7826     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()7827     virtual bool cleanOut() const override { return false; }
cleanLhs()7828     virtual bool cleanLhs() const override { return false; }
cleanRhs()7829     virtual bool cleanRhs() const override { return false; }
cleanThs()7830     virtual bool cleanThs() const override { return false; }
sizeMattersLhs()7831     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()7832     virtual bool sizeMattersRhs() const override { return true; }
sizeMattersThs()7833     virtual bool sizeMattersThs() const override { return true; }
7834 };
7835 class AstEqCase final : public AstNodeBiCom {
7836 public:
AstEqCase(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7837     AstEqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7838         : ASTGEN_SUPER_EqCase(fl, lhsp, rhsp) {
7839         dtypeSetBit();
7840     }
ASTNODE_NODE_FUNCS(EqCase)7841     ASTNODE_NODE_FUNCS(EqCase)
7842     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7843         return new AstEqCase(this->fileline(), lhsp, rhsp);
7844     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7845     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7846         out.opCaseEq(lhs, rhs);
7847     }
emitVerilog()7848     virtual string emitVerilog() override { return "%k(%l %f=== %r)"; }
emitC()7849     virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7850     virtual string emitSimpleOperator() override { return "=="; }
cleanOut()7851     virtual bool cleanOut() const override { return true; }
cleanLhs()7852     virtual bool cleanLhs() const override { return true; }
cleanRhs()7853     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7854     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7855     virtual bool sizeMattersRhs() const override { return false; }
7856 };
7857 class AstNeqCase final : public AstNodeBiCom {
7858 public:
AstNeqCase(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7859     AstNeqCase(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7860         : ASTGEN_SUPER_NeqCase(fl, lhsp, rhsp) {
7861         dtypeSetBit();
7862     }
ASTNODE_NODE_FUNCS(NeqCase)7863     ASTNODE_NODE_FUNCS(NeqCase)
7864     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7865         return new AstNeqCase(this->fileline(), lhsp, rhsp);
7866     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7867     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7868         out.opCaseNeq(lhs, rhs);
7869     }
emitVerilog()7870     virtual string emitVerilog() override { return "%k(%l %f!== %r)"; }
emitC()7871     virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7872     virtual string emitSimpleOperator() override { return "!="; }
cleanOut()7873     virtual bool cleanOut() const override { return true; }
cleanLhs()7874     virtual bool cleanLhs() const override { return true; }
cleanRhs()7875     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7876     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7877     virtual bool sizeMattersRhs() const override { return false; }
7878 };
7879 class AstEqWild final : public AstNodeBiop {
7880     // Note wildcard operator rhs differs from lhs
7881 public:
AstEqWild(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7882     AstEqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7883         : ASTGEN_SUPER_EqWild(fl, lhsp, rhsp) {
7884         dtypeSetBit();
7885     }
ASTNODE_NODE_FUNCS(EqWild)7886     ASTNODE_NODE_FUNCS(EqWild)
7887     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7888         return new AstEqWild(this->fileline(), lhsp, rhsp);
7889     }
7890     static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp,
7891                                  AstNode* rhsp);  // Return AstEqWild/AstEqD
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7892     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7893         out.opWildEq(lhs, rhs);
7894     }
emitVerilog()7895     virtual string emitVerilog() override { return "%k(%l %f==? %r)"; }
emitC()7896     virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7897     virtual string emitSimpleOperator() override { return "=="; }
cleanOut()7898     virtual bool cleanOut() const override { return true; }
cleanLhs()7899     virtual bool cleanLhs() const override { return true; }
cleanRhs()7900     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7901     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7902     virtual bool sizeMattersRhs() const override { return false; }
7903 };
7904 class AstNeqWild final : public AstNodeBiop {
7905 public:
AstNeqWild(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7906     AstNeqWild(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7907         : ASTGEN_SUPER_NeqWild(fl, lhsp, rhsp) {
7908         dtypeSetBit();
7909     }
ASTNODE_NODE_FUNCS(NeqWild)7910     ASTNODE_NODE_FUNCS(NeqWild)
7911     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7912         return new AstNeqWild(this->fileline(), lhsp, rhsp);
7913     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7914     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7915         out.opWildNeq(lhs, rhs);
7916     }
emitVerilog()7917     virtual string emitVerilog() override { return "%k(%l %f!=? %r)"; }
emitC()7918     virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; }
emitSimpleOperator()7919     virtual string emitSimpleOperator() override { return "!="; }
cleanOut()7920     virtual bool cleanOut() const override { return true; }
cleanLhs()7921     virtual bool cleanLhs() const override { return true; }
cleanRhs()7922     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7923     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7924     virtual bool sizeMattersRhs() const override { return false; }
7925 };
7926 class AstConcat final : public AstNodeBiop {
7927     // If you're looking for {#{}}, see AstReplicate
7928 public:
AstConcat(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7929     AstConcat(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7930         : ASTGEN_SUPER_Concat(fl, lhsp, rhsp) {
7931         if (lhsp->dtypep() && rhsp->dtypep()) {
7932             dtypeSetLogicSized(lhsp->dtypep()->width() + rhsp->dtypep()->width(),
7933                                VSigning::UNSIGNED);
7934         }
7935     }
ASTNODE_NODE_FUNCS(Concat)7936     ASTNODE_NODE_FUNCS(Concat)
7937     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7938         return new AstConcat(this->fileline(), lhsp, rhsp);
7939     }
emitVerilog()7940     virtual string emitVerilog() override { return "%f{%l, %k%r}"; }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7941     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7942         out.opConcat(lhs, rhs);
7943     }
emitC()7944     virtual string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
cleanOut()7945     virtual bool cleanOut() const override { return true; }
cleanLhs()7946     virtual bool cleanLhs() const override { return true; }
cleanRhs()7947     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7948     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7949     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7950     virtual int instrCount() const override { return widthInstrs() * 2; }
7951 };
7952 class AstConcatN final : public AstNodeBiop {
7953     // String concatenate
7954 public:
AstConcatN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7955     AstConcatN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7956         : ASTGEN_SUPER_ConcatN(fl, lhsp, rhsp) {
7957         dtypeSetString();
7958     }
ASTNODE_NODE_FUNCS(ConcatN)7959     ASTNODE_NODE_FUNCS(ConcatN)
7960     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7961         return new AstConcatN(this->fileline(), lhsp, rhsp);
7962     }
emitVerilog()7963     virtual string emitVerilog() override { return "%f{%l, %k%r}"; }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7964     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7965         out.opConcatN(lhs, rhs);
7966     }
emitC()7967     virtual string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; }
cleanOut()7968     virtual bool cleanOut() const override { return true; }
cleanLhs()7969     virtual bool cleanLhs() const override { return true; }
cleanRhs()7970     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()7971     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()7972     virtual bool sizeMattersRhs() const override { return false; }
instrCount()7973     virtual int instrCount() const override { return INSTR_COUNT_STR; }
stringFlavor()7974     virtual bool stringFlavor() const override { return true; }
7975 };
7976 class AstReplicate final : public AstNodeBiop {
7977     // Also used as a "Uniop" flavor of Concat, e.g. "{a}"
7978     // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp()
7979 public:
AstReplicate(FileLine * fl,AstNode * lhsp,AstNode * rhsp)7980     AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
7981         : ASTGEN_SUPER_Replicate(fl, lhsp, rhsp) {
7982         if (lhsp) {
7983             if (const AstConst* const constp = VN_CAST(rhsp, Const)) {
7984                 dtypeSetLogicSized(lhsp->width() * constp->toUInt(), VSigning::UNSIGNED);
7985             }
7986         }
7987     }
AstReplicate(FileLine * fl,AstNode * lhsp,uint32_t repCount)7988     AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount)
7989         : AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {}
ASTNODE_NODE_FUNCS(Replicate)7990     ASTNODE_NODE_FUNCS(Replicate)
7991     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
7992         return new AstReplicate(this->fileline(), lhsp, rhsp);
7993     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)7994     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
7995         out.opRepl(lhs, rhs);
7996     }
emitVerilog()7997     virtual string emitVerilog() override { return "%f{%r{%k%l}}"; }
emitC()7998     virtual string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%lw, %P, %li, %ri)"; }
cleanOut()7999     virtual bool cleanOut() const override { return false; }
cleanLhs()8000     virtual bool cleanLhs() const override { return true; }
cleanRhs()8001     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8002     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8003     virtual bool sizeMattersRhs() const override { return false; }
instrCount()8004     virtual int instrCount() const override { return widthInstrs() * 2; }
8005 };
8006 class AstReplicateN final : public AstNodeBiop {
8007     // String replicate
8008 public:
AstReplicateN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8009     AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8010         : ASTGEN_SUPER_ReplicateN(fl, lhsp, rhsp) {
8011         dtypeSetString();
8012     }
AstReplicateN(FileLine * fl,AstNode * lhsp,uint32_t repCount)8013     AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount)
8014         : AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {}
ASTNODE_NODE_FUNCS(ReplicateN)8015     ASTNODE_NODE_FUNCS(ReplicateN)
8016     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8017         return new AstReplicateN(this->fileline(), lhsp, rhsp);
8018     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8019     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8020         out.opReplN(lhs, rhs);
8021     }
emitVerilog()8022     virtual string emitVerilog() override { return "%f{%r{%k%l}}"; }
emitC()8023     virtual string emitC() override { return "VL_REPLICATEN_NN%rq(%li, %ri)"; }
cleanOut()8024     virtual bool cleanOut() const override { return false; }
cleanLhs()8025     virtual bool cleanLhs() const override { return true; }
cleanRhs()8026     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8027     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8028     virtual bool sizeMattersRhs() const override { return false; }
instrCount()8029     virtual int instrCount() const override { return widthInstrs() * 2; }
stringFlavor()8030     virtual bool stringFlavor() const override { return true; }
8031 };
8032 class AstStreamL final : public AstNodeStream {
8033     // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
8034 public:
AstStreamL(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8035     AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8036         : ASTGEN_SUPER_StreamL(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(StreamL)8037     ASTNODE_NODE_FUNCS(StreamL)
8038     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8039         return new AstStreamL(this->fileline(), lhsp, rhsp);
8040     }
emitVerilog()8041     virtual string emitVerilog() override { return "%f{ << %r %k{%l} }"; }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8042     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8043         out.opStreamL(lhs, rhs);
8044     }
emitC()8045     virtual string emitC() override { return "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)"; }
cleanOut()8046     virtual bool cleanOut() const override { return true; }
cleanLhs()8047     virtual bool cleanLhs() const override { return true; }
cleanRhs()8048     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8049     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()8050     virtual bool sizeMattersRhs() const override { return false; }
instrCount()8051     virtual int instrCount() const override { return widthInstrs() * 2; }
8052 };
8053 class AstStreamR final : public AstNodeStream {
8054     // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
8055 public:
AstStreamR(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8056     AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8057         : ASTGEN_SUPER_StreamR(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(StreamR)8058     ASTNODE_NODE_FUNCS(StreamR)
8059     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8060         return new AstStreamR(this->fileline(), lhsp, rhsp);
8061     }
emitVerilog()8062     virtual string emitVerilog() override { return "%f{ >> %r %k{%l} }"; }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8063     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8064         out.opAssign(lhs);
8065     }
emitC()8066     virtual string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; }
cleanOut()8067     virtual bool cleanOut() const override { return false; }
cleanLhs()8068     virtual bool cleanLhs() const override { return false; }
cleanRhs()8069     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()8070     virtual bool sizeMattersLhs() const override { return true; }
sizeMattersRhs()8071     virtual bool sizeMattersRhs() const override { return false; }
instrCount()8072     virtual int instrCount() const override { return widthInstrs() * 2; }
8073 };
8074 class AstBufIf1 final : public AstNodeBiop {
8075     // lhs is enable, rhs is data to drive
8076     // Note unlike the Verilog bufif1() UDP, this allows any width; each lhsp
8077     // bit enables respective rhsp bit
8078 public:
AstBufIf1(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8079     AstBufIf1(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8080         : ASTGEN_SUPER_BufIf1(fl, lhsp, rhsp) {
8081         dtypeFrom(lhsp);
8082     }
ASTNODE_NODE_FUNCS(BufIf1)8083     ASTNODE_NODE_FUNCS(BufIf1)
8084     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8085         return new AstBufIf1(this->fileline(), lhsp, rhsp);
8086     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8087     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8088         out.opBufIf1(lhs, rhs);
8089     }
emitVerilog()8090     virtual string emitVerilog() override { return "bufif(%r,%l)"; }
emitC()8091     virtual string emitC() override { V3ERROR_NA_RETURN(""); }  // Lclean || Rclean
emitSimpleOperator()8092     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }  // Lclean || Rclean
cleanOut()8093     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }  // Lclean || Rclean
cleanLhs()8094     virtual bool cleanLhs() const override { return false; }
cleanRhs()8095     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()8096     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8097     virtual bool sizeMattersRhs() const override { return false; }
8098 };
8099 class AstFGetS final : public AstNodeBiop {
8100 public:
AstFGetS(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8101     AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8102         : ASTGEN_SUPER_FGetS(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(FGetS)8103     ASTNODE_NODE_FUNCS(FGetS)
8104     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8105         return new AstFGetS(this->fileline(), lhsp, rhsp);
8106     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8107     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8108         V3ERROR_NA;
8109     }
emitVerilog()8110     virtual string emitVerilog() override { return "%f$fgets(%l,%r)"; }
emitC()8111     virtual string emitC() override {
8112         return strgp()->dtypep()->basicp()->isString() ? "VL_FGETS_NI(%li, %ri)"
8113                                                        : "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)";
8114     }
cleanOut()8115     virtual bool cleanOut() const override { return false; }
cleanLhs()8116     virtual bool cleanLhs() const override { return true; }
cleanRhs()8117     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8118     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8119     virtual bool sizeMattersRhs() const override { return false; }
instrCount()8120     virtual int instrCount() const override { return widthInstrs() * 64; }
strgp()8121     AstNode* strgp() const { return lhsp(); }
filep()8122     AstNode* filep() const { return rhsp(); }
8123 };
8124 
8125 class AstNodeSystemBiop VL_NOT_FINAL : public AstNodeBiop {
8126 public:
AstNodeSystemBiop(AstType t,FileLine * fl,AstNode * lhsp,AstNode * rhsp)8127     AstNodeSystemBiop(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8128         : AstNodeBiop(t, fl, lhsp, rhsp) {
8129         dtypeSetDouble();
8130     }
cleanOut()8131     virtual bool cleanOut() const override { return false; }
cleanLhs()8132     virtual bool cleanLhs() const override { return false; }
cleanRhs()8133     virtual bool cleanRhs() const override { return false; }
sizeMattersLhs()8134     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8135     virtual bool sizeMattersRhs() const override { return false; }
instrCount()8136     virtual int instrCount() const override { return INSTR_COUNT_DBL_TRIG; }
doubleFlavor()8137     virtual bool doubleFlavor() const override { return true; }
8138 };
8139 
8140 class AstAtan2D final : public AstNodeSystemBiop {
8141 public:
AstAtan2D(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8142     AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8143         : ASTGEN_SUPER_Atan2D(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(Atan2D)8144     ASTNODE_NODE_FUNCS(Atan2D)
8145     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8146         return new AstAtan2D(this->fileline(), lhsp, rhsp);
8147     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8148     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8149         out.setDouble(std::atan2(lhs.toDouble(), rhs.toDouble()));
8150     }
emitVerilog()8151     virtual string emitVerilog() override { return "%f$atan2(%l,%r)"; }
emitC()8152     virtual string emitC() override { return "atan2(%li,%ri)"; }
8153 };
8154 
8155 class AstHypotD final : public AstNodeSystemBiop {
8156 public:
AstHypotD(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8157     AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8158         : ASTGEN_SUPER_HypotD(fl, lhsp, rhsp) {}
ASTNODE_NODE_FUNCS(HypotD)8159     ASTNODE_NODE_FUNCS(HypotD)
8160     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8161         return new AstHypotD(this->fileline(), lhsp, rhsp);
8162     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8163     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8164         out.setDouble(std::hypot(lhs.toDouble(), rhs.toDouble()));
8165     }
emitVerilog()8166     virtual string emitVerilog() override { return "%f$hypot(%l,%r)"; }
emitC()8167     virtual string emitC() override { return "hypot(%li,%ri)"; }
8168 };
8169 
8170 class AstPutcN final : public AstNodeTriop {
8171     // Verilog string.putc()
8172 public:
AstPutcN(FileLine * fl,AstNode * lhsp,AstNode * rhsp,AstNode * ths)8173     AstPutcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths)
8174         : ASTGEN_SUPER_PutcN(fl, lhsp, rhsp, ths) {
8175         dtypeSetString();
8176     }
ASTNODE_NODE_FUNCS(PutcN)8177     ASTNODE_NODE_FUNCS(PutcN)
8178     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
8179                                const V3Number& ths) override {
8180         out.opPutcN(lhs, rhs, ths);
8181     }
name()8182     virtual string name() const override { return "putc"; }
emitVerilog()8183     virtual string emitVerilog() override { return "%k(%l.putc(%r,%t))"; }
emitC()8184     virtual string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; }
emitSimpleOperator()8185     virtual string emitSimpleOperator() override { return ""; }
cleanOut()8186     virtual bool cleanOut() const override { return true; }
cleanLhs()8187     virtual bool cleanLhs() const override { return true; }
cleanRhs()8188     virtual bool cleanRhs() const override { return true; }
cleanThs()8189     virtual bool cleanThs() const override { return true; }
sizeMattersLhs()8190     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8191     virtual bool sizeMattersRhs() const override { return false; }
sizeMattersThs()8192     virtual bool sizeMattersThs() const override { return false; }
8193 };
8194 
8195 class AstGetcN final : public AstNodeBiop {
8196     // Verilog string.getc()
8197 public:
AstGetcN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8198     AstGetcN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8199         : ASTGEN_SUPER_GetcN(fl, lhsp, rhsp) {
8200         dtypeSetBitSized(8, VSigning::UNSIGNED);
8201     }
ASTNODE_NODE_FUNCS(GetcN)8202     ASTNODE_NODE_FUNCS(GetcN)
8203     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8204         return new AstGetcN(this->fileline(), lhsp, rhsp);
8205     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8206     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8207         out.opGetcN(lhs, rhs);
8208     }
name()8209     virtual string name() const override { return "getc"; }
emitVerilog()8210     virtual string emitVerilog() override { return "%k(%l.getc(%r))"; }
emitC()8211     virtual string emitC() override { return "VL_GETC_N(%li,%ri)"; }
emitSimpleOperator()8212     virtual string emitSimpleOperator() override { return ""; }
cleanOut()8213     virtual bool cleanOut() const override { return true; }
cleanLhs()8214     virtual bool cleanLhs() const override { return true; }
cleanRhs()8215     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8216     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8217     virtual bool sizeMattersRhs() const override { return false; }
8218 };
8219 
8220 class AstGetcRefN final : public AstNodeBiop {
8221     // Verilog string[#] on the left-hand-side of assignment
8222     // Spec says is of type byte (not string of single character)
8223 public:
AstGetcRefN(FileLine * fl,AstNode * lhsp,AstNode * rhsp)8224     AstGetcRefN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
8225         : ASTGEN_SUPER_GetcRefN(fl, lhsp, rhsp) {
8226         dtypeSetBitSized(8, VSigning::UNSIGNED);
8227     }
ASTNODE_NODE_FUNCS(GetcRefN)8228     ASTNODE_NODE_FUNCS(GetcRefN)
8229     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8230         return new AstGetcRefN(this->fileline(), lhsp, rhsp);
8231     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8232     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8233         V3ERROR_NA;
8234     }
emitVerilog()8235     virtual string emitVerilog() override { return "%k%l[%r]"; }
emitC()8236     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8237     virtual string emitSimpleOperator() override { return ""; }
cleanOut()8238     virtual bool cleanOut() const override { return true; }
cleanLhs()8239     virtual bool cleanLhs() const override { return true; }
cleanRhs()8240     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8241     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8242     virtual bool sizeMattersRhs() const override { return false; }
8243 };
8244 
8245 class AstSubstrN final : public AstNodeTriop {
8246     // Verilog string.substr()
8247 public:
AstSubstrN(FileLine * fl,AstNode * lhsp,AstNode * rhsp,AstNode * ths)8248     AstSubstrN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, AstNode* ths)
8249         : ASTGEN_SUPER_SubstrN(fl, lhsp, rhsp, ths) {
8250         dtypeSetString();
8251     }
ASTNODE_NODE_FUNCS(SubstrN)8252     ASTNODE_NODE_FUNCS(SubstrN)
8253     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
8254                                const V3Number& ths) override {
8255         out.opSubstrN(lhs, rhs, ths);
8256     }
name()8257     virtual string name() const override { return "substr"; }
emitVerilog()8258     virtual string emitVerilog() override { return "%k(%l.substr(%r,%t))"; }
emitC()8259     virtual string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; }
emitSimpleOperator()8260     virtual string emitSimpleOperator() override { return ""; }
cleanOut()8261     virtual bool cleanOut() const override { return true; }
cleanLhs()8262     virtual bool cleanLhs() const override { return true; }
cleanRhs()8263     virtual bool cleanRhs() const override { return true; }
cleanThs()8264     virtual bool cleanThs() const override { return true; }
sizeMattersLhs()8265     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8266     virtual bool sizeMattersRhs() const override { return false; }
sizeMattersThs()8267     virtual bool sizeMattersThs() const override { return false; }
8268 };
8269 
8270 class AstCompareNN final : public AstNodeBiop {
8271     // Verilog str.compare() and str.icompare()
8272 private:
8273     const bool m_ignoreCase;  // True for str.icompare()
8274 public:
AstCompareNN(FileLine * fl,AstNode * lhsp,AstNode * rhsp,bool ignoreCase)8275     AstCompareNN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, bool ignoreCase)
8276         : ASTGEN_SUPER_CompareNN(fl, lhsp, rhsp)
8277         , m_ignoreCase{ignoreCase} {
8278         dtypeSetUInt32();
8279     }
ASTNODE_NODE_FUNCS(CompareNN)8280     ASTNODE_NODE_FUNCS(CompareNN)
8281     virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override {
8282         return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase);
8283     }
numberOperate(V3Number & out,const V3Number & lhs,const V3Number & rhs)8284     virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override {
8285         out.opCompareNN(lhs, rhs, m_ignoreCase);
8286     }
name()8287     virtual string name() const override { return m_ignoreCase ? "icompare" : "compare"; }
emitVerilog()8288     virtual string emitVerilog() override {
8289         return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))";
8290     }
emitC()8291     virtual string emitC() override {
8292         return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)";
8293     }
emitSimpleOperator()8294     virtual string emitSimpleOperator() override { return ""; }
cleanOut()8295     virtual bool cleanOut() const override { return true; }
cleanLhs()8296     virtual bool cleanLhs() const override { return true; }
cleanRhs()8297     virtual bool cleanRhs() const override { return true; }
sizeMattersLhs()8298     virtual bool sizeMattersLhs() const override { return false; }
sizeMattersRhs()8299     virtual bool sizeMattersRhs() const override { return false; }
8300 };
8301 
8302 class AstFell final : public AstNodeMath {
8303     // Verilog $fell
8304     // Parents: math
8305     // Children: expression
8306 public:
AstFell(FileLine * fl,AstNode * exprp)8307     AstFell(FileLine* fl, AstNode* exprp)
8308         : ASTGEN_SUPER_Fell(fl) {
8309         addOp1p(exprp);
8310     }
ASTNODE_NODE_FUNCS(Fell)8311     ASTNODE_NODE_FUNCS(Fell)
8312     virtual string emitVerilog() override { return "$fell(%l)"; }
emitC()8313     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8314     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8315     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8316     virtual int instrCount() const override { return widthInstrs(); }
exprp()8317     AstNode* exprp() const { return op1p(); }  // op1 = expression
sentreep()8318     AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); }  // op2 = clock domain
sentreep(AstSenTree * sentreep)8319     void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); }  // op2 = clock domain
same(const AstNode * samep)8320     virtual bool same(const AstNode* samep) const override { return true; }
8321 };
8322 
8323 class AstPast final : public AstNodeMath {
8324     // Verilog $past
8325     // Parents: math
8326     // Children: expression
8327 public:
AstPast(FileLine * fl,AstNode * exprp,AstNode * ticksp)8328     AstPast(FileLine* fl, AstNode* exprp, AstNode* ticksp)
8329         : ASTGEN_SUPER_Past(fl) {
8330         addOp1p(exprp);
8331         addNOp2p(ticksp);
8332     }
ASTNODE_NODE_FUNCS(Past)8333     ASTNODE_NODE_FUNCS(Past)
8334     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()8335     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8336     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8337     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8338     virtual int instrCount() const override { return widthInstrs(); }
exprp()8339     AstNode* exprp() const { return op1p(); }  // op1 = expression
ticksp()8340     AstNode* ticksp() const { return op2p(); }  // op2 = ticks or nullptr means 1
sentreep()8341     AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); }  // op4 = clock domain
sentreep(AstSenTree * sentreep)8342     void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); }  // op4 = clock domain
same(const AstNode * samep)8343     virtual bool same(const AstNode* samep) const override { return true; }
8344 };
8345 
8346 class AstRose final : public AstNodeMath {
8347     // Verilog $rose
8348     // Parents: math
8349     // Children: expression
8350 public:
AstRose(FileLine * fl,AstNode * exprp)8351     AstRose(FileLine* fl, AstNode* exprp)
8352         : ASTGEN_SUPER_Rose(fl) {
8353         addOp1p(exprp);
8354     }
ASTNODE_NODE_FUNCS(Rose)8355     ASTNODE_NODE_FUNCS(Rose)
8356     virtual string emitVerilog() override { return "$rose(%l)"; }
emitC()8357     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8358     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8359     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8360     virtual int instrCount() const override { return widthInstrs(); }
exprp()8361     AstNode* exprp() const { return op1p(); }  // op1 = expression
sentreep()8362     AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); }  // op2 = clock domain
sentreep(AstSenTree * sentreep)8363     void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); }  // op2 = clock domain
same(const AstNode * samep)8364     virtual bool same(const AstNode* samep) const override { return true; }
8365 };
8366 
8367 class AstSampled final : public AstNodeMath {
8368     // Verilog $sampled
8369     // Parents: math
8370     // Children: expression
8371 public:
AstSampled(FileLine * fl,AstNode * exprp)8372     AstSampled(FileLine* fl, AstNode* exprp)
8373         : ASTGEN_SUPER_Sampled(fl) {
8374         addOp1p(exprp);
8375     }
ASTNODE_NODE_FUNCS(Sampled)8376     ASTNODE_NODE_FUNCS(Sampled)
8377     virtual string emitVerilog() override { return "$sampled(%l)"; }
emitC()8378     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8379     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8380     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8381     virtual int instrCount() const override { return 0; }
exprp()8382     AstNode* exprp() const { return op1p(); }  // op1 = expression
same(const AstNode * samep)8383     virtual bool same(const AstNode* samep) const override { return true; }
8384 };
8385 
8386 class AstStable final : public AstNodeMath {
8387     // Verilog $stable
8388     // Parents: math
8389     // Children: expression
8390 public:
AstStable(FileLine * fl,AstNode * exprp)8391     AstStable(FileLine* fl, AstNode* exprp)
8392         : ASTGEN_SUPER_Stable(fl) {
8393         addOp1p(exprp);
8394     }
ASTNODE_NODE_FUNCS(Stable)8395     ASTNODE_NODE_FUNCS(Stable)
8396     virtual string emitVerilog() override { return "$stable(%l)"; }
emitC()8397     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8398     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8399     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8400     virtual int instrCount() const override { return widthInstrs(); }
exprp()8401     AstNode* exprp() const { return op1p(); }  // op1 = expression
sentreep()8402     AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); }  // op2 = clock domain
sentreep(AstSenTree * sentreep)8403     void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); }  // op2 = clock domain
same(const AstNode * samep)8404     virtual bool same(const AstNode* samep) const override { return true; }
8405 };
8406 
8407 class AstPattern final : public AstNodeMath {
8408     // Verilog '{a,b,c,d...}
8409     // Parents: AstNodeAssign, AstPattern, ...
8410     // Children: expression, AstPattern, AstPatReplicate
8411 public:
AstPattern(FileLine * fl,AstNode * itemsp)8412     AstPattern(FileLine* fl, AstNode* itemsp)
8413         : ASTGEN_SUPER_Pattern(fl) {
8414         addNOp2p(itemsp);
8415     }
ASTNODE_NODE_FUNCS(Pattern)8416     ASTNODE_NODE_FUNCS(Pattern)
8417     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()8418     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8419     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8420     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8421     virtual int instrCount() const override { return widthInstrs(); }
getChildDTypep()8422     virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
subDTypep()8423     virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); }
8424     // op1 = Type assigning to
childDTypep()8425     AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
childDTypep(AstNodeDType * nodep)8426     void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
itemsp()8427     AstNode* itemsp() const { return op2p(); }  // op2 = AstPatReplicate, AstPatMember, etc
8428 };
8429 class AstPatMember final : public AstNodeMath {
8430     // Verilog '{a} or '{a{b}}
8431     // Parents: AstPattern
8432     // Children: expression, AstPattern, replication count
8433 private:
8434     bool m_default = false;
8435 
8436 public:
AstPatMember(FileLine * fl,AstNode * lhsp,AstNode * keyp,AstNode * repp)8437     AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp)
8438         : ASTGEN_SUPER_PatMember(fl) {
8439         addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp);
8440     }
ASTNODE_NODE_FUNCS(PatMember)8441     ASTNODE_NODE_FUNCS(PatMember)
8442     virtual string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; }
emitC()8443     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8444     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8445     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8446     virtual int instrCount() const override { return widthInstrs() * 2; }
8447     virtual void dump(std::ostream& str = std::cout) const override;
8448     // op1 = expression to assign or another AstPattern (list if replicated)
lhssp()8449     AstNode* lhssp() const { return op1p(); }
keyp()8450     AstNode* keyp() const { return op2p(); }  // op2 = assignment key (Const, id Text)
repp()8451     AstNode* repp() const { return op3p(); }  // op3 = replication count, or nullptr for count 1
isDefault()8452     bool isDefault() const { return m_default; }
isDefault(bool flag)8453     void isDefault(bool flag) { m_default = flag; }
8454 };
8455 
8456 class AstImplication final : public AstNodeMath {
8457     // Verilog |-> |=>
8458     // Parents: math
8459     // Children: expression
8460 public:
AstImplication(FileLine * fl,AstNode * lhs,AstNode * rhs)8461     AstImplication(FileLine* fl, AstNode* lhs, AstNode* rhs)
8462         : ASTGEN_SUPER_Implication(fl) {
8463         setOp1p(lhs);
8464         setOp2p(rhs);
8465     }
ASTNODE_NODE_FUNCS(Implication)8466     ASTNODE_NODE_FUNCS(Implication)
8467     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()8468     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
emitSimpleOperator()8469     virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
cleanOut()8470     virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); }
instrCount()8471     virtual int instrCount() const override { return widthInstrs(); }
lhsp()8472     AstNode* lhsp() const { return op1p(); }
rhsp()8473     AstNode* rhsp() const { return op2p(); }
lhsp(AstNode * nodep)8474     void lhsp(AstNode* nodep) { return setOp1p(nodep); }
rhsp(AstNode * nodep)8475     void rhsp(AstNode* nodep) { return setOp2p(nodep); }
sentreep()8476     AstSenTree* sentreep() const { return VN_AS(op4p(), SenTree); }  // op4 = clock domain
sentreep(AstSenTree * sentreep)8477     void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); }  // op4 = clock domain
same(const AstNode * samep)8478     virtual bool same(const AstNode* samep) const override { return true; }
8479 };
8480 
8481 //======================================================================
8482 // Assertions
8483 
8484 class AstClocking final : public AstNode {
8485     // Set default clock region
8486     // Parents:  MODULE
8487     // Children: Assertions
8488 public:
AstClocking(FileLine * fl,AstSenItem * sensesp,AstNode * bodysp)8489     AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp)
8490         : ASTGEN_SUPER_Clocking(fl) {
8491         addOp1p(sensesp);
8492         addNOp2p(bodysp);
8493     }
ASTNODE_NODE_FUNCS(Clocking)8494     ASTNODE_NODE_FUNCS(Clocking)
8495     // op1 = Sensitivity list
8496     AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); }
bodysp()8497     AstNode* bodysp() const { return op2p(); }  // op2 = Body
8498 };
8499 
8500 //======================================================================
8501 // PSL
8502 
8503 class AstPropClocked final : public AstNode {
8504     // A clocked property
8505     // Parents:  ASSERT|COVER (property)
8506     // Children: SENITEM, Properties
8507 public:
AstPropClocked(FileLine * fl,AstSenItem * sensesp,AstNode * disablep,AstNode * propp)8508     AstPropClocked(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp)
8509         : ASTGEN_SUPER_PropClocked(fl) {
8510         addNOp1p(sensesp);
8511         addNOp2p(disablep);
8512         addOp3p(propp);
8513     }
ASTNODE_NODE_FUNCS(PropClocked)8514     ASTNODE_NODE_FUNCS(PropClocked)
8515     virtual bool hasDType() const override {
8516         return true;
8517     }  // Used under Cover, which expects a bool child
sensesp()8518     AstSenItem* sensesp() const { return VN_AS(op1p(), SenItem); }  // op1 = Sensitivity list
disablep()8519     AstNode* disablep() const { return op2p(); }  // op2 = disable
propp()8520     AstNode* propp() const { return op3p(); }  // op3 = property
8521 };
8522 
8523 class AstNodeCoverOrAssert VL_NOT_FINAL : public AstNodeStmt {
8524     // Cover or Assert
8525     // Parents:  {statement list}
8526     // Children: expression, report string
8527 private:
8528     const bool m_immediate;  // Immediate assertion/cover
8529     string m_name;  // Name to report
8530 public:
8531     AstNodeCoverOrAssert(AstType t, FileLine* fl, AstNode* propp, AstNode* passsp, bool immediate,
8532                          const string& name = "")
8533         : AstNodeStmt{t, fl}
8534         , m_immediate{immediate}
8535         , m_name{name} {
8536         addOp1p(propp);
8537         addNOp4p(passsp);
8538     }
ASTNODE_BASE_FUNCS(NodeCoverOrAssert)8539     ASTNODE_BASE_FUNCS(NodeCoverOrAssert)
8540     virtual string name() const override { return m_name; }  // * = Var name
same(const AstNode * samep)8541     virtual bool same(const AstNode* samep) const override { return samep->name() == name(); }
name(const string & name)8542     virtual void name(const string& name) override { m_name = name; }
8543     virtual void dump(std::ostream& str = std::cout) const override;
propp()8544     AstNode* propp() const { return op1p(); }  // op1 = property
sentreep()8545     AstSenTree* sentreep() const { return VN_AS(op2p(), SenTree); }  // op2 = clock domain
sentreep(AstSenTree * sentreep)8546     void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); }  // op2 = clock domain
passsp()8547     AstNode* passsp() const { return op4p(); }  // op4 = statements (assert/cover passes)
immediate()8548     bool immediate() const { return m_immediate; }
8549 };
8550 
8551 class AstAssert final : public AstNodeCoverOrAssert {
8552 public:
ASTNODE_NODE_FUNCS(Assert)8553     ASTNODE_NODE_FUNCS(Assert)
8554     AstAssert(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp, bool immediate,
8555               const string& name = "")
8556         : ASTGEN_SUPER_Assert(fl, propp, passsp, immediate, name) {
8557         addNOp3p(failsp);
8558     }
failsp()8559     AstNode* failsp() const { return op3p(); }  // op3 = if assertion fails
8560 };
8561 
8562 class AstAssertIntrinsic final : public AstNodeCoverOrAssert {
8563     // A $cast or other compiler inserted assert, that must run even without --assert option
8564 public:
ASTNODE_NODE_FUNCS(AssertIntrinsic)8565     ASTNODE_NODE_FUNCS(AssertIntrinsic)
8566     AstAssertIntrinsic(FileLine* fl, AstNode* propp, AstNode* passsp, AstNode* failsp,
8567                        bool immediate, const string& name = "")
8568         : ASTGEN_SUPER_AssertIntrinsic(fl, propp, passsp, immediate, name) {
8569         addNOp3p(failsp);
8570     }
failsp()8571     AstNode* failsp() const { return op3p(); }  // op3 = if assertion fails
8572 };
8573 
8574 class AstCover final : public AstNodeCoverOrAssert {
8575 public:
ASTNODE_NODE_FUNCS(Cover)8576     ASTNODE_NODE_FUNCS(Cover)
8577     AstCover(FileLine* fl, AstNode* propp, AstNode* stmtsp, bool immediate,
8578              const string& name = "")
8579         : ASTGEN_SUPER_Cover(fl, propp, stmtsp, immediate, name) {}
coverincp()8580     AstNode* coverincp() const { return op3p(); }  // op3 = coverage node
coverincp(AstCoverInc * nodep)8581     void coverincp(AstCoverInc* nodep) { addOp3p(nodep); }  // op3 = coverage node
immediate()8582     virtual bool immediate() const { return false; }
8583 };
8584 
8585 class AstRestrict final : public AstNodeCoverOrAssert {
8586 public:
ASTNODE_NODE_FUNCS(Restrict)8587     ASTNODE_NODE_FUNCS(Restrict)
8588     AstRestrict(FileLine* fl, AstNode* propp)
8589         : ASTGEN_SUPER_Restrict(fl, propp, nullptr, false, "") {}
8590 };
8591 
8592 //======================================================================
8593 // Text based nodes
8594 
8595 class AstNodeSimpleText VL_NOT_FINAL : public AstNodeText {
8596 private:
8597     bool m_tracking;  // When emit, it's ok to parse the string to do indentation
8598 public:
8599     AstNodeSimpleText(AstType t, FileLine* fl, const string& textp, bool tracking = false)
AstNodeText(t,fl,textp)8600         : AstNodeText(t, fl, textp)
8601         , m_tracking(tracking) {}
ASTNODE_BASE_FUNCS(NodeSimpleText)8602     ASTNODE_BASE_FUNCS(NodeSimpleText)
8603     void tracking(bool flag) { m_tracking = flag; }
tracking()8604     bool tracking() const { return m_tracking; }
8605 };
8606 
8607 class AstText final : public AstNodeSimpleText {
8608 public:
8609     AstText(FileLine* fl, const string& textp, bool tracking = false)
ASTGEN_SUPER_Text(fl,textp,tracking)8610         : ASTGEN_SUPER_Text(fl, textp, tracking) {}
8611     ASTNODE_NODE_FUNCS(Text)
8612 };
8613 
8614 class AstTextBlock final : public AstNodeSimpleText {
8615 private:
8616     bool m_commas;  // Comma separate emitted children
8617 public:
8618     explicit AstTextBlock(FileLine* fl, const string& textp = "", bool tracking = false,
8619                           bool commas = false)
ASTGEN_SUPER_TextBlock(fl,textp,tracking)8620         : ASTGEN_SUPER_TextBlock(fl, textp, tracking)
8621         , m_commas(commas) {}
ASTNODE_NODE_FUNCS(TextBlock)8622     ASTNODE_NODE_FUNCS(TextBlock)
8623     void commas(bool flag) { m_commas = flag; }
commas()8624     bool commas() const { return m_commas; }
nodesp()8625     AstNode* nodesp() const { return op1p(); }
addNodep(AstNode * nodep)8626     void addNodep(AstNode* nodep) { addOp1p(nodep); }
8627     void addText(FileLine* fl, const string& textp, bool tracking = false) {
8628         addNodep(new AstText(fl, textp, tracking));
8629     }
8630 };
8631 
8632 class AstScCtor final : public AstNodeText {
8633 public:
AstScCtor(FileLine * fl,const string & textp)8634     AstScCtor(FileLine* fl, const string& textp)
8635         : ASTGEN_SUPER_ScCtor(fl, textp) {}
ASTNODE_NODE_FUNCS(ScCtor)8636     ASTNODE_NODE_FUNCS(ScCtor)
8637     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()8638     virtual bool isOutputter() const override { return true; }
8639 };
8640 
8641 class AstScDtor final : public AstNodeText {
8642 public:
AstScDtor(FileLine * fl,const string & textp)8643     AstScDtor(FileLine* fl, const string& textp)
8644         : ASTGEN_SUPER_ScDtor(fl, textp) {}
ASTNODE_NODE_FUNCS(ScDtor)8645     ASTNODE_NODE_FUNCS(ScDtor)
8646     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()8647     virtual bool isOutputter() const override { return true; }
8648 };
8649 
8650 class AstScHdr final : public AstNodeText {
8651 public:
AstScHdr(FileLine * fl,const string & textp)8652     AstScHdr(FileLine* fl, const string& textp)
8653         : ASTGEN_SUPER_ScHdr(fl, textp) {}
ASTNODE_NODE_FUNCS(ScHdr)8654     ASTNODE_NODE_FUNCS(ScHdr)
8655     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()8656     virtual bool isOutputter() const override { return true; }
8657 };
8658 
8659 class AstScImp final : public AstNodeText {
8660 public:
AstScImp(FileLine * fl,const string & textp)8661     AstScImp(FileLine* fl, const string& textp)
8662         : ASTGEN_SUPER_ScImp(fl, textp) {}
ASTNODE_NODE_FUNCS(ScImp)8663     ASTNODE_NODE_FUNCS(ScImp)
8664     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()8665     virtual bool isOutputter() const override { return true; }
8666 };
8667 
8668 class AstScImpHdr final : public AstNodeText {
8669 public:
AstScImpHdr(FileLine * fl,const string & textp)8670     AstScImpHdr(FileLine* fl, const string& textp)
8671         : ASTGEN_SUPER_ScImpHdr(fl, textp) {}
ASTNODE_NODE_FUNCS(ScImpHdr)8672     ASTNODE_NODE_FUNCS(ScImpHdr)
8673     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()8674     virtual bool isOutputter() const override { return true; }
8675 };
8676 
8677 class AstScInt final : public AstNodeText {
8678 public:
AstScInt(FileLine * fl,const string & textp)8679     AstScInt(FileLine* fl, const string& textp)
8680         : ASTGEN_SUPER_ScInt(fl, textp) {}
ASTNODE_NODE_FUNCS(ScInt)8681     ASTNODE_NODE_FUNCS(ScInt)
8682     virtual bool isPure() const override { return false; }  // SPECIAL: User may order w/other sigs
isOutputter()8683     virtual bool isOutputter() const override { return true; }
8684 };
8685 
8686 class AstUCStmt final : public AstNodeStmt {
8687     // User $c statement
8688 public:
AstUCStmt(FileLine * fl,AstNode * exprsp)8689     AstUCStmt(FileLine* fl, AstNode* exprsp)
8690         : ASTGEN_SUPER_UCStmt(fl) {
8691         addNOp1p(exprsp);
8692     }
ASTNODE_NODE_FUNCS(UCStmt)8693     ASTNODE_NODE_FUNCS(UCStmt)
8694     AstNode* bodysp() const { return op1p(); }  // op1 = expressions to print
isGateOptimizable()8695     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()8696     virtual bool isPredictOptimizable() const override { return false; }
isPure()8697     virtual bool isPure() const override { return false; }
isOutputter()8698     virtual bool isOutputter() const override { return true; }
same(const AstNode * samep)8699     virtual bool same(const AstNode* samep) const override { return true; }
8700 };
8701 
8702 //======================================================================
8703 // Emitted file nodes
8704 
8705 class AstNodeFile VL_NOT_FINAL : public AstNode {
8706     // Emitted Otput file
8707     // Parents:  NETLIST
8708     // Children: AstTextBlock
8709 private:
8710     string m_name;  ///< Filename
8711 public:
AstNodeFile(AstType t,FileLine * fl,const string & name)8712     AstNodeFile(AstType t, FileLine* fl, const string& name)
8713         : AstNode(t, fl) {
8714         m_name = name;
8715     }
8716     ASTNODE_BASE_FUNCS(NodeFile)
8717     virtual void dump(std::ostream& str) const override;
name()8718     virtual string name() const override { return m_name; }
same(const AstNode * samep)8719     virtual bool same(const AstNode* samep) const override { return true; }
tblockp(AstTextBlock * tblockp)8720     void tblockp(AstTextBlock* tblockp) { setOp1p(tblockp); }
tblockp()8721     AstTextBlock* tblockp() { return VN_AS(op1p(), TextBlock); }
8722 };
8723 
8724 //======================================================================
8725 // Emit V nodes
8726 
8727 class AstVFile final : public AstNodeFile {
8728     // Verilog output file
8729     // Parents:  NETLIST
8730 public:
AstVFile(FileLine * fl,const string & name)8731     AstVFile(FileLine* fl, const string& name)
8732         : ASTGEN_SUPER_VFile(fl, name) {}
8733     ASTNODE_NODE_FUNCS(VFile)
8734     virtual void dump(std::ostream& str = std::cout) const override;
8735 };
8736 
8737 //======================================================================
8738 // Emit C nodes
8739 
8740 class AstCFile final : public AstNodeFile {
8741     // C++ output file
8742     // Parents:  NETLIST
8743 private:
8744     bool m_slow : 1;  ///< Compile w/o optimization
8745     bool m_source : 1;  ///< Source file (vs header file)
8746     bool m_support : 1;  ///< Support file (non systemc)
8747 public:
AstCFile(FileLine * fl,const string & name)8748     AstCFile(FileLine* fl, const string& name)
8749         : ASTGEN_SUPER_CFile(fl, name)
8750         , m_slow{false}
8751         , m_source{false}
8752         , m_support{false} {}
8753     ASTNODE_NODE_FUNCS(CFile)
8754     virtual void dump(std::ostream& str = std::cout) const override;
slow()8755     bool slow() const { return m_slow; }
slow(bool flag)8756     void slow(bool flag) { m_slow = flag; }
source()8757     bool source() const { return m_source; }
source(bool flag)8758     void source(bool flag) { m_source = flag; }
support()8759     bool support() const { return m_support; }
support(bool flag)8760     void support(bool flag) { m_support = flag; }
8761 };
8762 
8763 class AstCFunc final : public AstNode {
8764     // C++ function
8765     // Parents:  MODULE/SCOPE
8766     // Children: VAR/statements
8767 private:
8768     AstScope* m_scopep;
8769     string m_name;
8770     string m_cname;  // C name, for dpiExports
8771     string m_rtnType;  // void, bool, or other return type
8772     string m_argTypes;  // Argument types
8773     string m_ctorInits;  // Constructor sub-class inits
8774     string m_ifdef;  // #ifdef symbol around this function
8775     VBoolOrUnknown m_isConst;  // Function is declared const (*this not changed)
8776     bool m_isStatic : 1;  // Function is static (no need for a 'this' pointer)
8777     bool m_isTrace : 1;  // Function is related to tracing
8778     bool m_dontCombine : 1;  // V3Combine shouldn't compare this func tree, it's special
8779     bool m_declPrivate : 1;  // Declare it private
8780     bool m_formCallTree : 1;  // Make a global function to call entire tree of functions
8781     bool m_slow : 1;  // Slow routine, called once or just at init time
8782     bool m_funcPublic : 1;  // From user public task/function
8783     bool m_isConstructor : 1;  // Is C class constructor
8784     bool m_isDestructor : 1;  // Is C class destructor
8785     bool m_isMethod : 1;  // Is inside a class definition
8786     bool m_isLoose : 1;  // Semantically this is a method, but is implemented as a function
8787                          // with an explicitly passed 'self' pointer as the first argument
8788     bool m_isInline : 1;  // Inline function
8789     bool m_isVirtual : 1;  // Virtual function
8790     bool m_entryPoint : 1;  // User may call into this top level function
8791     bool m_pure : 1;  // Pure function
8792     bool m_dpiContext : 1;  // Declared as 'context' DPI import/export function
8793     bool m_dpiExportDispatcher : 1;  // This is the DPI export entry point (i.e.: called by user)
8794     bool m_dpiExportImpl : 1;  // DPI export implementation (called from DPI dispatcher via lookup)
8795     bool m_dpiImportPrototype : 1;  // This is the DPI import prototype (i.e.: provided by user)
8796     bool m_dpiImportWrapper : 1;  // Wrapper for invoking DPI import prototype from generated code
8797     bool m_dpiTraceInit : 1;  // DPI trace_init
8798 public:
8799     AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType = "")
ASTGEN_SUPER_CFunc(fl)8800         : ASTGEN_SUPER_CFunc(fl) {
8801         m_isConst = VBoolOrUnknown::BU_UNKNOWN;  // Unknown until analyzed
8802         m_scopep = scopep;
8803         m_name = name;
8804         m_rtnType = rtnType;
8805         m_isStatic = false;
8806         m_isTrace = false;
8807         m_dontCombine = false;
8808         m_declPrivate = false;
8809         m_formCallTree = false;
8810         m_slow = false;
8811         m_funcPublic = false;
8812         m_isConstructor = false;
8813         m_isDestructor = false;
8814         m_isMethod = true;
8815         m_isLoose = false;
8816         m_isInline = false;
8817         m_isVirtual = false;
8818         m_entryPoint = false;
8819         m_pure = false;
8820         m_dpiContext = false;
8821         m_dpiExportDispatcher = false;
8822         m_dpiExportImpl = false;
8823         m_dpiImportPrototype = false;
8824         m_dpiImportWrapper = false;
8825         m_dpiTraceInit = false;
8826     }
ASTNODE_NODE_FUNCS(CFunc)8827     ASTNODE_NODE_FUNCS(CFunc)
8828     virtual string name() const override { return m_name; }
broken()8829     virtual const char* broken() const override {
8830         BROKEN_RTN((m_scopep && !m_scopep->brokeExists()));
8831         return nullptr;
8832     }
maybePointedTo()8833     virtual bool maybePointedTo() const override { return true; }
8834     virtual void dump(std::ostream& str = std::cout) const override;
same(const AstNode * samep)8835     virtual bool same(const AstNode* samep) const override {
8836         const AstCFunc* const asamep = static_cast<const AstCFunc*>(samep);
8837         return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
8838                 && (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits())
8839                 && isLoose() == asamep->isLoose()
8840                 && (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name()));
8841     }
8842     //
name(const string & name)8843     virtual void name(const string& name) override { m_name = name; }
instrCount()8844     virtual int instrCount() const override {
8845         return dpiImportPrototype() ? v3Global.opt.instrCountDpi() : 0;
8846     }
isConst()8847     VBoolOrUnknown isConst() const { return m_isConst; }
isConst(bool flag)8848     void isConst(bool flag) { m_isConst.setTrueOrFalse(flag); }
isConst(VBoolOrUnknown flag)8849     void isConst(VBoolOrUnknown flag) { m_isConst = flag; }
isStatic()8850     bool isStatic() const { return m_isStatic; }
isStatic(bool flag)8851     void isStatic(bool flag) { m_isStatic = flag; }
isTrace()8852     bool isTrace() const { return m_isTrace; }
isTrace(bool flag)8853     void isTrace(bool flag) { m_isTrace = flag; }
cname(const string & name)8854     void cname(const string& name) { m_cname = name; }
cname()8855     string cname() const { return m_cname; }
scopep()8856     AstScope* scopep() const { return m_scopep; }
scopep(AstScope * nodep)8857     void scopep(AstScope* nodep) { m_scopep = nodep; }
rtnTypeVoid()8858     string rtnTypeVoid() const { return ((m_rtnType == "") ? "void" : m_rtnType); }
dontCombine()8859     bool dontCombine() const { return m_dontCombine || isTrace(); }
dontCombine(bool flag)8860     void dontCombine(bool flag) { m_dontCombine = flag; }
dontInline()8861     bool dontInline() const { return dontCombine() || slow() || funcPublic(); }
declPrivate()8862     bool declPrivate() const { return m_declPrivate; }
declPrivate(bool flag)8863     void declPrivate(bool flag) { m_declPrivate = flag; }
formCallTree()8864     bool formCallTree() const { return m_formCallTree; }
formCallTree(bool flag)8865     void formCallTree(bool flag) { m_formCallTree = flag; }
slow()8866     bool slow() const { return m_slow; }
slow(bool flag)8867     void slow(bool flag) { m_slow = flag; }
funcPublic()8868     bool funcPublic() const { return m_funcPublic; }
funcPublic(bool flag)8869     void funcPublic(bool flag) { m_funcPublic = flag; }
argTypes(const string & str)8870     void argTypes(const string& str) { m_argTypes = str; }
argTypes()8871     string argTypes() const { return m_argTypes; }
ctorInits(const string & str)8872     void ctorInits(const string& str) { m_ctorInits = str; }
ctorInits()8873     string ctorInits() const { return m_ctorInits; }
ifdef(const string & str)8874     void ifdef(const string& str) { m_ifdef = str; }
ifdef()8875     string ifdef() const { return m_ifdef; }
isConstructor()8876     bool isConstructor() const { return m_isConstructor; }
isConstructor(bool flag)8877     void isConstructor(bool flag) { m_isConstructor = flag; }
isDestructor()8878     bool isDestructor() const { return m_isDestructor; }
isDestructor(bool flag)8879     void isDestructor(bool flag) { m_isDestructor = flag; }
isMethod()8880     bool isMethod() const { return m_isMethod; }
isMethod(bool flag)8881     void isMethod(bool flag) { m_isMethod = flag; }
isLoose()8882     bool isLoose() const { return m_isLoose; }
isLoose(bool flag)8883     void isLoose(bool flag) { m_isLoose = flag; }
isProperMethod()8884     bool isProperMethod() const { return isMethod() && !isLoose(); }
isInline()8885     bool isInline() const { return m_isInline; }
isInline(bool flag)8886     void isInline(bool flag) { m_isInline = flag; }
isVirtual()8887     bool isVirtual() const { return m_isVirtual; }
isVirtual(bool flag)8888     void isVirtual(bool flag) { m_isVirtual = flag; }
entryPoint()8889     bool entryPoint() const { return m_entryPoint; }
entryPoint(bool flag)8890     void entryPoint(bool flag) { m_entryPoint = flag; }
pure()8891     bool pure() const { return m_pure; }
pure(bool flag)8892     void pure(bool flag) { m_pure = flag; }
dpiContext()8893     bool dpiContext() const { return m_dpiContext; }
dpiContext(bool flag)8894     void dpiContext(bool flag) { m_dpiContext = flag; }
dpiExportDispatcher()8895     bool dpiExportDispatcher() const { return m_dpiExportDispatcher; }
dpiExportDispatcher(bool flag)8896     void dpiExportDispatcher(bool flag) { m_dpiExportDispatcher = flag; }
dpiExportImpl()8897     bool dpiExportImpl() const { return m_dpiExportImpl; }
dpiExportImpl(bool flag)8898     void dpiExportImpl(bool flag) { m_dpiExportImpl = flag; }
dpiImportPrototype()8899     bool dpiImportPrototype() const { return m_dpiImportPrototype; }
dpiImportPrototype(bool flag)8900     void dpiImportPrototype(bool flag) { m_dpiImportPrototype = flag; }
dpiImportWrapper()8901     bool dpiImportWrapper() const { return m_dpiImportWrapper; }
dpiImportWrapper(bool flag)8902     void dpiImportWrapper(bool flag) { m_dpiImportWrapper = flag; }
dpiTraceInit(bool flag)8903     void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; }
dpiTraceInit()8904     bool dpiTraceInit() const { return m_dpiTraceInit; }
8905     //
8906     // If adding node accessors, see below emptyBody
argsp()8907     AstNode* argsp() const { return op1p(); }
addArgsp(AstNode * nodep)8908     void addArgsp(AstNode* nodep) { addOp1p(nodep); }
initsp()8909     AstNode* initsp() const { return op2p(); }
addInitsp(AstNode * nodep)8910     void addInitsp(AstNode* nodep) { addOp2p(nodep); }
stmtsp()8911     AstNode* stmtsp() const { return op3p(); }
addStmtsp(AstNode * nodep)8912     void addStmtsp(AstNode* nodep) { addOp3p(nodep); }
finalsp()8913     AstNode* finalsp() const { return op4p(); }
addFinalsp(AstNode * nodep)8914     void addFinalsp(AstNode* nodep) { addOp4p(nodep); }
8915     // Special methods
emptyBody()8916     bool emptyBody() const {
8917         return argsp() == nullptr && initsp() == nullptr && stmtsp() == nullptr
8918                && finalsp() == nullptr;
8919     }
8920 };
8921 
8922 class AstCCall final : public AstNodeCCall {
8923     // C++ function call
8924     // Parents:  Anything above a statement
8925     // Children: Args to the function
8926 
8927     string m_selfPointer;  // Output code object pointer (e.g.: 'this')
8928 
8929 public:
8930     AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr)
ASTGEN_SUPER_CCall(fl,funcp,argsp)8931         : ASTGEN_SUPER_CCall(fl, funcp, argsp) {}
ASTNODE_NODE_FUNCS(CCall)8932     ASTNODE_NODE_FUNCS(CCall)
8933 
8934     string selfPointer() const { return m_selfPointer; }
selfPointer(const string & value)8935     void selfPointer(const string& value) { m_selfPointer = value; }
8936     string selfPointerProtect(bool useSelfForThis) const;
8937 };
8938 
8939 class AstCMethodCall final : public AstNodeCCall {
8940     // C++ method call
8941     // Parents:  Anything above a statement
8942     // Children: Args to the function
8943 public:
8944     AstCMethodCall(FileLine* fl, AstNode* fromp, AstCFunc* funcp, AstNode* argsp = nullptr)
ASTGEN_SUPER_CMethodCall(fl,funcp,argsp)8945         : ASTGEN_SUPER_CMethodCall(fl, funcp, argsp) {
8946         setOp1p(fromp);
8947     }
ASTNODE_NODE_FUNCS(CMethodCall)8948     ASTNODE_NODE_FUNCS(CMethodCall)
8949     virtual const char* broken() const override {
8950         BROKEN_BASE_RTN(AstNodeCCall::broken());
8951         BROKEN_RTN(!fromp());
8952         return nullptr;
8953     }
fromp()8954     AstNode* fromp() const {
8955         return op1p();
8956     }  // op1 = Extracting what (nullptr=TBD during parsing)
fromp(AstNode * nodep)8957     void fromp(AstNode* nodep) { setOp1p(nodep); }
8958 };
8959 
8960 class AstCNew final : public AstNodeCCall {
8961     // C++ new() call
8962     // Parents:  Anything above an expression
8963     // Children: Args to the function
8964 public:
8965     AstCNew(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr)
ASTGEN_SUPER_CNew(fl,funcp,argsp)8966         : ASTGEN_SUPER_CNew(fl, funcp, argsp) {
8967         statement(false);
8968     }
hasDType()8969     virtual bool hasDType() const override { return true; }
8970     ASTNODE_NODE_FUNCS(CNew)
8971 };
8972 
8973 class AstCReturn final : public AstNodeStmt {
8974     // C++ return from a function
8975     // Parents:  CFUNC/statement
8976     // Children: Math
8977 public:
AstCReturn(FileLine * fl,AstNode * lhsp)8978     AstCReturn(FileLine* fl, AstNode* lhsp)
8979         : ASTGEN_SUPER_CReturn(fl) {
8980         setOp1p(lhsp);
8981     }
ASTNODE_NODE_FUNCS(CReturn)8982     ASTNODE_NODE_FUNCS(CReturn)
8983     virtual int instrCount() const override { return widthInstrs(); }
same(const AstNode * samep)8984     virtual bool same(const AstNode* samep) const override { return true; }
8985     //
lhsp()8986     AstNode* lhsp() const { return op1p(); }
8987 };
8988 
8989 class AstCMath final : public AstNodeMath {
8990 private:
8991     const bool m_cleanOut;
8992     bool m_pure;  // Pure optimizable
8993 public:
8994     // Emit C textual math function (like AstUCFunc)
AstCMath(FileLine * fl,AstNode * exprsp)8995     AstCMath(FileLine* fl, AstNode* exprsp)
8996         : ASTGEN_SUPER_CMath(fl)
8997         , m_cleanOut{true}
8998         , m_pure{false} {
8999         addOp1p(exprsp);
9000         dtypeFrom(exprsp);
9001     }
9002     AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true)
ASTGEN_SUPER_CMath(fl)9003         : ASTGEN_SUPER_CMath(fl)
9004         , m_cleanOut{cleanOut}
9005         , m_pure{true} {
9006         addNOp1p(new AstText(fl, textStmt, true));
9007         if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
9008     }
ASTNODE_NODE_FUNCS(CMath)9009     ASTNODE_NODE_FUNCS(CMath)
9010     virtual bool isGateOptimizable() const override { return m_pure; }
isPredictOptimizable()9011     virtual bool isPredictOptimizable() const override { return m_pure; }
cleanOut()9012     virtual bool cleanOut() const override { return m_cleanOut; }
emitVerilog()9013     virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); }
emitC()9014     virtual string emitC() override { V3ERROR_NA_RETURN(""); }
same(const AstNode * samep)9015     virtual bool same(const AstNode* samep) const override { return true; }
addBodysp(AstNode * nodep)9016     void addBodysp(AstNode* nodep) { addNOp1p(nodep); }
bodysp()9017     AstNode* bodysp() const { return op1p(); }  // op1 = expressions to print
pure()9018     bool pure() const { return m_pure; }
pure(bool flag)9019     void pure(bool flag) { m_pure = flag; }
9020 };
9021 
9022 class AstCReset final : public AstNodeStmt {
9023     // Reset variable at startup
9024 public:
AstCReset(FileLine * fl,AstVarRef * exprsp)9025     AstCReset(FileLine* fl, AstVarRef* exprsp)
9026         : ASTGEN_SUPER_CReset(fl) {
9027         addNOp1p(exprsp);
9028     }
ASTNODE_NODE_FUNCS(CReset)9029     ASTNODE_NODE_FUNCS(CReset)
9030     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()9031     virtual bool isPredictOptimizable() const override { return false; }
same(const AstNode * samep)9032     virtual bool same(const AstNode* samep) const override { return true; }
varrefp()9033     AstVarRef* varrefp() const { return VN_AS(op1p(), VarRef); }  // op1 = varref to reset
9034 };
9035 
9036 class AstCStmt final : public AstNodeStmt {
9037     // Emit C statement
9038 public:
AstCStmt(FileLine * fl,AstNode * exprsp)9039     AstCStmt(FileLine* fl, AstNode* exprsp)
9040         : ASTGEN_SUPER_CStmt(fl) {
9041         addNOp1p(exprsp);
9042     }
AstCStmt(FileLine * fl,const string & textStmt)9043     AstCStmt(FileLine* fl, const string& textStmt)
9044         : ASTGEN_SUPER_CStmt(fl) {
9045         addNOp1p(new AstText(fl, textStmt, true));
9046     }
ASTNODE_NODE_FUNCS(CStmt)9047     ASTNODE_NODE_FUNCS(CStmt)
9048     virtual bool isGateOptimizable() const override { return false; }
isPredictOptimizable()9049     virtual bool isPredictOptimizable() const override { return false; }
same(const AstNode * samep)9050     virtual bool same(const AstNode* samep) const override { return true; }
addBodysp(AstNode * nodep)9051     void addBodysp(AstNode* nodep) { addNOp1p(nodep); }
bodysp()9052     AstNode* bodysp() const { return op1p(); }  // op1 = expressions to print
9053 };
9054 
9055 class AstCUse final : public AstNode {
9056     // C++ use of a class or #include; indicates need of forward declaration
9057     // Parents:  NODEMODULE
9058 private:
9059     const VUseType m_useType;  // What sort of use this is
9060     const string m_name;
9061 
9062 public:
AstCUse(FileLine * fl,VUseType useType,const string & name)9063     AstCUse(FileLine* fl, VUseType useType, const string& name)
9064         : ASTGEN_SUPER_CUse(fl)
9065         , m_useType{useType}
9066         , m_name{name} {}
9067     ASTNODE_NODE_FUNCS(CUse)
9068     virtual void dump(std::ostream& str = std::cout) const override;
name()9069     virtual string name() const override { return m_name; }
useType()9070     VUseType useType() const { return m_useType; }
9071 };
9072 
9073 class AstMTaskBody final : public AstNode {
9074     // Hold statements for each MTask
9075 private:
9076     ExecMTask* m_execMTaskp = nullptr;
9077 
9078 public:
AstMTaskBody(FileLine * fl)9079     explicit AstMTaskBody(FileLine* fl)
9080         : ASTGEN_SUPER_MTaskBody(fl) {}
9081     ASTNODE_NODE_FUNCS(MTaskBody);
broken()9082     virtual const char* broken() const override {
9083         BROKEN_RTN(!m_execMTaskp);
9084         return nullptr;
9085     }
stmtsp()9086     AstNode* stmtsp() const { return op1p(); }
addStmtsp(AstNode * nodep)9087     void addStmtsp(AstNode* nodep) { addOp1p(nodep); }
execMTaskp()9088     ExecMTask* execMTaskp() const { return m_execMTaskp; }
execMTaskp(ExecMTask * execMTaskp)9089     void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; }
9090     virtual void dump(std::ostream& str = std::cout) const override;
9091 };
9092 
9093 class AstExecGraph final : public AstNode {
9094     // For parallel execution, this node contains a dependency graph.  Each
9095     // node in the graph is an ExecMTask, which contains a body for the
9096     // mtask, which contains a set of AstActive's, each of which calls a
9097     // leaf AstCFunc. whew!
9098     //
9099     // The mtask bodies are also children of this node, so we can visit
9100     // them without traversing the graph (it's not always needed to
9101     // traverse the graph.)
9102 private:
9103     V3Graph* const m_depGraphp;  // contains ExecMTask's
9104 
9105 public:
9106     explicit AstExecGraph(FileLine* fl);
9107     ASTNODE_NODE_FUNCS_NO_DTOR(ExecGraph)
9108     virtual ~AstExecGraph() override;
broken()9109     virtual const char* broken() const override {
9110         BROKEN_RTN(!m_depGraphp);
9111         return nullptr;
9112     }
depGraphp()9113     const V3Graph* depGraphp() const { return m_depGraphp; }
mutableDepGraphp()9114     V3Graph* mutableDepGraphp() { return m_depGraphp; }
addMTaskBody(AstMTaskBody * bodyp)9115     void addMTaskBody(AstMTaskBody* bodyp) { addOp1p(bodyp); }
addStmtsp(AstNode * stmtp)9116     void addStmtsp(AstNode* stmtp) { addOp2p(stmtp); }
9117 };
9118 
9119 class AstSplitPlaceholder final : public AstNode {
9120 public:
9121     // Dummy node used within V3Split; never exists outside of V3Split.
AstSplitPlaceholder(FileLine * fl)9122     explicit AstSplitPlaceholder(FileLine* fl)
9123         : ASTGEN_SUPER_SplitPlaceholder(fl) {}
9124     ASTNODE_NODE_FUNCS(SplitPlaceholder)
9125 };
9126 
9127 //######################################################################
9128 // Right below top
9129 
9130 class AstTypeTable final : public AstNode {
9131     // Container for hash of standard data types
9132     // Children:  NODEDTYPEs
9133     AstEmptyQueueDType* m_emptyQueuep = nullptr;
9134     AstQueueDType* m_queueIndexp = nullptr;
9135     AstVoidDType* m_voidp = nullptr;
9136     AstBasicDType* m_basicps[AstBasicDTypeKwd::_ENUM_MAX];
9137     //
9138     using DetailedMap = std::map<VBasicTypeKey, AstBasicDType*>;
9139     DetailedMap m_detailedMap;
9140 
9141 public:
9142     explicit AstTypeTable(FileLine* fl);
ASTNODE_NODE_FUNCS(TypeTable)9143     ASTNODE_NODE_FUNCS(TypeTable)
9144     AstNodeDType* typesp() const { return VN_AS(op1p(), NodeDType); }  // op1 = List of dtypes
addTypesp(AstNodeDType * nodep)9145     void addTypesp(AstNodeDType* nodep) { addOp1p(nodep); }
9146     AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd);
9147     AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, int width, int widthMin,
9148                                      VSigning numeric);
9149     AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, const VNumRange& range,
9150                                      int widthMin, VSigning numeric);
9151     AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
9152     AstEmptyQueueDType* findEmptyQueueDType(FileLine* fl);
9153     AstQueueDType* findQueueIndexDType(FileLine* fl);
9154     AstVoidDType* findVoidDType(FileLine* fl);
9155     void clearCache();
9156     void repairCache();
9157     virtual void dump(std::ostream& str = std::cout) const override;
9158 };
9159 
9160 class AstConstPool final : public AstNode {
9161     // Container for const static data
9162     std::unordered_multimap<uint32_t, AstVarScope*> m_tables;  // Constant tables (unpacked arrays)
9163     std::unordered_multimap<uint32_t, AstVarScope*> m_consts;  // Constant tables (scalars)
9164     AstModule* const m_modp;  // The Module holding the Scope below ...
9165     AstScope* const m_scopep;  // Scope holding the constant variables
9166 
9167     AstVarScope* createNewEntry(const string& name, AstNode* initp);
9168 
9169 public:
9170     explicit AstConstPool(FileLine* fl);
ASTNODE_NODE_FUNCS(ConstPool)9171     ASTNODE_NODE_FUNCS(ConstPool)
9172     AstModule* modp() const { return m_modp; }
9173 
9174     // Find a table (unpacked array) within the constant pool which is initialized with the
9175     // given value, or create one if one does not already exists. The returned VarScope *might*
9176     // have a different dtype than the given initp->dtypep(), including a different element type,
9177     // but it will always have the same size and element width. In contexts where this matters,
9178     // the caller must handle the dtype difference as appropriate.
9179     AstVarScope* findTable(AstInitArray* initp);
9180     // Find a constant within the constant pool which is initialized with the given value, or
9181     // create one if one does not already exists. If 'mergeDType' is true, then the returned
9182     // VarScope *might* have a different type than the given initp->dtypep(). In contexts where
9183     // this matters, the caller must handle the dtype difference as appropriate. If 'mergeDType' is
9184     // false, the returned VarScope will have _->dtypep()->sameTree(initp->dtypep()) return true.
9185     AstVarScope* findConst(AstConst* initp, bool mergeDType);
9186 };
9187 
9188 //######################################################################
9189 // Top
9190 
9191 class AstNetlist final : public AstNode {
9192     // All modules are under this single top node.
9193     // Parents:   none
9194     // Children:  MODULEs & CFILEs
9195 private:
9196     AstTypeTable* const m_typeTablep;  // Reference to top type table, for faster lookup
9197     AstConstPool* const m_constPoolp;  // Reference to constant pool, for faster lookup
9198     AstPackage* m_dollarUnitPkgp = nullptr;  // $unit
9199     AstCFunc* m_evalp = nullptr;  // The '_eval' function
9200     AstExecGraph* m_execGraphp = nullptr;  // Execution MTask graph for threads>1 mode
9201     AstVarScope* m_dpiExportTriggerp = nullptr;  // The DPI export trigger variable
9202     AstTopScope* m_topScopep = nullptr;  // The singleton AstTopScope under the top module
9203     VTimescale m_timeunit;  // Global time unit
9204     VTimescale m_timeprecision;  // Global time precision
9205     bool m_changeRequest = false;  // Have _change_request method
9206     bool m_timescaleSpecified = false;  // Input HDL specified timescale
9207 public:
9208     AstNetlist();
ASTNODE_NODE_FUNCS(Netlist)9209     ASTNODE_NODE_FUNCS(Netlist)
9210     virtual const char* broken() const override {
9211         BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists());
9212         BROKEN_RTN(m_evalp && !m_evalp->brokeExists());
9213         BROKEN_RTN(m_dpiExportTriggerp && !m_dpiExportTriggerp->brokeExists());
9214         BROKEN_RTN(m_topScopep && !m_topScopep->brokeExists());
9215         return nullptr;
9216     }
name()9217     virtual string name() const override { return "$root"; }
9218     virtual void dump(std::ostream& str) const override;
modulesp()9219     AstNodeModule* modulesp() const {  // op1 = List of modules
9220         return VN_AS(op1p(), NodeModule);
9221     }
topModulep()9222     AstNodeModule* topModulep() const {  // Top module in hierarchy
9223         return modulesp();  // First one in the list, for now
9224     }
addModulep(AstNodeModule * modulep)9225     void addModulep(AstNodeModule* modulep) { addOp1p(modulep); }
filesp()9226     AstNodeFile* filesp() const { return VN_AS(op2p(), NodeFile); }  // op2 = List of files
addFilesp(AstNodeFile * filep)9227     void addFilesp(AstNodeFile* filep) { addOp2p(filep); }
addMiscsp(AstNode * nodep)9228     void addMiscsp(AstNode* nodep) { addOp3p(nodep); }
typeTablep()9229     AstTypeTable* typeTablep() { return m_typeTablep; }
changeRequest(bool specified)9230     void changeRequest(bool specified) { m_changeRequest = specified; }
changeRequest()9231     bool changeRequest() const { return m_changeRequest; }
constPoolp()9232     AstConstPool* constPoolp() { return m_constPoolp; }
dollarUnitPkgp()9233     AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; }
dollarUnitPkgAddp()9234     AstPackage* dollarUnitPkgAddp() {
9235         if (!m_dollarUnitPkgp) {
9236             m_dollarUnitPkgp = new AstPackage(fileline(), AstPackage::dollarUnitName());
9237             // packages are always libraries; don't want to make them a "top"
9238             m_dollarUnitPkgp->inLibrary(true);
9239             m_dollarUnitPkgp->modTrace(false);  // may reconsider later
9240             m_dollarUnitPkgp->internal(true);
9241             addModulep(m_dollarUnitPkgp);
9242         }
9243         return m_dollarUnitPkgp;
9244     }
evalp()9245     AstCFunc* evalp() const { return m_evalp; }
evalp(AstCFunc * evalp)9246     void evalp(AstCFunc* evalp) { m_evalp = evalp; }
execGraphp()9247     AstExecGraph* execGraphp() const { return m_execGraphp; }
execGraphp(AstExecGraph * graphp)9248     void execGraphp(AstExecGraph* graphp) { m_execGraphp = graphp; }
dpiExportTriggerp()9249     AstVarScope* dpiExportTriggerp() const { return m_dpiExportTriggerp; }
dpiExportTriggerp(AstVarScope * varScopep)9250     void dpiExportTriggerp(AstVarScope* varScopep) { m_dpiExportTriggerp = varScopep; }
topScopep()9251     AstTopScope* topScopep() const { return m_topScopep; }
createTopScope(AstScope * scopep)9252     void createTopScope(AstScope* scopep) {
9253         UASSERT(scopep, "Must not be nullptr");
9254         UASSERT_OBJ(!m_topScopep, scopep, "TopScope already exits");
9255         m_topScopep = new AstTopScope{scopep->modp()->fileline(), scopep};
9256         scopep->modp()->addStmtp(v3Global.rootp()->topScopep());
9257     }
timeunit()9258     VTimescale timeunit() const { return m_timeunit; }
timeunit(const VTimescale & value)9259     void timeunit(const VTimescale& value) { m_timeunit = value; }
timeprecision()9260     VTimescale timeprecision() const { return m_timeprecision; }
timeInit()9261     void timeInit() {
9262         m_timeunit = v3Global.opt.timeDefaultUnit();
9263         m_timeprecision = v3Global.opt.timeDefaultPrec();
9264     }
9265     void timeprecisionMerge(FileLine*, const VTimescale& value);
timescaleSpecified(bool specified)9266     void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; }
timescaleSpecified()9267     bool timescaleSpecified() const { return m_timescaleSpecified; }
9268 };
9269 
9270 //######################################################################
9271 
9272 #include "V3AstInlines.h"
9273 
9274 #endif  // Guard
9275