Add a busy flag from MMU ports

iBus/dBus now halt on MMU busy, which avoid looping forever on page fault
This commit is contained in:
Charles Papon 2019-04-08 11:38:40 +02:00
parent f89ee0d422
commit c2595273ec
7 changed files with 65 additions and 28 deletions

View file

@ -78,10 +78,11 @@ case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
val cmd = MemoryTranslatorCmd()
val rsp = MemoryTranslatorRsp()
val end = Bool
val busy = Bool
override def asMaster() : Unit = {
out(cmd, end)
in(rsp)
in(rsp, busy)
}
}

View file

@ -99,10 +99,11 @@ case class InstructionCacheCpuFetch(p : InstructionCacheConfig) extends Bundle w
val mmuBus = MemoryTranslatorBus()
val physicalAddress = UInt(p.addressWidth bits)
val cacheMiss, error, mmuRefilling, mmuException, isUser = ifGen(!p.twoCycleCache)(Bool)
val haltIt = Bool
override def asMaster(): Unit = {
out(isValid, isStuck, isRemoved, pc)
inWithNull(error,mmuRefilling,mmuException,data, cacheMiss,physicalAddress)
inWithNull(error,mmuRefilling,mmuException,data, cacheMiss,physicalAddress, haltIt)
outWithNull(isUser, dataBypass, dataBypassValid)
slaveWithNull(mmuBus)
}
@ -290,10 +291,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
}
})
io.cpu.prefetch.haltIt := False
io.cpu.fetch.haltIt := io.cpu.fetch.mmuBus.busy
val lineLoader = new Area{
val fire = False
@ -307,7 +305,7 @@ class InstructionCache(p : InstructionCacheConfig) extends Component{
address := io.cpu.fill.payload
}
io.cpu.prefetch.haltIt setWhen(valid || flushPending)
io.cpu.prefetch.haltIt := valid || flushPending
val flushCounter = Reg(UInt(log2Up(wayLineCount) + 1 bit))
when(!flushCounter.msb){

View file

@ -159,7 +159,13 @@ class DBusCachedPlugin(config : DataCacheConfig,
dBus.cmd << optionPipe(dBusCmdMasterPipe, cmdBuf)(_.m2sPipe())
cache.io.mem.rsp << optionPipe(dBusRspSlavePipe,dBus.rsp)(_.m2sPipe())
decode plug new Area {
import decode._
when(mmuBus.busy && arbitration.isValid && input(MEMORY_ENABLE)) {
arbitration.haltItself := True
}
}
execute plug new Area {
import execute._

View file

@ -312,6 +312,15 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
dBus = master(DBusSimpleBus()).setName("dBus")
decode plug new Area {
import decode._
if(mmuBus != null) when(mmuBus.busy && arbitration.isValid && input(MEMORY_ENABLE)) {
arbitration.haltItself := True
}
}
//Emit dBus.cmd request
val cmdStage = if(emitCmdInMemoryStage) memory else execute
cmdStage plug new Area{
@ -359,6 +368,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
mmuBus.cmd.isValid := arbitration.isValid && input(MEMORY_ENABLE)
mmuBus.cmd.virtualAddress := input(SRC_ADD).asUInt
mmuBus.cmd.bypassTranslation := False
mmuBus.end := !arbitration.isStuck || arbitration.isRemoved
dBus.cmd.address := mmuBus.rsp.physicalAddress
//do not emit memory request if MMU refilling

View file

@ -165,6 +165,9 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
cache.io.cpu.fetch.isStuck := !stages(1).input.ready
cache.io.cpu.fetch.pc := stages(1).input.payload
stages(1).halt setWhen(cache.io.cpu.fetch.haltIt)
if (!twoCycleCache) {
cache.io.cpu.fetch.isUser := privilegeService.isUser()
}
@ -188,39 +191,49 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
val cacheRsp = if (twoCycleCache) cache.io.cpu.decode else cache.io.cpu.fetch
val cacheRspArbitration = stages(if (twoCycleCache) 2 else 1)
var issueDetected = False
val redoFetch = False //RegNext(False) init(False)
when(cacheRsp.isValid && (cacheRsp.cacheMiss || cacheRsp.mmuRefilling) && !issueDetected) {
issueDetected \= True
redoFetch := iBusRsp.readyForError
}
val redoFetch = False
//Refill / redo
assert(decodePcGen == compressedGen)
cache.io.cpu.fill.valid := redoFetch
cache.io.cpu.fill.valid := redoFetch && !cacheRsp.mmuRefilling
cache.io.cpu.fill.payload := cacheRsp.physicalAddress
redoBranch.valid := redoFetch
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
if (catchSomething) {
decodeExceptionPort.valid := False
decodeExceptionPort.code.assignDontCare()
decodeExceptionPort.badAddr := cacheRsp.pc(31 downto 2) @@ "00"
if(catchIllegalAccess) when(cacheRsp.isValid && cacheRsp.mmuException && !issueDetected) {
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
decodeExceptionPort.code := 12
}
if(catchAccessFault) when(cacheRsp.isValid && cacheRsp.error && !issueDetected) {
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
decodeExceptionPort.code := 1
}
decodeExceptionPort.valid clearWhen(fetcherHalt)
}
when(cacheRsp.isValid && cacheRsp.mmuRefilling && !issueDetected) {
issueDetected \= True
redoFetch := True
}
if(catchIllegalAccess) when(cacheRsp.isValid && cacheRsp.mmuException && !issueDetected) {
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
decodeExceptionPort.code := 12
}
when(cacheRsp.isValid && cacheRsp.cacheMiss && !issueDetected) {
issueDetected \= True
cache.io.cpu.fill.valid := True
redoFetch := True
}
if(catchAccessFault) when(cacheRsp.isValid && cacheRsp.error && !issueDetected) {
issueDetected \= True
decodeExceptionPort.valid := iBusRsp.readyForError
decodeExceptionPort.code := 1
}
redoFetch clearWhen(!iBusRsp.readyForError)
if (catchSomething) decodeExceptionPort.valid clearWhen(fetcherHalt)
redoBranch.valid := redoFetch
redoBranch.payload := (if (decodePcGen) decode.input(PC) else cacheRsp.pc)
cacheRspArbitration.halt setWhen (issueDetected || iBusRspOutputHalt)
iBusRsp.output.valid := cacheRspArbitration.output.valid

View file

@ -247,6 +247,8 @@ class IBusSimplePlugin(resetVector : BigInt,
mmuBus.cmd.isValid := cmdForkStage.input.valid
mmuBus.cmd.virtualAddress := cmdForkStage.input.payload
mmuBus.cmd.bypassTranslation := False
mmuBus.end := !cmdForkStage.output.fire || flush
cmd.pc := mmuBus.rsp.physicalAddress(31 downto 2) @@ "00"
//do not emit memory request if MMU miss
@ -255,6 +257,8 @@ class IBusSimplePlugin(resetVector : BigInt,
cmd.valid := False
}
cmdForkStage.halt.setWhen(mmuBus.busy)
val joinCtx = stageXToIBusRsp(cmdForkStage, mmuBus.rsp)
}

View file

@ -100,6 +100,7 @@ class MmuPlugin(ioRange : UInt => Bool,
val core = pipeline plug new Area {
val ports = for (port <- sortedPortsInfo) yield new Area {
val handle = port
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)))
@ -224,6 +225,10 @@ class MmuPlugin(ioRange : UInt => Bool,
}
}
for(port <- ports) {
port.handle.bus.busy := state =/= State.IDLE && portId === port.id
}
when(dBusAccess.rsp.valid && !dBusAccess.rsp.redo && (dBusRsp.leaf || dBusRsp.exception)){
for(port <- ports){
when(portId === port.id) {