File: t_randsequence.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 (218 lines) | stat: -rw-r--r-- 6,937 bytes parent folder | download | duplicates (2)
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// DESCRIPTION: Verilator: Verilog Test module
//
// Copyright 2023 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

`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d:  got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
`define check_range(gotv,minv,maxv) do if ((gotv) < (minv) || (gotv) > (maxv)) begin $write("%%Error: %s:%0d:  got=%0d exp=%0d-%0d\n", `__FILE__,`__LINE__, (gotv), (minv), (maxv)); `stop; end while(0);
`define check_within_30_percent(gotv,val) `check_range((gotv), (val) * 70 / 100, (val) * 130 / 100)

module t(/*AUTOARG*/);

   localparam int COUNT = 1000;

   int seq;
   int counts[8];

   function automatic int sfunc();
      int o = 2;
      randsequence(main)
         main : one;
         one : { o = 1; };
      endsequence
      return o;
   endfunction

   task prep();
      for (int i = 0; i < COUNT; ++i) counts[i] = 0;
   endtask

   initial begin;
      if (sfunc() != 1) $stop;

      // simple
      prep();
      seq = 0;
      randsequence(main)
         main: one two three;
         two: { `checkd(seq, 1); seq = 2; };
         one: { `checkd(seq, 0); seq = 1; };
         three: { `checkd(seq, 2); seq = 3; };
      endsequence
      `checkd(seq, 3);

      // simple unnamed
      prep();
      seq = 0;
      randsequence()
         unnamed: { seq = 2; };
      endsequence
      `checkd(seq, 2);

      // empty block
      prep();
      randsequence()
         unnamed: { };
      endsequence

      // weight
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         randsequence(main)
            main: one | two | three := 2;
            one: { ++counts[0]; };
            two: { ++counts[1]; };
            three: { ++counts[2]; };
         endsequence
      end
      `check_within_30_percent(counts[0], COUNT * 1 / 4);
      `check_within_30_percent(counts[1], COUNT * 1 / 4);
      `check_within_30_percent(counts[2], COUNT * 2 / 4);

      // case
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         randsequence(main)
            main: one_if;
            one_if: if (i % 10 == 0) count_1 else most;
            count_1: { ++counts[1]; };
            count_2: { ++counts[2]; };
            count_3: { ++counts[3]; };
            count_4: { ++counts[4]; };
            bad: { $stop; };
            most: case (i % 10)
                    0: bad;
                    1, 2: count_2;
                    3, 4, 5: count_3;
                    default: count_4;
                  endcase;
         endsequence
      end
      `check_within_30_percent(counts[1], COUNT * 1 / 10);
      `check_within_30_percent(counts[2], COUNT * 2 / 10);
      `check_within_30_percent(counts[3], COUNT * 3 / 10);
      `check_within_30_percent(counts[4], COUNT * 4 / 10);

      // case - different default
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         randsequence(main)
            main: one_if;
            one_if: if (i % 10 == 0) count_1 else most;
            count_1: { ++counts[1]; };
            count_2: { ++counts[2]; };
            count_3: { ++counts[3]; };
            count_4: { ++counts[4]; };
            bad: { $stop; };
            most: case (i % 10)
                    0: bad;
                    1, 2: count_2;
                    3, 4, 5: count_3;
                    default count_4;  // No :
                  endcase;
         endsequence
      end
      `check_within_30_percent(counts[1], COUNT * 1 / 10);
      `check_within_30_percent(counts[2], COUNT * 2 / 10);
      `check_within_30_percent(counts[3], COUNT * 3 / 10);
      `check_within_30_percent(counts[4], COUNT * 4 / 10);

      // repeat
      prep();
      randsequence(main)
         main: repeat(10) count_1;
         count_1: { ++counts[1]; };
      endsequence
      `checkd(counts[1], 10);

      // rand join
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         randsequence(main)
            main: rand join count_1 count_2;
            count_1: { ++counts[1]; };
            count_2: { ++counts[2]; };
         endsequence
      end
      `check_within_30_percent(counts[1], COUNT * 1 / 1);
      `check_within_30_percent(counts[2], COUNT * 1 / 1);

      // rand join weight (TODO weight not tested yet)
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         randsequence(main)
            main: rand join (1.0) count_1 count_2;
            count_1: { ++counts[1]; };
            count_2: { ++counts[2]; };
         endsequence
         randsequence(main)
            main: rand join (0.0) count_3 count_4;
            count_3: { ++counts[3]; };
            count_4: { ++counts[4]; };
         endsequence
      end
      `check_within_30_percent(counts[1], COUNT * 1 / 1);
      `check_within_30_percent(counts[2], COUNT * 1 / 1);
      `check_within_30_percent(counts[3], COUNT * 1 / 1);
      `check_within_30_percent(counts[4], COUNT * 1 / 1);

      // break
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         automatic bit fiftyfifty = i[0];
         randsequence(main)
            main: count_1 check count_2;
            check: count_3 { if (fiftyfifty) break; } count_4;
            count_1: { ++counts[1]; };
            count_2: { ++counts[2]; };
            count_3: { ++counts[3]; };
            count_4: { ++counts[4]; };
         endsequence
      end
      `checkd(counts[1], COUNT * 1 / 1);
      `checkd(counts[2], COUNT * 1 / 2);  // break
      `checkd(counts[3], COUNT * 1 / 1);
      `checkd(counts[4], COUNT * 1 / 2);  // break or return

      // return
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         automatic bit fiftyfifty = i[0];
         randsequence(main)
            main: count_1 check count_2;
            check: count_3 { if (fiftyfifty) return; } count_4;
            count_1: { ++counts[1]; };
            count_2: { ++counts[2]; };
            count_3: { ++counts[3]; };
            count_4: { ++counts[4]; };
         endsequence
      end
      `checkd(counts[1], COUNT * 1 / 1);
      `checkd(counts[2], COUNT * 1 / 1);  // return
      `checkd(counts[3], COUNT * 1 / 1);
      `checkd(counts[4], COUNT * 1 / 2);  // break or return

      // functions
      prep();
      for (int i = 0; i < COUNT; ++i) begin
         randsequence(main)
            main: f_1 f_2 f_3;
            f_1 : func(10);
            f_2 : func(20);
            f_3 : fnoarg;
            void func(int n) : { counts[1] += n; };
            void fnoarg : { ++counts[2]; };
         endsequence
      end
      `checkd(counts[1], COUNT * (10 + 20));
      `checkd(counts[2], COUNT * 1 / 1);  // return

      $write("*-* All Finished *-*\n");
      $finish;
   end

endmodule