DataCache add invalidate/clean/invalidateClean on a virtual address/way

This commit is contained in:
Charles Papon 2017-05-05 00:43:41 +02:00
parent 48a5dc8e79
commit 5ba8ab7947
4 changed files with 50 additions and 126 deletions

View File

@ -63,7 +63,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
List(SB, SH, SW).map(_ -> storeActions) List(SB, SH, SW).map(_ -> storeActions)
) )
if(askMemoryTranslation != null) if(askMemoryTranslation)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig) mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig)
if(catchSomething) if(catchSomething)
@ -100,8 +100,10 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
default -> B"1111" default -> B"1111"
) << cache.io.cpu.execute.args.address(1 downto 0)).resized ) << cache.io.cpu.execute.args.address(1 downto 0)).resized
cache.io.cpu.execute.args.bypass := cache.io.cpu.execute.args.address(31 downto 28) === 0xF cache.io.cpu.execute.args.bypass := cache.io.cpu.execute.args.address(31 downto 28) === 0xF
cache.io.cpu.execute.args.all := False
cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY cache.io.cpu.execute.args.kind := DataCacheCpuCmdKind.MEMORY
cache.io.cpu.execute.args.clean := False
cache.io.cpu.execute.args.invalidate := False
cache.io.cpu.execute.args.way := False
insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.args.address(1 downto 0) insert(MEMORY_ADDRESS_LOW) := cache.io.cpu.execute.args.address(1 downto 0)
} }
@ -228,7 +230,7 @@ object Bypasser{
} }
object DataCacheCpuCmdKind extends SpinalEnum{ object DataCacheCpuCmdKind extends SpinalEnum{
val MEMORY,FLUSH,EVICT = newElement() val MEMORY,LINE = newElement()
} }
object DataCacheCpuExecute{ object DataCacheCpuExecute{
@ -254,7 +256,8 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
val data = Bits(p.cpuDataWidth bit) val data = Bits(p.cpuDataWidth bit)
val mask = Bits(p.cpuDataWidth/8 bit) val mask = Bits(p.cpuDataWidth/8 bit)
val bypass = Bool val bypass = Bool
val all = Bool //Address should be zero when "all" is used val clean, invalidate, way = Bool
// val all = Bool //Address should be zero when "all" is used
} }
case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSlave{ case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSlave{
@ -330,7 +333,7 @@ class DataCache(p : DataCacheConfig) extends Component{
val io = new Bundle{ val io = new Bundle{
val cpu = slave(DataCacheCpuBus(p)) val cpu = slave(DataCacheCpuBus(p))
val mem = master(DataCacheMemBus(p)) val mem = master(DataCacheMemBus(p))
val flushDone = out Bool //It pulse at the same time than the manager.request.fire // val flushDone = out Bool //It pulse at the same time than the manager.request.fire
} }
val haltCpu = False val haltCpu = False
val lineWidth = bytePerLine*8 val lineWidth = bytePerLine*8
@ -385,8 +388,6 @@ class DataCache(p : DataCacheConfig) extends Component{
io.mem.cmd.payload.assignDontCare() io.mem.cmd.payload.assignDontCare()
val way = new Area{ val way = new Area{
val tags = Mem(new LineInfo(),wayLineCount) val tags = Mem(new LineInfo(),wayLineCount)
val data = Mem(Bits(wordWidth bit),wayWordCount) val data = Mem(Bits(wordWidth bit),wayWordCount)
@ -430,7 +431,6 @@ class DataCache(p : DataCacheConfig) extends Component{
val tagReadRspTwo = RegNextWhen(tagReadRspTwoRegIn ,tagReadRspTwoEnable) val tagReadRspTwo = RegNextWhen(tagReadRspTwoRegIn ,tagReadRspTwoEnable)
val dataReadRspTwoEnable = !io.cpu.writeBack.isStuck val dataReadRspTwoEnable = !io.cpu.writeBack.isStuck
val dataReadRspTwo = Bypasser.writeFirstRegWrap( val dataReadRspTwo = Bypasser.writeFirstRegWrap(
sample = dataReadRspTwoEnable, sample = dataReadRspTwoEnable,
@ -444,9 +444,6 @@ class DataCache(p : DataCacheConfig) extends Component{
) )
} }
// val dataReadedValue = Vec(id => RegNext(ways(id).dataReadRsp),ways.length)
when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){ when(io.cpu.execute.isValid && !io.cpu.execute.isStuck){
tagsReadCmd.valid := True tagsReadCmd.valid := True
tagsReadCmd.payload := io.cpu.execute.address(lineRange) tagsReadCmd.payload := io.cpu.execute.address(lineRange)
@ -458,7 +455,7 @@ class DataCache(p : DataCacheConfig) extends Component{
val victim = new Area{ val victim = new Area{
val requestIn = Stream(cloneable(new Bundle{ val requestIn = Stream(cloneable(new Bundle{
val way = UInt(log2Up(wayCount) bits) // val way = UInt(log2Up(wayCount) bits)
val address = UInt(p.addressWidth bits) val address = UInt(p.addressWidth bits)
})) }))
requestIn.valid := False requestIn.valid := False
@ -547,107 +544,70 @@ class DataCache(p : DataCacheConfig) extends Component{
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck) val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck)
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid && request.kind === MEMORY //TODO filter request kind
io.cpu.memory.mmuBus.cmd.virtualAddress := request.address io.cpu.memory.mmuBus.cmd.virtualAddress := request.address
io.cpu.memory.mmuBus.cmd.bypass := request.way
} }
val stageB = new Area { val stageB = new Area {
io.flushDone := False
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck) val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck) val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck)
// val waysHit = RegNextWhen(way.tagReadRspTwoRegIn.used && stageA.mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming // val waysHit = RegNextWhen(way.tagReadRspTwoRegIn.used && stageA.mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming
val waysHit = way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address val waysHit = way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address
//Evict the cache after reset
val requestValid = io.cpu.writeBack.isValid || RegNextWhen(False, !io.cpu.writeBack.isStuck, True)
request.kind init(DataCacheCpuCmdKind.EVICT)
request.all init(True)
mmuRsp.physicalAddress init(0)
io.cpu.writeBack.haltIt := requestValid
//Loader interface //Loader interface
val loaderValid = False val loaderValid = False
val loaderReady = False val loaderReady = False
val loadingDone = RegNext(loaderValid && loaderReady) init(False) //one cycle pulse val loadingDone = RegNext(loaderValid && loaderReady) init(False) //one cycle pulse
//delayedXX are used to relax logic timings in flush and evict modes
// val flushAllState = RegInit(False) //Used to keep logic timings fast val delayedIsStuck = RegNext(io.cpu.writeBack.isStuck)
// val flushAllDone = RegNext(False) init(False) val delayedWaysHitValid = RegNext(waysHit)
val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) setWhen(!io.cpu.memory.isStuck) val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) setWhen(!io.cpu.memory.isStuck)
val loadingNotDone = RegInit(False) clearWhen(loaderReady) setWhen(!io.cpu.memory.isStuck) val loadingNotDone = RegInit(False) clearWhen(loaderReady) setWhen(!io.cpu.memory.isStuck)
io.cpu.writeBack.haltIt := io.cpu.writeBack.isValid
io.cpu.writeBack.mmuMiss := False io.cpu.writeBack.mmuMiss := False
io.cpu.writeBack.badAddr := request.address io.cpu.writeBack.badAddr := request.address
//Evict the cache after reset logics
when(requestValid) { val bootEvicts = new Area {
switch(request.kind) { val valid = RegInit(True)
is(EVICT){ mmuRsp.physicalAddress init (0)
when(request.all){ when(valid) {
tagsWriteCmd.valid := True tagsWriteCmd.valid := valid
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := False tagsWriteCmd.data.used := False
when(mmuRsp.physicalAddress(lineRange) =/= lineCount-1){ when(mmuRsp.physicalAddress(lineRange) =/= lineCount - 1) {
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1 mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
}otherwise{ io.cpu.writeBack.haltIt := True
} otherwise {
valid := False
}
}
}
when(io.cpu.writeBack.isValid) {
switch(request.kind) {
is(LINE) {
if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss
}
when(delayedIsStuck && !mmuRsp.miss) {
when(delayedWaysHitValid || (request.way && way.tagReadRspTwo.used)) {
io.cpu.writeBack.haltIt.clearWhen(!(victim.requestIn.valid && !victim.requestIn.ready))
victim.requestIn.valid := request.clean && way.tagReadRspTwo.dirty
tagsWriteCmd.valid := victim.requestIn.ready
} otherwise{
io.cpu.writeBack.haltIt := False io.cpu.writeBack.haltIt := False
} }
}otherwise{ }
when(waysHit) {
tagsWriteCmd.valid := True victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange) tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := False tagsWriteCmd.data.used := !request.invalidate
tagsWriteCmd.data.dirty := !request.clean
} }
io.cpu.writeBack.haltIt := False
}
}
// is(FLUSH) { //TODO!
// when(request.all) {
// when(!flushAllState){
// victim.requestIn.valid := waysRead(0).tag.used && waysRead(0).tag.dirty
// victim.requestIn.way := writebackWayId
// victim.requestIn.address := writebackWayInfo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
//
// tagsWriteCmd.way := writebackWayId
// tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
// tagsWriteCmd.data.used := False
//
// when(!victim.requestIn.isStall) {
// mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
// flushAllDone := mmuRsp.physicalAddress(lineRange) === lineCount-1
// flushAllState := True
// tagsWriteCmd.valid := True
// }
// } otherwise{
// //Wait tag read
// flushAllState := False
// io.cpu.memory.haltIt.clearWhen(flushAllDone)
// io.flushDone := flushAllDone
// }
// } otherwise {
// when(delayedValid) {
// when(delayedWaysHitValid) {
// io.cpu.memory.haltIt.clearWhen(victim.requestIn.ready)
//
// victim.requestIn.valid := True
// victim.requestIn.way := writebackWayId
// victim.requestIn.address := writebackWayInfo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
//
// tagsWriteCmd.valid := victim.requestIn.ready
// tagsWriteCmd.way := writebackWayId
// tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
// tagsWriteCmd.data.used := False
// } otherwise{
// io.cpu.memory.haltIt := False
// io.flushDone := True
// }
// }
// }
// }
is(MEMORY) { is(MEMORY) {
if (catchMemoryTranslationMiss) { if (catchMemoryTranslationMiss) {
io.cpu.writeBack.mmuMiss := mmuRsp.miss io.cpu.writeBack.mmuMiss := mmuRsp.miss
@ -738,29 +698,3 @@ class DataCache(p : DataCacheConfig) extends Component{
} }
} }
} }
object DataCacheMain{
def main(args: Array[String]) {
//
// SpinalVhdl({
// implicit val p = DataCacheConfig(
// cacheSize =4096,
// bytePerLine =32,
// wayCount = 1,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32)
// new WrapWithReg.Wrapper(new DataCache(p)).setDefinitionName("TopLevel")
// })
// SpinalVhdl({
// implicit val p = DataCacheConfig(
// cacheSize =512,
// bytePerLine =16,
// wayCount = 1,
// addressWidth = 12,
// cpuDataWidth = 16,
// memDataWidth = 16)
// new DataCache(p)
// })
}
}

View File

@ -41,7 +41,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : B
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1) decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
} }
if(askMemoryTranslation != null) if(askMemoryTranslation)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig) mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig)
} }
@ -172,18 +172,6 @@ case class InstructionCacheCpuBus(p : InstructionCacheConfig) extends Bundle wit
} }
} }
case class InstructionCacheTranslationBus(p : InstructionCacheConfig) extends Bundle with IMasterSlave{
val virtualAddress = UInt(32 bits)
val physicalAddress = UInt(32 bits)
val error = if(p.catchAccessFault) Bool else null
override def asMaster(): Unit = {
out(virtualAddress)
in(physicalAddress)
if(p.catchAccessFault) in(error)
}
}
case class InstructionCacheMemCmd(p : InstructionCacheConfig) extends Bundle{ case class InstructionCacheMemCmd(p : InstructionCacheConfig) extends Bundle{
val address = UInt(p.addressWidth bit) val address = UInt(p.addressWidth bit)
} }
@ -470,6 +458,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.address
io.cpu.fetch.mmuBus.cmd.bypass := False
val mmuRsp = RegNextWhen(io.cpu.fetch.mmuBus.rsp,!io.cpu.decode.isStuck) val mmuRsp = RegNextWhen(io.cpu.fetch.mmuBus.rsp,!io.cpu.decode.isStuck)
val hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange))) val hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange)))

View File

@ -66,7 +66,7 @@ class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plu
val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12)) val cacheHits = cache.map(line => line.valid && line.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12))
val cacheHit = cacheHits.asBits.orR val cacheHit = cacheHits.asBits.orR
val cacheLine = MuxOH(cacheHits, cache) val cacheLine = MuxOH(cacheHits, cache)
val isInMmuRange = mmuRange(port.bus.cmd.virtualAddress) val isInMmuRange = mmuRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypass
val sharedMiss = RegInit(False) val sharedMiss = RegInit(False)
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits)) val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))

View File

@ -25,6 +25,7 @@ trait ExceptionService{
case class MemoryTranslatorCmd() extends Bundle{ case class MemoryTranslatorCmd() extends Bundle{
val isValid = Bool val isValid = Bool
val virtualAddress = UInt(32 bits) val virtualAddress = UInt(32 bits)
val bypass = Bool
} }
case class MemoryTranslatorRsp() extends Bundle{ case class MemoryTranslatorRsp() extends Bundle{
val physicalAddress = UInt(32 bits) val physicalAddress = UInt(32 bits)