goldenmodel Implement some of the supervisor CSR
This commit is contained in:
parent
39b2803914
commit
6f2e5a0eb7
|
@ -190,21 +190,49 @@ class success : public std::exception { };
|
||||||
#define MCYCLEH 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
|
#define MCYCLEH 0xB80 // MRW Upper 32 bits of mcycle, RV32I only.
|
||||||
#define MINSTRETH 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
|
#define MINSTRETH 0xB82 // MRW Upper 32 bits of minstret, RV32I only.
|
||||||
|
|
||||||
|
|
||||||
|
#define SSTATUS 0x100
|
||||||
|
#define SIE 0x104
|
||||||
|
#define STVEC 0x105
|
||||||
|
#define SCOUNTEREN 0x106
|
||||||
|
#define SSCRATCH 0x140
|
||||||
|
#define SEPC 0x141
|
||||||
|
#define SCAUSE 0x142
|
||||||
|
#define STVAL 0x143
|
||||||
|
#define SIP 0x144
|
||||||
|
#define SATP 0x180
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define SSTATUS_SIE 0x00000002
|
||||||
|
#define SSTATUS_SPIE 0x00000020
|
||||||
|
#define SSTATUS_SPP 0x00000100
|
||||||
|
|
||||||
class RiscvGolden {
|
class RiscvGolden {
|
||||||
public:
|
public:
|
||||||
int32_t pc, lastPc;
|
int32_t pc, lastPc;
|
||||||
int32_t regs[32];
|
int32_t regs[32];
|
||||||
|
|
||||||
uint32_t mscratch;
|
uint32_t mscratch;
|
||||||
uint32_t misa;
|
uint32_t misa;
|
||||||
|
uint32_t privilege;
|
||||||
|
|
||||||
|
uint32_t medeleg;
|
||||||
|
uint32_t mideleg;
|
||||||
|
|
||||||
union status {
|
union status {
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
struct {
|
struct {
|
||||||
uint32_t _1 : 3;
|
uint32_t _1a : 1;
|
||||||
|
uint32_t sie : 1;
|
||||||
|
uint32_t _1b : 1;
|
||||||
uint32_t mie : 1;
|
uint32_t mie : 1;
|
||||||
uint32_t _2 : 3;
|
uint32_t _2a : 1;
|
||||||
|
uint32_t spie : 1;
|
||||||
|
uint32_t _2b : 1;
|
||||||
uint32_t mpie : 1;
|
uint32_t mpie : 1;
|
||||||
uint32_t _3 : 3;
|
uint32_t spp : 1;
|
||||||
|
uint32_t _3 : 2;
|
||||||
uint32_t mpp : 2;
|
uint32_t mpp : 2;
|
||||||
};
|
};
|
||||||
}__attribute__((packed)) status;
|
}__attribute__((packed)) status;
|
||||||
|
@ -235,13 +263,16 @@ public:
|
||||||
};
|
};
|
||||||
}__attribute__((packed)) mie;
|
}__attribute__((packed)) mie;
|
||||||
|
|
||||||
union mtvec {
|
union Xtvec {
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
struct {
|
struct __attribute__((packed)) {
|
||||||
uint32_t _1 : 2;
|
uint32_t _1 : 2;
|
||||||
uint32_t base : 30;
|
uint32_t base : 30;
|
||||||
};
|
};
|
||||||
}__attribute__((packed)) mtvec;
|
};
|
||||||
|
|
||||||
|
Xtvec mtvec, stvec;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
union mcause {
|
union mcause {
|
||||||
|
@ -253,19 +284,16 @@ public:
|
||||||
}__attribute__((packed)) mcause;
|
}__attribute__((packed)) mcause;
|
||||||
|
|
||||||
|
|
||||||
//Machine CSR
|
union scause {
|
||||||
// misaAccess(CSR.MISA, xlen-2 -> misa.base , 0 -> misa.extensions)
|
uint32_t raw;
|
||||||
// READ_ONLY(CSR.MIP, 11 -> mip.MEIP, 7 -> mip.MTIP)
|
struct {
|
||||||
// READ_WRITE(CSR.MIP, 3 -> mip.MSIP)
|
uint32_t exceptionCode : 31;
|
||||||
// READ_WRITE(CSR.MIE, 11 -> mie.MEIE, 7 -> mie.MTIE, 3 -> mie.MSIE)
|
uint32_t interrupt : 1;
|
||||||
//
|
};
|
||||||
// mtvecAccess(CSR.MTVEC, mtvec)
|
}__attribute__((packed)) scause;
|
||||||
// mepcAccess(CSR.MEPC, mepc)
|
|
||||||
// READ_WRITE(CSR.MSTATUS,11 -> mstatus.MPP, 7 -> mstatus.MPIE, 3 -> mstatus.MIE)
|
|
||||||
// if(mscratchGen) READ_WRITE(CSR.MSCRATCH, mscratch)
|
|
||||||
// mcauseAccess(CSR.MCAUSE, xlen-1 -> mcause.interrupt, 0 -> mcause.exceptionCode)
|
|
||||||
// mbadaddrAccess(CSR.MBADADDR, mbadaddr)
|
|
||||||
//READ_WRITE(CSR.MSTATUS,11 -> mstatus.MPP, 7 -> mstatus.MPIE, 3 -> mstatus.MIE)
|
|
||||||
RiscvGolden() {
|
RiscvGolden() {
|
||||||
pc = 0x80000000;
|
pc = 0x80000000;
|
||||||
regs[0] = 0;
|
regs[0] = 0;
|
||||||
|
@ -281,6 +309,9 @@ public:
|
||||||
mepc = 0;
|
mepc = 0;
|
||||||
misa = 0; //TODO
|
misa = 0; //TODO
|
||||||
status.mpp = 3;
|
status.mpp = 3;
|
||||||
|
privilege = 3;
|
||||||
|
medeleg = 0;
|
||||||
|
mideleg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void rfWrite(int32_t address, int32_t data) {
|
virtual void rfWrite(int32_t address, int32_t data) {
|
||||||
|
@ -296,8 +327,8 @@ public:
|
||||||
exception(0, 0, target);
|
exception(0, 0, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t mbadaddr;
|
uint32_t mbadaddr, sbadaddr;
|
||||||
uint32_t mepc;
|
uint32_t mepc, sepc;
|
||||||
|
|
||||||
virtual bool iRead(int32_t address, uint32_t *data) = 0;
|
virtual bool iRead(int32_t address, uint32_t *data) = 0;
|
||||||
virtual bool dRead(int32_t address, int32_t size, uint32_t *data) = 0;
|
virtual bool dRead(int32_t address, int32_t size, uint32_t *data) = 0;
|
||||||
|
@ -310,18 +341,36 @@ public:
|
||||||
exception(interrupt, cause, true, value);
|
exception(interrupt, cause, true, value);
|
||||||
}
|
}
|
||||||
void exception(bool interrupt,int32_t cause, bool valueWrite, uint32_t value) {
|
void exception(bool interrupt,int32_t cause, bool valueWrite, uint32_t value) {
|
||||||
if(valueWrite){
|
uint32_t deleg = interrupt ? mideleg : medeleg;
|
||||||
mbadaddr = value;
|
uint32_t targetPrivilege = 3;
|
||||||
}
|
if(deleg & (1 << cause)) targetPrivilege = 1;
|
||||||
mcause.interrupt = interrupt;
|
Xtvec xtvec = targetPrivilege == 3 ? mtvec : stvec;
|
||||||
mcause.exceptionCode = cause;
|
|
||||||
status.mie = false;
|
switch(targetPrivilege){
|
||||||
status.mpie = status.mie;
|
case 3:
|
||||||
mepc = pc;
|
if(valueWrite) mbadaddr = value;
|
||||||
pcWrite(mtvec.base << 2);
|
mcause.interrupt = interrupt;
|
||||||
|
mcause.exceptionCode = cause;
|
||||||
|
status.mie = false;
|
||||||
|
status.mpie = status.mie;
|
||||||
|
status.mpp = privilege;
|
||||||
|
mepc = pc;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if(valueWrite) sbadaddr = value;
|
||||||
|
scause.interrupt = interrupt;
|
||||||
|
scause.exceptionCode = cause;
|
||||||
|
status.sie = false;
|
||||||
|
status.spie = status.sie;
|
||||||
|
status.spp = privilege;
|
||||||
|
sepc = pc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
privilege = targetPrivilege;
|
||||||
|
pcWrite(xtvec.base << 2);
|
||||||
if(interrupt) livenessInterrupt = 0;
|
if(interrupt) livenessInterrupt = 0;
|
||||||
|
|
||||||
//status.MPP := privilege
|
|
||||||
if(!interrupt) step(); //As VexRiscv instruction which trap do not reach writeback stage fire
|
if(!interrupt) step(); //As VexRiscv instruction which trap do not reach writeback stage fire
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,33 +382,37 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t* csrPtr(int32_t csr){
|
|
||||||
switch(csr){
|
|
||||||
case MSTATUS: return &status.raw; break;
|
|
||||||
case MIP: return &mip.raw; break;
|
|
||||||
case MIE: return &mie.raw; break;
|
|
||||||
case MTVEC: return &mtvec.raw; break;
|
|
||||||
case MCAUSE: return &mcause.raw; break;
|
|
||||||
case MBADADDR: return &mbadaddr; break;
|
|
||||||
case MEPC: return &mepc; break;
|
|
||||||
case MSCRATCH: return &mscratch; break;
|
|
||||||
case MISA: return &misa; break;
|
|
||||||
default: ilegalInstruction(); return NULL; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool csrRead(int32_t csr, uint32_t *value){
|
virtual bool csrRead(int32_t csr, uint32_t *value){
|
||||||
auto ptr = csrPtr(csr);
|
switch(csr){
|
||||||
if(ptr){
|
case MSTATUS: *value = status.raw; break;
|
||||||
*value = *ptr;
|
case MIP: *value = mip.raw; break;
|
||||||
|
case MIE: *value = mie.raw; break;
|
||||||
|
case MTVEC: *value = mtvec.raw; break;
|
||||||
|
case MCAUSE: *value = mcause.raw; break;
|
||||||
|
case MBADADDR: *value = mbadaddr; break;
|
||||||
|
case MEPC: *value = mepc; break;
|
||||||
|
case MSCRATCH: *value = mscratch; break;
|
||||||
|
case MISA: *value = misa; break;
|
||||||
|
default: return true; break;
|
||||||
}
|
}
|
||||||
return ptr == NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool csrWrite(int32_t csr, uint32_t value){
|
virtual bool csrWrite(int32_t csr, uint32_t value){
|
||||||
auto ptr = csrPtr(csr);
|
switch(csr){
|
||||||
if(ptr) *csrPtr(csr) = value;
|
case MSTATUS: status.raw = value; break;
|
||||||
return ptr == NULL;
|
case MIP: mip.raw = value; break;
|
||||||
|
case MIE: mie.raw = value; break;
|
||||||
|
case MTVEC: mtvec.raw = value; break;
|
||||||
|
case MCAUSE: mcause.raw = value; break;
|
||||||
|
case MBADADDR: mbadaddr = value; break;
|
||||||
|
case MEPC: mepc = value; break;
|
||||||
|
case MSCRATCH: mscratch = value; break;
|
||||||
|
case MISA: misa = value; break;
|
||||||
|
default: ilegalInstruction(); return true; break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -559,19 +612,30 @@ public:
|
||||||
if(i32_func3 == 0){
|
if(i32_func3 == 0){
|
||||||
switch(i){
|
switch(i){
|
||||||
case 0x30200073:{ //MRET
|
case 0x30200073:{ //MRET
|
||||||
status.mie = status.mpie;
|
if(privilege < 3){ ilegalInstruction(); return;}
|
||||||
//privilege := mstatus.MPP
|
status.mpp = 0;
|
||||||
pcWrite(mepc);
|
status.mie = status.mpie;
|
||||||
}break;
|
status.mpie = 1;
|
||||||
|
privilege = status.mpp;
|
||||||
|
pcWrite(mepc);
|
||||||
|
}break;
|
||||||
|
case 0x10200073:{ //SRET
|
||||||
|
if(privilege < 1){ ilegalInstruction(); return;}
|
||||||
|
status.spp = 0;
|
||||||
|
status.sie = status.spie;
|
||||||
|
status.spie = 1;
|
||||||
|
privilege = status.spp;
|
||||||
|
pcWrite(sepc);
|
||||||
|
}break;
|
||||||
case 0x00000073:{ //ECALL
|
case 0x00000073:{ //ECALL
|
||||||
exception(0, 11);
|
exception(0, 11);
|
||||||
}break;
|
}break;
|
||||||
case 0x10500073:{ //WFI
|
case 0x10500073:{ //WFI
|
||||||
pcWrite(pc + 4);
|
pcWrite(pc + 4);
|
||||||
}break;
|
}break;
|
||||||
default:
|
default:
|
||||||
ilegalInstruction();
|
ilegalInstruction();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//CSR
|
//CSR
|
||||||
|
|
Loading…
Reference in New Issue