MmuPlugin now support multiple stages, D$ can now take advantage of that
This commit is contained in:
parent
8e025aeeaa
commit
41ee8fd226
|
@ -65,6 +65,7 @@ trait RegFileService{
|
||||||
|
|
||||||
case class MemoryTranslatorCmd() extends Bundle{
|
case class MemoryTranslatorCmd() extends Bundle{
|
||||||
val isValid = Bool
|
val isValid = Bool
|
||||||
|
val isStuck = Bool
|
||||||
val virtualAddress = UInt(32 bits)
|
val virtualAddress = UInt(32 bits)
|
||||||
val bypassTranslation = Bool
|
val bypassTranslation = Bool
|
||||||
}
|
}
|
||||||
|
@ -82,9 +83,9 @@ case class MemoryTranslatorRspWay() extends Bundle{
|
||||||
val physical = UInt(32 bits)
|
val physical = UInt(32 bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class MemoryTranslatorBusParameter(wayCount : Int)
|
case class MemoryTranslatorBusParameter(wayCount : Int = 0, latency : Int = 0)
|
||||||
case class MemoryTranslatorBus(p : MemoryTranslatorBusParameter) extends Bundle with IMasterSlave{
|
case class MemoryTranslatorBus(p : MemoryTranslatorBusParameter) extends Bundle with IMasterSlave{
|
||||||
val cmd = MemoryTranslatorCmd()
|
val cmd = Vec(MemoryTranslatorCmd(), p.latency + 1)
|
||||||
val rsp = MemoryTranslatorRsp(p)
|
val rsp = MemoryTranslatorRsp(p)
|
||||||
val end = Bool
|
val end = Bool
|
||||||
val busy = Bool
|
val busy = Bool
|
||||||
|
|
|
@ -73,7 +73,8 @@ object TestsWorkspace {
|
||||||
// )
|
// )
|
||||||
),
|
),
|
||||||
memoryTranslatorPortConfig = MmuPortConfig(
|
memoryTranslatorPortConfig = MmuPortConfig(
|
||||||
portTlbSize = 4
|
portTlbSize = 4,
|
||||||
|
latency = 0
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
// ).newTightlyCoupledPort(TightlyCoupledPortParameter("iBusTc", a => a(30 downto 28) === 0x0 && a(5))),
|
||||||
|
@ -108,7 +109,8 @@ object TestsWorkspace {
|
||||||
// )
|
// )
|
||||||
),
|
),
|
||||||
memoryTranslatorPortConfig = MmuPortConfig(
|
memoryTranslatorPortConfig = MmuPortConfig(
|
||||||
portTlbSize = 4
|
portTlbSize = 4,
|
||||||
|
latency = 1
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,10 @@ object VexRiscvSmpClusterGen {
|
||||||
// )
|
// )
|
||||||
),
|
),
|
||||||
memoryTranslatorPortConfig = MmuPortConfig(
|
memoryTranslatorPortConfig = MmuPortConfig(
|
||||||
portTlbSize = 4
|
portTlbSize = 4,
|
||||||
|
latency = 1,
|
||||||
|
earlyRequireMmuLockup = true,
|
||||||
|
earlyCacheHits = true
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
@ -128,15 +128,14 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
|
||||||
case class DataCacheCpuMemory(p : DataCacheConfig, mmu : MemoryTranslatorBusParameter) extends Bundle with IMasterSlave{
|
case class DataCacheCpuMemory(p : DataCacheConfig, mmu : MemoryTranslatorBusParameter) extends Bundle with IMasterSlave{
|
||||||
val isValid = Bool
|
val isValid = Bool
|
||||||
val isStuck = Bool
|
val isStuck = Bool
|
||||||
val isRemoved = Bool
|
|
||||||
val isWrite = Bool
|
val isWrite = Bool
|
||||||
val address = UInt(p.addressWidth bit)
|
val address = UInt(p.addressWidth bit)
|
||||||
val mmuBus = MemoryTranslatorBus(mmu)
|
val mmuRsp = MemoryTranslatorRsp(mmu)
|
||||||
|
|
||||||
override def asMaster(): Unit = {
|
override def asMaster(): Unit = {
|
||||||
out(isValid, isStuck, isRemoved, address)
|
out(isValid, isStuck, address)
|
||||||
in(isWrite)
|
in(isWrite)
|
||||||
slave(mmuBus)
|
out(mmuRsp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,10 +618,6 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam
|
||||||
def stagePipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else 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 request = stagePipe(io.cpu.execute.args)
|
||||||
val mask = stagePipe(stage0.mask)
|
val mask = stagePipe(stage0.mask)
|
||||||
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid
|
|
||||||
io.cpu.memory.mmuBus.cmd.virtualAddress := io.cpu.memory.address
|
|
||||||
io.cpu.memory.mmuBus.cmd.bypassTranslation := False
|
|
||||||
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
|
|
||||||
io.cpu.memory.isWrite := request.wr
|
io.cpu.memory.isWrite := request.wr
|
||||||
|
|
||||||
val isAmo = if(withAmo) request.isAmo else False
|
val isAmo = if(withAmo) request.isAmo else False
|
||||||
|
@ -634,8 +629,8 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam
|
||||||
val o = CombInit(sync.w2o.busy)
|
val o = CombInit(sync.w2o.busy)
|
||||||
val i = CombInit(sync.w2i.busy)
|
val i = CombInit(sync.w2i.busy)
|
||||||
|
|
||||||
val s = io.cpu.memory.mmuBus.rsp.isIoAccess ? o | w
|
val s = io.cpu.memory.mmuRsp.isIoAccess ? o | w
|
||||||
val l = io.cpu.memory.mmuBus.rsp.isIoAccess ? i | r
|
val l = io.cpu.memory.mmuRsp.isIoAccess ? i | r
|
||||||
|
|
||||||
when(isAmo? (s || l) | (request.wr ? s | l)){
|
when(isAmo? (s || l) | (request.wr ? s | l)){
|
||||||
hazard := True
|
hazard := True
|
||||||
|
@ -647,15 +642,15 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam
|
||||||
|
|
||||||
val wayHits = earlyWaysHits generate Bits(wayCount bits)
|
val wayHits = earlyWaysHits generate Bits(wayCount bits)
|
||||||
val indirectTlbHitGen = (earlyWaysHits && !directTlbHit) generate new Area {
|
val indirectTlbHitGen = (earlyWaysHits && !directTlbHit) generate new Area {
|
||||||
wayHits := B(ways.map(way => (io.cpu.memory.mmuBus.rsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid)))
|
wayHits := B(ways.map(way => (io.cpu.memory.mmuRsp.physicalAddress(tagRange) === way.tagsReadRsp.address && way.tagsReadRsp.valid)))
|
||||||
}
|
}
|
||||||
val directTlbHitGen = (earlyWaysHits && directTlbHit) generate new Area {
|
val directTlbHitGen = (earlyWaysHits && directTlbHit) generate new Area {
|
||||||
val wayTlbHits = for (way <- ways) yield for (tlb <- io.cpu.memory.mmuBus.rsp.ways) yield {
|
val wayTlbHits = for (way <- ways) yield for (tlb <- io.cpu.memory.mmuRsp.ways) yield {
|
||||||
way.tagsReadRsp.address === tlb.physical(tagRange) && tlb.sel
|
way.tagsReadRsp.address === tlb.physical(tagRange) && tlb.sel
|
||||||
}
|
}
|
||||||
val translatedHits = B(wayTlbHits.map(_.orR))
|
val translatedHits = B(wayTlbHits.map(_.orR))
|
||||||
val bypassHits = B(ways.map(_.tagsReadRsp.address === io.cpu.memory.address(tagRange)))
|
val bypassHits = B(ways.map(_.tagsReadRsp.address === io.cpu.memory.address(tagRange)))
|
||||||
wayHits := (io.cpu.memory.mmuBus.rsp.bypassTranslation ? bypassHits | translatedHits) & B(ways.map(_.tagsReadRsp.valid))
|
wayHits := (io.cpu.memory.mmuRsp.bypassTranslation ? bypassHits | translatedHits) & B(ways.map(_.tagsReadRsp.valid))
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp))
|
val dataMux = earlyDataMux generate MuxOH(wayHits, ways.map(_.dataReadRsp))
|
||||||
|
@ -673,7 +668,7 @@ class DataCache(val p : DataCacheConfig, mmuParameter : MemoryTranslatorBusParam
|
||||||
def ramPipe[T <: Data](that : T) = if(mergeExecuteMemory) CombInit(that) else 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 request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
|
||||||
val mmuRspFreeze = False
|
val mmuRspFreeze = False
|
||||||
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze)
|
val mmuRsp = RegNextWhen(io.cpu.memory.mmuRsp, !io.cpu.writeBack.isStuck && !mmuRspFreeze)
|
||||||
val tagsReadRsp = ways.map(w => ramPipe(w.tagsReadRsp))
|
val tagsReadRsp = ways.map(w => ramPipe(w.tagsReadRsp))
|
||||||
val dataReadRsp = !earlyDataMux generate ways.map(w => ramPipe(w.dataReadRsp))
|
val dataReadRsp = !earlyDataMux generate ways.map(w => ramPipe(w.dataReadRsp))
|
||||||
val wayInvalidate = stagePipe(stageA. wayInvalidate)
|
val wayInvalidate = stagePipe(stageA. wayInvalidate)
|
||||||
|
|
|
@ -429,9 +429,9 @@ class InstructionCache(p : InstructionCacheConfig, mmuParameter : MemoryTranslat
|
||||||
io.cpu.fetch.data := (if(p.bypassGen) (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | cacheData) else cacheData)
|
io.cpu.fetch.data := (if(p.bypassGen) (io.cpu.fetch.dataBypassValid ? io.cpu.fetch.dataBypass | cacheData) else cacheData)
|
||||||
}
|
}
|
||||||
|
|
||||||
io.cpu.fetch.mmuBus.cmd.isValid := io.cpu.fetch.isValid
|
io.cpu.fetch.mmuBus.cmd.last.isValid := io.cpu.fetch.isValid
|
||||||
io.cpu.fetch.mmuBus.cmd.virtualAddress := io.cpu.fetch.pc
|
io.cpu.fetch.mmuBus.cmd.last.virtualAddress := io.cpu.fetch.pc
|
||||||
io.cpu.fetch.mmuBus.cmd.bypassTranslation := False
|
io.cpu.fetch.mmuBus.cmd.last.bypassTranslation := False
|
||||||
io.cpu.fetch.mmuBus.end := !io.cpu.fetch.isStuck || io.cpu.fetch.isRemoved
|
io.cpu.fetch.mmuBus.end := !io.cpu.fetch.isStuck || io.cpu.fetch.isRemoved
|
||||||
io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress
|
io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,10 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
||||||
import pipeline._
|
import pipeline._
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
|
val twoStageMmu = mmuBus.p.latency match {
|
||||||
|
case 0 => false
|
||||||
|
case 1 => true
|
||||||
|
}
|
||||||
|
|
||||||
val cache = new DataCache(
|
val cache = new DataCache(
|
||||||
this.config.copy(
|
this.config.copy(
|
||||||
|
@ -242,6 +246,12 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
||||||
)
|
)
|
||||||
cache.io.cpu.execute.args.size := size
|
cache.io.cpu.execute.args.size := size
|
||||||
|
|
||||||
|
if(twoStageMmu) {
|
||||||
|
mmuBus.cmd(0).isValid := cache.io.cpu.execute.isValid
|
||||||
|
mmuBus.cmd(0).isStuck := arbitration.isStuck
|
||||||
|
mmuBus.cmd(0).virtualAddress := cache.io.cpu.execute.address
|
||||||
|
mmuBus.cmd(0).bypassTranslation := False
|
||||||
|
}
|
||||||
|
|
||||||
cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT)
|
cache.io.cpu.flush.valid := arbitration.isValid && input(MEMORY_MANAGMENT)
|
||||||
cache.io.cpu.execute.args.totalyConsistent := input(MEMORY_FORCE_CONSTISTENCY)
|
cache.io.cpu.execute.args.totalyConsistent := input(MEMORY_FORCE_CONSTISTENCY)
|
||||||
|
@ -281,11 +291,15 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
||||||
|
|
||||||
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||||
cache.io.cpu.memory.isStuck := arbitration.isStuck
|
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 if(mmuAndBufferStage == execute) cache.io.cpu.execute.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
|
mmuBus.cmd.last.isValid := cache.io.cpu.memory.isValid
|
||||||
cache.io.cpu.memory.mmuBus.rsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite)
|
mmuBus.cmd.last.isStuck := cache.io.cpu.memory.isStuck
|
||||||
|
mmuBus.cmd.last.virtualAddress := cache.io.cpu.memory.address
|
||||||
|
mmuBus.cmd.last.bypassTranslation := False
|
||||||
|
mmuBus.end := !arbitration.isStuck || arbitration.removeIt
|
||||||
|
cache.io.cpu.memory.mmuRsp := mmuBus.rsp
|
||||||
|
cache.io.cpu.memory.mmuRsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
val managementStage = stages.last
|
val managementStage = stages.last
|
||||||
|
@ -397,9 +411,9 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire
|
execute.insert(IS_DBUS_SHARING) := dBusAccess.cmd.fire
|
||||||
|
mmuBus.cmd.last.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING))
|
||||||
|
if(twoStageMmu) mmuBus.cmd(0).bypassTranslation setWhen(execute.input(IS_DBUS_SHARING))
|
||||||
|
|
||||||
|
|
||||||
mmuBus.cmd.bypassTranslation setWhen(mmuAndBufferStage.input(IS_DBUS_SHARING))
|
|
||||||
if(mmuAndBufferStage != execute) (cache.io.cpu.memory.isValid 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))
|
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.valid := managementStage.input(IS_DBUS_SHARING) && !cache.io.cpu.writeBack.isWrite && (cache.io.cpu.redo || !cache.io.cpu.writeBack.haltIt)
|
||||||
|
|
|
@ -449,9 +449,10 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
||||||
insert(FORMAL_MEM_WDATA) := dBus.cmd.payload.data
|
insert(FORMAL_MEM_WDATA) := dBus.cmd.payload.data
|
||||||
|
|
||||||
val mmu = (mmuBus != null) generate new Area {
|
val mmu = (mmuBus != null) generate new Area {
|
||||||
mmuBus.cmd.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
mmuBus.cmd.last.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||||
mmuBus.cmd.virtualAddress := input(SRC_ADD).asUInt
|
mmuBus.cmd.last.isStuck := arbitration.isStuck
|
||||||
mmuBus.cmd.bypassTranslation := False
|
mmuBus.cmd.last.virtualAddress := input(SRC_ADD).asUInt
|
||||||
|
mmuBus.cmd.last.bypassTranslation := False
|
||||||
mmuBus.end := !arbitration.isStuck || arbitration.isRemoved
|
mmuBus.end := !arbitration.isStuck || arbitration.isRemoved
|
||||||
dBus.cmd.address := mmuBus.rsp.physicalAddress
|
dBus.cmd.address := mmuBus.rsp.physicalAddress
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
|
|
||||||
pipeline plug new FetchArea(pipeline) {
|
pipeline plug new FetchArea(pipeline) {
|
||||||
val cache = new InstructionCache(IBusCachedPlugin.this.config.copy(bypassGen = tightlyGen), mmuBus.p)
|
val cache = new InstructionCache(IBusCachedPlugin.this.config.copy(bypassGen = tightlyGen), if(mmuBus != null) mmuBus.p else MemoryTranslatorBusParameter(0,0))
|
||||||
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus")
|
iBus = master(new InstructionCacheMemBus(IBusCachedPlugin.this.config)).setName("iBus")
|
||||||
iBus <> cache.io.mem
|
iBus <> cache.io.mem
|
||||||
iBus.cmd.address.allowOverride := cache.io.mem.cmd.address
|
iBus.cmd.address.allowOverride := cache.io.mem.cmd.address
|
||||||
|
@ -251,7 +251,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
|
||||||
if (mmuBus != null) {
|
if (mmuBus != null) {
|
||||||
cache.io.cpu.fetch.mmuBus <> mmuBus
|
cache.io.cpu.fetch.mmuBus <> mmuBus
|
||||||
} else {
|
} else {
|
||||||
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
|
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.last.virtualAddress
|
||||||
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
|
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
|
||||||
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
|
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
|
||||||
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
|
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
|
||||||
|
|
|
@ -318,9 +318,9 @@ class IBusSimplePlugin( resetVector : BigInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
val mmu = (mmuBus != null) generate new Area {
|
val mmu = (mmuBus != null) generate new Area {
|
||||||
mmuBus.cmd.isValid := cmdForkStage.input.valid
|
mmuBus.cmd.last.isValid := cmdForkStage.input.valid
|
||||||
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
|
mmuBus.cmd.last.virtualAddress := cmdForkStage.input.payload
|
||||||
mmuBus.cmd.bypassTranslation := False
|
mmuBus.cmd.last.bypassTranslation := False
|
||||||
mmuBus.end := cmdForkStage.output.fire || externalFlush
|
mmuBus.end := cmdForkStage.output.fire || externalFlush
|
||||||
|
|
||||||
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00"
|
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ U"00"
|
||||||
|
|
|
@ -70,17 +70,17 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
||||||
|
|
||||||
val ports = for ((port, portId) <- sortedPortsInfo.zipWithIndex) yield new Area {
|
val ports = for ((port, portId) <- sortedPortsInfo.zipWithIndex) yield new Area {
|
||||||
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
|
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
|
||||||
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.last.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 = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation
|
val isInMmuRange = virtualRange(port.bus.cmd.last.virtualAddress) && !port.bus.cmd.last.bypassTranslation
|
||||||
|
|
||||||
val sharedMiss = RegInit(False)
|
val sharedMiss = RegInit(False)
|
||||||
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
|
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
|
||||||
val sharedAccessed = RegInit(B"00")
|
val sharedAccessed = RegInit(B"00")
|
||||||
val entryToReplace = Counter(port.args.portTlbSize)
|
val entryToReplace = Counter(port.args.portTlbSize)
|
||||||
|
|
||||||
val sharedAccessAsked = RegNext(port.bus.cmd.isValid && !cacheHit && sharedIterator < tlbSize && isInMmuRange)
|
val sharedAccessAsked = RegNext(port.bus.cmd.last.isValid && !cacheHit && sharedIterator < tlbSize && isInMmuRange)
|
||||||
val sharedAccessGranted = sharedAccessAsked && shared.free
|
val sharedAccessGranted = sharedAccessAsked && shared.free
|
||||||
when(sharedAccessGranted) {
|
when(sharedAccessGranted) {
|
||||||
shared.readAddr := sharedIterator.resized
|
shared.readAddr := sharedIterator.resized
|
||||||
|
@ -92,7 +92,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
||||||
}
|
}
|
||||||
|
|
||||||
when(sharedAccessed.msb){
|
when(sharedAccessed.msb){
|
||||||
when(shared.readData.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12)){
|
when(shared.readData.virtualAddress === port.bus.cmd.last.virtualAddress(31 downto 12)){
|
||||||
cache(entryToReplace) := shared.readData
|
cache(entryToReplace) := shared.readData
|
||||||
entryToReplace.increment()
|
entryToReplace.increment()
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
||||||
|
|
||||||
|
|
||||||
when(isInMmuRange) {
|
when(isInMmuRange) {
|
||||||
port.bus.rsp.physicalAddress := cacheLine.physicalAddress @@ port.bus.cmd.virtualAddress(11 downto 0)
|
port.bus.rsp.physicalAddress := cacheLine.physicalAddress @@ port.bus.cmd.last.virtualAddress(11 downto 0)
|
||||||
port.bus.rsp.allowRead := cacheLine.allowRead
|
port.bus.rsp.allowRead := cacheLine.allowRead
|
||||||
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
||||||
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
||||||
|
@ -116,7 +116,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
|
||||||
// port.bus.rsp.hit := cacheHit
|
// port.bus.rsp.hit := cacheHit
|
||||||
// port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
|
// port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
|
||||||
} otherwise {
|
} otherwise {
|
||||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress
|
||||||
port.bus.rsp.allowRead := True
|
port.bus.rsp.allowRead := True
|
||||||
port.bus.rsp.allowWrite := True
|
port.bus.rsp.allowWrite := True
|
||||||
port.bus.rsp.allowExecute := True
|
port.bus.rsp.allowExecute := True
|
||||||
|
|
|
@ -34,9 +34,9 @@ object MmuPort{
|
||||||
val PRIORITY_DATA = 1
|
val PRIORITY_DATA = 1
|
||||||
val PRIORITY_INSTRUCTION = 0
|
val PRIORITY_INSTRUCTION = 0
|
||||||
}
|
}
|
||||||
case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConfig, id : Int/*, exceptionBus: Flow[ExceptionCause]*/)
|
case class MmuPort(bus : MemoryTranslatorBus, priority : Int, args : MmuPortConfig, id : Int)
|
||||||
|
|
||||||
case class MmuPortConfig(portTlbSize : Int)
|
case class MmuPortConfig(portTlbSize : Int, latency : Int = 0, earlyRequireMmuLockup : Boolean = false, earlyCacheHits : Boolean = false)
|
||||||
|
|
||||||
class MmuPlugin(ioRange : UInt => Bool,
|
class MmuPlugin(ioRange : UInt => Bool,
|
||||||
virtualRange : UInt => Bool = address => True,
|
virtualRange : UInt => Bool = address => True,
|
||||||
|
@ -48,7 +48,7 @@ class MmuPlugin(ioRange : UInt => Bool,
|
||||||
|
|
||||||
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
|
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
|
||||||
val config = args.asInstanceOf[MmuPortConfig]
|
val config = args.asInstanceOf[MmuPortConfig]
|
||||||
val port = MmuPort(MemoryTranslatorBus(MemoryTranslatorBusParameter(wayCount = config.portTlbSize)),priority, config, portsInfo.length)
|
val port = MmuPort(MemoryTranslatorBus(MemoryTranslatorBusParameter(wayCount = config.portTlbSize, latency = config.latency)),priority, config, portsInfo.length)
|
||||||
portsInfo += port
|
portsInfo += port
|
||||||
port.bus
|
port.bus
|
||||||
}
|
}
|
||||||
|
@ -103,33 +103,51 @@ class MmuPlugin(ioRange : UInt => Bool,
|
||||||
val ports = for (port <- sortedPortsInfo) yield new Area {
|
val ports = for (port <- sortedPortsInfo) yield new Area {
|
||||||
val handle = port
|
val handle = port
|
||||||
val id = port.id
|
val id = port.id
|
||||||
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
|
|
||||||
val cacheHits = cache.map(line => line.valid && line.virtualAddress(1) === port.bus.cmd.virtualAddress(31 downto 22) && (line.superPage || line.virtualAddress(0) === port.bus.cmd.virtualAddress(21 downto 12)))
|
|
||||||
val cacheHit = cacheHits.asBits.orR
|
|
||||||
val cacheLine = MuxOH(cacheHits, cache)
|
|
||||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||||
val entryToReplace = Counter(port.args.portTlbSize)
|
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
|
||||||
val requireMmuLockup = virtualRange(port.bus.cmd.virtualAddress) && !port.bus.cmd.bypassTranslation && csr.satp.mode
|
|
||||||
|
def toRsp[T <: Data](data : T, from : MemoryTranslatorCmd) : T = from match {
|
||||||
|
case _ if from == port.bus.cmd.last => data
|
||||||
|
case _ => {
|
||||||
|
val next = port.bus.cmd.dropWhile(_ != from)(1)
|
||||||
|
toRsp(RegNextWhen(data, !next.isStuck), next)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val requireMmuLockupCmd = port.bus.cmd.takeRight(if(port.args.earlyRequireMmuLockup) 2 else 1).head
|
||||||
|
|
||||||
|
val requireMmuLockupCalc = virtualRange(requireMmuLockupCmd.virtualAddress) && !requireMmuLockupCmd.bypassTranslation && csr.satp.mode
|
||||||
if(!enableMmuInMachineMode) {
|
if(!enableMmuInMachineMode) {
|
||||||
requireMmuLockup clearWhen(!csr.status.mprv && privilegeService.isMachine())
|
requireMmuLockupCalc clearWhen(!csr.status.mprv && privilegeService.isMachine())
|
||||||
when(privilegeService.isMachine()) {
|
when(privilegeService.isMachine()) {
|
||||||
if (port.priority == MmuPort.PRIORITY_DATA) {
|
if (port.priority == MmuPort.PRIORITY_DATA) {
|
||||||
requireMmuLockup clearWhen (!csr.status.mprv || pipeline(MPP) === 3)
|
requireMmuLockupCalc clearWhen (!csr.status.mprv || pipeline(MPP) === 3)
|
||||||
} else {
|
} else {
|
||||||
requireMmuLockup := False
|
requireMmuLockupCalc := False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val cacheHitsCmd = port.bus.cmd.takeRight(if(port.args.earlyCacheHits) 2 else 1).head
|
||||||
|
val cacheHitsCalc = B(cache.map(line => line.valid && line.virtualAddress(1) === cacheHitsCmd.virtualAddress(31 downto 22) && (line.superPage || line.virtualAddress(0) === cacheHitsCmd.virtualAddress(21 downto 12))))
|
||||||
|
|
||||||
|
|
||||||
|
val requireMmuLockup = toRsp(requireMmuLockupCalc, requireMmuLockupCmd)
|
||||||
|
val cacheHits = toRsp(cacheHitsCalc, cacheHitsCmd)
|
||||||
|
|
||||||
|
val cacheHit = cacheHits.asBits.orR
|
||||||
|
val cacheLine = MuxOH(cacheHits, cache)
|
||||||
|
val entryToReplace = Counter(port.args.portTlbSize)
|
||||||
|
|
||||||
|
|
||||||
when(requireMmuLockup) {
|
when(requireMmuLockup) {
|
||||||
port.bus.rsp.physicalAddress := cacheLine.physicalAddress(1) @@ (cacheLine.superPage ? port.bus.cmd.virtualAddress(21 downto 12) | cacheLine.physicalAddress(0)) @@ port.bus.cmd.virtualAddress(11 downto 0)
|
port.bus.rsp.physicalAddress := cacheLine.physicalAddress(1) @@ (cacheLine.superPage ? port.bus.cmd.last.virtualAddress(21 downto 12) | cacheLine.physicalAddress(0)) @@ port.bus.cmd.last.virtualAddress(11 downto 0)
|
||||||
port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute
|
port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute
|
||||||
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
port.bus.rsp.allowWrite := cacheLine.allowWrite
|
||||||
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
port.bus.rsp.allowExecute := cacheLine.allowExecute
|
||||||
port.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser())
|
port.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser())
|
||||||
port.bus.rsp.refilling := !cacheHit
|
port.bus.rsp.refilling := !cacheHit
|
||||||
} otherwise {
|
} otherwise {
|
||||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress
|
||||||
port.bus.rsp.allowRead := True
|
port.bus.rsp.allowRead := True
|
||||||
port.bus.rsp.allowWrite := True
|
port.bus.rsp.allowWrite := True
|
||||||
port.bus.rsp.allowExecute := True
|
port.bus.rsp.allowExecute := True
|
||||||
|
@ -141,7 +159,7 @@ class MmuPlugin(ioRange : UInt => Bool,
|
||||||
port.bus.rsp.bypassTranslation := !requireMmuLockup
|
port.bus.rsp.bypassTranslation := !requireMmuLockup
|
||||||
for(wayId <- 0 until port.args.portTlbSize){
|
for(wayId <- 0 until port.args.portTlbSize){
|
||||||
port.bus.rsp.ways(wayId).sel := cacheHits(wayId)
|
port.bus.rsp.ways(wayId).sel := cacheHits(wayId)
|
||||||
port.bus.rsp.ways(wayId).physical := cache(wayId).physicalAddress(1) @@ (cache(wayId).superPage ? port.bus.cmd.virtualAddress(21 downto 12) | cache(wayId).physicalAddress(0)) @@ port.bus.cmd.virtualAddress(11 downto 0)
|
port.bus.rsp.ways(wayId).physical := cache(wayId).physicalAddress(1) @@ (cache(wayId).superPage ? port.bus.cmd.last.virtualAddress(21 downto 12) | cache(wayId).physicalAddress(0)) @@ port.bus.cmd.last.virtualAddress(11 downto 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid keeping any invalid line in the cache after an exception.
|
// Avoid keeping any invalid line in the cache after an exception.
|
||||||
|
@ -186,13 +204,13 @@ class MmuPlugin(ioRange : UInt => Bool,
|
||||||
dBusAccess.cmd.data.assignDontCare()
|
dBusAccess.cmd.data.assignDontCare()
|
||||||
dBusAccess.cmd.writeMask.assignDontCare()
|
dBusAccess.cmd.writeMask.assignDontCare()
|
||||||
|
|
||||||
val refills = OHMasking.last(B(sortedPortsInfo.map(port => port.bus.cmd.isValid && port.bus.rsp.refilling)))
|
val refills = OHMasking.last(B(sortedPortsInfo.map(port => port.bus.cmd.last.isValid && port.bus.rsp.refilling)))
|
||||||
switch(state){
|
switch(state){
|
||||||
is(State.IDLE){
|
is(State.IDLE){
|
||||||
when(refills.orR){
|
when(refills.orR){
|
||||||
portSortedOh := refills
|
portSortedOh := refills
|
||||||
state := State.L1_CMD
|
state := State.L1_CMD
|
||||||
val address = MuxOH(refills, sortedPortsInfo.map(_.bus.cmd.virtualAddress))
|
val address = MuxOH(refills, sortedPortsInfo.map(_.bus.cmd.last.virtualAddress))
|
||||||
vpn(1) := address(31 downto 22)
|
vpn(1) := address(31 downto 22)
|
||||||
vpn(0) := address(21 downto 12)
|
vpn(0) := address(21 downto 12)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis
|
||||||
|
|
||||||
val core = pipeline plug new Area {
|
val core = pipeline plug new Area {
|
||||||
val ports = for ((port, portId) <- portsInfo.zipWithIndex) yield new Area {
|
val ports = for ((port, portId) <- portsInfo.zipWithIndex) yield new Area {
|
||||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress
|
||||||
port.bus.rsp.allowRead := True
|
port.bus.rsp.allowRead := True
|
||||||
port.bus.rsp.allowWrite := True
|
port.bus.rsp.allowWrite := True
|
||||||
port.bus.rsp.allowExecute := True
|
port.bus.rsp.allowExecute := True
|
||||||
|
|
|
@ -405,13 +405,12 @@ class DBusDimension extends VexRiscvDimension("DBus") {
|
||||||
|
|
||||||
override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = {
|
override def randomPositionImpl(universes: Seq[ConfigUniverse], r: Random) = {
|
||||||
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
|
val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL)
|
||||||
val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig( portTlbSize = 4) else null
|
|
||||||
val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY)
|
val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY)
|
||||||
val noWriteBack = universes.contains(VexRiscvUniverse.NO_WRITEBACK)
|
val noWriteBack = universes.contains(VexRiscvUniverse.NO_WRITEBACK)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(r.nextDouble() < 0.4 || noMemory){
|
if(r.nextDouble() < 0.4 || noMemory){
|
||||||
|
val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig( portTlbSize = 4, latency = 0) else null
|
||||||
val withLrSc = catchAll
|
val withLrSc = catchAll
|
||||||
val earlyInjection = r.nextBoolean() && !universes.contains(VexRiscvUniverse.NO_WRITEBACK)
|
val earlyInjection = r.nextBoolean() && !universes.contains(VexRiscvUniverse.NO_WRITEBACK)
|
||||||
new VexRiscvPosition("Simple" + (if(earlyInjection) "Early" else "Late")) {
|
new VexRiscvPosition("Simple" + (if(earlyInjection) "Early" else "Late")) {
|
||||||
|
@ -426,6 +425,8 @@ class DBusDimension extends VexRiscvDimension("DBus") {
|
||||||
// override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition])
|
// override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
val twoStageMmu = r.nextBoolean() && !noMemory && !noWriteBack
|
||||||
|
val mmuConfig = if(universes.contains(VexRiscvUniverse.MMU)) MmuPortConfig(portTlbSize = 4, latency = if(twoStageMmu) 1 else 0, earlyRequireMmuLockup = Random.nextBoolean() && twoStageMmu, earlyCacheHits = Random.nextBoolean() && twoStageMmu) else null
|
||||||
val memDataWidth = List(32,64,128)(r.nextInt(3))
|
val memDataWidth = List(32,64,128)(r.nextInt(3))
|
||||||
val bytePerLine = Math.max(memDataWidth/8, List(8,16,32,64)(r.nextInt(4)))
|
val bytePerLine = Math.max(memDataWidth/8, List(8,16,32,64)(r.nextInt(4)))
|
||||||
var cacheSize = 0
|
var cacheSize = 0
|
||||||
|
@ -443,7 +444,7 @@ class DBusDimension extends VexRiscvDimension("DBus") {
|
||||||
cacheSize = 512 << r.nextInt(5)
|
cacheSize = 512 << r.nextInt(5)
|
||||||
wayCount = 1 << r.nextInt(3)
|
wayCount = 1 << r.nextInt(3)
|
||||||
}while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096))
|
}while(cacheSize/wayCount < 512 || (catchAll && cacheSize/wayCount > 4096))
|
||||||
new VexRiscvPosition(s"Cached${memDataWidth}d" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(dBusCmdMasterPipe) "Cmp " else "") + (if(dBusCmdSlavePipe) "Csp " else "") + (if(dBusRspSlavePipe) "Rsp " else "") + (if(relaxedMemoryTranslationRegister) "Rmtr " else "") + (if(earlyWaysHits) "Ewh " else "") + (if(withAmo) "Amo " else "") + (if(withSmp) "Smp " else "") + (if(directTlbHit) "Dtlb " else "")) {
|
new VexRiscvPosition(s"Cached${memDataWidth}d" + "S" + cacheSize + "W" + wayCount + "BPL" + bytePerLine + (if(dBusCmdMasterPipe) "Cmp " else "") + (if(dBusCmdSlavePipe) "Csp " else "") + (if(dBusRspSlavePipe) "Rsp " else "") + (if(relaxedMemoryTranslationRegister) "Rmtr " else "") + (if(earlyWaysHits) "Ewh " else "") + (if(withAmo) "Amo " else "") + (if(withSmp) "Smp " else "") + (if(directTlbHit) "Dtlb " else "") + (if(twoStageMmu) "Tsmmu " else "")) {
|
||||||
override def testParam = s"DBUS=CACHED DBUS_DATA_WIDTH=$memDataWidth " + (if(withLrSc) "LRSC=yes " else "") + (if(withAmo) "AMO=yes " else "") + (if(withSmp) "DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes " else "")
|
override def testParam = s"DBUS=CACHED DBUS_DATA_WIDTH=$memDataWidth " + (if(withLrSc) "LRSC=yes " else "") + (if(withAmo) "AMO=yes " else "") + (if(withSmp) "DBUS_EXCLUSIVE=yes DBUS_INVALIDATE=yes " else "")
|
||||||
|
|
||||||
override def applyOn(config: VexRiscvConfig): Unit = {
|
override def applyOn(config: VexRiscvConfig): Unit = {
|
||||||
|
|
Loading…
Reference in New Issue