mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 21:57:11 -04:00
Add sign extend in LSU
This commit is contained in:
parent
c4edf3de3d
commit
ec4384a95f
2 changed files with 146 additions and 15 deletions
153
lsu.sv
153
lsu.sv
|
@ -32,6 +32,7 @@ module lsu #(
|
|||
input logic lsu_valid_i, // Input is valid
|
||||
input logic [TRANS_ID_BITS-1:0] lsu_trans_id_i, // transaction id, needed for WB
|
||||
output logic [TRANS_ID_BITS-1:0] lsu_trans_id_o, // ID of scoreboard entry at which to write back
|
||||
output logic [63:0] lsu_result_o,
|
||||
output logic lsu_valid_o, // transaction id for which the output is the requested one
|
||||
|
||||
input logic enable_translation_i,
|
||||
|
@ -56,11 +57,20 @@ module lsu #(
|
|||
output exception lsu_exception_o // to WB, signal exception status LD/ST exception
|
||||
|
||||
);
|
||||
mem_if ptw_if(clk_i);
|
||||
// data is misaligned
|
||||
logic data_misaligned;
|
||||
assign lsu_trans_id_o = lsu_trans_id_i;
|
||||
assign lsu_valid_o = 1'b0;
|
||||
|
||||
logic [63:0] vaddr;
|
||||
|
||||
// ------------------------------
|
||||
// Address Generation Unit (AGU)
|
||||
// ------------------------------
|
||||
assign vaddr = imm_i + operand_a_i;
|
||||
assign data_if.address = vaddr;
|
||||
|
||||
// ---------------
|
||||
// Memory Arbiter
|
||||
// ---------------
|
||||
|
@ -73,7 +83,8 @@ module lsu #(
|
|||
logic [2:0] data_rvalid_o;
|
||||
logic [2:0][63:0] data_rdata_o;
|
||||
|
||||
mem_arbiter i_mem_arbiter (
|
||||
// port 0 PTW, port 1 loads, port 2 stores
|
||||
mem_arbiter mem_arbiter_i (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
||||
|
@ -98,6 +109,16 @@ module lsu #(
|
|||
.data_rdata_o ( data_rdata_o )
|
||||
);
|
||||
|
||||
// connecting PTW to D$ (aka mem arbiter)
|
||||
assign address_i[0] = ptw_if.address;
|
||||
assign data_wdata_i[0] = ptw_if.data_wdata;
|
||||
assign data_req_i[0] = ptw_if.data_req;
|
||||
assign data_we_i [0] = ptw_if.data_we;
|
||||
assign data_be_i [0] = ptw_if.data_be;
|
||||
assign ptw_if.data_rvalid = data_rvalid_o[0];
|
||||
assign ptw_if.data_rdata = data_rdata_o[0];
|
||||
|
||||
|
||||
// -------------------
|
||||
// MMU e.g.: TLBs/PTW
|
||||
// -------------------
|
||||
|
@ -112,32 +133,142 @@ module lsu #(
|
|||
) i_mmu (
|
||||
.lsu_req_i ( lsu_req_i ),
|
||||
.lsu_vaddr_i ( lsu_vaddr_i ),
|
||||
.lsu_valid_o ( ),
|
||||
.lsu_valid_o ( ),
|
||||
.data_if ( ptw_if ),
|
||||
.*
|
||||
);
|
||||
|
||||
// ------------------
|
||||
// LSU Control
|
||||
// ------------------
|
||||
always_comb begin : lsu_control
|
||||
|
||||
end
|
||||
|
||||
// ---------------
|
||||
// Store Queue
|
||||
// ---------------
|
||||
|
||||
// ---------------
|
||||
// Sign Extend
|
||||
// Byte Enable
|
||||
// ---------------
|
||||
|
||||
// ------------------------------
|
||||
// Address Generation Unit (AGU)
|
||||
// ------------------------------
|
||||
assign vaddr = imm_i + operand_a_i;
|
||||
assign data_if.address = vaddr;
|
||||
// ---------------
|
||||
// Sign Extend
|
||||
// ---------------
|
||||
logic [63:0] rdata_ext;
|
||||
// data coming from arbiter interface 1
|
||||
assign rdata_ext = data_rdata_o[1];
|
||||
logic [63:0] rdata_d_ext; // sign extension for double words, actually only misaligned assembly
|
||||
logic [63:0] rdata_w_ext; // sign extension for words
|
||||
logic [63:0] rdata_h_ext; // sign extension for half words
|
||||
logic [63:0] rdata_b_ext; // sign extension for bytes
|
||||
|
||||
// ------------------
|
||||
// LSU Control
|
||||
// ------------------
|
||||
// double words
|
||||
always_comb begin : sign_extend_double_word
|
||||
case (vaddr[2:0])
|
||||
3'b000: rdata_d_ext = operand_b_i[63:0];
|
||||
// this is for misaligned accesse only
|
||||
// 3'b001: rdata_d_ext = {data_rdata_i[7:0], rdata_q[63:8]};
|
||||
// 3'b010: rdata_d_ext = {data_rdata_i[15:0], rdata_q[63:16]};
|
||||
// 3'b011: rdata_d_ext = {data_rdata_i[23:0], rdata_q[63:24]};
|
||||
// 3'b100: rdata_d_ext = {data_rdata_i[31:0], rdata_q[63:32]};
|
||||
// 3'b101: rdata_d_ext = {data_rdata_i[39:0], rdata_q[63:40]};
|
||||
// 3'b110: rdata_d_ext = {data_rdata_i[47:0], rdata_q[63:48]};
|
||||
// 3'b111: rdata_d_ext = {data_rdata_i[55:0], rdata_q[63:56]};
|
||||
endcase
|
||||
end
|
||||
|
||||
// sign extension for words
|
||||
always_comb begin : sign_extend_word
|
||||
case (vaddr[2:0])
|
||||
3'b000: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[31]}}, rdata_ext[31:0]} : {32'h0, rdata_ext[31:0]};
|
||||
3'b001: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[39]}}, rdata_ext[39:8]} : {32'h0, rdata_ext[39:8]};
|
||||
3'b010: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[47]}}, rdata_ext[47:16]} : {32'h0, rdata_ext[47:16]};
|
||||
3'b011: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[55]}}, rdata_ext[55:24]} : {32'h0, rdata_ext[55:24]};
|
||||
3'b100: rdata_w_ext = (operator_i == LW) ? {{32{rdata_ext[63]}}, rdata_ext[63:32]} : {32'h0, rdata_ext[63:32]};
|
||||
// miss-aligned access
|
||||
// 3'b101: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[63:40]} : {32'h0, data_rdata_i[7:0], rdata_q[63:40]};
|
||||
// 3'b110: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[15]}}, data_rdata_i[15:0], rdata_q[63:48]} : {32'h0, data_rdata_i[15:0], rdata_q[63:48]};
|
||||
// 3'b111: rdata_w_ext = (data_sign_ext_q) ? {{32{data_rdata_i[23]}}, data_rdata_i[23:0], rdata_q[63:56]} : {32'h0, data_rdata_i[23:0], rdata_q[63:56]};
|
||||
endcase
|
||||
end
|
||||
|
||||
// sign extension for half words
|
||||
always_comb begin : sign_extend_half_word
|
||||
case (vaddr[2:0])
|
||||
3'b000: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[15]}}, rdata_ext[15:0]} : {48'h0, rdata_ext[15:0]};
|
||||
3'b001: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[23]}}, rdata_ext[23:8]} : {48'h0, rdata_ext[23:8]};
|
||||
3'b010: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[31]}}, rdata_ext[31:16]} : {48'h0, rdata_ext[31:16]};
|
||||
3'b011: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[39]}}, rdata_ext[39:24]} : {48'h0, rdata_ext[39:24]};
|
||||
3'b100: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[47]}}, rdata_ext[47:32]} : {48'h0, rdata_ext[47:32]};
|
||||
3'b101: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[55]}}, rdata_ext[55:40]} : {48'h0, rdata_ext[55:40]};
|
||||
3'b110: rdata_h_ext = (operator_i == LH) ? {{48{rdata_ext[63]}}, rdata_ext[63:48]} : {48'h0, rdata_ext[63:48]};
|
||||
// miss-aligned access
|
||||
// 3'b111: rdata_h_ext = (data_sign_ext_q) ? {{48{data_rdata_i[7]}}, data_rdata_i[7:0], rdata_q[31:24]} : {48'h0, data_rdata_i[7:0], rdata_q[31:24]};
|
||||
endcase
|
||||
end
|
||||
|
||||
always_comb begin : sign_extend_byte
|
||||
case (vaddr[2:0])
|
||||
3'b000: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[7]}}, rdata_ext[7:0]} : {56'h0, rdata_ext[7:0]};
|
||||
3'b001: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[15]}}, rdata_ext[15:8]} : {56'h0, rdata_ext[15:8]};
|
||||
3'b010: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[23]}}, rdata_ext[23:16]} : {56'h0, rdata_ext[23:16]};
|
||||
3'b011: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[31]}}, rdata_ext[31:24]} : {56'h0, rdata_ext[31:24]};
|
||||
3'b100: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[39]}}, rdata_ext[39:32]} : {56'h0, rdata_ext[39:32]};
|
||||
3'b101: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[47]}}, rdata_ext[47:40]} : {56'h0, rdata_ext[47:40]};
|
||||
3'b110: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[55]}}, rdata_ext[55:48]} : {56'h0, rdata_ext[55:48]};
|
||||
3'b111: rdata_b_ext = (operator_i == LB) ? {{56{rdata_ext[63]}}, rdata_ext[63:56]} : {56'h0, rdata_ext[63:56]};
|
||||
endcase // case (rdata_offset_q)
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case (operator_i)
|
||||
LD: lsu_result_o = rdata_d_ext;
|
||||
LW, LWU: lsu_result_o = rdata_w_ext;
|
||||
LH, LHU: lsu_result_o = rdata_h_ext;
|
||||
LB, LBU: lsu_result_o = rdata_b_ext;
|
||||
endcase //~case(rdata_type_q)
|
||||
end
|
||||
|
||||
// ------------------
|
||||
// Exception Control
|
||||
// ------------------
|
||||
// misaligned detector
|
||||
// page fault, privilege exception
|
||||
always_comb begin : exception_control
|
||||
|
||||
data_misaligned = 1'b0;
|
||||
|
||||
if(lsu_valid_i) begin
|
||||
case (operator_i)
|
||||
LD, SD: begin // double word
|
||||
if(vaddr[2:0] != 3'b000)
|
||||
data_misaligned = 1'b1;
|
||||
end
|
||||
|
||||
LW, LWU, SW: begin // word
|
||||
if(vaddr[2] == 1'b1 && vaddr[2:0] != 3'b100)
|
||||
data_misaligned = 1'b1;
|
||||
end
|
||||
|
||||
LH, LHU, SH: begin // half word
|
||||
if(vaddr[2:0] == 3'b111)
|
||||
data_misaligned = 1'b1;
|
||||
end // byte -> is always aligned
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
// if the request was valid latch it
|
||||
// it is the purpose of the issue stage to not dispatch
|
||||
// instructions if the unit was not ready
|
||||
end else if (lsu_valid_i) begin
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -108,11 +108,11 @@ module mem_arbiter #(
|
|||
data_rvalid_o[i] = 1'b0;
|
||||
data_rdata_o[i] = 64'b0;
|
||||
end
|
||||
// if there is an entry in the queue we are waiting for a read to return
|
||||
// there is a valid signal and the FIFO should not be empty anyway
|
||||
// if there is an entry in the queue -> we are waiting for a read/write to return
|
||||
// if there is a valid signal the FIFO should not be empty anyway
|
||||
if (data_rvalid_i) begin
|
||||
// pass the read through to the appropriate slave
|
||||
pop_i = 1'b1;
|
||||
// pass the read to the appropriate slave
|
||||
pop_i = 1'b1;
|
||||
data_rvalid_o[data_o] = data_rvalid_i;
|
||||
data_rdata_o[data_o] = data_rdata_i;
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue