mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-06-27 17:00:57 -04:00
Update ID stage to support ZCMP, ZCMT and CVXIF with Superscalar (#2756)
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:
parent
fd8c890def
commit
2ef1c1b1fc
11 changed files with 321 additions and 241 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
368
core/id_stage.sv
368
core/id_stage.sv
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue