diff --git a/controller.sv b/controller.sv index ebcfb135..54108191 100644 --- a/controller.sv +++ b/controller.sv @@ -79,8 +79,9 @@ module controller output logic prepost_useincr_o, // When not active bypass the alu result=op_a input logic data_misaligned_i, - output logic sp_we_o, // Write enable to special purpose register - input logic sp_we_ex_i, // Manipulated sp_we from ex stage : FW + // CSR manipulation + output logic csr_access_o, + output logic [1:0] csr_op_o, // LD/ST unit signals output logic data_we_o, // Write enable to data memory @@ -171,8 +172,6 @@ module controller logic lsu_stall; logic misalign_stall; - logic mtspr_stall; - logic mfspr_stall; logic instr_ack_stall; logic load_stall; logic jr_stall; @@ -225,7 +224,7 @@ module controller mult_use_carry_o = 1'b0; mult_mac_en_o = 1'b0; - regfile_wdata_mux_sel_o = 1'b1; + regfile_wdata_mux_sel_o = 1'b1; // TODO: Remove, no longer used regfile_we = 1'b0; regfile_alu_we = 1'b0; regfile_alu_waddr_mux_sel_o = 2'b01; @@ -237,7 +236,8 @@ module controller hwloop_cnt_mux_sel_o = 2'b00; immediate_mux_sel_o = `IMM_I; - sp_we_o = 1'b0; + csr_access_o = 1'b0; + csr_op_o = `CSR_OP_NONE; data_we = 1'b0; data_type_o = 2'b00; @@ -311,6 +311,7 @@ module controller begin unique case (instr_rdata_i[6:0]) + /* `OPCODE_CUST0: begin // Custom-0 opcode: Get core id // TODO: Temporary hack? alu_op_a_mux_sel_o = `OP_A_ZERO; @@ -324,6 +325,7 @@ module controller // TODO: Replace with WFI instruction as soon as compiler support available pipe_flush_o = 1'b1; end + */ ////////////////////////////////////// @@ -431,7 +433,6 @@ module controller immediate_mux_sel_o = `IMM_I; alu_operator = `ALU_ADD; data_req = 1'b1; - regfile_wdata_mux_sel_o = 1'b1; regfile_we = 1'b1; rega_used = 1'b1; data_type_o = 2'b00; @@ -934,63 +935,56 @@ module controller */ + `OPCODE_SYSTEM: begin - unique case (instr_rdata_i) inside - `INSTR_EBREAK: begin - // debugger trap - trap_insn_o = 1'b1; - end - `INSTR_ERET: begin - pc_mux_sel_o = `PC_ERET; - restore_sr_o = 1'b1; // TODO: Check if needed - clear_isr_running_o = 1'b1; // TODO: Check if needed - end - `INSTR_WFI: begin - // flush pipeline - pipe_flush_o = 1'b1; - end - default: illegal_insn_o = 1'b1; - endcase // unique case (instr_rdata_i) - end - - /* - - `OPCODE_MTSPR: begin // Move To Special-Purpose Register - alu_operator = `ALU_OR; - alu_op_b_mux_sel_o = `OP_B_IMM; - sp_we_o = 1'b1; - rega_used = 1'b1; - regb_used = 1'b1; - end - - `OPCODE_MFSPR: begin // Move From Special-Purpose Register - alu_operator = `ALU_OR; - alu_op_b_mux_sel_o = `OP_B_IMM; - immediate_mux_sel_o = `IMM_16; - regfile_wdata_mux_sel_o = 1'b0; - regfile_we = 1'b1; - rega_used = 1'b1; - end - - `OPCODE_SYNC: - begin - if (instr_rdata_i[25] == 1'b1) // sync operation - begin // l.psync, flush pipeline. Actually this also does l.msync - pipe_flush_o = 1'b1; + if (instr_rdata_i[14:12] == 3'b000) + begin + // non CSR realted SYSTEM instructions + unique case (instr_rdata_i) inside + `INSTR_EBREAK: begin + // debugger trap + trap_insn_o = 1'b1; + end + `INSTR_ERET: begin + pc_mux_sel_o = `PC_ERET; + clear_isr_running_o = 1'b1; + end + `INSTR_WFI: begin + // flush pipeline + pipe_flush_o = 1'b1; + end + default: illegal_insn_o = 1'b1; + endcase // unique case (instr_rdata_i) end else begin - if (instr_rdata_i[24:16] == 9'h100) - begin - // l.trap - // Currently we ignore the immediate - trap_insn_o = 1'b1; + // instructions to read/modify CSRs + csr_access_o = 1'b1; + regfile_alu_we = 1'b1; + alu_op_b_mux_sel_o = `OP_B_IMM; + immediate_mux_sel_o = `IMM_I; // CSR address is encoded in I imm + + if (instr_rdata_i[14] == 1'b1) begin + // rs1 field is immediate + alu_op_a_mux_sel_o = `OP_A_ZIMM; + end else begin + rega_used = 1'b1; + alu_op_a_mux_sel_o = `OP_A_REGA_OR_FWD; end - else - illegal_insn_o = 1'b1; + + unique case (instr_rdata_i[13:12]) + 2'b01: csr_op_o = `CSR_OP_WRITE; + 2'b10: csr_op_o = `CSR_OP_SET; + 2'b11: csr_op_o = `CSR_OP_CLEAR; + default: illegal_insn_o = 1'b1; + endcase end + end + + /* + /////////////////////////////////////////////// // _ ___ ___ ___ ___ ____ // // | | | \ \ / / | / _ \ / _ \| _ \ // @@ -1113,30 +1107,10 @@ module controller //////////////////////////////////////////////////////////////////////////////////////////// always_comb begin - mfspr_stall = 1'b0; - mtspr_stall = 1'b0; load_stall = 1'b0; jr_stall = 1'b0; deassert_we = 1'b0; - /* - // Stall because of l.mfspr with dependency - if ((regfile_wdata_mux_sel_ex_i == 1'b0) && (regfile_we_ex_i == 1'b1) && - ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) - begin - deassert_we = 1'b1; - mfspr_stall = 1'b1; - end - - // Stall because of l.mtspr (always...) - // mtspr in ex stage, normal instruction in id stage which can change an spr reg - if ((sp_we_ex_i == 1'b1) && (instr_rdata_i[31:26] != `OPCODE_MTSPR)) - begin - deassert_we = 1'b1; - mtspr_stall = 1'b1; - end - */ - // Stall because of load operation if ((data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) && ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) @@ -1200,8 +1174,8 @@ module controller // we unstall the if_stage if the debug unit wants to set a new // pc, so that the new value gets written into current_pc_if and is // used by the instr_core_interface - stall_if_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i | (~pc_valid_i); - stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i; + stall_if_o = instr_ack_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i | (~pc_valid_i); + stall_id_o = instr_ack_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i; stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i; stall_wb_o = lsu_stall | dbg_stall_i; end diff --git a/cs_registers.sv b/cs_registers.sv new file mode 100644 index 00000000..08619cd6 --- /dev/null +++ b/cs_registers.sv @@ -0,0 +1,166 @@ +//////////////////////////////////////////////////////////////////////////////// +// Company: IIS @ ETHZ - Federal Institute of Technology // +// // +// Engineer: Sven Stucki - svstucki@student.ethz.ch.ch // +// // +// Additional contributions by: // +// // +// // +// Create Date: 25/05/2015 // +// Design Name: Pipelined Processor // +// Module Name: cs_registers.sv // +// Project Name: Processor // +// Language: SystemVerilog // +// // +// Description: Control and Status Registers (CSRs) loosely following the // +// RiscV draft priviledged instruction set spec (v1.7) // +// // +// // +// Revision: // +// // +// // +// // +//////////////////////////////////////////////////////////////////////////////// + +`include "defines.sv" + + +module cs_registers +( + // Clock and Reset + input logic clk, + input logic rst_n, + + // Core and Cluster ID + input logic [4:0] core_id_i, + input logic [4:0] cluster_id_i, + + // Interface to special purpose registers (SRAM like) + input logic [11:0] csr_addr_i, + input logic [31:0] csr_wdata_i, + input logic [1:0] csr_op_i, + output logic [31:0] csr_rdata_o, + + // Interrupts + input logic [31:0] curr_pc_if_i, + input logic [31:0] curr_pc_id_i, + input logic save_pc_if_i, + input logic save_pc_id_i, // TODO: check if both IF/ID pc save is needed + output logic [31:0] epcr_o, + output logic irq_enable_o, // TODO: check if needed + + // HWLoop Signals + input logic [`HWLOOP_REGS-1:0] [31:0] hwlp_start_addr_i, + input logic [`HWLOOP_REGS-1:0] [31:0] hwlp_end_addr_i, + input logic [`HWLOOP_REGS-1:0] [31:0] hwlp_counter_i, + + output logic [31:0] hwlp_start_o, + output logic [31:0] hwlp_end_o, + output logic [31:0] hwlp_counter_o, + output logic [1:0] hwlp_regid_o, + output logic [2:0] hwlp_we_o, + + // Signals for NPC register + output logic [31:0] npc_o, // TODO: check if needed + output logic set_npc_o // TODO: check if needed +); + + + logic is_constant; + logic is_register; + + logic [31:0] constant_rdata_int; + logic [31:0] register_rdata_int; + + logic is_readonly; + logic illegal_address; + + // CSRs and index of CSR to access + int csr_index; // TODO: check synthesis result + logic [31:0] csr [0:`CSR_MAX_IDX]; + + + assign is_readonly = (csr_addr_i[11:10] == 2'b11); + assign illegal_address = ~is_constant && ~is_register; + + + // output mux + always_comb + begin + csr_rdata_o = 32'bx; + + if (is_constant == 1'b1) + csr_rdata_o = constant_rdata_int; + else if (is_register == 1'b1) + csr_rdata_o = register_rdata_int; + end + + + // address decoder for constant CSRs + always_comb + begin + is_constant = 1'b1; + unique case (csr_addr_i) + 12'hF00: constant_rdata_int = 32'h00_00_01_00; // mcpuid: RV32I + 12'hF01: constant_rdata_int = 32'h00_00_80_00; // mimpid: PULP3, anonymous source (no allocated ID) + 12'hF10: constant_rdata_int = {22'b0, cluster_id_i, core_id_i}; // mhartid: unique hardware thread id + + default: is_constant = 1'b0; + endcase + end + + // address decoder for regular CSRs + always_comb + begin + is_register = 1'b1; + unique case (csr_addr_i) + 12'h340: csr_index = `CSR_IDX_MSCRATCH; + 12'h341: csr_index = `CSR_IDX_MEPC; + + default: is_register = 1'b0; + endcase + end + + assign register_rdata_int = csr[csr_index]; + + + // directly output some registers + assign epcr_o = csr[`CSR_IDX_MEPC]; + + + // actual registers + always_ff @(posedge clk, negedge rst_n) + begin + if (rst_n == 1'b0) + begin + csr <= '{default: 32'b0}; // new SV syntax TODO: check synthesis result + end + else + begin + // write CSR through instruction + if (is_readonly == 1'b0) begin + unique case (csr_op_i) + `CSR_OP_NONE: ; + `CSR_OP_WRITE: csr[csr_index] <= csr_wdata_i; + `CSR_OP_SET: csr[csr_index] <= csr_wdata_i | register_rdata_int; + `CSR_OP_CLEAR: csr[csr_index] <= csr_wdata_i & ~(register_rdata_int); + endcase + end + + // writes from exception controller get priority + + // write exception PC + if (save_pc_if_i == 1'b1) + csr[`CSR_IDX_MEPC] <= curr_pc_if_i; + else if (save_pc_id_i == 1'b1) + csr[`CSR_IDX_MEPC] <= curr_pc_id_i; + end + end + + + // synopsys translate_off + // make sure decoding works correctly + //assert property (!((is_constant == 1'b1) && (is_register == 1'b1))); // not supported by ModelSim :/ + // synopsys translate_on + +endmodule diff --git a/ex_stage.sv b/ex_stage.sv index bd01f940..18bc9d65 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -35,10 +35,9 @@ // wb = writeback // sp = special registers - - `include "defines.sv" + module ex_stage ( input logic clk, @@ -88,7 +87,9 @@ module ex_stage input logic set_overflow_i, input logic set_carry_i, - input logic sp_we_i, + // CSR access + input logic csr_access_i, + input logic [31:0] csr_rdata_i, // Output of EX stage pipeline @@ -101,7 +102,6 @@ module ex_stage output logic set_overflow_o, output logic set_carry_o, - output logic [15:0] sp_addr_wb_o, output logic [4:0] regfile_waddr_wb_o, output logic regfile_wdata_mux_sel_wb_o, output logic regfile_we_wb_o, @@ -111,8 +111,6 @@ module ex_stage output logic [31:0] hwloop_end_data_o, output logic [31:0] hwloop_cnt_data_o, - output logic sp_we_wb_o, - // Forwarding ports : to ID stage output logic [4:0] regfile_alu_waddr_fw_o, output logic regfile_alu_we_fw_o, @@ -149,7 +147,18 @@ module ex_stage assign regfile_alu_we_fw_o = regfile_alu_we_i; assign regfile_alu_waddr_fw_o = regfile_alu_waddr_i; - assign regfile_alu_wdata_fw_o = (mult_en_i == 1'b0) ? alu_result : mult_result; + + always_comb + begin + regfile_alu_wdata_fw_o = alu_result; + + if (mult_en_i == 1'b1) + regfile_alu_wdata_fw_o = mult_result; + + if (csr_access_i == 1'b1) + regfile_alu_wdata_fw_o = csr_rdata_i; + end + // assign regfile_alu_wdata_fw_o = (mult_en_i == 1'b0) ? alu_result : mult_result; // generate flags: goes to special purpose register assign set_overflow_o = (stall_ex_i == 1'b0) ? set_overflow_i : 1'b0; @@ -244,23 +253,19 @@ module ex_stage begin : EX_WB_Pipeline_Register if (rst_n == 1'b0) begin - sp_addr_wb_o <= 16'h0000; regfile_waddr_wb_o <= 5'b0_0000; regfile_wdata_mux_sel_wb_o <= 1'b0; regfile_we_wb_o <= 1'b0; regfile_rb_data_wb_o <= 32'h0000_0000; - sp_we_wb_o <= 1'b0; end else begin if (stall_wb_i == 1'b0) begin - sp_addr_wb_o <= alu_result[15:0]; // this is only used for SPR address regfile_we_wb_o <= regfile_we_i; regfile_waddr_wb_o <= regfile_waddr_i; regfile_wdata_mux_sel_wb_o <= regfile_wdata_mux_sel_i; regfile_rb_data_wb_o <= regfile_rb_data_i; - sp_we_wb_o <= sp_we_i; end end end diff --git a/id_stage.sv b/id_stage.sv index 9da69da4..c78528d5 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -7,16 +7,17 @@ // Additional contributions by: // // Igor Loi - igor.loi@unibo.it // // Andreas Traber - atraber@student.ethz.ch // +// Sven Stucki - svstucki@student.ethz.ch // // // // // // Create Date: 19/09/2013 // // Design Name: Decode stage // // Module Name: id_stage.sv // -// Project Name: OR10N // +// Project Name: RiscV // // Language: SystemVerilog // // // -// Description: Decode stage of the OR10N core. It decodes the instructions// -// and hosts the register file and the pipe controller // +// Description: Decode stage of the core. It decodes the instructions // +// and hosts the register file. // // // // Revision: // // Revision v0.1 - File Created // @@ -38,8 +39,6 @@ module id_stage input logic clk, input logic rst_n, - input logic [4:0] core_id_i, - input logic fetch_enable_i, output logic core_busy_o, @@ -106,7 +105,8 @@ module id_stage output logic [`HWLOOP_REGS-1:0] hwloop_dec_cnt_o, output logic [31:0] hwloop_targ_addr_o, - output logic sp_we_ex_o, + output logic csr_access_ex_o, + output logic [1:0] csr_op_ex_o, // Interface to load store unit output logic data_we_ex_o, @@ -241,9 +241,6 @@ module id_stage logic regfile_we_id; logic [1:0] regfile_alu_waddr_mux_sel; // TODO: FixMe -> 1bit - // Special-Purpose Register Write Control - logic sp_we_id; - // Data Memory Control logic data_we_id; logic [1:0] data_type_id; @@ -260,6 +257,10 @@ module id_stage logic hwloop_jump; logic hwloop_enable; + // CSR control + logic csr_access; + logic [1:0] csr_op; + // Supervision Register logic set_flag; logic set_carry; @@ -295,6 +296,9 @@ module id_stage assign imm_uj_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[19:12], instr_rdata_i[20], instr_rdata_i[30:21], 1'b0 }; + // immediate for CSR manipulatin (zero extended) + assign imm_z_type = { 27'b0, instr_rdata_i[`REG_S1] }; + // source registers assign regfile_addr_ra_id = instr_rdata_i[`REG_S1]; assign regfile_addr_rb_id = instr_rdata_i[`REG_S2]; @@ -342,7 +346,7 @@ module id_stage begin : hwloop_cnt_mux case (hwloop_cnt_mux_sel) 2'b00: hwloop_cnt = 32'b0; - //2'b01: hwloop_cnt = immediate21z_id; // TODO: FixMe + //2'b01: hwloop_cnt = immediate21z_id; // TODO: FIXME use correct immediate when adding hwloops //2'b10: hwloop_cnt = immediate13z_id; 2'b11: hwloop_cnt = operand_a_fw_id; default: hwloop_cnt = 32'b0; @@ -388,6 +392,7 @@ module id_stage default: alu_operand_a = operand_a_fw_id; `OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; `OP_A_CURRPC: alu_operand_a = current_pc; + `OP_A_ZIMM: alu_operand_a = imm_z_type; `OP_A_ZERO: alu_operand_a = 32'b0; endcase; // case (alu_op_a_mux_sel) end @@ -421,7 +426,6 @@ module id_stage `IMM_S: immediate_b = imm_s_type; `IMM_U: immediate_b = imm_u_type; `IMM_HEX4: immediate_b = 32'h4; - `IMM_CID: immediate_b = core_id_i; // TODO: Temporary hack default: immediate_b = 32'h4; endcase; // case (immediate_mux_sel) end @@ -432,7 +436,7 @@ module id_stage case (alu_op_b_mux_sel) default: operand_b = operand_b_fw_id; `OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; - //`OP_B_REGC_OR_FWD: operand_b = alu_operand_c; + // `OP_B_REGC_OR_FWD: operand_b = alu_operand_c; `OP_B_IMM: operand_b = immediate_b; endcase // case (alu_op_b_mux_sel) end @@ -580,9 +584,9 @@ module id_stage .prepost_useincr_o ( prepost_useincr ), .data_misaligned_i ( data_misaligned_i ), - // SP register signals - .sp_we_o ( sp_we_id ), - .sp_we_ex_i ( sp_we_ex_o ), + // CSR control signals + .csr_access_o ( csr_access ), + .csr_op_o ( csr_op ), // Data bus interface .data_we_o ( data_we_id ), @@ -773,7 +777,6 @@ module id_stage mult_use_carry_ex_o <= 1'b0; mult_mac_en_ex_o <= 1'b0; - regfile_waddr_ex_o <= 5'b0; regfile_wdata_mux_sel_ex_o <= 1'b0; regfile_we_ex_o <= 1'b0; @@ -782,7 +785,8 @@ module id_stage regfile_alu_we_ex_o <= 1'b0; prepost_useincr_ex_o <= 1'b0; - sp_we_ex_o <= 1'b0; + csr_access_ex_o <= 1'b0; + csr_op_ex_o <= 2'b0; data_we_ex_o <= 1'b0; data_type_ex_o <= 2'b0; @@ -854,8 +858,8 @@ module id_stage prepost_useincr_ex_o <= prepost_useincr; - - sp_we_ex_o <= sp_we_id; + csr_access_ex_o <= csr_access; + csr_op_ex_o <= csr_op; data_we_ex_o <= data_we_id; data_type_ex_o <= data_type_id; diff --git a/include/defines.sv b/include/defines.sv index bcee7c52..511c410d 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -102,6 +102,12 @@ `define INSTR_FENCE { 4'b0000, {8 {1'b?}}, {13 {1'b0}}, `OPCODE_FENCE } `define INSTR_FENCEI { {17 {1'b0}}, 3'b001, {5 {1'b0}}, `OPCODE_FENCE } // SYSTEM +`define INSTR_CSRRW { {17 {1'b?}}, 3'b001, {5 {1'b?}}, `OPCODE_SYSTEM } +`define INSTR_CSRRS { {17 {1'b?}}, 3'b010, {5 {1'b?}}, `OPCODE_SYSTEM } +`define INSTR_CSRRC { {17 {1'b?}}, 3'b011, {5 {1'b?}}, `OPCODE_SYSTEM } +`define INSTR_CSRRWI { {17 {1'b?}}, 3'b101, {5 {1'b?}}, `OPCODE_SYSTEM } +`define INSTR_CSRRSI { {17 {1'b?}}, 3'b110, {5 {1'b?}}, `OPCODE_SYSTEM } +`define INSTR_CSRRCI { {17 {1'b?}}, 3'b111, {5 {1'b?}}, `OPCODE_SYSTEM } `define INSTR_ECALL { 12'b000000000000, {13 {1'b0}}, `OPCODE_SYSTEM } `define INSTR_EBREAK { 12'b000000000001, {13 {1'b0}}, `OPCODE_SYSTEM } `define INSTR_ERET { 12'b000100000000, {13 {1'b0}}, `OPCODE_SYSTEM } @@ -245,20 +251,27 @@ endfunction // prettyPrintInstruction `define ALU_CMP_ALL 2'b10 -//////////////////////////////////////////////////////// -// ____ ____ ____ _ _ // -// / ___|| _ \ | _ \ ___ __ _(_)___| |_ ___ _ __ // -// \___ \| |_) | | |_) / _ \/ _` | / __| __/ _ \ '__| // -// ___) | __/ | _ < __/ (_| | \__ \ || __/ | // -// |____/|_| |_| \_\___|\__, |_|___/\__\___|_| // -// |___/ // -//////////////////////////////////////////////////////// +///////////////////////////////////////////////////////// +// ____ ____ ____ _ _ // +// / ___/ ___| | _ \ ___ __ _(_)___| |_ ___ _ __ // +// | | \___ \ | |_) / _ \/ _` | / __| __/ _ \ '__| // +// | |___ ___) | | _ < __/ (_| | \__ \ || __/ | // +// \____|____/ |_| \_\___|\__, |_|___/\__\___|_| // +// |___/ // +///////////////////////////////////////////////////////// +// internal CSR addresses `define CSR_IDX_MSCRATCH 0 `define CSR_IDX_MEPC 1 `define CSR_MAX_IDX 1 +// CSR operations +`define CSR_OP_NONE 2'b00 +`define CSR_OP_WRITE 2'b01 +`define CSR_OP_SET 2'b10 +`define CSR_OP_CLEAR 2'b11 + // Special-Purpose Register Addresses // see OpenRISC manual p. 22ff `define SP_GRP_SYS 5'h00 @@ -301,8 +314,8 @@ endfunction // prettyPrintInstruction // operand a selection `define OP_A_REGA_OR_FWD 2'b00 -`define OP_A_CURRPC 2'b10 -`define OP_A_IMM16 2'b11 +`define OP_A_CURRPC 2'b01 +`define OP_A_ZIMM 2'b10 `define OP_A_ZERO 2'b11 // operand b selection @@ -315,12 +328,10 @@ endfunction // prettyPrintInstruction `define OP_C_JT 1'b1 // operand b immediate selection -`define IMM_I 3'b000 -`define IMM_S 3'b001 -`define IMM_U 3'b010 -`define IMM_HEX4 3'b011 -`define IMM_CID 3'b100 // core id -`define IMM_CLID 3'b100 // cluster id +`define IMM_I 2'b00 +`define IMM_S 2'b01 +`define IMM_U 2'b10 +`define IMM_HEX4 2'b11 // PC mux selector defines `define PC_INCR 3'b000 diff --git a/riscv_core.sv b/riscv_core.sv index d96f3355..af29c6c6 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -148,14 +148,14 @@ module riscv_core logic regfile_alu_we_fw; logic [31:0] regfile_alu_wdata_fw; - // Special-Purpose Register Control - logic sp_we_ex; // Output of ID_stage to EX stage - logic sp_we_wb; - logic [31:0] sp_rdata; - logic [11:0] sp_addr; - logic [31:0] sp_wdata; - logic sp_we; + // CSR control + logic csr_access_ex; + logic [1:0] csr_op_ex; + logic [1:0] csr_op; + logic [11:0] csr_addr; + logic [31:0] csr_rdata; + logic [31:0] csr_wdata; // Data Memory Control: From ID stage (id-ex pipe) <--> load store unit logic data_we_ex; @@ -181,9 +181,6 @@ module riscv_core logic sr_flag_fw; logic carry_sp; - // Calculation Result - logic [15:0] sp_addr_wb; - // Signals between instruction core interface and pipe (if and id stages) logic [31:0] instr_rdata_int; // read instruction from the instruction core interface to if_stage logic instr_req_int; // Id stage asserts a req to instruction core interface @@ -241,7 +238,7 @@ module riscv_core logic dbg_reg_mux; logic dbg_sp_mux; logic dbg_reg_we; - logic [15:0] dbg_reg_addr; + logic [11:0] dbg_reg_addr; logic [31:0] dbg_reg_wdata; logic [31:0] dbg_reg_rdata; logic [31:0] dbg_rdata; @@ -354,8 +351,6 @@ module riscv_core .clk ( clk ), .rst_n ( rst_n ), - .core_id_i ( core_id_i ), // TODO: Temporary hack - // Processor Enable .fetch_enable_i ( fetch_enable_i ), @@ -412,6 +407,10 @@ module riscv_core .regfile_alu_we_ex_o ( regfile_alu_we_ex ), .regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ), + // CSR ID/EX + .csr_access_ex_o ( csr_access_ex ), + .csr_op_ex_o ( csr_op_ex ), + // hwloop signals .hwloop_we_ex_o ( hwlp_we_ex ), .hwloop_regid_ex_o ( hwlp_regid_ex ), @@ -420,8 +419,6 @@ module riscv_core .hwloop_dec_cnt_o ( hwlp_dec_cnt ), .hwloop_targ_addr_o ( hwlp_targ_addr ), - .sp_we_ex_o ( sp_we_ex ), - .prepost_useincr_ex_o ( useincr_addr_ex ), .data_misaligned_i ( data_misaligned ), @@ -515,11 +512,16 @@ module riscv_core .mult_use_carry_i ( mult_use_carry_ex ), .mult_mac_en_i ( mult_mac_en_ex ), +/* // interface with Special registers .carry_o ( carry_ex ), .overflow_o ( overflow_ex ), .set_overflow_o ( set_overflow_fw_ex ), // to special registers .set_carry_o ( set_carry_fw_ex ), // to special registers +*/ + // interface with CSRs + .csr_access_i ( csr_access_ex ), + .csr_rdata_i ( csr_rdata ), // input from ID stage .stall_ex_i ( stall_ex ), @@ -545,11 +547,8 @@ module riscv_core .set_carry_i ( set_carry_ex ), .regfile_rb_data_i ( regfile_rb_data_ex ), - .sp_we_i ( sp_we_ex ), - // Output of ex stage pipeline - .sp_addr_wb_o ( sp_addr_wb ), .regfile_waddr_wb_o ( regfile_waddr_fw_wb_o ), .regfile_wdata_mux_sel_wb_o ( regfile_wdata_mux_sel_wb ), .regfile_we_wb_o ( regfile_we_wb ), @@ -562,8 +561,6 @@ module riscv_core .hwloop_end_data_o ( hwlp_end_data_ex ), .hwloop_cnt_data_o ( hwlp_cnt_data_ex ), - .sp_we_wb_o ( sp_we_wb ), - // To IF: Jump and branch target and decision .jump_target_o ( jump_target ), .branch_decision_o ( branch_decision ), @@ -593,7 +590,6 @@ module riscv_core // Mux selector of regfile wdata .regfile_wdata_mux_sel_i ( regfile_wdata_mux_sel_wb ), // Mux inputs - .sp_rdata_i ( sp_rdata ), .data_rdata_i ( data_rdata_int ), .lsu_data_reg_i ( lsu_data_reg ), // Mux output @@ -662,10 +658,56 @@ module riscv_core .core_id_i ( core_id_i ), .cluster_id_i ( cluster_id_i ), + // Interface to Special register (SRAM LIKE) + .csr_addr_i ( csr_addr ), + .csr_wdata_i ( csr_wdata ), + .csr_op_i ( csr_op ), + .csr_rdata_o ( csr_rdata ), + + // HWLoop signals + .hwlp_start_addr_i ( hwlp_start_addr ), + .hwlp_end_addr_i ( hwlp_end_addr ), + .hwlp_counter_i ( hwlp_counter ), + + .hwlp_start_o ( sp_hwlp_start ), + .hwlp_end_o ( sp_hwlp_end ), + .hwlp_counter_o ( sp_hwlp_cnt ), + .hwlp_regid_o ( sp_hwlp_regid ), + .hwlp_we_o ( sp_hwlp_we ), + + .curr_pc_if_i ( current_pc_if ), // from IF stage + .curr_pc_id_i ( current_pc_id ), // from IF stage + .save_pc_if_i ( save_pc_if ), + .save_pc_id_i ( save_pc_id ), + .epcr_o ( epcr ), + .irq_enable_o ( irq_enable ), + + .npc_o ( dbg_npc ), // PC from debug unit + .set_npc_o ( dbg_set_npc ) // set PC to new value + ); + + // Mux for SPR access through Debug Unit + assign csr_addr = (dbg_sp_mux == 1'b0) ? alu_operand_b_ex[11:0] : dbg_reg_addr; + assign csr_wdata = (dbg_sp_mux == 1'b0) ? alu_operand_a_ex : dbg_reg_wdata; + assign csr_op = (dbg_sp_mux == 1'b0) ? csr_op_ex + : (dbg_reg_we == 1'b1 ? `CSR_OP_WRITE : `CSR_OP_NONE); + assign dbg_rdata = (dbg_sp_mux == 1'b0) ? dbg_reg_rdata : csr_rdata; + + + /* + sp_registers sp_registers_i + ( + .clk ( clk ), + .rst_n ( rst_n ), + + // Core and Cluster ID from outside + .core_id_i ( core_id_i ), + .cluster_id_i ( cluster_id_i ), + // Interface to Special register (SRAM LIKE) .sp_addr_i ( sp_addr ), .sp_wdata_i ( sp_wdata ), - .sp_we_i ( sp_we ), + .sp_op_i ( sp_op ), .sp_rdata_o ( sp_rdata ), // Stall direct write @@ -698,8 +740,10 @@ module riscv_core // Mux for SPR access through Debug Unit assign sp_addr = (dbg_sp_mux == 1'b0) ? sp_addr_wb : dbg_reg_addr; assign sp_wdata = (dbg_sp_mux == 1'b0) ? regfile_rb_data_wb : dbg_reg_wdata; - assign sp_we = (dbg_sp_mux == 1'b0) ? sp_we_wb : dbg_reg_we; + assign sp_op = (dbg_sp_mux == 1'b0) ? sp_op_wb + : (dbg_reg_we == 1'b1 ? `CSR_OP_WRITE : `CSR_OP_NONE); assign dbg_rdata = (dbg_sp_mux == 1'b0) ? dbg_reg_rdata : sp_rdata; + */ /* @@ -884,10 +928,18 @@ module riscv_core // FENCE `INSTR_FENCE: printMnemonic("FENCE"); `INSTR_FENCEI: printMnemonic("FENCEI"); - // SYSTEM + // SYSTEM (CSR manipulation) + `INSTR_CSRRW: printCSRInstr("CSRRW"); + `INSTR_CSRRS: printCSRInstr("CSRRS"); + `INSTR_CSRRC: printCSRInstr("CSRRC"); + `INSTR_CSRRWI: printCSRInstr("CSRRWI"); + `INSTR_CSRRSI: printCSRInstr("CSRRSI"); + `INSTR_CSRRCI: printCSRInstr("CSRRCI"); + // SYSTEM (others) `INSTR_ECALL: printMnemonic("ECALL"); `INSTR_EBREAK: printMnemonic("EBREAK"); `INSTR_ERET: printMnemonic("ERET"); + `INSTR_WFI: printMnemonic("WFI"); `INSTR_RDCYCLE: printRDInstr("RDCYCLE"); `INSTR_RDCYCLEH: printRDInstr("RDCYCLEH"); `INSTR_RDTIME: printRDInstr("RDTIME"); @@ -916,7 +968,7 @@ module riscv_core function void printRInstr(input string mnemonic); begin riscv_core.mnemonic = mnemonic; - $fdisplay(f, "%s\tx%0d, x%d (0x%h), x%0d (0x%h)", mnemonic, + $fdisplay(f, "%s\tx%0d, x%0d (0x%h), x%0d (0x%h)", mnemonic, rd, rs1, rs1_value, rs2, rs2_value); end endfunction // printRInstr @@ -963,6 +1015,22 @@ module riscv_core end endfunction // printRDInstr + function void printCSRInstr(input string mnemonic); + logic [11:0] csr; + begin + riscv_core.mnemonic = mnemonic; + imm = id_stage_i.imm_z_type; + csr = instr[31:20]; + + if (instr[14] == 1'b0) begin + $fdisplay(f, "%s\tx%0d, 0x%h (csr), x%0d (0x%h)", mnemonic, rd, csr, + rs1, rs1_value); + end else begin + $fdisplay(f, "%s\tx%0d, 0x%h (csr), 0x%h (imm)", mnemonic, rd, csr, imm); + end + end + endfunction // printCSRInstr + `endif // TRACE_EXECUTION // synopsys translate_on diff --git a/wb_stage.sv b/wb_stage.sv index 99ce61a7..37a84a2c 100644 --- a/wb_stage.sv +++ b/wb_stage.sv @@ -41,14 +41,14 @@ module wb_stage input logic regfile_wdata_mux_sel_i, // Comes from the controller (thru id-ex and ex-wb pipe) // MUX INPUTS - input logic [31:0] sp_rdata_i, // From the read port of the special register input logic [31:0] data_rdata_i, // read Data from data memory system - input logic [31:0] lsu_data_reg_i, // read data registered in LSU + input logic [31:0] lsu_data_reg_i, // TODO: remove; read data registered in LSU // MUX OUTPUT output logic [31:0] regfile_wdata_o // write data for register file ); + // TODO: Remove this mux and the associated signals // Register Write Data Selection --> Data to write in the regfile // Select between: // 0: From Special Register @@ -56,7 +56,7 @@ module wb_stage always_comb begin : REGFILE_WDATA_MUX casex (regfile_wdata_mux_sel_i) - 1'b0: begin regfile_wdata_o <= sp_rdata_i; end + //1'b0: begin regfile_wdata_o <= sp_rdata_i; end 1'b1: begin regfile_wdata_o <= data_rdata_i; end endcase; // case (regfile_wdata_mux_sel_i) end