mirror of
https://github.com/verilator/verilator.git
synced 2026-09-01 02:16:47 +02:00
This commit is contained in:
+55
-3
@@ -6505,7 +6505,17 @@ class WidthVisitor final : public VNVisitor {
|
||||
AstNodeExpr* const newp = new AstToStringN{argp->fileline(), argp};
|
||||
formatAttr = VFormatAttr::COMPLEX;
|
||||
argp = newp;
|
||||
} else if (dtypep->isSigned()) {
|
||||
} else if (nodep->exprFormat()) {
|
||||
if (AstEnumDType* const enumDtp = formatEnumDType(argp)) {
|
||||
nodep->addExprsp(new AstSFormatArg{argp->fileline(), VFormatAttr::ENUM, argp});
|
||||
AstNodeExpr* const namep
|
||||
= enumSelect(argp->cloneTreePure(false), enumDtp, VAttrType::ENUM_NAME);
|
||||
nodep->addExprsp(
|
||||
new AstSFormatArg{namep->fileline(), VFormatAttr::STRING, namep});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (formatAttr.isUnsigned() && dtypep->isSigned()) {
|
||||
formatAttr = VFormatAttr::SIGNED;
|
||||
}
|
||||
if (VN_IS(argp, SFormatArg) // Already done
|
||||
@@ -8387,13 +8397,16 @@ class WidthVisitor final : public VNVisitor {
|
||||
// For sformatf's with constant format, iterate/check arguments
|
||||
UASSERT_OBJ(!nodep->exprFormat(), nodep, "Assumes constant format");
|
||||
bool inPct = false;
|
||||
string fmtMods;
|
||||
AstNodeExpr* argp = nodep->exprsp();
|
||||
string newFormat;
|
||||
for (char ch : nodep->text()) {
|
||||
if (!inPct && ch == '%') {
|
||||
inPct = true;
|
||||
fmtMods = "";
|
||||
newFormat += ch;
|
||||
} else if (inPct && (std::isdigit(ch) || ch == '.' || ch == '-')) {
|
||||
fmtMods += ch;
|
||||
newFormat += ch;
|
||||
} else if (!inPct) { // Normal text
|
||||
newFormat += ch;
|
||||
@@ -8401,7 +8414,7 @@ class WidthVisitor final : public VNVisitor {
|
||||
inPct = false;
|
||||
AstNodeExpr* const nextp = argp ? VN_AS(argp->nextp(), NodeExpr) : nullptr;
|
||||
AstSFormatArg* const fargp = VN_CAST(argp, SFormatArg); // May not exist yet
|
||||
AstNodeExpr* const subargp = fargp ? fargp->exprp() : argp;
|
||||
AstNodeExpr* subargp = fargp ? fargp->exprp() : argp;
|
||||
const AstNodeDType* const dtypep
|
||||
= subargp ? subargp->dtypep()->skipRefp() : nullptr;
|
||||
ch = std::tolower(ch);
|
||||
@@ -8458,7 +8471,34 @@ class WidthVisitor final : public VNVisitor {
|
||||
}
|
||||
break;
|
||||
case 'p': // FALLTHRU
|
||||
case 's': // FALLTHRU
|
||||
case 's':
|
||||
// As with enum.name(): valid values print the mnemonic, else numeric
|
||||
if (subargp) {
|
||||
if (AstEnumDType* const enumDtp = formatEnumDType(subargp)) {
|
||||
string fallbackFormat = "%0d";
|
||||
if (ch == 'p') {
|
||||
bool widthSet = false;
|
||||
size_t width = 0;
|
||||
for (const char mod : fmtMods) {
|
||||
if (!std::isdigit(mod)) continue;
|
||||
widthSet = true;
|
||||
width = width * 10 + (mod - '0');
|
||||
}
|
||||
if (widthSet && width == 0) fallbackFormat = "'h%0h";
|
||||
}
|
||||
AstNodeExpr* const newp = new AstCond{
|
||||
subargp->fileline(), enumTestValid(subargp, enumDtp),
|
||||
enumSelect(subargp->cloneTreePure(false), enumDtp,
|
||||
VAttrType::ENUM_NAME),
|
||||
new AstSFormatF{subargp->fileline(), fallbackFormat, true,
|
||||
subargp->cloneTreePure(false)}};
|
||||
subargp->replaceWith(new AstSFormatArg{subargp->fileline(),
|
||||
VFormatAttr::COMPLEX, newp});
|
||||
VL_DO_DANGLING(pushDeletep(subargp), subargp);
|
||||
}
|
||||
}
|
||||
argp = nextp;
|
||||
break;
|
||||
default: // Most operators, just move to next argument
|
||||
argp = nextp;
|
||||
break;
|
||||
@@ -8469,6 +8509,18 @@ class WidthVisitor final : public VNVisitor {
|
||||
nodep->text(newFormat);
|
||||
}
|
||||
|
||||
static AstEnumDType* formatEnumDType(AstNodeExpr* subargp) {
|
||||
AstEnumDType* enumDtp = VN_CAST(subargp->dtypep()->skipRefToEnump(), EnumDType);
|
||||
if (!enumDtp) {
|
||||
if (const AstVarRef* const varrefp = VN_CAST(subargp, VarRef)) {
|
||||
enumDtp = VN_CAST(varrefp->varp()->dtypep()->skipRefToEnump(), EnumDType);
|
||||
}
|
||||
}
|
||||
// Enums > 64 bits have no name table (see enumMaxValue); format as plain numbers
|
||||
if (enumDtp && enumDtp->width() > VL_QUADSIZE) return nullptr;
|
||||
return enumDtp;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// LOWER LEVEL WIDTH METHODS (none iterate)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user