rework csr exception/interrupt handeling wip
This commit is contained in:
parent
dd47db9ad0
commit
d73aa9ce00
|
@ -122,7 +122,7 @@ trait Pipeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
|
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
|
||||||
stage.arbitration.isStuckByOthers := stage.arbitration.haltByOther || stages.takeRight(stages.length - stageIndex - 1).map(s => s.arbitration.haltItself/* && !s.arbitration.removeIt*/).foldLeft(False)(_ || _)
|
stage.arbitration.isStuckByOthers := stage.arbitration.haltByOther || stages.takeRight(stages.length - stageIndex - 1).map(s => s.arbitration.isStuck/* && !s.arbitration.removeIt*/).foldLeft(False)(_ || _)
|
||||||
stage.arbitration.isStuck := stage.arbitration.haltItself || stage.arbitration.isStuckByOthers
|
stage.arbitration.isStuck := stage.arbitration.haltItself || stage.arbitration.isStuckByOthers
|
||||||
stage.arbitration.isMoving := !stage.arbitration.isStuck && !stage.arbitration.removeIt
|
stage.arbitration.isMoving := !stage.arbitration.isStuck && !stage.arbitration.removeIt
|
||||||
stage.arbitration.isFiring := stage.arbitration.isValid && !stage.arbitration.isStuck && !stage.arbitration.removeIt
|
stage.arbitration.isFiring := stage.arbitration.isValid && !stage.arbitration.isStuck && !stage.arbitration.removeIt
|
||||||
|
|
|
@ -14,7 +14,7 @@ trait JumpService{
|
||||||
trait IBusFetcher{
|
trait IBusFetcher{
|
||||||
def haltIt() : Unit
|
def haltIt() : Unit
|
||||||
def incoming() : Bool
|
def incoming() : Bool
|
||||||
def nextPc() : (Bool, UInt)
|
def pcValid(stage : Stage) : Bool
|
||||||
def getInjectionPort() : Stream[Bits]
|
def getInjectionPort() : Stream[Bits]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,14 +33,14 @@ object TestsWorkspace {
|
||||||
plugins = List(
|
plugins = List(
|
||||||
new IBusSimplePlugin(
|
new IBusSimplePlugin(
|
||||||
resetVector = 0x80000000l,
|
resetVector = 0x80000000l,
|
||||||
relaxedPcCalculation = true,
|
relaxedPcCalculation = false,
|
||||||
relaxedBusCmdValid = false,
|
relaxedBusCmdValid = false,
|
||||||
prediction = NONE,
|
prediction = NONE,
|
||||||
historyRamSizeLog2 = 10,
|
historyRamSizeLog2 = 10,
|
||||||
catchAccessFault = true,
|
catchAccessFault = true,
|
||||||
compressedGen = false,
|
compressedGen = false,
|
||||||
busLatencyMin = 3,
|
busLatencyMin = 1,
|
||||||
injectorStage = false
|
injectorStage = true
|
||||||
),
|
),
|
||||||
// new IBusCachedPlugin(
|
// new IBusCachedPlugin(
|
||||||
// resetVector = 0x80000000l,
|
// resetVector = 0x80000000l,
|
||||||
|
|
|
@ -101,8 +101,8 @@ object VexRiscvSynthesisBench {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
|
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||||
// val rtls = List(noCacheNoMmuMaxPerf, fullNoMmuMaxPerf)
|
val rtls = List(smallestNoCsr, smallest, smallAndProductive)
|
||||||
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
|
||||||
// val rtls = List(smallAndProductive, full)
|
// val rtls = List(smallAndProductive, full)
|
||||||
|
|
||||||
|
|
|
@ -260,7 +260,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL))
|
if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL))
|
||||||
|
|
||||||
val pcManagerService = pipeline.service(classOf[JumpService])
|
val pcManagerService = pipeline.service(classOf[JumpService])
|
||||||
jumpInterface = pcManagerService.createJumpInterface(pipeline.execute)
|
jumpInterface = pcManagerService.createJumpInterface(pipeline.writeBack)
|
||||||
jumpInterface.valid := False
|
jumpInterface.valid := False
|
||||||
jumpInterface.payload.assignDontCare()
|
jumpInterface.payload.assignDontCare()
|
||||||
|
|
||||||
|
@ -372,15 +372,15 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
minstret := minstret + 1
|
minstret := minstret + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mepcCaptureStage = if(exceptionPortsInfos.nonEmpty) writeBack else decode
|
||||||
|
|
||||||
//Used to make the pipeline empty softly (for interrupts)
|
//Used to make the pipeline empty softly (for interrupts)
|
||||||
val pipelineLiberator = new Area{
|
val pipelineLiberator = new Area{
|
||||||
val enable = False.noBackendCombMerge //Verilator Perf
|
val enable = False.noBackendCombMerge //Verilator Perf
|
||||||
when(enable){
|
when(enable && decode.arbitration.isValid){
|
||||||
decode.arbitration.haltByOther := True
|
decode.arbitration.haltByOther := True
|
||||||
}
|
}
|
||||||
val done = ! List(execute, memory, writeBack).map(_.arbitration.isValid).orR && !fetcher.nextPc()._1
|
val done = !List(execute, memory, writeBack).map(_.arbitration.isValid).orR && fetcher.pcValid(mepcCaptureStage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,11 +392,6 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
val exceptionValidsRegs = Vec(stages.map(s => Reg(Bool).init(False).setPartialName(s.getName()))).allowUnsetRegToAvoidLatch
|
val exceptionValidsRegs = Vec(stages.map(s => Reg(Bool).init(False).setPartialName(s.getName()))).allowUnsetRegToAvoidLatch
|
||||||
val exceptionContext = Reg(ExceptionCause())
|
val exceptionContext = Reg(ExceptionCause())
|
||||||
|
|
||||||
//Assume 2 stages before decode
|
|
||||||
when(exceptionValidsRegs.drop(1).orR) {
|
|
||||||
decode.arbitration.haltByOther := True
|
|
||||||
}
|
|
||||||
|
|
||||||
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
|
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
|
||||||
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
|
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
|
||||||
val stagePort = stagePortsInfos.length match{
|
val stagePort = stagePortsInfos.length match{
|
||||||
|
@ -418,14 +413,15 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
exceptionValids := exceptionValidsRegs
|
exceptionValids := exceptionValidsRegs
|
||||||
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
||||||
when(port.valid) {
|
when(port.valid) {
|
||||||
if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True
|
// if(indexOf(stage) != 0) stages(indexOf(stage) - 1).arbitration.flushAll := True
|
||||||
stage.arbitration.removeIt := True
|
stage.arbitration.removeIt := True
|
||||||
exceptionValids(stageId) := True
|
exceptionValids(stageId) := True
|
||||||
// when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) {
|
when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) {
|
||||||
exceptionContext := port.payload
|
exceptionContext := port.payload
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){
|
for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){
|
||||||
when(stage.arbitration.isFlushed){
|
when(stage.arbitration.isFlushed){
|
||||||
exceptionValids(stageId) := False
|
exceptionValids(stageId) := False
|
||||||
|
@ -436,6 +432,12 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
}otherwise{
|
}otherwise{
|
||||||
exceptionValidsRegs(stageId) := exceptionValids(stageId)
|
exceptionValidsRegs(stageId) := exceptionValids(stageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(stageId != 0){
|
||||||
|
when(exceptionValidsRegs(stageId)){
|
||||||
|
stages(stageId-1).arbitration.haltByOther := True
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
|
@ -489,23 +491,15 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
//Interrupt/Exception entry logic
|
//Interrupt/Exception entry logic
|
||||||
pipelineLiberator.enable setWhen(interrupt)
|
pipelineLiberator.enable setWhen(interrupt)
|
||||||
|
|
||||||
// if(exceptionPortCtrl != null) {
|
|
||||||
// when(exception) {
|
|
||||||
// exceptionPortCtrl.exceptionValidsRegs.foreach(_ := False)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
when(exception || (interrupt && pipelineLiberator.done)){
|
when(exception || (interrupt && pipelineLiberator.done)){
|
||||||
jumpInterface.valid := True
|
jumpInterface.valid := True
|
||||||
jumpInterface.payload := mtvec
|
jumpInterface.payload := mtvec
|
||||||
memory.arbitration.flushAll := True //Mouai
|
memory.arbitration.flushAll := True
|
||||||
|
if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValidsRegs.last := False
|
||||||
mstatus.MIE := False
|
mstatus.MIE := False
|
||||||
mstatus.MPIE := mstatus.MIE
|
mstatus.MPIE := mstatus.MIE
|
||||||
mstatus.MPP := privilege
|
mstatus.MPP := privilege
|
||||||
mepc := exception mux(
|
mepc := mepcCaptureStage.input(PC)
|
||||||
True -> writeBack.input(PC),
|
|
||||||
False -> fetcher.nextPc()._2
|
|
||||||
)
|
|
||||||
|
|
||||||
mcause.interrupt := interrupt
|
mcause.interrupt := interrupt
|
||||||
mcause.exceptionCode := ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7)))
|
mcause.exceptionCode := ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7)))
|
||||||
}
|
}
|
||||||
|
@ -517,12 +511,13 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
|
||||||
|
|
||||||
|
|
||||||
//Manage MRET instructions
|
//Manage MRET instructions
|
||||||
when(memory.input(ENV_CTRL) === EnvCtrlEnum.MRET) {
|
when(execute.arbitration.isValid && execute.input(ENV_CTRL) === EnvCtrlEnum.MRET) {
|
||||||
memory.arbitration.haltItself := writeBack.arbitration.isValid
|
when(memory.arbitration.isValid || writeBack.arbitration.isValid){
|
||||||
when(memory.arbitration.isFiring) {
|
execute.arbitration.haltItself := True
|
||||||
|
} otherwise {
|
||||||
jumpInterface.valid := True
|
jumpInterface.valid := True
|
||||||
jumpInterface.payload := mepc
|
jumpInterface.payload := mepc
|
||||||
execute.arbitration.flushAll := True
|
decode.arbitration.flushAll := True
|
||||||
mstatus.MIE := mstatus.MPIE
|
mstatus.MIE := mstatus.MPIE
|
||||||
privilege := mstatus.MPP
|
privilege := mstatus.MPP
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ import StreamVexPimper._
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
|
|
||||||
|
//TODO val killLastStage = jump.pcLoad.valid || decode.arbitration.isRemoved
|
||||||
|
// DBUSSimple check memory halt execute optimization
|
||||||
|
|
||||||
abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
|
abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
|
||||||
val resetVector : BigInt,
|
val resetVector : BigInt,
|
||||||
val keepPcPlus4 : Boolean,
|
val keepPcPlus4 : Boolean,
|
||||||
|
@ -28,9 +31,8 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
|
||||||
assert(!(cmdToRspStageCount == 1 && !injectorStage))
|
assert(!(cmdToRspStageCount == 1 && !injectorStage))
|
||||||
assert(!(compressedGen && !decodePcGen))
|
assert(!(compressedGen && !decodePcGen))
|
||||||
var fetcherHalt : Bool = null
|
var fetcherHalt : Bool = null
|
||||||
lazy val decodeNextPcValid = Bool //TODO remove me ?
|
lazy val pcValids = Vec(Bool, 4)
|
||||||
lazy val decodeNextPc = UInt(32 bits)
|
def pcValid(stage : Stage) = pcValids(pipeline.indexOf(stage))
|
||||||
def nextPc() = (False, decodeNextPc)
|
|
||||||
var incomingInstruction : Bool = null
|
var incomingInstruction : Bool = null
|
||||||
override def incoming() = incomingInstruction
|
override def incoming() = incomingInstruction
|
||||||
|
|
||||||
|
@ -303,16 +305,29 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
|
||||||
inputBeforeStage
|
inputBeforeStage
|
||||||
})
|
})
|
||||||
|
|
||||||
if (decodePcGen) {
|
|
||||||
decodeNextPcValid := True
|
|
||||||
decodeNextPc := decodePc.pcReg
|
|
||||||
} else {
|
|
||||||
val lastStageStream = if (injectorStage) inputBeforeStage
|
|
||||||
else if (cmdToRspStageCount > 1) iBusRsp.inputPipeline(cmdToRspStageCount - 2)
|
|
||||||
else throw new Exception("Fetch should at least have two stages")
|
|
||||||
|
|
||||||
decodeNextPcValid := RegNext(lastStageStream.isStall)
|
def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = {
|
||||||
decodeNextPc := decode.input(PC)
|
stucks.scanLeft(input)((i, stuck) => {
|
||||||
|
val reg = RegInit(False)
|
||||||
|
if(!relaxedInput) when(flush) {
|
||||||
|
reg := False
|
||||||
|
}
|
||||||
|
when(!stuck) {
|
||||||
|
reg := i
|
||||||
|
}
|
||||||
|
if(relaxedInput || i != input) when(flush) {
|
||||||
|
reg := False
|
||||||
|
}
|
||||||
|
reg
|
||||||
|
}).tail
|
||||||
|
}
|
||||||
|
|
||||||
|
val nextPcCalc = if (decodePcGen) {
|
||||||
|
val valids = pcUpdatedGen(True, List(execute, memory, writeBack).map(_.arbitration.isStuck), true)
|
||||||
|
pcValids := Vec(valids.takeRight(4))
|
||||||
|
} else new Area{
|
||||||
|
val valids = pcUpdatedGen(True, iBusRsp.inputPipeline.map(!_.ready) ++ (if (injectorStage) List(!decodeInput.ready) else Nil) ++ List(execute, memory, writeBack).map(_.arbitration.isStuck), relaxedPcCalculation)
|
||||||
|
pcValids := Vec(valids.takeRight(4))
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeInput.ready := !decode.arbitration.isStuck
|
decodeInput.ready := !decode.arbitration.isStuck
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
*.regTraceRef
|
*.regTraceRef
|
||||||
|
/freertos.gtkw
|
||||||
|
|
|
@ -1734,7 +1734,7 @@ string riscvTestDiv[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
string freeRtosTests[] = {
|
string freeRtosTests[] = {
|
||||||
"AltBlock", "AltQTest", "AltPollQ", "blocktim", "countsem", "dead", "EventGroupsDemo", "flop", "integer", "QPeek",
|
"AltQTest", "AltBlock", "AltPollQ", "blocktim", "countsem", "dead", "EventGroupsDemo", "flop", "integer", "QPeek",
|
||||||
"QueueSet", "recmutex", "semtest", "TaskNotify", "BlockQ", "crhook", "dynamic",
|
"QueueSet", "recmutex", "semtest", "TaskNotify", "BlockQ", "crhook", "dynamic",
|
||||||
"GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1"
|
"GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1"
|
||||||
//"flop", "sp_flop" // <- Simple test
|
//"flop", "sp_flop" // <- Simple test
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
.word 0x3c12083
|
.word 0x34129073
|
||||||
|
|
Loading…
Reference in New Issue