Reintroduce MMU feature (pass tests)
This commit is contained in:
parent
35fbf177e2
commit
7ffbfab312
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue