Reintroduce MMU feature (pass tests)

This commit is contained in:
Dolu1990 2018-05-16 20:32:12 +02:00
parent 35fbf177e2
commit 7ffbfab312
9 changed files with 66 additions and 37 deletions

View File

@ -56,20 +56,22 @@ case class MemoryTranslatorRsp() extends Bundle{
val isIoAccess = Bool
val allowRead, allowWrite, allowExecute, allowUser = Bool
val miss = Bool
val hit = Bool
}
case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
val cmd = MemoryTranslatorCmd()
val rsp = MemoryTranslatorRsp()
val end = Bool
override def asMaster() : Unit = {
out(cmd)
out(cmd, end)
in(rsp)
}
}
trait MemoryTranslator{
def newTranslationPort(stage : Stage, args : Any) : MemoryTranslatorBus
def newTranslationPort(priority : Int, args : Any) : MemoryTranslatorBus
}

View File

@ -41,6 +41,7 @@ object TestsWorkspace {
// ),
new IBusCachedPlugin(
resetVector = 0x80000000l,
compressedGen = true,
config = InstructionCacheConfig(
cacheSize = 1024*16,
bytePerLine = 32,
@ -54,10 +55,10 @@ object TestsWorkspace {
asyncTagMemory = false,
twoCycleRam = false,
twoCycleCache = true
)//,
// memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
// portTlbSize = 4
// )
),
memoryTranslatorPortConfig = MemoryTranslatorPortConfig(
portTlbSize = 4
)
),
// new DBusSimplePlugin(
// catchAddressMisaligned = true,

View File

@ -511,6 +511,7 @@ class DataCache(p : DataCacheConfig) extends Component{
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.bypassTranslation := request.way
io.cpu.memory.mmuBus.end := !io.cpu.memory.isStuck || io.cpu.memory.isRemoved
cpuMemoryStageNeedReadData := io.cpu.memory.isValid && request.kind === MEMORY && !request.wr
}

View File

@ -63,6 +63,7 @@ trait InstructionCacheCommons{
val isValid : Bool
val isStuck : Bool
val pc : UInt
val physicalAddress : UInt
val data : Bits
val cacheMiss, error, mmuMiss, illegalAccess,isUser : Bool
}
@ -70,14 +71,16 @@ trait InstructionCacheCommons{
case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle with IMasterSlave with InstructionCacheCommons {
val isValid = Bool
val isStuck = Bool
val isRemoved = Bool
val pc = UInt(p.addressWidth bits)
val data = Bits(p.cpuDataWidth bits)
val mmuBus = MemoryTranslatorBus()
val physicalAddress = UInt(p.addressWidth bits)
val cacheMiss, error, mmuMiss, illegalAccess,isUser = ifGen(!p.twoCycleCache)(Bool)
override def asMaster(): Unit = {
out(isValid, isStuck, pc)
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss)
out(isValid, isStuck, isRemoved, pc)
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss,physicalAddress)
outWithNull(isUser)
slaveWithNull(mmuBus)
}
@ -88,13 +91,14 @@ case class InstructionCacheCpuDecode(p : InstructionCacheConfig) extends Bundle
val isValid = Bool
val isStuck = Bool
val pc = UInt(p.addressWidth bits)
val physicalAddress = UInt(p.addressWidth bits)
val data = Bits(p.cpuDataWidth bits)
val cacheMiss, error, mmuMiss, illegalAccess, isUser = ifGen(p.twoCycleCache)(Bool)
override def asMaster(): Unit = {
out(isValid, isStuck, pc)
outWithNull(isUser)
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss)
inWithNull(error,mmuMiss,illegalAccess,data, cacheMiss, physicalAddress)
}
}
@ -328,6 +332,8 @@ 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.pc
io.cpu.fetch.mmuBus.cmd.bypassTranslation := False
io.cpu.fetch.mmuBus.end := !io.cpu.fetch.isStuck || io.cpu.fetch.isRemoved
io.cpu.fetch.physicalAddress := io.cpu.fetch.mmuBus.rsp.physicalAddress
val resolution = ifGen(!twoCycleCache)( new Area{
def stage[T <: Data](that : T) = RegNextWhen(that,!io.cpu.decode.isStuck)
@ -371,6 +377,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
io.cpu.decode.error := hit.error
io.cpu.decode.mmuMiss := mmuRsp.miss
io.cpu.decode.illegalAccess := !mmuRsp.allowExecute || (io.cpu.decode.isUser && !mmuRsp.allowUser)
io.cpu.decode.physicalAddress := mmuRsp.physicalAddress
})
}

View File

@ -95,7 +95,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
MEMORY_MANAGMENT -> True
))
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,memoryTranslatorPortConfig)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_DATA ,memoryTranslatorPortConfig)
if(catchSomething)
exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(pipeline.writeBack)
@ -171,6 +171,7 @@ class DBusCachedPlugin(config : DataCacheConfig, memoryTranslatorPortConfig : An
arbitration.haltItself setWhen(cache.io.cpu.memory.haltIt)
cache.io.cpu.memory.mmuBus <> mmuBus
arbitration.haltItself setWhen (mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
}
writeBack plug new Area{

View File

@ -200,11 +200,12 @@ abstract class IBusFetcherImpl(val catchAccessFault : Boolean,
val iBusRsp = new Area {
val input = Stream(UInt(32 bits))
val inputPipeline = Vec(Stream(UInt(32 bits)), cmdToRspStageCount)
val inputPipelineHalt = Vec(False, cmdToRspStageCount-1)
for(i <- 0 until cmdToRspStageCount) {
// val doFlush = if(i == cmdToRspStageCount- 1 && ???) killLastStage else flush
inputPipeline(i) << {i match {
case 0 => input.m2sPipeWithFlush(flush, relaxedPcCalculation, collapsBubble = false)
case _ => inputPipeline(i-1)/*.haltWhen(fetcherHalt)*/.m2sPipeWithFlush(flush,collapsBubble = false)
case _ => inputPipeline(i-1).haltWhen(inputPipelineHalt(i-1)).m2sPipeWithFlush(flush,collapsBubble = false)
}}
}

View File

@ -62,9 +62,8 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
decodeExceptionPort = exceptionService.newExceptionPort(pipeline.decode,1)
}
// if(pipeline.serviceExist(classOf[MemoryTranslator]))
// ??? //TODO
//mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.fetch, memoryTranslatorPortConfig)
if(pipeline.serviceExist(classOf[MemoryTranslator]))
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(MemoryTranslatorPort.PRIORITY_INSTRUCTION, memoryTranslatorPortConfig)
if(pipeline.serviceExist(classOf[PrivilegeService]))
privilegeService = pipeline.service(classOf[PrivilegeService])
@ -105,6 +104,22 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
cache.io.cpu.prefetch.pc := fetchPc.output.payload
iBusRsp.input << fetchPc.output.haltWhen(cache.io.cpu.prefetch.haltIt)
cache.io.cpu.fetch.isRemoved := flush
if (mmuBus != null) {
cache.io.cpu.fetch.mmuBus <> mmuBus
iBusRsp.inputPipelineHalt(0) setWhen(mmuBus.cmd.isValid && !mmuBus.rsp.hit && !mmuBus.rsp.miss)
} else {
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False
cache.io.cpu.fetch.mmuBus.rsp.miss := False
cache.io.cpu.fetch.mmuBus.rsp.hit := False
}
//Connect fetch cache side
cache.io.cpu.fetch.isValid := iBusRsp.inputPipeline(0).valid
cache.io.cpu.fetch.isStuck := !iBusRsp.input.ready
@ -123,17 +138,6 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
}
if (mmuBus != null) {
cache.io.cpu.fetch.mmuBus <> mmuBus
} else {
cache.io.cpu.fetch.mmuBus.rsp.physicalAddress := cache.io.cpu.fetch.mmuBus.cmd.virtualAddress //- debugAddressOffset
cache.io.cpu.fetch.mmuBus.rsp.allowExecute := True
cache.io.cpu.fetch.mmuBus.rsp.allowRead := True
cache.io.cpu.fetch.mmuBus.rsp.allowWrite := True
cache.io.cpu.fetch.mmuBus.rsp.allowUser := True
cache.io.cpu.fetch.mmuBus.rsp.isIoAccess := False
cache.io.cpu.fetch.mmuBus.rsp.miss := False
}
// val missHalt = cache.io.cpu.fetch.isValid && cache.io.cpu.fetch.cacheMiss
val cacheRsp = if(twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
@ -148,13 +152,17 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
redoBranch.valid := redoFetch
assert(decodePcGen == compressedGen)
redoBranch.payload := (if(decodePcGen) decode.input(PC) else cacheRsp.pc)
cache.io.cpu.fill.payload := cacheRsp.pc
cache.io.cpu.fill.payload := cacheRsp.physicalAddress
if(catchSomething){
val accessFault = if (catchAccessFault) cacheRsp.error else False
val mmuMiss = if (catchMemoryTranslationMiss) cacheRsp.mmuMiss else False
val illegalAccess = if (catchIllegalAccess) cacheRsp.illegalAccess else False
decodeExceptionPort.valid := False
decodeExceptionPort.code := 1
decodeExceptionPort.code := mmuMiss ? U(14) | 1
decodeExceptionPort.badAddr := cacheRsp.pc
when(cacheRsp.isValid && cacheRsp.error && !issueDetected){
when(cacheRsp.isValid && (accessFault || mmuMiss || illegalAccess) && !issueDetected){
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
}

View File

@ -5,7 +5,12 @@ import spinal.core._
import spinal.lib._
import scala.collection.mutable.ArrayBuffer
case class MemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage, args : MemoryTranslatorPortConfig/*, exceptionBus: Flow[ExceptionCause]*/)
object MemoryTranslatorPort{
val PRIORITY_DATA = 1
val PRIORITY_INSTRUCTION = 0
}
case class MemoryTranslatorPort(bus : MemoryTranslatorBus, priority : Int, args : MemoryTranslatorPortConfig/*, exceptionBus: Flow[ExceptionCause]*/)
case class MemoryTranslatorPortConfig(portTlbSize : Int)
@ -16,9 +21,9 @@ class MemoryTranslatorPlugin(tlbSize : Int,
val portsInfo = ArrayBuffer[MemoryTranslatorPort]()
override def newTranslationPort(stage : Stage,args : Any): MemoryTranslatorBus = {
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
// val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage)
val port = MemoryTranslatorPort(MemoryTranslatorBus(),stage,args.asInstanceOf[MemoryTranslatorPortConfig]/*,exceptionBus*/)
val port = MemoryTranslatorPort(MemoryTranslatorBus(),priority,args.asInstanceOf[MemoryTranslatorPortConfig]/*,exceptionBus*/)
portsInfo += port
port.bus
}
@ -41,7 +46,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
import Riscv._
//Sorted by priority
val sortedPortsInfo = portsInfo.sortWith((a,b) => indexOf(a.stage) > indexOf(b.stage))
val sortedPortsInfo = portsInfo.sortWith((a,b) => a.priority > b.priority)
case class CacheLine() extends Bundle {
val valid = Bool
@ -94,7 +99,7 @@ class MemoryTranslatorPlugin(tlbSize : Int,
}
sharedMiss.setWhen(sharedIterator >= tlbSize && sharedAccessed === B"00")
when(!port.stage.arbitration.isStuck){
when(port.bus.end){
sharedIterator := 0
sharedMiss.clear()
sharedAccessAsked.clear()
@ -108,13 +113,15 @@ class MemoryTranslatorPlugin(tlbSize : Int,
port.bus.rsp.allowWrite := cacheLine.allowWrite
port.bus.rsp.allowExecute := cacheLine.allowExecute
port.bus.rsp.allowUser := cacheLine.allowUser
port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
port.bus.rsp.hit := cacheHit
// port.stage.arbitration.haltItself setWhen (port.bus.cmd.isValid && !cacheHit && !sharedMiss)
} otherwise {
port.bus.rsp.physicalAddress := port.bus.cmd.virtualAddress
port.bus.rsp.allowRead := True
port.bus.rsp.allowWrite := True
port.bus.rsp.allowExecute := True
port.bus.rsp.allowUser := True
port.bus.rsp.hit := True
}
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
port.bus.rsp.miss := sharedMiss

View File

@ -5,14 +5,14 @@ import spinal.core._
import spinal.lib._
import scala.collection.mutable.ArrayBuffer
case class StaticMemoryTranslatorPort(bus : MemoryTranslatorBus, stage : Stage)
case class StaticMemoryTranslatorPort(bus : MemoryTranslatorBus, priority : Int)
class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator {
val portsInfo = ArrayBuffer[StaticMemoryTranslatorPort]()
override def newTranslationPort(stage : Stage,args : Any): MemoryTranslatorBus = {
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
// val exceptionBus = pipeline.service(classOf[ExceptionService]).newExceptionPort(stage)
val port = StaticMemoryTranslatorPort(MemoryTranslatorBus(),stage)
val port = StaticMemoryTranslatorPort(MemoryTranslatorBus(),priority)
portsInfo += port
port.bus
}
@ -34,6 +34,7 @@ class StaticMemoryTranslatorPlugin(ioRange : UInt => Bool) extends Plugin[VexRis
port.bus.rsp.allowUser := True
port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress)
port.bus.rsp.miss := False
port.bus.rsp.hit := True
}
}
}