mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 05:07:21 -04:00
🐛 Fix misaligned data in store buffer
This commit is contained in:
parent
1ec3253441
commit
00e500f08c
5 changed files with 82 additions and 26 deletions
40
README.md
40
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: | | | | |
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ),
|
||||
|
|
|
@ -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/*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue