diff --git a/verif/env/corev-dv/cva6_asm_program_gen.sv b/verif/env/corev-dv/cva6_asm_program_gen.sv index e2b22314c1..0fb37d34b9 100644 --- a/verif/env/corev-dv/cva6_asm_program_gen.sv +++ b/verif/env/corev-dv/cva6_asm_program_gen.sv @@ -61,14 +61,6 @@ class cva6_asm_program_gen_c extends riscv_asm_program_gen; // 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 @@ -177,25 +169,35 @@ class cva6_asm_program_gen_c extends riscv_asm_program_gen; bit is_interrupt = 'b1; string tvec_name; string instr[$]; + string str; if (cfg_cva6.mtvec_mode == VECTORED) begin 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 - push_gpr_to_kernel_stack(status, scratch, cfg_cva6.mstatus_mprv, cfg_cva6.sp, cfg_cva6.tp, instr); + push_used_gpr_to_kernel_stack(status, scratch, 4, cfg_cva6.mstatus_mprv, cfg_cva6.sp, cfg_cva6.tp, instr); // Checking xStatus can be optional if ISS (like spike) has different implementation of // certain fields compared with the RTL processor. if (cfg_cva6.check_xstatus) begin instr = {instr, $sformatf("csrr x%0d, 0x%0x # %0s", cfg_cva6.gpr[0], status, status.name())}; end + str = format_string("exception_handler_incr_mepc2:", LABEL_STR_LEN); 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 x%0d, 0x%0x # %0s", cfg_cva6.gpr[0], cause, cause.name()), - $sformatf("srli x%0d, x%0d, %0d", cfg_cva6.gpr[0], cfg_cva6.gpr[0], XLEN-1), - $sformatf("bne x%0d, x0, %0s%0smode_intr_handler", - cfg_cva6.gpr[0], hart_prefix(hart), mode)}; + $sformatf("csrr x%0d, mepc", cfg_cva6.gpr[0]), + $sformatf("lbu x%0d, 0(x%0d)", cfg_cva6.gpr[3],cfg_cva6.gpr[0]), + $sformatf("li x%0d, 0x3", cfg_cva6.gpr[1]), + $sformatf("and x%0d, x%0d, x%0d", cfg_cva6.gpr[3], cfg_cva6.gpr[3], cfg_cva6.gpr[1]), + $sformatf("bne x%0d, x%0d, exception_handler_incr_mepc2", cfg_cva6.gpr[3], cfg_cva6.gpr[1]), + $sformatf("addi x%0d, x%0d, 2", cfg_cva6.gpr[0], cfg_cva6.gpr[0]), + str, + $sformatf("addi x%0d, x%0d, 2", cfg_cva6.gpr[0], cfg_cva6.gpr[0]), + $sformatf("csrw mepc, x%0d", cfg_cva6.gpr[0])}; + pop_used_gpr_from_kernel_stack(MSTATUS, MSCRATCH, 4, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); + instr.push_back("mret"); end // The trap handler will occupy one 4KB page, it will be allocated one entry in the page table // with a specific privileged mode. @@ -212,66 +214,77 @@ class cva6_asm_program_gen_c extends riscv_asm_program_gen; push_gpr_to_kernel_stack(status, scratch, cfg_cva6.mstatus_mprv, cfg_cva6.sp, cfg_cva6.tp, instr); end gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION); - instr = {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). - $sformatf("csrr x%0d, 0x%0x # %0s", cfg_cva6.gpr[0], epc, epc.name()), - $sformatf("csrr x%0d, 0x%0x # %0s", cfg_cva6.gpr[0], cause, cause.name()), - // Breakpoint - $sformatf("li x%0d, 0x%0x # BREAKPOINT", cfg_cva6.gpr[1], BREAKPOINT), - $sformatf("beq x%0d, x%0d, %0sebreak_handler", - cfg_cva6.gpr[0], cfg_cva6.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_cva6.gpr[1], ECALL_UMODE), - $sformatf("beq x%0d, x%0d, %0secall_handler", - cfg_cva6.gpr[0], cfg_cva6.gpr[1], hart_prefix(hart)), - $sformatf("li x%0d, 0x%0x # ECALL_SMODE", cfg_cva6.gpr[1], ECALL_SMODE), - $sformatf("beq x%0d, x%0d, %0secall_handler", - cfg_cva6.gpr[0], cfg_cva6.gpr[1], hart_prefix(hart)), - $sformatf("li x%0d, 0x%0x # ECALL_MMODE", cfg.gpr[1], ECALL_MMODE), - $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, %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, %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, %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, %0spt_instr_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, %0spt_load_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, %0spt_store_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, %0sillegal_instr_handler", - cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), - // Instruction Address misaligned exception - $sformatf("li x%0d, 0x%0x # INSTR ADDR MISALIGNED", cfg.gpr[1], INSTRUCTION_ADDRESS_MISALIGNED), - $sformatf("beq x%0d, x%0d, %0sinstr_misaligned_handler", - cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), - // Load Address misaligned exception - $sformatf("li x%0d, 0x%0x # LOAD ADDR MISALIGNED", cfg.gpr[1], LOAD_ADDRESS_MISALIGNED), - $sformatf("beq x%0d, x%0d, %0sload_misaligned_handler", - cfg.gpr[0], cfg.gpr[1], hart_prefix(hart)), - // Store Address misaligned exception - $sformatf("li x%0d, 0x%0x # STORE ADDR MISALIGNED", cfg.gpr[1], STORE_AMO_ADDRESS_MISALIGNED), - $sformatf("beq x%0d, x%0d, %0sstore_misaligned_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(get_label($sformatf("%0smode_exception_handler", mode), hart), instr); + endfunction + + // Push used general purpose register to stack, this is needed before trap handling + virtual function void push_used_gpr_to_kernel_stack(privileged_reg_t status, + privileged_reg_t scratch, + int gpr_num, + bit mprv, + riscv_reg_t sp, + riscv_reg_t tp, + ref string instr[$]); + string store_instr = (XLEN == 32) ? "sw" : "sd"; + if (scratch inside {implemented_csr}) begin + // Push USP from gpr.SP onto the kernel stack + instr.push_back($sformatf("addi x%0d, x%0d, -4", tp, tp)); + instr.push_back($sformatf("%0s x%0d, (x%0d)", store_instr, sp, tp)); + // Move KSP to gpr.SP + instr.push_back($sformatf("add x%0d, x%0d, zero", sp, tp)); + end + // If MPRV is set and MPP is S/U mode, it means the address translation and memory protection + // for load/store instruction is the same as the mode indicated by MPP. In this case, we + // 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 pushed to the kernel stack, so can be recovered later) + if(mprv) begin + instr.push_back($sformatf("csrr x%0d, 0x%0x // MSTATUS", tp, status)); + instr.push_back($sformatf("srli x%0d, x%0d, 11", tp, tp)); // Move MPP to bit 0 + instr.push_back($sformatf("andi x%0d, x%0d, 0x3", tp, tp)); // keep the MPP bits + // Check if MPP equals to M-mode('b11) + instr.push_back($sformatf("xori x%0d, x%0d, 0x3", tp, tp)); + instr.push_back($sformatf("bnez x%0d, 1f", tp)); // Use physical address for kernel SP + // Use virtual address for stack pointer + instr.push_back($sformatf("slli x%0d, x%0d, %0d", sp, sp, XLEN - MAX_USED_VADDR_BITS)); + instr.push_back($sformatf("srli x%0d, x%0d, %0d", sp, sp, XLEN - MAX_USED_VADDR_BITS)); + instr.push_back("1: nop"); + end + end + // Push used GPRs (except for x0) to kernel stack + // (gpr.SP currently holds the KSP) + instr.push_back($sformatf("addi x%0d, x%0d, -%0d", sp, sp, 32 * (XLEN/8))); + for(int i = 1; i <= gpr_num; i++) begin + instr.push_back($sformatf("%0s x%0d, %0d(x%0d)", store_instr, cfg_cva6.gpr[i-1], i * (XLEN/8), sp)); + end + // Move KSP back to gpr.TP + // (this is needed if we again take a interrupt (nested) before restoring our USP) + instr.push_back($sformatf("add x%0d, x%0d, zero", tp, sp)); + endfunction + + // Pop used general purpose register from stack, this is needed before returning to user program + virtual function void pop_used_gpr_from_kernel_stack(privileged_reg_t status, + privileged_reg_t scratch, + int gpr_num, + bit mprv, + riscv_reg_t sp, + riscv_reg_t tp, + ref string instr[$]); + string load_instr = (XLEN == 32) ? "lw" : "ld"; + // Move KSP to gpr.SP + instr.push_back($sformatf("add x%0d, x%0d, zero", sp, tp)); + // Pop GPRs from kernel stack + for(int i = 1; i <= gpr_num; i++) begin + instr.push_back($sformatf("%0s x%0d, %0d(x%0d)", load_instr, cfg_cva6.gpr[i-1], i * (XLEN/8), sp)); + end + instr.push_back($sformatf("addi x%0d, x%0d, %0d", sp, sp, 32 * (XLEN/8))); + if (scratch inside {implemented_csr}) begin + // Move KSP back to gpr.TP + instr.push_back($sformatf("add x%0d, x%0d, zero", tp, sp)); + // Pop USP from the kernel stack, move back to gpr.SP + instr.push_back($sformatf("%0s x%0d, (x%0d)", load_instr, sp, tp)); + instr.push_back($sformatf("addi x%0d, x%0d, 4", tp, tp)); + end endfunction // Trap handling routine @@ -279,32 +292,8 @@ class cva6_asm_program_gen_c extends riscv_asm_program_gen; string instr[$]; // 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); + gen_trap_handlers(hart); end - // Ebreak handler - gen_ebreak_handler(hart); - // Illegal instruction handler - gen_illegal_instr_handler(hart); - // Instruction page fault handler - gen_pt_instr_fault_handler(hart); - // Load page fault handler - gen_pt_load_fault_handler(hart); - // Store page fault handler - gen_pt_store_fault_handler(hart); - // Instruction Address Misaligned handler - gen_instr_misaligned_handler(hart); - // Load Address Misaligned handler - gen_load_misaligned_handler(hart); - // Store Address Misaligned handler - gen_store_misaligned_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. @@ -391,242 +380,6 @@ class cva6_asm_program_gen_c extends riscv_asm_program_gen; end endfunction - // Illegal instruction trap handler - virtual function void gen_illegal_instr_handler(int hart); - string instr[$]; - string str = format_string("illegal_instr_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, illegal_instr_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("illegal_instr_handler", hart), instr); - endfunction - - // ECALL trap handler - virtual function void gen_ecall_handler(int hart); - string instr[$]; - string str = format_string("ecall_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, ecall_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("ecall_handler", hart), instr); - endfunction - - // TODO: handshake correct csr based on delegation - virtual function void gen_instr_fault_handler(int hart); - string instr[$]; - string str = format_string("instr_fault_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, instr_fault_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("instr_fault_handler", hart), instr); - endfunction - - // TODO: handshake correct csr based on delegation - virtual function void gen_load_fault_handler(int hart); - string instr[$]; - string str = format_string("load_fault_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, load_fault_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("load_fault_handler", hart), instr); - endfunction - - // TODO: handshake correct csr based on delegation - virtual function void gen_store_fault_handler(int hart); - string instr[$]; - string str = format_string("store_fault_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, store_fault_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("store_fault_handler", hart), instr); - endfunction - - virtual function void gen_pt_instr_fault_handler(int hart); - string instr[$]; - string str = format_string("pt_instr_fault_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, pt_instr_fault_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("pt_instr_fault_handler", hart), instr); - endfunction - - virtual function void gen_pt_load_fault_handler(int hart); - string instr[$]; - string str = format_string("pt_load_fault_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, pt_load_fault_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("pt_load_fault_handler", hart), instr); - endfunction - - virtual function void gen_pt_store_fault_handler(int hart); - string instr[$]; - string str = format_string("pt_store_fault_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, pt_store_fault_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("pt_store_fault_handler", hart), instr); - endfunction - - virtual function void gen_load_misaligned_handler(int hart); - string instr[$]; - string str = format_string("load_misaligned_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, load_misaligned_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("load_misaligned_handler", hart), instr); - endfunction - - virtual function void gen_store_misaligned_handler(int hart); - string instr[$]; - string str = format_string("store_misaligned_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, store_misaligned_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("store_misaligned_handler", hart), instr); - endfunction - - virtual function void gen_instr_misaligned_handler(int hart); - string instr[$]; - string str = format_string("instr_misaligned_handler_incr_mepc2:", LABEL_STR_LEN); - gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION); - gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE)); - instr = {instr, - $sformatf("csrr x%0d, mepc", cfg.gpr[0]), - $sformatf("lbu x%0d, 0(x%0d)", cfg.gpr[3],cfg.gpr[0]), - $sformatf("li x%0d, 0x3", cfg.gpr[2]), - $sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]), - $sformatf("bne x%0d, x%0d, instr_misaligned_handler_incr_mepc2", cfg.gpr[3], cfg.gpr[2]), - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - str, - $sformatf("addi x%0d, x%0d, 2", cfg.gpr[0], cfg.gpr[0]), - $sformatf("csrw mepc, x%0d", cfg.gpr[0]) - }; - pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr); - instr.push_back("mret"); - gen_section(get_label("instr_misaligned_handler", hart), instr); - endfunction - virtual function void gen_test_done(); string str = format_string("test_done:", LABEL_STR_LEN); instr_stream.push_back(str); diff --git a/verif/env/corev-dv/cva6_instr_gen_config.sv b/verif/env/corev-dv/cva6_instr_gen_config.sv index 24438cecf3..7a8f53a11d 100644 --- a/verif/env/corev-dv/cva6_instr_gen_config.sv +++ b/verif/env/corev-dv/cva6_instr_gen_config.sv @@ -42,6 +42,10 @@ class cva6_instr_gen_config_c extends riscv_instr_gen_config; } } + constraint mtvec_mode_c { + mtvec_mode == DIRECT; + } + `uvm_object_utils_begin(cva6_instr_gen_config_c) `uvm_field_int(enable_x_extension, UVM_DEFAULT) `uvm_field_int(enable_rdrs1_hazard, UVM_DEFAULT) diff --git a/verif/env/corev-dv/cva6_instr_sequence.sv b/verif/env/corev-dv/cva6_instr_sequence.sv index e0f17ae12d..c1c17a8418 100644 --- a/verif/env/corev-dv/cva6_instr_sequence.sv +++ b/verif/env/corev-dv/cva6_instr_sequence.sv @@ -47,10 +47,18 @@ class cva6_instr_sequence_c extends riscv_instr_sequence; `DV_CHECK_RANDOMIZE_WITH_FATAL(unsupported_instr, unsupported_instr inside {rv64i_instr, rv64c_instr, rv64m_instr, rvfdq_instr, illegal_slli_srai, sys_instr, illegal_rv32zcb_instr, rv64zcb_instr, rv32vf_instr};) - str = {indent, $sformatf(".4byte 0x%s # %0s", - unsupported_instr.get_bin_str(), unsupported_instr.comment)}; - idx = $urandom_range(0, instr_string_list.size()); - instr_string_list.insert(idx, str); + if (unsupported_instr.compressed) begin + str = {indent, $sformatf(".2byte 0x%s # %0s", + unsupported_instr.get_bin_str(), unsupported_instr.comment)}; + idx = $urandom_range(0, instr_string_list.size()); + instr_string_list.insert(idx, str); + end + else begin + str = {indent, $sformatf(".4byte 0x%s # %0s", + unsupported_instr.get_bin_str(), unsupported_instr.comment)}; + idx = $urandom_range(0, instr_string_list.size()); + instr_string_list.insert(idx, str); + end end end endfunction