verilator/src/V3AstNodeDType.h

1446 lines
70 KiB
C++

// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: AstNode sub-types representing data types
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2024 by Wilson Snyder. This program is free software; you
// can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
//
// This files contains all 'AstNode' sub-types that relate to the
// representation of data types.
//
//*************************************************************************
#ifndef VERILATOR_V3ASTNODEDTYPE_H_
#define VERILATOR_V3ASTNODEDTYPE_H_
#ifndef VERILATOR_V3AST_H_
#error "Use V3Ast.h as the include"
#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h
#define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE
#endif
// === Abstract base node types (AstNode*) =====================================
class AstNodeDType VL_NOT_FINAL : public AstNode {
// Ideally width() would migrate to BasicDType as that's where it makes sense,
// but it's currently so prevalent in the code we leave it here.
// Note the below members are included in AstTypeTable::Key lookups
int m_width = 0; // (also in AstTypeTable::Key) Bit width of operation
int m_widthMin
= 0; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
VSigning m_numeric; // (also in AstTypeTable::Key) Node is signed
// Other members
bool m_generic = false; // Simple globally referenced type, don't garbage collect
// Unique number assigned to each dtype during creation for IEEE matching
static int s_uniqueNum;
protected:
// CONSTRUCTORS
AstNodeDType(VNType t, FileLine* fl)
: AstNode{t, fl} {}
public:
ASTGEN_MEMBERS_AstNodeDType;
// ACCESSORS
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
virtual void dumpSmall(std::ostream& str) const VL_MT_STABLE;
bool hasDType() const override { return true; }
/// Require VlUnpacked, instead of [] for POD elements.
/// A non-POD object is always compound, but some POD elements
/// are compound when methods calls operate on object, or when
/// under another compound-requiring object e.g. class
virtual bool isCompound() const = 0;
// Integral or packed, allowed inside an unpacked union/struct
virtual bool isIntegralOrPacked() const { return !isCompound(); }
// (Slow) recurse down to find basic data type
virtual AstBasicDType* basicp() const VL_MT_STABLE = 0;
// recurses over typedefs/const/enum to next non-typeref type
virtual AstNodeDType* skipRefp() const VL_MT_STABLE = 0;
// recurses over typedefs to next non-typeref-or-const type
virtual AstNodeDType* skipRefToConstp() const = 0;
// recurses over typedefs/const to next non-typeref-or-enum/struct type
virtual AstNodeDType* skipRefToEnump() const = 0;
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
virtual int widthAlignBytes() const = 0;
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
virtual int widthTotalBytes() const = 0;
bool maybePointedTo() const override { return true; }
// Iff has a non-null refDTypep(), as generic node function
virtual AstNodeDType* virtRefDTypep() const { return nullptr; }
// Iff has refDTypep(), set as generic node function
virtual void virtRefDTypep(AstNodeDType* nodep) {}
// Iff has a non-null second dtypep, as generic node function
virtual AstNodeDType* virtRefDType2p() const { return nullptr; }
// Iff has second dtype, set as generic node function
virtual void virtRefDType2p(AstNodeDType* nodep) {}
// Assignable equivalence. Call skipRefp() on this and samep before calling
virtual bool similarDType(const AstNodeDType* samep) const = 0;
// Iff has a non-null subDTypep(), as generic node function
virtual AstNodeDType* subDTypep() const VL_MT_SAFE { return nullptr; }
virtual bool isFourstate() const;
// Ideally an IEEE $typename
virtual string prettyDTypeName() const { return prettyTypeName(); }
string prettyDTypeNameQ() const { return "'" + prettyDTypeName() + "'"; }
//
// Changing the width may confuse the data type resolution, so must clear
// TypeTable cache after use.
void widthForce(int width, int widthMin) {
m_width = width;
m_widthMin = widthMin;
}
// For backward compatibility inherit width and signing from the subDType/base type
void widthFromSub(const AstNodeDType* nodep) {
m_width = nodep->m_width;
m_widthMin = nodep->m_widthMin;
m_numeric = nodep->m_numeric;
}
//
int width() const VL_MT_SAFE { return m_width; }
void numeric(VSigning flag) { m_numeric = flag; }
bool isSigned() const VL_MT_SAFE { return m_numeric.isSigned(); }
bool isNosign() const VL_MT_SAFE { return m_numeric.isNosign(); }
VSigning numeric() const { return m_numeric; }
int widthWords() const VL_MT_SAFE { return VL_WORDS_I(width()); }
int widthMin() const VL_MT_SAFE { // If sized, the size,
// if unsized the min digits to represent it
return m_widthMin ? m_widthMin : m_width;
}
int widthPow2() const;
void widthMinFromWidth() { m_widthMin = m_width; }
bool widthSized() const VL_MT_SAFE { return !m_widthMin || m_widthMin == m_width; }
bool generic() const VL_MT_SAFE { return m_generic; }
void generic(bool flag) { m_generic = flag; }
std::pair<uint32_t, uint32_t> dimensions(bool includeBasic);
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
static int uniqueNumInc() { return ++s_uniqueNum; }
const char* charIQWN() const {
return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I");
}
string cType(const string& name, bool forFunc, bool isRef, bool packed = false) const;
// Represents a C++ LiteralType? (can be constexpr)
bool isLiteralType() const VL_MT_STABLE;
private:
class CTypeRecursed;
CTypeRecursed cTypeRecurse(bool compound, bool packed) const;
};
class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType {
// Array data type, ie "some_dtype var_name [2:0]"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := rangep : Optional[AstRange] // array bounds
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
AstNode* rangenp() const { return reinterpret_cast<AstNode*>(rangep()); }
protected:
AstNodeArrayDType(VNType t, FileLine* fl)
: AstNodeDType{t, fl} {}
public:
ASTGEN_MEMBERS_AstNodeArrayDType;
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
void dumpSmall(std::ostream& str) const override;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override {
const AstNodeArrayDType* const asamep = VN_DBG_AS(samep, NodeArrayDType);
return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep()
&& rangenp()->sameTree(asamep->rangenp()));
} // HashedDT doesn't recurse, so need to check children
bool similarDType(const AstNodeDType* samep) const override {
if (type() != samep->type()) return false;
const AstNodeArrayDType* const asamep = VN_DBG_AS(samep, NodeArrayDType);
return (hi() == asamep->hi() && rangenp()->sameTree(asamep->rangenp())
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE {
return subDTypep()->basicp();
} // (Slow) recurse down to find basic data type
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override {
return elementsConst() * subDTypep()->widthTotalBytes();
}
inline int left() const VL_MT_STABLE;
inline int right() const VL_MT_STABLE;
inline int hi() const VL_MT_STABLE;
inline int lo() const VL_MT_STABLE;
inline int elementsConst() const VL_MT_STABLE;
inline VNumRange declRange() const VL_MT_STABLE;
};
class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType {
// A struct or union; common handling
// @astgen op1 := membersp : List[AstMemberDType]
//
// @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Package emitted with
string m_name; // Name from upper typedef, if any
const int m_uniqueNum;
bool m_packed;
bool m_isFourstate = false; // V3Width computes
protected:
AstNodeUOrStructDType(VNType t, FileLine* fl, VSigning numericUnpack)
: AstNodeDType{t, fl}
, m_uniqueNum{uniqueNumInc()} {
// VSigning::NOSIGN overloaded to indicate not packed
m_packed = (numericUnpack != VSigning::NOSIGN);
numeric(VSigning::fromBool(numericUnpack.isSigned()));
}
public:
ASTGEN_MEMBERS_AstNodeUOrStructDType;
int uniqueNum() const { return m_uniqueNum; }
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
bool isCompound() const override { return !packed(); }
// For basicp() we reuse the size to indicate a "fake" basic type of same size
AstBasicDType* basicp() const override {
return (isFourstate()
? VN_AS(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()),
BasicDType)
: VN_AS(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()),
BasicDType));
}
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
int widthAlignBytes() const override;
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
int widthTotalBytes() const override;
bool similarDType(const AstNodeDType* samep) const override {
return this == samep; // We don't compare members, require exact equivalence
}
string name() const override VL_MT_STABLE { return m_name; }
void name(const string& flag) override { m_name = flag; }
bool packed() const VL_MT_SAFE { return m_packed; }
void packed(bool flag) { m_packed = flag; }
// packed() but as don't support unpacked, presently all structs
static bool packedUnsup() { return true; }
void isFourstate(bool flag) { m_isFourstate = flag; }
bool isFourstate() const override VL_MT_SAFE { return m_isFourstate; }
static int lo() { return 0; }
int hi() const { return dtypep()->width() - 1; } // Packed classes look like arrays
VNumRange declRange() const { return VNumRange{hi(), lo()}; }
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
void classOrPackagep(AstNodeModule* classpackagep) { m_classOrPackagep = classpackagep; }
};
// === Concrete node types =====================================================
// === AstNode ===
class AstEnumItem final : public AstNode {
// @astgen op1 := rangep : Optional[AstRange] // Range for name appending
// @astgen op2 := valuep : Optional[AstNodeExpr]
string m_name;
public:
// Parents: ENUM
AstEnumItem(FileLine* fl, const string& name, AstRange* rangep, AstNodeExpr* valuep)
: ASTGEN_SUPER_EnumItem(fl)
, m_name{name} {
this->rangep(rangep);
this->valuep(valuep);
}
ASTGEN_MEMBERS_AstEnumItem;
string name() const override VL_MT_STABLE { return m_name; }
bool maybePointedTo() const override { return true; }
bool hasDType() const override { return true; }
void name(const string& flag) override { m_name = flag; }
};
// === AstNodeDType ===
class AstAssocArrayDType final : public AstNodeDType {
// Associative array data type, ie "[some_dtype]"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := keyChildDTypep : Optional[AstNodeDType]
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
// @astgen ptr := m_keyDTypep : Optional[AstNodeDType] // Keys of this type (post-width)
public:
AstAssocArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeDType* keyDtp)
: ASTGEN_SUPER_AssocArrayDType(fl) {
childDTypep(dtp); // Only for parser
keyChildDTypep(keyDtp); // Only for parser
refDTypep(nullptr);
keyDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
AstAssocArrayDType(FileLine* fl, AstNodeDType* dtp, AstNodeDType* keyDtp)
: ASTGEN_SUPER_AssocArrayDType(fl) {
refDTypep(dtp);
keyDTypep(keyDtp);
dtypep(dtp);
}
ASTGEN_MEMBERS_AstAssocArrayDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
BROKEN_RTN(!((m_keyDTypep && !childDTypep()) || (!m_keyDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override {
const AstAssocArrayDType* const asamep = VN_DBG_AS(samep, AssocArrayDType);
if (!asamep->subDTypep()) return false;
if (!asamep->keyDTypep()) return false;
return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep());
}
bool similarDType(const AstNodeDType* samep) const override {
if (type() != samep->type()) return false;
const AstAssocArrayDType* const asamep = VN_DBG_AS(samep, AssocArrayDType);
return asamep->subDTypep()
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
string prettyDTypeName() const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; }
void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); }
//
AstNodeDType* keyDTypep() const VL_MT_STABLE {
return m_keyDTypep ? m_keyDTypep : keyChildDTypep();
}
void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
bool isCompound() const override { return true; }
};
class AstBasicDType final : public AstNodeDType {
// Builtin atomic/vectored data type
// @astgen op1 := rangep : Optional[AstRange] // Range of variable
struct Members final {
VBasicDTypeKwd m_keyword; // (also in VBasicTypeKey) What keyword created basic type
VNumRange m_nrange; // (also in VBasicTypeKey) Numeric msb/lsb (if non-opaque keyword)
bool operator==(const Members& rhs) const {
return rhs.m_keyword == m_keyword && rhs.m_nrange == m_nrange;
}
} m;
// See also in AstNodeDType: m_width, m_widthMin, m_numeric(issigned)
public:
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN)
: ASTGEN_SUPER_BasicDType(fl) {
init(kwd, signst, 0, -1, nullptr);
}
AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth)
: ASTGEN_SUPER_BasicDType(fl) {
init(VBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr);
}
AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth)
: ASTGEN_SUPER_BasicDType(fl) {
init(VBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr);
}
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin)
: ASTGEN_SUPER_BasicDType(fl) {
init(kwd, numer, wantwidth, widthmin, nullptr);
}
AstBasicDType(FileLine* fl, VBasicDTypeKwd kwd, VSigning numer, VNumRange range, int widthmin)
: ASTGEN_SUPER_BasicDType(fl) {
init(kwd, numer, range.elements(), widthmin, nullptr);
m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be
}
// See also addRange in verilog.y
private:
void init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
AstRange* rangep);
public:
ASTGEN_MEMBERS_AstBasicDType;
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
// width/widthMin/numeric compared elsewhere
bool same(const AstNode* samep) const override;
bool similarDType(const AstNodeDType* samep) const override {
return type() == samep->type() && same(samep);
}
string name() const override VL_MT_STABLE { return m.m_keyword.ascii(); }
string prettyDTypeName() const override;
const char* broken() const override {
BROKEN_RTN(dtypep() != this);
return nullptr;
}
void setSignedState(const VSigning& signst) {
// Note NOSIGN does NOT change the state; this is required by the parser
if (signst == VSigning::UNSIGNED) {
numeric(signst);
} else if (signst == VSigning::SIGNED) {
numeric(signst);
}
}
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return (AstBasicDType*)this; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
int widthAlignBytes() const override;
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
int widthTotalBytes() const override;
bool isFourstate() const override { return keyword().isFourstate(); }
VBasicDTypeKwd keyword() const VL_MT_SAFE { // Avoid using - use isSomething accessors instead
return m.m_keyword;
}
bool isBitLogic() const { return keyword().isBitLogic(); }
bool isDouble() const VL_MT_SAFE { return keyword().isDouble(); }
bool isEvent() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::EVENT; }
bool isTriggerVec() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::TRIGGERVEC; }
bool isForkSync() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::FORK_SYNC; }
bool isProcessRef() const VL_MT_SAFE { return keyword() == VBasicDTypeKwd::PROCESS_REFERENCE; }
bool isDelayScheduler() const VL_MT_SAFE {
return keyword() == VBasicDTypeKwd::DELAY_SCHEDULER;
}
bool isTriggerScheduler() const VL_MT_SAFE {
return keyword() == VBasicDTypeKwd::TRIGGER_SCHEDULER;
}
bool isDynamicTriggerScheduler() const VL_MT_SAFE {
return keyword() == VBasicDTypeKwd::DYNAMIC_TRIGGER_SCHEDULER;
}
bool isRandomGenerator() const VL_MT_SAFE {
return keyword() == VBasicDTypeKwd::RANDOM_GENERATOR;
}
bool isOpaque() const VL_MT_SAFE { return keyword().isOpaque(); }
bool isString() const VL_MT_SAFE { return keyword().isString(); }
bool isZeroInit() const { return keyword().isZeroInit(); }
bool isRanged() const { return rangep() || m.m_nrange.ranged(); }
bool isDpiBitVec() const { // DPI uses svBitVecVal
return keyword() == VBasicDTypeKwd::BIT && isRanged();
}
bool isDpiLogicVec() const { // DPI uses svLogicVecVal
return keyword().isFourstate() && !(keyword() == VBasicDTypeKwd::LOGIC && !isRanged());
}
bool isDpiPrimitive() const { // DPI uses a primitive type
return !isDpiBitVec() && !isDpiLogicVec();
}
// Generally the lo/hi/left/right funcs should be used instead of nrange()
const VNumRange& nrange() const { return m.m_nrange; }
inline int hi() const;
inline int lo() const;
inline int elements() const;
int left() const { return ascending() ? lo() : hi(); } // How to show a declaration
int right() const { return ascending() ? hi() : lo(); }
inline bool ascending() const;
bool implicit() const { return keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT; }
bool untyped() const { return keyword() == VBasicDTypeKwd::UNTYPED; }
VNumRange declRange() const { return isRanged() ? VNumRange{left(), right()} : VNumRange{}; }
void cvtRangeConst(); // Convert to smaller representation
bool isCompound() const override { return isString(); }
bool isIntegralOrPacked() const override { return keyword().isIntNumeric(); }
};
class AstBracketArrayDType final : public AstNodeDType {
// Associative/Queue/Normal array data type, ie "[dtype_or_expr]"
// only for early parsing then becomes another data type
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := elementsp : AstNode // ??? key dtype ???
public:
AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* childDTypep,
AstNode* elementsp)
: ASTGEN_SUPER_BracketArrayDType(fl) {
this->childDTypep(childDTypep);
this->elementsp(elementsp);
}
ASTGEN_MEMBERS_AstBracketArrayDType;
bool similarDType(const AstNodeDType* samep) const override { return same(samep); }
AstNodeDType* subDTypep() const override VL_MT_STABLE { return childDTypep(); }
// METHODS
// Will be removed in V3Width, which relies on this
// being a child not a dtype pointed node
bool maybePointedTo() const override { return false; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); }
int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); }
bool isCompound() const override { return true; }
};
class AstCDType final : public AstNodeDType {
// Raw "C" data type passed directly to output
string m_name; // Name of data type, printed when do V3EmitC
public:
AstCDType(FileLine* fl, const string& name)
: ASTGEN_SUPER_CDType(fl)
, m_name{name} {
this->dtypep(this);
}
public:
ASTGEN_MEMBERS_AstCDType;
bool same(const AstNode* samep) const override {
const AstCDType* const asamep = VN_DBG_AS(samep, CDType);
return m_name == asamep->m_name;
}
bool similarDType(const AstNodeDType* samep) const override { return same(samep); }
string name() const override VL_MT_STABLE { return m_name; }
string prettyDTypeName() const override { return m_name; }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 8; } // Assume
int widthTotalBytes() const override { return 8; } // Assume
bool isCompound() const override { return true; }
static string typeToHold(int width) {
if (width <= 8)
return "CData";
else if (width <= 16)
return "SData";
else if (width <= VL_IDATASIZE)
return "IData";
else if (width <= VL_QUADSIZE)
return "QData";
else
return "VlWide<" + std::to_string(VL_WORDS_I(width)) + ">";
}
};
class AstClassRefDType final : public AstNodeDType {
// Reference to a class
// @astgen op1 := paramsp: List[AstPin]
//
// @astgen ptr := m_classp : Optional[AstClass] // data type pointed to, BELOW the AstTypedef
// @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Package hierarchy
public:
AstClassRefDType(FileLine* fl, AstClass* classp, AstPin* paramsp)
: ASTGEN_SUPER_ClassRefDType(fl)
, m_classp{classp} {
this->dtypep(this);
this->addParamsp(paramsp);
}
ASTGEN_MEMBERS_AstClassRefDType;
// METHODS
bool same(const AstNode* samep) const override {
const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType);
return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep);
}
bool similarDType(const AstNodeDType* samep) const override {
return this == samep || (type() == samep->type() && same(samep));
}
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
void dumpSmall(std::ostream& str) const override;
string name() const override VL_MT_STABLE;
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 0; }
int widthTotalBytes() const override { return 0; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; }
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
AstClass* classp() const VL_MT_STABLE { return m_classp; }
void classp(AstClass* nodep) { m_classp = nodep; }
bool isCompound() const override { return true; }
};
class AstConstDType final : public AstNodeDType {
// const data type, ie "const some_dtype var_name [2:0]"
// ConstDType are removed in V3LinkLValue and become AstVar::isConst.
// When more generic types are supported AstConstDType will be propagated further.
// @astgen op1 := childDTypep : Optional[AstNodeDType]
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Inherit from this base data type
public:
AstConstDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
: ASTGEN_SUPER_ConstDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(nullptr); // V3Width will resolve
dtypep(nullptr); // V3Width will resolve
widthFromSub(subDTypep());
}
ASTGEN_MEMBERS_AstConstDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override {
const AstConstDType* const sp = VN_DBG_AS(samep, ConstDType);
return (m_refDTypep == sp->m_refDTypep);
}
bool similarDType(const AstNodeDType* samep) const override {
return skipRefp()->similarDType(samep->skipRefp());
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
bool isCompound() const override {
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
}
};
class AstConstraintRefDType final : public AstNodeDType {
// For e.g. a reference to constraint for constraint_mode
public:
explicit AstConstraintRefDType(FileLine* fl)
: ASTGEN_SUPER_ConstraintRefDType(fl) {
dtypep(this);
}
ASTGEN_MEMBERS_AstConstraintRefDType;
bool hasDType() const override { return true; }
bool maybePointedTo() const override { return true; }
bool undead() const override { return true; }
AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }
bool isCompound() const override { return false; }
};
class AstDefImplicitDType final : public AstNodeDType {
// For parsing enum/struct/unions that are declared with a variable rather than typedef
// This allows "var enum {...} a,b" to share the enum definition for both variables
// After link, these become typedefs
// @astgen op1 := childDTypep : Optional[AstNodeDType]
string m_name;
void* m_containerp; // In what scope is the name unique, so we can know what are duplicate
// definitions (arbitrary value)
const int m_uniqueNum;
public:
AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType,
AstNodeDType* dtp)
: ASTGEN_SUPER_DefImplicitDType(fl)
, m_name{name}
, m_containerp{containerp}
, m_uniqueNum{uniqueNumInc()} {
childDTypep(dtp); // Only for parser
dtypep(nullptr); // V3Width will resolve
}
ASTGEN_MEMBERS_AstDefImplicitDType;
int uniqueNum() const { return m_uniqueNum; }
bool same(const AstNode* samep) const override {
const AstDefImplicitDType* const sp = VN_DBG_AS(samep, DefImplicitDType);
return uniqueNum() == sp->uniqueNum();
}
bool similarDType(const AstNodeDType* samep) const override {
return type() == samep->type() && same(samep);
}
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return dtypep() ? dtypep() : childDTypep();
}
void* containerp() const { return m_containerp; }
// METHODS
// op1 = Range of variable
AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); }
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); }
string name() const override VL_MT_STABLE { return m_name; }
void name(const string& flag) override { m_name = flag; }
bool isCompound() const override { return false; }
};
class AstDynArrayDType final : public AstNodeDType {
// Dynamic array data type, ie "[]"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
public:
AstDynArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
: ASTGEN_SUPER_DynArrayDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
AstDynArrayDType(FileLine* fl, AstNodeDType* dtp)
: ASTGEN_SUPER_DynArrayDType(fl) {
refDTypep(dtp);
dtypep(nullptr); // V3Width will resolve
}
ASTGEN_MEMBERS_AstDynArrayDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override {
const AstDynArrayDType* const asamep = VN_DBG_AS(samep, DynArrayDType);
if (!asamep->subDTypep()) return false;
return subDTypep() == asamep->subDTypep();
}
bool similarDType(const AstNodeDType* samep) const override {
if (type() != samep->type()) return false;
const AstDynArrayDType* const asamep = VN_DBG_AS(samep, DynArrayDType);
return asamep->subDTypep()
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
string prettyDTypeName() const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
bool isCompound() const override { return true; }
};
class AstEmptyQueueDType final : public AstNodeDType {
// For EmptyQueue
public:
explicit AstEmptyQueueDType(FileLine* fl)
: ASTGEN_SUPER_EmptyQueueDType(fl) {
dtypep(this);
}
ASTGEN_MEMBERS_AstEmptyQueueDType;
void dumpSmall(std::ostream& str) const override;
bool hasDType() const override { return true; }
bool maybePointedTo() const override { return true; }
bool undead() const override { return true; }
AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }
bool isCompound() const override { return false; }
};
class AstEnumDType final : public AstNodeDType {
// Parents: TYPEDEF/MODULE
// @astgen op1 := childDTypep : Optional[AstNodeDType]
// @astgen op2 := itemsp : List[AstEnumItem]
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
public:
using TableMap = std::map<VAttrType, AstVar*>;
private:
string m_name; // Name from upper typedef, if any
const int m_uniqueNum = 0;
TableMap m_tableMap; // Created table for V3Width only to remove duplicates
public:
AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstEnumItem* itemsp)
: ASTGEN_SUPER_EnumDType(fl)
, m_uniqueNum{uniqueNumInc()} {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
addItemsp(itemsp);
dtypep(nullptr); // V3Width will resolve
widthFromSub(subDTypep());
}
ASTGEN_MEMBERS_AstEnumDType;
const char* broken() const override;
int uniqueNum() const { return m_uniqueNum; }
bool same(const AstNode* samep) const override {
const AstEnumDType* const sp = VN_DBG_AS(samep, EnumDType);
return uniqueNum() == sp->uniqueNum();
}
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
string name() const override VL_MT_STABLE { return m_name; }
void name(const string& flag) override { m_name = flag; }
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
void dumpSmall(std::ostream& str) const override;
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); }
AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
int itemCount() const {
size_t count = 0;
for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++;
return count;
}
bool isCompound() const override { return false; }
TableMap& tableMap() { return m_tableMap; }
const TableMap& tableMap() const { return m_tableMap; }
};
class AstIfaceRefDType final : public AstNodeDType {
// Reference to an interface, either for a port, or inside parent cell
// @astgen op1 := paramsp : List[AstPin]
//
// @astgen ptr := m_ifacep : Optional[AstIface] // Interface; cellp() should override
// @astgen ptr := m_cellp : Optional[AstCell] // When exact parent cell known; not a guess
// @astgen ptr := m_modportp : Optional[AstModport] // nullptr = unlinked or no modport
bool m_virtual = false; // True if virtual interface
FileLine* m_modportFileline; // Where modport token was
string m_cellName; // "" = no cell, such as when connects to 'input' iface
string m_ifaceName; // Interface name
string m_modportName; // "" = no modport
public:
AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName)
: ASTGEN_SUPER_IfaceRefDType(fl)
, m_modportFileline{nullptr}
, m_cellName{cellName}
, m_ifaceName{ifaceName}
, m_modportName{""} {}
AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName,
const string& ifaceName, const string& modport)
: ASTGEN_SUPER_IfaceRefDType(fl)
, m_modportFileline{modportFl}
, m_cellName{cellName}
, m_ifaceName{ifaceName}
, m_modportName{modport} {}
AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName,
const string& ifaceName, const string& modport, AstPin* paramsp)
: ASTGEN_SUPER_IfaceRefDType(fl)
, m_modportFileline{modportFl}
, m_cellName{cellName}
, m_ifaceName{ifaceName} {
addParamsp(paramsp);
}
ASTGEN_MEMBERS_AstIfaceRefDType;
// METHODS
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
void dumpSmall(std::ostream& str) const override;
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }
void isVirtual(bool flag) {
m_virtual = flag;
if (flag) v3Global.setHasVirtIfaces();
}
bool isVirtual() const { return m_virtual; }
FileLine* modportFileline() const { return m_modportFileline; }
string cellName() const { return m_cellName; }
void cellName(const string& name) { m_cellName = name; }
string ifaceName() const { return m_ifaceName; }
void ifaceName(const string& name) { m_ifaceName = name; }
string modportName() const { return m_modportName; }
AstIface* ifaceViaCellp() const; // Use cellp or ifacep
AstIface* ifacep() const { return m_ifacep; }
void ifacep(AstIface* nodep) { m_ifacep = nodep; }
AstCell* cellp() const { return m_cellp; }
void cellp(AstCell* nodep) { m_cellp = nodep; }
AstModport* modportp() const { return m_modportp; }
void modportp(AstModport* modportp) { m_modportp = modportp; }
bool isModport() { return !m_modportName.empty(); }
bool isCompound() const override { return true; } // But not relevant
};
class AstMemberDType final : public AstNodeDType {
// A member of a struct/union
// PARENT: AstNodeUOrStructDType
// @astgen op1 := childDTypep : Optional[AstNodeDType]
// @astgen op3 := valuep : Optional[AstNode]
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
string m_name; // Name of variable
string m_tag; // Holds the string of the verilator tag -- used in XML output.
int m_lsb = -1; // Within this level's packed struct, the LSB of the first bit of the member
// UNSUP: int m_randType; // Randomization type (IEEE)
public:
AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp,
AstNode* valuep)
: ASTGEN_SUPER_MemberDType(fl)
, m_name{name} {
childDTypep(dtp); // Only for parser
this->valuep(valuep);
dtypep(nullptr); // V3Width will resolve
refDTypep(nullptr);
}
AstMemberDType(FileLine* fl, const string& name, AstNodeDType* dtp)
: ASTGEN_SUPER_MemberDType(fl)
, m_name{name} {
UASSERT(dtp, "AstMember created with no dtype");
refDTypep(dtp);
dtypep(this);
widthFromSub(subDTypep());
}
ASTGEN_MEMBERS_AstMemberDType;
void dumpSmall(std::ostream& str) const override;
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
bool hasDType() const override { return true; }
bool maybePointedTo() const override { return true; }
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeUOrStructDType* getChildStructp() const;
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
//
// (Slow) recurse down to find basic data type (Note don't need virtual -
// AstVar isn't a NodeDType)
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
// op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType)
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); }
AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); }
AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
// METHODS
void name(const string& name) override { m_name = name; }
void tag(const string& text) override { m_tag = text; }
string tag() const override { return m_tag; }
int lsb() const { return m_lsb; }
void lsb(int lsb) { m_lsb = lsb; }
bool isCompound() const override {
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
}
};
class AstNBACommitQueueDType final : public AstNodeDType {
// @astgen ptr := m_subDTypep : AstNodeDType // Type of the corresponding variable
const bool m_partial; // Partial element update required
public:
AstNBACommitQueueDType(FileLine* fl, AstNodeDType* subDTypep, bool partial)
: ASTGEN_SUPER_NBACommitQueueDType(fl)
, m_partial{partial}
, m_subDTypep{subDTypep} {
dtypep(this);
}
ASTGEN_MEMBERS_AstNBACommitQueueDType;
AstNodeDType* subDTypep() const override { return m_subDTypep; }
bool partial() const { return m_partial; }
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override { return nullptr; }
AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 24; }
bool isCompound() const override { return true; }
};
class AstParamTypeDType final : public AstNodeDType {
// Parents: MODULE
// A parameter type statement; much like a var or typedef
// @astgen op1 := childDTypep : Optional[AstNodeDType]
const VVarType m_varType; // Type of variable (for localparam vs. param)
string m_name; // Name of variable
public:
AstParamTypeDType(FileLine* fl, VVarType type, const string& name, VFlagChildDType,
AstNodeDType* dtp)
: ASTGEN_SUPER_ParamTypeDType(fl)
, m_varType{type}
, m_name{name} {
childDTypep(dtp); // Only for parser
dtypep(nullptr); // V3Width will resolve
}
ASTGEN_MEMBERS_AstParamTypeDType;
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return dtypep() ? dtypep() : childDTypep();
}
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); }
AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); }
AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
bool similarDType(const AstNodeDType* samep) const override {
if (type() != samep->type()) return false;
const AstParamTypeDType* const sp = VN_DBG_AS(samep, ParamTypeDType);
return this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp());
}
int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); }
// METHODS
string name() const override VL_MT_STABLE { return m_name; }
bool maybePointedTo() const override { return true; }
bool hasDType() const override { return true; }
void name(const string& flag) override { m_name = flag; }
VVarType varType() const { return m_varType; } // * = Type of variable
bool isParam() const { return true; }
bool isGParam() const { return (varType() == VVarType::GPARAM); }
bool isCompound() const override {
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
}
};
class AstParseTypeDType final : public AstNodeDType {
// Parents: VAR
// During parsing, this indicates the type of a parameter is a "parameter type"
// e.g. the data type is a container of any data type
public:
explicit AstParseTypeDType(FileLine* fl)
: ASTGEN_SUPER_ParseTypeDType(fl) {}
ASTGEN_MEMBERS_AstParseTypeDType;
AstNodeDType* dtypep() const { return nullptr; }
// METHODS
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 0; }
int widthTotalBytes() const override { return 0; }
bool isCompound() const override {
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
}
};
class AstQueueDType final : public AstNodeDType {
// Queue array data type, ie "[ $ ]"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
// @astgen op2 := boundp : Optional[AstNodeExpr]
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
public:
AstQueueDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNodeExpr* boundp)
: ASTGEN_SUPER_QueueDType(fl) {
this->childDTypep(dtp);
this->boundp(boundp);
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
AstQueueDType(FileLine* fl, AstNodeDType* dtp, AstNodeExpr* boundp)
: ASTGEN_SUPER_QueueDType(fl) {
this->boundp(boundp);
refDTypep(dtp);
dtypep(dtp);
}
ASTGEN_MEMBERS_AstQueueDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override {
const AstQueueDType* const asamep = VN_DBG_AS(samep, QueueDType);
if (!asamep->subDTypep()) return false;
return (subDTypep() == asamep->subDTypep());
}
bool similarDType(const AstNodeDType* samep) const override {
if (type() != samep->type()) return false;
const AstQueueDType* const asamep = VN_DBG_AS(samep, QueueDType);
return asamep->subDTypep()
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
void dumpSmall(std::ostream& str) const override;
string prettyDTypeName() const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
inline int boundConst() const VL_MT_STABLE;
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
bool isCompound() const override { return true; }
};
class AstRefDType final : public AstNodeDType {
// @astgen op1 := typeofp : Optional[AstNode]
// @astgen op2 := classOrPackageOpp : Optional[AstNodeExpr]
// @astgen op3 := paramsp : List[AstPin]
//
// Pre-Width must reference the Typeref, not what it points to, as some child
// types like AstBracketArrayType will disappear and can't lose the handle
// @astgen ptr := m_typedefp : Optional[AstTypedef] // Referenced type
// Post-width typedefs are removed and point to type directly
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Data type references
// @astgen ptr := m_classOrPackagep : Optional[AstNodeModule] // Class/package defined in
string m_name; // Name of an AstTypedef
public:
AstRefDType(FileLine* fl, const string& name)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name} {}
AstRefDType(FileLine* fl, const string& name, AstNodeExpr* classOrPackagep, AstPin* paramsp)
: ASTGEN_SUPER_RefDType(fl)
, m_name{name} {
this->classOrPackageOpp(classOrPackagep);
addParamsp(paramsp);
}
class FlagTypeOfExpr {}; // type(expr) for parser only
AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp)
: ASTGEN_SUPER_RefDType(fl) {
this->typeofp(typeofp);
if (AstNodeDType* const dtp = VN_CAST(typeofp, NodeDType)) refDTypep(dtp);
}
ASTGEN_MEMBERS_AstRefDType;
// METHODS
bool same(const AstNode* samep) const override {
const AstRefDType* const asamep = VN_DBG_AS(samep, RefDType);
return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep
&& m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep);
}
bool similarDType(const AstNodeDType* samep) const override {
return skipRefp()->similarDType(samep->skipRefp());
}
void dump(std::ostream& str = std::cout) const override;
void dumpJson(std::ostream& str = std::cout) const override;
void dumpSmall(std::ostream& str) const override;
string name() const override VL_MT_STABLE { return m_name; }
string prettyDTypeName() const override {
return subDTypep() ? prettyName(subDTypep()->name()) : prettyName();
}
AstBasicDType* basicp() const override VL_MT_STABLE {
return subDTypep() ? subDTypep()->basicp() : nullptr;
}
AstNodeDType* subDTypep() const override VL_MT_STABLE;
AstNodeDType* skipRefp() const override VL_MT_STABLE {
// Skip past both the Ref and the Typedef
if (subDTypep()) {
return subDTypep()->skipRefp();
} else {
v3fatalSrc("Typedef not linked");
return nullptr;
}
}
AstNodeDType* skipRefToConstp() const override {
if (subDTypep()) {
return subDTypep()->skipRefToConstp();
} else {
v3fatalSrc("Typedef not linked");
return nullptr;
}
}
AstNodeDType* skipRefToEnump() const override {
if (subDTypep()) {
return subDTypep()->skipRefToEnump();
} else {
v3fatalSrc("Typedef not linked");
return nullptr;
}
}
int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); }
int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); }
void name(const string& flag) override { m_name = flag; }
AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); }
AstTypedef* typedefp() const VL_MT_SAFE { return m_typedefp; }
void typedefp(AstTypedef* nodep) { m_typedefp = nodep; }
AstNodeDType* refDTypep() const VL_MT_SAFE { return m_refDTypep; }
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return refDTypep(); }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
bool isCompound() const override {
v3fatalSrc("call isCompound on subdata type, not reference");
return false;
}
};
class AstSampleQueueDType final : public AstNodeDType {
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
public:
AstSampleQueueDType(FileLine* fl, AstNodeDType* dtp)
: ASTGEN_SUPER_SampleQueueDType(fl) {
refDTypep(dtp);
dtypep(dtp);
}
ASTGEN_MEMBERS_AstSampleQueueDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override {
const AstSampleQueueDType* const asamep = VN_DBG_AS(samep, SampleQueueDType);
if (!asamep->subDTypep()) return false;
return (subDTypep() == asamep->subDTypep());
}
bool similarDType(const AstNodeDType* samep) const override {
if (type() != samep->type()) return false;
const AstSampleQueueDType* const asamep = VN_DBG_AS(samep, SampleQueueDType);
return asamep->subDTypep()
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
// op1 = Range of variable
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return sizeof(std::map<std::string, std::string>); }
int widthTotalBytes() const override { return sizeof(std::map<std::string, std::string>); }
bool isCompound() const override { return true; }
};
class AstStreamDType final : public AstNodeDType {
// Stream data type, used only as data type of stream operations
// Should behave like AstPackArrayDType, but it doesn't have a size
public:
explicit AstStreamDType(FileLine* fl)
: ASTGEN_SUPER_StreamDType(fl) {
dtypep(this);
}
ASTGEN_MEMBERS_AstStreamDType;
void dumpSmall(std::ostream& str) const override;
bool hasDType() const override { return true; }
bool maybePointedTo() const override { return true; }
bool undead() const override { return true; }
AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }
bool isCompound() const override { return false; }
};
class AstUnsizedArrayDType final : public AstNodeDType {
// Unsized/open-range Array data type, ie "some_dtype var_name []"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
public:
AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
: ASTGEN_SUPER_UnsizedArrayDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
ASTGEN_MEMBERS_AstUnsizedArrayDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override;
bool similarDType(const AstNodeDType* samep) const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
bool isCompound() const override { return true; }
};
class AstVoidDType final : public AstNodeDType {
// For e.g. a function returning void
public:
explicit AstVoidDType(FileLine* fl)
: ASTGEN_SUPER_VoidDType(fl) {
dtypep(this);
}
ASTGEN_MEMBERS_AstVoidDType;
void dumpSmall(std::ostream& str) const override;
bool hasDType() const override { return true; }
bool maybePointedTo() const override { return true; }
bool undead() const override { return true; }
AstNodeDType* subDTypep() const override VL_MT_SAFE { return nullptr; }
AstNodeDType* virtRefDTypep() const override { return nullptr; }
void virtRefDTypep(AstNodeDType* nodep) override {}
bool similarDType(const AstNodeDType* samep) const override { return this == samep; }
AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
// cppcheck-suppress csyleCast
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return 1; }
int widthTotalBytes() const override { return 1; }
bool isCompound() const override { return false; }
};
class AstWildcardArrayDType final : public AstNodeDType {
// Wildcard index type associative array data type, ie "some_dtype var_name [*]"
// @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
//
// @astgen ptr := m_refDTypep : Optional[AstNodeDType] // Elements of this type (post-width)
public:
AstWildcardArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp)
: ASTGEN_SUPER_WildcardArrayDType(fl) {
childDTypep(dtp); // Only for parser
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
}
ASTGEN_MEMBERS_AstWildcardArrayDType;
const char* broken() const override {
BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep())));
return nullptr;
}
bool same(const AstNode* samep) const override;
bool similarDType(const AstNodeDType* samep) const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
}
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; }
AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
int widthAlignBytes() const override { return sizeof(std::map<std::string, std::string>); }
int widthTotalBytes() const override { return sizeof(std::map<std::string, std::string>); }
bool isCompound() const override { return true; }
};
// === AstNodeArrayDType ===
class AstPackArrayDType final : public AstNodeArrayDType {
// Packed array data type, ie "some_dtype [2:0] var_name"
public:
inline AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep);
inline AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep);
ASTGEN_MEMBERS_AstPackArrayDType;
string prettyDTypeName() const override;
bool isCompound() const override { return false; }
};
class AstUnpackArrayDType final : public AstNodeArrayDType {
// Array data type, ie "some_dtype var_name [2:0]"
bool m_isCompound = false; // Non-POD subDType, or parent requires compound
public:
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
: ASTGEN_SUPER_UnpackArrayDType(fl) {
this->childDTypep(dtp); // Only for parser
this->rangep(rangep);
refDTypep(nullptr);
dtypep(nullptr); // V3Width will resolve
// For backward compatibility AstNodeArrayDType and others inherit
// width and signing from the subDType/base type
widthFromSub(subDTypep());
}
AstUnpackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
: ASTGEN_SUPER_UnpackArrayDType(fl) {
this->rangep(rangep);
refDTypep(dtp);
dtypep(this);
// For backward compatibility AstNodeArrayDType and others inherit
// width and signing from the subDType/base type
widthFromSub(subDTypep());
}
ASTGEN_MEMBERS_AstUnpackArrayDType;
string prettyDTypeName() const override;
bool same(const AstNode* samep) const override {
const AstUnpackArrayDType* const sp = VN_DBG_AS(samep, UnpackArrayDType);
return m_isCompound == sp->m_isCompound;
}
// Outer dimension comes first. The first element is this node.
std::vector<AstUnpackArrayDType*> unpackDimensions();
void isCompound(bool flag) { m_isCompound = flag; }
bool isCompound() const override VL_MT_SAFE { return m_isCompound; }
bool isIntegralOrPacked() const override { return false; }
};
// === AstNodeUOrStructDType ===
class AstStructDType final : public AstNodeUOrStructDType {
public:
// VSigning below is mispurposed to indicate if packed or not
AstStructDType(FileLine* fl, VSigning numericUnpack)
: ASTGEN_SUPER_StructDType(fl, numericUnpack) {}
ASTGEN_MEMBERS_AstStructDType;
string verilogKwd() const override { return "struct"; }
};
class AstUnionDType final : public AstNodeUOrStructDType {
public:
// UNSUP: bool isTagged;
// VSigning below is mispurposed to indicate if packed or not
AstUnionDType(FileLine* fl, VSigning numericUnpack)
: ASTGEN_SUPER_UnionDType(fl, numericUnpack) {}
ASTGEN_MEMBERS_AstUnionDType;
string verilogKwd() const override { return "union"; }
};
#endif // Guard