Rework CsrPlugin interrupt delegation
This commit is contained in:
parent
9e72971ff0
commit
acaa931e11
|
@ -314,21 +314,15 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
|
|
||||||
val csrMapping = new CsrMapping()
|
val csrMapping = new CsrMapping()
|
||||||
|
|
||||||
|
//Interruption specification data model
|
||||||
|
case class Delegator(var enable : Bool, privilege : Int)
|
||||||
|
case class InterruptSource(var cond : Bool, id : Int, privilege : Int, delegators : List[Delegator])
|
||||||
|
var interruptSpecs = ArrayBuffer[InterruptSource]()
|
||||||
|
|
||||||
|
def addInterrupt(cond : Bool, id : Int, privilege : Int, delegators : List[Delegator]): Unit = {
|
||||||
case class InterruptSource(var cond : Bool, id : Int)
|
interruptSpecs += InterruptSource(cond, id, privilege, delegators)
|
||||||
case class InterruptPrivilege(privilege : Int){
|
|
||||||
var privilegeCond : Bool = null
|
|
||||||
val sources = ArrayBuffer[InterruptSource]()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def getInterruptPrivilege(privilege : Int) = customInterrupts.getOrElseUpdate(privilege, InterruptPrivilege(privilege))
|
|
||||||
var customInterrupts = mutable.LinkedHashMap[Int, InterruptPrivilege]()
|
|
||||||
def addInterrupt(cond : Bool, id : Int, privilege : Int): Unit = {
|
|
||||||
getInterruptPrivilege(privilege).sources += InterruptSource(cond, id)
|
|
||||||
}
|
|
||||||
def createInterrupt(id : Int, privilege : Int) : Bool = { val ret = Bool(); addInterrupt(ret, id, privilege); ret}
|
|
||||||
|
|
||||||
override def r(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r(csrAddress, bitOffset, that)
|
override def r(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r(csrAddress, bitOffset, that)
|
||||||
override def w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.w(csrAddress, bitOffset, that)
|
override def w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.w(csrAddress, bitOffset, that)
|
||||||
override def r2w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r2w(csrAddress, bitOffset, that)
|
override def r2w(csrAddress: Int, bitOffset: Int, that: Data): Unit = csrMapping.r2w(csrAddress, bitOffset, that)
|
||||||
|
@ -399,10 +393,8 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
allowInterrupts = True
|
allowInterrupts = True
|
||||||
allowException = True
|
allowException = True
|
||||||
|
|
||||||
for (privilege <- customInterrupts.values;
|
for (i <- interruptSpecs) i.cond = i.cond.pull()
|
||||||
source <- privilege.sources){
|
|
||||||
source.cond = source.cond.pull()
|
|
||||||
}
|
|
||||||
|
|
||||||
pipeline.update(MPP, UInt(2 bits))
|
pipeline.update(MPP, UInt(2 bits))
|
||||||
}
|
}
|
||||||
|
@ -474,7 +466,9 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
|
|
||||||
|
|
||||||
val medeleg = Reg(Bits(32 bits)) init(0)
|
val medeleg = Reg(Bits(32 bits)) init(0)
|
||||||
val mideleg = Reg(Bits(32 bits)) init(0)
|
val mideleg = supervisorGen generate new Area {
|
||||||
|
val ST, SE, SS = RegInit(False)
|
||||||
|
}
|
||||||
|
|
||||||
if(mvendorid != null) READ_ONLY(CSR.MVENDORID, U(mvendorid))
|
if(mvendorid != null) READ_ONLY(CSR.MVENDORID, U(mvendorid))
|
||||||
if(marchid != null) READ_ONLY(CSR.MARCHID , U(marchid ))
|
if(marchid != null) READ_ONLY(CSR.MARCHID , U(marchid ))
|
||||||
|
@ -498,8 +492,10 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
|
minstretAccess(CSR.MINSTRET, minstret(31 downto 0))
|
||||||
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
|
minstretAccess(CSR.MINSTRETH, minstret(63 downto 32))
|
||||||
|
|
||||||
|
if(supervisorGen) {
|
||||||
medelegAccess(CSR.MEDELEG, medeleg)
|
medelegAccess(CSR.MEDELEG, medeleg)
|
||||||
midelegAccess(CSR.MIDELEG, mideleg)
|
midelegAccess(CSR.MIDELEG, 9 -> mideleg.SE, 5 -> mideleg.ST, 1 -> mideleg.SS)
|
||||||
|
}
|
||||||
|
|
||||||
//User CSR
|
//User CSR
|
||||||
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
|
ucycleAccess(CSR.UCYCLE, mcycle(31 downto 0))
|
||||||
|
@ -579,20 +575,14 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
|
|
||||||
|
|
||||||
if(supervisorGen) {
|
if(supervisorGen) {
|
||||||
getInterruptPrivilege(1).privilegeCond = (sstatus.SIE && privilege === "01") || privilege === "00"
|
addInterrupt(sip.STIP && sie.STIE, id = 5, privilege = 1, delegators = List(Delegator(mideleg.ST, 3)))
|
||||||
getInterruptPrivilege(1).sources ++= List(
|
addInterrupt(sip.SSIP && sie.SSIE, id = 1, privilege = 1, delegators = List(Delegator(mideleg.SS, 3)))
|
||||||
InterruptSource(sip.STIP && sie.STIE, 5),
|
addInterrupt(sip.SEIP_OR && sie.SEIE, id = 9, privilege = 1, delegators = List(Delegator(mideleg.SE, 3)))
|
||||||
InterruptSource(sip.SSIP && sie.SSIE, 1),
|
|
||||||
InterruptSource(sip.SEIP_OR && sie.SEIE, 9)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getInterruptPrivilege(3).privilegeCond = mstatus.MIE || privilege =/= "11"
|
addInterrupt(mip.MTIP && mie.MTIE, id = 7, privilege = 3, delegators = Nil)
|
||||||
getInterruptPrivilege(3).sources ++= List(
|
addInterrupt(mip.MSIP && mie.MSIE, id = 3, privilege = 3, delegators = Nil)
|
||||||
InterruptSource(mip.MTIP && mie.MTIE, 7),
|
addInterrupt(mip.MEIP && mie.MEIE, id = 11, privilege = 3, delegators = Nil)
|
||||||
InterruptSource(mip.MSIP && mie.MSIE, 3),
|
|
||||||
InterruptSource(mip.MEIP && mie.MEIE, 11)
|
|
||||||
)
|
|
||||||
|
|
||||||
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
case class DelegatorModel(value : Bits, source : Int, target : Int)
|
||||||
// def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
// def solveDelegators(delegators : Seq[DelegatorModel], id : Int, lowerBound : Int): UInt = {
|
||||||
|
@ -626,9 +616,6 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
// ret.max(lowerBound)
|
// ret.max(lowerBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
val interruptDelegators = ArrayBuffer[DelegatorModel]()
|
|
||||||
if(midelegAccess.canWrite) interruptDelegators += DelegatorModel(mideleg,3, 1)
|
|
||||||
|
|
||||||
val exceptionDelegators = ArrayBuffer[DelegatorModel]()
|
val exceptionDelegators = ArrayBuffer[DelegatorModel]()
|
||||||
if(medelegAccess.canWrite) exceptionDelegators += DelegatorModel(medeleg,3, 1)
|
if(medelegAccess.canWrite) exceptionDelegators += DelegatorModel(medeleg,3, 1)
|
||||||
|
|
||||||
|
@ -703,32 +690,28 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
||||||
//Process interrupt request, code and privilege
|
//Process interrupt request, code and privilege
|
||||||
val interrupt = False
|
val interrupt = False
|
||||||
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
val interruptCode = UInt(4 bits).assignDontCare().addTag(Verilator.public)
|
||||||
val interruptDelegatorHit = interruptDelegators.map(d => (d -> False)).toMap
|
val privilegeAllowInterrupts = mutable.HashMap(
|
||||||
for(model <- customInterrupts.values.toSeq.sortBy(_.privilege)){
|
1 -> ((sstatus.SIE && privilege === "01") || privilege < "01"),
|
||||||
when(model.privilegeCond){
|
3 -> (mstatus.MIE || privilege < "11")
|
||||||
when(model.sources.map(_.cond).orR){
|
)
|
||||||
|
var interruptPrivilegs = if (supervisorGen) List(1, 3) else List(3)
|
||||||
|
val interruptTargetPrivilege = UInt(2 bits).assignDontCare()
|
||||||
|
while(interruptPrivilegs.nonEmpty){
|
||||||
|
val p = interruptPrivilegs.head
|
||||||
|
when(privilegeAllowInterrupts(p)){
|
||||||
|
for(i <- interruptSpecs
|
||||||
|
if i.privilege <= p //EX : Machine timer interrupt can't go into supervisor mode
|
||||||
|
if interruptPrivilegs.tail.forall(e => i.delegators.exists(_.privilege == e))){ // EX : Supervisor timer need to have machine mode delegator
|
||||||
|
val delegUpOn = i.delegators.filter(_.privilege > p).map(_.enable).fold(True)(_ && _)
|
||||||
|
val delegDownOff = !i.delegators.filter(_.privilege <= p).map(_.enable).orR
|
||||||
|
when(i.cond && delegUpOn && delegDownOff){
|
||||||
interrupt := True
|
interrupt := True
|
||||||
}
|
interruptCode := i.id
|
||||||
for(source <- model.sources){
|
interruptTargetPrivilege := p
|
||||||
when(source.cond){
|
|
||||||
interruptCode := source.id
|
|
||||||
for(interruptDelegator <- interruptDelegators){
|
|
||||||
interruptDelegatorHit(interruptDelegator) := (if(interruptDelegator.target < model.privilege){
|
|
||||||
False
|
|
||||||
} else {
|
|
||||||
interruptDelegator.value(source.id)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
interruptPrivilegs = interruptPrivilegs.tail
|
||||||
}
|
|
||||||
|
|
||||||
val interruptTargetPrivilege = U(if(interruptDelegators.isEmpty) 3 else interruptDelegators.last.target, 2 bits)
|
|
||||||
for(interruptDelegator <- interruptDelegators){
|
|
||||||
when(!interruptDelegatorHit(interruptDelegator)){
|
|
||||||
interruptTargetPrivilege := interruptDelegator.source
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt.clearWhen(!allowInterrupts)
|
interrupt.clearWhen(!allowInterrupts)
|
||||||
|
|
Loading…
Reference in New Issue