diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index 26ef72ce..21ded156 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: 6bd323385d454858ea5e50dedd42a563b37931fe + rev: 4583049cc2b3469ba9dea56b5e2d75809a89d8f3 } } diff --git a/vendor/google_riscv-dv/docs/source/configuration.rst b/vendor/google_riscv-dv/docs/source/configuration.rst index d458ad81..398a0f4b 100644 --- a/vendor/google_riscv-dv/docs/source/configuration.rst +++ b/vendor/google_riscv-dv/docs/source/configuration.rst @@ -145,57 +145,73 @@ You can also add directed assembly/C test in the testlist Runtime options of the generator -------------------------------- -+-----------------------------+---------------------------------------------------+---------+ -| Option | Description | Default | -+=============================+===================================================+=========+ -| num_of_tests | Number of assembly tests to be generated | 1 | -+-----------------------------+---------------------------------------------------+---------+ -| num_of_sub_program | Number of sub-program in one test | 5 | -+-----------------------------+---------------------------------------------------+---------+ -| instr_cnt | Instruction count per test | 200 | -+-----------------------------+---------------------------------------------------+---------+ -| enable_page_table_exception | Enable page table exception | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| enable_unaligned_load_store | Enable unaligned memory operations | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| no_ebreak | Disable ebreak instruction | 1 | -+-----------------------------+---------------------------------------------------+---------+ -| no_wfi | Disable WFI instruction | 1 | -+-----------------------------+---------------------------------------------------+---------+ -| no_dret | Disable dret instruction | 1 | -+-----------------------------+---------------------------------------------------+---------+ -| no_branch_jump | Disable branch/jump instruction | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| no_load_store | Disable load/store instruction | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| no_csr_instr | Disable CSR instruction | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| no_fence | Disable fence instruction | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| illegal_instr_ratio | Number of illegal instructions every 1000 instr | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| hint_instr_ratio | Number of HINT instructions every 1000 instr | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| boot_mode | m:Machine mode, s:Supervisor mode, u:User mode | m | -+-----------------------------+---------------------------------------------------+---------+ -| no_directed_instr | Disable directed instruction stream | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| require_signature_addr | Set to 1 if test needs to talk to testbench | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| signature_addr | Write to this addr to send data to testbench | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| enable_interrupt | Enable MStatus.MIE, used in interrupt test | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| gen_debug_section | Disables randomized debug_rom section | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| num_debug_sub_program | Number of debug sub-programs in test | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| enable_ebreak_in_debug_rom | Generate ebreak instructions inside debug ROM | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| set_dcsr_ebreak | Randomly enable dcsr.ebreak(m/s/u) | 0 | -+-----------------------------+---------------------------------------------------+---------+ -| randomize_csr | Fully randomize main CSRs (xSTATUS, xIE) | 0 | -+-----------------------------+---------------------------------------------------+---------+ ++---------------------------------+---------------------------------------------------+---------+ +| Option | Description | Default | ++=================================+===================================================+=========+ +| num_of_tests | Number of assembly tests to be generated | 1 | ++---------------------------------+---------------------------------------------------+---------+ +| num_of_sub_program | Number of sub-program in one test | 5 | ++---------------------------------+---------------------------------------------------+---------+ +| instr_cnt | Instruction count per test | 200 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_page_table_exception | Enable page table exception | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_unaligned_load_store | Enable unaligned memory operations | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| no_ebreak | Disable ebreak instruction | 1 | ++---------------------------------+---------------------------------------------------+---------+ +| no_wfi | Disable WFI instruction | 1 | ++---------------------------------+---------------------------------------------------+---------+ +| set_mstatus_tw | Enable WFI to be treated as illegal instruction | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| no_dret | Disable dret instruction | 1 | ++---------------------------------+---------------------------------------------------+---------+ +| no_branch_jump | Disable branch/jump instruction | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| no_csr_instr | Disable CSR instruction | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_illegal_csr_instruction | Enable illegal CSR instructions | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_access_invalid_csr_level | Enable accesses to higher privileged CSRs | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_dummy_csr_write | Enable some dummy CSR writes in setup routine | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_misaligned_instr | Enable jumps to misaligned instruction addresses | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| no_fence | Disable fence instruction | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| no_data_page | Disable data page generation | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| disable_compressed_instr | Disable compressed instruction generation | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| illegal_instr_ratio | Number of illegal instructions every 1000 instr | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| hint_instr_ratio | Number of HINT instructions every 1000 instr | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| boot_mode | m:Machine mode, s:Supervisor mode, u:User mode | m | ++---------------------------------+---------------------------------------------------+---------+ +| no_directed_instr | Disable directed instruction stream | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| require_signature_addr | Set to 1 if test needs to talk to testbench | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| signature_addr | Write to this addr to send data to testbench | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_interrupt | Enable MStatus.MIE, used in interrupt test | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_timer_irq | Enable xIE.xTIE, used to enable timer interrupts | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| gen_debug_section | Enables randomized debug_rom section | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| num_debug_sub_program | Number of debug sub-programs in test | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_ebreak_in_debug_rom | Generate ebreak instructions inside debug ROM | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| set_dcsr_ebreak | Randomly enable dcsr.ebreak(m/s/u) | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| enable_debug_single_step | Enable debug single stepping functionality | 0 | ++---------------------------------+---------------------------------------------------+---------+ +| randomize_csr | Fully randomize main CSRs (xSTATUS, xIE) | 0 | ++---------------------------------+---------------------------------------------------+---------+ Setup Privileged CSR description (optional) ------------------------------------------- diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index 1650de2d..9e1a6af1 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -135,7 +135,7 @@ def get_iss_cmd(base_cmd, elf, log): def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, - cmp_opts, output_dir, debug_cmd): + cmp_opts, output_dir, debug_cmd, lsf_cmd): """Compile the instruction generator Args: @@ -147,6 +147,7 @@ def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, cmd_opts : Compile options for the generator output_dir : Output directory of the ELF files debug_cmd : Produce the debug cmd log without running + lsf_cmd : LSF command used to run the instruction generator """ if (not((len(test_list) == 1) and (test_list[0]['test'] == 'riscv_csr_test'))): logging.info("Building RISC-V instruction generator") @@ -159,9 +160,12 @@ def do_compile(compile_cmd, test_list, core_setting_dir, cwd, ext_dir, cmd = re.sub("", ext_dir, cmd) cmd = re.sub("", cwd, cmd) cmd = re.sub("", cmp_opts, cmd) - - logging.debug("Compile command: %s" % cmd) - run_cmd(cmd, debug_cmd = debug_cmd) + if lsf_cmd: + cmd = lsf_cmd + " " + cmd + run_parallel_cmd([cmd], debug_cmd = debug_cmd) + else: + 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, @@ -296,7 +300,7 @@ def gen(test_list, cfg, output_dir, cwd): # Compile the instruction generator if not argv.so: do_compile(compile_cmd, test_list, argv.core_setting_dir, cwd, argv.user_extension_dir, - argv.cmp_opts, output_dir, argv.debug) + argv.cmp_opts, output_dir, argv.debug, argv.lsf_cmd) # Run the instruction generator if not argv.co: do_simulate(sim_cmd, test_list, cwd, argv.sim_opts, argv.seed_yaml, argv.seed, argv.csr_yaml, @@ -765,6 +769,9 @@ def load_config(args, cwd): if args.target == "rv32imc": args.mabi = "ilp32" args.isa = "rv32imc" + elif args.target == "multi_harts": + args.mabi = "ilp32" + args.isa = "rv32gc" elif args.target == "rv32i": args.mabi = "ilp32" args.isa = "rv32i" diff --git a/vendor/google_riscv-dv/scripts/gen_csr_test.py b/vendor/google_riscv-dv/scripts/gen_csr_test.py index bc1ca421..84c4fce9 100644 --- a/vendor/google_riscv-dv/scripts/gen_csr_test.py +++ b/vendor/google_riscv-dv/scripts/gen_csr_test.py @@ -225,7 +225,7 @@ def gen_csr_test_fail(test_file, end_addr): test_file.write(f"\tli x1, {TEST_FAIL}\n") test_file.write(f"\tslli x1, x1, 8\n") test_file.write(f"\taddi x1, x1, {TEST_RESULT}\n") - test_file.write(f"\tli x2, {end_addr}\n") + test_file.write(f"\tli x2, 0x{end_addr}\n") test_file.write(f"\tsw x1, 0(x2)\n") test_file.write(f"\tj csr_fail\n") @@ -244,7 +244,7 @@ def gen_csr_test_pass(test_file, end_addr): test_file.write(f"\tli x1, {TEST_PASS}\n") test_file.write(f"\tslli x1, x1, 8\n") test_file.write(f"\taddi x1, x1, {TEST_RESULT}\n") - test_file.write(f"\tli x2, {end_addr}\n") + test_file.write(f"\tli x2, 0x{end_addr}\n") test_file.write(f"\tsw x1, 0(x2)\n") test_file.write(f"\tj csr_pass\n") @@ -318,28 +318,42 @@ def gen_csr_instr(original_csr_map, csr_instructions, xlen, gen_csr_test_fail(csr_test_file, end_signature_addr) -""" -Define command line arguments. -""" -parser = argparse.ArgumentParser() -parser.add_argument("--csr_file", type=str, default="yaml/csr_template.yaml", - help="The YAML file contating descriptions of all processor supported CSRs") -parser.add_argument("--xlen", type=int, default=32, - help="Specify the ISA width, e.g. 32 or 64 or 128") -parser.add_argument("--iterations", type=int, default=1, - help="Specify how many tests to be generated") -parser.add_argument("--out", type=str, default="./", - help="Specify output directory") -parser.add_argument("--end_signature_addr", type=str, default="0", - help="Address that should be written to at end of this test") -args = parser.parse_args() +def main(): + """Main entry point of CSR test generation script. + Will set up a list of all supported CSR instructions, + and seed the RNG.""" + + # define command line arguments + parser = argparse.ArgumentParser() + parser.add_argument("--csr_file", type=str, default="yaml/csr_template.yaml", + help="The YAML file contating descriptions of all processor supported CSRs") + parser.add_argument("--xlen", type=int, default=32, + help="Specify the ISA width, e.g. 32 or 64 or 128") + parser.add_argument("--iterations", type=int, default=1, + help="Specify how many tests to be generated") + parser.add_argument("--out", type=str, default="./", + help="Specify output directory") + parser.add_argument("--end_signature_addr", type=str, default="0", + help="Address that should be written to at end of this test") + parser.add_argument("--seed", type=int, default=None, + help="""Value used to seed the random number generator. If no value is passed in, + the RNG will be seeded from an internal source of randomness.""") + args = parser.parse_args() + + """All supported CSR operations""" + csr_ops = ['csrrw', 'csrrs', 'csrrc', 'csrrwi', 'csrrsi', 'csrrci'] + + """ + Seed the RNG. + If args.seed is None, seed will be drawn from some internal random source. + If args.seed is defined, this will be used to seed the RNG for user reproducibility. + """ + random.seed(args.seed) + + gen_csr_instr(get_csr_map(args.csr_file, args.xlen), + csr_ops, args.xlen, args.iterations, args.out, + args.end_signature_addr) -""" -A list containing all supported CSR instructions. -""" -csr_ops = ['csrrw', 'csrrs', 'csrrc', 'csrrwi', 'csrrsi', 'csrrci'] - -gen_csr_instr(get_csr_map(args.csr_file, args.xlen), - csr_ops, args.xlen, args.iterations, args.out, - args.end_signature_addr) +if __name__ == "__main__": + main() diff --git a/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv b/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv index 67ffbd89..8464aa5d 100644 --- a/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv +++ b/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv @@ -50,6 +50,21 @@ class riscv_amo_base_instr_stream extends riscv_mem_access_stream; super.new(name); endfunction + function void pre_randomize(); + data_page = cfg.amo_region; + 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; + la_instr.imm_str = $sformatf("%0s+%0d", cfg.amo_region[id].name, base); + instr_list.push_front(la_instr); + endfunction + function void post_randomize(); gen_amo_instr(); // rs1 cannot be modified by other instructions diff --git a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv index dec34500..ae18ede0 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -27,8 +27,8 @@ class riscv_asm_program_gen extends uvm_object; riscv_instr_gen_config cfg; riscv_data_page_gen data_page_gen; // User mode programs - riscv_instr_sequence main_program; - riscv_instr_sequence sub_program[]; + riscv_instr_sequence main_program[NUM_HARTS]; + riscv_instr_sequence sub_program[NUM_HARTS][]; riscv_asm_program_gen debug_rom; // Kernel programs // These programs are called in the interrupt/exception handling routine based on the privileged @@ -47,6 +47,7 @@ class riscv_asm_program_gen extends uvm_object; // Directed instruction ratio, occurance per 1000 instructions int unsigned directed_instr_stream_ratio[string]; riscv_page_table_list#(SATP_MODE) page_table_list; + int hart; `uvm_object_utils(riscv_asm_program_gen) @@ -60,120 +61,149 @@ class riscv_asm_program_gen extends uvm_object; // This is the main function to generate all sections of the program. virtual function void gen_program(); - string sub_program_name[$]; instr_stream.delete(); // Generate program header gen_program_header(); - // Initialize general purpose registers - init_gpr(); - if (!cfg.bare_program_mode) begin - setup_misa(); - // Create all page tables - create_page_table(); - // Setup privileged mode registers and enter target privileged mode - pre_enter_privileged_mode(); - end - // Init section - gen_init_section(); - // Generate sub program - gen_sub_program(sub_program, sub_program_name, cfg.num_of_sub_program); - // Generate main program - main_program = riscv_instr_sequence::type_id::create("main_program"); - main_program.instr_cnt = cfg.main_program_instr_cnt; - main_program.is_debug_program = 0; - main_program.label_name = "_main"; - generate_directed_instr_stream(.label("main"), - .original_instr_cnt(main_program.instr_cnt), - .min_insert_cnt(1), - .instr_stream(main_program.directed_instr)); - main_program.cfg = cfg; - `DV_CHECK_RANDOMIZE_FATAL(main_program) - main_program.gen_instr(.is_main_program(1), .no_branch(cfg.no_branch_jump)); - // Setup jump instruction among main program and sub programs - gen_callstack(main_program, sub_program, sub_program_name, cfg.num_of_sub_program); - `uvm_info(`gfn, "Generating callstack...done", UVM_LOW) - main_program.post_process_instr(); - `uvm_info(`gfn, "Post-processing main program...done", UVM_LOW) - main_program.generate_instr_stream(); - `uvm_info(`gfn, "Generating main program instruction stream...done", UVM_LOW) - instr_stream = {instr_stream, main_program.instr_string_list}; - // Test done section - gen_test_done(); - // Shuffle the sub programs and insert to the instruction stream - insert_sub_program(sub_program, instr_stream); - `uvm_info(`gfn, "Inserting sub-programs...done", UVM_LOW) - `uvm_info(`gfn, "Main/sub program generation...done", UVM_LOW) - // Program end - gen_program_end(); - if (!cfg.bare_program_mode) begin - // Privileged mode switch routine - gen_privileged_mode_switch_routine(); - // Generate debug rom section - if (riscv_instr_pkg::support_debug_mode) begin - gen_debug_rom(); + for (int hart = 0; hart < cfg.num_of_harts; hart++) begin + string sub_program_name[$]; + instr_stream.push_back($sformatf("h%0d_start:", hart)); + if (!cfg.bare_program_mode) begin + setup_misa(); + // Create all page tables + create_page_table(hart); + // Setup privileged mode registers and enter target privileged mode + pre_enter_privileged_mode(hart); end + // Init section + gen_init_section(hart); + // If PMP is supported, we want to generate the associated trap handlers and the test_done + // section at the start of the program so we can allow access through the pmpcfg0 CSR + if (support_pmp) begin + gen_trap_handlers(hart); + // Ecall handler + gen_ecall_handler(hart); + // Instruction fault handler + gen_instr_fault_handler(hart); + // Load fault handler + gen_load_fault_handler(hart); + // Store fault handler + gen_store_fault_handler(hart); + gen_test_done(); + end + // Generate sub program + gen_sub_program(hart, sub_program[hart], sub_program_name, cfg.num_of_sub_program); + // Generate main program + main_program[hart] = riscv_instr_sequence::type_id::create(get_label("main", hart)); + main_program[hart].instr_cnt = cfg.main_program_instr_cnt; + main_program[hart].is_debug_program = 0; + main_program[hart].label_name = main_program[hart].get_name(); + generate_directed_instr_stream(.hart(hart), + .label(main_program[hart].label_name), + .original_instr_cnt(main_program[hart].instr_cnt), + .min_insert_cnt(1), + .instr_stream(main_program[hart].directed_instr)); + main_program[hart].cfg = cfg; + `DV_CHECK_RANDOMIZE_FATAL(main_program[hart]) + main_program[hart].gen_instr(.is_main_program(1), .no_branch(cfg.no_branch_jump)); + // Setup jump instruction among main program and sub programs + gen_callstack(main_program[hart], sub_program[hart], sub_program_name, cfg.num_of_sub_program); + `uvm_info(`gfn, "Generating callstack...done", UVM_LOW) + main_program[hart].post_process_instr(); + `uvm_info(`gfn, "Post-processing main program...done", UVM_LOW) + main_program[hart].generate_instr_stream(); + `uvm_info(`gfn, "Generating main program instruction stream...done", UVM_LOW) + instr_stream = {instr_stream, main_program[hart].instr_string_list}; + // If PMP is supported, need to jump from end of main program to test_done section at the end + // of main_program, as the test_done will have moved to the beginning of the program + instr_stream = {instr_stream, $sformatf("%sj test_done", indent)}; + // Test done section + // If PMP isn't supported, generate this in the normal location + if (hart == 0 & !support_pmp) begin + gen_test_done(); + end + // Shuffle the sub programs and insert to the instruction stream + insert_sub_program(sub_program[hart], instr_stream); + `uvm_info(`gfn, "Inserting sub-programs...done", UVM_LOW) + `uvm_info(`gfn, "Main/sub program generation...done", UVM_LOW) + // Program end + gen_program_end(hart); + if (!cfg.bare_program_mode) begin + // Privileged mode switch routine + gen_privileged_mode_switch_routine(hart); + // Generate debug rom section + if (riscv_instr_pkg::support_debug_mode) begin + gen_debug_rom(hart); + end + end + gen_section({hart_prefix(hart), "instr_end"}, {"nop"}); end - // Starting point of data section - gen_data_page_begin(); - // Page table - if (!cfg.bare_program_mode) begin - gen_page_table_section(); - end - if(!cfg.no_data_page) begin - // Kernel data section - gen_data_page(); - end - gen_data_page_end(); - // Stack section - gen_stack_section(); - if (!cfg.bare_program_mode) begin - // Generate kernel program/data/stack section - gen_kernel_sections(); + for (int hart = 0; hart < cfg.num_of_harts; hart++) begin + // Starting point of data section + gen_data_page_begin(hart); + if(!cfg.no_data_page) begin + // User data section + gen_data_page(hart); + // AMO memory region + if ((hart == 0) && (RV32A inside {supported_isa})) begin + gen_data_page(hart, .amo(1)); + end + end + // Stack section + gen_stack_section(hart); + if (!cfg.bare_program_mode) begin + // Generate kernel program/data/stack section + gen_kernel_sections(hart); + end + // Page table + if (!cfg.bare_program_mode) begin + gen_page_table_section(hart); + end end endfunction //--------------------------------------------------------------------------------------- // Generate kernel program/data/stack sections //--------------------------------------------------------------------------------------- - virtual function void gen_kernel_sections(); - instr_stream.push_back("_kernel_instr_start: .align 12"); + virtual function void gen_kernel_sections(int hart); + instr_stream.push_back(get_label("kernel_instr_start: .align 12", hart)); instr_stream.push_back(".text"); // Kernel programs if (cfg.virtual_addr_translation_on) begin - umode_program = riscv_instr_sequence::type_id::create("umode_program"); - gen_kernel_program(umode_program); - smode_program = riscv_instr_sequence::type_id::create("smode_program"); - gen_kernel_program(smode_program); - smode_lsu_program = riscv_instr_sequence::type_id::create("smode_lsu_program"); - gen_kernel_program(smode_lsu_program); + umode_program = riscv_instr_sequence::type_id::create(get_label("umode_program", hart)); + gen_kernel_program(hart, umode_program); + smode_program = riscv_instr_sequence::type_id::create(get_label("smode_program", hart)); + gen_kernel_program(hart, smode_program); + smode_lsu_program = riscv_instr_sequence::type_id::create( + get_label("smode_lsu_program", hart)); + gen_kernel_program(hart, smode_lsu_program); end // All trap/interrupt handling is in the kernel region // Trap/interrupt delegation to user mode is not supported now // Trap handler - gen_all_trap_handler(); + gen_all_trap_handler(hart); // Interrupt handling subroutine foreach(riscv_instr_pkg::supported_privileged_mode[i]) begin - gen_interrupt_handler_section(riscv_instr_pkg::supported_privileged_mode[i]); + gen_interrupt_handler_section(riscv_instr_pkg::supported_privileged_mode[i], hart); end - instr_stream.push_back("_kernel_instr_end: nop"); + instr_stream.push_back(get_label("kernel_instr_end: nop", hart)); // User stack and data pages may not be accessible when executing trap handling programs in // machine/supervisor mode. Generate separate kernel data/stack sections to solve it. if (cfg.virtual_addr_translation_on) begin // Kernel data pages - instr_stream.push_back("_kernel_data_start: .align 12"); + instr_stream.push_back(get_label("kernel_data_start: .align 12", hart)); if(!cfg.no_data_page) begin // Data section - gen_data_page(1'b1); + gen_data_page(hart, 1'b1); end - gen_data_page_end(); end // Kernel stack section - gen_kernel_stack_section(); + gen_kernel_stack_section(hart); endfunction - virtual function void gen_kernel_program(riscv_instr_sequence seq); + virtual function void gen_kernel_program(int hart, riscv_instr_sequence seq); seq.instr_cnt = cfg.kernel_program_instr_cnt; - generate_directed_instr_stream(.label(seq.get_name()), + generate_directed_instr_stream(.hart(hart), + .label(seq.get_name()), .original_instr_cnt(seq.instr_cnt), .min_insert_cnt(0), .instr_stream(seq.directed_instr), @@ -192,7 +222,8 @@ class riscv_asm_program_gen extends uvm_object; // Generate any subprograms and set up the callstack //--------------------------------------------------------------------------------------- - virtual function void gen_sub_program(ref riscv_instr_sequence sub_program[], + virtual function void gen_sub_program(int hart, + ref riscv_instr_sequence sub_program[], ref string sub_program_name[$], input int num_sub_program, bit is_debug = 1'b0, @@ -200,15 +231,17 @@ class riscv_asm_program_gen extends uvm_object; if(num_sub_program > 0) begin sub_program = new[num_sub_program]; foreach(sub_program[i]) begin - sub_program[i] = riscv_instr_sequence::type_id::create($sformatf("%s_%0d",prefix,i+1)); - `uvm_info(`gfn, $sformatf("sub program name: %s", prefix), UVM_LOW) + sub_program[i] = riscv_instr_sequence::type_id::create( + get_label($sformatf("%s_%0d", prefix, i + 1), hart)); + `uvm_info(`gfn, $sformatf("sub program name: %s", sub_program[i].get_name()), UVM_LOW) sub_program[i].is_debug_program = is_debug; if (is_debug) begin sub_program[i].instr_cnt = cfg.debug_sub_program_instr_cnt[i]; end else begin sub_program[i].instr_cnt = cfg.sub_program_instr_cnt[i]; end - generate_directed_instr_stream(.label(sub_program[i].get_name()), + generate_directed_instr_stream(.hart(hart), + .label(sub_program[i].get_name()), .original_instr_cnt(sub_program[i].instr_cnt), .min_insert_cnt(0), .instr_stream(sub_program[i].directed_instr)); @@ -267,74 +300,96 @@ class riscv_asm_program_gen extends uvm_object; //--------------------------------------------------------------------------------------- virtual function void gen_program_header(); + string str[$]; instr_stream.push_back(".include \"user_define.h\""); instr_stream.push_back(".globl _start"); instr_stream.push_back(".section .text"); if (cfg.disable_compressed_instr) begin instr_stream.push_back(".option norvc;"); end - instr_stream.push_back("_start:"); + str = {"csrr x5, mhartid"}; + for (int hart = 0; hart < cfg.num_of_harts; hart++) begin + str = {str, $sformatf("li x6, %0d", hart), + $sformatf("beq x5, x6, %0df", hart)}; + end + gen_section("_start", str); + for (int hart = 0; hart < cfg.num_of_harts; hart++) begin + instr_stream.push_back($sformatf("%0d: j h%0d_start", hart, hart)); + end endfunction - virtual function void gen_program_end(); - // Use write_tohost to terminate spike simulation - gen_section("write_tohost", {"sw gp, tohost, t5"}); - gen_section("_exit", {"j write_tohost"}); + virtual function void gen_program_end(int hart); + if (hart == 0) begin + // Use write_tohost to terminate spike simulation + gen_section("write_tohost", {"sw gp, tohost, t5"}); + gen_section("_exit", {"j write_tohost"}); + end endfunction - virtual function void gen_data_page_begin(); - instr_stream.push_back(".data"); - instr_stream.push_back(".pushsection .tohost,\"aw\",@progbits;"); - instr_stream.push_back(".align 6; .global tohost; tohost: .dword 0;"); - instr_stream.push_back(".align 6; .global fromhost; fromhost: .dword 0;"); - instr_stream.push_back(".popsection;"); + virtual function void gen_data_page_begin(int hart); + instr_stream.push_back(".section .data"); + if (hart == 0) begin + instr_stream.push_back(".align 6; .global tohost; tohost: .dword 0;"); + instr_stream.push_back(".align 6; .global fromhost; fromhost: .dword 0;"); + end endfunction - virtual function void gen_data_page(bit is_kernel = 1'b0); + virtual function void gen_data_page(int hart, bit is_kernel = 1'b0, bit amo = 0); string data_page; data_page_gen = riscv_data_page_gen::type_id::create("data_page_gen"); data_page_gen.cfg = cfg; - data_page_gen.gen_data_page(cfg.data_page_pattern, is_kernel); + data_page_gen.gen_data_page(hart, cfg.data_page_pattern, is_kernel, amo); instr_stream = {instr_stream, data_page_gen.data_page_str}; endfunction - virtual function void gen_data_page_end(); - instr_stream.push_back(".align 4;"); - endfunction - // Generate the user stack section - virtual function void gen_stack_section(); - instr_stream.push_back(".pushsection .user_stack,\"aw\",@progbits;"); + virtual function void gen_stack_section(int hart); + if (cfg.use_push_data_section) begin + instr_stream.push_back($sformatf(".pushsection .%0suser_stack,\"aw\",@progbits;", + hart_prefix(hart))); + end instr_stream.push_back(".align 12"); - instr_stream.push_back("_user_stack_start:"); + instr_stream.push_back(get_label("user_stack_start:", hart)); instr_stream.push_back($sformatf(".rept %0d", cfg.stack_len - 1)); instr_stream.push_back($sformatf(".%0dbyte 0x0", XLEN/8)); instr_stream.push_back(".endr"); - instr_stream.push_back("_user_stack_end:"); + instr_stream.push_back(get_label("user_stack_end:", hart)); instr_stream.push_back($sformatf(".%0dbyte 0x0", XLEN/8)); - instr_stream.push_back(".popsection;"); + if (cfg.use_push_data_section) begin + instr_stream.push_back(".popsection;"); + end endfunction // The kernal stack is used to save user program context before executing exception handling - virtual function void gen_kernel_stack_section(); - instr_stream.push_back(".pushsection .kernel_stack,\"aw\",@progbits;"); + virtual function void gen_kernel_stack_section(int hart); + if (cfg.use_push_data_section) begin + instr_stream.push_back($sformatf(".pushsection .%0skernel_stack,\"aw\",@progbits;", + hart_prefix(hart))); + end instr_stream.push_back(".align 12"); - instr_stream.push_back("_kernel_stack_start:"); + instr_stream.push_back(get_label("kernel_stack_start:", hart)); instr_stream.push_back($sformatf(".rept %0d", cfg.kernel_stack_len - 1)); instr_stream.push_back($sformatf(".%0dbyte 0x0", XLEN/8)); instr_stream.push_back(".endr"); - instr_stream.push_back("_kernel_stack_end:"); + instr_stream.push_back(get_label("kernel_stack_end:", hart)); instr_stream.push_back($sformatf(".%0dbyte 0x0", XLEN/8)); - instr_stream.push_back(".popsection;"); + if (cfg.use_push_data_section) begin + instr_stream.push_back(".popsection;"); + end endfunction - virtual function void gen_init_section(); + virtual function void gen_init_section(int hart); string str; - str = format_string("_init:", LABEL_STR_LEN); + str = format_string(get_label("init:", hart), LABEL_STR_LEN); instr_stream.push_back(str); + init_gpr(); // Init stack pointer to point to the end of the user stack - str = {indent, $sformatf("la x%0d, _user_stack_end", cfg.sp)}; + str = {indent, $sformatf("la x%0d, %0suser_stack_end", cfg.sp, hart_prefix(hart))}; instr_stream.push_back(str); + if (support_pmp) begin + str = {indent, "j main"}; + instr_stream.push_back(str); + end if (cfg.enable_floating_point) begin init_floating_point_gpr(); end @@ -431,6 +486,7 @@ class riscv_asm_program_gen extends uvm_object; bit [DATA_WIDTH-1:0] reg_val; // Init general purpose registers with random values for(int i = 0; i < 32; i++) begin + if (i inside {cfg.sp, cfg.tp}) continue; `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(reg_val, reg_val dist { 'h0 :/ 1, @@ -515,28 +571,29 @@ class riscv_asm_program_gen extends uvm_object; // Privileged mode entering routine //--------------------------------------------------------------------------------------- - virtual function void pre_enter_privileged_mode(); + virtual function void pre_enter_privileged_mode(int hart); string instr[]; // Setup kerenal stack pointer - gen_section("kernel_sp", {$sformatf("la x%0d, _kernel_stack_end", cfg.tp)}); + gen_section(get_label("kernel_sp", hart), + {$sformatf("la x%0d, %0skernel_stack_end", cfg.tp, hart_prefix(hart))}); // Setup interrupt and exception delegation if(!cfg.no_delegation && (cfg.init_privileged_mode != MACHINE_MODE)) begin - gen_delegation(); + gen_delegation(hart); end // Setup trap vector register - trap_vector_init(); + trap_vector_init(hart); // Setup PMP CSRs - setup_pmp(); + setup_pmp(hart); // Initialize PTE (link page table based on their real physical address) if(cfg.virtual_addr_translation_on) begin page_table_list.process_page_table(instr); - gen_section("process_pt", instr); + gen_section(get_label("process_pt", hart), instr); end // Setup mepc register, jump to init entry - setup_epc(); + setup_epc(hart); endfunction - virtual function void gen_privileged_mode_switch_routine(); + virtual function void gen_privileged_mode_switch_routine(int hart); privil_seq = riscv_privileged_common_seq::type_id::create("privil_seq"); foreach(riscv_instr_pkg::supported_privileged_mode[i]) begin string instr[$]; @@ -547,6 +604,7 @@ class riscv_asm_program_gen extends uvm_object; riscv_instr_pkg::supported_privileged_mode[i].name()), UVM_LOW) // Enter privileged mode privil_seq.cfg = cfg; + privil_seq.hart = hart; `DV_CHECK_RANDOMIZE_FATAL(privil_seq) privil_seq.enter_privileged_mode(riscv_instr_pkg::supported_privileged_mode[i], instr); if (cfg.require_signature_addr) begin @@ -577,10 +635,10 @@ class riscv_asm_program_gen extends uvm_object; endfunction // Setup EPC before entering target privileged mode - virtual function void setup_epc(); + virtual function void setup_epc(int hart); string instr[]; string mode_name; - instr = {$sformatf("la x%0d, _init", cfg.gpr[0])}; + instr = {$sformatf("la x%0d, %0sinit", cfg.gpr[0], hart_prefix(hart))}; if(cfg.virtual_addr_translation_on) begin // For supervisor and user mode, use virtual address instead of physical address. // Virtual address starts from address 0x0, here only the lower 12 bits are kept @@ -592,18 +650,18 @@ class riscv_asm_program_gen extends uvm_object; mode_name = cfg.init_privileged_mode.name(); instr = {instr, $sformatf("csrw mepc, x%0d", cfg.gpr[0]), - $sformatf("j init_%0s", mode_name.tolower()) + $sformatf("j %0sinit_%0s", hart_prefix(hart), mode_name.tolower()) }; - gen_section("mepc_setup", instr); + gen_section(get_label("mepc_setup", hart), instr); endfunction // Setup PMP CSR configuration - virtual function void setup_pmp(); + virtual function void setup_pmp(int hart); string instr[$]; if (riscv_instr_pkg::support_pmp) begin cfg.pmp_cfg.setup_pmp(); cfg.pmp_cfg.gen_pmp_instr(instr, cfg.scratch_reg); - gen_section("pmp_setup", instr); + gen_section(get_label("pmp_setup", hart), instr); end endfunction @@ -613,18 +671,19 @@ class riscv_asm_program_gen extends uvm_object; // Interrupt and exception delegation setting. // The lower level exception and interrupt can be delegated to higher level handler. - virtual function void gen_delegation(); - gen_delegation_instr(MEDELEG, MIDELEG, + virtual function void gen_delegation(int hart); + gen_delegation_instr(hart, MEDELEG, MIDELEG, cfg.m_mode_exception_delegation, cfg.m_mode_interrupt_delegation); if(riscv_instr_pkg::support_umode_trap) begin - gen_delegation_instr(SEDELEG, SIDELEG, + gen_delegation_instr(hart, SEDELEG, SIDELEG, cfg.s_mode_exception_delegation, cfg.s_mode_interrupt_delegation); end endfunction - virtual function void gen_delegation_instr(privileged_reg_t edeleg, + virtual function void gen_delegation_instr(int hart, + privileged_reg_t edeleg, privileged_reg_t ideleg, bit edeleg_enable[exception_cause_t], bit ideleg_enable[interrupt_cause_t]); @@ -651,11 +710,11 @@ class riscv_asm_program_gen extends uvm_object; $sformatf("csrw 0x%0x, x%0d # %0s", ideleg, cfg.gpr[0], ideleg.name())}; section_name = edeleg.name(); section_name = section_name.tolower(); - gen_section($sformatf("%0s_setup", section_name), instr); + gen_section(get_label($sformatf("%0s_setup", section_name), hart), instr); endfunction // Setup trap vector - MTVEC, STVEC, UTVEC - virtual function void trap_vector_init(); + virtual function void trap_vector_init(int hart); string instr[]; privileged_reg_t trap_vec_reg; string tvec_name; @@ -670,7 +729,8 @@ class riscv_asm_program_gen extends uvm_object; !riscv_instr_pkg::support_umode_trap) continue; if (riscv_instr_pkg::supported_privileged_mode[i] < cfg.init_privileged_mode) continue; tvec_name = trap_vec_reg.name(); - instr = {instr, $sformatf("la x%0d, %0s_handler", cfg.gpr[0], tvec_name.tolower())}; + instr = {instr, $sformatf("la x%0d, %0s%0s_handler", + cfg.gpr[0], hart_prefix(hart), tvec_name.tolower())}; if (SATP_MODE != BARE && riscv_instr_pkg::supported_privileged_mode[i] != MACHINE_MODE) begin // For supervisor and user mode, use virtual address instead of physical address. // Virtual address starts from address 0x0, here only the lower 20 bits are kept @@ -683,7 +743,7 @@ class riscv_asm_program_gen extends uvm_object; instr = {instr, $sformatf("csrw 0x%0x, x%0d # %0s", trap_vec_reg, cfg.gpr[0], trap_vec_reg.name())}; end - gen_section("trap_vec_init", instr); + gen_section(get_label("trap_vec_init", hart), instr); endfunction //--------------------------------------------------------------------------------------- @@ -691,33 +751,24 @@ class riscv_asm_program_gen extends uvm_object; //--------------------------------------------------------------------------------------- // Trap handling routine - virtual function void gen_all_trap_handler(); + virtual function void gen_all_trap_handler(int hart); string instr[$]; - foreach(riscv_instr_pkg::supported_privileged_mode[i]) begin - if(riscv_instr_pkg::supported_privileged_mode[i] < cfg.init_privileged_mode) continue; - case(riscv_instr_pkg::supported_privileged_mode[i]) - MACHINE_MODE: - gen_trap_handler_section("m", MCAUSE, MTVEC, MTVAL, MEPC, MSCRATCH, MSTATUS, MIE, MIP); - SUPERVISOR_MODE: - gen_trap_handler_section("s", SCAUSE, STVEC, STVAL, SEPC, SSCRATCH, SSTATUS, SIE, SIP); - USER_MODE: - if(riscv_instr_pkg::support_umode_trap) begin - gen_trap_handler_section("u", UCAUSE, UTVEC, UTVAL, UEPC, USCRATCH, USTATUS, UIE, UIP); - end - endcase + // If PMP isn't supported, generate the relevant trap handler sections as per usual + if (!support_pmp) begin + gen_trap_handlers(hart); + // Ecall handler + gen_ecall_handler(hart); + // Instruction fault handler + gen_instr_fault_handler(hart); + // Load fault handler + gen_load_fault_handler(hart); + // Store fault handler + gen_store_fault_handler(hart); end // Ebreak handler - gen_ebreak_handler(); - // Ecall handler - gen_ecall_handler(); + gen_ebreak_handler(hart); // Illegal instruction handler - gen_illegal_instr_handler(); - // Instruction fault handler - gen_instr_fault_handler(); - // Load fault handler - gen_load_fault_handler(); - // Store fault handler - gen_store_fault_handler(); + gen_illegal_instr_handler(hart); // Generate page table fault handling routine // Page table fault is always handled in machine mode, as virtual address translation may be // broken when page fault happens. @@ -727,22 +778,42 @@ class riscv_asm_program_gen extends uvm_object; end else begin instr.push_back("nop"); end - gen_section("pt_fault_handler", instr); + gen_section(get_label("pt_fault_handler", hart), instr); + endfunction + + virtual function void gen_trap_handlers(int hart); + foreach(riscv_instr_pkg::supported_privileged_mode[i]) begin + if(riscv_instr_pkg::supported_privileged_mode[i] < cfg.init_privileged_mode) continue; + case(riscv_instr_pkg::supported_privileged_mode[i]) + MACHINE_MODE: + gen_trap_handler_section(hart, "m", MCAUSE, MTVEC, MTVAL, + MEPC, MSCRATCH, MSTATUS, MIE, MIP); + SUPERVISOR_MODE: + gen_trap_handler_section(hart, "s", SCAUSE, STVEC, STVAL, + SEPC, SSCRATCH, SSTATUS, SIE, SIP); + USER_MODE: + if(riscv_instr_pkg::support_umode_trap) begin + gen_trap_handler_section(hart, "u", UCAUSE, UTVEC, UTVAL, + UEPC, USCRATCH, USTATUS, UIE, UIP); + end + endcase + end endfunction // Generate the interrupt and trap handler for different privileged mode. // The trap handler checks the xCAUSE to determine the type of the exception and jumps to // corresponding exeception handling routine. - virtual function void gen_trap_handler_section(string mode, - privileged_reg_t cause, privileged_reg_t tvec, - privileged_reg_t tval, privileged_reg_t epc, - privileged_reg_t scratch, privileged_reg_t status, - privileged_reg_t ie, privileged_reg_t ip); + virtual function void gen_trap_handler_section(int hart, + string mode, + privileged_reg_t cause, privileged_reg_t tvec, + privileged_reg_t tval, privileged_reg_t epc, + privileged_reg_t scratch, privileged_reg_t status, + privileged_reg_t ie, privileged_reg_t ip); bit is_interrupt = 'b1; string tvec_name; string instr[$]; if (cfg.mtvec_mode == VECTORED) begin - gen_interrupt_vector_table(mode, status, cause, ie, ip, scratch, instr); + gen_interrupt_vector_table(hart, mode, status, cause, ie, ip, scratch, instr); end else begin // Push user mode GPR to kernel stack before executing exception handling, this is to avoid // exception handling routine modify user program state unexpectedly @@ -758,13 +829,14 @@ class riscv_asm_program_gen extends uvm_object; // handler Interrupt is indicated by xCause[XLEN-1] $sformatf("csrr x%0d, 0x%0x # %0s", cfg.gpr[0], cause, cause.name()), $sformatf("srli x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN-1), - $sformatf("bne x%0d, x0, %0smode_intr_handler", cfg.gpr[0], mode)}; + $sformatf("bne x%0d, x0, %0s%0smode_intr_handler", + cfg.gpr[0], hart_prefix(hart), mode)}; end // The trap handler will occupy one 4KB page, it will be allocated one entry in the page table // with a specific privileged mode. instr_stream.push_back(".align 12"); tvec_name = tvec.name(); - gen_section($sformatf("%0s_handler", tvec_name.tolower()), instr); + gen_section(get_label($sformatf("%0s_handler", tvec_name.tolower()), hart), instr); // Exception handler instr = {}; if (cfg.mtvec_mode == VECTORED) begin @@ -779,39 +851,51 @@ class riscv_asm_program_gen extends uvm_object; $sformatf("csrr x%0d, 0x%0x # %0s", cfg.gpr[0], cause, cause.name()), // Breakpoint $sformatf("li x%0d, 0x%0x # BREAKPOINT", cfg.gpr[1], BREAKPOINT), - $sformatf("beq x%0d, x%0d, ebreak_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0sebreak_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), // Check if it's an ECALL exception. Jump to ECALL exception handler $sformatf("li x%0d, 0x%0x # ECALL_UMODE", cfg.gpr[1], ECALL_UMODE), - $sformatf("beq x%0d, x%0d, ecall_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0secall_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x # ECALL_SMODE", cfg.gpr[1], ECALL_SMODE), - $sformatf("beq x%0d, x%0d, ecall_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0secall_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x # ECALL_MMODE", cfg.gpr[1], ECALL_MMODE), - $sformatf("beq x%0d, x%0d, ecall_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0secall_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), // Page table fault or access fault conditions $sformatf("li x%0d, 0x%0x", cfg.gpr[1], INSTRUCTION_ACCESS_FAULT), - $sformatf("beq x%0d, x%0d, instr_fault_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0sinstr_fault_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x", cfg.gpr[1], LOAD_ACCESS_FAULT), - $sformatf("beq x%0d, x%0d, load_fault_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0sload_fault_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x", cfg.gpr[1], STORE_AMO_ACCESS_FAULT), - $sformatf("beq x%0d, x%0d, store_fault_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0sstore_fault_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x", cfg.gpr[1], INSTRUCTION_PAGE_FAULT), - $sformatf("beq x%0d, x%0d, pt_fault_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0spt_fault_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x", cfg.gpr[1], LOAD_PAGE_FAULT), - $sformatf("beq x%0d, x%0d, pt_fault_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0spt_fault_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), $sformatf("li x%0d, 0x%0x", cfg.gpr[1], STORE_AMO_PAGE_FAULT), - $sformatf("beq x%0d, x%0d, pt_fault_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0spt_fault_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), // Illegal instruction exception $sformatf("li x%0d, 0x%0x # ILLEGAL_INSTRUCTION", cfg.gpr[1], ILLEGAL_INSTRUCTION), - $sformatf("beq x%0d, x%0d, illegal_instr_handler", cfg.gpr[0], cfg.gpr[1]), + $sformatf("beq x%0d, x%0d, %0sillegal_instr_handler", + cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), // Skip checking tval for illegal instruction as it's implementation specific $sformatf("csrr x%0d, 0x%0x # %0s", cfg.gpr[1], tval, tval.name()), "1: jal x1, test_done " }; - gen_section($sformatf("%0smode_exception_handler", mode), instr); + gen_section(get_label($sformatf("%0smode_exception_handler", mode), hart), instr); endfunction // Generate for interrupt vector table - virtual function void gen_interrupt_vector_table(string mode, + virtual function void gen_interrupt_vector_table(int hart, + string mode, privileged_reg_t status, privileged_reg_t cause, privileged_reg_t ie, @@ -825,10 +909,10 @@ class riscv_asm_program_gen extends uvm_object; // ambiguity does not arise in practice, since user-mode software interrupts are either // disabled or delegated instr = {instr, ".option norvc;", - $sformatf("j %0smode_exception_handler", mode)}; + $sformatf("j %0s%0smode_exception_handler", hart_prefix(hart), mode)}; // Redirect the interrupt to the corresponding interrupt handler for (int i = 1; i < max_interrupt_vector_num; i++) begin - instr.push_back($sformatf("j %0smode_intr_vector_%0d", mode, i)); + instr.push_back($sformatf("j %0s%0smode_intr_vector_%0d", hart_prefix(hart), mode, i)); end if (!cfg.disable_compressed_instr) begin instr = {instr, ".option rvc;"}; @@ -849,18 +933,18 @@ class riscv_asm_program_gen extends uvm_object; gen_signature_handshake(.instr(intr_handler), .signature_type(WRITE_CSR), .csr(ip)); // Jump to commmon interrupt handling routine intr_handler = {intr_handler, - $sformatf("j %0smode_intr_handler", mode), + $sformatf("j %0s%0smode_intr_handler", hart_prefix(hart), mode), "1: j test_done"}; - gen_section($sformatf("%0smode_intr_vector_%0d", mode, i), intr_handler); + gen_section(get_label($sformatf("%0smode_intr_vector_%0d", mode, i), hart), intr_handler); end endfunction // ECALL trap handler // It does some clean up like dump GPRs before communicating with host to terminate the test. // User can extend this function if some custom clean up routine is needed. - virtual function void gen_ecall_handler(); + virtual function void gen_ecall_handler(int hart); string str; - str = format_string("ecall_handler:", LABEL_STR_LEN); + str = format_string(get_label("ecall_handler:", hart), LABEL_STR_LEN); instr_stream.push_back(str); dump_perf_stats(); gen_register_dump(); @@ -877,7 +961,7 @@ class riscv_asm_program_gen extends uvm_object; // TODO: Support random operations in debug mode // TODO: Support ebreak exception delegation // TODO: handshake the correct Xcause CSR based on delegation privil. mode - virtual function void gen_ebreak_handler(); + virtual function void gen_ebreak_handler(int hart); string instr[$]; gen_signature_handshake(instr, CORE_STATUS, EBREAK_EXCEPTION); gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); @@ -888,7 +972,7 @@ class riscv_asm_program_gen extends uvm_object; }; pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); instr.push_back("mret"); - gen_section("ebreak_handler", instr); + gen_section(get_label("ebreak_handler", hart), instr); endfunction // Illegal instruction handler @@ -898,7 +982,7 @@ class riscv_asm_program_gen extends uvm_object; // 4 and resumes execution. The way that the illegal instruction is injected guarantees that // PC + 4 is a valid instruction boundary. // TODO: handshake the corret Xcause CSR based on delegation setup - virtual function void gen_illegal_instr_handler(); + virtual function void gen_illegal_instr_handler(int hart); string instr[$]; gen_signature_handshake(instr, CORE_STATUS, ILLEGAL_INSTR_EXCEPTION); gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); @@ -909,37 +993,37 @@ class riscv_asm_program_gen extends uvm_object; }; pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); instr.push_back("mret"); - gen_section("illegal_instr_handler", instr); + gen_section(get_label("illegal_instr_handler", hart), instr); endfunction // TODO: handshake correct csr based on delegation - virtual function void gen_instr_fault_handler(); + virtual function void gen_instr_fault_handler(int hart); string instr[$]; gen_signature_handshake(instr, CORE_STATUS, INSTR_FAULT_EXCEPTION); gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); instr.push_back("mret"); - gen_section("instr_fault_handler", instr); + gen_section(get_label("instr_fault_handler", hart), instr); endfunction // TODO: handshake correct csr based on delegation - virtual function void gen_load_fault_handler(); + virtual function void gen_load_fault_handler(int hart); string instr[$]; gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); instr.push_back("mret"); - gen_section("load_fault_handler", instr); + gen_section(get_label("load_fault_handler", hart), instr); endfunction // TODO: handshake correct csr based on delegation - virtual function void gen_store_fault_handler(); + virtual function void gen_store_fault_handler(int hart); string instr[$]; gen_signature_handshake(instr, CORE_STATUS, STORE_FAULT_EXCEPTION); gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); instr.push_back("mret"); - gen_section("store_fault_handler", instr); + gen_section(get_label("store_fault_handler", hart), instr); endfunction //--------------------------------------------------------------------------------------- @@ -950,7 +1034,7 @@ class riscv_asm_program_gen extends uvm_object; // The page is created based on the address translation mode - SV32, SV39, SV48 // Right now only the lowest level 4KB page table is configured as leaf page table entry (PTE), // all the other super pages are link PTE. - virtual function void create_page_table(); + virtual function void create_page_table(int hart); string instr[]; if(cfg.virtual_addr_translation_on) begin page_table_list = riscv_page_table_list#(SATP_MODE):: @@ -969,15 +1053,20 @@ class riscv_asm_program_gen extends uvm_object; // Generate the page table section of the program // The page table is generated as a group of continuous 4KB data sections. - virtual function void gen_page_table_section(); + virtual function void gen_page_table_section(int hart); string page_table_section[$]; if(page_table_list != null) begin - instr_stream.push_back(".pushsection .page_table,\"aw\",@progbits;"); + if (cfg.use_push_data_section) begin + instr_stream.push_back($sformatf(".pushsection .%0spage_table,\"aw\",@progbits;", + hart_prefix(hart))); + end foreach(page_table_list.page_table[i]) begin page_table_list.page_table[i].gen_page_table_section(page_table_section); instr_stream = {instr_stream, page_table_section}; end - instr_stream.push_back(".popsection;"); + if (cfg.use_push_data_section) begin + instr_stream.push_back(".popsection;"); + end end endfunction @@ -992,7 +1081,7 @@ class riscv_asm_program_gen extends uvm_object; endfunction // Interrupt handler routine - virtual function void gen_interrupt_handler_section(privileged_mode_t mode); + virtual function void gen_interrupt_handler_section(privileged_mode_t mode, int hart); string mode_prefix; string ls_unit; privileged_reg_t status, ip, ie, scratch; @@ -1063,7 +1152,8 @@ class riscv_asm_program_gen extends uvm_object; }; // The interrupt handler will use one 4KB page instr_stream.push_back(".align 12"); - gen_section($sformatf("%0smode_intr_handler", mode_prefix), interrupt_handler_instr); + gen_section(get_label($sformatf("%0smode_intr_handler", mode_prefix), hart), + interrupt_handler_instr); endfunction //--------------------------------------------------------------------------------------- @@ -1227,7 +1317,8 @@ class riscv_asm_program_gen extends uvm_object; endfunction // Generate directed instruction stream based on the ratio setting - virtual function void generate_directed_instr_stream(input string label, + virtual function void generate_directed_instr_stream(input int hart, + input string label, input int unsigned original_instr_cnt, input int unsigned min_insert_cnt = 0, input bit kernel_mode = 0, @@ -1262,6 +1353,7 @@ class riscv_asm_program_gen extends uvm_object; end if($cast(new_instr_stream, object_h)) begin new_instr_stream.cfg = cfg; + new_instr_stream.hart = hart; new_instr_stream.label = $sformatf("%0s_%0d", label, idx); new_instr_stream.kernel_mode = kernel_mode; `DV_CHECK_RANDOMIZE_FATAL(new_instr_stream) @@ -1279,10 +1371,11 @@ class riscv_asm_program_gen extends uvm_object; // Generate the debug ROM, and any related programs //--------------------------------------------------------------------------------------- - virtual function void gen_debug_rom(); + virtual function void gen_debug_rom(int hart); `uvm_info(`gfn, "Creating debug ROM", UVM_LOW) debug_rom = riscv_asm_program_gen::type_id::create("debug_rom", , {"uvm_test_top", ".", `gfn}); debug_rom.cfg = cfg; + debug_rom.hart = hart; debug_rom.gen_program(); instr_stream = {instr_stream, debug_rom.instr_stream}; endfunction diff --git a/vendor/google_riscv-dv/src/riscv_data_page_gen.sv b/vendor/google_riscv-dv/src/riscv_data_page_gen.sv index e80ab35e..e79d8ccb 100644 --- a/vendor/google_riscv-dv/src/riscv_data_page_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_data_page_gen.sv @@ -23,7 +23,7 @@ class riscv_data_page_gen extends uvm_object; riscv_instr_gen_config cfg; string data_page_str[$]; - mem_region_t mem_region_setting[$]; + mem_region_t mem_region_setting[$]; `uvm_object_utils(riscv_data_page_gen) @@ -50,7 +50,10 @@ class riscv_data_page_gen extends uvm_object; endfunction // Generate data pages for all memory regions - function void gen_data_page(data_pattern_t pattern, bit is_kernel = 1'b0); + function void gen_data_page(int hart_id, + data_pattern_t pattern, + bit is_kernel = 1'b0, + bit amo = 0); string tmp_str; bit [7:0] tmp_data[]; int page_cnt; @@ -58,23 +61,30 @@ class riscv_data_page_gen extends uvm_object; data_page_str = {}; if (is_kernel) begin mem_region_setting = cfg.s_mem_region; + end else if (amo) begin + mem_region_setting = cfg.amo_region; end else begin mem_region_setting = cfg.mem_region; end - if (is_kernel) begin - // All kernel data pages in the same section - data_page_str.push_back(".pushsection .kernel_data,\"aw\",@progbits;"); - end foreach (mem_region_setting[i]) begin `uvm_info(`gfn, $sformatf("Generate data section: %0s size:0x%0x xwr:0x%0x]", mem_region_setting[i].name, mem_region_setting[i].size_in_bytes, mem_region_setting[i].xwr), UVM_LOW) - if (!is_kernel) begin - data_page_str.push_back($sformatf(".pushsection .%0s,\"aw\",@progbits;", - mem_region_setting[i].name)); + if (amo) begin + if (cfg.use_push_data_section) begin + data_page_str.push_back($sformatf(".pushsection .%0s,\"aw\",@progbits;", + mem_region_setting[i].name)); + end + data_page_str.push_back($sformatf("%0s:", mem_region_setting[i].name)); + end else begin + if (cfg.use_push_data_section) begin + data_page_str.push_back($sformatf(".pushsection .%0s,\"aw\",@progbits;", + {hart_prefix(hart_id), mem_region_setting[i].name})); + end + data_page_str.push_back($sformatf("%0s:", + {hart_prefix(hart_id), mem_region_setting[i].name})); end - data_page_str.push_back($sformatf("%0s:", mem_region_setting[i].name)); page_size = mem_region_setting[i].size_in_bytes; for(int i = 0; i < page_size; i+= 32) begin if (page_size-i >= 32) begin @@ -85,13 +95,10 @@ class riscv_data_page_gen extends uvm_object; tmp_str = format_string($sformatf(".word %0s", format_data(tmp_data)), LABEL_STR_LEN); data_page_str.push_back(tmp_str); end - if (!is_kernel) begin + if (cfg.use_push_data_section) begin data_page_str.push_back(".popsection;"); end end - if (is_kernel) begin - data_page_str.push_back(".popsection;"); - end endfunction endclass diff --git a/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv b/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv index b44a1f12..6e6ba854 100644 --- a/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv @@ -27,6 +27,7 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen; string debug_end[$]; string str[$]; string dret; + int hart; `uvm_object_utils(riscv_debug_rom_gen) @@ -45,7 +46,7 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen; // If the debug section should not be generated, we just populate it // with a dret instruction. debug_main = {dret}; - gen_section("debug_rom", debug_main); + gen_section($sformatf("%0sdebug_rom", hart_prefix(hart)), debug_main); end else begin if (cfg.enable_ebreak_in_debug_rom) begin gen_ebreak_header(); @@ -80,21 +81,21 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen; gen_increment_ebreak_counter(); end format_section(debug_main); - gen_sub_program(sub_program, sub_program_name, + gen_sub_program(hart, sub_program[hart], sub_program_name, cfg.num_debug_sub_program, 1'b1, "debug_sub"); - main_program = riscv_instr_sequence::type_id::create("main_program"); - main_program.instr_cnt = cfg.debug_program_instr_cnt; - main_program.is_debug_program = 1; - main_program.cfg = cfg; - `DV_CHECK_RANDOMIZE_FATAL(main_program) - main_program.gen_instr(.is_main_program(1'b1), .no_branch(cfg.no_branch_jump)); - gen_callstack(main_program, sub_program, sub_program_name, + main_program[hart] = riscv_instr_sequence::type_id::create("debug_program"); + main_program[hart].instr_cnt = cfg.debug_program_instr_cnt; + main_program[hart].is_debug_program = 1; + main_program[hart].cfg = cfg; + `DV_CHECK_RANDOMIZE_FATAL(main_program[hart]) + main_program[hart].gen_instr(.is_main_program(1'b1), .no_branch(cfg.no_branch_jump)); + gen_callstack(main_program[hart], sub_program[hart], sub_program_name, cfg.num_debug_sub_program); - main_program.post_process_instr(); - main_program.generate_instr_stream(.no_label(1'b1)); - insert_sub_program(sub_program, debug_main); - debug_main = {debug_main, main_program.instr_string_list}; - gen_section("debug_rom", debug_main); + main_program[hart].post_process_instr(); + main_program[hart].generate_instr_stream(.no_label(1'b1)); + insert_sub_program(sub_program[hart], debug_main); + debug_main = {debug_main, main_program[hart].instr_string_list}; + gen_section($sformatf("%0sdebug_rom", hart_prefix(hart)), debug_main); if (cfg.enable_ebreak_in_debug_rom) begin gen_ebreak_footer(); end @@ -105,7 +106,7 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen; end //format_section(debug_end); debug_end = {debug_end, dret}; - gen_section("debug_end", debug_end); + gen_section($sformatf("%0sdebug_end", hart_prefix(hart)), debug_end); end gen_debug_exception_handler(); endfunction @@ -114,7 +115,7 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen; // TODO(udinator) - remains empty for now, only a DRET virtual function void gen_debug_exception_handler(); str = {"dret"}; - gen_section("debug_exception", str); + gen_section($sformatf("%0sdebug_exception", hart_prefix(hart)), str); endfunction //------------------------------------------------------------------------------------- @@ -130,7 +131,7 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen; str = {$sformatf("csrw 0x%0x, x%0d", DSCRATCH1, cfg.scratch_reg), $sformatf("csrr x%0d, 0x%0x", cfg.scratch_reg, DSCRATCH0), $sformatf("beq x%0d, x0, 1f", cfg.scratch_reg), - $sformatf("j debug_end"), + $sformatf("j %0sdebug_end", hart_prefix(hart)), $sformatf("1: csrr x%0d, 0x%0x", cfg.scratch_reg, DSCRATCH1)}; debug_main = {debug_main, str}; endfunction diff --git a/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv b/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv index 53519730..64984ffe 100644 --- a/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv +++ b/vendor/google_riscv-dv/src/riscv_directed_instr_lib.sv @@ -65,9 +65,11 @@ class riscv_mem_access_stream extends riscv_directed_instr_stream; 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); + la_instr.imm_str = $sformatf("%0s%s+%0d", + hart_prefix(hart), cfg.s_mem_region[id].name, base); end else begin - la_instr.imm_str = $sformatf("%s+%0d", cfg.mem_region[id].name, base); + la_instr.imm_str = $sformatf("%0s%s+%0d", + hart_prefix(hart), cfg.mem_region[id].name, base); end instr_list.push_front(la_instr); endfunction @@ -184,8 +186,10 @@ class riscv_jump_instr extends riscv_directed_instr_stream; 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; + jump.label = "1"; + jump.comment = $sformatf("%s jump %0s -> %0s", + hart_prefix(hart), label, target_program_label); + branch.imm_str = "1f"; branch.comment = "branch to jump instr"; branch.branch_assigned = 1'b1; endfunction diff --git a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv index fe38c020..907fbc00 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv @@ -106,6 +106,11 @@ class riscv_instr_gen_config extends uvm_object; '{name:"region_4", size_in_bytes: 4096, xwr: 3'b111} }; + // Dedicated shared memory region for multi-harts atomic operations + mem_region_t amo_region[$] = '{ + '{name:"amo_0", size_in_bytes: 64, xwr: 3'b111} + }; + // Stack section word length int stack_len = 5000; @@ -148,8 +153,12 @@ class riscv_instr_gen_config extends uvm_object; bit enable_unaligned_load_store; int illegal_instr_ratio; int hint_instr_ratio; + // Number of harts to be simulated, must be <= NUM_HARTS + int num_of_harts = NUM_HARTS; // Use SP as stack pointer bit fix_sp; + // Use push/pop section for data pages + bit use_push_data_section = 0; // Directed boot privileged mode, u, m, s string boot_mode_opts; int enable_page_table_exception; @@ -303,6 +312,11 @@ class riscv_instr_gen_config extends uvm_object; // This is default disabled at setup phase. It can be enabled in the exception and interrupt // handling routine mstatus_mprv == 1'b0; + if (SATP_MODE == BARE) { + mstatus_mxr == 0; + mstatus_sum == 0; + mstatus_tvm == 0; + } } // Exception delegation setting @@ -379,8 +393,11 @@ class riscv_instr_gen_config extends uvm_object; unique {gpr}; } - constraint addr_translaction_c { + constraint addr_translaction_rnd_order_c { solve init_privileged_mode before virtual_addr_translation_on; + } + + constraint addr_translaction_c { if ((init_privileged_mode != MACHINE_MODE) && (SATP_MODE != BARE)) { virtual_addr_translation_on == 1'b1; } else { @@ -444,6 +461,7 @@ class riscv_instr_gen_config extends uvm_object; `uvm_field_int(support_supervisor_mode, UVM_DEFAULT) `uvm_field_int(disable_compressed_instr, UVM_DEFAULT) `uvm_field_int(signature_addr, UVM_DEFAULT) + `uvm_field_int(num_of_harts, UVM_DEFAULT) `uvm_field_int(require_signature_addr, UVM_DEFAULT) `uvm_field_int(gen_debug_section, UVM_DEFAULT) `uvm_field_int(enable_ebreak_in_debug_rom, UVM_DEFAULT) @@ -456,6 +474,7 @@ class riscv_instr_gen_config extends uvm_object; `uvm_field_int(max_directed_instr_stream_seq, UVM_DEFAULT) `uvm_field_int(enable_floating_point, UVM_DEFAULT) `uvm_field_int(enable_vector_extension, UVM_DEFAULT) + `uvm_field_int(use_push_data_section, UVM_DEFAULT) `uvm_object_utils_end function new (string name = ""); @@ -477,6 +496,7 @@ class riscv_instr_gen_config extends uvm_object; get_bool_arg_value("+no_load_store=", no_load_store); get_bool_arg_value("+no_csr_instr=", no_csr_instr); get_bool_arg_value("+fix_sp=", fix_sp); + get_bool_arg_value("+use_push_data_section=", use_push_data_section); 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_misaligned_instr=", enable_misaligned_instr); @@ -488,6 +508,7 @@ class riscv_instr_gen_config extends uvm_object; 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_int_arg_value("+num_of_harts=", num_of_harts); 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); @@ -517,6 +538,7 @@ class riscv_instr_gen_config extends uvm_object; $sformatf("Illegal boot mode option - %0s", boot_mode_opts)) endcase init_privileged_mode.rand_mode(0); + addr_translaction_rnd_order_c.constraint_mode(0); end `uvm_info(`gfn, $sformatf("riscv_instr_pkg::supported_privileged_mode = %0d", riscv_instr_pkg::supported_privileged_mode.size()), UVM_LOW) diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index fe4c7176..3a06a714 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -954,6 +954,18 @@ package riscv_instr_pkg; rand bit [XLEN - 1 : 0] addr; } pmp_cfg_reg_t; + function automatic string hart_prefix(int hart = 0); + if (NUM_HARTS <= 1) begin + return ""; + end else begin + return $sformatf("h%0d_", hart); + end + endfunction : hart_prefix + + function automatic string get_label(string label, int hart = 0); + return {hart_prefix(hart), label}; + endfunction : get_label + typedef struct packed { bit ill; bit [XLEN-2:7] reserved; diff --git a/vendor/google_riscv-dv/src/riscv_instr_stream.sv b/vendor/google_riscv-dv/src/riscv_instr_stream.sv index 473e8d83..ab72debc 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_stream.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_stream.sv @@ -28,6 +28,7 @@ class riscv_instr_stream extends uvm_object; // Some additional reserved registers that should not be used as rd register // by this instruction stream riscv_reg_t reserved_rd[]; + int hart; `uvm_object_utils(riscv_instr_stream) `uvm_object_new diff --git a/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv b/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv index c7100510..235178ab 100644 --- a/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv +++ b/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv @@ -39,8 +39,11 @@ class riscv_load_store_base_instr_stream extends riscv_mem_access_stream; `uvm_object_utils(riscv_load_store_base_instr_stream) - constraint sp_c { + constraint sp_rnd_order_c { solve use_sp_as_rs1 before rs1_reg; + } + + constraint sp_c { use_sp_as_rs1 dist {1 := 1, 0 := 2}; if (use_sp_as_rs1) { rs1_reg == SP; @@ -97,6 +100,7 @@ class riscv_load_store_base_instr_stream extends riscv_mem_access_stream; if (SP inside {cfg.reserved_regs, reserved_rd}) begin use_sp_as_rs1 = 0; use_sp_as_rs1.rand_mode(0); + sp_rnd_order_c.constraint_mode(0); end endfunction diff --git a/vendor/google_riscv-dv/src/riscv_page_table_list.sv b/vendor/google_riscv-dv/src/riscv_page_table_list.sv index 82e114af..d05bffdc 100644 --- a/vendor/google_riscv-dv/src/riscv_page_table_list.sv +++ b/vendor/google_riscv-dv/src/riscv_page_table_list.sv @@ -354,7 +354,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object; // Fix kernel leaf PTE instr.push_back("fix_kernel_leaf_pte:"); // - Load the starting virtual address of the kernel space - instr.push_back($sformatf("la x%0d, _kernel_instr_start", tmp_reg)); + instr.push_back($sformatf("la x%0d, kernel_instr_start", tmp_reg)); // TODO: Fix kernel instruction/data pages separatedly instr.push_back($sformatf("slli x%0d, x%0d, %0d", tmp_reg, tmp_reg, XLEN - MAX_USED_VADDR_BITS)); @@ -471,8 +471,8 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object; if (cfg.support_supervisor_mode) begin instr = {instr, // Process kernel instruction pages - $sformatf("la x%0d, _kernel_instr_start", cfg.gpr[0]), - $sformatf("la x%0d, _kernel_instr_end", cfg.gpr[1]), + $sformatf("la x%0d, kernel_instr_start", cfg.gpr[0]), + $sformatf("la x%0d, kernel_instr_end", cfg.gpr[1]), // Get the VPN of the physical address $sformatf("slli x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN - MAX_USED_VADDR_BITS), @@ -501,7 +501,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object; // If not the end of the kernel space, process the next PTE $sformatf("ble x%0d, x%0d, 1b", cfg.gpr[0], cfg.gpr[1]), // Process kernel data pages - $sformatf("la x%0d, _kernel_data_start", cfg.gpr[0]), + $sformatf("la x%0d, kernel_data_start", cfg.gpr[0]), // Get the VPN of the physical address $sformatf("slli x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN - MAX_USED_VADDR_BITS), diff --git a/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv b/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv index bcc0f0ff..8abf685a 100644 --- a/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv +++ b/vendor/google_riscv-dv/src/riscv_pmp_cfg.sv @@ -104,12 +104,13 @@ class riscv_pmp_cfg extends uvm_object; arg_name = $sformatf("+pmp_region_%0d=", i); if (inst.get_arg_value(arg_name, pmp_region)) begin parse_pmp_config(pmp_region, pmp_cfg[i]); - `uvm_info(`gfn, $sformatf("Configured pmp_cfg[%0d] from command line: %p", i, pmp_cfg[i]), UVM_LOW) + `uvm_info(`gfn, $sformatf("Configured pmp_cfg[%0d] from command line: %p", + i, pmp_cfg[i]), UVM_LOW) end end endfunction - function void parse_pmp_config(string pmp_region, ref pmp_cfg_reg_t pmp_cfg_reg); + function void parse_pmp_config(string pmp_region, output pmp_cfg_reg_t pmp_cfg_reg); string fields[$]; string field_vals[$]; string field_type; @@ -160,7 +161,7 @@ class riscv_pmp_cfg extends uvm_object; // RV64 - pmpaddr is bits [55:2] of the whole 56 bit address, prepended by 10'b0 // Return {10'b0, shifted_addr[53:0]} 64: begin - return {10'b0, shifted_addr[53:0]}; + return {10'b0, shifted_addr[XLEN - 11 : 0]}; end endcase endfunction diff --git a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv index 0970da08..4dc3f2c1 100644 --- a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv +++ b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv @@ -18,6 +18,7 @@ class riscv_privileged_common_seq extends uvm_sequence; riscv_instr_gen_config cfg; + int hart; riscv_privil_reg mstatus; riscv_privil_reg mie; riscv_privil_reg sstatus; @@ -33,7 +34,8 @@ class riscv_privileged_common_seq extends uvm_sequence; virtual function void enter_privileged_mode(input privileged_mode_t mode, output string instrs[$]); - string label = format_string({"init_", mode.name(), ":"}, LABEL_STR_LEN); + string label = format_string({$sformatf("%0sinit_%0s:", + hart_prefix(hart), mode.name())}, LABEL_STR_LEN); string ret_instr[] = {"mret"}; riscv_privil_reg regs[$]; label = label.tolower(); @@ -69,10 +71,16 @@ class riscv_privileged_common_seq extends uvm_sequence; mstatus.set_field("TW", cfg.set_mstatus_tw); mstatus.set_field("FS", cfg.mstatus_fs); mstatus.set_field("VS", cfg.mstatus_vs); - if(XLEN==64) begin - mstatus.set_field("UXL", 2'b10); + if (!(SUPERVISOR_MODE inside {supported_privileged_mode}) && (XLEN != 32)) begin + mstatus.set_field("SXL", 2'b00); + end else if (XLEN == 64) begin mstatus.set_field("SXL", 2'b10); end + if (!(USER_MODE inside {supported_privileged_mode}) && (XLEN != 32)) begin + mstatus.set_field("UXL", 2'b00); + end else if (XLEN == 64) begin + mstatus.set_field("UXL", 2'b10); + end mstatus.set_field("XS", 0); mstatus.set_field("SD", 0); mstatus.set_field("UIE", 0); diff --git a/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic b/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic index a3e8052a..b1cadaa1 100644 --- a/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic @@ -1,5 +1,5 @@ # riscOVPsim configuration file converted from YAML ---variant RVB64I +--variant RV64I --override riscvOVPsim/cpu/add_Extensions=MC --override riscvOVPsim/cpu/misa_MXL=2 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 diff --git a/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv b/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv index 19f15b23..18cf13c9 100644 --- a/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv @@ -60,6 +60,8 @@ parameter int VLEN = 512; parameter int ELEN = 64; parameter int SLEN = 64; +// Number of harts +parameter int NUM_HARTS = 1; // ---------------------------------------------------------------------------- // Previleged CSR implementation // ---------------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/target/multi_harts/riscvOVPsim.ic b/vendor/google_riscv-dv/target/multi_harts/riscvOVPsim.ic new file mode 100644 index 00000000..36e0eea5 --- /dev/null +++ b/vendor/google_riscv-dv/target/multi_harts/riscvOVPsim.ic @@ -0,0 +1,22 @@ +# riscOVPsim configuration file converted from YAML +--variant RV32I +--override riscvOVPsim/cpu/add_Extensions=MCA +--override riscvOVPsim/cpu/misa_MXL=1 +--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 +--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 +--override riscvOVPsim/cpu/unaligned=T +--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 +--override riscvOVPsim/cpu/user_version=2.3 +--override riscvOVPsim/cpu/priv_version=1.11 +--override riscvOVPsim/cpu/mvendorid=0 +--override riscvOVPsim/cpu/marchid=0 +--override riscvOVPsim/cpu/mimpid=0 +--override riscvOVPsim/cpu/mhartid=0 +--override riscvOVPsim/cpu/cycle_undefined=F +--override riscvOVPsim/cpu/instret_undefined=F +--override riscvOVPsim/cpu/time_undefined=T +--override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/simulateexceptions=T +--override riscvOVPsim/cpu/defaultsemihost=F +--override riscvOVPsim/cpu/wfi_is_nop=T +--exitonsymbol _exit diff --git a/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv b/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv new file mode 100644 index 00000000..9e6e966d --- /dev/null +++ b/vendor/google_riscv-dv/target/multi_harts/riscv_core_setting.sv @@ -0,0 +1,118 @@ +/* + * 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. + */ + +//----------------------------------------------------------------------------- +// Processor feature configuration +//----------------------------------------------------------------------------- +// XLEN +parameter int XLEN = 32; + +// Parameter for SATP mode, set to BARE if address translation is not supported +parameter satp_mode_t SATP_MODE = BARE; + +// Supported Privileged mode +privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE}; + +// Unsupported instructions +riscv_instr_name_t unsupported_instr[]; + +// ISA supported by the processor +riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32A}; + +// Interrupt mode support +mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED}; + +// The number of interrupt vectors to be generated, only used if VECTORED interrupt mode is +// supported +int max_interrupt_vector_num = 16; + +// Physical memory protection support +bit support_pmp = 0; + +// Debug mode support +bit support_debug_mode = 0; + +// Support delegate trap to user mode +bit support_umode_trap = 0; + +// Support sfence.vma instruction +bit support_sfence = 0; + +// Support unaligned load/store +bit support_unaligned_load_store = 1'b1; + +// Parameter for vector extension +parameter int VECTOR_EXTENSION_ENABLE = 0; +parameter int VLEN = 512; +parameter int ELEN = 64; +parameter int SLEN = 64; + +// Number of harts +parameter int NUM_HARTS = 2; + +// ---------------------------------------------------------------------------- +// Previleged CSR implementation +// ---------------------------------------------------------------------------- + +// Implemented previlieged CSR list +`ifdef DSIM +privileged_reg_t implemented_csr[] = { +`else +parameter privileged_reg_t implemented_csr[] = { +`endif + // Machine mode mode CSR + MVENDORID, // Vendor ID + MARCHID, // Architecture ID + MIMPID, // Implementation ID + MHARTID, // Hardware thread ID + MSTATUS, // Machine status + MISA, // ISA and extensions + MIE, // Machine interrupt-enable register + MTVEC, // Machine trap-handler base address + MCOUNTEREN, // Machine counter enable + MSCRATCH, // Scratch register for machine trap handlers + MEPC, // Machine exception program counter + MCAUSE, // Machine trap cause + MTVAL, // Machine bad address or instruction + MIP // Machine interrupt pending +}; + +// ---------------------------------------------------------------------------- +// Supported interrupt/exception setting, used for functional coverage +// ---------------------------------------------------------------------------- + +`ifdef DSIM +interrupt_cause_t implemented_interrupt[] = { +`else +parameter interrupt_cause_t implemented_interrupt[] = { +`endif + M_SOFTWARE_INTR, + M_TIMER_INTR, + M_EXTERNAL_INTR +}; + +`ifdef DSIM +exception_cause_t implemented_exception[] = { +`else +parameter exception_cause_t implemented_exception[] = { +`endif + INSTRUCTION_ACCESS_FAULT, + ILLEGAL_INSTRUCTION, + BREAKPOINT, + LOAD_ADDRESS_MISALIGNED, + LOAD_ACCESS_FAULT, + ECALL_MMODE +}; diff --git a/vendor/google_riscv-dv/target/multi_harts/testlist.yaml b/vendor/google_riscv-dv/target/multi_harts/testlist.yaml new file mode 100644 index 00000000..c491ae7c --- /dev/null +++ b/vendor/google_riscv-dv/target/multi_harts/testlist.yaml @@ -0,0 +1,79 @@ +# Copyright 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. + +# ================================================================================ +# Regression test list format +# -------------------------------------------------------------------------------- +# test : Assembly test name +# description : Description of this test +# gen_opts : Instruction generator options +# iterations : Number of iterations of this test +# 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 +# rtl_test : RTL simulation test name +# cmp_opts : Compile options passed to the instruction generator +# sim_opts : Simulation options passed to the instruction generator +# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional) +# compare_opts : Options for the RTL & ISS trace comparison +# gcc_opts : gcc compile options +# -------------------------------------------------------------------------------- + +- import: /yaml/base_testlist.yaml + + +- test: riscv_non_compressed_instr_test + description: > + Random instruction test without compressed instructions + iterations: 1 + gen_test: riscv_rand_instr_test + gen_opts: > + +disable_compressed_instr=1 + rtl_test: core_base_test + + +- test: riscv_hint_instr_test + description: > + HINT instruction test, verify the processor can detect HINT instruction + treat it as NOP. No illegal instruction exception is expected + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +hint_instr_ratio=5 + rtl_test: core_base_test + + +- test: riscv_amo_test + description: > + RISC-V atomic instruction extension test + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=5000 + +num_of_sub_program=5 + +directed_instr_0=riscv_lr_sc_instr_stream,10 + +directed_instr_1=riscv_amo_instr_stream,10 + rtl_test: core_base_test + + +- test: riscv_single_hart_test + description: > + single hart random test + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=6000 + +num_of_harts=1 + rtl_test: core_base_test + diff --git a/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic index 7471c760..64bc56ba 100644 --- a/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic @@ -1,5 +1,5 @@ # riscOVPsim configuration file converted from YAML ---variant RVB32I +--variant RV32I --override riscvOVPsim/cpu/misa_MXL=1 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 --override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 diff --git a/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv index 93377f02..8f4a9778 100644 --- a/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv32i/riscv_core_setting.sv @@ -60,6 +60,8 @@ parameter int VLEN = 512; parameter int ELEN = 64; parameter int SLEN = 64; +// Number of harts +parameter int NUM_HARTS = 1; // ---------------------------------------------------------------------------- // Previleged CSR implementation // ---------------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic index 8a866c51..43c8b8c4 100644 --- a/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic @@ -1,5 +1,5 @@ # riscOVPsim configuration file converted from YAML ---variant RVB32I +--variant RV32I --override riscvOVPsim/cpu/add_Extensions=MC --override riscvOVPsim/cpu/misa_MXL=1 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 diff --git a/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv index 8113895b..9926318e 100644 --- a/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv32imc/riscv_core_setting.sv @@ -60,6 +60,9 @@ parameter int VLEN = 512; parameter int ELEN = 64; parameter int SLEN = 64; +// Number of harts +parameter int NUM_HARTS = 1; + // ---------------------------------------------------------------------------- // Previleged CSR implementation // ---------------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/target/rv32imc/testlist.yaml b/vendor/google_riscv-dv/target/rv32imc/testlist.yaml index 9efc5336..78d64fcb 100644 --- a/vendor/google_riscv-dv/target/rv32imc/testlist.yaml +++ b/vendor/google_riscv-dv/target/rv32imc/testlist.yaml @@ -62,5 +62,5 @@ +pmp_randomize=0 +pmp_num_regions=1 +pmp_granularity=1 - +pmp_region_0=L:0,A:NAPOT,X=1,W=1,R=1,ADDR=0x090000000 + +pmp_region_0=L:0,A:TOR,X:1,W:1,R:1,ADDR:FFFFFFFF rtl_test: core_base_test diff --git a/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv index b2b1f7a3..7e7ba604 100644 --- a/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv @@ -60,6 +60,9 @@ parameter int VLEN = 512; parameter int ELEN = 64; parameter int SLEN = 64; +// Number of harts +parameter int NUM_HARTS = 1; + // ---------------------------------------------------------------------------- // Previleged CSR implementation // ---------------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv index 454b568c..df86af5f 100644 --- a/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv64gcv/riscv_core_setting.sv @@ -60,6 +60,8 @@ parameter int VLEN = 512; parameter int ELEN = 64; parameter int SLEN = 64; +// Number of harts +parameter int NUM_HARTS = 1; // ---------------------------------------------------------------------------- // Previleged CSR implementation // ---------------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic index a3e8052a..b1cadaa1 100644 --- a/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic @@ -1,5 +1,5 @@ # riscOVPsim configuration file converted from YAML ---variant RVB64I +--variant RV64I --override riscvOVPsim/cpu/add_Extensions=MC --override riscvOVPsim/cpu/misa_MXL=2 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 diff --git a/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv index 6c62d48c..5ce7e0ee 100644 --- a/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv64imc/riscv_core_setting.sv @@ -60,6 +60,9 @@ parameter int VLEN = 512; parameter int ELEN = 64; parameter int SLEN = 64; +// Number of harts +parameter int NUM_HARTS = 1; + // ---------------------------------------------------------------------------- // Previleged CSR implementation // ---------------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv b/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv index 9f35d557..36ed566b 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv @@ -52,7 +52,9 @@ class riscv_ml_test extends riscv_instr_base_test; cfg.init_privileged_mode = MACHINE_MODE; cfg.init_privileged_mode.rand_mode(0); cfg.enable_unaligned_load_store = 1'b1; + cfg.addr_translaction_rnd_order_c.constraint_mode(0); `DV_CHECK_RANDOMIZE_FATAL(cfg) + cfg.addr_translaction_rnd_order_c.constraint_mode(1); `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", cfg.sprint()), UVM_LOW) endfunction diff --git a/vendor/google_riscv-dv/yaml/simulator.yaml b/vendor/google_riscv-dv/yaml/simulator.yaml index 339003f2..d926809d 100644 --- a/vendor/google_riscv-dv/yaml/simulator.yaml +++ b/vendor/google_riscv-dv/yaml/simulator.yaml @@ -79,6 +79,7 @@ +incdir+$UVM_HOME/src $UVM_HOME/src/uvm_pkg.sv +define+DSIM + -suppress EnumMustBePositive +incdir+ +incdir+ -f /files.f