// 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