From 1a64c7d232b4965784c7c1f035631793054ebdae Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Wed, 15 Apr 2020 22:26:15 +0100 Subject: [PATCH] Fix run-time formatting of variable wider than 1023 bits (#2261) --- src/V3EmitC.cpp | 7 +++--- test_regress/t/t_format_wide_decimal.out | 2 ++ test_regress/t/t_format_wide_decimal.v | 31 ++++++++++++++++++------ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index f0c81b11d..ba95d9fee 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -2042,9 +2042,10 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const string pfmt; if ((fmtLetter == '#' || fmtLetter == 'd' || fmtLetter == 't') && !isScan && vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros - double mantissabits = argp->widthMin() - ((fmtLetter == 'd') ? 1 : 0); - double maxval = pow(2.0, mantissabits); - double dchars = log10(maxval) + 1.0; + const double mantissabits = argp->widthMin() - ((fmtLetter == 'd') ? 1 : 0); + // This is log10(2**mantissabits) as log2(2**mantissabits)/log2(10), + // + 1.0 rounding bias. + double dchars = mantissabits / 3.321928094887362 + 1.0; if (fmtLetter == 'd') dchars++; // space for sign int nchars = int(dchars); pfmt = string("%") + cvtToStr(nchars) + fmtLetter; diff --git a/test_regress/t/t_format_wide_decimal.out b/test_regress/t/t_format_wide_decimal.out index 4c5c7138a..8dd14a9b7 100644 --- a/test_regress/t/t_format_wide_decimal.out +++ b/test_regress/t/t_format_wide_decimal.out @@ -1,2 +1,4 @@ 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215 + 89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678164812112068607 + 44942328371557897693232629769725618340449424473557664318357520289433168951375240783177119330601884005280028469967848339414697442203604155623211857659868531094441973356216371319075554900311523529863270738021251442209537670585615720368478277635206809290837627671146574559986811484619929076208839082406056034303 *-* All Finished *-* diff --git a/test_regress/t/t_format_wide_decimal.v b/test_regress/t/t_format_wide_decimal.v index c901f959d..2b2a04835 100644 --- a/test_regress/t/t_format_wide_decimal.v +++ b/test_regress/t/t_format_wide_decimal.v @@ -6,15 +6,32 @@ // Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -module t_format_wide_decimal; +module t_format_wide_decimal(/*AUTOARG*/ + // Inputs + clk + ); + input clk; - initial begin - // Format very wide constant number (which has more bits than can - // be counted in exponent of a double precision float), with %d. - $display("%d", 1024'hffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + int cycle = 0; + bit [1023:0] x = '1; - $write("*-* All Finished *-*\n"); - $finish; + always @(posedge clk) begin + if (cycle == 0) begin + // Format very wide constant number (which has more bits than can + // be counted in exponent of a double precision float), with %d. + $display("%d", 1024'hffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + end else begin + // Same, but for a variable with value only known at run-time + $display("%d", x); + end + + cycle <= cycle + 1; + x <= x >> 1; + + if (cycle == 2) begin + $write("*-* All Finished *-*\n"); + $finish; + end end endmodule