From 276688f9efea6cac3d06e4c49b42da8049c59aaf Mon Sep 17 00:00:00 2001 From: Graham Edgecombe Date: Sat, 30 Dec 2017 11:34:14 +0000 Subject: [PATCH] Move CSR access to the execute stage This reduces the amount of logic slightly, and also removes the one cycle delay between a CSR read and a subsequent instruction reading from the destination register. --- rv32.sv | 19 ++++++------------- rv32_alu.sv | 5 ++--- rv32_control.sv | 32 ++++++++----------------------- rv32_csrs.sv | 18 +++++++++++++----- rv32_decode.sv | 3 +++ rv32_execute.sv | 50 ++++++++++++++++++++++++++++++++++++------------- rv32_hazard.sv | 3 +-- rv32_mem.sv | 30 +---------------------------- 8 files changed, 71 insertions(+), 89 deletions(-) diff --git a/rv32.sv b/rv32.sv index e895e5d..8c35342 100644 --- a/rv32.sv +++ b/rv32.sv @@ -68,6 +68,7 @@ module rv32 ( logic decode_csr_read; logic decode_csr_write; logic [1:0] decode_csr_write_op; + logic decode_csr_src; logic [1:0] decode_branch_op; logic decode_branch_pc_src; logic [4:0] decode_rd; @@ -84,9 +85,6 @@ module rv32 ( logic execute_valid; logic execute_mem_read; logic execute_mem_write; - logic execute_csr_read; - logic execute_csr_write; - logic [1:0] execute_csr_write_op; logic [1:0] execute_mem_width; logic execute_mem_zero_extend; logic execute_mem_fence; @@ -97,10 +95,10 @@ module rv32 ( /* execute -> mem data */ logic [31:0] execute_result; logic [31:0] execute_rs2_value; - logic [11:0] execute_csr; logic [31:0] execute_branch_pc; /* mem -> writeback control */ + logic mem_valid; logic [4:0] mem_rd; logic mem_rd_write; @@ -123,7 +121,6 @@ module rv32 ( .decode_mem_read_in(decode_mem_read), .decode_mem_fence_in(decode_mem_fence), - .decode_csr_read_in(decode_csr_read), .decode_rd_in(decode_rd), .decode_rd_write_in(decode_rd_write), @@ -220,6 +217,7 @@ module rv32 ( .csr_read_out(decode_csr_read), .csr_write_out(decode_csr_write), .csr_write_op_out(decode_csr_write_op), + .csr_src_out(decode_csr_src), .branch_op_out(decode_branch_op), .branch_pc_src_out(decode_branch_pc_src), .rd_out(decode_rd), @@ -256,12 +254,14 @@ module rv32 ( .csr_read_in(decode_csr_read), .csr_write_in(decode_csr_write), .csr_write_op_in(decode_csr_write_op), + .csr_src_in(decode_csr_src), .branch_op_in(decode_branch_op), .branch_pc_src_in(decode_branch_pc_src), .rd_in(decode_rd), .rd_write_in(decode_rd_write), /* control in (from writeback) */ + .writeback_valid_in(mem_valid), .writeback_rd_in(mem_rd), .writeback_rd_write_in(mem_rd_write), @@ -282,9 +282,6 @@ module rv32 ( .mem_width_out(execute_mem_width), .mem_zero_extend_out(execute_mem_zero_extend), .mem_fence_out(execute_mem_fence), - .csr_read_out(execute_csr_read), - .csr_write_out(execute_csr_write), - .csr_write_op_out(execute_csr_write_op), .branch_op_out(execute_branch_op), .rd_out(execute_rd), .rd_write_out(execute_rd_write), @@ -292,7 +289,6 @@ module rv32 ( /* data out */ .result_out(execute_result), .rs2_value_out(execute_rs2_value), - .csr_out(execute_csr), .branch_pc_out(execute_branch_pc) ); @@ -309,9 +305,6 @@ module rv32 ( .write_in(execute_mem_write), .width_in(execute_mem_width), .zero_extend_in(execute_mem_zero_extend), - .csr_read_in(execute_csr_read), - .csr_write_in(execute_csr_write), - .csr_write_op_in(execute_csr_write_op), .branch_op_in(execute_branch_op), .rd_in(execute_rd), .rd_write_in(execute_rd_write), @@ -319,13 +312,13 @@ module rv32 ( /* data in */ .result_in(execute_result), .rs2_value_in(execute_rs2_value), - .csr_in(execute_csr), .branch_pc_in(execute_branch_pc), /* data in (from memory bus) */ .data_read_value_in(data_read_value_in), /* control out */ + .valid_out(mem_valid), .branch_taken_out(mem_branch_taken), .rd_out(mem_rd), .rd_write_out(mem_rd_write), diff --git a/rv32_alu.sv b/rv32_alu.sv index 93c8cf2..a5c7936 100644 --- a/rv32_alu.sv +++ b/rv32_alu.sv @@ -16,8 +16,7 @@ `define RV32_ALU_SRC2_REG 2'b00 `define RV32_ALU_SRC2_IMM 2'b01 -`define RV32_ALU_SRC2_ZERO 2'b10 -`define RV32_ALU_SRC2_FOUR 2'b11 +`define RV32_ALU_SRC2_FOUR 2'b10 module rv32_alu ( /* control in */ @@ -64,8 +63,8 @@ module rv32_alu ( case (src2_in) `RV32_ALU_SRC2_REG: src2 = rs2_value_in; `RV32_ALU_SRC2_IMM: src2 = imm_value_in; - `RV32_ALU_SRC2_ZERO: src2 = 0; `RV32_ALU_SRC2_FOUR: src2 = 4; + default: src2 = 32'bx; endcase end diff --git a/rv32_control.sv b/rv32_control.sv index 07a2a57..0df09bc 100644 --- a/rv32_control.sv +++ b/rv32_control.sv @@ -33,6 +33,7 @@ module rv32_control_unit ( output logic csr_read_out, output logic csr_write_out, output logic [1:0] csr_write_op_out, + output logic csr_src_out, output logic [1:0] branch_op_out, output logic branch_pc_src_out, output logic rd_write_out @@ -54,6 +55,7 @@ module rv32_control_unit ( csr_read_out = 0; csr_write_out = 0; csr_write_op_out = 2'bx; + csr_src_out = 1'bx; branch_op_out = `RV32_BRANCH_OP_NEVER; branch_pc_src_out = 1'bx; rd_write_out = 0; @@ -479,73 +481,55 @@ module rv32_control_unit ( `RV32_INSTR_CSRRW: begin valid_out = 1; rs1_read_out = 1; - alu_op_out = `RV32_ALU_OP_ADD_SUB; - alu_sub_sra_out = 0; - alu_src1_out = `RV32_ALU_SRC1_REG; - alu_src2_out = `RV32_ALU_SRC2_ZERO; csr_read_out = |rd_in; csr_write_out = 1; csr_write_op_out = `RV32_CSR_WRITE_OP_RW; + csr_src_out = `RV32_CSR_SRC_REG; rd_write_out = |rd_in; end `RV32_INSTR_CSRRS: begin valid_out = 1; rs1_read_out = 1; - alu_op_out = `RV32_ALU_OP_ADD_SUB; - alu_sub_sra_out = 0; - alu_src1_out = `RV32_ALU_SRC1_REG; - alu_src2_out = `RV32_ALU_SRC2_ZERO; csr_read_out = 1; csr_write_out = |rs1_in; csr_write_op_out = `RV32_CSR_WRITE_OP_RS; + csr_src_out = `RV32_CSR_SRC_REG; rd_write_out = 1; end `RV32_INSTR_CSRRC: begin valid_out = 1; rs1_read_out = 1; - alu_op_out = `RV32_ALU_OP_ADD_SUB; - alu_sub_sra_out = 0; - alu_src1_out = `RV32_ALU_SRC1_REG; - alu_src2_out = `RV32_ALU_SRC2_ZERO; csr_read_out = 1; csr_write_out = |rs1_in; csr_write_op_out = `RV32_CSR_WRITE_OP_RC; + csr_src_out = `RV32_CSR_SRC_REG; rd_write_out = 1; end `RV32_INSTR_CSRRWI: begin valid_out = 1; imm_out = `RV32_IMM_ZIMM; - alu_op_out = `RV32_ALU_OP_ADD_SUB; - alu_sub_sra_out = 0; - alu_src1_out = `RV32_ALU_SRC1_ZERO; - alu_src2_out = `RV32_ALU_SRC2_IMM; csr_read_out = |rd_in; csr_write_out = 1; csr_write_op_out = `RV32_CSR_WRITE_OP_RW; + csr_src_out = `RV32_CSR_SRC_IMM; rd_write_out = |rd_in; end `RV32_INSTR_CSRRSI: begin valid_out = 1; imm_out = `RV32_IMM_ZIMM; - alu_op_out = `RV32_ALU_OP_ADD_SUB; - alu_sub_sra_out = 0; - alu_src1_out = `RV32_ALU_SRC1_ZERO; - alu_src2_out = `RV32_ALU_SRC2_IMM; csr_read_out = 1; csr_write_out = |rs1_in; csr_write_op_out = `RV32_CSR_WRITE_OP_RS; + csr_src_out = `RV32_CSR_SRC_IMM; rd_write_out = 1; end `RV32_INSTR_CSRRCI: begin valid_out = 1; imm_out = `RV32_IMM_ZIMM; - alu_op_out = `RV32_ALU_OP_ADD_SUB; - alu_sub_sra_out = 0; - alu_src1_out = `RV32_ALU_SRC1_ZERO; - alu_src2_out = `RV32_ALU_SRC2_IMM; csr_read_out = 1; csr_write_out = |rs1_in; csr_write_op_out = `RV32_CSR_WRITE_OP_RC; + csr_src_out = `RV32_CSR_SRC_IMM; rd_write_out = 1; end endcase diff --git a/rv32_csrs.sv b/rv32_csrs.sv index 2d7a0f4..f3fbf46 100644 --- a/rv32_csrs.sv +++ b/rv32_csrs.sv @@ -13,6 +13,9 @@ `define RV32_CSR_WRITE_OP_RS 2'b01 `define RV32_CSR_WRITE_OP_RC 2'b10 +`define RV32_CSR_SRC_IMM 1'b0 +`define RV32_CSR_SRC_REG 1'b1 + module rv32_csrs ( input clk, @@ -20,22 +23,27 @@ module rv32_csrs ( input read_in, input write_in, input [1:0] write_op_in, + input src_in, /* control in (from writeback) */ input instr_retired_in, /* data in */ - input [31:0] result_in, input [11:0] csr_in, + input [31:0] rs1_value_in, + input [31:0] imm_value_in, /* data out */ output logic [31:0] read_value_out ); logic [31:0] write_value; + logic [31:0] new_value; logic [63:0] cycle; logic [63:0] instret; + assign write_value = src_in ? imm_value_in : rs1_value_in; + always_comb begin case (csr_in) `RV32_CSR_CYCLE: read_value_out = cycle[31:0]; @@ -48,10 +56,10 @@ module rv32_csrs ( endcase case (write_op_in) - `RV32_CSR_WRITE_OP_RW: write_value = result_in; - `RV32_CSR_WRITE_OP_RS: write_value = read_value_out | result_in; - `RV32_CSR_WRITE_OP_RC: write_value = read_value_out & ~result_in; - default: write_value = 32'bx; + `RV32_CSR_WRITE_OP_RW: new_value = write_value; + `RV32_CSR_WRITE_OP_RS: new_value = read_value_out | write_value; + `RV32_CSR_WRITE_OP_RC: new_value = read_value_out & ~write_value; + default: new_value = 32'bx; endcase end diff --git a/rv32_decode.sv b/rv32_decode.sv index c222bb6..94f17f8 100644 --- a/rv32_decode.sv +++ b/rv32_decode.sv @@ -45,6 +45,7 @@ module rv32_decode ( output logic csr_read_out, output logic csr_write_out, output logic [1:0] csr_write_op_out, + output logic csr_src_out, output logic [1:0] branch_op_out, output logic branch_pc_src_out, output logic [4:0] rd_out, @@ -102,6 +103,7 @@ module rv32_decode ( logic csr_read; logic csr_write; logic [1:0] csr_write_op; + logic csr_src; logic [1:0] branch_op; logic branch_pc_src; logic rd_write; @@ -174,6 +176,7 @@ module rv32_decode ( csr_read_out <= csr_read; csr_write_out <= csr_write; csr_write_op_out <= csr_write_op; + csr_src_out <= csr_src; branch_op_out <= branch_op; branch_pc_src_out <= branch_pc_src; rd_out <= rd; diff --git a/rv32_execute.sv b/rv32_execute.sv index 4045ee8..655abc7 100644 --- a/rv32_execute.sv +++ b/rv32_execute.sv @@ -3,6 +3,7 @@ `include "rv32_alu.sv" `include "rv32_branch.sv" +`include "rv32_csrs.sv" module rv32_execute ( input clk, @@ -27,12 +28,14 @@ module rv32_execute ( input csr_read_in, input csr_write_in, input [1:0] csr_write_op_in, + input csr_src_in, input [1:0] branch_op_in, input branch_pc_src_in, input [4:0] rd_in, input rd_write_in, /* control in (from writeback) */ + input writeback_valid_in, input [4:0] writeback_rd_in, input writeback_rd_write_in, @@ -53,9 +56,6 @@ module rv32_execute ( output logic [1:0] mem_width_out, output logic mem_zero_extend_out, output logic mem_fence_out, - output logic csr_read_out, - output logic csr_write_out, - output logic [1:0] csr_write_op_out, output logic [1:0] branch_op_out, output logic [4:0] rd_out, output logic rd_write_out, @@ -63,9 +63,9 @@ module rv32_execute ( /* data out */ output logic [31:0] result_out, output logic [31:0] rs2_value_out, - output logic [11:0] csr_out, output logic [31:0] branch_pc_out ); + /* bypassing */ logic [31:0] rs1_value; logic [31:0] rs2_value; @@ -85,7 +85,8 @@ module rv32_execute ( rs2_value = rs2_value_in; end - logic [31:0] result; + /* ALU */ + logic [31:0] alu_result; rv32_alu alu ( /* control in */ @@ -101,9 +102,34 @@ module rv32_execute ( .imm_value_in(imm_value_in), /* data out */ - .result_out(result) + .result_out(alu_result) ); + /* csr file */ + logic [31:0] csr_read_value; + + rv32_csrs csrs ( + .clk(clk), + + /* control in */ + .read_in(csr_read_in), + .write_in(csr_write_in), + .write_op_in(csr_write_op_in), + .src_in(csr_src_in), + + /* control in (from writeback) */ + .instr_retired_in(writeback_valid_in), + + /* data in */ + .rs1_value_in(rs1_value), + .imm_value_in(imm_value_in), + .csr_in(csr_in), + + /* data out */ + .read_value_out(csr_read_value) + ); + + /* branch target calculation */ logic [31:0] branch_pc; rv32_branch_pc_mux branch_pc_mux ( @@ -127,23 +153,21 @@ module rv32_execute ( mem_width_out <= mem_width_in; mem_zero_extend_out <= mem_zero_extend_in; mem_fence_out <= mem_fence_in; - csr_read_out <= csr_read_in; - csr_write_out <= csr_write_in; - csr_write_op_out <= csr_write_op_in; branch_op_out <= branch_op_in; rd_out <= rd_in; rd_write_out <= rd_write_in; - result_out <= result; rs2_value_out <= rs2_value; - csr_out <= csr_in; branch_pc_out <= branch_pc; + if (csr_read_in) + result_out <= csr_read_value; + else + result_out <= alu_result; + if (flush_in) begin valid_out <= 0; mem_read_out <= 0; mem_write_out <= 0; - csr_read_out <= 0; - csr_write_out <= 0; branch_op_out <= `RV32_BRANCH_OP_NEVER; rd_write_out <= 0; end diff --git a/rv32_hazard.sv b/rv32_hazard.sv index a854455..6889080 100644 --- a/rv32_hazard.sv +++ b/rv32_hazard.sv @@ -11,7 +11,6 @@ module rv32_hazard_unit ( input decode_mem_read_in, input decode_mem_fence_in, - input decode_csr_read_in, input [4:0] decode_rd_in, input decode_rd_write_in, @@ -49,7 +48,7 @@ module rv32_hazard_unit ( assign rs1_matches = decode_rs1_unreg_in == decode_rd_in && decode_rs1_read_unreg_in; assign rs2_matches = decode_rs2_unreg_in == decode_rd_in && decode_rs2_read_unreg_in; assign fetch_wait_for_bus = instr_read_in && !instr_ready_in; - assign fetch_wait_for_mem_read = (rs1_matches || rs2_matches) && |decode_rd_in && (decode_mem_read_in || decode_csr_read_in) && decode_rd_write_in; + assign fetch_wait_for_mem_read = (rs1_matches || rs2_matches) && |decode_rd_in && decode_mem_read_in && decode_rd_write_in; assign fetch_wait_for_mem_fence = decode_mem_fence_unreg_in || decode_mem_fence_in || execute_mem_fence_in; assign mem_wait_for_bus = (data_read_in || data_write_in) && !data_ready_in; diff --git a/rv32_mem.sv b/rv32_mem.sv index 4a43e45..d522a31 100644 --- a/rv32_mem.sv +++ b/rv32_mem.sv @@ -20,9 +20,6 @@ module rv32_mem ( input write_in, input [1:0] width_in, input zero_extend_in, - input csr_read_in, - input csr_write_in, - input [1:0] csr_write_op_in, input [1:0] branch_op_in, input [4:0] rd_in, input rd_write_in, @@ -30,7 +27,6 @@ module rv32_mem ( /* data in */ input [31:0] result_in, input [31:0] rs2_value_in, - input [11:0] csr_in, input [31:0] branch_pc_in, /* data in (from data memory bus) */ @@ -69,28 +65,6 @@ module rv32_mem ( assign branch_pc_out = branch_pc_in; - /* csr file */ - logic [31:0] csr_read_value; - - rv32_csrs csrs ( - .clk(clk), - - /* control in */ - .read_in(csr_read_in), - .write_in(csr_write_in), - .write_op_in(csr_write_op_in), - - /* control in (from writeback) */ - .instr_retired_in(valid_out), - - /* data in */ - .result_in(result_in), - .csr_in(csr_in), - - /* data out */ - .read_value_out(csr_read_value) - ); - /* memory access unit */ logic [31:0] mem_read_value; @@ -183,9 +157,7 @@ module rv32_mem ( rd_out <= rd_in; rd_write_out <= rd_write_in; - if (csr_read_in) - rd_value_out <= csr_read_value; - else if (read_in) + if (read_in) rd_value_out <= mem_read_value; else rd_value_out <= result_in;