diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index f4674aab..6b3c8979 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: 7cce16c0a212c8713a82516fbf8f2570d3dc4505 + rev: 73274f227000f1316cb201a8503aad437e427948 } } diff --git a/vendor/google_riscv-dv/README.md b/vendor/google_riscv-dv/README.md index 769d7bc3..0f29a577 100644 --- a/vendor/google_riscv-dv/README.md +++ b/vendor/google_riscv-dv/README.md @@ -186,24 +186,27 @@ riscv_instr_group_t supported_isa[] = {RV32I, RV32M, RV64I, RV64M}; ### 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 | -| no_ebreak | Disable ebreak instruction | 1 | -| no_wfi | Disable WFI 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 | -| enable_illegal_instruction | Enable illegal instructions | 0 | -| enable_hint_instruction | Enable HINT instruction | 0 | -| boot_mode | m:Machine mode, s:Supervisor mode, u:User mode | m | -| no_directed_instr | Disable directed instruction stream | 0 | -| enable_interrupt | Enable MStatus.MIE, used in interrupt test | 0 | -| empty_debug_section | Disables randomized debug_rom section | 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 | +| no_ebreak | Disable ebreak instruction | 1 | +| no_wfi | Disable WFI 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 | +| enable_illegal_instruction | Enable illegal instructions | 0 | +| enable_hint_instruction | Enable HINT instruction | 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 | ### Setup Privileged CSR description diff --git a/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py b/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py index 05d0bfa9..1f4f6d27 100644 --- a/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py +++ b/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py @@ -65,6 +65,9 @@ def process_spike_sim_log(spike_log, csv): rv_instr_trace.instr_str = spike_instr rv_instr_trace.addr = m.group("addr") rv_instr_trace.binary = m.group("bin") + if spike_instr == "wfi": + trace_csv.write_trace_entry(rv_instr_trace) + continue nextline = f.readline() if nextline != "": m = RD_RE.search(nextline) diff --git a/vendor/google_riscv-dv/setting/riscv_core_setting.sv b/vendor/google_riscv-dv/setting/riscv_core_setting.sv index a893983f..86b91fe5 100644 --- a/vendor/google_riscv-dv/setting/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/setting/riscv_core_setting.sv @@ -32,6 +32,9 @@ riscv_instr_name_t unsupported_instr[]; // ISA supported by the processor riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C}; +// Interrupt mode support +mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED}; + // Debug mode support bit support_debug_mode = 0; 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 213aca14..4fe82fe2 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -32,6 +32,7 @@ class riscv_asm_program_gen extends uvm_object; // Program in binary format, stored in the data section, used to inject illegal/HINT instruction riscv_instr_sequence bin_program; riscv_instr_sequence debug_program; + riscv_instr_sequence debug_sub_program[]; string instr_binary[$]; // Kernel programs // These programs are called in the interrupt/exception handling routine based on the privileged @@ -96,23 +97,7 @@ class riscv_asm_program_gen extends uvm_object; // Init section gen_init_section(); // Generate sub program - if(cfg.num_of_sub_program > 0) begin - sub_program = new[cfg.num_of_sub_program]; - foreach(sub_program[i]) begin - sub_program[i] = riscv_instr_sequence::type_id::create($sformatf("sub_%0d",i+1)); - sub_program[i].instr_cnt = cfg.sub_program_instr_cnt[i]; - sub_program[i].is_debug_program = 0; - generate_directed_instr_stream(.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)); - sub_program[i].label_name = sub_program[i].get_name(); - sub_program[i].cfg = cfg; - `DV_CHECK_RANDOMIZE_FATAL(sub_program[i]) - sub_program[i].gen_instr(0); - sub_program_name.push_back(sub_program[i].label_name); - end - end + 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; @@ -126,30 +111,7 @@ class riscv_asm_program_gen extends uvm_object; `DV_CHECK_RANDOMIZE_FATAL(main_program) main_program.gen_instr(1); // Setup jump instruction among main program and sub programs - if(cfg.num_of_sub_program != 0) begin - callstack_gen = riscv_callstack_gen::type_id::create("callstack_gen"); - callstack_gen.init(cfg.num_of_sub_program+1); - `uvm_info(get_full_name(), "Randomizing call stack", UVM_LOW) - if(callstack_gen.randomize()) begin - program_id_t pid; - int idx; - // Insert the jump instruction based on the call stack - foreach(callstack_gen.program_h[i]) begin - foreach(callstack_gen.program_h[i].sub_program_id[j]) begin - idx++; - pid = callstack_gen.program_h[i].sub_program_id[j] - 1; - `uvm_info(get_full_name(), $sformatf( - "Gen jump instr %0d -> sub[%0d] %0d", i, j, pid+1), UVM_HIGH) - if(i == 0) - main_program.insert_jump_instr(sub_program_name[pid], idx); - else - sub_program[i-1].insert_jump_instr(sub_program_name[pid], idx); - end - end - end else begin - `uvm_fatal(get_full_name(), "Failed to generate callstack") - end - end + gen_callstack(main_program, sub_program, sub_program_name, cfg.num_of_sub_program); if (bin_program != null) begin main_program.insert_jump_instr("sub_bin", 0); end @@ -159,12 +121,7 @@ class riscv_asm_program_gen extends uvm_object; // Test done section gen_test_done(); // Shuffle the sub programs and insert to the instruction stream - sub_program.shuffle(); - foreach(sub_program[i]) begin - sub_program[i].post_process_instr(); - sub_program[i].generate_instr_stream(); - instr_stream = {instr_stream, sub_program[i].instr_string_list}; - end + insert_sub_program(sub_program, instr_stream); // Reserve some space to copy instruction from data section if (instr_binary.size() > 0) begin instr_stream.push_back(".align 2"); @@ -179,9 +136,9 @@ class riscv_asm_program_gen extends uvm_object; // Program end gen_program_end(); // Generate debug rom section - gen_debug_mode_section(); + gen_debug_rom(); // Generate debug mode exception handler - gen_debug_exception_section(); + gen_debug_exception_handler(); // Starting point of data section gen_data_page_begin(); // Generate the sub program in binary format @@ -253,6 +210,79 @@ class riscv_asm_program_gen extends uvm_object; instr_stream = {instr_stream, seq.instr_string_list}; endfunction + //--------------------------------------------------------------------------------------- + // Generate any subprograms and set up the callstack + //--------------------------------------------------------------------------------------- + + virtual function void gen_sub_program(ref riscv_instr_sequence sub_program[], + ref string sub_program_name[$], + input int num_sub_program, + bit is_debug = 1'b0, + string prefix = "sub"); + 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].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()), + .original_instr_cnt(sub_program[i].instr_cnt), + .min_insert_cnt(0), + .instr_stream(sub_program[i].directed_instr)); + sub_program[i].label_name = sub_program[i].get_name(); + sub_program[i].cfg = cfg; + `DV_CHECK_RANDOMIZE_FATAL(sub_program[i]) + sub_program[i].gen_instr(0); + sub_program_name.push_back(sub_program[i].label_name); + end + end + endfunction + + virtual function void gen_callstack(riscv_instr_sequence main_program, + ref riscv_instr_sequence sub_program[], + ref string sub_program_name[$], + input int num_sub_program); + if(num_sub_program != 0) begin + callstack_gen = riscv_callstack_gen::type_id::create("callstack_gen"); + callstack_gen.init(num_sub_program+1); + `uvm_info(get_full_name(), "Randomizing call stack", UVM_LOW) + if(callstack_gen.randomize()) begin + program_id_t pid; + int idx; + // Insert the jump instruction based on the call stack + foreach(callstack_gen.program_h[i]) begin + foreach(callstack_gen.program_h[i].sub_program_id[j]) begin + idx++; + pid = callstack_gen.program_h[i].sub_program_id[j] - 1; + `uvm_info(get_full_name(), $sformatf( + "Gen jump instr %0d -> sub[%0d] %0d", i, j, pid+1), UVM_HIGH) + if(i == 0) + main_program.insert_jump_instr(sub_program_name[pid], idx); + else + sub_program[i-1].insert_jump_instr(sub_program_name[pid], idx); + end + end + end else begin + `uvm_fatal(get_full_name(), "Failed to generate callstack") + end + end + endfunction + + virtual function void insert_sub_program(ref riscv_instr_sequence sub_program[], + ref string instr_list[$]); + sub_program.shuffle(); + foreach(sub_program[i]) begin + sub_program[i].post_process_instr(); + sub_program[i].generate_instr_stream(); + instr_list = {instr_list, sub_program[i].instr_string_list}; + end + endfunction + //--------------------------------------------------------------------------------------- // Major sections - init, stack, data, test_done etc. //--------------------------------------------------------------------------------------- @@ -327,6 +357,7 @@ class riscv_asm_program_gen extends uvm_object; str = {indent, "la sp, _user_stack_end"}; setup_misa(); instr_stream.push_back(str); + core_is_initialized(); // Copy the instruction from data section to instruction section if (instr_binary.size() > 0) begin instr_stream.push_back({indent, "la x31, instr_bin"}); @@ -363,6 +394,24 @@ class riscv_asm_program_gen extends uvm_object; instr_stream.push_back({indent, "csrw misa, x15"}); endfunction + // Write to the signature_addr with values to indicate to the core testbench + // that is safe to start sending interrupt and debug stimulus + virtual function void core_is_initialized(); + if (cfg.require_signature_addr) begin + if (cfg.signature_addr != 32'hdead_beef) begin + string str; + str = {indent, $sformatf("li x5, 0x%0h", cfg.signature_addr)}; + instr_stream.push_back(str); + str = {indent, $sformatf("li x6, 0x%0h", riscv_instr_pkg::CORE_INITIALIZATION_DONE)}; + instr_stream.push_back(str); + str = {indent, "sw x6, 0(x5)"}; + instr_stream.push_back(str); + end else begin + `uvm_fatal(`gfn, "The signature_addr is not properly configured!") + end + end + endfunction + // Initialize general purpose registers with random value virtual function void init_gpr(); string str; @@ -531,9 +580,9 @@ class riscv_asm_program_gen extends uvm_object; USER_MODE: trap_vec_reg = UTVEC; endcase // Skip utvec init if trap delegation to u_mode is not supported - // TODO: For now the default mode is direct mode, needs to support vector mode - if((riscv_instr_pkg::supported_privileged_mode[i] == USER_MODE) && !riscv_instr_pkg::support_umode_trap) continue; - if(riscv_instr_pkg::supported_privileged_mode[i] < cfg.init_privileged_mode) continue; + if ((riscv_instr_pkg::supported_privileged_mode[i] == USER_MODE) && + !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 a0, %0s_handler", tvec_name.tolower())}; if(SATP_MODE != BARE && riscv_instr_pkg::supported_privileged_mode[i] != MACHINE_MODE) begin @@ -544,6 +593,7 @@ class riscv_asm_program_gen extends uvm_object; $sformatf("slli a0, a0, %0d", XLEN - 20), $sformatf("srli a0, a0, %0d", XLEN - 20)}; end + instr = {instr, $sformatf("ori a0, a0, %0d", cfg.mtvec_mode)}; instr = {instr, $sformatf("csrw 0x%0x, a0 # %0s", trap_vec_reg, trap_vec_reg.name())}; end gen_section("trap_vec_init", instr); @@ -595,21 +645,32 @@ class riscv_asm_program_gen extends uvm_object; bit is_interrupt = 'b1; string tvec_name; string instr[$]; - // Push user mode GPR to kernel stack before executing exception handling, this is to avoid - // exception handling routine modify user program state unexpectedly - push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, instr); - // Checking xStatus can be optional if ISS (like spike) has different implementation of certain - // fields compared with the RTL processor. - if (cfg.check_xstatus) begin - instr = {instr, $sformatf("csrr x15, 0x%0x # %0s", status, status.name())}; + // 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"); + if (cfg.mtvec_mode == VECTORED) begin + gen_interrupt_vector_table(mode, status, cause, 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 + push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, instr); + // Checking xStatus can be optional if ISS (like spike) has different implementation of certain + // fields compared with the RTL processor. + if (cfg.check_xstatus) begin + instr = {instr, $sformatf("csrr x15, 0x%0x # %0s", status, status.name())}; + end + instr = {instr, + // Use scratch CSR to save a GPR value + // Check if the exception is caused by an interrupt, if yes, jump to interrupt handler + // Interrupt is indicated by xCause[XLEN-1] + $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()), + $sformatf("srli a1, a1, %0d", XLEN-1), + $sformatf("bne a1, x0, %0smode_intr_handler", mode)}; end - instr = {instr, - // Use scratch CSR to save a GPR value - // Check if the exception is caused by an interrupt, if yes, jump to interrupt handler - // Interrupt is indicated by xCause[XLEN-1] - $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()), - $sformatf("srli a1, a1, %0d", XLEN-1), - $sformatf("bne a1, x0, %0smode_intr_handler", mode), + tvec_name = tvec.name(); + gen_section($sformatf("%0s_handler", tvec_name.tolower()), instr); + // Exception handler + instr = {"", // The trap is caused by an exception, read back xCAUSE, xEPC to see if these // CSR values are set properly. The checking is done by comparing against the log // generated by ISA simulator (spike). @@ -645,13 +706,41 @@ class riscv_asm_program_gen extends uvm_object; $sformatf("csrr x30, 0x%0x # %0s", tval, tval.name()), "1: jal x1, test_done " }; + gen_section($sformatf("%0smode_exception_handler", mode), instr); + endfunction - // 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); + // Generate for interrupt vector table + virtual function void gen_interrupt_vector_table(string mode, + privileged_reg_t status, + privileged_reg_t cause, + privileged_reg_t scratch, + ref string instr[$]); + // In vector mode, the BASE address is shared between interrupt 0 and exception handling. + // When vectored interrupts are enabled, interrupt cause 0, which corresponds to user-mode + // software interrupts, are vectored to the same location as synchronous exceptions. This + // 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)}; + // Redirect the interrupt to the corresponding interrupt handler + for (int i = 1; i < 16; i++) begin + instr.push_back($sformatf("j intr_vector_%0d", i)); + end + instr = {instr, ".option rvc;"}; + for (int i = 1; i < 16; i++) begin + string intr_handler[$]; + push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, intr_handler); + intr_handler = {intr_handler, + $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()), + // Terminate the test if xCause[31] != 0 (indicating exception) + $sformatf("bltz a1, 1f"), + // TODO(taliu) write xCause to the signature address + // Jump to commmon interrupt handling routine + $sformatf("j %0smode_intr_handler", mode), + "1: j test_done"}; + gen_section($sformatf("intr_vector_%0d", i), intr_handler); + end endfunction // ECALL trap handler @@ -932,21 +1021,26 @@ class riscv_asm_program_gen extends uvm_object; // Generate the program in the debug ROM // Processor will fetch instruction from here upon receiving debug request from debug module - virtual function void gen_debug_mode_section(); + virtual function void gen_debug_rom(); string push_gpr[$]; string pop_gpr[$]; string instr[$]; string dret; + string debug_sub_program_name[$] = {}; if (riscv_instr_pkg::support_debug_mode) begin // The main debug rom - if (!cfg.empty_debug_section) begin + if (cfg.gen_debug_section) begin + gen_sub_program(debug_sub_program, debug_sub_program_name, + cfg.num_debug_sub_program, 1'b1, "debug_sub"); debug_program = riscv_instr_sequence::type_id::create("debug_program"); debug_program.instr_cnt = cfg.debug_program_instr_cnt; debug_program.is_debug_program = 1; debug_program.cfg = cfg; `DV_CHECK_RANDOMIZE_FATAL(debug_program) debug_program.gen_instr(.is_main_program(1'b1), .enable_hint_instr(1'b0), - .no_branch(1'b1)); + .no_branch(1'b0)); + gen_callstack(debug_program, debug_sub_program, debug_sub_program_name, + cfg.num_debug_sub_program); debug_program.post_process_instr(); debug_program.generate_instr_stream(.no_label(1'b1)); // Need to save off GPRs to avoid modifying program flow @@ -955,6 +1049,7 @@ class riscv_asm_program_gen extends uvm_object; pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, pop_gpr); format_section(pop_gpr); instr = {push_gpr, debug_program.instr_string_list, pop_gpr}; + insert_sub_program(debug_sub_program, instr_stream); end dret = {format_string(" ", LABEL_STR_LEN), "dret"}; instr = {instr, dret}; @@ -963,7 +1058,7 @@ class riscv_asm_program_gen extends uvm_object; endfunction // Generate exception handling routine for debug ROM - virtual function void gen_debug_exception_section(); + virtual function void gen_debug_exception_handler(); if (riscv_instr_pkg::support_debug_mode) begin string instr[]; instr = {"dret"}; 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 878df684..5ff6bcf4 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv @@ -33,6 +33,9 @@ class riscv_instr_gen_config extends uvm_object; // 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; @@ -55,6 +58,7 @@ class riscv_instr_gen_config extends uvm_object; rand bit mstatus_mxr; rand bit mstatus_sum; rand bit mstatus_tvm; + rand mtvec_mode_t mtvec_mode; // Enable sfence.vma instruction rand bit enable_sfence; @@ -65,12 +69,6 @@ class riscv_instr_gen_config extends uvm_object; bit check_misa_init_val = 1'b0; bit check_xstatus = 1'b1; - // 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 empty_debug_section = 1'b0; - //----------------------------------------------------------------------------- // Command line options or control knobs //----------------------------------------------------------------------------- @@ -111,6 +109,18 @@ class riscv_instr_gen_config extends uvm_object; bit force_m_delegation = 0; bit force_s_delegation = 0; bit support_supervisor_mode; + // "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; + bit gen_debug_section = 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 empty_debug_section = 1'b0; + // Number of sub programs in the debug rom + int num_debug_sub_program = 0; // Stack space allocated to each program, need to be enough to store necessary context // Example: RA, SP, T0, loop registers int min_stack_len_per_program = 10 * (XLEN/8); @@ -132,13 +142,19 @@ class riscv_instr_gen_config extends uvm_object; constraint default_c { sub_program_instr_cnt.size() == num_of_sub_program; + debug_sub_program_instr_cnt.size() == num_debug_sub_program; if (riscv_instr_pkg::support_debug_mode) { - main_program_instr_cnt + sub_program_instr_cnt.sum() + debug_program_instr_cnt == instr_cnt; + main_program_instr_cnt + sub_program_instr_cnt.sum() + + debug_program_instr_cnt + + debug_sub_program_instr_cnt.sum() == instr_cnt; + debug_program_instr_cnt inside {[100 : 300]}; + foreach(debug_sub_program_instr_cnt[i]) { + debug_sub_program_instr_cnt[i] inside {[100 : 300]}; + } } else { main_program_instr_cnt + sub_program_instr_cnt.sum() == instr_cnt; } main_program_instr_cnt inside {[1 : instr_cnt]}; - debug_program_instr_cnt inside {[1 : instr_cnt]}; foreach(sub_program_instr_cnt[i]) { sub_program_instr_cnt[i] inside {[1 : instr_cnt]}; } @@ -169,6 +185,10 @@ class riscv_instr_gen_config extends uvm_object; } } + 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 @@ -269,7 +289,12 @@ class riscv_instr_gen_config extends uvm_object; get_bool_arg_value("+enable_hint_instruction=", enable_hint_instruction); get_bool_arg_value("+force_m_delegation=", force_m_delegation); get_bool_arg_value("+force_s_delegation=", force_s_delegation); - get_bool_arg_value("+empty_debug_section=", empty_debug_section); + get_bool_arg_value("+require_signature_addr=", require_signature_addr); + 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_int_arg_value("+num_debug_sub_program=", num_debug_sub_program); 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) @@ -379,15 +404,25 @@ class riscv_instr_gen_config extends uvm_object; // 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)) + 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)) + 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 endclass diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index 6b035a28..30183d44 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -24,6 +24,8 @@ package riscv_instr_pkg; `define include_file(f) `include `"f`" + parameter CORE_INITIALIZATION_DONE = 2; + typedef enum bit [3:0] { BARE = 4'b0000, SV32 = 4'b0001, @@ -33,6 +35,11 @@ package riscv_instr_pkg; SV64 = 4'b1011 } satp_mode_t; + typedef enum bit [1:0] { + DIRECT = 2'b00, + VECTORED = 2'b01 + } mtvec_mode_t; + typedef enum bit [2:0] { IMM, // Signed immediate UIMM, // Unsigned immediate @@ -729,7 +736,7 @@ package riscv_instr_pkg; // need to use the virtual address to access the kernel stack. if((status == MSTATUS) && (SATP_MODE != BARE)) begin // We temporarily use tp to check mstatus to avoid changing other GPR. The value of sp has - // been saved to xStatus and can be restored later. + // been saved to xScratch and can be restored later. if(mprv) begin instr.push_back($sformatf("csrr tp, 0x%0x // MSTATUS", status)); instr.push_back("srli tp, tp, 11"); // Move MPP to bit 0 diff --git a/vendor/google_riscv-dv/yaml/csr_template.yaml b/vendor/google_riscv-dv/yaml/csr_template.yaml index 230ae026..feeb096d 100644 --- a/vendor/google_riscv-dv/yaml/csr_template.yaml +++ b/vendor/google_riscv-dv/yaml/csr_template.yaml @@ -4,7 +4,7 @@ # 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 +# 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, diff --git a/vendor/google_riscv-dv/yaml/iss.yaml b/vendor/google_riscv-dv/yaml/iss.yaml index 4ed2a496..216cc6d3 100644 --- a/vendor/google_riscv-dv/yaml/iss.yaml +++ b/vendor/google_riscv-dv/yaml/iss.yaml @@ -4,7 +4,7 @@ # 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 +# 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, diff --git a/vendor/google_riscv-dv/yaml/simulator.yaml b/vendor/google_riscv-dv/yaml/simulator.yaml index 96fc0dad..f73eca26 100644 --- a/vendor/google_riscv-dv/yaml/simulator.yaml +++ b/vendor/google_riscv-dv/yaml/simulator.yaml @@ -4,7 +4,7 @@ # 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 +# 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, diff --git a/vendor/google_riscv-dv/yaml/testlist.yaml b/vendor/google_riscv-dv/yaml/testlist.yaml index 6e0bc889..7307b8d9 100644 --- a/vendor/google_riscv-dv/yaml/testlist.yaml +++ b/vendor/google_riscv-dv/yaml/testlist.yaml @@ -4,7 +4,7 @@ # 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 +# 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, @@ -185,10 +185,12 @@ iterations: 2 gen_test: riscv_rand_instr_test gen_opts: > + +require_signature_addr=1 +instr_cnt=6000 +no_ebreak=0 rtl_test: core_base_test sim_opts: > + +require_signature_addr=1 +enable_debug_seq=1 compare_opts: > +compare_final_value_only=1 @@ -203,10 +205,12 @@ iterations: 2 gen_test: riscv_rand_instr_test gen_opts: > + +require_signature_addr=1 +skip_trap_handling=1 +no_wfi=0 rtl_test: core_base_test sim_opts: > + +require_signature_addr=1 +enable_irq_seq=1 - test: riscv_full_interrupt_test @@ -214,8 +218,11 @@ Random instruction test with complete interrupt handling iterations: 2 gen_test: riscv_rand_instr_test + gen_opts: > + +require_signature_addr=1 rtl_test: core_base_test sim_opts: > + +require_signature_addr=1 +enable_irq_seq=1 compare_opts: > +compare_final_value_only=1