Add Arbitration.flushIt

Add ExceptionService
Add unremovableStage
Add MachineCsr (untested)
This commit is contained in:
Charles Papon 2017-03-21 18:40:50 +01:00
parent c49373f3d1
commit e9d3977737
11 changed files with 201 additions and 15 deletions

View file

@ -1,7 +1,8 @@
package SpinalRiscv
import SpinalRiscv.Plugin.Plugin
import SpinalRiscv.Plugin._
import spinal.core._
import spinal.lib._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
@ -11,6 +12,7 @@ trait Pipeline {
type T <: Pipeline
val plugins = ArrayBuffer[Plugin[T]]()
var stages = ArrayBuffer[Stage]()
var unremovableStages = mutable.Set[Stage]()
// val services = ArrayBuffer[Any]()
def indexOf(stage : Stage) = stages.indexOf(stage)
@ -99,6 +101,14 @@ trait Pipeline {
}
//Arbitration
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)) {
if(!unremovableStages.contains(stage))
stage.arbitration.removeIt setWhen stages.drop(stageIndex).map(_.arbitration.flushIt).orR
else
assert(stage.arbitration.removeIt === False,"removeIt should never be asserted on this stage")
}
for(stageIndex <- 0 until stages.length; stage = stages(stageIndex)){
stage.arbitration.isStuckByOthers := stages.takeRight(stages.length - stageIndex - 1).map(s => s.arbitration.haltIt && !s.arbitration.removeIt).foldLeft(False)(_ || _)
stage.arbitration.isStuck := stage.arbitration.haltIt || stage.arbitration.isStuckByOthers

View file

@ -159,7 +159,7 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
predictionJumpInterface.valid := input(PREDICTION_HAD_BRANCHED) && arbitration.isFiring //TODO OH Doublon de priorité
predictionJumpInterface.payload := input(PC) + ((input(BRANCH_CTRL) === BranchCtrlEnum.JAL) ? imm.j_sext | imm.b_sext).asUInt
when(predictionJumpInterface.valid) {
fetch.arbitration.removeIt := True
fetch.arbitration.flushIt := True
}
}
@ -209,9 +209,10 @@ class BranchPlugin(earlyBranch : Boolean,prediction : BranchPrediction,historyRa
jumpInterface.payload := input(BRANCH_CALC)
when(jumpInterface.valid) {
fetch.arbitration.removeIt := True
decode.arbitration.removeIt := True
if(!earlyBranch) execute.arbitration.removeIt := True
stages(indexOf(branchStage) - 1).arbitration.flushIt := True
// fetch.arbitration.removeIt := True
// decode.arbitration.removeIt := True
// if(!earlyBranch) execute.arbitration.removeIt := True
}
}

View file

@ -24,7 +24,7 @@ class IBusSimplePlugin(interfaceKeepData : Boolean) extends Plugin[VexRiscv]{
//Emit iCmd request
require(interfaceKeepData)
iCmd = master(Stream(IBusSimpleCmd())).setName("iCmd")
iCmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
iCmd.valid := prefetch.arbitration.isFiring //prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
iCmd.pc := prefetch.output(PC)
prefetch.arbitration.haltIt setWhen(!iCmd.ready)

View file

@ -0,0 +1,148 @@
package SpinalRiscv.Plugin
import spinal.core._
import spinal.lib._
import SpinalRiscv._
import SpinalRiscv.Riscv._
import scala.collection.mutable.ArrayBuffer
/**
* Created by spinalvm on 21.03.17.
*/
case class ExceptionPortInfo(port : Flow[UInt],stage : Stage)
case class MachineCsrConfig()
class MachineCsr extends Plugin[VexRiscv] with ExceptionService{
val exceptionPortsInfos = ArrayBuffer[ExceptionPortInfo]()
def exceptionCodeWidth = 4
override def newExceptionPort(stage : Stage) = {
val interface = Flow(UInt(exceptionCodeWidth bits))
exceptionPortsInfos += ExceptionPortInfo(interface,stage)
interface
}
var jumpInterface : Flow[UInt] = null
object EnvCtrlEnum extends SpinalEnum(binarySequential){
val NONE, EBREAK, ECALL, MRET = newElement()
}
object ENV_CTRL extends Stageable(EnvCtrlEnum())
object EXCEPTION extends Stageable(Bool)
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
val defaultEnv = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True
)
val defaultActions = List[(Stageable[_ <: BaseType],Any)](
LEGAL_INSTRUCTION -> True,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> False
)
val nonImmediatActions = defaultActions ++ List(
SRC1_CTRL -> Src1CtrlEnum.RS
)
val immediatActions = defaultActions
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(ENV_CTRL, EnvCtrlEnum.NONE)
decoderService.add(List(
CSRRW -> nonImmediatActions,
CSRRS -> nonImmediatActions,
CSRRC -> nonImmediatActions,
CSRRWI -> immediatActions,
CSRRSI -> immediatActions,
CSRRCI -> immediatActions,
ECALL -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.ECALL)),
EBREAK -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.EBREAK)),
MRET -> (defaultEnv ++ List(ENV_CTRL -> EnvCtrlEnum.MRET))
))
pipeline.fetch.insert(EXCEPTION) := False
val pcManagerService = pipeline.service(classOf[JumpService])
jumpInterface = pcManagerService.createJumpInterface(pipeline.execute)
jumpInterface.valid := False
jumpInterface.payload.assignDontCare()
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
val mtvec = UInt(32 bits)
val mepc = Reg(UInt(32 bits))
val mstatus = new Area{
val MIE, MPIE = Reg(Bool) init(False)
}
val pipelineLiberator = new Area{
val enable = False
decode.arbitration.haltIt setWhen(enable)
val done = ! List(fetch, decode, execute, memory, writeBack).map(_.arbitration.isValid).orR
}
val exceptionPortCtrl = new Area{
val pipelineHasException = List(fetch, decode, execute, memory, writeBack).map(s => s.arbitration.isValid && s.input(EXCEPTION)).orR
decode.arbitration.haltIt setWhen(pipelineHasException)
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s)
val stagePort = stagePortsInfos.length match{
case 1 => stagePortsInfos.head.port
case _ => {
val groupedPort = Flow(UInt(exceptionCodeWidth bits))
val valids = stagePortsInfos.map(_.port.valid)
val codes = stagePortsInfos.map(_.port.payload)
groupedPort.valid := valids.orR
groupedPort.payload := MuxOH(stagePortsInfos.map(_.port.valid), codes)
groupedPort
}
}
ExceptionPortInfo(stagePort,s)
})
val sortedByStage = groupedByStage.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage){
when(port.valid){
stages(indexOf(stage)).arbitration.flushIt := True
stage.input(EXCEPTION) := True
}
}
}
val interrupt = False
val exception = writeBack.arbitration.isValid && writeBack.input(EXCEPTION)
when(mstatus.MIE){
pipelineLiberator.enable := True
when(exception || (interrupt && pipelineLiberator.done)){
jumpInterface.valid := True
jumpInterface.payload := mtvec
mstatus.MIE := False
mstatus.MPIE := mstatus.MIE
mepc := exception ? writeBack.input(PC) | prefetch.input(PC_CALC_WITHOUT_JUMP)
}
}
when(memory.arbitration.isFiring && memory.input(ENV_CTRL) === EnvCtrlEnum.MRET){
jumpInterface.valid := True
jumpInterface.payload := mepc
mstatus.MIE := mstatus.MPIE
}
}
}

View file

@ -18,6 +18,10 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
interface
}
override def setup(pipeline: VexRiscv): Unit = {
pipeline.unremovableStages += pipeline.prefetch
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline.config._
@ -31,7 +35,7 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
//PC calculation without Jump
val pcReg = Reg(UInt(pcWidth bits)) init(resetVector) addAttribute("verilator public")
val inc = RegInit(False)
val pc = if(fastPcCalculation){
val pcBeforeJumps = if(fastPcCalculation){
val pcPlus4 = pcReg + U(4)
pcPlus4.addAttribute("keep")
Mux(inc,pcPlus4,pcReg)
@ -39,6 +43,10 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
pcReg + Mux[UInt](inc,4,0)
}
insert(PC_CALC_WITHOUT_JUMP) := pcBeforeJumps
val pc = UInt(pcWidth bits)
pc := input(PC_CALC_WITHOUT_JUMP)
val samplePcNext = False
//JumpService hardware implementation
@ -48,8 +56,8 @@ class PcManagerSimplePlugin(resetVector : BigInt,fastPcCalculation : Boolean) ex
val pcs = sortedByStage.map(_.interface.payload)
val pcLoad = Flow(UInt(pcWidth bits))
pcLoad.valid := jumpInfos.foldLeft(False)(_ || _.interface.valid)
pcLoad.payload := MuxOH(valids, pcs)
pcLoad.valid := jumpInfos.map(_.interface.valid).orR
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
//application of the selected jump request
when(pcLoad.valid) {

View file

@ -70,5 +70,16 @@ object Riscv{
def AUIPC = M"-------------------------0010111"
def MULX = M"0000001----------0-------0110011"
def DIVX = M"0000001----------1-------0110011"
def DIVX = M"0000001----------1-------0110011"
def CSRRW = M"-----------------001-----1110011"
def CSRRS = M"-----------------010-----1110011"
def CSRRC = M"-----------------011-----1110011"
def CSRRWI = M"-----------------101-----1110011"
def CSRRSI = M"-----------------110-----1110011"
def CSRRCI = M"-----------------111-----1110011"
def ECALL = M"00000000000000000000000001110011"
def EBREAK = M"00000000000100000000000001110011"
def MRET = M"00110000001000000000000001110011"
}

View file

@ -11,4 +11,8 @@ trait DecoderService{
def add(key : MaskedLiteral,values : Seq[(Stageable[_ <: BaseType],Any)])
def add(encoding :Seq[(MaskedLiteral,Seq[(Stageable[_ <: BaseType],Any)])])
def addDefault(key : Stageable[_ <: BaseType], value : Any)
}
trait ExceptionService{
def newExceptionPort(stage : Stage) : Flow[UInt]
}

View file

@ -47,6 +47,7 @@ class Stage() extends Area{
val arbitration = new Area{
val haltIt = False
val removeIt = False
val flushIt = False
val isValid = RegInit(False)
val isStuck = Bool
val isStuckByOthers = Bool

View file

@ -40,12 +40,12 @@ object TopLevel {
new FullBarrielShifterPlugin,
// new LightShifterPlugin,
new DBusSimplePlugin,
new HazardSimplePlugin(false, true, false, true),
// new HazardSimplePlugin(true, true, true, true),
// new HazardSimplePlugin(false, true, false, true),
new HazardSimplePlugin(true, true, true, true),
// new HazardSimplePlugin(false, false, false, false),
new MulPlugin,
new DivPlugin,
new BranchPlugin(false, NONE)
new BranchPlugin(false, DYNAMIC)
)
val toplevel = new VexRiscv(config)

View file

@ -17,6 +17,7 @@ case class VexRiscvConfig(pcWidth : Int){
object REG2_USE extends Stageable(Bool)
object RESULT extends Stageable(UInt(32 bits))
object PC extends Stageable(UInt(pcWidth bits))
object PC_CALC_WITHOUT_JUMP extends Stageable(UInt(pcWidth bits))
object INSTRUCTION extends Stageable(Bits(32 bits))
object LEGAL_INSTRUCTION extends Stageable(Bool)
object REGFILE_WRITE_VALID extends Stageable(Bool)

View file

@ -522,11 +522,13 @@ int main(int argc, char **argv, char **env) {
}
uint64_t duration = timer_end(startedAt);
cout << endl << "****************************************************************" << endl;
cout << "Had simulate " << Workspace::cycles << " clock cycles in " << duration*1e-9 << " s (" << Workspace::cycles / (duration*1e-9) << " Khz)" << endl;
if(successCounter == testsCounter)
cout << "Success " << successCounter << "/" << testsCounter << endl;
cout << "SUCCESS " << successCounter << "/" << testsCounter << endl;
else
cout << "Failure " << testsCounter - successCounter << "/" << testsCounter << endl;
cout<< "FAILURE " << testsCounter - successCounter << "/" << testsCounter << endl;
cout << "****************************************************************" << endl << endl;
exit(0);