mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 13:47:13 -04:00
Merge pull request #2043 from ThalesSiliconSecurity/core-dv
CVA6-DV : Update cva6-dv to support cvxif custom instruction base on new spec
This commit is contained in:
commit
f8cf804f75
11 changed files with 500 additions and 105 deletions
60
cva6/env/corev-dv/custom/cvxif_custom_instr.sv
vendored
60
cva6/env/corev-dv/custom/cvxif_custom_instr.sv
vendored
|
@ -17,26 +17,25 @@
|
|||
*/
|
||||
class cvxif_custom_instr extends riscv_custom_instr;
|
||||
|
||||
riscv_instr_name_t instr_name;
|
||||
|
||||
rand riscv_reg_t rs1;
|
||||
rand riscv_reg_t rs2;
|
||||
rand riscv_reg_t rs3;
|
||||
|
||||
`uvm_object_utils(cvxif_custom_instr)
|
||||
`uvm_object_new
|
||||
|
||||
static function bit register(riscv_instr_name_t instr_name);
|
||||
`uvm_info("custom_cva6_instr", $sformatf("Registering %0s", instr_name.name()), UVM_LOW)
|
||||
instr_registry[instr_name] = 1;
|
||||
return 1;
|
||||
endfunction : register
|
||||
|
||||
virtual function string get_instr_name();
|
||||
get_instr_name = instr_name.name();
|
||||
return get_instr_name;
|
||||
endfunction : get_instr_name
|
||||
|
||||
|
||||
constraint cus_rx {
|
||||
if (instr_name inside {CUS_EXC}) {
|
||||
rd == 0;
|
||||
rs1 inside {[0:9],[11:13],15};
|
||||
rs2 == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the instruction to assembly code
|
||||
virtual function string convert2asm(string prefix = "");
|
||||
string asm_str;
|
||||
|
@ -46,12 +45,9 @@ class cvxif_custom_instr extends riscv_custom_instr;
|
|||
CUS_ADD_MULTI: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
CUS_ADD_RS3: asm_str = $sformatf("%0s %0s, %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name(), rs3.name());
|
||||
CUS_NOP: asm_str = "cus_nop";
|
||||
/* following instructions are not yet supported by cva6 */
|
||||
//CUS_EXC: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
//CUS_U_ADD: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
//CUS_S_ADD: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
//CUS_NOP_EXC: asm_str = "cus_nop_exc";
|
||||
//CUS_ISS_EXC: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
CUS_S_ADD: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
CUS_U_ADD: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
CUS_EXC: asm_str = $sformatf("%0s %0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name());
|
||||
endcase
|
||||
comment = {get_instr_name(), " ", comment};
|
||||
if (comment != "") begin
|
||||
|
@ -61,22 +57,21 @@ class cvxif_custom_instr extends riscv_custom_instr;
|
|||
endfunction : convert2asm
|
||||
|
||||
virtual function void set_imm_len();
|
||||
imm_len = 7;
|
||||
imm_len = 6;
|
||||
endfunction : set_imm_len
|
||||
|
||||
function bit [6:0] get_opcode();
|
||||
case (instr_name) inside
|
||||
{CUS_ADD, CUS_ADD_MULTI, CUS_ADD_RS3, CUS_NOP} : get_opcode = 7'b1111011;
|
||||
// {CUS_ADD, CUS_ADD_MULTI, CUS_ADD_RS3, CUS_NOP, CUS_EXC, CUS_U_ADD, CUS_S_ADD} : get_opcode = 7'b1111011;
|
||||
{CUS_ADD, CUS_ADD_MULTI, CUS_ADD_RS3, CUS_NOP, CUS_U_ADD, CUS_S_ADD, CUS_EXC} : get_opcode = 7'b1111011;
|
||||
default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
virtual function bit [2:0] get_func3();
|
||||
case (instr_name) inside
|
||||
{CUS_ADD_MULTI, CUS_ADD_RS3, CUS_NOP} : get_func3 = 3'b000;
|
||||
{CUS_ADD} : get_func3 = 3'b001;
|
||||
// {CUS_ADD, CUS_ADD_MULTI, CUS_ADD_RS3, CUS_NOP, CUS_EXC, CUS_U_ADD, CUS_S_ADD} : get_func3 = 3'b000;
|
||||
CUS_ADD_MULTI, CUS_ADD_RS3, CUS_U_ADD, CUS_S_ADD : get_func3 = 3'b000;
|
||||
CUS_ADD : get_func3 = 3'b001;
|
||||
CUS_EXC : get_func3 = 3'b010;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
|
@ -85,10 +80,9 @@ class cvxif_custom_instr extends riscv_custom_instr;
|
|||
CUS_ADD : get_func7 = 7'b0000000;
|
||||
CUS_NOP : get_func7 = 7'b0000000;
|
||||
CUS_ADD_MULTI : get_func7 = 7'b0001000;
|
||||
// CUS_EXC : get_func7 = 7'b1000000;
|
||||
// CUS_M_ADD : get_func7 = 7'b0000010;
|
||||
// CUS_S_ADD : get_func7 = 7'b0000110;
|
||||
// CUS_EXC : get_func7 = 7'b0100000;
|
||||
CUS_U_ADD : get_func7 = 7'b0000010;
|
||||
CUS_S_ADD : get_func7 = 7'b0000110;
|
||||
CUS_EXC : get_func7 = 7'b1100000;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
|
@ -99,17 +93,21 @@ class cvxif_custom_instr extends riscv_custom_instr;
|
|||
endfunction
|
||||
|
||||
virtual function void set_rand_mode();
|
||||
/*case (instr_name) inside
|
||||
"CUS_EXC", "CUS_ISS_EXC": begin
|
||||
has_rd= 1'b0;
|
||||
has_rs2= 1'b0;
|
||||
case (instr_name) inside
|
||||
"CUS_NOP": begin
|
||||
has_rd = 1'b0;
|
||||
has_rs2 = 1'b0;
|
||||
has_rs2 = 1'b0;
|
||||
has_imm = 1'b0;
|
||||
end
|
||||
endcase*/
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
function void pre_randomize();
|
||||
rd.rand_mode(has_rd);
|
||||
rs1.rand_mode(has_rs1);
|
||||
rs2.rand_mode(has_rs2);
|
||||
imm.rand_mode(has_imm);
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
|
@ -15,8 +15,6 @@ CUS_ADD,
|
|||
CUS_ADD_MULTI,
|
||||
CUS_NOP,
|
||||
CUS_ADD_RS3,
|
||||
// CUS_EXC,
|
||||
// CUS_M_ADD,
|
||||
// CUS_S_ADD,
|
||||
// CUS_NOP_EXC,
|
||||
// CUS_ISS_EXC,
|
||||
CUS_EXC,
|
||||
CUS_U_ADD,
|
||||
CUS_S_ADD,
|
||||
|
|
8
cva6/env/corev-dv/custom/rv32x_instr.sv
vendored
8
cva6/env/corev-dv/custom/rv32x_instr.sv
vendored
|
@ -13,8 +13,6 @@
|
|||
`DEFINE_CVXIF_CUSTOM_INSTR(CUS_ADD_MULTI, R_FORMAT, ARITHMETIC, RV32X)
|
||||
`DEFINE_CVXIF_CUSTOM_INSTR(CUS_NOP, R_FORMAT, ARITHMETIC, RV32X)
|
||||
`DEFINE_CVXIF_CUSTOM_INSTR(CUS_ADD_RS3, R4_FORMAT, ARITHMETIC, RV32X)
|
||||
// `DEFINE_CVXIF_CUSTOM_INSTR(CUS_EXC, R_FORMAT, ARITHMETIC, RV32X)
|
||||
// `DEFINE_CVXIF_CUSTOM_INSTR(CUS_M_ADD, R_FORMAT, ARITHMETIC, RV32X)
|
||||
// `DEFINE_CVXIF_CUSTOM_INSTR(CUS_S_ADD, R_FORMAT, ARITHMETIC, RV32X)
|
||||
// `DEFINE_CVXIF_CUSTOM_INSTR(CUS_NOP_EXC, R_FORMAT, ARITHMETIC, RV32X)
|
||||
// `DEFINE_CVXIF_CUSTOM_INSTR(CUS_ISS_EXC, R_FORMAT, ARITHMETIC, RV32X)
|
||||
`DEFINE_CVXIF_CUSTOM_INSTR(CUS_EXC, R_FORMAT, ARITHMETIC, RV32X)
|
||||
`DEFINE_CVXIF_CUSTOM_INSTR(CUS_U_ADD, R_FORMAT, ARITHMETIC, RV32X)
|
||||
`DEFINE_CVXIF_CUSTOM_INSTR(CUS_S_ADD, R_FORMAT, ARITHMETIC, RV32X)
|
||||
|
|
2
cva6/env/corev-dv/cva6-files.f
vendored
2
cva6/env/corev-dv/cva6-files.f
vendored
|
@ -15,6 +15,6 @@
|
|||
+incdir+${CVA6_DV_ROOT}/user_extension
|
||||
|
||||
// SOURCES
|
||||
${CVA6_DV_ROOT}/cva6_instr_pkg.sv
|
||||
${CVA6_DV_ROOT}/cva6_signature_pkg.sv
|
||||
${CVA6_DV_ROOT}/cva6_instr_test_pkg.sv
|
||||
|
||||
|
|
369
cva6/env/corev-dv/cva6_asm_program_gen.sv
vendored
369
cva6/env/corev-dv/cva6_asm_program_gen.sv
vendored
|
@ -60,6 +60,375 @@ class cva6_asm_program_gen_c extends riscv_asm_program_gen;
|
|||
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(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(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.mstatus_mprv, cfg.sp, cfg.tp, 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 x%0d, 0x%0x # %0s", cfg.gpr[0], 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 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, %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.
|
||||
if (SATP_MODE != BARE) begin
|
||||
instr_stream.push_back(".align 12");
|
||||
end else begin
|
||||
instr_stream.push_back($sformatf(".align %d", cfg.tvec_alignment));
|
||||
end
|
||||
tvec_name = tvec.name();
|
||||
gen_section(get_label($sformatf("%0s_handler", tvec_name.tolower()), hart), instr);
|
||||
// Exception handler
|
||||
instr = {};
|
||||
if (cfg.mtvec_mode == VECTORED) begin
|
||||
push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.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.gpr[0], epc, epc.name()),
|
||||
$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, %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, %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, %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, %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
|
||||
|
||||
// Trap handling routine
|
||||
virtual function void gen_all_trap_handler(int hart);
|
||||
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);
|
||||
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.
|
||||
gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION);
|
||||
if(page_table_list != null) begin
|
||||
page_table_list.gen_page_fault_handling_routine(instr);
|
||||
end else begin
|
||||
instr.push_back("nop");
|
||||
end
|
||||
gen_section(get_label("pt_fault_handler", hart), instr);
|
||||
endfunction
|
||||
|
||||
// Helper function to generate the proper sequence of handshake instructions
|
||||
// to signal the testbench (see riscv_signature_pkg.sv)
|
||||
function void gen_signature_handshake(ref string instr[$],
|
||||
input signature_type_t signature_type,
|
||||
core_status_t core_status = INITIALIZED,
|
||||
test_result_t test_result = TEST_FAIL,
|
||||
privileged_reg_t csr = MSCRATCH,
|
||||
string addr_label = "");
|
||||
if (cfg.require_signature_addr) begin
|
||||
string str[$];
|
||||
str = {$sformatf("li x%0d, 0x%0h", cfg.gpr[1], cfg.signature_addr)};
|
||||
instr = {instr, str};
|
||||
case (signature_type)
|
||||
// A single data word is written to the signature address.
|
||||
// Bits [7:0] contain the signature_type of CORE_STATUS, and the upper
|
||||
// XLEN-8 bits contain the core_status_t data.
|
||||
CORE_STATUS: begin
|
||||
str = {$sformatf("li x%0d, 0x%0h", cfg.gpr[0], core_status),
|
||||
$sformatf("slli x%0d, x%0d, 8", cfg.gpr[0], cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 0x%0h", cfg.gpr[0],
|
||||
cfg.gpr[0], signature_type),
|
||||
$sformatf("sw x%0d, 0(x%0d)", cfg.gpr[0], cfg.gpr[1])};
|
||||
instr = {instr, str};
|
||||
end
|
||||
// A single data word is written to the signature address.
|
||||
// Bits [7:0] contain the signature_type of TEST_RESULT, and the upper
|
||||
// XLEN-8 bits contain the test_result_t data.
|
||||
TEST_RESULT: begin
|
||||
str = {$sformatf("li x%0d, 0x%0h", cfg.gpr[0], test_result),
|
||||
$sformatf("slli x%0d, x%0d, 8", cfg.gpr[0], cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 0x%0h", cfg.gpr[0],
|
||||
cfg.gpr[0], signature_type),
|
||||
$sformatf("sw x%0d, 0(x%0d)", cfg.gpr[0], cfg.gpr[1])};
|
||||
instr = {instr, str};
|
||||
end
|
||||
// The first write to the signature address contains just the
|
||||
// signature_type of WRITE_GPR.
|
||||
// It is followed by 32 consecutive writes to the signature address,
|
||||
// each writing the data contained in one GPR, starting from x0 as the
|
||||
// first write, and ending with x31 as the 32nd write.
|
||||
WRITE_GPR: begin
|
||||
str = {$sformatf("li x%0d, 0x%0h", cfg.gpr[0], signature_type),
|
||||
$sformatf("sw x%0d, 0(x%0d)", cfg.gpr[0], cfg.gpr[1])};
|
||||
instr = {instr, str};
|
||||
for(int i = 0; i < 32; i++) begin
|
||||
str = {$sformatf("sw x%0x, 0(x%0d)", i, cfg.gpr[1])};
|
||||
instr = {instr, str};
|
||||
end
|
||||
end
|
||||
// The first write to the signature address contains the
|
||||
// signature_type of WRITE_CSR in bits [7:0], and the CSR address in
|
||||
// the upper XLEN-8 bits.
|
||||
// It is followed by a second write to the signature address,
|
||||
// containing the data stored in the specified CSR.
|
||||
WRITE_CSR: begin
|
||||
if (!(csr inside {implemented_csr})) begin
|
||||
return;
|
||||
end
|
||||
str = {$sformatf("li x%0d, 0x%0h", cfg.gpr[0], csr),
|
||||
$sformatf("slli x%0d, x%0d, 8", cfg.gpr[0], cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 0x%0h", cfg.gpr[0],
|
||||
cfg.gpr[0], signature_type),
|
||||
$sformatf("sw x%0d, 0(x%0d)", cfg.gpr[0], cfg.gpr[1]),
|
||||
$sformatf("csrr x%0d, 0x%0h", cfg.gpr[0], csr),
|
||||
$sformatf("sw x%0d, 0(x%0d)", cfg.gpr[0], cfg.gpr[1])};
|
||||
instr = {instr, str};
|
||||
end
|
||||
default: begin
|
||||
`uvm_fatal(`gfn, "signature_type is not defined")
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endfunction
|
||||
|
||||
// ECALL trap handler
|
||||
virtual function void gen_ecall_handler(int hart);
|
||||
string instr[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, ECALL_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, INSTR_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
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("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, STORE_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, INSTR_PAGE_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, LOAD_PAGE_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, STORE_PAGE_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, LD_MISALIGNED_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, ST_MISALIGNED_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, INSTR_MISALIGNED_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, mepc", cfg.gpr[0]),
|
||||
$sformatf("addi x%0d, x%0d, 4", 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);
|
||||
|
|
15
cva6/env/corev-dv/cva6_defines.svh
vendored
15
cva6/env/corev-dv/cva6_defines.svh
vendored
|
@ -10,21 +10,6 @@
|
|||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
// Custom extension instruction for CVXIF
|
||||
`define INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
|
||||
static bit valid = cvxif_custom_instr::register(instr_n); \
|
||||
`uvm_object_utils(riscv_``instr_n``_instr) \
|
||||
function new(string name = ""); \
|
||||
super.new(name); \
|
||||
this.instr_name = ``instr_n; \
|
||||
this.format = ``instr_format; \
|
||||
this.group = ``instr_group; \
|
||||
this.category = ``instr_category; \
|
||||
this.imm_type = ``imm_tp; \
|
||||
set_imm_len(); \
|
||||
set_rand_mode(); \
|
||||
endfunction \
|
||||
endclass
|
||||
|
||||
`define DEFINE_CVXIF_CUSTOM_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
|
||||
class riscv_``instr_n``_instr extends cvxif_custom_instr; \
|
||||
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
|
||||
|
|
36
cva6/env/corev-dv/cva6_instr_pkg.sv
vendored
36
cva6/env/corev-dv/cva6_instr_pkg.sv
vendored
|
@ -1,36 +0,0 @@
|
|||
// Copyright 2022 Thales DIS design services SAS
|
||||
// Copyright 2022 OpenHW Group
|
||||
//
|
||||
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
|
||||
// You may obtain a copy of the License at https://solderpad.org/licenses/
|
||||
//
|
||||
// Original Author: Zineb EL KACIMI (zineb.el-kacimi@external.thalesgroup.com)
|
||||
// ------------------------------------------------------------------------------ //
|
||||
|
||||
package cva6_instr_pkg;
|
||||
|
||||
typedef enum {
|
||||
// Add custom instruction name enum
|
||||
CUS_ADD,
|
||||
CUS_ADD_MULTI,
|
||||
CUS_NOP,
|
||||
CUS_ADD_RS3
|
||||
// CUS_EXC,
|
||||
// CUS_M_ADD,
|
||||
// CUS_S_ADD,
|
||||
// CUS_NOP_EXC,
|
||||
// CUS_ISS_EXC,
|
||||
} riscv_instr_name_t;
|
||||
|
||||
import uvm_pkg::*;
|
||||
`include "cva6_defines.svh"
|
||||
import riscv_instr_pkg::*;
|
||||
`include "cva6_instr_gen_config.sv"
|
||||
`include "cva6_asm_program_gen.sv"
|
||||
`include "cvxif_custom_instr.sv"
|
||||
`include "rv32x_instr.sv"
|
||||
`include "riscv_core_setting.sv"
|
||||
|
||||
endpackage
|
8
cva6/env/corev-dv/cva6_instr_test_pkg.sv
vendored
8
cva6/env/corev-dv/cva6_instr_test_pkg.sv
vendored
|
@ -12,11 +12,15 @@
|
|||
package cva6_instr_test_pkg;
|
||||
|
||||
import uvm_pkg::*;
|
||||
`include "cva6_defines.svh"
|
||||
import riscv_instr_pkg::*;
|
||||
import riscv_instr_test_pkg::*;
|
||||
import cva6_instr_pkg::*;
|
||||
import cva6_signature_pkg::*;
|
||||
|
||||
`include "cva6_instr_gen_config.sv"
|
||||
`include "cva6_asm_program_gen.sv"
|
||||
`include "cva6_instr_base_test.sv"
|
||||
|
||||
`include "cvxif_custom_instr.sv"
|
||||
`include "rv32x_instr.sv"
|
||||
|
||||
endpackage : cva6_instr_test_pkg;
|
||||
|
|
66
cva6/env/corev-dv/cva6_signature_pkg.sv
vendored
Normal file
66
cva6/env/corev-dv/cva6_signature_pkg.sv
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package cva6_signature_pkg;
|
||||
|
||||
// Will be the lowest 8 bits of the data word
|
||||
typedef enum bit[7:0] {
|
||||
// Information sent to the core relating its current status.
|
||||
// Bits [12:8] of the data word will be the core_status_t value
|
||||
// corresponding to the current core status.
|
||||
CORE_STATUS,
|
||||
// Information sent to the core conveying the uvm simulation result.
|
||||
// Bit [8] of the data word will be the test_result_t value.
|
||||
TEST_RESULT,
|
||||
// Sent to the core to indicate a dump of GPRs to testbench.
|
||||
// Will be followed by 32 writes of registers x0-x32.
|
||||
WRITE_GPR,
|
||||
// Sent to the core to indicate a write of a CSR's data.
|
||||
// Bits [19:8] of the data word will be the CSR address.
|
||||
// Will be followed by a second write of the actual data from the CSR.
|
||||
WRITE_CSR
|
||||
} signature_type_t;
|
||||
|
||||
typedef enum bit[4:0] {
|
||||
INITIALIZED,
|
||||
IN_DEBUG_MODE,
|
||||
IN_MACHINE_MODE,
|
||||
IN_HYPERVISOR_MODE,
|
||||
IN_SUPERVISOR_MODE,
|
||||
IN_USER_MODE,
|
||||
HANDLING_IRQ,
|
||||
FINISHED_IRQ,
|
||||
HANDLING_EXCEPTION,
|
||||
INSTR_FAULT_EXCEPTION,
|
||||
ILLEGAL_INSTR_EXCEPTION,
|
||||
LOAD_FAULT_EXCEPTION,
|
||||
STORE_FAULT_EXCEPTION,
|
||||
EBREAK_EXCEPTION,
|
||||
ECALL_EXCEPTION,
|
||||
INSTR_MISALIGNED_EXCEPTION,
|
||||
LD_MISALIGNED_EXCEPTION,
|
||||
ST_MISALIGNED_EXCEPTION,
|
||||
INSTR_PAGE_FAULT_EXCEPTION,
|
||||
LOAD_PAGE_FAULT_EXCEPTION,
|
||||
STORE_PAGE_FAULT_EXCEPTION
|
||||
} core_status_t;
|
||||
|
||||
typedef enum bit {
|
||||
TEST_PASS,
|
||||
TEST_FAIL
|
||||
} test_result_t;
|
||||
|
||||
endpackage
|
|
@ -24,7 +24,7 @@ parameter int XLEN = 32;
|
|||
parameter satp_mode_t SATP_MODE = BARE;
|
||||
|
||||
// Supported Privileged mode
|
||||
privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
|
||||
privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MACHINE_MODE};
|
||||
|
||||
// Unsupported instructions
|
||||
riscv_instr_name_t unsupported_instr[];
|
||||
|
@ -99,8 +99,14 @@ interrupt_cause_t implemented_interrupt[] = {
|
|||
`else
|
||||
const interrupt_cause_t implemented_interrupt[] = {
|
||||
`endif
|
||||
U_SOFTWARE_INTR,
|
||||
S_SOFTWARE_INTR,
|
||||
M_SOFTWARE_INTR,
|
||||
U_TIMER_INTR,
|
||||
S_TIMER_INTR,
|
||||
M_TIMER_INTR,
|
||||
U_EXTERNAL_INTR,
|
||||
S_EXTERNAL_INTR,
|
||||
M_EXTERNAL_INTR
|
||||
};
|
||||
|
||||
|
@ -109,10 +115,18 @@ exception_cause_t implemented_exception[] = {
|
|||
`else
|
||||
const exception_cause_t implemented_exception[] = {
|
||||
`endif
|
||||
INSTRUCTION_ADDRESS_MISALIGNED,
|
||||
INSTRUCTION_ACCESS_FAULT,
|
||||
ILLEGAL_INSTRUCTION,
|
||||
BREAKPOINT,
|
||||
LOAD_ADDRESS_MISALIGNED,
|
||||
LOAD_ACCESS_FAULT,
|
||||
ECALL_MMODE
|
||||
STORE_AMO_ADDRESS_MISALIGNED,
|
||||
STORE_AMO_ACCESS_FAULT,
|
||||
ECALL_UMODE,
|
||||
ECALL_SMODE,
|
||||
ECALL_MMODE,
|
||||
INSTRUCTION_PAGE_FAULT,
|
||||
LOAD_PAGE_FAULT,
|
||||
STORE_AMO_PAGE_FAULT
|
||||
};
|
||||
|
|
|
@ -27,14 +27,14 @@
|
|||
.insn r CUSTOM_3, 0x0, 0x1, \rd, \rs1, \rs2, \rs3
|
||||
.endm
|
||||
|
||||
# CUS_U_ADD rd, rs1, rs2 -> .insn r CUSTOM_3, 0x0, 0x6, rd, rs1, rs2
|
||||
.macro cus_m_add rd, rs1, rs2
|
||||
.insn r CUSTOM_3, 0x0, 0x6, \rd, \rs1, \rs2
|
||||
# CUS_U_ADD rd, rs1, rs2 -> .insn r CUSTOM_3, 0x0, 0x2, rd, rs1, rs2
|
||||
.macro cus_u_add rd, rs1, rs2
|
||||
.insn r CUSTOM_3, 0x0, 0x2, \rd, \rs1, \rs2
|
||||
.endm
|
||||
|
||||
# CUS_S_ADD rd, rs1, rs2 -> .insn r CUSTOM_3, 0x0, 0x2, rd, rs1, rs2
|
||||
# CUS_S_ADD rd, rs1, rs2 -> .insn r CUSTOM_3, 0x0, 0x6, rd, rs1, rs2
|
||||
.macro cus_s_add rd, rs1, rs2
|
||||
.insn r CUSTOM_3, 0x0, 0x2, \rd, \rs1, \rs2
|
||||
.insn r CUSTOM_3, 0x0, 0x6, \rd, \rs1, \rs2
|
||||
.endm
|
||||
|
||||
# CUS_ADD_MULTI rd, rs1, rs2 -> .insn r CUSTOM_3, 0x0, 0x8, rd, rs1, rs2
|
||||
|
@ -42,9 +42,8 @@
|
|||
.insn r CUSTOM_3, 0x0, 0x8, \rd, \rs1, \rs2
|
||||
.endm
|
||||
|
||||
# CUS_EXC rd, rs1, rs2 -> .insn r CUSTOM_3, 0x0, 0x40, rd, rs1, rs2
|
||||
# CUS_EXC rd, rs1, rs2 -> .insn r CUSTOM_3, 0x2, 0x60, rd, rs1, rs2
|
||||
.macro cus_exc rd, rs1, rs2
|
||||
.insn r CUSTOM_3, 0x0, 0x40, \rd, \rs1, \rs2
|
||||
.insn r CUSTOM_3, 0x2, 0x60, \rd, \rs1, \rs2
|
||||
.endm
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue