iBusSimplePlugin done, DebugPlugin need minor rework

This commit is contained in:
Dolu1990 2018-03-18 13:21:21 +01:00
parent 64022557bf
commit ac74fb9ce8
13 changed files with 939 additions and 735 deletions

View file

@ -31,33 +31,33 @@ object TestsWorkspace {
SpinalConfig(mergeAsyncProcess = false).generateVerilog {
val configFull = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(
resetVector = 0x80000000l,
relaxedPcCalculation = false
),
// new IBusSimplePlugin(
// interfaceKeepData = false,
// catchAccessFault = true
// new PcManagerSimplePlugin(
// resetVector = 0x80000000l,
// relaxedPcCalculation = false
// ),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 1024*16,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = true,
catchAccessFault = true,
catchMemoryTranslationMiss = true,
asyncTagMemory = false,
twoCycleRam = false
),
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 4
)
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = true
),
// new DBusSimplePlugin(
// new IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 1024*16,
// bytePerLine = 32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = true,
// catchAccessFault = true,
// catchMemoryTranslationMiss = true,
// asyncTagMemory = false,
// twoCycleRam = false
// ),
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 4
// )
// ),
//// new DBusSimplePlugin(
// catchAddressMisaligned = true,
// catchAccessFault = true,
// earlyInjection = false
@ -122,11 +122,11 @@ object TestsWorkspace {
),
// new DivPlugin,
new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
// new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin(
earlyBranch = true,
catchAddressMisaligned = true,
prediction = DYNAMIC_TARGET,
prediction = NONE,
historyRamSizeLog2 = 8
),
new YamlPlugin("cpu0.yaml")

View file

@ -58,8 +58,8 @@ class VexRiscv(val config : VexRiscvConfig) extends Component with Pipeline{
type T = VexRiscv
import config._
stages ++= List.fill(6)(new Stage())
val prefetch :: fetch :: decode :: execute :: memory :: writeBack :: Nil = stages.toList
stages ++= List.fill(4)(new Stage())
val /*prefetch :: fetch :: */decode :: execute :: memory :: writeBack :: Nil = stages.toList
plugins ++= config.plugins
//regression usage

View file

@ -11,10 +11,10 @@ object GenSmallestNoCsr extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
relaxedPcCalculation = false
),
// new PcManagerSimplePlugin(
// resetVector = 0x00000000l,
// relaxedPcCalculation = false
// ),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = false

View file

@ -64,7 +64,7 @@ class MuraxMasterArbiter(simpleBusConfig : SimpleBusConfig) extends Component{
io.masterBus.cmd.valid := False
}
io.iBus.rsp.ready := io.masterBus.rsp.valid && !rspTarget
io.iBus.rsp.valid := io.masterBus.rsp.valid && !rspTarget
io.iBus.rsp.inst := io.masterBus.rsp.data
io.iBus.rsp.error := False

View file

@ -70,8 +70,8 @@ class BranchPlugin(earlyBranch : Boolean,
prediction match {
case NONE =>
case STATIC | DYNAMIC => predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode)
case DYNAMIC_TARGET => predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.fetch)
// case STATIC | DYNAMIC => predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.decode)
// case DYNAMIC_TARGET => predictionJumpInterface = pcManagerService.createJumpInterface(pipeline.fetch)
}
if (catchAddressMisaligned) {
@ -79,17 +79,17 @@ class BranchPlugin(earlyBranch : Boolean,
branchExceptionPort = exceptionService.newExceptionPort(if (earlyBranch) pipeline.execute else pipeline.memory)
prediction match {
case NONE =>
case STATIC | DYNAMIC => predictionExceptionPort = exceptionService.newExceptionPort(pipeline.decode)
case DYNAMIC_TARGET =>
// case STATIC | DYNAMIC => predictionExceptionPort = exceptionService.newExceptionPort(pipeline.decode)
// case DYNAMIC_TARGET =>
}
}
}
override def build(pipeline: VexRiscv): Unit = prediction match {
case `NONE` => buildWithoutPrediction(pipeline)
case `STATIC` => buildWithPrediction(pipeline)
case `DYNAMIC` => buildWithPrediction(pipeline)
case `DYNAMIC_TARGET` => buildDynamicTargetPrediction(pipeline)
// case `STATIC` => buildWithPrediction(pipeline)
// case `DYNAMIC` => buildWithPrediction(pipeline)
// case `DYNAMIC_TARGET` => buildDynamicTargetPrediction(pipeline)
}
def buildWithoutPrediction(pipeline: VexRiscv): Unit = {
@ -147,262 +147,262 @@ class BranchPlugin(earlyBranch : Boolean,
}
def buildWithPrediction(pipeline: VexRiscv): Unit = {
case class BranchPredictorLine() extends Bundle{
val history = SInt(historyWidth bits)
}
object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
object HISTORY_LINE extends Stageable(BranchPredictorLine())
import pipeline._
import pipeline.config._
val historyCache = if(prediction == DYNAMIC) Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) setName("branchCache") else null
val historyCacheWrite = if(prediction == DYNAMIC) historyCache.writePort else null
//Read historyCache
if(prediction == DYNAMIC) fetch plug new Area{
val readAddress = prefetch.output(PC)(2, historyRamSizeLog2 bits)
fetch.insert(HISTORY_LINE) := historyCache.readSync(readAddress,!prefetch.arbitration.isStuckByOthers)
//WriteFirst bypass TODO long combinatorial path
// val writePortReg = RegNext(historyCacheWrite)
// when(writePortReg.valid && writePortReg.address === readAddress){
// fetch.insert(HISTORY_LINE) := writePortReg.data
// def buildWithPrediction(pipeline: VexRiscv): Unit = {
// case class BranchPredictorLine() extends Bundle{
// val history = SInt(historyWidth bits)
// }
//
// object PREDICTION_HAD_BRANCHED extends Stageable(Bool)
// object HISTORY_LINE extends Stageable(BranchPredictorLine())
//
// import pipeline._
// import pipeline.config._
//
// val historyCache = if(prediction == DYNAMIC) Mem(BranchPredictorLine(), 1 << historyRamSizeLog2) setName("branchCache") else null
// val historyCacheWrite = if(prediction == DYNAMIC) historyCache.writePort else null
//
// //Read historyCache
// if(prediction == DYNAMIC) fetch plug new Area{
// val readAddress = prefetch.output(PC)(2, historyRamSizeLog2 bits)
// fetch.insert(HISTORY_LINE) := historyCache.readSync(readAddress,!prefetch.arbitration.isStuckByOthers)
//
// //WriteFirst bypass TODO long combinatorial path
//// val writePortReg = RegNext(historyCacheWrite)
//// when(writePortReg.valid && writePortReg.address === readAddress){
//// fetch.insert(HISTORY_LINE) := writePortReg.data
//// }
// }
//
// //Branch JAL, predict Bxx and branch it
// decode plug new Area{
// import decode._
// val imm = IMM(input(INSTRUCTION))
//
// val conditionalBranchPrediction = (prediction match {
// case `STATIC` => imm.b_sext.msb
// case `DYNAMIC` => input(HISTORY_LINE).history.msb
// })
// insert(PREDICTION_HAD_BRANCHED) := input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction)
//
// 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.flushAll := True
// }
}
//Branch JAL, predict Bxx and branch it
decode plug new Area{
import decode._
val imm = IMM(input(INSTRUCTION))
val conditionalBranchPrediction = (prediction match {
case `STATIC` => imm.b_sext.msb
case `DYNAMIC` => input(HISTORY_LINE).history.msb
})
insert(PREDICTION_HAD_BRANCHED) := input(BRANCH_CTRL) === BranchCtrlEnum.JAL || (input(BRANCH_CTRL) === BranchCtrlEnum.B && conditionalBranchPrediction)
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.flushAll := True
}
if(catchAddressMisaligned) {
predictionExceptionPort.valid := input(INSTRUCTION_READY) && input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0
predictionExceptionPort.code := 0
predictionExceptionPort.badAddr := predictionJumpInterface.payload
}
}
//Do real branch calculation
execute plug new Area {
import execute._
val less = input(SRC_LESS)
val eq = input(SRC1) === input(SRC2)
insert(BRANCH_COND_RESULT) := input(BRANCH_CTRL).mux(
BranchCtrlEnum.INC -> False,
BranchCtrlEnum.JAL -> True,
BranchCtrlEnum.JALR -> True,
BranchCtrlEnum.B -> input(INSTRUCTION)(14 downto 12).mux(
B"000" -> eq ,
B"001" -> !eq ,
M"1-1" -> !less,
default -> less
)
)
insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= insert(BRANCH_COND_RESULT)
//Calculation of the branch target / correction
val imm = IMM(input(INSTRUCTION))
val branch_src1,branch_src2 = UInt(32 bits)
switch(input(BRANCH_CTRL)){
is(BranchCtrlEnum.JALR){
branch_src1 := input(RS1).asUInt
branch_src2 := imm.i_sext.asUInt
}
default{
branch_src1 := input(PC)
branch_src2 := (input(PREDICTION_HAD_BRANCHED) ? B(4) | imm.b_sext).asUInt
}
}
val branchAdder = branch_src1 + branch_src2
insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
}
// branch JALR or JAL/Bxx prediction miss corrections
val branchStage = if(earlyBranch) execute else memory
branchStage plug new Area {
import branchStage._
jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
jumpInterface.payload := input(BRANCH_CALC)
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
if(catchAddressMisaligned) {
branchExceptionPort.valid := input(INSTRUCTION_READY) && arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
branchExceptionPort.code := 0
branchExceptionPort.badAddr := jumpInterface.payload
}
}
//Update historyCache
if(prediction == DYNAMIC) branchStage plug new Area {
import branchStage._
val newHistory = input(HISTORY_LINE).history.resize(historyWidth + 1) + Mux(input(BRANCH_COND_RESULT),S(-1),S(1))
val noOverflow = newHistory(newHistory.high downto newHistory.high - 1) =/= S"10" && newHistory(newHistory.high downto newHistory.high - 1) =/= S"01"
historyCacheWrite.valid := arbitration.isFiring && input(BRANCH_CTRL) === BranchCtrlEnum.B && noOverflow
historyCacheWrite.address := input(PC)(2, historyRamSizeLog2 bits)
historyCacheWrite.data.history := newHistory.resized
}
}
//
// if(catchAddressMisaligned) {
// predictionExceptionPort.valid := input(INSTRUCTION_READY) && input(PREDICTION_HAD_BRANCHED) && arbitration.isValid && predictionJumpInterface.payload(1 downto 0) =/= 0
// predictionExceptionPort.code := 0
// predictionExceptionPort.badAddr := predictionJumpInterface.payload
// }
// }
//
// //Do real branch calculation
// execute plug new Area {
// import execute._
//
// val less = input(SRC_LESS)
// val eq = input(SRC1) === input(SRC2)
//
// insert(BRANCH_COND_RESULT) := input(BRANCH_CTRL).mux(
// BranchCtrlEnum.INC -> False,
// BranchCtrlEnum.JAL -> True,
// BranchCtrlEnum.JALR -> True,
// BranchCtrlEnum.B -> input(INSTRUCTION)(14 downto 12).mux(
// B"000" -> eq ,
// B"001" -> !eq ,
// M"1-1" -> !less,
// default -> less
// )
// )
//
// insert(BRANCH_DO) := input(PREDICTION_HAD_BRANCHED) =/= insert(BRANCH_COND_RESULT)
//
// //Calculation of the branch target / correction
// val imm = IMM(input(INSTRUCTION))
// val branch_src1,branch_src2 = UInt(32 bits)
// switch(input(BRANCH_CTRL)){
// is(BranchCtrlEnum.JALR){
// branch_src1 := input(RS1).asUInt
// branch_src2 := imm.i_sext.asUInt
// }
// default{
// branch_src1 := input(PC)
// branch_src2 := (input(PREDICTION_HAD_BRANCHED) ? B(4) | imm.b_sext).asUInt
// }
// }
// val branchAdder = branch_src1 + branch_src2
// insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
// }
//
//
// // branch JALR or JAL/Bxx prediction miss corrections
// val branchStage = if(earlyBranch) execute else memory
// branchStage plug new Area {
// import branchStage._
// jumpInterface.valid := input(BRANCH_DO) && arbitration.isFiring
// jumpInterface.payload := input(BRANCH_CALC)
//
// when(jumpInterface.valid) {
// stages(indexOf(branchStage) - 1).arbitration.flushAll := True
// }
//
// if(catchAddressMisaligned) {
// branchExceptionPort.valid := input(INSTRUCTION_READY) && arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
// branchExceptionPort.code := 0
// branchExceptionPort.badAddr := jumpInterface.payload
// }
// }
//
// //Update historyCache
// if(prediction == DYNAMIC) branchStage plug new Area {
// import branchStage._
// val newHistory = input(HISTORY_LINE).history.resize(historyWidth + 1) + Mux(input(BRANCH_COND_RESULT),S(-1),S(1))
// val noOverflow = newHistory(newHistory.high downto newHistory.high - 1) =/= S"10" && newHistory(newHistory.high downto newHistory.high - 1) =/= S"01"
//
// historyCacheWrite.valid := arbitration.isFiring && input(BRANCH_CTRL) === BranchCtrlEnum.B && noOverflow
// historyCacheWrite.address := input(PC)(2, historyRamSizeLog2 bits)
// historyCacheWrite.data.history := newHistory.resized
// }
// }
def buildDynamicTargetPrediction(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
case class BranchPredictorLine() extends Bundle{
val source = Bits(31 - historyRamSizeLog2 bits)
val confidence = UInt(2 bits)
val target = UInt(32 bits)
}
object PREDICTION_WRITE_HAZARD extends Stageable(Bool)
object PREDICTION extends Stageable(BranchPredictorLine())
object PREDICTION_HIT extends Stageable(Bool)
val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
val historyWrite = history.writePort
fetch plug new Area{
import fetch._
val line = history.readSync((prefetch.output(PC) >> 2).resized, prefetch.arbitration.isFiring)
// val line = history.readAsync((fetch.output(PC) >> 2).resized)
val hit = line.source === (input(PC).asBits >> 1 + historyRamSizeLog2)
//Avoid write to read hazard
val historyWriteLast = RegNext(historyWrite)
val hazard = historyWriteLast.valid && historyWriteLast.address === (output(PC) >> 2).resized
insert(PREDICTION_WRITE_HAZARD) := hazard
predictionJumpInterface.valid := line.confidence.msb && hit && arbitration.isFiring && !hazard
predictionJumpInterface.payload := line.target
insert(PREDICTION) := line
insert(PREDICTION_HIT) := hit
}
//Do branch calculations (conditions + target PC)
execute plug new Area {
import execute._
val less = input(SRC_LESS)
val eq = input(SRC1) === input(SRC2)
insert(BRANCH_DO) := input(BRANCH_CTRL).mux(
BranchCtrlEnum.INC -> False,
BranchCtrlEnum.JAL -> True,
BranchCtrlEnum.JALR -> True,
BranchCtrlEnum.B -> input(INSTRUCTION)(14 downto 12).mux(
B"000" -> eq ,
B"001" -> !eq ,
M"1-1" -> !less,
default -> less
)
)
val imm = IMM(input(INSTRUCTION))
val branch_src1 = (input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? input(RS1).asUInt | input(PC)
val branch_src2 = input(BRANCH_CTRL).mux(
BranchCtrlEnum.JAL -> imm.j_sext,
BranchCtrlEnum.JALR -> imm.i_sext,
default -> imm.b_sext
).asUInt
val branchAdder = branch_src1 + branch_src2
insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
}
//Apply branchs (JAL,JALR, Bxx)
val branchStage = if(earlyBranch) execute else memory
branchStage plug new Area {
import branchStage._
val predictionMissmatch = input(PREDICTION).confidence.msb =/= input(BRANCH_DO) || (input(BRANCH_DO) && input(PREDICTION).target =/= input(BRANCH_CALC))
historyWrite.valid := False
historyWrite.address := (branchStage.output(PC) >> 2).resized
historyWrite.data.source := input(PC).asBits >> 1 + historyRamSizeLog2
historyWrite.data.target := input(BRANCH_CALC)
jumpInterface.valid := False
jumpInterface.payload := input(BRANCH_CALC)
when(!input(BRANCH_DO)){
historyWrite.valid := arbitration.isFiring && input(PREDICTION_HIT)
historyWrite.data.confidence := input(PREDICTION).confidence - (input(PREDICTION).confidence =/= 0).asUInt
historyWrite.data.target := input(BRANCH_CALC)
jumpInterface.valid := input(PREDICTION_HIT) && input(PREDICTION).confidence.msb && !input(PREDICTION_WRITE_HAZARD) && arbitration.isFiring
jumpInterface.payload := input(PC) + 4
} otherwise{
when(!input(PREDICTION_HIT) || input(PREDICTION_WRITE_HAZARD)){
jumpInterface.valid := arbitration.isFiring
historyWrite.valid := arbitration.isFiring
historyWrite.data.confidence := "10"
} otherwise {
historyWrite.valid := arbitration.isFiring
historyWrite.data.confidence := input(PREDICTION).confidence + (input(PREDICTION).confidence =/= 3).asUInt
when(!input(PREDICTION).confidence.msb || input(PREDICTION).target =/= input(BRANCH_CALC)){
jumpInterface.valid := arbitration.isFiring
}
}
}
//Prevent rewriting an history which already had hazard
historyWrite.valid clearWhen(input(PREDICTION_WRITE_HAZARD))
when(jumpInterface.valid) {
stages(indexOf(branchStage) - 1).arbitration.flushAll := True
}
if(catchAddressMisaligned) {
branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
branchExceptionPort.code := 0
branchExceptionPort.badAddr := jumpInterface.payload
}
}
//Init History
val historyInit = pipeline plug new Area{
val counter = Reg(UInt(historyRamSizeLog2 + 1 bits)) init(0)
when(!counter.msb){
prefetch.arbitration.haltByOther := True
historyWrite.valid := True
historyWrite.address := counter.resized
historyWrite.data.confidence := 0
counter := counter + 1
}
}
}
// def buildDynamicTargetPrediction(pipeline: VexRiscv): Unit = {
// import pipeline._
// import pipeline.config._
//
// case class BranchPredictorLine() extends Bundle{
// val source = Bits(31 - historyRamSizeLog2 bits)
// val confidence = UInt(2 bits)
// val target = UInt(32 bits)
// }
//
// object PREDICTION_WRITE_HAZARD extends Stageable(Bool)
// object PREDICTION extends Stageable(BranchPredictorLine())
// object PREDICTION_HIT extends Stageable(Bool)
//
// val history = Mem(BranchPredictorLine(), 1 << historyRamSizeLog2)
// val historyWrite = history.writePort
//
//
// fetch plug new Area{
// import fetch._
// val line = history.readSync((prefetch.output(PC) >> 2).resized, prefetch.arbitration.isFiring)
//// val line = history.readAsync((fetch.output(PC) >> 2).resized)
// val hit = line.source === (input(PC).asBits >> 1 + historyRamSizeLog2)
//
// //Avoid write to read hazard
// val historyWriteLast = RegNext(historyWrite)
// val hazard = historyWriteLast.valid && historyWriteLast.address === (output(PC) >> 2).resized
// insert(PREDICTION_WRITE_HAZARD) := hazard
//
// predictionJumpInterface.valid := line.confidence.msb && hit && arbitration.isFiring && !hazard
// predictionJumpInterface.payload := line.target
//
// insert(PREDICTION) := line
// insert(PREDICTION_HIT) := hit
// }
//
//
//
// //Do branch calculations (conditions + target PC)
// execute plug new Area {
// import execute._
//
// val less = input(SRC_LESS)
// val eq = input(SRC1) === input(SRC2)
//
// insert(BRANCH_DO) := input(BRANCH_CTRL).mux(
// BranchCtrlEnum.INC -> False,
// BranchCtrlEnum.JAL -> True,
// BranchCtrlEnum.JALR -> True,
// BranchCtrlEnum.B -> input(INSTRUCTION)(14 downto 12).mux(
// B"000" -> eq ,
// B"001" -> !eq ,
// M"1-1" -> !less,
// default -> less
// )
// )
//
// val imm = IMM(input(INSTRUCTION))
// val branch_src1 = (input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? input(RS1).asUInt | input(PC)
// val branch_src2 = input(BRANCH_CTRL).mux(
// BranchCtrlEnum.JAL -> imm.j_sext,
// BranchCtrlEnum.JALR -> imm.i_sext,
// default -> imm.b_sext
// ).asUInt
//
// val branchAdder = branch_src1 + branch_src2
// insert(BRANCH_CALC) := branchAdder(31 downto 1) @@ ((input(BRANCH_CTRL) === BranchCtrlEnum.JALR) ? False | branchAdder(0))
// }
//
// //Apply branchs (JAL,JALR, Bxx)
// val branchStage = if(earlyBranch) execute else memory
// branchStage plug new Area {
// import branchStage._
//
// val predictionMissmatch = input(PREDICTION).confidence.msb =/= input(BRANCH_DO) || (input(BRANCH_DO) && input(PREDICTION).target =/= input(BRANCH_CALC))
//
// historyWrite.valid := False
// historyWrite.address := (branchStage.output(PC) >> 2).resized
// historyWrite.data.source := input(PC).asBits >> 1 + historyRamSizeLog2
// historyWrite.data.target := input(BRANCH_CALC)
//
// jumpInterface.valid := False
// jumpInterface.payload := input(BRANCH_CALC)
//
//
// when(!input(BRANCH_DO)){
// historyWrite.valid := arbitration.isFiring && input(PREDICTION_HIT)
// historyWrite.data.confidence := input(PREDICTION).confidence - (input(PREDICTION).confidence =/= 0).asUInt
// historyWrite.data.target := input(BRANCH_CALC)
//
//
// jumpInterface.valid := input(PREDICTION_HIT) && input(PREDICTION).confidence.msb && !input(PREDICTION_WRITE_HAZARD) && arbitration.isFiring
// jumpInterface.payload := input(PC) + 4
// } otherwise{
// when(!input(PREDICTION_HIT) || input(PREDICTION_WRITE_HAZARD)){
// jumpInterface.valid := arbitration.isFiring
// historyWrite.valid := arbitration.isFiring
// historyWrite.data.confidence := "10"
// } otherwise {
// historyWrite.valid := arbitration.isFiring
// historyWrite.data.confidence := input(PREDICTION).confidence + (input(PREDICTION).confidence =/= 3).asUInt
// when(!input(PREDICTION).confidence.msb || input(PREDICTION).target =/= input(BRANCH_CALC)){
// jumpInterface.valid := arbitration.isFiring
// }
// }
// }
//
// //Prevent rewriting an history which already had hazard
// historyWrite.valid clearWhen(input(PREDICTION_WRITE_HAZARD))
//
//
//
// when(jumpInterface.valid) {
// stages(indexOf(branchStage) - 1).arbitration.flushAll := True
// }
//
// if(catchAddressMisaligned) {
// branchExceptionPort.valid := arbitration.isValid && input(BRANCH_DO) && jumpInterface.payload(1 downto 0) =/= 0
// branchExceptionPort.code := 0
// branchExceptionPort.badAddr := jumpInterface.payload
// }
// }
//
// //Init History
// val historyInit = pipeline plug new Area{
// val counter = Reg(UInt(historyRamSizeLog2 + 1 bits)) init(0)
// when(!counter.msb){
// prefetch.arbitration.haltByOther := True
// historyWrite.valid := True
// historyWrite.address := counter.resized
// historyWrite.data.confidence := 0
// counter := counter + 1
// }
// }
// }
}

View file

@ -376,8 +376,8 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
//Used to make the pipeline empty softly (for interrupts)
val pipelineLiberator = new Area{
val enable = False.noBackendCombMerge //Verilator Perf
prefetch.arbitration.haltByOther setWhen(enable)
val done = ! List(fetch, decode, execute, memory, writeBack).map(_.arbitration.isValid).orR
decode.arbitration.haltByOther setWhen(enable) //TODO FETCH
val done = ! List(execute, memory, writeBack).map(_.arbitration.isValid).orR
}
@ -388,9 +388,8 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
val exceptionValids = Vec(Bool,stages.length)
val exceptionValidsRegs = Vec(Reg(Bool) init(False), stages.length).allowUnsetRegToAvoidLatch
val exceptionContext = Reg(ExceptionCause())
val pipelineHasException = exceptionValids.orR //TODO FMAX maybe could be partialy pipelined
pipelineLiberator.enable setWhen(pipelineHasException)
pipelineLiberator.enable setWhen(exceptionValidsRegs.tail.orR)
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
@ -409,14 +408,16 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
})
val sortedByStage = groupedByStage.sortWith((a, b) => pipeline.indexOf(a.stage) < pipeline.indexOf(b.stage))
sortedByStage.zipWithIndex.foreach(e => e._1.port.setName(e._1.stage.getName() + "_exception_agregat"))
exceptionValids := exceptionValidsRegs
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
when(port.valid) {
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
exceptionContext := port.payload
when(!exceptionValidsRegs.takeRight(stages.length-stageId-1).fold(False)(_ || _)) {
exceptionContext := port.payload
}
}
}
for(stageId <- firstStageIndexWithExceptionPort until stages.length; stage = stages(stageId) ){
@ -482,6 +483,12 @@ 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
@ -490,7 +497,7 @@ class CsrPlugin(config : CsrPluginConfig) extends Plugin[VexRiscv] with Exceptio
mstatus.MPP := privilege
mepc := exception mux(
True -> writeBack.input(PC),
False -> (writeBackWasWfi ? writeBack.input(PC) | prefetch.input(PC_CALC_WITHOUT_JUMP))
False -> (writeBackWasWfi ? writeBack.input(PC) | decode.input(PC))
)
mcause.interrupt := interrupt

View file

@ -128,6 +128,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
isInjectingOnDecode = Bool()
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
@ -140,7 +141,7 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
val haltIt = RegInit(False)
val stepIt = RegInit(False)
val isPipActive = RegNext(List(fetch, decode, execute, memory, writeBack).map(_.arbitration.isValid).orR)
val isPipActive = RegNext(List(decode, execute, memory, writeBack).map(_.arbitration.isValid).orR)
val isPipBusy = isPipActive || RegNext(isPipActive)
val haltedByBreak = RegInit(False)
@ -201,17 +202,17 @@ class DebugPlugin(val debugClockDomain : ClockDomain) extends Plugin[VexRiscv] w
when(execute.arbitration.isFiring && execute.input(IS_EBREAK)) {
prefetch.arbitration.haltByOther := True
decode.arbitration.haltByOther := True
decode.arbitration.flushAll := True
haltIt := True
haltedByBreak := True
}
when(haltIt) {
prefetch.arbitration.haltByOther := True
decode.arbitration.haltByOther := True
}
when(stepIt && prefetch.arbitration.isFiring) {
when(stepIt && decode.arbitration.isFiring) {
haltIt := True
}
when(stepIt && Cat(pipeline.stages.map(_.arbitration.redoIt)).asBits.orR) {

View file

@ -5,146 +5,149 @@ import vexriscv.ip._
import spinal.core._
import spinal.lib._
class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
import config._
var iBus : InstructionCacheMemBus = null
var mmuBus : MemoryTranslatorBus = null
var decodeExceptionPort : Flow[ExceptionCause] = null
var privilegeService : PrivilegeService = null
var redoBranch : Flow[UInt] = null
object FLUSH_ALL extends Stageable(Bool)
object IBUS_ACCESS_ERROR extends Stageable(Bool)
object IBUS_MMU_MISS extends Stageable(Bool)
object IBUS_ILLEGAL_ACCESS extends Stageable(Bool)
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
import pipeline.config._
def MANAGEMENT = M"-----------------100-----0001111"
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(FLUSH_ALL, False)
decoderService.add(MANAGEMENT, List(
FLUSH_ALL -> True
))
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor
if(catchSomething) {
val exceptionService = pipeline.service(classOf[ExceptionService])
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
}
if(pipeline.serviceExist(classOf[MemoryTranslator]))
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig)
if(pipeline.serviceExist(classOf[PrivilegeService]))
privilegeService = pipeline.service(classOf[PrivilegeService])
if(pipeline.serviceExist(classOf[ReportService])){
val report = pipeline.service(classOf[ReportService])
report.add("iBus" -> {
val e = new BusReport()
val c = new CacheReport()
e.kind = "cached"
e.flushInstructions.add(0x400F) //invalid instruction cache
e.flushInstructions.add(0x13)
e.flushInstructions.add(0x13)
e.flushInstructions.add(0x13)
e.info = c
c.size = cacheSize
c.bytePerLine = bytePerLine
e
})
}
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
// val debugAddressOffset = 28
val cache = new InstructionCache(this.config)
iBus = master(new InstructionCacheMemBus(this.config)).setName("iBus")
iBus <> cache.io.mem
iBus.cmd.address.allowOverride := cache.io.mem.cmd.address // - debugAddressOffset
//Connect prefetch cache side
cache.io.cpu.prefetch.isValid := prefetch.arbitration.isValid
cache.io.cpu.prefetch.pc := prefetch.output(PC)// + debugAddressOffset
prefetch.arbitration.haltItself setWhen(cache.io.cpu.prefetch.haltIt)
//Connect fetch cache side
cache.io.cpu.fetch.isValid := fetch.arbitration.isValid
cache.io.cpu.fetch.isStuck := fetch.arbitration.isStuck
cache.io.cpu.fetch.pc := fetch.output(PC) // + debugAddressOffset
if (mmuBus != null) {
cache.io.cpu.fetch.mmuBus <> mmuBus
} else {
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress //- debugAddressOffset
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False
cache.io.cpu.fetch.mmuBus.rsp.miss := False
}
if(dataOnDecode){
decode.insert(INSTRUCTION) := cache.io.cpu.decode.data
}else{
fetch.insert(INSTRUCTION) := cache.io.cpu.fetch.data
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION))
}
decode.insert(INSTRUCTION_READY) := True
cache.io.cpu.decode.pc := decode.output(PC)
val ownDecode = pipeline.plugins.filter(_.isInstanceOf[InstructionInjector]).foldLeft(True)(_ && !_.asInstanceOf[InstructionInjector].isInjecting(decode))
cache.io.cpu.decode.isValid := decode.arbitration.isValid && ownDecode
cache.io.cpu.decode.isStuck := decode.arbitration.isStuck
cache.io.cpu.decode.isUser := (if(privilegeService != null) privilegeService.isUser(decode) else False)
// cache.io.cpu.decode.pc := decode.input(PC)
redoBranch.valid := decode.arbitration.isValid && ownDecode && cache.io.cpu.decode.cacheMiss && !cache.io.cpu.decode.mmuMiss && !cache.io.cpu.decode.illegalAccess
redoBranch.payload := decode.input(PC)
when(redoBranch.valid){
decode.arbitration.redoIt := True
decode.arbitration.flushAll := True
}
// val redo = RegInit(False) clearWhen(decode.arbitration.isValid) setWhen(redoBranch.valid)
// when(redoBranch.valid || redo){
// service(classOf[InterruptionInhibitor]).inhibateInterrupts()
// }
if(catchSomething){
val accessFault = if(catchAccessFault) cache.io.cpu.decode.error else False
val mmuMiss = if(catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False
val illegalAccess = if(catchIllegalAccess) cache.io.cpu.decode.illegalAccess else False
decodeExceptionPort.valid := decode.arbitration.isValid && ownDecode && (accessFault || mmuMiss || illegalAccess)
decodeExceptionPort.code := mmuMiss ? U(14) | 1
decodeExceptionPort.badAddr := decode.input(PC)
}
memory plug new Area{
import memory._
cache.io.flush.cmd.valid := False
when(arbitration.isValid && input(FLUSH_ALL)){
cache.io.flush.cmd.valid := True
decode.arbitration.flushAll := True
when(!cache.io.flush.cmd.ready){
arbitration.haltItself := True
}
}
}
}
override def build(pipeline: VexRiscv): Unit = ???
}
//class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
// import config._
//
// var iBus : InstructionCacheMemBus = null
// var mmuBus : MemoryTranslatorBus = null
// var decodeExceptionPort : Flow[ExceptionCause] = null
// var privilegeService : PrivilegeService = null
// var redoBranch : Flow[UInt] = null
//
// object FLUSH_ALL extends Stageable(Bool)
// object IBUS_ACCESS_ERROR extends Stageable(Bool)
// object IBUS_MMU_MISS extends Stageable(Bool)
// object IBUS_ILLEGAL_ACCESS extends Stageable(Bool)
// override def setup(pipeline: VexRiscv): Unit = {
// import Riscv._
// import pipeline.config._
//
// def MANAGEMENT = M"-----------------100-----0001111"
//
// val decoderService = pipeline.service(classOf[DecoderService])
// decoderService.addDefault(FLUSH_ALL, False)
// decoderService.add(MANAGEMENT, List(
// FLUSH_ALL -> True
// ))
//
//
// redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(pipeline.decode, priority = 1) //Priority 1 will win against branch predictor
//
// if(catchSomething) {
// val exceptionService = pipeline.service(classOf[ExceptionService])
// decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
// }
//
// if(pipeline.serviceExist(classOf[MemoryTranslator]))
// mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig)
//
// if(pipeline.serviceExist(classOf[PrivilegeService]))
// privilegeService = pipeline.service(classOf[PrivilegeService])
//
// if(pipeline.serviceExist(classOf[ReportService])){
// val report = pipeline.service(classOf[ReportService])
// report.add("iBus" -> {
// val e = new BusReport()
// val c = new CacheReport()
// e.kind = "cached"
// e.flushInstructions.add(0x400F) //invalid instruction cache
// e.flushInstructions.add(0x13)
// e.flushInstructions.add(0x13)
// e.flushInstructions.add(0x13)
//
// e.info = c
// c.size = cacheSize
// c.bytePerLine = bytePerLine
//
// e
// })
// }
// }
//
// override def build(pipeline: VexRiscv): Unit = {
// import pipeline._
// import pipeline.config._
//// val debugAddressOffset = 28
// val cache = new InstructionCache(this.config)
// iBus = master(new InstructionCacheMemBus(this.config)).setName("iBus")
// iBus <> cache.io.mem
// iBus.cmd.address.allowOverride := cache.io.mem.cmd.address // - debugAddressOffset
//
// //Connect prefetch cache side
// cache.io.cpu.prefetch.isValid := prefetch.arbitration.isValid
// cache.io.cpu.prefetch.pc := prefetch.output(PC)// + debugAddressOffset
// prefetch.arbitration.haltItself setWhen(cache.io.cpu.prefetch.haltIt)
//
// //Connect fetch cache side
// cache.io.cpu.fetch.isValid := fetch.arbitration.isValid
// cache.io.cpu.fetch.isStuck := fetch.arbitration.isStuck
// cache.io.cpu.fetch.pc := fetch.output(PC) // + debugAddressOffset
//
// if (mmuBus != null) {
// cache.io.cpu.fetch.mmuBus <> mmuBus
// } else {
// cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress //- debugAddressOffset
// cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
// cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
// cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
// cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
// cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False
// cache.io.cpu.fetch.mmuBus.rsp.miss := False
// }
//
// if(dataOnDecode){
// decode.insert(INSTRUCTION) := cache.io.cpu.decode.data
// }else{
// fetch.insert(INSTRUCTION) := cache.io.cpu.fetch.data
// decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION))
// }
// decode.insert(INSTRUCTION_READY) := True
//
// cache.io.cpu.decode.pc := decode.output(PC)
//
// val ownDecode = pipeline.plugins.filter(_.isInstanceOf[InstructionInjector]).foldLeft(True)(_ && !_.asInstanceOf[InstructionInjector].isInjecting(decode))
// cache.io.cpu.decode.isValid := decode.arbitration.isValid && ownDecode
// cache.io.cpu.decode.isStuck := decode.arbitration.isStuck
// cache.io.cpu.decode.isUser := (if(privilegeService != null) privilegeService.isUser(decode) else False)
//// cache.io.cpu.decode.pc := decode.input(PC)
//
// redoBranch.valid := decode.arbitration.isValid && ownDecode && cache.io.cpu.decode.cacheMiss && !cache.io.cpu.decode.mmuMiss && !cache.io.cpu.decode.illegalAccess
// redoBranch.payload := decode.input(PC)
// when(redoBranch.valid){
// decode.arbitration.redoIt := True
// decode.arbitration.flushAll := True
// }
//
//// val redo = RegInit(False) clearWhen(decode.arbitration.isValid) setWhen(redoBranch.valid)
//// when(redoBranch.valid || redo){
//// service(classOf[InterruptionInhibitor]).inhibateInterrupts()
//// }
//
// if(catchSomething){
// val accessFault = if(catchAccessFault) cache.io.cpu.decode.error else False
// val mmuMiss = if(catchMemoryTranslationMiss) cache.io.cpu.decode.mmuMiss else False
// val illegalAccess = if(catchIllegalAccess) cache.io.cpu.decode.illegalAccess else False
//
// decodeExceptionPort.valid := decode.arbitration.isValid && ownDecode && (accessFault || mmuMiss || illegalAccess)
// decodeExceptionPort.code := mmuMiss ? U(14) | 1
// decodeExceptionPort.badAddr := decode.input(PC)
// }
//
// memory plug new Area{
// import memory._
// cache.io.flush.cmd.valid := False
// when(arbitration.isValid && input(FLUSH_ALL)){
// cache.io.flush.cmd.valid := True
// decode.arbitration.flushAll := True
//
// when(!cache.io.flush.cmd.ready){
// arbitration.haltItself := True
// }
// }
// }
// }
//}

View file

@ -1,10 +1,12 @@
package vexriscv.plugin
import vexriscv.{Stageable, ExceptionService, ExceptionCause, VexRiscv}
import vexriscv._
import spinal.core._
import spinal.lib._
import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.avalon.{AvalonMMConfig, AvalonMM}
import spinal.lib.bus.avalon.{AvalonMM, AvalonMMConfig}
import scala.collection.mutable.ArrayBuffer
case class IBusSimpleCmd() extends Bundle{
@ -12,15 +14,66 @@ case class IBusSimpleCmd() extends Bundle{
}
case class IBusSimpleRsp() extends Bundle with IMasterSlave{
val ready = Bool
val error = Bool
val inst = Bits(32 bits)
override def asMaster(): Unit = {
out(ready,error,inst)
out(error,inst)
}
}
object StreamVexPimper{
implicit class StreamFlushPimper[T <: Data](pimped : Stream[T]){
def m2sPipe(flush : Bool, collapsBubble : Boolean = true): Stream[T] = {
val ret = cloneOf(pimped)
val rValid = RegInit(False)
val rData = Reg(pimped.dataType)
pimped.ready := (Bool(collapsBubble) && !ret.valid) || ret.ready
when(pimped.ready) {
rValid := pimped.valid
rData := pimped.payload
}
ret.valid := rValid
ret.payload := rData
rValid.clearWhen(flush)
ret
}
def s2mPipe(flush : Bool): Stream[T] = {
val ret = cloneOf(pimped)
val rValid = RegInit(False)
val rBits = Reg(pimped.dataType)
ret.valid := pimped.valid || rValid
pimped.ready := !rValid
ret.payload := Mux(rValid, rBits, pimped.payload)
when(ret.ready) {
rValid := False
}
when(pimped.ready && (!ret.ready)) {
rValid := pimped.valid
rBits := pimped.payload
}
rValid.clearWhen(flush)
ret
}
}
}
import StreamVexPimper._
object IBusSimpleBus{
def getAxi4Config() = Axi4Config(
addressWidth = 32,
@ -40,12 +93,12 @@ object IBusSimpleBus{
dataWidth = 32
).getReadOnlyConfig.copy(
useResponse = true,
maximumPendingReadTransactions = 1
maximumPendingReadTransactions = 8
)
}
case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMasterSlave{
var cmd = Stream(IBusSimpleCmd())
var rsp = IBusSimpleRsp()
var rsp = Flow(IBusSimpleRsp())
override def asMaster(): Unit = {
master(cmd)
@ -64,7 +117,7 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
cmd.ready := axi.ar.ready
rsp.ready := axi.r.valid
rsp.valid := axi.r.valid
rsp.inst := axi.r.data
rsp.error := !axi.r.isOKAY()
axi.r.ready := True
@ -87,7 +140,7 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
mm.address := (cmd.pc >> 2) @@ U"00"
cmd.ready := mm.waitRequestn
rsp.ready := mm.readDataValid
rsp.valid := mm.readDataValid
rsp.inst := mm.readData
rsp.error := mm.response =/= AvalonMM.Response.OKAY
@ -95,66 +148,196 @@ case class IBusSimpleBus(interfaceKeepData : Boolean) extends Bundle with IMaste
}
}
class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean) extends Plugin[VexRiscv]{
class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean, pendingMax : Int = 7) extends Plugin[VexRiscv] with JumpService{
var iBus : IBusSimpleBus = null
var prefetchExceptionPort : Flow[ExceptionCause] = null
def resetVector = BigInt(0x80000000l)
def keepPcPlus4 = false
case class JumpInfo(interface : Flow[UInt], stage: Stage, priority : Int)
val jumpInfos = ArrayBuffer[JumpInfo]()
override def createJumpInterface(stage: Stage, priority : Int = 0): Flow[UInt] = {
val interface = Flow(UInt(32 bits))
jumpInfos += JumpInfo(interface,stage, priority)
interface
}
object IBUS_ACCESS_ERROR extends Stageable(Bool)
var decodeExceptionPort : Flow[ExceptionCause] = null
override def setup(pipeline: VexRiscv): Unit = {
iBus = master(IBusSimpleBus(interfaceKeepData)).setName("iBus")
if(catchAccessFault) {
val exceptionService = pipeline.service(classOf[ExceptionService])
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1).setName("iBusErrorExceptionnPort")
}
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
iBus = master(IBusSimpleBus(interfaceKeepData)).setName("iBus")
prefetch plug new Area {
val pendingCmd = RegInit(False) clearWhen (iBus.rsp.ready) setWhen (iBus.cmd.fire)
//Emit iBus.cmd request
iBus.cmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.removeIt && !prefetch.arbitration.isStuckByOthers && !(pendingCmd && !iBus.rsp.ready) //prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
iBus.cmd.pc := prefetch.output(PC)
prefetch.arbitration.haltItself setWhen (!iBus.cmd.ready || (pendingCmd && !iBus.rsp.ready))
}
pipeline plug new Area {
val pcCalc = new Area {
val output = Stream(UInt(32 bits))
//Bus rsp buffer
val rspBuffer = if(!interfaceKeepData) new Area{
val valid = RegInit(False) setWhen(iBus.rsp.ready) clearWhen(!fetch.arbitration.isStuck)
val error = Reg(Bool)
val data = Reg(Bits(32 bits))
when(!valid) {
data := iBus.rsp.inst
error := iBus.rsp.error
//PC calculation without Jump
val pcReg = Reg(UInt(32 bits)) init (resetVector) addAttribute (Verilator.public)
val pcPlus4 = pcReg + 4
if (keepPcPlus4) KeepAttribute(pcPlus4)
when(output.fire) {
pcReg := pcPlus4
}
//JumpService hardware implementation
val jump = new Area {
val sortedByStage = jumpInfos.sortWith((a, b) => {
(pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage)) ||
(pipeline.indexOf(a.stage) == pipeline.indexOf(b.stage) && a.priority > b.priority)
})
val valids = sortedByStage.map(_.interface.valid)
val pcs = sortedByStage.map(_.interface.payload)
val pcLoad = Flow(UInt(32 bits))
pcLoad.valid := jumpInfos.map(_.interface.valid).orR
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
//application of the selected jump request
when(pcLoad.valid) {
pcReg := pcLoad.payload
}
}
output.valid := (RegNext(True) init (False)) // && !jump.pcLoad.valid
output.payload := pcReg
}
} else null
//Insert iBus.rsp into INSTRUCTION
fetch.insert(INSTRUCTION) := iBus.rsp.inst
fetch.insert(IBUS_ACCESS_ERROR) := iBus.rsp.error
if(!interfaceKeepData) {
when(rspBuffer.valid) {
fetch.insert(INSTRUCTION) := rspBuffer.data
fetch.insert(IBUS_ACCESS_ERROR) := rspBuffer.error
def flush = pcCalc.jump.pcLoad.valid
val iBusCmd = new Area {
def input = pcCalc.output
val output = input.continueWhen(iBus.cmd.fire)
//Avoid sending to many iBus cmd
val pendingCmd = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
val pendingCmdNext = pendingCmd + iBus.cmd.fire.asUInt - iBus.rsp.fire.asUInt
pendingCmd := pendingCmdNext
iBus.cmd.valid := input.valid && output.ready && pendingCmd =/= pendingMax
iBus.cmd.pc := input.payload
}
}
fetch.insert(IBUS_ACCESS_ERROR) clearWhen(!fetch.arbitration.isValid) //Avoid interference with instruction injection from the debug plugin
val iBusRsp = new Area {
val input = iBusCmd.output.m2sPipe(flush)// ASYNC .throwWhen(flush)
if(interfaceKeepData)
fetch.arbitration.haltItself setWhen(fetch.arbitration.isValid && !iBus.rsp.ready)
else
fetch.arbitration.haltItself setWhen(fetch.arbitration.isValid && !iBus.rsp.ready && !rspBuffer.valid)
//Manage flush for iBus transactions in flight
val discardCounter = Reg(UInt(log2Up(pendingMax + 1) bits)) init (0)
discardCounter := discardCounter - (iBus.rsp.fire && discardCounter =/= 0).asUInt
when(flush) {
discardCounter := iBusCmd.pendingCmdNext
}
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION))
decode.insert(INSTRUCTION_READY) := True
val rsp = iBus.rsp.throwWhen(discardCounter =/= 0).toStream.s2mPipe(flush)
if(catchAccessFault){
decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR)
decodeExceptionPort.code := 1
decodeExceptionPort.badAddr := decode.input(PC)
case class FetchRsp() extends Bundle {
val pc = UInt(32 bits)
val rsp = IBusSimpleRsp()
}
val fetchRsp = FetchRsp()
fetchRsp.pc := input.payload
fetchRsp.rsp := rsp.payload
fetchRsp.rsp.error.clearWhen(!rsp.valid) //Avoid interference with instruction injection from the debug plugin
val output = StreamJoin(Seq(input, rsp), fetchRsp)
}
val injector = new Area {
val input = iBusRsp.output.s2mPipe(flush)
val stage = input.m2sPipe(flush, false)
stage.ready := !decode.arbitration.isStuck
decode.arbitration.isValid.setAsComb().removeAssignments()
decode.arbitration.isValid := stage.valid
decode.insert(PC) := stage.pc
decode.insert(INSTRUCTION) := stage.rsp.inst
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), input.rsp.inst)
decode.insert(INSTRUCTION_READY) := True
if(catchAccessFault){
decodeExceptionPort.valid := decode.arbitration.isValid && stage.rsp.error
decodeExceptionPort.code := 1
decodeExceptionPort.badAddr := decode.input(PC)
}
}
}
}
}
//class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean) extends Plugin[VexRiscv]{
// var iBus : IBusSimpleBus = null
//
// object IBUS_ACCESS_ERROR extends Stageable(Bool)
// var decodeExceptionPort : Flow[ExceptionCause] = null
// override def setup(pipeline: VexRiscv): Unit = {
// if(catchAccessFault) {
// val exceptionService = pipeline.service(classOf[ExceptionService])
// decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
// }
// }
//
// override def build(pipeline: VexRiscv): Unit = {
// import pipeline._
// import pipeline.config._
// iBus = master(IBusSimpleBus(interfaceKeepData)).setName("iBus")
// prefetch plug new Area {
// val pendingCmd = RegInit(False) clearWhen (iBus.rsp.ready) setWhen (iBus.cmd.fire)
//
// //Emit iBus.cmd request
// iBus.cmd.valid := prefetch.arbitration.isValid && !prefetch.arbitration.removeIt && !prefetch.arbitration.isStuckByOthers && !(pendingCmd && !iBus.rsp.ready) //prefetch.arbitration.isValid && !prefetch.arbitration.isStuckByOthers
// iBus.cmd.pc := prefetch.output(PC)
// prefetch.arbitration.haltItself setWhen (!iBus.cmd.ready || (pendingCmd && !iBus.rsp.ready))
// }
//
// //Bus rsp buffer
// val rspBuffer = if(!interfaceKeepData) new Area{
// val valid = RegInit(False) setWhen(iBus.rsp.ready) clearWhen(!fetch.arbitration.isStuck)
// val error = Reg(Bool)
// val data = Reg(Bits(32 bits))
// when(!valid) {
// data := iBus.rsp.inst
// error := iBus.rsp.error
// }
// } else null
//
// //Insert iBus.rsp into INSTRUCTION
// fetch.insert(INSTRUCTION) := iBus.rsp.inst
// fetch.insert(IBUS_ACCESS_ERROR) := iBus.rsp.error
// if(!interfaceKeepData) {
// when(rspBuffer.valid) {
// fetch.insert(INSTRUCTION) := rspBuffer.data
// fetch.insert(IBUS_ACCESS_ERROR) := rspBuffer.error
// }
// }
//
// fetch.insert(IBUS_ACCESS_ERROR) clearWhen(!fetch.arbitration.isValid) //Avoid interference with instruction injection from the debug plugin
//
// if(interfaceKeepData)
// fetch.arbitration.haltItself setWhen(fetch.arbitration.isValid && !iBus.rsp.ready)
// else
// fetch.arbitration.haltItself setWhen(fetch.arbitration.isValid && !iBus.rsp.ready && !rspBuffer.valid)
//
// decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck,decode.input(INSTRUCTION),fetch.output(INSTRUCTION))
// decode.insert(INSTRUCTION_READY) := True
//
// if(catchAccessFault){
// decodeExceptionPort.valid := decode.arbitration.isValid && decode.input(IBUS_ACCESS_ERROR)
// decodeExceptionPort.code := 1
// decodeExceptionPort.badAddr := decode.input(PC)
// }
// }
//}

View file

@ -20,130 +20,139 @@ object KeepAttribute{
def apply[T <: Data](that : T) = that.addAttribute(keep).addAttribute(syn_keep_verilog).addAttribute(syn_keep_vhdl)
}
class PcManagerSimplePlugin(resetVector : BigInt,
relaxedPcCalculation : Boolean = false,
keepPcPlus4 : Boolean = true) extends Plugin[VexRiscv] with JumpService{
//FetchService interface
case class JumpInfo(interface : Flow[UInt], stage: Stage, priority : Int)
val jumpInfos = ArrayBuffer[JumpInfo]()
override def createJumpInterface(stage: Stage, priority : Int = 0): Flow[UInt] = {
val interface = Flow(UInt(32 bits))
jumpInfos += JumpInfo(interface,stage, priority)
interface
}
var prefetchExceptionPort : Flow[ExceptionCause] = null
override def setup(pipeline: VexRiscv): Unit = {
if(!relaxedPcCalculation) pipeline.unremovableStages += pipeline.prefetch
}
keepPcPlus4 : Boolean = true) extends Plugin[VexRiscv]{
override def build(pipeline: VexRiscv): Unit = ???
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline.config._
import pipeline._
if(relaxedPcCalculation)
relaxedImpl(pipeline)
else
cycleEffectiveImpl(pipeline)
//Formal verification signals generation
prefetch.insert(FORMAL_PC_NEXT) := prefetch.input(PC) + 4
jumpInfos.foreach(info => {
when(info.interface.valid){
info.stage.output(FORMAL_PC_NEXT) := info.interface.payload
}
})
}
//reduce combinatorial path, and expose the PC to the pipeline as a register
def relaxedImpl(pipeline: VexRiscv): Unit = {
import pipeline.config._
import pipeline._
prefetch plug new Area {
import prefetch._
//Stage always valid
arbitration.isValid := True
//PC calculation without Jump
val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
val pcPlus4 = pcReg + 4
if(keepPcPlus4) KeepAttribute(pcPlus4)
when(arbitration.isFiring){
pcReg := pcPlus4
}
//JumpService hardware implementation
val jump = if(jumpInfos.length != 0) new Area {
val sortedByStage = jumpInfos.sortWith((a, b) => {
(pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage)) ||
(pipeline.indexOf(a.stage) == pipeline.indexOf(b.stage) && a.priority > b.priority)
})
val valids = sortedByStage.map(_.interface.valid)
val pcs = sortedByStage.map(_.interface.payload)
val pcLoad = Flow(UInt(32 bits))
pcLoad.valid := jumpInfos.map(_.interface.valid).orR
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
//application of the selected jump request
when(pcLoad.valid) {
pcReg := pcLoad.payload
}
}
insert(PC_CALC_WITHOUT_JUMP) := pcReg
insert(PC) := pcReg
}
}
//Jump take effect instantly (save one cycle), but expose the PC to the pipeline as a 'long' combinatorial path
def cycleEffectiveImpl(pipeline: VexRiscv): Unit = {
import pipeline.config._
import pipeline.prefetch
prefetch plug new Area {
import prefetch._
//Stage always valid
arbitration.isValid := True
//PC calculation without Jump
val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
val inc = RegInit(False)
val pcBeforeJumps = pcReg + (inc ## B"00").asUInt
insert(PC_CALC_WITHOUT_JUMP) := pcBeforeJumps
val pc = UInt(32 bits)
pc := input(PC_CALC_WITHOUT_JUMP)
val samplePcNext = False
//JumpService hardware implementation
val jump = if(jumpInfos.length != 0) new Area {
val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
val valids = sortedByStage.map(_.interface.valid)
val pcs = sortedByStage.map(_.interface.payload)
val pcLoad = Flow(UInt(32 bits))
pcLoad.valid := jumpInfos.map(_.interface.valid).orR
pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
//application of the selected jump request
when(pcLoad.valid) {
inc := False
samplePcNext := True
pc := pcLoad.payload
}
}
when(arbitration.isFiring){
inc := True
samplePcNext := True
}
when(samplePcNext) { pcReg := pc }
insert(PC) := pc
}
}
}
//class PcManagerSimplePlugin(resetVector : BigInt,
// relaxedPcCalculation : Boolean = false,
// keepPcPlus4 : Boolean = true) extends Plugin[VexRiscv] with JumpService{
// //FetchService interface
// case class JumpInfo(interface : Flow[UInt], stage: Stage, priority : Int)
// val jumpInfos = ArrayBuffer[JumpInfo]()
// override def createJumpInterface(stage: Stage, priority : Int = 0): Flow[UInt] = {
// val interface = Flow(UInt(32 bits))
// jumpInfos += JumpInfo(interface,stage, priority)
// interface
// }
// var prefetchExceptionPort : Flow[ExceptionCause] = null
//
// override def setup(pipeline: VexRiscv): Unit = {
// if(!relaxedPcCalculation) pipeline.unremovableStages += pipeline.prefetch
// }
//
//
// override def build(pipeline: VexRiscv): Unit = {
// import pipeline.config._
// import pipeline._
//
// if(relaxedPcCalculation)
// relaxedImpl(pipeline)
// else
// cycleEffectiveImpl(pipeline)
//
// //Formal verification signals generation
// prefetch.insert(FORMAL_PC_NEXT) := prefetch.input(PC) + 4
// jumpInfos.foreach(info => {
// when(info.interface.valid){
// info.stage.output(FORMAL_PC_NEXT) := info.interface.payload
// }
// })
// }
//
// //reduce combinatorial path, and expose the PC to the pipeline as a register
// def relaxedImpl(pipeline: VexRiscv): Unit = {
// import pipeline.config._
// import pipeline._
//
// prefetch plug new Area {
// import prefetch._
// //Stage always valid
// arbitration.isValid := True
//
// //PC calculation without Jump
// val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
// val pcPlus4 = pcReg + 4
// if(keepPcPlus4) KeepAttribute(pcPlus4)
// when(arbitration.isFiring){
// pcReg := pcPlus4
// }
//
// //JumpService hardware implementation
// val jump = if(jumpInfos.length != 0) new Area {
// val sortedByStage = jumpInfos.sortWith((a, b) => {
// (pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage)) ||
// (pipeline.indexOf(a.stage) == pipeline.indexOf(b.stage) && a.priority > b.priority)
// })
// val valids = sortedByStage.map(_.interface.valid)
// val pcs = sortedByStage.map(_.interface.payload)
//
// val pcLoad = Flow(UInt(32 bits))
// pcLoad.valid := jumpInfos.map(_.interface.valid).orR
// pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
//
// //application of the selected jump request
// when(pcLoad.valid) {
// pcReg := pcLoad.payload
// }
// }
//
// insert(PC_CALC_WITHOUT_JUMP) := pcReg
// insert(PC) := pcReg
// }
// }
//
// //Jump take effect instantly (save one cycle), but expose the PC to the pipeline as a 'long' combinatorial path
// def cycleEffectiveImpl(pipeline: VexRiscv): Unit = {
// import pipeline.config._
// import pipeline.prefetch
//
// prefetch plug new Area {
// import prefetch._
// //Stage always valid
// arbitration.isValid := True
//
// //PC calculation without Jump
// val pcReg = Reg(UInt(32 bits)) init(resetVector) addAttribute(Verilator.public)
// val inc = RegInit(False)
// val pcBeforeJumps = pcReg + (inc ## B"00").asUInt
// insert(PC_CALC_WITHOUT_JUMP) := pcBeforeJumps
// val pc = UInt(32 bits)
// pc := input(PC_CALC_WITHOUT_JUMP)
//
// val samplePcNext = False
//
// //JumpService hardware implementation
// val jump = if(jumpInfos.length != 0) new Area {
// val sortedByStage = jumpInfos.sortWith((a, b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
// val valids = sortedByStage.map(_.interface.valid)
// val pcs = sortedByStage.map(_.interface.payload)
//
// val pcLoad = Flow(UInt(32 bits))
// pcLoad.valid := jumpInfos.map(_.interface.valid).orR
// pcLoad.payload := MuxOH(OHMasking.first(valids.asBits), pcs)
//
// //application of the selected jump request
// when(pcLoad.valid) {
// inc := False
// samplePcNext := True
// pc := pcLoad.payload
// }
// }
//
// when(arbitration.isFiring){
// inc := True
// samplePcNext := True
// }
//
// when(samplePcNext) { pcReg := pc }
//
// insert(PC) := pc
// }
// }
//}

View file

@ -10,6 +10,6 @@ class SingleInstructionLimiterPlugin() extends Plugin[VexRiscv] {
import pipeline._
import pipeline.config._
prefetch.arbitration.haltByOther.setWhen(List(fetch,decode,execute,memory,writeBack).map(_.arbitration.isValid).orR)
decode.arbitration.haltByOther.setWhen(List(decode,execute,memory,writeBack).map(_.arbitration.isValid).orR)
}
}

View file

@ -386,7 +386,7 @@ public:
#ifdef REF
if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
#else
if(bootPc != -1) top->VexRiscv->prefetch_PcManagerSimplePlugin_pcReg = bootPc;
if(bootPc != -1) top->VexRiscv->IBusSimplePlugin_pcCalc_pcReg = bootPc;
#endif
@ -511,7 +511,7 @@ public:
virtual void onReset(){
top->iBus_cmd_ready = 1;
top->iBus_rsp_ready = 1;
top->iBus_rsp_valid = 0;
}
virtual void preCycle(){
@ -523,12 +523,12 @@ public:
}
//TODO doesn't catch when instruction removed ?
virtual void postCycle(){
top->iBus_rsp_ready = !pending;
top->iBus_rsp_valid = 0;
if(pending && (!ws->iStall || VL_RANDOM_I(7) < 100)){
top->iBus_rsp_inst = inst_next;
top->iBus_rsp_payload_inst = inst_next;
pending = false;
top->iBus_rsp_ready = 1;
top->iBus_rsp_error = error_next;
top->iBus_rsp_valid = 1;
top->iBus_rsp_payload_error = error_next;
}
if(ws->iStall) top->iBus_cmd_ready = VL_RANDOM_I(7) < 100 && !pending;
}
@ -1426,8 +1426,9 @@ public:
uint32_t readCmd(uint32_t size, uint32_t address){
accessCmd(false, 2, address, VL_RANDOM_I(32));
if(recv(clientSocket, buffer, 4, 0) != 4){
printf("Should read 4 bytes");
int error;
if((error = recv(clientSocket, buffer, 4, 0)) != 4){
printf("Should read 4 bytes, had %d", error);
fail();
}

View file

@ -1,117 +1,117 @@
package vexriscv
import spinal.core._
import spinal.lib.master
import vexriscv.ip.InstructionCacheConfig
import vexriscv.plugin._
object PlayGen extends App{
def cpu() = new VexRiscv(
config = VexRiscvConfig(
plugins = List(
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 16,
bytePerLine = 4,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = false,
catchAccessFault = false,
catchMemoryTranslationMiss = false,
asyncTagMemory = false,
twoCycleRam = false,
preResetFlush = false
)
),
new FormalPlugin,
new HaltOnExceptionPlugin,
new PcManagerSimplePlugin(
resetVector = 0x00000000l,
relaxedPcCalculation = false
),
// new IBusSimplePlugin(
// interfaceKeepData = false,
//package vexriscv
//
//import spinal.core._
//import spinal.lib.master
//import vexriscv.ip.InstructionCacheConfig
//import vexriscv.plugin._
//
//object PlayGen extends App{
// def cpu() = new VexRiscv(
// config = VexRiscvConfig(
// plugins = List(
// new IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 16,
// bytePerLine = 4,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchIllegalAccess = false,
// catchAccessFault = false,
// catchMemoryTranslationMiss = false,
// asyncTagMemory = false,
// twoCycleRam = false,
// preResetFlush = false
// )
// ),
// new FormalPlugin,
// new HaltOnExceptionPlugin,
// new PcManagerSimplePlugin(
// resetVector = 0x00000000l,
// relaxedPcCalculation = false
// ),
//// new IBusSimplePlugin(
//// interfaceKeepData = false,
//// catchAccessFault = false
//// ),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,
// catchAccessFault = false
// ),
new DBusSimplePlugin(
catchAddressMisaligned = true,
catchAccessFault = false
),
new DecoderSimplePlugin(
catchIllegalInstruction = true,
forceLegalInstructionComputation = true
),
new RegFilePlugin(
regFileReadyKind = plugin.SYNC,
zeroBoot = false
),
new IntAluPlugin,
new SrcPlugin(
separatedAddSub = false,
executeInsertion = false
),
new FullBarrielShifterPlugin,
new HazardSimplePlugin(
bypassExecute = false,
bypassMemory = false,
bypassWriteBack = false,
bypassWriteBackBuffer = false,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
),
new BranchPlugin(
earlyBranch = false,
catchAddressMisaligned = true,
prediction = NONE
),
new YamlPlugin("cpu0.yaml")
)
)
)
// Wrap with input/output registers
def wrap(that : => VexRiscv) : Component = {
val c = that
// c.rework {
// for (e <- c.getOrdredNodeIo) {
// if (e.isInput) {
// e.asDirectionLess()
// e := RegNext(RegNext(in(cloneOf(e))))
// new DecoderSimplePlugin(
// catchIllegalInstruction = true,
// forceLegalInstructionComputation = true
// ),
// new RegFilePlugin(
// regFileReadyKind = plugin.SYNC,
// zeroBoot = false
// ),
// new IntAluPlugin,
// new SrcPlugin(
// separatedAddSub = false,
// executeInsertion = false
// ),
// new FullBarrielShifterPlugin,
// new HazardSimplePlugin(
// bypassExecute = false,
// bypassMemory = false,
// bypassWriteBack = false,
// bypassWriteBackBuffer = false,
// pessimisticUseSrc = false,
// pessimisticWriteRegFile = false,
// pessimisticAddressMatch = false
// ),
// new BranchPlugin(
// earlyBranch = false,
// catchAddressMisaligned = true,
// prediction = NONE
// ),
// new YamlPlugin("cpu0.yaml")
// )
// )
// )
// // Wrap with input/output registers
// def wrap(that : => VexRiscv) : Component = {
// val c = that
//// c.rework {
//// for (e <- c.getOrdredNodeIo) {
//// if (e.isInput) {
//// e.asDirectionLess()
//// e := RegNext(RegNext(in(cloneOf(e))))
////
//// } else {
//// e.asDirectionLess()
//// out(cloneOf(e)) := RegNext(RegNext(e))
//// }
//// }
//// }
//
// } else {
// e.asDirectionLess()
// out(cloneOf(e)) := RegNext(RegNext(e))
// c.rework{
// c.config.plugins.foreach{
// case p : IBusCachedPlugin => {
// p.iBus.asDirectionLess().unsetName()
// val iBusNew = master(IBusSimpleBus(false)).setName("iBus")
//
// iBusNew.cmd.valid := p.iBus.cmd.valid
// iBusNew.cmd.pc := p.iBus.cmd.address
// p.iBus.cmd.ready := iBusNew.cmd.ready
//
// val pending = RegInit(False) clearWhen(iBusNew.rsp.ready) setWhen (iBusNew.cmd.fire)
// p.iBus.rsp.valid := iBusNew.rsp.ready & pending
// p.iBus.rsp.error := iBusNew.rsp.error
// p.iBus.rsp.data := iBusNew.rsp.inst
// }
// case _ =>
// }
// }
c.rework{
c.config.plugins.foreach{
case p : IBusCachedPlugin => {
p.iBus.asDirectionLess().unsetName()
val iBusNew = master(IBusSimpleBus(false)).setName("iBus")
iBusNew.cmd.valid := p.iBus.cmd.valid
iBusNew.cmd.pc := p.iBus.cmd.address
p.iBus.cmd.ready := iBusNew.cmd.ready
val pending = RegInit(False) clearWhen(iBusNew.rsp.ready) setWhen (iBusNew.cmd.fire)
p.iBus.rsp.valid := iBusNew.rsp.ready & pending
p.iBus.rsp.error := iBusNew.rsp.error
p.iBus.rsp.data := iBusNew.rsp.inst
}
case _ =>
}
}
c
}
SpinalConfig(
defaultConfigForClockDomains = ClockDomainConfig(
resetKind = spinal.core.SYNC,
resetActiveLevel = spinal.core.HIGH
),
inlineRom = true
).generateVerilog(wrap(cpu()))
}
// c
// }
// SpinalConfig(
// defaultConfigForClockDomains = ClockDomainConfig(
// resetKind = spinal.core.SYNC,
// resetActiveLevel = spinal.core.HIGH
// ),
// inlineRom = true
// ).generateVerilog(wrap(cpu()))
//}