feat: implement privileged mode support
This commit is contained in:
@@ -5,20 +5,42 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val cmd = Input(new CsrCommand(p))
|
||||
val readAddr = Input(UInt(12.W))
|
||||
val currentPriv = Input(UInt(2.W))
|
||||
val rdata = Output(UInt(p.xlen.W))
|
||||
val readIllegal = Output(Bool())
|
||||
val writeIllegal = Output(Bool())
|
||||
val illegal = Output(Bool())
|
||||
val trap = Input(Bool())
|
||||
val trapPc = Input(UInt(p.xlen.W))
|
||||
val trapCause = Input(UInt(p.xlen.W))
|
||||
val trapTval = Input(UInt(p.xlen.W))
|
||||
val trapTargetPriv = Input(UInt(2.W))
|
||||
val trapIsInterrupt = Input(Bool())
|
||||
val trapVector = Output(UInt(p.xlen.W))
|
||||
val xret = Input(Bool())
|
||||
val xretIsMret = Input(Bool())
|
||||
val satp = Output(UInt(p.xlen.W))
|
||||
val mtvec = Output(UInt(p.xlen.W))
|
||||
val mepc = Output(UInt(p.xlen.W))
|
||||
val stvec = Output(UInt(p.xlen.W))
|
||||
val sepc = Output(UInt(p.xlen.W))
|
||||
val medeleg = Output(UInt(p.xlen.W))
|
||||
val mideleg = Output(UInt(p.xlen.W))
|
||||
val mie = Output(UInt(p.xlen.W))
|
||||
val mip = Output(UInt(p.xlen.W))
|
||||
val mstatus = Output(UInt(p.xlen.W))
|
||||
})
|
||||
|
||||
val cycle = RegInit(0.U(p.xlen.W))
|
||||
val instret = RegInit(0.U(p.xlen.W))
|
||||
val mcountinhibit = RegInit(0.U(p.xlen.W))
|
||||
val suppressInstretIncrement = WireDefault(false.B)
|
||||
val suppressInstretAfterWrite = RegInit(false.B)
|
||||
dontTouch(suppressInstretIncrement)
|
||||
val mstatus = RegInit(0.U(p.xlen.W))
|
||||
val misa = RegInit("h800000000014112d".U(p.xlen.W))
|
||||
val misa = RegInit(Privileged.MISA_RV64_IMASU)
|
||||
val mtvecReg = RegInit(0.U(p.xlen.W))
|
||||
val mscratch = RegInit(0.U(p.xlen.W))
|
||||
val mepcReg = RegInit(0.U(p.xlen.W))
|
||||
val mcause = RegInit(0.U(p.xlen.W))
|
||||
val mtval = RegInit(0.U(p.xlen.W))
|
||||
@@ -26,7 +48,14 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
val mideleg = RegInit(0.U(p.xlen.W))
|
||||
val mie = RegInit(0.U(p.xlen.W))
|
||||
val mip = RegInit(0.U(p.xlen.W))
|
||||
val sstatus = RegInit(0.U(p.xlen.W))
|
||||
val mcounteren = RegInit(0.U(p.xlen.W))
|
||||
val pmpcfg0 = RegInit(0.U(p.xlen.W))
|
||||
val pmpaddr0 = RegInit(0.U(p.xlen.W))
|
||||
val tdata1 = RegInit(0.U(p.xlen.W))
|
||||
val tdata2 = RegInit(0.U(p.xlen.W))
|
||||
val tcontrol = RegInit(0.U(p.xlen.W))
|
||||
val mnstatus = RegInit(0.U(p.xlen.W))
|
||||
val scounteren = RegInit(0.U(p.xlen.W))
|
||||
val stvec = RegInit(0.U(p.xlen.W))
|
||||
val sepc = RegInit(0.U(p.xlen.W))
|
||||
val scause = RegInit(0.U(p.xlen.W))
|
||||
@@ -35,59 +64,116 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
val satpReg = RegInit(0.U(p.xlen.W))
|
||||
|
||||
cycle := cycle + 1.U
|
||||
when(!mcountinhibit(2) && !suppressInstretIncrement && !suppressInstretAfterWrite) {
|
||||
instret := instret + 1.U
|
||||
}
|
||||
io.satp := satpReg
|
||||
io.mtvec := mtvecReg
|
||||
io.mepc := mepcReg
|
||||
io.stvec := stvec
|
||||
io.sepc := sepc
|
||||
io.medeleg := medeleg
|
||||
io.mideleg := mideleg
|
||||
io.mie := mie
|
||||
io.mip := mip
|
||||
io.mstatus := mstatus
|
||||
|
||||
val readAllowed = CSRPermission.readAllowed(io.readAddr, io.currentPriv)
|
||||
val writeAllowed = CSRPermission.writeAllowed(io.cmd.addr, io.currentPriv)
|
||||
val readIllegal = !readAllowed
|
||||
val writeIllegal = io.cmd.valid && io.cmd.cmd =/= 0.U && !writeAllowed
|
||||
val xlenStatusMask = "h0000000f00000000".U(p.xlen.W)
|
||||
val rv64XlenStatus = "h0000000a00000000".U(p.xlen.W)
|
||||
val mstatusView = (mstatus & ~xlenStatusMask) | rv64XlenStatus
|
||||
val sstatusMask = "h00000002000de162".U(p.xlen.W)
|
||||
val sstatusView = mstatusView & sstatusMask
|
||||
|
||||
val r = WireDefault(0.U(p.xlen.W))
|
||||
switch(io.readAddr) {
|
||||
is("h300".U) { r := mstatus }
|
||||
is("h301".U) { r := misa }
|
||||
is("h302".U) { r := medeleg }
|
||||
is("h303".U) { r := mideleg }
|
||||
is("h304".U) { r := mie }
|
||||
is("h305".U) { r := mtvecReg }
|
||||
is("h341".U) { r := mepcReg }
|
||||
is("h342".U) { r := mcause }
|
||||
is("h343".U) { r := mtval }
|
||||
is("h344".U) { r := mip }
|
||||
is("h100".U) { r := sstatus }
|
||||
is("h105".U) { r := stvec }
|
||||
is("h140".U) { r := sscratch }
|
||||
is("h141".U) { r := sepc }
|
||||
is("h142".U) { r := scause }
|
||||
is("h143".U) { r := stval }
|
||||
is("h180".U) { r := satpReg }
|
||||
is("hf14".U) { r := 0.U }
|
||||
is("hc00".U) { r := cycle }
|
||||
is("hc01".U) { r := 0.U }
|
||||
is("hc02".U) { r := instret }
|
||||
is(Privileged.CSR_MSTATUS) { r := mstatusView }
|
||||
is(Privileged.CSR_MISA) { r := misa }
|
||||
is(Privileged.CSR_MEDELEG) { r := medeleg }
|
||||
is(Privileged.CSR_MIDELEG) { r := mideleg }
|
||||
is(Privileged.CSR_MIE) { r := mie }
|
||||
is(Privileged.CSR_MTVEC) { r := mtvecReg }
|
||||
is(Privileged.CSR_MCOUNTEREN) { r := mcounteren }
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { r := mcountinhibit }
|
||||
is(Privileged.CSR_MSCRATCH) { r := mscratch }
|
||||
is(Privileged.CSR_MEPC) { r := mepcReg }
|
||||
is(Privileged.CSR_MCAUSE) { r := mcause }
|
||||
is(Privileged.CSR_MTVAL) { r := mtval }
|
||||
is(Privileged.CSR_MIP) { r := mip }
|
||||
is(Privileged.CSR_PMPCFG0) { r := pmpcfg0 }
|
||||
is(Privileged.CSR_PMPADDR0) { r := pmpaddr0 }
|
||||
is(Privileged.CSR_TSELECT) { r := 1.U }
|
||||
is(Privileged.CSR_TDATA1) { r := tdata1 }
|
||||
is(Privileged.CSR_TDATA2) { r := tdata2 }
|
||||
is(Privileged.CSR_TCONTROL) { r := tcontrol }
|
||||
is(Privileged.CSR_MNSTATUS) { r := mnstatus }
|
||||
is(Privileged.CSR_SSTATUS) { r := sstatusView }
|
||||
is(Privileged.CSR_SIE) { r := mie & mideleg }
|
||||
is(Privileged.CSR_STVEC) { r := stvec }
|
||||
is(Privileged.CSR_SCOUNTEREN) { r := scounteren }
|
||||
is(Privileged.CSR_SSCRATCH) { r := sscratch }
|
||||
is(Privileged.CSR_SEPC) { r := sepc }
|
||||
is(Privileged.CSR_SCAUSE) { r := scause }
|
||||
is(Privileged.CSR_STVAL) { r := stval }
|
||||
is(Privileged.CSR_SIP) { r := mip & mideleg }
|
||||
is(Privileged.CSR_SATP) { r := satpReg }
|
||||
is(Privileged.CSR_MVENDORID) { r := 0.U }
|
||||
is(Privileged.CSR_MARCHID) { r := 0.U }
|
||||
is(Privileged.CSR_MIMPID) { r := 0.U }
|
||||
is(Privileged.CSR_MHARTID) { r := 0.U }
|
||||
is(Privileged.CSR_MINSTRET) { r := instret }
|
||||
is(Privileged.CSR_CYCLE) { r := cycle }
|
||||
is(Privileged.CSR_TIME) { r := cycle }
|
||||
is(Privileged.CSR_INSTRET) { r := instret }
|
||||
}
|
||||
io.rdata := r
|
||||
io.rdata := Mux(readAllowed, r, 0.U)
|
||||
io.readIllegal := readIllegal
|
||||
io.writeIllegal := writeIllegal
|
||||
io.illegal := readIllegal || writeIllegal
|
||||
|
||||
val writeOld = WireDefault(0.U(p.xlen.W))
|
||||
switch(io.cmd.addr) {
|
||||
is("h300".U) { writeOld := mstatus }
|
||||
is("h301".U) { writeOld := misa }
|
||||
is("h302".U) { writeOld := medeleg }
|
||||
is("h303".U) { writeOld := mideleg }
|
||||
is("h304".U) { writeOld := mie }
|
||||
is("h305".U) { writeOld := mtvecReg }
|
||||
is("h341".U) { writeOld := mepcReg }
|
||||
is("h342".U) { writeOld := mcause }
|
||||
is("h343".U) { writeOld := mtval }
|
||||
is("h344".U) { writeOld := mip }
|
||||
is("h100".U) { writeOld := sstatus }
|
||||
is("h105".U) { writeOld := stvec }
|
||||
is("h140".U) { writeOld := sscratch }
|
||||
is("h141".U) { writeOld := sepc }
|
||||
is("h142".U) { writeOld := scause }
|
||||
is("h143".U) { writeOld := stval }
|
||||
is("h180".U) { writeOld := satpReg }
|
||||
is("hf14".U) { writeOld := 0.U }
|
||||
is("hc00".U) { writeOld := cycle }
|
||||
is("hc01".U) { writeOld := 0.U }
|
||||
is("hc02".U) { writeOld := instret }
|
||||
is(Privileged.CSR_MSTATUS) { writeOld := mstatusView }
|
||||
is(Privileged.CSR_MISA) { writeOld := misa }
|
||||
is(Privileged.CSR_MEDELEG) { writeOld := medeleg }
|
||||
is(Privileged.CSR_MIDELEG) { writeOld := mideleg }
|
||||
is(Privileged.CSR_MIE) { writeOld := mie }
|
||||
is(Privileged.CSR_MTVEC) { writeOld := mtvecReg }
|
||||
is(Privileged.CSR_MCOUNTEREN) { writeOld := mcounteren }
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { writeOld := mcountinhibit }
|
||||
is(Privileged.CSR_MSCRATCH) { writeOld := mscratch }
|
||||
is(Privileged.CSR_MEPC) { writeOld := mepcReg }
|
||||
is(Privileged.CSR_MCAUSE) { writeOld := mcause }
|
||||
is(Privileged.CSR_MTVAL) { writeOld := mtval }
|
||||
is(Privileged.CSR_MIP) { writeOld := mip }
|
||||
is(Privileged.CSR_PMPCFG0) { writeOld := pmpcfg0 }
|
||||
is(Privileged.CSR_PMPADDR0) { writeOld := pmpaddr0 }
|
||||
is(Privileged.CSR_TSELECT) { writeOld := 1.U }
|
||||
is(Privileged.CSR_TDATA1) { writeOld := tdata1 }
|
||||
is(Privileged.CSR_TDATA2) { writeOld := tdata2 }
|
||||
is(Privileged.CSR_TCONTROL) { writeOld := tcontrol }
|
||||
is(Privileged.CSR_MNSTATUS) { writeOld := mnstatus }
|
||||
is(Privileged.CSR_SSTATUS) { writeOld := sstatusView }
|
||||
is(Privileged.CSR_SIE) { writeOld := mie & mideleg }
|
||||
is(Privileged.CSR_STVEC) { writeOld := stvec }
|
||||
is(Privileged.CSR_SCOUNTEREN) { writeOld := scounteren }
|
||||
is(Privileged.CSR_SSCRATCH) { writeOld := sscratch }
|
||||
is(Privileged.CSR_SEPC) { writeOld := sepc }
|
||||
is(Privileged.CSR_SCAUSE) { writeOld := scause }
|
||||
is(Privileged.CSR_STVAL) { writeOld := stval }
|
||||
is(Privileged.CSR_SIP) { writeOld := mip & mideleg }
|
||||
is(Privileged.CSR_SATP) { writeOld := satpReg }
|
||||
is(Privileged.CSR_MVENDORID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MARCHID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MIMPID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MHARTID) { writeOld := 0.U }
|
||||
is(Privileged.CSR_MINSTRET) { writeOld := instret }
|
||||
is(Privileged.CSR_CYCLE) { writeOld := cycle }
|
||||
is(Privileged.CSR_TIME) { writeOld := cycle }
|
||||
is(Privileged.CSR_INSTRET) { writeOld := instret }
|
||||
}
|
||||
|
||||
val operand = Mux(io.cmd.cmd(2), io.cmd.zimm, io.cmd.rs1)
|
||||
@@ -97,29 +183,82 @@ class CSRFile(p: CoreParams = CoreParams()) extends Module {
|
||||
3.U -> (writeOld & ~operand)
|
||||
))
|
||||
|
||||
when(io.cmd.valid && io.cmd.cmd =/= 0.U) {
|
||||
when(io.cmd.valid && io.cmd.cmd =/= 0.U && writeAllowed) {
|
||||
switch(io.cmd.addr) {
|
||||
is("h300".U) { mstatus := next }
|
||||
is("h302".U) { medeleg := next }
|
||||
is("h303".U) { mideleg := next }
|
||||
is("h304".U) { mie := next }
|
||||
is("h305".U) { mtvecReg := next }
|
||||
is("h341".U) { mepcReg := next }
|
||||
is("h342".U) { mcause := next }
|
||||
is("h343".U) { mtval := next }
|
||||
is("h344".U) { mip := next }
|
||||
is("h100".U) { sstatus := next }
|
||||
is("h105".U) { stvec := next }
|
||||
is("h140".U) { sscratch := next }
|
||||
is("h141".U) { sepc := next }
|
||||
is("h142".U) { scause := next }
|
||||
is("h143".U) { stval := next }
|
||||
is("h180".U) { satpReg := next }
|
||||
is(Privileged.CSR_MSTATUS) { mstatus := next }
|
||||
is(Privileged.CSR_MEDELEG) { medeleg := next }
|
||||
is(Privileged.CSR_MIDELEG) { mideleg := next }
|
||||
is(Privileged.CSR_MIE) { mie := next }
|
||||
is(Privileged.CSR_MTVEC) { mtvecReg := next }
|
||||
is(Privileged.CSR_MCOUNTEREN) { mcounteren := next }
|
||||
is(Privileged.CSR_MCOUNTINHIBIT) { mcountinhibit := next & 4.U }
|
||||
is(Privileged.CSR_MSCRATCH) { mscratch := next }
|
||||
is(Privileged.CSR_MEPC) { mepcReg := next }
|
||||
is(Privileged.CSR_MCAUSE) { mcause := next }
|
||||
is(Privileged.CSR_MTVAL) { mtval := next }
|
||||
is(Privileged.CSR_MIP) { mip := next }
|
||||
is(Privileged.CSR_PMPCFG0) { pmpcfg0 := next }
|
||||
is(Privileged.CSR_PMPADDR0) { pmpaddr0 := next }
|
||||
is(Privileged.CSR_TDATA1) { tdata1 := next }
|
||||
is(Privileged.CSR_TDATA2) { tdata2 := next }
|
||||
is(Privileged.CSR_TCONTROL) { tcontrol := next }
|
||||
is(Privileged.CSR_MNSTATUS) { mnstatus := next }
|
||||
is(Privileged.CSR_SSTATUS) { mstatus := (mstatus & ~sstatusMask) | (next & sstatusMask) }
|
||||
is(Privileged.CSR_SIE) { mie := (mie & ~mideleg) | (next & mideleg) }
|
||||
is(Privileged.CSR_STVEC) { stvec := next }
|
||||
is(Privileged.CSR_SCOUNTEREN) { scounteren := next }
|
||||
is(Privileged.CSR_SSCRATCH) { sscratch := next }
|
||||
is(Privileged.CSR_SEPC) { sepc := next }
|
||||
is(Privileged.CSR_SCAUSE) { scause := next }
|
||||
is(Privileged.CSR_STVAL) { stval := next }
|
||||
is(Privileged.CSR_SIP) { mip := (mip & ~mideleg) | (next & mideleg) }
|
||||
is(Privileged.CSR_SATP) { satpReg := next }
|
||||
is(Privileged.CSR_MINSTRET) {
|
||||
instret := next
|
||||
suppressInstretIncrement := true.B
|
||||
suppressInstretAfterWrite := true.B
|
||||
}
|
||||
}
|
||||
}
|
||||
when(suppressInstretAfterWrite) {
|
||||
suppressInstretAfterWrite := false.B
|
||||
}
|
||||
|
||||
val trapToS = io.trapTargetPriv === Privileged.PRV_S
|
||||
io.trapVector := Mux(trapToS, stvec, mtvecReg)
|
||||
val bitMie = 1.U(p.xlen.W) << 3
|
||||
val bitMpie = 1.U(p.xlen.W) << 7
|
||||
val mppMask = 3.U(p.xlen.W) << 11
|
||||
val bitSie = 1.U(p.xlen.W) << 1
|
||||
val bitSpie = 1.U(p.xlen.W) << 5
|
||||
val bitSpp = 1.U(p.xlen.W) << 8
|
||||
|
||||
when(io.trap) {
|
||||
mepcReg := io.trapPc
|
||||
mcause := io.trapCause
|
||||
when(trapToS) {
|
||||
sepc := io.trapPc
|
||||
scause := io.trapCause
|
||||
stval := io.trapTval
|
||||
val withSpie = Mux((mstatus & bitSie) =/= 0.U, mstatus | bitSpie, mstatus & ~bitSpie)
|
||||
val withSieCleared = withSpie & ~bitSie
|
||||
val withSpp = Mux(io.currentPriv === Privileged.PRV_S, withSieCleared | bitSpp, withSieCleared & ~bitSpp)
|
||||
mstatus := withSpp
|
||||
}.otherwise {
|
||||
mepcReg := io.trapPc
|
||||
mcause := io.trapCause
|
||||
mtval := io.trapTval
|
||||
val withMpie = Mux((mstatus & bitMie) =/= 0.U, mstatus | bitMpie, mstatus & ~bitMpie)
|
||||
val withMieCleared = withMpie & ~bitMie
|
||||
mstatus := (withMieCleared & ~mppMask) | (io.currentPriv.pad(p.xlen) << 11)
|
||||
}
|
||||
}.elsewhen(io.xret) {
|
||||
when(io.xretIsMret) {
|
||||
val withMie = Mux((mstatus & bitMpie) =/= 0.U, mstatus | bitMie, mstatus & ~bitMie)
|
||||
val withMpie = withMie | bitMpie
|
||||
mstatus := withMpie & ~mppMask
|
||||
}.otherwise {
|
||||
val withSie = Mux((mstatus & bitSpie) =/= 0.U, mstatus | bitSie, mstatus & ~bitSie)
|
||||
val withSpie = withSie | bitSpie
|
||||
mstatus := withSpie & ~bitSpp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
63
src/main/scala/csr/CSRPermission.scala
Normal file
63
src/main/scala/csr/CSRPermission.scala
Normal file
@@ -0,0 +1,63 @@
|
||||
import chisel3._
|
||||
|
||||
object CSRPermission {
|
||||
private val machineCsrs = Set(
|
||||
0x300, 0x301, 0x302, 0x303, 0x304, 0x305, 0x306, 0x340, 0x341, 0x342, 0x343, 0x344,
|
||||
0x320, 0x3a0, 0x3b0, 0x744, 0x7a0, 0x7a1, 0x7a2, 0x7a5, 0xb02,
|
||||
0xf11, 0xf12, 0xf13, 0xf14)
|
||||
private val supervisorCsrs = Set(0x100, 0x104, 0x105, 0x106, 0x140, 0x141, 0x142, 0x143, 0x144, 0x180)
|
||||
private val counterCsrs = Set(0xc00, 0xc01, 0xc02)
|
||||
private val readOnlyCsrs = Set(0xf11, 0xf12, 0xf13, 0xf14) ++ counterCsrs
|
||||
|
||||
def implementedLit(addr: BigInt): Boolean =
|
||||
machineCsrs(addr.toInt) || supervisorCsrs(addr.toInt) || counterCsrs(addr.toInt)
|
||||
|
||||
def readAllowedLit(addr: BigInt, priv: BigInt): Boolean =
|
||||
implementedLit(addr) && {
|
||||
if (machineCsrs(addr.toInt)) priv == 3
|
||||
else if (supervisorCsrs(addr.toInt)) priv != 0
|
||||
else true
|
||||
}
|
||||
|
||||
def writeAllowedLit(addr: BigInt, priv: BigInt): Boolean =
|
||||
readAllowedLit(addr, priv) && !readOnlyCsrs(addr.toInt)
|
||||
|
||||
private def isMachine(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_MSTATUS || addr === Privileged.CSR_MISA ||
|
||||
addr === Privileged.CSR_MEDELEG || addr === Privileged.CSR_MIDELEG ||
|
||||
addr === Privileged.CSR_MIE || addr === Privileged.CSR_MTVEC ||
|
||||
addr === Privileged.CSR_MCOUNTEREN || addr === Privileged.CSR_MSCRATCH || addr === Privileged.CSR_MEPC ||
|
||||
addr === Privileged.CSR_MCAUSE || addr === Privileged.CSR_MTVAL ||
|
||||
addr === Privileged.CSR_MIP || addr === Privileged.CSR_PMPCFG0 ||
|
||||
addr === Privileged.CSR_PMPADDR0 || addr === Privileged.CSR_TSELECT ||
|
||||
addr === Privileged.CSR_TDATA1 || addr === Privileged.CSR_TDATA2 ||
|
||||
addr === Privileged.CSR_TCONTROL || addr === Privileged.CSR_MNSTATUS ||
|
||||
addr === Privileged.CSR_MCOUNTINHIBIT || addr === Privileged.CSR_MINSTRET ||
|
||||
addr === Privileged.CSR_MVENDORID || addr === Privileged.CSR_MARCHID ||
|
||||
addr === Privileged.CSR_MIMPID || addr === Privileged.CSR_MHARTID
|
||||
|
||||
private def isSupervisor(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_SSTATUS || addr === Privileged.CSR_SIE ||
|
||||
addr === Privileged.CSR_STVEC || addr === Privileged.CSR_SSCRATCH ||
|
||||
addr === Privileged.CSR_SCOUNTEREN || addr === Privileged.CSR_SEPC || addr === Privileged.CSR_SCAUSE ||
|
||||
addr === Privileged.CSR_STVAL || addr === Privileged.CSR_SIP ||
|
||||
addr === Privileged.CSR_SATP
|
||||
|
||||
private def isCounter(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_CYCLE || addr === Privileged.CSR_TIME ||
|
||||
addr === Privileged.CSR_INSTRET
|
||||
|
||||
private def isReadOnly(addr: UInt): Bool =
|
||||
addr === Privileged.CSR_MVENDORID || addr === Privileged.CSR_MARCHID ||
|
||||
addr === Privileged.CSR_MIMPID || addr === Privileged.CSR_MHARTID ||
|
||||
isCounter(addr)
|
||||
|
||||
def implemented(addr: UInt): Bool = isMachine(addr) || isSupervisor(addr) || isCounter(addr)
|
||||
|
||||
def readAllowed(addr: UInt, priv: UInt): Bool =
|
||||
implemented(addr) && Mux(isMachine(addr), priv === Privileged.PRV_M,
|
||||
Mux(isSupervisor(addr), priv =/= Privileged.PRV_U, true.B))
|
||||
|
||||
def writeAllowed(addr: UInt, priv: UInt): Bool =
|
||||
readAllowed(addr, priv) && !isReadOnly(addr)
|
||||
}
|
||||
@@ -2,20 +2,14 @@ import chisel3._
|
||||
|
||||
class PrivilegeControl(p: CoreParams = CoreParams()) extends Module {
|
||||
val io = IO(new Bundle {
|
||||
val trap = Input(Bool())
|
||||
val mret = Input(Bool())
|
||||
val sret = Input(Bool())
|
||||
val privilege = Output(UInt(2.W))
|
||||
val nextPriv = Input(UInt(2.W))
|
||||
val setPriv = Input(Bool())
|
||||
val priv = Output(UInt(2.W))
|
||||
})
|
||||
|
||||
val mode = RegInit(3.U(2.W))
|
||||
when(io.trap) {
|
||||
mode := 3.U
|
||||
}.elsewhen(io.mret) {
|
||||
mode := 0.U
|
||||
}.elsewhen(io.sret) {
|
||||
mode := 0.U
|
||||
val privReg = RegInit(Privileged.PRV_M)
|
||||
when(io.setPriv) {
|
||||
privReg := io.nextPriv
|
||||
}
|
||||
io.privilege := mode
|
||||
io.priv := privReg
|
||||
}
|
||||
|
||||
|
||||
47
src/main/scala/csr/PrivilegeTransitions.scala
Normal file
47
src/main/scala/csr/PrivilegeTransitions.scala
Normal file
@@ -0,0 +1,47 @@
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
object PrivilegeTransitions {
|
||||
private def delegated(cause: UInt, delegation: UInt): Bool = delegation(cause(5, 0))
|
||||
|
||||
def trapTargetPriv(
|
||||
currentPriv: UInt,
|
||||
cause: UInt,
|
||||
isInterrupt: Bool,
|
||||
medeleg: UInt,
|
||||
mideleg: UInt): UInt = {
|
||||
val delegation = Mux(isInterrupt, mideleg, medeleg)
|
||||
val toSupervisor = currentPriv =/= Privileged.PRV_M && delegated(cause, delegation)
|
||||
Mux(toSupervisor, Privileged.PRV_S, Privileged.PRV_M)
|
||||
}
|
||||
|
||||
def mretNextPriv(mstatus: UInt): UInt = mstatus(12, 11)
|
||||
|
||||
def sretNextPriv(mstatus: UInt): UInt = Mux(mstatus(8), Privileged.PRV_S, Privileged.PRV_U)
|
||||
|
||||
def xretTargetPc(isMret: Bool, mepc: UInt, sepc: UInt): UInt =
|
||||
Mux(isMret, mepc, sepc)
|
||||
|
||||
def xretNextPriv(isMret: Bool, mstatus: UInt): UInt =
|
||||
Mux(isMret, mretNextPriv(mstatus), sretNextPriv(mstatus))
|
||||
|
||||
def trapTargetPrivLit(
|
||||
currentPriv: BigInt,
|
||||
cause: BigInt,
|
||||
isInterrupt: Boolean,
|
||||
medeleg: BigInt,
|
||||
mideleg: BigInt): BigInt = {
|
||||
val delegation = if (isInterrupt) mideleg else medeleg
|
||||
val delegated = ((delegation >> cause.toInt) & 1) == 1
|
||||
if (currentPriv != Privileged.PRV_M.litValue && delegated) Privileged.PRV_S.litValue
|
||||
else Privileged.PRV_M.litValue
|
||||
}
|
||||
|
||||
def mretNextPrivLit(mstatus: BigInt): BigInt = (mstatus >> 11) & 3
|
||||
|
||||
def sretNextPrivLit(mstatus: BigInt): BigInt =
|
||||
if (((mstatus >> 8) & 1) == 1) Privileged.PRV_S.litValue else Privileged.PRV_U.litValue
|
||||
|
||||
def xretTargetPcLit(isMret: Boolean, mepc: BigInt, sepc: BigInt): BigInt =
|
||||
if (isMret) mepc else sepc
|
||||
}
|
||||
Reference in New Issue
Block a user