diff --git a/Changes b/Changes index c7b45459e..ae6acf5d3 100644 --- a/Changes +++ b/Changes @@ -16,7 +16,7 @@ Verilator 5.039 devel * Add ENUMITEMWIDTH error, and apply to X-extended and ranged values. * Add NOEFFECT warning, replacing previous `foreach` error. * Add SPECIFYIGN warning for specify constructs that were previously silently ignored. -* Add enum base type checking per IEEE. +* Add enum base data type, and wire data type checking per IEEE. * Support member-level triggers for virtual interfaces (#5166) (#6148). [Yilou Wang] * Support disabling a fork in additional contexts (#5432 partial) (#6174) (#6183). [Ryszard Rozak, Antmicro Ltd.] * Support disable dotted references (#6154). [Ryszard Rozak, Antmicro Ltd.] diff --git a/docs/gen/ex_WIDTHEXPAND_1_faulty.rst b/docs/gen/ex_WIDTHEXPAND_1_faulty.rst index 08c1f0ba2..5dcab8d80 100644 --- a/docs/gen/ex_WIDTHEXPAND_1_faulty.rst +++ b/docs/gen/ex_WIDTHEXPAND_1_faulty.rst @@ -3,6 +3,6 @@ :linenos: :emphasize-lines: 3 - int array[5]; - bit [1:0] rd_addr; - wire int rd_value = array[rd_addr]; //<--- Warning + logic [31:0] array[5]; + bit [1:0] rd_addr; + wire [31:0] rd_value = array[rd_addr]; //<--- Warning diff --git a/docs/gen/ex_WIDTHEXPAND_1_fixed.rst b/docs/gen/ex_WIDTHEXPAND_1_fixed.rst index b40b8b2a6..616e5c1d0 100644 --- a/docs/gen/ex_WIDTHEXPAND_1_fixed.rst +++ b/docs/gen/ex_WIDTHEXPAND_1_fixed.rst @@ -2,4 +2,4 @@ .. code-block:: sv :emphasize-lines: 1 - wire int rd_value = array[{1'b0, rd_addr}]; //<--- Fixed + wire [31:0] rd_value = array[{1'b0, rd_addr}]; //<--- Fixed diff --git a/docs/gen/ex_WIDTHEXPAND_1_msg.rst b/docs/gen/ex_WIDTHEXPAND_1_msg.rst index 927476284..57806096f 100644 --- a/docs/gen/ex_WIDTHEXPAND_1_msg.rst +++ b/docs/gen/ex_WIDTHEXPAND_1_msg.rst @@ -1,4 +1,4 @@ .. comment: generated by t_lint_widthexpand_docs_bad .. code-block:: - %Warning-WIDTHEXPAND: example.v:3:29 Bit extraction of array[4:0] requires 3 bit index, not 2 bits. + %Warning-WIDTHEXPAND: example.v:3:31 Bit extraction of array[4:0] requires 3 bit index, not 2 bits. diff --git a/src/V3Width.cpp b/src/V3Width.cpp index def288069..f938a6a5c 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2422,6 +2422,18 @@ class WidthVisitor final : public VNVisitor { nodep->dtypeSetLogicSized(1, bdtypep->numeric()); VL_DANGLING(bdtypep); } + if (nodep->isNet()) { + AstNodeDType* const badDtp = dtypeNot4StateIntegralRecurse(nodep->dtypep()); + if (badDtp) + nodep->v3error( + "Net " << nodep->prettyNameQ() + << " data type must be 4-state integral or array/union/struct of such" + << " (IEEE 1800-2023 6.7.1)\n" + << nodep->warnContextPrimary() << '\n' + << badDtp->warnOther() << "... Location of failing data type " + << badDtp->prettyDTypeNameQ() << '\n' + << badDtp->warnContextSecondary()); + } if (nodep->valuep() && !didchk) { // if (debug()) nodep->dumpTree("- final: "); // AstPattern requires assignments to pass datatype on PRELIM @@ -8328,6 +8340,25 @@ class WidthVisitor final : public VNVisitor { } return nodep; } + AstNodeDType* dtypeNot4StateIntegralRecurse(AstNodeDType* nodep) { + // If node is _not_ inet valid data type, 4-state integral packed or union, return node + // that makes it fail + nodep = nodep->skipRefp(); + if (AstBasicDType* const dtp = VN_CAST(nodep, BasicDType)) { + if (!dtp->keyword().isFourstate()) return dtp; + return nullptr; + } else if (AstNodeArrayDType* const dtp = VN_CAST(nodep, NodeArrayDType)) { + return dtypeNot4StateIntegralRecurse(nodep->subDTypep()); + } else if (AstNodeUOrStructDType* const dtp = VN_CAST(nodep, NodeUOrStructDType)) { + for (AstMemberDType* itemp = dtp->membersp(); itemp; + itemp = VN_AS(itemp->nextp(), MemberDType)) { + AstNodeDType* const badDtp = dtypeNot4StateIntegralRecurse(itemp->dtypep()); + if (badDtp) return badDtp; + } + return nullptr; + } + return nodep; + } //---------------------------------------------------------------------- // METHODS - special type detection diff --git a/test_regress/t/t_extract_static_const.v b/test_regress/t/t_extract_static_const.v index 94a1c528b..2eb35d791 100644 --- a/test_regress/t/t_extract_static_const.v +++ b/test_regress/t/t_extract_static_const.v @@ -6,7 +6,8 @@ module t (/*AUTOARG*/); - wire bit [255:0] C = {32'h1111_1111, + bit [255:0] C; + initial C = {32'h1111_1111, 32'h2222_2222, 32'h3333_3333, 32'h4444_4444, @@ -16,7 +17,8 @@ module t (/*AUTOARG*/); 32'h8888_8888}; // Same values as above, but with different type - wire logic [255:0] D = {32'h1111_1111, + logic [255:0] D; + initial D = {32'h1111_1111, 32'h2222_2222, 32'h3333_3333, 32'h4444_4444, @@ -28,7 +30,7 @@ module t (/*AUTOARG*/); int i; initial begin - // Note: Base index via $c to prevent optimizatoin by Verilator + // Note: Base index via $c to prevent optimization by Verilator i = $c(0*32); $display("0x%8x", C[i+:32]); i = $c(1*32); $display("0x%8x", D[i+:32]); i = $c(2*32); $display("0x%8x", C[i+:32]); diff --git a/test_regress/t/t_extract_static_const_no_merge.py b/test_regress/t/t_extract_static_const_no_merge.py index 8c3835a5d..354d90d19 100755 --- a/test_regress/t/t_extract_static_const_no_merge.py +++ b/test_regress/t/t_extract_static_const_no_merge.py @@ -19,6 +19,6 @@ test.execute(expect_filename=test.golden_filename) if test.vlt_all: test.file_grep(test.stats, r'Optimizations, Prelim extracted value to ConstPool\s+(\d+)', 8) - test.file_grep(test.stats, r'ConstPool, Constants emitted\s+(\d+)', 2) + test.file_grep(test.stats, r'ConstPool, Constants emitted\s+(\d+)', 1) test.passes() diff --git a/test_regress/t/t_flag_prefix.v b/test_regress/t/t_flag_prefix.v index 1ee503c93..d350086b8 100644 --- a/test_regress/t/t_flag_prefix.v +++ b/test_regress/t/t_flag_prefix.v @@ -13,7 +13,7 @@ module sub; /* verilator no_inline_module */ // Goes into const pool which is separate file - wire bit [255:0] C = {32'h1111_1111, + wire logic [255:0] C = {32'h1111_1111, 32'h2222_2222, 32'h3333_3333, 32'h4444_4444, diff --git a/test_regress/t/t_lint_widthexpand_docs_bad.out b/test_regress/t/t_lint_widthexpand_docs_bad.out index 8af03b587..686a662d9 100644 --- a/test_regress/t/t_lint_widthexpand_docs_bad.out +++ b/test_regress/t/t_lint_widthexpand_docs_bad.out @@ -1,7 +1,7 @@ -%Warning-WIDTHEXPAND: t/t_lint_widthexpand_docs_bad.v:10:29: Bit extraction of array[4:0] requires 3 bit index, not 2 bits. +%Warning-WIDTHEXPAND: t/t_lint_widthexpand_docs_bad.v:10:31: Bit extraction of array[4:0] requires 3 bit index, not 2 bits. : ... note: In instance 't' - 10 | wire int rd_value = array[rd_addr]; - | ^ + 10 | wire [31:0] rd_value = array[rd_addr]; + | ^ ... For warning description see https://verilator.org/warn/WIDTHEXPAND?v=latest ... Use "/* verilator lint_off WIDTHEXPAND */" and lint_on around source to disable this message. %Error: Exiting due to diff --git a/test_regress/t/t_lint_widthexpand_docs_bad.v b/test_regress/t/t_lint_widthexpand_docs_bad.v index 1a99073a0..896a6d389 100644 --- a/test_regress/t/t_lint_widthexpand_docs_bad.v +++ b/test_regress/t/t_lint_widthexpand_docs_bad.v @@ -5,15 +5,15 @@ // SPDX-License-Identifier: CC0-1.0 module t; - int array[5]; - bit [1:0] rd_addr; - wire int rd_value = array[rd_addr]; //<--- Warning + logic [31:0] array[5]; + bit [1:0] rd_addr; + wire [31:0] rd_value = array[rd_addr]; //<--- Warning - ok ok(); + ok ok (); endmodule module ok; - int array[5]; - bit [1:0] rd_addr; - wire int rd_value = array[{1'b0, rd_addr}]; //<--- Fixed -endmodule; + logic [31:0] array[5]; + bit [1:0] rd_addr; + wire [31:0] rd_value = array[{1'b0, rd_addr}]; //<--- Fixed +endmodule diff --git a/test_regress/t/t_net_dtype_bad.out b/test_regress/t/t_net_dtype_bad.out new file mode 100644 index 000000000..2bf44915c --- /dev/null +++ b/test_regress/t/t_net_dtype_bad.out @@ -0,0 +1,37 @@ +%Error: t/t_net_dtype_bad.v:25:15: Net 'bad_real' data type must be 4-state integral or array/union/struct of such (IEEE 1800-2023 6.7.1) + : ... note: In instance 't' + 25 | wire real_t bad_real; + | ^~~~~~~~ + t/t_net_dtype_bad.v:11:11: ... Location of failing data type 'real' + 11 | typedef real real_t; + | ^~~~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_net_dtype_bad.v:27:12: Net 'bad_class' data type must be 4-state integral or array/union/struct of such (IEEE 1800-2023 6.7.1) + : ... note: In instance 't' + 27 | wire Cls bad_class; + | ^~~~~~~~~ + t/t_net_dtype_bad.v:27:8: ... Location of failing data type 'class{}Cls' + 27 | wire Cls bad_class; + | ^~~ +%Error: t/t_net_dtype_bad.v:29:15: Net 'bad_string' data type must be 4-state integral or array/union/struct of such (IEEE 1800-2023 6.7.1) + : ... note: In instance 't' + 29 | wire string bad_string; + | ^~~~~~~~~~ + t/t_net_dtype_bad.v:29:8: ... Location of failing data type 'string' + 29 | wire string bad_string; + | ^~~~~~ +%Error: t/t_net_dtype_bad.v:31:12: Net 'bad_bit' data type must be 4-state integral or array/union/struct of such (IEEE 1800-2023 6.7.1) + : ... note: In instance 't' + 31 | wire bit bad_bit; + | ^~~~~~~ + t/t_net_dtype_bad.v:31:8: ... Location of failing data type 'bit' + 31 | wire bit bad_bit; + | ^~~ +%Error: t/t_net_dtype_bad.v:33:14: Net 'bad_struct' data type must be 4-state integral or array/union/struct of such (IEEE 1800-2023 6.7.1) + : ... note: In instance 't' + 33 | wire bad_t bad_struct; + | ^~~~~~~~~~ + t/t_net_dtype_bad.v:14:5: ... Location of failing data type 'bit' + 14 | bit m_bit; + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_net_dtype_bad.py b/test_regress/t/t_net_dtype_bad.py new file mode 100755 index 000000000..55203b6c9 --- /dev/null +++ b/test_regress/t/t_net_dtype_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_net_dtype_bad.v b/test_regress/t/t_net_dtype_bad.v new file mode 100644 index 000000000..f5f3383ea --- /dev/null +++ b/test_regress/t/t_net_dtype_bad.v @@ -0,0 +1,40 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; +endclass + +module t; + typedef real real_t; + + typedef struct packed { + bit m_bit; + } bad_t; + + typedef struct { + logic m_bit; + } ok_unpk_t; + + typedef struct packed { + logic m_bit; + } ok_t; + + wire real_t bad_real; // <--- Error - bad net type + + wire Cls bad_class; // <--- Error - bad net type + + wire string bad_string; // <--- Error - bad net type + + wire bit bad_bit; // <--- Error - bad net type + + wire bad_t bad_struct; // <--- Error - bad net type + + wire ok_unpk_t ok_unpk_struct; + + wire ok_t ok_struct; // Ok + + initial $stop; +endmodule diff --git a/test_regress/t/t_scheduling_many_clocks.v b/test_regress/t/t_scheduling_many_clocks.v index 04aeccb45..b403efb4e 100644 --- a/test_regress/t/t_scheduling_many_clocks.v +++ b/test_regress/t/t_scheduling_many_clocks.v @@ -45,7 +45,8 @@ module t(/*AUTOARG*/ int cnt = 0; always @(posedge gclk[n]) cnt <= cnt + 1; - wire int cnt_plus_one = cnt + 1; + int cnt_plus_one; + always_comb cnt_plus_one = cnt + 1; final begin `checkh(cnt_plus_one, ITERATIONS + 1); diff --git a/test_regress/t/t_struct_init.v b/test_regress/t/t_struct_init.v index 79f2dd373..c9825d019 100644 --- a/test_regress/t/t_struct_init.v +++ b/test_regress/t/t_struct_init.v @@ -10,10 +10,10 @@ module t; //typedef struct pack2; // Forward declaration typedef struct packed { // [3:0] - bit b3; - bit b2; - bit b1; - bit b0; + logic b3; + logic b2; + logic b1; + logic b0; } b4_t; typedef struct packed { // [3:0] @@ -28,17 +28,17 @@ module t; } q4_t; typedef struct packed { // [5:0] - bit msb; + logic msb; q4_t four; - bit lsb; + logic lsb; } pack2_t; typedef union packed { // [5:0] pack2_t pack2; bit [6:1] pvec; // Vector not allowed in packed structure, per spec: - // bit vec[6]; - // bit vec2d[2][3]; + // logic vec[6]; + // logic vec2d[2][3]; } pack3_t; const b4_t b4_const_a = '{1'b1, 1'b0, 1'b0, 1'b1}; diff --git a/test_regress/t/t_trace_dumpvars_dyn.v b/test_regress/t/t_trace_dumpvars_dyn.v index dfeaa16dd..4c9705348 100644 --- a/test_regress/t/t_trace_dumpvars_dyn.v +++ b/test_regress/t/t_trace_dumpvars_dyn.v @@ -28,7 +28,8 @@ endmodule module sub1 #(parameter int ADD) (input int cyc); - wire int value = cyc + ADD; + int value; + always_comb value = cyc + ADD; sub2 #(ADD + 1) sub2a(.*); sub2 #(ADD + 2) sub2b(.*); @@ -38,5 +39,6 @@ endmodule module sub2 #(parameter int ADD) (input int cyc); - wire int value = cyc + ADD; + int value; + always_comb value = cyc + ADD; endmodule diff --git a/test_regress/t/t_trace_dumpvars_dyn_fst_0.out b/test_regress/t/t_trace_dumpvars_dyn_fst_0.out index e3d5eaaf3..ed5398dd3 100644 --- a/test_regress/t/t_trace_dumpvars_dyn_fst_0.out +++ b/test_regress/t/t_trace_dumpvars_dyn_fst_0.out @@ -1,5 +1,5 @@ $date - Sat Mar 5 14:06:13 2022 + Sat Jul 19 22:57:16 2025 $end $version @@ -16,41 +16,41 @@ $var int 32 " cyc [31:0] $end $scope module sub1a $end $var parameter 32 # ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 $ value [31:0] $end +$var int 32 $ value [31:0] $end $scope module sub2a $end $var parameter 32 % ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 & value [31:0] $end +$var int 32 & value [31:0] $end $upscope $end $scope module sub2b $end $var parameter 32 ' ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 ( value [31:0] $end +$var int 32 ( value [31:0] $end $upscope $end $scope module sub2c $end $var parameter 32 ) ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 * value [31:0] $end +$var int 32 * value [31:0] $end $upscope $end $upscope $end $scope module sub1b $end $var parameter 32 + ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 , value [31:0] $end +$var int 32 , value [31:0] $end $scope module sub2a $end $var parameter 32 - ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 . value [31:0] $end +$var int 32 . value [31:0] $end $upscope $end $scope module sub2b $end $var parameter 32 / ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 0 value [31:0] $end +$var int 32 0 value [31:0] $end $upscope $end $scope module sub2c $end $var parameter 32 1 ADD [31:0] $end $var wire 32 " cyc [31:0] $end -$var wire 32 2 value [31:0] $end +$var int 32 2 value [31:0] $end $upscope $end $upscope $end $upscope $end diff --git a/test_regress/t/t_trace_dumpvars_dyn_fst_1.out b/test_regress/t/t_trace_dumpvars_dyn_fst_1.out index 68b1899ee..6426ca007 100644 --- a/test_regress/t/t_trace_dumpvars_dyn_fst_1.out +++ b/test_regress/t/t_trace_dumpvars_dyn_fst_1.out @@ -1,5 +1,5 @@ $date - Sat Apr 5 13:56:24 2025 + Sat Jul 19 22:57:23 2025 $end $version @@ -14,7 +14,7 @@ $var int 32 ! cyc [31:0] $end $scope module sub1a $end $var parameter 32 " ADD [31:0] $end $var wire 32 ! cyc [31:0] $end -$var wire 32 # value [31:0] $end +$var int 32 # value [31:0] $end $scope module sub2a $end $upscope $end $scope module sub2b $end @@ -25,21 +25,21 @@ $upscope $end $scope module sub1b $end $var parameter 32 $ ADD [31:0] $end $var wire 32 ! cyc [31:0] $end -$var wire 32 % value [31:0] $end +$var int 32 % value [31:0] $end $scope module sub2a $end $var parameter 32 & ADD [31:0] $end $var wire 32 ! cyc [31:0] $end -$var wire 32 ' value [31:0] $end +$var int 32 ' value [31:0] $end $upscope $end $scope module sub2b $end $var parameter 32 ( ADD [31:0] $end $var wire 32 ! cyc [31:0] $end -$var wire 32 ) value [31:0] $end +$var int 32 ) value [31:0] $end $upscope $end $scope module sub2c $end $var parameter 32 * ADD [31:0] $end $var wire 32 ! cyc [31:0] $end -$var wire 32 + value [31:0] $end +$var int 32 + value [31:0] $end $upscope $end $upscope $end $upscope $end diff --git a/test_regress/t/t_trace_scope_vlt.v b/test_regress/t/t_trace_scope_vlt.v index dfeaa16dd..4c9705348 100644 --- a/test_regress/t/t_trace_scope_vlt.v +++ b/test_regress/t/t_trace_scope_vlt.v @@ -28,7 +28,8 @@ endmodule module sub1 #(parameter int ADD) (input int cyc); - wire int value = cyc + ADD; + int value; + always_comb value = cyc + ADD; sub2 #(ADD + 1) sub2a(.*); sub2 #(ADD + 2) sub2b(.*); @@ -38,5 +39,6 @@ endmodule module sub2 #(parameter int ADD) (input int cyc); - wire int value = cyc + ADD; + int value; + always_comb value = cyc + ADD; endmodule diff --git a/test_regress/t/t_wire_types.v b/test_regress/t/t_wire_types.v index a1389327e..d99864d9b 100644 --- a/test_regress/t/t_wire_types.v +++ b/test_regress/t/t_wire_types.v @@ -15,48 +15,23 @@ module t (/*AUTOARG*/ input clk; // IEEE: integer_atom_type - wire byte w_byte; - wire shortint w_shortint; - wire int w_int; - wire longint w_longint; wire integer w_integer; // IEEE: integer_atom_type - wire bit w_bit; wire logic w_logic; - wire bit [1:0] w_bit2; wire logic [1:0] w_logic2; - // IEEE: non_integer_type - //UNSUP shortreal w_shortreal; - wire real w_real; - - assign w_byte = 8'h12; - assign w_shortint = 16'h1234; - assign w_int = -123456; - assign w_longint = -1234567; assign w_integer = -123456; - assign w_bit = 1'b1; assign w_logic = 1'b1; - assign w_bit2 = 2'b10; assign w_logic2 = 2'b10; - assign w_real = 3.14; - always @ (posedge clk) begin - `checkh(w_byte, 8'h12); - `checkh(w_shortint, 16'h1234); - `checkh(w_int, -123456); - `checkh(w_longint, -1234567); `checkh(w_integer, -123456); - `checkh(w_bit, 1'b1); `checkh(w_logic, 1'b1); - `checkh(w_bit2, 2'b10); `checkh(w_logic2, 2'b10); - `checkr(w_real, 3.14); $write("*-* All Finished *-*\n"); $finish; end