diff --git a/README.md b/README.md index 11e1b849a..3bfac1859 100644 --- a/README.md +++ b/README.md @@ -41,23 +41,23 @@ Check out the [contribution guide](CONTRIBUTING.md) # Test Overview -| **Test Name** | **P/F/U** | **Test Name** | **P/F/U** | **Test Name** | **P/F/U** | -|---------------|----------------------|---------------|----------------------|---------------|--------------------| -| add | :white_check_mark: | lb | :white_check_mark: | sll | :white_check_mark: | -| addi | :white_check_mark: | lbu | :white_check_mark: | slli | :white_check_mark: | -| addiw | :white_check_mark: | ld | :white_check_mark: | slliw | :white_check_mark: | -| addw | :white_check_mark: | lh | :white_check_mark: | sllw | :white_check_mark: | -| and | :white_check_mark: | lhu | :white_check_mark: | slt | :white_check_mark: | -| andi | :white_check_mark: | lui | :white_check_mark: | slti | :white_check_mark: | -| auipc | :white_check_mark: | lw | :white_check_mark: | sltiu | :white_check_mark: | -| beq | :white_check_mark: | lwu | :white_check_mark: | sltu | :white_check_mark: | -| bge | :white_check_mark: | or | :white_check_mark: | sra | :white_check_mark: | -| bgeu | :white_check_mark: | ori | :white_check_mark: | srai | :white_check_mark: | -| blt | :white_check_mark: | sb | :white_large_square: | sraiw | :white_check_mark: | -| bltu | :white_check_mark: | sd | :white_large_square: | sraw | :white_check_mark: | -| bne | :white_check_mark: | sh | :white_large_square: | srl | :white_check_mark: | -| sub | :white_check_mark: | simple | :white_check_mark: | srli | :white_check_mark: | -| subw | :white_check_mark: | jal | :white_check_mark: | srliw | :white_check_mark: | -| sw | :white_large_square: | jalr | :white_check_mark: | srlw | :white_check_mark: | -| xor | :white_check_mark: | | | | | -| xori | :white_check_mark: | | | | | +| **Test Name** | **P/F/U** | **Test Name** | **P/F/U** | **Test Name** | **P/F/U** | +|---------------|--------------------|---------------|--------------------|---------------|--------------------| +| add | :white_check_mark: | lb | :white_check_mark: | sll | :white_check_mark: | +| addi | :white_check_mark: | lbu | :white_check_mark: | slli | :white_check_mark: | +| addiw | :white_check_mark: | ld | :white_check_mark: | slliw | :white_check_mark: | +| addw | :white_check_mark: | lh | :white_check_mark: | sllw | :white_check_mark: | +| and | :white_check_mark: | lhu | :white_check_mark: | slt | :white_check_mark: | +| andi | :white_check_mark: | lui | :white_check_mark: | slti | :white_check_mark: | +| auipc | :white_check_mark: | lw | :white_check_mark: | sltiu | :white_check_mark: | +| beq | :white_check_mark: | lwu | :white_check_mark: | sltu | :white_check_mark: | +| bge | :white_check_mark: | or | :white_check_mark: | sra | :white_check_mark: | +| bgeu | :white_check_mark: | ori | :white_check_mark: | srai | :white_check_mark: | +| blt | :white_check_mark: | sb | :white_check_mark: | sraiw | :white_check_mark: | +| bltu | :white_check_mark: | sd | :white_check_mark: | sraw | :white_check_mark: | +| bne | :white_check_mark: | sh | :white_check_mark: | srl | :white_check_mark: | +| sub | :white_check_mark: | simple | :white_check_mark: | srli | :white_check_mark: | +| subw | :white_check_mark: | jal | :white_check_mark: | srliw | :white_check_mark: | +| sw | :white_check_mark: | jalr | :white_check_mark: | srlw | :white_check_mark: | +| xor | :white_check_mark: | | | | | +| xori | :white_check_mark: | | | | | diff --git a/src/load_unit.sv b/src/load_unit.sv index 45b05df42..7288cbb4c 100644 --- a/src/load_unit.sv +++ b/src/load_unit.sv @@ -56,7 +56,7 @@ module load_unit ( input logic data_rvalid_i, input logic [63:0] data_rdata_i ); - enum logic [2:0] {IDLE, WAIT_GNT, SEND_TAG, ABORT_TRANSLATION, WAIT_FLUSH} NS, CS; + enum logic [2:0] {IDLE, WAIT_GNT, SEND_TAG, WAIT_PAGE_OFFSET, ABORT_TRANSLATION, WAIT_FLUSH} NS, CS; // in order to decouple the response interface from the request interface we need a // a queue which can hold all outstanding memory requests typedef struct packed { @@ -141,6 +141,41 @@ module load_unit ( end else begin // stall and wait for the store-buffer to drain ready_o = 1'b0; + // wait for the store buffer to train and the page offset to not match anymore + NS = WAIT_PAGE_OFFSET; + end + end + end + // wait here for the page offset to not match anymore + WAIT_PAGE_OFFSET: begin + // we are definitely not ready to accept a new request + // we need unique access to the LSU + ready_o = 1'b0; + translation_req_o = 1'b1; + + // we make a new request as soon as the page offset does not match anymore + // essentially the same part as above + if (!page_offset_matches_i) begin + // make a load request to memory + data_req_o = 1'b1; + // the translation request we got is valid + if (translation_valid_i) begin + // save the physical address for the next cycle + paddr_n = paddr_i; + // we got no data grant so wait for the grant before sending the tag + if (!data_gnt_i) begin + NS = WAIT_GNT; + end else begin + // put the request in the queue + push = 1'b1; + // we got a grant so we can send the tag in the next cycle + NS = SEND_TAG; + end + // we got a TLB miss + end else begin + // we need to abort the translation and let the PTW walker fix the TLB miss + NS = ABORT_TRANSLATION; + ready_o = 1'b0; end end end @@ -262,9 +297,11 @@ module load_unit ( // do not push this request push = 1'b0; end - // if we just flushed and the queue is not empty or we are getting an rvalid this cycle wait in an extra stage + // if we just flushed and the queue is not empty or we are getting an rvalid this cycle wait in a extra stage if (flush_i && (!empty || data_rvalid_i)) begin NS = WAIT_FLUSH; + end else if (flush_i) begin + NS = IDLE; end end diff --git a/src/scoreboard.sv b/src/scoreboard.sv index 55bd1fdef..7c79e4ff0 100644 --- a/src/scoreboard.sv +++ b/src/scoreboard.sv @@ -128,7 +128,7 @@ module scoreboard #( mem_n[trans_id_i[i]].sbe.result = wdata_i[i]; // write the exception back if it is valid if (ex_i[i].valid) - mem_n[trans_id_i[i]].sbe.ex = ex_i[i]; + mem_n[trans_id_i[i]].sbe.ex = ex_i[i]; end end diff --git a/src/store_unit.sv b/src/store_unit.sv index 258e683d0..554b3c3b6 100644 --- a/src/store_unit.sv +++ b/src/store_unit.sv @@ -59,8 +59,9 @@ module store_unit ( ); assign result_o = 64'b0; - logic [63:0] st_buffer_paddr; // physical address for store - logic [63:0] st_buffer_data; // store buffer data out + logic [63:0] st_buffer_paddr; // physical address for store + logic [63:0] st_buffer_data; // store buffer data out + logic [63:0] st_data; // aligned data to store buffer logic [7:0] st_buffer_be; logic st_buffer_valid; // store buffer control signals @@ -108,13 +109,30 @@ module store_unit ( end end end - + // ----------- + // Re-aligner + // ----------- + // re-align the write data to comply with the address offset + always_comb begin + st_data = data_i; + case (vaddr_i[2:0]) + 3'b000: st_data = data_i; + 3'b001: st_data = {data_i[55:0], data_i[63:56]}; + 3'b010: st_data = {data_i[47:0], data_i[63:48]}; + 3'b011: st_data = {data_i[39:0], data_i[63:40]}; + 3'b100: st_data = {data_i[31:0], data_i[63:32]}; + 3'b101: st_data = {data_i[23:0], data_i[63:24]}; + 3'b110: st_data = {data_i[15:0], data_i[63:16]}; + 3'b111: st_data = {data_i[7:0], data_i[63:8]}; + endcase + end // --------------- // Store Queue // --------------- store_queue store_queue_i ( // store queue write port .valid_i ( st_valid ), + .data_i ( st_data ), // store buffer in .paddr_o ( st_buffer_paddr ), .data_o ( st_buffer_data ), diff --git a/tb/wave/wave_core.do b/tb/wave/wave_core.do index 0b523b4eb..f8590b78f 100644 --- a/tb/wave/wave_core.do +++ b/tb/wave/wave_core.do @@ -12,6 +12,7 @@ add wave -noupdate -group ex_stage -group lsu /core_tb/dut/ex_stage_i/lsu_i/* add wave -noupdate -group ex_stage -group lsu -group mem_arbiter /core_tb/dut/ex_stage_i/lsu_i/dcache_arbiter_i/* add wave -noupdate -group ex_stage -group lsu -group mem_arbiter -group arbiter_fifo /core_tb/dut/ex_stage_i/lsu_i/dcache_arbiter_i/fifo_i/* add wave -noupdate -group ex_stage -group lsu -group store_unit /core_tb/dut/ex_stage_i/lsu_i/store_unit_i/* +add wave -noupdate -group ex_stage -group lsu -group store_unit -group store_queue /core_tb/dut/ex_stage_i/lsu_i/store_unit_i/store_queue_i/* add wave -noupdate -group ex_stage -group lsu -group load_unit /core_tb/dut/ex_stage_i/lsu_i/load_unit_i/* add wave -noupdate -group ex_stage -group lsu -group load_unit -group fifo /core_tb/dut/ex_stage_i/lsu_i/load_unit_i/fifo_i/* add wave -noupdate -group ex_stage -group lsu -group lsu_arbiter /core_tb/dut/ex_stage_i/lsu_i/lsu_arbiter_i/*