Support queue of arrays
This commit is contained in:
parent
0ca72f8098
commit
517fdb7587
|
|
@ -96,7 +96,7 @@ public:
|
||||||
// simply use a C style array (which is just a pointer).
|
// simply use a C style array (which is just a pointer).
|
||||||
|
|
||||||
template <std::size_t T_Words> class VlWide final {
|
template <std::size_t T_Words> class VlWide final {
|
||||||
WData m_storage[T_Words];
|
EData m_storage[T_Words];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// cppcheck-suppress uninitVar
|
// cppcheck-suppress uninitVar
|
||||||
|
|
@ -104,11 +104,17 @@ public:
|
||||||
~VlWide() = default;
|
~VlWide() = default;
|
||||||
VlWide(const VlWide&) = default;
|
VlWide(const VlWide&) = default;
|
||||||
VlWide(VlWide&&) = default;
|
VlWide(VlWide&&) = default;
|
||||||
|
|
||||||
|
// OPERATOR METHODS
|
||||||
VlWide& operator=(const VlWide&) = default;
|
VlWide& operator=(const VlWide&) = default;
|
||||||
VlWide& operator=(VlWide&&) = default;
|
VlWide& operator=(VlWide&&) = default;
|
||||||
|
const EData& operator[](size_t index) const { return m_storage[index]; };
|
||||||
|
EData& operator[](size_t index) { return m_storage[index]; };
|
||||||
|
operator WDataOutP() { return &m_storage[0]; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
const WData& at(size_t index) const { return m_storage[index]; }
|
const EData& at(size_t index) const { return m_storage[index]; }
|
||||||
WData& at(size_t index) { return m_storage[index]; }
|
EData& at(size_t index) { return m_storage[index]; }
|
||||||
WData* data() { return &m_storage[0]; }
|
WData* data() { return &m_storage[0]; }
|
||||||
const WData* data() const { return &m_storage[0]; }
|
const WData* data() const { return &m_storage[0]; }
|
||||||
bool operator<(const VlWide<T_Words>& rhs) const {
|
bool operator<(const VlWide<T_Words>& rhs) const {
|
||||||
|
|
@ -788,6 +794,41 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// Verilog packed array container
|
||||||
|
// For when a standard C++[] array is not sufficient, e.g. an
|
||||||
|
// array under a queue, or methods operating on the array
|
||||||
|
|
||||||
|
template <class T_Value, std::size_t T_Depth> class VlUnpacked final {
|
||||||
|
private:
|
||||||
|
// TYPES
|
||||||
|
typedef std::array<T_Value, T_Depth> Array;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename Array::const_iterator const_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// MEMBERS
|
||||||
|
Array m_array; // State of the assoc array
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTRUCTORS
|
||||||
|
VlUnpacked() = default;
|
||||||
|
~VlUnpacked() = default;
|
||||||
|
VlUnpacked(const VlUnpacked&) = default;
|
||||||
|
VlUnpacked(VlUnpacked&&) = default;
|
||||||
|
VlUnpacked& operator=(const VlUnpacked&) = default;
|
||||||
|
VlUnpacked& operator=(VlUnpacked&&) = default;
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
// Raw access
|
||||||
|
WData* data() { return &m_array[0]; }
|
||||||
|
const WData* data() const { return &m_array[0]; }
|
||||||
|
|
||||||
|
T_Value& operator[](size_t index) { return m_array[index]; };
|
||||||
|
const T_Value& operator[](size_t index) const { return m_array[index]; };
|
||||||
|
};
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
// Verilog class reference container
|
// Verilog class reference container
|
||||||
// There are no multithreaded locks on this; the base variable must
|
// There are no multithreaded locks on this; the base variable must
|
||||||
|
|
|
||||||
|
|
@ -2388,7 +2388,13 @@ public:
|
||||||
virtual void dump(std::ostream& str) const override;
|
virtual void dump(std::ostream& str) const override;
|
||||||
virtual void dumpSmall(std::ostream& str) const;
|
virtual void dumpSmall(std::ostream& str) const;
|
||||||
virtual bool hasDType() const override { return true; }
|
virtual bool hasDType() const override { return true; }
|
||||||
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
|
/// 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;
|
||||||
|
// (Slow) recurse down to find basic data type
|
||||||
|
virtual AstBasicDType* basicp() const = 0;
|
||||||
// recurses over typedefs/const/enum to next non-typeref type
|
// recurses over typedefs/const/enum to next non-typeref type
|
||||||
virtual AstNodeDType* skipRefp() const = 0;
|
virtual AstNodeDType* skipRefp() const = 0;
|
||||||
// recurses over typedefs to next non-typeref-or-const type
|
// recurses over typedefs to next non-typeref-or-const type
|
||||||
|
|
@ -2480,6 +2486,7 @@ public:
|
||||||
ASTNODE_BASE_FUNCS(NodeUOrStructDType)
|
ASTNODE_BASE_FUNCS(NodeUOrStructDType)
|
||||||
virtual const char* broken() const override;
|
virtual const char* broken() const override;
|
||||||
virtual void dump(std::ostream& str) const override;
|
virtual void dump(std::ostream& str) const override;
|
||||||
|
virtual bool isCompound() const { return false; } // Because don't support unpacked
|
||||||
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
||||||
virtual AstBasicDType* basicp() const override {
|
virtual AstBasicDType* basicp() const override {
|
||||||
return (isFourstate()
|
return (isFourstate()
|
||||||
|
|
|
||||||
|
|
@ -653,12 +653,16 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const {
|
||||||
} else if (const auto* adtypep = VN_CAST_CONST(dtypep, ClassRefDType)) {
|
} else if (const auto* adtypep = VN_CAST_CONST(dtypep, ClassRefDType)) {
|
||||||
info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">";
|
info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">";
|
||||||
} else if (const auto* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) {
|
} else if (const auto* adtypep = VN_CAST_CONST(dtypep, UnpackArrayDType)) {
|
||||||
if (compound) {
|
if (adtypep->isCompound()) compound = true;
|
||||||
v3fatalSrc("Dynamic arrays or queues with unpacked elements are not yet supported");
|
|
||||||
}
|
|
||||||
const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(compound);
|
const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(compound);
|
||||||
info.m_type = sub.m_type;
|
if (compound) {
|
||||||
info.m_dims = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + sub.m_dims;
|
info.m_type = "VlUnpacked<" + sub.m_type;
|
||||||
|
info.m_type += ", " + cvtToStr(adtypep->declRange().elements());
|
||||||
|
info.m_type += ">";
|
||||||
|
} else {
|
||||||
|
info.m_type = sub.m_type;
|
||||||
|
info.m_dims = "[" + cvtToStr(adtypep->declRange().elements()) + "]" + sub.m_dims;
|
||||||
|
}
|
||||||
} else if (const AstBasicDType* bdtypep = dtypep->basicp()) {
|
} else if (const AstBasicDType* bdtypep = dtypep->basicp()) {
|
||||||
// We don't print msb()/lsb() as multidim packed would require recursion,
|
// We don't print msb()/lsb() as multidim packed would require recursion,
|
||||||
// and may confuse users as C++ data is stored always with bit 0 used
|
// and may confuse users as C++ data is stored always with bit 0 used
|
||||||
|
|
@ -1387,15 +1391,17 @@ void AstNodeDType::dumpSmall(std::ostream& str) const {
|
||||||
}
|
}
|
||||||
void AstNodeArrayDType::dumpSmall(std::ostream& str) const {
|
void AstNodeArrayDType::dumpSmall(std::ostream& str) const {
|
||||||
this->AstNodeDType::dumpSmall(str);
|
this->AstNodeDType::dumpSmall(str);
|
||||||
if (VN_IS(this, PackArrayDType)) {
|
if (auto* adtypep = VN_CAST_CONST(this, UnpackArrayDType)) {
|
||||||
str << "p";
|
// uc = packed compound object, u = unpacked POD
|
||||||
|
str << (adtypep->isCompound() ? "uc" : "u");
|
||||||
} else {
|
} else {
|
||||||
str << "u";
|
str << "p";
|
||||||
}
|
}
|
||||||
str << declRange();
|
str << declRange();
|
||||||
}
|
}
|
||||||
void AstNodeArrayDType::dump(std::ostream& str) const {
|
void AstNodeArrayDType::dump(std::ostream& str) const {
|
||||||
this->AstNodeDType::dump(str);
|
this->AstNodeDType::dump(str);
|
||||||
|
if (isCompound()) str << " [COMPOUND]";
|
||||||
str << " " << declRange();
|
str << " " << declRange();
|
||||||
}
|
}
|
||||||
string AstPackArrayDType::prettyDTypeName() const {
|
string AstPackArrayDType::prettyDTypeName() const {
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,10 @@ public:
|
||||||
AstVarType varType() const { return m_varType; } // * = Type of variable
|
AstVarType varType() const { return m_varType; } // * = Type of variable
|
||||||
bool isParam() const { return true; }
|
bool isParam() const { return true; }
|
||||||
bool isGParam() const { return (varType() == AstVarType::GPARAM); }
|
bool isGParam() const { return (varType() == AstVarType::GPARAM); }
|
||||||
|
virtual bool isCompound() const override {
|
||||||
|
v3fatalSrc("call isCompound on subdata type, not reference");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstTypedef final : public AstNode {
|
class AstTypedef final : public AstNode {
|
||||||
|
|
@ -507,6 +511,7 @@ public:
|
||||||
virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); }
|
||||||
virtual string name() const override { return m_name; }
|
virtual string name() const override { return m_name; }
|
||||||
virtual void name(const string& flag) override { m_name = flag; }
|
virtual void name(const string& flag) override { m_name = flag; }
|
||||||
|
virtual bool isCompound() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstAssocArrayDType final : public AstNodeDType {
|
class AstAssocArrayDType final : public AstNodeDType {
|
||||||
|
|
@ -578,6 +583,7 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
||||||
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
||||||
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
||||||
|
virtual bool isCompound() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstBracketArrayDType final : public AstNodeDType {
|
class AstBracketArrayDType final : public AstNodeDType {
|
||||||
|
|
@ -608,6 +614,7 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
||||||
virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); }
|
virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); }
|
||||||
virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); }
|
virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); }
|
||||||
|
virtual bool isCompound() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstDynArrayDType final : public AstNodeDType {
|
class AstDynArrayDType final : public AstNodeDType {
|
||||||
|
|
@ -667,6 +674,7 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
||||||
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
||||||
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
||||||
|
virtual bool isCompound() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstPackArrayDType final : public AstNodeArrayDType {
|
class AstPackArrayDType final : public AstNodeArrayDType {
|
||||||
|
|
@ -693,12 +701,14 @@ public:
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(PackArrayDType)
|
ASTNODE_NODE_FUNCS(PackArrayDType)
|
||||||
virtual string prettyDTypeName() const override;
|
virtual string prettyDTypeName() const override;
|
||||||
|
virtual bool isCompound() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstUnpackArrayDType final : public AstNodeArrayDType {
|
class AstUnpackArrayDType final : public AstNodeArrayDType {
|
||||||
// Array data type, ie "some_dtype var_name [2:0]"
|
// Array data type, ie "some_dtype var_name [2:0]"
|
||||||
// Children: DTYPE (moved to refDTypep() in V3Width)
|
// Children: DTYPE (moved to refDTypep() in V3Width)
|
||||||
// Children: RANGE (array bounds)
|
// Children: RANGE (array bounds)
|
||||||
|
bool m_isCompound = false; // Non-POD subDType, or parent requires compound
|
||||||
public:
|
public:
|
||||||
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep)
|
||||||
: ASTGEN_SUPER(fl) {
|
: ASTGEN_SUPER(fl) {
|
||||||
|
|
@ -721,8 +731,14 @@ public:
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(UnpackArrayDType)
|
ASTNODE_NODE_FUNCS(UnpackArrayDType)
|
||||||
virtual string prettyDTypeName() const override;
|
virtual string prettyDTypeName() const override;
|
||||||
|
virtual bool same(const AstNode* samep) const override {
|
||||||
|
const AstUnpackArrayDType* sp = static_cast<const AstUnpackArrayDType*>(samep);
|
||||||
|
return m_isCompound == sp->m_isCompound;
|
||||||
|
}
|
||||||
// Outer dimension comes first. The first element is this node.
|
// Outer dimension comes first. The first element is this node.
|
||||||
std::vector<AstUnpackArrayDType*> unpackDimensions();
|
std::vector<AstUnpackArrayDType*> unpackDimensions();
|
||||||
|
void isCompound(bool flag) { m_isCompound = flag; }
|
||||||
|
virtual bool isCompound() const override { return m_isCompound; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstUnsizedArrayDType final : public AstNodeDType {
|
class AstUnsizedArrayDType final : public AstNodeDType {
|
||||||
|
|
@ -775,6 +791,7 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
||||||
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
||||||
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
||||||
|
virtual bool isCompound() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstBasicDType final : public AstNodeDType {
|
class AstBasicDType final : public AstNodeDType {
|
||||||
|
|
@ -930,6 +947,7 @@ public:
|
||||||
rangep(nullptr);
|
rangep(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual bool isCompound() const override { return isString(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstConstDType final : public AstNodeDType {
|
class AstConstDType final : public AstNodeDType {
|
||||||
|
|
@ -982,6 +1000,10 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
|
virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); }
|
||||||
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
||||||
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
||||||
|
virtual bool isCompound() const override {
|
||||||
|
v3fatalSrc("call isCompound on subdata type, not reference");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstClassRefDType final : public AstNodeDType {
|
class AstClassRefDType final : public AstNodeDType {
|
||||||
|
|
@ -1033,6 +1055,7 @@ public:
|
||||||
AstClass* classp() const { return m_classp; }
|
AstClass* classp() const { return m_classp; }
|
||||||
void classp(AstClass* nodep) { m_classp = nodep; }
|
void classp(AstClass* nodep) { m_classp = nodep; }
|
||||||
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
|
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
|
||||||
|
virtual bool isCompound() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstIfaceRefDType final : public AstNodeDType {
|
class AstIfaceRefDType final : public AstNodeDType {
|
||||||
|
|
@ -1088,6 +1111,7 @@ public:
|
||||||
AstModport* modportp() const { return m_modportp; }
|
AstModport* modportp() const { return m_modportp; }
|
||||||
void modportp(AstModport* modportp) { m_modportp = modportp; }
|
void modportp(AstModport* modportp) { m_modportp = modportp; }
|
||||||
bool isModport() { return !m_modportName.empty(); }
|
bool isModport() { return !m_modportName.empty(); }
|
||||||
|
virtual bool isCompound() const override { return true; } // But not relevant
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstQueueDType final : public AstNodeDType {
|
class AstQueueDType final : public AstNodeDType {
|
||||||
|
|
@ -1158,6 +1182,7 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
||||||
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
||||||
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); }
|
||||||
|
virtual bool isCompound() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstRefDType final : public AstNodeDType {
|
class AstRefDType final : public AstNodeDType {
|
||||||
|
|
@ -1259,6 +1284,10 @@ public:
|
||||||
AstNode* typeofp() const { return op2p(); }
|
AstNode* typeofp() const { return op2p(); }
|
||||||
AstNode* classOrPackageOpp() const { return op3p(); }
|
AstNode* classOrPackageOpp() const { return op3p(); }
|
||||||
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
|
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
|
||||||
|
virtual bool isCompound() const override {
|
||||||
|
v3fatalSrc("call isCompound on subdata type, not reference");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstStructDType final : public AstNodeUOrStructDType {
|
class AstStructDType final : public AstNodeUOrStructDType {
|
||||||
|
|
@ -1341,6 +1370,10 @@ public:
|
||||||
virtual string tag() const override { return m_tag; }
|
virtual string tag() const override { return m_tag; }
|
||||||
int lsb() const { return m_lsb; }
|
int lsb() const { return m_lsb; }
|
||||||
void lsb(int lsb) { m_lsb = lsb; }
|
void lsb(int lsb) { m_lsb = lsb; }
|
||||||
|
virtual bool isCompound() const override {
|
||||||
|
v3fatalSrc("call isCompound on subdata type, not reference");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstVoidDType final : public AstNodeDType {
|
class AstVoidDType final : public AstNodeDType {
|
||||||
|
|
@ -1368,6 +1401,7 @@ public:
|
||||||
virtual int widthAlignBytes() const override { return 1; }
|
virtual int widthAlignBytes() const override { return 1; }
|
||||||
virtual int widthTotalBytes() const override { return 1; }
|
virtual int widthTotalBytes() const override { return 1; }
|
||||||
virtual V3Hash sameHash() const override { return V3Hash(); }
|
virtual V3Hash sameHash() const override { return V3Hash(); }
|
||||||
|
virtual bool isCompound() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstEnumItem final : public AstNode {
|
class AstEnumItem final : public AstNode {
|
||||||
|
|
@ -1489,6 +1523,7 @@ public:
|
||||||
for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++;
|
for (AstNode* itemp = itemsp(); itemp; itemp = itemp->nextp()) count++;
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
virtual bool isCompound() const override { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstParseTypeDType final : public AstNodeDType {
|
class AstParseTypeDType final : public AstNodeDType {
|
||||||
|
|
@ -1510,6 +1545,10 @@ public:
|
||||||
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
||||||
virtual int widthAlignBytes() const override { return 0; }
|
virtual int widthAlignBytes() const override { return 0; }
|
||||||
virtual int widthTotalBytes() const override { return 0; }
|
virtual int widthTotalBytes() const override { return 0; }
|
||||||
|
virtual bool isCompound() const override {
|
||||||
|
v3fatalSrc("call isCompound on subdata type, not reference");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
|
||||||
|
|
@ -549,7 +549,7 @@ private:
|
||||||
if (nodep->name() == "") nodep->name("genblk" + cvtToStr(m_genblkNum));
|
if (nodep->name() == "") nodep->name("genblk" + cvtToStr(m_genblkNum));
|
||||||
}
|
}
|
||||||
if (nodep->generate() && nodep->name() == ""
|
if (nodep->generate() && nodep->name() == ""
|
||||||
&& (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf)) && !nestedIf) {
|
&& (VN_IS(backp, CaseItem) || VN_IS(backp, GenIf)) && !nestedIf) {
|
||||||
nodep->name("genblk" + cvtToStr(m_genblkAbove));
|
nodep->name("genblk" + cvtToStr(m_genblkAbove));
|
||||||
}
|
}
|
||||||
if (nodep->name() != "") {
|
if (nodep->name() != "") {
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,8 @@ class SliceVisitor final : public AstNVisitor {
|
||||||
? snodep->declRange().elements() - 1 - offset
|
? snodep->declRange().elements() - 1 - offset
|
||||||
: offset));
|
: offset));
|
||||||
newp = new AstArraySel(nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset);
|
newp = new AstArraySel(nodep->fileline(), snodep->fromp()->cloneTree(false), leOffset);
|
||||||
} else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel)) {
|
} else if (VN_IS(nodep, ArraySel) || VN_IS(nodep, NodeVarRef) || VN_IS(nodep, NodeSel)
|
||||||
|
|| VN_IS(nodep, CMethodHard)) {
|
||||||
UINFO(9, " cloneSel(" << elements << "," << offset << ") " << nodep << endl);
|
UINFO(9, " cloneSel(" << elements << "," << offset << ") " << nodep << endl);
|
||||||
int leOffset = !arrayp->rangep()->littleEndian()
|
int leOffset = !arrayp->rangep()->littleEndian()
|
||||||
? arrayp->rangep()->elementsConst() - 1 - offset
|
? arrayp->rangep()->elementsConst() - 1 - offset
|
||||||
|
|
|
||||||
|
|
@ -1451,9 +1451,10 @@ private:
|
||||||
// Cleanup array size
|
// Cleanup array size
|
||||||
userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p());
|
userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p());
|
||||||
nodep->dtypep(nodep); // The array itself, not subDtype
|
nodep->dtypep(nodep); // The array itself, not subDtype
|
||||||
if (VN_IS(nodep, UnpackArrayDType)) {
|
if (auto* adtypep = VN_CAST(nodep, UnpackArrayDType)) {
|
||||||
// Historically array elements have width of the ref type not the full array
|
// Historically array elements have width of the ref type not the full array
|
||||||
nodep->widthFromSub(nodep->subDTypep());
|
nodep->widthFromSub(nodep->subDTypep());
|
||||||
|
if (nodep->subDTypep()->skipRefp()->isCompound()) adtypep->isCompound(true);
|
||||||
} else {
|
} else {
|
||||||
int width = nodep->subDTypep()->width() * nodep->rangep()->elementsConst();
|
int width = nodep->subDTypep()->width() * nodep->rangep()->elementsConst();
|
||||||
nodep->widthForce(width, width);
|
nodep->widthForce(width, width);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2019 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
|
||||||
|
|
||||||
|
scenarios(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`define stop $stop
|
||||||
|
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
|
||||||
|
integer i;
|
||||||
|
|
||||||
|
typedef string sarray_t[2];
|
||||||
|
typedef sarray_t q_sarray_t[$];
|
||||||
|
|
||||||
|
typedef bit [95:0] wide_t;
|
||||||
|
typedef wide_t warray_t[2];
|
||||||
|
typedef warray_t q_warray_t[$];
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
begin
|
||||||
|
q_sarray_t iq;
|
||||||
|
sarray_t a;
|
||||||
|
sarray_t b0;
|
||||||
|
sarray_t b1;
|
||||||
|
|
||||||
|
a[0] = "hello";
|
||||||
|
a[1] = "world";
|
||||||
|
iq.push_back(a);
|
||||||
|
a[0] = "bye";
|
||||||
|
a[1] = "world";
|
||||||
|
iq.push_back(a);
|
||||||
|
|
||||||
|
b0 = iq[0];
|
||||||
|
b1 = iq[1];
|
||||||
|
`checks(b0[0], "hello");
|
||||||
|
`checks(b0[1], "world");
|
||||||
|
`checks(b1[0], "bye");
|
||||||
|
`checks(b1[1], "world");
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifndef verilator
|
||||||
|
// Need wide conversion into VlUnpacked types
|
||||||
|
|
||||||
|
// If we convert all arrays to VlUnpacked it works, so we need to track
|
||||||
|
// data types and insert conversions perhaps in V3Cast, but we currently
|
||||||
|
// don't know the output datatypes, so work needed.
|
||||||
|
begin
|
||||||
|
q_warray_t iq;
|
||||||
|
warray_t a;
|
||||||
|
warray_t b0;
|
||||||
|
|
||||||
|
a[0] = "abcdefg_ijkl";
|
||||||
|
a[1] = "012123123128";
|
||||||
|
iq.push_back(a);
|
||||||
|
|
||||||
|
b0 = iq[0];
|
||||||
|
`checks(b0[0], "abcdefg_ijkl");
|
||||||
|
`checks(b0[1], "012123123128");
|
||||||
|
end
|
||||||
|
`endif
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue