From 069858a20ce101310c49900af0da211838931e92 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 26 Mar 2017 18:18:35 -0700 Subject: [PATCH] rocket: separate page faults from physical memory access exceptions --- riscv-tools | 2 +- src/main/scala/rocket/CSR.scala | 21 +++++--- src/main/scala/rocket/DCache.scala | 6 ++- src/main/scala/rocket/Frontend.scala | 22 +++++--- src/main/scala/rocket/HellaCache.scala | 1 + src/main/scala/rocket/IBuf.scala | 17 ++++-- src/main/scala/rocket/Instructions.scala | 18 ++++--- src/main/scala/rocket/NBDcache.scala | 6 ++- src/main/scala/rocket/PTW.scala | 20 ++++--- src/main/scala/rocket/Rocket.scala | 12 +++-- src/main/scala/rocket/TLB.scala | 68 +++++++++++++----------- 11 files changed, 120 insertions(+), 73 deletions(-) diff --git a/riscv-tools b/riscv-tools index 4f430b18..89d48702 160000 --- a/riscv-tools +++ b/riscv-tools @@ -1 +1 @@ -Subproject commit 4f430b184ed07890cd30ad144ded6d7cb07dcdf0 +Subproject commit 89d487023c1e59ff574872e2f51ee479cda380ab diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index ea0c265d..cd028a28 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -119,10 +119,15 @@ object CSR def R = UInt(5,SZ) val ADDRSZ = 12 - def debugIntCause = new MIP().getWidth + def debugIntCause = { + val res = 14 + require(res >= new MIP().getWidth) + res + } def debugTriggerCause = { - require(debugIntCause >= Causes.all.max) - debugIntCause + val res = 14 + require(!(Causes.all contains res)) + res } val firstCtr = CSRs.cycle @@ -224,10 +229,10 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param } val delegable_exceptions = UInt(Seq( Causes.misaligned_fetch, - Causes.fault_fetch, + Causes.fetch_page_fault, Causes.breakpoint, - Causes.fault_load, - Causes.fault_store, + Causes.load_page_fault, + Causes.store_page_fault, Causes.user_ecall).map(1 << _).sum) val reg_debug = Reg(init=Bool(false)) @@ -483,7 +488,9 @@ class CSRFile(perfEventSets: EventSets = new EventSets(Seq()))(implicit p: Param val write_badaddr = cause isOneOf (Causes.breakpoint, Causes.misaligned_load, Causes.misaligned_store, Causes.misaligned_fetch, - Causes.fault_load, Causes.fault_store, Causes.fault_fetch) + Causes.load_access, Causes.store_access, Causes.fetch_access, + Causes.load_page_fault, Causes.store_page_fault, Causes.fetch_page_fault + ) when (trapToDebug) { reg_debug := true diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 1083e5bb..b8f44c16 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -185,8 +185,10 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val no_xcpt = Bool(usingDataScratchpad) && s1_req.phys /* slave port */ && s1_hit_state.isValid() io.cpu.xcpt.ma.ld := !no_xcpt && s1_read && s1_storegen.misaligned io.cpu.xcpt.ma.st := !no_xcpt && s1_write && s1_storegen.misaligned - io.cpu.xcpt.pf.ld := !no_xcpt && s1_read && tlb.io.resp.xcpt_ld - io.cpu.xcpt.pf.st := !no_xcpt && s1_write && tlb.io.resp.xcpt_st + io.cpu.xcpt.pf.ld := !no_xcpt && s1_read && tlb.io.resp.pf.ld + io.cpu.xcpt.pf.st := !no_xcpt && s1_write && tlb.io.resp.pf.st + io.cpu.xcpt.ae.ld := !no_xcpt && s1_read && tlb.io.resp.ae.ld + io.cpu.xcpt.ae.st := !no_xcpt && s1_write && tlb.io.resp.ae.st // load reservations val s2_lr = Bool(usingAtomics) && s2_req.cmd === M_XLR diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 80d3b1e7..80aa8dde 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -22,7 +22,8 @@ class FrontendResp(implicit p: Parameters) extends CoreBundle()(p) { val pc = UInt(width = vaddrBitsExtended) // ID stage PC val data = UInt(width = fetchWidth * coreInstBits) val mask = Bits(width = fetchWidth) - val xcpt_if = Bool() + val pf = Bool() + val ae = Bool() val replay = Bool() } @@ -72,9 +73,12 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) val s2_pc = Reg(init=io.resetVector) val s2_btb_resp_valid = Reg(init=Bool(false)) val s2_btb_resp_bits = Reg(new BTBResp) - val s2_maybe_xcpt_if = Reg(init=Bool(false)) + val s2_maybe_pf = Reg(init=Bool(false)) + val s2_maybe_ae = Reg(init=Bool(false)) val s2_tlb_miss = Reg(Bool()) - val s2_xcpt_if = s2_maybe_xcpt_if && !s2_tlb_miss + val s2_pf = s2_maybe_pf && !s2_tlb_miss + val s2_ae = s2_maybe_ae && !s2_tlb_miss + val s2_xcpt = s2_pf || s2_ae val s2_speculative = Reg(init=Bool(false)) val s2_cacheable = Reg(init=Bool(false)) @@ -101,7 +105,8 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) s2_pc := s1_pc s2_speculative := s1_speculative s2_cacheable := tlb.io.resp.cacheable - s2_maybe_xcpt_if := tlb.io.resp.xcpt_if + s2_maybe_pf := tlb.io.resp.pf.inst + s2_maybe_ae := tlb.io.resp.ae.inst s2_tlb_miss := tlb.io.resp.miss } } @@ -144,18 +149,19 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) icache.io.invalidate := io.cpu.flush_icache icache.io.s1_paddr := tlb.io.resp.paddr icache.io.s1_kill := io.cpu.req.valid || tlb.io.resp.miss || icmiss - icache.io.s2_kill := s2_speculative && !s2_cacheable || s2_xcpt_if + icache.io.s2_kill := s2_speculative && !s2_cacheable || s2_xcpt icache.io.resp.ready := !stall && !s1_same_block - io.cpu.resp.valid := s2_valid && (icache.io.resp.valid || icache.io.s2_kill || s2_xcpt_if) + io.cpu.resp.valid := s2_valid && (icache.io.resp.valid || icache.io.s2_kill || s2_xcpt) io.cpu.resp.bits.pc := s2_pc io.cpu.npc := Mux(io.cpu.req.valid, io.cpu.req.bits.pc, npc) require(fetchWidth * coreInstBytes <= rowBytes && isPow2(fetchWidth)) io.cpu.resp.bits.data := icache.io.resp.bits.datablock >> (s2_pc.extract(log2Ceil(rowBytes)-1,log2Ceil(fetchWidth*coreInstBytes)) << log2Ceil(fetchWidth*coreInstBits)) io.cpu.resp.bits.mask := UInt((1 << fetchWidth)-1) << s2_pc.extract(log2Ceil(fetchWidth)+log2Ceil(coreInstBytes)-1, log2Ceil(coreInstBytes)) - io.cpu.resp.bits.xcpt_if := s2_xcpt_if - io.cpu.resp.bits.replay := icache.io.s2_kill && !icache.io.resp.valid && !s2_xcpt_if + io.cpu.resp.bits.pf := s2_pf + io.cpu.resp.bits.ae := s2_ae + io.cpu.resp.bits.replay := icache.io.s2_kill && !icache.io.resp.valid && !s2_xcpt io.cpu.resp.bits.btb.valid := s2_btb_resp_valid io.cpu.resp.bits.btb.bits := s2_btb_resp_bits diff --git a/src/main/scala/rocket/HellaCache.scala b/src/main/scala/rocket/HellaCache.scala index bafd4289..2d4f1178 100644 --- a/src/main/scala/rocket/HellaCache.scala +++ b/src/main/scala/rocket/HellaCache.scala @@ -113,6 +113,7 @@ class AlignmentExceptions extends Bundle { class HellaCacheExceptions extends Bundle { val ma = new AlignmentExceptions val pf = new AlignmentExceptions + val ae = new AlignmentExceptions } // interface between D$ and processor/DTLB diff --git a/src/main/scala/rocket/IBuf.scala b/src/main/scala/rocket/IBuf.scala index d81f9a4b..ac50ac10 100644 --- a/src/main/scala/rocket/IBuf.scala +++ b/src/main/scala/rocket/IBuf.scala @@ -11,6 +11,8 @@ import util._ class Instruction(implicit val p: Parameters) extends ParameterizedBundle with HasCoreParameters { val pf0 = Bool() // page fault on first half of instruction val pf1 = Bool() // page fault on second half of instruction + val ae0 = Bool() // access exception on first half of instruction + val ae1 = Bool() // access exception on second half of instruction val replay = Bool() val btb_hit = Bool() val rvc = Bool() @@ -78,7 +80,8 @@ class IBuf(implicit p: Parameters) extends CoreModule { val valid = (UIntToOH(nValid) - 1)(fetchWidth-1, 0) val bufMask = UIntToOH(nBufValid) - 1 - val xcpt_if = valid & (Mux(buf.xcpt_if, bufMask, UInt(0)) | Mux(io.imem.bits.xcpt_if, ~bufMask, UInt(0))) + val pf = valid & (Mux(buf.pf, bufMask, UInt(0)) | Mux(io.imem.bits.pf, ~bufMask, UInt(0))) + val ae = valid & (Mux(buf.ae, bufMask, UInt(0)) | Mux(io.imem.bits.ae, ~bufMask, UInt(0))) val ic_replay = valid & (Mux(buf.replay, bufMask, UInt(0)) | Mux(io.imem.bits.replay, ~bufMask, UInt(0))) val ibufBTBHitMask = Mux(ibufBTBHit, UIntToOH(ibufBTBResp.bridx), UInt(0)) assert(!io.imem.bits.btb.valid || io.imem.bits.btb.bits.bridx >= pcWordBits) @@ -97,9 +100,11 @@ class IBuf(implicit p: Parameters) extends CoreModule { if (usingCompressed) { val replay = ic_replay(j) || (!exp.io.rvc && (btbHitMask(j) || ic_replay(j+1))) - io.inst(i).valid := valid(j) && (exp.io.rvc || valid(j+1) || xcpt_if(j+1) || replay) - io.inst(i).bits.pf0 := xcpt_if(j) - io.inst(i).bits.pf1 := !exp.io.rvc && xcpt_if(j+1) + io.inst(i).valid := valid(j) && (exp.io.rvc || valid(j+1) || pf(j+1) || ae(j+1) || replay) + io.inst(i).bits.pf0 := pf(j) + io.inst(i).bits.pf1 := !exp.io.rvc && pf(j+1) + io.inst(i).bits.ae0 := ae(j) + io.inst(i).bits.ae1 := !exp.io.rvc && ae(j+1) io.inst(i).bits.replay := replay io.inst(i).bits.btb_hit := btbHitMask(j) || (!exp.io.rvc && btbHitMask(j+1)) io.inst(i).bits.rvc := exp.io.rvc @@ -110,8 +115,10 @@ class IBuf(implicit p: Parameters) extends CoreModule { } else { when (io.inst(i).ready) { nReady := i+1 } io.inst(i).valid := valid(i) - io.inst(i).bits.pf0 := xcpt_if(i) + io.inst(i).bits.pf0 := pf(i) io.inst(i).bits.pf1 := false + io.inst(i).bits.ae0 := ae(i) + io.inst(i).bits.ae1 := false io.inst(i).bits.replay := ic_replay(i) io.inst(i).bits.rvc := false io.inst(i).bits.btb_hit := btbHitMask(i) diff --git a/src/main/scala/rocket/Instructions.scala b/src/main/scala/rocket/Instructions.scala index 5ac87564..81579f57 100644 --- a/src/main/scala/rocket/Instructions.scala +++ b/src/main/scala/rocket/Instructions.scala @@ -216,31 +216,37 @@ object Instructions { } object Causes { val misaligned_fetch = 0x0 - val fault_fetch = 0x1 + val fetch_access = 0x1 val illegal_instruction = 0x2 val breakpoint = 0x3 val misaligned_load = 0x4 - val fault_load = 0x5 + val load_access = 0x5 val misaligned_store = 0x6 - val fault_store = 0x7 + val store_access = 0x7 val user_ecall = 0x8 val supervisor_ecall = 0x9 val hypervisor_ecall = 0xa val machine_ecall = 0xb + val fetch_page_fault = 0xc + val load_page_fault = 0xd + val store_page_fault = 0xf val all = { val res = collection.mutable.ArrayBuffer[Int]() res += misaligned_fetch - res += fault_fetch + res += fetch_access res += illegal_instruction res += breakpoint res += misaligned_load - res += fault_load + res += load_access res += misaligned_store - res += fault_store + res += store_access res += user_ecall res += supervisor_ecall res += hypervisor_ecall res += machine_ecall + res += fetch_page_fault + res += load_page_fault + res += store_page_fault res.toArray } } diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index 9ec9ec4f..b840f527 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -745,8 +745,10 @@ class NonBlockingDCacheModule(outer: NonBlockingDCache) extends HellaCacheModule val misaligned = new StoreGen(s1_req.typ, s1_req.addr, UInt(0), wordBytes).misaligned io.cpu.xcpt.ma.ld := s1_read && misaligned io.cpu.xcpt.ma.st := s1_write && misaligned - io.cpu.xcpt.pf.ld := s1_read && dtlb.io.resp.xcpt_ld - io.cpu.xcpt.pf.st := s1_write && dtlb.io.resp.xcpt_st + io.cpu.xcpt.pf.ld := s1_read && dtlb.io.resp.pf.ld + io.cpu.xcpt.pf.st := s1_write && dtlb.io.resp.pf.st + io.cpu.xcpt.ae.ld := s1_read && dtlb.io.resp.ae.ld + io.cpu.xcpt.ae.st := s1_write && dtlb.io.resp.ae.st // tags def onReset = L1Metadata(UInt(0), ClientMetadata.onReset) diff --git a/src/main/scala/rocket/PTW.scala b/src/main/scala/rocket/PTW.scala index cab539ea..edeef24b 100644 --- a/src/main/scala/rocket/PTW.scala +++ b/src/main/scala/rocket/PTW.scala @@ -19,6 +19,7 @@ class PTWReq(implicit p: Parameters) extends CoreBundle()(p) { } class PTWResp(implicit p: Parameters) extends CoreBundle()(p) { + val ae = Bool() val pte = new PTE val level = UInt(width = log2Ceil(pgLevels)) val homogeneous = Bool() @@ -77,7 +78,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( val count = Reg(UInt(width = log2Up(pgLevels))) val s1_kill = Reg(next = Bool(false)) val resp_valid = Reg(next = Vec.fill(io.requestor.size)(Bool(false))) - val exception = Reg(next = io.mem.xcpt.pf.ld) + val ae = Reg(next = io.mem.xcpt.ae.ld) val r_req = Reg(new PTWReq) val r_req_dest = Reg(Bits()) @@ -90,14 +91,15 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( arb.io.in <> io.requestor.map(_.req) arb.io.out.ready := state === s_ready - val pte = { + val (pte, invalid_paddr) = { val tmp = new PTE().fromBits(io.mem.resp.bits.data) val res = Wire(init = new PTE().fromBits(io.mem.resp.bits.data)) res.ppn := tmp.ppn(ppnBits-1, 0) - when ((tmp.ppn >> ppnBits) =/= 0) { res.v := false } - res + (res, (tmp.ppn >> ppnBits) =/= 0) } + val traverse = pte.table() && !invalid_paddr && count < pgLevels-1 val pte_addr = Cat(r_pte.ppn, vpn_idx) << log2Ceil(xLen/8) + val resp_ae = Reg(next = ae || invalid_paddr) when (arb.io.out.fire()) { r_req := arb.io.out.bits @@ -114,7 +116,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( val hits = tags.map(_ === pte_addr).asUInt & valid val hit = hits.orR - when (io.mem.resp.valid && pte.table() && !hit) { + when (io.mem.resp.valid && traverse && !hit) { val r = Mux(valid.andR, plru.replace, PriorityEncoder(~valid)) valid := valid | UIntToOH(r) tags(r) := pte_addr @@ -142,6 +144,7 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( for (i <- 0 until io.requestor.size) { io.requestor(i).resp.valid := resp_valid(i) + io.requestor(i).resp.bits.ae := resp_ae io.requestor(i).resp.bits.pte := r_pte io.requestor(i).resp.bits.level := count io.requestor(i).resp.bits.pte.ppn := pte_addr >> pgIdxBits @@ -177,16 +180,17 @@ class PTW(n: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()( } when (io.mem.resp.valid) { r_pte := pte - when (pte.table() && count < pgLevels-1) { + when (traverse) { state := s_req count := count + 1 }.otherwise { + resp_ae := invalid_paddr state := s_ready resp_valid(r_req_dest) := true } } - when (exception) { - r_pte.v := false + when (ae) { + resp_ae := true state := s_ready resp_valid(r_req_dest) := true } diff --git a/src/main/scala/rocket/Rocket.scala b/src/main/scala/rocket/Rocket.scala index 51dd8316..03857960 100644 --- a/src/main/scala/rocket/Rocket.scala +++ b/src/main/scala/rocket/Rocket.scala @@ -225,12 +225,14 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) bpu.io.pc := ibuf.io.pc bpu.io.ea := mem_reg_wdata - val id_xcpt_if = ibuf.io.inst(0).bits.pf0 || ibuf.io.inst(0).bits.pf1 + val id_xcpt_pf = ibuf.io.inst(0).bits.pf0 || ibuf.io.inst(0).bits.pf1 + val id_xcpt_ae = ibuf.io.inst(0).bits.ae0 || ibuf.io.inst(0).bits.ae1 val (id_xcpt, id_cause) = checkExceptions(List( (csr.io.interrupt, csr.io.interrupt_cause), (bpu.io.debug_if, UInt(CSR.debugTriggerCause)), (bpu.io.xcpt_if, UInt(Causes.breakpoint)), - (id_xcpt_if, UInt(Causes.fault_fetch)), + (id_xcpt_pf, UInt(Causes.fetch_page_fault)), + (id_xcpt_ae, UInt(Causes.fetch_access)), (id_illegal_insn, UInt(Causes.illegal_instruction)))) val dcache_bypass_data = @@ -423,8 +425,10 @@ class Rocket(implicit p: Parameters) extends CoreModule()(p) val (wb_xcpt, wb_cause) = checkExceptions(List( (wb_reg_xcpt, wb_reg_cause), - (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.st, mem_pc_valid), UInt(Causes.fault_store)), - (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.ld, mem_pc_valid), UInt(Causes.fault_load)) + (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.st, mem_pc_valid), UInt(Causes.store_page_fault)), + (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.pf.ld, mem_pc_valid), UInt(Causes.load_page_fault)), + (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.ae.st, mem_pc_valid), UInt(Causes.store_access)), + (wb_reg_valid && wb_ctrl.mem && RegEnable(io.dmem.xcpt.ae.ld, mem_pc_valid), UInt(Causes.load_access)) )) val wb_wxd = wb_reg_valid && wb_ctrl.wxd diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index 51f84459..b2714a35 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -33,20 +33,25 @@ class TLBReq(lgMaxSize: Int)(implicit p: Parameters) extends CoreBundle()(p) { override def cloneType = new TLBReq(lgMaxSize).asInstanceOf[this.type] } +class TLBExceptions extends Bundle { + val ld = Bool() + val st = Bool() + val inst = Bool() +} + class TLBResp(implicit p: Parameters) extends CoreBundle()(p) { // lookup responses - val miss = Bool(OUTPUT) - val paddr = UInt(OUTPUT, paddrBits) - val xcpt_ld = Bool(OUTPUT) - val xcpt_st = Bool(OUTPUT) - val xcpt_if = Bool(OUTPUT) - val cacheable = Bool(OUTPUT) + val miss = Bool() + val paddr = UInt(width = paddrBits) + val pf = new TLBExceptions + val ae = new TLBExceptions + val cacheable = Bool() } class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters) extends CoreModule()(p) { val io = new Bundle { val req = Decoupled(new TLBReq(lgMaxSize)).flip - val resp = new TLBResp + val resp = new TLBResp().asOutput val ptw = new TLBPTWIO } @@ -59,8 +64,10 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters val sw = Bool() val sx = Bool() val sr = Bool() - val xr = Bool() - val cacheable = Bool() + val pw = Bool() + val px = Bool() + val pr = Bool() + val c = Bool() } val totalEntries = nEntries + 1 @@ -101,7 +108,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters val prot_w = fastCheck(_.supportsPutFull) && pmp.io.w val prot_x = fastCheck(_.executable) && pmp.io.x val cacheable = fastCheck(_.supportsAcquireB) - val isSpecial = !io.ptw.resp.bits.homogeneous + val isSpecial = !(io.ptw.resp.bits.homogeneous || io.ptw.resp.bits.ae) val lookup_tag = Cat(io.ptw.ptbr.asid, vpn(vpnBits-1,0)) val hitsVec = (0 until totalEntries).map { i => vm_enabled && { @@ -123,13 +130,6 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters } // permission bit arrays - val u_array = Reg(Vec(totalEntries, Bool())) // user permission - val g_array = Reg(Vec(totalEntries, Bool())) // global mapping - val sw_array = Reg(Vec(totalEntries, Bool())) // write permission - val sx_array = Reg(Vec(totalEntries, Bool())) // execute permission - val sr_array = Reg(Vec(totalEntries, Bool())) // read permission - val xr_array = Reg(Vec(totalEntries, Bool())) // read permission to executable page - val cash_array = Reg(Vec(normalEntries, Bool())) // cacheable when (do_refill && !invalidate_refill) { val waddr = Mux(isSpecial, specialEntry.U, r_refill_waddr) val pte = io.ptw.resp.bits.pte @@ -137,13 +137,15 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters newEntry.ppn := pte.ppn newEntry.tag := r_refill_tag newEntry.level := io.ptw.resp.bits.level + newEntry.c := cacheable newEntry.u := pte.u newEntry.g := pte.g - newEntry.sw := pte.sw() && (isSpecial || prot_w) - newEntry.sx := pte.sx() && (isSpecial || prot_x) - newEntry.sr := pte.sr() && (isSpecial || prot_r) - newEntry.xr := pte.sx() && (isSpecial || prot_r) - newEntry.cacheable := isSpecial || cacheable + newEntry.sr := pte.sr() + newEntry.sw := pte.sw() + newEntry.sx := pte.sx() + newEntry.pr := prot_r && !io.ptw.resp.bits.ae + newEntry.pw := prot_w && !io.ptw.resp.bits.ae + newEntry.px := prot_x && !io.ptw.resp.bits.ae valid := valid | UIntToOH(waddr) reg_entries(waddr) := newEntry.asUInt @@ -153,10 +155,13 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters val repl_waddr = Mux(!valid(normalEntries-1, 0).andR, PriorityEncoder(~valid(normalEntries-1, 0)), plru.replace) val priv_ok = Mux(priv_s, ~Mux(io.ptw.status.sum, UInt(0), entries.map(_.u).asUInt), entries.map(_.u).asUInt) - val w_array = Cat(prot_w, priv_ok & ~(~prot_w << specialEntry) & entries.map(_.sw).asUInt) - val x_array = Cat(prot_x, priv_ok & ~(~prot_x << specialEntry) & entries.map(_.sx).asUInt) - val r_array = Cat(prot_r, priv_ok & ~(~prot_r << specialEntry) & (entries.map(_.sr).asUInt | Mux(io.ptw.status.mxr, entries.map(_.xr).asUInt, UInt(0)))) - val c_array = Cat(cacheable, ~(~cacheable << specialEntry) & entries.map(_.cacheable).asUInt) + val r_array = Cat(true.B, priv_ok & (entries.map(_.sr).asUInt | Mux(io.ptw.status.mxr, entries.map(_.sx).asUInt, UInt(0)))) + val w_array = Cat(true.B, priv_ok & entries.map(_.sw).asUInt) + val x_array = Cat(true.B, priv_ok & entries.map(_.sx).asUInt) + val pr_array = Cat(Fill(2, prot_r), entries.init.map(_.pr).asUInt) + val pw_array = Cat(Fill(2, prot_w), entries.init.map(_.pw).asUInt) + val px_array = Cat(Fill(2, prot_x), entries.init.map(_.px).asUInt) + val c_array = Cat(Fill(2, cacheable), entries.init.map(_.c).asUInt) val bad_va = if (vpnBits == vpnBitsExtended) Bool(false) @@ -176,9 +181,12 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters val multipleHits = PopCountAtLeast(hits(totalEntries-1, 0), 2) io.req.ready := state === s_ready - io.resp.xcpt_ld := bad_va || (~r_array & hits).orR - io.resp.xcpt_st := bad_va || (~w_array & hits).orR - io.resp.xcpt_if := bad_va || (~x_array & hits).orR + io.resp.pf.ld := bad_va || (~r_array & hits).orR + io.resp.pf.st := bad_va || (~w_array & hits).orR + io.resp.pf.inst := bad_va || (~x_array & hits).orR + io.resp.ae.ld := (~pr_array & hits).orR + io.resp.ae.st := (~pw_array & hits).orR + io.resp.ae.inst := (~px_array & hits).orR io.resp.cacheable := (c_array & hits).orR io.resp.miss := do_refill || tlb_miss || multipleHits io.resp.paddr := Cat(ppn, pgOffset) @@ -208,7 +216,7 @@ class TLB(lgMaxSize: Int, nEntries: Int)(implicit edge: TLEdgeOut, p: Parameters when (sfence) { valid := Mux(io.req.bits.sfence.bits.rs1, valid & ~hits(totalEntries-1, 0), - Mux(io.req.bits.sfence.bits.rs2, valid & g_array.asUInt, 0)) + Mux(io.req.bits.sfence.bits.rs2, valid & entries.map(_.g).asUInt, 0)) } when (multipleHits) { valid := 0