This commit is contained in:
Dolu1990 2018-04-13 12:51:27 +02:00
parent 19d5d1ecf1
commit 76352b44fa
7 changed files with 265 additions and 172 deletions

View File

@ -35,28 +35,28 @@ object TestsWorkspace {
// resetVector = 0x80000000l,
// relaxedPcCalculation = false
// ),
new IBusSimplePlugin(
interfaceKeepData = false,
catchAccessFault = true
),
// 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
// ),
// new IBusSimplePlugin(
// interfaceKeepData = false,
// catchAccessFault = true
// ),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 1024*16,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchIllegalAccess = false,
catchAccessFault = false,
catchMemoryTranslationMiss = false,
asyncTagMemory = false,
twoCycleRam = false
)//,
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 4
// )
// ),
),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,
// catchAccessFault = true,

View File

@ -340,6 +340,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
lineLoader.valid := True
lineLoader.address := mmuRsp.physicalAddress //Could be optimise if mmu not used
}
// when(io.cpu)
io.cpu.decode.error := hit.error
io.cpu.decode.mmuMiss := mmuRsp.miss

View File

@ -189,12 +189,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
val iBusRsp = new Area {
val input = Stream(UInt(32 bits))
val pipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount)
val inputPipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount)
for(i <- 0 until cmdToRspStageCount) {
// val doFlush = if(i == cmdToRspStageCount- 1 && ???) killLastStage else flush
pipeline(i) << {i match {
inputPipeline(i) << {i match {
case 0 => input.m2sPipeWithFlush(flush, relaxedPcCalculation)
case _ => pipeline(i-1)/*.haltWhen(fetcherHalt)*/.m2sPipeWithFlush(flush)
case _ => inputPipeline(i-1)/*.haltWhen(fetcherHalt)*/.m2sPipeWithFlush(flush)
}}
}
@ -255,7 +255,7 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
}else {
val lastStageStream = if(injectorStage) inputBeforeHalt
else if(rspStageGen) iBusRsp.outputBeforeStage
else if(cmdToRspStageCount > 1)iBusRsp.pipeline(cmdToRspStageCount-2)
else if(cmdToRspStageCount > 1)iBusRsp.inputPipeline(cmdToRspStageCount-2)
else throw new Exception("Fetch should at least have two stages")
// when(fetcherHalt){

View File

@ -5,149 +5,167 @@ import vexriscv.ip._
import spinal.core._
import spinal.lib._
class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv] {
var iBus : InstructionCacheMemBus = null
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
// }
// }
// }
// }
// override def build(pipeline: VexRiscv): Unit = ???
//}
class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConfig : Any = null) extends IBusFetcherImpl(
catchAccessFault = config.catchAccessFault,
resetVector = BigInt(0x80000000l),
keepPcPlus4 = false,
decodePcGen = true,
compressedGen = true,
cmdToRspStageCount = 1,
rspStageGen = false,
injectorReadyCutGen = false,
relaxedPcCalculation = false,
prediction = NONE,
catchAddressMisaligned = false,
injectorStage = true){
import config._
var iBus : InstructionCacheMemBus = null
var mmuBus : MemoryTranslatorBus = 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._
super.setup(pipeline)
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]))
// ??? //TODO
//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._
pipeline plug new FetchArea(pipeline) {
val cache = new InstructionCache(IBusCachedPlugin.this.config)
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.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 := fetchPc.output.valid
cache.io.cpu.prefetch.pc := fetchPc.output.payload
iBusRsp.input << fetchPc.output.haltWhen(cache.io.cpu.prefetch.haltIt)
//Connect fetch cache side
cache.io.cpu.fetch.isValid := iBusRsp.inputPipeline(0).valid
cache.io.cpu.fetch.isStuck := !iBusRsp.inputPipeline(0).ready
cache.io.cpu.fetch.pc := iBusRsp.inputPipeline(0).payload
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 {
iBusRsp.outputBeforeStage.arbitrationFrom(iBusRsp.inputPipeline(0))
iBusRsp.outputBeforeStage.rsp.inst := cache.io.cpu.fetch.data
iBusRsp.outputBeforeStage.pc := iBusRsp.inputPipeline(0).payload
}
cache.io.cpu.decode.pc := injector.inputBeforeHalt.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 := !injector.inputBeforeHalt.ready
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

@ -163,12 +163,12 @@ class IBusSimplePlugin(interfaceKeepData : Boolean, catchAccessFault : Boolean,
rspBuffer.io.flush := flush
val fetchRsp = FetchRsp()
fetchRsp.pc := pipeline.last.payload
fetchRsp.pc := inputPipeline.last.payload
fetchRsp.rsp := rspBuffer.io.pop.payload
fetchRsp.rsp.error.clearWhen(!rspBuffer.io.pop.valid) //Avoid interference with instruction injection from the debug plugin
val join = StreamJoin(Seq(pipeline.last, rspBuffer.io.pop), fetchRsp)
val join = StreamJoin(Seq(inputPipeline.last, rspBuffer.io.pop), fetchRsp)
output << (if(rspStageGen) join.m2sPipeWithFlush(flush) else join)
}
}

View File

@ -0,0 +1,67 @@
[*]
[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI
[*] Wed Apr 11 18:53:23 2018
[*]
[dumpfile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/rv32ui-p-lui.vcd"
[dumpfile_mtime] "Wed Apr 11 18:52:18 2018"
[dumpfile_size] 325049
[savefile] "/home/spinalvm/hdl/VexRiscv/src/test/cpp/regression/icache.gtkw"
[timestart] 1006
[size] 1784 950
[pos] -383 -155
*-5.000000 1046 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] TOP.
[treeopen] TOP.VexRiscv.
[sst_width] 370
[signals_width] 349
[sst_expanded] 1
[sst_vpaned_height] 271
@28
TOP.VexRiscv.decode_arbitration_isValid
TOP.VexRiscv.decode_arbitration_redoIt
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_haltIt
@22
TOP.VexRiscv.iBus_cmd_payload_address[31:0]
@28
TOP.VexRiscv.iBus_cmd_payload_size[2:0]
TOP.VexRiscv.iBus_cmd_ready
@29
TOP.VexRiscv.iBus_cmd_valid
@22
TOP.VexRiscv.iBus_rsp_payload_data[31:0]
@28
TOP.VexRiscv.iBus_rsp_payload_error
TOP.VexRiscv.iBus_rsp_valid
[color] 2
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_isValid
[color] 2
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_haltIt
@22
[color] 2
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_prefetch_pc[31:0]
@28
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_isValid
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_isStuck
@22
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_data[31:0]
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_fetch_pc[31:0]
@28
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isValid
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_cacheMiss
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_error
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_illegalAccess
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isStuck
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_isUser
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_mmuMiss
@22
[color] 6
TOP.VexRiscv.IBusCachedPlugin_cache.io_cpu_decode_pc[31:0]
[pattern_trace] 1
[pattern_trace] 0

View File

@ -387,10 +387,17 @@ public:
if(bootPc != -1) top->VexRiscv->core->prefetch_pc = bootPc;
#else
if(bootPc != -1) {
top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
#ifdef COMPRESSED
top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
#endif
#ifdef IBUS_SIMPLE
top->VexRiscv->IBusSimplePlugin_fetchPc_pcReg = bootPc;
#ifdef COMPRESSED
top->VexRiscv->IBusSimplePlugin_decodePc_pcReg = bootPc;
#endif
#else
top->VexRiscv->IBusCachedPlugin_fetchPc_pcReg = bootPc;
#ifdef COMPRESSED
top->VexRiscv->IBusCachedPlugin_decodePc_pcReg = bootPc;
#endif
#endif
}
#endif