Add store queue test, flush missing

This commit is contained in:
Florian Zaruba 2017-04-28 18:42:51 +02:00
parent 26cf604ee0
commit 6131b1b7c8
4 changed files with 75 additions and 41 deletions

View file

@ -57,7 +57,7 @@ $(tests):
# Optimize top level
vopt${questa_version} ${compile_flag} $@_tb -o $@_tb_optimized +acc -check_synthesis
# vsim${questa_version} $@_tb_optimized
# vsim${questa_version} -c +UVM_TESTNAME=$@_test -coverage -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" $@_tb_optimized
vsim${questa_version} -c +UVM_TESTNAME=$@_test -coverage -do "coverage save -onexit $@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" $@_tb_optimized
# User Verilator to lint the target
lint:
verilator ${src} --lint-only \

View file

@ -82,7 +82,7 @@ module store_queue (
// if we got a grant this implies that the value was not speculative anymore and that we
// do not need to save the values anymore since the memory already processed them
automatic logic ready = ~commit_queue_q.valid | data_gnt_i;
ready_o = ready;
ready_o = ready & ~flush_i;
commit_queue_n = commit_queue_q;

View file

@ -63,25 +63,47 @@ module store_queue_tb;
end
// combinatorial signals
assign store_queue.flush = 1'b0;
assign store_queue.store_valid = store_valid & store_queue.ready;
assign slave.data_gnt = slave_data_gnt;
// simulator stopper, this is suboptimal better go for coverage
initial begin
#10000000ns
#1000000ns
$stop;
end
program testbench (mem_if slave, store_queue_if store_queue);
// data to store
class store_data;
rand logic [63:0] address;
rand logic [63:0] data;
rand logic [7:0] be;
function new (logic [63:0] address, logic [63:0] data, logic [7:0] be);
this.address = address;
this.data = data;
this.be = be;
endfunction : new
function string convert2string();
string s;
$sformat(s, "Address: %0h, Data: %0h, BE: %0h", address, data, be);
return s;
endfunction : convert2string
function bit do_compare(store_data rhs);
if (rhs.address == address && rhs.data == data && rhs.be == be)
return 1;
else return 0;
endfunction : do_compare
endclass : store_data
store_data data = new();
store_data data = new(64'b0, 64'b0, 8'b0);
semaphore sem = new(1);
logic flush;
// ----------
// Driver
// ----------
@ -98,22 +120,23 @@ module store_queue_tb;
forever begin
@(store_queue.mck);
store_queue.mck.commit <= 1'b0;
if (store_queue.mck.ready) begin
store_queue.mck.store_paddr <= 64'h1;
store_valid <= 1'b1;
// get some randomized data
void'(data.randomize());
store_queue.mck.store_data <= data.data;
store_queue.mck.store_be <= data.be;
store_queue.mck.store_paddr <= data.address;
store_queue.mck.store_data <= data.data;
store_queue.mck.store_be <= data.be;
store_valid <= 1'b1;
// commit a couple of cycles later
fork
commit_block: begin
sem.get(1);
@(store_queue.mck);
@(store_queue.mck);
@(store_queue.mck)
wait(~flush);
store_queue.mck.commit <= 1'b1;
@(store_queue.mck)
store_queue.mck.commit <= 1'b0;
sem.put(1);
end
join_none
@ -123,10 +146,6 @@ module store_queue_tb;
end
end
end
// commit part
initial begin
end
// grant process
@ -152,13 +171,51 @@ module store_queue_tb;
end
end
// random flush signal
initial begin
flush = 1'b0;
store_queue.mck.flush <= 0;
forever begin
repeat (20) @(store_queue.mck);
// TODO: Implement Flush test, needs some more test logic
store_queue.mck.flush <= 0;
flush = 1'b1;
repeat (4) @(store_queue.mck);
store_queue.mck.flush <= 0;
flush = 1'b0;
end
end
// -------------------
// Monitor && Checker
// -------------------
store_data request_data_queue [$];
store_data tmp;
store_data result;
// check that all requested stores got through
// therefore put them in a queue when requested from the LSU and check them on the
// memory interface output
initial begin
forever begin
@(store_queue.pck iff store_queue.pck.store_valid)
tmp = new(store_queue.pck.store_paddr, store_queue.pck.store_data, store_queue.pck.store_be);
request_data_queue.push_back(tmp);
// $display("[LSU] Got: %s", tmp.convert2string());
end
end
// check here what we actually got on the memory interface
initial begin
automatic store_data queue_data;
forever begin
@(slave.pck iff slave.pck.data_req & slave.pck.data_gnt)
result = new(slave.pck.address, slave.pck.data_wdata, slave.pck.data_be);
// $display("[MEM] Got: %s", result.convert2string());
// pop from queue and check if this was indeed requested
queue_data = request_data_queue.pop_front();
assert(queue_data.do_compare(result)) else $error("Mismatch: Expected %s, Got: %s", queue_data.convert2string() , result.convert2string());
end
end
endprogram

View file

@ -1,29 +1,6 @@
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /store_queue_tb/dut/clk_i
add wave -noupdate /store_queue_tb/dut/rst_ni
add wave -noupdate /store_queue_tb/dut/flush_i
add wave -noupdate /store_queue_tb/dut/paddr_o
add wave -noupdate /store_queue_tb/dut/data_o
add wave -noupdate /store_queue_tb/dut/valid_o
add wave -noupdate /store_queue_tb/dut/be_o
add wave -noupdate /store_queue_tb/dut/commit_i
add wave -noupdate /store_queue_tb/dut/ready_o
add wave -noupdate /store_queue_tb/dut/valid_i
add wave -noupdate /store_queue_tb/dut/paddr_i
add wave -noupdate /store_queue_tb/dut/data_i
add wave -noupdate /store_queue_tb/dut/be_i
add wave -noupdate /store_queue_tb/dut/address_o
add wave -noupdate /store_queue_tb/dut/data_wdata_o
add wave -noupdate /store_queue_tb/dut/data_req_o
add wave -noupdate /store_queue_tb/dut/data_we_o
add wave -noupdate /store_queue_tb/dut/data_be_o
add wave -noupdate /store_queue_tb/dut/data_gnt_i
add wave -noupdate /store_queue_tb/dut/data_rvalid_i
add wave -noupdate /store_queue_tb/dut/CS
add wave -noupdate /store_queue_tb/dut/NS
add wave -noupdate /store_queue_tb/dut/commit_queue_n
add wave -noupdate /store_queue_tb/dut/commit_queue_q
add wave -noupdate /store_queue_tb/dut/*
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {0 ns} 0}
quietly wave cursor active 0