Fix multi port MMU design
Change machineCSR to handle exceptions from the writeBack stage Change the DBusCachedPlugin to emit miss exception
This commit is contained in:
parent
2ed33106d6
commit
889a040f90
|
@ -12,20 +12,23 @@ case class DataCacheConfig( cacheSize : Int,
|
||||||
addressWidth : Int,
|
addressWidth : Int,
|
||||||
cpuDataWidth : Int,
|
cpuDataWidth : Int,
|
||||||
memDataWidth : Int,
|
memDataWidth : Int,
|
||||||
catchAccessFault : Boolean = false,
|
catchAccessFault : Boolean,
|
||||||
|
catchMemoryTranslationMiss : Boolean,
|
||||||
tagSizeShift : Int = 0){ //Used to force infering ram
|
tagSizeShift : Int = 0){ //Used to force infering ram
|
||||||
def burstSize = bytePerLine*8/memDataWidth
|
def burstSize = bytePerLine*8/memDataWidth
|
||||||
val burstLength = bytePerLine/(memDataWidth/8)
|
val burstLength = bytePerLine/(memDataWidth/8)
|
||||||
assert(catchAccessFault == false)
|
assert(catchAccessFault == false)
|
||||||
|
def catchSomething = catchAccessFault || catchMemoryTranslationMiss
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DataMmuConfig(dTlbSize : Int)
|
|
||||||
|
|
||||||
|
|
||||||
class DBusCachedPlugin(config : DataCacheConfig, mmuConfig : DataMmuConfig = null) extends Plugin[VexRiscv]{
|
|
||||||
|
class DBusCachedPlugin(config : DataCacheConfig, askMemoryTranslation : Boolean = false, memoryTranslatorPortConfig : Any = null) extends Plugin[VexRiscv]{
|
||||||
import config._
|
import config._
|
||||||
var dBus : DataCacheMemBus = null
|
var dBus : DataCacheMemBus = null
|
||||||
var mmuBus : MemoryTranslatorBus = null
|
var mmuBus : MemoryTranslatorBus = null
|
||||||
|
var exceptionBus : Flow[ExceptionCause] = null
|
||||||
object MEMORY_ENABLE extends Stageable(Bool)
|
object MEMORY_ENABLE extends Stageable(Bool)
|
||||||
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
|
||||||
|
|
||||||
|
@ -60,8 +63,11 @@ class DBusCachedPlugin(config : DataCacheConfig, mmuConfig : DataMmuConfig = nul
|
||||||
List(SB, SH, SW).map(_ -> storeActions)
|
List(SB, SH, SW).map(_ -> storeActions)
|
||||||
)
|
)
|
||||||
|
|
||||||
if(mmuConfig != null)
|
if(askMemoryTranslation != null)
|
||||||
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,mmuConfig.dTlbSize)
|
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig)
|
||||||
|
|
||||||
|
if(catchSomething)
|
||||||
|
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def build(pipeline: VexRiscv): Unit = {
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
|
@ -119,6 +125,7 @@ class DBusCachedPlugin(config : DataCacheConfig, mmuConfig : DataMmuConfig = nul
|
||||||
import writeBack._
|
import writeBack._
|
||||||
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
cache.io.cpu.writeBack.isValid := arbitration.isValid && input(MEMORY_ENABLE)
|
||||||
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
cache.io.cpu.writeBack.isStuck := arbitration.isStuck
|
||||||
|
if(catchSomething) cache.io.cpu.writeBack.exceptionBus <> exceptionBus
|
||||||
arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt)
|
arbitration.haltIt.setWhen(cache.io.cpu.writeBack.haltIt)
|
||||||
|
|
||||||
val rspShifted = Bits(32 bits)
|
val rspShifted = Bits(32 bits)
|
||||||
|
@ -266,10 +273,12 @@ case class DataCacheCpuWriteBack(p : DataCacheConfig) extends Bundle with IMaste
|
||||||
val isStuck = Bool
|
val isStuck = Bool
|
||||||
val haltIt = Bool
|
val haltIt = Bool
|
||||||
val data = Bits(p.cpuDataWidth bit)
|
val data = Bits(p.cpuDataWidth bit)
|
||||||
|
val exceptionBus = if(p.catchSomething) Flow(ExceptionCause()) else null
|
||||||
|
|
||||||
override def asMaster(): Unit = {
|
override def asMaster(): Unit = {
|
||||||
out(isValid,isStuck)
|
out(isValid,isStuck)
|
||||||
in(haltIt, data)
|
in(haltIt, data)
|
||||||
|
slaveWithNull(exceptionBus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +319,7 @@ case class DataCacheMemBus(p : DataCacheConfig) extends Bundle with IMasterSlave
|
||||||
|
|
||||||
class DataCache(p : DataCacheConfig) extends Component{
|
class DataCache(p : DataCacheConfig) extends Component{
|
||||||
import p._
|
import p._
|
||||||
|
import DataCacheCpuCmdKind._
|
||||||
assert(wayCount == 1)
|
assert(wayCount == 1)
|
||||||
assert(cpuDataWidth == memDataWidth)
|
assert(cpuDataWidth == memDataWidth)
|
||||||
|
|
||||||
|
@ -531,7 +541,7 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
|
|
||||||
val stageA = new Area{
|
val stageA = new Area{
|
||||||
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 //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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +575,12 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
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)
|
||||||
|
|
||||||
import DataCacheCpuCmdKind._
|
if(catchSomething){
|
||||||
|
io.cpu.writeBack.exceptionBus.valid := False
|
||||||
|
io.cpu.writeBack.exceptionBus.code := 13
|
||||||
|
io.cpu.writeBack.exceptionBus.badAddr := request.address
|
||||||
|
}
|
||||||
|
|
||||||
when(requestValid) {
|
when(requestValid) {
|
||||||
switch(request.kind) {
|
switch(request.kind) {
|
||||||
is(EVICT){
|
is(EVICT){
|
||||||
|
@ -631,41 +646,47 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
is(MEMORY) {
|
is(MEMORY) {
|
||||||
when(request.bypass) {
|
if (catchMemoryTranslationMiss) {
|
||||||
val memCmdSent = RegInit(False)
|
io.cpu.writeBack.exceptionBus.valid := mmuRsp.miss
|
||||||
when(!victim.request.valid) { //Avoid mixing memory request while victim is pending
|
}
|
||||||
io.mem.cmd.wr := request.wr
|
when(Bool(!catchMemoryTranslationMiss) || !mmuRsp.miss) {
|
||||||
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0,wordRange.low bit)
|
when(request.bypass) {
|
||||||
io.mem.cmd.mask := request.mask
|
val memCmdSent = RegInit(False)
|
||||||
io.mem.cmd.data := request.data
|
when(!victim.request.valid) {
|
||||||
io.mem.cmd.length := 1
|
//Avoid mixing memory request while victim is pending
|
||||||
|
io.mem.cmd.wr := request.wr
|
||||||
|
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0, wordRange.low bit)
|
||||||
|
io.mem.cmd.mask := request.mask
|
||||||
|
io.mem.cmd.data := request.data
|
||||||
|
io.mem.cmd.length := 1
|
||||||
|
|
||||||
when(!memCmdSent) {
|
when(!memCmdSent) {
|
||||||
io.mem.cmd.valid := True
|
io.mem.cmd.valid := True
|
||||||
memCmdSent setWhen(io.mem.cmd.ready)
|
memCmdSent setWhen (io.mem.cmd.ready)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.cpu.writeBack.haltIt.clearWhen(memCmdSent && (io.mem.rsp.fire || request.wr)) //Cut mem.cmd.ready path but insert one cycle stall when write
|
||||||
}
|
}
|
||||||
|
memCmdSent clearWhen (!io.cpu.writeBack.isStuck)
|
||||||
io.cpu.writeBack.haltIt.clearWhen(memCmdSent && (io.mem.rsp.fire || request.wr)) //Cut mem.cmd.ready path but insert one cycle stall when write
|
|
||||||
}
|
|
||||||
memCmdSent clearWhen(!io.cpu.writeBack.isStuck)
|
|
||||||
} otherwise {
|
|
||||||
when(waysHit || !loadingNotDone){
|
|
||||||
io.cpu.writeBack.haltIt := False
|
|
||||||
dataWriteCmd.valid := request.wr
|
|
||||||
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
|
|
||||||
dataWriteCmd.data := request.data
|
|
||||||
dataWriteCmd.mask := request.mask
|
|
||||||
|
|
||||||
tagsWriteCmd.valid := !loadingNotDone || request.wr
|
|
||||||
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
|
||||||
tagsWriteCmd.data.used := True
|
|
||||||
tagsWriteCmd.data.dirty := request.wr
|
|
||||||
tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange)
|
|
||||||
} otherwise {
|
} otherwise {
|
||||||
val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty
|
when(waysHit || !loadingNotDone) {
|
||||||
loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM
|
io.cpu.writeBack.haltIt := False
|
||||||
victim.requestIn.valid := victimRequired && victimNotSent
|
dataWriteCmd.valid := request.wr
|
||||||
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
|
||||||
|
dataWriteCmd.data := request.data
|
||||||
|
dataWriteCmd.mask := request.mask
|
||||||
|
|
||||||
|
tagsWriteCmd.valid := !loadingNotDone || request.wr
|
||||||
|
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
|
||||||
|
tagsWriteCmd.data.used := True
|
||||||
|
tagsWriteCmd.data.dirty := request.wr
|
||||||
|
tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange)
|
||||||
|
} otherwise {
|
||||||
|
val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty
|
||||||
|
loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM
|
||||||
|
victim.requestIn.valid := victimRequired && victimNotSent
|
||||||
|
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,17 +738,17 @@ class DataCache(p : DataCacheConfig) extends Component{
|
||||||
|
|
||||||
object DataCacheMain{
|
object DataCacheMain{
|
||||||
def main(args: Array[String]) {
|
def main(args: Array[String]) {
|
||||||
|
//
|
||||||
SpinalVhdl({
|
// SpinalVhdl({
|
||||||
implicit val p = DataCacheConfig(
|
// implicit val p = DataCacheConfig(
|
||||||
cacheSize =4096,
|
// cacheSize =4096,
|
||||||
bytePerLine =32,
|
// bytePerLine =32,
|
||||||
wayCount = 1,
|
// wayCount = 1,
|
||||||
addressWidth = 32,
|
// addressWidth = 32,
|
||||||
cpuDataWidth = 32,
|
// cpuDataWidth = 32,
|
||||||
memDataWidth = 32)
|
// memDataWidth = 32)
|
||||||
new WrapWithReg.Wrapper(new DataCache(p)).setDefinitionName("TopLevel")
|
// new WrapWithReg.Wrapper(new DataCache(p)).setDefinitionName("TopLevel")
|
||||||
})
|
// })
|
||||||
// SpinalVhdl({
|
// SpinalVhdl({
|
||||||
// implicit val p = DataCacheConfig(
|
// implicit val p = DataCacheConfig(
|
||||||
// cacheSize =512,
|
// cacheSize =512,
|
||||||
|
|
|
@ -245,7 +245,6 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
pipelineLiberator.enable setWhen(pipelineHasException)
|
pipelineLiberator.enable setWhen(pipelineHasException)
|
||||||
|
|
||||||
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
|
val groupedByStage = exceptionPortsInfos.map(_.stage).distinct.map(s => {
|
||||||
assert(s != writeBack)
|
|
||||||
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
|
val stagePortsInfos = exceptionPortsInfos.filter(_.stage == s).sortWith(_.priority > _.priority)
|
||||||
val stagePort = stagePortsInfos.length match{
|
val stagePort = stagePortsInfos.length match{
|
||||||
case 1 => stagePortsInfos.head.port
|
case 1 => stagePortsInfos.head.port
|
||||||
|
@ -309,8 +308,8 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
True -> ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7))),
|
True -> ((mip.MEIP && mie.MEIE) ? U(11) | ((mip.MSIP && mie.MSIE) ? U(3) | U(7))),
|
||||||
False -> (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.code else U(0))
|
False -> (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.code else U(0))
|
||||||
)
|
)
|
||||||
when(exception){
|
when(RegNext(exception)){
|
||||||
mbadaddr := exceptionPortCtrl.exceptionContext.badAddr
|
mbadaddr := (if(exceptionPortCtrl != null) exceptionPortCtrl.exceptionContext.badAddr else U(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,17 +342,22 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
|
|
||||||
val imm = IMM(input(INSTRUCTION))
|
val imm = IMM(input(INSTRUCTION))
|
||||||
|
|
||||||
val writeEnable = arbitration.isValid && !arbitration.isStuckByOthers && !arbitration.removeIt && input(IS_CSR) &&
|
|
||||||
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|
|
||||||
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)))
|
|
||||||
|
|
||||||
|
|
||||||
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
|
val writeSrc = input(INSTRUCTION)(14) ? imm.z.asBits.resized | input(SRC1)
|
||||||
val readData = B(0, 32 bits)
|
val readData = B(0, 32 bits)
|
||||||
|
val readDataReg = RegNext(readData)
|
||||||
|
val readDataRegValid = Reg(Bool) setWhen(arbitration.isValid) clearWhen(!arbitration.isStuck)
|
||||||
val writeData = input(INSTRUCTION)(13).mux(
|
val writeData = input(INSTRUCTION)(13).mux(
|
||||||
False -> writeSrc,
|
False -> writeSrc,
|
||||||
True -> Mux(input(INSTRUCTION)(12), readData & ~writeSrc, readData | writeSrc)
|
True -> Mux(input(INSTRUCTION)(12), readDataReg & ~writeSrc, readDataReg | writeSrc)
|
||||||
)
|
)
|
||||||
|
val writeInstruction = arbitration.isValid && input(IS_CSR)
|
||||||
|
(!((input(INSTRUCTION)(14 downto 13) === "01" && input(INSTRUCTION)(rs1Range) === 0)
|
||||||
|
|| (input(INSTRUCTION)(14 downto 13) === "11" && imm.z === 0)))
|
||||||
|
|
||||||
|
arbitration.haltIt setWhen(writeInstruction && !readDataRegValid)
|
||||||
|
val writeEnable = writeInstruction && !arbitration.isStuckByOthers && !arbitration.removeIt && readDataRegValid
|
||||||
|
|
||||||
when(arbitration.isValid && input(IS_CSR)) {
|
when(arbitration.isValid && input(IS_CSR)) {
|
||||||
output(REGFILE_WRITE_DATA) := readData
|
output(REGFILE_WRITE_DATA) := readData
|
||||||
|
@ -361,21 +365,21 @@ class MachineCsr(config : MachineCsrConfig) extends Plugin[VexRiscv] with Except
|
||||||
|
|
||||||
|
|
||||||
//Translation of the csrMapping into real logic
|
//Translation of the csrMapping into real logic
|
||||||
val csrAddress = input(INSTRUCTION)(csrRange)
|
switch(input(INSTRUCTION)(csrRange)) {
|
||||||
|
for ((address, jobs) <- csrMapping.mapping) {
|
||||||
|
is(address) {
|
||||||
|
when(writeEnable) {
|
||||||
|
for (element <- jobs) element match {
|
||||||
|
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ((address, jobs) <- csrMapping.mapping) {
|
|
||||||
when(csrAddress === address) {
|
|
||||||
when(writeEnable) {
|
|
||||||
for (element <- jobs) element match {
|
for (element <- jobs) element match {
|
||||||
case element: CsrWrite => element.that.assignFromBits(writeData(element.bitOffset, element.that.getBitsWidth bits))
|
case element: CsrRead if element.that.getBitsWidth != 0 => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (element <- jobs) element match {
|
|
||||||
case element: CsrRead if element.that.getBitsWidth != 0 => readData(element.bitOffset, element.that.getBitsWidth bits) := element.that.asBits
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,18 @@ import spinal.core._
|
||||||
import spinal.lib._
|
import spinal.lib._
|
||||||
|
|
||||||
import scala.collection.mutable.ArrayBuffer
|
import scala.collection.mutable.ArrayBuffer
|
||||||
case class MemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage, cacheSize : Int, exceptionBus: Flow[ExceptionCause])
|
case class MemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage, args : MemoryTranslatorPortConfig/*, exceptionBus: Flow[ExceptionCause]*/)
|
||||||
|
|
||||||
class MemoryTranslatorPlugin(tlbSize : Int, exceptionCode : Int, mmuRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
|
case class MemoryTranslatorPortConfig(portTlbSize : Int)
|
||||||
|
|
||||||
|
class MemoryTranslatorPlugin(tlbSize : Int, mmuRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||||
assert(isPow2(tlbSize))
|
assert(isPow2(tlbSize))
|
||||||
|
|
||||||
val portsInfo = ArrayBuffer[MemoryTranslatorPort]()
|
val portsInfo = ArrayBuffer[MemoryTranslatorPort]()
|
||||||
|
|
||||||
override def newTranslationPort(stage : Stage,cacheSize : Int): MemoryTranslatorBus = {
|
override def newTranslationPort(stage : Stage,args : Any): MemoryTranslatorBus = {
|
||||||
val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage)
|
// val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage)
|
||||||
val port = MemoryTranslatorPort(MemoryTranslatorBus(),stage,cacheSize,exceptionBus)
|
val port = MemoryTranslatorPort(MemoryTranslatorBus(),stage,args.asInstanceOf[MemoryTranslatorPortConfig]/*,exceptionBus*/)
|
||||||
portsInfo += port
|
portsInfo += port
|
||||||
port.bus
|
port.bus
|
||||||
}
|
}
|
||||||
|
@ -54,76 +56,64 @@ class MemoryTranslatorPlugin(tlbSize : Int, exceptionCode : Int, mmuRange : UInt
|
||||||
val core = pipeline plug new Area {
|
val core = pipeline plug new Area {
|
||||||
val shared = new Area {
|
val shared = new Area {
|
||||||
val cache = Mem(CacheLine(), tlbSize)
|
val cache = Mem(CacheLine(), tlbSize)
|
||||||
val cmd = Stream(UInt(log2Up(sortedPortsInfo.length) bits))
|
var free = True
|
||||||
val rsp = new Bundle {
|
val readAddr = cache.addressType.assignDontCare()
|
||||||
val portId = UInt()
|
val readData = RegNext(cache.readSync(readAddr))
|
||||||
val hit = Bool
|
|
||||||
val line = CacheLine()
|
|
||||||
}
|
|
||||||
|
|
||||||
val cmdVirtualAddress = RegNext(sortedPortsInfo.map(_.bus).read(cmd.payload).cmd.virtualAddress(31 downto 12))
|
|
||||||
val ptr = Counter(tlbSize)
|
|
||||||
val setup = RegNext(False) init (False)
|
|
||||||
val last = RegNext(ptr.willOverflowIfInc)
|
|
||||||
rsp.portId := RegNext(cmd.payload)
|
|
||||||
rsp.line := cache.readSync(ptr)
|
|
||||||
rsp.hit := rsp.line.valid && rsp.line.virtualAddress === cmdVirtualAddress
|
|
||||||
cmd.ready := !setup && (rsp.hit || last)
|
|
||||||
|
|
||||||
when(cmd.valid) {
|
|
||||||
ptr.increment()
|
|
||||||
}
|
|
||||||
|
|
||||||
when(!cmd.valid || cmd.ready || sortedPortsInfo.map(_.stage.arbitration.removeIt).read(cmd.payload)) {
|
|
||||||
ptr.clear()
|
|
||||||
last := False
|
|
||||||
setup := True
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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.cacheSize)
|
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
|
||||||
val entryToReplace = Counter(port.cacheSize)
|
|
||||||
|
|
||||||
val sharedMiss = RegInit(False)
|
|
||||||
when(shared.cmd.fire && shared.rsp.portId === portId) {
|
|
||||||
cache(entryToReplace) := shared.rsp.line //TODO FMAX pipelining
|
|
||||||
sharedMiss := !shared.rsp.hit
|
|
||||||
entryToReplace.increment()
|
|
||||||
}
|
|
||||||
sharedMiss clearWhen (!port.stage.arbitration.isStuck)
|
|
||||||
|
|
||||||
val sharedRequest = Stream(UInt(log2Up(sortedPortsInfo.length) bits))
|
|
||||||
sharedRequest.valid := False
|
|
||||||
sharedRequest.payload := portId
|
|
||||||
|
|
||||||
port.exceptionBus.valid := False
|
|
||||||
port.exceptionBus.code := exceptionCode
|
|
||||||
port.exceptionBus.badAddr := port.bus.cmd.virtualAddress
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
val sharedMiss = RegInit(False)
|
||||||
|
val sharedIterator = Reg(UInt(log2Up(tlbSize + 1) bits))
|
||||||
|
val sharedAccessed = RegInit(B"00")
|
||||||
|
val entryToReplace = Counter(port.args.portTlbSize)
|
||||||
|
|
||||||
|
val sharedAccessAsked = RegNext(port.bus.cmd.isValid && !cacheHit && sharedIterator < tlbSize && isInMmuRange)
|
||||||
|
val sharedAccessGranted = sharedAccessAsked && shared.free
|
||||||
|
when(sharedAccessGranted) {
|
||||||
|
shared.readAddr := sharedIterator.resized
|
||||||
|
sharedIterator := sharedIterator + 1
|
||||||
|
}
|
||||||
|
sharedAccessed := (sharedAccessed ## sharedAccessGranted).resized
|
||||||
|
when(sharedAccessAsked){
|
||||||
|
shared.free \= False
|
||||||
|
}
|
||||||
|
|
||||||
|
when(sharedAccessed.msb){
|
||||||
|
when(shared.readData.virtualAddress === port.bus.cmd.virtualAddress(31 downto 12)){
|
||||||
|
cache(entryToReplace) := shared.readData
|
||||||
|
entryToReplace.increment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedMiss.setWhen(sharedIterator >= tlbSize && sharedAccessed === B"00")
|
||||||
|
when(!port.stage.arbitration.isStuck){
|
||||||
|
sharedIterator := 0
|
||||||
|
sharedMiss.clear()
|
||||||
|
sharedAccessAsked.clear()
|
||||||
|
sharedAccessed := 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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.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
|
||||||
port.stage.arbitration.haltIt setWhen (port.bus.cmd.isValid && !cacheHit)
|
port.stage.arbitration.haltIt setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
|
||||||
port.exceptionBus.valid := sharedMiss
|
|
||||||
sharedRequest.valid := port.bus.cmd.isValid && !cacheHit && !sharedMiss
|
|
||||||
} otherwise {
|
} otherwise {
|
||||||
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
|
port.bus.rsp.physicalAddress := port.bus.cmd.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
|
||||||
}
|
}
|
||||||
|
port.bus.rsp.miss := sharedMiss
|
||||||
}
|
}
|
||||||
|
|
||||||
shared.cmd << StreamArbiterFactory.lowerFirst.noLock.on(ports.map(_.sharedRequest))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Manage TLBW0 and TLBW1 instructions
|
//Manage TLBW0 and TLBW1 instructions
|
||||||
|
|
|
@ -29,6 +29,7 @@ case class MemoryTranslatorCmd() extends Bundle{
|
||||||
case class MemoryTranslatorRsp() extends Bundle{
|
case class MemoryTranslatorRsp() extends Bundle{
|
||||||
val physicalAddress = UInt(32 bits)
|
val physicalAddress = UInt(32 bits)
|
||||||
val allowRead, allowWrite, allowExecute = Bool
|
val allowRead, allowWrite, allowExecute = Bool
|
||||||
|
val miss = Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
|
case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
|
||||||
|
@ -42,5 +43,5 @@ case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
|
||||||
}
|
}
|
||||||
|
|
||||||
trait MemoryTranslator{
|
trait MemoryTranslator{
|
||||||
def newTranslationPort(stage : Stage, cacheSize : Int) : MemoryTranslatorBus
|
def newTranslationPort(stage : Stage, args : Any) : MemoryTranslatorBus
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,22 +60,43 @@ object TopLevel {
|
||||||
wfiGen = true
|
wfiGen = true
|
||||||
)
|
)
|
||||||
|
|
||||||
// val csrConfig = MachineCsrConfig(
|
val csrConfigSmall = MachineCsrConfig(
|
||||||
// mvendorid = null,
|
mvendorid = null,
|
||||||
// marchid = null,
|
marchid = null,
|
||||||
// mimpid = null,
|
mimpid = null,
|
||||||
// mhartid = null,
|
mhartid = null,
|
||||||
// misaExtensionsInit = 66,
|
misaExtensionsInit = 66,
|
||||||
// misaAccess = CsrAccess.NONE,
|
misaAccess = CsrAccess.NONE,
|
||||||
// mtvecAccess = CsrAccess.NONE,
|
mtvecAccess = CsrAccess.NONE,
|
||||||
// mtvecInit = 0x00000020l,
|
mtvecInit = 0x00000020l,
|
||||||
// mepcAccess = CsrAccess.READ_ONLY,
|
mepcAccess = CsrAccess.READ_WRITE,
|
||||||
// mscratchGen = false,
|
mscratchGen = false,
|
||||||
// mcauseAccess = CsrAccess.READ_ONLY,
|
mcauseAccess = CsrAccess.READ_ONLY,
|
||||||
// mbadaddrAccess = CsrAccess.NONE,
|
mbadaddrAccess = CsrAccess.READ_ONLY,
|
||||||
// mcycleAccess = CsrAccess.NONE,
|
mcycleAccess = CsrAccess.NONE,
|
||||||
// minstretAccess = CsrAccess.NONE
|
minstretAccess = CsrAccess.NONE,
|
||||||
// )
|
ecallGen = false,
|
||||||
|
wfiGen = false
|
||||||
|
)
|
||||||
|
|
||||||
|
val csrConfigSmallest = MachineCsrConfig(
|
||||||
|
mvendorid = null,
|
||||||
|
marchid = null,
|
||||||
|
mimpid = null,
|
||||||
|
mhartid = null,
|
||||||
|
misaExtensionsInit = 66,
|
||||||
|
misaAccess = CsrAccess.NONE,
|
||||||
|
mtvecAccess = CsrAccess.NONE,
|
||||||
|
mtvecInit = 0x00000020l,
|
||||||
|
mepcAccess = CsrAccess.READ_ONLY,
|
||||||
|
mscratchGen = false,
|
||||||
|
mcauseAccess = CsrAccess.READ_ONLY,
|
||||||
|
mbadaddrAccess = CsrAccess.NONE,
|
||||||
|
mcycleAccess = CsrAccess.NONE,
|
||||||
|
minstretAccess = CsrAccess.NONE,
|
||||||
|
ecallGen = false,
|
||||||
|
wfiGen = false
|
||||||
|
)
|
||||||
|
|
||||||
configFull.plugins ++= List(
|
configFull.plugins ++= List(
|
||||||
new PcManagerSimplePlugin(0x00000000l, false),
|
new PcManagerSimplePlugin(0x00000000l, false),
|
||||||
|
@ -109,7 +130,8 @@ object TopLevel {
|
||||||
addressWidth = 32,
|
addressWidth = 32,
|
||||||
cpuDataWidth = 32,
|
cpuDataWidth = 32,
|
||||||
memDataWidth = 32,
|
memDataWidth = 32,
|
||||||
catchAccessFault = false
|
catchAccessFault = false,
|
||||||
|
catchMemoryTranslationMiss = false
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
|
@ -246,19 +268,20 @@ object TopLevel {
|
||||||
cpuDataWidth = 32,
|
cpuDataWidth = 32,
|
||||||
memDataWidth = 32,
|
memDataWidth = 32,
|
||||||
catchAccessFault = false,
|
catchAccessFault = false,
|
||||||
|
catchMemoryTranslationMiss = true,
|
||||||
tagSizeShift = 2
|
tagSizeShift = 2
|
||||||
),
|
),
|
||||||
mmuConfig = DataMmuConfig(
|
askMemoryTranslation = true,
|
||||||
dTlbSize = 6
|
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
|
||||||
|
portTlbSize = 6
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
new MemoryTranslatorPlugin(
|
new MemoryTranslatorPlugin(
|
||||||
tlbSize = 32,
|
tlbSize = 32,
|
||||||
exceptionCode = 13,
|
|
||||||
mmuRange = _(31 downto 28) === 0xC
|
mmuRange = _(31 downto 28) === 0xC
|
||||||
),
|
),
|
||||||
new MachineCsr(csrConfigAll),
|
new MachineCsr(csrConfigSmall),
|
||||||
new DecoderSimplePlugin(
|
new DecoderSimplePlugin(
|
||||||
catchIllegalInstruction = false
|
catchIllegalInstruction = false
|
||||||
),
|
),
|
||||||
|
@ -275,10 +298,10 @@ object TopLevel {
|
||||||
// new HazardSimplePlugin(true, true, true, true),
|
// new HazardSimplePlugin(true, true, true, true),
|
||||||
// new HazardSimplePlugin(false, true, false, true),
|
// new HazardSimplePlugin(false, true, false, true),
|
||||||
new HazardSimplePlugin(
|
new HazardSimplePlugin(
|
||||||
bypassExecute = true,
|
bypassExecute = false,
|
||||||
bypassMemory = true,
|
bypassMemory = false,
|
||||||
bypassWriteBack = true,
|
bypassWriteBack = false,
|
||||||
bypassWriteBackBuffer = true,
|
bypassWriteBackBuffer = false,
|
||||||
pessimisticUseSrc = false,
|
pessimisticUseSrc = false,
|
||||||
pessimisticWriteRegFile = false,
|
pessimisticWriteRegFile = false,
|
||||||
pessimisticAddressMatch = false
|
pessimisticAddressMatch = false
|
||||||
|
|
Loading…
Reference in New Issue