Randomise I$ interface on TB

This commit is contained in:
Florian Zaruba 2017-06-29 18:19:20 +02:00
parent 31eaa9624a
commit 31bfa5f3d3
6 changed files with 263 additions and 38 deletions

View file

@ -15,9 +15,6 @@ test_alu:
script:
- make alu library=alu_lib
- vcover-10.6 report alu.ucdb
artifacts:
paths:
- covhtmlreport
test_fifo:
stage: test
@ -26,9 +23,6 @@ test_fifo:
script:
- make fifo library=fifo_lib
- vcover-10.6 report fifo.ucdb
artifacts:
paths:
- covhtmlreport
test_scoreboard:
stage: test
@ -37,9 +31,6 @@ test_scoreboard:
script:
- make scoreboard library=scoreboard_lib
- vcover-10.6 report scoreboard.ucdb
artifacts:
paths:
- covhtmlreport
test_dcache_arbiter:
stage: test
@ -48,9 +39,6 @@ test_dcache_arbiter:
script:
- make dcache_arbiter library=dcache_arbiter_lib
- vcover-10.6 report dcache_arbiter.ucdb
artifacts:
paths:
- covhtmlreport
test_store_queue:
stage: test
@ -59,9 +47,6 @@ test_store_queue:
script:
- make store_queue library=store_queue_lib
- vcover-10.6 report store_queue.ucdb
artifacts:
paths:
- covhtmlreport
test_core_asm:
stage: test
@ -72,9 +57,18 @@ test_core_asm:
script:
- make run-asm-tests library=core_lib
- vcover-10.6 report run-asm-tests.ucdb
artifacts:
paths:
- covhtmlreport
# test with the randomized memory interfaces
test_core_asm_rand:
stage: test
before_script:
- git submodule update --init --recursive
- make build-tests
- make build library=core_rand_lib
script:
# same as above but pass the rand_mem_if flag
- make run-asm-tests library=core_rand_lib uvm-flags=+rand_mem_if
- vcover-10.6 report run-asm-rand-tests.ucdb
test_failed_tests:
stage: test
@ -84,9 +78,6 @@ test_failed_tests:
script:
- make run-failed-tests library=failed_tests_lib
- vcover-10.6 report run-failed-tests.ucdb
artifacts:
paths:
- covhtmlreport
# test_lsu:
# stage: test
@ -104,10 +95,7 @@ test_failed_tests:
pages:
stage: deploy
dependencies:
- test_alu
- test_fifo
- test_scoreboard
- test_dcache_arbiter
- build_rtl
script:
- mkdir public
- mkdocs build -d public

View file

@ -67,6 +67,7 @@ questa_version = -10.6
compile_flag = +cover=bcfst+/dut -incr -64 -nologo -quiet -suppress 13262 -permissive
# Moore binary
moore = ~fschuiki/bin/moore
uvm-flags =
# Iterate over all include directories and write them with +incdir+ prefixed
# +incdir+ works for Verilator and QuestaSim
list_incdir = $(foreach dir, ${incdir}, +incdir+$(dir))
@ -115,15 +116,15 @@ $(library):
sim: build
vsim${questa_version} -lib ${library} ${top_level}_optimized +UVM_TESTNAME=${test_case} +BASEDIR=$(riscv-test-dir) \
+ASMTEST=$(riscv-test) +UVM_VERBOSITY=HIGH -coverage -classdebug -do "do tb/wave/wave_core.do"
+ASMTEST=$(riscv-test) $(uvm-flags) +UVM_VERBOSITY=HIGH -coverage -classdebug -do "do tb/wave/wave_core.do"
simc: build
vsim${questa_version} -c -lib ${library} ${top_level}_optimized +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
+BASEDIR=$(riscv-test-dir) +UVM_VERBOSITY=HIGH +ASMTEST=$(riscv-test) -coverage -classdebug -do "do tb/wave/wave_core.do"
+BASEDIR=$(riscv-test-dir) +UVM_VERBOSITY=HIGH $(uvm-flags) +ASMTEST=$(riscv-test) -coverage -classdebug -do "do tb/wave/wave_core.do"
run-asm-tests: build
$(foreach test, $(riscv-tests), vsim$(questa_version) +BASEDIR=$(riscv-test-dir) +max-cycles=$(max_cycles) \
+UVM_TESTNAME=$(test_case) +UVM_VERBOSITY=LOW +ASMTEST=$(test) +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c +UVM_VERBOSITY=LOW\
+UVM_TESTNAME=$(test_case) +UVM_VERBOSITY=LOW $(uvm-flags) +ASMTEST=$(test) +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c +UVM_VERBOSITY=LOW\
-coverage -classdebug -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
$(library).$(test_top_level)_optimized;)
@ -132,7 +133,7 @@ run-failed-tests: build
cd failedtests && make
# run the RTL simulation
$(foreach test, $(failed-tests:.S=), vsim$(questa_version) +BASEDIR=. +max-cycles=$(max_cycles) \
+UVM_TESTNAME=$(test_case) +ASMTEST=$(test) +signature=$(test).rtlsim.sig +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c \
+UVM_TESTNAME=$(test_case) $(uvm-flags) +ASMTEST=$(test) +signature=$(test).rtlsim.sig +uvm_set_action="*,_ALL_,UVM_ERROR,UVM_DISPLAY|UVM_STOP" -c \
-coverage -classdebug -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
$(library).$(test_top_level)_optimized;)
# run it on spike

View file

@ -61,7 +61,8 @@ module if_stage (
//---------------------------------
// we are busy if we are either waiting for a grant
// or if the FIFO is full
assign if_busy_o = (CS == WAIT_GNT) || !fifo_ready;
// or if we are waiting for a rvalid and we didn't receive one yet
assign if_busy_o = (CS == WAIT_GNT) || !fifo_ready || (CS == WAIT_RVALID && !instr_rvalid_i);
assign fetch_address = {fetch_address_i[63:2], 2'b0};
//---------------------------------
@ -138,6 +139,10 @@ module if_stage (
// we wait for rvalid, after that we are ready to serve a new request
WAIT_RVALID: begin
instr_addr_o = fetch_address;
// we are waiting for a rvalid and in case we don't receive one, wait in the aborted state if we flushed
if (flush_i)
NS = WAIT_ABORTED;
// prepare for next request
if (fifo_ready && fetch_valid_i) begin
// wait for the valid signal
@ -147,7 +152,7 @@ module if_stage (
addr_valid = 1'b1;
if (instr_gnt_i) begin
// we have one outstanding rvalid: wait for it
// we have one outstanding rvalid -> wait for it
// if we are receiving a data item during a flush ignore it
if (flush_i)
NS = WAIT_ABORTED;
@ -220,11 +225,11 @@ module if_stage (
//-------------
always_ff @(posedge clk_i, negedge rst_ni) begin
if (~rst_ni) begin
CS <= IDLE;
instr_addr_q <= '0;
branchpredict_q <= '{default: 0};
CS <= IDLE;
instr_addr_q <= '0;
branchpredict_q <= '{default: 0};
end else begin
CS <= NS;
CS <= NS;
if (addr_valid) begin
instr_addr_q <= fetch_address_i;
branchpredict_q <= branch_predict_i;

View file

@ -57,7 +57,7 @@ module core_mem (
assign data_address = {data_if_address_tag_i, index[11:3]};
assign #($urandom_range(0,40)) delayed_instr_request = instr_if_data_req_i;
assign delayed_instr_request = instr_if_data_req_i;
// we always grant the request
assign instr_if_data_gnt_o = delayed_instr_request;
assign instr_address = instr_if_address_i[ADDRESS_WIDTH-1+3:3];

197
tb/common/random_stalls.sv Executable file
View file

@ -0,0 +1,197 @@
// Author: Andreas Traber, ACP
// Date: 22/02/2016
// Description: Randomly inject stalls in the instruction interface
//
// Copyright (C) 2017 ETH Zurich, University of Bologna
// All rights reserved.
//
// This code is under development and not yet released to the public.
// Until it is released, the code is under the copyright of ETH Zurich and
// the University of Bologna, and may contain confidential and/or unpublished
// work. Any reuse/redistribution is strictly forbidden without written
// permission from ETH Zurich.
//
// Bug fixes and contributions will eventually be released under the
// SolderPad open hardware license in the context of the PULP platform
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
// University of Bologna.
//
module random_stalls
(
input logic clk_i,
input logic core_req_i,
output logic core_gnt_o,
input logic [63:0] core_addr_i,
input logic core_we_i,
input logic [ 3:0] core_be_i,
input logic [31:0] core_wdata_i,
output logic [31:0] core_rdata_o,
output logic core_rvalid_o,
output logic data_req_o,
input logic data_gnt_i,
output logic [63:0] data_addr_o,
output logic data_we_o,
output logic [ 3:0] data_be_o,
output logic [31:0] data_wdata_o,
input logic [31:0] data_rdata_i,
input logic data_rvalid_i
);
class rand_wait_cycles;
rand int n;
constraint default_c { n >= 0 ; n < 6;}
endclass
// random staller
typedef struct {
logic [63:0] addr;
logic we;
logic [ 3:0] be;
logic [31:0] wdata;
logic [31:0] rdata;
} stall_mem_t;
mailbox core_reqs = new (4);
mailbox core_resps = new (4);
mailbox core_resps_granted = new (4);
mailbox platform_transfers = new (4);
semaphore req_served = new (1);
// ------------------
// Core Request Side
// ------------------
// Waits for requests and puts them in a queue, does not perform actual
// requests to the platform
initial begin
stall_mem_t mem_acc;
automatic rand_wait_cycles wait_cycles = new ();
int temp;
forever begin
core_gnt_o = 1'b0;
#1;
if (!core_req_i)
continue;
// we got a request, now let's wait for a random number of cycles before
// we give the grant
temp = wait_cycles.randomize();
while(wait_cycles.n != 0) begin
@(posedge clk_i);
wait_cycles.n--;
#1;
end
// block until the we served all outstanding requests
req_served.get();
// we waited for a random number of cycles, let's give the grant
core_gnt_o = 1'b1;
mem_acc.addr = core_addr_i;
mem_acc.be = core_be_i;
mem_acc.we = core_we_i;
mem_acc.wdata = core_wdata_i;
core_reqs.put(mem_acc);
@(posedge clk_i);
core_resps_granted.put(1'b1);
end
end
// ------------------
// Core Response Side
// ------------------
// Waits for a response from the platform and then waits for a random number
// of cycles before giving the rvalid
initial begin
stall_mem_t mem_acc;
automatic rand_wait_cycles wait_cycles = new ();
logic granted;
int temp;
forever begin
@(posedge clk_i);
core_rvalid_o = 1'b0;
core_rdata_o = 'x;
core_resps_granted.get(granted);
core_resps.get(mem_acc);
// we got a response, now let's wait for a random amount of cycles
// we give the grant
temp = wait_cycles.randomize();
while(wait_cycles.n != 0) begin
@(posedge clk_i);
wait_cycles.n--;
end
// put back the semaphore
req_served.put();
// we waited for a random number of cycles, let's give the rvalid
core_rdata_o = mem_acc.rdata;
core_rvalid_o = 1'b1;
end
end
// platform request side
// Waits for requests from the core and then performs the request on the
// platform immediately
// Simulates a "virtual" core
initial begin
stall_mem_t mem_acc;
forever begin
@(posedge clk_i);
data_req_o = 1'b0;
data_addr_o = '0;
data_we_o = 1'b0;
data_be_o = 4'b0;
data_wdata_o = 'x;
core_reqs.get(mem_acc);
data_req_o = 1'b1;
data_addr_o = mem_acc.addr;
data_we_o = mem_acc.we;
data_be_o = mem_acc.be;
data_wdata_o = mem_acc.wdata;
#1;
while(!data_gnt_i) begin
@(posedge clk_i);
#1;
end
platform_transfers.put(mem_acc);
end
end
// platform response side
// Waits for rvalids and puts the responses into the core response mailbox
initial begin
stall_mem_t mem_acc;
forever begin
@(posedge clk_i);
platform_transfers.get(mem_acc);
while(!data_rvalid_i) begin
@(posedge clk_i);
end
mem_acc.rdata = data_rdata_i;
core_resps.put(mem_acc);
end
end
endmodule

View file

@ -80,6 +80,40 @@ module core_tb;
assign dcache_if.data_rvalid = data_if_data_rvalid_o;
assign dcache_if.data_rdata = data_if_data_rdata_o;
random_stalls instr_stalls_i (
.clk_i ( clk_i ),
.core_req_i ( dut.instr_if_data_req_o ),
.core_addr_i ( dut.instr_if_address_o ),
.core_we_i ( ),
.core_be_i ( ),
.core_wdata_i ( ),
.core_gnt_o ( ),
.core_rdata_o ( ),
.core_rvalid_o ( ),
.data_req_o ( ),
.data_addr_o ( ),
.data_we_o ( ),
.data_be_o ( ),
.data_wdata_o ( ),
.data_gnt_i ( instr_if_data_gnt ),
.data_rdata_i ( instr_if_data_rdata ),
.data_rvalid_i ( instr_if_data_rvalid )
);
initial begin
string rand_mem;
// if the randomize memory interface is set to 1 do so
if(uvcl.get_arg_value("+rand_mem_if", rand_mem) != 0) begin
force dut.instr_if_data_gnt_i = instr_stalls_i.core_gnt_o;
force dut.instr_if_data_rvalid_i = instr_stalls_i.core_rvalid_o;
force dut.instr_if_data_rdata_i = instr_stalls_i.core_rdata_o;
force instr_if_data_req = instr_stalls_i.data_req_o;
force instr_if_address = instr_stalls_i.data_addr_o;
end
end
core_mem core_mem_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -116,9 +150,9 @@ module core_tb;
.core_id_i ( core_if.core_id ),
.cluster_id_i ( core_if.cluster_id ),
.instr_if_address_o ( instr_if_address ),
.instr_if_data_req_o ( instr_if_data_req ),
.instr_if_data_be_o ( instr_if_data_be ),
.instr_if_address_o ( instr_if_address ),
.instr_if_data_be_o ( ),
.instr_if_data_gnt_i ( instr_if_data_gnt ),
.instr_if_data_rvalid_i ( instr_if_data_rvalid ),
.instr_if_data_rdata_i ( instr_if_data_rdata ),