Fix MmuPlugin when used in multi stage config

This commit is contained in:
Dolu1990 2020-07-05 13:17:39 +02:00
parent 06584518da
commit 51070d0e69
1 changed files with 18 additions and 4 deletions

View File

@ -105,6 +105,10 @@ class MmuPlugin(ioRange : UInt => Bool,
val id = port.id val id = port.id
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault()) val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize) val cache = Vec(Reg(CacheLine()) init, port.args.portTlbSize)
val dirty = RegInit(False).allowUnsetRegToAvoidLatch
if(port.args.earlyRequireMmuLockup){
dirty clearWhen(!port.bus.cmd.last.isStuck)
}
def toRsp[T <: Data](data : T, from : MemoryTranslatorCmd) : T = from match { def toRsp[T <: Data](data : T, from : MemoryTranslatorCmd) : T = from match {
case _ if from == port.bus.cmd.last => data case _ if from == port.bus.cmd.last => data
@ -144,8 +148,8 @@ class MmuPlugin(ioRange : UInt => Bool,
port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute port.bus.rsp.allowRead := cacheLine.allowRead || csr.status.mxr && cacheLine.allowExecute
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.bus.rsp.exception := cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser()) port.bus.rsp.exception := !dirty && cacheHit && (cacheLine.exception || cacheLine.allowUser && privilegeService.isSupervisor() && !csr.status.sum || !cacheLine.allowUser && privilegeService.isUser())
port.bus.rsp.refilling := !cacheHit port.bus.rsp.refilling := dirty || !cacheHit
} otherwise { } otherwise {
port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress port.bus.rsp.physicalAddress := port.bus.cmd.last.virtualAddress
port.bus.rsp.allowRead := True port.bus.rsp.allowRead := True
@ -204,7 +208,7 @@ class MmuPlugin(ioRange : UInt => Bool,
dBusAccess.cmd.data.assignDontCare() dBusAccess.cmd.data.assignDontCare()
dBusAccess.cmd.writeMask.assignDontCare() dBusAccess.cmd.writeMask.assignDontCare()
val refills = OHMasking.last(B(sortedPortsInfo.map(port => port.bus.cmd.last.isValid && port.bus.rsp.refilling))) val refills = OHMasking.last(B(ports.map(port => port.handle.bus.cmd.last.isValid && port.requireMmuLockup && !port.dirty && !port.cacheHit)))
switch(state){ switch(state){
is(State.IDLE){ is(State.IDLE){
when(refills.orR){ when(refills.orR){
@ -266,6 +270,9 @@ class MmuPlugin(ioRange : UInt => Bool,
for((port, id) <- ports.zipWithIndex) { for((port, id) <- ports.zipWithIndex) {
when(portSortedOh(id)) { when(portSortedOh(id)) {
port.entryToReplace.increment() port.entryToReplace.increment()
if(port.handle.args.earlyRequireMmuLockup) {
port.dirty := True
} //Avoid having non coherent TLB lookup
for ((line, lineId) <- port.cache.zipWithIndex) { for ((line, lineId) <- port.cache.zipWithIndex) {
when(port.entryToReplace === lineId){ when(port.entryToReplace === lineId){
val superPage = state === State.L1_RSP val superPage = state === State.L1_RSP
@ -289,9 +296,16 @@ class MmuPlugin(ioRange : UInt => Bool,
val fenceStage = stages.last val fenceStage = stages.last
fenceStage plug new Area{ fenceStage plug new Area{
import fenceStage._ import fenceStage._
when(arbitration.isValid && input(IS_SFENCE_VMA)){ // || csrService.isWriting(CSR.SATP) when(arbitration.isValid && input(IS_SFENCE_VMA)){
for(port <- core.ports; line <- port.cache) line.valid := False //Assume that the instruction already fetched into the pipeline are ok for(port <- core.ports; line <- port.cache) line.valid := False //Assume that the instruction already fetched into the pipeline are ok
} }
csrService.duringWrite(CSR.SATP){
for(port <- core.ports; line <- port.cache) line.valid := False
core.ports.filter(_.handle.args.earlyRequireMmuLockup).foreach{p =>
p.dirty := True
}
}
} }
} }
} }