Write test harness in Chisel
This is an unavoidably invasive commit, because it affects the unit tests (which formerly exited using stop()), the test harness Verilog generator (since it is no longer necessary), and the DRAM model (since it is no longer connected). However, this should substantially reduce the effort of building test harnesses in the future, since manual or semi-automatic Verilog writing should no longer be necessary. Furthermore, there is now very little duplication of effort between the Verilator and VCS test harnesses. This commit removes support for DRAMsim, which is a bit of an unfortunate consequence. The main blocker is the lack of Verilog parameterization for BlackBox. It would be straightforward to revive DRAMsim once support for that feature is added to Chisel and FIRRTL. But that might not even be necessary, as we move towards synthesizable DRAM models and FAME-1 transformations.
This commit is contained in:
80
vsrc/SimDTM.v
Normal file
80
vsrc/SimDTM.v
Normal file
@ -0,0 +1,80 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
import "DPI-C" function int debug_tick
|
||||
(
|
||||
output bit debug_req_valid,
|
||||
input bit debug_req_ready,
|
||||
output int debug_req_bits_addr,
|
||||
output int debug_req_bits_op,
|
||||
output longint debug_req_bits_data,
|
||||
|
||||
input bit debug_resp_valid,
|
||||
output bit debug_resp_ready,
|
||||
input int debug_resp_bits_resp,
|
||||
input longint debug_resp_bits_data
|
||||
);
|
||||
|
||||
module SimDTM(
|
||||
input clk,
|
||||
input reset,
|
||||
|
||||
output debug_req_valid,
|
||||
input debug_req_ready,
|
||||
output [ 4:0] debug_req_bits_addr,
|
||||
output [ 1:0] debug_req_bits_op,
|
||||
output [33:0] debug_req_bits_data,
|
||||
|
||||
input debug_resp_valid,
|
||||
output debug_resp_ready,
|
||||
input [ 1:0] debug_resp_bits_resp,
|
||||
input [33:0] debug_resp_bits_data,
|
||||
|
||||
output [31:0] exit
|
||||
);
|
||||
|
||||
bit r_reset;
|
||||
|
||||
wire #0.1 __debug_req_ready = debug_req_ready;
|
||||
wire #0.1 __debug_resp_valid = debug_resp_valid;
|
||||
wire [31:0] #0.1 __debug_resp_bits_resp = {30'b0, debug_resp_bits_resp};
|
||||
wire [63:0] #0.1 __debug_resp_bits_data = {30'b0, debug_resp_bits_data};
|
||||
|
||||
bit __debug_req_valid;
|
||||
int __debug_req_bits_addr;
|
||||
int __debug_req_bits_op;
|
||||
longint __debug_req_bits_data;
|
||||
bit __debug_resp_ready;
|
||||
int __exit;
|
||||
|
||||
assign #0.1 debug_req_valid = __debug_req_valid;
|
||||
assign #0.1 debug_req_bits_addr = __debug_req_bits_addr[4:0];
|
||||
assign #0.1 debug_req_bits_op = __debug_req_bits_op[1:0];
|
||||
assign #0.1 debug_req_bits_data = __debug_req_bits_data[33:0];
|
||||
assign #0.1 debug_resp_ready = __debug_resp_ready;
|
||||
assign #0.1 exit = __exit;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
r_reset <= reset;
|
||||
if (reset || r_reset)
|
||||
begin
|
||||
__debug_req_valid = 0;
|
||||
__debug_resp_ready = 0;
|
||||
__exit = 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
__exit = debug_tick(
|
||||
__debug_req_valid,
|
||||
__debug_req_ready,
|
||||
__debug_req_bits_addr,
|
||||
__debug_req_bits_op,
|
||||
__debug_req_bits_data,
|
||||
__debug_resp_valid,
|
||||
__debug_resp_ready,
|
||||
__debug_resp_bits_resp,
|
||||
__debug_resp_bits_data
|
||||
);
|
||||
end
|
||||
end
|
||||
endmodule
|
90
vsrc/TestDriver.v
Normal file
90
vsrc/TestDriver.v
Normal file
@ -0,0 +1,90 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
module TestDriver;
|
||||
|
||||
reg clk = 1'b0;
|
||||
reg reset = 1'b1;
|
||||
|
||||
always #`CLOCK_PERIOD clk = ~clk;
|
||||
initial #777.7 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;
|
||||
initial
|
||||
begin
|
||||
$value$plusargs("max-cycles=%d", max_cycles);
|
||||
verbose = $test$plusargs("verbose");
|
||||
`ifdef DEBUG
|
||||
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
|
||||
begin
|
||||
$vcdplusfile(vcdplusfile);
|
||||
$vcdpluson(0);
|
||||
$vcdplusmemon(0);
|
||||
end
|
||||
|
||||
if ($value$plusargs("vcdfile=%s", vcdfile))
|
||||
begin
|
||||
$dumpfile(vcdfile);
|
||||
$dumpvars(0, testHarness);
|
||||
$dumpon;
|
||||
end
|
||||
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
|
||||
`else
|
||||
`define VCDPLUSCLOSE
|
||||
`endif
|
||||
end
|
||||
|
||||
reg [255:0] reason = "";
|
||||
reg failure = 1'b0;
|
||||
wire success;
|
||||
integer stderr = 32'h80000002;
|
||||
always @(posedge clk)
|
||||
begin
|
||||
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
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
trace_count = trace_count + 1;
|
||||
`ifdef GATE_LEVEL
|
||||
if (verbose)
|
||||
begin
|
||||
$fdisplay(stderr, "C: %10d", trace_count-1);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
|
||||
TestHarness testHarness(
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.io_success(success)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1,183 +0,0 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
extern "A" void debug_tick
|
||||
(
|
||||
output reg debug_req_valid,
|
||||
input reg debug_req_ready,
|
||||
output reg [ 4:0] debug_req_bits_addr,
|
||||
output reg [ 1:0] debug_req_bits_op,
|
||||
output reg [33:0] debug_req_bits_data,
|
||||
|
||||
input reg debug_resp_valid,
|
||||
output reg debug_resp_ready,
|
||||
input reg [ 1:0] debug_resp_bits_resp,
|
||||
input reg [33:0] debug_resp_bits_data,
|
||||
|
||||
output reg [31:0] exit
|
||||
);
|
||||
|
||||
extern "A" void memory_tick
|
||||
(
|
||||
input reg [31:0] channel,
|
||||
|
||||
input reg ar_valid,
|
||||
output reg ar_ready,
|
||||
input reg [`MEM_ADDR_BITS-1:0] ar_addr,
|
||||
input reg [`MEM_ID_BITS-1:0] ar_id,
|
||||
input reg [2:0] ar_size,
|
||||
input reg [7:0] ar_len,
|
||||
|
||||
input reg aw_valid,
|
||||
output reg aw_ready,
|
||||
input reg [`MEM_ADDR_BITS-1:0] aw_addr,
|
||||
input reg [`MEM_ID_BITS-1:0] aw_id,
|
||||
input reg [2:0] aw_size,
|
||||
input reg [7:0] aw_len,
|
||||
|
||||
input reg w_valid,
|
||||
output reg w_ready,
|
||||
input reg [`MEM_STRB_BITS-1:0] w_strb,
|
||||
input reg [`MEM_DATA_BITS-1:0] w_data,
|
||||
input reg w_last,
|
||||
|
||||
output reg r_valid,
|
||||
input reg r_ready,
|
||||
output reg [1:0] r_resp,
|
||||
output reg [`MEM_ID_BITS-1:0] r_id,
|
||||
output reg [`MEM_DATA_BITS-1:0] r_data,
|
||||
output reg r_last,
|
||||
|
||||
output reg b_valid,
|
||||
input reg b_ready,
|
||||
output reg [1:0] b_resp,
|
||||
output reg [`MEM_ID_BITS-1:0] b_id
|
||||
);
|
||||
|
||||
module rocketTestHarness;
|
||||
|
||||
reg [31:0] seed;
|
||||
initial seed = $get_initial_random_seed();
|
||||
|
||||
//-----------------------------------------------
|
||||
// Instantiate the processor
|
||||
|
||||
reg clk = 1'b0;
|
||||
reg reset = 1'b1;
|
||||
reg r_reset = 1'b1;
|
||||
reg start = 1'b0;
|
||||
|
||||
always #`CLOCK_PERIOD clk = ~clk;
|
||||
|
||||
reg [ 31:0] n_mem_channel = `N_MEM_CHANNELS;
|
||||
reg [ 31:0] mem_width = `MEM_DATA_BITS;
|
||||
reg [ 63:0] max_cycles = 0;
|
||||
reg [ 63:0] trace_count = 0;
|
||||
reg [1023:0] loadmem = 0;
|
||||
reg [1023:0] vcdplusfile = 0;
|
||||
reg [1023:0] vcdfile = 0;
|
||||
reg verbose = 0;
|
||||
wire printf_cond = verbose && !reset;
|
||||
integer stderr = 32'h80000002;
|
||||
|
||||
`include `TBVFRAG
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
r_reset <= reset;
|
||||
end
|
||||
|
||||
reg [31:0] exit = 0;
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (reset || r_reset)
|
||||
begin
|
||||
debug_req_valid <= 0;
|
||||
debug_resp_ready <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
debug_tick
|
||||
(
|
||||
debug_req_valid,
|
||||
debug_req_ready,
|
||||
debug_req_bits_addr,
|
||||
debug_req_bits_op,
|
||||
debug_req_bits_data,
|
||||
debug_resp_valid,
|
||||
debug_resp_ready,
|
||||
debug_resp_bits_resp,
|
||||
debug_resp_bits_data,
|
||||
exit
|
||||
);
|
||||
end
|
||||
end
|
||||
|
||||
//-----------------------------------------------
|
||||
// Start the simulation
|
||||
|
||||
// Read input arguments and initialize
|
||||
initial
|
||||
begin
|
||||
$value$plusargs("max-cycles=%d", max_cycles);
|
||||
verbose = $test$plusargs("verbose");
|
||||
`ifdef DEBUG
|
||||
if ($value$plusargs("vcdplusfile=%s", vcdplusfile))
|
||||
begin
|
||||
$vcdplusfile(vcdplusfile);
|
||||
$vcdpluson(0);
|
||||
$vcdplusmemon(0);
|
||||
end
|
||||
|
||||
if ($value$plusargs("vcdfile=%s", vcdfile))
|
||||
begin
|
||||
$dumpfile(vcdfile);
|
||||
$dumpvars(0, dut);
|
||||
$dumpon;
|
||||
end
|
||||
`define VCDPLUSCLOSE $vcdplusclose; $dumpoff;
|
||||
`else
|
||||
`define VCDPLUSCLOSE
|
||||
`endif
|
||||
|
||||
// Strobe reset
|
||||
#777.7 reset = 0;
|
||||
|
||||
end
|
||||
|
||||
reg [255:0] reason = 0;
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (max_cycles > 0 && trace_count > max_cycles)
|
||||
reason = "timeout";
|
||||
if (exit > 1)
|
||||
$sformat(reason, "tohost = %d", exit >> 1);
|
||||
|
||||
if (reason)
|
||||
begin
|
||||
$fdisplay(stderr, "*** FAILED *** (%s) after %d simulation cycles", reason, trace_count);
|
||||
`VCDPLUSCLOSE
|
||||
$fatal;
|
||||
end
|
||||
|
||||
if (exit == 1)
|
||||
begin
|
||||
if (verbose)
|
||||
$fdisplay(stderr, "Completed after %d simulation cycles", trace_count);
|
||||
`VCDPLUSCLOSE
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
trace_count = trace_count + 1;
|
||||
`ifdef GATE_LEVEL
|
||||
if (verbose)
|
||||
begin
|
||||
$fdisplay(stderr, "C: %10d", trace_count-1);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
|
||||
endmodule
|
Reference in New Issue
Block a user