Data cache can now be used without writeback stage
This commit is contained in:
parent
ace963b542
commit
bf82829e9e
|
@ -24,8 +24,9 @@ case class DataCacheConfig(cacheSize : Int,
|
|||
earlyDataMux : Boolean = false,
|
||||
tagSizeShift : Int = 0, //Used to force infering ram
|
||||
withLrSc : Boolean = false,
|
||||
withAmo : Boolean = false){
|
||||
|
||||
withAmo : Boolean = false,
|
||||
mergeExecuteMemory : Boolean = false){
|
||||
assert(!(mergeExecuteMemory && (earlyDataMux || earlyWaysHits)))
|
||||
assert(!(earlyDataMux && !earlyWaysHits))
|
||||
def burstSize = bytePerLine*8/memDataWidth
|
||||
val burstLength = bytePerLine/(memDataWidth/8)
|
||||
|
@ -446,7 +447,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
}
|
||||
|
||||
val stageA = new Area{
|
||||
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.memory.isStuck)
|
||||
def stagePipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.memory.isStuck)
|
||||
val request = stagePipe(io.cpu.execute.args)
|
||||
val mask = stagePipe(stage0.mask)
|
||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid
|
||||
|
@ -457,16 +458,22 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
val wayHits = earlyWaysHits generate ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid))
|
||||
val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp))
|
||||
val colisions = stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask) //Assume the writeback stage will never be unstall memory acces while memory stage is stalled
|
||||
val colisions = if(mergeExecuteMemory){
|
||||
stagePipe(stage0.colisions)
|
||||
} else {
|
||||
//Assume the writeback stage will never be unstall memory acces while memory stage is stalled
|
||||
stagePipe(stage0.colisions) | collisionProcess(io.cpu.memory.address(lineRange.high downto wordRange.low), mask)
|
||||
}
|
||||
}
|
||||
|
||||
val stageB = new Area {
|
||||
def stagePipe[T <: Data](that : T) = RegNextWhen(that, !io.cpu.writeBack.isStuck)
|
||||
def ramPipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else RegNextWhen(that, !io.cpu.writeBack.isStuck)
|
||||
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
|
||||
val mmuRspFreeze = False
|
||||
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze)
|
||||
val tagsReadRsp = ways.map(w => stagePipe(w.tagsReadRsp))
|
||||
val dataReadRsp = !earlyDataMux generate ways.map(w => stagePipe(w.dataReadRsp))
|
||||
val tagsReadRsp = ways.map(w => ramPipe(w.tagsReadRsp))
|
||||
val dataReadRsp = !earlyDataMux generate ways.map(w => ramPipe(w.dataReadRsp))
|
||||
val waysHits = if(earlyWaysHits) stagePipe(B(stageA.wayHits)) else B(tagsReadRsp.map(tag => mmuRsp.physicalAddress(tagRange) === tag.address && tag.valid).asBits())
|
||||
val waysHit = waysHits.orR
|
||||
val dataMux = if(earlyDataMux) stagePipe(stageA.dataMux) else MuxOH(waysHits, dataReadRsp)
|
||||
|
|
|
@ -148,7 +148,7 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
redoBranch = pipeline.service(classOf[JumpService]).createJumpInterface(if(pipeline.writeBack != null) pipeline.writeBack else pipeline.execute)
|
||||
|
||||
if(catchSomething)
|
||||
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack)
|
||||
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(if(pipeline.writeBack == null) pipeline.memory else pipeline.writeBack)
|
||||
|
||||
if(pipeline.serviceExist(classOf[PrivilegeService]))
|
||||
privilegeService = pipeline.service(classOf[PrivilegeService])
|
||||
|
@ -162,7 +162,9 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
|
||||
dBus = master(DataCacheMemBus(this.config)).setName("dBus")
|
||||
|
||||
val cache = new DataCache(this.config)
|
||||
val cache = new DataCache(this.config.copy(
|
||||
mergeExecuteMemory = writeBack == null
|
||||
))
|
||||
|
||||
//Interconnect the plugin dBus with the cache dBus with some optional pipelining
|
||||
def optionPipe[T](cond : Boolean, on : T)(f : T => T) : T = if(cond) f(on) else on
|
||||
|
@ -226,22 +228,22 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
if(relaxedMemoryTranslationRegister) insert(MEMORY_VIRTUAL_ADDRESS) := cache.io.cpu.execute.address
|
||||
}
|
||||
|
||||
val flushStage = if(memory != null) memory else execute
|
||||
flushStage plug new Area {
|
||||
import flushStage._
|
||||
val mmuAndBufferStage = if(writeBack != null) memory else execute
|
||||
mmuAndBufferStage plug new Area {
|
||||
import mmuAndBufferStage._
|
||||
|
||||
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.memory.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.memory.isRemoved := arbitration.removeIt
|
||||
cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else U(input(REGFILE_WRITE_DATA)))
|
||||
cache.io.cpu.memory.address := (if(relaxedMemoryTranslationRegister) input(MEMORY_VIRTUAL_ADDRESS) else if(mmuAndBufferStage == execute) cache.io.cpu.execute.address else U(input(REGFILE_WRITE_DATA)))
|
||||
|
||||
cache.io.cpu.memory.mmuBus <> mmuBus
|
||||
cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite)
|
||||
}
|
||||
|
||||
val fenceStage = stages.last
|
||||
fenceStage plug new Area{
|
||||
import fenceStage._
|
||||
val managementStage = stages.last
|
||||
managementStage plug new Area{
|
||||
import managementStage._
|
||||
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
||||
cache.io.cpu.writeBack.isUser := (if(privilegeService != null) privilegeService.isUser() else False)
|
||||
|
@ -326,10 +328,10 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire
|
||||
|
||||
|
||||
mmuBus.cmd.bypassTranslation setWhen(flushStage.input(IS_DBUS_SHARING))
|
||||
cache.io.cpu.memory.isValid setWhen(flushStage.input(IS_DBUS_SHARING))
|
||||
cache.io.cpu.writeBack.isValid setWhen(fenceStage.input(IS_DBUS_SHARING))
|
||||
dBusAccess.rsp.valid := fenceStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt)
|
||||
mmuBus.cmd.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING))
|
||||
if(mmuAndBufferStage != execute) (cache.io.cpu.memory.isValid setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING)))
|
||||
cache.io.cpu.writeBack.isValid setWhen(managementStage.input(IS_DBUS_SHARING))
|
||||
dBusAccess.rsp.valid := managementStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt)
|
||||
dBusAccess.rsp.data := cache.io.cpu.writeBack.data
|
||||
dBusAccess.rsp.error := cache.io.cpu.writeBack.unalignedAccess || cache.io.cpu.writeBack.accessError
|
||||
dBusAccess.rsp.redo := cache.io.cpu.redo
|
||||
|
@ -337,10 +339,10 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
when(forceDatapath){
|
||||
execute.output(REGFILE_WRITE_DATA) := dBusAccess.cmd.address.asBits
|
||||
}
|
||||
flushStage.input(IS_DBUS_SHARING) init(False)
|
||||
fenceStage.input(IS_DBUS_SHARING) init(False)
|
||||
if(mmuAndBufferStage != execute) mmuAndBufferStage.input(IS_DBUS_SHARING) init(False)
|
||||
managementStage.input(IS_DBUS_SHARING) init(False)
|
||||
when(dBusAccess.rsp.valid){
|
||||
fenceStage.input(IS_DBUS_SHARING).getDrivingReg := False
|
||||
managementStage.input(IS_DBUS_SHARING).getDrivingReg := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue