mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
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:
parent
f89ee0d422
commit
c2595273ec
7 changed files with 65 additions and 28 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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._
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue