diff --git a/Changes b/Changes index b949dba1e..1495898e0 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Fix genblk naming with directly nested generate blocks, #2176. [Alexander Grobman] +**** Implement $displayb/o/h, $writeb/o/h, etc, #1637. + **** Use gcc -Os in examples instead of -O2 for better average performance. **** Fix undeclared VL_SHIFTR_WWQ, #2114. [Alex Solomatnikov] diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 7365d6430..b7ab752a8 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -2956,17 +2956,21 @@ public: class AstSFormatF : public AstNode { // Convert format to string, generally under an AstDisplay or AstSFormat // Also used as "real" function for /*verilator sformat*/ functions - string m_text; - bool m_hidden; // Under display, etc - bool m_hasFormat; // Has format code + string m_text; + bool m_hidden; // Under display, etc + bool m_hasFormat; // Has format code + char m_missingArgChar; // Format code when argument without format, 'h'/'o'/'b' public: class NoFormat {}; - AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp) - : ASTGEN_SUPER(fl), m_text(text), m_hidden(hidden), m_hasFormat(true) { + AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp, + char missingArgChar = 'd') + : ASTGEN_SUPER(fl) + , m_text(text), m_hidden(hidden), m_hasFormat(true), m_missingArgChar(missingArgChar) { dtypeSetString(); addNOp1p(exprsp); addNOp2p(NULL); } - AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp) - : ASTGEN_SUPER(fl), m_text(""), m_hidden(true), m_hasFormat(false) { + AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd') + : ASTGEN_SUPER(fl) + , m_text(""), m_hidden(true), m_hasFormat(false), m_missingArgChar(missingArgChar) { dtypeSetString(); addNOp1p(exprsp); addNOp2p(NULL); } ASTNODE_NODE_FUNCS(SFormatF) @@ -2988,6 +2992,7 @@ public: bool hidden() const { return m_hidden; } void hasFormat(bool flag) { m_hasFormat = flag; } bool hasFormat() const { return m_hasFormat; } + char missingArgChar() const { return m_missingArgChar; } }; class AstDisplay : public AstNodeStmt { @@ -2995,18 +3000,19 @@ class AstDisplay : public AstNodeStmt { // Children: file which must be a varref // Children: SFORMATF to generate print string private: - AstDisplayType m_displayType; + AstDisplayType m_displayType; public: AstDisplay(FileLine* fl, AstDisplayType dispType, const string& text, AstNode* filep, - AstNode* exprsp) + AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER(fl) { - setOp1p(new AstSFormatF(fl, text, true, exprsp)); + setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); setNOp3p(filep); m_displayType = dispType; } - AstDisplay(FileLine* fl, AstDisplayType dispType, AstNode* filep, AstNode* exprsp) + AstDisplay(FileLine* fl, AstDisplayType dispType, AstNode* filep, AstNode* exprsp, + char missingArgChar = 'd') : ASTGEN_SUPER(fl) { - setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp)); + setOp1p(new AstSFormatF(fl, AstSFormatF::NoFormat(), exprsp, missingArgChar)); setNOp3p(filep); m_displayType = dispType; } @@ -3092,9 +3098,10 @@ class AstSFormat : public AstNodeStmt { // Children: string to load // Children: SFORMATF to generate print string public: - AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp) + AstSFormat(FileLine* fl, AstNode* lhsp, const string& text, AstNode* exprsp, + char missingArgChar = 'd') : ASTGEN_SUPER(fl) { - setOp1p(new AstSFormatF(fl, text, true, exprsp)); + setOp1p(new AstSFormatF(fl, text, true, exprsp, missingArgChar)); setOp3p(lhsp); } ASTNODE_NODE_FUNCS(SFormat) diff --git a/src/V3Width.cpp b/src/V3Width.cpp index dc4152b46..0f886eea2 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2819,7 +2819,7 @@ private: } else if (argp && argp->isString()) { ch = '@'; } else { - ch = 'h'; + ch = nodep->missingArgChar(); } if (argp) argp = argp->nextp(); break; diff --git a/src/verilog.l b/src/verilog.l index 33b791946..2ebd3694e 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -197,6 +197,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$cos" { FL; return yD_COS; } "$cosh" { FL; return yD_COSH; } "$display" { FL; return yD_DISPLAY; } + "$displayb" { FL; return yD_DISPLAYB; } + "$displayh" { FL; return yD_DISPLAYH; } + "$displayo" { FL; return yD_DISPLAYO; } "$dumpall" { FL; return yD_DUMPALL; } "$dumpfile" { FL; return yD_DUMPFILE; } "$dumpflush" { FL; return yD_DUMPFLUSH; } @@ -213,6 +216,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$exp" { FL; return yD_EXP; } "$fclose" { FL; return yD_FCLOSE; } "$fdisplay" { FL; return yD_FDISPLAY; } + "$fdisplayb" { FL; return yD_FDISPLAYB; } + "$fdisplayh" { FL; return yD_FDISPLAYH; } + "$fdisplayo" { FL; return yD_FDISPLAYO; } "$feof" { FL; return yD_FEOF; } "$fflush" { FL; return yD_FFLUSH; } "$fgetc" { FL; return yD_FGETC; } @@ -227,6 +233,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$ftell" { FL; return yD_FTELL; } "$fullskew" { FL; return yaTIMINGSPEC; } "$fwrite" { FL; return yD_FWRITE; } + "$fwriteb" { FL; return yD_FWRITEB; } + "$fwriteh" { FL; return yD_FWRITEH; } + "$fwriteo" { FL; return yD_FWRITEO; } "$hold" { FL; return yaTIMINGSPEC; } "$hypot" { FL; return yD_HYPOT; } "$itor" { FL; return yD_ITOR; } @@ -245,9 +254,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$removal" { FL; return yaTIMINGSPEC; } "$rewind" { FL; return yD_REWIND; } "$rtoi" { FL; return yD_RTOI; } + "$sampled" { FL; return yD_SAMPLED; } "$setup" { FL; return yaTIMINGSPEC; } "$setuphold" { FL; return yaTIMINGSPEC; } - "$sampled" { FL; return yD_SAMPLED; } "$sformat" { FL; return yD_SFORMAT; } "$sformatf" { FL; return yD_SFORMATF; } "$shortrealtobits" { FL; return yD_SHORTREALTOBITS; } @@ -259,6 +268,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$stime" { FL; return yD_STIME; } "$stop" { FL; return yD_STOP; } "$swrite" { FL; return yD_SWRITE; } + "$swriteb" { FL; return yD_SWRITEB; } + "$swriteh" { FL; return yD_SWRITEH; } + "$swriteo" { FL; return yD_SWRITEO; } "$system" { FL; return yD_SYSTEM; } "$tan" { FL; return yD_TAN; } "$tanh" { FL; return yD_TANH; } @@ -270,6 +282,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$value$plusargs" { FL; return yD_VALUEPLUSARGS; } "$width" { FL; return yaTIMINGSPEC; } "$write" { FL; return yD_WRITE; } + "$writeb" { FL; return yD_WRITEB; } + "$writeh" { FL; return yD_WRITEH; } + "$writeo" { FL; return yD_WRITEO; } "$writememh" { FL; return yD_WRITEMEMH; } /* Keywords */ "always" { FL; return yALWAYS; } @@ -374,19 +389,6 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "wor" { FL; return yWOR; } "xnor" { FL; return yXNOR; } "xor" { FL; return yXOR; } - /* Special errors */ - "$displayb" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $display with %%b format instead: %s", yytext); } - "$displayh" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $display with %%x format instead: %s", yytext); } - "$displayo" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $display with %%o format instead: %s", yytext); } - "$fdisplayb" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fdisplay with %%b format instead: %s", yytext); } - "$fdisplayh" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fdisplay with %%x format instead: %s", yytext); } - "$fdisplayo" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fdisplay with %%o format instead: %s", yytext); } - "$fwriteb" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fwrite with %%b format instead: %s", yytext); } - "$fwriteh" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fwrite with %%x format instead: %s", yytext); } - "$fwriteo" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $fwrite with %%o format instead: %s", yytext); } - "$writeb" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $write with %%b format instead: %s", yytext); } - "$writeh" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $write with %%x format instead: %s", yytext); } - "$writeo" { FL; RETURN_BBOX_SYS_OR_MSG("Unsupported: Use $write with %%o format instead: %s", yytext); } } /* Verilog 2001 */ diff --git a/src/verilog.y b/src/verilog.y index 8ad3f5fb9..70c6288e0 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -553,6 +553,9 @@ class AstSenTree; %token yD_COUNTONES "$countones" %token yD_DIMENSIONS "$dimensions" %token yD_DISPLAY "$display" +%token yD_DISPLAYB "$displayb" +%token yD_DISPLAYH "$displayh" +%token yD_DISPLAYO "$displayo" %token yD_DUMPALL "$dumpall" %token yD_DUMPFILE "$dumpfile" %token yD_DUMPFLUSH "$dumpflush" @@ -566,6 +569,9 @@ class AstSenTree; %token yD_FATAL "$fatal" %token yD_FCLOSE "$fclose" %token yD_FDISPLAY "$fdisplay" +%token yD_FDISPLAYB "$fdisplayb" +%token yD_FDISPLAYH "$fdisplayh" +%token yD_FDISPLAYO "$fdisplayo" %token yD_FEOF "$feof" %token yD_FFLUSH "$fflush" %token yD_FGETC "$fgetc" @@ -579,6 +585,9 @@ class AstSenTree; %token yD_FSEEK "$fseek" %token yD_FTELL "$ftell" %token yD_FWRITE "$fwrite" +%token yD_FWRITEB "$fwriteb" +%token yD_FWRITEH "$fwriteh" +%token yD_FWRITEO "$fwriteo" %token yD_HIGH "$high" %token yD_HYPOT "$hypot" %token yD_INCREMENT "$increment" @@ -614,6 +623,9 @@ class AstSenTree; %token yD_STIME "$stime" %token yD_STOP "$stop" %token yD_SWRITE "$swrite" +%token yD_SWRITEB "$swriteb" +%token yD_SWRITEH "$swriteh" +%token yD_SWRITEO "$swriteo" %token yD_SYSTEM "$system" %token yD_TAN "$tan" %token yD_TANH "$tanh" @@ -627,7 +639,10 @@ class AstSenTree; %token yD_VALUEPLUSARGS "$value$plusargs" %token yD_WARNING "$warning" %token yD_WRITE "$write" +%token yD_WRITEB "$writeb" +%token yD_WRITEH "$writeh" %token yD_WRITEMEMH "$writememh" +%token yD_WRITEO "$writeo" %token yVL_CLOCK "/*verilator sc_clock*/" %token yVL_CLOCKER "/*verilator clocker*/" @@ -3195,16 +3210,40 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_STOP parenE { $$ = new AstStop($1, false); } | yD_STOP '(' expr ')' { $$ = new AstStop($1, false); DEL($3); } // - | yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } - | yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } + | yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1, $3, *$5, $6); } + | yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1, $3, *$5, $6); } + | yD_SWRITEB '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1, $3, *$5, $6, 'b'); } + | yD_SWRITEH '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1, $3, *$5, $6, 'h'); } + | yD_SWRITEO '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1, $3, *$5, $6, 'o'); } // | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL); } | yD_DISPLAY '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3); } + | yD_DISPLAYB parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL, 'b'); } + | yD_DISPLAYB '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3, 'b'); } + | yD_DISPLAYH parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL, 'h'); } + | yD_DISPLAYH '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3, 'h'); } + | yD_DISPLAYO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL, 'o'); } + | yD_DISPLAYO '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3, 'o'); } | yD_WRITE parenE { $$ = NULL; } // NOP | yD_WRITE '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3); } + | yD_WRITEB parenE { $$ = NULL; } // NOP + | yD_WRITEB '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3, 'b'); } + | yD_WRITEH parenE { $$ = NULL; } // NOP + | yD_WRITEH '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3, 'h'); } + | yD_WRITEO parenE { $$ = NULL; } // NOP + | yD_WRITEO '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3, 'o'); } | yD_FDISPLAY '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL); } | yD_FDISPLAY '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5); } + | yD_FDISPLAYB '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL, 'b'); } + | yD_FDISPLAYB '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'b'); } + | yD_FDISPLAYH '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL, 'h'); } + | yD_FDISPLAYH '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'h'); } + | yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL, 'o'); } + | yD_FDISPLAYO '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'o'); } | yD_FWRITE '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5); } + | yD_FWRITEB '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'b'); } + | yD_FWRITEO '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'h'); } + | yD_FWRITEH '(' expr ',' exprListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'o'); } | yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, NULL, NULL); } | yD_INFO '(' exprList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, NULL, $3); } | yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, NULL); } diff --git a/test_regress/t/t_assert_comp_bad.out b/test_regress/t/t_assert_comp_bad.out index ec27ed155..a3d3be7a7 100644 --- a/test_regress/t/t_assert_comp_bad.out +++ b/test_regress/t/t_assert_comp_bad.out @@ -7,7 +7,7 @@ $warning("User compile-time warning"); ^~~~~~~~ ... Use "/* verilator lint_off USERWARN */" and lint_on around source to disable this message. -%Warning-USERWARN: t/t_assert_comp_bad.v:11: 00000001 +%Warning-USERWARN: t/t_assert_comp_bad.v:11: 1 : ... In instance t $warning(1); ^~~~~~~~ diff --git a/test_regress/t/t_display.out b/test_regress/t/t_display.out index 289022a90..7102f4108 100644 --- a/test_regress/t/t_display.out +++ b/test_regress/t/t_display.out @@ -43,11 +43,15 @@ [0] %s=! %s= what! %s= hmmm!1234 [0] %6s=: !: %6s=: what!: %6s=: hmmm!1234: [0] %8s=: sv-str: +d: 12 12 +h: 00c 00c +o: 014 014 +b: 000001100 000001100 [0] hello, from a very long string. Percent %s are literally substituted in. hello, from a concatenated string. hello, from a concatenated format string [0]. -extra argument: 0000000000000000 -0000000000000000: pre argument +extra argument: 0 + 0: pre argument [0] Embedded <#013> return [0] Embedded multiline diff --git a/test_regress/t/t_display.v b/test_regress/t/t_display.v index 90b80c6eb..12bc6db5f 100644 --- a/test_regress/t/t_display.v +++ b/test_regress/t/t_display.v @@ -132,6 +132,12 @@ module t; $display("[%0t] %%8s=:%8s:", $time, svs); + // Displays without format, must use default + $write("d: "); $write(nine); $write(" "); $display(nine); + $writeh("h: "); $writeh(nine); $writeh(" "); $displayh(nine); + $writeo("o: "); $writeo(nine); $writeo(" "); $displayo(nine); + $writeb("b: "); $writeb(nine); $writeb(" "); $displayb(nine); + $display("[%0t] %s%s%s", $time, "hel", "lo, fr", "om a very long string. Percent %s are literally substituted in."); $display("hel", "lo, fr", "om a concatenated string."); diff --git a/test_regress/t/t_display_merge.out b/test_regress/t/t_display_merge.out index 5d290cba7..7ab198f50 100644 --- a/test_regress/t/t_display_merge.out +++ b/test_regress/t/t_display_merge.out @@ -8,12 +8,12 @@ f t2=0 post t3=0 - t4=0 t5=00000000000000000 + t4=0 t5=0 0 m t=0 t2=0 t3=0 t4=0 t5=0 t=0 t2=0 t3=0 t4=0 t5=0 mm -f a=top.t b=top.t pre t=0 t2=0 post t3=0 t4=0 t5=00000000000000000m t=0 t2=0 t3=0 t4=0 t5=0 t=0 t2=0 t3=0 t4=0 t5=0mm +f a=top.t b=top.t pre t=0 t2=0 post t3=0 t4=0 t5=0 0m t=0 t2=0 t3=0 t4=0 t5=0 t=0 t2=0 t3=0 t4=0 t5=0mm *-* All Finished *-* diff --git a/test_regress/t/t_sys_file_basic.out b/test_regress/t/t_sys_file_basic.out new file mode 100644 index 000000000..bd5e9f664 --- /dev/null +++ b/test_regress/t/t_sys_file_basic.out @@ -0,0 +1,6 @@ +[0] hello v=12345667 +[0] Hello2 +d: 12 12 +h: 00000000014 0000000c +o: 0000000c 00000000014 +b: 00000000000000000000000000001100 00000000000000000000000000001100 diff --git a/test_regress/t/t_sys_file_basic.pl b/test_regress/t/t_sys_file_basic.pl index 1c167efd4..5e4c3a3ba 100755 --- a/test_regress/t/t_sys_file_basic.pl +++ b/test_regress/t/t_sys_file_basic.pl @@ -21,10 +21,7 @@ execute( check_finished => 1, ); -file_grep("$Self->{obj_dir}/t_sys_file_basic_test.log", -qr/\[0\] hello v=12345667 -\[0\] Hello2 -/); +files_identical("$Self->{obj_dir}/t_sys_file_basic_test.log", $Self->{golden_filename}); ok(1); 1; diff --git a/test_regress/t/t_sys_file_basic.v b/test_regress/t/t_sys_file_basic.v index d0bb007c4..60ed787bb 100644 --- a/test_regress/t/t_sys_file_basic.v +++ b/test_regress/t/t_sys_file_basic.v @@ -19,6 +19,7 @@ module t; reg [16*8:1] letterz; real r; string s; + integer i; reg [7:0] v_a,v_b,v_c,v_d; reg [31:0] v_worda; @@ -51,6 +52,13 @@ module t; $fdisplay(file, "[%0t] hello v=%x", $time, 32'h12345667); $fwrite(file, "[%0t] %s\n", $time, "Hello2"); + + i = 12; + $fwrite(file, "d: "); $fwrite(file, i); $fwrite(file, " "); $fdisplay(file, i); + $fwriteh(file, "h: "); $fwriteh(file, i); $fwriteh(file, " "); $fdisplayh(file, i); + $fwriteo(file, "o: "); $fwriteo(file, i); $fwriteo(file, " "); $fdisplayo(file, i); + $fwriteb(file, "b: "); $fwriteb(file, i); $fwriteb(file, " "); $fdisplayb(file, i); + $fflush(file); $fclose(file);