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