Introduce HAS_SIDE_EFFECT Stageable to solve sensitive instruction squeduling

(uncached DBus TODO)
This commit is contained in:
Dolu1990 2018-10-01 12:13:05 +02:00
parent 7770eefa3b
commit 65a8d84d30
8 changed files with 81 additions and 59 deletions

View File

@ -45,8 +45,7 @@ case class VexRiscvConfig(){
object SRC_LESS_UNSIGNED extends Stageable(Bool)
object DISRUPT_IN_MEMORY_STAGE extends Stageable(Bool)
object DISRUPT_IN_WRITEBACK_STAGE extends Stageable(Bool)
object HAS_SIDE_EFFECT extends Stageable(Bool)
//Formal verification purposes
object FORMAL_HALT extends Stageable(Bool)

View File

@ -104,17 +104,17 @@ object VexRiscvSynthesisBench {
// val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full)
val rtls = List(smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache)
// val rtls = List(smallAndProductive, smallAndProductiveWithICache, fullNoMmuMaxPerf, fullNoMmu, full)
// val rtls = List(smallAndProductive, full)
// val rtls = List(smallestNoCsr)
val targets =/* XilinxStdTargets(
val targets = XilinxStdTargets(
vivadoArtix7Path = "/eda/Xilinx/Vivado/2017.2/bin"
) ++ AlteraStdTargets(
quartusCycloneIVPath = "/eda/intelFPGA_lite/17.0/quartus/bin",
quartusCycloneVPath = "/eda/intelFPGA_lite/17.0/quartus/bin"
) ++ */IcestormStdTargets().take(1)
) ++ IcestormStdTargets().take(1)
// val targets = IcestormStdTargets()
Bench(rtls, targets, "/home/spinalvm/tmp/")
Bench(rtls, targets, "/eda/tmp/")
}
}

View File

@ -90,14 +90,16 @@ class BranchPlugin(earlyBranch : Boolean,
SRC2_CTRL -> Src2CtrlEnum.RS,
SRC_USE_SUB_LESS -> True,
RS1_USE -> True,
RS2_USE -> True
RS2_USE -> True,
HAS_SIDE_EFFECT -> True
)
val jActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.PC_INCREMENT,
SRC2_CTRL -> Src2CtrlEnum.PC,
SRC_USE_SUB_LESS -> False,
REGFILE_WRITE_VALID -> True
REGFILE_WRITE_VALID -> True,
HAS_SIDE_EFFECT -> True
)
import IntAluPlugin._

View File

@ -277,7 +277,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
REGFILE_WRITE_VALID -> True,
ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1,
ALU_CTRL -> AluCtrlEnum.BITWISE
)
) ++ (if(catchIllegalAccess) List(HAS_SIDE_EFFECT -> True) else Nil)
val nonImmediatActions = defaultCsrActions ++ List(
SRC1_CTRL -> Src1CtrlEnum.RS,
@ -299,11 +299,11 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
CSRRWI -> immediatActions,
CSRRSI -> immediatActions,
CSRRCI -> immediatActions,
MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET)),
SRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET))
MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET, HAS_SIDE_EFFECT -> True)),
SRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.XRET, HAS_SIDE_EFFECT -> True))
))
if(wfiGen) decoderService.add(WFI, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.WFI))
if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL))
if(ecallGen) decoderService.add(ECALL, defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL, HAS_SIDE_EFFECT -> True))
val pcManagerService = pipeline.service(classOf[JumpService])
jumpInterface = pcManagerService.createJumpInterface(pipeline.writeBack)
@ -322,7 +322,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
privilege = RegInit(U"11").setName("CsrPlugin_privilege")
if(catchIllegalAccess || ecallGen)
selfException = newExceptionPort(pipeline.writeBack)
selfException = newExceptionPort(pipeline.execute)
allowInterrupts = True
allowException = True
@ -555,31 +555,31 @@ 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
}
exceptionContext := port.payload
}
}
for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){
when(stage.arbitration.isFlushed){
exceptionValids(stageId) := False
}
val previousStage = if(stageId == firstStageIndexWithExceptionPort) stage else stages(stageId-1)
when(!stage.arbitration.isStuck){
exceptionValidsRegs(stageId) := (if(stageId != firstStageIndexWithExceptionPort) exceptionValids(stageId-1) && !previousStage.arbitration.isStuck else False)
}otherwise{
exceptionValidsRegs(stageId) := exceptionValids(stageId)
if(stage != stages.last)
exceptionValidsRegs(stageId) := exceptionValids(stageId)
else
exceptionValidsRegs(stageId) := False
}
if(stage != stages.last) when(stage.arbitration.isFlushed){
exceptionValids(stageId) := False
}
}
if(stageId != 0){
when(exceptionValidsRegs(stageId)){
stages(stageId-1).arbitration.haltByOther := True
}
}
when(exceptionValids.orR){
fetcher.haltIt()
fetcher.flushIt()
}
} else null
@ -627,8 +627,6 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
interruptJump := interrupt && pipelineLiberator.done
val hadException = RegNext(exception) init(False)
exception clearWhen(hadException)
writeBack.arbitration.haltItself setWhen(exception)
val targetPrivilege = CombInit(interruptTargetPrivilege)
@ -641,11 +639,21 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
trapCause := exceptionPortCtrl.exceptionContext.code
}
when(exception || interruptJump){
switch(privilege){
if(supervisorGen) is(1) {
sepc := mepcCaptureStage.input(PC)
}
is(3){
mepc := mepcCaptureStage.input(PC)
}
}
}
when(hadException || (interruptJump && !exception)){
jumpInterface.valid := True
jumpInterface.payload := mtvec
memory.arbitration.flushAll := True
if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionValidsRegs.last := False
switch(targetPrivilege){
if(supervisorGen) is(1) {
@ -654,7 +662,6 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
sstatus.SPP := privilege(0 downto 0)
scause.interrupt := !hadException
scause.exceptionCode := trapCause
sepc := mepcCaptureStage.input(PC)
if (exceptionPortCtrl != null) {
stval := exceptionPortCtrl.exceptionContext.badAddr
}
@ -666,13 +673,36 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
mstatus.MPP := privilege
mcause.interrupt := !hadException
mcause.exceptionCode := trapCause
mepc := mepcCaptureStage.input(PC)
if(exceptionPortCtrl != null) {
mtval := exceptionPortCtrl.exceptionContext.badAddr
}
}
}
}
writeBack plug new Area{
import writeBack._
def previousStage = memory
//Manage MRET / SRET instructions
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
jumpInterface.payload := mepc
jumpInterface.valid := True
previousStage.arbitration.flushAll := True
switch(input(INSTRUCTION)(29 downto 28)){
is(3){
mstatus.MIE := mstatus.MPIE
mstatus.MPP := U"00"
mstatus.MPIE := True
privilege := mstatus.MPP
}
if(supervisorGen) is(1){
sstatus.SIE := sstatus.SPIE
sstatus.SPP := U"0"
sstatus.SPIE := True
privilege := U"0" @@ sstatus.SPP
}
}
}
}
@ -701,12 +731,11 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
}
}
// writeBack plug new Area {
// import writeBack._
// def previousStage = memory
execute plug new Area {
import execute._
def previousStage = decode
val blockedBySideEffects = List(memory, writeBack).map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR
val illegalAccess = arbitration.isValid && input(IS_CSR)
val illegalInstruction = False
@ -718,29 +747,13 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
//Manage MRET / SRET instructions
when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.XRET) {
jumpInterface.payload := mepc
//TODO check MPP value too
when(input(INSTRUCTION)(29 downto 28).asUInt =/= privilege) {
illegalInstruction := True
} otherwise{
jumpInterface.valid := True
previousStage.arbitration.flushAll := True
switch(input(INSTRUCTION)(29 downto 28)){
is(3){
mstatus.MIE := mstatus.MPIE
mstatus.MPP := U"00"
mstatus.MPIE := True
privilege := mstatus.MPP //TODO check MPP value
}
if(supervisorGen) is(1){
sstatus.SIE := sstatus.SPIE
sstatus.SPP := U"0"
sstatus.SPIE := True
privilege := U"0" @@ sstatus.SPP
}
}
}
}
//Manage ECALL instructions
if(ecallGen) when(arbitration.isValid && input(ENV_CTRL) === EnvCtrlEnum.ECALL){
selfException.valid := True
@ -762,11 +775,12 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
val readInstruction = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE)
// arbitration.haltItself setWhen(writeInstruction && !readDataRegValid)
val writeEnable = writeInstruction// && readDataRegValid
val readEnable = readInstruction// && !readDataRegValid
val writeEnable = writeInstruction && ! arbitration.isStuck// && readDataRegValid
val readEnable = readInstruction && ! arbitration.isStuck// && !readDataRegValid
when(arbitration.isValid && input(IS_CSR)) {
output(REGFILE_WRITE_DATA) := readData
arbitration.haltItself setWhen(blockedBySideEffects)
}
//Translation of the csrMapping into real logic

View File

@ -53,7 +53,7 @@ class DBusCachedPlugin(config : DataCacheConfig,
BYPASSABLE_MEMORY_STAGE -> False,
MEMORY_WR -> False,
MEMORY_MANAGMENT -> False
)
) ++ (if(catchSomething) List(HAS_SIDE_EFFECT -> True) else Nil)
val storeActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMS,

View File

@ -211,7 +211,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false, catchAccessFaul
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> Bool(earlyInjection)
)
) ++ (if(catchAccessFault || catchAddressMisaligned) List(HAS_SIDE_EFFECT -> True) else Nil)
val storeActions = stdActions ++ List(
SRC2_CTRL -> Src2CtrlEnum.IMS,

View File

@ -197,11 +197,11 @@ class DebugPlugin(val debugClockDomain : ClockDomain, hardwareBreakpointCount :
decode.insert(DO_EBREAK) := !haltIt && (decode.input(IS_EBREAK) || hardwareBreakpoints.map(hb => hb.valid && hb.pc === (execute.input(PC) >> 1)).foldLeft(False)(_ || _))
when(execute.arbitration.isValid && execute.input(DO_EBREAK)){
iBusFetcher.flushIt()
iBusFetcher.haltIt()
execute.arbitration.haltByOther := True
busReadDataReg := execute.input(PC).asBits
when(List(memory, writeBack).map(_.arbitration.isValid).orR === False){
iBusFetcher.flushIt()
iBusFetcher.haltIt()
execute.arbitration.flushAll := True
haltIt := True
haltedByBreak := True

View File

@ -4,7 +4,6 @@ import vexriscv._
import spinal.core._
import spinal.lib._
class HazardSimplePlugin(bypassExecute : Boolean = false,
bypassMemory: Boolean = false,
bypassWriteBack: Boolean = false,
@ -13,6 +12,14 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
pessimisticWriteRegFile : Boolean = false,
pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] {
import Riscv._
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(HAS_SIDE_EFFECT, False) //TODO implement it in each plugin
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._