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:
Charles Papon 2017-05-01 14:29:37 +02:00
parent 2ed33106d6
commit 889a040f90
5 changed files with 187 additions and 148 deletions

View File

@ -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,

View File

@ -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 _ =>
}
} }
} }
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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