Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions dv/cosim/spike_cosim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc,
// (If the current step causes a synchronous trap, it will be
// recorded against the current pc)
initial_spike_pc = (processor->get_state()->pc & 0xffffffff);
// A trap on a stepped instruction enters debug mode within this step, but
// the cpuctrlsts update depends on the mode the trap was taken in.
bool initial_spike_debug_mode = processor->get_state()->debug_mode;
processor->step(1);

// ISS
Expand Down Expand Up @@ -278,7 +281,7 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data, uint32_t pc,
return false;
}

handle_cpuctrl_exception_entry();
handle_cpuctrl_exception_entry(initial_spike_debug_mode);

// This is all the checking possible when consider a
// synchronously-trapping instruction that never retired.
Expand Down Expand Up @@ -534,8 +537,8 @@ void SpikeCosim::leave_nmi_mode() {
#endif
}

void SpikeCosim::handle_cpuctrl_exception_entry() {
if (!processor->get_state()->debug_mode) {
void SpikeCosim::handle_cpuctrl_exception_entry(bool debug_mode_at_trap) {
if (!debug_mode_at_trap) {
bool old_sync_exc_seen = change_cpuctrlsts_sync_exc_seen(true);
if (old_sync_exc_seen) {
set_cpuctrlsts_double_fault_seen();
Expand Down
2 changes: 1 addition & 1 deletion dv/cosim/spike_cosim.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class SpikeCosim : public simif_t, public Cosim {

bool change_cpuctrlsts_sync_exc_seen(bool flag);
void set_cpuctrlsts_double_fault_seen();
void handle_cpuctrl_exception_entry();
void handle_cpuctrl_exception_entry(bool debug_mode_at_trap);

void initial_proc_setup(uint32_t start_pc, uint32_t start_mtvec,
uint32_t mhpm_counter_num, bool rv32b_enabled);
Expand Down
2 changes: 2 additions & 0 deletions dv/uvm/core_ibex/riscv_dv_extension/ibex_asm_program_gen.sv
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class ibex_asm_program_gen extends riscv_asm_program_gen;
$sformatf("addi x%0d, x%0d, 4", cfg.gpr[0], cfg.gpr[0]),
$sformatf("csrw 0x%0x, x%0d", MEPC, cfg.gpr[0])
};
// Pop the frame pushed on trap entry.
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
Expand Down
4 changes: 2 additions & 2 deletions dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -653,11 +653,11 @@
+no_ebreak=0
+no_ecall=0
+no_branch_jump=0
+instr_cnt=10000
+instr_cnt=2000
+no_csr_instr=0
+randomize_csr=1
+gen_all_csrs_by_default=1
+add_csr_write=MSTATUS,MEPC,MCAUSE,MTVAL,0x7c0,0x7c1
+add_csr_write=0x7c0,0x7c1
+no_fence=0
+no_wfi=0
+num_of_sub_program=1
Expand Down
19 changes: 19 additions & 0 deletions dv/uvm/core_ibex/tests/core_ibex_seq_lib.sv
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,17 @@ class debug_seq extends core_base_seq#(irq_seq_item);
`uvm_object_new

int unsigned drop_delay = 75;
// Cycles to wait for the core to take the request before giving up.
int unsigned hold_timeout_cycles = 5000;
virtual core_ibex_rvfi_if rvfi_vif;

virtual task body();
if (!uvm_config_db#(virtual core_ibex_dut_probe_if)::get(null, "", "dut_if", dut_vif)) begin
`uvm_fatal(get_full_name(), "Cannot get dut_if")
end
if (!uvm_config_db#(virtual core_ibex_rvfi_if)::get(null, "", "rvfi_if", rvfi_vif)) begin
`uvm_fatal(get_full_name(), "Cannot get rvfi_if")
end
dut_vif.dut_cb.debug_req <= 1'b0;
super.body();
endtask
Expand All @@ -188,6 +194,19 @@ class debug_seq extends core_base_seq#(irq_seq_item);
`uvm_info(get_full_name(), "Sending debug request", UVM_HIGH)
dut_vif.dut_cb.debug_req <= 1'b1;
clk_vif.wait_clks(drop_delay);
// Like a debug module holding haltreq, keep the request up until a retirement reports it on
// RVFI. Otherwise a request that wakes the core from WFI can drop before the cosim sees it.
`DV_SPINWAIT_EXIT(begin
wait (dut_vif.dut_cb.debug_mode == 1'b1);
do @(rvfi_vif.monitor_cb);
while (!(rvfi_vif.monitor_cb.valid && rvfi_vif.monitor_cb.ext_debug_req));
end,
begin
clk_vif.wait_clks(hold_timeout_cycles);
`uvm_error(get_full_name(),
"No retirement reported the debug request before the hold timeout")
end,
"")
dut_vif.dut_cb.debug_req <= 1'b0;
endtask

Expand Down
9 changes: 7 additions & 2 deletions vendor/google_riscv-dv/src/riscv_debug_rom_gen.sv
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,14 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen;
endfunction

// Generate exception handling routine for debug ROM
// TODO(udinator) - remains empty for now, only a DRET
// Return through debug_end, which pops the frame pushed on debug ROM entry.
virtual function void gen_debug_exception_handler();
str = {"dret"};
if (cfg.gen_debug_section) begin
str = {$sformatf("j %0sdebug_end", hart_prefix(hart))};
end else begin
// No debug section, so no frame to pop.
str = {"dret"};
end
gen_section($sformatf("%0sdebug_exception", hart_prefix(hart)), str);
endfunction

Expand Down
23 changes: 21 additions & 2 deletions vendor/google_riscv-dv/src/riscv_instr_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,16 @@ package riscv_instr_pkg;
riscv_reg_t tp,
ref string instr[$]);
string store_instr = (XLEN == 32) ? "sw" : "sd";
if (scratch inside {implemented_csr}) begin
// On RV32 bare metal, reserve the whole frame with one addi before any store, so a debug
// entry in the middle of the push builds its frame below this one.
bit atomic_claim = (scratch inside {implemented_csr}) && (XLEN == 32) && (SATP_MODE == BARE);
if (atomic_claim) begin
instr.push_back($sformatf("addi x%0d, x%0d, -132", tp, tp));
// Push USP from gpr.SP onto the kernel stack (the top slot of the frame)
instr.push_back($sformatf("%0s x%0d, 128(x%0d)", store_instr, sp, tp));
// Move KSP to gpr.SP
instr.push_back($sformatf("add x%0d, x%0d, zero", sp, tp));
end else 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));
Expand Down Expand Up @@ -1409,7 +1418,9 @@ package riscv_instr_pkg;
end
// Push all 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)));
if (!atomic_claim) begin
instr.push_back($sformatf("addi x%0d, x%0d, -%0d", sp, sp, 32 * (XLEN/8)));
end
for(int i = 1; i < 32; i++) begin
instr.push_back($sformatf("%0s x%0d, %0d(x%0d)", store_instr, i, i * (XLEN/8), sp));
end
Expand All @@ -1426,12 +1437,20 @@ package riscv_instr_pkg;
riscv_reg_t tp,
ref string instr[$]);
string load_instr = (XLEN == 32) ? "lw" : "ld";
// Same condition as in push_gpr_to_kernel_stack.
bit atomic_claim = (scratch inside {implemented_csr}) && (XLEN == 32) && (SATP_MODE == BARE);
// 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 < 32; i++) begin
instr.push_back($sformatf("%0s x%0d, %0d(x%0d)", load_instr, i, i * (XLEN/8), sp));
end
if (atomic_claim) begin
// Restore USP, then release the whole frame with one addi.
instr.push_back($sformatf("%0s x%0d, 128(x%0d)", load_instr, sp, tp));
instr.push_back($sformatf("addi x%0d, x%0d, 132", tp, tp));
return;
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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- a/src/riscv_debug_rom_gen.sv
+++ b/src/riscv_debug_rom_gen.sv
@@ -118,5 +118,10 @@ class riscv_debug_rom_gen extends riscv_asm_program_gen;
// Generate exception handling routine for debug ROM
- // TODO(udinator) - remains empty for now, only a DRET
+ // Return through debug_end, which pops the frame pushed on debug ROM entry.
virtual function void gen_debug_exception_handler();
- str = {"dret"};
+ if (cfg.gen_debug_section) begin
+ str = {$sformatf("j %0sdebug_end", hart_prefix(hart))};
+ end else begin
+ // No debug section, so no frame to pop.
+ str = {"dret"};
+ end
gen_section($sformatf("%0sdebug_exception", hart_prefix(hart)), str);
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--- a/src/riscv_instr_pkg.sv
+++ b/src/riscv_instr_pkg.sv
@@ -1381,7 +1381,16 @@ package riscv_instr_pkg;
riscv_reg_t tp,
ref string instr[$]);
string store_instr = (XLEN == 32) ? "sw" : "sd";
- if (scratch inside {implemented_csr}) begin
+ // On RV32 bare metal, reserve the whole frame with one addi before any store, so a debug
+ // entry in the middle of the push builds its frame below this one.
+ bit atomic_claim = (scratch inside {implemented_csr}) && (XLEN == 32) && (SATP_MODE == BARE);
+ if (atomic_claim) begin
+ instr.push_back($sformatf("addi x%0d, x%0d, -132", tp, tp));
+ // Push USP from gpr.SP onto the kernel stack (the top slot of the frame)
+ instr.push_back($sformatf("%0s x%0d, 128(x%0d)", store_instr, sp, tp));
+ // Move KSP to gpr.SP
+ instr.push_back($sformatf("add x%0d, x%0d, zero", sp, tp));
+ end else 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));
@@ -1409,7 +1418,9 @@ package riscv_instr_pkg;
end
// Push all 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)));
+ if (!atomic_claim) begin
+ instr.push_back($sformatf("addi x%0d, x%0d, -%0d", sp, sp, 32 * (XLEN/8)));
+ end
for(int i = 1; i < 32; i++) begin
instr.push_back($sformatf("%0s x%0d, %0d(x%0d)", store_instr, i, i * (XLEN/8), sp));
end
@@ -1426,12 +1437,20 @@ package riscv_instr_pkg;
riscv_reg_t tp,
ref string instr[$]);
string load_instr = (XLEN == 32) ? "lw" : "ld";
+ // Same condition as in push_gpr_to_kernel_stack.
+ bit atomic_claim = (scratch inside {implemented_csr}) && (XLEN == 32) && (SATP_MODE == BARE);
// 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 < 32; i++) begin
instr.push_back($sformatf("%0s x%0d, %0d(x%0d)", load_instr, i, i * (XLEN/8), sp));
end
+ if (atomic_claim) begin
+ // Restore USP, then release the whole frame with one addi.
+ instr.push_back($sformatf("%0s x%0d, 128(x%0d)", load_instr, sp, tp));
+ instr.push_back($sformatf("addi x%0d, x%0d, 132", tp, tp));
+ return;
+ 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
Loading