Fix string to be more standard (#5082) (#5083).

This commit is contained in:
Wilson Snyder 2024-05-31 21:51:12 -04:00
parent dbf68a99e8
commit 7c9fa8647c
19 changed files with 125 additions and 57 deletions

View File

@ -40,6 +40,7 @@ Verilator 5.025 devel
* Fix CMake builds to export VERILATOR_ROOT (#5063). [Michael Bikovitsky]
* Fix false ASSIGNIN on functions with explicit port map (#5069).
* Fix DFG assertion with SystemC (#5076). [Geza Lore]
* Fix `$typename` string to be more standard (#5082) (#5083). [Andrew Nolte]
* Fix missed optimization in V3Delayed (#5089). [Geza Lore]
* Fix macro expansion in strings per 1800-2023 (#5094). [Geza Lore]
* Fix width extension of unpacked array select (#5095). [Varun Koyyalagunta]

View File

@ -89,8 +89,8 @@ public:
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() + "'"; }
virtual string prettyDTypeName(bool) const { return prettyTypeName(); }
string prettyDTypeNameQ() const { return "'" + prettyDTypeName(false) + "'"; }
//
// Changing the width may confuse the data type resolution, so must clear
// TypeTable cache after use.
@ -215,6 +215,7 @@ public:
int uniqueNum() const { return m_uniqueNum; }
void dump(std::ostream& str) const override;
void dumpJson(std::ostream& str) const override;
string prettyDTypeName(bool) 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 {
@ -313,7 +314,7 @@ public:
return asamep->subDTypep()
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
string prettyDTypeName() const override;
string prettyDTypeName(bool full) const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); }
@ -387,7 +388,7 @@ public:
return type() == samep->type() && same(samep);
}
string name() const override VL_MT_STABLE { return m.m_keyword.ascii(); }
string prettyDTypeName() const override;
string prettyDTypeName(bool full) const override;
const char* broken() const override {
BROKEN_RTN(dtypep() != this);
return nullptr;
@ -504,7 +505,7 @@ public:
}
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; }
string prettyDTypeName(bool) 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; }
@ -551,6 +552,7 @@ public:
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 prettyDTypeName(bool full) 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; }
@ -719,7 +721,7 @@ public:
return asamep->subDTypep()
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
string prettyDTypeName() const override;
string prettyDTypeName(bool full) const override;
void dumpSmall(std::ostream& str) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
@ -809,6 +811,7 @@ public:
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 prettyDTypeName(bool full) const override;
// METHODS
AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); }
AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); }
@ -1093,7 +1096,7 @@ public:
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
}
void dumpSmall(std::ostream& str) const override;
string prettyDTypeName() const override;
string prettyDTypeName(bool full) const override;
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
AstNodeDType* subDTypep() const override VL_MT_STABLE {
return m_refDTypep ? m_refDTypep : childDTypep();
@ -1156,8 +1159,8 @@ public:
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();
string prettyDTypeName(bool full) const override {
return subDTypep() ? prettyName(subDTypep()->prettyDTypeName(full)) : prettyName();
}
AstBasicDType* basicp() const override VL_MT_STABLE {
return subDTypep() ? subDTypep()->basicp() : nullptr;
@ -1384,7 +1387,7 @@ 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;
string prettyDTypeName(bool full) const override;
bool isCompound() const override { return false; }
};
class AstUnpackArrayDType final : public AstNodeArrayDType {
@ -1411,7 +1414,7 @@ public:
widthFromSub(subDTypep());
}
ASTGEN_MEMBERS_AstUnpackArrayDType;
string prettyDTypeName() const override;
string prettyDTypeName(bool full) const override;
bool same(const AstNode* samep) const override {
const AstUnpackArrayDType* const sp = VN_DBG_AS(samep, UnpackArrayDType);
return m_isCompound == sp->m_isCompound;

View File

@ -1506,7 +1506,7 @@ void AstBasicDType::dumpJson(std::ostream& str) const {
}
dumpJsonGen(str);
}
string AstBasicDType::prettyDTypeName() const {
string AstBasicDType::prettyDTypeName(bool) const {
std::ostringstream os;
os << keyword().ascii();
if (isRanged() && !rangep() && keyword().width() <= 1) {
@ -1631,6 +1631,10 @@ void AstClassRefDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "class:" << name();
}
string AstClassRefDType::prettyDTypeName(bool) const {
return "class{}"s + prettyName();
return prettyTypeName();
}
string AstClassRefDType::name() const { return classp() ? classp()->name() : "<unlinked>"; }
void AstNodeCoverOrAssert::dump(std::ostream& str) const {
this->AstNodeStmt::dump(str);
@ -1667,6 +1671,22 @@ void AstEnumDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "enum";
}
string AstEnumDType::prettyDTypeName(bool full) const {
string result = "enum{";
if (full) { // else shorten for error messages
for (AstEnumItem* itemp = itemsp(); itemp; itemp = VN_AS(itemp->nextp(), EnumItem)) {
result += itemp->prettyName() + "=";
if (AstConst* constp = VN_CAST(itemp->valuep(), Const)) {
result += constp->num().ascii(true, true);
} else {
result += "?";
}
result += ";";
}
}
result += "}" + prettyName();
return result;
}
void AstEnumItemRef::dump(std::ostream& str) const {
this->AstNodeExpr::dump(str);
str << " -> ";
@ -1981,6 +2001,18 @@ void AstNodeUOrStructDType::dumpJson(std::ostream& str) const {
dumpJsonBoolFunc(str, isFourstate);
dumpJsonGen(str);
}
string AstNodeUOrStructDType::prettyDTypeName(bool full) const {
string result = verilogKwd() + "{";
if (full) { // else shorten for errors
for (AstMemberDType* itemp = membersp(); itemp;
itemp = VN_AS(itemp->nextp(), MemberDType)) {
result += itemp->subDTypep()->prettyDTypeName(full);
result += " " + itemp->prettyName() + ";";
}
}
result += "}" + prettyName();
return result;
}
void AstNodeDType::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (generic()) str << " [GENERIC]";
@ -2020,13 +2052,13 @@ void AstNodeArrayDType::dumpJson(std::ostream& str) const {
dumpJsonStr(str, "declRange", cvtToStr(declRange()));
dumpJsonGen(str);
}
string AstPackArrayDType::prettyDTypeName() const {
string AstPackArrayDType::prettyDTypeName(bool full) const {
std::ostringstream os;
if (const auto subp = subDTypep()) os << subp->prettyDTypeName();
if (const auto subp = subDTypep()) os << subp->prettyDTypeName(full);
os << declRange();
return os.str();
}
string AstUnpackArrayDType::prettyDTypeName() const {
string AstUnpackArrayDType::prettyDTypeName(bool full) const {
std::ostringstream os;
string ranges = cvtToStr(declRange());
// Unfortunately we need a single $ for the first unpacked, and all
@ -2036,7 +2068,7 @@ string AstUnpackArrayDType::prettyDTypeName() const {
ranges += cvtToStr(adtypep->declRange());
subp = adtypep->subDTypep()->skipRefp();
}
os << subp->prettyDTypeName() << "$" << ranges;
os << subp->prettyDTypeName(full) << "$" << ranges;
return os.str();
}
std::vector<AstUnpackArrayDType*> AstUnpackArrayDType::unpackDimensions() {
@ -2180,20 +2212,22 @@ void AstAssocArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "[assoc-" << nodeAddr(keyDTypep()) << "]";
}
string AstAssocArrayDType::prettyDTypeName() const {
return subDTypep()->prettyDTypeName() + "[" + keyDTypep()->prettyDTypeName() + "]";
string AstAssocArrayDType::prettyDTypeName(bool full) const {
return subDTypep()->prettyDTypeName(full) + "$[" + keyDTypep()->prettyDTypeName(full) + "]";
}
void AstDynArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "[]";
str << "$[]";
}
string AstDynArrayDType::prettyDTypeName(bool full) const {
return subDTypep()->prettyDTypeName(full) + "$[]";
}
string AstDynArrayDType::prettyDTypeName() const { return subDTypep()->prettyDTypeName() + "[]"; }
void AstQueueDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str << "[queue]";
}
string AstQueueDType::prettyDTypeName() const {
string str = subDTypep()->prettyDTypeName() + "[$";
string AstQueueDType::prettyDTypeName(bool full) const {
string str = subDTypep()->prettyDTypeName(full) + "$[$";
if (boundConst()) str += ":" + cvtToStr(boundConst());
return str + "]";
}

View File

@ -694,7 +694,7 @@ class TaskVisitor final : public VNVisitor {
// differ we may get C compilation problems later
const std::string dpiType = portp->dpiArgType(false, false);
dpiproto += dpiType;
const std::string vType = portp->dtypep()->prettyDTypeName();
const std::string vType = portp->dtypep()->prettyDTypeName(false);
if (!portp->isDpiOpenArray() && dpiType != vType) {
dpiproto += " /* " + vType + " */ ";
}

View File

@ -1615,7 +1615,8 @@ class WidthVisitor final : public VNVisitor {
}
case VAttrType::TYPENAME: {
UASSERT_OBJ(nodep->fromp(), nodep, "Unprovided expression");
const string result = nodep->fromp()->dtypep()->prettyDTypeName();
const string result = nodep->fromp()->dtypep()->prettyDTypeName(true);
UINFO(9, "typename '" << result << "' from " << nodep->fromp()->dtypep() << "\n");
AstNode* const newp = new AstConst{nodep->fileline(), AstConst::String{}, result};
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
@ -4091,7 +4092,7 @@ class WidthVisitor final : public VNVisitor {
} else if (const AstNodeDType* nodedtypep
= VN_CAST(patp->keyp(), NodeDType)) {
// data_type: default_value
const string dtype = nodedtypep->dtypep()->prettyDTypeName();
const string dtype = nodedtypep->dtypep()->prettyDTypeName(true);
const auto pair = dtypemap.emplace(dtype, patp);
if (!pair.second) {
// Override stored default_value
@ -4195,7 +4196,7 @@ class WidthVisitor final : public VNVisitor {
AstPatMember* patp,
AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, const DTypeMap& dtypemap) {
const string memp_DType = memp->virtRefDTypep()->prettyDTypeName();
const string memp_DType = memp->virtRefDTypep()->prettyDTypeName(true);
const auto it = dtypemap.find(memp_DType);
if (it != dtypemap.end()) {
// default_value for data_type
@ -5787,8 +5788,8 @@ class WidthVisitor final : public VNVisitor {
&& !similarDTypeRecurse(portDTypep, pinDTypep)) {
pinp->v3error("Ref argument requires matching types;"
<< " port " << portp->prettyNameQ() << " requires "
<< portDTypep->prettyDTypeName() << " but connection is "
<< pinDTypep->prettyDTypeName() << ".");
<< portDTypep->prettyDTypeNameQ() << " but connection is "
<< pinDTypep->prettyDTypeNameQ() << ".");
} else if (portp->isWritable() && pinp->width() != portp->width()) {
pinp->v3widthWarn(portp->width(), pinp->width(),
"Function output argument "
@ -7035,7 +7036,7 @@ class WidthVisitor final : public VNVisitor {
AstNodeExpr* checkCvtUS(AstNodeExpr* nodep) {
if (nodep && nodep->isDouble()) {
nodep->v3error("Expected integral (non-" << nodep->dtypep()->prettyDTypeName()
nodep->v3error("Expected integral (non-" << nodep->dtypep()->prettyDTypeNameQ()
<< ") input to "
<< nodep->backp()->prettyTypeName());
nodep = spliceCvtS(nodep, true, 32);

View File

@ -1,9 +1,9 @@
%Error: t/t_cast_class_incompat_bad.v:26:16: Dynamic, not static cast, required to cast 'CLASSREFDTYPE 'BaseExtended'' from 'CLASSREFDTYPE 'Base''
%Error: t/t_cast_class_incompat_bad.v:26:16: Dynamic, not static cast, required to cast 'class{}BaseExtended' from 'class{}Base'
: ... note: In instance 't'
: ... Suggest dynamic $cast
26 | cls_ab = BaseExtended'(cls_a);
| ^~~~~~~~~~~~
%Error: t/t_cast_class_incompat_bad.v:27:15: Incompatible types to static cast to 'CLASSREFDTYPE 'Other'' from 'CLASSREFDTYPE 'BaseExtended''
%Error: t/t_cast_class_incompat_bad.v:27:15: Incompatible types to static cast to 'class{}Other' from 'class{}BaseExtended'
: ... note: In instance 't'
27 | other = Other'(cls_ab);
| ^~~~~

View File

@ -5,12 +5,12 @@
| ^~~~~
... For warning description see https://verilator.org/warn/CASTCONST?v=latest
... Use "/* verilator lint_off CASTCONST */" and lint_on around source to disable this message.
%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:21:11: $cast will always return one as 'CLASSREFDTYPE 'Base'' is always castable from 'CLASSREFDTYPE 'Base''
%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:21:11: $cast will always return one as 'class{}Base' is always castable from 'class{}Base'
: ... note: In instance 't'
: ... Suggest static cast
21 | i = $cast(b, b);
| ^~~~~
%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:22:11: $cast will always return zero as 'CLASSREFDTYPE 'Base'' is not castable from 'CLASSREFDTYPE 'Other''
%Warning-CASTCONST: t/t_castdyn_castconst_bad.v:22:11: $cast will always return zero as 'class{}Base' is not castable from 'class{}Other'
: ... note: In instance 't'
22 | i = $cast(b, o);
| ^~~~~

View File

@ -1,4 +1,4 @@
%Error-UNSUPPORTED: t/t_castdyn_unsup_bad.v:13:7: Unsupported: $cast to 'string[$]' from 'int[string]'
%Error-UNSUPPORTED: t/t_castdyn_unsup_bad.v:13:7: Unsupported: $cast to 'string$[$]' from 'int$[string]'
: ... note: In instance 't'
: ... Suggest try static cast
13 | $cast(q, aarray);

View File

@ -2,7 +2,7 @@
: ... note: In instance 't'
20 | Converter#(bit) conv2 = conv1;
| ^~~~~
%Error-ENUMVALUE: t/t_class_param_enum_bad.v:21:19: Implicit conversion to enum 'ENUMDTYPE '$unit::enum_t'' from 'logic[31:0]' (IEEE 1800-2023 6.19.3)
%Error-ENUMVALUE: t/t_class_param_enum_bad.v:21:19: Implicit conversion to enum 'enum{}$unit::enum_t' from 'logic[31:0]' (IEEE 1800-2023 6.19.3)
: ... note: In instance 't'
: ... Suggest use enum's mnemonic, or static cast
21 | conv1.toInt(0);

View File

@ -1,15 +1,15 @@
%Error-ENUMVALUE: t/t_enum_type_bad.v:28:11: Implicit conversion to enum 't.e_t' from 'logic[31:0]' (IEEE 1800-2023 6.19.3)
%Error-ENUMVALUE: t/t_enum_type_bad.v:28:11: Implicit conversion to enum 'enum{}t.e_t' from 'logic[31:0]' (IEEE 1800-2023 6.19.3)
: ... note: In instance 't'
: ... Suggest use enum's mnemonic, or static cast
28 | e = 1;
| ^
... For error description see https://verilator.org/warn/ENUMVALUE?v=latest
%Error-ENUMVALUE: t/t_enum_type_bad.v:29:11: Implicit conversion to enum 't.o_t' from 't.e_t' (IEEE 1800-2023 6.19.3)
%Error-ENUMVALUE: t/t_enum_type_bad.v:29:11: Implicit conversion to enum 'enum{}t.o_t' from 'enum{}t.e_t' (IEEE 1800-2023 6.19.3)
: ... note: In instance 't'
: ... Suggest use enum's mnemonic, or static cast
29 | o = e;
| ^
%Error-ENUMVALUE: t/t_enum_type_bad.v:35:15: Implicit conversion to enum 't.o_t' from 'ENUMDTYPE 't.e_t'' (IEEE 1800-2023 6.19.3)
%Error-ENUMVALUE: t/t_enum_type_bad.v:35:15: Implicit conversion to enum 'enum{}t.o_t' from 'enum{}t.e_t' (IEEE 1800-2023 6.19.3)
: ... note: In instance 't'
: ... Suggest use enum's mnemonic, or static cast
35 | o = str.m_e;

View File

@ -1,4 +1,4 @@
%Error: t/t_flag_structs_packed.v:14:19: Unpacked data type 'STRUCTDTYPE 'x.notpacked_t'' in packed struct/union (IEEE 1800-2023 7.2.1)
%Error: t/t_flag_structs_packed.v:14:19: Unpacked data type 'struct{}x.notpacked_t' in packed struct/union (IEEE 1800-2023 7.2.1)
: ... note: In instance 'x'
14 | notpacked_t b;
| ^

View File

@ -1,4 +1,4 @@
%Error: t/t_func_refio_bad.v:16:17: Ref argument requires matching types; port 'q' requires integer[$] but connection is logic[31:0].
%Error: t/t_func_refio_bad.v:16:17: Ref argument requires matching types; port 'q' requires 'integer$[$]' but connection is 'logic[31:0]'.
: ... note: In instance 't'
16 | queue_set(42);
| ^~

View File

@ -4,14 +4,14 @@
| ^~
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:19:25: Unsupported: random member variable with type 'int[]'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:19:25: Unsupported: random member variable with type 'int$[]'
19 | constraint dynsize { dynarr.size < 20; }
| ^~~~~~
%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:20:28: Constraint expression ignored (unsupported)
: ... note: In instance 't'
20 | constraint statedep { i < st + 2; }
| ^
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variable with type 'int[string]'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:12:13: Unsupported: random member variable with type 'int$[string]'
: ... note: In instance 't'
12 | rand int assocarr[string];
| ^~~~~~~~
@ -19,7 +19,7 @@
: ... note: In instance 't'
14 | rand int unpackarr[5];
| ^~~~~~~~~
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variable with type '$unit::Union'
%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:15: Unsupported: random member variable with type 'union{}$unit::Union'
: ... note: In instance 't'
15 | rand Union uni;
| ^~~

View File

@ -22,11 +22,11 @@
: ... note: In instance 't'
26 | event e;
| ^
%Error: t/t_struct_contents_bad.v:27:25: Unpacked data type 'STRUCTDTYPE 't.struct_unpacked_t'' in packed struct/union (IEEE 1800-2023 7.2.1)
%Error: t/t_struct_contents_bad.v:27:25: Unpacked data type 'struct{}t.struct_unpacked_t' in packed struct/union (IEEE 1800-2023 7.2.1)
: ... note: In instance 't'
27 | struct_unpacked_t sp;
| ^~
%Error: t/t_struct_contents_bad.v:28:24: Unpacked data type 'UNIONDTYPE 't.union_unpacked_t'' in packed struct/union (IEEE 1800-2023 7.2.1)
%Error: t/t_struct_contents_bad.v:28:24: Unpacked data type 'union{}t.union_unpacked_t' in packed struct/union (IEEE 1800-2023 7.2.1)
: ... note: In instance 't'
28 | union_unpacked_t up;
| ^~
@ -34,7 +34,7 @@
: ... note: In instance 't'
29 | int uarray[2];
| ^~~~~~
%Error: t/t_struct_contents_bad.v:30:11: Unpacked data type 'CLASSREFDTYPE 'Cls'' in packed struct/union (IEEE 1800-2023 7.2.1)
%Error: t/t_struct_contents_bad.v:30:11: Unpacked data type 'class{}Cls' in packed struct/union (IEEE 1800-2023 7.2.1)
: ... note: In instance 't'
30 | Cls c;
| ^

View File

@ -14,7 +14,15 @@
"bit[2:0]" ==? "bit[2:0]"
"int" ==? "int"
"bit[9:1]" ==? "bit[9:1]"
"A::__typeimpenum1" ==? "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::<unspecified>"
"STRUCTDTYPE 't.AB_t'" ==? "struct{bit A;bit B;}"
"STRUCTDTYPE 't.AB_t'$[0:9]" ==? "struct{bit A;bit B;}top.AB_t$[0:9]"
"string$[longint]" ==? "string$[longint]"
"int$[$]" ==? "int$[$]"
"int$[$:3]" ==? "int$[$:3]"
"bit$[]" ==? "bit$[]"
"enum{A=32'h0;B=32'h1;C=32'h63;}A::__typeimpenum1" ==? "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::<unspecified>"
"struct{bit A;bit B;}t.AB_t" ==? "struct{bit A;bit B;}<some_have_typename>"
"struct{bit A;bit B;}t.AB_t$[0:9]" ==? "struct{bit A;bit B;}top.AB_t$[0:9]"
"union{bit A;bit B;}t.UAB_t" ==? "union{bit A;bit B;}"
"class{}Cls" ==? "class{}t.Cls <or class t.Cls>"
*-* All Finished *-*

View File

@ -34,6 +34,16 @@ module t(/*AUTOARG*/);
mybit_t [2:0] bitp20;
mybit_t bitu32 [3:2];
mybit_t bitu31 [3:1][4:5];
string assoc[longint];
int q[$];
int q3[$:3];
bit dyn[] = '{0, 0};
class Cls;
int m_c;
endclass
typedef union {node A,B;} UAB_t;
// From LRM
typedef struct {node A,B;} AB_t;
@ -60,12 +70,23 @@ module t(/*AUTOARG*/);
`printtype(Y, "int");
`printtype(A::word, "bit[9:1]");
`printtype(assoc, "string$[longint]");
`printtype(q, "int$[$]");
`printtype(q3, "int$[$:3]"); // Some omit :3 - need it so != unbounded
`printtype(dyn, "bit$[]");
`printtype(A::X, "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::<unspecified>");
$display;
`printtype(A::X, "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::<unspecified>"); // Some have just "enum <typename>"
`printtype(AB_t, "struct{bit A;bit B;}<some_have_typename>");
`printtype(AB_t, "struct{bit A;bit B;}");
`printtype(AB, "struct{bit A;bit B;}top.AB_t$[0:9]");
`printtype(UAB_t, "union{bit A;bit B;}");
`printtype(Cls, "class{}t.Cls <or class t.Cls>");
$display;
$write("*-* All Finished *-*\n");
$finish;
end

View File

@ -15,17 +15,17 @@ module t;
string s;
initial begin
s = $typename(array.min);
`checks(s, "int[$]");
`checks(s, "int$[$]");
s = $sformatf("%p", array.min);
`checks(s, "'{'h1} ");
s = $typename(queue.min);
`checks(s, "int[$]");
`checks(s, "int$[$]");
s = $sformatf("%p", queue.min);
`checks(s, "'{'h1} ");
s = $typename(assoc.min);
`checks(s, "int[$]");
`checks(s, "int$[$]");
s = $sformatf("%p", assoc.min);
`checks(s, "'{'h1} ");

View File

@ -2,7 +2,7 @@
: ... note: In instance 't'
13 | bad_const_set = 32'h4567;
| ^~~~~~~~~~~~~
%Error: t/t_var_ref_bad2.v:23:17: Ref argument requires matching types; port 'int_ref' requires int but connection is byte.
%Error: t/t_var_ref_bad2.v:23:17: Ref argument requires matching types; port 'int_ref' requires 'int' but connection is 'byte'.
: ... note: In instance 't'
23 | checkset2(bad_non_int);
| ^~~~~~~~~~~

View File

@ -14,7 +14,7 @@
: ... note: In instance 't'
46 | d_real[0] = 1'b1;
| ^
%Error: t/t_var_types_bad.v:46:7: Expected integral (non-real) input to SEL
%Error: t/t_var_types_bad.v:46:7: Expected integral (non-'real') input to SEL
: ... note: In instance 't'
46 | d_real[0] = 1'b1;
| ^~~~~~
@ -27,7 +27,7 @@
: ... note: In instance 't'
47 | d_realtime[0] = 1'b1;
| ^
%Error: t/t_var_types_bad.v:47:7: Expected integral (non-real) input to SEL
%Error: t/t_var_types_bad.v:47:7: Expected integral (non-'real') input to SEL
: ... note: In instance 't'
47 | d_realtime[0] = 1'b1;
| ^~~~~~~~~~