Improve code coverage of V3SplitVar.cpp (#2418)
This commit is contained in:
parent
c367b671b6
commit
19c2906a64
|
|
@ -173,10 +173,7 @@ struct SplitVarImpl {
|
||||||
if (const char* reason = cannotSplitVarTypeReason(varp->varType())) return reason;
|
if (const char* reason = cannotSplitVarTypeReason(varp->varType())) return reason;
|
||||||
if (const char* reason = cannotSplitVarDirectionReason(varp->direction())) return reason;
|
if (const char* reason = cannotSplitVarDirectionReason(varp->direction())) return reason;
|
||||||
if (varp->isSigPublic()) return "it is public";
|
if (varp->isSigPublic()) return "it is public";
|
||||||
if (varp->isInoutish()) return "it is bidirectional";
|
|
||||||
if (varp->isUsedLoopIdx()) return "it is used as a loop variable";
|
if (varp->isUsedLoopIdx()) return "it is used as a loop variable";
|
||||||
if (varp->isGenVar()) return "it is genvar";
|
|
||||||
if (varp->isParam()) return "it is parameter";
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -291,14 +288,6 @@ public:
|
||||||
|
|
||||||
class UnpackRefMap {
|
class UnpackRefMap {
|
||||||
public:
|
public:
|
||||||
struct Hash {
|
|
||||||
size_t operator()(const UnpackRef& r) const { return reinterpret_cast<size_t>(r.nodep()); }
|
|
||||||
};
|
|
||||||
struct Compare {
|
|
||||||
bool operator()(const UnpackRef& a, const UnpackRef& b) const {
|
|
||||||
return a.nodep() == b.nodep();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef std::map<AstVar*, std::set<UnpackRef>, AstNodeComparator> MapType;
|
typedef std::map<AstVar*, std::set<UnpackRef>, AstNodeComparator> MapType;
|
||||||
typedef MapType::iterator MapIt;
|
typedef MapType::iterator MapIt;
|
||||||
typedef MapType::value_type::second_type::iterator SetIt;
|
typedef MapType::value_type::second_type::iterator SetIt;
|
||||||
|
|
@ -981,19 +970,6 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl {
|
||||||
int m_numSplit; // Total number of split variables
|
int m_numSplit; // Total number of split variables
|
||||||
// key:variable to be split. value:location where the variable is referenced.
|
// key:variable to be split. value:location where the variable is referenced.
|
||||||
PackedVarRefMap m_refs;
|
PackedVarRefMap m_refs;
|
||||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
|
||||||
UASSERT_OBJ(m_modp == NULL, m_modp, "Nested module declaration");
|
|
||||||
if (!VN_IS(nodep, Module)) {
|
|
||||||
UINFO(5, "Skip " << nodep->prettyNameQ() << "\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UASSERT_OBJ(m_refs.empty(), nodep, "The last module didn't finish split()");
|
|
||||||
m_modp = nodep;
|
|
||||||
UINFO(3, "Start analyzing module " << nodep->prettyName() << '\n');
|
|
||||||
iterateChildren(nodep);
|
|
||||||
split();
|
|
||||||
m_modp = NULL;
|
|
||||||
}
|
|
||||||
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
||||||
if (!cannotSplitTaskReason(nodep)) iterateChildren(nodep);
|
if (!cannotSplitTaskReason(nodep)) iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
|
|
@ -1238,7 +1214,7 @@ public:
|
||||||
, m_modp(NULL)
|
, m_modp(NULL)
|
||||||
, m_numSplit(0) {
|
, m_numSplit(0) {
|
||||||
// If you want ignore refs and walk the tne entire AST,
|
// If you want ignore refs and walk the tne entire AST,
|
||||||
// just call iterate(nodep) and disable the following for-loop.
|
// just call iterateChildren(m_modp) and split() for each module
|
||||||
for (SplitVarRefsMap::iterator it = refs.begin(), it_end = refs.end(); it != it_end;
|
for (SplitVarRefsMap::iterator it = refs.begin(), it_end = refs.end(); it != it_end;
|
||||||
++it) {
|
++it) {
|
||||||
m_modp = it->first;
|
m_modp = it->first;
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ module barshift_2d_packed_array #(parameter DEPTH = 2, localparam WIDTH = 2**DEP
|
||||||
|
|
||||||
generate
|
generate
|
||||||
for(genvar i = 0; i < DEPTH; ++i) begin
|
for(genvar i = 0; i < DEPTH; ++i) begin
|
||||||
always_comb
|
always @(shift or tmp)
|
||||||
/*verilator lint_off ALWCOMBORDER*/
|
/*verilator lint_off ALWCOMBORDER*/
|
||||||
if (shift[i]) begin
|
if (shift[i]) begin
|
||||||
tmp[i+1+OFFSET] = {tmp[i+OFFSET][(1 << i)-1:0], tmp[i+OFFSET][WIDTH-1:(2**i)]};
|
tmp[i+1+OFFSET] = {tmp[i+OFFSET][(1 << i)-1:0], tmp[i+OFFSET][WIDTH-1:(2**i)]};
|
||||||
|
|
|
||||||
|
|
@ -11,28 +11,28 @@
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:12:16: 'should_show_warning_ifs1' has split_var metacomment, but will not be split because it is not declared in a module.
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:12:16: 'should_show_warning_ifs1' has split_var metacomment, but will not be split because it is not declared in a module.
|
||||||
12 | logic [7:0] should_show_warning_ifs1 [1:0] /*verilator split_var*/ ;
|
12 | logic [7:0] should_show_warning_ifs1 [1:0] /*verilator split_var*/ ;
|
||||||
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:38:14: 'cannot_split1' has split_var metacomment but will not be split because it is accessed from another module via a dot.
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:40:14: 'cannot_split1' has split_var metacomment but will not be split because it is accessed from another module via a dot.
|
||||||
38 | i_sub0.cannot_split1[0] = 0;
|
40 | i_sub0.cannot_split1[0] = 0;
|
||||||
| ^~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~
|
||||||
%Warning-SELRANGE: t/t_split_var_1_bad.v:83:33: Selection index out of range: 13 outside 12:10
|
%Warning-SELRANGE: t/t_split_var_1_bad.v:90:33: Selection index out of range: 13 outside 12:10
|
||||||
: ... In instance t.i_sub3
|
: ... In instance t.i_sub3
|
||||||
83 | assign outwires[12] = inwires[13];
|
90 | assign outwires[12] = inwires[13];
|
||||||
| ^
|
| ^
|
||||||
%Warning-WIDTH: t/t_split_var_1_bad.v:39:31: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's FUNCREF 'bad_func' generates 32 bits.
|
%Warning-WIDTH: t/t_split_var_1_bad.v:41:31: Operator ASSIGN expects 8 bits on the Assign RHS, but Assign RHS's FUNCREF 'bad_func' generates 32 bits.
|
||||||
: ... In instance t
|
: ... In instance t
|
||||||
39 | i_sub0.cannot_split1[1] = bad_func(addr, rd_data0);
|
41 | i_sub0.cannot_split1[1] = bad_func(addr, rd_data0);
|
||||||
| ^
|
| ^
|
||||||
%Error: t/t_split_var_1_bad.v:72:16: Illegal assignment of constant to unpacked array
|
%Error: t/t_split_var_1_bad.v:79:16: Illegal assignment of constant to unpacked array
|
||||||
: ... In instance t.i_sub2
|
: ... In instance t.i_sub2
|
||||||
72 | assign b = a[0];
|
79 | assign b = a[0];
|
||||||
| ^
|
| ^
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:51:31: 'cannot_split0' has split_var metacomment but will not be split because index cannot be determined statically.
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:56:31: 'cannot_split0' has split_var metacomment but will not be split because index cannot be determined statically.
|
||||||
: ... In instance t.i_sub0
|
: ... In instance t.i_sub0
|
||||||
51 | rd_data = cannot_split0[addr];
|
56 | rd_data = cannot_split0[addr];
|
||||||
| ^~~~
|
| ^~~~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:83:34: 'inwires' has split_var metacomment but will not be split because index is out of range.
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:90:34: 'inwires' has split_var metacomment but will not be split because index is out of range.
|
||||||
: ... In instance t.i_sub3
|
: ... In instance t.i_sub3
|
||||||
83 | assign outwires[12] = inwires[13];
|
90 | assign outwires[12] = inwires[13];
|
||||||
| ^~
|
| ^~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:17:9: 'should_show_warning0' has split_var metacomment but will not be split because it is not an aggregate type of bit nor logic
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:17:9: 'should_show_warning0' has split_var metacomment but will not be split because it is not an aggregate type of bit nor logic
|
||||||
: ... In instance t
|
: ... In instance t
|
||||||
|
|
@ -46,20 +46,32 @@
|
||||||
: ... In instance t
|
: ... In instance t
|
||||||
19 | wire should_show_warning2 /*verilator split_var*/ ;
|
19 | wire should_show_warning2 /*verilator split_var*/ ;
|
||||||
| ^~~~~~~~~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~~~~~~~~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:30:44: 'inout_port' has split_var metacomment but will not be split because it is an inout port
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:23:16: 'public_signal' has split_var metacomment but will not be split because it is public
|
||||||
: ... In instance t
|
: ... In instance t
|
||||||
30 | function int bad_func(inout logic [3:0] inout_port /*verilator split_var*/ ,
|
23 | logic [1:0] public_signal /*verilator public*/ /*verilator split_var*/ ;
|
||||||
|
| ^~~~~~~~~~~~~
|
||||||
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:31:44: 'inout_port' has split_var metacomment but will not be split because it is an inout port
|
||||||
|
: ... In instance t
|
||||||
|
31 | function int bad_func(inout logic [3:0] inout_port /*verilator split_var*/ ,
|
||||||
| ^~~~~~~~~~
|
| ^~~~~~~~~~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:31:42: 'ref_port' has split_var metacomment but will not be split because it is a ref argument
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:32:42: 'ref_port' has split_var metacomment but will not be split because it is a ref argument
|
||||||
: ... In instance t
|
: ... In instance t
|
||||||
31 | ref logic [7:0] ref_port /*verilator split_var*/ );
|
32 | ref logic [7:0] ref_port /*verilator split_var*/ );
|
||||||
| ^~~~~~~~
|
| ^~~~~~~~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:57:11: 'cannot_split_genvar' has split_var metacomment but will not be split because it is not an aggregate type of bit nor logic
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:37:19: 'loop_idx' has split_var metacomment but will not be split because it is used as a loop variable
|
||||||
|
: ... In instance t
|
||||||
|
37 | logic [7:0] loop_idx /*verilator split_var*/ ;
|
||||||
|
| ^~~~~~~~
|
||||||
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:62:11: 'cannot_split_genvar' has split_var metacomment but will not be split because it is not an aggregate type of bit nor logic
|
||||||
: ... In instance t.i_sub1
|
: ... In instance t.i_sub1
|
||||||
57 | genvar cannot_split_genvar /*verilator split_var*/ ;
|
62 | genvar cannot_split_genvar /*verilator split_var*/ ;
|
||||||
| ^~~~~~~~~~~~~~~~~~~
|
| ^~~~~~~~~~~~~~~~~~~
|
||||||
%Warning-SPLITVAR: t/t_split_var_1_bad.v:60:29: 'cannot_split' has split_var metacomment but will not be split because its bit range cannot be determined statically.
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:65:65: 'cannot_split' has split_var metacomment but will not be split because its bit range cannot be determined statically.
|
||||||
: ... In instance t.i_sub1
|
: ... In instance t.i_sub1
|
||||||
60 | rd_data = cannot_split[addr];
|
65 | logic [8:0] rd_tmp /*verilator split_var*/ = cannot_split[addr];
|
||||||
| ^
|
| ^
|
||||||
|
%Warning-SPLITVAR: t/t_split_var_1_bad.v:66:23: 'rd_tmp' has split_var metacomment but will not be split because its bit range cannot be determined statically.
|
||||||
|
: ... In instance t.i_sub1
|
||||||
|
66 | rd_data = rd_tmp[{3'b0, addr[0]}+:8];
|
||||||
|
| ^
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ module t();
|
||||||
|
|
||||||
logic [3:0] addr;
|
logic [3:0] addr;
|
||||||
logic [7:0] rd_data0, rd_data1, rd_data2;
|
logic [7:0] rd_data0, rd_data1, rd_data2;
|
||||||
|
logic [1:0] public_signal /*verilator public*/ /*verilator split_var*/;
|
||||||
|
|
||||||
sub0 i_sub0(.addr(addr), .rd_data(rd_data0));
|
sub0 i_sub0(.addr(addr), .rd_data(rd_data0));
|
||||||
sub1 i_sub1(.addr(addr), .rd_data(rd_data2));
|
sub1 i_sub1(.addr(addr), .rd_data(rd_data2));
|
||||||
|
|
@ -33,10 +34,14 @@ module t();
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
logic [7:0] loop_idx /*verilator split_var*/;
|
||||||
addr = 0;
|
addr = 0;
|
||||||
addr = 1;
|
addr = 1;
|
||||||
i_sub0.cannot_split1[0] = 0;
|
i_sub0.cannot_split1[0] = 0;
|
||||||
i_sub0.cannot_split1[1] = bad_func(addr, rd_data0);
|
i_sub0.cannot_split1[1] = bad_func(addr, rd_data0);
|
||||||
|
for (loop_idx = 0; loop_idx < 8'd4; loop_idx = loop_idx + 2) begin
|
||||||
|
addr += 1;
|
||||||
|
end
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -55,9 +60,11 @@ endmodule
|
||||||
|
|
||||||
module sub1(input [3:0]addr, output logic [7:0] rd_data);
|
module sub1(input [3:0]addr, output logic [7:0] rd_data);
|
||||||
genvar cannot_split_genvar /*verilator split_var*/;
|
genvar cannot_split_genvar /*verilator split_var*/;
|
||||||
logic [15:0] [7:0] cannot_split /*verilator split_var*/;
|
logic [15:0] [8:0] cannot_split /*verilator split_var*/;
|
||||||
always_comb
|
always_comb begin
|
||||||
rd_data = cannot_split[addr];
|
logic [8:0] rd_tmp /*verilator split_var*/ = cannot_split[addr];
|
||||||
|
rd_data = rd_tmp[{3'b0, addr[0]}+:8];
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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(simulator => 1);
|
||||||
|
|
||||||
|
compile(
|
||||||
|
verilator_flags2 => ['--stats'],
|
||||||
|
);
|
||||||
|
|
||||||
|
execute(
|
||||||
|
check_finished => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
file_grep($Self->{stats}, qr/SplitVar,\s+Split packed variables\s+(\d+)/i, 0);
|
||||||
|
file_grep($Self->{stats}, qr/SplitVar,\s+Split unpacked arrays\s+(\d+)/i, 3);
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Yutetsu TAKATSUKASA.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
`begin_keywords "VAMS-2.3"
|
||||||
|
|
||||||
|
module t (/*autoarg*/
|
||||||
|
// Inputs
|
||||||
|
clk
|
||||||
|
);
|
||||||
|
|
||||||
|
input clk;
|
||||||
|
|
||||||
|
integer cyc=0;
|
||||||
|
|
||||||
|
real vin[0:1] /*verilator split_var*/;
|
||||||
|
wreal vout[0:1] /*verilator split_var*/;
|
||||||
|
swap i_swap(.in0(vin[0]), .in1(vin[1]), .out0(vout[0]), .out1(vout[1]));
|
||||||
|
|
||||||
|
always @ (posedge clk) begin
|
||||||
|
cyc <= cyc + 1;
|
||||||
|
if (cyc==0) begin
|
||||||
|
// Setup
|
||||||
|
vin[0] = 1.0;
|
||||||
|
vin[1] = 2.0;
|
||||||
|
end
|
||||||
|
else if (cyc==2) begin
|
||||||
|
vin[0] = 3.0;
|
||||||
|
vin[1] = 4.0;
|
||||||
|
end
|
||||||
|
else if (cyc==3) begin
|
||||||
|
if (vout[0] == vin[1] && vout[1] == vin[0]) begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end else begin
|
||||||
|
$write("Mismatch %f %f\n", vout[0], vout[1]);
|
||||||
|
$stop;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
module swap
|
||||||
|
(input wreal in0, in1,
|
||||||
|
output wreal out0, out1);
|
||||||
|
wreal tmp[0:1] /* verilator split_var*/;
|
||||||
|
assign tmp[0] = in0;
|
||||||
|
assign tmp[1] = in1;
|
||||||
|
assign out0 = tmp[1];
|
||||||
|
assign out1 = tmp[0];
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue