1446 lines
70 KiB
C++
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
|