forked from github/verilator
197 lines
6.2 KiB
Systemverilog
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
|