diff --git a/include/ariane_pkg.svh b/include/ariane_pkg.svh index 8ede557dc..6e4b8a9d1 100644 --- a/include/ariane_pkg.svh +++ b/include/ariane_pkg.svh @@ -65,7 +65,7 @@ package ariane_pkg; } branchpredict_sbe; typedef enum logic[3:0] { - NONE, LSU, ALU, CTRL_FLOW, MULT, CSR + NONE, LOAD, STORE, ALU, CTRL_FLOW, MULT, CSR } fu_t; localparam EXC_OFF_RST = 8'h80; diff --git a/src/ariane.sv b/src/ariane.sv index 383fd9726..a88ee052f 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -118,6 +118,7 @@ module ariane // -------------- logic [63:0] imm_id_ex; logic [TRANS_ID_BITS-1:0] trans_id_id_ex; + fu_t fu_id_ex; fu_op operator_id_ex; logic [63:0] operand_a_id_ex; logic [63:0] operand_b_id_ex; @@ -275,6 +276,7 @@ module ariane .ready_o ( ready_id_if ), .priv_lvl_i ( priv_lvl ), // Functional Units + .fu_o ( fu_id_ex ), .operator_o ( operator_id_ex ), .operand_a_o ( operand_a_id_ex ), .operand_b_o ( operand_b_id_ex ), @@ -319,6 +321,7 @@ module ariane // --------- ex_stage ex_stage_i ( .flush_i ( flush_ctrl_ex ), + .fu_i ( fu_id_ex ), .operator_i ( operator_id_ex ), .operand_a_i ( operand_a_id_ex ), .operand_b_i ( operand_b_id_ex ), diff --git a/src/commit_stage.sv b/src/commit_stage.sv index 57a325a8c..9a7cf88fe 100644 --- a/src/commit_stage.sv +++ b/src/commit_stage.sv @@ -76,7 +76,7 @@ module commit_stage ( we_a_o = 1'b1; commit_ack_o = 1'b1; // check whether the instruction we retire was a store - if (commit_instr_i.op inside {SD, SW, SH, SB}) begin + if (commit_instr_i.fu == STORE) begin commit_lsu_o = 1'b1; end // --------- diff --git a/src/decoder.sv b/src/decoder.sv index bec6dae97..1b46ab390 100644 --- a/src/decoder.sv +++ b/src/decoder.sv @@ -291,7 +291,7 @@ module decoder ( end OPCODE_STORE: begin - instruction_o.fu = LSU; + instruction_o.fu = STORE; imm_select = SIMM; instruction_o.rs1 = instr.stype.rs1; instruction_o.rs2 = instr.stype.rs2; @@ -311,7 +311,7 @@ module decoder ( end OPCODE_LOAD: begin - instruction_o.fu = LSU; + instruction_o.fu = LOAD; imm_select = IIMM; instruction_o.rs1 = instr.itype.rs1; instruction_o.rd = instr.itype.rd; diff --git a/src/ex_stage.sv b/src/ex_stage.sv index 5b1700604..64d25d651 100644 --- a/src/ex_stage.sv +++ b/src/ex_stage.sv @@ -26,6 +26,7 @@ module ex_stage #( input logic rst_ni, // Asynchronous reset active low input logic flush_i, + input fu_t fu_i, input fu_op operator_i, input logic [63:0] operand_a_i, input logic [63:0] operand_b_i, diff --git a/src/id_stage.sv b/src/id_stage.sv index cc2149243..1e2b14ba7 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -38,6 +38,7 @@ module id_stage #( input priv_lvl_t priv_lvl_i, // current privilege level output logic ready_o, // id is ready + output fu_t fu_o, output fu_op operator_o, output logic [63:0] operand_a_o, output logic [63:0] operand_b_o, diff --git a/src/issue_read_operands.sv b/src/issue_read_operands.sv index ca49d9651..3d02c8c1d 100644 --- a/src/issue_read_operands.sv +++ b/src/issue_read_operands.sv @@ -39,6 +39,7 @@ module issue_read_operands ( // get clobber input input fu_t [31:0] rd_clobber_i, // To FU, just single issue for now + output fu_t fu_o, output fu_op operator_o, output logic [63:0] operand_a_o, output logic [63:0] operand_b_o, @@ -84,7 +85,8 @@ module issue_read_operands ( logic branch_valid_n, branch_valid_q; logic [TRANS_ID_BITS-1:0] trans_id_n, trans_id_q; - fu_op operator_n, operator_q; + fu_op operator_n, operator_q; // operation to perform + fu_t fu_n, fu_q; // functional unit to use // forwarding signals logic forward_rs1, forward_rs2; @@ -92,6 +94,7 @@ module issue_read_operands ( assign operand_a_o = operand_a_q; assign operand_b_o = operand_b_q; assign operand_c_o = operand_c_q; + assign fu_o = fu_q; assign operator_o = operator_q; assign alu_valid_o = alu_valid_q; assign branch_valid_o = branch_valid_q; @@ -150,7 +153,7 @@ module issue_read_operands ( fu_busy = ~alu_ready_i; MULT: fu_busy = ~mult_ready_i; - LSU: + LOAD, STORE: fu_busy = ~lsu_ready_i; CSR: fu_busy = ~csr_ready_i; @@ -203,8 +206,8 @@ module issue_read_operands ( // immediates are the third operands in the store case imm_n = issue_instr_i.result; trans_id_n = issue_instr_i.trans_id; + fu_n = issue_instr_i.fu; operator_n = issue_instr_i.op; - // or should we forward if (forward_rs1) begin operand_a_n = rs1_i; @@ -225,7 +228,7 @@ module issue_read_operands ( operand_a_n = {52'b0, issue_instr_i.rs1}; end // or is it an immediate (including PC), this is not the case for a store - if (issue_instr_i.use_imm && ~(issue_instr_i.op inside {SD, SW, SH, SB})) begin + if (issue_instr_i.use_imm && (issue_instr_i.fu != STORE)) begin operand_b_n = issue_instr_i.result; end // special assignments in the JAL and JALR case @@ -269,7 +272,7 @@ module issue_read_operands ( alu_valid_n = 1'b1; MULT: mult_valid_n = 1'b1; - LSU: + LOAD, STORE: lsu_valid_n = 1'b1; CSR: csr_valid_n = 1'b1; @@ -330,6 +333,7 @@ module issue_read_operands ( mult_valid_q <= 1'b0; lsu_valid_q <= 1'b0; csr_valid_q <= 1'b0; + fu_q <= NONE; operator_q <= ADD; trans_id_q <= 5'b0; pc_o <= 64'b0; @@ -345,6 +349,7 @@ module issue_read_operands ( mult_valid_q <= mult_valid_n; lsu_valid_q <= lsu_valid_n; csr_valid_q <= csr_valid_n; + fu_q <= fu_n; operator_q <= operator_n; trans_id_q <= trans_id_n; pc_o <= issue_instr_i.pc; diff --git a/src/lsu.sv b/src/lsu.sv index 90099c227..a28baf477 100644 --- a/src/lsu.sv +++ b/src/lsu.sv @@ -25,6 +25,7 @@ module lsu #( input logic rst_ni, input logic flush_i, + input fu_t fu_i, input fu_op operator_i, input logic [63:0] operand_a_i, input logic [63:0] operand_b_i, @@ -85,11 +86,13 @@ module lsu #( logic [63:0] vaddr; logic [63:0] data; logic [7:0] be; + fu_t fu; fu_op operator; logic [TRANS_ID_BITS-1:0] trans_id; // registered address in case of a necessary stall logic [63:0] vaddr_n, vaddr_q; logic [63:0] data_n, data_q; + fu_t fu_n, fu_q; fu_op operator_n, operator_q; logic [TRANS_ID_BITS-1:0] trans_id_n, trans_id_q; logic [7:0] be_n, be_q; @@ -100,6 +103,7 @@ module lsu #( // virtual address as calculated by the AGU in the first cycle logic [63:0] vaddr_i; logic [7:0] be_i; + assign vaddr_i = $signed(imm_i) + $signed(operand_a_i); logic st_valid_i; @@ -325,8 +329,6 @@ module lsu #( end end - enum logic {LD_OP, ST_OP} op; - // determine whether this is a load or store always_comb begin : which_op @@ -334,20 +336,14 @@ module lsu #( st_valid_i = 1'b0; // only activate one of the units if we didn't got an misaligned exception - // we can directly output an misaligned exception and do not need to process it any further + // 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 (operator) + unique case (fu) // all loads go here - LD, LW, LWU, LH, LHU, LB, LBU: begin - ld_valid_i = 1'b1; - op = LD_OP; - end + LOAD: ld_valid_i = 1'b1; // all stores go here - SD, SW, SH, SB: begin - st_valid_i = 1'b1; - op = ST_OP; - end + STORE: st_valid_i = 1'b1; // not relevant for the LSU default: ; endcase @@ -444,14 +440,14 @@ module lsu #( if (data_misaligned) begin - if (op == LD_OP) begin + if (fu == LOAD) begin misaligned_exception = { 64'b0, LD_ADDR_MISALIGNED, 1'b1 }; - end else if (op == ST_OP) begin + end else if (fu == STORE) begin misaligned_exception = { 64'b0, ST_ADDR_MISALIGNED, @@ -468,12 +464,14 @@ module lsu #( if (stall_q) begin vaddr = vaddr_q; data = data_q; + fu = fu_q; operator = operator_q; trans_id = trans_id_q; be = be_q; end else begin // otherwise bypass them vaddr = vaddr_i; data = operand_b_i; + fu = fu_i; operator = operator_i; trans_id = trans_id_i; be = be_i; @@ -483,6 +481,7 @@ module lsu #( always_comb begin : register_stage vaddr_n = vaddr_q; data_n = data_q; + fu_n = fu_q; operator_n = operator_q; trans_id_n = trans_id_q; be_n = be_q; @@ -490,6 +489,7 @@ module lsu #( if (lsu_valid_i) begin vaddr_n = vaddr_i; data_n = operand_b_i; + fu_n = fu_i; operator_n = operator_i; trans_id_n = trans_id_i; be_n = be_i; @@ -508,6 +508,7 @@ module lsu #( // 1st LSU stage vaddr_q <= 64'b0; data_q <= 64'b0; + fu_q <= NONE; operator_q <= ADD; trans_id_q <= '{default: 0}; be_q <= 8'b0; @@ -516,6 +517,7 @@ module lsu #( // 1st LSU stage vaddr_q <= vaddr_n; data_q <= data_n; + fu_q <= fu_n; operator_q <= operator_n; trans_id_q <= trans_id_n; be_q <= be_n;