Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion bhv/cv32e40x_wrapper.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
`include "cv32e40x_rvfi_sva.sv"
`include "cv32e40x_sequencer_sva.sv"
`include "cv32e40x_clic_int_controller_sva.sv"
`include "cv32e40x_register_file_sva.sv"
`endif

`include "cv32e40x_wrapper.vh"
Expand Down Expand Up @@ -166,7 +167,7 @@ module cv32e40x_wrapper
);

bind cv32e40x_id_stage:
core_i.id_stage_i cv32e40x_id_stage_sva id_stage_sva
core_i.id_stage_i cv32e40x_id_stage_sva #(.RV32(RV32)) id_stage_sva
(
.jmp_taken_id_ctrl_i (core_i.controller_i.controller_fsm_i.jump_taken_id),
.*
Expand Down Expand Up @@ -196,6 +197,11 @@ module cv32e40x_wrapper
.illegal_insn (core_i.id_stage_i.illegal_insn ),
.*);

bind cv32e40x_register_file:
core_i.register_file_wrapper_i.register_file_i cv32e40x_register_file_sva #(.RV32(RV32))
register_file_sva
(.*);

generate
if(M_EXT != M_NONE) begin: mul_sva
bind cv32e40x_mult:
Expand Down
8 changes: 6 additions & 2 deletions rtl/cv32e40x_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
module cv32e40x_core import cv32e40x_pkg::*;
#(
parameter LIB = 0,
parameter rv32_e RV32 = RV32I, // todo: Add support for RV32E
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter m_ext_e M_EXT = M,
Expand Down Expand Up @@ -414,6 +414,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_if_stage
#(
.RV32 ( RV32 ),
.A_EXT ( A_EXT ),
.B_EXT ( B_EXT ),
.X_EXT ( X_EXT ),
Expand Down Expand Up @@ -478,6 +479,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_id_stage
#(
.RV32 ( RV32 ),
.A_EXT ( A_EXT ),
.B_EXT ( B_EXT ),
.M_EXT ( M_EXT ),
Expand Down Expand Up @@ -716,6 +718,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_cs_registers
#(
.RV32 ( RV32 ),
.A_EXT ( A_EXT ),
.M_EXT ( M_EXT ),
.X_EXT ( X_EXT ),
Expand Down Expand Up @@ -1014,7 +1017,8 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_register_file_wrapper
#(
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS )
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS ),
.RV32 ( RV32 )
)
register_file_wrapper_i
(
Expand Down
16 changes: 9 additions & 7 deletions rtl/cv32e40x_cs_registers.sv
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

module cv32e40x_cs_registers import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter m_ext_e M_EXT = M,
parameter bit X_EXT = 0,
Expand Down Expand Up @@ -106,13 +107,14 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
);

localparam logic [31:0] CORE_MISA =
(32'(A_EXT) << 0) | // A - Atomic Instructions extension
(32'(1) << 2) | // C - Compressed extension
(32'(1) << 8) | // I - RV32I/64I/128I base ISA
(32'(M_EXT == M) << 12) | // M - Integer Multiply/Divide extension
(32'(0) << 20) | // U - User mode implemented
(32'(1) << 23) | // X - Non-standard extensions present
(32'(MXL) << 30); // M-XLEN
(32'(A_EXT) << 0) | // A - Atomic Instructions extension
(32'(1) << 2) | // C - Compressed extension
(32'(RV32 == RV32E) << 4) | // E - RV32E/64E base ISA
(32'(RV32 == RV32I) << 8) | // I - RV32I/64I/128I base ISA
(32'(M_EXT == M) << 12) | // M - Integer Multiply/Divide extension
(32'(0) << 20) | // U - User mode implemented
(32'(1) << 23) | // X - Non-standard extensions present
(32'(MXL) << 30); // M-XLEN

localparam logic [31:0] MISA_VALUE = CORE_MISA | (X_EXT ? X_MISA : 32'h0000_0000);

Expand Down
28 changes: 26 additions & 2 deletions rtl/cv32e40x_decoder.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

module cv32e40x_decoder import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter m_ext_e M_EXT = M,
Expand Down Expand Up @@ -84,6 +86,10 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
output logic rf_we_o, // Write enable for register file
output logic [1:0] rf_re_o,

input rf_addr_t rf_raddr_i[REGFILE_NUM_READ_PORTS],
input rf_addr_t rf_waddr_i,
output logic [REGFILE_NUM_READ_PORTS-1:0] rf_illegal_raddr_o,

// Mux selects
output op_c_mux_e op_c_mux_sel_o, // Operand c selection: reg value or jump target
output imm_a_mux_e imm_a_mux_sel_o, // Immediate selection for operand a
Expand All @@ -108,6 +114,9 @@ module cv32e40x_decoder import cv32e40x_pkg::*;

logic [31:0] instr_rdata;

logic rf_illegal_addr;
logic rf_illegal_waddr;

decoder_ctrl_t decoder_i_ctrl;
decoder_ctrl_t decoder_m_ctrl;
decoder_ctrl_t decoder_a_ctrl;
Expand Down Expand Up @@ -186,9 +195,24 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
endcase
end

// Take illegal compressed instruction into account
// Check for illegal GPR address if using RV32E
genvar rf_rport_idx;
generate
for (rf_rport_idx = 0; rf_rport_idx < REGFILE_NUM_READ_PORTS; rf_rport_idx++) begin: gen_rf_raddr_illegal
assign rf_illegal_raddr_o[rf_rport_idx] = (RV32 == RV32I) ? 1'b0 : rf_raddr_i[rf_rport_idx][4];
end
endgenerate

assign rf_illegal_waddr = (RV32 == RV32I) ? 1'b0 : rf_waddr_i[4];

assign rf_illegal_addr = (decoder_ctrl_mux_subdec.rf_re[0] && rf_illegal_raddr_o[0]) ||
(decoder_ctrl_mux_subdec.rf_re[1] && rf_illegal_raddr_o[1]) ||
(decoder_ctrl_mux_subdec.rf_we && rf_illegal_waddr);


// Take illegal compressed instruction and illegal RV32E GPR address into account
always_comb begin
if (if_id_pipe_i.illegal_c_insn) begin
if (if_id_pipe_i.illegal_c_insn || rf_illegal_addr) begin
decoder_ctrl_mux = DECODER_CTRL_ILLEGAL_INSN;
end
else begin
Expand Down
17 changes: 14 additions & 3 deletions rtl/cv32e40x_id_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

module cv32e40x_id_stage import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter m_ext_e M_EXT = M,
Expand Down Expand Up @@ -119,6 +120,7 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
logic rf_we;
logic rf_we_dec;
rf_addr_t rf_waddr;
logic [REGFILE_NUM_READ_PORTS-1:0] rf_illegal_raddr;

// ALU Control
logic alu_en;
Expand Down Expand Up @@ -404,6 +406,8 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;

cv32e40x_decoder
#(
.RV32 ( RV32 ),
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS ),
.A_EXT ( A_EXT ),
.B_EXT ( B_EXT ),
.M_EXT ( M_EXT ),
Expand Down Expand Up @@ -462,6 +466,9 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
// Register file control signals
.rf_re_o ( rf_re ),
.rf_we_o ( rf_we_dec ),
.rf_raddr_i ( rf_raddr_o ),
.rf_waddr_i ( rf_waddr ),
.rf_illegal_raddr_o ( rf_illegal_raddr ),

// Mux selects
.imm_a_mux_sel_o ( imm_a_mux_sel ),
Expand Down Expand Up @@ -739,16 +746,20 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
xif_issue_if.issue_req.rs_valid = '0;
if (xif_issue_if.X_NUM_RS > 0) begin
xif_issue_if.issue_req.rs [0] = operand_a_fw;
xif_issue_if.issue_req.rs_valid[0] = 1'b1;
xif_issue_if.issue_req.rs_valid[0] = (ctrl_byp_i.operand_a_fw_mux_sel == SEL_REGFILE) ?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the select based on ctrl_byp_i.operand_a_fw_mux_sel == SEL_REGFILE?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because values can be forwarded from EX or WB stage. Upon forwarding, the RF address check in the decode stage will not be applicable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say that the RF address check from the decoder stage would always apply, so it should be:

      xif_issue_if.issue_req.rs_valid[0] = !rf_illegal_raddr[0];

(Of course in reality ctrl_byp_i.operand_a_fw_mux_sel == SEL_REGFILE will always hold and then your code proposal and my proposal are the same. Also note that stalls/bypass usage is not correct yet, see #277)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, you're right. Updated.

!rf_illegal_raddr[0] :
1'b1;
end
if (xif_issue_if.X_NUM_RS > 1) begin
xif_issue_if.issue_req.rs [1] = operand_b_fw;
xif_issue_if.issue_req.rs_valid[1] = 1'b1;
xif_issue_if.issue_req.rs_valid[1] = (ctrl_byp_i.operand_b_fw_mux_sel == SEL_REGFILE) ?
!rf_illegal_raddr[1] :
1'b1;
end
// TODO: implement forwarding for other operands than rs1 and rs2
for (integer i = 2; i < xif_issue_if.X_NUM_RS && i < REGFILE_NUM_READ_PORTS; i++) begin
xif_issue_if.issue_req.rs [i] = rf_rdata_i[i];
xif_issue_if.issue_req.rs_valid[i] = 1'b1;
xif_issue_if.issue_req.rs_valid[i] = !rf_illegal_raddr[i];
end
end

Expand Down
2 changes: 2 additions & 0 deletions rtl/cv32e40x_if_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

module cv32e40x_if_stage import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter bit X_EXT = 0,
Expand Down Expand Up @@ -424,6 +425,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
generate
if (ZC_EXT) begin : gen_seq
cv32e40x_sequencer
#(.RV32(RV32))
sequencer_i
(
.clk ( clk ),
Expand Down
9 changes: 7 additions & 2 deletions rtl/cv32e40x_register_file.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@

module cv32e40x_register_file import cv32e40x_pkg::*;
#(
parameter int unsigned REGFILE_NUM_READ_PORTS = 2
parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
parameter rv32_e RV32 = RV32I
)
(
// Clock and Reset
Expand All @@ -45,6 +46,10 @@ module cv32e40x_register_file import cv32e40x_pkg::*;
input logic we_i [REGFILE_NUM_WRITE_PORTS]
);

// Number of regfile integer registers
localparam REGFILE_NUM_WORDS = (RV32 == RV32I) ? 32 : 16;
localparam REGFILE_IMPL_ADDR_WIDTH = $clog2(REGFILE_NUM_WORDS);

// integer register file
logic [REGFILE_WORD_WIDTH-1:0] mem [REGFILE_NUM_WORDS];

Expand All @@ -57,7 +62,7 @@ module cv32e40x_register_file import cv32e40x_pkg::*;
genvar ridx;
generate
for (ridx=0; ridx<REGFILE_NUM_READ_PORTS; ridx++) begin : gen_regfile_rdata
assign rdata_o[ridx] = mem[raddr_i[ridx]];
assign rdata_o[ridx] = mem[raddr_i[ridx][REGFILE_IMPL_ADDR_WIDTH-1:0]];
end
endgenerate

Expand Down
6 changes: 4 additions & 2 deletions rtl/cv32e40x_register_file_wrapper.sv
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@

module cv32e40x_register_file_wrapper import cv32e40x_pkg::*;
#(
parameter int unsigned REGFILE_NUM_READ_PORTS = 2
parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
parameter rv32_e RV32 = RV32I
)
(
// Clock and Reset
Expand All @@ -49,7 +50,8 @@ module cv32e40x_register_file_wrapper import cv32e40x_pkg::*;

cv32e40x_register_file
#(
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS )
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS ),
.RV32 ( RV32 )
)
register_file_i
(
Expand Down
30 changes: 22 additions & 8 deletions rtl/cv32e40x_sequencer.sv
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
// //
////////////////////////////////////////////////////////////////////////////////

module cv32e40x_sequencer
import cv32e40x_pkg::*;
module cv32e40x_sequencer import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I
)
(
input logic clk,
input logic rst_n,
Expand Down Expand Up @@ -78,6 +80,8 @@ import cv32e40x_pkg::*;

logic ready_fsm;

logic dmove_legal_dest;
logic pushpop_legal_rlist;

assign instr = instr_i.bus_resp.rdata;
assign rlist = instr[7:4];
Expand Down Expand Up @@ -118,6 +122,17 @@ import cv32e40x_pkg::*;
///////////////////////////////////
// Decode sequenced instructions //
///////////////////////////////////

// rlist values 0 to 3 are reserved for a future EABI variant called cm.popret.e
// For RV32E, S2-S11 are not present (i.e. rlist must be < 7)
assign pushpop_legal_rlist = (RV32 == RV32I) ? (rlist > 4'h3) :
(rlist < 4'h7) && (rlist > 4'h3);

// rs1 must be different from rs2
// For RV32E, S2-S11 are not present
assign dmove_legal_dest = (RV32 == RV32I) ? (instr[9:7] != instr[4:2]) :
(instr[9:7] != instr[4:2]) && (instr[9:7] < 3'h2) && (instr[4:2] < 3'h2);

always_comb
begin
seq_instr = INVALID_INST;
Expand All @@ -138,8 +153,7 @@ import cv32e40x_pkg::*;
end

3'b011: begin
// rs1 must be different from rs2
if (instr[9:7] != instr[4:2]) begin
if (dmove_legal_dest) begin
if (instr[6:5] == 2'b11) begin
// cm.mva01s
seq_instr = MVA01S;
Expand All @@ -154,13 +168,13 @@ import cv32e40x_pkg::*;
3'b110: begin
if (instr[9:8] == 2'b00) begin
// cm.push
if (rlist > 3) begin
if (pushpop_legal_rlist) begin
seq_instr = PUSH;
seq_store = 1'b1;
end
end else if (instr[9:8] == 2'b10) begin
// cm.pop
if (rlist > 3) begin
if (pushpop_legal_rlist) begin
seq_instr = POP;
seq_load = 1'b1;
end
Expand All @@ -169,13 +183,13 @@ import cv32e40x_pkg::*;
3'b111: begin
if (instr[9:8] == 2'b00) begin
// cm.popretz
if (rlist > 3) begin
if (pushpop_legal_rlist) begin
seq_instr = POPRETZ;
seq_load = 1'b1;
end
end else if (instr[9:8] == 2'b10) begin
// cm.popret
if (rlist > 3) begin
if (pushpop_legal_rlist) begin
seq_instr = POPRET;
seq_load = 1'b1;
end
Expand Down
3 changes: 0 additions & 3 deletions rtl/include/cv32e40x_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,6 @@ parameter REGFILE_DATA_WIDTH = 32;
// Word width of register file memory
parameter REGFILE_WORD_WIDTH = REGFILE_DATA_WIDTH;

// Number of regfile integer registers
parameter REGFILE_NUM_WORDS = 2**(REGFILE_ADDR_WIDTH);

// Register file address type
typedef logic [REGFILE_ADDR_WIDTH-1:0] rf_addr_t;

Expand Down
Loading