#define CSR_SSTATUS 0x100
#define CSR_STVEC 0x101
#define CSR_SIE 0x104
-#define CSR_STIMECMP 0x121
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SIP 0x144
#define CSR_INSTRETHW 0x982
#define CSR_STIMEH 0xd81
#define CSR_STIMEHW 0xa81
+#define CSR_MTIMECMPH 0x361
#define CSR_MTIMEH 0x741
#define CAUSE_MISALIGNED_FETCH 0x0
#define CAUSE_FAULT_FETCH 0x1
DECLARE_CSR(sstatus, CSR_SSTATUS)
DECLARE_CSR(stvec, CSR_STVEC)
DECLARE_CSR(sie, CSR_SIE)
-DECLARE_CSR(stimecmp, CSR_STIMECMP)
DECLARE_CSR(sscratch, CSR_SSCRATCH)
DECLARE_CSR(sepc, CSR_SEPC)
DECLARE_CSR(sip, CSR_SIP)
DECLARE_CSR(instrethw, CSR_INSTRETHW)
DECLARE_CSR(stimeh, CSR_STIMEH)
DECLARE_CSR(stimehw, CSR_STIMEHW)
+DECLARE_CSR(mtimecmph, CSR_MTIMECMPH)
DECLARE_CSR(mtimeh, CSR_MTIMEH)
#endif
#ifdef DECLARE_CAUSE
DECLARE_CAUSE("sstatus", CAUSE_SSTATUS)
DECLARE_CAUSE("stvec", CAUSE_STVEC)
DECLARE_CAUSE("sie", CAUSE_SIE)
-DECLARE_CAUSE("stimecmp", CAUSE_STIMECMP)
DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH)
DECLARE_CAUSE("sepc", CAUSE_SEPC)
DECLARE_CAUSE("sip", CAUSE_SIP)
DECLARE_CAUSE("instrethw", CAUSE_INSTRETHW)
DECLARE_CAUSE("stimeh", CAUSE_STIMEH)
DECLARE_CAUSE("stimehw", CAUSE_STIMEHW)
+DECLARE_CAUSE("mtimecmph", CAUSE_MTIMECMPH)
DECLARE_CAUSE("mtimeh", CAUSE_MTIMEH)
#endif
if (interrupts & MIP_MSIP)
raise_interrupt(IRQ_SOFT);
+ if (interrupts & MIP_MTIP)
+ raise_interrupt(IRQ_TIMER);
+
if (state.fromhost != 0)
raise_interrupt(IRQ_HOST);
}
void processor_t::check_timer()
{
- // this assumes the rtc doesn't change asynchronously during step(),
- if (state.stimecmp >= (uint32_t)state.prev_rtc
- && state.stimecmp < (uint32_t)sim->rtc)
- state.mip |= MIP_STIP;
- state.prev_rtc = sim->rtc;
+ if (sim->rtc >= state.mtimecmp)
+ state.mip |= MIP_MTIP;
}
void processor_t::step(size_t n)
break;
}
case CSR_MIP: {
- reg_t mask = MIP_SSIP | MIP_MSIP;
+ reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
state.mip = (state.mip & ~mask) | (val & mask);
break;
}
case CSR_MIE: {
- reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
+ reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP;
state.mie = (state.mie & ~mask) | (val & mask);
break;
}
}
case CSR_SEPC: state.sepc = val; break;
case CSR_STVEC: state.stvec = val & ~3; break;
- case CSR_STIMECMP:
- state.mip &= ~MIP_STIP;
- state.stimecmp = val;
- break;
case CSR_SPTBR: state.sptbr = zext_xlen(val & -PGSIZE); break;
case CSR_SSCRATCH: state.sscratch = val; break;
case CSR_MEPC: state.mepc = val; break;
case CSR_MSCRATCH: state.mscratch = val; break;
case CSR_MCAUSE: state.mcause = val; break;
case CSR_MBADADDR: state.mbadaddr = val; break;
+ case CSR_MTIMECMP:
+ state.mip &= ~MIP_MTIP;
+ state.mtimecmp = val;
+ break;
case CSR_SEND_IPI: sim->send_ipi(val); break;
case CSR_MTOHOST:
if (state.tohost == 0)
case CSR_SEPC: return state.sepc;
case CSR_SBADADDR: return state.sbadaddr;
case CSR_STVEC: return state.stvec;
- case CSR_STIMECMP: return state.stimecmp;
case CSR_SCAUSE:
if (max_xlen > xlen)
return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1));
case CSR_MSCRATCH: return state.mscratch;
case CSR_MCAUSE: return state.mcause;
case CSR_MBADADDR: return state.mbadaddr;
+ case CSR_MTIMECMP: return state.mtimecmp;
case CSR_MCPUID: return cpuid;
case CSR_MIMPID: return IMPL_ROCKET;
case CSR_MHARTID: return id;