verilator/test_regress/t/t_queue_void_ops.v
2022-09-27 18:42:03 -04:00

197 lines
6.2 KiB
Systemverilog

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