Update ID stage to support ZCMP, ZCMT and CVXIF with Superscalar (#2756)
Some checks failed
bender-up-to-date / bender-up-to-date (push) Has been cancelled
ci / build-riscv-tests (push) Has been cancelled
ci / execute-riscv64-tests (push) Has been cancelled
ci / execute-riscv32-tests (push) Has been cancelled

Add support for Superscalar with ZCMP, ZCMT and CVXIF.
ZCMP decoder, ZCMT decoder and CVXIF interface driver are using port 0.
Standard RVC and 32 bits instruction can take port 0 or 1.
This commit is contained in:
Guillaume Chauvon 2025-02-03 13:40:02 +01:00 committed by GitHub
parent fd8c890def
commit 2ef1c1b1fc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 321 additions and 241 deletions

View file

@ -301,10 +301,10 @@ module commit_stage
end
if (CVA6Cfg.NrCommitPorts > 1) begin
commit_ack_o[1] = 1'b0;
we_gpr_o[1] = 1'b0;
wdata_o[1] = commit_instr_i[1].result;
commit_macro_ack[1] = 1'b0;
commit_ack_o[1] = 1'b0;
we_gpr_o[1] = 1'b0;
wdata_o[1] = commit_instr_i[1].result;
// -----------------
// Commit Port 2
@ -350,10 +350,9 @@ module commit_stage
end
end
if (CVA6Cfg.RVZCMP) begin
if (CVA6Cfg.NrCommitPorts > 1)
commit_macro_ack_o = (commit_instr_i[0].is_macro_instr || commit_instr_i[1].is_macro_instr) ? commit_macro_ack : commit_ack_o;
else
commit_macro_ack_o = (commit_instr_i[0].is_macro_instr) ? commit_macro_ack : commit_ack_o;
for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin
commit_macro_ack_o[i] = commit_instr_i[i].is_macro_instr ? commit_macro_ack[i] : commit_ack_o[i];
end
end else commit_macro_ack_o = commit_ack_o;
end

View file

@ -16,24 +16,24 @@ module cvxif_compressed_if_driver #(
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
input logic flush_i,
// CVA6 Hart id
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_i,
input logic [CVA6Cfg.NrIssuePorts-1:0] instruction_valid_i,
input logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_i,
input logic is_compressed_i,
input logic is_illegal_i,
input logic [31:0] instruction_i,
output logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_o,
output logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_o,
output logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_o,
input logic stall_i,
output logic [CVA6Cfg.NrIssuePorts-1:0] stall_o,
output logic is_compressed_o,
output logic is_illegal_o,
output logic [31:0] instruction_o,
input logic stall_i,
output logic stall_o,
// CVXIF Compressed interface
input logic compressed_ready_i,
input x_compressed_resp_t compressed_resp_i,
output logic compressed_valid_o,
output x_compressed_req_t compressed_req_o
input logic compressed_ready_i,
input x_compressed_resp_t compressed_resp_i,
output logic compressed_valid_o,
output x_compressed_req_t compressed_req_o
);
@ -44,32 +44,22 @@ module cvxif_compressed_if_driver #(
compressed_valid_o = 1'b0;
compressed_req_o.instr = '0;
compressed_req_o.hartid = hart_id_i;
stall_o[0] = stall_i;
stall_o[1] = 1'b0;
if (is_illegal_i[0]) begin
compressed_valid_o = is_illegal_i[0] && instruction_valid_i[0];
compressed_req_o.instr = instruction_i[0][15:0];
is_illegal_o[0] = ~compressed_resp_i.accept;
instruction_o[0] = compressed_resp_i.accept ? compressed_resp_i.instr : instruction_i[0];
is_compressed_o[0] = compressed_resp_i.accept ? 1'b0 : is_compressed_i[0];
stall_o = stall_i;
if (is_illegal_i) begin
compressed_valid_o = is_illegal_i;
compressed_req_o.instr = instruction_i[15:0];
is_illegal_o = ~compressed_resp_i.accept;
instruction_o = compressed_resp_i.accept ? compressed_resp_i.instr : instruction_i;
is_compressed_o = compressed_resp_i.accept ? 1'b0 : is_compressed_i;
if (~stall_i) begin
// Propagate stall from macro decoder or wait for compressed ready if compressed transaction is happening.
// Stall if both instruction are illegal
stall_o[0] = (compressed_valid_o && ~compressed_ready_i);
if (CVA6Cfg.SuperscalarEn) begin
stall_o[1] = is_illegal_i[1];
end
stall_o = (compressed_valid_o && ~compressed_ready_i);
end
end
if (CVA6Cfg.SuperscalarEn) begin
if (~is_illegal_i[0] && is_illegal_i[1]) begin // 2nd instruction is illegal
compressed_valid_o = is_illegal_i[1] && instruction_valid_i[1];
compressed_req_o.instr = instruction_i[1][15:0];
is_illegal_o[1] = ~compressed_resp_i.accept;
instruction_o[1] = compressed_resp_i.accept ? compressed_resp_i.instr : instruction_i[1];
is_compressed_o[1] = compressed_resp_i.accept ? 1'b0 : is_compressed_i[1];
stall_o[1] = (compressed_valid_o && ~compressed_ready_i);
end
if (flush_i) begin
compressed_valid_o = 1'b0;
compressed_req_o.instr = '0;
compressed_req_o.hartid = hart_id_i;
end
end

View file

@ -56,7 +56,7 @@ module cvxif_fu
assign x_ready_o = 1'b1; // Readyness of cvxif_fu is determined in issue stage by CVXIF issue interface
// Result signals
assign x_valid_o = x_illegal_i && x_valid_i ? 1'b1 : result_valid_i;
assign x_valid_o = x_illegal_i || result_valid_i;
assign x_result_o = result_i.data;
assign x_trans_id_o = x_illegal_i ? x_trans_id_i : result_i.id;
assign x_we_o = result_i.we;
@ -64,13 +64,10 @@ module cvxif_fu
// Handling of illegal instruction exception
always_comb begin
x_exception_o = '0; // No exception in this interface
if (x_illegal_i && x_valid_i) begin
x_exception_o.valid = '1;
x_exception_o.cause = riscv::ILLEGAL_INSTR;
if (CVA6Cfg.TvalEn)
x_exception_o.tval = x_off_instr_i; // TODO Optimization : Set exception in IRO.
end
x_exception_o.valid = x_illegal_i;
x_exception_o.cause = x_illegal_i ? riscv::ILLEGAL_INSTR : '0;
if (CVA6Cfg.TvalEn)
x_exception_o.tval = x_off_instr_i; // TODO Optimization : Set exception in IRO.
end
endmodule

View file

@ -86,7 +86,7 @@ module id_stage #(
// CVXIF Compressed interface
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
input logic compressed_ready_i,
//JVT
//JVT
input jvt_t jvt_i,
input x_compressed_resp_t compressed_resp_i,
output logic compressed_valid_o,
@ -104,30 +104,52 @@ module id_stage #(
logic is_ctrl_flow;
} issue_struct_t;
issue_struct_t [CVA6Cfg.NrIssuePorts-1:0] issue_n, issue_q;
// stall required for ZCMP ZCMT CVXIF
logic [CVA6Cfg.NrIssuePorts-1:0] stall_instr_fetch;
logic [CVA6Cfg.NrIssuePorts-1:0] is_control_flow_instr;
scoreboard_entry_t [CVA6Cfg.NrIssuePorts-1:0] decoded_instruction;
logic [CVA6Cfg.NrIssuePorts-1:0] decoded_instruction_valid;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] orig_instr;
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal;
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cmp;
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cvxif, is_illegal_cvxif_zcmp, is_illegal_cvxif_zcmt;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] compressed_instr;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0]
instruction_cvxif, instruction_cvxif_zcmp, instruction_cvxif_zcmt;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_cmp;
logic [CVA6Cfg.NrIssuePorts-1:0]
is_compressed_cvxif, is_compressed_cvxif_zcmp, is_compressed_cvxif_zcmt;
// Compressed decoder signals
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_rvc;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_rvc;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_rvc;
logic [CVA6Cfg.NrIssuePorts-1:0] is_zcmt_instr;
logic [CVA6Cfg.NrIssuePorts-1:0] is_macro_instr;
// CVXIF compressed interface driver signals
// Inputs
logic is_illegal_cvxif_i;
logic [ 31:0] instruction_cvxif_i;
logic is_compressed_cvxif_i;
logic stall_macro_deco;
// Outputs
logic is_illegal_cvxif_o;
logic [ 31:0] instruction_cvxif_o;
logic is_compressed_cvxif_o;
// ZCMP decoder signals
logic is_illegal_zcmp;
logic [ 31:0] instruction_zcmp;
logic is_compressed_zcmp;
logic stall_macro_deco_zcmp;
logic is_last_macro_instr;
logic is_double_rd_macro_instr;
// ZCMT decoder signals
logic is_illegal_zcmt;
logic [ 31:0] instruction_zcmt;
logic is_compressed_zcmt;
logic stall_macro_deco_zcmt;
logic [ CVA6Cfg.XLEN-1:0] jump_address;
// Decoder signals
logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_deco;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] instruction_deco;
logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_deco;
logic [CVA6Cfg.NrIssuePorts-1:0] is_macro_instr_i;
logic [CVA6Cfg.NrIssuePorts-1:0] stall_instr_fetch;
logic stall_macro_deco, stall_macro_deco_zcmp, stall_macro_deco_zcmt;
logic is_last_macro_instr_o;
logic is_double_rd_macro_instr_o;
logic [CVA6Cfg.NrIssuePorts-1:0] is_zcmt_instr;
logic [ CVA6Cfg.XLEN-1:0] jump_address;
if (CVA6Cfg.RVC) begin
// ---------------------------------------------------------
@ -138,141 +160,139 @@ module id_stage #(
.CVA6Cfg(CVA6Cfg)
) compressed_decoder_i (
.instr_i (fetch_entry_i[i].instruction),
.instr_o (compressed_instr[i]),
.illegal_instr_o (is_illegal[i]),
.is_compressed_o (is_compressed[i]),
.is_macro_instr_o(is_macro_instr_i[i]),
.instr_o (instruction_rvc[i]),
.illegal_instr_o (is_illegal_rvc[i]),
.is_compressed_o (is_compressed_rvc[i]),
.is_macro_instr_o(is_macro_instr[i]),
.is_zcmt_instr_o (is_zcmt_instr[i])
);
end
if (CVA6Cfg.RVZCMP || (CVA6Cfg.RVZCMT & ~CVA6Cfg.MmuPresent)) begin //MMU should be off when using ZCMT
//sequencial decoder
if (CVA6Cfg.RVZCMP) begin
macro_decoder #(
.CVA6Cfg(CVA6Cfg)
) macro_decoder_i (
.instr_i (compressed_instr[0]),
.is_macro_instr_i (is_macro_instr_i[0]),
.clk_i (clk_i),
.rst_ni (rst_ni),
.instr_o (instruction_cvxif_zcmp),
.illegal_instr_i (is_illegal[0]),
.is_compressed_i (is_compressed[0]),
.issue_ack_i (issue_instr_ack_i[0]),
.illegal_instr_o (is_illegal_cvxif_zcmp),
.is_compressed_o (is_compressed_cvxif_zcmp),
.fetch_stall_o (stall_macro_deco_zcmp),
.is_last_macro_instr_o (is_last_macro_instr_o),
.is_double_rd_macro_instr_o(is_double_rd_macro_instr_o)
);
end
if (CVA6Cfg.RVZCMT) begin
zcmt_decoder #(
.CVA6Cfg(CVA6Cfg),
.dcache_req_i_t(dcache_req_i_t),
.dcache_req_o_t(dcache_req_o_t),
.jvt_t(jvt_t),
.branchpredict_sbe_t(branchpredict_sbe_t)
) zcmt_decoder_i (
.instr_i (compressed_instr[0]),
.pc_i (fetch_entry_i[0].address),
.is_zcmt_instr_i(is_zcmt_instr[0]),
.clk_i (clk_i),
.rst_ni (rst_ni),
.instr_o (instruction_cvxif_zcmt),
.illegal_instr_i(is_illegal[0]),
.is_compressed_i(is_compressed[0]),
.illegal_instr_o(is_illegal_cvxif_zcmt),
.is_compressed_o(is_compressed_cvxif_zcmt),
.fetch_stall_o (stall_macro_deco_zcmt),
.jvt_i (jvt_i),
.req_port_i (dcache_req_ports_i),
.req_port_o (dcache_req_ports_o),
.jump_address_o (jump_address)
);
end else assign jump_address = '0;
assign instruction_cvxif[0] = is_zcmt_instr[0] ? instruction_cvxif_zcmt : instruction_cvxif_zcmp;
assign is_illegal_cvxif[0] = is_zcmt_instr[0] ? is_illegal_cvxif_zcmt : is_illegal_cvxif_zcmp;
assign is_compressed_cvxif[0] = is_zcmt_instr[0] ? is_compressed_cvxif_zcmt : is_compressed_cvxif_zcmp;
assign stall_macro_deco = is_zcmt_instr[0] ? stall_macro_deco_zcmt : stall_macro_deco_zcmp;
if (CVA6Cfg.SuperscalarEn) begin
assign stall_instr_fetch[1] = is_illegal_rvc[1] || is_macro_instr[1] || is_zcmt_instr[1];
end
if (CVA6Cfg.SuperscalarEn) begin
assign instruction_cvxif[CVA6Cfg.NrIssuePorts-1] = '0;
assign is_illegal_cvxif[CVA6Cfg.NrIssuePorts-1] = '0;
assign is_compressed_cvxif[CVA6Cfg.NrIssuePorts-1] = '0;
end
cvxif_compressed_if_driver #(
.CVA6Cfg(CVA6Cfg),
.x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) i_cvxif_compressed_if_driver_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.hart_id_i (hart_id_i),
.is_compressed_i (is_compressed_cvxif),
.is_illegal_i (is_illegal_cvxif),
.instruction_i (instruction_cvxif),
.instruction_valid_i(fetch_entry_valid_i),
.is_compressed_o (is_compressed_cmp),
.is_illegal_o (is_illegal_cmp),
.instruction_o (instruction),
.stall_i (stall_macro_deco),
.stall_o (stall_instr_fetch),
.compressed_ready_i (compressed_ready_i),
.compressed_resp_i (compressed_resp_i),
.compressed_valid_o (compressed_valid_o),
.compressed_req_o (compressed_req_o)
if (CVA6Cfg.RVZCMP) begin
macro_decoder #(
.CVA6Cfg(CVA6Cfg)
) macro_decoder_i (
.instr_i (instruction_rvc[0]),
.is_macro_instr_i (is_macro_instr[0]),
.clk_i (clk_i),
.rst_ni (rst_ni),
.instr_o (instruction_zcmp),
.illegal_instr_i (is_illegal_rvc[0]),
.is_compressed_i (is_compressed_rvc[0]),
.issue_ack_i (issue_instr_ack_i[0]),
.illegal_instr_o (is_illegal_zcmp),
.is_compressed_o (is_compressed_zcmp),
.fetch_stall_o (stall_macro_deco_zcmp),
.is_last_macro_instr_o (is_last_macro_instr),
.is_double_rd_macro_instr_o(is_double_rd_macro_instr)
);
end else begin
assign instruction_zcmp = instruction_rvc;
assign is_illegal_zcmp = is_illegal_rvc;
assign is_compressed_zcmp = is_compressed_rvc;
assign stall_macro_deco_zcmp = '0;
assign is_last_macro_instr = '0;
assign is_double_rd_macro_instr = '0;
end
if (CVA6Cfg.RVZCMT) begin
zcmt_decoder #(
.CVA6Cfg(CVA6Cfg),
.dcache_req_i_t(dcache_req_i_t),
.dcache_req_o_t(dcache_req_o_t),
.jvt_t(jvt_t),
.branchpredict_sbe_t(branchpredict_sbe_t)
) zcmt_decoder_i (
.instr_i (instruction_rvc[0]),
.pc_i (fetch_entry_i[0].address),
.is_zcmt_instr_i(is_zcmt_instr[0]),
.clk_i (clk_i),
.rst_ni (rst_ni),
.instr_o (instruction_zcmt),
.illegal_instr_i(is_illegal_rvc[0]),
.is_compressed_i(is_compressed_rvc[0]),
.illegal_instr_o(is_illegal_zcmt),
.is_compressed_o(is_compressed_zcmt),
.fetch_stall_o (stall_macro_deco_zcmt),
.jvt_i (jvt_i),
.req_port_i (dcache_req_ports_i),
.req_port_o (dcache_req_ports_o),
.jump_address_o (jump_address)
);
end else begin
assign instruction_zcmt = instruction_rvc;
assign is_illegal_zcmt = is_illegal_rvc;
assign is_compressed_zcmt = is_compressed_rvc;
assign stall_macro_deco_zcmt = '0;
assign jump_address = '0;
end
if (CVA6Cfg.RVZCMT) begin
assign instruction_cvxif_i = is_zcmt_instr[0] ? instruction_zcmt : instruction_zcmp;
assign is_illegal_cvxif_i = is_zcmt_instr[0] ? is_illegal_zcmt : is_illegal_zcmp;
assign is_compressed_cvxif_i = is_zcmt_instr[0] ? is_compressed_zcmt : is_compressed_zcmp;
assign stall_macro_deco = is_zcmt_instr[0] ? stall_macro_deco_zcmt : stall_macro_deco_zcmp;
end else begin // Do not instantiate the mux which is not optimized cross-bondaries
assign instruction_cvxif_i = instruction_zcmp;
assign is_illegal_cvxif_i = is_illegal_zcmp;
assign is_compressed_cvxif_i = is_compressed_zcmp;
assign stall_macro_deco = stall_macro_deco_zcmp;
end
if (CVA6Cfg.CvxifEn) begin
cvxif_compressed_if_driver #(
.CVA6Cfg(CVA6Cfg),
.x_compressed_req_t(x_compressed_req_t),
.x_compressed_resp_t(x_compressed_resp_t)
) i_cvxif_compressed_if_driver_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.hart_id_i (hart_id_i),
.is_compressed_i (is_compressed),
.is_illegal_i (is_illegal),
.instruction_valid_i(fetch_entry_valid_i),
.instruction_i (compressed_instr),
.is_compressed_o (is_compressed_cmp),
.is_illegal_o (is_illegal_cmp),
.instruction_o (instruction),
.stall_i (1'b0),
.stall_o (stall_instr_fetch),
.compressed_ready_i (compressed_ready_i),
.compressed_resp_i (compressed_resp_i),
.compressed_valid_o (compressed_valid_o),
.compressed_req_o (compressed_req_o)
.clk_i (clk_i),
.rst_ni (rst_ni),
.flush_i (flush_i),
.hart_id_i (hart_id_i),
.is_compressed_i (is_compressed_cvxif_i),
.is_illegal_i (is_illegal_cvxif_i),
.instruction_i (instruction_cvxif_i),
.is_compressed_o (is_compressed_cvxif_o),
.is_illegal_o (is_illegal_cvxif_o),
.instruction_o (instruction_cvxif_o),
.stall_i (stall_macro_deco),
.stall_o (stall_instr_fetch[0]),
.compressed_ready_i(compressed_ready_i),
.compressed_resp_i (compressed_resp_i),
.compressed_valid_o(compressed_valid_o),
.compressed_req_o (compressed_req_o)
);
assign is_last_macro_instr_o = '0;
assign is_double_rd_macro_instr_o = '0;
assign jump_address = '0;
end else begin
assign stall_instr_fetch[0] = stall_macro_deco;
end
end else begin
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
assign instruction[i] = fetch_entry_i[i].instruction;
end
assign is_illegal_cmp = '0;
assign is_compressed_cmp = '0;
assign is_macro_instr_i = '0;
assign is_zcmt_instr = '0;
assign jump_address = '0;
assign is_last_macro_instr_o = '0;
assign is_double_rd_macro_instr_o = '0;
if (CVA6Cfg.CvxifEn) begin
assign compressed_valid_o = '0;
assign compressed_req_o.instr = '0;
assign compressed_req_o.hartid = hart_id_i;
end // TODO Add else to map x_compressed_if outputs to '0 ?
end
assign rvfi_is_compressed_o = is_compressed_cmp;
// ---------------------------------------------------------
// 2. Decode and emit instruction to issue stage
// ---------------------------------------------------------
always_comb begin
// No CVXIF, No ZCMP, No ZCMT => Connect directly compressed decoder to decoder
is_illegal_deco = is_illegal_rvc;
instruction_deco = instruction_rvc;
is_compressed_deco = is_compressed_rvc;
if (CVA6Cfg.CvxifEn) begin
is_illegal_deco[0] = is_illegal_cvxif_o;
instruction_deco[0] = instruction_cvxif_o;
is_compressed_deco[0] = is_compressed_cvxif_o;
end else if (!CVA6Cfg.CvxifEn && (CVA6Cfg.RVZCMP || CVA6Cfg.RVZCMT)) begin
is_illegal_deco[0] = is_illegal_cvxif_i;
instruction_deco[0] = instruction_cvxif_i;
is_compressed_deco[0] = is_compressed_cvxif_i;
end
end
assign rvfi_is_compressed_o = is_compressed_rvc;
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
decoder #(
.CVA6Cfg(CVA6Cfg),
@ -287,14 +307,14 @@ module id_stage #(
.irq_ctrl_i,
.irq_i,
.pc_i (fetch_entry_i[i].address),
.is_compressed_i (is_compressed_cmp[i]),
.is_macro_instr_i (is_macro_instr_i[i]),
.is_compressed_i (is_compressed_deco[i]),
.is_macro_instr_i (is_macro_instr[i]),
.is_zcmt_i (is_zcmt_instr[i]),
.is_last_macro_instr_i (is_last_macro_instr_o),
.is_double_rd_macro_instr_i(is_double_rd_macro_instr_o),
.is_last_macro_instr_i (is_last_macro_instr),
.is_double_rd_macro_instr_i(is_double_rd_macro_instr),
.jump_address_i (jump_address),
.is_illegal_i (is_illegal_cmp[i]),
.instruction_i (instruction[i]),
.is_illegal_i (is_illegal_deco[i]),
.instruction_i (instruction_deco[i]),
.compressed_instr_i (fetch_entry_i[i].instruction[15:0]),
.branch_predict_i (fetch_entry_i[i].branch_predict),
.ex_i (fetch_entry_i[i].ex),
@ -317,7 +337,7 @@ module id_stage #(
end
// ------------------
// Pipeline Register
// 3. Pipeline Register
// ------------------
for (genvar i = 0; i < CVA6Cfg.NrIssuePorts; i++) begin
assign issue_entry_o[i] = issue_q[i].sbe;
@ -331,6 +351,12 @@ module id_stage #(
always_comb begin
issue_n = issue_q;
fetch_entry_ready_o = '0;
// instruction is not valid if we stall due to ZCMT or CVXIF
decoded_instruction_valid[0] = (CVA6Cfg.RVZCMT && is_zcmt_instr[0] && stall_macro_deco_zcmt) ||
(CVA6Cfg.CvxifEn && is_illegal_cvxif_i && ~stall_macro_deco) && stall_instr_fetch[0]
? 1'b0 : 1'b1;
// Instruction on port 1 are always valid. It is either 32bits or legal 16bits.
decoded_instruction_valid[1] = ~stall_instr_fetch[1];
// Clear the valid flag if issue has acknowledged the instruction
if (issue_instr_ack_i[0]) begin
@ -344,21 +370,36 @@ module id_stage #(
if (issue_n[1].valid) begin
issue_n[0] = issue_n[1];
issue_n[1].valid = 1'b0;
end else if (fetch_entry_valid_i[0] && !stall_instr_fetch[0]) begin
fetch_entry_ready_o[0] = 1'b1;
issue_n[0] = '{1'b1, decoded_instruction[0], orig_instr[0], is_control_flow_instr[0]};
end else if (fetch_entry_valid_i[0]) begin
fetch_entry_ready_o[0] = ~stall_instr_fetch[0];
issue_n[0] = '{
decoded_instruction_valid[0],
decoded_instruction[0],
orig_instr[0],
is_control_flow_instr[0]
};
end
end
if (!issue_n[1].valid) begin
if (fetch_entry_ready_o[0]) begin
if (fetch_entry_valid_i[1] && !stall_instr_fetch[1]) begin
fetch_entry_ready_o[1] = 1'b1;
issue_n[1] = '{1'b1, decoded_instruction[1], orig_instr[1], is_control_flow_instr[1]};
if (fetch_entry_valid_i[1]) begin
fetch_entry_ready_o[1] = ~stall_instr_fetch[1];
issue_n[1] = '{
decoded_instruction_valid[1],
decoded_instruction[1],
orig_instr[1],
is_control_flow_instr[1]
};
end
end else if (fetch_entry_valid_i[0] && !stall_instr_fetch[0]) begin
fetch_entry_ready_o[0] = 1'b1;
issue_n[1] = '{1'b1, decoded_instruction[0], orig_instr[0], is_control_flow_instr[0]};
end else if (fetch_entry_valid_i[0]) begin
fetch_entry_ready_o[0] = ~stall_instr_fetch[0];
issue_n[1] = '{
decoded_instruction_valid[0],
decoded_instruction[0],
orig_instr[0],
is_control_flow_instr[0]
};
end
end
@ -369,22 +410,27 @@ module id_stage #(
end
end else begin
always_comb begin
issue_n = issue_q;
issue_n = issue_q;
fetch_entry_ready_o = '0;
// instruction is not valid if we stall due to ZCMT or CVXIF
decoded_instruction_valid[0] = (CVA6Cfg.RVZCMT && is_zcmt_instr[0] && stall_macro_deco_zcmt) ||
(CVA6Cfg.CvxifEn && is_illegal_cvxif_i && ~stall_macro_deco && stall_instr_fetch[0])
? 1'b0 : 1'b1;
// Clear the valid flag if issue has acknowledged the instruction
if (issue_instr_ack_i[0]) issue_n[0].valid = 1'b0;
// TODO: refaire
// if we have a space in the register and the fetch is valid, go get it
// or the issue stage is currently acknowledging an instruction, which means that we will have space
// for a new instruction
if ((!issue_q[0].valid || issue_instr_ack_i[0]) && fetch_entry_valid_i[0]) begin
if (stall_instr_fetch[0]) begin
fetch_entry_ready_o[0] = 1'b0;
end else begin
fetch_entry_ready_o[0] = 1'b1;
end
issue_n[0] = '{1'b1, decoded_instruction[0], orig_instr[0], is_control_flow_instr[0]};
if (!issue_n[0].valid && fetch_entry_valid_i[0]) begin
fetch_entry_ready_o[0] = ~stall_instr_fetch[0];
issue_n[0] = '{
decoded_instruction_valid[0],
decoded_instruction[0],
orig_instr[0],
is_control_flow_instr[0]
};
end
// invalidate the pipeline register on a flush
@ -401,5 +447,5 @@ module id_stage #(
issue_q <= issue_n;
end
end
endmodule
endmodule

View file

@ -392,14 +392,12 @@ package config_pkg;
assert (Cfg.NrCachedRegionRules <= NrMaxRules);
assert (Cfg.NrPMPEntries <= 64);
assert (!(Cfg.SuperscalarEn && Cfg.RVF));
assert (!(Cfg.SuperscalarEn && Cfg.RVZCMP));
assert (Cfg.FETCH_WIDTH == 32 || Cfg.FETCH_WIDTH == 64)
else $fatal(1, "[frontend] fetch width != not supported");
// Support for disabling MIP.MSIP and MIE.MSIE in Hypervisor and Supervisor mode is not supported
// Software Interrupt can be disabled when there is only M machine mode in CVA6.
assert (!(Cfg.RVS && !Cfg.SoftwareInterruptEn));
assert (!(Cfg.RVH && !Cfg.SoftwareInterruptEn));
assert (!(Cfg.SuperscalarEn && Cfg.RVZCMT));
assert (!(Cfg.RVZCMT && ~Cfg.MmuPresent));
// pragma translate_on
endfunction

View file

@ -43,9 +43,9 @@ package cva6_config_pkg;
RVV: bit'(0),
RVC: bit'(1),
RVH: bit'(0),
RVZCMT: bit'(1),
RVZCMT: bit'(0),
RVZCB: bit'(1),
RVZCMP: bit'(1),
RVZCMP: bit'(0),
XFVec: bit'(0),
CvxifEn: bit'(1),
RVZiCond: bit'(0),

View file

@ -176,11 +176,11 @@ module issue_stage
scoreboard_entry_t [CVA6Cfg.NR_SB_ENTRIES-1:0] sbe;
} forwarding_t;
forwarding_t fwd;
scoreboard_entry_t [CVA6Cfg.NrIssuePorts-1:0] issue_instr_sb_iro;
logic [CVA6Cfg.NrIssuePorts-1:0][ 31:0] orig_instr_sb_iro;
logic [CVA6Cfg.NrIssuePorts-1:0] issue_instr_valid_sb_iro;
logic [CVA6Cfg.NrIssuePorts-1:0] issue_ack_iro_sb;
forwarding_t fwd;
scoreboard_entry_t [CVA6Cfg.NrIssuePorts-1:0] issue_instr_sb_iro;
logic [CVA6Cfg.NrIssuePorts-1:0][31:0] orig_instr_sb_iro;
logic [CVA6Cfg.NrIssuePorts-1:0] issue_instr_valid_sb_iro;
logic [CVA6Cfg.NrIssuePorts-1:0] issue_ack_iro_sb;
assign issue_instr_o = issue_instr_sb_iro[0];
assign issue_instr_hs_o = issue_instr_valid_sb_iro[0] & issue_ack_iro_sb[0];

View file

@ -272,9 +272,9 @@ module macro_decoder #(
unique case (state_q)
IDLE: begin
if (is_macro_instr_i && issue_ack_i) begin
if (is_macro_instr_i) begin
reg_numbers_d = reg_numbers - 1'b1;
state_d = INIT;
state_d = issue_ack_i ? INIT : IDLE;
case (macro_instr_type)
PUSH: begin
offset_d = 12'hFFC + 12'hFFC;
@ -423,7 +423,7 @@ module macro_decoder #(
end
end
INIT: begin
fetch_stall_o = 1'b1; // stall inst fetch
fetch_stall_o = is_macro_instr_i; // stall inst fetch
if (issue_ack_i && is_macro_instr_i && macro_instr_type == PUSH) begin
if (reg_numbers_q == 4'b0001) begin
if (CVA6Cfg.XLEN == 64) begin

View file

@ -62,7 +62,7 @@ module zcmt_decoder #(
state_d = state_q;
illegal_instr_o = 1'b0;
is_compressed_o = is_zcmt_instr_i || is_compressed_i;
fetch_stall_o = is_zcmt_instr_i;
fetch_stall_o = '0;
jump_address_o = '0;
// cache request port
@ -78,6 +78,7 @@ module zcmt_decoder #(
unique case (state_q)
IDLE: begin
fetch_stall_o = 1'b0;
if (is_zcmt_instr_i) begin
if (CVA6Cfg.XLEN == 32) begin //It is only target for 32 bit targets in cva6 with No MMU
table_address = {jvt_i.base, 6'b000000} + {24'h0, instr_i[7:2], 2'b00};
@ -85,6 +86,7 @@ module zcmt_decoder #(
req_port_o.address_tag = table_address[CVA6Cfg.VLEN-1:10]; // No MMU support
state_d = TABLE_JUMP;
req_port_o.data_req = 1'b1;
fetch_stall_o = 1'b1;
end else illegal_instr_o = 1'b1;
// Condition may be extented for 64 bits embedded targets with No MMU
end else begin

View file

@ -247,7 +247,9 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #(
assign cvxif_if.compressed_valid = cvxif_req.compressed_valid;
assign cvxif_if.compressed_req = cvxif_req.compressed_req;
assign cvxif_if.issue_valid = cvxif_req.issue_valid;
assign cvxif_if.issue_req = cvxif_req.issue_req;
assign cvxif_if.issue_req.instr = cvxif_req.issue_req.instr;
assign cvxif_if.issue_req.hartid = cvxif_req.issue_req.hartid;
assign cvxif_if.issue_req.id = cvxif_req.issue_req.id;
assign cvxif_if.register_valid = cvxif_req.register_valid;
assign cvxif_if.register = cvxif_req.register;
assign cvxif_if.commit_valid = cvxif_req.commit_valid;

View file

@ -1,4 +1,4 @@
// Copyright 2021 Thales DIS design services SAS
// Copyright 2022 Thales DIS design services SAS
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -8,21 +8,67 @@
// Original Author: Zineb EL KACIMI (zineb.el-kacimi@external.thalesgroup.com)
// Contributor : Guillaume Chauvon
# Add user macros, routines in this file
#define LOAD_RS(rs,value) li rs, value
#define COMP_RS(rs1,rs2,rd) xor rd, rs1, rs2
# Mappings of custom_* mnemonics to .insn pseudo-op of GAS
#define CUS_NOP() .word 0b##0000000##00000####00000##000##00000##1111011
#define CUS_ADD(rs1,rs2,rd) .word 0b##0000000##rs2####rs1##001##rd##1111011
#define CUS_ADD_RS1(rs1,rs2,rd) .word 0b##0000001##rs2####rs1##001##rd##1111011 // only use rs1 : rs1 + rs1 => rd
#define CUS_ADD_RS2(rs1,rs2,rd) .word 0b##0000010##rs2####rs1##001##rd##1111011 // only use rs2 : rs2 + rs2 => rd
#define CUS_ADD_MULTI(rs1,rs2,rd) .word 0b##0000011##rs2####rs1##001##rd##1111011
#define CUS_ADD_RS3_MADD(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1000011 //MADD
#define CUS_ADD_RS3_MSUB(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1000111 //MSUB
#define CUS_ADD_RS3_NMSUB(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1001011 //NMSUB
#define CUS_ADD_RS3_NMADD(rs1,rs2,rs3,rd) .word 0b##rs3##00##rs2####rs1##000##rd##1001111 //NMADD
#define CUS_ADD_RS3_RTYPE(rs1,rs2,rs3) .word 0b##0000100##rs2####rs1##001##rs3##1111011
# CUS_ADD rd, rs1, rs2 -> .insn r CUSTOM_3, 0x1, 0x0, rd, rs1, rs2
.macro cus_add rd, rs1, rs2
.insn r CUSTOM_3, 0x1, 0x0, \rd, \rs1, \rs2
.endm
#define CUS_CADD(rs1, rs2) .half 0b##111##1##rs1##rs2##00 // -> Extend to CUS_ADD(rs1,rs2,x10)
#define CUS_CNOP() .half 0b##111##0##00000##00000##00 // -> Extend to CUS_NOP
# CUS_NOP -> .insn r CUSTOM_3, 0x0, 0x0, x0, x0, x0
.macro cus_nop
.insn r CUSTOM_3, 0x0, 0x0, x0, x0, x0
.endm
# CUS_DOUBLE_RS1 rd, rs1, rs2 -> .insn r CUSTOM_3, 0x1, 0x1, rd, rs1, rs2
.macro cus_double_rs1 rd, rs1, rs2
.insn r CUSTOM_3, 0x1, 0x1, \rd, \rs1, \rs2
.endm
# CUS_DOUBLE_RS2 rd, rs1, rs2 -> .insn r CUSTOM_3, 0x1, 0x2, rd, rs1, rs2
.macro cus_double_rs2 rd, rs1, rs2
.insn r CUSTOM_3, 0x1, 0x2, \rd, \rs1, \rs2
.endm
# CUS_ADD_MULTI rd, rs1, rs2 -> .insn r CUSTOM_3, 0x1, 0x3, rd, rs1, rs2
.macro cus_add_multi rd, rs1, rs2
.insn r CUSTOM_3, 0x1, 0x3, \rd, \rs1, \rs2
.endm
# CUS_ADD_RS3_MADD rd, rs1, rs2, rs3 -> .insn r MADD, 0x0, 0x0, rd, rs1, rs2, rs3
.macro cus_add_rs3_madd rd, rs1, rs2, rs3
.insn r MADD, 0x0, 0x0, \rd, \rs1, \rs2, \rs3
.endm
# CUS_ADD_RS3_MSUB rd, rs1, rs2, rs3 -> .insn r MSUB, 0x0, 0x0, rd, rs1, rs2, rs3
.macro cus_add_rs3_msub rd, rs1, rs2, rs3
.insn r MSUB, 0x0, 0x0, \rd, \rs1, \rs2, \rs3
.endm
# CUS_ADD_RS3_NMADD rd, rs1, rs2, rs3 -> .insn r NMADD, 0x0, 0x0, rd, rs1, rs2, rs3
.macro cus_add_rs3_nmadd rd, rs1, rs2, rs3
.insn r NMADD, 0x0, 0x0, \rd, \rs1, \rs2, \rs3
.endm
# CUS_ADD_RS3_NMSUB rd, rs1, rs2, rs3 -> .insn r NMSUB, 0x0, 0x0, rd, rs1, rs2, rs3
.macro cus_add_rs3_nmsub rd, rs1, rs2, rs3
.insn r NMSUB, 0x0, 0x0, \rd, \rs1, \rs2, \rs3
.endm
# CUS_ADD_RS3_RTYPE rs3, rs1, rs2 -> .insn r MADD, 0x1, 0x4, rs3, rs1, rs2
.macro cus_add_rs3_rtype rs1, rs2, rs3
.insn r MADD, 0x1, 0x4, \rs3, \rs1, \rs2
.endm
# CUS_CNOP -> .insn cr 0x0, 0xe, x0, x0
.macro cus_cnop
.insn cr 0x0, 0xe, x0, x0
.endm
# CUS_CADD rs1, rs2 -> .insn cr 0x0, 0xf, rs1, rs2
.macro cus_cadd rs1, rs2
.insn cr 0x0, 0xf, \rs1, \rs2
.endm