mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
Restore two cycle instruction cache features
This commit is contained in:
parent
df3d9ccb13
commit
3b54ecf303
3 changed files with 70 additions and 54 deletions
|
@ -31,32 +31,33 @@ object TestsWorkspace {
|
|||
SpinalConfig(mergeAsyncProcess = false).generateVerilog {
|
||||
val configFull = VexRiscvConfig(
|
||||
plugins = List(
|
||||
new IBusSimplePlugin(
|
||||
resetVector = 0x80000000l,
|
||||
relaxedPcCalculation = false,
|
||||
prediction = NONE,
|
||||
catchAccessFault = true,
|
||||
catchAddressMisaligned = true,
|
||||
compressedGen = true
|
||||
),
|
||||
// new IBusCachedPlugin(
|
||||
// config = InstructionCacheConfig(
|
||||
// cacheSize = 1024*16,
|
||||
// bytePerLine = 32,
|
||||
// wayCount = 1,
|
||||
// addressWidth = 32,
|
||||
// cpuDataWidth = 32,
|
||||
// memDataWidth = 32,
|
||||
// catchIllegalAccess = false,
|
||||
// catchAccessFault = true,
|
||||
// catchMemoryTranslationMiss = false,
|
||||
// asyncTagMemory = false,
|
||||
// twoCycleRam = false
|
||||
// )//,
|
||||
//// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
//// portTlbSize = 4
|
||||
//// )
|
||||
// new IBusSimplePlugin(
|
||||
// resetVector = 0x80000000l,
|
||||
// relaxedPcCalculation = false,
|
||||
// prediction = NONE,
|
||||
// catchAccessFault = true,
|
||||
// catchAddressMisaligned = false,
|
||||
// compressedGen = true
|
||||
// ),
|
||||
new IBusCachedPlugin(
|
||||
config = InstructionCacheConfig(
|
||||
cacheSize = 1024*16,
|
||||
bytePerLine = 32,
|
||||
wayCount = 1,
|
||||
addressWidth = 32,
|
||||
cpuDataWidth = 32,
|
||||
memDataWidth = 32,
|
||||
catchIllegalAccess = false,
|
||||
catchAccessFault = true,
|
||||
catchMemoryTranslationMiss = false,
|
||||
asyncTagMemory = false,
|
||||
twoCycleRam = false,
|
||||
twoCycleCache = true
|
||||
)//,
|
||||
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||
// portTlbSize = 4
|
||||
// )
|
||||
),
|
||||
// new DBusSimplePlugin(
|
||||
// catchAddressMisaligned = true,
|
||||
// catchAccessFault = true,
|
||||
|
|
|
@ -23,7 +23,6 @@ case class InstructionCacheConfig( cacheSize : Int,
|
|||
|
||||
assert(!(twoCycleRam && !twoCycleCache))
|
||||
|
||||
def dataOnDecode = twoCycleRam && wayCount > 1
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
def catchSomething = catchAccessFault || catchMemoryTranslationMiss || catchIllegalAccess
|
||||
|
||||
|
@ -60,7 +59,15 @@ case class InstructionCacheCpuPrefetch(p : InstructionCacheConfig) extends Bundl
|
|||
}
|
||||
}
|
||||
|
||||
case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave {
|
||||
trait InstructionCacheCommons{
|
||||
val isValid : Bool
|
||||
val isStuck : Bool
|
||||
val pc : UInt
|
||||
val data : Bits
|
||||
val cacheMiss, error, mmuMiss, illegalAccess,isUser : Bool
|
||||
}
|
||||
|
||||
case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons {
|
||||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val pc = UInt(p.addressWidth bits)
|
||||
|
@ -77,11 +84,11 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
|
|||
}
|
||||
|
||||
|
||||
case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle with IMasterSlave {
|
||||
case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons {
|
||||
val isValid = Bool
|
||||
val isStuck = Bool
|
||||
val pc = UInt(p.addressWidth bits)
|
||||
val data = ifGen(p.dataOnDecode) (Bits(p.cpuDataWidth bits))
|
||||
val data = Bits(p.cpuDataWidth bits)
|
||||
val cacheMiss, error, mmuMiss, illegalAccess, isUser = ifGen(p.twoCycleCache)(Bool)
|
||||
|
||||
override def asMaster(): Unit = {
|
||||
|
@ -309,6 +316,9 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val data = read.waysValues.map(_.data).read(id)
|
||||
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.fetch.pc(memWordToCpuWordRange))
|
||||
io.cpu.fetch.data := word
|
||||
if(twoCycleCache){
|
||||
io.cpu.decode.data := RegNextWhen(io.cpu.fetch.data,!io.cpu.decode.isStuck)
|
||||
}
|
||||
} else null
|
||||
|
||||
if(twoCycleRam && wayCount == 1){
|
||||
|
@ -345,11 +355,9 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
|
|||
val valid = Cat(hits).orR
|
||||
val id = OHToUInt(hits)
|
||||
val error = tags(id).error
|
||||
if(dataOnDecode) {
|
||||
val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id)
|
||||
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange))
|
||||
io.cpu.decode.data := word
|
||||
}
|
||||
val data = fetchStage.read.waysValues.map(way => stage(way.data)).read(id)
|
||||
val word = data.subdivideIn(cpuDataWidth bits).read(io.cpu.decode.pc(memWordToCpuWordRange))
|
||||
io.cpu.decode.data := word
|
||||
}
|
||||
|
||||
io.cpu.decode.cacheMiss := !hit.valid
|
||||
|
|
|
@ -13,14 +13,14 @@ class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConf
|
|||
catchAccessFault = config.catchAccessFault,
|
||||
resetVector = BigInt(0x80000000l),
|
||||
keepPcPlus4 = false,
|
||||
decodePcGen = false,
|
||||
compressedGen = false,
|
||||
cmdToRspStageCount = 1,
|
||||
decodePcGen = true,
|
||||
compressedGen = true,
|
||||
cmdToRspStageCount = (if(config.twoCycleCache) 2 else 1),
|
||||
injectorReadyCutGen = false,
|
||||
relaxedPcCalculation = false,
|
||||
prediction = NONE,
|
||||
catchAddressMisaligned = false,
|
||||
injectorStage = true){
|
||||
injectorStage = !config.twoCycleCache){
|
||||
import config._
|
||||
|
||||
var iBus : InstructionCacheMemBus = null
|
||||
|
@ -103,6 +103,19 @@ class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConf
|
|||
cache.io.cpu.fetch.isStuck := !iBusRsp.input.ready
|
||||
cache.io.cpu.fetch.pc := iBusRsp.inputPipeline(0).payload
|
||||
|
||||
|
||||
if(twoCycleCache){
|
||||
cache.io.cpu.decode.isValid := iBusRsp.inputPipeline(1).valid
|
||||
cache.io.cpu.decode.isStuck := !iBusRsp.input.ready
|
||||
cache.io.cpu.decode.pc := iBusRsp.inputPipeline(1).payload
|
||||
cache.io.cpu.decode.isUser := (if (privilegeService != null) privilegeService.isUser(decode) else False)
|
||||
|
||||
if((!twoCycleRam || wayCount == 1) && !compressedGen){
|
||||
decode.insert(INSTRUCTION_ANTICIPATED) := Mux(decode.arbitration.isStuck, decode.input(INSTRUCTION), cache.io.cpu.fetch.data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mmuBus != null) {
|
||||
cache.io.cpu.fetch.mmuBus <> mmuBus
|
||||
} else {
|
||||
|
@ -116,40 +129,34 @@ class IBusCachedPlugin(config : InstructionCacheConfig, memoryTranslatorPortConf
|
|||
}
|
||||
|
||||
// val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss
|
||||
val cacheRsp = if(twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
|
||||
val cacheRspArbitration = iBusRsp.inputPipeline(if(twoCycleCache) 1 else 0)
|
||||
var issueDetected = False
|
||||
|
||||
val redoFetch = False //RegNext(False) init(False)
|
||||
when(cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss && !issueDetected){
|
||||
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected){
|
||||
issueDetected \= True
|
||||
redoFetch := iBusRsp.readyForError
|
||||
// if(decodePcGen) {
|
||||
// redoFetch := !flush && iBusRsp.readyForError
|
||||
// } else {
|
||||
// redoFetch := !flush && iBusRsp.readyForError
|
||||
// }
|
||||
}
|
||||
cache.io.cpu.fill.valid := redoFetch
|
||||
redoBranch.valid := redoFetch
|
||||
assert(decodePcGen == compressedGen)
|
||||
redoBranch.payload := (if(decodePcGen) decode.input(PC) else cache.io.cpu.fetch.pc)
|
||||
cache.io.cpu.fill.payload := cache.io.cpu.fetch.pc
|
||||
redoBranch.payload := (if(decodePcGen) decode.input(PC) else cacheRsp.pc)
|
||||
cache.io.cpu.fill.payload := cacheRsp.pc
|
||||
|
||||
if(catchSomething){
|
||||
// val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss
|
||||
|
||||
decodeExceptionPort.valid := False
|
||||
decodeExceptionPort.code := 1
|
||||
decodeExceptionPort.badAddr := cache.io.cpu.fetch.pc
|
||||
when(cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.error && !issueDetected){
|
||||
decodeExceptionPort.badAddr := cacheRsp.pc
|
||||
when(cacheRsp.isValid && cacheRsp.error && !issueDetected){
|
||||
issueDetected \= True
|
||||
decodeExceptionPort.valid := iBusRsp.readyForError
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
iBusRsp.output.arbitrationFrom(iBusRsp.inputPipeline(0).haltWhen(issueDetected))
|
||||
iBusRsp.output.rsp.inst := cache.io.cpu.fetch.data
|
||||
iBusRsp.output.pc := iBusRsp.inputPipeline(0).payload
|
||||
iBusRsp.output.arbitrationFrom(cacheRspArbitration.haltWhen(issueDetected))
|
||||
iBusRsp.output.rsp.inst := cacheRsp.data
|
||||
iBusRsp.output.pc := cacheRspArbitration.payload
|
||||
|
||||
|
||||
// if (dataOnDecode) {
|
||||
|
|
Loading…
Reference in a new issue