diff --git a/Makefile b/Makefile index 91e7745ec..fb1afa11e 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/store_queue.sv b/store_queue.sv index f1b110337..347f69258 100644 --- a/store_queue.sv +++ b/store_queue.sv @@ -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; diff --git a/tb/store_queue_tb.sv b/tb/store_queue_tb.sv index d2f6b9af4..51476ef70 100755 --- a/tb/store_queue_tb.sv +++ b/tb/store_queue_tb.sv @@ -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 diff --git a/tb/wave_store_queue.do b/tb/wave_store_queue.do index b459477d6..674dfded0 100644 --- a/tb/wave_store_queue.do +++ b/tb/wave_store_queue.do @@ -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