From d73aa9ce007ae5cf8f0682e0bd33757fec976d88 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Sun, 24 Jun 2018 00:14:55 +0200 Subject: [PATCH] rework csr exception/interrupt handeling wip --- src/main/scala/vexriscv/Pipeline.scala | 2 +- src/main/scala/vexriscv/Services.scala | 2 +- src/main/scala/vexriscv/TestsWorkspace.scala | 6 +-- .../scala/vexriscv/demo/SynthesisBench.scala | 4 +- .../scala/vexriscv/plugin/CsrPlugin.scala | 51 +++++++++---------- src/main/scala/vexriscv/plugin/Fetcher.scala | 39 +++++++++----- src/test/cpp/regression/.gitignore | 1 + src/test/cpp/regression/main.cpp | 2 +- src/test/python/tool/disasm.s | 2 +- 9 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/main/scala/vexriscv/Pipeline.scala b/src/main/scala/vexriscv/Pipeline.scala index a28cf6d..f0466c5 100644 --- a/src/main/scala/vexriscv/Pipeline.scala +++ b/src/main/scala/vexriscv/Pipeline.scala @@ -122,7 +122,7 @@ trait Pipeline { } 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.isMoving := !stage.arbitration.isStuck && !stage.arbitration.removeIt stage.arbitration.isFiring := stage.arbitration.isValid && !stage.arbitration.isStuck && !stage.arbitration.removeIt diff --git a/src/main/scala/vexriscv/Services.scala b/src/main/scala/vexriscv/Services.scala index 44e9a80..411df57 100644 --- a/src/main/scala/vexriscv/Services.scala +++ b/src/main/scala/vexriscv/Services.scala @@ -14,7 +14,7 @@ trait JumpService{ trait IBusFetcher{ def haltIt() : Unit def incoming() : Bool - def nextPc() : (Bool, UInt) + def pcValid(stage : Stage) : Bool def getInjectionPort() : Stream[Bits] } diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 575ccaa..dbe2260 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -33,14 +33,14 @@ object TestsWorkspace { plugins = List( new IBusSimplePlugin( resetVector = 0x80000000l, - relaxedPcCalculation = true, + relaxedPcCalculation = false, relaxedBusCmdValid = false, prediction = NONE, historyRamSizeLog2 = 10, catchAccessFault = true, compressedGen = false, - busLatencyMin = 3, - injectorStage = false + busLatencyMin = 1, + injectorStage = true ), // new IBusCachedPlugin( // resetVector = 0x80000000l, diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index 77275b5..748c416 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -101,8 +101,8 @@ object VexRiscvSynthesisBench { } - val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full) -// val rtls = List(noCacheNoMmuMaxPerf, fullNoMmuMaxPerf) +// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full) + val rtls = List(smallestNoCsr, smallest, smallAndProductive) // val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full) // val rtls = List(smallAndProductive, full) diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index dff7e5b..1b16a8b 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -260,7 +260,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL)) val pcManagerService = pipeline.service(classOf[JumpService]) - jumpInterface = pcManagerService.createJumpInterface(pipeline.execute) + jumpInterface = pcManagerService.createJumpInterface(pipeline.writeBack) jumpInterface.valid := False jumpInterface.payload.assignDontCare() @@ -372,15 +372,15 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio minstret := minstret + 1 } - + val mepcCaptureStage = if(exceptionPortsInfos.nonEmpty) writeBack else decode //Used to make the pipeline empty softly (for interrupts) val pipelineLiberator = new Area{ val enable = False.noBackendCombMerge //Verilator Perf - when(enable){ + when(enable && decode.arbitration.isValid){ 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 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 stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority) val stagePort = stagePortsInfos.length match{ @@ -418,14 +413,15 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio exceptionValids := exceptionValidsRegs for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) { 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 exceptionValids(stageId) := True -// when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) { - exceptionContext := port.payload -// } + when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) { + exceptionContext := port.payload + } } } + for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){ when(stage.arbitration.isFlushed){ exceptionValids(stageId) := False @@ -436,6 +432,12 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio }otherwise{ exceptionValidsRegs(stageId) := exceptionValids(stageId) } + + if(stageId != 0){ + when(exceptionValidsRegs(stageId)){ + stages(stageId-1).arbitration.haltByOther := True + } + } } } else null @@ -489,23 +491,15 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio //Interrupt/Exception entry logic pipelineLiberator.enable setWhen(interrupt) -// if(exceptionPortCtrl != null) { -// when(exception) { -// exceptionPortCtrl.exceptionValidsRegs.foreach(_ := False) -// } -// } when(exception || (interrupt && pipelineLiberator.done)){ jumpInterface.valid := True jumpInterface.payload := mtvec - memory.arbitration.flushAll := True //Mouai + memory.arbitration.flushAll := True + if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValidsRegs.last := False mstatus.MIE := False mstatus.MPIE := mstatus.MIE mstatus.MPP := privilege - mepc := exception mux( - True -> writeBack.input(PC), - False -> fetcher.nextPc()._2 - ) - + mepc := mepcCaptureStage.input(PC) mcause.interrupt := interrupt 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 - when(memory.input(ENV_CTRL) === EnvCtrlEnum.MRET) { - memory.arbitration.haltItself := writeBack.arbitration.isValid - when(memory.arbitration.isFiring) { + when(execute.arbitration.isValid && execute.input(ENV_CTRL) === EnvCtrlEnum.MRET) { + when(memory.arbitration.isValid || writeBack.arbitration.isValid){ + execute.arbitration.haltItself := True + } otherwise { jumpInterface.valid := True jumpInterface.payload := mepc - execute.arbitration.flushAll := True + decode.arbitration.flushAll := True mstatus.MIE := mstatus.MPIE privilege := mstatus.MPP } diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index a47e3b1..864f846 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -8,6 +8,9 @@ import StreamVexPimper._ 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, val resetVector : BigInt, val keepPcPlus4 : Boolean, @@ -28,9 +31,8 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, assert(!(cmdToRspStageCount == 1 && !injectorStage)) assert(!(compressedGen && !decodePcGen)) var fetcherHalt : Bool = null - lazy val decodeNextPcValid = Bool //TODO remove me ? - lazy val decodeNextPc = UInt(32 bits) - def nextPc() = (False, decodeNextPc) + lazy val pcValids = Vec(Bool, 4) + def pcValid(stage : Stage) = pcValids(pipeline.indexOf(stage)) var incomingInstruction : Bool = null override def incoming() = incomingInstruction @@ -303,16 +305,29 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean, 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) - decodeNextPc := decode.input(PC) + def pcUpdatedGen(input : Bool, stucks : Seq[Bool], relaxedInput : Boolean) : Seq[Bool] = { + 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 diff --git a/src/test/cpp/regression/.gitignore b/src/test/cpp/regression/.gitignore index df54a57..b37f733 100644 --- a/src/test/cpp/regression/.gitignore +++ b/src/test/cpp/regression/.gitignore @@ -1 +1,2 @@ *.regTraceRef +/freertos.gtkw diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index f0fd4d7..653a493 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -1734,7 +1734,7 @@ string riscvTestDiv[] = { }; 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", "GenQTest", "PollQ", "QueueOverwrite", "QueueSetPolling", "sp_flop", "test1" //"flop", "sp_flop" // <- Simple test diff --git a/src/test/python/tool/disasm.s b/src/test/python/tool/disasm.s index 257b105..78db665 100644 --- a/src/test/python/tool/disasm.s +++ b/src/test/python/tool/disasm.s @@ -1 +1 @@ -.word 0x3c12083 +.word 0x34129073