Support `$timeformat` with missing arguments (#6113).

This commit is contained in:
Wilson Snyder 2025-06-24 17:30:05 -04:00
parent f9f70383fa
commit 6af694b04b
9 changed files with 69 additions and 19 deletions

View File

@ -18,6 +18,7 @@ Verilator 5.037 devel
* Support assignments to concatenations with impure RHS (#6002). [Ryszard Rozak, Antmicro Ltd.] * Support assignments to concatenations with impure RHS (#6002). [Ryszard Rozak, Antmicro Ltd.]
* Support SARIF JSON diagnostic output with `--diagnostics-sarif`. (#6017) * Support SARIF JSON diagnostic output with `--diagnostics-sarif`. (#6017)
* Support 1-bit params with -G and -pvalue (#6051) (#6082). [Paul Swirhun] * Support 1-bit params with -G and -pvalue (#6051) (#6082). [Paul Swirhun]
* Support `$timeformat` with missing arguments (#6113). [Alex Solomatnikov]
* Support parameter forward types. * Support parameter forward types.
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon] * Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu] * Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]

View File

@ -2567,12 +2567,13 @@ void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp,
VL_PRINTF_MT("Time scale of %s is %s / %s\n", namep, timeunitp, VL_PRINTF_MT("Time scale of %s is %s / %s\n", namep, timeunitp,
contextp->timeprecisionString()); contextp->timeprecisionString());
} }
void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, int width, void VL_TIMEFORMAT_IINI(bool hasUnits, int units, bool hasPrecision, int precision, bool hasSuffix,
const std::string& suffix, bool hasWidth, int width,
VerilatedContext* contextp) VL_MT_SAFE { VerilatedContext* contextp) VL_MT_SAFE {
contextp->impp()->timeFormatUnits(units); if (hasUnits) contextp->impp()->timeFormatUnits(units);
contextp->impp()->timeFormatPrecision(precision); if (hasPrecision) contextp->impp()->timeFormatPrecision(precision);
contextp->impp()->timeFormatSuffix(suffix); if (hasSuffix) contextp->impp()->timeFormatSuffix(suffix);
contextp->impp()->timeFormatWidth(width); if (hasWidth) contextp->impp()->timeFormatWidth(width);
} }
//====================================================================== //======================================================================

View File

@ -2800,7 +2800,8 @@ extern IData VL_SSCANF_INNX(int lbits, const std::string& ld, const std::string&
extern void VL_SFORMAT_NX(int obits_ignored, std::string& output, const std::string& format, extern void VL_SFORMAT_NX(int obits_ignored, std::string& output, const std::string& format,
int argc, ...) VL_MT_SAFE; int argc, ...) VL_MT_SAFE;
extern std::string VL_SFORMATF_N_NX(const std::string& format, int argc, ...) VL_MT_SAFE; extern std::string VL_SFORMATF_N_NX(const std::string& format, int argc, ...) VL_MT_SAFE;
extern void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, int width, extern void VL_TIMEFORMAT_IINI(bool hasUnits, int units, bool hasPrecision, int precision,
bool hasSuffix, const std::string& suffix, bool hasWidth, int width,
VerilatedContext* contextp) VL_MT_SAFE; VerilatedContext* contextp) VL_MT_SAFE;
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE; extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE;
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, CData& rdr) VL_MT_SAFE { inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, CData& rdr) VL_MT_SAFE {

View File

@ -3490,10 +3490,10 @@ public:
}; };
class AstTimeFormat final : public AstNodeStmt { class AstTimeFormat final : public AstNodeStmt {
// Parents: stmtlist // Parents: stmtlist
// @astgen op1 := unitsp : AstNodeExpr // @astgen op1 := unitsp : Optional[AstNodeExpr]
// @astgen op2 := precisionp : AstNodeExpr // @astgen op2 := precisionp : Optional[AstNodeExpr]
// @astgen op3 := suffixp : AstNodeExpr // @astgen op3 := suffixp : Optional[AstNodeExpr]
// @astgen op4 := widthp : AstNodeExpr // @astgen op4 := widthp : Optional[AstNodeExpr]
public: public:
AstTimeFormat(FileLine* fl, AstNodeExpr* unitsp, AstNodeExpr* precisionp, AstNodeExpr* suffixp, AstTimeFormat(FileLine* fl, AstNodeExpr* unitsp, AstNodeExpr* precisionp, AstNodeExpr* suffixp,
AstNodeExpr* widthp) AstNodeExpr* widthp)

View File

@ -1083,13 +1083,33 @@ public:
} }
void visit(AstTimeFormat* nodep) override { void visit(AstTimeFormat* nodep) override {
putns(nodep, "VL_TIMEFORMAT_IINI("); putns(nodep, "VL_TIMEFORMAT_IINI(");
iterateAndNextConstNull(nodep->unitsp()); if (nodep->unitsp()) {
puts("true, ");
iterateAndNextConstNull(nodep->unitsp());
} else {
puts("false, 0");
}
puts(", "); puts(", ");
iterateAndNextConstNull(nodep->precisionp()); if (nodep->precisionp()) {
puts("true, ");
iterateAndNextConstNull(nodep->precisionp());
} else {
puts("false, 0");
}
puts(", "); puts(", ");
emitCvtPackStr(nodep->suffixp()); if (nodep->suffixp()) {
puts("true, ");
emitCvtPackStr(nodep->suffixp());
} else {
puts("false, \"\"");
}
puts(", "); puts(", ");
iterateAndNextConstNull(nodep->widthp()); if (nodep->widthp()) {
puts("true, ");
iterateAndNextConstNull(nodep->widthp());
} else {
puts("false, 0");
}
puts(", vlSymsp->_vm_contextp__);\n"); puts(", vlSymsp->_vm_contextp__);\n");
} }
void visit(AstTimePrecision* nodep) override { void visit(AstTimePrecision* nodep) override {

View File

@ -5718,10 +5718,11 @@ class WidthVisitor final : public VNVisitor {
} }
void visit(AstTimeFormat* nodep) override { void visit(AstTimeFormat* nodep) override {
assertAtStatement(nodep); assertAtStatement(nodep);
iterateCheckSigned32(nodep, "units", nodep->unitsp(), BOTH); if (nodep->unitsp()) iterateCheckSigned32(nodep, "units", nodep->unitsp(), BOTH);
iterateCheckSigned32(nodep, "precision", nodep->precisionp(), BOTH); if (nodep->precisionp())
iterateCheckString(nodep, "suffix", nodep->suffixp(), BOTH); iterateCheckSigned32(nodep, "precision", nodep->precisionp(), BOTH);
iterateCheckSigned32(nodep, "width", nodep->widthp(), BOTH); if (nodep->suffixp()) iterateCheckString(nodep, "suffix", nodep->suffixp(), BOTH);
if (nodep->widthp()) iterateCheckSigned32(nodep, "width", nodep->widthp(), BOTH);
} }
void visit(AstUCStmt* nodep) override { void visit(AstUCStmt* nodep) override {
// Just let all arguments seek their natural sizes // Just let all arguments seek their natural sizes

View File

@ -4362,8 +4362,14 @@ system_t_call<nodeStmtp>: // IEEE: system_tf_call (as task)
| yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale{$1}; } | yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale{$1}; }
| yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale{$1}; } | yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale{$1}; }
| yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale{$1}; DEL($3); } | yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale{$1}; DEL($3); }
| yD_TIMEFORMAT '(' expr ',' expr ',' expr ',' expr ')' | yD_TIMEFORMAT '(' exprE ',' exprE ',' exprE ',' exprE ')'
{ $$ = new AstTimeFormat{$1, $3, $5, $7, $9}; } { $$ = new AstTimeFormat{$1, $3, $5, $7, $9}; }
| yD_TIMEFORMAT '(' exprE ',' exprE ',' exprE ')'
{ $$ = new AstTimeFormat{$1, $3, $5, $7, nullptr}; }
| yD_TIMEFORMAT '(' exprE ',' exprE ')'
{ $$ = new AstTimeFormat{$1, $3, $5, nullptr, nullptr}; }
| yD_TIMEFORMAT '(' exprE ')'
{ $$ = new AstTimeFormat{$1, $3, nullptr, nullptr, nullptr}; }
// //
| yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem{$1, false, $3, $5, nullptr, nullptr}; } | yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem{$1, false, $3, $5, nullptr, nullptr}; }
| yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem{$1, false, $3, $5, $7, nullptr}; } | yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem{$1, false, $3, $5, $7, nullptr}; }

View File

@ -3,5 +3,10 @@ default: [10] 0t time [ 10] No0 time p= 10
-9,0,,10: [10] 0t time [ 10] No0 time p= 10 0p='ha -9,0,,10: [10] 0t time [ 10] No0 time p= 10 0p='ha
-9,0,ns,5: [10ns] 0t time [ 10ns] No0 time p= 10 0p='ha -9,0,ns,5: [10ns] 0t time [ 10ns] No0 time p= 10 0p='ha
-9,3,ns,8: [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha -9,3,ns,8: [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha
-9,3,ns : [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha
-9,3: [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha
-9: [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha
: [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha
-9,,,: [10.000ns] 0t time [10.000ns] No0 time p= 10 0p='ha
*-* All Finished *-* *-* All Finished *-*

View File

@ -30,6 +30,21 @@ module t (/*AUTOARG*/
$timeformat(-9, 3, "ns", 8); $timeformat(-9, 3, "ns", 8);
$write("-9,3,ns,8: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n", $write("-9,3,ns,8: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time); $time, $time, $time, $time);
$timeformat(-9, 3, "ns");
$write("-9,3,ns : [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat(-9, 3);
$write("-9,3: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat(-9);
$write("-9: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat();
$write(": [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$timeformat(-9,,,);
$write("-9,,,: [%0t] 0t time [%t] No0 time p=%p 0p=%0p\n",
$time, $time, $time, $time);
$write("\n"); $write("\n");
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;