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
|
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t
(/*AUTOARG*/
// Inputs
clk
);
input clk;
int cyc = 0;
// Test for https://github.com/verilator/verilator/issues/3364
// Make sure all SV queue API is supported and verilator can generate
// compile-able C++ models for it.
// simple queue
logic [31:0] my_int_queue [$];
// On the functions and tasks, the my_int_queue.pop_[front|back]() call will
// have nodep->firstAbovep() != nullptr. Because the pop_front or pop_back is
// the first node on the "list".
// To fix this, V3Width.cpp will not use firstAbovep(), and instead us
// isStandalongStmt() -- which checks if the pop_front or pop_back is
// 2nd or later, or if it's first in the list that it's in a "block" of code.
// For functions/tasks, that is checked with:
// VN_IS(backp(), NodeFTask)=True, so even though
function automatic void f_pop_back__my_int_queue();
void'(my_int_queue.pop_back());
endfunction : f_pop_back__my_int_queue
function automatic void f_pop_front__my_int_queue();
void'(my_int_queue.pop_front());
endfunction : f_pop_front__my_int_queue
task automatic t_pop_back__my_int_queue();
void'(my_int_queue.pop_back());
endtask : t_pop_back__my_int_queue
task automatic t_pop_front__my_int_queue();
void'(my_int_queue.pop_front());
endtask : t_pop_front__my_int_queue
task automatic do_random_queue_operation();
bit [7:0] rand_op;
int rand_index;
logic [31:0] item;
rand_op = 8'($urandom_range(32, 0));
case(rand_op)
8'd0: ; // nop
// pushes (2x of these)
8'd1, 8'd2: my_int_queue.push_back($urandom);
8'd3, 8'd4: my_int_queue.push_front($urandom);
// delete:
8'd5: my_int_queue.delete();
// insert(index, item):
8'd6: begin
rand_index = $urandom_range(my_int_queue.size());
my_int_queue.insert(rand_index, item);
end
// shuffle
8'd7: my_int_queue.shuffle();
// Various pops for rand_op >= 8:
// pops to var
// V3Width debug -- firstAbovep()=ASSIGN (which I guess does the ; for us
// so we don't need the queue op to
// do it.)
// isStandalongStmt() will ignore ASSIGN, return false (NodeAssign is
// child of AstNodeStmt)
8'd8: if (my_int_queue.size() > 0) item = my_int_queue.pop_front();
8'd9: if (my_int_queue.size() > 0) item = my_int_queue.pop_back();
// pops to the void
// V3Width debug -- firstAbovep()=IF
// This is fixed with isStandalongStmt() -- VN_IS(backp(), NodeIf)=True
8'd10: if (my_int_queue.size() > 0) void'(my_int_queue.pop_front());
8'd11: if (my_int_queue.size() > 0) void'(my_int_queue.pop_back());
// pop result to the lhs of a condition, and do something with it.
8'd12:
if (my_int_queue.size() > 0)
// V3Width debug -- firstAbovep()=LTE (good we don't want a ; here)
if (my_int_queue.pop_front() <= 2022)
my_int_queue.push_front(3022); // living in the year 3022.
// pop result to the rhs of a condition, and do something with it.
8'd13:
if (my_int_queue.size() > 0)
// V3Width debug -- firstAbovep()=GT (good we don't want a ; here)
if (4022 > my_int_queue.pop_front())
my_int_queue.push_front(3023); // living in the year 3023.
// pops to the void after yet another case:
// V3Width debug -- firstAbovep()=CASEITEM (not a nullptr)
// This is fixed with isStandalongStmt() -- VN_IS(backp(), CaseItem)=True
8'd14:
case (my_int_queue.size() > 0)
0: ;
1: void'(my_int_queue.pop_front());
default: ;
endcase // case (my_int_queue.size() > 0)
// V3Width debug -- firstAbovep()=CASEITEM (not a nullptr)
// backp()->nextp()=CASEITEM (different one)
// This is fixed with isStandalongStmt() -- VN_IS(backp(), CaseItem)=True
8'd15:
case (my_int_queue.size() > 0)
0: ;
1: void'(my_int_queue.pop_back());
default;
endcase // case (my_int_queue.size() > 0)
// pops in a function or task
8'd16: if (my_int_queue.size() > 0) f_pop_back__my_int_queue();
8'd17: if (my_int_queue.size() > 0) f_pop_front__my_int_queue();
8'd18: if (my_int_queue.size() > 0) t_pop_back__my_int_queue();
8'd19: if (my_int_queue.size() > 0) t_pop_front__my_int_queue();
// But what if we put some dummy code before the pop_back() or pop_front():
8'd20: begin
if (my_int_queue.size() > 0) begin
; // dummy line
// V3Width debug -- firstAbovep()=BEGIN (is not nullptr).
// This is fixed with isStandalongStmt() -- VN_IS(backp(), NodeIf)=True
void'(my_int_queue.pop_back());
end
end
8'd21: begin
automatic int temp_int = 0;
if (my_int_queue.size() > 0) begin
temp_int = 5; // dummy line
// V3Width debug -- firstAbovep()=nullptr (good)
void'(my_int_queue.pop_back());
end
end
8'd22: begin
if (my_int_queue.size() > 0) begin
automatic int some_temp_dummy_int;
some_temp_dummy_int = 42;
// V3Width debug -- firstAbovep()=nullptr (good)
void'(my_int_queue.pop_back());
end
end
8'd23: begin
if (my_int_queue.size() > 0) begin
// no dummy here, just a 'begin' helper before it.
// V3Width debug -- firstAbovep()=BEGIN (is not nullptr).
// This is fixed with isStandalongStmt() -- VN_IS(backp(), NodeIf)=True
void'(my_int_queue.pop_back());
end
end
// What about an if of something else, followed by a pop_front?
8'd24: begin
automatic int temp_int = 0;
if (my_int_queue.size() == 0) begin // dummy
temp_int = 1000;
end
void'(my_int_queue.pop_front()); // firstAbovep() should be nullptr here.
end
default: ; // nop
endcase // case (rand_op)
endtask : do_random_queue_operation
always @ (posedge clk) begin : main
cyc <= cyc + 1;
do_random_queue_operation();
if (cyc > 100) begin
$write("*-* All Finished *-*\n");
$finish();
end
end
endmodule : t
|