mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-24 05:47:36 -04:00
Added all RiscV CSR manipulation instructions, major update and cleanup
This commit is contained in:
parent
c0c5b5f8a1
commit
60a842c81d
7 changed files with 380 additions and 152 deletions
130
controller.sv
130
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
|
||||
|
|
166
cs_registers.sv
Normal file
166
cs_registers.sv
Normal file
|
@ -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
|
27
ex_stage.sv
27
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
|
||||
|
|
42
id_stage.sv
42
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;
|
||||
|
|
|
@ -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
|
||||
|
|
118
riscv_core.sv
118
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue