diff --git a/core/Flist.cva6 b/core/Flist.cva6 index cac849e2b7..8005a35f1e 100644 --- a/core/Flist.cva6 +++ b/core/Flist.cva6 @@ -110,6 +110,7 @@ ${CVA6_REPO_DIR}/core/branch_unit.sv ${CVA6_REPO_DIR}/core/compressed_decoder.sv ${CVA6_REPO_DIR}/core/macro_decoder.sv ${CVA6_REPO_DIR}/core/controller.sv +${CVA6_REPO_DIR}/core/zcmt_decoder.sv ${CVA6_REPO_DIR}/core/csr_buffer.sv ${CVA6_REPO_DIR}/core/csr_regfile.sv ${CVA6_REPO_DIR}/core/decoder.sv diff --git a/core/branch_unit.sv b/core/branch_unit.sv index 0688836639..52ed90ba90 100644 --- a/core/branch_unit.sv +++ b/core/branch_unit.sv @@ -31,6 +31,8 @@ module branch_unit #( input fu_data_t fu_data_i, // Instruction PC - ISSUE_STAGE input logic [CVA6Cfg.VLEN-1:0] pc_i, + // Is zcmt instruction - ISSUE_STAGE + input logic is_zcmt_i, // Instruction is compressed - ISSUE_STAGE input logic is_compressed_instr_i, // Branch unit instruction is valid - ISSUE_STAGE @@ -75,13 +77,23 @@ module branch_unit #( // we need to put the branch target address into rd, this is the result of this unit branch_result_o = next_pc; resolved_branch_o.pc = pc_i; - // There are only two sources of mispredicts: + // There are only three sources of mispredicts: // 1. Branches // 2. Jumps to register addresses + // 3. Zcmt instructions if (branch_valid_i) begin - // write target address which goes to PC Gen + // write target address which goes to PC Gen or select target address if zcmt resolved_branch_o.target_address = (branch_comp_res_i) ? target_address : next_pc; resolved_branch_o.is_taken = branch_comp_res_i; + if (CVA6Cfg.RVZCMT) begin + if (is_zcmt_i) begin + // Unconditional jump handling + resolved_branch_o.target_address = target_address; + resolved_branch_o.is_taken = 1'b1; + resolved_branch_o.is_mispredict = 1'b1; // miss prediction for ZCMT + resolved_branch_o.cf_type = ariane_pkg::Jump; + end + end // check the outcome of the branch speculation if (ariane_pkg::op_is_branch(fu_data_i.operation)) begin // Set the `cf_type` of the output as `branch`, this will update the BHT. diff --git a/core/cache_subsystem/wt_dcache.sv b/core/cache_subsystem/wt_dcache.sv index a829fc48bd..5b49d957fb 100644 --- a/core/cache_subsystem/wt_dcache.sv +++ b/core/cache_subsystem/wt_dcache.sv @@ -188,10 +188,10 @@ module wt_dcache // read controllers (LD unit and PTW/MMU) /////////////////////////////////////////////////////// - // 0 is used by MMU, 1 by READ access requests + // 0 is used by MMU or implicit read by zcmt, 1 by READ access requests for (genvar k = 0; k < NumPorts - 1; k++) begin : gen_rd_ports // set these to high prio ports - if ((k == 0 && CVA6Cfg.MmuPresent) || (k == 1) || (k == 2 && CVA6Cfg.EnableAccelerator)) begin + if ((k == 0 && (CVA6Cfg.MmuPresent || CVA6Cfg.RVZCMT )) || (k == 1) || (k == 2 && CVA6Cfg.EnableAccelerator)) begin assign rd_prio[k] = 1'b1; wt_dcache_ctrl #( .CVA6Cfg(CVA6Cfg), diff --git a/core/compressed_decoder.sv b/core/compressed_decoder.sv index 1f09fd1f29..c691dfa75b 100644 --- a/core/compressed_decoder.sv +++ b/core/compressed_decoder.sv @@ -31,7 +31,9 @@ module compressed_decoder #( // Output instruction is macro - decoder output logic is_macro_instr_o, // Output instruction is compressed - decoder - output logic is_compressed_o + output logic is_compressed_o, + // Output instruction is macro - decoder + output logic is_zcmt_instr_o ); // ------------------- @@ -42,6 +44,7 @@ module compressed_decoder #( is_compressed_o = 1'b1; instr_o = instr_i; is_macro_instr_o = 0; + is_zcmt_instr_o = 1'b0; // I: | imm[11:0] | rs1 | funct3 | rd | opcode | // S: | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | @@ -867,10 +870,12 @@ module compressed_decoder #( 3'b000, riscv::OpcodeStoreFp }; - end else if (CVA6Cfg.RVZCMP) begin + end else if (CVA6Cfg.RVZCMP || CVA6Cfg.RVZCMT) begin if (instr_i[12:10] == 3'b110 || instr_i[12:10] == 3'b111 || instr_i[12:10] == 3'b011) begin //is a push/pop instruction is_macro_instr_o = 1; instr_o = instr_i; + end else if (instr_i[12:10] == 3'b000) begin //jt/jalt instruction + is_zcmt_instr_o = 1'b1; end else begin illegal_instr_o = 1'b1; end diff --git a/core/csr_regfile.sv b/core/csr_regfile.sv index 296a8d7916..c44d84bd0a 100644 --- a/core/csr_regfile.sv +++ b/core/csr_regfile.sv @@ -18,6 +18,7 @@ module csr_regfile #( parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, parameter type exception_t = logic, + parameter type jvt_t = logic, parameter type irq_ctrl_t = logic, parameter type scoreboard_entry_t = logic, parameter type rvfi_probes_csr_t = logic, @@ -167,7 +168,9 @@ module csr_regfile // TO_BE_COMPLETED - PERF_COUNTERS output logic [31:0] mcountinhibit_o, // RVFI - output rvfi_probes_csr_t rvfi_csr_o + output rvfi_probes_csr_t rvfi_csr_o, + //jvt output + output jvt_t jvt_o ); localparam logic [63:0] SMODE_STATUS_READ_MASK = ariane_pkg::smode_status_read_mask(CVA6Cfg); @@ -295,6 +298,7 @@ module csr_regfile assign pmpaddr_o = pmpaddr_q[(CVA6Cfg.NrPMPEntries>0?CVA6Cfg.NrPMPEntries-1 : 0):0]; riscv::fcsr_t fcsr_q, fcsr_d; + riscv::jvt_t jvt_q, jvt_d; // ---------------- // Assignments // ---------------- @@ -350,6 +354,13 @@ module csr_regfile read_access_exception = 1'b1; end end + riscv::CSR_JVT: begin + if (CVA6Cfg.RVZCMT) begin + csr_rdata = {jvt_q.base, jvt_q.mode}; + end else begin + read_access_exception = 1'b1; + end + end // non-standard extension riscv::CSR_FTRAN: begin if (CVA6Cfg.FpPresent && !(mstatus_q.fs == riscv::Off || (CVA6Cfg.RVH && v_q && vsstatus_q.fs == riscv::Off))) begin @@ -908,12 +919,14 @@ module csr_regfile perf_we_o = 1'b0; perf_data_o = 'b0; + if (CVA6Cfg.RVZCMT) begin + jvt_d = jvt_q; + end + fcsr_d = fcsr_q; - fcsr_d = fcsr_q; - - priv_lvl_d = priv_lvl_q; - v_d = v_q; - debug_mode_d = debug_mode_q; + priv_lvl_d = priv_lvl_q; + v_d = v_q; + debug_mode_d = debug_mode_q; if (CVA6Cfg.DebugEn) begin dcsr_d = dcsr_q; @@ -1060,6 +1073,14 @@ module csr_regfile riscv::CSR_DSCRATCH1: if (CVA6Cfg.DebugEn) dscratch1_d = csr_wdata; else update_access_exception = 1'b1; + riscv::CSR_JVT: begin + if (CVA6Cfg.RVZCMT) begin + jvt_d.base = csr_wdata[CVA6Cfg.XLEN-1:6]; + jvt_d.mode = 6'b000000; + end else begin + update_access_exception = 1'b1; + end + end // trigger module CSRs riscv::CSR_TSELECT: update_access_exception = 1'b1; // not implemented riscv::CSR_TDATA1: update_access_exception = 1'b1; // not implemented @@ -2452,8 +2473,16 @@ module csr_regfile assign fflags_o = fcsr_q.fflags; assign frm_o = fcsr_q.frm; assign fprec_o = fcsr_q.fprec; + //JVT outputs + if (CVA6Cfg.RVZCMT) begin + assign jvt_o.base = jvt_q.base; + assign jvt_o.mode = jvt_q.mode; + end else begin + assign jvt_o.base = '0; + assign jvt_o.mode = '0; + end // MMU outputs - assign satp_ppn_o = CVA6Cfg.RVS ? satp_q.ppn : '0; + assign satp_ppn_o = CVA6Cfg.RVS ? satp_q.ppn : '0; assign vsatp_ppn_o = CVA6Cfg.RVH ? vsatp_q.ppn : '0; assign hgatp_ppn_o = CVA6Cfg.RVH ? hgatp_q.ppn : '0; if (CVA6Cfg.RVS) begin @@ -2515,9 +2544,12 @@ module csr_regfile // sequential process always_ff @(posedge clk_i or negedge rst_ni) begin if (~rst_ni) begin - priv_lvl_q <= riscv::PRIV_LVL_M; + priv_lvl_q <= riscv::PRIV_LVL_M; // floating-point registers - fcsr_q <= '0; + fcsr_q <= '0; + if (CVA6Cfg.RVZCMT) begin + jvt_q <= '0; + end // debug signals debug_mode_q <= 1'b0; if (CVA6Cfg.DebugEn) begin @@ -2601,6 +2633,9 @@ module csr_regfile priv_lvl_q <= priv_lvl_d; // floating-point registers fcsr_q <= fcsr_d; + if (CVA6Cfg.RVZCMT) begin + jvt_q <= jvt_d; + end // debug signals if (CVA6Cfg.DebugEn) begin debug_mode_q <= debug_mode_d; @@ -2722,6 +2757,7 @@ module csr_regfile // RVFI //------------- assign rvfi_csr_o.fcsr_q = CVA6Cfg.FpPresent ? fcsr_q : '0; + assign rvfi_csr_o.jvt_q = CVA6Cfg.RVZCMT ? jvt_q : '0; assign rvfi_csr_o.dcsr_q = CVA6Cfg.DebugEn ? dcsr_q : '0; assign rvfi_csr_o.dpc_q = CVA6Cfg.DebugEn ? dpc_q : '0; assign rvfi_csr_o.dscratch0_q = CVA6Cfg.DebugEn ? dscratch0_q : '0; diff --git a/core/cva6.sv b/core/cva6.sv index ffb6d28460..3c2e576be4 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -86,6 +86,11 @@ module cva6 branchpredict_sbe_t branch_predict; // this field contains branch prediction information regarding the forward branch path exception_t ex; // this field contains exceptions which might have happened earlier, e.g.: fetch exceptions }, + //JVT struct{base,mode} + localparam type jvt_t = struct packed { + logic [CVA6Cfg.XLEN-7:0] base; + logic [5:0] mode; + }, // ID/EX/WB Stage localparam type scoreboard_entry_t = struct packed { @@ -113,6 +118,7 @@ module cva6 logic is_last_macro_instr; // is last decoded 32bit instruction of macro definition logic is_double_rd_macro_instr; // is double move decoded 32bit instruction of macro definition logic vfp; // is this a vector floating-point instruction? + logic is_zcmt; //is a zcmt instruction }, localparam type writeback_t = struct packed { logic valid; // wb data is valid @@ -415,6 +421,7 @@ module cva6 fu_data_t [CVA6Cfg.NrIssuePorts-1:0] fu_data_id_ex; logic [CVA6Cfg.VLEN-1:0] pc_id_ex; + logic zcmt_id_ex; logic is_compressed_instr_id_ex; logic [CVA6Cfg.NrIssuePorts-1:0][31:0] tinst_ex; // fixed latency units @@ -563,6 +570,8 @@ module cva6 riscv::pmpcfg_t [CVA6Cfg.NrPMPEntries-1:0] pmpcfg; logic [CVA6Cfg.NrPMPEntries-1:0][CVA6Cfg.PLEN-3:0] pmpaddr; logic [31:0] mcountinhibit_csr_perf; + //jvt + jvt_t jvt; // ---------------------------- // Performance Counters <-> * // ---------------------------- @@ -617,6 +626,8 @@ module cva6 // ---------------- dcache_req_i_t [2:0] dcache_req_ports_ex_cache; dcache_req_o_t [2:0] dcache_req_ports_cache_ex; + dcache_req_i_t dcache_req_ports_id_cache; + dcache_req_o_t dcache_req_ports_cache_id; dcache_req_i_t [1:0] dcache_req_ports_acc_cache; dcache_req_o_t [1:0] dcache_req_ports_cache_acc; logic dcache_commit_wbuffer_empty; @@ -671,8 +682,11 @@ module cva6 id_stage #( .CVA6Cfg(CVA6Cfg), .branchpredict_sbe_t(branchpredict_sbe_t), + .dcache_req_i_t(dcache_req_i_t), + .dcache_req_o_t(dcache_req_o_t), .exception_t(exception_t), .fetch_entry_t(fetch_entry_t), + .jvt_t(jvt_t), .irq_ctrl_t(irq_ctrl_t), .scoreboard_entry_t(scoreboard_entry_t), .interrupts_t(interrupts_t), @@ -716,7 +730,11 @@ module cva6 .compressed_ready_i(x_compressed_ready), .compressed_resp_i (x_compressed_resp), .compressed_valid_o(x_compressed_valid), - .compressed_req_o (x_compressed_req) + .compressed_req_o (x_compressed_req), + .jvt_i (jvt), + // DCACHE interfaces + .dcache_req_ports_i(dcache_req_ports_cache_id), + .dcache_req_ports_o(dcache_req_ports_id_cache) ); logic [CVA6Cfg.NrWbPorts-1:0][CVA6Cfg.TRANS_ID_BITS-1:0] trans_id_ex_id; @@ -817,6 +835,7 @@ module cva6 .rs2_forwarding_o (rs2_forwarding_id_ex), .fu_data_o (fu_data_id_ex), .pc_o (pc_id_ex), + .is_zcmt_o (zcmt_id_ex), .is_compressed_instr_o (is_compressed_instr_id_ex), .tinst_o (tinst_ex), // fixed latency unit ready @@ -908,6 +927,7 @@ module cva6 .rs2_forwarding_i(rs2_forwarding_id_ex), .fu_data_i(fu_data_id_ex), .pc_i(pc_id_ex), + .is_zcmt_i(zcmt_id_ex), .is_compressed_instr_i(is_compressed_instr_id_ex), .tinst_i(tinst_ex), // fixed latency units @@ -1078,6 +1098,7 @@ module cva6 csr_regfile #( .CVA6Cfg (CVA6Cfg), .exception_t (exception_t), + .jvt_t (jvt_t), .irq_ctrl_t (irq_ctrl_t), .scoreboard_entry_t(scoreboard_entry_t), .rvfi_probes_csr_t (rvfi_probes_csr_t), @@ -1154,6 +1175,7 @@ module cva6 .pmpcfg_o (pmpcfg), .pmpaddr_o (pmpaddr), .mcountinhibit_o (mcountinhibit_csr_perf), + .jvt_o (jvt), //RVFI .rvfi_csr_o (rvfi_csr) ); @@ -1258,15 +1280,29 @@ module cva6 dcache_req_o_t [NumPorts-1:0] dcache_req_from_cache; // D$ request - assign dcache_req_to_cache[0] = dcache_req_ports_ex_cache[0]; + // Since ZCMT is only enable for embdeed class so MMU should be disable. + // Cache port 0 is being ultilize in implicit read access in ZCMT extension. + if (CVA6Cfg.RVZCMT & ~(CVA6Cfg.MmuPresent)) begin + assign dcache_req_to_cache[0] = dcache_req_ports_id_cache; + end else begin + assign dcache_req_to_cache[0] = dcache_req_ports_ex_cache[0]; + end assign dcache_req_to_cache[1] = dcache_req_ports_ex_cache[1]; assign dcache_req_to_cache[2] = dcache_req_ports_acc_cache[0]; assign dcache_req_to_cache[3] = dcache_req_ports_ex_cache[2].data_req ? dcache_req_ports_ex_cache [2] : dcache_req_ports_acc_cache[1]; // D$ response - assign dcache_req_ports_cache_ex[0] = dcache_req_from_cache[0]; - assign dcache_req_ports_cache_ex[1] = dcache_req_from_cache[1]; + // Since ZCMT is only enable for embdeed class so MMU should be disable. + // Cache port 0 is being ultilized in implicit read access in ZCMT extension. + if (CVA6Cfg.RVZCMT & ~(CVA6Cfg.MmuPresent)) begin + assign dcache_req_ports_cache_id = dcache_req_from_cache[0]; + assign dcache_req_ports_cache_ex[0] = '0; + end else begin + assign dcache_req_ports_cache_ex[0] = dcache_req_from_cache[0]; + assign dcache_req_ports_cache_id = '0; + end + assign dcache_req_ports_cache_ex[1] = dcache_req_from_cache[1]; assign dcache_req_ports_cache_acc[0] = dcache_req_from_cache[2]; always_comb begin : gen_dcache_req_store_data_gnt dcache_req_ports_cache_ex[2] = dcache_req_from_cache[3]; diff --git a/core/cva6_rvfi.sv b/core/cva6_rvfi.sv index 83e197e0c5..02bd564f76 100644 --- a/core/cva6_rvfi.sv +++ b/core/cva6_rvfi.sv @@ -344,6 +344,7 @@ module cva6_rvfi `CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, fflags, csr.fcsr_q.fflags) `CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, frm, csr.fcsr_q.frm) `CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, fcsr, { csr.fcsr_q.frm `COMMA csr.fcsr_q.fflags}) + `CONNECT_RVFI_FULL(CVA6Cfg.RVZCMT, jvt, { csr.jvt_q.base `COMMA csr.jvt_q.mode}) `CONNECT_RVFI_FULL(CVA6Cfg.FpPresent, ftran, csr.fcsr_q.fprec) `CONNECT_RVFI_SAME(CVA6Cfg.FpPresent, dcsr) diff --git a/core/decoder.sv b/core/decoder.sv index 65e7c22450..0113865204 100644 --- a/core/decoder.sv +++ b/core/decoder.sv @@ -48,6 +48,8 @@ module decoder input logic is_last_macro_instr_i, // Is mvsa01/mva01s macro instruction - macro_decoder input logic is_double_rd_macro_instr_i, + //zcmt instruction + input logic is_zcmt_i, // Is a branch predict instruction - FRONTEND input branchpredict_sbe_t branch_predict_i, // If an exception occured in fetch stage - FRONTEND @@ -178,6 +180,7 @@ module decoder instruction_o.use_zimm = 1'b0; instruction_o.bp = branch_predict_i; instruction_o.vfp = 1'b0; + instruction_o.is_zcmt = is_zcmt_i; ecall = 1'b0; ebreak = 1'b0; check_fprm = 1'b0; diff --git a/core/ex_stage.sv b/core/ex_stage.sv index 115c17f1c5..e7f2ea0d80 100644 --- a/core/ex_stage.sv +++ b/core/ex_stage.sv @@ -47,6 +47,8 @@ module ex_stage input fu_data_t [CVA6Cfg.NrIssuePorts-1:0] fu_data_i, // PC of the current instruction - ISSUE_STAGE input logic [CVA6Cfg.VLEN-1:0] pc_i, + // Is_zcmt instruction - ISSUE_STAGE + input logic is_zcmt_i, // Report whether instruction is compressed - ISSUE_STAGE input logic is_compressed_instr_i, // Report instruction encoding - ISSUE_STAGE @@ -320,6 +322,7 @@ module ex_stage .debug_mode_i, .fu_data_i (one_cycle_data), .pc_i, + .is_zcmt_i, .is_compressed_instr_i, .branch_valid_i (|branch_valid_i), .branch_comp_res_i (alu_branch_res), diff --git a/core/id_stage.sv b/core/id_stage.sv index 43583bde01..2c97fa3a21 100644 --- a/core/id_stage.sv +++ b/core/id_stage.sv @@ -16,8 +16,11 @@ module id_stage #( parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, parameter type branchpredict_sbe_t = logic, + parameter type dcache_req_i_t = logic, + parameter type dcache_req_o_t = logic, parameter type exception_t = logic, parameter type fetch_entry_t = logic, + parameter type jvt_t = logic, parameter type irq_ctrl_t = logic, parameter type scoreboard_entry_t = logic, parameter type interrupts_t = logic, @@ -83,9 +86,15 @@ module id_stage #( // CVXIF Compressed interface input logic [CVA6Cfg.XLEN-1:0] hart_id_i, input logic compressed_ready_i, + //JVT + input jvt_t jvt_i, input x_compressed_resp_t compressed_resp_i, output logic compressed_valid_o, - output x_compressed_req_t compressed_req_o + output x_compressed_req_t compressed_req_o, + // Data cache request ouput - CACHE + input dcache_req_o_t dcache_req_ports_i, + // Data cache request input - CACHE + output dcache_req_i_t dcache_req_ports_o ); // ID/ISSUE register stage typedef struct packed { @@ -103,18 +112,22 @@ module id_stage #( logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal; logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cmp; logic [CVA6Cfg.NrIssuePorts-1:0] is_illegal_cvxif; - 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; - logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed; - logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_cmp; - logic [CVA6Cfg.NrIssuePorts-1:0] is_compressed_cvxif; + logic 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; + logic [31:0] 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; + logic is_compressed_cvxif_zcmp, is_compressed_cvxif_zcmt; - logic [CVA6Cfg.NrIssuePorts-1:0] is_macro_instr_i; - logic stall_instr_fetch; - logic stall_macro_deco; - logic is_last_macro_instr_o; - logic is_double_rd_macro_instr_o; + logic [CVA6Cfg.NrIssuePorts-1:0] is_macro_instr_i; + logic 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_i; if (CVA6Cfg.RVC) begin // --------------------------------------------------------- @@ -128,28 +141,61 @@ module id_stage #( .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]) + .is_macro_instr_o(is_macro_instr_i[i]), + .is_zcmt_instr_o (is_zcmt_instr_i[i]) ); end - if (CVA6Cfg.RVZCMP) begin + if (CVA6Cfg.RVZCMP || (CVA6Cfg.RVZCMT & ~CVA6Cfg.MmuPresent)) begin //MMU should be off when using ZCMT //sequencial decoder - 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[0]), - .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[0]), - .is_compressed_o (is_compressed_cvxif[0]), - .fetch_stall_o (stall_macro_deco), - .is_last_macro_instr_o (is_last_macro_instr_o), - .is_double_rd_macro_instr_o(is_double_rd_macro_instr_o) - ); + 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_i[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) + ); + end + + assign instruction_cvxif[0] = is_zcmt_instr_i[0] ? instruction_cvxif_zcmt : instruction_cvxif_zcmp; + assign is_illegal_cvxif[0] = is_zcmt_instr_i[0] ? is_illegal_cvxif_zcmt : is_illegal_cvxif_zcmp; + assign is_compressed_cvxif[0] = is_zcmt_instr_i[0] ? is_compressed_cvxif_zcmt : is_compressed_cvxif_zcmp; + assign stall_macro_deco = is_zcmt_instr_i[0] ? stall_macro_deco_zcmt : stall_macro_deco_zcmp; + if (CVA6Cfg.SuperscalarEn) begin assign instruction_cvxif[CVA6Cfg.NrIssuePorts-1] = '0; assign is_illegal_cvxif[CVA6Cfg.NrIssuePorts-1] = '0; @@ -208,6 +254,7 @@ module id_stage #( assign is_illegal_cmp = '0; assign is_compressed_cmp = '0; assign is_macro_instr_i = '0; + assign is_zcmt_instr_i = '0; assign is_last_macro_instr_o = '0; assign is_double_rd_macro_instr_o = '0; if (CVA6Cfg.CvxifEn) begin @@ -237,6 +284,7 @@ module id_stage #( .pc_i (fetch_entry_i[i].address), .is_compressed_i (is_compressed_cmp[i]), .is_macro_instr_i (is_macro_instr_i[i]), + .is_zcmt_i (is_zcmt_instr_i[i]), .is_last_macro_instr_i (is_last_macro_instr_o), .is_double_rd_macro_instr_i(is_double_rd_macro_instr_o), .is_illegal_i (is_illegal_cmp[i]), @@ -348,3 +396,4 @@ module id_stage #( end end endmodule + diff --git a/core/include/build_config_pkg.sv b/core/include/build_config_pkg.sv index 5d4808bb1c..dcf66275d8 100644 --- a/core/include/build_config_pkg.sv +++ b/core/include/build_config_pkg.sv @@ -69,6 +69,7 @@ package build_config_pkg; cfg.RVC = CVA6Cfg.RVC; cfg.RVH = CVA6Cfg.RVH; cfg.RVZCB = CVA6Cfg.RVZCB; + cfg.RVZCMT = CVA6Cfg.RVZCMT; cfg.RVZCMP = CVA6Cfg.RVZCMP; cfg.XFVec = CVA6Cfg.XFVec; cfg.CvxifEn = CVA6Cfg.CvxifEn; @@ -123,7 +124,8 @@ package build_config_pkg; cfg.AxiBurstWriteEn = CVA6Cfg.AxiBurstWriteEn; cfg.ICACHE_SET_ASSOC = CVA6Cfg.IcacheSetAssoc; - cfg.ICACHE_SET_ASSOC_WIDTH = CVA6Cfg.IcacheSetAssoc > 1 ? $clog2(CVA6Cfg.IcacheSetAssoc) : CVA6Cfg.IcacheSetAssoc; + cfg.ICACHE_SET_ASSOC_WIDTH = CVA6Cfg.IcacheSetAssoc > 1 ? $clog2(CVA6Cfg.IcacheSetAssoc) : + CVA6Cfg.IcacheSetAssoc; cfg.ICACHE_INDEX_WIDTH = ICACHE_INDEX_WIDTH; cfg.ICACHE_TAG_WIDTH = cfg.PLEN - ICACHE_INDEX_WIDTH; cfg.ICACHE_LINE_WIDTH = CVA6Cfg.IcacheLineWidth; @@ -131,7 +133,8 @@ package build_config_pkg; cfg.DCacheType = CVA6Cfg.DCacheType; cfg.DcacheIdWidth = CVA6Cfg.DcacheIdWidth; cfg.DCACHE_SET_ASSOC = CVA6Cfg.DcacheSetAssoc; - cfg.DCACHE_SET_ASSOC_WIDTH = CVA6Cfg.DcacheSetAssoc > 1 ? $clog2(CVA6Cfg.DcacheSetAssoc) : CVA6Cfg.DcacheSetAssoc; + cfg.DCACHE_SET_ASSOC_WIDTH = CVA6Cfg.DcacheSetAssoc > 1 ? $clog2(CVA6Cfg.DcacheSetAssoc) : + CVA6Cfg.DcacheSetAssoc; cfg.DCACHE_INDEX_WIDTH = DCACHE_INDEX_WIDTH; cfg.DCACHE_TAG_WIDTH = cfg.PLEN - DCACHE_INDEX_WIDTH; cfg.DCACHE_LINE_WIDTH = CVA6Cfg.DcacheLineWidth; diff --git a/core/include/config_pkg.sv b/core/include/config_pkg.sv index d711d5f262..cb061ee3c7 100644 --- a/core/include/config_pkg.sv +++ b/core/include/config_pkg.sv @@ -64,6 +64,8 @@ package config_pkg; bit RVZCB; // Zcmp RISC-V extension bit RVZCMP; + // Zcmt RISC-V extension + bit RVZCMT; // Zicond RISC-V extension bit RVZiCond; // Zicntr RISC-V extension @@ -245,6 +247,7 @@ package config_pkg; bit RVH; bit RVZCB; bit RVZCMP; + bit RVZCMT; bit XFVec; bit CvxifEn; bit RVZiCond; @@ -373,6 +376,7 @@ package config_pkg; assert (Cfg.NrPMPEntries <= 64); assert (!(Cfg.SuperscalarEn && Cfg.RVF)); assert (!(Cfg.SuperscalarEn && Cfg.RVZCMP)); + assert (!(Cfg.SuperscalarEn && Cfg.RVZCMT && ~CVA6Cfg.MmuPresent)); `endif // pragma translate_on endfunction diff --git a/core/include/cv32a60x_config_pkg.sv b/core/include/cv32a60x_config_pkg.sv index 9604b24d39..7cf0af9b43 100644 --- a/core/include/cv32a60x_config_pkg.sv +++ b/core/include/cv32a60x_config_pkg.sv @@ -42,6 +42,7 @@ package cva6_config_pkg; RVV: bit'(0), RVC: bit'(1), RVH: bit'(0), + RVZCMT: bit'(1), RVZCB: bit'(1), RVZCMP: bit'(1), XFVec: bit'(0), diff --git a/core/include/cv32a65x_config_pkg.sv b/core/include/cv32a65x_config_pkg.sv index d9d028fa16..5d0e73c912 100644 --- a/core/include/cv32a65x_config_pkg.sv +++ b/core/include/cv32a65x_config_pkg.sv @@ -42,6 +42,7 @@ package cva6_config_pkg; RVV: bit'(0), RVC: bit'(1), RVH: bit'(0), + RVZCMT: bit'(0), RVZCB: bit'(1), RVZCMP: bit'(0), XFVec: bit'(0), diff --git a/core/include/cv32a6_embedded_config_pkg_deprecated.sv b/core/include/cv32a6_embedded_config_pkg_deprecated.sv index ff6a1fcd41..7c3e02a746 100644 --- a/core/include/cv32a6_embedded_config_pkg_deprecated.sv +++ b/core/include/cv32a6_embedded_config_pkg_deprecated.sv @@ -96,6 +96,7 @@ package cva6_config_pkg; RVZCB: bit'(CVA6ConfigZcbExtEn), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), + RVZCMT: bit'(0), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), RVZicntr: bit'(1), diff --git a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv index be7ff3ee14..7adff10e84 100644 --- a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv +++ b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv32a6_imac_sv0_config_pkg.sv b/core/include/cv32a6_imac_sv0_config_pkg.sv index 2687370b26..676fcfc720 100644 --- a/core/include/cv32a6_imac_sv0_config_pkg.sv +++ b/core/include/cv32a6_imac_sv0_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv32a6_imac_sv32_config_pkg.sv b/core/include/cv32a6_imac_sv32_config_pkg.sv index 9c2e622947..e28ed552b0 100644 --- a/core/include/cv32a6_imac_sv32_config_pkg.sv +++ b/core/include/cv32a6_imac_sv32_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv32a6_imafc_sv32_config_pkg.sv b/core/include/cv32a6_imafc_sv32_config_pkg.sv index 6ad09136e4..ea5be1d1e3 100644 --- a/core/include/cv32a6_imafc_sv32_config_pkg.sv +++ b/core/include/cv32a6_imafc_sv32_config_pkg.sv @@ -96,6 +96,7 @@ package cva6_config_pkg; RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), RVZCMP: bit'(CVA6ConfigZcmpExtEn), + RVZCMT: bit'(0), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), diff --git a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv index 0422eef3bf..f252538b11 100644 --- a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv +++ b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv @@ -96,6 +96,7 @@ package cva6_config_pkg; RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), RVZCMP: bit'(CVA6ConfigZcmpExtEn), + RVZCMT: bit'(0), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), diff --git a/core/include/cv64a6_imafdc_sv39_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_config_pkg.sv index 8050e88f27..e01d7201f3 100644 --- a/core/include/cv64a6_imafdc_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv index 36c4397ade..200c5c7f79 100644 --- a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv @@ -103,6 +103,7 @@ package cva6_config_pkg; RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), RVZCMP: bit'(CVA6ConfigZcmpExtEn), + RVZCMT: bit'(0), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), diff --git a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv index 16f329c456..6e84e73a58 100644 --- a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv index b785da8296..51f8a25da5 100644 --- a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv64a6_imafdch_sv39_config_pkg.sv b/core/include/cv64a6_imafdch_sv39_config_pkg.sv index 6e4d755ea1..22c52b8f98 100644 --- a/core/include/cv64a6_imafdch_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdch_sv39_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv index 49bc7693b2..a832745051 100644 --- a/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv @@ -95,6 +95,7 @@ package cva6_config_pkg; RVC: bit'(CVA6ConfigCExtEn), RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMT: bit'(0), RVZCMP: bit'(CVA6ConfigZcmpExtEn), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), diff --git a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv index 2c642f5345..a35691c5d8 100644 --- a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv @@ -96,6 +96,7 @@ package cva6_config_pkg; RVH: bit'(CVA6ConfigHExtEn), RVZCB: bit'(CVA6ConfigZcbExtEn), RVZCMP: bit'(CVA6ConfigZcmpExtEn), + RVZCMT: bit'(0), XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), diff --git a/core/include/cv64a6_mmu_config_pkg.sv b/core/include/cv64a6_mmu_config_pkg.sv index 8e0b686386..4d9d053431 100644 --- a/core/include/cv64a6_mmu_config_pkg.sv +++ b/core/include/cv64a6_mmu_config_pkg.sv @@ -51,6 +51,7 @@ package cva6_config_pkg; RVH: bit'(0), RVZCB: bit'(1), RVZCMP: bit'(0), + RVZCMT: bit'(0), XFVec: bit'(0), CvxifEn: bit'(1), RVZiCond: bit'(0), diff --git a/core/include/riscv_pkg.sv b/core/include/riscv_pkg.sv index 40499c6371..5e29330277 100644 --- a/core/include/riscv_pkg.sv +++ b/core/include/riscv_pkg.sv @@ -385,6 +385,8 @@ package riscv; CSR_FFLAGS = 12'h001, CSR_FRM = 12'h002, CSR_FCSR = 12'h003, + //jvt + CSR_JVT = 12'h017, CSR_FTRAN = 12'h800, // Vector CSRs CSR_VSTART = 12'h008, @@ -724,6 +726,8 @@ package riscv; localparam logic [63:0] SSTATUS_MXR = 'h00080000; localparam logic [63:0] SSTATUS_UPIE = 'h00000010; localparam logic [63:0] SSTATUS_UXL = 64'h0000000300000000; + // CSR Bit Implementation Masks + function automatic logic [63:0] sstatus_sd(logic IS_XLEN64); return {IS_XLEN64, 31'h00000000, ~IS_XLEN64, 31'h00000000}; endfunction @@ -859,6 +863,12 @@ package riscv; priv_lvl_t prv; } dcsr_t; + //jvt struct + parameter JVT_ADDR_WIDTH = XLEN - 6; + typedef struct packed { + logic [JVT_ADDR_WIDTH-1:0] base; + logic [5:0] mode; + } jvt_t; // Instruction Generation *incomplete* function automatic logic [31:0] jal(logic [4:0] rd, logic [20:0] imm); // OpCode Jal diff --git a/core/include/rvfi_types.svh b/core/include/rvfi_types.svh index 68881bf0d1..8bf20f7659 100644 --- a/core/include/rvfi_types.svh +++ b/core/include/rvfi_types.svh @@ -39,6 +39,7 @@ rvfi_csr_elmt_t fflags; \ rvfi_csr_elmt_t frm; \ rvfi_csr_elmt_t fcsr; \ + rvfi_csr_elmt_t jvt; \ rvfi_csr_elmt_t ftran; \ rvfi_csr_elmt_t dcsr; \ rvfi_csr_elmt_t dpc; \ @@ -130,6 +131,7 @@ `define RVFI_PROBES_CSR_T(Cfg) struct packed { \ riscv::fcsr_t fcsr_q; \ riscv::dcsr_t dcsr_q; \ + riscv::jvt_t jvt_q; \ logic [Cfg.XLEN-1:0] dpc_q; \ logic [Cfg.XLEN-1:0] dscratch0_q; \ logic [Cfg.XLEN-1:0] dscratch1_q; \ diff --git a/core/issue_read_operands.sv b/core/issue_read_operands.sv index fa357f42fb..82c9ea5af2 100644 --- a/core/issue_read_operands.sv +++ b/core/issue_read_operands.sv @@ -56,6 +56,8 @@ module issue_read_operands output logic [CVA6Cfg.NrIssuePorts-1:0][CVA6Cfg.XLEN-1:0] rs2_forwarding_o, // Program Counter - EX_STAGE output logic [CVA6Cfg.VLEN-1:0] pc_o, + // Is zcmt - EX_STAGE + output logic is_zcmt_o, // Is compressed instruction - EX_STAGE output logic is_compressed_instr_o, // Fixed Latency Unit is ready - EX_STAGE @@ -119,7 +121,6 @@ module issue_read_operands input logic [CVA6Cfg.NrCommitPorts-1:0] we_gpr_i, // FPR write enable - COMMIT_STAGE input logic [CVA6Cfg.NrCommitPorts-1:0] we_fpr_i, - // Issue stall - PERF_COUNTERS output logic stall_issue_o ); @@ -1101,6 +1102,7 @@ module issue_read_operands tinst_q <= '0; end pc_o <= '0; + is_zcmt_o <= '0; is_compressed_instr_o <= 1'b0; branch_predict_o <= {cf_t'(0), {CVA6Cfg.VLEN{1'b0}}}; x_transaction_rejected_o <= 1'b0; @@ -1120,6 +1122,8 @@ module issue_read_operands pc_o <= issue_instr_i[0].pc; is_compressed_instr_o <= issue_instr_i[0].is_compressed; branch_predict_o <= issue_instr_i[0].bp; + if (CVA6Cfg.RVZCMT) is_zcmt_o <= issue_instr_i[0].is_zcmt; + else is_zcmt_o <= '0; end x_transaction_rejected_o <= 1'b0; if (issue_instr_i[0].fu == CVXIF) begin diff --git a/core/issue_stage.sv b/core/issue_stage.sv index ea922d5ce0..eb33f6af2b 100644 --- a/core/issue_stage.sv +++ b/core/issue_stage.sv @@ -60,6 +60,8 @@ module issue_stage output fu_data_t [CVA6Cfg.NrIssuePorts-1:0] fu_data_o, // Program Counter - EX_STAGE output logic [CVA6Cfg.VLEN-1:0] pc_o, + // Is zcmt instruction - EX_STAGE + output logic is_zcmt_o, // Is compressed instruction - EX_STAGE output logic is_compressed_instr_o, // Transformed trap instruction - EX_STAGE @@ -263,6 +265,7 @@ module issue_stage .rs1_forwarding_o (rs1_forwarding_xlen), .rs2_forwarding_o (rs2_forwarding_xlen), .pc_o, + .is_zcmt_o, .is_compressed_instr_o, .flu_ready_i (flu_ready_i), .alu_valid_o (alu_valid_o), diff --git a/core/zcmt_decoder.sv b/core/zcmt_decoder.sv new file mode 100644 index 0000000000..75fd1d33b6 --- /dev/null +++ b/core/zcmt_decoder.sv @@ -0,0 +1,121 @@ +// Author: Farhan Ali Shah, 10xEngineers +// Date: 15.11.2024 +// Description: ZCMT extension in the CVA6 core targeting the 32-bit embedded-class platforms (CV32A60x). +// ZCMT is a code-size reduction feature that utilizes compressed table jump instructions (cm.jt and cm.jalt) to +//reduce code size for embedded systems +// +module zcmt_decoder #( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, + parameter type dcache_req_i_t = logic, + parameter type dcache_req_o_t = logic, + parameter type jvt_t = logic, + parameter type branchpredict_sbe_t = logic +) ( + input logic clk_i, // Clock + input logic rst_ni, // Synchronous reset + input logic [31:0] instr_i, // instruction + input logic [CVA6Cfg.VLEN-1:0] pc_i, // PC + input logic is_zcmt_instr_i, // Intruction is of macro extension + input logic illegal_instr_i, // From compressed decoder + input logic is_compressed_i, // is compressed instruction + input jvt_t jvt_i, + input dcache_req_o_t req_port_i, // Data cache request ouput - CACHE + + output logic [31:0] instr_o, // Instruction out + output logic illegal_instr_o, // Illegel instruction + output logic is_compressed_o, // is compressed instruction + output logic fetch_stall_o, // Wait while address fetched from table + output dcache_req_i_t req_port_o // Data cache request input - CACHE +); + + // FSM States + enum logic { + IDLE, // if ZCMT instruction then request sent to fetch the entry from jump table + TABLE_JUMP // Check the valid data from jump table and Calculate the offset for jump and create jal instruction + } + state_d, state_q; + // Temporary registers + //Physical address: jvt + (index <<2) + logic [CVA6Cfg.XLEN+1:0] table_address; //Virtual address: {00,Physical address} + logic [31:0] jump_addr; //jump address immidiate + + always_comb begin + state_d = state_q; + illegal_instr_o = 1'b0; + is_compressed_o = is_zcmt_instr_i ? 1'b1 : is_compressed_i; + fetch_stall_o = is_zcmt_instr_i ? 1'b1 : 0; + + //cache request port + req_port_o.data_wdata = '0; + req_port_o.data_wuser = '0; + req_port_o.data_req = 1'b0; + req_port_o.data_we = 1'b0; + req_port_o.data_be = '0; + req_port_o.data_size = 2'b10; + req_port_o.data_id = 1'b1; + req_port_o.kill_req = 1'b0; + req_port_o.tag_valid = 1'b1; + + unique case (state_q) + IDLE: begin + 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 = {2'b00, ({jvt_i.base, instr_i[7:2], 2'b00})}; + table_address = {2'b00, ({jvt_i.base, jvt_i.mode} + {24'h0, instr_i[7:2], 2'b00})}; + req_port_o.address_index = table_address[9:0]; + req_port_o.address_tag = table_address[33:10]; + state_d = TABLE_JUMP; + req_port_o.data_req = 1'b1; + end else illegal_instr_o = 1'b1; + //Condition may be extented for 64 bits embedded targets with No MMU + end else begin + illegal_instr_o = illegal_instr_i; + instr_o = instr_i; + state_d = IDLE; + end + end + TABLE_JUMP: begin + if (req_port_i.data_rvalid) begin + jump_addr = $unsigned($signed(req_port_i.data_rdata) - $signed(pc_i)); + if (instr_i[9:2] < 32) begin //- jal pc_offset, x0 for no return stack + instr_o = { + jump_addr[20], + jump_addr[10:1], + jump_addr[11], + jump_addr[19:12], + 5'h0, + riscv::OpcodeJal + }; + end else if ((instr_i[9:2] >= 32) & (instr_i[9:2] <= 255)) begin //- jal pc_offset, x1 for return stack + instr_o = { + jump_addr[20], + jump_addr[10:1], + jump_addr[11], + jump_addr[19:12], + 5'h1, + riscv::OpcodeJal + }; + end else begin + illegal_instr_o = 1'b1; + instr_o = instr_i; + end + state_d = IDLE; + end else begin + state_d = TABLE_JUMP; + end + end + default: begin + state_d = IDLE; + end + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (~rst_ni) begin + state_q <= IDLE; + + end else begin + state_q <= state_d; + end + end +endmodule diff --git a/verif/tests/custom/zcmt/cm_jalt.S b/verif/tests/custom/zcmt/cm_jalt.S new file mode 100644 index 0000000000..46e1ff79ab --- /dev/null +++ b/verif/tests/custom/zcmt/cm_jalt.S @@ -0,0 +1,62 @@ +.globl _start +_start: + la t0, trap_handler + csrw mtvec, t0 + + la a1, target1 + la t0, __jvt_base$ + + sw a1, 128(t0) //cm.jalt entry start from index >=32 + + csrw jvt, t0 + + fence.i + # Perform jump using the index from JVT + cm.jalt 32 + + li t1, 1 + addi x20,x20, 9 + j write_tohost + + + + +exit: + j write_tohost + +write_tohost: + li x1, 1 + la t0, tohost + sw x1, 0(t0) + j write_tohost + + +# Jump Vector Table (JVT) Section +# Create a separate section for the JVT +.section .riscv.jvt, "ax" +.align 6 # Align the JVT on a 64-byte boundary (6 = 2^6 = 64) +__jvt_base$: + .word 0x80000054 + .word 0x80000800 + .word 0x80000802 + .word 0x80000804 + +# Target Addresses (Where cm.jalt will jump) +target0: + li x5, 99 + j write_tohost +target1: + li x2, 99 + j write_tohost + +target2: + addi x2,x20, 5 + j write_tohost + + +trap_handler: + j exit + + +.align 6; .global tohost; tohost: .dword 0; +.align 6; .global fromhost; fromhost: .dword 0; diff --git a/verif/tests/custom/zcmt/cm_jalt_ret.S b/verif/tests/custom/zcmt/cm_jalt_ret.S new file mode 100644 index 0000000000..82eaf36cc4 --- /dev/null +++ b/verif/tests/custom/zcmt/cm_jalt_ret.S @@ -0,0 +1,62 @@ +.globl _start +_start: + la t0, trap_handler + csrw mtvec, t0 + + la a1, target1 + la t0, __jvt_base$ + + sw a1, 128(t0) //cm.jalt entry start from index >=32 + + csrw jvt, t0 + + fence.i + # Perform jump using the index from JVT + cm.jalt 32 + + li t1, 1 + addi x20,x20, 9 + j write_tohost + + + + +exit: + j write_tohost + +write_tohost: + li x1, 1 + la t0, tohost + sw x1, 0(t0) + j write_tohost + + +# Jump Vector Table (JVT) Section +# Create a separate section for the JVT +.section .riscv.jvt, "ax" +.align 6 # Align the JVT on a 64-byte boundary (6 = 2^6 = 64) +__jvt_base$: + .word 0x80000054 + .word 0x80000800 + .word 0x80000802 + .word 0x80000804 + +# Target Addresses (Where cm.jalt will jump) +target0: + li x5, 9 + j write_tohost +target1: + li x2, 99 + ret + +target2: + addi x2,x20, 5 + j write_tohost + + +trap_handler: + j exit + + +.align 6; .global tohost; tohost: .dword 0; +.align 6; .global fromhost; fromhost: .dword 0; diff --git a/verif/tests/custom/zcmt/cm_jt.S b/verif/tests/custom/zcmt/cm_jt.S new file mode 100644 index 0000000000..b2dd88a49c --- /dev/null +++ b/verif/tests/custom/zcmt/cm_jt.S @@ -0,0 +1,58 @@ +.globl _start +_start: + la t0, trap_handler + csrw mtvec, t0 + + la a1, target1 + la t0, __jvt_base$ + + sw a1, 0(t0) + + csrw jvt, t0 + + fence.i + + cm.jt 0 # Perform jump using the index 0 from JVT + + addi x18,x18, 3 + j target2 + +exit: + j write_tohost + +write_tohost: + li x1, 1 + la t0, tohost + sw x1, 0(t0) + j write_tohost + + + +# Jump Vector Table (JVT) Section +# Create a separate section for the JVT +.section .riscv.jvt, "ax" +.align 6 # Align the JVT on a 64-byte boundary (6 = 2^6 = 64) +__jvt_base$: + .word 0x80000054 + .word 0x80000800 + .word 0x80000802 + .word 0x80000804 + +# Target Addresses (Where cm.jt will jump) +target0: + j write_tohost +target1: + addi x6,x0, 7 + j write_tohost + +target2: + addi x2,x20, 5 + j write_tohost + + +trap_handler: + j exit + + +.align 6; .global tohost; tohost: .dword 0; +.align 6; .global fromhost; fromhost: .dword 0; diff --git a/verif/tests/custom/zcmt/jvt_csr.S b/verif/tests/custom/zcmt/jvt_csr.S new file mode 100644 index 0000000000..4ccd3d9fd2 --- /dev/null +++ b/verif/tests/custom/zcmt/jvt_csr.S @@ -0,0 +1,51 @@ +.globl _start +_start: + la t0, trap_handler + csrw mtvec, t0 + la t0, __jvt_base$ + + csrw jvt, t0 + fence.i + csrr x7, jvt + + j exit + +exit: + j write_tohost + +write_tohost: + li x1, 1 + la t0, tohost + sw x1, 0(t0) + j write_tohost + + + +# Jump Vector Table (JVT) Section +# Create a separate section for the JVT +.section .riscv.jvt, "ax" +.align 6 # Align the JVT on a 64-byte boundary (6 = 2^6 = 64) +__jvt_base$: + .word 0x80000054 + .word 0x80000800 + .word 0x80000802 + .word 0x80000804 + +# Target Addresses (Where cm.jt will jump) +target0: + j write_tohost +target1: + addi x6,x0, 7 + j write_tohost + +target2: + addi x2,x20, 5 + j write_tohost + + +trap_handler: + j exit + + +.align 6; .global tohost; tohost: .dword 0; +.align 6; .global fromhost; fromhost: .dword 0;