Skip to content

Commit ed214d6

Browse files
authored
feat(dbltrp): support full dbltrp extension in spike (#54)
1 parent 5f8a8b3 commit ed214d6

File tree

8 files changed

+60
-8
lines changed

8 files changed

+60
-8
lines changed

difftest/difftest-def.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@
8181
"_svinval_sscofpmf" \
8282
"_svpbmt" \
8383
"_zicbom_zicboz" \
84-
"_sstc"
84+
"_sstc" \
85+
"_smrnmi_smdbltrp_ssdbltrp" \
8586

8687
#define CONFIG_MEMORY_SIZE (16 * 1024 * 1024 * 1024UL)
8788
#define CONFIG_FLASH_BASE 0x10000000UL

difftest/difftest.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ void DifftestRef::raise_intr(uint64_t no) {
394394
}
395395
}
396396

397+
bool DifftestRef::raise_critical_error() {
398+
return state->critical_error;
399+
}
400+
397401
void DifftestRef::update_mip(void *non_reg_interrupt_pending) {
398402
auto n = (DifftestNonRegInterruptPending *) non_reg_interrupt_pending;
399403
state->mip->backdoor_write_with_mask(MIP_MTIP, n->platform_irp_mtip ? MIP_MTIP : 0);
@@ -568,6 +572,10 @@ void difftest_raise_intr(uint64_t NO) {
568572
ref->raise_intr(NO);
569573
}
570574

575+
bool difftest_raise_critical_error() {
576+
return ref->raise_critical_error();
577+
}
578+
571579
void isa_reg_display() {
572580
ref->display();
573581
}

difftest/difftest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ class DifftestRef {
142142
void debug_memcpy_from_dut(reg_t dest, void* src, size_t n);
143143
int store_commit(uint64_t *addr, uint64_t *data, uint8_t *mask);
144144
void raise_intr(uint64_t no);
145+
bool raise_critical_error();
145146
void display();
146147
void update_mip(void *non_reg_interrupt_pending);
147148
void update_dynamic_config(void* config) {

riscv/csr_init.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa)
341341
if (proc->extension_enabled_const(EXT_SMRNMI)) {
342342
add_csr(CSR_MNSCRATCH, std::make_shared<basic_csr_t>(proc, CSR_MNSCRATCH, 0));
343343
add_csr(CSR_MNEPC, mnepc = std::make_shared<epc_csr_t>(proc, CSR_MNEPC));
344-
add_csr(CSR_MNCAUSE, std::make_shared<const_csr_t>(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1)));
344+
add_csr(CSR_MNCAUSE, mncause = std::make_shared<cause_csr_t>(proc, CSR_MNCAUSE));
345345
add_csr(CSR_MNSTATUS, mnstatus = std::make_shared<mnstatus_csr_t>(proc, CSR_MNSTATUS));
346346
}
347347

riscv/csrs.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,18 +598,31 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
598598
| (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
599599
| (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0)
600600
| (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0)
601+
#if defined(DIFFTEST) && defined(CPU_XIANGSHAN)
602+
| 0
603+
#else
601604
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
605+
#endif
602606
| 0; // initial value for mstatus
603607
}
604608

605609
// implement class mnstatus_csr_t
606610
mnstatus_csr_t::mnstatus_csr_t(processor_t* const proc, const reg_t addr):
607-
basic_csr_t(proc, addr, 0) {
611+
#if defined(DIFFTEST) && defined(CPU_XIANGSHAN)
612+
basic_csr_t(proc, addr, MNSTATUS_NMIE)
613+
#else
614+
basic_csr_t(proc, addr, 0)
615+
#endif
616+
{
608617
}
609618

610619
bool mnstatus_csr_t::unlogged_write(const reg_t val) noexcept {
611620
// NMIE can be set but not cleared
621+
#if defined(DIFFTEST) && defined(CPU_XIANGSHAN)
622+
const reg_t mask = MNSTATUS_NMIE
623+
#else
612624
const reg_t mask = (~read() & MNSTATUS_NMIE)
625+
#endif
613626
| (proc->extension_enabled('H') ? MNSTATUS_MNPV : 0)
614627
| MNSTATUS_MNPP;
615628

@@ -620,6 +633,10 @@ bool mnstatus_csr_t::unlogged_write(const reg_t val) noexcept {
620633
return basic_csr_t::unlogged_write(new_mnstatus);
621634
}
622635

636+
bool mnstatus_csr_t::bare_write(const reg_t val) noexcept {
637+
return basic_csr_t::unlogged_write(val);
638+
}
639+
623640
// implement class rv32_low_csr_t
624641
rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig):
625642
csr_t(proc, addr),

riscv/csrs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ typedef std::shared_ptr<mstatus_csr_t> mstatus_csr_t_p;
271271
class mnstatus_csr_t final: public basic_csr_t {
272272
public:
273273
mnstatus_csr_t(processor_t* const proc, const reg_t addr);
274+
bool bare_write(const reg_t val) noexcept;
274275
protected:
275276
virtual bool unlogged_write(const reg_t val) noexcept override;
276277
};
@@ -551,6 +552,8 @@ class wide_counter_csr_t: public csr_t {
551552

552553
typedef std::shared_ptr<wide_counter_csr_t> wide_counter_csr_t_p;
553554

555+
typedef std::shared_ptr<mnstatus_csr_t> mnstatus_csr_t_p;
556+
554557
class time_counter_csr_t: public csr_t {
555558
public:
556559
time_counter_csr_t(processor_t* const proc, const reg_t addr);

riscv/processor.cc

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
463463
// An unexpected trap - a trap when SDT is 1 - traps to M-mode
464464
if ((state.prv <= PRV_S && bit < max_xlen) &&
465465
(((vsdeleg >> bit) & 1) || ((hsdeleg >> bit) & 1))) {
466-
reg_t s = curr_virt ? state.nonvirtual_sstatus->read() : state.sstatus->read();
466+
reg_t s = state.sstatus->read();
467467
supv_double_trap = get_field(s, MSTATUS_SDT);
468468
if (supv_double_trap)
469469
vsdeleg = hsdeleg = 0;
@@ -534,17 +534,38 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
534534

535535
reg_t s = state.mstatus->read();
536536
if ( extension_enabled(EXT_SMDBLTRP)) {
537-
if (get_field(s, MSTATUS_MDT) || !nmie) {
537+
bool m_double_trap = get_field(s, MSTATUS_MDT);
538+
if (!nmie) {
538539
// Critical error - Double trap in M-mode or trap when nmie is 0
539540
// RNMI is not modeled else double trap in M-mode would trap to
540541
// RNMI handler instead of leading to a critical error
541542
state.critical_error = 1;
542543
return;
543544
}
544-
s = set_field(s, MSTATUS_MDT, 1);
545+
if (m_double_trap) {
546+
state.pc = trap_handler_address;
547+
reg_t mnstatus_val = state.mnstatus->read();
548+
mnstatus_val = set_field(mnstatus_val, MNSTATUS_MNPP, state.prv);
549+
mnstatus_val = set_field(mnstatus_val, MNSTATUS_MNPV, curr_virt);
550+
mnstatus_val = set_field(mnstatus_val, MNSTATUS_NMIE, 0);
551+
state.mnstatus->bare_write(mnstatus_val);
552+
#ifdef CPU_ROCKET_CHIP
553+
state.mnepc->write(encode_vaddr(epc));
554+
#else
555+
state.mnepc->write(epc);
556+
#endif
557+
state.mncause->write(t.cause());
558+
set_privilege(PRV_M, false);
559+
return;
560+
} else {
561+
s = set_field(s, MSTATUS_MDT, 1);
562+
}
545563
}
546-
564+
#if defined(DIFFTEST) && defined(CPU_XIANGSHAN)
565+
state.pc = trap_handler_address;
566+
#else
547567
state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
568+
#endif
548569
#ifdef CPU_ROCKET_CHIP
549570
state.mepc->write(encode_vaddr(epc));
550571
#else

riscv/processor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ struct state_t
101101
csr_t_p mideleg;
102102
csr_t_p mcounteren;
103103
csr_t_p mevent[N_HPMCOUNTERS];
104-
csr_t_p mnstatus;
104+
mnstatus_csr_t_p mnstatus;
105105
csr_t_p mnepc;
106+
csr_t_p mncause;
106107
csr_t_p scounteren;
107108
csr_t_p sepc;
108109
csr_t_p stval;

0 commit comments

Comments
 (0)