File: t_assign_slice_overflow.v

package info (click to toggle)
verilator 5.038-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 162,552 kB
  • sloc: cpp: 139,204; python: 20,931; ansic: 10,222; yacc: 6,000; lex: 1,925; makefile: 1,260; sh: 494; perl: 282; fortran: 22
file content (179 lines) | stat: -rw-r--r-- 7,549 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// DESCRIPTION: Test that slice assignment overflows are handled correctly,
// i.e. that if you assign to a slice such that some of the bits you assign to
// do not actually exist, that those bits get correctly discarded.
// Issue #2803 existed in a number number of different codepaths in
// verilated.h and V3Expand.cpp.  This test should cover all of these cases
// when run both with and without the -Ox flag to verilator.
//  - Select offset constant, insert IData into CData
//  - Select offset constant, insert IData into SData
//  - Select offset constant, insert IData into IData
//  - Select offset constant, insert QData into QData
//  - Select offset constant, insert IData into WData within a word
//  - Select offset constant, insert IData into WData crossing a word boundary
//  - Select offset constant, insert IData into WData whole word insertion
//  - Select offset constant, insert QData into WData
//  - Select offset constant, insert WData into WData, several whole words
//  - Select offset constant, insert WData into WData, starting at word-offset
//  - Select offset constant, insert WData into WData, all other cases
//  - Select offset is non-constant, destination is wide, bit-select width == 1
//  - Select offset is non-constant, destination is wide, bit-select width != 1
//  - Select offset is non-constant, destination is narrow
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2021 by David Turner.
// SPDX-License-Identifier: CC0-1.0

module t(/*AUTOARG*/
   // Inputs
   clk
   );
   input clk;

   integer cyc = 0;
   // Non-constant offsets
   reg        varoffset1;
   reg [6:0]  varoffset2;
   reg [6:0]  varoffset3;

   // Destinations for variable-offset assignments
   reg [69:0] dstwide1;
   reg [69:0] dstwide2;
   reg [1:0] dstnarrow;

   // Constant offsets
   reg [6:0] constoffset;

   // Destinations for constant-offset assignments
   reg [2:0]  dst_cdata;
   reg [11:0] dst_sdata;
   reg [29:0] dst_idata;
   reg [59:0] dst_qdata;
   reg [69:0] dst_wdata1; // assign idata within word
   reg [69:0] dst_wdata2; // assign idata crossing word boundary
   reg [69:0] dst_wdata3; // assign idata corresponding to whole word
   reg [69:0] dst_wdata4; // assign qdata
   reg [69:0] dst_wdata5; // assign wdata corresponding to several whole words
   reg [69:0] dst_wdata6; // assign wdata starting at word-offset
   reg [69:0] dst_wdata7; // assign wdata unaligned

   always @(*) begin
      // Non-constant select offset, destination narrow
      dstnarrow = 2'd0;
      dstnarrow[varoffset1 +: 2'd2] = 2'd2;

      // Non-constant select offset, destination wide, width == 1
      dstwide1 = 70'd0;
      dstwide1[varoffset2 +: 1'd1] = 1'd1;

      // Non-constant select offset, destination wide, width != 1
      dstwide2 = 70'd0;
      dstwide2[varoffset3 +: 2'd2] = 2'd2;

      // Constant offset, IData into CData
      constoffset = 7'd2;
      dst_cdata = 3'd0;
      dst_cdata[constoffset[0 +: 2] +: 3'd3] = 3'd6;

      // Constant offset, IData into SData
      constoffset = 7'd11;
      dst_sdata = 12'd0;
      dst_sdata[constoffset[0 +: 4] +: 2'd2] = 2'd2;

      // Constant offset, IData into IData
      constoffset = 7'd29;
      dst_idata = 30'd0;
      dst_idata[constoffset[0 +: 5] +: 2'd2] = 2'd2;

      // Constant offset, QData into QData
      constoffset = 7'd59;
      dst_qdata = 60'd0;
      dst_qdata[constoffset[0 +: 6] +: 2'd2] = 2'd2;

      // Constant offset, IData into WData within word
      constoffset = 7'd69;
      dst_wdata1 = 70'd0;
      dst_wdata1[constoffset +: 2'd2] = 2'd2;

      // Constant offset, IData into WData crossing word boundary
      constoffset = 7'd61;
      dst_wdata2 = 70'd0;
      dst_wdata2[constoffset +: 4'd10] = 10'd1 << 4'd9;

      // Constant offset, IData into WData replacing a whole word
      constoffset = 7'd64;
      dst_wdata3 = 70'd0;
      dst_wdata3[constoffset +: 6'd32] = 32'd1 << 3'd6;

      // Constant offset, QData into WData
      constoffset = 7'd31;
      dst_wdata4 = 70'd0;
      dst_wdata4[constoffset +: 7'd40] = 40'd1 << 7'd39;

      // Constant offset, WData into WData replacing whole words
      constoffset = 7'd32;
      dst_wdata5 = 70'd0;
      dst_wdata5[constoffset +: 7'd64] = 64'd1 << 7'd38;

      // Constant offset, WData into WData offset word aligned
      constoffset = 7'd32;
      dst_wdata6 = 70'd0;
      dst_wdata6[constoffset +: 7'd40] = 40'd1 << 7'd38;

      // Constant offset, WData into WData unaligned
      constoffset = 7'd1;
      dst_wdata7 = 70'd0;
      dst_wdata7[constoffset +: 7'd70] = 70'd1 << 7'd69;
   end

   // Test loop
   always @ (posedge clk) begin
      // State machine to avoid verilator constant-folding offset
      if (cyc == 0) begin
         // Initialisation
         varoffset1 <= 1'd0;
         varoffset2 <= 7'd0;
         varoffset3 <= 7'd0;
      end else if (cyc == 1) begin
         // Variable offsets set here to avoid verilator constant folding
         varoffset1 <= 1'd1;
         varoffset2 <= 7'd70;
         varoffset3 <= 7'd69;
      end else if (cyc == 2) begin
         // Check all destinations are 0
         $write("dstwide1   = %23d, downshifted = %23d\n", dstwide1, dstwide1 >> 1);
         $write("dstwide2   = %23d, downshifted = %23d\n", dstwide2, dstwide2 >> 1);
         $write("dstnarrow  = %23d, downshifted = %23d\n", dstnarrow, dstnarrow >> 1);
         $write("dst_cdata  = %23d, downshifted = %23d\n", dst_cdata, dst_cdata >> 1);
         $write("dst_sdata  = %23d, downshifted = %23d\n", dst_sdata, dst_sdata >> 1);
         $write("dst_idata  = %23d, downshifted = %23d\n", dst_idata, dst_idata >> 1);
         $write("dst_qdata  = %23d, downshifted = %23d\n", dst_qdata, dst_qdata >> 1);
         $write("dst_wdata1 = %23d, downshifted = %23d\n", dst_wdata1, dst_wdata1 >> 1);
         $write("dst_wdata2 = %23d, downshifted = %23d\n", dst_wdata2, dst_wdata2 >> 1);
         $write("dst_wdata3 = %23d, downshifted = %23d\n", dst_wdata3, dst_wdata3 >> 1);
         $write("dst_wdata4 = %23d, downshifted = %23d\n", dst_wdata4, dst_wdata4 >> 1);
         $write("dst_wdata5 = %23d, downshifted = %23d\n", dst_wdata5, dst_wdata5 >> 1);
         $write("dst_wdata6 = %23d, downshifted = %23d\n", dst_wdata6, dst_wdata6 >> 1);
         $write("dst_wdata7 = %23d, downshifted = %23d\n", dst_wdata7, dst_wdata7 >> 1);

         if (dstwide1 !== 70'd0 || (dstwide1 >> 1) !== 70'd0) $stop;
         if (dstwide2 !== 70'd0 || (dstwide2 >> 1) !== 70'd0) $stop;
         if (dstnarrow !== 2'd0 || (dstnarrow >> 1) !== 2'd0) $stop;
         if (dst_cdata !== 3'd0 || (dst_cdata >> 1) !== 3'd0) $stop;
         if (dst_sdata !== 12'd0 || (dst_sdata >> 1) !== 12'd0) $stop;
         if (dst_idata !== 30'd0 || (dst_idata >> 1) !== 30'd0) $stop;
         if (dst_qdata !== 60'd0 || (dst_qdata >> 1) !== 60'd0) $stop;
         if (dst_wdata1 !== 70'd0 || (dst_wdata1 >> 1) !== 70'd0) $stop;
         if (dst_wdata2 !== 70'd0 || (dst_wdata2 >> 1) !== 70'd0) $stop;
         if (dst_wdata3 !== 70'd0 || (dst_wdata3 >> 1) !== 70'd0) $stop;
         if (dst_wdata4 !== 70'd0 || (dst_wdata4 >> 1) !== 70'd0) $stop;
         if (dst_wdata5 !== 70'd0 || (dst_wdata5 >> 1) !== 70'd0) $stop;
         if (dst_wdata6 !== 70'd0 || (dst_wdata6 >> 1) !== 70'd0) $stop;
         if (dst_wdata7 !== 70'd0 || (dst_wdata7 >> 1) !== 70'd0) $stop;
      end else begin
         $write("*-* All Finished *-*\n");
         $finish;
      end

      cyc <= cyc + 1;
   end
endmodule