<commit_before>/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

`ifdef COVERAGE_WITH_NO_HAZARDS
    `define CG_HAZARD_COV(CG_HAZARD_CODE) \
        // CG_HAZARD_CODE
`else
     `define CG_HAZARD_COV(CG_HAZARD_CODE) \
        CG_HAZARD_CODE
`endif

`ifdef COVERAGE_WITH_NO_IGNORES
    `define CG_IGNORE_COV(CG_IGNORE_CODE) \
        // CG_IGNORE_CODE
`else
    `define CG_IGNORE_COV(CG_IGNORE_CODE) \
        CG_IGNORE_CODE
`endif

`define INSTR_CG_BEGIN(INSTR_NAME) \
  covergroup ``INSTR_NAME``_cg with function sample(riscv_instr_cov_item instr);

`define R_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rs2         : coverpoint instr.rs2; \
    cp_rd          : coverpoint instr.rd;  \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_rs2_sign    : coverpoint instr.rs2_sign; \
    cp_rd_sign     : coverpoint instr.rd_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define CMP_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rd          : coverpoint instr.rd;  \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_result      : coverpoint instr.rd_value[0]; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define SB_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rs2         : coverpoint instr.rs2; \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_rs2_sign    : coverpoint instr.rs2_sign; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    cp_branch_hit  : coverpoint instr.branch_hit; \
    cp_sign_cross  : cross cp_rs1_sign, cp_rs2_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define STORE_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1 { \
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};) \
    } \
    cp_rs2         : coverpoint instr.rs2; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        } \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define LOAD_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1 { \
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};) \
    } \
    cp_rd          : coverpoint instr.rd; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard; \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define I_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rd          : coverpoint instr.rd; \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_rd_sign     : coverpoint instr.rd_sign; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define U_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd          : coverpoint instr.rd; \
    cp_rd_sign     : coverpoint instr.rd_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \


`define J_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    cp_rd          : coverpoint instr.rd; \
    cp_rd_align    : coverpoint instr.rd_value[1];


`define CSR_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd          : coverpoint instr.rd; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define CR_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs2         : coverpoint instr.rs2; \
    cp_rd          : coverpoint instr.rd; \
    cp_rs2_sign    : coverpoint instr.rs2_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define CI_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd       : coverpoint instr.rd; \
    cp_imm_sign : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define CSS_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs2      : coverpoint instr.rs2; \
    cp_imm_sign : coverpoint instr.imm_sign; \
    cp_rs2_sign : coverpoint instr.rs2_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define CIW_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_imm_sign : coverpoint instr.imm_sign; \
    cp_rd       : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define CL_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1      : coverpoint instr.rs1 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    cp_rd       : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard; \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define CL_SP_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd       : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    }

`define CS_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1      : coverpoint instr.rs1 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    cp_rs2      : coverpoint instr.rs2 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        } \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define CS_SP_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs2      : coverpoint instr.rs2 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    }

`define CA_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd      : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    cp_rs2      : coverpoint instr.rs2 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \


`define CB_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1      : coverpoint instr.rs1 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define CJ_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_imm_sign : coverpoint instr.imm_sign;

`define CG_END endgroup

`define CG_SELECTOR_BEGIN(CG_ISA) \
    if ((CG_ISA inside {supported_isa}) && (default_cov || (cov_isa == CG_ISA))) begin \

`define CG_SELECTOR_END \
    end \

class riscv_instr_cover_group;

  riscv_instr_gen_config  cfg;
  riscv_instr_cov_item    cur_instr;
  riscv_instr_cov_item    pre_instr;
  riscv_instr_name_t      instr_list[$];
  int unsigned            instr_cnt;
  int unsigned            branch_instr_cnt;
  bit [4:0]               branch_hit_history; // The last 5 branch result
  bit                     default_cov = 'b1;

`VECTOR_INCLUDE("riscv_instr_cover_group_inc_cpu_declare.sv")

  ///////////// RV32I instruction functional coverage //////////////

  // Arithmetic instructions
  `R_INSTR_CG_BEGIN(add)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(sub)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(addi)
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign, cp_rd_sign;
  `CG_END

  `U_INSTR_CG_BEGIN(lui)
  `CG_END

  `U_INSTR_CG_BEGIN(auipc)
  `CG_END

  // Shift instructions
  `R_INSTR_CG_BEGIN(sra)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(sll)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(srl)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `INSTR_CG_BEGIN(srai)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(slli)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(srli)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  // Logical instructions
  `R_INSTR_CG_BEGIN(xor)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(or)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(and)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(xori)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(ori)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(andi)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  // Compare instructions
  `CMP_INSTR_CG_BEGIN(slt)
    cp_rs2        : coverpoint instr.rs2;
    cp_rs2_sign   : coverpoint instr.rs2_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `CMP_INSTR_CG_BEGIN(sltu)
    cp_rs2        : coverpoint instr.rs2;
    cp_rs2_sign   : coverpoint instr.rs2_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `CMP_INSTR_CG_BEGIN(slti)
    cp_imm_sign   : coverpoint instr.imm_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  `CMP_INSTR_CG_BEGIN(sltiu)
    cp_imm_sign   : coverpoint instr.imm_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  // Branch instruction
  `SB_INSTR_CG_BEGIN(beq)
  `CG_END

  `SB_INSTR_CG_BEGIN(bne)
  `CG_END

  `SB_INSTR_CG_BEGIN(blt)
  `CG_END

  `SB_INSTR_CG_BEGIN(bge)
  `CG_END

  `SB_INSTR_CG_BEGIN(bltu)
  `CG_END

  `SB_INSTR_CG_BEGIN(bgeu)
  `CG_END

  // Load instructions
  `LOAD_INSTR_CG_BEGIN(lb)
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lh)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lw)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lbu)
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lhu)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  // Store instruction
  `STORE_INSTR_CG_BEGIN(sb)
  `CG_END

  `STORE_INSTR_CG_BEGIN(sh)
    cp_misalign: coverpoint instr.unaligned_mem_access;
  `CG_END

  `STORE_INSTR_CG_BEGIN(sw)
    cp_misalign: coverpoint instr.unaligned_mem_access;
  `CG_END

  // JUMP instruction
  `J_INSTR_CG_BEGIN(jal)
  `CG_END

  `J_INSTR_CG_BEGIN(jalr)
    cp_rs1_link : coverpoint instr.rs1 {
      bins ra = {RA};
      bins t1 = {T1};
      bins non_link = default;
    }
    cp_rd_link : coverpoint instr.rd {
      bins ra = {RA};
      bins t1 = {T1};
      bins non_link = default;
    }
    cp_ras : cross cp_rs1_link, cp_rd_link;
  `CG_END


  // CSR instructions
  `CSR_INSTR_CG_BEGIN(csrrw)
    cp_rs1 : coverpoint instr.rs1;
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrs)
    cp_rs1 : coverpoint instr.rs1;
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrc)
    cp_rs1 : coverpoint instr.rs1;
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrwi)
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrsi)
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrci)
  `CG_END

  covergroup rv32i_misc_cg with function sample(riscv_instr_cov_item instr);
    cp_misc : coverpoint instr.instr_name {
      bins instr[] = {FENCE, FENCE_I, EBREAK, ECALL, MRET, WFI};
    }
  endgroup



  // RV32M

  `R_INSTR_CG_BEGIN(mul)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(mulh)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(mulhsu)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(mulhu)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(div)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(divu)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(rem)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(remu)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  // RV64M
  // Below instructions only do calculation based on lower 32 bits, and extend the result to 64
  // bits. Add special covergroup for corner cases

  `R_INSTR_CG_BEGIN(mulw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(divw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(divuw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(remw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(remuw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  // RV64I
  `LOAD_INSTR_CG_BEGIN(lwu)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `LOAD_INSTR_CG_BEGIN(ld)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `STORE_INSTR_CG_BEGIN(sd)
    cp_misalign: coverpoint instr.unaligned_mem_access;
  `CG_END

  `R_INSTR_CG_BEGIN(sraw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(sllw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(srlw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  // imm[5] could be 1 for RV64I SLLI/SRAI/SRLI
  `INSTR_CG_BEGIN(srai64)
    cp_imm: coverpoint instr.imm[5];
  `CG_END

  `INSTR_CG_BEGIN(slli64)
    cp_imm: coverpoint instr.imm[5];
  `CG_END

  `INSTR_CG_BEGIN(srli64)
    cp_imm: coverpoint instr.imm[5];
  `CG_END

  `INSTR_CG_BEGIN(sraiw)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(slliw)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(srliw)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `R_INSTR_CG_BEGIN(addw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(subw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(addiw)
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign, cp_rd_sign;
  `CG_END

  // RV32C

  `CL_INSTR_CG_BEGIN(c_lw)
  `CG_END

  `CL_SP_INSTR_CG_BEGIN(c_lwsp)
  `CG_END

  `CS_INSTR_CG_BEGIN(c_sw)
  `CG_END

  `CS_SP_INSTR_CG_BEGIN(c_swsp)
  `CG_END

  `CIW_INSTR_CG_BEGIN(c_addi4spn)
  `CG_END

  `CI_INSTR_CG_BEGIN(c_addi)
  `CG_END

  `INSTR_CG_BEGIN(c_addi16sp)
    cp_imm_sign : coverpoint instr.imm_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard {
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD};
        })
  `CG_END

  `CI_INSTR_CG_BEGIN(c_li)
  `CG_END

  `INSTR_CG_BEGIN(c_lui)
    cp_rd : coverpoint instr.rd {
        `CG_IGNORE_COV(ignore_bins bin = {ZERO, SP};)
    }
  `CG_END

  `CA_INSTR_CG_BEGIN(c_sub)
  `CG_END

  `CR_INSTR_CG_BEGIN(c_add)
  `CG_END

  `CR_INSTR_CG_BEGIN(c_mv)
  `CG_END

  `CB_INSTR_CG_BEGIN(c_andi)
    cp_imm_sign : coverpoint instr.imm_sign;
  `CG_END

  `CA_INSTR_CG_BEGIN(c_xor)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_or)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_and)
  `CG_END

  `CB_INSTR_CG_BEGIN(c_beqz)
    cp_imm_sign : coverpoint instr.imm_sign;
  `CG_END

  `CB_INSTR_CG_BEGIN(c_bnez)
    cp_imm_sign : coverpoint instr.imm_sign;
  `CG_END

  `CB_INSTR_CG_BEGIN(c_srli)
  `CG_END

  `CB_INSTR_CG_BEGIN(c_srai)
  `CG_END

  `INSTR_CG_BEGIN(c_slli)
    cp_rd          : coverpoint instr.rd;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard {
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
        })
  `CG_END

  `CJ_INSTR_CG_BEGIN(c_j)
  `CG_END

  `CJ_INSTR_CG_BEGIN(c_jal)
  `CG_END

  `INSTR_CG_BEGIN(c_jr)
    cp_rs1      : coverpoint instr.rs1 {
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};)
    }
  `CG_END

  `INSTR_CG_BEGIN(c_jalr)
    cp_rs1      : coverpoint instr.rs1 {
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};)
    }
    cp_rd_align : coverpoint instr.rd_value[1];
  `CG_END

  // RV64C

  `CL_INSTR_CG_BEGIN(c_ld)
  `CG_END

  `CL_SP_INSTR_CG_BEGIN(c_ldsp)
  `CG_END

  `CS_INSTR_CG_BEGIN(c_sd)
  `CG_END

  `CS_SP_INSTR_CG_BEGIN(c_sdsp)
  `CG_END

  `CI_INSTR_CG_BEGIN(c_addiw)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_subw)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_addw)
  `CG_END

  `INSTR_CG_BEGIN(hint)
    cp_hint : coverpoint instr.binary[15:0] {
      wildcard bins addi    = {16'b0000_1xxx_x000_0001,
                               16'b0000_x1xx_x000_0001,
                               16'b0000_xx1x_x000_0001,
                               16'b0000_xxx1_x000_0001,
                               16'b0000_xxxx_1000_0001};
      wildcard bins li      = {16'b010x_0000_0xxx_xx01};
      wildcard bins lui     = {16'b011x_0000_0xxx_xx01};
      wildcard bins srli64  = {16'b1000_00xx_x000_0001};
      wildcard bins srai64  = {16'b1000_01xx_x000_0001};
      wildcard bins slli    = {16'b000x_0000_0xxx_xx10};
      wildcard bins slli64  = {16'b0000_xxxx_x000_0010};
      wildcard bins mv      = {16'b1000_0000_01xx_xx10,
                               16'b1000_0000_0x1x_xx10,
                               16'b1000_0000_0xx1_xx10,
                               16'b1000_0000_0xxx_1x10,
                               16'b1000_0000_0xxx_x110};
      wildcard bins add     = {16'b1001_0000_01xx_xx10,
                               16'b1001_0000_0x1x_xx10,
                               16'b1001_0000_0xx1_xx10,
                               16'b1001_0000_0xxx_1x10,
                               16'b1001_0000_0xxx_x110};
    }
  `CG_END

  // Cover all illegal instruction
  covergroup illegal_compressed_instr_cg with function sample(bit [31:0] binary);
    cp_point : coverpoint binary {
      wildcard bins c_addi4spn = {32'bxxxx_xxxxx_0000_0000_000x_xx00};
      wildcard bins c_addi16sp = {32'bxxxx_xxxxx_0110_0001_0000_0001};
      wildcard bins c_lui      = {32'bxxxx_xxxxx_0110_xxxx_1000_0001,
                                  32'bxxxx_xxxxx_0110_xx1x_x000_0001,
                                  32'bxxxx_xxxxx_0110_x1xx_x000_0001,
                                  32'bxxxx_xxxxx_0110_1xxx_x000_0001};
      wildcard bins c_jr       = {32'bxxxx_xxxxx_1000_0000_0000_0001};
    }
  endgroup

  // Cover all non-compressed opcode
  covergroup opcode_cg with function sample(bit [4:0] opcode);
    cp_opcode: coverpoint opcode;
  endgroup

  // Cover all compressed instruction opcode
  covergroup compressed_opcode_cg with function sample(bit [15:0] binary);
    cp_00 : coverpoint binary[15:13] iff (binary[1:0] == 2'b00);
    cp_01 : coverpoint binary[15:13] iff (binary[1:0] == 2'b01);
    cp_10 : coverpoint binary[15:13] iff (binary[1:0] == 2'b10);
  endgroup

  // Branch hit history
  covergroup branch_hit_history_cg;
    cp_branch_history: coverpoint branch_hit_history;
  endgroup

  // Instruction transition for all supported instructions
  /* TODO: Refine the transition functional coverage, not all combinations are interesting
  covergroup instr_trans_cg with function sample();
    cp_instr: coverpoint instr_name {
      bins instr[] = cp_instr with (is_supported_instr(riscv_instr_name_t'(item)));
    }
    cp_pre_instr: coverpoint pre_instr_name {
      // This is a helper coverpoint for cross coverpoint below, it should not be counted when
      // calculate the coverage score
      type_option.weight = 0;
      bins instr[] = cp_pre_instr with (is_supported_instr(riscv_instr_name_t'(item)));
    }
    cp_trans: cross cp_pre_instr, cp_instr {
      // Cover all instruction transitions, except for below system instructions
      ignore_bins ignore = binsof(cp_instr) intersect {ECALL, URET, SRET, SRET, DRET} ||
                           binsof(cp_pre_instr) intersect {ECALL, URET, SRET, SRET, DRET};
    }
  endgroup
  */

  covergroup privileged_csr_cg with function sample(bit [11:0] csr);
    cp_csr : coverpoint csr {
      bins pcsr[] = cp_csr with (item inside {implemented_csr});
    }
  endgroup


  // Privileged CSR covergroup
  covergroup mcause_exception_cg with function sample(exception_cause_t exception);
    cp_exception: coverpoint exception {
       bins exception[] = cp_exception with (item inside {implemented_exception});
    }
  endgroup

  covergroup mcause_interrupt_cg with function sample(interrupt_cause_t interrupt);
    cp_interrupt: coverpoint interrupt {
       bins interrupt[] = cp_interrupt with (item inside {implemented_interrupt});
    }
  endgroup

  covergroup mepc_alignment_cg with function sample(bit [XLEN-1:0] val);
    cp_align: coverpoint val[1:0] {
      bins alignment[] = {2'b00, 2'b10};
    }
  endgroup

  covergroup mstatus_m_cg with function sample(bit [XLEN-1:0] val);
    cp_mie  : coverpoint val[3];
    cp_mpie : coverpoint val[7];
    cp_mpp  : coverpoint val[12:11];
  endgroup

`VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_add.sv")

  function new(riscv_instr_gen_config cfg);
    riscv_instr_group_t cov_isa;
    default_cov = 'b1;
    this.cfg = cfg;
    cur_instr = riscv_instr_cov_item::type_id::create("cur_instr");
    pre_instr = riscv_instr_cov_item::type_id::create("pre_instr");
    build_instr_list();

    // TODO should be moved out of coverage for reporting
    if (has_vector_engine) begin
      $display("vector_options: VLEN=%0d", VLEN);
      $display("vector_options: ELEN=%0d", ELEN);
      $display("vector_options: SLEN=%0d", SLEN);
    end

    // process coverage options
    if ($test$plusargs("no_default_cov"))  begin
      $display("coverage option: +no_default_cov");
      default_cov = 'b0;
    end
    if ($test$plusargs("cov_isa=")) begin
      string cov_isa_str;
      riscv_instr_group_t isa;
      bit got_one = 'b0;
      void'($value$plusargs("cov_isa=%0s", cov_isa_str));
      cov_isa_str = cov_isa_str.toupper();
      $display("coverage option: +cov_isa=%0s", cov_isa_str);
      isa = isa.first;
      do begin
        if (isa.name == cov_isa_str) begin
          cov_isa = isa;
          got_one = 'b1;
          break;
        end
        isa =  isa.next;
      end while (isa != isa.first);
      if (got_one == 'b1) begin
        //$display ($sformatf("GOT  cov_isa=%0s [%d]", cov_isa.name, cov_isa));
      end else begin
        fatal($sformatf("riscv_instr_gen_config cfg cant find enum for specifed cov_isa=%0s",
                        cov_isa_str));
      end
    end
    // TODO if we want to selectively enable/disable coverage based on categories...
    // e.g. +cov_category=OPV_CONFIG
    if ($test$plusargs("cov_category=")) begin
      string cov_category_str;
      void'($value$plusargs("cov_category=%0s", cov_category_str));
      $display("coverage option: +cov_category=%0s", cov_category_str);
      // used to further subset coverage (used by vectors)
    end

    // show coverage defines
    // they will be set on command line and used before here...
    `ifdef COVERAGE_WITH_NO_HAZARDS
      $display("coverage option: +define+COVERAGE_WITH_NO_HAZARDS");
    `endif
    `ifdef COVERAGE_WITH_NO_IGNORES
      $display("coverage option: +define+COVERAGE_WITH_NO_IGNORES");
    `endif
    if ($test$plusargs("stop_on_first_error")) begin
      $display("coverage option: +stop_on_first_error");
    end

   `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_instantiation.sv")

    // RV32I instruction functional coverage instantiation
    `CG_SELECTOR_BEGIN(RV32I)
        add_cg = new();
        sub_cg = new();
        addi_cg = new();
        lui_cg = new();
        auipc_cg = new();
        sll_cg = new();
        srl_cg = new();
        sra_cg = new();
        slli_cg = new();
        srli_cg = new();
        srai_cg = new();
        and_cg = new();
        or_cg = new();
        xor_cg = new();
        andi_cg = new();
        ori_cg = new();
        xori_cg = new();
        slt_cg = new();
        sltu_cg = new();
        slti_cg = new();
        sltiu_cg = new();
        jal_cg = new();
        jalr_cg = new();
        beq_cg = new();
        bne_cg = new();
        blt_cg = new();
        bge_cg = new();
        bgeu_cg = new();
        bltu_cg = new();
        lb_cg = new();
        lh_cg = new();
        lw_cg = new();
        lbu_cg = new();
        lhu_cg = new();
        sb_cg = new();
        sh_cg = new();
        sw_cg = new();
    `CG_SELECTOR_END

    // TODO sort when there is a RV32ZICSR isa enum
    if (RV32I inside {supported_isa}) begin
        if (default_cov) begin
            csrrw_cg = new();
            csrrs_cg = new();
            csrrc_cg = new();
            csrrwi_cg = new();
            csrrsi_cg = new();
            csrrci_cg = new();
        end
    end

    if (default_cov) begin
        // instr_trans_cg = new();
        branch_hit_history_cg = new();
        rv32i_misc_cg = new();
        opcode_cg = new();
    end

    if (RV32C inside {supported_isa} || RV64C inside {supported_isa}) begin
        if (default_cov) begin
            compressed_opcode_cg = new();
            hint_cg = new();
            if (!cfg.disable_compressed_instr) begin
              illegal_compressed_instr_cg = new();
            end
        end
    end

    `CG_SELECTOR_BEGIN(RV32M)
      mul_cg = new();
      mulh_cg = new();
      mulhsu_cg = new();
      mulhu_cg = new();
      div_cg = new();
      divu_cg = new();
      rem_cg = new();
      remu_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV64M)
      mulw_cg = new();
      divw_cg = new();
      divuw_cg = new();
      remw_cg = new();
      remuw_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV64I)
      lwu_cg = new();
      ld_cg = new();
      sd_cg = new();
      slli64_cg = new();
      srli64_cg = new();
      srai64_cg = new();
      sllw_cg = new();
      slliw_cg = new();
      srlw_cg = new();
      srliw_cg = new();
      sraw_cg = new();
      sraiw_cg = new();
      addw_cg = new();
      addiw_cg = new();
      subw_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV32C)
      c_lw_cg = new();
      c_sw_cg = new();
      c_lwsp_cg = new();
      c_swsp_cg = new();
      c_addi4spn_cg = new();
      c_addi_cg = new();
      c_addi16sp_cg = new();
      c_li_cg = new();
      c_lui_cg = new();
      c_sub_cg = new();
      c_add_cg = new();
      c_mv_cg = new();
      c_andi_cg = new();
      c_xor_cg = new();
      c_or_cg = new();
      c_and_cg = new();
      c_beqz_cg = new();
      c_bnez_cg = new();
      c_srli_cg = new();
      c_srai_cg = new();
      c_slli_cg = new();
      c_j_cg = new();
      if (XLEN == 32) begin
        c_jal_cg = new();
      end
      c_jr_cg = new();
      c_jalr_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV64C)
      c_ld_cg = new();
      c_sd_cg = new();
      c_ldsp_cg = new();
      c_sdsp_cg = new();
      c_addiw_cg = new();
      c_subw_cg = new();
      c_addw_cg = new();
    `CG_SELECTOR_END

    if (default_cov) begin
        privileged_csr_cg = new();
        mcause_exception_cg = new();
        mcause_interrupt_cg = new();
        if (!cfg.disable_compressed_instr) begin
          mepc_alignment_cg = new();
        end
        mstatus_m_cg = new();
    end
  endfunction

  function void sample(riscv_instr_cov_item instr);
    instr_cnt += 1;
    if (instr_cnt > 1) begin
      instr.check_hazard_condition(pre_instr);
    end
    if ((instr.binary[1:0] != 2'b11) && (RV32C inside {supported_isa})) begin
        if (default_cov) begin
            hint_cg.sample(instr);
            compressed_opcode_cg.sample(instr.binary[15:0]);
        end
    end
    if (instr.binary[1:0] == 2'b11) begin
        if (default_cov) begin
            opcode_cg.sample(instr.binary[6:2]);
        end
    end
    case (instr.instr_name)
      ADD        : add_cg.sample(instr);
      SUB        : sub_cg.sample(instr);
      ADDI       : addi_cg.sample(instr);
      LUI        : lui_cg.sample(instr);
      AUIPC      : auipc_cg.sample(instr);
      SLL        : sll_cg.sample(instr);
      SRL        : srl_cg.sample(instr);
      SRA        : sra_cg.sample(instr);
      SLLI       : begin
                     slli_cg.sample(instr);
                     if (RV64I inside {supported_isa}) begin
                       slli64_cg.sample(instr);
                     end
                   end
      SRLI       : begin
                     srli_cg.sample(instr);
                     if (RV64I inside {supported_isa}) begin
                       srli64_cg.sample(instr);
                     end
                   end
      SRAI       : begin
                     srai_cg.sample(instr);
                     if (RV64I inside {supported_isa}) begin
                       srai64_cg.sample(instr);
                     end
                   end
      AND        : and_cg.sample(instr);
      OR         : or_cg.sample(instr);
      XOR        : xor_cg.sample(instr);
      ANDI       : andi_cg.sample(instr);
      ORI        : ori_cg.sample(instr);
      XORI       : xori_cg.sample(instr);
      SLT        : slt_cg.sample(instr);
      SLTU       : sltu_cg.sample(instr);
      SLTI       : slti_cg.sample(instr);
      SLTIU      : sltiu_cg.sample(instr);
      JAL        : jal_cg.sample(instr);
      JALR       : jalr_cg.sample(instr);
      BEQ        : beq_cg.sample(instr);
      BNE        : bne_cg.sample(instr);
      BLT        : blt_cg.sample(instr);
      BGE        : bge_cg.sample(instr);
      BLTU       : bltu_cg.sample(instr);
      BGEU       : bgeu_cg.sample(instr);
      LW         : lw_cg.sample(instr);
      LH         : lh_cg.sample(instr);
      LB         : lb_cg.sample(instr);
      LBU        : lbu_cg.sample(instr);
      LHU        : lhu_cg.sample(instr);
      SW         : sw_cg.sample(instr);
      SH         : sh_cg.sample(instr);
      SB         : sb_cg.sample(instr);
      CSRRW      : csrrw_cg.sample(instr);
      CSRRS      : csrrs_cg.sample(instr);
      CSRRC      : csrrc_cg.sample(instr);
      CSRRWI     : csrrwi_cg.sample(instr);
      CSRRSI     : csrrsi_cg.sample(instr);
      CSRRCI     : csrrci_cg.sample(instr);
      MUL        : mul_cg.sample(instr);
      MULH       : mulh_cg.sample(instr);
      MULHSU     : mulhsu_cg.sample(instr);
      MULHU      : mulhu_cg.sample(instr);
      DIV        : div_cg.sample(instr);
      DIVU       : divu_cg.sample(instr);
      REM        : rem_cg.sample(instr);
      REMU       : remu_cg.sample(instr);
      MULW       : mulw_cg.sample(instr);
      DIVW       : divw_cg.sample(instr);
      DIVUW      : divuw_cg.sample(instr);
      REMW       : remw_cg.sample(instr);
      REMUW      : remuw_cg.sample(instr);
      LWU        : lwu_cg.sample(instr);
      LD         : ld_cg.sample(instr);
      SD         : sd_cg.sample(instr);
      SLLW       : sllw_cg.sample(instr);
      SLLIW      : slliw_cg.sample(instr);
      SRLW       : srlw_cg.sample(instr);
      SRLIW      : srliw_cg.sample(instr);
      SRAW       : sraw_cg.sample(instr);
      SRAIW      : sraiw_cg.sample(instr);
      ADDW       : addw_cg.sample(instr);
      ADDIW      : addiw_cg.sample(instr);
      SUBW       : subw_cg.sample(instr);
      C_LW       : c_lw_cg.sample(instr);
      C_SW       : c_sw_cg.sample(instr);
      C_LWSP     : c_lwsp_cg.sample(instr);
      C_SWSP     : c_swsp_cg.sample(instr);
      C_ADDI4SPN : c_addi4spn_cg.sample(instr);
      C_ADDI     : c_addi_cg.sample(instr);
      C_ADDI16SP : c_addi16sp_cg.sample(instr);
      C_LI       : c_li_cg.sample(instr);
      C_LUI      : c_lui_cg.sample(instr);
      C_SUB      : c_sub_cg.sample(instr);
      C_ADD      : c_add_cg.sample(instr);
      C_MV       : c_mv_cg.sample(instr);
      C_ANDI     : c_andi_cg.sample(instr);
      C_XOR      : c_xor_cg.sample(instr);
      C_OR       : c_or_cg.sample(instr);
      C_AND      : c_and_cg.sample(instr);
      C_BEQZ     : c_beqz_cg.sample(instr);
      C_BNEZ     : c_bnez_cg.sample(instr);
      C_SRLI     : c_srli_cg.sample(instr);
      C_SRAI     : c_srai_cg.sample(instr);
      C_SLLI     : c_slli_cg.sample(instr);
      C_J        : c_j_cg.sample(instr);
      C_JAL      : if (XLEN == 32) c_jal_cg.sample(instr);
      C_JR       : c_jr_cg.sample(instr);
      C_JALR     : c_jalr_cg.sample(instr);
      C_LD       : c_ld_cg.sample(instr);
      C_SD       : c_sd_cg.sample(instr);
      C_LDSP     : c_ldsp_cg.sample(instr);
      C_SDSP     : c_sdsp_cg.sample(instr);
      C_SUBW     : c_subw_cg.sample(instr);
      C_ADDW     : c_addw_cg.sample(instr);
      C_ADDIW    : c_addiw_cg.sample(instr);
      `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv")
      default: begin
        if (RV32C inside {supported_isa}) begin
          if (default_cov) begin
            illegal_compressed_instr_cg.sample(instr.binary);
          end
        end
        if (instr.group == RV32I) begin
          if (default_cov) begin
            rv32i_misc_cg.sample(instr);
          end
        end
      end
    endcase
    if (instr.category == BRANCH) begin
      branch_hit_history = (branch_hit_history << 1) | instr.branch_hit;
      branch_instr_cnt += 1;
      if (branch_instr_cnt >= $bits(branch_hit_history)) begin
          if (default_cov) begin
            branch_hit_history_cg.sample();
          end
      end
    end
    if (instr.category == CSR) begin
          if (default_cov) begin
            privileged_csr_cg.sample(instr.csr);
          end
      case (instr.csr)
        MCAUSE: begin
          if (instr.rd_value[XLEN-1]) begin
            interrupt_cause_t interrupt;
            if ($cast(interrupt, instr.rd_value[3:0])) begin
                if (default_cov) begin
                    mcause_interrupt_cg.sample(interrupt);
                end
            end
          end else begin
            exception_cause_t exception;
            if ($cast(exception, instr.rd_value[3:0])) begin
                if (default_cov) begin
                    mcause_exception_cg.sample(exception);
                end
            end
          end
        end
        MEPC: begin
          if (RV32C inside {supported_isa}) begin
            if (default_cov) begin
              mepc_alignment_cg.sample(instr.rd_value);
            end
          end
        end
        MSTATUS: begin
            if (default_cov) begin
                mstatus_m_cg.sample(instr.rd_value);
            end
        end
      endcase
    end
    if (instr_cnt > 1) begin
        if (default_cov) begin
            //instr_trans_cg.sample();
        end
    end
   `VECTOR_INCLUDE("riscv_instr_cover_group_inc_sample.sv")
    pre_instr.copy(instr);
    pre_instr.mem_addr = instr.mem_addr;
  endfunction

  // Check if the instruction is supported
  virtual function bit is_supported_instr(riscv_instr_name_t name);
    if (name inside {instr_list}) begin
      return 1'b1;
    end else begin
      return 1'b0;
    end
  endfunction

  // Check if the instruction is supported
  virtual function bit is_compressed_gpr(riscv_reg_t gpr);
    if (gpr inside {[S0:A5]}) begin
      return 1'b1;
    end else begin
      return 1'b0;
    end
  endfunction

  // Build the supported instruction list based on the core setting
  virtual function void build_instr_list();
    riscv_instr_name_t instr_name;
    instr_name = instr_name.first;
    do begin
      `INSTR instr;
      if (!(instr_name inside {unsupported_instr}) && (instr_name != INVALID_INSTR)) begin
        `ifdef DEPRECATED
          instr = riscv_instr_base::type_id::create("instr");
          if (!instr.randomize() with {instr_name == local::instr_name;}) begin
            `uvm_fatal("riscv_instr_cover_group",
                     $sformatf("Instruction %0s randomization failure", instr_name.name()))
          end
        `else
          instr = riscv_instr::create_instr(instr_name);
        `endif
        if ((instr.group inside {supported_isa}) &&<commit_msg>Add compliance mode and RTL mode to the coverage model (#354)<commit_after>/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

`ifdef COVERAGE_WITH_NO_HAZARDS
    `define CG_HAZARD_COV(CG_HAZARD_CODE) \
        // CG_HAZARD_CODE
`else
     `define CG_HAZARD_COV(CG_HAZARD_CODE) \
        CG_HAZARD_CODE
`endif

`ifdef COVERAGE_WITH_NO_IGNORES
    `define CG_IGNORE_COV(CG_IGNORE_CODE) \
        // CG_IGNORE_CODE
`else
    `define CG_IGNORE_COV(CG_IGNORE_CODE) \
        CG_IGNORE_CODE
`endif

`define INSTR_CG_BEGIN(INSTR_NAME) \
  covergroup ``INSTR_NAME``_cg with function sample(riscv_instr_cov_item instr);

`define R_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rs2         : coverpoint instr.rs2; \
    cp_rd          : coverpoint instr.rd;  \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_rs2_sign    : coverpoint instr.rs2_sign; \
    cp_rd_sign     : coverpoint instr.rd_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define CMP_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rd          : coverpoint instr.rd;  \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_result      : coverpoint instr.rd_value[0]; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define SB_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rs2         : coverpoint instr.rs2; \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_rs2_sign    : coverpoint instr.rs2_sign; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    cp_branch_hit  : coverpoint instr.branch_hit; \
    cp_sign_cross  : cross cp_rs1_sign, cp_rs2_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define STORE_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1 { \
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};) \
    } \
    cp_rs2         : coverpoint instr.rs2; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        } \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define LOAD_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1 { \
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};) \
    } \
    cp_rd          : coverpoint instr.rd; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard; \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define I_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1         : coverpoint instr.rs1; \
    cp_rd          : coverpoint instr.rd; \
    cp_rs1_sign    : coverpoint instr.rs1_sign; \
    cp_rd_sign     : coverpoint instr.rd_sign; \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define U_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd          : coverpoint instr.rd; \
    cp_rd_sign     : coverpoint instr.rd_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \


`define J_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_imm_sign    : coverpoint instr.imm_sign; \
    cp_rd          : coverpoint instr.rd; \
    cp_rd_align    : coverpoint instr.rd_value[1];


`define CSR_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd          : coverpoint instr.rd; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define CR_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs2         : coverpoint instr.rs2; \
    cp_rd          : coverpoint instr.rd; \
    cp_rs2_sign    : coverpoint instr.rs2_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \

`define CI_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd       : coverpoint instr.rd; \
    cp_imm_sign : coverpoint instr.imm_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define CSS_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs2      : coverpoint instr.rs2; \
    cp_imm_sign : coverpoint instr.imm_sign; \
    cp_rs2_sign : coverpoint instr.rs2_sign; \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define CIW_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_imm_sign : coverpoint instr.imm_sign; \
    cp_rd       : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define CL_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1      : coverpoint instr.rs1 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    cp_rd       : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard; \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define CL_SP_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd       : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    }

`define CS_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1      : coverpoint instr.rs1 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    cp_rs2      : coverpoint instr.rs2 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        } \
        cp_lsu_hazard  : coverpoint instr.lsu_hazard { \
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
        }) \

`define CS_SP_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs2      : coverpoint instr.rs2 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    }

`define CA_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rd      : coverpoint instr.rd { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    cp_rs2      : coverpoint instr.rs2 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;) \


`define CB_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_rs1      : coverpoint instr.rs1 { \
      bins gpr[] = {S0, S1, A0, A1, A2, A3, A4, A5}; \
    } \
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard { \
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
        }) \

`define CJ_INSTR_CG_BEGIN(INSTR_NAME) \
  `INSTR_CG_BEGIN(INSTR_NAME) \
    cp_imm_sign : coverpoint instr.imm_sign;

`define CG_END endgroup

`define CG_SELECTOR_BEGIN(CG_ISA) \
    if ((CG_ISA inside {supported_isa}) && (!compliance_mode || (cov_isa == CG_ISA))) begin

`define CG_SELECTOR_END \
    end

class riscv_instr_cover_group;

  riscv_instr_gen_config  cfg;
  riscv_instr_cov_item    cur_instr;
  riscv_instr_cov_item    pre_instr;
  riscv_instr_name_t      instr_list[$];
  int unsigned            instr_cnt;
  int unsigned            branch_instr_cnt;
  bit [4:0]               branch_hit_history; // The last 5 branch result

  // Mode of the coverage model

  // In complicance mode, all the micro-architecture related covergroups are removed. Only the ones
  // related to RISC-V specification compliance is sampled.
  bit                     compliance_mode;

  // By default the coverage model run with instruction trace from ISS simulation. When simulating
  // with ISS, certain covergroups like debug/interrupt could not be hit as these are not simulated
  // with ISS. You can turn off this mode by adding +iss_mode=0 if you use the instruction trace
  // from RTL simulation.
  bit                     iss_mode = 1'b1;

  `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cpu_declare.sv")

  ///////////// RV32I instruction functional coverage //////////////

  // Arithmetic instructions
  `R_INSTR_CG_BEGIN(add)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(sub)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(addi)
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign, cp_rd_sign;
  `CG_END

  `U_INSTR_CG_BEGIN(lui)
  `CG_END

  `U_INSTR_CG_BEGIN(auipc)
  `CG_END

  // Shift instructions
  `R_INSTR_CG_BEGIN(sra)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(sll)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(srl)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `INSTR_CG_BEGIN(srai)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(slli)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(srli)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  // Logical instructions
  `R_INSTR_CG_BEGIN(xor)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(or)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(and)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(xori)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(ori)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(andi)
    cp_logical   : coverpoint instr.logical_similarity;
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  // Compare instructions
  `CMP_INSTR_CG_BEGIN(slt)
    cp_rs2        : coverpoint instr.rs2;
    cp_rs2_sign   : coverpoint instr.rs2_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `CMP_INSTR_CG_BEGIN(sltu)
    cp_rs2        : coverpoint instr.rs2;
    cp_rs2_sign   : coverpoint instr.rs2_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `CMP_INSTR_CG_BEGIN(slti)
    cp_imm_sign   : coverpoint instr.imm_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  `CMP_INSTR_CG_BEGIN(sltiu)
    cp_imm_sign   : coverpoint instr.imm_sign;
    cp_sign_cross : cross cp_rs1_sign, cp_imm_sign;
  `CG_END

  // Branch instruction
  `SB_INSTR_CG_BEGIN(beq)
  `CG_END

  `SB_INSTR_CG_BEGIN(bne)
  `CG_END

  `SB_INSTR_CG_BEGIN(blt)
  `CG_END

  `SB_INSTR_CG_BEGIN(bge)
  `CG_END

  `SB_INSTR_CG_BEGIN(bltu)
  `CG_END

  `SB_INSTR_CG_BEGIN(bgeu)
  `CG_END

  // Load instructions
  `LOAD_INSTR_CG_BEGIN(lb)
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lh)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lw)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lbu)
  `CG_END

  `LOAD_INSTR_CG_BEGIN(lhu)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  // Store instruction
  `STORE_INSTR_CG_BEGIN(sb)
  `CG_END

  `STORE_INSTR_CG_BEGIN(sh)
    cp_misalign: coverpoint instr.unaligned_mem_access;
  `CG_END

  `STORE_INSTR_CG_BEGIN(sw)
    cp_misalign: coverpoint instr.unaligned_mem_access;
  `CG_END

  // JUMP instruction
  `J_INSTR_CG_BEGIN(jal)
  `CG_END

  `J_INSTR_CG_BEGIN(jalr)
    cp_rs1_link : coverpoint instr.rs1 {
      bins ra = {RA};
      bins t1 = {T1};
      bins non_link = default;
    }
    cp_rd_link : coverpoint instr.rd {
      bins ra = {RA};
      bins t1 = {T1};
      bins non_link = default;
    }
    cp_ras : cross cp_rs1_link, cp_rd_link;
  `CG_END

  // CSR instructions
  `CSR_INSTR_CG_BEGIN(csrrw)
    cp_rs1 : coverpoint instr.rs1;
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrs)
    cp_rs1 : coverpoint instr.rs1;
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrc)
    cp_rs1 : coverpoint instr.rs1;
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrwi)
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrsi)
  `CG_END

  `CSR_INSTR_CG_BEGIN(csrrci)
  `CG_END

  covergroup rv32i_misc_cg with function sample(riscv_instr_cov_item instr);
    cp_misc : coverpoint instr.instr_name {
      bins instr[] = {FENCE, FENCE_I, EBREAK, ECALL, MRET, WFI};
    }
  endgroup

  // RV32M
  `R_INSTR_CG_BEGIN(mul)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(mulh)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(mulhsu)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(mulhu)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(div)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(divu)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(rem)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(remu)
    cp_div_result: coverpoint instr.div_result;
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  // RV64M
  // Below instructions only do calculation based on lower 32 bits, and extend the result to 64
  // bits. Add special covergroup for corner cases

  `R_INSTR_CG_BEGIN(mulw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(divw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(divuw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(remw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(remuw)
    cp_div_result: coverpoint instr.div_result;
    cp_div_zero  : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) {
      bins zero     = {0};
      bins non_zero = default;
    }
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  // RV64I
  `LOAD_INSTR_CG_BEGIN(lwu)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `LOAD_INSTR_CG_BEGIN(ld)
    cp_align: coverpoint instr.unaligned_mem_access;
  `CG_END

  `STORE_INSTR_CG_BEGIN(sd)
    cp_misalign: coverpoint instr.unaligned_mem_access;
  `CG_END

  `R_INSTR_CG_BEGIN(sraw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(sllw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(srlw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign;
  `CG_END

  // imm[5] could be 1 for RV64I SLLI/SRAI/SRLI
  `INSTR_CG_BEGIN(srai64)
    cp_imm: coverpoint instr.imm[5];
  `CG_END

  `INSTR_CG_BEGIN(slli64)
    cp_imm: coverpoint instr.imm[5];
  `CG_END

  `INSTR_CG_BEGIN(srli64)
    cp_imm: coverpoint instr.imm[5];
  `CG_END

  `INSTR_CG_BEGIN(sraiw)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(slliw)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `INSTR_CG_BEGIN(srliw)
    cp_rs1         : coverpoint instr.rs1;
    cp_rd          : coverpoint instr.rd;
    cp_rs1_sign    : coverpoint instr.rs1_sign;
    cp_rd_sign     : coverpoint instr.rd_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard;)
  `CG_END

  `R_INSTR_CG_BEGIN(addw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `R_INSTR_CG_BEGIN(subw)
    cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign, cp_rd_sign;
  `CG_END

  `I_INSTR_CG_BEGIN(addiw)
    cp_sign_cross: cross cp_rs1_sign, cp_imm_sign, cp_rd_sign;
  `CG_END

  // RV32C

  `CL_INSTR_CG_BEGIN(c_lw)
  `CG_END

  `CL_SP_INSTR_CG_BEGIN(c_lwsp)
  `CG_END

  `CS_INSTR_CG_BEGIN(c_sw)
  `CG_END

  `CS_SP_INSTR_CG_BEGIN(c_swsp)
  `CG_END

  `CIW_INSTR_CG_BEGIN(c_addi4spn)
  `CG_END

  `CI_INSTR_CG_BEGIN(c_addi)
  `CG_END

  `INSTR_CG_BEGIN(c_addi16sp)
    cp_imm_sign : coverpoint instr.imm_sign;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard {
            bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD};
        })
  `CG_END

  `CI_INSTR_CG_BEGIN(c_li)
  `CG_END

  `INSTR_CG_BEGIN(c_lui)
    cp_rd : coverpoint instr.rd {
        `CG_IGNORE_COV(ignore_bins bin = {ZERO, SP};)
    }
  `CG_END

  `CA_INSTR_CG_BEGIN(c_sub)
  `CG_END

  `CR_INSTR_CG_BEGIN(c_add)
  `CG_END

  `CR_INSTR_CG_BEGIN(c_mv)
  `CG_END

  `CB_INSTR_CG_BEGIN(c_andi)
    cp_imm_sign : coverpoint instr.imm_sign;
  `CG_END

  `CA_INSTR_CG_BEGIN(c_xor)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_or)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_and)
  `CG_END

  `CB_INSTR_CG_BEGIN(c_beqz)
    cp_imm_sign : coverpoint instr.imm_sign;
  `CG_END

  `CB_INSTR_CG_BEGIN(c_bnez)
    cp_imm_sign : coverpoint instr.imm_sign;
  `CG_END

  `CB_INSTR_CG_BEGIN(c_srli)
  `CG_END

  `CB_INSTR_CG_BEGIN(c_srai)
  `CG_END

  `INSTR_CG_BEGIN(c_slli)
    cp_rd          : coverpoint instr.rd;
    `CG_HAZARD_COV(cp_gpr_hazard  : coverpoint instr.gpr_hazard {
            bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
        })
  `CG_END

  `CJ_INSTR_CG_BEGIN(c_j)
  `CG_END

  `CJ_INSTR_CG_BEGIN(c_jal)
  `CG_END

  `INSTR_CG_BEGIN(c_jr)
    cp_rs1      : coverpoint instr.rs1 {
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};)
    }
  `CG_END

  `INSTR_CG_BEGIN(c_jalr)
    cp_rs1      : coverpoint instr.rs1 {
        `CG_IGNORE_COV(ignore_bins zero = {ZERO};)
    }
    cp_rd_align : coverpoint instr.rd_value[1];
  `CG_END

  // RV64C

  `CL_INSTR_CG_BEGIN(c_ld)
  `CG_END

  `CL_SP_INSTR_CG_BEGIN(c_ldsp)
  `CG_END

  `CS_INSTR_CG_BEGIN(c_sd)
  `CG_END

  `CS_SP_INSTR_CG_BEGIN(c_sdsp)
  `CG_END

  `CI_INSTR_CG_BEGIN(c_addiw)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_subw)
  `CG_END

  `CA_INSTR_CG_BEGIN(c_addw)
  `CG_END

  `INSTR_CG_BEGIN(hint)
    cp_hint : coverpoint instr.binary[15:0] {
      wildcard bins addi    = {16'b0000_1xxx_x000_0001,
                               16'b0000_x1xx_x000_0001,
                               16'b0000_xx1x_x000_0001,
                               16'b0000_xxx1_x000_0001,
                               16'b0000_xxxx_1000_0001};
      wildcard bins li      = {16'b010x_0000_0xxx_xx01};
      wildcard bins lui     = {16'b011x_0000_0xxx_xx01};
      wildcard bins srli64  = {16'b1000_00xx_x000_0001};
      wildcard bins srai64  = {16'b1000_01xx_x000_0001};
      wildcard bins slli    = {16'b000x_0000_0xxx_xx10};
      wildcard bins slli64  = {16'b0000_xxxx_x000_0010};
      wildcard bins mv      = {16'b1000_0000_01xx_xx10,
                               16'b1000_0000_0x1x_xx10,
                               16'b1000_0000_0xx1_xx10,
                               16'b1000_0000_0xxx_1x10,
                               16'b1000_0000_0xxx_x110};
      wildcard bins add     = {16'b1001_0000_01xx_xx10,
                               16'b1001_0000_0x1x_xx10,
                               16'b1001_0000_0xx1_xx10,
                               16'b1001_0000_0xxx_1x10,
                               16'b1001_0000_0xxx_x110};
    }
  `CG_END

  // Cover all illegal instruction
  covergroup illegal_compressed_instr_cg with function sample(bit [31:0] binary);
    cp_point : coverpoint binary {
      wildcard bins c_addi4spn = {32'bxxxx_xxxxx_0000_0000_000x_xx00};
      wildcard bins c_addi16sp = {32'bxxxx_xxxxx_0110_0001_0000_0001};
      wildcard bins c_lui      = {32'bxxxx_xxxxx_0110_xxxx_1000_0001,
                                  32'bxxxx_xxxxx_0110_xx1x_x000_0001,
                                  32'bxxxx_xxxxx_0110_x1xx_x000_0001,
                                  32'bxxxx_xxxxx_0110_1xxx_x000_0001};
      wildcard bins c_jr       = {32'bxxxx_xxxxx_1000_0000_0000_0001};
    }
  endgroup

  // Cover all non-compressed opcode
  covergroup opcode_cg with function sample(bit [4:0] opcode);
    cp_opcode: coverpoint opcode;
  endgroup

  // Cover all compressed instruction opcode
  covergroup compressed_opcode_cg with function sample(bit [15:0] binary);
    cp_00 : coverpoint binary[15:13] iff (binary[1:0] == 2'b00);
    cp_01 : coverpoint binary[15:13] iff (binary[1:0] == 2'b01);
    cp_10 : coverpoint binary[15:13] iff (binary[1:0] == 2'b10);
  endgroup

  // Branch hit history
  covergroup branch_hit_history_cg;
    cp_branch_history: coverpoint branch_hit_history;
  endgroup

  // Instruction transition for all supported instructions
  /* TODO: Refine the transition functional coverage, not all combinations are interesting
  covergroup instr_trans_cg with function sample();
    cp_instr: coverpoint instr_name {
      bins instr[] = cp_instr with (is_supported_instr(riscv_instr_name_t'(item)));
    }
    cp_pre_instr: coverpoint pre_instr_name {
      // This is a helper coverpoint for cross coverpoint below, it should not be counted when
      // calculate the coverage score
      type_option.weight = 0;
      bins instr[] = cp_pre_instr with (is_supported_instr(riscv_instr_name_t'(item)));
    }
    cp_trans: cross cp_pre_instr, cp_instr {
      // Cover all instruction transitions, except for below system instructions
      ignore_bins ignore = binsof(cp_instr) intersect {ECALL, URET, SRET, SRET, DRET} ||
                           binsof(cp_pre_instr) intersect {ECALL, URET, SRET, SRET, DRET};
    }
  endgroup
  */

  covergroup privileged_csr_cg with function sample(bit [11:0] csr);
    cp_csr : coverpoint csr {
      bins pcsr[] = cp_csr with (item inside {implemented_csr});
    }
  endgroup

  // Privileged CSR covergroup
  covergroup mcause_exception_cg with function sample(exception_cause_t exception);
    cp_exception: coverpoint exception {
       bins exception[] = cp_exception with (item inside {implemented_exception});
    }
  endgroup

  covergroup mcause_interrupt_cg with function sample(interrupt_cause_t interrupt);
    cp_interrupt: coverpoint interrupt {
       bins interrupt[] = cp_interrupt with (item inside {implemented_interrupt});
    }
  endgroup

  covergroup mepc_alignment_cg with function sample(bit [XLEN-1:0] val);
    cp_align: coverpoint val[1:0] {
      bins alignment[] = {2'b00, 2'b10};
    }
  endgroup

  covergroup mstatus_m_cg with function sample(bit [XLEN-1:0] val);
    cp_mie  : coverpoint val[3];
    cp_mpie : coverpoint val[7];
    cp_mpp  : coverpoint val[12:11];
  endgroup

  `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_add.sv")

  function new(riscv_instr_gen_config cfg);
    riscv_instr_group_t cov_isa;
    this.cfg = cfg;
    cur_instr = riscv_instr_cov_item::type_id::create("cur_instr");
    pre_instr = riscv_instr_cov_item::type_id::create("pre_instr");
    build_instr_list();

    // process coverage options
    void'($value$plusargs("compliance_mode=%0d", compliance_mode));
    void'($value$plusargs("iss_mode=%0d", iss_mode));

    if ($test$plusargs("cov_isa=")) begin
      string cov_isa_str;
      riscv_instr_group_t isa;
      bit got_one = 'b0;
      void'($value$plusargs("cov_isa=%0s", cov_isa_str));
      cov_isa_str = cov_isa_str.toupper();
      `uvm_info("riscv_instr_covergroup",
                $sformatf("coverage option: +cov_isa=%0s", cov_isa_str), UVM_LOW)
      isa = isa.first;
      do begin
        if (isa.name == cov_isa_str) begin
          cov_isa = isa;
          got_one = 'b1;
          break;
        end
        isa =  isa.next;
      end while (isa != isa.first);
      if (!got_one) begin
        `uvm_fatal("riscv_instr_covergroup",
                   $sformatf("Cannot find enum for specifed cov_isa=%0s", cov_isa_str))
      end
    end
    // TODO if we want to selectively enable/disable coverage based on categories...
    // e.g. +cov_category=OPV_CONFIG
    if ($test$plusargs("cov_category=")) begin
      string cov_category_str;
      void'($value$plusargs("cov_category=%0s", cov_category_str));
      $display("coverage option: +cov_category=%0s", cov_category_str);
      // used to further subset coverage (used by vectors)
    end

    // show coverage defines
    // they will be set on command line and used before here...
    `ifdef COVERAGE_WITH_NO_HAZARDS
      $display("coverage option: +define+COVERAGE_WITH_NO_HAZARDS");
    `endif
    `ifdef COVERAGE_WITH_NO_IGNORES
      $display("coverage option: +define+COVERAGE_WITH_NO_IGNORES");
    `endif
    if ($test$plusargs("stop_on_first_error")) begin
      $display("coverage option: +stop_on_first_error");
    end

   `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_instantiation.sv")

    // RV32I instruction functional coverage instantiation
    `CG_SELECTOR_BEGIN(RV32I)
        add_cg = new();
        sub_cg = new();
        addi_cg = new();
        lui_cg = new();
        auipc_cg = new();
        sll_cg = new();
        srl_cg = new();
        sra_cg = new();
        slli_cg = new();
        srli_cg = new();
        srai_cg = new();
        and_cg = new();
        or_cg = new();
        xor_cg = new();
        andi_cg = new();
        ori_cg = new();
        xori_cg = new();
        slt_cg = new();
        sltu_cg = new();
        slti_cg = new();
        sltiu_cg = new();
        jal_cg = new();
        jalr_cg = new();
        beq_cg = new();
        bne_cg = new();
        blt_cg = new();
        bge_cg = new();
        bgeu_cg = new();
        bltu_cg = new();
        lb_cg = new();
        lh_cg = new();
        lw_cg = new();
        lbu_cg = new();
        lhu_cg = new();
        sb_cg = new();
        sh_cg = new();
        sw_cg = new();
    `CG_SELECTOR_END

    // TODO sort when there is a RV32ZICSR isa enum
    if (RV32I inside {supported_isa}) begin
      if (!compliance_mode) begin
        csrrw_cg = new();
        csrrs_cg = new();
        csrrc_cg = new();
        csrrwi_cg = new();
        csrrsi_cg = new();
        csrrci_cg = new();
      end
    end

    if (!compliance_mode) begin
        // instr_trans_cg = new();
        branch_hit_history_cg = new();
        rv32i_misc_cg = new();
        opcode_cg = new();
    end

    if (RV32C inside {supported_isa} || RV64C inside {supported_isa}) begin
      if (!compliance_mode) begin
        compressed_opcode_cg = new();
        hint_cg = new();
        if (!cfg.disable_compressed_instr) begin
          illegal_compressed_instr_cg = new();
        end
      end
    end

    `CG_SELECTOR_BEGIN(RV32M)
      mul_cg = new();
      mulh_cg = new();
      mulhsu_cg = new();
      mulhu_cg = new();
      div_cg = new();
      divu_cg = new();
      rem_cg = new();
      remu_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV64M)
      mulw_cg = new();
      divw_cg = new();
      divuw_cg = new();
      remw_cg = new();
      remuw_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV64I)
      lwu_cg = new();
      ld_cg = new();
      sd_cg = new();
      slli64_cg = new();
      srli64_cg = new();
      srai64_cg = new();
      sllw_cg = new();
      slliw_cg = new();
      srlw_cg = new();
      srliw_cg = new();
      sraw_cg = new();
      sraiw_cg = new();
      addw_cg = new();
      addiw_cg = new();
      subw_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV32C)
      c_lw_cg = new();
      c_sw_cg = new();
      c_lwsp_cg = new();
      c_swsp_cg = new();
      c_addi4spn_cg = new();
      c_addi_cg = new();
      c_addi16sp_cg = new();
      c_li_cg = new();
      c_lui_cg = new();
      c_sub_cg = new();
      c_add_cg = new();
      c_mv_cg = new();
      c_andi_cg = new();
      c_xor_cg = new();
      c_or_cg = new();
      c_and_cg = new();
      c_beqz_cg = new();
      c_bnez_cg = new();
      c_srli_cg = new();
      c_srai_cg = new();
      c_slli_cg = new();
      c_j_cg = new();
      if (XLEN == 32) begin
        c_jal_cg = new();
      end
      c_jr_cg = new();
      c_jalr_cg = new();
    `CG_SELECTOR_END

    `CG_SELECTOR_BEGIN(RV64C)
      c_ld_cg = new();
      c_sd_cg = new();
      c_ldsp_cg = new();
      c_sdsp_cg = new();
      c_addiw_cg = new();
      c_subw_cg = new();
      c_addw_cg = new();
    `CG_SELECTOR_END

    if (!compliance_mode) begin
      privileged_csr_cg = new();
      mcause_exception_cg = new();
      if (!iss_mode) begin
        mcause_interrupt_cg = new();
      end
      if (!cfg.disable_compressed_instr) begin
        mepc_alignment_cg = new();
      end
      mstatus_m_cg = new();
    end
  endfunction

  function void sample(riscv_instr_cov_item instr);
    instr_cnt += 1;
    if (instr_cnt > 1) begin
      instr.check_hazard_condition(pre_instr);
    end
    if ((instr.binary[1:0] != 2'b11) && (RV32C inside {supported_isa})) begin
      if (!compliance_mode) begin
        hint_cg.sample(instr);
        compressed_opcode_cg.sample(instr.binary[15:0]);
      end
    end
    if (instr.binary[1:0] == 2'b11) begin
      if (!compliance_mode) begin
        opcode_cg.sample(instr.binary[6:2]);
      end
    end
    case (instr.instr_name)
      ADD        : add_cg.sample(instr);
      SUB        : sub_cg.sample(instr);
      ADDI       : addi_cg.sample(instr);
      LUI        : lui_cg.sample(instr);
      AUIPC      : auipc_cg.sample(instr);
      SLL        : sll_cg.sample(instr);
      SRL        : srl_cg.sample(instr);
      SRA        : sra_cg.sample(instr);
      SLLI       : begin
                     slli_cg.sample(instr);
                     if (RV64I inside {supported_isa}) begin
                       slli64_cg.sample(instr);
                     end
                   end
      SRLI       : begin
                     srli_cg.sample(instr);
                     if (RV64I inside {supported_isa}) begin
                       srli64_cg.sample(instr);
                     end
                   end
      SRAI       : begin
                     srai_cg.sample(instr);
                     if (RV64I inside {supported_isa}) begin
                       srai64_cg.sample(instr);
                     end
                   end
      AND        : and_cg.sample(instr);
      OR         : or_cg.sample(instr);
      XOR        : xor_cg.sample(instr);
      ANDI       : andi_cg.sample(instr);
      ORI        : ori_cg.sample(instr);
      XORI       : xori_cg.sample(instr);
      SLT        : slt_cg.sample(instr);
      SLTU       : sltu_cg.sample(instr);
      SLTI       : slti_cg.sample(instr);
      SLTIU      : sltiu_cg.sample(instr);
      JAL        : jal_cg.sample(instr);
      JALR       : jalr_cg.sample(instr);
      BEQ        : beq_cg.sample(instr);
      BNE        : bne_cg.sample(instr);
      BLT        : blt_cg.sample(instr);
      BGE        : bge_cg.sample(instr);
      BLTU       : bltu_cg.sample(instr);
      BGEU       : bgeu_cg.sample(instr);
      LW         : lw_cg.sample(instr);
      LH         : lh_cg.sample(instr);
      LB         : lb_cg.sample(instr);
      LBU        : lbu_cg.sample(instr);
      LHU        : lhu_cg.sample(instr);
      SW         : sw_cg.sample(instr);
      SH         : sh_cg.sample(instr);
      SB         : sb_cg.sample(instr);
      CSRRW      : csrrw_cg.sample(instr);
      CSRRS      : csrrs_cg.sample(instr);
      CSRRC      : csrrc_cg.sample(instr);
      CSRRWI     : csrrwi_cg.sample(instr);
      CSRRSI     : csrrsi_cg.sample(instr);
      CSRRCI     : csrrci_cg.sample(instr);
      MUL        : mul_cg.sample(instr);
      MULH       : mulh_cg.sample(instr);
      MULHSU     : mulhsu_cg.sample(instr);
      MULHU      : mulhu_cg.sample(instr);
      DIV        : div_cg.sample(instr);
      DIVU       : divu_cg.sample(instr);
      REM        : rem_cg.sample(instr);
      REMU       : remu_cg.sample(instr);
      MULW       : mulw_cg.sample(instr);
      DIVW       : divw_cg.sample(instr);
      DIVUW      : divuw_cg.sample(instr);
      REMW       : remw_cg.sample(instr);
      REMUW      : remuw_cg.sample(instr);
      LWU        : lwu_cg.sample(instr);
      LD         : ld_cg.sample(instr);
      SD         : sd_cg.sample(instr);
      SLLW       : sllw_cg.sample(instr);
      SLLIW      : slliw_cg.sample(instr);
      SRLW       : srlw_cg.sample(instr);
      SRLIW      : srliw_cg.sample(instr);
      SRAW       : sraw_cg.sample(instr);
      SRAIW      : sraiw_cg.sample(instr);
      ADDW       : addw_cg.sample(instr);
      ADDIW      : addiw_cg.sample(instr);
      SUBW       : subw_cg.sample(instr);
      C_LW       : c_lw_cg.sample(instr);
      C_SW       : c_sw_cg.sample(instr);
      C_LWSP     : c_lwsp_cg.sample(instr);
      C_SWSP     : c_swsp_cg.sample(instr);
      C_ADDI4SPN : c_addi4spn_cg.sample(instr);
      C_ADDI     : c_addi_cg.sample(instr);
      C_ADDI16SP : c_addi16sp_cg.sample(instr);
      C_LI       : c_li_cg.sample(instr);
      C_LUI      : c_lui_cg.sample(instr);
      C_SUB      : c_sub_cg.sample(instr);
      C_ADD      : c_add_cg.sample(instr);
      C_MV       : c_mv_cg.sample(instr);
      C_ANDI     : c_andi_cg.sample(instr);
      C_XOR      : c_xor_cg.sample(instr);
      C_OR       : c_or_cg.sample(instr);
      C_AND      : c_and_cg.sample(instr);
      C_BEQZ     : c_beqz_cg.sample(instr);
      C_BNEZ     : c_bnez_cg.sample(instr);
      C_SRLI     : c_srli_cg.sample(instr);
      C_SRAI     : c_srai_cg.sample(instr);
      C_SLLI     : c_slli_cg.sample(instr);
      C_J        : c_j_cg.sample(instr);
      C_JAL      : if (XLEN == 32) c_jal_cg.sample(instr);
      C_JR       : c_jr_cg.sample(instr);
      C_JALR     : c_jalr_cg.sample(instr);
      C_LD       : c_ld_cg.sample(instr);
      C_SD       : c_sd_cg.sample(instr);
      C_LDSP     : c_ldsp_cg.sample(instr);
      C_SDSP     : c_sdsp_cg.sample(instr);
      C_SUBW     : c_subw_cg.sample(instr);
      C_ADDW     : c_addw_cg.sample(instr);
      C_ADDIW    : c_addiw_cg.sample(instr);
      `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv")
      default: begin
        if (RV32C inside {supported_isa}) begin
          if (!compliance_mode) begin
            illegal_compressed_instr_cg.sample(instr.binary);
          end
        end
        if (instr.group == RV32I) begin
          if (!compliance_mode) begin
            rv32i_misc_cg.sample(instr);
          end
        end
      end
    endcase
    if (instr.category == BRANCH) begin
      branch_hit_history = (branch_hit_history << 1) | instr.branch_hit;
      branch_instr_cnt += 1;
      if (branch_instr_cnt >= $bits(branch_hit_history)) begin
        if (!compliance_mode) begin
          branch_hit_history_cg.sample();
        end
      end
    end
    if (instr.category == CSR) begin
      if (!compliance_mode) begin
        privileged_csr_cg.sample(instr.csr);
      end
      case (instr.csr)
        MCAUSE: begin
          if (instr.rd_value[XLEN-1]) begin
            interrupt_cause_t interrupt;
            if ($cast(interrupt, instr.rd_value[3:0])) begin
              if (!compliance_mode && !iss_mode) begin
                mcause_interrupt_cg.sample(interrupt);
              end
            end
          end else begin
            exception_cause_t exception;
            if ($cast(exception, instr.rd_value[3:0])) begin
              if (!compliance_mode) begin
                mcause_exception_cg.sample(exception);
              end
            end
          end
        end
        MEPC: begin
          if (RV32C inside {supported_isa}) begin
            if (!compliance_mode) begin
              mepc_alignment_cg.sample(instr.rd_value);
            end
          end
        end
        MSTATUS: begin
          if (!compliance_mode) begin
            mstatus_m_cg.sample(instr.rd_value);
          end
        end
      endcase
    end
    if (instr_cnt > 1) begin
      if (!compliance_mode) begin
        //instr_trans_cg.sample();
      end
    end
   `VECTOR_INCLUDE("riscv_instr_cover_group_inc_sample.sv")
    pre_instr.copy(instr);
    pre_instr.mem_addr = instr.mem_addr;
  endfunction

  // Check if the instruction is supported
  virtual function bit is_supported_instr(riscv_instr_name_t name);
    if (name inside {instr_list}) begin
      return 1'b1;
    end else begin
      return 1'b0;
    end
  endfunction

  // Check if the instruction is supported
  virtual function bit is_compressed_gpr(riscv_reg_t gpr);
    if (gpr inside {[S0:A5]}) begin
      return 1'b1;
    end else begin
      return 1'b0;
    end
  endfunction

  // Build the supported instruction list based on the core setting
  virtual function void build_instr_list();
    riscv_instr_name_t instr_name;
    instr_name = instr_name.first;
    do begin
      `INSTR instr;
      if (!(instr_name inside {unsupported_instr}) && (instr_name != INVALID_INSTR)) begin
        `ifdef DEPRECATED
          instr = riscv_instr_base::type_id::create("instr");
          if (!instr.randomize() with {instr_name == local::instr_name;}) begin
            `uvm_fatal("riscv_instr_cover_group",
                       $sformatf("Instruction %0s randomization failure", instr_name.name()))
          end
        `else
          instr = riscv_instr::create_instr(instr_name);
        `endif
        if ((instr.group inside {supported_isa}) &&
{'fraction_non_alphanumeric': 0.1000706499798143, 'fraction_numerical': 0.022885547032700848, 'mean_word_length': 2.494929453262787, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '753343', 'n_tokens_mistral': 32587, 'n_tokens_neox': 30716, 'n_words': 5331}