Skip to content

Commit c302e8b

Browse files
committed
Add Smdbltrp
1 parent 11fbcb5 commit c302e8b

File tree

12 files changed

+95
-20
lines changed

12 files changed

+95
-20
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Spike supports the following RISC-V ISA features:
4141
- Sdtrig extension, v1.0-STABLE
4242
- Smepmp extension v1.0
4343
- Smstateen extension, v1.0
44+
- Smdbltrp extension, v1.0
4445
- Sscofpmf v0.5.2
4546
- Zca extension, v1.0
4647
- Zcb extension, v1.0

disasm/isa_parser.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv)
355355
elen = std::max(elen, new_elen);
356356
} else if (ext_str == "ssdbltrp") {
357357
extension_table[EXT_SSDBLTRP] = true;
358+
} else if (ext_str == "smdbltrp") {
359+
extension_table[EXT_SMDBLTRP] = true;
358360
} else if (ext_str[0] == 'x') {
359361
extension_table['X'] = true;
360362
if (ext_str.size() == 1) {

riscv/csrs.cc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,13 +548,17 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept {
548548
| (has_page ? MSTATUS_TVM : 0)
549549
| (has_gva ? MSTATUS_GVA : 0)
550550
| (has_mpv ? MSTATUS_MPV : 0)
551+
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
551552
| (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0)
552553
| (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0)
553554
;
554555

555556
const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP));
556557
const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp);
557-
const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
558+
reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask);
559+
if (new_mstatus & MSTATUS_MDT) {
560+
new_mstatus = new_mstatus & ~MSTATUS_MIE;
561+
}
558562
maybe_flush_tlb(new_mstatus);
559563
this->val = adjust_sd(new_mstatus);
560564
return true;
@@ -569,6 +573,7 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept {
569573
| (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)
570574
| (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)
571575
| (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0)
576+
| (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0)
572577
| 0; // initial value for mstatus
573578
}
574579

@@ -1343,6 +1348,8 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
13431348
halt(false),
13441349
v(false),
13451350
cause(0),
1351+
ext_cause(0),
1352+
cetrig(0),
13461353
pelp(elp_t::NO_LP_EXPECTED) {
13471354
}
13481355

@@ -1363,6 +1370,9 @@ reg_t dcsr_csr_t::read() const noexcept {
13631370
result = set_field(result, DCSR_STOPCOUNT, 0);
13641371
result = set_field(result, DCSR_STOPTIME, 0);
13651372
result = set_field(result, DCSR_CAUSE, cause);
1373+
result = set_field(result, DCSR_EXTCAUSE, ext_cause);
1374+
if (proc->extension_enabled(EXT_SMDBLTRP))
1375+
result = set_field(result, DCSR_CETRIG, cetrig);
13661376
result = set_field(result, DCSR_STEP, step);
13671377
result = set_field(result, DCSR_PRV, prv);
13681378
result = set_field(result, CSR_DCSR_V, v);
@@ -1382,12 +1392,14 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept {
13821392
v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false;
13831393
pelp = proc->extension_enabled(EXT_ZICFILP) ?
13841394
static_cast<elp_t>(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED;
1395+
cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false;
13851396
return true;
13861397
}
13871398

1388-
void dcsr_csr_t::update_fields(const uint8_t cause, const reg_t prv,
1399+
void dcsr_csr_t::update_fields(const uint8_t cause, uint8_t ext_cause, const reg_t prv,
13891400
const bool v, const elp_t pelp) noexcept {
13901401
this->cause = cause;
1402+
this->ext_cause = ext_cause;
13911403
this->prv = prv;
13921404
this->v = v;
13931405
this->pelp = pelp;

riscv/csrs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ class dcsr_csr_t: public csr_t {
684684
dcsr_csr_t(processor_t* const proc, const reg_t addr);
685685
virtual void verify_permissions(insn_t insn, bool write) const override;
686686
virtual reg_t read() const noexcept override;
687-
void update_fields(const uint8_t cause, const reg_t prv,
687+
void update_fields(const uint8_t cause, const uint8_t ext_cause, const reg_t prv,
688688
const bool v, const elp_t pelp) noexcept;
689689
protected:
690690
virtual bool unlogged_write(const reg_t val) noexcept override;
@@ -699,6 +699,8 @@ class dcsr_csr_t: public csr_t {
699699
bool halt;
700700
bool v;
701701
uint8_t cause;
702+
uint8_t ext_cause;
703+
bool cetrig;
702704
elp_t pelp;
703705
};
704706

riscv/encoding.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
/*
66
* This file is auto-generated by running 'make' in
7-
* https://github.com/riscv/riscv-opcodes (c55d30f)
7+
* https://github.com/riscv/riscv-opcodes (048218e)
88
*/
99

1010
#ifndef RISCV_CSR_ENCODING_H
@@ -110,14 +110,17 @@
110110
#define DCSR_CAUSE_STEP 4
111111
#define DCSR_CAUSE_HALT 5
112112
#define DCSR_CAUSE_GROUP 6
113+
#define DCSR_CAUSE_EXTCAUSE 7
114+
115+
#define DCSR_EXTCAUSE_CRITERR 0
113116

114117
#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
115118
#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
116119
#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
117120

118121
#define MCONTROL_SELECT (1<<19)
119122
#define MCONTROL_TIMING (1<<18)
120-
#define MCONTROL_ACTION (0x3f<<12)
123+
#define MCONTROL_ACTION (0xf<<12)
121124
#define MCONTROL_CHAIN (1<<11)
122125
#define MCONTROL_MATCH (0xf<<7)
123126
#define MCONTROL_M (1<<6)

riscv/execute.cc

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,11 @@ void processor_t::step(size_t n)
213213
{
214214
if (!state.debug_mode) {
215215
if (halt_request == HR_REGULAR) {
216-
enter_debug_mode(DCSR_CAUSE_DEBUGINT);
216+
enter_debug_mode(DCSR_CAUSE_DEBUGINT, 0);
217217
} else if (halt_request == HR_GROUP) {
218-
enter_debug_mode(DCSR_CAUSE_GROUP);
219-
}
220-
else if (state.dcsr->halt) {
221-
enter_debug_mode(DCSR_CAUSE_HALT);
218+
enter_debug_mode(DCSR_CAUSE_GROUP, 0);
219+
} else if (state.dcsr->halt) {
220+
enter_debug_mode(DCSR_CAUSE_HALT, 0);
222221
}
223222
}
224223

@@ -257,7 +256,7 @@ void processor_t::step(size_t n)
257256
if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
258257
state.single_step = state.STEP_NONE;
259258
if (!state.debug_mode) {
260-
enter_debug_mode(DCSR_CAUSE_STEP);
259+
enter_debug_mode(DCSR_CAUSE_STEP, 0);
261260
// enter_debug_mode changed state.pc, so we can't just continue.
262261
break;
263262
}
@@ -286,6 +285,17 @@ void processor_t::step(size_t n)
286285
disasm(fetch.insn);
287286
pc = execute_insn_logged(this, pc, fetch);
288287
advance_pc();
288+
289+
// Resume from debug mode in critical error
290+
if (state.critical_error && !state.debug_mode) {
291+
if (state.dcsr->read() & DCSR_CETRIG) {
292+
enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
293+
} else {
294+
// Handling of critical error is implementation defined
295+
// For now just enter debug mode
296+
enter_debug_mode(DCSR_CAUSE_HALT, 0);
297+
}
298+
}
289299
}
290300
}
291301
else while (instret < n)
@@ -311,13 +321,23 @@ void processor_t::step(size_t n)
311321
take_trap(t, pc);
312322
n = instret;
313323

324+
// If critical error then enter debug mode critical error trigger enabled
325+
if (state.critical_error) {
326+
if (state.dcsr->read() & DCSR_CETRIG) {
327+
enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR);
328+
} else {
329+
// Handling of critical error is implementation defined
330+
// For now just enter debug mode
331+
enter_debug_mode(DCSR_CAUSE_HALT, 0);
332+
}
333+
}
314334
// Trigger action takes priority over single step
315335
auto match = TM.detect_trap_match(t);
316336
if (match.has_value())
317337
take_trigger_action(match->action, 0, state.pc, 0);
318338
else if (unlikely(state.single_step == state.STEP_STEPPED)) {
319339
state.single_step = state.STEP_NONE;
320-
enter_debug_mode(DCSR_CAUSE_STEP);
340+
enter_debug_mode(DCSR_CAUSE_STEP, 0);
321341
}
322342
}
323343
catch (triggers::matched_t& t)
@@ -330,7 +350,7 @@ void processor_t::step(size_t n)
330350
}
331351
catch(trap_debug_mode&)
332352
{
333-
enter_debug_mode(DCSR_CAUSE_SWBP);
353+
enter_debug_mode(DCSR_CAUSE_SWBP, 0);
334354
}
335355
catch (wait_for_interrupt_t &t)
336356
{

riscv/insns/dret.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@ if (ZICFILP_xLPE(STATE.dcsr->v, STATE.dcsr->prv)) {
44
STATE.elp = STATE.dcsr->pelp;
55
}
66
p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v);
7-
if (STATE.prv < PRV_M)
7+
if (STATE.prv < PRV_M) {
88
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV);
9+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
10+
}
11+
12+
if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
13+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
14+
15+
if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U)
16+
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
917

1018
if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v)
1119
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);

riscv/insns/mret.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) {
1313
STATE.elp = static_cast<elp_t>(get_field(s, MSTATUS_MPELP));
1414
}
1515
s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED);
16+
s = set_field(s, MSTATUS_MDT, 0);
1617
if (prev_prv == PRV_U || prev_virt)
1718
s = set_field(s, MSTATUS_SDT, 0);
1819
if (prev_virt && prev_prv == PRV_U)

riscv/insns/sret.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ if (!STATE.v) {
2626
if (ZICFILP_xLPE(prev_virt, prev_prv)) {
2727
STATE.elp = static_cast<elp_t>(get_field(s, SSTATUS_SPELP));
2828
}
29+
30+
if (STATE.prv == PRV_M) {
31+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT);
32+
if (prev_prv == PRV_U || prev_virt)
33+
STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT);
34+
if (prev_virt && prev_prv == PRV_U)
35+
STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT);
36+
}
37+
2938
s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED);
3039

3140
if (STATE.prv == PRV_S) {

riscv/isa_parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ typedef enum {
8282
EXT_ZICFILP,
8383
EXT_ZICFISS,
8484
EXT_SSDBLTRP,
85+
EXT_SMDBLTRP,
8586
EXT_SMMPM,
8687
EXT_SMNPM,
8788
EXT_SSNPM,

riscv/processor.cc

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
159159

160160
elp = elp_t::NO_LP_EXPECTED;
161161

162+
critical_error = false;
163+
162164
csr_init(proc, max_isa);
163165
}
164166

@@ -379,11 +381,11 @@ const char* processor_t::get_privilege_string()
379381
abort();
380382
}
381383

382-
void processor_t::enter_debug_mode(uint8_t cause)
384+
void processor_t::enter_debug_mode(uint8_t cause, uint8_t extcause)
383385
{
384386
const bool has_zicfilp = extension_enabled(EXT_ZICFILP);
385387
state.debug_mode = true;
386-
state.dcsr->update_fields(cause, state.prv, state.v, state.elp);
388+
state.dcsr->update_fields(cause, extcause, state.prv, state.v, state.elp);
387389
state.elp = elp_t::NO_LP_EXPECTED;
388390
set_privilege(PRV_M, false);
389391
state.dpc->write(state.pc);
@@ -500,18 +502,30 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
500502
// Handle the trap in M-mode
501503
const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0;
502504
const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector;
503-
// RNMI exception vector is implementation-defined. Since we don't model
504505
// RNMI sources, the feature isn't very useful, so pick an invalid address.
506+
// RNMI exception vector is implementation-defined. Since we don't model
505507
const reg_t rnmi_trap_handler_address = 0;
506508
const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE));
509+
510+
reg_t s = state.mstatus->read();
511+
if ( extension_enabled(EXT_SMDBLTRP)) {
512+
if (get_field(s, MSTATUS_MDT) || !nmie) {
513+
// Critical error - Double trap in M-mode or trap when nmie is 0
514+
// RNMI is not modeled else double trap in M-mode would trap to
515+
// RNMI handler instead of leading to a critical error
516+
state.critical_error = 1;
517+
return;
518+
}
519+
s = set_field(s, MSTATUS_MDT, 1);
520+
}
521+
507522
state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address;
508523
state.mepc->write(epc);
509524
state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause());
510525
state.mtval->write(t.get_tval());
511526
state.mtval2->write(supv_double_trap ? t.cause() : t.get_tval2());
512527
state.mtinst->write(t.get_tinst());
513528

514-
reg_t s = state.mstatus->read();
515529
s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE));
516530
s = set_field(s, MSTATUS_MPP, state.prv);
517531
s = set_field(s, MSTATUS_MIE, 0);
@@ -537,7 +551,7 @@ void processor_t::take_trigger_action(triggers::action_t action, reg_t breakpoin
537551

538552
switch (action) {
539553
case triggers::ACTION_DEBUG_MODE:
540-
enter_debug_mode(DCSR_CAUSE_HWBP);
554+
enter_debug_mode(DCSR_CAUSE_HWBP, 0);
541555
break;
542556
case triggers::ACTION_DEBUG_EXCEPTION: {
543557
trap_breakpoint trap(virt, breakpoint_tval);

riscv/processor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ struct state_t
190190

191191
elp_t elp;
192192

193+
bool critical_error;
194+
193195
private:
194196
void csr_init(processor_t* const proc, reg_t max_isa);
195197
};
@@ -405,7 +407,7 @@ class processor_t : public abstract_device_t
405407
void register_insn(insn_desc_t, bool);
406408
int paddr_bits();
407409

408-
void enter_debug_mode(uint8_t cause);
410+
void enter_debug_mode(uint8_t cause, uint8_t ext_cause);
409411

410412
void debug_output_log(std::stringstream *s); // either output to interactive user or write to log file
411413

0 commit comments

Comments
 (0)