From ec4384a95f8e02bd19f94cb1fe3563b8692cf0d2 Mon Sep 17 00:00:00 2001 From: Florian Zaruba Date: Tue, 25 Apr 2017 15:27:18 +0200 Subject: [PATCH] Add sign extend in LSU --- lsu.sv | 153 +++++++++++++++++++++++++++++++++++++++++++++---- mem_arbiter.sv | 8 +-- 2 files changed, 146 insertions(+), 15 deletions(-) diff --git a/lsu.sv b/lsu.sv index b1ff6e584..65b6e68db 100644 --- a/lsu.sv +++ b/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 \ No newline at end of file diff --git a/mem_arbiter.sv b/mem_arbiter.sv index 3cbde5758..0e28b4ab3 100644 --- a/mem_arbiter.sv +++ b/mem_arbiter.sv @@ -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