🐛 Fix bug in misaligned ld/st exception

This commit is contained in:
Florian Zaruba 2017-06-08 15:35:44 +02:00
parent 121852957b
commit 0abbabad86
5 changed files with 25 additions and 23 deletions

View file

@ -40,7 +40,7 @@ riscv-tests = rv64ui-p-add rv64ui-p-addi rv64ui-p-slli rv64ui-p-addiw rv64ui-p-a
rv64ui-p-sraiw rv64ui-p-sraw rv64ui-p-srl rv64ui-p-srli rv64ui-p-srliw rv64ui-p-srlw \
rv64ui-p-lb rv64ui-p-lbu rv64ui-p-ld rv64ui-p-lh rv64ui-p-lhu rv64ui-p-lui \
rv64ui-p-lw rv64ui-p-lwu \
rv64mi-p-csr rv64mi-p-mcsr rv64mi-p-illegal
rv64mi-p-csr rv64mi-p-mcsr rv64mi-p-illegal rv64mi-p-ma_addr
riscv-test = rv64ui-p-add
# Search here for include files (e.g.: non-standalone components)

View file

@ -69,5 +69,5 @@ Check out the [contribution guide](CONTRIBUTING.md)
| **Test Name** | **P/F/U** | **Test Name** | **P/F/U** | **Test Name** | **P/F/U** |
|---------------|----------------------|---------------|----------------------|---------------|----------------------|
| csr | :white_check_mark: | illegal | :white_check_mark: | mcsr | :white_check_mark: |
| breakpoint | :white_large_square: | ma_addr | :white_large_square: | ma_fetch | :white_large_square: |
| breakpoint | :white_large_square: | ma_addr | :white_check_mark: | ma_fetch | :white_large_square: |
| sbreak | :white_large_square: | scall | :white_large_square: | | |

View file

@ -296,6 +296,8 @@ module load_unit (
ready_o = 1'b1;
// do not push this request
push = 1'b0;
// reset state machine
NS = IDLE;
end
// 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
@ -309,6 +311,9 @@ module load_unit (
always_comb begin : rvalid_output
pop = 1'b0;
valid_o = 1'b0;
// output the queue data directly, the valid signal is set corresponding to the process above
trans_id_o = out_data.trans_id;
// we got an rvalid and are currently not flushing
if (data_rvalid_i && CS != WAIT_FLUSH) begin
pop = 1'b1;
@ -316,12 +321,13 @@ module load_unit (
end
// pass through an exception
if (valid_i && ex_i.valid) begin
valid_o = 1'b1;
valid_o = 1'b1;
// in case of an exception we can use the current trans_id since we either stalled
// or we are taking the exception in the first cycle
trans_id_o = trans_id_i;
end
end
// output the queue data directly, the valid signal is set corresponding to the process above
assign trans_id_o = out_data.trans_id;
// latch physical address
always_ff @(posedge clk_i or negedge rst_ni) begin

View file

@ -335,19 +335,15 @@ module lsu #(
ld_valid_i = 1'b0;
st_valid_i = 1'b0;
// only activate one of the units if we didn't got an misaligned exception
// we can directly output a misaligned exception and do not need to process it any further
if (!data_misaligned) begin
// check the operator to activate the right functional unit accordingly
unique case (fu)
// all loads go here
LOAD: ld_valid_i = lsu_valid_i;
// all stores go here
STORE: st_valid_i = lsu_valid_i;
// not relevant for the LSU
default: ;
endcase
end
// check the operator to activate the right functional unit accordingly
unique case (fu)
// all loads go here
LOAD: ld_valid_i = lsu_valid_i;
// all stores go here
STORE: st_valid_i = lsu_valid_i;
// not relevant for the LSU
default: ;
endcase
end
@ -424,13 +420,13 @@ module lsu #(
end
// word
LW, LWU, SW: begin
if (vaddr_i[2] == 1'b1 && vaddr_i[2:0] != 3'b100)
if (vaddr_i[1:0] != 1'b00)
data_misaligned = 1'b1;
end
// half word
LH, LHU, SH: begin
if (vaddr_i[2:0] == 3'b111)
if (vaddr_i[0] != 1'b0)
data_misaligned = 1'b1;
end
// byte -> is always aligned
@ -442,15 +438,15 @@ module lsu #(
if (fu == LOAD) begin
misaligned_exception = {
64'b0,
LD_ADDR_MISALIGNED,
vaddr,
1'b1
};
end else if (fu == STORE) begin
misaligned_exception = {
64'b0,
ST_ADDR_MISALIGNED,
vaddr,
1'b1
};
end

View file

@ -102,7 +102,7 @@ module store_unit (
if (ex_i.valid) begin
// result is valid
valid_o = 1'b1;
// do not store this
// do not store this
st_valid = 1'b0;
// we are ready if we got this exception
ready_o = 1'b1;