Update google_riscv-dv to 73274f2 (#254)

Update code from upstream repository https://github.com/google/riscv-
dv to revision 73274f227000f1316cb201a8503aad437e427948

* Merge pull request #88 from google/dev (taoliug)
* Fix spike log processing issue (Tao Liu)
* Merge pull request #87 from google/dev (udinator)
* Add vectored interrupt support (Tao Liu)
* Merge pull request #85 from udinator/debug (udinator)
* Add debug sub-programs, and extra options to generator (Udi)
* Merge pull request #84 from imphil/fix-apache-urls (taoliug)
* Fix license URLs in comments (Philipp Wagner)
This commit is contained in:
taoliug 2019-08-21 17:14:15 -07:00 committed by GitHub
parent 9311b25fdb
commit a752277247
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 263 additions and 110 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: 7cce16c0a212c8713a82516fbf8f2570d3dc4505
rev: 73274f227000f1316cb201a8503aad437e427948
}
}

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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"};

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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