diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index 28b8cfe5..2a722670 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/google/riscv-dv - rev: 162ea7312d21ac0b8ae73669fb68bf284b68f851 + rev: e6a63ff19ddf162a89379f9e03f76345c3558ecc } } diff --git a/vendor/google_riscv-dv/pygen/experimental/README.md b/vendor/google_riscv-dv/pygen/experimental/README.md index 5469208f..293bd8ab 100644 --- a/vendor/google_riscv-dv/pygen/experimental/README.md +++ b/vendor/google_riscv-dv/pygen/experimental/README.md @@ -2,8 +2,8 @@ This directory contains the proof-of-concept work of python based RISC-V random instruction generator. The class structure can be directly mapped to the -existing SV/UVM verison. The constraint part is implemented basd on -[https://labix.org/python-constraint](python-constraint). +existing SV/UVM verison. The constraint part is implemented based on +[python-constraint](https://labix.org/python-constraint). The work here is just experimental. We plan to take a fresh look of the framework and build a scalable python based generator in the near future. diff --git a/vendor/google_riscv-dv/pygen/experimental/riscv_asm_program_gen.py b/vendor/google_riscv-dv/pygen/experimental/riscv_asm_program_gen.py index 5824905f..ac79d8a8 100644 --- a/vendor/google_riscv-dv/pygen/experimental/riscv_asm_program_gen.py +++ b/vendor/google_riscv-dv/pygen/experimental/riscv_asm_program_gen.py @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. """ +import subprocess import random from bitstring import BitArray, BitStream import utils @@ -209,6 +210,7 @@ class riscv_asm_program_gen: self.instr_stream.append(str) def print_instr_stream(self): + subprocess.run(["mkdir", "-p", "out"]) f = open("./out/test.S", "w+") for s in self.instr_stream: if isinstance(s, list): diff --git a/vendor/google_riscv-dv/pygen/experimental/riscv_instr_base.py b/vendor/google_riscv-dv/pygen/experimental/riscv_instr_base.py index 5d775aae..7012a357 100644 --- a/vendor/google_riscv-dv/pygen/experimental/riscv_instr_base.py +++ b/vendor/google_riscv-dv/pygen/experimental/riscv_instr_base.py @@ -329,7 +329,7 @@ class riscv_instr_base: return True def only_arithmetic_and_logical_c(category): - if category == "ARITHMETIC" or category == "LOGICAL" or + if category == "ARITHMETIC" or category == "LOGICAL" or \ category == "BRANCH" or category == "LOAD" or category == "STORE": return True diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index 78c0ac0e..c46d69fb 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -18,6 +18,7 @@ Regression script for RISC-V random instruction generator import argparse import os +import random import re import sys import logging @@ -33,6 +34,39 @@ from types import SimpleNamespace LOGGER = logging.getLogger() + +class SeedGen: + '''An object that will generate a pseudo-random seed for test iterations''' + def __init__(self, start_seed, fixed_seed, seed_yaml): + # These checks are performed with proper error messages at argument parsing + # time, but it can't hurt to do a belt-and-braces check here too. + assert fixed_seed is None or start_seed is None + + self.fixed_seed = fixed_seed + self.start_seed = start_seed + self.rerun_seed = {} if seed_yaml is None else read_yaml(seed_yaml) + + def get(self, test_id, test_iter): + '''Get the seed to use for the given test and iteration''' + + if test_id in self.rerun_seed: + # Note that test_id includes the iteration index (well, the batch index, + # at any rate), so this makes sense even if test_iter > 0. + return self.rerun_seed[test_id] + + if self.fixed_seed is not None: + # Checked at argument parsing time + assert test_iter == 0 + return self.fixed_seed + + if self.start_seed is not None: + return self.start_seed + test_iter + + # If the user didn't specify seeds in some way, we generate a random seed + # every time + return random.getrandbits(31) + + def get_generator_cmd(simulator, simulator_yaml, cov, exp, debug_cmd): """ Setup the compile and simulation command for the generator @@ -186,7 +220,7 @@ def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, run_cmd(cmd, timeout_s, debug_cmd = debug_cmd) -def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, +def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_gen, csr_file, isa, end_signature_addr, lsf_cmd, timeout_s, log_suffix, batch_size, output_dir, verbose, check_return_code, debug_cmd): """Run the instruction generator @@ -196,8 +230,7 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, test_list : List of assembly programs to be compiled cwd : Filesystem path to RISCV-DV repo sim_opts : Simulation options for the generator - seed_yaml : Seed specification from a prior regression - seed : Seed to the instruction generator + seed_gen : A SeedGen seed generator csr_file : YAML file containing description of all CSRs isa : Processor supported ISA subset end_signature_addr : Address that tests will write pass/fail signature to at end of test @@ -213,9 +246,7 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, sim_cmd = re.sub("", os.path.abspath(output_dir), sim_cmd) sim_cmd = re.sub("", cwd, sim_cmd) sim_cmd = re.sub("", sim_opts, sim_cmd) - rerun_seed = {} - if seed_yaml: - rerun_seed = read_yaml(seed_yaml) + logging.info("Running RISC-V instruction generator") sim_seed = {} for test in test_list: @@ -233,10 +264,7 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, logging.info("Running %s with %0d batches" % (test['test'], batch_cnt)) for i in range(0, batch_cnt): test_id = '%0s_%0d' % (test['test'], i) - if test_id in rerun_seed: - rand_seed = rerun_seed[test_id] - else: - rand_seed = get_seed(seed) + rand_seed = seed_gen.get(test_id, i * batch_cnt) if i < batch_cnt - 1: test_cnt = batch_size else: @@ -270,18 +298,15 @@ def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, debug_cmd = debug_cmd) -def gen(test_list, cfg, output_dir, cwd): +def gen(test_list, argv, output_dir, cwd): """Run the instruction generator Args: test_list : List of assembly programs to be compiled - cfg : Loaded configuration dictionary. + argv : Configuration arguments output_dir : Output directory of the ELF files cwd : Filesystem path to RISCV-DV repo """ - # Convert key dictionary to argv variable - argv= SimpleNamespace(**cfg) - check_return_code = True if argv.simulator == "ius": # Incisive return non-zero return code even test passes @@ -304,7 +329,8 @@ def gen(test_list, cfg, output_dir, cwd): argv.cmp_opts, output_dir, argv.debug, argv.lsf_cmd) # Run the instruction generator if not argv.co: - do_simulate(sim_cmd, test_list, cwd, argv.sim_opts, argv.seed_yaml, argv.seed, argv.csr_yaml, + seed_gen = SeedGen(argv.start_seed, argv.seed, argv.seed_yaml) + do_simulate(sim_cmd, test_list, cwd, argv.sim_opts, seed_gen, argv.csr_yaml, argv.isa, argv.end_signature_addr, argv.lsf_cmd, argv.gen_timeout, argv.log_suffix, argv.batch_size, output_dir, argv.verbose, check_return_code, argv.debug) @@ -644,7 +670,20 @@ def save_regr_report(report): logging.info("ISS regression report is saved to %s" % report) -def setup_parser(): +def read_seed(arg): + '''Read --seed or --seed_start''' + try: + seed = int(arg) + if seed < 0: + raise ValueError('bad seed') + return seed + + except ValueError: + raise argparse.ArgumentTypeError('Bad seed ({}): ' + 'must be a non-negative integer.' + .format(arg)) + +def parse_args(cwd): """Create a command line parser. Returns: The created parser. @@ -661,8 +700,6 @@ def setup_parser(): help="Regression testlist", dest="testlist") parser.add_argument("-tn", "--test", type=str, default="all", help="Test name, 'all' means all tests in the list", dest="test") - parser.add_argument("--seed", type=int, default=-1, - help="Randomization seed, default -1 means random seed") parser.add_argument("-i", "--iterations", type=int, default=0, help="Override the iteration count in the test list", dest="iterations") parser.add_argument("-si", "--simulator", type=str, default="vcs", @@ -706,9 +743,6 @@ def setup_parser(): help="RTL simulator setting YAML") parser.add_argument("--csr_yaml", type=str, default="", help="CSR description file") - parser.add_argument("--seed_yaml", type=str, default="", - help="Rerun the generator with the seed specification \ - from a prior regression") parser.add_argument("-ct", "--custom_target", type=str, default="", help="Directory name of the custom target") parser.add_argument("-cs", "--core_setting_dir", type=str, default="", @@ -735,7 +769,47 @@ def setup_parser(): help="Run verilog style check") parser.add_argument("-d", "--debug", type=str, default="", help="Generate debug command log file") - return parser + + rsg = parser.add_argument_group('Random seeds', + 'To control random seeds, use at most one ' + 'of the --start_seed, --seed or --seed_yaml ' + 'arguments. Since the latter two only give ' + 'a single seed for each test, they imply ' + '--iterations=1.') + + rsg.add_argument("--start_seed", type=read_seed, + help=("Randomization seed to use for first iteration of " + "each test. Subsequent iterations use seeds " + "counting up from there. Cannot be used with " + "--seed or --seed_yaml.")) + rsg.add_argument("--seed", type=read_seed, + help=("Randomization seed to use for each test. " + "Implies --iterations=1. Cannot be used with " + "--start_seed or --seed_yaml.")) + rsg.add_argument("--seed_yaml", type=str, + help=("Rerun the generator with the seed specification " + "from a prior regression. Implies --iterations=1. " + "Cannot be used with --start_seed or --seed.")) + + args = parser.parse_args() + + if args.seed is not None and args.start_seed is not None: + logging.error('--start_seed and --seed are mutually exclusive.') + sys.exit(RET_FAIL) + + if args.seed is not None: + if args.iterations == 0: + args.iterations = 1 + elif args.iterations > 1: + logging.error('--seed is incompatible with setting --iterations ' + 'greater than 1.') + sys.exit(RET_FAIL) + + # We've parsed all the arguments from the command line; default values + # can be set in the config file. Read that here. + load_config(args, cwd) + + return args def load_config(args, cwd): @@ -804,21 +878,17 @@ def load_config(args, cwd): sys.exit("mabi and isa must be specified for custom target %0s" % args.custom_target) if not args.testlist: args.testlist = args.custom_target + "/testlist.yaml" - # Create loaded configuration dictionary. - cfg = vars(args) - return cfg def main(): """This is the main entry point.""" try: - parser = setup_parser() - args = parser.parse_args() cwd = os.path.dirname(os.path.realpath(__file__)) os.environ["RISCV_DV_ROOT"] = cwd + + args = parse_args(cwd) setup_logging(args.verbose) - # Load configuration from the command line and the configuration file. - cfg = load_config(args, cwd) + # Create output directory output_dir = create_output(args.o, args.noclean) @@ -941,7 +1011,7 @@ def main(): sys.exit(RET_FAIL) # Run remaining tests using the instruction generator - gen(matched_list, cfg, output_dir, cwd) + gen(matched_list, args, output_dir, cwd) if not args.co: # Compile the assembly program to ELF, convert to plain binary diff --git a/vendor/google_riscv-dv/scripts/lib.py b/vendor/google_riscv-dv/scripts/lib.py index cc8b655d..5e607b9b 100644 --- a/vendor/google_riscv-dv/scripts/lib.py +++ b/vendor/google_riscv-dv/scripts/lib.py @@ -85,20 +85,6 @@ def get_env_var(var, debug_cmd = None): return val -def get_seed(seed): - """Get the seed to run the generator - - Args: - seed : input seed - - Returns: - seed to run instruction generator - """ - if seed >= 0: - return seed - return random.getrandbits(31) - - def run_cmd(cmd, timeout_s = 999, exit_on_error = 1, check_return_code = True, debug_cmd = None): """Run a command and return output diff --git a/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv index 82944aa8..1b9120f2 100755 --- a/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv @@ -475,9 +475,7 @@ class riscv_b_instr extends riscv_instr; }) || (ZBE inside {cfg.enable_bitmanip_groups} && instr_name inside { BEXT, BEXTW, - BDEP, BDEPW, - // TODO, spec 0.92 doesn't categorize these 2 instr in any group, put in ZBE for now - SEXT_B, SEXT_H + BDEP, BDEPW }) || (ZBF inside {cfg.enable_bitmanip_groups} && instr_name inside {BFP, BFPW}) || (ZBC inside {cfg.enable_bitmanip_groups} && instr_name inside { @@ -492,7 +490,11 @@ class riscv_b_instr extends riscv_instr; }) || (ZBT inside {cfg.enable_bitmanip_groups} && instr_name inside { CMOV, CMIX, - FSL, FSLW, FSR, FSRW, FSRI, FSRIW})); + FSL, FSLW, FSR, FSRW, FSRI, FSRIW}) || + // TODO, spec 0.92 doesn't categorize these 2 instr, put them in ZB_TMP #572 + (ZB_TMP inside {cfg.enable_bitmanip_groups} && instr_name inside { + SEXT_B, SEXT_H}) + ); endfunction endclass diff --git a/vendor/google_riscv-dv/src/isa/riscv_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_instr.sv index dd81bc19..087884e9 100644 --- a/vendor/google_riscv-dv/src/isa/riscv_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_instr.sv @@ -649,4 +649,6 @@ class riscv_instr extends uvm_object; imm_str = $sformatf("%0d", $signed(imm)); endfunction + `include "isa/riscv_instr_cov.svh" + endclass diff --git a/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh b/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh new file mode 100644 index 00000000..63f20de8 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/riscv_instr_cov.svh @@ -0,0 +1,510 @@ + + typedef uvm_enum_wrapper#(riscv_reg_t) gpr_enum; + typedef uvm_enum_wrapper#(riscv_fpr_t) fpr_enum; + typedef uvm_enum_wrapper#(privileged_reg_t) preg_enum; + + typedef enum bit[1:0] { + POSITIVE, NEGATIVE + } operand_sign_e; + + typedef enum bit[1:0] { + DIV_NORMAL, DIV_BY_ZERO, DIV_OVERFLOW + } div_result_e; + + typedef enum bit[1:0] { + EQUAL, LARGER, SMALLER + } compare_result_e; + + typedef enum bit [1:0] { + IDENTICAL, OPPOSITE, SIMILAR, DIFFERENT + } logical_similarity_e; + + typedef enum bit[2:0] { + NORMAL_VAL, MIN_VAL, MAX_VAL, ZERO_VAL + } special_val_e; + + static bit [XLEN-1:0] gpr_state[string]; + + rand bit [XLEN-1:0] rs1_value; + rand bit [XLEN-1:0] rs2_value; + rand bit [XLEN-1:0] rs3_value; + rand bit [XLEN-1:0] rd_value; + rand bit [XLEN-1:0] fs1_value; + rand bit [XLEN-1:0] fs2_value; + rand bit [XLEN-1:0] fs3_value; + rand bit [XLEN-1:0] fd_value; + bit [31:0] binary; + bit [XLEN-1:0] pc; + bit [XLEN-1:0] mem_addr; + + bit unaligned_pc; + bit unaligned_mem_access; + bit compressed; + bit branch_hit; + div_result_e div_result; + operand_sign_e rs1_sign; + operand_sign_e rs2_sign; + operand_sign_e rs3_sign; + operand_sign_e fs1_sign; + operand_sign_e fs2_sign; + operand_sign_e fs3_sign; + operand_sign_e imm_sign; + operand_sign_e rd_sign; + operand_sign_e fd_sign; + hazard_e gpr_hazard; + hazard_e lsu_hazard; + special_val_e rs1_special_val; + special_val_e rs2_special_val; + special_val_e rs3_special_val; + special_val_e rd_special_val; + special_val_e imm_special_val; + compare_result_e compare_result; + logical_similarity_e logical_similarity; + string trace; + + // TODO, remove it? + //`VECTOR_INCLUDE("riscv_instr_cov_item_inc_declares.sv") + + virtual function void pre_sample(); + unaligned_pc = (pc[1:0] != 2'b00); + rs1_sign = get_operand_sign(rs1_value); + rs2_sign = get_operand_sign(rs2_value); + rs3_sign = get_operand_sign(rs3_value); + rd_sign = get_operand_sign(rd_value); + fs1_sign = get_operand_sign(fs1_value); + fs2_sign = get_operand_sign(fs2_value); + fs3_sign = get_operand_sign(fs2_value); + fd_sign = get_operand_sign(fd_value); + imm_sign = get_imm_sign(imm); + rs1_special_val = get_operand_special_val(rs1_value); + rd_special_val = get_operand_special_val(rd_value); + rs2_special_val = get_operand_special_val(rs2_value); + rs3_special_val = get_operand_special_val(rs3_value); + if ((format != R_FORMAT) && (format != CR_FORMAT)) begin + imm_special_val = get_imm_special_val(imm); + end + if (category inside {COMPARE, BRANCH}) begin + compare_result = get_compare_result(); + end + if (category inside {LOAD, STORE}) begin + mem_addr = rs1_value + imm; + unaligned_mem_access = is_unaligned_mem_access(); + if (unaligned_mem_access) begin + `uvm_info(`gfn, $sformatf("Unaligned: %0s, mem_addr:%0x", instr_name.name(), mem_addr), + UVM_HIGH) + end + end + if (category == LOGICAL) begin + logical_similarity = get_logical_similarity(); + end + if (category == BRANCH) begin + branch_hit = is_branch_hit(); + end + if (instr_name inside {DIV, DIVU, REM, REMU, DIVW, DIVUW, REMW, REMUW}) begin + div_result = get_div_result(); + end + endfunction + + virtual function operand_sign_e get_operand_sign(bit [XLEN-1:0] value); + if (value[XLEN-1]) begin + return NEGATIVE; + end else begin + return POSITIVE; + end + endfunction + + virtual function bit is_unaligned_mem_access(); + if ((instr_name inside {LWU, LD, SD, C_LD, C_SD}) && (mem_addr % 8 != 0)) begin + return 1'b1; + end else if ((instr_name inside {LW, SW, C_LW, C_SW}) && (mem_addr % 4 != 0)) begin + return 1'b1; + end else if ((instr_name inside {LH, LHU, SH}) && (mem_addr % 2 != 0)) begin + return 1'b1; + end begin + return 1'b0; + end + endfunction + + virtual function operand_sign_e get_imm_sign(bit [31:0] value); + if (value[31]) begin + return NEGATIVE; + end else begin + return POSITIVE; + end + endfunction + + virtual function div_result_e get_div_result(); + if (rs2_value == 0) begin + return DIV_BY_ZERO; + end else if ((rs2_value == '1) && (rs1_value == (1'b1 << (XLEN-1)))) + return DIV_OVERFLOW; + else + return DIV_NORMAL; + endfunction + + virtual function special_val_e get_operand_special_val(bit [XLEN-1:0] value); + if (value == 0) begin + return ZERO_VAL; + end else if (value == '1 << (XLEN-1)) begin + return MIN_VAL; + end else if (value == '1 >> 1) begin + return MAX_VAL; + end else begin + return NORMAL_VAL; + end + endfunction + + virtual function special_val_e get_imm_special_val(bit [31:0] value); + if (value == 0) begin + return ZERO_VAL; + end else if (format == U_FORMAT) begin + // unsigend immediate value + bit [31:0] max_val; + max_val = (1 << imm_len)-1; + if (value == '0) begin + return MIN_VAL; + end + if (value == max_val) begin + return MAX_VAL; + end + end else begin + // signed immediate value + int signed max_val, min_val; + max_val = 2 ** (imm_len-1) - 1; + min_val = -2 ** (imm_len-1); + if (min_val == $signed(value)) begin + return MIN_VAL; + end + if (max_val == $signed(value)) begin + return MAX_VAL; + end + end + return NORMAL_VAL; + endfunction + + virtual function compare_result_e get_compare_result(); + bit [XLEN-1:0] val1, val2; + val1 = rs1_value; + val2 = (format == I_FORMAT) ? imm : rs2_value; + if (val1 == val2) begin + return EQUAL; + end else if (val1 < val2) begin + return SMALLER; + end else begin + return LARGER; + end + endfunction + + virtual function bit is_branch_hit(); + case(instr_name) + BEQ : is_branch_hit = (rs1_value == rs2_value); + C_BEQZ : is_branch_hit = (rs1_value == 0); + BNE : is_branch_hit = (rs1_value != rs2_value); + C_BNEZ : is_branch_hit = (rs1_value != 0); + BLT : is_branch_hit = ($signed(rs1_value) < $signed(rs2_value)); + BGE : is_branch_hit = ($signed(rs1_value) >= $signed(rs2_value)); + BLTU : is_branch_hit = (rs1_value < rs2_value); + BGEU : is_branch_hit = (rs1_value >= rs2_value); + default: `uvm_error(get_name(), $sformatf("Unexpected instr %0s", instr_name.name())) + endcase + return is_branch_hit; + endfunction + + virtual function logical_similarity_e get_logical_similarity(); + bit [XLEN-1:0] val1, val2; + int bit_difference; + val1 = rs1_value; + val2 = (format == I_FORMAT) ? imm : rs2_value; + bit_difference = $countones(val1 ^ val2); + if (val1 == val2) + return IDENTICAL; + else if (bit_difference == 32) + return OPPOSITE; + else if (bit_difference < 5) + return SIMILAR; + else + return DIFFERENT; + endfunction + + virtual function void check_hazard_condition(riscv_instr pre_instr); + riscv_reg_t gpr; + if (pre_instr.has_rd) begin + if ((has_rs1 && (rs1 == pre_instr.rd)) || (has_rs2 && (rs2 == pre_instr.rd))) begin + gpr_hazard = RAW_HAZARD; + end else if (has_rd && (rd == pre_instr.rd)) begin + gpr_hazard = WAW_HAZARD; + end else if (has_rd && ((pre_instr.has_rs1 && (pre_instr.rs1 == rd)) || + (pre_instr.has_rs2 && (pre_instr.rs2 == rd)))) begin + gpr_hazard = WAR_HAZARD; + end else begin + gpr_hazard = NO_HAZARD; + end + end + if (category == LOAD) begin + if ((pre_instr.category == STORE) && (pre_instr.mem_addr == mem_addr)) begin + lsu_hazard = RAW_HAZARD; + end else begin + lsu_hazard = NO_HAZARD; + end + end + if (category == STORE) begin + if ((pre_instr.category == STORE) && (pre_instr.mem_addr == mem_addr)) begin + lsu_hazard = WAW_HAZARD; + end else if ((pre_instr.category == LOAD) && (pre_instr.mem_addr == mem_addr)) begin + lsu_hazard = WAR_HAZARD; + end else begin + lsu_hazard = NO_HAZARD; + end + end + `uvm_info(`gfn, $sformatf("Pre:%0s, Cur:%0s, Hazard: %0s/%0s", + pre_instr.convert2asm(), this.convert2asm(), + gpr_hazard.name(), lsu_hazard.name()), UVM_FULL) + endfunction + + virtual function void sample_cov(); + pre_sample(); + endfunction + + virtual function void update_src_regs(string operands[$]); + privileged_reg_t preg; + case(format) + J_FORMAT, U_FORMAT : begin + // instr rd,imm + `DV_CHECK_FATAL(operands.size() == 2) + get_val(operands[1], imm); + end + I_FORMAT: begin + // TODO, support I_FORMAT floating point later + // if (group == RV32F) return; + if (instr_name inside {FSRI, FSRIW}) begin + `DV_CHECK_FATAL(operands.size() == 4, instr_name) + end else begin + `DV_CHECK_FATAL(operands.size() == 3, instr_name) + end + if(category == LOAD) begin + // load rd, imm(rs1) + rs1 = get_gpr(operands[2]); + rs1_value = get_gpr_state(operands[2]); + get_val(operands[1], imm); + end else if(category == CSR) begin + // csrrwi rd, csr, imm + get_val(operands[2], imm); + if (preg_enum::from_name(operands[1].toupper(), preg)) begin + csr = preg; + end else begin + get_val(operands[1], csr); + end + //end else if (instr_name inside {FSRI, FSRIW}) begin + // // fsri rd, rs1, rs3, imm + // rs1 = get_gpr(operands[1]); + // rs1_value = get_gpr_state(operands[1]); + // rs3 = get_gpr(operands[2]); + // rs3_value = get_gpr_state(operands[2]); + // get_val(operands[3], imm); + end else begin + // addi rd, rs1, imm + rs1 = get_gpr(operands[1]); + rs1_value = get_gpr_state(operands[1]); + get_val(operands[2], imm); + end + end + S_FORMAT, B_FORMAT: begin + `DV_CHECK_FATAL(operands.size() == 3) + if(category == STORE) begin + // sw rs2,imm(rs1) + //update_instr_reg_by_abi_name(operands[0], // FSW rs2 is fp, TODO + // rs2, rs2_value, + // fs2, fs2_value); + + rs2 = get_gpr(operands[0]); + rs2_value = get_gpr_state(operands[0]); + rs1 = get_gpr(operands[2]); + rs1_value = get_gpr_state(operands[2]); + get_val(operands[1], imm); + end else begin + // bne rs1, rs2, imm + rs1 = get_gpr(operands[0]); + rs1_value = get_gpr_state(operands[0]); + rs2 = get_gpr(operands[1]); + rs2_value = get_gpr_state(operands[1]); + get_val(operands[2], imm); + end + end + R_FORMAT: begin + if ((has_rs2 || category == CSR) && + !(instr_name inside {FCLASS_S, FCLASS_D})) begin + `DV_CHECK_FATAL(operands.size() == 3) + end else begin + `DV_CHECK_FATAL(operands.size() == 2) + end + if(category == CSR) begin + // csrrw rd, csr, rs1 + if (preg_enum::from_name(operands[1].toupper(), preg)) begin + csr = preg; + end else begin + get_val(operands[1], csr); + end + rs1 = get_gpr(operands[2]); + rs1_value = get_gpr_state(operands[2]); + end + //else if (group inside {RV32F, RV64F, RV32D, RV64D}) begin // TODO + // // fs1 + // fs1 = get_fpr(operands[1]); + // fs1_value = get_gpr_state(operands[1]); + // // fs2 + // if (!instr_name inside {FCLASS_S, FCLASS_D}) begin + // fs2 = get_fpr(operands[2]); + // fs2_value = get_gpr_state(operands[2]); + // end + //end + else begin + // add rd, rs1, rs2 + rs1 = get_gpr(operands[1]); + rs1_value = get_gpr_state(operands[1]); + if (has_rs2) begin + rs2 = get_gpr(operands[2]); + rs2_value = get_gpr_state(operands[2]); + end + end + end + R4_FORMAT: begin + `DV_CHECK_FATAL(operands.size() == 4) + //update_instr_reg_by_abi_name(operands[1], // TODO + // rs1, rs1_value, + // fs1, fs1_value); + //update_instr_reg_by_abi_name(operands[2], + // rs2, rs2_value, + // fs2, fs2_value); + //update_instr_reg_by_abi_name(operands[3], + // rs3, rs3_value, + // fs3, fs3_value); + rs1 = get_gpr(operands[1]); + rs1_value = get_gpr_state(operands[1]); + rs2 = get_gpr(operands[2]); + rs2_value = get_gpr_state(operands[2]); + rs2 = get_gpr(operands[3]); + rs2_value = get_gpr_state(operands[3]); + end + CI_FORMAT, CIW_FORMAT: begin + if (instr_name == C_ADDI16SP) begin + get_val(operands[1], imm); + rs1 = SP; + rs1_value = get_gpr_state("sp"); + end else if (instr_name == C_ADDI4SPN) begin + rs1 = SP; + rs1_value = get_gpr_state("sp"); + end else if (instr_name inside {C_LDSP, C_LWSP, C_LQSP}) begin + // c.ldsp rd, imm + get_val(operands[1], imm); + rs1 = SP; + rs1_value = get_gpr_state("sp"); + end else begin + // c.lui rd, imm + get_val(operands[1], imm); + end + end + CL_FORMAT: begin + // c.lw rd, imm(rs1) + get_val(operands[1], imm); + rs1 = get_gpr(operands[2]); + rs1_value = get_gpr_state(operands[2]); + end + CS_FORMAT: begin + // c.sw rs2,imm(rs1) + rs2 = get_gpr(operands[0]); + rs2_value = get_gpr_state(operands[0]); + rs1 = get_gpr(operands[2]); + rs1_value = get_gpr_state(operands[2]); + get_val(operands[1], imm); + end + CA_FORMAT: begin + // c.and rd, rs2 (rs1 == rd) + rs2 = get_gpr(operands[1]); + rs2_value = get_gpr_state(operands[1]); + rs1 = get_gpr(operands[0]); + rs1_value = get_gpr_state(operands[0]); + end + CB_FORMAT: begin + // c.beqz rs1, imm + rs1 = get_gpr(operands[0]); + rs1_value = get_gpr_state(operands[0]); + get_val(operands[1], imm); + end + CSS_FORMAT: begin + // c.swsp rs2, imm + rs2 = get_gpr(operands[0]); + rs2_value = get_gpr_state(operands[0]); + rs1 = SP; + rs1_value = get_gpr_state("sp"); + get_val(operands[1], imm); + end + CR_FORMAT: begin + if (instr_name inside {C_JR, C_JALR}) begin + // c.jalr rs1 + rs1 = get_gpr(operands[0]); + rs1_value = get_gpr_state(operands[0]); + end else begin + // c.add rd, rs2 + rs2 = get_gpr(operands[1]); + rs2_value = get_gpr_state(operands[1]); + end + end + CJ_FORMAT: begin + // c.j imm + get_val(operands[0], imm); + end + endcase + endfunction : update_src_regs + + virtual function void update_dst_regs(string reg_name, string val_str); + // update_instr_reg_by_abi_name(pair[0], instr.rd, instr.rd_value, instr.fd, instr.fd_value); + get_val(val_str, gpr_state[reg_name], .hex(1)); + rd = get_gpr(reg_name); + rd_value = get_gpr_state(reg_name); + endfunction : update_dst_regs + + function riscv_reg_t get_gpr(input string str); + str = str.toupper(); + if (!gpr_enum::from_name(str, get_gpr)) begin + `uvm_fatal(`gfn, $sformatf("Cannot convert %0s to GPR", str)) + end + endfunction : get_gpr + + virtual function bit [XLEN-1:0] get_gpr_state(string name); + if (name inside {"zero", "x0"}) begin + return 0; + end else if (gpr_state.exists(name)) begin + return gpr_state[name]; + end else begin + `uvm_warning(`gfn, $sformatf("Cannot find GPR state: %0s", name)) + return 0; + end + endfunction : get_gpr_state + + // TODO +// virtual function riscv_fpr_t get_fpr(input string str); +// str = str.toupper(); +// if (!fpr_enum::from_name(str, get_fpr)) begin +// `uvm_fatal(`gfn, $sformatf("Cannot convert %0s to FPR", str)) +// end +// endfunction : get_fpr +// +// function bit is_fp_reg(input string str); +// riscv_fpr_t tmp; +// str = str.toupper(); +// return fpr_enum::from_name(str, tmp); +// endfunction : is_fp_reg +// +// virtual function void update_instr_reg_by_abi_name(string abi_name, +// ref riscv_reg_t rs, +// ref bit [XLEN-1:0] rs_value, +// ref riscv_fpr_t fs, +// ref bit [XLEN-1:0] fs_value); +// if (is_fp_reg(abi_name)) begin +// fs = get_fpr(abi_name); +// fs_value = get_gpr_state(abi_name); +// end else begin +// rs = get_gpr(abi_name); +// rs_value = get_gpr_state(abi_name); +// end +// endfunction : update_instr_reg_by_abi_name diff --git a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv index c29378bc..96d3cadc 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -357,7 +357,7 @@ class riscv_asm_program_gen extends uvm_object; // Generate the user stack section virtual function void gen_stack_section(int hart); - string hart_prefix_string = hart_prefix(hart); + string hart_prefix_string = hart_prefix(hart); if (cfg.use_push_data_section) begin instr_stream.push_back($sformatf(".pushsection .%0suser_stack,\"aw\",@progbits;", hart_prefix_string)); @@ -383,7 +383,7 @@ class riscv_asm_program_gen extends uvm_object; // The kernal stack is used to save user program context before executing exception handling virtual function void gen_kernel_stack_section(int hart); - string hart_prefix_string = hart_prefix(hart); + string hart_prefix_string = hart_prefix(hart); if (cfg.use_push_data_section) begin instr_stream.push_back($sformatf(".pushsection .%0skernel_stack,\"aw\",@progbits;", hart_prefix_string)); diff --git a/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv b/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv deleted file mode 100644 index 3893c929..00000000 --- a/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv +++ /dev/null @@ -1,270 +0,0 @@ -class riscv_instr_cov_item extends riscv_instr; - - typedef enum bit[1:0] { - POSITIVE, NEGATIVE - } operand_sign_e; - - typedef enum bit[1:0] { - DIV_NORMAL, DIV_BY_ZERO, DIV_OVERFLOW - } div_result_e; - - typedef enum bit[1:0] { - EQUAL, LARGER, SMALLER - } compare_result_e; - - typedef enum bit [1:0] { - IDENTICAL, OPPOSITE, SIMILAR, DIFFERENT - } logical_similarity_e; - - typedef enum bit[2:0] { - NORMAL_VAL, MIN_VAL, MAX_VAL, ZERO_VAL - } special_val_e; - - rand riscv_reg_t rs3; - rand bit [XLEN-1:0] rs1_value; - rand bit [XLEN-1:0] rs2_value; - rand bit [XLEN-1:0] rs3_value; - rand bit [XLEN-1:0] rd_value; - rand riscv_fpr_t fs1; - rand riscv_fpr_t fs2; - rand riscv_fpr_t fs3; - rand riscv_fpr_t fd; - rand bit [XLEN-1:0] fs1_value; - rand bit [XLEN-1:0] fs2_value; - rand bit [XLEN-1:0] fs3_value; - rand bit [XLEN-1:0] fd_value; - bit [31:0] binary; - bit [XLEN-1:0] pc; - bit [XLEN-1:0] mem_addr; - - bit unaligned_pc; - bit unaligned_mem_access; - bit compressed; - bit branch_hit; - div_result_e div_result; - operand_sign_e rs1_sign; - operand_sign_e rs2_sign; - operand_sign_e rs3_sign; - operand_sign_e fs1_sign; - operand_sign_e fs2_sign; - operand_sign_e fs3_sign; - operand_sign_e imm_sign; - operand_sign_e rd_sign; - operand_sign_e fd_sign; - hazard_e gpr_hazard; - hazard_e lsu_hazard; - special_val_e rs1_special_val; - special_val_e rs2_special_val; - special_val_e rs3_special_val; - special_val_e rd_special_val; - special_val_e imm_special_val; - compare_result_e compare_result; - logical_similarity_e logical_similarity; - string trace; - - `VECTOR_INCLUDE("riscv_instr_cov_item_inc_declares.sv") - - `uvm_object_utils(riscv_instr_cov_item) - `uvm_object_new - - virtual function void pre_sample(); - unaligned_pc = (pc[1:0] != 2'b00); - rs1_sign = get_operand_sign(rs1_value); - rs2_sign = get_operand_sign(rs2_value); - rs3_sign = get_operand_sign(rs3_value); - rd_sign = get_operand_sign(rd_value); - fs1_sign = get_operand_sign(fs1_value); - fs2_sign = get_operand_sign(fs2_value); - fs3_sign = get_operand_sign(fs2_value); - fd_sign = get_operand_sign(fd_value); - imm_sign = get_imm_sign(imm); - rs1_special_val = get_operand_special_val(rs1_value); - rd_special_val = get_operand_special_val(rd_value); - rs2_special_val = get_operand_special_val(rs2_value); - rs3_special_val = get_operand_special_val(rs3_value); - if ((format != R_FORMAT) && (format != CR_FORMAT)) begin - imm_special_val = get_imm_special_val(imm); - end - if (category inside {COMPARE, BRANCH}) begin - compare_result = get_compare_result(); - end - if (category inside {LOAD, STORE}) begin - mem_addr = rs1_value + imm; - unaligned_mem_access = is_unaligned_mem_access(); - if (unaligned_mem_access) begin - `uvm_info(`gfn, $sformatf("Unaligned: %0s, mem_addr:%0x", instr_name.name(), mem_addr), - UVM_HIGH) - end - end - if (category == LOGICAL) begin - logical_similarity = get_logical_similarity(); - end - if (category == BRANCH) begin - branch_hit = is_branch_hit(); - end - if (instr_name inside {DIV, DIVU, REM, REMU, DIVW, DIVUW, REMW, REMUW}) begin - div_result = get_div_result(); - end - endfunction - - function operand_sign_e get_operand_sign(bit [XLEN-1:0] value); - if (value[XLEN-1]) begin - return NEGATIVE; - end else begin - return POSITIVE; - end - endfunction - - function bit is_unaligned_mem_access(); - if ((instr_name inside {LWU, LD, SD, C_LD, C_SD}) && (mem_addr % 8 != 0)) begin - return 1'b1; - end else if ((instr_name inside {LW, SW, C_LW, C_SW}) && (mem_addr % 4 != 0)) begin - return 1'b1; - end else if ((instr_name inside {LH, LHU, SH}) && (mem_addr % 2 != 0)) begin - return 1'b1; - end begin - return 1'b0; - end - endfunction - - function operand_sign_e get_imm_sign(bit [31:0] value); - if (value[31]) begin - return NEGATIVE; - end else begin - return POSITIVE; - end - endfunction - - function div_result_e get_div_result(); - if (rs2_value == 0) begin - return DIV_BY_ZERO; - end else if ((rs2_value == '1) && (rs1_value == (1'b1 << (XLEN-1)))) - return DIV_OVERFLOW; - else - return DIV_NORMAL; - endfunction - - function special_val_e get_operand_special_val(bit [XLEN-1:0] value); - if (value == 0) begin - return ZERO_VAL; - end else if (value == '1 << (XLEN-1)) begin - return MIN_VAL; - end else if (value == '1 >> 1) begin - return MAX_VAL; - end else begin - return NORMAL_VAL; - end - endfunction - - function special_val_e get_imm_special_val(bit [31:0] value); - if (value == 0) begin - return ZERO_VAL; - end else if (format == U_FORMAT) begin - // unsigend immediate value - bit [31:0] max_val; - max_val = (1 << imm_len)-1; - if (value == '0) begin - return MIN_VAL; - end - if (value == max_val) begin - return MAX_VAL; - end - end else begin - // signed immediate value - int signed max_val, min_val; - max_val = 2 ** (imm_len-1) - 1; - min_val = -2 ** (imm_len-1); - if (min_val == $signed(value)) begin - return MIN_VAL; - end - if (max_val == $signed(value)) begin - return MAX_VAL; - end - end - return NORMAL_VAL; - endfunction - - function compare_result_e get_compare_result(); - bit [XLEN-1:0] val1, val2; - val1 = rs1_value; - val2 = (format == I_FORMAT) ? imm : rs2_value; - if (val1 == val2) begin - return EQUAL; - end else if (val1 < val2) begin - return SMALLER; - end else begin - return LARGER; - end - endfunction - - function bit is_branch_hit(); - case(instr_name) - BEQ : is_branch_hit = (rs1_value == rs2_value); - C_BEQZ : is_branch_hit = (rs1_value == 0); - BNE : is_branch_hit = (rs1_value != rs2_value); - C_BNEZ : is_branch_hit = (rs1_value != 0); - BLT : is_branch_hit = ($signed(rs1_value) < $signed(rs2_value)); - BGE : is_branch_hit = ($signed(rs1_value) >= $signed(rs2_value)); - BLTU : is_branch_hit = (rs1_value < rs2_value); - BGEU : is_branch_hit = (rs1_value >= rs2_value); - default: `uvm_error(get_name(), $sformatf("Unexpected instr %0s", instr_name.name())) - endcase - return is_branch_hit; - endfunction - - function logical_similarity_e get_logical_similarity(); - bit [XLEN-1:0] val1, val2; - int bit_difference; - val1 = rs1_value; - val2 = (format == I_FORMAT) ? imm : rs2_value; - bit_difference = $countones(val1 ^ val2); - if (val1 == val2) - return IDENTICAL; - else if (bit_difference == 32) - return OPPOSITE; - else if (bit_difference < 5) - return SIMILAR; - else - return DIFFERENT; - endfunction - - function void check_hazard_condition(riscv_instr_cov_item pre_instr); - riscv_reg_t gpr; - if (pre_instr.has_rd) begin - if ((has_rs1 && (rs1 == pre_instr.rd)) || (has_rs2 && (rs2 == pre_instr.rd))) begin - gpr_hazard = RAW_HAZARD; - end else if (has_rd && (rd == pre_instr.rd)) begin - gpr_hazard = WAW_HAZARD; - end else if (has_rd && ((pre_instr.has_rs1 && (pre_instr.rs1 == rd)) || - (pre_instr.has_rs2 && (pre_instr.rs2 == rd)))) begin - gpr_hazard = WAR_HAZARD; - end else begin - gpr_hazard = NO_HAZARD; - end - end - if (category == LOAD) begin - if ((pre_instr.category == STORE) && (pre_instr.mem_addr == mem_addr)) begin - lsu_hazard = RAW_HAZARD; - end else begin - lsu_hazard = NO_HAZARD; - end - end - if (category == STORE) begin - if ((pre_instr.category == STORE) && (pre_instr.mem_addr == mem_addr)) begin - lsu_hazard = WAW_HAZARD; - end else if ((pre_instr.category == LOAD) && (pre_instr.mem_addr == mem_addr)) begin - lsu_hazard = WAR_HAZARD; - end else begin - lsu_hazard = NO_HAZARD; - end - end - `uvm_info(`gfn, $sformatf("Pre:%0s, Cur:%0s, Hazard: %0s/%0s", - pre_instr.convert2asm(), this.convert2asm(), - gpr_hazard.name(), lsu_hazard.name()), UVM_FULL) - endfunction - - virtual function void sample_cov(); - pre_sample(); - endfunction - -endclass diff --git a/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv b/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv index f2153efa..9c016e6f 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv @@ -23,8 +23,20 @@ `define SAMPLE(cg, val) \ if (cg != null) cg.sample(val); -`define INSTR_CG_BEGIN(INSTR_NAME) \ - covergroup ``INSTR_NAME``_cg with function sample(riscv_instr_cov_item instr); +// sample with type cast +`define SAMPLE_W_TYPE(cg, val, typ = riscv_instr) \ + if (cg != null) begin \ + typ t; \ + `DV_CHECK_FATAL($cast(t, val), $sformatf("Cannot cast %0s to %0s", `"val`", `"typ`"), \ + "riscv_instr_cover_group") \ + cg.sample(t); \ + end + +`define SAMPLE_F(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_floating_point_instr) +`define SAMPLE_B(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_b_instr) + +`define INSTR_CG_BEGIN(INSTR_NAME, INSTR_CLASS = riscv_instr) \ + covergroup ``INSTR_NAME``_cg with function sample(INSTR_CLASS instr); `define R_INSTR_CG_BEGIN(INSTR_NAME) \ `INSTR_CG_BEGIN(INSTR_NAME) \ @@ -92,12 +104,6 @@ cp_imm_sign : coverpoint instr.imm_sign; \ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) -`define B_I_INSTR_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ - cp_rs1 : coverpoint instr.rs1; \ - cp_rd : coverpoint instr.rd; \ - `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) - `define U_INSTR_CG_BEGIN(INSTR_NAME) \ `INSTR_CG_BEGIN(INSTR_NAME) \ cp_rd : coverpoint instr.rd; \ @@ -233,7 +239,7 @@ } `define FP_R_INSTR_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \ cp_fs1 : coverpoint instr.fs1; \ cp_fs2 : coverpoint instr.fs2; \ cp_fd : coverpoint instr.fd; \ @@ -243,7 +249,7 @@ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ `define FP_R4_INSTR_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \ cp_fs1 : coverpoint instr.fs1; \ cp_fs2 : coverpoint instr.fs2; \ cp_fs3 : coverpoint instr.fs3; \ @@ -256,35 +262,40 @@ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ `define FSQRT_INSTR_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \ cp_fs1 : coverpoint instr.fs1; \ cp_fd : coverpoint instr.fd; \ cp_fs1_sign : coverpoint instr.fs1_sign; \ cp_fd_sign : coverpoint instr.fd_sign; \ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ +`define B_I_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) + `define B_R_INSTR_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \ cp_rs1 : coverpoint instr.rs1; \ cp_rs2 : coverpoint instr.rs2; \ cp_rd : coverpoint instr.rd; \ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ `define B_R_INSTR_NO_RS2_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \ cp_rs1 : coverpoint instr.rs1; \ cp_rd : coverpoint instr.rd; \ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ `define B_R4_INSTR_CG_BEGIN(INSTR_NAME) \ - `INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \ cp_rs1 : coverpoint instr.rs1; \ cp_rs2 : coverpoint instr.rs2; \ cp_rs3 : coverpoint instr.rs3; \ cp_rd : coverpoint instr.rd; \ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ - // only enable the coverpoint for a particular XLEN (32, 64, 128) `define ENABLE_CP_BY_XLEN(XLEN_VAL) \ option.weight = (XLEN == XLEN_VAL); \ @@ -306,8 +317,8 @@ class riscv_instr_cover_group; riscv_instr_gen_config cfg; - riscv_instr_cov_item cur_instr; - riscv_instr_cov_item pre_instr; + riscv_instr cur_instr; + riscv_instr pre_instr; riscv_instr_name_t instr_list[$]; int unsigned instr_cnt; int unsigned branch_instr_cnt; @@ -526,7 +537,7 @@ class riscv_instr_cover_group; `CG_END // floating instructions - `INSTR_CG_BEGIN(flw) + `INSTR_CG_BEGIN(flw, riscv_floating_point_instr) cp_rs1 : coverpoint instr.rs1 { `DV(ignore_bins zero = {ZERO};) } @@ -538,7 +549,7 @@ class riscv_instr_cover_group; }) `CG_END - `INSTR_CG_BEGIN(fsw) + `INSTR_CG_BEGIN(fsw, riscv_floating_point_instr) cp_rs1 : coverpoint instr.rs1 { `DV(ignore_bins zero = {ZERO};) } @@ -1006,13 +1017,13 @@ class riscv_instr_cover_group; `CSR_INSTR_CG_BEGIN(csrrci) `CG_END - covergroup rv32i_misc_cg with function sample(riscv_instr_cov_item instr); + covergroup rv32i_misc_cg with function sample(riscv_instr instr); cp_misc : coverpoint instr.instr_name { bins instr[] = {FENCE, FENCE_I, EBREAK, ECALL, MRET}; } endgroup - covergroup wfi_cg with function sample(riscv_instr_cov_item instr); + covergroup wfi_cg with function sample(riscv_instr instr); cp_misc : coverpoint instr.instr_name { bins wfi = {WFI}; } @@ -1042,7 +1053,7 @@ class riscv_instr_cover_group; `R_INSTR_CG_BEGIN(divu) cp_div_result: coverpoint instr.div_result { - ignore_bins no_overflow = {riscv_instr_cov_item::DIV_OVERFLOW}; + ignore_bins no_overflow = {riscv_instr::DIV_OVERFLOW}; } cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign; `CG_END @@ -1054,7 +1065,7 @@ class riscv_instr_cover_group; `R_INSTR_CG_BEGIN(remu) cp_div_result: coverpoint instr.div_result { - ignore_bins no_overflow = {riscv_instr_cov_item::DIV_OVERFLOW}; + ignore_bins no_overflow = {riscv_instr::DIV_OVERFLOW}; } cp_sign_cross: cross cp_rs1_sign, cp_rs2_sign; `CG_END @@ -1078,7 +1089,7 @@ class riscv_instr_cover_group; `R_INSTR_CG_BEGIN(divuw) cp_div_result: coverpoint instr.div_result { - ignore_bins no_overflow = {riscv_instr_cov_item::DIV_OVERFLOW}; + ignore_bins no_overflow = {riscv_instr::DIV_OVERFLOW}; } cp_div_zero : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) { bins zero = {0}; @@ -1098,7 +1109,7 @@ class riscv_instr_cover_group; `R_INSTR_CG_BEGIN(remuw) cp_div_result: coverpoint instr.div_result { - ignore_bins no_overflow = {riscv_instr_cov_item::DIV_OVERFLOW}; + ignore_bins no_overflow = {riscv_instr::DIV_OVERFLOW}; } cp_div_zero : coverpoint instr.rs2_value iff (instr.rs2_value[31:0] == 0) { bins zero = {0}; @@ -1451,8 +1462,8 @@ class riscv_instr_cover_group; function new(riscv_instr_gen_config cfg); string opts; 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"); + cur_instr = riscv_instr::type_id::create("cur_instr"); + pre_instr = riscv_instr::type_id::create("pre_instr"); build_instr_list(); `ifdef COMPLIANCE_MODE compliance_mode = 1; @@ -1777,7 +1788,7 @@ class riscv_instr_cover_group; end endfunction - function void sample(riscv_instr_cov_item instr); + function void sample(riscv_instr instr); instr_cnt += 1; if (instr_cnt > 1) begin instr.check_hazard_condition(pre_instr); @@ -1901,113 +1912,113 @@ class riscv_instr_cover_group; C_SUBW : `SAMPLE(c_subw_cg, instr) C_ADDW : `SAMPLE(c_addw_cg, instr) C_ADDIW : `SAMPLE(c_addiw_cg, instr) - FLW : `SAMPLE(flw_cg, instr) - FSW : `SAMPLE(fsw_cg, instr) - FADD_S : `SAMPLE(fadd_s_cg, instr) - FSUB_S : `SAMPLE(fsub_s_cg, instr) - FMUL_S : `SAMPLE(fmul_s_cg, instr) - FDIV_S : `SAMPLE(fdiv_s_cg, instr) - FSQRT_S : `SAMPLE(fsqrt_s_cg, instr) - FMIN_S : `SAMPLE(fmin_s_cg, instr) - FMAX_S : `SAMPLE(fmax_s_cg, instr) - FMADD_S : `SAMPLE(fmadd_s_cg, instr) - FNMADD_S : `SAMPLE(fnmadd_s_cg, instr) - FMSUB_S : `SAMPLE(fmsub_s_cg, instr) - FNMSUB_S : `SAMPLE(fnmsub_s_cg, instr) + FLW : `SAMPLE_F(flw_cg, instr) + FSW : `SAMPLE_F(fsw_cg, instr) + FADD_S : `SAMPLE_F(fadd_s_cg, instr) + FSUB_S : `SAMPLE_F(fsub_s_cg, instr) + FMUL_S : `SAMPLE_F(fmul_s_cg, instr) + FDIV_S : `SAMPLE_F(fdiv_s_cg, instr) + FSQRT_S : `SAMPLE_F(fsqrt_s_cg, instr) + FMIN_S : `SAMPLE_F(fmin_s_cg, instr) + FMAX_S : `SAMPLE_F(fmax_s_cg, instr) + FMADD_S : `SAMPLE_F(fmadd_s_cg, instr) + FNMADD_S : `SAMPLE_F(fnmadd_s_cg, instr) + FMSUB_S : `SAMPLE_F(fmsub_s_cg, instr) + FNMSUB_S : `SAMPLE_F(fnmsub_s_cg, instr) // RV32B - CLZ : `SAMPLE(clz_cg, instr) - CTZ : `SAMPLE(ctz_cg, instr) - PCNT : `SAMPLE(pcnt_cg, instr) - ANDN : `SAMPLE(andn_cg, instr) - ORN : `SAMPLE(orn_cg, instr) - XNOR : `SAMPLE(xnor_cg, instr) - PACK : `SAMPLE(pack_cg, instr) - PACKH : `SAMPLE(packh_cg, instr) - MIN : `SAMPLE(min_cg, instr) - MAX : `SAMPLE(max_cg, instr) - MINU : `SAMPLE(minu_cg, instr) - MAXU : `SAMPLE(maxu_cg, instr) - SEXT_B : `SAMPLE(sext_b_cg, instr) - SEXT_H : `SAMPLE(sext_h_cg, instr) - SBSET : `SAMPLE(sbset_cg, instr) - SBCLR : `SAMPLE(sbclr_cg, instr) - SBINV : `SAMPLE(sbinv_cg, instr) - SBEXT : `SAMPLE(sbext_cg, instr) - SBSETI : `SAMPLE(sbseti_cg, instr) - SBCLRI : `SAMPLE(sbclri_cg, instr) - SBINVI : `SAMPLE(sbinvi_cg, instr) - SBEXTI : `SAMPLE(sbexti_cg, instr) - SLO : `SAMPLE(slo_cg, instr) - SRO : `SAMPLE(sro_cg, instr) - SLOI : `SAMPLE(sloi_cg, instr) - SROI : `SAMPLE(sroi_cg, instr) - ROR : `SAMPLE(ror_cg, instr) - ROL : `SAMPLE(rol_cg, instr) - RORI : `SAMPLE(rori_cg, instr) - GREV : `SAMPLE(grev_cg, instr) - GREVI : `SAMPLE(grevi_cg, instr) - SHFLI : `SAMPLE(shfli_cg, instr) - UNSHFLI : `SAMPLE(unshfli_cg, instr) - SHFL : `SAMPLE(shfl_cg, instr) - UNSHFL : `SAMPLE(unshfl_cg, instr) - GORC : `SAMPLE(gorc_cg, instr) - GORCI : `SAMPLE(gorci_cg, instr) - BFP : `SAMPLE(bfp_cg, instr) - BEXT : `SAMPLE(bext_cg, instr) - BDEP : `SAMPLE(bdep_cg, instr) - CLMUL : `SAMPLE(clmul_cg, instr) - CLMULH : `SAMPLE(clmulh_cg, instr) - CLMULR : `SAMPLE(clmulr_cg, instr) - CRC32_B : `SAMPLE(crc32_b_cg, instr) - CRC32_H : `SAMPLE(crc32_h_cg, instr) - CRC32_W : `SAMPLE(crc32_w_cg, instr) - CRC32C_B : `SAMPLE(crc32c_b_cg, instr) - CRC32C_H : `SAMPLE(crc32c_h_cg, instr) - CRC32C_W : `SAMPLE(crc32c_w_cg, instr) - CMIX : `SAMPLE(cmix_cg, instr) - CMOV : `SAMPLE(cmov_cg, instr) - FSL : `SAMPLE(fsl_cg, instr) - FSR : `SAMPLE(fsr_cg, instr) - FSRI : `SAMPLE(fsri_cg, instr) + CLZ : `SAMPLE_B(clz_cg, instr) + CTZ : `SAMPLE_B(ctz_cg, instr) + PCNT : `SAMPLE_B(pcnt_cg, instr) + ANDN : `SAMPLE_B(andn_cg, instr) + ORN : `SAMPLE_B(orn_cg, instr) + XNOR : `SAMPLE_B(xnor_cg, instr) + PACK : `SAMPLE_B(pack_cg, instr) + PACKH : `SAMPLE_B(packh_cg, instr) + MIN : `SAMPLE_B(min_cg, instr) + MAX : `SAMPLE_B(max_cg, instr) + MINU : `SAMPLE_B(minu_cg, instr) + MAXU : `SAMPLE_B(maxu_cg, instr) + SEXT_B : `SAMPLE_B(sext_b_cg, instr) + SEXT_H : `SAMPLE_B(sext_h_cg, instr) + SBSET : `SAMPLE_B(sbset_cg, instr) + SBCLR : `SAMPLE_B(sbclr_cg, instr) + SBINV : `SAMPLE_B(sbinv_cg, instr) + SBEXT : `SAMPLE_B(sbext_cg, instr) + SBSETI : `SAMPLE_B(sbseti_cg, instr) + SBCLRI : `SAMPLE_B(sbclri_cg, instr) + SBINVI : `SAMPLE_B(sbinvi_cg, instr) + SBEXTI : `SAMPLE_B(sbexti_cg, instr) + SLO : `SAMPLE_B(slo_cg, instr) + SRO : `SAMPLE_B(sro_cg, instr) + SLOI : `SAMPLE_B(sloi_cg, instr) + SROI : `SAMPLE_B(sroi_cg, instr) + ROR : `SAMPLE_B(ror_cg, instr) + ROL : `SAMPLE_B(rol_cg, instr) + RORI : `SAMPLE_B(rori_cg, instr) + GREV : `SAMPLE_B(grev_cg, instr) + GREVI : `SAMPLE_B(grevi_cg, instr) + SHFLI : `SAMPLE_B(shfli_cg, instr) + UNSHFLI : `SAMPLE_B(unshfli_cg, instr) + SHFL : `SAMPLE_B(shfl_cg, instr) + UNSHFL : `SAMPLE_B(unshfl_cg, instr) + GORC : `SAMPLE_B(gorc_cg, instr) + GORCI : `SAMPLE_B(gorci_cg, instr) + BFP : `SAMPLE_B(bfp_cg, instr) + BEXT : `SAMPLE_B(bext_cg, instr) + BDEP : `SAMPLE_B(bdep_cg, instr) + CLMUL : `SAMPLE_B(clmul_cg, instr) + CLMULH : `SAMPLE_B(clmulh_cg, instr) + CLMULR : `SAMPLE_B(clmulr_cg, instr) + CRC32_B : `SAMPLE_B(crc32_b_cg, instr) + CRC32_H : `SAMPLE_B(crc32_h_cg, instr) + CRC32_W : `SAMPLE_B(crc32_w_cg, instr) + CRC32C_B : `SAMPLE_B(crc32c_b_cg, instr) + CRC32C_H : `SAMPLE_B(crc32c_h_cg, instr) + CRC32C_W : `SAMPLE_B(crc32c_w_cg, instr) + CMIX : `SAMPLE_B(cmix_cg, instr) + CMOV : `SAMPLE_B(cmov_cg, instr) + FSL : `SAMPLE_B(fsl_cg, instr) + FSR : `SAMPLE_B(fsr_cg, instr) + FSRI : `SAMPLE_B(fsri_cg, instr) // RV64B - CLZW : `SAMPLE(clzw_cg, instr) - CTZW : `SAMPLE(ctzw_cg, instr) - PCNTW : `SAMPLE(pcntw_cg, instr) - PACKW : `SAMPLE(packw_cg, instr) - PACKUW : `SAMPLE(packuw_cg, instr) - SLOW : `SAMPLE(slow_cg, instr) - SROW : `SAMPLE(srow_cg, instr) - SLOIW : `SAMPLE(sloiw_cg, instr) - SROIW : `SAMPLE(sroiw_cg, instr) - RORW : `SAMPLE(rorw_cg, instr) - ROLW : `SAMPLE(rolw_cg, instr) - RORIW : `SAMPLE(roriw_cg, instr) - GREVW : `SAMPLE(grevw_cg, instr) - GREVIW : `SAMPLE(greviw_cg, instr) - SHFLW : `SAMPLE(shflw_cg, instr) - UNSHFLW : `SAMPLE(unshflw_cg, instr) - GORCW : `SAMPLE(gorcw_cg, instr) - GORCIW : `SAMPLE(gorciw_cg, instr) - BFPW : `SAMPLE(bfpw_cg, instr) - BEXTW : `SAMPLE(bextw_cg, instr) - BDEPW : `SAMPLE(bdepw_cg, instr) - CLMULW : `SAMPLE(clmulw_cg, instr) - CLMULHW : `SAMPLE(clmulhw_cg, instr) - CLMULRW : `SAMPLE(clmulrw_cg, instr) - CRC32_D : `SAMPLE(crc32_d_cg, instr) - CRC32C_D : `SAMPLE(crc32c_d_cg, instr) - BMATOR : `SAMPLE(bmator_cg, instr) - BMATXOR : `SAMPLE(bmatxor_cg, instr) - BMATFLIP : `SAMPLE(bmatflip_cg, instr) - FSLW : `SAMPLE(fslw_cg, instr) - FSRW : `SAMPLE(fsrw_cg, instr) - FSRIW : `SAMPLE(fsriw_cg, instr) - ADDWU : `SAMPLE(addwu_cg, instr) - SUBWU : `SAMPLE(subwu_cg, instr) - ADDIWU : `SAMPLE(addiwu_cg, instr) - ADDU_W : `SAMPLE(addu_w_cg, instr) - SUBU_W : `SAMPLE(subu_w_cg, instr) - SLLIU_W : `SAMPLE(slliu_w_cg, instr) + CLZW : `SAMPLE_B(clzw_cg, instr) + CTZW : `SAMPLE_B(ctzw_cg, instr) + PCNTW : `SAMPLE_B(pcntw_cg, instr) + PACKW : `SAMPLE_B(packw_cg, instr) + PACKUW : `SAMPLE_B(packuw_cg, instr) + SLOW : `SAMPLE_B(slow_cg, instr) + SROW : `SAMPLE_B(srow_cg, instr) + SLOIW : `SAMPLE_B(sloiw_cg, instr) + SROIW : `SAMPLE_B(sroiw_cg, instr) + RORW : `SAMPLE_B(rorw_cg, instr) + ROLW : `SAMPLE_B(rolw_cg, instr) + RORIW : `SAMPLE_B(roriw_cg, instr) + GREVW : `SAMPLE_B(grevw_cg, instr) + GREVIW : `SAMPLE_B(greviw_cg, instr) + SHFLW : `SAMPLE_B(shflw_cg, instr) + UNSHFLW : `SAMPLE_B(unshflw_cg, instr) + GORCW : `SAMPLE_B(gorcw_cg, instr) + GORCIW : `SAMPLE_B(gorciw_cg, instr) + BFPW : `SAMPLE_B(bfpw_cg, instr) + BEXTW : `SAMPLE_B(bextw_cg, instr) + BDEPW : `SAMPLE_B(bdepw_cg, instr) + CLMULW : `SAMPLE_B(clmulw_cg, instr) + CLMULHW : `SAMPLE_B(clmulhw_cg, instr) + CLMULRW : `SAMPLE_B(clmulrw_cg, instr) + CRC32_D : `SAMPLE_B(crc32_d_cg, instr) + CRC32C_D : `SAMPLE_B(crc32c_d_cg, instr) + BMATOR : `SAMPLE_B(bmator_cg, instr) + BMATXOR : `SAMPLE_B(bmatxor_cg, instr) + BMATFLIP : `SAMPLE_B(bmatflip_cg, instr) + FSLW : `SAMPLE_B(fslw_cg, instr) + FSRW : `SAMPLE_B(fsrw_cg, instr) + FSRIW : `SAMPLE_B(fsriw_cg, instr) + ADDWU : `SAMPLE_B(addwu_cg, instr) + SUBWU : `SAMPLE_B(subwu_cg, instr) + ADDIWU : `SAMPLE_B(addiwu_cg, instr) + ADDU_W : `SAMPLE_B(addu_w_cg, instr) + SUBU_W : `SAMPLE_B(subu_w_cg, instr) + SLLIU_W : `SAMPLE_B(slliu_w_cg, instr) `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv") default: begin if (instr.group == RV32I) begin diff --git a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv index f9541749..ea3460da 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv @@ -245,7 +245,8 @@ class riscv_instr_gen_config extends uvm_object; bit enable_vector_extension; // Bit manipulation extension support bit enable_b_extension; - b_ext_group_t enable_bitmanip_groups[] = {ZBB, ZBS, ZBP, ZBE, ZBF, ZBC, ZBR, ZBM, ZBT}; + b_ext_group_t enable_bitmanip_groups[] = {ZBB, ZBS, ZBP, ZBE, ZBF, ZBC, ZBR, ZBM, ZBT, + ZB_TMP}; //----------------------------------------------------------------------------- // Command line options for instruction distribution control diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index 3b35521e..c60dd574 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -1111,7 +1111,8 @@ package riscv_instr_pkg; ZBC, ZBR, ZBM, - ZBT + ZBT, + ZB_TMP // for uncategorized instructions } b_ext_group_t; `VECTOR_INCLUDE("riscv_instr_pkg_inc_variables.sv") @@ -1298,6 +1299,28 @@ package riscv_instr_pkg; SYNCH, SYSTEM, COUNTER, CSR, CHANGELEVEL, TRAP, INTERRUPT, AMO }; + function automatic void get_val(input string str, output bit [XLEN-1:0] val, input hex = 0); + if (str.len() > 2) begin + if (str.substr(0, 1) == "0x") begin + str = str.substr(2, str.len() -1); + val = str.atohex(); + return; + end + end + if (hex) begin + val = str.atohex(); + end else begin + if (str.substr(0, 0) == "-") begin + str = str.substr(1, str.len() - 1); + val = -str.atoi(); + end else begin + val = str.atoi(); + end + end + `uvm_info("riscv_instr_pkg", $sformatf("imm:%0s -> 0x%0x/%0d", str, val, $signed(val)), + UVM_FULL) + endfunction : get_val + `include "riscv_vector_cfg.sv" `include "riscv_pmp_cfg.sv" typedef class riscv_instr; @@ -1352,7 +1375,6 @@ package riscv_instr_pkg; `include "riscv_instr_sequence.sv" `include "riscv_asm_program_gen.sv" `include "riscv_debug_rom_gen.sv" - `include "riscv_instr_cov_item.sv" `include "riscv_instr_cover_group.sv" `include "user_extension.svh" diff --git a/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv b/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv index 1de70deb..fb0fa20b 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv @@ -2,20 +2,15 @@ class riscv_instr_cov_test extends uvm_test; typedef uvm_enum_wrapper#(riscv_instr_name_t) instr_enum; - typedef uvm_enum_wrapper#(riscv_reg_t) gpr_enum; - typedef uvm_enum_wrapper#(riscv_fpr_t) fpr_enum; - typedef uvm_enum_wrapper#(privileged_reg_t) preg_enum; riscv_instr_gen_config cfg; riscv_instr_cover_group instr_cg; - riscv_instr_cov_item instr; string trace_csv[$]; string trace[string]; int unsigned entry_cnt; int unsigned total_entry_cnt; int unsigned skipped_cnt; int unsigned unexpected_illegal_instr_cnt; - bit [XLEN-1:0] gpr_state[string]; `uvm_component_utils(riscv_instr_cov_test) `uvm_component_new @@ -41,8 +36,6 @@ class riscv_instr_cov_test extends uvm_test; // disable_compressed_instr is not relevant to coverage test cfg.disable_compressed_instr = 0; riscv_instr::create_instr_list(cfg); - instr = riscv_instr_cov_item::type_id::create("instr"); - instr.rand_mode(0); instr_cg = new(cfg); `uvm_info(`gfn, $sformatf("%0d CSV trace files to be processed", trace_csv.size()), UVM_LOW) foreach (trace_csv[i]) begin @@ -136,7 +129,8 @@ class riscv_instr_cov_test extends uvm_test; end if (instr_enum::from_name(process_instr_name(trace["instr"]), instr_name)) begin if (riscv_instr::instr_template.exists(instr_name)) begin - instr.copy(riscv_instr::instr_template[instr_name]); + riscv_instr instr; + instr = riscv_instr::get_instr(instr_name); if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C, RV32F, RV32B, RV64B}) begin assign_trace_info_to_instr(instr); @@ -150,12 +144,11 @@ class riscv_instr_cov_test extends uvm_test; process_instr_name(trace["instr"])), UVM_LOW) endfunction - virtual function void assign_trace_info_to_instr(riscv_instr_cov_item instr); + virtual function void assign_trace_info_to_instr(riscv_instr instr); riscv_reg_t gpr; string operands[$]; string gpr_update[$]; string pair[$]; - privileged_reg_t preg; get_val(trace["pc"], instr.pc, .hex(1)); get_val(trace["binary"], instr.binary, .hex(1)); instr.trace = trace["instr_str"]; @@ -163,262 +156,20 @@ class riscv_instr_cov_test extends uvm_test; ECALL, C_NOP, MRET, SRET, URET}) begin return; end - split_string(trace["operand"], ",", operands); - case(instr.format) - J_FORMAT, U_FORMAT : begin - // instr rd,imm - `DV_CHECK_FATAL(operands.size() == 2) - get_val(operands[1], instr.imm); - end - I_FORMAT: begin - // TODO, support I_FORMAT floating point later - if (instr.group == RV32F) return; - if (instr.instr_name inside {FSRI, FSRIW}) begin - `DV_CHECK_FATAL(operands.size() == 4, trace["instr_str"]) - end else begin - `DV_CHECK_FATAL(operands.size() == 3, trace["instr_str"]) - end - if(instr.category == LOAD) begin - // load rd, imm(rs1) - instr.rs1 = get_gpr(operands[2]); - instr.rs1_value = get_gpr_state(operands[2]); - get_val(operands[1], instr.imm); - end else if(instr.category == CSR) begin - // csrrwi rd, csr, imm - get_val(operands[2], instr.imm); - if (preg_enum::from_name(operands[1].toupper(), preg)) begin - instr.csr = preg; - end else begin - get_val(operands[1], instr.csr); - end - end else if (instr.instr_name inside {FSRI, FSRIW}) begin - // fsri rd, rs1, rs3, imm - instr.rs1 = get_gpr(operands[1]); - instr.rs1_value = get_gpr_state(operands[1]); - instr.rs3 = get_gpr(operands[2]); - instr.rs3_value = get_gpr_state(operands[2]); - get_val(operands[3], instr.imm); - end else begin - // addi rd, rs1, imm - instr.rs1 = get_gpr(operands[1]); - instr.rs1_value = get_gpr_state(operands[1]); - get_val(operands[2], instr.imm); - end - end - S_FORMAT, B_FORMAT: begin - `DV_CHECK_FATAL(operands.size() == 3) - if(instr.category == STORE) begin - // sw rs2,imm(rs1) - update_instr_reg_by_abi_name(operands[0], // FSW rs2 is fp - instr.rs2, instr.rs2_value, - instr.fs2, instr.fs2_value); - instr.rs1 = get_gpr(operands[2]); - instr.rs1_value = get_gpr_state(operands[2]); - get_val(operands[1], instr.imm); - end else begin - // bne rs1, rs2, imm - instr.rs1 = get_gpr(operands[0]); - instr.rs1_value = get_gpr_state(operands[0]); - instr.rs2 = get_gpr(operands[1]); - instr.rs2_value = get_gpr_state(operands[1]); - get_val(operands[2], instr.imm); - end - end - R_FORMAT: begin - if ((instr.has_rs2 || instr.category == CSR) && - !(instr.instr_name inside {FCLASS_S, FCLASS_D})) begin - `DV_CHECK_FATAL(operands.size() == 3) - end else begin - `DV_CHECK_FATAL(operands.size() == 2) - end - if(instr.category == CSR) begin - // csrrw rd, csr, rs1 - if (preg_enum::from_name(operands[1].toupper(), preg)) begin - instr.csr = preg; - end else begin - get_val(operands[1], instr.csr); - end - instr.rs1 = get_gpr(operands[2]); - instr.rs1_value = get_gpr_state(operands[2]); - end - else if (instr.group inside {RV32F, RV64F, RV32D, RV64D}) begin - // fs1 - instr.fs1 = get_fpr(operands[1]); - instr.fs1_value = get_gpr_state(operands[1]); - // fs2 - if (!instr.instr_name inside {FCLASS_S, FCLASS_D}) begin - instr.fs2 = get_fpr(operands[2]); - instr.fs2_value = get_gpr_state(operands[2]); - end - end else begin - // add rd, rs1, rs2 - instr.rs1 = get_gpr(operands[1]); - instr.rs1_value = get_gpr_state(operands[1]); - if (instr.has_rs2) begin - instr.rs2 = get_gpr(operands[2]); - instr.rs2_value = get_gpr_state(operands[2]); - end - end - end - R4_FORMAT: begin - `DV_CHECK_FATAL(operands.size() == 4) - update_instr_reg_by_abi_name(operands[1], - instr.rs1, instr.rs1_value, - instr.fs1, instr.fs1_value); - update_instr_reg_by_abi_name(operands[2], - instr.rs2, instr.rs2_value, - instr.fs2, instr.fs2_value); - update_instr_reg_by_abi_name(operands[3], - instr.rs3, instr.rs3_value, - instr.fs3, instr.fs3_value); - end - CI_FORMAT, CIW_FORMAT: begin - if (instr.instr_name == C_ADDI16SP) begin - get_val(operands[1], instr.imm); - instr.rs1 = SP; - instr.rs1_value = get_gpr_state("sp"); - end else if (instr.instr_name == C_ADDI4SPN) begin - instr.rs1 = SP; - instr.rs1_value = get_gpr_state("sp"); - end else if (instr.instr_name inside {C_LDSP, C_LWSP, C_LQSP}) begin - // c.ldsp rd, imm - get_val(operands[1], instr.imm); - instr.rs1 = SP; - instr.rs1_value = get_gpr_state("sp"); - end else begin - // c.lui rd, imm - get_val(operands[1], instr.imm); - end - end - CL_FORMAT: begin - // c.lw rd, imm(rs1) - get_val(operands[1], instr.imm); - instr.rs1 = get_gpr(operands[2]); - instr.rs1_value = get_gpr_state(operands[2]); - end - CS_FORMAT: begin - // c.sw rs2,imm(rs1) - instr.rs2 = get_gpr(operands[0]); - instr.rs2_value = get_gpr_state(operands[0]); - instr.rs1 = get_gpr(operands[2]); - instr.rs1_value = get_gpr_state(operands[2]); - get_val(operands[1], instr.imm); - end - CA_FORMAT: begin - // c.and rd, rs2 (rs1 == rd) - instr.rs2 = get_gpr(operands[1]); - instr.rs2_value = get_gpr_state(operands[1]); - instr.rs1 = get_gpr(operands[0]); - instr.rs1_value = get_gpr_state(operands[0]); - end - CB_FORMAT: begin - // c.beqz rs1, imm - instr.rs1 = get_gpr(operands[0]); - instr.rs1_value = get_gpr_state(operands[0]); - get_val(operands[1], instr.imm); - end - CSS_FORMAT: begin - // c.swsp rs2, imm - instr.rs2 = get_gpr(operands[0]); - instr.rs2_value = get_gpr_state(operands[0]); - instr.rs1 = SP; - instr.rs1_value = get_gpr_state("sp"); - get_val(operands[1], instr.imm); - end - CR_FORMAT: begin - if (instr.instr_name inside {C_JR, C_JALR}) begin - // c.jalr rs1 - instr.rs1 = get_gpr(operands[0]); - instr.rs1_value = get_gpr_state(operands[0]); - end else begin - // c.add rd, rs2 - instr.rs2 = get_gpr(operands[1]); - instr.rs2_value = get_gpr_state(operands[1]); - end - end - CJ_FORMAT: begin - // c.j imm - get_val(operands[0], instr.imm); - end - endcase + split_string(trace["operand"], ",", operands); + instr.update_src_regs(operands); + split_string(trace["gpr"], ";", gpr_update); foreach (gpr_update[i]) begin split_string(gpr_update[i], ":", pair); if (pair.size() != 2) begin `uvm_fatal(`gfn, $sformatf("Illegal gpr update format: %0s", gpr_update[i])) end - get_val(pair[1], gpr_state[pair[0]], .hex(1)); - update_instr_reg_by_abi_name(pair[0], instr.rd, instr.rd_value, instr.fd, instr.fd_value); + instr.update_dst_regs(pair[0], pair[1]); end endfunction : assign_trace_info_to_instr - function riscv_reg_t get_gpr(input string str); - str = str.toupper(); - if (!gpr_enum::from_name(str, get_gpr)) begin - `uvm_fatal(`gfn, $sformatf("Cannot convert %0s to GPR", str)) - end - endfunction : get_gpr - - function riscv_fpr_t get_fpr(input string str); - str = str.toupper(); - if (!fpr_enum::from_name(str, get_fpr)) begin - `uvm_fatal(`gfn, $sformatf("Cannot convert %0s to FPR", str)) - end - endfunction : get_fpr - - function bit [XLEN-1:0] get_gpr_state(string name); - if (name inside {"zero", "x0"}) begin - return 0; - end else if (gpr_state.exists(name)) begin - return gpr_state[name]; - end else begin - `uvm_warning(`gfn, $sformatf("Cannot find GPR state: %0s", name)) - return 0; - end - endfunction : get_gpr_state - - function void get_val(input string str, output bit [XLEN-1:0] val, input hex = 0); - if (str.len() > 2) begin - if (str.substr(0, 1) == "0x") begin - str = str.substr(2, str.len() -1); - val = str.atohex(); - return; - end - end - if (hex) begin - val = str.atohex(); - end else begin - if (str.substr(0, 0) == "-") begin - str = str.substr(1, str.len() - 1); - val = -str.atoi(); - end else begin - val = str.atoi(); - end - end - `uvm_info(`gfn, $sformatf("imm:%0s -> 0x%0x/%0d", str, val, $signed(val)), UVM_FULL) - endfunction : get_val - - function bit is_fp_reg(input string str); - riscv_fpr_t tmp; - str = str.toupper(); - return fpr_enum::from_name(str, tmp); - endfunction : is_fp_reg - - function void update_instr_reg_by_abi_name(string abi_name, - ref riscv_reg_t rs, - ref bit [XLEN-1:0] rs_value, - ref riscv_fpr_t fs, - ref bit [XLEN-1:0] fs_value); - if (is_fp_reg(abi_name)) begin - fs = get_fpr(abi_name); - fs_value = get_gpr_state(abi_name); - end else begin - rs = get_gpr(abi_name); - rs_value = get_gpr_state(abi_name); - end - endfunction : update_instr_reg_by_abi_name - function string process_instr_name(string instr_name); instr_name = instr_name.toupper(); foreach (instr_name[i]) begin diff --git a/vendor/google_riscv-dv/verilog_style/exclude_filelist.f b/vendor/google_riscv-dv/verilog_style/exclude_filelist.f index 44b86802..b065ea37 100644 --- a/vendor/google_riscv-dv/verilog_style/exclude_filelist.f +++ b/vendor/google_riscv-dv/verilog_style/exclude_filelist.f @@ -5,3 +5,4 @@ riscv_instr_cover_group.sv riscv_instr_pkg.sv # tool does not support included file very well. Issue at github.com/google/verible/issues/178 riscv_custom_instr_enum.sv +isa/riscv_instr_cov.svh