diff --git a/src/V3Ast.h b/src/V3Ast.h index 674c393f9..f990b491c 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -1891,6 +1891,7 @@ public: // For documentation on emitC format see EmitCStmts::emitOpName virtual string emitC() = 0; virtual string emitSimpleOperator() { return ""; } + virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS virtual bool cleanOut() const = 0; // True if output has extra upper bits zero // Someday we will generically support data types on every math node // Until then isOpaque indicates we shouldn't constant optimize this node type diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 474d6a31f..661941ecf 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -7151,6 +7151,7 @@ public: virtual string emitVerilog() { return "%k(%l %f* %r)"; } virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } virtual string emitSimpleOperator() { return ""; } + virtual bool emitCheckMaxWords() { return true; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } @@ -7288,6 +7289,7 @@ public: } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool emitCheckMaxWords() { return true; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } @@ -7333,6 +7335,7 @@ public: } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; } + virtual bool emitCheckMaxWords() { return true; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } @@ -7356,6 +7359,7 @@ public: } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; } + virtual bool emitCheckMaxWords() { return true; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } @@ -7379,6 +7383,7 @@ public: } virtual string emitVerilog() { return "%k(%l %f** %r)"; } virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; } + virtual bool emitCheckMaxWords() { return true; } virtual bool cleanOut() const { return false; } virtual bool cleanLhs() const { return true; } virtual bool cleanRhs() const { return true; } diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index e8e9a1e8f..2c78bead9 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -888,6 +888,13 @@ public: } } virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { + if (nodep->emitCheckMaxWords() && nodep->widthWords() > VL_MULS_MAX_WORDS) { + nodep->v3warn( + E_UNSUPPORTED, + "Unsupported: " + << nodep->prettyOperatorName() << " operator of " << nodep->width() + << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); + } if (emitSimpleOk(nodep)) { putbs("("); iterateAndNextNull(nodep->lhsp()); @@ -915,56 +922,6 @@ public: puts(")"); } } - virtual void visit(AstMulS* nodep) VL_OVERRIDE { - if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3warn( - E_UNSUPPORTED, - "Unsupported: Signed multiply of " - << nodep->width() - << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); - } - visit(VN_CAST(nodep, NodeBiop)); - } - virtual void visit(AstPow* nodep) VL_OVERRIDE { - if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3warn( - E_UNSUPPORTED, - "Unsupported: Power of " - << nodep->width() - << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); - } - visit(VN_CAST(nodep, NodeBiop)); - } - virtual void visit(AstPowSS* nodep) VL_OVERRIDE { - if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3warn( - E_UNSUPPORTED, - "Unsupported: Power of " - << nodep->width() - << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); - } - visit(VN_CAST(nodep, NodeBiop)); - } - virtual void visit(AstPowSU* nodep) VL_OVERRIDE { - if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3warn( - E_UNSUPPORTED, - "Unsupported: Power of " - << nodep->width() - << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); - } - visit(VN_CAST(nodep, NodeBiop)); - } - virtual void visit(AstPowUS* nodep) VL_OVERRIDE { - if (nodep->widthWords() > VL_MULS_MAX_WORDS) { - nodep->v3warn( - E_UNSUPPORTED, - "Unsupported: Power of " - << nodep->width() - << " bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h"); - } - visit(VN_CAST(nodep, NodeBiop)); - } virtual void visit(AstCCast* nodep) VL_OVERRIDE { // Extending a value of the same word width is just a NOP. if (nodep->size() <= VL_IDATASIZE) { diff --git a/test_regress/t/t_math_wide_bad.out b/test_regress/t/t_math_wide_bad.out new file mode 100644 index 000000000..12170466c --- /dev/null +++ b/test_regress/t/t_math_wide_bad.out @@ -0,0 +1,7 @@ +%Error-UNSUPPORTED: t/t_math_wide_bad.v:21:18: Unsupported: operator POWSS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h + 21 | assign z2 = a ** 3; + | ^~ +%Error-UNSUPPORTED: t/t_math_wide_bad.v:20:17: Unsupported: operator MULS operator of 576 bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h + 20 | assign z = a * b; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_math_wide_bad.pl b/test_regress/t/t_math_wide_bad.pl new file mode 100755 index 000000000..9c9fb65a0 --- /dev/null +++ b/test_regress/t/t_math_wide_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2010 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_math_wide_bad.v b/test_regress/t/t_math_wide_bad.v new file mode 100644 index 000000000..222faca7f --- /dev/null +++ b/test_regress/t/t_math_wide_bad.v @@ -0,0 +1,23 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Outputs + z, z2, + // Inputs + a, b + ); + + input signed [17*32 : 0] a; + input signed [17*32 : 0] b; + + output signed [17*32 : 0] z; + output signed [17*32 : 0] z2; + + assign z = a * b; + assign z2 = a ** 3; + +endmodule