f382ee70da
If user compiles without +define+DEBUG but then requests +vcdfile at simulation time, that request would be silently ignored. This changes it to a fatal error. It's good philosophy to treat plusargs like +vcdfile as commands, not suggestions, and die immediately if they cannot be honored, instead of silently ignoring them. Otherwise the user sits through the entire simulation and then is left scratching his head wondering where his waveforms are.
137 lines
3.1 KiB
Verilog
137 lines
3.1 KiB
Verilog
// See LICENSE for license details.
|
|
|
|
`ifndef RESET_DELAY
|
|
`define RESET_DELAY 777.7
|
|
`endif
|
|
|
|
module TestDriver;
|
|
|
|
reg clock = 1'b0;
|
|
reg reset = 1'b1;
|
|
|
|
always #(`CLOCK_PERIOD/2.0) clock = ~clock;
|
|
initial #(`RESET_DELAY) reset = 0;
|
|
|
|
// Read input arguments and initialize
|
|
reg verbose = 1'b0;
|
|
wire printf_cond = verbose && !reset;
|
|
reg [63:0] max_cycles = 0;
|
|
reg [63:0] trace_count = 0;
|
|
reg [1023:0] vcdplusfile = 0;
|
|
reg [1023:0] vcdfile = 0;
|
|
int unsigned rand_value;
|
|
initial
|
|
begin
|
|
void'($value$plusargs("max-cycles=%d", max_cycles));
|
|
verbose = $test$plusargs("verbose");
|
|
|
|
// do not delete the lines below.
|
|
// $random function needs to be called with the seed once to affect all
|
|
// the downstream $random functions within the Chisel-generated Verilog
|
|
// code.
|
|
// $urandom is seeded via cmdline (+ntb_random_seed in VCS) but that
|
|
// doesn't seed $random.
|
|
rand_value = $urandom;
|
|
rand_value = $random(rand_value);
|
|
if (verbose) begin
|
|
`ifdef VCS
|
|
$fdisplay(stderr, "testing $random %0x seed %d", rand_value, unsigned'($get_initial_random_seed));
|
|
`else
|
|
$fdisplay(stderr, "testing $random %0x", rand_value);
|
|
`endif
|
|
end
|
|
|
|
`ifdef DEBUG
|
|
|
|
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
|
|
begin
|
|
`ifdef VCS
|
|
$vcdplusfile(vcdplusfile);
|
|
$vcdpluson(0);
|
|
$vcdplusmemon(0);
|
|
`else
|
|
$fdisplay(stderr, "Error: +vcdplusfile is VCS-only; use +vcdfile instead");
|
|
$fatal;
|
|
`endif
|
|
end
|
|
|
|
if ($value$plusargs("vcdfile=%s", vcdfile))
|
|
begin
|
|
$dumpfile(vcdfile);
|
|
$dumpvars(0, testHarness);
|
|
$dumpon;
|
|
end
|
|
`ifdef VCS
|
|
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
|
|
`else
|
|
`define VCDPLUSCLOSE $dumpoff;
|
|
`endif
|
|
`else
|
|
// No +define+DEBUG
|
|
`define VCDPLUSCLOSE
|
|
|
|
if ($test$plusargs("vcdplusfile=") || $test$plusargs("vcdfile="))
|
|
begin
|
|
$fdisplay(stderr, "Error: +vcdfile or +vcdplusfile requested but compile did not have +define+DEBUG enabled");
|
|
$fatal;
|
|
end
|
|
|
|
`endif
|
|
end
|
|
|
|
`ifdef TESTBENCH_IN_UVM
|
|
// UVM library has its own way to manage end-of-simulation.
|
|
// A UVM-based testbench will raise an objection, watch this signal until this goes 1, then drop the objection.
|
|
reg finish_request = 1'b0;
|
|
`endif
|
|
reg [255:0] reason = "";
|
|
reg failure = 1'b0;
|
|
wire success;
|
|
integer stderr = 32'h80000002;
|
|
always @(posedge clock)
|
|
begin
|
|
`ifdef GATE_LEVEL
|
|
if (verbose)
|
|
begin
|
|
$fdisplay(stderr, "C: %10d", trace_count);
|
|
end
|
|
`endif
|
|
|
|
trace_count = trace_count + 1;
|
|
if (!reset)
|
|
begin
|
|
if (max_cycles > 0 && trace_count > max_cycles)
|
|
begin
|
|
reason = " (timeout)";
|
|
failure = 1'b1;
|
|
end
|
|
|
|
if (failure)
|
|
begin
|
|
$fdisplay(stderr, "*** FAILED ***%s after %d simulation cycles", reason, trace_count);
|
|
`VCDPLUSCLOSE
|
|
$fatal;
|
|
end
|
|
|
|
if (success)
|
|
begin
|
|
if (verbose)
|
|
$fdisplay(stderr, "Completed after %d simulation cycles", trace_count);
|
|
`VCDPLUSCLOSE
|
|
`ifdef TESTBENCH_IN_UVM
|
|
finish_request = 1;
|
|
`else
|
|
$finish;
|
|
`endif
|
|
end
|
|
end
|
|
end
|
|
|
|
TestHarness testHarness(
|
|
.clock(clock),
|
|
.reset(reset),
|
|
.io_success(success)
|
|
);
|
|
|
|
endmodule
|