diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index d1152a11..3ede25cd 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: a655f34eb5058da442b38ca010b0d008291c11b5 + rev: f7e35d7939a27ae17b0481eb070e9a36ea335d1f } } diff --git a/vendor/google_riscv-dv/docs/source/getting_started.rst b/vendor/google_riscv-dv/docs/source/getting_started.rst index d2582f91..a53a183e 100644 --- a/vendor/google_riscv-dv/docs/source/getting_started.rst +++ b/vendor/google_riscv-dv/docs/source/getting_started.rst @@ -179,21 +179,24 @@ real RISC-V processor:: run --test=riscv_rand_instr_test --iss=ovpsim,whisper run --test=riscv_rand_instr_test --iss=spike,sail -Run directed assembly tests +Run directed assembly/C tests --------------------------- -Sometimes it might be useful to run some hand-coded assembly tests to hit some +Sometimes it might be useful to run some hand-coded assembly/C tests to hit some corner cases:: - # Run a single/multiple assembly test + # Run a single/multiple assembly/C test run --asm_tests asm_test_path1/asm_test1.S,asm_test_path2/asm_test2.S + run --c_tests c_test_path1/c_test1.c,c_test_path2/c_test2.c - # Run regression with all assembly tests(*.S) under a given directory + # Run regression with all assembly tests(*.S)/ C tests(*.c) under a given directory run --asm_tests asm_test_path1,asm_test_path2 + run --c_tests c_test_path1,c_test_path2 - # Run mix between the assembly test and assembly tests under a directory + # Run mix between the assembly/C test and assembly/C tests under a directory run --asm_tests asm_test_path1/asm_test1.S,asm_test_path2 + run --c_tests c_test_path1/c_test1.c,c_test_path2 -You could also use this approach to integrate the assembly tests +You could also use this approach to integrate the assembly/C tests from other sources to riscv-dv flow. diff --git a/vendor/google_riscv-dv/qrun_option.f b/vendor/google_riscv-dv/qrun_option.f index bd1de096..0d2998d3 100644 --- a/vendor/google_riscv-dv/qrun_option.f +++ b/vendor/google_riscv-dv/qrun_option.f @@ -1,6 +1,7 @@ -64 -uvmhome uvm-1.2 -sv +-access=rwc+/. -mfcu -cuname design_cuname +define+UVM_REGEX_NO_DPI diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index 8cc6fb4f..7fcdbfec 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -133,6 +133,7 @@ def get_iss_cmd(base_cmd, elf, log): cmd += (" &> %s" % log) return cmd + def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, cmp_opts, output_dir, debug_cmd): """Compile the instruction generator @@ -162,6 +163,7 @@ def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, logging.debug("Compile command: %s" % cmd) run_cmd(cmd, debug_cmd = debug_cmd) + def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, end_signature_addr, timeout_s, output_dir, debug_cmd): """Run CSR test @@ -179,6 +181,7 @@ def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, else: run_cmd(cmd, timeout_s, debug_cmd = debug_cmd) + def do_simulate(sim_cmd, test_list, cwd, sim_opts, seed_yaml, seed, csr_file, isa, end_signature_addr, lsf_cmd, timeout_s, log_suffix, batch_size, output_dir, verbose, check_return_code, debug_cmd): @@ -411,6 +414,7 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, if len(iss_list) == 2: compare_iss_log(iss_list, log_list, report) + def run_assembly_from_dir(asm_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, output_dir, setting_dir, debug_cmd): """Run a directed assembly test from a directory with spike @@ -440,6 +444,7 @@ def run_assembly_from_dir(asm_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, else: logging.error("No assembly test(*.S) found under %s" % asm_test_dir) + def run_c(c_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, setting_dir, debug_cmd): """Run a directed c test with ISS @@ -498,9 +503,10 @@ def run_c(c_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, if len(iss_list) == 2: compare_iss_log(iss_list, log_list, report) + def run_c_from_dir(c_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, output_dir, setting_dir, debug_cmd): - """Run a directed assembly test from a directory with spike + """Run a directed c test from a directory with spike Args: c_test_dir : C test file directory @@ -527,6 +533,7 @@ def run_c_from_dir(c_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, else: logging.error("No c test(*.c) found under %s" % c_test_dir) + def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, setting_dir, timeout_s, debug_cmd): """Run ISS simulation with the generated test program @@ -593,6 +600,7 @@ def iss_cmp(test_list, iss, output_dir, stop_on_first_error, exp, debug_cmd): compare_iss_log(iss_list, log_list, report, stop_on_first_error, exp) save_regr_report(report) + def compare_iss_log(iss_list, log_list, report, stop_on_first_error=0, exp=False): if (len(iss_list) != 2 or len(log_list) != 2) : logging.error("Only support comparing two ISS logs") @@ -716,6 +724,7 @@ def setup_parser(): help="Generate debug command log file") return parser + def load_config(args, cwd): """ Load configuration from the command line and the configuration file. @@ -777,6 +786,7 @@ def load_config(args, cwd): cfg = vars(args) return cfg + def main(): """This is the main entry point.""" try: @@ -832,27 +842,38 @@ def main(): # Process regression test list matched_list = [] # Any tests in the YAML test list that specify a directed assembly test - directed_list = [] + asm_directed_list = [] + # Any tests in the YAML test list that specify a directed c test + c_directed_list = [] if not args.co: process_regression_list(args.testlist, args.test, args.iterations, matched_list, cwd) for t in list(matched_list): + # Check mutual exclusive between gen_test, asm_tests, and c_tests if 'asm_tests' in t: - if 'gen_test' in t: - logging.error('asm_test must not be defined in the testlist ' - 'together with the gen_test field') + if 'gen_test' in t or 'c_tests' in t: + logging.error('asm_tests must not be defined in the testlist ' + 'together with the gen_test or c_tests field') sys.exit(RET_FATAL) - directed_list.append(t) + asm_directed_list.append(t) matched_list.remove(t) - if len(matched_list) == 0 and len(directed_list) == 0: + if 'c_tests' in t: + if 'gen_test' in t or 'asm_tests' in t: + logging.error('c_tests must not be defined in the testlist ' + 'together with the gen_test or asm_tests field') + sys.exit(RET_FATAL) + c_directed_list.append(t) + matched_list.remove(t) + + if len(matched_list) == 0 and len(asm_directed_list) == 0 and len(c_directed_list) == 0: sys.exit("Cannot find %s in %s" % (args.test, args.testlist)) # Run instruction generator if args.steps == "all" or re.match(".*gen.*", args.steps): # Run any handcoded/directed assembly tests specified in YAML format - if len(directed_list) != 0: - for test_entry in directed_list: + if len(asm_directed_list) != 0: + for test_entry in asm_directed_list: gcc_opts = args.gcc_opts gcc_opts += test_entry.get('gcc_opts', '') path_asm_test = os.path.expanduser(test_entry.get('asm_tests')) @@ -870,6 +891,28 @@ def main(): if not args.debug: logging.error('%s does not exist' % path_asm_test) sys.exit(RET_FAIL) + + # Run any handcoded/directed C tests specified in YAML format + if len(c_directed_list) != 0: + for test_entry in c_directed_list: + gcc_opts = args.gcc_opts + gcc_opts += test_entry.get('gcc_opts', '') + path_c_test = os.path.expanduser(test_entry.get('c_tests')) + if path_c_test: + # path_c_test is a directory + if os.path.isdir(path_c_test): + run_c_from_dir(path_c_test, args.iss_yaml, args.isa, args.mabi, + gcc_opts, args.iss, output_dir, + args.core_setting_dir, args.debug) + # path_c_test is a C file + elif os.path.isfile(path_c_test): + run_c(path_c_test, args.iss_yaml, args.isa, args.mabi, gcc_opts, + args.iss, output_dir, args.core_setting_dir, args.debug) + else: + if not args.debug: + logging.error('%s does not exist' % path_c_test) + sys.exit(RET_FAIL) + # Run remaining tests using the instruction generator gen(matched_list, cfg, output_dir, cwd) diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_amo_instr_lib.sv b/vendor/google_riscv-dv/src/deprecated/riscv_amo_instr_lib.sv deleted file mode 100644 index ba60035f..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_amo_instr_lib.sv +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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. - */ - -// Base class for AMO instruction stream -class riscv_amo_base_instr_stream extends riscv_mem_access_stream; - - rand int unsigned num_amo; - rand int unsigned num_mixed_instr; - rand int base; - rand riscv_reg_t rs1_reg; - rand int unsigned data_page_id; - rand int max_load_store_offset; - - // User can specify a small group of available registers to generate various hazard condition - rand riscv_reg_t avail_regs[]; - - `uvm_object_utils(riscv_amo_base_instr_stream) - - constraint rs1_c { - !(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO}); - } - - constraint addr_range_c { - data_page_id < max_data_page_id; - base inside {[0 : max_load_store_offset-1]}; - } - - constraint aligned_amo_c { - if (XLEN == 32) { - base % 4 == 0; - } else { - base % 8 == 0; - } - } - - function new(string name = ""); - super.new(name); - endfunction - - function void post_randomize(); - gen_amo_instr(); - // rs1 cannot be modified by other instructions - if(!(rs1_reg inside {reserved_rd})) begin - reserved_rd = {reserved_rd, rs1_reg}; - end - add_mixed_instr(num_mixed_instr); - add_rs1_init_la_instr(rs1_reg, data_page_id); - super.post_randomize(); - endfunction - - // AMO instruction generation - virtual function void gen_amo_instr(); - endfunction - -endclass - -// A pair of LR/SC instruction -class riscv_lr_sc_instr_stream extends riscv_amo_base_instr_stream; - - riscv_rand_instr lr_instr; - riscv_rand_instr sc_instr; - - constraint legal_c { - num_amo == 1; - num_mixed_instr inside {[0:15]}; - } - - `uvm_object_utils(riscv_lr_sc_instr_stream) - - function new(string name = ""); - super.new(name); - lr_instr = riscv_rand_instr::type_id::create("lr_instr"); - sc_instr = riscv_rand_instr::type_id::create("sc_instr"); - endfunction - - virtual function void gen_amo_instr(); - lr_instr.cfg = cfg; - sc_instr.cfg = cfg; - lr_instr.disable_a_extension_c.constraint_mode(0); - sc_instr.disable_a_extension_c.constraint_mode(0); - `DV_CHECK_RANDOMIZE_WITH_FATAL(lr_instr, - rs1 == rs1_reg; - rd != rs1_reg; - instr_name inside {LR_W, LR_D};) - `DV_CHECK_RANDOMIZE_WITH_FATAL(sc_instr, - rs1 == rs1_reg; - rd != rs1_reg; - instr_name inside {SC_W, SC_D};) - instr_list.push_front(lr_instr); - instr_list.push_front(sc_instr); - endfunction - -endclass - -class riscv_amo_instr_stream extends riscv_amo_base_instr_stream; - - riscv_rand_instr amo_instr[]; - - constraint reasonable_c { - solve num_amo before num_mixed_instr; - num_amo inside {[1:10]}; - num_mixed_instr inside {[0:2*num_amo]}; - } - - `uvm_object_utils(riscv_amo_instr_stream) - `uvm_object_new - - virtual function void gen_amo_instr(); - amo_instr = new[num_amo]; - foreach (amo_instr[i]) begin - amo_instr[i] = riscv_rand_instr::type_id::create($sformatf("amo_instr_%0d", i)); - amo_instr[i].cfg = cfg; - amo_instr[i].disable_a_extension_c.constraint_mode(0); - `ifdef DSIM - `DV_CHECK_RANDOMIZE_WITH_FATAL(amo_instr[i], - rs1 == rs1_reg; - rd != rs1_reg; - instr_name inside {[AMOSWAP_W:AMOMAXU_D]};) - `else - `DV_CHECK_RANDOMIZE_WITH_FATAL(amo_instr[i], - rs1 == rs1_reg; - rd != rs1_reg; - category == AMO;) - `endif - instr_list.push_front(amo_instr[i]); - end - endfunction - -endclass diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_directed_instr_lib.sv b/vendor/google_riscv-dv/src/deprecated/riscv_directed_instr_lib.sv deleted file mode 100644 index 30a5343e..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_directed_instr_lib.sv +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright 2018 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. - */ - -// Base class for directed instruction stream -class riscv_directed_instr_stream extends riscv_rand_instr_stream; - - `uvm_object_utils(riscv_directed_instr_stream) - - string label; - - function new(string name = ""); - super.new(name); - endfunction - - function void post_randomize(); - foreach(instr_list[i]) begin - instr_list[i].has_label = 1'b0; - instr_list[i].atomic = 1'b1; - end - instr_list[0].comment = $sformatf("Start %0s", get_name()); - instr_list[$].comment = $sformatf("End %0s", get_name()); - if(label!= "") begin - instr_list[0].label = label; - instr_list[0].has_label = 1'b1; - end - endfunction - -endclass - -// Base class for memory access stream -class riscv_mem_access_stream extends riscv_directed_instr_stream; - - int max_data_page_id; - mem_region_t data_page[$]; - - `uvm_object_utils(riscv_mem_access_stream) - `uvm_object_new - - function void pre_randomize(); - if(kernel_mode) begin - data_page = cfg.s_mem_region; - end else begin - data_page = cfg.mem_region; - end - max_data_page_id = data_page.size(); - endfunction - - // Use "la" instruction to initialize the base regiseter - virtual function void add_rs1_init_la_instr(riscv_reg_t gpr, int id, int base = 0); - riscv_pseudo_instr la_instr; - la_instr = riscv_pseudo_instr::type_id::create("la_instr"); - la_instr.pseudo_instr_name = LA; - la_instr.rd = gpr; - if(kernel_mode) begin - la_instr.imm_str = $sformatf("%s+%0d", cfg.s_mem_region[id].name, base); - end else begin - la_instr.imm_str = $sformatf("%s+%0d", cfg.mem_region[id].name, base); - end - instr_list.push_front(la_instr); - endfunction - - // Insert some other instructions to mix with mem_access instruction - virtual function void add_mixed_instr(int instr_cnt); - riscv_instr_base instr; - setup_allowed_instr(1, 1); - for(int i = 0; i < instr_cnt; i ++) begin - instr = riscv_instr_base::type_id::create("instr"); - randomize_instr(instr); - insert_instr(instr); - end - endfunction - -endclass - -// Jump instruction (JAL, JALR) -// la rd0, jump_tagert_label -// addi rd1, offset, rd0 -// jalr rd, offset, rd1 -// For JAL, restore the stack before doing the jump -class riscv_jump_instr extends riscv_directed_instr_stream; - - riscv_instr_base jump; - riscv_instr_base addi; - riscv_pseudo_instr la; - riscv_instr_base branch; - rand riscv_reg_t gpr; - rand int imm; - rand bit enable_branch; - rand int mixed_instr_cnt; - riscv_instr_base stack_exit_instr[]; - string target_program_label; - int idx; - bit use_jalr; - - constraint instr_c { - !(gpr inside {cfg.reserved_regs, ZERO}); - imm inside {[-1023:1023]}; - mixed_instr_cnt inside {[5:10]}; - } - - `uvm_object_utils(riscv_jump_instr) - - function new(string name = ""); - super.new(name); - jump = riscv_instr_base::type_id::create("jump"); - la = riscv_pseudo_instr::type_id::create("la"); - addi = riscv_instr_base::type_id::create("addi"); - branch = riscv_instr_base::type_id::create("branch"); - endfunction - - function void post_randomize(); - riscv_instr_base instr[]; - `DV_CHECK_RANDOMIZE_WITH_FATAL(jump, - (use_jalr) -> (instr_name == JALR); - instr_name dist {JAL := 2, JALR := 6, C_JALR := 2}; - if (cfg.disable_compressed_instr || (cfg.ra != RA)) { - instr_name != C_JALR; - } - rd == cfg.ra; - rs1 == gpr; - ) - `DV_CHECK_RANDOMIZE_WITH_FATAL(addi, - rs1 == gpr; - instr_name == ADDI; - rd == gpr; - ) - `DV_CHECK_RANDOMIZE_WITH_FATAL(branch, - instr_name inside {BEQ, BNE, BLT, BGE, BLTU, BGEU};) - la.pseudo_instr_name = LA; - la.imm_str = target_program_label; - la.rd = gpr; - // Generate some random instructions to mix with jump instructions - reserved_rd = {gpr}; - initialize_instr_list(mixed_instr_cnt); - gen_instr(1'b1); - addi.imm_str = $sformatf("%0d", imm); - jump.imm_str = $sformatf("%0d", -imm); - // The branch instruction is always inserted right before the jump instruction to avoid - // skipping other required instructions like restore stack, load jump base etc. - // The purse of adding the branch instruction here is to cover branch -> jump scenario. - if(enable_branch) instr = {branch}; - // Restore stack before unconditional jump - if(jump.rd == ZERO) begin - instr= {stack_exit_instr, instr}; - end - if(jump.instr_name == JAL) begin - jump.imm_str = target_program_label; - end else if (jump.instr_name == C_JALR) begin - instr = {la, instr}; - end else begin - instr = {la, addi, instr}; - end - mix_instr_stream(instr); - instr_list = {instr_list, jump}; - foreach(instr_list[i]) begin - instr_list[i].has_label = 1'b0; - instr_list[i].atomic = 1'b1; - end - jump.has_label = 1'b1; - jump.label = $sformatf("j_%0s_%0s_%0d", label, target_program_label, idx); - branch.imm_str = jump.label; - branch.comment = "branch to jump instr"; - branch.branch_assigned = 1'b1; - endfunction -endclass - -// Stress back to back jump instruction -class riscv_jal_instr extends riscv_rand_instr_stream; - - riscv_instr_base jump[]; - riscv_instr_base jump_start; - riscv_instr_base jump_end; - rand int unsigned num_of_jump_instr; - riscv_instr_name_t jal[$]; - - constraint instr_c { - num_of_jump_instr inside {[10:30]}; - } - - `uvm_object_utils(riscv_jal_instr) - - function new(string name = ""); - super.new(name); - endfunction - - function void post_randomize(); - int order[]; - order = new[num_of_jump_instr]; - jump = new[num_of_jump_instr]; - foreach (order[i]) begin - order[i] = i; - end - order.shuffle(); - setup_allowed_instr(1, 1); - jal = {JAL}; - if (!cfg.disable_compressed_instr) begin - jal.push_back(C_J); - if (XLEN == 32) begin - jal.push_back(C_JAL); - end - end - // First instruction - jump_start = riscv_instr_base::type_id::create("jump_start"); - `DV_CHECK_RANDOMIZE_WITH_FATAL(jump_start, - instr_name == JAL; - rd == cfg.ra; - ) - jump_start.imm_str = $sformatf("%0df", order[0]); - jump_start.label = label; - // Last instruction - jump_end = riscv_instr_base::type_id::create("jump_end"); - randomize_instr(jump_end); - jump_end.label = $sformatf("%0d", num_of_jump_instr); - foreach (jump[i]) begin - jump[i] = riscv_instr_base::type_id::create($sformatf("jump_%0d", i)); - `DV_CHECK_RANDOMIZE_WITH_FATAL(jump[i], - instr_name inside {jal}; - rd dist {RA := 5, T1 := 2, [SP:T0] :/ 1, [T2:T6] :/ 2}; - !(rd inside {cfg.reserved_regs}); - ) - jump[i].label = $sformatf("%0d", i); - end - foreach (order[i]) begin - if (i == num_of_jump_instr - 1) begin - jump[order[i]].imm_str = $sformatf("%0df", num_of_jump_instr); - end else begin - if (order[i+1] > order[i]) begin - jump[order[i]].imm_str = $sformatf("%0df", order[i+1]); - end else begin - jump[order[i]].imm_str = $sformatf("%0db", order[i+1]); - end - end - end - instr_list = {jump_start, jump, jump_end}; - foreach (instr_list[i]) begin - instr_list[i].has_label = 1'b1; - instr_list[i].atomic = 1'b1; - end - endfunction -endclass - -// Push stack instruction stream -class riscv_push_stack_instr extends riscv_rand_instr_stream; - - int stack_len; - int num_of_reg_to_save; - int num_of_redudant_instr; - riscv_instr_base push_stack_instr[]; - riscv_reg_t saved_regs[]; - rand riscv_rand_instr branch_instr; - rand bit enable_branch; - string push_start_label; - - `uvm_object_utils(riscv_push_stack_instr) - - function new(string name = ""); - super.new(name); - endfunction - - function void init(); - // Save RA, T0 - reserved_rd = {cfg.ra}; - saved_regs = {cfg.ra}; - num_of_reg_to_save = saved_regs.size(); - if(num_of_reg_to_save * (XLEN/8) > stack_len) begin - `uvm_fatal(get_full_name(), $sformatf("stack len [%0d] is not enough to store %d regs", - stack_len, num_of_reg_to_save)) - end - num_of_redudant_instr = $urandom_range(3,10); - initialize_instr_list(num_of_redudant_instr); - endfunction - - virtual function void gen_push_stack_instr(int stack_len, bit allow_branch = 1); - this.stack_len = stack_len; - init(); - gen_instr(1'b1); - push_stack_instr = new[num_of_reg_to_save+1]; - foreach(push_stack_instr[i]) begin - push_stack_instr[i] = riscv_instr_base::type_id:: - create($sformatf("push_stack_instr_%0d", i)); - end - // addi sp,sp,-imm - `DV_CHECK_RANDOMIZE_WITH_FATAL(push_stack_instr[0], - instr_name == ADDI; rd == cfg.sp; rs1 == cfg.sp; - imm == (~stack_len + 1);) - push_stack_instr[0].imm_str = $sformatf("-%0d", stack_len); - foreach(saved_regs[i]) begin - if(XLEN == 32) begin - `DV_CHECK_RANDOMIZE_WITH_FATAL(push_stack_instr[i+1], - instr_name == SW; rs2 == saved_regs[i]; rs1 == cfg.sp; imm == 4 * (i+1);) - end else begin - `DV_CHECK_RANDOMIZE_WITH_FATAL(push_stack_instr[i+1], - instr_name == SD; rs2 == saved_regs[i]; rs1 == cfg.sp; imm == 8 * (i+1);) - end - push_stack_instr[i+1].process_load_store = 0; - end - if (allow_branch) begin - `DV_CHECK_STD_RANDOMIZE_FATAL(enable_branch) - end else begin - enable_branch = 0; - end - if(enable_branch) begin - // Cover jal -> branch scenario, the branch is added before push stack operation - branch_instr = riscv_rand_instr::type_id::create("branch_instr"); - branch_instr.cfg = cfg; - `ifdef DSIM - `DV_CHECK_RANDOMIZE_WITH_FATAL(branch_instr, - instr_name inside {[BEQ:BGEU], C_BEQZ, C_BNEZ};) - `else - `DV_CHECK_RANDOMIZE_WITH_FATAL(branch_instr, category == BRANCH;) - `endif - branch_instr.imm_str = push_start_label; - branch_instr.branch_assigned = 1'b1; - push_stack_instr[0].label = push_start_label; - push_stack_instr[0].has_label = 1'b1; - push_stack_instr = {branch_instr, push_stack_instr}; - end - mix_instr_stream(push_stack_instr); - foreach(instr_list[i]) begin - instr_list[i].atomic = 1'b1; - if(instr_list[i].label == "") - instr_list[i].has_label = 1'b0; - end - endfunction - -endclass - -// Pop stack instruction stream -class riscv_pop_stack_instr extends riscv_rand_instr_stream; - - int stack_len; - int num_of_reg_to_save; - int num_of_redudant_instr; - riscv_instr_base pop_stack_instr[]; - riscv_reg_t saved_regs[]; - - `uvm_object_utils(riscv_pop_stack_instr) - - function new(string name = ""); - super.new(name); - endfunction - - function void init(); - reserved_rd = {cfg.ra}; - num_of_reg_to_save = saved_regs.size(); - if(num_of_reg_to_save * 4 > stack_len) begin - `uvm_fatal(get_full_name(), $sformatf("stack len [%0d] is not enough to store %d regs", - stack_len, num_of_reg_to_save)) - end - num_of_redudant_instr = $urandom_range(3,10); - initialize_instr_list(num_of_redudant_instr); - endfunction - - virtual function void gen_pop_stack_instr(int stack_len, riscv_reg_t saved_regs[]); - this.stack_len = stack_len; - this.saved_regs = saved_regs; - init(); - gen_instr(1'b1); - pop_stack_instr = new[num_of_reg_to_save+1]; - foreach(pop_stack_instr[i]) begin - pop_stack_instr[i] = riscv_instr_base::type_id:: - create($sformatf("pop_stack_instr_%0d", i)); - end - foreach(saved_regs[i]) begin - if(XLEN == 32) begin - `DV_CHECK_RANDOMIZE_WITH_FATAL(pop_stack_instr[i], - instr_name == LW; rd == saved_regs[i]; rs1 == cfg.sp; imm == 4 * (i+1);) - end else begin - `DV_CHECK_RANDOMIZE_WITH_FATAL(pop_stack_instr[i], - instr_name == LD; rd == saved_regs[i]; rs1 == cfg.sp; imm == 8 * (i+1);) - end - pop_stack_instr[i].process_load_store = 0; - end - // addi sp,sp,imm - `DV_CHECK_RANDOMIZE_WITH_FATAL(pop_stack_instr[num_of_reg_to_save], - instr_name == ADDI; rd == cfg.sp; rs1 == cfg.sp; imm == stack_len;) - pop_stack_instr[num_of_reg_to_save].imm_str = $sformatf("%0d", stack_len); - mix_instr_stream(pop_stack_instr); - foreach(instr_list[i]) begin - instr_list[i].atomic = 1'b1; - instr_list[i].has_label = 1'b0; - end - endfunction - -endclass - -// Cover the long fprward and backward jump -class riscv_long_branch_instr extends riscv_rand_instr_stream; - - int branch_instr_stream_len = 100; - int branch_instr_offset = 999; - riscv_rand_instr_stream forward_branch_instr_stream; - riscv_rand_instr_stream backward_branch_instr_stream; - riscv_instr_base jump_instr; - - `uvm_object_utils(riscv_long_branch_instr) - - function new(string name = ""); - super.new(name); - forward_branch_instr_stream = riscv_rand_instr_stream::type_id:: - create("forward_branch_instr_stream"); - backward_branch_instr_stream = riscv_rand_instr_stream::type_id:: - create("backward_branch_instr_stream"); - jump_instr = riscv_instr_base::type_id::create("jump_instr"); - endfunction - - function void init(int instr_len); - branch_instr_stream_len = instr_len; - initialize_instr_list(branch_instr_offset-branch_instr_stream_len); - forward_branch_instr_stream.cfg = cfg; - backward_branch_instr_stream.cfg = cfg; - forward_branch_instr_stream.initialize_instr_list(branch_instr_stream_len); - backward_branch_instr_stream.initialize_instr_list(branch_instr_stream_len); - endfunction - - virtual function void gen_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1, - bit is_debug_program = 1'b0); - int branch_offset; - super.gen_instr(1'b1); - forward_branch_instr_stream.gen_instr(); - backward_branch_instr_stream.gen_instr(); - `DV_CHECK_RANDOMIZE_WITH_FATAL(jump_instr, instr_name == JAL;) - jump_instr.imm_str = "test_done"; - instr_list = {forward_branch_instr_stream.instr_list, instr_list, - jump_instr, backward_branch_instr_stream.instr_list}; - foreach(instr_list[i]) begin - instr_list[i].atomic = 1'b1; - if(!instr_list[i].is_branch_target) begin - instr_list[i].has_label = 1'b0; - end - if(instr_list[i].category == BRANCH) begin - if(i < branch_instr_stream_len) - branch_offset = branch_instr_offset; - else - branch_offset = -branch_instr_offset; - instr_list[i].imm_str = $sformatf("target_%0d", i); - instr_list[i].branch_assigned = 1'b1; - // Avoid dead loop - if(((instr_list[i+branch_offset].category == BRANCH) || - instr_list[i+branch_offset].is_branch_target) && (branch_offset < 0)) - branch_offset = branch_offset + 1; - `uvm_info(get_full_name(), $sformatf("Branch [%0d] %0s -> [%0d] %0s", i, - instr_list[i].convert2asm(), i+branch_offset, - instr_list[i+branch_offset].convert2asm()), UVM_LOW) - if(i < -branch_offset) - `uvm_fatal(get_name(), $sformatf("Unexpected branch instr at %0d", i)) - instr_list[i+branch_offset].label = $sformatf("target_%0d", i); - instr_list[i+branch_offset].has_label = 1'b1; - instr_list[i+branch_offset].is_branch_target = 1; - end - end - endfunction - -endclass - -class riscv_sw_interrupt_instr extends riscv_directed_instr_stream; - - rand bit usip; - rand bit ssip; - rand bit msip; - rand privileged_reg_t ip_reg; - rand riscv_pseudo_instr li_instr; - rand riscv_instr_base csr_instr; - riscv_privil_reg ip; - rand riscv_reg_t rs1_reg; - - constraint ip_reg_c { - if(cfg.init_privileged_mode == MACHINE_MODE) { - ip_reg == MIP; - } else { - ip_reg == SIP; - } - (ip_reg == MIP) -> (usip || ssip || msip); - (ip_reg == SIP) -> (usip || ssip); - } - - constraint instr_c { - !(rs1_reg inside {cfg.reserved_regs}); - rs1_reg != ZERO; - li_instr.pseudo_instr_name == LI; - li_instr.rd == rs1_reg; - csr_instr.instr_name == CSRRW; - csr_instr.rs1 == rs1_reg; - // TODO: Support non-zero rd for SIP, MIP - // csr_instr.rd inside {cfg.avail_regs}; - csr_instr.rd == ZERO; - csr_instr.csr == ip_reg; - } - - `uvm_object_utils(riscv_sw_interrupt_instr) - - function new(string name = ""); - super.new(name); - li_instr = riscv_pseudo_instr::type_id::create("li_instr"); - csr_instr = riscv_instr_base::type_id::create("csr_instr"); - ip = riscv_privil_reg::type_id::create("ip"); - endfunction - - function void post_randomize(); - // TODO: Support UIP - if(cfg.init_privileged_mode == USER_MODE) return; - ip.init_reg(ip_reg); - if(ip_reg == SIP) begin - ip.set_field("USIP", usip); - ip.set_field("SSIP", ssip); - end else begin - ip.set_field("USIP", usip); - ip.set_field("SSIP", ssip); - ip.set_field("MSIP", msip); - end - li_instr.imm_str = $sformatf("0x%0x", ip.get_val()); - csr_instr.comment = ip_reg.name(); - instr_list = {li_instr, csr_instr}; - super.post_randomize(); - endfunction - -endclass - diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_instr_base.sv b/vendor/google_riscv-dv/src/deprecated/riscv_instr_base.sv deleted file mode 100644 index 548758e6..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_instr_base.sv +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * Copyright 2018 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. - */ - -class riscv_instr_base extends uvm_object; - - rand riscv_instr_group_t group; - rand riscv_instr_format_t format; - rand riscv_instr_category_t category; - rand riscv_instr_name_t instr_name; - rand bit [11:0] csr; - - rand riscv_reg_t rs2; - rand riscv_reg_t rs1; - rand riscv_reg_t rd; - rand riscv_fpr_t fs1; - rand riscv_fpr_t fs2; - rand riscv_fpr_t fs3; - rand riscv_fpr_t fd; - rand bit [31:0] imm; - rand imm_t imm_type; - rand bit [4:0] imm_len; - rand bit aq; - rand bit rl; - bit is_pseudo_instr; - bit is_branch_target; - bit has_label = 1'b1; - bit atomic = 0; - bit branch_assigned; - bit process_load_store = 1'b1; - bit is_compressed; - bit is_illegal_instr; - bit is_hint_instr; - bit has_imm; - bit has_rs1; - bit has_rs2; - bit has_rd; - bit has_fs1; - bit has_fs2; - bit has_fs3; - bit has_fd; - bit is_floating_point; - bit [31:0] imm_mask = '1; - string imm_str; - string comment; - string label; - bit is_local_numeric_label; - int idx = -1; - `VECTOR_INCLUDE("riscv_instr_base_inc_riscv_instr_base_declares.sv") - - `uvm_object_utils(riscv_instr_base) - - constraint default_c { - instr_name != INVALID_INSTR; - } - - // Immediate bit length for different instruction format - constraint imm_len_c { - solve imm_type before imm_len; - if(format inside {U_FORMAT, J_FORMAT}) { - imm_len == 20; - } - if(format inside {I_FORMAT, S_FORMAT, B_FORMAT}) { - if(imm_type == UIMM) { - imm_len == 5; - } else { - imm_len == 11; - } - } - if(format inside {CI_FORMAT, CSS_FORMAT}) { - // TODO: gcc compiler seems to not support 6 bits unsigned imm for c.lui, - // hardcoded to 5 bits for now - if(instr_name == C_LUI) { - imm_len == 5; - } else { - imm_len == 6; - } - } - if(format inside {CL_FORMAT, CS_FORMAT}) { - imm_len == 5; - } - if(format inside {CJ_FORMAT}) { - imm_len == 11; - } - if(format inside {CB_FORMAT, CIW_FORMAT}) { - if(instr_name == C_ANDI) { - imm_len == 6; - } else { - imm_len == 8; - } - } - imm_len <= 20; - } - - constraint legal_operand_c { - (instr_name == C_LUI) -> (rd != SP); - } - - constraint imm_val_c { - if(imm_type inside {NZIMM, NZUIMM}) { - imm != 0; - } - } - - constraint aq_rl_c { - aq && rl == 0; - } - - // Avoid generating HINT or illegal instruction by default as it's not supported by the compiler - constraint no_hint_illegal_instr_c { - if (instr_name inside {C_ADDI, C_ADDIW, C_LI, C_LUI, C_SLLI, C_SLLI64, - C_LQSP, C_LDSP, C_MV, C_ADD}) { - rd != ZERO; - } - if (instr_name == C_JR) { - rs1 != ZERO; - } - if (instr_name inside {C_ADD, C_MV}) { - rs2 != ZERO; - } - } - - // Cannot shift more than the width of the bus - constraint shift_imm_val_c { - solve category before imm; - if(category == SHIFT) { - if(group == RV64I) { - // The new instruction in RV64I only handles 32 bits value - imm < 32; - } else { - imm < XLEN; - } - } - } - - constraint load_store_c { - if(category inside {LOAD, STORE}) { - rs1 != ZERO; // x0 cannot be used to save the base address - } - } - - constraint nop_c { - if(instr_name inside {NOP, C_NOP}) { - rs1 == ZERO; - rs2 == ZERO; - rd == ZERO; - } - } - - constraint jal_c { - if (XLEN != 32) { - soft instr_name != C_JAL; - } - } - - constraint system_instr_c { - if (category inside {SYSTEM, SYNCH}) { - rd == ZERO; - rs1 == ZERO; - } - } - - constraint rvc_csr_c { - // Registers specified by the three-bit rs1’, rs2’, and rd’ - if(format inside {CIW_FORMAT, CL_FORMAT, CS_FORMAT, CB_FORMAT, CA_FORMAT}) { - rs1 inside {[S0:A5]}; - rs2 inside {[S0:A5]}; - rd inside {[S0:A5]}; - } - // C_ADDI16SP is only valid when rd == SP - if(instr_name == C_ADDI16SP) { - rd == SP; - rs1 == SP; - } - - if(instr_name inside {C_JR, C_JALR}) { - rs2 == ZERO; - rs1 != ZERO; - } - } - - //////////// RV32I instructions ////////////// - // LOAD instructions - `add_instr(LB, I_FORMAT, LOAD, RV32I) - `add_instr(LH, I_FORMAT, LOAD, RV32I) - `add_instr(LW, I_FORMAT, LOAD, RV32I) - `add_instr(LBU, I_FORMAT, LOAD, RV32I) - `add_instr(LHU, I_FORMAT, LOAD, RV32I) - // STORE instructions - `add_instr(SB, S_FORMAT, STORE, RV32I) - `add_instr(SH, S_FORMAT, STORE, RV32I) - `add_instr(SW, S_FORMAT, STORE, RV32I) - // SHIFT intructions - `add_instr(SLL, R_FORMAT, SHIFT, RV32I) - `add_instr(SLLI, I_FORMAT, SHIFT, RV32I) - `add_instr(SRL, R_FORMAT, SHIFT, RV32I) - `add_instr(SRLI, I_FORMAT, SHIFT, RV32I) - `add_instr(SRA, R_FORMAT, SHIFT, RV32I) - `add_instr(SRAI, I_FORMAT, SHIFT, RV32I) - // ARITHMETIC intructions - `add_instr(ADD, R_FORMAT, ARITHMETIC, RV32I) - `add_instr(ADDI, I_FORMAT, ARITHMETIC, RV32I) - `add_instr(NOP, I_FORMAT, ARITHMETIC, RV32I) - `add_instr(SUB, R_FORMAT, ARITHMETIC, RV32I) - `add_instr(LUI, U_FORMAT, ARITHMETIC, RV32I, UIMM) - `add_instr(AUIPC, U_FORMAT, ARITHMETIC, RV32I, UIMM) - // LOGICAL instructions - `add_instr(XOR, R_FORMAT, LOGICAL, RV32I) - `add_instr(XORI, I_FORMAT, LOGICAL, RV32I) - `add_instr(OR, R_FORMAT, LOGICAL, RV32I) - `add_instr(ORI, I_FORMAT, LOGICAL, RV32I) - `add_instr(AND, R_FORMAT, LOGICAL, RV32I) - `add_instr(ANDI, I_FORMAT, LOGICAL, RV32I) - // COMPARE instructions - `add_instr(SLT, R_FORMAT, COMPARE, RV32I) - `add_instr(SLTI, I_FORMAT, COMPARE, RV32I) - `add_instr(SLTU, R_FORMAT, COMPARE, RV32I) - `add_instr(SLTIU, I_FORMAT, COMPARE, RV32I) - // BRANCH instructions - `add_instr(BEQ, B_FORMAT, BRANCH, RV32I) - `add_instr(BNE, B_FORMAT, BRANCH, RV32I) - `add_instr(BLT, B_FORMAT, BRANCH, RV32I) - `add_instr(BGE, B_FORMAT, BRANCH, RV32I) - `add_instr(BLTU, B_FORMAT, BRANCH, RV32I) - `add_instr(BGEU, B_FORMAT, BRANCH, RV32I) - // JUMP instructions - `add_instr(JAL, J_FORMAT, JUMP, RV32I) - `add_instr(JALR, I_FORMAT, JUMP, RV32I) - // SYNCH instructions - `add_instr(FENCE, I_FORMAT, SYNCH, RV32I) - `add_instr(FENCE_I, I_FORMAT, SYNCH, RV32I) - // SYSTEM instructions - `add_instr(ECALL, I_FORMAT, SYSTEM, RV32I) - `add_instr(EBREAK, I_FORMAT, SYSTEM, RV32I) - `add_instr(URET, I_FORMAT, SYSTEM, RV32I) - `add_instr(SRET, I_FORMAT, SYSTEM, RV32I) - `add_instr(MRET, I_FORMAT, SYSTEM, RV32I) - `add_instr(DRET, I_FORMAT, SYSTEM, RV32I) - `add_instr(WFI, I_FORMAT, INTERRUPT, RV32I) - // CSR instructions - `add_instr(CSRRW, R_FORMAT, CSR, RV32I, UIMM) - `add_instr(CSRRS, R_FORMAT, CSR, RV32I, UIMM) - `add_instr(CSRRC, R_FORMAT, CSR, RV32I, UIMM) - `add_instr(CSRRWI, I_FORMAT, CSR, RV32I, UIMM) - `add_instr(CSRRSI, I_FORMAT, CSR, RV32I, UIMM) - `add_instr(CSRRCI, I_FORMAT, CSR, RV32I, UIMM) - - //////////// RV32M instructions ////////////// - `add_instr(MUL, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(MULH, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(MULHSU, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(MULHU, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(DIV, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(DIVU, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(REM, R_FORMAT, ARITHMETIC, RV32M) - `add_instr(REMU, R_FORMAT, ARITHMETIC, RV32M) - - //////////// RV64M instructions ////////////// - `add_instr(MULW, R_FORMAT, ARITHMETIC, RV64M) - `add_instr(DIVW, R_FORMAT, ARITHMETIC, RV64M) - `add_instr(DIVUW, R_FORMAT, ARITHMETIC, RV64M) - `add_instr(REMW, R_FORMAT, ARITHMETIC, RV64M) - `add_instr(REMUW, R_FORMAT, ARITHMETIC, RV64M) - - //////////// RV32F instructions ////////////// - `add_instr(FLW, I_FORMAT, LOAD, RV32F) - `add_instr(FSW, S_FORMAT, STORE, RV32F) - `add_instr(FMADD_S, R4_FORMAT, ARITHMETIC, RV32F) - `add_instr(FMSUB_S, R4_FORMAT, ARITHMETIC, RV32F) - `add_instr(FNMSUB_S, R4_FORMAT, ARITHMETIC, RV32F) - `add_instr(FNMADD_S, R4_FORMAT, ARITHMETIC, RV32F) - `add_instr(FADD_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FSUB_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FMUL_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FDIV_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FSQRT_S, I_FORMAT, ARITHMETIC, RV32F) - `add_instr(FSGNJ_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FSGNJN_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FSGNJX_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FMIN_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FMAX_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FCVT_W_S, I_FORMAT, ARITHMETIC, RV32F) - `add_instr(FCVT_WU_S, I_FORMAT, ARITHMETIC, RV32F) - `add_instr(FMV_X_W, I_FORMAT, ARITHMETIC, RV32F) - `add_instr(FEQ_S, R_FORMAT, COMPARE, RV32F) - `add_instr(FLT_S, R_FORMAT, COMPARE, RV32F) - `add_instr(FLE_S, R_FORMAT, COMPARE, RV32F) - `add_instr(FCLASS_S, R_FORMAT, ARITHMETIC, RV32F) - `add_instr(FCVT_S_W, I_FORMAT, ARITHMETIC, RV32F) - `add_instr(FCVT_S_WU, I_FORMAT, ARITHMETIC, RV32F) - `add_instr(FMV_W_X, I_FORMAT, ARITHMETIC, RV32F) - - ///////////// RV64F instruction ///////////////// - `add_instr(FCVT_L_S, I_FORMAT, ARITHMETIC, RV64F) - `add_instr(FCVT_LU_S, I_FORMAT, ARITHMETIC, RV64F) - `add_instr(FCVT_S_L, I_FORMAT, ARITHMETIC, RV64F) - `add_instr(FCVT_S_LU, I_FORMAT, ARITHMETIC, RV64F) - - //////////// RV32D instructions //////////////// - `add_instr(FLD, I_FORMAT, LOAD, RV32D) - `add_instr(FSD, S_FORMAT, STORE, RV32D) - `add_instr(FMADD_D, R4_FORMAT, ARITHMETIC, RV32D) - `add_instr(FMSUB_D, R4_FORMAT, ARITHMETIC, RV32D) - `add_instr(FNMSUB_D, R4_FORMAT, ARITHMETIC, RV32D) - `add_instr(FNMADD_D, R4_FORMAT, ARITHMETIC, RV32D) - `add_instr(FADD_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FSUB_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FMUL_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FDIV_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FSQRT_D, I_FORMAT, ARITHMETIC, RV32D) - `add_instr(FSGNJ_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FSGNJN_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FSGNJX_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FMIN_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FMAX_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FCVT_S_D, I_FORMAT, ARITHMETIC, RV32D) - `add_instr(FCVT_D_S, I_FORMAT, ARITHMETIC, RV32D) - `add_instr(FEQ_D, R_FORMAT, COMPARE, RV32D) - `add_instr(FLT_D, R_FORMAT, COMPARE, RV32D) - `add_instr(FLE_D, R_FORMAT, COMPARE, RV32D) - `add_instr(FCLASS_D, R_FORMAT, ARITHMETIC, RV32D) - `add_instr(FCVT_W_D, I_FORMAT, ARITHMETIC, RV32D) - `add_instr(FCVT_WU_D, I_FORMAT, ARITHMETIC, RV32D) - `add_instr(FCVT_D_W, I_FORMAT, ARITHMETIC, RV32D) - `add_instr(FCVT_D_WU, I_FORMAT, ARITHMETIC, RV32D) - - ////////////// RV64D instruction /////////////// - `add_instr(FMV_X_D, I_FORMAT, ARITHMETIC, RV64D) - `add_instr(FMV_D_X, I_FORMAT, ARITHMETIC, RV64D) - `add_instr(FCVT_L_D, I_FORMAT, ARITHMETIC, RV64D) - `add_instr(FCVT_LU_D, I_FORMAT, ARITHMETIC, RV64D) - `add_instr(FCVT_D_L, I_FORMAT, ARITHMETIC, RV64D) - `add_instr(FCVT_D_LU, I_FORMAT, ARITHMETIC, RV64D) - - // RV64I instructions - // LOAD/STORE instructions - `add_instr(LWU, I_FORMAT, LOAD, RV64I) - `add_instr(LD, I_FORMAT, LOAD, RV64I) - `add_instr(SD, S_FORMAT, STORE, RV64I) - // SHIFT intructions - `add_instr(SLLW, R_FORMAT, SHIFT, RV64I) - `add_instr(SLLIW, I_FORMAT, SHIFT, RV64I) - `add_instr(SRLW, R_FORMAT, SHIFT, RV64I) - `add_instr(SRLIW, I_FORMAT, SHIFT, RV64I) - `add_instr(SRAW, R_FORMAT, SHIFT, RV64I) - `add_instr(SRAIW, I_FORMAT, SHIFT, RV64I) - // ARITHMETIC intructions - `add_instr(ADDW, R_FORMAT, ARITHMETIC, RV64I) - `add_instr(ADDIW, I_FORMAT, ARITHMETIC, RV64I) - `add_instr(SUBW, R_FORMAT, ARITHMETIC, RV64I) - - // RV32IC - `add_instr(C_LW, CL_FORMAT, LOAD, RV32C, UIMM) - `add_instr(C_SW, CS_FORMAT, STORE, RV32C, UIMM) - `add_instr(C_LWSP, CI_FORMAT, LOAD, RV32C, UIMM) - `add_instr(C_SWSP, CSS_FORMAT, STORE, RV32C, UIMM) - `add_instr(C_ADDI4SPN, CIW_FORMAT, ARITHMETIC, RV32C, NZUIMM) - `add_instr(C_ADDI, CI_FORMAT, ARITHMETIC, RV32C, NZIMM) - `add_instr(C_ADDI16SP, CI_FORMAT, ARITHMETIC, RV32C, NZIMM) - - `add_instr(C_LI, CI_FORMAT, ARITHMETIC, RV32C) - `add_instr(C_LUI, CI_FORMAT, ARITHMETIC, RV32C, NZUIMM) - `add_instr(C_SUB, CA_FORMAT, ARITHMETIC, RV32C) - `add_instr(C_ADD, CR_FORMAT, ARITHMETIC, RV32C) - `add_instr(C_NOP, CI_FORMAT, ARITHMETIC, RV32C) - `add_instr(C_MV, CR_FORMAT, ARITHMETIC, RV32C) - `add_instr(C_ANDI, CB_FORMAT, LOGICAL, RV32C) - `add_instr(C_XOR, CA_FORMAT, LOGICAL, RV32C) - `add_instr(C_OR, CA_FORMAT, LOGICAL, RV32C) - `add_instr(C_AND, CA_FORMAT, LOGICAL, RV32C) - `add_instr(C_BEQZ, CB_FORMAT, BRANCH, RV32C) - `add_instr(C_BNEZ, CB_FORMAT, BRANCH, RV32C) - `add_instr(C_SRLI, CB_FORMAT, SHIFT, RV32C, NZUIMM) - `add_instr(C_SRAI, CB_FORMAT, SHIFT, RV32C, NZUIMM) - `add_instr(C_SLLI, CI_FORMAT, SHIFT, RV32C, NZUIMM) - `add_instr(C_J, CJ_FORMAT, JUMP, RV32C) - `add_instr(C_JAL, CJ_FORMAT, JUMP, RV32C) - `add_instr(C_JR, CR_FORMAT, JUMP, RV32C) - `add_instr(C_JALR, CR_FORMAT, JUMP, RV32C) - `add_instr(C_EBREAK, CI_FORMAT, SYSTEM, RV32C) - - // RV64C - `add_instr(C_ADDIW, CI_FORMAT, ARITHMETIC, RV64C) - `add_instr(C_SUBW, CA_FORMAT, ARITHMETIC, RV64C) - `add_instr(C_ADDW, CA_FORMAT, ARITHMETIC, RV64C) - `add_instr(C_LD, CL_FORMAT, LOAD, RV64C, UIMM) - `add_instr(C_SD, CS_FORMAT, STORE, RV64C, UIMM) - `add_instr(C_LDSP, CI_FORMAT, LOAD, RV64C, UIMM) - `add_instr(C_SDSP, CSS_FORMAT, STORE, RV64C, UIMM) - - // RV128C - `add_instr(C_SRLI64, CB_FORMAT, SHIFT, RV128C, NZUIMM) - `add_instr(C_SRAI64, CB_FORMAT, SHIFT, RV128C, NZUIMM) - `add_instr(C_SLLI64, CI_FORMAT, SHIFT, RV128C, NZUIMM) - `add_instr(C_LQ, CL_FORMAT, LOAD, RV32DC, UIMM) - `add_instr(C_SQ, CS_FORMAT, STORE, RV32DC, UIMM) - `add_instr(C_LQSP, CI_FORMAT, LOAD, RV32DC, UIMM) - `add_instr(C_SQSP, CSS_FORMAT, STORE, RV32DC, UIMM) - - // RV32FC - `add_instr(C_FLW, CL_FORMAT, LOAD, RV32FC, UIMM) - `add_instr(C_FSW, CS_FORMAT, STORE, RV32FC, UIMM) - `add_instr(C_FLWSP, CI_FORMAT, LOAD, RV32FC, UIMM) - `add_instr(C_FSWSP, CSS_FORMAT, STORE, RV32FC, UIMM) - - // RV32DC - `add_instr(C_FLD, CL_FORMAT, LOAD, RV32DC, UIMM) - `add_instr(C_FSD, CS_FORMAT, STORE, RV32DC, UIMM) - `add_instr(C_FLDSP, CI_FORMAT, LOAD, RV32DC, UIMM) - `add_instr(C_FSDSP, CSS_FORMAT, STORE, RV32DC, UIMM) - - // RV32A - `add_instr(LR_W, R_FORMAT, LOAD, RV32A) - `add_instr(SC_W, R_FORMAT, STORE, RV32A) - `add_instr(AMOSWAP_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOADD_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOAND_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOOR_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOXOR_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOMIN_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOMAX_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOMINU_W, R_FORMAT, AMO, RV32A) - `add_instr(AMOMAXU_W, R_FORMAT, AMO, RV32A) - - // RV64A - `add_instr(LR_D, R_FORMAT, LOAD, RV64A) - `add_instr(SC_D, R_FORMAT, STORE, RV64A) - `add_instr(AMOSWAP_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOADD_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOAND_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOOR_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOXOR_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOMIN_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOMAX_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOMINU_D, R_FORMAT, AMO, RV64A) - `add_instr(AMOMAXU_D, R_FORMAT, AMO, RV64A) - - // Supervisor Instructions - `add_instr(SFENCE_VMA, R_FORMAT,SYNCH,RV32I) - - `VECTOR_INCLUDE("riscv_instr_base_inc_add_instr.sv") - - function void post_randomize(); - if (group inside {RV32C, RV64C, RV128C, RV32DC, RV32FC}) begin - is_compressed = 1'b1; - end - if (!(format inside {R_FORMAT, CR_FORMAT})) begin - imm_mask = '1; - imm_mask = imm_mask << imm_len; - has_imm = 1'b1; - mask_imm(); - if (imm_str == "") begin - update_imm_str(); - end - end - if (format inside {R_FORMAT, S_FORMAT, B_FORMAT, CSS_FORMAT, - CS_FORMAT, CR_FORMAT, CA_FORMAT}) begin - has_rs2 = 1'b1; - end - if (!(format inside {J_FORMAT, U_FORMAT, CJ_FORMAT, CSS_FORMAT, - CA_FORMAT, CR_FORMAT, CI_FORMAT})) begin - has_rs1 = 1'b1; - end else if (instr_name inside {C_JR, C_JALR}) begin - has_rs1 = 1'b1; - has_rs2 = 1'b0; - end - if (!(format inside {CJ_FORMAT, CB_FORMAT, CS_FORMAT, CSS_FORMAT, B_FORMAT, S_FORMAT})) begin - has_rd = 1'b1; - end - if (category == CSR) begin - has_rs2 = 1'b0; - if (instr_name inside {CSRRWI, CSRRSI, CSRRCI}) begin - has_rs1 = 1'b0; - end - end - // TODO(taliu) Add support for compressed floating point format - if (group inside {RV32F, RV64F, RV32D, RV64D, RV32FC, RV32DC}) begin - is_floating_point = 1'b1; - has_rs1 = 1'b0; - has_rs2 = 1'b0; - has_rd = 1'b0; - has_fs1 = 1'b1; - if (format == R4_FORMAT) begin - has_fs3 = 1'b1; - end - if (format != S_FORMAT) begin - if ((category == COMPARE) || (instr_name inside {FCLASS_S, FCLASS_D})) begin - has_rd = 1'b1; - end else begin - has_fd = 1'b1; - end - end - if (format != I_FORMAT) begin - has_fs2 = 1'b1; - end - if (instr_name inside {FMV_X_W, FMV_X_D, FCVT_W_S, FCVT_WU_S, - FCVT_L_S, FCVT_LU_S, FCVT_L_D, FCVT_LU_D, FCVT_LU_S, - FCVT_W_D, FCVT_WU_D}) begin - // Floating point to integer operation - has_rd = 1'b1; - has_fs1 = 1'b1; - has_fd = 1'b0; - end else if (instr_name inside {FMV_W_X, FMV_D_X, FCVT_S_W, FCVT_S_WU, - FCVT_S_L, FCVT_D_L, FCVT_S_LU, FCVT_D_W, - FCVT_D_LU, FCVT_D_WU, FLW, FLD, FSW, FSD, - C_FLW, C_FLD, C_FSW, C_FSD}) begin - // Integer to floating point operation - has_fd = 1'b1; - has_fs1 = 1'b0; - has_rs1 = 1'b1; - end - end - - `VECTOR_INCLUDE("riscv_instr_base_inc_post_randomize.sv") - - endfunction - - function void mask_imm(); - // Process the immediate value and sign extension - if (imm_type inside {UIMM, NZUIMM}) begin - imm = imm & ~imm_mask; - end else begin - if (imm[imm_len-1]) begin - imm = imm | imm_mask; - end else begin - imm = imm & ~imm_mask; - end - end - // Give a random value if imm is zero after masking unexpectedly - if((imm_type inside {NZIMM, NZUIMM}) && (imm == '0)) begin - imm = $urandom_range(2 ** (imm_len-1) - 1, 1); - end - endfunction - - function void gen_rand_imm(); - if (!randomize(imm)) begin - `uvm_fatal(`gfn, "Cannot randomize imm") - end - mask_imm(); - update_imm_str(); - endfunction - - function void update_imm_str(); - imm_str = $sformatf("%0d", $signed(imm)); - endfunction - - function void set_imm(int imm); - this.imm = imm; - mask_imm(); - update_imm_str(); - endfunction - - function riscv_reg_t gen_rand_gpr(riscv_reg_t included_reg[] = {}, - riscv_reg_t excluded_reg[] = {}); - riscv_reg_t gpr; - int unsigned i; - riscv_reg_t legal_gpr[$]; - if (included_reg.size() > 0) begin - legal_gpr = included_reg; - if (is_compressed && !(format inside {CR_FORMAT, CI_FORMAT, CSS_FORMAT})) begin - while (i < legal_gpr.size()) begin - if (legal_gpr[i] < S0 || legal_gpr[i] > A5) begin - legal_gpr.delete(i); - end else begin - i++; - end - end - end - end else if (is_compressed && - !(format inside {CR_FORMAT, CI_FORMAT, CSS_FORMAT})) begin - legal_gpr = riscv_instr_pkg::compressed_gpr; - end else begin - legal_gpr = riscv_instr_pkg::all_gpr; - end - if (format inside {CR_FORMAT, CI_FORMAT}) begin - excluded_reg = {excluded_reg, ZERO}; - end - if (excluded_reg.size() > 0) begin - i = 0; - while (i < legal_gpr.size()) begin - if (legal_gpr[i] inside {excluded_reg}) begin - legal_gpr.delete(i); - end else begin - i++; - end - end - end - `DV_CHECK_FATAL(legal_gpr.size() > 0) - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(i, i < legal_gpr.size();) - gpr = legal_gpr[i]; - return gpr; - endfunction - - function riscv_fpr_t gen_rand_fpr(riscv_fpr_t excluded_reg[] = {}); - riscv_fpr_t fpr; - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(fpr, - if (excluded_reg.size() > 0) { - !(fpr inside {excluded_reg}); - } - if (is_compressed) { - fpr inside {[F8:F15]}; - }); - return fpr; - endfunction - - function void gen_rand_csr(bit illegal_csr_instr = 0, - bit legal_invalid_csr_instr = 0, - privileged_reg_t invalid_csrs[$] = {}, - bit enable_floating_point = 0, - privileged_mode_t privileged_mode = MACHINE_MODE); - privileged_reg_t preg[$]; - if (illegal_csr_instr) begin - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(csr, !(csr inside {implemented_csr});) - end else if (legal_invalid_csr_instr) begin - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(csr, csr inside {invalid_csrs};) - end else begin - // Use scratch register to avoid the side effect of modifying other privileged mode CSR. - if (privileged_mode == MACHINE_MODE) - preg = {MSCRATCH}; - else if (privileged_mode == SUPERVISOR_MODE) - preg = {SSCRATCH}; - else - preg = {USCRATCH}; - if (enable_floating_point) begin - preg = {preg, FFLAGS, FRM, FCSR}; - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(csr, csr inside {preg};) - end else begin - csr = preg[0]; - end - end - endfunction - - function new(string name = ""); - super.new(name); - endfunction - - // Convert the instruction to one-liner print message - virtual function string convert2string(); - return convert2asm(); - endfunction - - virtual function void do_print (uvm_printer printer); - `uvm_info(get_type_name(), convert2string(), UVM_LOW) - endfunction - - // Convert the instruction to assembly code - virtual function string convert2asm(string prefix = ""); - string asm_str; - asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN); - if (is_floating_point) begin - case (format) - I_FORMAT: - if (category == LOAD) begin - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, fd.name(), get_imm(), rs1.name()); - end else if (instr_name inside {FMV_X_W, FMV_X_D, FCVT_W_S, FCVT_WU_S, - FCVT_L_S, FCVT_LU_S, FCVT_L_D, FCVT_LU_D, FCVT_LU_S, - FCVT_W_D, FCVT_WU_D}) begin - asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), fs1.name()); - end else if (instr_name inside {FMV_W_X, FMV_D_X, FCVT_S_W, FCVT_S_WU, - FCVT_S_L, FCVT_D_L, FCVT_S_LU, FCVT_D_W, - FCVT_D_LU, FCVT_D_WU}) begin - asm_str = $sformatf("%0s%0s, %0s", asm_str, fd.name(), rs1.name()); - end else begin - asm_str = $sformatf("%0s%0s, %0s", asm_str, fd.name(), fs1.name()); - end - S_FORMAT: - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, fs2.name(), get_imm(), rs1.name()); - R_FORMAT: - if (category == COMPARE) begin - asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rd.name(), fs1.name(), fs2.name()); - end else if (instr_name inside {FCLASS_S, FCLASS_D}) begin - asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), fs1.name()); - end else begin - asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, fd.name(), fs1.name(), fs2.name()); - end - R4_FORMAT: - asm_str = $sformatf("%0s%0s, %0s, %0s, %0s", asm_str, fd.name(), fs1.name(), - fs2.name(), fs3.name()); - CL_FORMAT: - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, fd.name(), get_imm(), rs1.name()); - CS_FORMAT: - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, fs2.name(), get_imm(), rs1.name()); - default: - `uvm_fatal(`gfn, $sformatf("Unsupported floating point format: %0s", format.name())) - endcase - end else if((category != SYSTEM) && !(group inside {RV32A, RV64A})) begin - case(format) - J_FORMAT, U_FORMAT : // instr rd,imm - asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), get_imm()); - I_FORMAT: // instr rd,rs1,imm - if(instr_name == NOP) - asm_str = "nop"; - else if(instr_name == C_NOP) - asm_str = "c.nop"; - else if(instr_name == WFI) - asm_str = "wfi"; - else if(instr_name == FENCE) - asm_str = $sformatf("fence"); // TODO: Support all fence combinations - else if(instr_name == FENCE_I) - asm_str = "fence.i"; - else if(category == LOAD) // Use psuedo instruction format - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, rd.name(), get_imm(), rs1.name()); - else if(category == CSR) - asm_str = $sformatf("%0s%0s, 0x%0x, %0s", asm_str, rd.name(), csr, get_imm()); - else - asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rd.name(), rs1.name(), get_imm()); - S_FORMAT, B_FORMAT: // instr rs1,rs2,imm - if(category == STORE) // Use psuedo instruction format - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, rs2.name(), get_imm(), rs1.name()); - else - asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rs1.name(), rs2.name(), get_imm()); - R_FORMAT: // instr rd,rs1,rs2 - if(category == CSR) begin - asm_str = $sformatf("%0s%0s, 0x%0x, %0s", asm_str, rd.name(), csr, rs1.name()); - end else if(instr_name == SFENCE_VMA) begin - asm_str = "sfence.vma x0, x0"; // TODO: Support all possible sfence - end else begin - asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name()); - end - CI_FORMAT, CIW_FORMAT: - if(instr_name == C_NOP) - asm_str = "c.nop"; - else if(instr_name == C_ADDI16SP) - asm_str = $sformatf("%0ssp, %0s", asm_str, get_imm()); - else - asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), get_imm()); - CL_FORMAT: - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, rd.name(), get_imm(), rs1.name()); - CS_FORMAT: - if(category == STORE) - asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, rs2.name(), get_imm(), rs1.name()); - else - asm_str = $sformatf("%0s%0s, %0s", asm_str, rs1.name(), rs2.name()); - CA_FORMAT: - asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs2.name()); - CB_FORMAT: - asm_str = $sformatf("%0s%0s, %0s", asm_str, rs1.name(), get_imm()); - CSS_FORMAT: - asm_str = $sformatf("%0s%0s, %0s", asm_str, rs2.name(), get_imm()); - CR_FORMAT: - if (instr_name inside {C_JR, C_JALR}) begin - asm_str = $sformatf("%0s%0s", asm_str, rs1.name()); - end else begin - asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs2.name()); - end - CJ_FORMAT: - asm_str = $sformatf("%0s%0s", asm_str, get_imm()); - endcase - end else if (group inside {RV32A, RV64A}) begin - if (instr_name inside {LR_W, LR_D}) begin - asm_str = $sformatf("%0s %0s, (%0s)", asm_str, rd.name(), rs1.name()); - end else begin - asm_str = $sformatf("%0s %0s, %0s, (%0s)", asm_str, rd.name(), rs2.name(), rs1.name()); - end - `VECTOR_INCLUDE("riscv_instr_base_inc_convert2asm.sv") - end else begin - // For EBREAK,C.EBREAK, making sure pc+4 is a valid instruction boundary - // This is needed to resume execution from epc+4 after ebreak handling - if(instr_name == EBREAK) begin - asm_str = ".4byte 0x00100073 # ebreak"; - end else if(instr_name == C_EBREAK) begin - asm_str = "c.ebreak;c.nop;"; - end - end - if(comment != "") - asm_str = {asm_str, " #",comment}; - return asm_str.tolower(); - endfunction - - function bit [6:0] get_opcode(); - case (instr_name) inside - LUI : get_opcode = 7'b0110111; - AUIPC : get_opcode = 7'b0010111; - JAL : get_opcode = 7'b1101111; - JALR : get_opcode = 7'b1100111; - BEQ, BNE, BLT, BGE, BLTU, BGEU : get_opcode = 7'b1100011; - LB, LH, LW, LBU, LHU, LWU, LD : get_opcode = 7'b0000011; - SB, SH, SW, SD : get_opcode = 7'b0100011; - ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI, NOP : get_opcode = 7'b0010011; - ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND, MUL, - MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU : get_opcode = 7'b0110011; - ADDIW, SLLIW, SRLIW, SRAIW : get_opcode = 7'b0011011; - MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU : get_opcode = 7'b0110011; - FENCE, FENCE_I : get_opcode = 7'b0001111; - ECALL, EBREAK, CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI : get_opcode = 7'b1110011; - ADDW, SUBW, SLLW, SRLW, SRAW, MULW, DIVW, DIVUW, REMW, REMUW : get_opcode = 7'b0111011; - ECALL, EBREAK, URET, SRET, MRET, DRET, WFI, SFENCE_VMA : get_opcode = 7'b1110011; - default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) - endcase - endfunction - - // Get opcode for compressed instruction - function bit [1:0] get_c_opcode(); - case (instr_name) inside - C_ADDI4SPN, C_FLD, C_FLD, C_LQ, C_LW, C_FLW, - C_LD, C_FSD, C_SQ, C_SW, C_FSW, C_SD : get_c_opcode = 2'b00; - C_NOP, C_ADDI, C_JAL, C_ADDIW, C_LI, C_ADDI16SP, - C_LUI, C_SRLI, C_SRLI64, C_SRAI, C_SRAI64, - C_ANDI, C_SUB, C_XOR, C_OR, C_AND, C_SUBW, - C_ADDW, C_J, C_BEQZ, C_BNEZ : get_c_opcode = 2'b01; - C_SLLI, C_SLLI64, C_FLDSP, C_LQSP, C_LWSP, - C_FLWSP, C_LDSP, C_JR, C_MV, C_EBREAK, C_JALR, - C_ADD, C_FSDSP, C_SQSP, C_SWSP, C_FSWSP, C_SDSP : get_c_opcode = 2'b10; - default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) - endcase - endfunction - - function bit [2:0] get_func3(); - case (instr_name) inside - JALR : get_func3 = 3'b000; - BEQ : get_func3 = 3'b000; - BNE : get_func3 = 3'b001; - BLT : get_func3 = 3'b100; - BGE : get_func3 = 3'b101; - BLTU : get_func3 = 3'b110; - BGEU : get_func3 = 3'b111; - LB : get_func3 = 3'b000; - LH : get_func3 = 3'b001; - LW : get_func3 = 3'b010; - LBU : get_func3 = 3'b100; - LHU : get_func3 = 3'b101; - SB : get_func3 = 3'b000; - SH : get_func3 = 3'b001; - SW : get_func3 = 3'b010; - ADDI : get_func3 = 3'b000; - NOP : get_func3 = 3'b000; - SLTI : get_func3 = 3'b010; - SLTIU : get_func3 = 3'b011; - XORI : get_func3 = 3'b100; - ORI : get_func3 = 3'b110; - ANDI : get_func3 = 3'b111; - SLLI : get_func3 = 3'b001; - SRLI : get_func3 = 3'b101; - SRAI : get_func3 = 3'b101; - ADD : get_func3 = 3'b000; - SUB : get_func3 = 3'b000; - SLL : get_func3 = 3'b001; - SLT : get_func3 = 3'b010; - SLTU : get_func3 = 3'b011; - XOR : get_func3 = 3'b100; - SRL : get_func3 = 3'b101; - SRA : get_func3 = 3'b101; - OR : get_func3 = 3'b110; - AND : get_func3 = 3'b111; - FENCE : get_func3 = 3'b000; - FENCE_I : get_func3 = 3'b001; - ECALL : get_func3 = 3'b000; - EBREAK : get_func3 = 3'b000; - CSRRW : get_func3 = 3'b001; - CSRRS : get_func3 = 3'b010; - CSRRC : get_func3 = 3'b011; - CSRRWI : get_func3 = 3'b101; - CSRRSI : get_func3 = 3'b110; - CSRRCI : get_func3 = 3'b111; - LWU : get_func3 = 3'b110; - LD : get_func3 = 3'b011; - SD : get_func3 = 3'b011; - ADDIW : get_func3 = 3'b000; - SLLIW : get_func3 = 3'b001; - SRLIW : get_func3 = 3'b101; - SRAIW : get_func3 = 3'b101; - ADDW : get_func3 = 3'b000; - SUBW : get_func3 = 3'b000; - SLLW : get_func3 = 3'b001; - SRLW : get_func3 = 3'b101; - SRAW : get_func3 = 3'b101; - MUL : get_func3 = 3'b000; - MULH : get_func3 = 3'b001; - MULHSU : get_func3 = 3'b010; - MULHU : get_func3 = 3'b011; - DIV : get_func3 = 3'b100; - DIVU : get_func3 = 3'b101; - REM : get_func3 = 3'b110; - REMU : get_func3 = 3'b111; - MULW : get_func3 = 3'b000; - DIVW : get_func3 = 3'b100; - DIVUW : get_func3 = 3'b101; - REMW : get_func3 = 3'b110; - REMUW : get_func3 = 3'b111; - C_ADDI4SPN : get_func3 = 3'b000; - C_FLD : get_func3 = 3'b001; - C_LQ : get_func3 = 3'b001; - C_LW : get_func3 = 3'b010; - C_FLW : get_func3 = 3'b011; - C_LD : get_func3 = 3'b011; - C_FSD : get_func3 = 3'b101; - C_SQ : get_func3 = 3'b101; - C_SW : get_func3 = 3'b110; - C_FSW : get_func3 = 3'b111; - C_SD : get_func3 = 3'b111; - C_NOP : get_func3 = 3'b000; - C_ADDI : get_func3 = 3'b000; - C_JAL : get_func3 = 3'b001; - C_ADDIW : get_func3 = 3'b001; - C_LI : get_func3 = 3'b010; - C_ADDI16SP : get_func3 = 3'b011; - C_LUI : get_func3 = 3'b011; - C_SRLI : get_func3 = 3'b100; - C_SRLI64 : get_func3 = 3'b100; - C_SRAI : get_func3 = 3'b100; - C_SRAI64 : get_func3 = 3'b100; - C_ANDI : get_func3 = 3'b100; - C_SUB : get_func3 = 3'b100; - C_XOR : get_func3 = 3'b100; - C_OR : get_func3 = 3'b100; - C_AND : get_func3 = 3'b100; - C_SUBW : get_func3 = 3'b100; - C_ADDW : get_func3 = 3'b100; - C_J : get_func3 = 3'b101; - C_BEQZ : get_func3 = 3'b110; - C_BNEZ : get_func3 = 3'b111; - C_SLLI : get_func3 = 3'b000; - C_SLLI64 : get_func3 = 3'b000; - C_FLDSP : get_func3 = 3'b001; - C_LQSP : get_func3 = 3'b001; - C_LWSP : get_func3 = 3'b010; - C_FLWSP : get_func3 = 3'b011; - C_LDSP : get_func3 = 3'b011; - C_JR : get_func3 = 3'b100; - C_MV : get_func3 = 3'b100; - C_EBREAK : get_func3 = 3'b100; - C_JALR : get_func3 = 3'b100; - C_ADD : get_func3 = 3'b100; - C_FSDSP : get_func3 = 3'b101; - C_SQSP : get_func3 = 3'b101; - C_SWSP : get_func3 = 3'b110; - C_FSWSP : get_func3 = 3'b111; - C_SDSP : get_func3 = 3'b111; - ECALL, EBREAK, URET, SRET, MRET, DRET, WFI, SFENCE_VMA : get_func3 = 3'b000; - default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) - endcase - endfunction - - function bit [6:0] get_func7(); - case (instr_name) - SLLI : get_func7 = 7'b0000000; - SRLI : get_func7 = 7'b0000000; - SRAI : get_func7 = 7'b0100000; - ADD : get_func7 = 7'b0000000; - SUB : get_func7 = 7'b0100000; - SLL : get_func7 = 7'b0000000; - SLT : get_func7 = 7'b0000000; - SLTU : get_func7 = 7'b0000000; - XOR : get_func7 = 7'b0000000; - SRL : get_func7 = 7'b0000000; - SRA : get_func7 = 7'b0100000; - OR : get_func7 = 7'b0000000; - AND : get_func7 = 7'b0000000; - FENCE : get_func7 = 7'b0000000; - FENCE_I : get_func7 = 7'b0000000; - SLLIW : get_func7 = 7'b0000000; - SRLIW : get_func7 = 7'b0000000; - SRAIW : get_func7 = 7'b0100000; - ADDW : get_func7 = 7'b0000000; - SUBW : get_func7 = 7'b0100000; - SLLW : get_func7 = 7'b0000000; - SRLW : get_func7 = 7'b0000000; - SRAW : get_func7 = 7'b0100000; - MUL : get_func7 = 7'b0000001; - MULH : get_func7 = 7'b0000001; - MULHSU : get_func7 = 7'b0000001; - MULHU : get_func7 = 7'b0000001; - DIV : get_func7 = 7'b0000001; - DIVU : get_func7 = 7'b0000001; - REM : get_func7 = 7'b0000001; - REMU : get_func7 = 7'b0000001; - MULW : get_func7 = 7'b0000001; - DIVW : get_func7 = 7'b0000001; - DIVUW : get_func7 = 7'b0000001; - REMW : get_func7 = 7'b0000001; - REMUW : get_func7 = 7'b0000001; - ECALL : get_func7 = 7'b0000000; - EBREAK : get_func7 = 7'b0000000; - URET : get_func7 = 7'b0000000; - SRET : get_func7 = 7'b0001000; - MRET : get_func7 = 7'b0011000; - DRET : get_func7 = 7'b0111101; - WFI : get_func7 = 7'b0001000; - SFENCE_VMA: get_func7 = 7'b0001001; - default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) - endcase - endfunction - - // Convert the instruction to assembly code - virtual function string convert2bin(string prefix = ""); - string binary; - if (!is_compressed) begin - case(format) - J_FORMAT: begin - binary = $sformatf("%8h", {imm[20], imm[10:1], imm[11], imm[19:12], rd, get_opcode()}); - end - U_FORMAT: begin - binary = $sformatf("%8h", {imm[31:12], rd, get_opcode()}); - end - I_FORMAT: begin - if(instr_name inside {FENCE, FENCE_I}) - binary = $sformatf("%8h", {17'b0, get_func3(), 5'b0, get_opcode()}); - else if(category == CSR) - binary = $sformatf("%8h", {csr[10:0], imm[4:0], get_func3(), rd, get_opcode()}); - else if(instr_name == ECALL) - binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()}); - else if(instr_name inside {URET, SRET, MRET}) - binary = $sformatf("%8h", {get_func7(), 5'b10, 13'b0, get_opcode()}); - else if(instr_name inside {DRET}) - binary = $sformatf("%8h", {get_func7(), 5'b10010, 13'b0, get_opcode()}); - else if(instr_name == EBREAK) - binary = $sformatf("%8h", {get_func7(), 5'b01, 13'b0, get_opcode()}); - else if(instr_name == WFI) - binary = $sformatf("%8h", {get_func7(), 5'b101, 13'b0, get_opcode()}); - else - binary = $sformatf("%8h", {imm[11:0], rs1, get_func3(), rd, get_opcode()}); - end - S_FORMAT: begin - binary = $sformatf("%8h", {imm[11:5], rs2, rs1, get_func3(), imm[4:0], get_opcode()}); - end - B_FORMAT: begin - binary = $sformatf("%8h", - {imm[12], imm[10:5], rs2, rs1, get_func3(), - imm[4:1], imm[11], get_opcode()}); - end - R_FORMAT: begin - if(category == CSR) - binary = $sformatf("%8h", {csr[10:0], rs1, get_func3(), rd, get_opcode()}); - else if(instr_name == SFENCE_VMA) - binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()}); - else - binary = $sformatf("%8h", {get_func7(), rs2, rs1, get_func3(), rd, get_opcode()}); - end - endcase - end else begin - case (instr_name) inside - C_ADDI4SPN: - binary = $sformatf("%4h", {get_func3(), imm[5:4], imm[9:6], - imm[2], imm[3], get_c_gpr(rd), get_c_opcode()}); - C_LQ: - binary = $sformatf("%4h", {get_func3(), imm[5:4], imm[8], - get_c_gpr(rs1), imm[7:6], get_c_gpr(rd), get_c_opcode()}); - C_FLD, C_LD: - binary = $sformatf("%4h", {get_func3(), imm[5:3], get_c_gpr(rs1), - imm[7:6], get_c_gpr(rd), get_c_opcode()}); - C_LW, C_FLW: - binary = $sformatf("%4h", {get_func3(), imm[5:3], get_c_gpr(rs1), - imm[2], imm[6], get_c_gpr(rd), get_c_opcode()}); - C_SQ: - binary = $sformatf("%4h", {get_func3(), imm[5:4], imm[8], - get_c_gpr(rs1), imm[7:6], get_c_gpr(rs2), get_c_opcode()}); - C_FSD, C_SD: - binary = $sformatf("%4h", {get_func3(), imm[5:3], get_c_gpr(rs1), - imm[7:6], get_c_gpr(rs2), get_c_opcode()}); - C_SW, C_FSW: - binary = $sformatf("%4h", {get_func3(), imm[5:3], get_c_gpr(rs1), - imm[2], imm[6], get_c_gpr(rs2), get_c_opcode()}); - C_NOP, C_ADDI, C_LI, C_ADDIW: - binary = $sformatf("%4h", {get_func3(), imm[5], rd, imm[4:0], get_c_opcode()}); - C_JAL, C_J: - binary = $sformatf("%4h", {get_func3(), imm[11], imm[4], imm[9:8], - imm[10], imm[6], imm[7], imm[3:1], imm[5], get_c_opcode()}); - C_ADDI16SP: - binary = $sformatf("%4h", {get_func3(), imm[9], 5'b10, - imm[4], imm[6], imm[8:7], imm[5], get_c_opcode()}); - C_LUI: - binary = $sformatf("%4h", {get_func3(), imm[5], rd, imm[4:0], get_c_opcode()}); - C_SRLI: - binary = $sformatf("%4h", {get_func3(), imm[5], - 2'b0, get_c_gpr(rd), imm[4:0], get_c_opcode()}); - C_SRLI64: - binary = $sformatf("%4h", {get_func3(), 3'b0, get_c_gpr(rd), 5'b0, get_c_opcode()}); - C_SRAI: - binary = $sformatf("%4h", {get_func3(), imm[5], - 2'b01, get_c_gpr(rd), imm[4:0], get_c_opcode()}); - C_SRAI64: - binary = $sformatf("%4h", {get_func3(), 3'b001, - get_c_gpr(rd), 5'b0, get_c_opcode()}); - C_ANDI: - binary = $sformatf("%4h", {get_func3(), imm[5], - 2'b10, get_c_gpr(rd), imm[4:0], get_c_opcode()}); - C_SUB: - binary = $sformatf("%4h", {get_func3(), 3'b011, get_c_gpr(rd), - 2'b00, get_c_gpr(rs2), get_c_opcode()}); - C_XOR: - binary = $sformatf("%4h", {get_func3(), 3'b011, get_c_gpr(rd), - 2'b01, get_c_gpr(rs2), get_c_opcode()}); - C_OR: - binary = $sformatf("%4h", {get_func3(), 3'b011, get_c_gpr(rd), - 2'b10, get_c_gpr(rs2), get_c_opcode()}); - C_AND: - binary = $sformatf("%4h", {get_func3(), 3'b011, get_c_gpr(rd), - 2'b11, get_c_gpr(rs2), get_c_opcode()}); - C_SUBW: - binary = $sformatf("%4h", {get_func3(), 3'b111, get_c_gpr(rd), - 2'b00, get_c_gpr(rs2), get_c_opcode()}); - C_ADDW: - binary = $sformatf("%4h", {get_func3(), 3'b111, get_c_gpr(rd), - 2'b01, get_c_gpr(rs2), get_c_opcode()}); - C_BEQZ, C_BNEZ: - binary = $sformatf("%4h", {get_func3(), imm[8], imm[4:3], - get_c_gpr(rs1), imm[7:6], imm[2:1], imm[5], get_c_opcode()}); - C_SLLI: - binary = $sformatf("%4h", {get_func3(), imm[5], rd, imm[4:0], get_c_opcode()}); - C_SLLI64: - binary = $sformatf("%4h", {get_func3(), 1'b0, rd, 5'b0, get_c_opcode()}); - C_FLDSP, C_LDSP: - binary = $sformatf("%4h", {get_func3(), imm[5], rd, imm[4:3], imm[8:6], get_c_opcode()}); - C_LQSP: - binary = $sformatf("%4h", {get_func3(), imm[5], rd, imm[4], imm[9:6], get_c_opcode()}); - C_LWSP, C_FLWSP: - binary = $sformatf("%4h", {get_func3(), imm[5], rd, imm[4:2], imm[7:6], get_c_opcode()}); - C_JR: - binary = $sformatf("%4h", {get_func3(), 1'b0, rs1, 5'b0, get_c_opcode()}); - C_MV: - binary = $sformatf("%4h", {get_func3(), 1'b0, rd, rs2, get_c_opcode()}); - C_EBREAK: - binary = $sformatf("%4h", {get_func3(), 1'b1, 10'b0, get_c_opcode()}); - C_JALR: - binary = $sformatf("%4h", {get_func3(), 1'b1, 10'b0, get_c_opcode()}); - C_ADD: - binary = $sformatf("%4h", {get_func3(), 1'b1, rd, rs2, get_c_opcode()}); - C_FSDSP, C_SDSP: - binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:3], imm[8:6], rs2, get_c_opcode()}); - C_SQSP: - binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:4], imm[9:6], rs2, get_c_opcode()}); - C_SWSP, C_FSWSP: - binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:2], imm[7:6], rs2, get_c_opcode()}); - default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) - endcase - end - return {prefix, binary}; - endfunction - - virtual function string get_instr_name(); - get_instr_name = instr_name.name(); - if(get_instr_name.substr(0, 1) == "C_") begin - get_instr_name = {"c.", get_instr_name.substr(2, get_instr_name.len() - 1)}; - end else if (group == RV32A) begin - get_instr_name = {get_instr_name.substr(0, get_instr_name.len() - 3), ".w"}; - get_instr_name = aq ? {get_instr_name, ".aq"} : - rl ? {get_instr_name, ".rl"} : get_instr_name; - end else if (group == RV64A) begin - get_instr_name = {get_instr_name.substr(0, get_instr_name.len() - 3), ".d"}; - get_instr_name = aq ? {get_instr_name, ".aq"} : - rl ? {get_instr_name, ".rl"} : get_instr_name; - end else if (group inside {RV32F, RV64F, RV32D, RV64D}) begin - foreach(get_instr_name[i]) begin - if (get_instr_name[i] == "_") begin - get_instr_name[i] = "."; - end - end - end - return get_instr_name; - endfunction - - // Get RVC register name for CIW, CL, CS, CB format - function bit [2:0] get_c_gpr(riscv_reg_t gpr); - return gpr[2:0]; - endfunction - - // Default return imm value directly, can be overriden to use labels and symbols - // Example: %hi(symbol), %pc_rel(label) ... - virtual function string get_imm(); - return imm_str; - endfunction - - virtual function void clear_unused_label(); - if(has_label && !is_branch_target && is_local_numeric_label) begin - has_label = 1'b0; - end - endfunction - - // Copy the rand fields of the base instruction - virtual function void copy_base_instr(riscv_instr_base obj); - this.group = obj.group; - this.format = obj.format; - this.category = obj.category; - this.instr_name = obj.instr_name; - this.rs2 = obj.rs2; - this.rs1 = obj.rs1; - this.rd = obj.rd; - this.imm = obj.imm; - this.imm_type = obj.imm_type; - this.imm_len = obj.imm_len; - this.imm_mask = obj.imm_mask; - this.imm_str = obj.imm_str; - this.is_pseudo_instr = obj.is_pseudo_instr; - this.aq = obj.aq; - this.rl = obj.rl; - this.is_compressed = obj.is_compressed; - this.has_imm = obj.has_imm; - this.has_rs1 = obj.has_rs1; - this.has_rs2 = obj.has_rs2; - this.has_rd = obj.has_rd; - this.fs3 = obj.fs3; - this.fs2 = obj.fs2; - this.fs1 = obj.fs1; - this.fd = obj.fd; - this.has_fs1 = obj.has_fs1; - this.has_fs2 = obj.has_fs2; - this.has_fs3 = obj.has_fs3; - this.has_fd = obj.has_fd; - this.is_floating_point = obj.is_floating_point; - `VECTOR_INCLUDE("riscv_instr_base_inc_copy_base_instr.sv") - endfunction - -endclass diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_instr_cov_test.sv b/vendor/google_riscv-dv/src/deprecated/riscv_instr_cov_test.sv deleted file mode 100644 index 10175fe0..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_instr_cov_test.sv +++ /dev/null @@ -1,295 +0,0 @@ -// This test read all trace CSV, and collect functional coverage from the instruction trace -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#(privileged_reg_t) preg_enum; - `VECTOR_INCLUDE("riscv_instr_cov_test_inc_typedef.sv") - - 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; - - `uvm_component_utils(riscv_instr_cov_test) - `uvm_component_new - - task run_phase(uvm_phase phase); - int i; - string args; - string csv; - string line; - string header[$]; - string entry[$]; - int fd; - while(1) begin - args = {$sformatf("trace_csv_%0d", i), "=%s"}; - if ($value$plusargs(args, csv)) begin - trace_csv.push_back(csv); - end else begin - break; - end - i++; - end - cfg = riscv_instr_gen_config::type_id::create("cfg"); - // disable_compressed_instr is not relevant to coverage test - cfg.disable_compressed_instr = 0; - `ifdef DEPRECATED - cfg.build_instruction_template(.skip_instr_exclusion(1)); - `else - riscv_instr::create_instr_list(cfg); - `endif - instr = riscv_instr_cov_item::type_id::create("instr"); - instr.rand_mode(0); - `ifdef DEPRECATED - instr.no_hint_illegal_instr_c.constraint_mode(0); - instr.imm_val_c.constraint_mode(0); - `endif - 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 - bit expect_illegal_instr; - entry_cnt = 0; - instr_cg.reset(); - if (uvm_is_match("*illegal*", trace_csv[i])) begin - expect_illegal_instr = 1; - end - `uvm_info(`gfn, $sformatf("Processing CSV trace[%0d]: %s", i, trace_csv[i]), UVM_LOW) - fd = $fopen(trace_csv[i], "r"); - if (fd) begin - // Get the header line - if ($fgets(line, fd)) begin - split_string(line, ",", header); - `uvm_info(`gfn, $sformatf("Header: %0s", line), UVM_HIGH); - end else begin - `uvm_info(`gfn, $sformatf("Skipping empty trace file: %0s", trace_csv[i]), UVM_LOW) - continue; - end - while ($fgets(line, fd)) begin - split_string(line, ",", entry); - if (entry.size() != header.size()) begin - `uvm_info(`gfn, $sformatf("Skipping malformed entry[%0d] : %0s", entry_cnt, line), UVM_LOW) - skipped_cnt += 1; - end else begin - trace["csv_entry"] = line; - foreach (header[j]) begin - trace[header[j]] = entry[j]; - end - post_process_trace(); - if (trace["instr"] inside {"li", "ret", "la"}) continue; - if (uvm_is_match("amo*",trace["instr"]) || - uvm_is_match("lr*" ,trace["instr"]) || - uvm_is_match("sc*" ,trace["instr"])) begin - // TODO: Enable functional coverage for AMO test - continue; - end - if (!sample()) begin - `uvm_info(`gfn, $sformatf("Found illegal instr: %0s [%0s]", - trace["instr"], line), UVM_HIGH) - if (!expect_illegal_instr) begin - unexpected_illegal_instr_cnt++; - end - end - end - entry_cnt += 1; - end - end else begin - `uvm_error(`gfn, $sformatf("%0s cannot be openned", trace_csv[i])) - end - `uvm_info(`gfn, $sformatf("[%s] : %0d instructions processed", - trace_csv[i], entry_cnt), UVM_LOW) - total_entry_cnt += entry_cnt; - end - `uvm_info(`gfn, $sformatf("Finished processing %0d trace CSV, %0d instructions", - trace_csv.size(), total_entry_cnt), UVM_LOW) - if ((skipped_cnt > 0) || (unexpected_illegal_instr_cnt > 0)) begin - `uvm_error(`gfn, $sformatf("%0d instructions skipped, %0d illegal instruction", - skipped_cnt, unexpected_illegal_instr_cnt)) - - end else begin - `uvm_info(`gfn, "TEST PASSED", UVM_NONE); - end - endtask - - virtual function void post_process_trace(); - endfunction - - function void fatal (string str); - `uvm_info(`gfn, str, UVM_NONE); - if ($test$plusargs("stop_on_first_error")) begin - `uvm_fatal(`gfn, "Errors: *. Warnings: * (written by riscv_instr_cov.sv)") - end - endfunction - - function bit sample(); - riscv_instr_name_t instr_name; - bit [XLEN-1:0] val; - if (instr_enum::from_name(process_instr_name(trace["instr"]), instr_name)) begin - `ifdef DEPRECATED - if (cfg.instr_template.exists(instr_name)) begin - instr.copy_base_instr(cfg.instr_template[instr_name]); - `else - if (riscv_instr::instr_template.exists(instr_name)) begin - instr.copy(riscv_instr::instr_template[instr_name]); - `endif - assign_trace_info_to_instr(instr); - instr.pre_sample(); - instr_cg.sample(instr); - return 1'b1; - end - end - `uvm_info(`gfn, $sformatf("Cannot find opcode: %0s", - process_instr_name(trace["instr"])), UVM_LOW) - get_val(trace["binary"], val); - if ((val[1:0] != 2'b11) && (RV32C inside {supported_isa})) begin - `SAMPLE(instr_cg.compressed_opcode_cg, val[15:0]) - `SAMPLE(instr_cg.illegal_compressed_instr_cg, val) - end - if (val[1:0] == 2'b11) begin - `uvm_info("DBG", $sformatf("Sample opcode: %0x [%0s]", val[6:2], trace["instr"]), UVM_LOW) - `SAMPLE(instr_cg.opcode_cg, val[6:2]) - end - endfunction - - virtual function void assign_trace_info_to_instr(riscv_instr_cov_item instr); - riscv_reg_t gpr; - `VECTOR_INCLUDE("riscv_instr_cov_test_inc_assign_trace_info_to_instr_declares.sv") - privileged_reg_t preg; - get_val(trace["addr"], instr.pc); - get_val(trace["binary"], instr.binary); - instr.trace = trace["str"]; - if (instr.instr_name inside {ECALL, EBREAK, FENCE, FENCE_I, NOP, - C_NOP, WFI, MRET, C_EBREAK}) begin - return; - end - if (instr.has_rs2) begin - if (get_gpr(trace["rs2"], gpr)) begin - instr.rs2 = gpr; - get_val(trace["rs2_val"], instr.rs2_value); - end else begin - `uvm_error(`gfn, $sformatf("Unrecognized rs2: [%0s] (%0s)", - trace["rs2"], trace["csv_entry"])) - end - end - if (instr.has_rd) begin - if (get_gpr(trace["rd"], gpr)) begin - instr.rd = gpr; - get_val(trace["rd_val"], instr.rd_value); - end else begin - `uvm_error(`gfn, $sformatf("Unrecognized rd: [%0s] (%0s)", - trace["rd"], trace["csv_entry"])) - end - end - if (instr.has_rs1) begin - if (instr.format inside {CI_FORMAT, CR_FORMAT} && - !(instr.instr_name inside {C_JR, C_JALR})) begin - instr.rs1 = instr.rd; - end else begin - if (get_gpr(trace["rs1"], gpr)) begin - instr.rs1 = gpr; - get_val(trace["rs1_val"], instr.rs1_value); - end else begin - `uvm_error(`gfn, $sformatf("Unrecognized rs1: [%0s] (%0s)", - trace["rs1"], trace["csv_entry"])) - end - end - end - if (instr.has_imm) begin - get_val(trace["imm"], instr.imm); - end - if (instr.category == CSR) begin - if (preg_enum::from_name(trace["csr"].toupper(), preg)) begin - instr.csr = preg; - end else begin - get_val(trace["csr"], instr.csr); - end - end - if (instr.category inside {LOAD, STORE}) begin - if (XLEN == 32) begin - instr.mem_addr = instr.rs1_value + instr.imm; - end else begin - bit [XLEN-32-1:0] padding; - if (instr.imm[31]) begin - padding = '1; - end else begin - padding = '0; - end - instr.mem_addr = instr.rs1_value + {padding, instr.imm}; - end - end - - `VECTOR_INCLUDE("riscv_instr_cov_test_inc_assign_trace_info_to_instr.sv") - - endfunction - - function bit get_gpr(input string str, output riscv_reg_t gpr); - str = str.toupper(); - if (gpr_enum::from_name(str, gpr)) begin - return 1'b1; - end else begin - return 1'b0; - end - endfunction - - `VECTOR_INCLUDE("riscv_instr_cov_test_inc_assign_trace_info_to_instr_functions.sv") - - function void get_val(input string str, output bit [XLEN-1:0] val); - val = str.atohex(); - endfunction - - function string process_instr_name(string instr_name); - instr_name = instr_name.toupper(); - foreach (instr_name[i]) begin - if (instr_name[i] == ".") begin - instr_name[i] = "_"; - end - end - return instr_name; - endfunction - - function void split_string(string str, byte step, ref string result[$]); - string tmp_str; - int i; - bit in_quote; - result = {}; - while (i < str.len()) begin - if (str[i] == "\"") begin - in_quote = ~in_quote; - end else if ((str[i] == step) && !in_quote) begin - result.push_back(tmp_str); - tmp_str = ""; - end else begin - tmp_str = {tmp_str, str[i]}; - end - if (i == str.len()-1) begin - result.push_back(tmp_str); - end - i++; - end - endfunction - - function void report_phase(uvm_phase phase); - uvm_report_server rs; - int error_count; - - rs = uvm_report_server::get_server(); - - error_count = rs.get_severity_count(UVM_WARNING) + - rs.get_severity_count(UVM_ERROR) + - rs.get_severity_count(UVM_FATAL); - - if (error_count == 0) begin - `uvm_info("", "TEST PASSED", UVM_NONE); - end else begin - `uvm_info("", "TEST FAILED", UVM_NONE); - end - `uvm_info("", "TEST GENERATION DONE", UVM_NONE); - super.report_phase(phase); - endfunction - -endclass diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_instr_gen_config.sv b/vendor/google_riscv-dv/src/deprecated/riscv_instr_gen_config.sv deleted file mode 100644 index d6ccb46e..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_instr_gen_config.sv +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright 2018 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. - */ - -//----------------------------------------------------------------------------- -// RISC-V assembly program generator configuration class -//----------------------------------------------------------------------------- - -class riscv_instr_gen_config extends uvm_object; - - //----------------------------------------------------------------------------- - // Random instruction generation settings - //----------------------------------------------------------------------------- - - // Instruction count of the main program - rand int main_program_instr_cnt; - - // Instruction count of each sub-program - rand int sub_program_instr_cnt[]; - - // Instruction count of the debug rom - rand int debug_program_instr_cnt; - - // Instruction count of debug sub-programs - rand int debug_sub_program_instr_cnt[]; - - // Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL - rand data_pattern_t data_page_pattern; - - // Associate array for delegation configuration for each exception and interrupt - // When the bit is 1, the corresponding delegation is enabled. - rand bit m_mode_exception_delegation[exception_cause_t]; - rand bit s_mode_exception_delegation[exception_cause_t]; - rand bit m_mode_interrupt_delegation[interrupt_cause_t]; - rand bit s_mode_interrupt_delegation[interrupt_cause_t]; - - // Priviledged mode after boot - rand privileged_mode_t init_privileged_mode; - - rand bit[XLEN-1:0] mstatus, mie, - sstatus, sie, - ustatus, uie; - - // Key fields in xSTATUS - // Memory protection bits - rand bit mstatus_mprv; - rand bit mstatus_mxr; - rand bit mstatus_sum; - rand bit mstatus_tvm; - rand bit [1:0] mstatus_fs; - rand mtvec_mode_t mtvec_mode; - - // Floating point rounding mode - rand f_rounding_mode_t fcsr_rm; - - // Enable sfence.vma instruction - rand bit enable_sfence; - - // Reserved register - // Reserved for various hardcoded routines - rand riscv_reg_t gpr[4]; - // Used by any DCSR operations inside of the debug rom - rand riscv_reg_t scratch_reg; - // Use a random register for stack pointer/thread pointer - rand riscv_reg_t sp; - rand riscv_reg_t tp; - rand riscv_reg_t ra; - - // Options for privileged mode CSR checking - // Below checking can be made optional as the ISS implementation could be different with the - // processor. - bit check_misa_init_val = 1'b0; - bit check_xstatus = 1'b1; - - // Virtual address translation is on for this test - rand bit virtual_addr_translation_on; - - //----------------------------------------------------------------------------- - // User space memory region and stack setting - //----------------------------------------------------------------------------- - - mem_region_t mem_region[$] = '{ - '{name:"region_0", size_in_bytes: 4096, xwr: 3'b111}, - '{name:"region_1", size_in_bytes: 4096 * 4, xwr: 3'b111}, - '{name:"region_2", size_in_bytes: 4096 * 2, xwr: 3'b111}, - '{name:"region_3", size_in_bytes: 512, xwr: 3'b111}, - '{name:"region_4", size_in_bytes: 4096, xwr: 3'b111} - }; - - // Stack section word length - int stack_len = 5000; - - //----------------------------------------------------------------------------- - // Kernel section setting, used by supervisor mode programs - //----------------------------------------------------------------------------- - - mem_region_t s_mem_region[$] = '{ - '{name:"s_region_0", size_in_bytes: 4096, xwr: 3'b111}, - '{name:"s_region_1", size_in_bytes: 4096, xwr: 3'b111}}; - - // Kernel Stack section word length - int kernel_stack_len = 4000; - - // Number of instructions for each kernel program - int kernel_program_instr_cnt = 400; - - //----------------------------------------------------------------------------- - // Instruction list based on the config, generate by build_instruction_template - //----------------------------------------------------------------------------- - riscv_instr_base instr_template[riscv_instr_name_t]; - riscv_instr_name_t basic_instr[$]; - riscv_instr_name_t instr_group[riscv_instr_group_t][$]; - riscv_instr_name_t instr_category[riscv_instr_category_t][$]; - - // Queue of all the main implemented CSRs that the boot privilege mode cannot access - // e.g. these CSRs are in higher privilege modes - access should raise an exception - privileged_reg_t invalid_priv_mode_csrs[$]; - - //----------------------------------------------------------------------------- - // Command line options or control knobs - //----------------------------------------------------------------------------- - // Main options for RISC-V assembly program generation - // Number of sub-programs per test - int num_of_sub_program = 5; - int instr_cnt = 200; - int num_of_tests = 1; - // For tests doesn't involve load/store, the data section generation could be skipped - bit no_data_page; - // Options to turn off some specific types of instructions - bit no_branch_jump; // No branch/jump instruction - bit no_load_store; // No load/store instruction - bit no_csr_instr; // No csr instruction - bit no_ebreak = 1; // No ebreak instruction - bit no_dret = 1; // No dret instruction - bit no_fence; // No fence instruction - bit no_wfi = 1; // No WFI instruction - bit enable_unaligned_load_store; - int illegal_instr_ratio; - int hint_instr_ratio; - // Directed boot privileged mode, u, m, s - string boot_mode_opts; - int enable_page_table_exception; - bit no_directed_instr; - // A name suffix for the generated assembly program - string asm_test_suffix; - // Enable interrupt bit in MSTATUS (MIE, SIE, UIE) - bit enable_interrupt; - // We need a separate control knob for enabling timer interrupts, as Spike - // throws an exception if xIE.xTIE is enabled - bit enable_timer_irq; - // Generate a bare program without any init/exit/error handling/page table routines - // The generated program can be integrated with a larger program. - // Note that the bare mode program is not expected to run in standalone mode - bit bare_program_mode; - // Enable accessing illegal CSR instruction - // - Accessing non-existence CSR - // - Accessing CSR with wrong privileged mode - bit enable_illegal_csr_instruction; - // Enable accessing CSRs at an invalid privilege level - bit enable_access_invalid_csr_level; - // Enable some dummy writes to main system CSRs (xSTATUS/xIE) at beginning of test - // to check repeated writes - bit enable_dummy_csr_write; - bit randomize_csr = 0; - // sfence support - bit allow_sfence_exception = 0; - // Interrupt/Exception Delegation - bit no_delegation = 1; - bit force_m_delegation = 0; - bit force_s_delegation = 0; - bit support_supervisor_mode; - bit disable_compressed_instr; - // "Memory mapped" address that when written to will indicate some event to - // the testbench - testbench will take action based on the value written - int signature_addr = 32'hdead_beef; - bit require_signature_addr = 1'b0; - // Enable a full or empty debug_rom section. - // Full debug_rom will contain random instruction streams. - // Empty debug_rom will contain just dret instruction and will return immediately. - // Will be empty by default. - bit gen_debug_section = 1'b0; - // Enable generation of a directed sequence of instructions containing - // ebreak inside the debug_rom. - // Disabled by default. - bit enable_ebreak_in_debug_rom = 1'b0; - // Enable setting dcsr.ebreak(m/s/u) - bit set_dcsr_ebreak = 1'b0; - // Number of sub programs in the debug rom - int num_debug_sub_program = 0; - // Enable debug single stepping - bit enable_debug_single_step = 0; - // Number of single stepping iterations - rand int single_step_iterations; - // Enable mstatus.tw bit - causes u-mode WFI to raise illegal instruction exceptions - bit set_mstatus_tw; - // Stack space allocated to each program, need to be enough to store necessary context - // Example: RA, SP, T0 - int min_stack_len_per_program = 10 * (XLEN/8); - int max_stack_len_per_program = 16 * (XLEN/8); - // Maximum branch distance, avoid skipping large portion of the code - int max_branch_step = 20; - // Maximum directed instruction stream sequence count - int max_directed_instr_stream_seq = 20; - // Reserved registers - riscv_reg_t reserved_regs[]; - // Floating point support - bit enable_floating_point; - - //----------------------------------------------------------------------------- - // Command line options for instruction distribution control - //----------------------------------------------------------------------------- - int dist_control_mode; - int unsigned category_dist[riscv_instr_category_t]; - - uvm_cmdline_processor inst; - - constraint default_c { - sub_program_instr_cnt.size() == num_of_sub_program; - debug_sub_program_instr_cnt.size() == num_debug_sub_program; - main_program_instr_cnt inside {[10 : instr_cnt]}; - foreach(sub_program_instr_cnt[i]) { - sub_program_instr_cnt[i] inside {[10 : instr_cnt]}; - } - // Disable sfence if the program is not boot to supervisor mode - // If sfence exception is allowed, we can enable sfence instruction in any priviledged mode. - // When MSTATUS.TVM is set, executing sfence.vma will be treate as illegal instruction - if(allow_sfence_exception) { - enable_sfence == 1'b1; - (init_privileged_mode != SUPERVISOR_MODE) || (mstatus_tvm == 1'b1); - } else { - (init_privileged_mode != SUPERVISOR_MODE || !riscv_instr_pkg::support_sfence || mstatus_tvm || no_fence) - -> (enable_sfence == 1'b0); - } - } - - constraint debug_mode_c { - if (riscv_instr_pkg::support_debug_mode) { - debug_program_instr_cnt inside {[100 : 300]}; - foreach(debug_sub_program_instr_cnt[i]) { - debug_sub_program_instr_cnt[i] inside {[100 : 300]}; - } - } - `ifndef DSIM - main_program_instr_cnt + sub_program_instr_cnt.sum() == instr_cnt; - `else - // dsim has some issue supporting sum(), use some approximate constraint to generate - // instruction cnt - if (num_of_sub_program > 0) { - main_program_instr_cnt inside {[10:instr_cnt/2]}; - foreach (sub_program_instr_cnt[i]) { - sub_program_instr_cnt[i] inside {[10:instr_cnt/num_of_sub_program]}; - } - } else { - main_program_instr_cnt == instr_cnt; - } - `endif - } - - // Keep the number of single step iterations relatively small - constraint debug_single_step_c { - if (enable_debug_single_step) { - single_step_iterations inside {[10 : 50]}; - } - } - - // Boot privileged mode distribution - constraint boot_privileged_mode_dist_c { - // Boot to higher privileged mode more often - if(riscv_instr_pkg::supported_privileged_mode.size() == 2) { - init_privileged_mode dist {riscv_instr_pkg::supported_privileged_mode[0] := 6, - riscv_instr_pkg::supported_privileged_mode[1] := 4}; - } else if (riscv_instr_pkg::supported_privileged_mode.size() == 3) { - init_privileged_mode dist {riscv_instr_pkg::supported_privileged_mode[0] := 4, - riscv_instr_pkg::supported_privileged_mode[1] := 3, - riscv_instr_pkg::supported_privileged_mode[2] := 3}; - } else { - init_privileged_mode == riscv_instr_pkg::supported_privileged_mode[0]; - } - } - - constraint mtvec_c { - mtvec_mode inside {supported_interrupt_mode}; - } - - constraint mstatus_c { - // This is default disabled at setup phase. It can be enabled in the exception and interrupt - // handling routine - mstatus_mprv == 1'b0; - } - - // Exception delegation setting - constraint exception_delegation_c { - // Do not delegate instructino page fault to supervisor/user mode because this may introduce - // dead loop. All the subsequent instruction fetches may fail and program cannot recover. - m_mode_exception_delegation[INSTRUCTION_PAGE_FAULT] == 1'b0; - if(force_m_delegation) { - foreach(m_mode_exception_delegation[i]) { - soft m_mode_exception_delegation[i] == 1'b1; - } - foreach(m_mode_interrupt_delegation[i]) { - soft m_mode_interrupt_delegation[i] == 1'b1; - } - } - if(force_s_delegation) { - foreach(s_mode_exception_delegation[i]) { - soft s_mode_exception_delegation[i] == 1'b1; - } - foreach(s_mode_interrupt_delegation[i]) { - soft s_mode_interrupt_delegation[i] == 1'b1; - } - } - } - - // Spike only supports a subset of exception and interrupt delegation - // You can modify this constraint if your ISS support different set of delegations - constraint delegation_c { - foreach(m_mode_exception_delegation[i]) { - if(!support_supervisor_mode || no_delegation) { - m_mode_exception_delegation[i] == 0; - } - if(!(i inside {INSTRUCTION_ADDRESS_MISALIGNED, BREAKPOINT, ECALL_UMODE, - INSTRUCTION_PAGE_FAULT, LOAD_PAGE_FAULT, STORE_AMO_PAGE_FAULT})) { - m_mode_exception_delegation[i] == 0; - } - } - foreach(m_mode_interrupt_delegation[i]) { - if(!support_supervisor_mode || no_delegation) { - m_mode_interrupt_delegation[i] == 0; - } - if(!(i inside {S_SOFTWARE_INTR, S_TIMER_INTR, S_EXTERNAL_INTR})) { - m_mode_interrupt_delegation[i] == 0; - } - } - } - - constraint ra_c { - ra dist {RA := 5, T1 := 2, [SP:T0] :/ 1, [T2:T6] :/ 2}; - ra != sp; - ra != tp; - ra != ZERO; - } - - constraint sp_tp_c { - sp != tp; - sp dist {SP := 6, RA := 1, [GP:T6] :/ 3}; - !(sp inside {GP, RA, ZERO}); - !(tp inside {GP, RA, ZERO}); - } - - constraint reserve_scratch_reg_c { - scratch_reg != ZERO; - scratch_reg != sp; - scratch_reg != tp; - } - - constraint gpr_c { - foreach (gpr[i]) { - !(gpr[i] inside {sp, tp, scratch_reg, ZERO, RA, GP}); - } - unique {gpr}; - } - - constraint addr_translaction_c { - solve init_privileged_mode before virtual_addr_translation_on; - if ((init_privileged_mode != MACHINE_MODE) && (SATP_MODE != BARE)) { - virtual_addr_translation_on == 1'b1; - } else { - virtual_addr_translation_on == 1'b0; - } - } - - constraint floating_point_c { - if (enable_floating_point) { - mstatus_fs == 2'b01; - } else { - mstatus_fs == 2'b00; - } - } - - `uvm_object_utils_begin(riscv_instr_gen_config) - `uvm_field_int(main_program_instr_cnt, UVM_DEFAULT) - `uvm_field_sarray_int(sub_program_instr_cnt, UVM_DEFAULT) - `uvm_field_int(debug_program_instr_cnt, UVM_DEFAULT) - `uvm_field_enum(data_pattern_t, data_page_pattern, UVM_DEFAULT) - `uvm_field_enum(privileged_mode_t, init_privileged_mode, UVM_DEFAULT) - `uvm_field_array_enum(riscv_reg_t, reserved_regs, UVM_DEFAULT) - `uvm_object_utils_end - - function new (string name = ""); - string s; - super.new(name); - init_delegation(); - inst = uvm_cmdline_processor::get_inst(); - get_int_arg_value("+num_of_tests=", num_of_tests); - get_int_arg_value("+enable_page_table_exception=", enable_page_table_exception); - get_bool_arg_value("+enable_interrupt=", enable_interrupt); - get_bool_arg_value("+enable_timer_irq=", enable_timer_irq); - get_int_arg_value("+num_of_sub_program=", num_of_sub_program); - get_int_arg_value("+instr_cnt=", instr_cnt); - get_bool_arg_value("+no_ebreak=", no_ebreak); - get_bool_arg_value("+no_dret=", no_dret); - get_bool_arg_value("+no_wfi=", no_wfi); - get_bool_arg_value("+no_branch_jump=", no_branch_jump); - get_bool_arg_value("+no_load_store=", no_load_store); - get_bool_arg_value("+no_csr_instr=", no_csr_instr); - get_bool_arg_value("+enable_illegal_csr_instruction=", enable_illegal_csr_instruction); - get_bool_arg_value("+enable_access_invalid_csr_level=", enable_access_invalid_csr_level); - get_bool_arg_value("+enable_dummy_csr_write=", enable_dummy_csr_write); - get_bool_arg_value("+allow_sfence_exception=", allow_sfence_exception); - get_bool_arg_value("+no_data_page=", no_data_page); - get_bool_arg_value("+no_directed_instr=", no_directed_instr); - get_bool_arg_value("+no_fence=", no_fence); - get_bool_arg_value("+no_delegation=", no_delegation); - get_int_arg_value("+illegal_instr_ratio=", illegal_instr_ratio); - get_int_arg_value("+hint_instr_ratio=", hint_instr_ratio); - get_bool_arg_value("+enable_unaligned_load_store=", enable_unaligned_load_store); - get_bool_arg_value("+force_m_delegation=", force_m_delegation); - get_bool_arg_value("+force_s_delegation=", force_s_delegation); - get_bool_arg_value("+require_signature_addr=", require_signature_addr); - get_bool_arg_value("+disable_compressed_instr=", disable_compressed_instr); - get_bool_arg_value("+randomize_csr=", randomize_csr); - if (this.require_signature_addr) begin - get_hex_arg_value("+signature_addr=", signature_addr); - end - get_bool_arg_value("+gen_debug_section=", gen_debug_section); - get_bool_arg_value("+bare_program_mode=", bare_program_mode); - get_int_arg_value("+num_debug_sub_program=", num_debug_sub_program); - get_bool_arg_value("+enable_ebreak_in_debug_rom=", enable_ebreak_in_debug_rom); - get_bool_arg_value("+set_dcsr_ebreak=", set_dcsr_ebreak); - get_bool_arg_value("+enable_debug_single_step=", enable_debug_single_step); - get_bool_arg_value("+set_mstatus_tw=", set_mstatus_tw); - get_bool_arg_value("+enable_floating_point=", enable_floating_point); - if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin - `uvm_info(get_full_name(), $sformatf( - "Got boot mode option - %0s", boot_mode_opts), UVM_LOW) - case(boot_mode_opts) - "m" : init_privileged_mode = MACHINE_MODE; - "s" : init_privileged_mode = SUPERVISOR_MODE; - "u" : init_privileged_mode = USER_MODE; - default: `uvm_fatal(get_full_name(), - $sformatf("Illegal boot mode option - %0s", boot_mode_opts)) - endcase - init_privileged_mode.rand_mode(0); - end - `uvm_info(`gfn, $sformatf("riscv_instr_pkg::supported_privileged_mode = %0d", - riscv_instr_pkg::supported_privileged_mode.size()), UVM_LOW) - void'(inst.get_arg_value("+asm_test_suffix=", asm_test_suffix)); - // Directed march list from the runtime options, ex. RV32I, RV32M etc. - void'(inst.get_arg_value("+march=", s)); - if(s != "") begin - string cmdline_march_list[$]; - riscv_instr_group_t march; - uvm_split_string(s, ",", cmdline_march_list); - riscv_instr_pkg::supported_isa.delete(); - foreach(cmdline_march_list[i]) begin - if(uvm_enum_wrapper#(riscv_instr_group_t)::from_name( - cmdline_march_list[i].toupper(), march)) begin - riscv_instr_pkg::supported_isa.push_back(march); - end else begin - `uvm_fatal(get_full_name(), $sformatf( - "Invalid march %0s specified in command line", cmdline_march_list[i])) - end - end - end - if (!(RV32C inside {supported_isa})) begin - disable_compressed_instr = 1; - end - setup_instr_distribution(); - get_invalid_priv_lvl_csr(); - endfunction - - function void setup_instr_distribution(); - string opts; - int val; - get_int_arg_value("+dist_control_mode=", dist_control_mode); - if (dist_control_mode == 1) begin - riscv_instr_category_t category; - category = category.first; - do begin - opts = {$sformatf("dist_%0s=", category.name()), "%d"}; - opts = opts.tolower(); - if ($value$plusargs(opts, val)) begin - category_dist[category] = val; - end else begin - category_dist[category] = 10; // Default ratio - end - `uvm_info(`gfn, $sformatf("Set dist[%0s] = %0d", - category.name(), category_dist[category]), UVM_LOW) - category = category.next; - end - while(category != category.first); - end - endfunction - - // Initialize the exception/interrupt delegation associate array, set all delegation default to 0 - virtual function void init_delegation(); - exception_cause_t cause; - interrupt_cause_t intr_cause; - cause = cause.first; - // Init exception delegation array - do begin - m_mode_exception_delegation[cause] = 1'b0; - s_mode_exception_delegation[cause] = 1'b0; - cause = cause.next; - end - while(cause != cause.first); - // Init interrupt delegation array - intr_cause = intr_cause.first; - do begin - m_mode_interrupt_delegation[intr_cause] = 1'b0; - s_mode_interrupt_delegation[intr_cause] = 1'b0; - intr_cause = intr_cause.next; - end - while(intr_cause != intr_cause.first); - endfunction - - function void pre_randomize(); - foreach (riscv_instr_pkg::supported_privileged_mode[i]) begin - if(riscv_instr_pkg::supported_privileged_mode[i] == SUPERVISOR_MODE) - support_supervisor_mode = 1; - end - endfunction - - function void get_non_reserved_gpr(); - endfunction - - function void post_randomize(); - // Setup the list all reserved registers - reserved_regs = {tp, sp, scratch_reg}; - // Need to save all loop registers, and RA/T0 - min_stack_len_per_program = 2 * (XLEN/8); - // Check if the setting is legal - check_setting(); - // WFI is not supported in umode - if (init_privileged_mode == USER_MODE) begin - no_wfi = 1'b1; - end - endfunction - - function void check_setting(); - bit support_64b; - bit support_128b; - foreach (riscv_instr_pkg::supported_isa[i]) begin - if (riscv_instr_pkg::supported_isa[i] inside {RV64I, RV64M, RV64A, RV64F, RV64D, RV64C}) begin - support_64b = 1'b1; - end else if (riscv_instr_pkg::supported_isa[i] inside {RV128I, RV128C}) begin - support_128b = 1'b1; - end - end - if (support_128b && XLEN != 128) begin - `uvm_fatal(`gfn, "XLEN should be set to 128 based on riscv_instr_pkg::supported_isa setting") - end - if (!support_128b && support_64b && XLEN != 64) begin - `uvm_fatal(`gfn, "XLEN should be set to 64 based on riscv_instr_pkg::supported_isa setting") - end - if (!(support_128b || support_64b) && XLEN != 32) begin - `uvm_fatal(`gfn, "XLEN should be set to 32 based on riscv_instr_pkg::supported_isa setting") - end - if (!(support_128b || support_64b) && !(SATP_MODE inside {SV32, BARE})) begin - `uvm_fatal(`gfn, $sformatf("SATP mode %0s is not supported for RV32G ISA", SATP_MODE.name())) - end - endfunction - - // Populate invalid_priv_mode_csrs with the main implemented CSRs for each supported privilege mode - // TODO(udi) - include performance/pmp/trigger CSRs? - virtual function void get_invalid_priv_lvl_csr(); - string invalid_lvl[$]; - string csr_name; - privileged_reg_t csr; - // Debug CSRs are inaccessible from all but Debug Mode, and we cannot boot into Debug Mode - invalid_lvl.push_back("D"); - case (init_privileged_mode) - MACHINE_MODE: begin - end - SUPERVISOR_MODE: begin - invalid_lvl.push_back("M"); - end - USER_MODE: begin - invalid_lvl.push_back("S"); - invalid_lvl.push_back("M"); - end - default: begin - `uvm_fatal(`gfn, "Unsupported initialization privilege mode") - end - endcase - foreach (implemented_csr[i]) begin - privileged_reg_t csr = implemented_csr[i]; - csr_name = csr.name(); - if (csr_name[0] inside {invalid_lvl}) begin - invalid_priv_mode_csrs.push_back(implemented_csr[i]); - end - end - endfunction - - // Get an integer argument from comand line - function void get_int_arg_value(string cmdline_str, ref int val); - string s; - if(inst.get_arg_value(cmdline_str, s)) begin - val = s.atoi(); - end - endfunction - - // Get a bool argument from comand line - function void get_bool_arg_value(string cmdline_str, ref bit val); - string s; - if(inst.get_arg_value(cmdline_str, s)) begin - val = s.atobin(); - end - endfunction - - // Get a hex argument from command line - function void get_hex_arg_value(string cmdline_str, ref int val); - string s; - if(inst.get_arg_value(cmdline_str, s)) begin - val = s.atohex(); - end - endfunction - - // Build instruction template - virtual function void build_instruction_template(bit skip_instr_exclusion = 0); - riscv_instr_name_t instr_name; - riscv_instr_name_t excluded_instr[$]; - excluded_instr = {INVALID_INSTR}; - if (!skip_instr_exclusion) begin - get_excluded_instr(excluded_instr); - end - instr_name = instr_name.first; - do begin - riscv_instr_base instr; - if (!(instr_name inside {unsupported_instr, excluded_instr})) begin - instr = riscv_instr_base::type_id::create("instr"); - `DV_CHECK_RANDOMIZE_WITH_FATAL(instr, instr_name == local::instr_name;) - if ((instr.group inside {supported_isa}) && - !(disable_compressed_instr && instr.is_compressed) && - !(!enable_floating_point && (instr.group inside {RV32F, RV64F, RV32D, RV64D}))) begin - `uvm_info(`gfn, $sformatf("Adding [%s] %s to the list", - instr.group.name(), instr.instr_name.name()), UVM_HIGH) - instr_group[instr.group].push_back(instr_name); - instr_category[instr.category].push_back(instr_name); - instr_template[instr_name] = instr; - end - end - instr_name = instr_name.next; - end - while (instr_name != instr_name.first); - endfunction - - virtual function void build_instruction_list(); - basic_instr = {instr_category[SHIFT], instr_category[ARITHMETIC], - instr_category[LOGICAL], instr_category[COMPARE]}; - basic_instr = {basic_instr, EBREAK}; - foreach(riscv_instr_pkg::supported_isa[i]) begin - if (riscv_instr_pkg::supported_isa[i] inside {RV32C, RV64C, RV128C, RV32DC, RV32FC}) begin - basic_instr = {basic_instr, C_EBREAK}; - break; - end - end - if (no_dret == 0) begin - basic_instr = {basic_instr, DRET}; - end - if (no_fence == 0) begin - basic_instr = {basic_instr, instr_category[SYNCH]}; - end - // TODO: Support CSR instruction in other mode - if ((no_csr_instr == 0) && (init_privileged_mode == MACHINE_MODE)) begin - `uvm_info(`gfn, $sformatf("Adding CSR instr, mode: %0s", init_privileged_mode.name()), UVM_LOW) - basic_instr = {basic_instr, instr_category[CSR]}; - end - if (no_wfi == 0) begin - basic_instr = {basic_instr, WFI}; - end - endfunction - - virtual function void get_excluded_instr(ref riscv_instr_name_t excluded[$]); - // Below instrutions will modify stack pointer, not allowed in normal instruction stream. - // It can be used in stack operation instruction stream. - excluded = {excluded, C_SWSP, C_SDSP, C_ADDI16SP}; - if (!enable_sfence) begin - excluded = {excluded, SFENCE_VMA}; - end - if (no_fence) begin - excluded = {excluded, FENCE, FENCE_I, SFENCE_VMA}; - end - // TODO: Support C_ADDI4SPN - excluded = {excluded, C_ADDI4SPN}; - endfunction - -endclass diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_instr_stream.sv b/vendor/google_riscv-dv/src/deprecated/riscv_instr_stream.sv deleted file mode 100644 index b4defc86..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_instr_stream.sv +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright 2018 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. - */ - -// Base class for RISC-V instruction stream -// A instruction stream here is a queue of RISC-V basic instructions. -// This class also provides some functions to manipulate the instruction stream, like insert a new -// instruction, mix two instruction streams etc. -class riscv_instr_stream extends uvm_object; - - `INSTR instr_list[$]; - int unsigned instr_cnt; - string label = ""; - // User can specify a small group of available registers to generate various hazard condition - rand riscv_reg_t avail_regs[]; - // Some additional reserved registers that should not be used as rd register - // by this instruction stream - riscv_reg_t reserved_rd[]; - - `uvm_object_utils(riscv_instr_stream) - `uvm_object_new - - // Initialize the instruction stream, create each instruction instance - function void initialize_instr_list(int unsigned instr_cnt); - instr_list = {}; - this.instr_cnt = instr_cnt; - create_instr_instance(); - endfunction - - virtual function void create_instr_instance(); - `INSTR instr; - for(int i = 0; i < instr_cnt; i++) begin - instr = `INSTR::type_id::create($sformatf("instr_%0d", i)); - instr_list.push_back(instr); - end - endfunction - - // Insert an instruction to the existing instruction stream at the given index - // When index is -1, the instruction is injected at a random location - function void insert_instr(`INSTR instr, int idx = -1); - int current_instr_cnt = instr_list.size(); - if(idx == -1) begin - idx = $urandom_range(0, current_instr_cnt-1); - while(instr_list[idx].atomic) begin - idx += 1; - if (idx == current_instr_cnt - 1) begin - instr_list = {instr_list, instr}; - return; - end - end - end else if((idx > current_instr_cnt) || (idx < 0)) begin - `uvm_error(`gfn, $sformatf("Cannot insert instr:%0s at idx %0d", - instr.convert2asm(), idx)) - end - instr_list.insert(idx, instr); - endfunction - - // Insert an instruction to the existing instruction stream at the given index - // When index is -1, the instruction is injected at a random location - // When replace is 1, the original instruction at the inserted position will be replaced - function void insert_instr_stream(`INSTR new_instr[], int idx = -1, bit replace = 1'b0); - int current_instr_cnt = instr_list.size(); - int new_instr_cnt = new_instr.size(); - if(current_instr_cnt == 0) begin - instr_list = new_instr; - return; - end - if(idx == -1) begin - idx = $urandom_range(0, current_instr_cnt-1); - repeat(10) begin - if (instr_list[idx].atomic) break; - idx = $urandom_range(0, current_instr_cnt-1); - end - if (instr_list[idx].atomic) begin - foreach (instr_list[i]) begin - if (!instr_list[i].atomic) begin - idx = i; - break; - end - end - if (instr_list[idx].atomic) begin - `uvm_fatal(`gfn, $sformatf("Cannot inject the instruction")) - end - end - end else if((idx > current_instr_cnt) || (idx < 0)) begin - `uvm_error(`gfn, $sformatf("Cannot insert instr stream at idx %0d", idx)) - end - // When replace is 1, the original instruction at this index will be removed. The label of the - // original instruction will be copied to the head of inserted instruction stream. - if(replace) begin - new_instr[0].label = instr_list[idx].label; - new_instr[0].has_label = instr_list[idx].has_label; - if (idx == 0) begin - instr_list = {new_instr, instr_list[idx+1:current_instr_cnt-1]}; - end else begin - instr_list = {instr_list[0:idx-1], new_instr, instr_list[idx+1:current_instr_cnt-1]}; - end - end else begin - if (idx == 0) begin - instr_list = {new_instr, instr_list[idx:current_instr_cnt-1]}; - end else begin - instr_list = {instr_list[0:idx-1], new_instr, instr_list[idx:current_instr_cnt-1]}; - end - end - endfunction - - // Mix the input instruction stream with the original instruction, the instruction order is - // preserved. When 'contained' is set, the original instruction stream will be inside the - // new instruction stream with the first and last instruction from the input instruction stream. - function void mix_instr_stream(`INSTR new_instr[], bit contained = 1'b0); - int current_instr_cnt = instr_list.size(); - int insert_instr_position[]; - int new_instr_cnt = new_instr.size(); - insert_instr_position = new[new_instr_cnt]; - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(insert_instr_position, - foreach(insert_instr_position[i]) { - insert_instr_position[i] inside {[0:current_instr_cnt-1]}; - }) - if (insert_instr_position.size() > 0) begin - insert_instr_position.sort(); - end - if(contained) begin - insert_instr_position[0] = 0; - if(new_instr_cnt > 1) - insert_instr_position[new_instr_cnt-1] = current_instr_cnt-1; - end - foreach(new_instr[i]) begin - insert_instr(new_instr[i], insert_instr_position[i] + i); - end - endfunction - - function string convert2string(); - string str; - foreach(instr_list[i]) - str = {str, instr_list[i].convert2asm(), "\n"}; - return str; - endfunction - -endclass - -// Generate a random instruction stream based on the configuration -// There are two ways to use this class to generate instruction stream -// 1. For short instruction stream, you can call randomize() directly. -// 2. For long instruction stream (>1K), randomize() all instructions together might take a long -// time for the constraint solver. In this case, you can call gen_instr to generate instructions -// one by one. The time only grows linearly with the instruction count -class riscv_rand_instr_stream extends riscv_instr_stream; - - riscv_instr_gen_config cfg; - bit kernel_mode; - riscv_instr_name_t allowed_instr[$]; - int unsigned category_dist[riscv_instr_category_t]; - - `uvm_object_utils(riscv_rand_instr_stream) - `uvm_object_new - - virtual function void create_instr_instance(); - `INSTR instr; - for (int i = 0; i < instr_cnt; i++) begin - instr = `INSTR::type_id::create($sformatf("instr_%0d", i)); - instr_list.push_back(instr); - end - endfunction - - virtual function void setup_allowed_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1); - allowed_instr = cfg.basic_instr; - if (no_branch == 0) begin - allowed_instr = {allowed_instr, cfg.instr_category[BRANCH]}; - end - if (no_load_store == 0) begin - allowed_instr = {allowed_instr, cfg.instr_category[LOAD], cfg.instr_category[STORE]}; - end - setup_instruction_dist(no_branch, no_load_store); - endfunction - - function void setup_instruction_dist(bit no_branch = 1'b0, bit no_load_store = 1'b1); - if (cfg.dist_control_mode) begin - category_dist = cfg.category_dist; - if (no_branch) begin - category_dist[BRANCH] = 0; - end - if (no_load_store) begin - category_dist[LOAD] = 0; - category_dist[STORE] = 0; - end - `uvm_info(`gfn, $sformatf("setup_instruction_dist: %0d", category_dist.size()), UVM_LOW) - end - endfunction - - virtual function void gen_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1, - bit is_debug_program = 1'b0); - setup_allowed_instr(no_branch, no_load_store); - foreach(instr_list[i]) begin - randomize_instr(instr_list[i], is_debug_program); - end - // Do not allow branch instruction as the last instruction because there's no - // forward branch target - while (instr_list[$].category == BRANCH) begin - void'(instr_list.pop_back()); - if (instr_list.size() == 0) break; - end - endfunction - - function void randomize_instr(riscv_instr_base instr, - bit is_in_debug = 1'b0, - bit skip_rs1 = 1'b0, - bit skip_rs2 = 1'b0, - bit skip_rd = 1'b0, - bit skip_imm = 1'b0, - bit skip_csr = 1'b0, - bit disable_dist = 1'b0); - riscv_instr_name_t instr_name; - if ((cfg.dist_control_mode == 1) && !disable_dist) begin - riscv_instr_category_t category; - int unsigned idx; - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(category, - category dist {LOAD := category_dist[LOAD], - STORE := category_dist[STORE], - SHIFT := category_dist[SHIFT], - ARITHMETIC := category_dist[ARITHMETIC], - LOGICAL := category_dist[LOGICAL], - COMPARE := category_dist[COMPARE], - BRANCH := category_dist[BRANCH], - SYNCH := category_dist[SYNCH], - CSR := category_dist[CSR]};) - idx = $urandom_range(0, cfg.instr_category[category].size() - 1); - instr_name = cfg.instr_category[category][idx]; - // if set_dcsr_ebreak is set, we do not want to generate any ebreak - // instructions inside the debug_rom - end else if ((cfg.no_ebreak && !is_in_debug) || - (!cfg.enable_ebreak_in_debug_rom && is_in_debug)) begin - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(instr_name, - instr_name inside {allowed_instr}; - !(instr_name inside {EBREAK, C_EBREAK});) - end else begin - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(instr_name, - instr_name inside {allowed_instr};) - end - instr.copy_base_instr(cfg.instr_template[instr_name]); - `uvm_info(`gfn, $sformatf("%s: rs1:%0d, rs2:%0d, rd:%0d, imm:%0d", - instr.instr_name.name(), - instr.has_rs1, - instr.has_rs2, - instr.has_rd, - instr.has_imm), UVM_FULL) - if (instr.has_imm && !skip_imm) begin - instr.gen_rand_imm(); - end - if (instr.has_rs1 && !skip_rs1) begin - if (instr.is_compressed) begin - // Compressed instruction could use the same register for rs1 and rd - instr.rs1 = instr.gen_rand_gpr( - .included_reg(avail_regs), - .excluded_reg({reserved_rd, cfg.reserved_regs})); - end else begin - instr.rs1 = instr.gen_rand_gpr(.included_reg(avail_regs)); - end - end - if (instr.has_rs2 && !skip_rs2) begin - instr.rs2 = instr.gen_rand_gpr(.included_reg(avail_regs)); - end - if (instr.has_rd && !skip_rd) begin - if (instr_name == C_LUI) begin - instr.rd = instr.gen_rand_gpr( - .included_reg(avail_regs), - .excluded_reg({reserved_rd, cfg.reserved_regs, SP})); - end else begin - instr.rd = instr.gen_rand_gpr( - .included_reg(avail_regs), - .excluded_reg({reserved_rd, cfg.reserved_regs})); - end - end - if ((instr.category == CSR) && !skip_csr) begin - instr.gen_rand_csr(.privileged_mode(cfg.init_privileged_mode), - .enable_floating_point(cfg.enable_floating_point), - .illegal_csr_instr(cfg.enable_illegal_csr_instruction), - .legal_invalid_csr_instr(cfg.enable_access_invalid_csr_level), - .invalid_csrs(cfg.invalid_priv_mode_csrs)); - end - if (instr.has_fs1) begin - instr.fs1 = instr.gen_rand_fpr(); - end - if (instr.has_fs2) begin - instr.fs2 = instr.gen_rand_fpr(); - end - if (instr.has_fs3) begin - instr.fs3 = instr.gen_rand_fpr(); - end - if (instr.has_fd) begin - instr.fd = instr.gen_rand_fpr(); - end - endfunction - -endclass diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_load_store_instr_lib.sv b/vendor/google_riscv-dv/src/deprecated/riscv_load_store_instr_lib.sv deleted file mode 100644 index 92b05706..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_load_store_instr_lib.sv +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright 2018 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. - */ - -// Base class for all load/store instruction stream - -class riscv_load_store_base_instr_stream extends riscv_mem_access_stream; - - typedef enum bit [1:0] { - NARROW, - HIGH, - MEDIUM, - SPARSE - } locality_e; - - rand int unsigned num_load_store; - rand int unsigned num_mixed_instr; - rand int base; - int offset[]; - int addr[]; - riscv_instr_base load_store_instr[$]; - rand int unsigned data_page_id; - rand riscv_reg_t rs1_reg; - rand locality_e locality; - rand int max_load_store_offset; - - `uvm_object_utils(riscv_load_store_base_instr_stream) - - constraint rs1_c { - !(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO}); - } - - constraint addr_c { - solve data_page_id before max_load_store_offset; - solve max_load_store_offset before base; - data_page_id < max_data_page_id; - foreach (data_page[i]) { - if (i == data_page_id) { - max_load_store_offset == data_page[i].size_in_bytes; - } - } - base inside {[0 : max_load_store_offset-1]}; - } - - function new(string name = ""); - super.new(name); - endfunction - - virtual function void randomize_offset(); - int offset_, addr_; - offset = new[num_load_store]; - addr = new[num_load_store]; - for (int i=0; i 0) begin - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(avail_regs, - unique{avail_regs}; - avail_regs[0] inside {[S0 : A5]}; - foreach(avail_regs[i]) { - !(avail_regs[i] inside {cfg.reserved_regs, reserved_rd}); - }, - "Cannot randomize avail_regs") - end - if ((rs1_reg inside {[S0 : A5]}) && !cfg.disable_compressed_instr) begin - enable_compressed_load_store = 1; - end - foreach(addr[i]) begin - instr = riscv_instr_base::type_id::create("instr"); - // Assign the allowed load/store instructions based on address alignment - // This is done separately rather than a constraint to improve the randomization performance - allowed_instr = {LB, LBU, SB}; - if (!cfg.enable_unaligned_load_store) begin - if (addr[i][0] == 1'b0) begin - allowed_instr = {LH, LHU, SH, allowed_instr}; - end - if (addr[i] % 4 == 0) begin - allowed_instr = {LW, SW, allowed_instr}; - if (cfg.enable_floating_point) begin - allowed_instr = {FLW, FSW, allowed_instr}; - end - if((offset[i] inside {[0:127]}) && (offset[i] % 4 == 0) && - (RV32C inside {riscv_instr_pkg::supported_isa}) && - enable_compressed_load_store) begin - allowed_instr = {C_LW, C_SW, allowed_instr}; - if (cfg.enable_floating_point && (RV32FC inside {supported_isa})) begin - allowed_instr = {C_FLW, C_FSW, allowed_instr}; - end - end - end - if ((XLEN >= 64) && (addr[i] % 8 == 0)) begin - allowed_instr = {LWU, LD, SD, allowed_instr}; - if (cfg.enable_floating_point && (RV32D inside {supported_isa})) begin - allowed_instr = {FLD, FSD, allowed_instr}; - end - if((offset[i] inside {[0:255]}) && (offset[i] % 8 == 0) && - (RV64C inside {riscv_instr_pkg::supported_isa} && - enable_compressed_load_store)) begin - allowed_instr = {C_LD, C_SD, allowed_instr}; - if (cfg.enable_floating_point && (RV32DC inside {supported_isa})) begin - allowed_instr = {C_FLD, C_FSD, allowed_instr}; - end - end - end - end else begin - allowed_instr = {LW, SW, LH, LHU, SH, allowed_instr}; - if ((offset[i] inside {[0:127]}) && (offset[i] % 4 == 0) && - (RV32C inside {riscv_instr_pkg::supported_isa}) && - enable_compressed_load_store) begin - allowed_instr = {C_LW, C_SW, allowed_instr}; - end - if (XLEN >= 64) begin - allowed_instr = {LWU, LD, SD, allowed_instr}; - if ((offset[i] inside {[0:255]}) && (offset[i] % 8 == 0) && - (RV64C inside {riscv_instr_pkg::supported_isa}) && - enable_compressed_load_store) begin - allowed_instr = {C_LD, C_SD, allowed_instr}; - end - end - end - randomize_instr(instr, .skip_rs1(1'b1), .skip_imm(1'b1), .disable_dist(1'b1)); - instr.rs1 = rs1_reg; - instr.set_imm(offset[i]); - instr.process_load_store = 0; - instr_list.push_back(instr); - load_store_instr.push_back(instr); - end - endfunction - -endclass - -// A single load/store instruction -class riscv_single_load_store_instr_stream extends riscv_load_store_base_instr_stream; - - constraint legal_c { - num_load_store == 1; - num_mixed_instr < 5; - } - - `uvm_object_utils(riscv_single_load_store_instr_stream) - `uvm_object_new - -endclass - -// Back to back load/store instructions -class riscv_load_store_stress_instr_stream extends riscv_load_store_base_instr_stream; - - int unsigned max_instr_cnt = 30; - int unsigned min_instr_cnt = 10; - - constraint legal_c { - num_load_store inside {[min_instr_cnt:max_instr_cnt]}; - num_mixed_instr == 0; - } - - `uvm_object_utils(riscv_load_store_stress_instr_stream) - `uvm_object_new - -endclass - -// Random load/store sequence -// A random mix of load/store instructions and other instructions -class riscv_load_store_rand_instr_stream extends riscv_load_store_base_instr_stream; - - constraint legal_c { - num_load_store inside {[10:30]}; - num_mixed_instr inside {[10:30]}; - } - - `uvm_object_utils(riscv_load_store_rand_instr_stream) - `uvm_object_new - -endclass - -// Use a small set of GPR to create various WAW, RAW, WAR hazard scenario -class riscv_hazard_instr_stream extends riscv_load_store_base_instr_stream; - - int unsigned num_of_avail_regs = 6; - - constraint legal_c { - num_load_store inside {[10:30]}; - num_mixed_instr inside {[10:30]}; - } - - `uvm_object_utils(riscv_hazard_instr_stream) - `uvm_object_new - - function void pre_randomize(); - avail_regs = new[num_of_avail_regs]; - super.pre_randomize(); - endfunction - -endclass - -// Use a small set of address to create various load/store hazard sequence -// This instruction stream focus more on hazard handling of load store unit. -class riscv_load_store_hazard_instr_stream extends riscv_load_store_base_instr_stream; - - rand int avail_addr[]; - - constraint legal_c { - num_load_store inside {[10:30]}; - num_mixed_instr inside {[10:30]}; - } - - constraint avail_addr_c { - avail_addr.size() inside {[1:3]}; - foreach(avail_addr[i]) { - avail_addr[i] inside {[0 : max_load_store_offset - 1]}; - } - } - - `uvm_object_utils(riscv_load_store_hazard_instr_stream) - `uvm_object_new - - // Randomize each address in the post_randomize to reduce the complexity of solving everything - // in one shot. - function void post_randomize(); - int temp_addr; - foreach(addr[i]) begin - `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(temp_addr, - temp_addr inside {avail_addr};, - "Cannot randomize address") - addr[i] = temp_addr; - end - endfunction -endclass - -// Back to back access to multiple data pages -// This is useful to test data TLB switch and replacement -class riscv_multi_page_load_store_instr_stream extends riscv_mem_access_stream; - - riscv_load_store_stress_instr_stream load_store_instr_stream[]; - rand int unsigned num_of_instr_stream; - rand int unsigned data_page_id[]; - rand riscv_reg_t rs1_reg[]; - - constraint default_c { - foreach(data_page_id[i]) { - data_page_id[i] < max_data_page_id; - } - data_page_id.size() == num_of_instr_stream; - rs1_reg.size() == num_of_instr_stream; - unique {rs1_reg}; - foreach(rs1_reg[i]) { - !(rs1_reg[i] inside {cfg.reserved_regs, ZERO}); - } - } - - constraint page_c { - solve num_of_instr_stream before data_page_id; - num_of_instr_stream inside {[1 : max_data_page_id]}; - unique {data_page_id}; - } - - // Avoid accessing a large number of pages because we may run out of registers for rs1 - // Each page access needs a reserved register as the base address of load/store instruction - constraint reasonable_c { - num_of_instr_stream inside {[2:8]}; - } - - `uvm_object_utils(riscv_multi_page_load_store_instr_stream) - `uvm_object_new - - // Generate each load/store seq, and mix them together - function void post_randomize(); - load_store_instr_stream = new[num_of_instr_stream]; - foreach(load_store_instr_stream[i]) begin - load_store_instr_stream[i] = riscv_load_store_stress_instr_stream::type_id:: - create($sformatf("load_store_instr_stream_%0d", i)); - load_store_instr_stream[i].min_instr_cnt = 5; - load_store_instr_stream[i].max_instr_cnt = 10; - load_store_instr_stream[i].cfg = cfg; - // Make sure each load/store sequence doesn't override the rs1 of other sequences. - foreach(rs1_reg[j]) begin - if(i != j) begin - load_store_instr_stream[i].reserved_rd = - {load_store_instr_stream[i].reserved_rd, rs1_reg[j]}; - end - end - `DV_CHECK_RANDOMIZE_WITH_FATAL(load_store_instr_stream[i], - rs1_reg == local::rs1_reg[i]; - data_page_id == local::data_page_id[i];, - "Cannot randomize load/store instruction") - // Mix the instruction stream of different page access, this could trigger the scenario of - // frequent data TLB switch - if(i == 0) begin - instr_list = load_store_instr_stream[i].instr_list; - end else begin - mix_instr_stream(load_store_instr_stream[i].instr_list); - end - end - endfunction - -endclass - -// Access the different locations of the same memory regions -class riscv_mem_region_stress_test extends riscv_multi_page_load_store_instr_stream; - - `uvm_object_utils(riscv_mem_region_stress_test) - `uvm_object_new - - constraint page_c { - num_of_instr_stream inside {[2:5]}; - foreach (data_page_id[i]) { - if (i > 0) { - data_page_id[i] == data_page_id[i-1]; - } - } - } - -endclass - -// Random load/store sequence to full address range -// The address range is not preloaded with data pages, use store instruction to initialize first -class riscv_load_store_rand_addr_instr_stream extends riscv_load_store_base_instr_stream; - - rand bit [XLEN-1:0] addr_offset; - - // Find an unused 4K page from address 1M onward - constraint addr_offset_c { - |addr_offset[XLEN-1:20] == 1'b1; - // TODO(taliu) Support larger address range - addr_offset[XLEN-1:31] == 0; - addr_offset[11:0] == 0; - } - - constraint legal_c { - num_load_store inside {[5:10]}; - num_mixed_instr inside {[5:10]}; - } - - `uvm_object_utils(riscv_load_store_rand_addr_instr_stream) - - virtual function void randomize_offset(); - int offset_, addr_; - offset = new[num_load_store]; - addr = new[num_load_store]; - for (int i=0; i 0; - // Avoid count to negative - loop_step_val[i] + loop_limit_val[i] > 0; - } else if (branch_type[i] == BLT) { - loop_step_val[i] > 0; - } else if (branch_type[i] == BLTU) { - loop_step_val[i] > 0; - loop_limit_val[i] > 0; - } - loop_init_val[i] inside {[-10:10]}; - loop_step_val[i] inside {[-10:10]}; - if(loop_init_val[i] < loop_limit_val[i]) { - loop_step_val[i] > 0; - } else { - loop_step_val[i] < 0; - } - } - } - - `uvm_object_utils(riscv_loop_instr) - `uvm_object_new - - function void post_randomize(); - reserved_rd = {loop_cnt_reg, loop_limit_reg}; - // Generate instructions that mixed with the loop instructions - initialize_instr_list(num_of_instr_in_loop); - gen_instr(1'b1); - // Randomize the key loop instructions - loop_init_instr = new[num_of_nested_loop*2]; - loop_update_instr = new[num_of_nested_loop]; - loop_branch_instr = new[num_of_nested_loop]; - loop_branch_target_instr = new[num_of_nested_loop]; - for(int i = 0; i < num_of_nested_loop; i++) begin - // Instruction to init the loop counter - loop_init_instr[2*i] = riscv_instr_base::type_id::create("loop_init_instr"); - `DV_CHECK_RANDOMIZE_WITH_FATAL(loop_init_instr[2*i], - instr_name == ADDI; - rd == loop_cnt_reg[i]; - rs1 == ZERO; - imm == loop_init_val[i];, - "Cannot randomize loop init insturction") - loop_init_instr[2*i].comment = $sformatf("init loop %0d counter", i); - - // Instruction to init loop limit - loop_init_instr[2*i+1] = riscv_instr_base::type_id::create("loop_init_instr"); - `DV_CHECK_RANDOMIZE_WITH_FATAL(loop_init_instr[2*i+1], - instr_name == ADDI; - rd == loop_limit_reg[i]; - rs1 == ZERO; - imm == loop_limit_val[i];, - "Cannot randomize init loop instruction") - loop_init_instr[2*i+1].comment = $sformatf("init loop %0d limit", i); - - // Branch target instruction, can be anything - loop_branch_target_instr[i] = riscv_rand_instr::type_id::create("loop_branch_target_instr"); - loop_branch_target_instr[i].cfg = cfg; - loop_branch_target_instr[i].reserved_rd = reserved_rd; - `DV_CHECK_RANDOMIZE_WITH_FATAL(loop_branch_target_instr[i], - !(category inside {LOAD, STORE, BRANCH, JUMP}); - // TODO: allow CSR instructions in all modes - if (cfg.init_privileged_mode == MACHINE_MODE) { - if (category == CSR) { - csr == MSCRATCH; - } - } else { - !(category == CSR); - }, - "Cannot randomize branch target instruction") - loop_branch_target_instr[i].label = $sformatf("%0s_%0d_t", label, i); - - // Instruction to update loop counter - loop_update_instr[i] = riscv_instr_base::type_id::create("loop_update_instr"); - `DV_CHECK_RANDOMIZE_WITH_FATAL(loop_update_instr[i], - instr_name == ADDI; - rd == loop_cnt_reg[i]; - rs1== loop_cnt_reg[i]; - imm == loop_step_val[i];, - "Cannot randomize loop update instruction") - loop_update_instr[i].comment = $sformatf("update loop %0d counter", i); - - // Backward branch instruction - loop_branch_instr[i] = riscv_instr_base::type_id::create("loop_branch_instr"); - `DV_CHECK_RANDOMIZE_WITH_FATAL(loop_branch_instr[i], - instr_name == branch_type[i]; - rs1 == loop_cnt_reg[i]; - if (!(branch_type[i] inside {C_BEQZ, C_BNEZ})) { - rs2 == loop_limit_reg[i]; - }, - "Cannot randomize backward branch instruction") - loop_branch_instr[i].comment = $sformatf("branch for loop %0d", i); - loop_branch_instr[i].imm_str = loop_branch_target_instr[i].label; - loop_branch_instr[i].branch_assigned = 1'b1; - end - // Randomly distribute the loop instruction in the existing instruction stream - build_loop_instr_stream(); - mix_instr_stream(loop_instr, 1'b1); - foreach(instr_list[i]) begin - if(instr_list[i].label != "") - instr_list[i].has_label = 1'b1; - else - instr_list[i].has_label = 1'b0; - instr_list[i].atomic = 1'b1; - end - endfunction - - // Build the whole loop structure from innermost loop to the outermost loop - function void build_loop_instr_stream(); - loop_instr.delete; - for(int i = 0; i < num_of_nested_loop; i++) begin - loop_instr = {loop_init_instr[2*i], - loop_init_instr[2*i+1], - loop_branch_target_instr[i], - loop_update_instr[i], - loop_instr, - loop_branch_instr[i]}; - end - `uvm_info(get_full_name(), $sformatf("Totally %0d instructions have been added", - loop_instr.size()), UVM_HIGH) - endfunction -endclass diff --git a/vendor/google_riscv-dv/src/deprecated/riscv_rand_instr.sv b/vendor/google_riscv-dv/src/deprecated/riscv_rand_instr.sv deleted file mode 100644 index e31e9467..00000000 --- a/vendor/google_riscv-dv/src/deprecated/riscv_rand_instr.sv +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2018 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. - */ - -class riscv_rand_instr extends riscv_instr_base; - - riscv_instr_gen_config cfg; - - // Some additional reserved registers - riscv_reg_t reserved_rd[]; - - `uvm_object_utils(riscv_rand_instr) - - constraint category_c { - soft category inside {LOAD, STORE, SHIFT, ARITHMETIC, LOGICAL, - BRANCH, COMPARE, CSR, SYSTEM, SYNCH}; - } - - // Atomic extension instructions are default disabled - // AMO instruction generation is handled by riscv_amo_instr_lib.sv - constraint disable_a_extension_c { - group != RV32A; - group != RV64A; - } - - constraint instr_c { - solve instr_name before imm; - solve instr_name before rs1; - solve instr_name before rs2; - !(instr_name inside {riscv_instr_pkg::unsupported_instr}); - group inside {riscv_instr_pkg::supported_isa}; - // Avoid using any special purpose register as rd, those registers are reserved for - // special instructions - !(rd inside {cfg.reserved_regs}); - if(reserved_rd.size() > 0) { - !(rd inside {reserved_rd}); - } - // Compressed instruction may use the same CSR for both rs1 and rd - if(group inside {RV32C, RV64C, RV128C, RV32FC, RV32DC}) { - !(rs1 inside {cfg.reserved_regs, reserved_rd}); - } - // Below instrutions will modify stack pointer, not allowed in normal instruction stream. - // It can be used in stack operation instruction stream. - !(instr_name inside {C_SWSP, C_SDSP, C_ADDI16SP}); - // Avoid using reserved registers as rs1 (base address) - if(category inside {LOAD, STORE}) { - !(rs1 inside {reserved_rd, cfg.reserved_regs, ZERO}); - } - if(!cfg.enable_sfence) { - instr_name != SFENCE_VMA; - } - if(cfg.no_fence) { - !(instr_name inside {FENCE, FENCE_I, SFENCE_VMA}); - } - // TODO: Support C_ADDI4SPN - instr_name != C_ADDI4SPN; - } - - constraint constraint_cfg_knob_c { - if(cfg.no_ebreak) { - instr_name != EBREAK; - instr_name != C_EBREAK; - } - if(cfg.no_wfi) { - instr_name != WFI; - } - if(cfg.no_dret) { - instr_name != DRET; - } - // Below previleged instruction is not generated by default - !(instr_name inside {ECALL, URET, SRET, MRET}); - if(cfg.no_load_store) { - category != LOAD; - category != STORE; - } - if(cfg.no_branch_jump) { - category != BRANCH; - } - if (cfg.disable_compressed_instr) { - !(group inside {RV32C, RV64C, RV128C, RV32FC, RV32DC}); - } - } - - constraint csr_instr_c { - // TODO: support CSR instruction in other modes - if(cfg.no_csr_instr) { - category != CSR; - } else { - if (category == CSR) { - if (cfg.enable_illegal_csr_instruction) { - !(csr inside {implemented_csr}); - } else if (cfg.enable_access_invalid_csr_level) { - csr inside {cfg.invalid_priv_mode_csrs}; - } else { - // Use scratch register to avoid the side effect of modifying other privileged mode CSR. - if (cfg.init_privileged_mode == MACHINE_MODE) { - if (MSCRATCH inside {implemented_csr}) { - csr == MSCRATCH; - } - } else if (cfg.init_privileged_mode == SUPERVISOR_MODE) { - if (SSCRATCH inside {implemented_csr}) { - csr == SSCRATCH; - } - } else { - if (USCRATCH inside {implemented_csr}) { - csr == USCRATCH; - } - } - } - } - } - } - - constraint floating_point_c { - if (!cfg.enable_floating_point) { - !(group inside {RV32F, RV64F, RV32D, RV64D}); - } - } - - function void pre_randomize(); - if (!cfg.enable_floating_point) begin - fs1.rand_mode(0); - fs2.rand_mode(0); - fs3.rand_mode(0); - fd.rand_mode(0); - end - endfunction - - // No label is needed if there's no branch/jump instruction - function void post_randomize(); - super.post_randomize(); - if (cfg.no_branch_jump) begin - has_label = 1'b0; - end - endfunction - - `uvm_object_new - -endclass diff --git a/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv b/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv index 5b8dcdcd..2777337c 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_cov_item.sv @@ -1,4 +1,4 @@ -class riscv_instr_cov_item extends `INSTR; +class riscv_instr_cov_item extends riscv_instr; typedef enum bit[1:0] { POSITIVE, NEGATIVE 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 13a6b87f..72fef81d 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv @@ -1315,17 +1315,9 @@ class riscv_instr_cover_group; riscv_instr_name_t instr_name; instr_name = instr_name.first; do begin - `INSTR instr; + riscv_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 + instr = riscv_instr::create_instr(instr_name); if ((instr.group inside {supported_isa}) && (instr.group inside {RV32I, RV32M, RV64M, RV64I, RV32C, RV64C, RV32V, RV64V, RV64B, RV32B})) begin diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index e2cfee5f..9b06e945 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -1080,40 +1080,33 @@ package riscv_instr_pkg; SYNCH, SYSTEM, COUNTER, CSR, CHANGELEVEL, TRAP, INTERRUPT, AMO }; - `include "riscv_vector_cfg.sv" - `ifdef DEPRECATED - `define INSTR riscv_instr_base - `include "deprecated/riscv_instr_base.sv" - `include "deprecated/riscv_instr_gen_config.sv" - `else - `define INSTR riscv_instr - typedef class riscv_instr; - `include "riscv_instr_gen_config.sv" - `include "isa/riscv_instr.sv" - `include "isa/riscv_amo_instr.sv" - `include "isa/riscv_floating_point_instr.sv" - `include "isa/riscv_vector_instr.sv" - `include "isa/riscv_compressed_instr.sv" - `include "isa/rv32a_instr.sv" - `include "isa/rv32c_instr.sv" - `include "isa/rv32dc_instr.sv" - `include "isa/rv32d_instr.sv" - `include "isa/rv32fc_instr.sv" - `include "isa/rv32f_instr.sv" - `include "isa/rv32i_instr.sv" - `include "isa/rv32m_instr.sv" - `include "isa/rv64a_instr.sv" - `include "isa/rv64c_instr.sv" - `include "isa/rv64d_instr.sv" - `include "isa/rv64f_instr.sv" - `include "isa/rv64i_instr.sv" - `include "isa/rv64m_instr.sv" - `include "isa/rv128c_instr.sv" - `include "isa/rv32v_instr.sv" - `include "isa/custom/riscv_custom_instr.sv" - `include "isa/custom/rv32x_instr.sv" - `include "isa/custom/rv64x_instr.sv" - `endif + `include "riscv_vector_cfg.sv" + typedef class riscv_instr; + `include "riscv_instr_gen_config.sv" + `include "isa/riscv_instr.sv" + `include "isa/riscv_amo_instr.sv" + `include "isa/riscv_floating_point_instr.sv" + `include "isa/riscv_vector_instr.sv" + `include "isa/riscv_compressed_instr.sv" + `include "isa/rv32a_instr.sv" + `include "isa/rv32c_instr.sv" + `include "isa/rv32dc_instr.sv" + `include "isa/rv32d_instr.sv" + `include "isa/rv32fc_instr.sv" + `include "isa/rv32f_instr.sv" + `include "isa/rv32i_instr.sv" + `include "isa/rv32m_instr.sv" + `include "isa/rv64a_instr.sv" + `include "isa/rv64c_instr.sv" + `include "isa/rv64d_instr.sv" + `include "isa/rv64f_instr.sv" + `include "isa/rv64i_instr.sv" + `include "isa/rv64m_instr.sv" + `include "isa/rv128c_instr.sv" + `include "isa/rv32v_instr.sv" + `include "isa/custom/riscv_custom_instr.sv" + `include "isa/custom/rv32x_instr.sv" + `include "isa/custom/rv64x_instr.sv" `include "riscv_pseudo_instr.sv" `include "riscv_illegal_instr.sv" @@ -1127,20 +1120,11 @@ package riscv_instr_pkg; `include "riscv_callstack_gen.sv" `include "riscv_data_page_gen.sv" -`ifdef DEPRECATED - `include "deprecated/riscv_rand_instr.sv" - `include "deprecated/riscv_instr_stream.sv" - `include "deprecated/riscv_loop_instr.sv" - `include "deprecated/riscv_directed_instr_lib.sv" - `include "deprecated/riscv_load_store_instr_lib.sv" - `include "deprecated/riscv_amo_instr_lib.sv" -`else `include "riscv_instr_stream.sv" `include "riscv_loop_instr.sv" `include "riscv_directed_instr_lib.sv" `include "riscv_load_store_instr_lib.sv" `include "riscv_amo_instr_lib.sv" -`endif `include "riscv_instr_sequence.sv" `include "riscv_asm_program_gen.sv" diff --git a/vendor/google_riscv-dv/src/riscv_instr_stream.sv b/vendor/google_riscv-dv/src/riscv_instr_stream.sv index cea93dc5..473e8d83 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_stream.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_stream.sv @@ -20,7 +20,7 @@ // instruction, mix two instruction streams etc. class riscv_instr_stream extends uvm_object; - `INSTR instr_list[$]; + riscv_instr instr_list[$]; int unsigned instr_cnt; string label = ""; // User can specify a small group of available registers to generate various hazard condition @@ -40,16 +40,16 @@ class riscv_instr_stream extends uvm_object; endfunction virtual function void create_instr_instance(); - `INSTR instr; + riscv_instr instr; for(int i = 0; i < instr_cnt; i++) begin - instr = `INSTR::type_id::create($sformatf("instr_%0d", i)); + instr = riscv_instr::type_id::create($sformatf("instr_%0d", i)); instr_list.push_back(instr); end endfunction // Insert an instruction to the existing instruction stream at the given index // When index is -1, the instruction is injected at a random location - function void insert_instr(`INSTR instr, int idx = -1); + function void insert_instr(riscv_instr instr, int idx = -1); int current_instr_cnt = instr_list.size(); if(idx == -1) begin idx = $urandom_range(0, current_instr_cnt-1); @@ -70,7 +70,7 @@ class riscv_instr_stream extends uvm_object; // Insert an instruction to the existing instruction stream at the given index // When index is -1, the instruction is injected at a random location // When replace is 1, the original instruction at the inserted position will be replaced - function void insert_instr_stream(`INSTR new_instr[], int idx = -1, bit replace = 1'b0); + function void insert_instr_stream(riscv_instr new_instr[], int idx = -1, bit replace = 1'b0); int current_instr_cnt = instr_list.size(); int new_instr_cnt = new_instr.size(); if(current_instr_cnt == 0) begin @@ -119,7 +119,7 @@ class riscv_instr_stream extends uvm_object; // Mix the input instruction stream with the original instruction, the instruction order is // preserved. When 'contained' is set, the original instruction stream will be inside the // new instruction stream with the first and last instruction from the input instruction stream. - function void mix_instr_stream(`INSTR new_instr[], bit contained = 1'b0); + function void mix_instr_stream(riscv_instr new_instr[], bit contained = 1'b0); int current_instr_cnt = instr_list.size(); int insert_instr_position[]; int new_instr_cnt = new_instr.size(); @@ -167,7 +167,7 @@ class riscv_rand_instr_stream extends riscv_instr_stream; `uvm_object_new virtual function void create_instr_instance(); - `INSTR instr; + riscv_instr instr; for (int i = 0; i < instr_cnt; i++) begin instr_list.push_back(null); end diff --git a/vendor/google_riscv-dv/src/riscv_pseudo_instr.sv b/vendor/google_riscv-dv/src/riscv_pseudo_instr.sv index 6423be4e..181b2fdd 100644 --- a/vendor/google_riscv-dv/src/riscv_pseudo_instr.sv +++ b/vendor/google_riscv-dv/src/riscv_pseudo_instr.sv @@ -1,5 +1,5 @@ // Psuedo instructions are used to simplify assembly program writing -class riscv_pseudo_instr extends `INSTR; +class riscv_pseudo_instr extends riscv_instr; rand riscv_pseudo_instr_name_t pseudo_instr_name; diff --git a/vendor/google_riscv-dv/test/riscv_instr_base_test.sv b/vendor/google_riscv-dv/test/riscv_instr_base_test.sv index 1de3d875..5063d46d 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_base_test.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_base_test.sv @@ -80,17 +80,10 @@ class riscv_instr_base_test extends uvm_test; task run_phase(uvm_phase phase); int fd; - `ifdef DEPRECATED - cfg.build_instruction_template(); - `endif for(int i = 0; i < cfg.num_of_tests; i++) begin string test_name; randomize_cfg(); - `ifdef DEPRECATED - cfg.build_instruction_list(); - `else - riscv_instr::create_instr_list(cfg); - `endif + riscv_instr::create_instr_list(cfg); asm_gen = riscv_asm_program_gen::type_id::create("asm_gen", , `gfn); asm_gen.cfg = cfg; asm_gen.get_directed_instr_stream(); 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 f13d2826..cfbb3184 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv @@ -39,17 +39,9 @@ class riscv_instr_cov_test extends uvm_test; cfg = riscv_instr_gen_config::type_id::create("cfg"); // disable_compressed_instr is not relevant to coverage test cfg.disable_compressed_instr = 0; - `ifdef DEPRECATED - cfg.build_instruction_template(.skip_instr_exclusion(1)); - `else - riscv_instr::create_instr_list(cfg); - `endif + riscv_instr::create_instr_list(cfg); instr = riscv_instr_cov_item::type_id::create("instr"); instr.rand_mode(0); - `ifdef DEPRECATED - instr.no_hint_illegal_instr_c.constraint_mode(0); - instr.imm_val_c.constraint_mode(0); - `endif 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 @@ -142,13 +134,8 @@ class riscv_instr_cov_test extends uvm_test; `SAMPLE(instr_cg.opcode_cg, binary[6:2]) end if (instr_enum::from_name(process_instr_name(trace["instr"]), instr_name)) begin - `ifdef DEPRECATED - if (cfg.instr_template.exists(instr_name)) begin - instr.copy_base_instr(cfg.instr_template[instr_name]); - `else if (riscv_instr::instr_template.exists(instr_name)) begin instr.copy(riscv_instr::instr_template[instr_name]); - `endif if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C}) begin assign_trace_info_to_instr(instr); end diff --git a/vendor/google_riscv-dv/yaml/base_testlist.yaml b/vendor/google_riscv-dv/yaml/base_testlist.yaml index 094a9f98..1ef0d206 100644 --- a/vendor/google_riscv-dv/yaml/base_testlist.yaml +++ b/vendor/google_riscv-dv/yaml/base_testlist.yaml @@ -22,6 +22,7 @@ # no_iss : Enable/disable ISS simulator (Optional) # gen_test : Test name used by the instruction generator # asm_tests : Path to directed, hand-coded assembly test file or directory +# c_tests : Path to directed, hand-coded C test file or directory # rtl_test : RTL simulation test name # cmp_opts : Compile options passed to the instruction generator # sim_opts : Simulation options passed to the instruction generator diff --git a/vendor/google_riscv-dv/yaml/simulator.yaml b/vendor/google_riscv-dv/yaml/simulator.yaml index 09313c30..d0a214b1 100644 --- a/vendor/google_riscv-dv/yaml/simulator.yaml +++ b/vendor/google_riscv-dv/yaml/simulator.yaml @@ -68,7 +68,6 @@ cov_opts: > -do "coverage save -onexit /cov.ucdb;" -# TODO: Remove +DEPRECATED for dsim - tool: dsim env_var: DSIM,DSIM_LIB_PATH compile: @@ -77,7 +76,6 @@ - " -sv -work /dsim -genimage image +incdir+$UVM_HOME/src - +define+DEPRECATED $UVM_HOME/src/uvm_pkg.sv +define+DSIM +incdir+