DataCache add invalidate/clean/invalidateClean on a virtual address/way
This commit is contained in:
parent
48a5dc8e79
commit
5ba8ab7947
|
@ -63,7 +63,7 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
|
|||
List(SB, SH, SW).map(_ -> storeActions)
|
||||
)
|
||||
|
||||
if(askMemoryTranslation != null)
|
||||
if(askMemoryTranslation)
|
||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig)
|
||||
|
||||
if(catchSomething)
|
||||
|
@ -100,8 +100,10 @@ class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean
|
|||
default -> B"1111"
|
||||
) << 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.all := False
|
||||
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)
|
||||
}
|
||||
|
@ -228,7 +230,7 @@ object Bypasser{
|
|||
}
|
||||
|
||||
object DataCacheCpuCmdKind extends SpinalEnum{
|
||||
val MEMORY,FLUSH,EVICT = newElement()
|
||||
val MEMORY,LINE = newElement()
|
||||
}
|
||||
|
||||
object DataCacheCpuExecute{
|
||||
|
@ -254,7 +256,8 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
|
|||
val data = Bits(p.cpuDataWidth bit)
|
||||
val mask = Bits(p.cpuDataWidth/8 bit)
|
||||
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{
|
||||
|
@ -330,7 +333,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
val io = new Bundle{
|
||||
val cpu = slave(DataCacheCpuBus(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 lineWidth = bytePerLine*8
|
||||
|
@ -385,8 +388,6 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
io.mem.cmd.payload.assignDontCare()
|
||||
|
||||
|
||||
|
||||
|
||||
val way = new Area{
|
||||
val tags = Mem(new LineInfo(),wayLineCount)
|
||||
val data = Mem(Bits(wordWidth bit),wayWordCount)
|
||||
|
@ -430,7 +431,6 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
val tagReadRspTwo = RegNextWhen(tagReadRspTwoRegIn ,tagReadRspTwoEnable)
|
||||
|
||||
|
||||
|
||||
val dataReadRspTwoEnable = !io.cpu.writeBack.isStuck
|
||||
val dataReadRspTwo = Bypasser.writeFirstRegWrap(
|
||||
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){
|
||||
tagsReadCmd.valid := True
|
||||
tagsReadCmd.payload := io.cpu.execute.address(lineRange)
|
||||
|
@ -458,7 +455,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
|
||||
val victim = new Area{
|
||||
val requestIn = Stream(cloneable(new Bundle{
|
||||
val way = UInt(log2Up(wayCount) bits)
|
||||
// val way = UInt(log2Up(wayCount) bits)
|
||||
val address = UInt(p.addressWidth bits)
|
||||
}))
|
||||
requestIn.valid := False
|
||||
|
@ -547,107 +544,70 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
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.virtualAddress := request.address
|
||||
io.cpu.memory.mmuBus.cmd.bypass := request.way
|
||||
}
|
||||
|
||||
val stageB = new Area {
|
||||
io.flushDone := False
|
||||
|
||||
val request = RegNextWhen(stageA.request, !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 = 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
|
||||
val loaderValid = False
|
||||
val loaderReady = False
|
||||
val loadingDone = RegNext(loaderValid && loaderReady) init(False) //one cycle pulse
|
||||
|
||||
|
||||
// val flushAllState = RegInit(False) //Used to keep logic timings fast
|
||||
// val flushAllDone = RegNext(False) init(False)
|
||||
|
||||
//delayedXX are used to relax logic timings in flush and evict modes
|
||||
val delayedIsStuck = RegNext(io.cpu.writeBack.isStuck)
|
||||
val delayedWaysHitValid = RegNext(waysHit)
|
||||
|
||||
val victimNotSent = RegInit(False) clearWhen(victim.requestIn.ready) 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.badAddr := request.address
|
||||
|
||||
//Evict the cache after reset logics
|
||||
val bootEvicts = new Area {
|
||||
val valid = RegInit(True)
|
||||
mmuRsp.physicalAddress init (0)
|
||||
when(valid) {
|
||||
tagsWriteCmd.valid := valid
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := False
|
||||
when(mmuRsp.physicalAddress(lineRange) =/= lineCount - 1) {
|
||||
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
|
||||
io.cpu.writeBack.haltIt := True
|
||||
} otherwise {
|
||||
valid := False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(requestValid) {
|
||||
when(io.cpu.writeBack.isValid) {
|
||||
switch(request.kind) {
|
||||
is(EVICT){
|
||||
when(request.all){
|
||||
tagsWriteCmd.valid := True
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := False
|
||||
when(mmuRsp.physicalAddress(lineRange) =/= lineCount-1){
|
||||
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
|
||||
}otherwise{
|
||||
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
|
||||
}
|
||||
}otherwise{
|
||||
when(waysHit) {
|
||||
tagsWriteCmd.valid := True
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := False
|
||||
}
|
||||
io.cpu.writeBack.haltIt := False
|
||||
}
|
||||
|
||||
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||
tagsWriteCmd.data.used := !request.invalidate
|
||||
tagsWriteCmd.data.dirty := !request.clean
|
||||
}
|
||||
// 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) {
|
||||
if (catchMemoryTranslationMiss) {
|
||||
io.cpu.writeBack.mmuMiss := mmuRsp.miss
|
||||
|
@ -737,30 +697,4 @@ class DataCache(p : DataCacheConfig) extends Component{
|
|||
stageB.loaderReady := True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
// })
|
||||
}
|
||||
}
|
|
@ -41,7 +41,7 @@ class IBusCachedPlugin(config : InstructionCacheConfig, askMemoryTranslation : B
|
|||
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
|
||||
}
|
||||
|
||||
if(askMemoryTranslation != null)
|
||||
if(askMemoryTranslation)
|
||||
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{
|
||||
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.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 hit = tag.valid && tag.address === mmuRsp.physicalAddress(tagRange) && !(tag.loading && !lineLoader.loadedWords(mmuRsp.physicalAddress(wordRange)))
|
||||
|
|
|
@ -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 cacheHit = cacheHits.asBits.orR
|
||||
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 sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
|
||||
|
|
|
@ -25,6 +25,7 @@ trait ExceptionService{
|
|||
case class MemoryTranslatorCmd() extends Bundle{
|
||||
val isValid = Bool
|
||||
val virtualAddress = UInt(32 bits)
|
||||
val bypass = Bool
|
||||
}
|
||||
case class MemoryTranslatorRsp() extends Bundle{
|
||||
val physicalAddress = UInt(32 bits)
|
||||
|
|
Loading…
Reference in New Issue