Add wire data type checking per IEEE.
This commit is contained in:
parent
b8b9478938
commit
078bb21a89
2
Changes
2
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.]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue