192e3bfefSLemover/*************************************************************************************** 292e3bfefSLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 392e3bfefSLemover* Copyright (c) 2020-2021 Peng Cheng Laboratory 492e3bfefSLemover* 592e3bfefSLemover* XiangShan is licensed under Mulan PSL v2. 692e3bfefSLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 792e3bfefSLemover* You may obtain a copy of Mulan PSL v2 at: 892e3bfefSLemover* http://license.coscl.org.cn/MulanPSL2 992e3bfefSLemover* 1092e3bfefSLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1192e3bfefSLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1292e3bfefSLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1392e3bfefSLemover* 1492e3bfefSLemover* See the Mulan PSL v2 for more details. 1592e3bfefSLemover***************************************************************************************/ 1692e3bfefSLemover 1792e3bfefSLemoverpackage xiangshan.cache.mmu 1892e3bfefSLemover 1992e3bfefSLemoverimport chipsalliance.rocketchip.config.Parameters 2092e3bfefSLemoverimport chisel3._ 2192e3bfefSLemoverimport chisel3.experimental.ExtModule 2292e3bfefSLemoverimport chisel3.util._ 2392e3bfefSLemoverimport chisel3.internal.naming.chiselName 2492e3bfefSLemoverimport xiangshan._ 2592e3bfefSLemoverimport xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} 2692e3bfefSLemoverimport utils._ 273c02ee8fSwakafaimport utility._ 2892e3bfefSLemoverimport freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp} 2992e3bfefSLemoverimport freechips.rocketchip.tilelink._ 3092e3bfefSLemoverimport xiangshan.backend.fu.{PMP, PMPChecker, PMPReqBundle, PMPRespBundle} 3192e3bfefSLemoverimport xiangshan.backend.fu.util.HasCSRConst 323c02ee8fSwakafaimport utility.ChiselDB 339c26bab7SHaoyuan Fengimport difftest._ 3492e3bfefSLemover 3592e3bfefSLemoverclass L2TLB()(implicit p: Parameters) extends LazyModule with HasPtwConst { 3692e3bfefSLemover 3792e3bfefSLemover val node = TLClientNode(Seq(TLMasterPortParameters.v1( 3892e3bfefSLemover clients = Seq(TLMasterParameters.v1( 3992e3bfefSLemover "ptw", 4092e3bfefSLemover sourceId = IdRange(0, MemReqWidth) 4192e3bfefSLemover )) 4292e3bfefSLemover ))) 4392e3bfefSLemover 4492e3bfefSLemover lazy val module = new L2TLBImp(this) 4592e3bfefSLemover} 4692e3bfefSLemover 4792e3bfefSLemover@chiselName 4892e3bfefSLemoverclass L2TLBImp(outer: L2TLB)(implicit p: Parameters) extends PtwModule(outer) with HasCSRConst with HasPerfEvents { 4992e3bfefSLemover 5092e3bfefSLemover val (mem, edge) = outer.node.out.head 5192e3bfefSLemover 5292e3bfefSLemover val io = IO(new L2TLBIO) 5392e3bfefSLemover val difftestIO = IO(new Bundle() { 5492e3bfefSLemover val ptwResp = Output(Bool()) 5592e3bfefSLemover val ptwAddr = Output(UInt(64.W)) 5692e3bfefSLemover val ptwData = Output(Vec(4, UInt(64.W))) 5792e3bfefSLemover }) 5892e3bfefSLemover 5992e3bfefSLemover /* Ptw processes multiple requests 6092e3bfefSLemover * Divide Ptw procedure into two stages: cache access ; mem access if cache miss 6192e3bfefSLemover * miss queue itlb dtlb 6292e3bfefSLemover * | | | 6392e3bfefSLemover * ------arbiter------ 6492e3bfefSLemover * | 6592e3bfefSLemover * l1 - l2 - l3 - sp 6692e3bfefSLemover * | 6792e3bfefSLemover * ------------------------------------------- 6892e3bfefSLemover * miss | queue | hit 6992e3bfefSLemover * [][][][][][] | 7092e3bfefSLemover * | | 7192e3bfefSLemover * state machine accessing mem | 7292e3bfefSLemover * | | 7392e3bfefSLemover * ---------------arbiter--------------------- 7492e3bfefSLemover * | | 7592e3bfefSLemover * itlb dtlb 7692e3bfefSLemover */ 7792e3bfefSLemover 7892e3bfefSLemover difftestIO <> DontCare 7992e3bfefSLemover 807797f035SbugGenerator val sfence_tmp = DelayN(io.sfence, 1) 817797f035SbugGenerator val csr_tmp = DelayN(io.csr.tlb, 1) 827797f035SbugGenerator val sfence_dup = Seq.fill(8)(RegNext(sfence_tmp)) 837797f035SbugGenerator val csr_dup = Seq.fill(7)(RegNext(csr_tmp)) 847797f035SbugGenerator val satp = csr_dup(0).satp 857797f035SbugGenerator val priv = csr_dup(0).priv 867797f035SbugGenerator val flush = sfence_dup(0).valid || satp.changed 8792e3bfefSLemover 8892e3bfefSLemover val pmp = Module(new PMP()) 8992e3bfefSLemover val pmp_check = VecInit(Seq.fill(2)(Module(new PMPChecker(lgMaxSize = 3, sameCycle = true)).io)) 9092e3bfefSLemover pmp.io.distribute_csr := io.csr.distribute_csr 9192e3bfefSLemover pmp_check.foreach(_.check_env.apply(ModeS, pmp.io.pmp, pmp.io.pma)) 9292e3bfefSLemover 9392e3bfefSLemover val missQueue = Module(new L2TlbMissQueue) 9492e3bfefSLemover val cache = Module(new PtwCache) 9592e3bfefSLemover val ptw = Module(new PTW) 9692e3bfefSLemover val llptw = Module(new LLPTW) 977797f035SbugGenerator val blockmq = Module(new BlockHelper(3)) 9892e3bfefSLemover val arb1 = Module(new Arbiter(new PtwReq, PtwWidth)) 9992e3bfefSLemover val arb2 = Module(new Arbiter(new Bundle { 10092e3bfefSLemover val vpn = UInt(vpnLen.W) 10192e3bfefSLemover val source = UInt(bSourceWidth.W) 1029c503409SLemover }, if (l2tlbParams.enablePrefetch) 4 else 3)) 10392e3bfefSLemover val outArb = (0 until PtwWidth).map(i => Module(new Arbiter(new PtwResp, 3)).io) 10492e3bfefSLemover val outArbCachePort = 0 10592e3bfefSLemover val outArbFsmPort = 1 10692e3bfefSLemover val outArbMqPort = 2 10792e3bfefSLemover 1089c503409SLemover // arb2 input port 1099c503409SLemover val InArbPTWPort = 0 1109c503409SLemover val InArbMissQueuePort = 1 1119c503409SLemover val InArbTlbPort = 2 1129c503409SLemover val InArbPrefetchPort = 3 11392e3bfefSLemover // NOTE: when cache out but miss and ptw doesnt accept, 11492e3bfefSLemover arb1.io.in <> VecInit(io.tlb.map(_.req(0))) 1159c503409SLemover arb1.io.out.ready := arb2.io.in(InArbTlbPort).ready 11692e3bfefSLemover 1179c503409SLemover arb2.io.in(InArbPTWPort).valid := ptw.io.llptw.valid 1189c503409SLemover arb2.io.in(InArbPTWPort).bits.vpn := ptw.io.llptw.bits.req_info.vpn 1199c503409SLemover arb2.io.in(InArbPTWPort).bits.source := ptw.io.llptw.bits.req_info.source 1209c503409SLemover ptw.io.llptw.ready := arb2.io.in(InArbPTWPort).ready 12192e3bfefSLemover block_decoupled(missQueue.io.out, arb2.io.in(InArbMissQueuePort), !ptw.io.req.ready) 1227797f035SbugGenerator 12392e3bfefSLemover arb2.io.in(InArbTlbPort).valid := arb1.io.out.valid 12492e3bfefSLemover arb2.io.in(InArbTlbPort).bits.vpn := arb1.io.out.bits.vpn 12592e3bfefSLemover arb2.io.in(InArbTlbPort).bits.source := arb1.io.chosen 12692e3bfefSLemover if (l2tlbParams.enablePrefetch) { 12792e3bfefSLemover val prefetch = Module(new L2TlbPrefetch()) 12892e3bfefSLemover val recv = cache.io.resp 12992e3bfefSLemover // NOTE: 1. prefetch doesn't gen prefetch 2. req from mq doesn't gen prefetch 13092e3bfefSLemover // NOTE: 1. miss req gen prefetch 2. hit but prefetched gen prefetch 13192e3bfefSLemover prefetch.io.in.valid := recv.fire() && !from_pre(recv.bits.req_info.source) && (!recv.bits.hit || 13292e3bfefSLemover recv.bits.prefetch) && recv.bits.isFirst 13392e3bfefSLemover prefetch.io.in.bits.vpn := recv.bits.req_info.vpn 1347797f035SbugGenerator prefetch.io.sfence := sfence_dup(0) 1357797f035SbugGenerator prefetch.io.csr := csr_dup(0) 13692e3bfefSLemover arb2.io.in(InArbPrefetchPort) <> prefetch.io.out 1375afdf73cSHaoyuan Feng 1385afdf73cSHaoyuan Feng val L2TlbPrefetchTable = ChiselDB.createTable("L2TlbPrefetch_hart" + p(XSCoreParamsKey).HartId.toString, new L2TlbPrefetchDB) 1395afdf73cSHaoyuan Feng val L2TlbPrefetchDB = Wire(new L2TlbPrefetchDB) 1405afdf73cSHaoyuan Feng L2TlbPrefetchDB.vpn := prefetch.io.out.bits.vpn 1415afdf73cSHaoyuan Feng L2TlbPrefetchTable.log(L2TlbPrefetchDB, prefetch.io.out.fire, "L2TlbPrefetch", clock, reset) 14292e3bfefSLemover } 14392e3bfefSLemover arb2.io.out.ready := cache.io.req.ready 14492e3bfefSLemover 1457797f035SbugGenerator 1467797f035SbugGenerator val mq_arb = Module(new Arbiter(new L2TlbInnerBundle, 2)) 1477797f035SbugGenerator mq_arb.io.in(0).valid := cache.io.resp.valid && !cache.io.resp.bits.hit && 1487797f035SbugGenerator (!cache.io.resp.bits.toFsm.l2Hit || cache.io.resp.bits.bypassed) && 1497797f035SbugGenerator !from_pre(cache.io.resp.bits.req_info.source) && 1507797f035SbugGenerator (cache.io.resp.bits.bypassed || cache.io.resp.bits.isFirst || !ptw.io.req.ready) 1517797f035SbugGenerator mq_arb.io.in(0).bits := cache.io.resp.bits.req_info 1527797f035SbugGenerator mq_arb.io.in(1) <> llptw.io.cache 1537797f035SbugGenerator missQueue.io.in <> mq_arb.io.out 1547797f035SbugGenerator missQueue.io.sfence := sfence_dup(6) 1557797f035SbugGenerator missQueue.io.csr := csr_dup(5) 1567797f035SbugGenerator 1577797f035SbugGenerator blockmq.io.start := missQueue.io.out.fire 1587797f035SbugGenerator blockmq.io.enable := ptw.io.req.fire() 1597797f035SbugGenerator 1609c503409SLemover llptw.io.in.valid := cache.io.resp.valid && !cache.io.resp.bits.hit && cache.io.resp.bits.toFsm.l2Hit && !cache.io.resp.bits.bypassed 1619c503409SLemover llptw.io.in.bits.req_info := cache.io.resp.bits.req_info 1629c503409SLemover llptw.io.in.bits.ppn := cache.io.resp.bits.toFsm.ppn 1637797f035SbugGenerator llptw.io.sfence := sfence_dup(1) 1647797f035SbugGenerator llptw.io.csr := csr_dup(1) 16592e3bfefSLemover 16692e3bfefSLemover cache.io.req.valid := arb2.io.out.valid 16792e3bfefSLemover cache.io.req.bits.req_info.vpn := arb2.io.out.bits.vpn 16892e3bfefSLemover cache.io.req.bits.req_info.source := arb2.io.out.bits.source 16992e3bfefSLemover cache.io.req.bits.isFirst := arb2.io.chosen =/= InArbMissQueuePort.U 1701f4a7c0cSLemover cache.io.req.bits.bypassed.map(_ := false.B) 1717797f035SbugGenerator cache.io.sfence := sfence_dup(2) 1727797f035SbugGenerator cache.io.csr := csr_dup(2) 1737797f035SbugGenerator cache.io.sfence_dup.zip(sfence_dup.drop(2).take(4)).map(s => s._1 := s._2) 1747797f035SbugGenerator cache.io.csr_dup.zip(csr_dup.drop(2).take(3)).map(c => c._1 := c._2) 17592e3bfefSLemover cache.io.resp.ready := Mux(cache.io.resp.bits.hit, 17692e3bfefSLemover outReady(cache.io.resp.bits.req_info.source, outArbCachePort), 1779c503409SLemover Mux(cache.io.resp.bits.toFsm.l2Hit && !cache.io.resp.bits.bypassed, llptw.io.in.ready, 1787797f035SbugGenerator Mux(cache.io.resp.bits.bypassed || cache.io.resp.bits.isFirst, mq_arb.io.in(0).ready, mq_arb.io.in(0).ready || ptw.io.req.ready))) 17992e3bfefSLemover 18092e3bfefSLemover // NOTE: missQueue req has higher priority 1817797f035SbugGenerator ptw.io.req.valid := cache.io.resp.valid && !cache.io.resp.bits.hit && !cache.io.resp.bits.toFsm.l2Hit && 1827797f035SbugGenerator !cache.io.resp.bits.bypassed && 1837797f035SbugGenerator !cache.io.resp.bits.isFirst 18492e3bfefSLemover ptw.io.req.bits.req_info := cache.io.resp.bits.req_info 18592e3bfefSLemover ptw.io.req.bits.l1Hit := cache.io.resp.bits.toFsm.l1Hit 18692e3bfefSLemover ptw.io.req.bits.ppn := cache.io.resp.bits.toFsm.ppn 1877797f035SbugGenerator ptw.io.sfence := sfence_dup(7) 1887797f035SbugGenerator ptw.io.csr := csr_dup(6) 18992e3bfefSLemover ptw.io.resp.ready := outReady(ptw.io.resp.bits.source, outArbFsmPort) 19092e3bfefSLemover 19192e3bfefSLemover // mem req 19292e3bfefSLemover def blockBytes_align(addr: UInt) = { 19392e3bfefSLemover Cat(addr(PAddrBits - 1, log2Up(l2tlbParams.blockBytes)), 0.U(log2Up(l2tlbParams.blockBytes).W)) 19492e3bfefSLemover } 19592e3bfefSLemover def addr_low_from_vpn(vpn: UInt) = { 19692e3bfefSLemover vpn(log2Ceil(l2tlbParams.blockBytes)-log2Ceil(XLEN/8)-1, 0) 19792e3bfefSLemover } 19892e3bfefSLemover def addr_low_from_paddr(paddr: UInt) = { 19992e3bfefSLemover paddr(log2Up(l2tlbParams.blockBytes)-1, log2Up(XLEN/8)) 20092e3bfefSLemover } 20192e3bfefSLemover def from_missqueue(id: UInt) = { 20292e3bfefSLemover (id =/= l2tlbParams.llptwsize.U) 20392e3bfefSLemover } 20492e3bfefSLemover val waiting_resp = RegInit(VecInit(Seq.fill(MemReqWidth)(false.B))) 20592e3bfefSLemover val flush_latch = RegInit(VecInit(Seq.fill(MemReqWidth)(false.B))) 20692e3bfefSLemover for (i <- waiting_resp.indices) { 20792e3bfefSLemover assert(!flush_latch(i) || waiting_resp(i)) // when sfence_latch wait for mem resp, waiting_resp should be true 20892e3bfefSLemover } 20992e3bfefSLemover 21092e3bfefSLemover val llptw_out = llptw.io.out 21192e3bfefSLemover val llptw_mem = llptw.io.mem 21292e3bfefSLemover llptw_mem.req_mask := waiting_resp.take(l2tlbParams.llptwsize) 21392e3bfefSLemover ptw.io.mem.mask := waiting_resp.last 21492e3bfefSLemover 21592e3bfefSLemover val mem_arb = Module(new Arbiter(new L2TlbMemReqBundle(), 2)) 21692e3bfefSLemover mem_arb.io.in(0) <> ptw.io.mem.req 21792e3bfefSLemover mem_arb.io.in(1) <> llptw_mem.req 21892e3bfefSLemover mem_arb.io.out.ready := mem.a.ready && !flush 21992e3bfefSLemover 2201f4a7c0cSLemover // assert, should not send mem access at same addr for twice. 2217797f035SbugGenerator val last_resp_vpn = RegEnable(cache.io.refill.bits.req_info_dup(0).vpn, cache.io.refill.valid) 2227797f035SbugGenerator val last_resp_level = RegEnable(cache.io.refill.bits.level_dup(0), cache.io.refill.valid) 2231f4a7c0cSLemover val last_resp_v = RegInit(false.B) 2241f4a7c0cSLemover val last_has_invalid = !Cat(cache.io.refill.bits.ptes.asTypeOf(Vec(blockBits/XLEN, UInt(XLEN.W))).map(a => a(0))).andR 2251f4a7c0cSLemover when (cache.io.refill.valid) { last_resp_v := !last_has_invalid} 2261f4a7c0cSLemover when (flush) { last_resp_v := false.B } 2271f4a7c0cSLemover XSError(last_resp_v && cache.io.refill.valid && 2287797f035SbugGenerator (cache.io.refill.bits.req_info_dup(0).vpn === last_resp_vpn) && 2297797f035SbugGenerator (cache.io.refill.bits.level_dup(0) === last_resp_level), 2301f4a7c0cSLemover "l2tlb should not access mem at same addr for twice") 2311f4a7c0cSLemover // ATTENTION: this may wronngly assert when: a ptes is l2, last part is valid, 2321f4a7c0cSLemover // but the current part is invalid, so one more mem access happened 2331f4a7c0cSLemover // If this happened, remove the assert. 2341f4a7c0cSLemover 23592e3bfefSLemover val req_addr_low = Reg(Vec(MemReqWidth, UInt((log2Up(l2tlbParams.blockBytes)-log2Up(XLEN/8)).W))) 23692e3bfefSLemover 23792e3bfefSLemover when (llptw.io.in.fire()) { 23892e3bfefSLemover // when enq miss queue, set the req_addr_low to receive the mem resp data part 23992e3bfefSLemover req_addr_low(llptw_mem.enq_ptr) := addr_low_from_vpn(llptw.io.in.bits.req_info.vpn) 24092e3bfefSLemover } 24192e3bfefSLemover when (mem_arb.io.out.fire()) { 24292e3bfefSLemover req_addr_low(mem_arb.io.out.bits.id) := addr_low_from_paddr(mem_arb.io.out.bits.addr) 24392e3bfefSLemover waiting_resp(mem_arb.io.out.bits.id) := true.B 24492e3bfefSLemover } 24592e3bfefSLemover // mem read 24692e3bfefSLemover val memRead = edge.Get( 24792e3bfefSLemover fromSource = mem_arb.io.out.bits.id, 24892e3bfefSLemover // toAddress = memAddr(log2Up(CacheLineSize / 2 / 8) - 1, 0), 24992e3bfefSLemover toAddress = blockBytes_align(mem_arb.io.out.bits.addr), 25092e3bfefSLemover lgSize = log2Up(l2tlbParams.blockBytes).U 25192e3bfefSLemover )._2 25292e3bfefSLemover mem.a.bits := memRead 25392e3bfefSLemover mem.a.valid := mem_arb.io.out.valid && !flush 25492e3bfefSLemover mem.d.ready := true.B 25592e3bfefSLemover // mem -> data buffer 25692e3bfefSLemover val refill_data = Reg(Vec(blockBits / l1BusDataWidth, UInt(l1BusDataWidth.W))) 25792e3bfefSLemover val refill_helper = edge.firstlastHelper(mem.d.bits, mem.d.fire()) 25892e3bfefSLemover val mem_resp_done = refill_helper._3 25992e3bfefSLemover val mem_resp_from_mq = from_missqueue(mem.d.bits.source) 26092e3bfefSLemover when (mem.d.valid) { 26192e3bfefSLemover assert(mem.d.bits.source <= l2tlbParams.llptwsize.U) 26292e3bfefSLemover refill_data(refill_helper._4) := mem.d.bits.data 26392e3bfefSLemover } 2647797f035SbugGenerator // refill_data_tmp is the wire fork of refill_data, but one cycle earlier 2657797f035SbugGenerator val refill_data_tmp = WireInit(refill_data) 2667797f035SbugGenerator refill_data_tmp(refill_helper._4) := mem.d.bits.data 2677797f035SbugGenerator 26892e3bfefSLemover // save only one pte for each id 26992e3bfefSLemover // (miss queue may can't resp to tlb with low latency, it should have highest priority, but diffcult to design cache) 27092e3bfefSLemover val resp_pte = VecInit((0 until MemReqWidth).map(i => 2717797f035SbugGenerator if (i == l2tlbParams.llptwsize) {RegEnable(get_part(refill_data_tmp, req_addr_low(i)), mem_resp_done && !mem_resp_from_mq) } 27292e3bfefSLemover else { DataHoldBypass(get_part(refill_data, req_addr_low(i)), llptw_mem.buffer_it(i)) } 2737797f035SbugGenerator // llptw could not use refill_data_tmp, because enq bypass's result works at next cycle 27492e3bfefSLemover )) 27592e3bfefSLemover 27692e3bfefSLemover // mem -> miss queue 27792e3bfefSLemover llptw_mem.resp.valid := mem_resp_done && mem_resp_from_mq 2787797f035SbugGenerator llptw_mem.resp.bits.id := DataHoldBypass(mem.d.bits.source, mem.d.valid) 27992e3bfefSLemover // mem -> ptw 28092e3bfefSLemover ptw.io.mem.req.ready := mem.a.ready 28192e3bfefSLemover ptw.io.mem.resp.valid := mem_resp_done && !mem_resp_from_mq 28292e3bfefSLemover ptw.io.mem.resp.bits := resp_pte.last 28392e3bfefSLemover // mem -> cache 2847797f035SbugGenerator val refill_from_mq = mem_resp_from_mq 2857797f035SbugGenerator val refill_level = Mux(refill_from_mq, 2.U, RegEnable(ptw.io.refill.level, init = 0.U, ptw.io.mem.req.fire())) 2867797f035SbugGenerator val refill_valid = mem_resp_done && !flush && !flush_latch(mem.d.bits.source) 2877797f035SbugGenerator 2887797f035SbugGenerator cache.io.refill.valid := RegNext(refill_valid, false.B) 28992e3bfefSLemover cache.io.refill.bits.ptes := refill_data.asUInt 2907797f035SbugGenerator cache.io.refill.bits.req_info_dup.map(_ := RegEnable(Mux(refill_from_mq, llptw_mem.refill, ptw.io.refill.req_info), refill_valid)) 2917797f035SbugGenerator cache.io.refill.bits.level_dup.map(_ := RegEnable(refill_level, refill_valid)) 2927797f035SbugGenerator cache.io.refill.bits.levelOH(refill_level, refill_valid) 2937797f035SbugGenerator cache.io.refill.bits.sel_pte_dup.map(_ := RegNext(sel_data(refill_data_tmp.asUInt, req_addr_low(mem.d.bits.source)))) 29492e3bfefSLemover 2959c26bab7SHaoyuan Feng if (env.EnableDifftest) { 2969c26bab7SHaoyuan Feng val difftest_ptw_addr = RegInit(VecInit(Seq.fill(MemReqWidth)(0.U(PAddrBits.W)))) 2979c26bab7SHaoyuan Feng when (mem.a.valid) { 2989c26bab7SHaoyuan Feng difftest_ptw_addr(mem.a.bits.source) := mem.a.bits.address 2999c26bab7SHaoyuan Feng } 3009c26bab7SHaoyuan Feng 3019c26bab7SHaoyuan Feng val difftest = Module(new DifftestRefillEvent) 3029c26bab7SHaoyuan Feng difftest.io.clock := clock 3039c26bab7SHaoyuan Feng difftest.io.coreid := p(XSCoreParamsKey).HartId.asUInt 3049c26bab7SHaoyuan Feng difftest.io.cacheid := 2.U 3059c26bab7SHaoyuan Feng difftest.io.valid := cache.io.refill.valid 3069c26bab7SHaoyuan Feng difftest.io.addr := difftest_ptw_addr(RegNext(mem.d.bits.source)) 3079c26bab7SHaoyuan Feng difftest.io.data := refill_data.asTypeOf(difftest.io.data) 3089c26bab7SHaoyuan Feng } 3099c26bab7SHaoyuan Feng 310*5ab1b84dSHaoyuan Feng if (env.EnableDifftest) { 311*5ab1b84dSHaoyuan Feng for (i <- 0 until PtwWidth) { 312*5ab1b84dSHaoyuan Feng val difftest = Module(new DifftestL2TLBEvent) 313*5ab1b84dSHaoyuan Feng difftest.io.clock := clock 314*5ab1b84dSHaoyuan Feng difftest.io.coreid := p(XSCoreParamsKey).HartId.asUInt 315*5ab1b84dSHaoyuan Feng difftest.io.valid := io.tlb(i).resp.fire && !io.tlb(i).resp.bits.af 316*5ab1b84dSHaoyuan Feng difftest.io.index := i.U 317*5ab1b84dSHaoyuan Feng difftest.io.satp := io.csr.tlb.satp.ppn 318*5ab1b84dSHaoyuan Feng difftest.io.vpn := io.tlb(i).resp.bits.entry.tag 319*5ab1b84dSHaoyuan Feng difftest.io.ppn := io.tlb(i).resp.bits.entry.ppn 320*5ab1b84dSHaoyuan Feng difftest.io.perm := io.tlb(i).resp.bits.entry.perm.getOrElse(0.U.asTypeOf(new PtePermBundle)).asUInt 321*5ab1b84dSHaoyuan Feng difftest.io.level := io.tlb(i).resp.bits.entry.level.getOrElse(0.U.asUInt) 322*5ab1b84dSHaoyuan Feng difftest.io.pf := io.tlb(i).resp.bits.pf 323*5ab1b84dSHaoyuan Feng } 324*5ab1b84dSHaoyuan Feng } 325*5ab1b84dSHaoyuan Feng 32692e3bfefSLemover // pmp 32792e3bfefSLemover pmp_check(0).req <> ptw.io.pmp.req 32892e3bfefSLemover ptw.io.pmp.resp <> pmp_check(0).resp 32992e3bfefSLemover pmp_check(1).req <> llptw.io.pmp.req 33092e3bfefSLemover llptw.io.pmp.resp <> pmp_check(1).resp 33192e3bfefSLemover 33292e3bfefSLemover llptw_out.ready := outReady(llptw_out.bits.req_info.source, outArbMqPort) 33392e3bfefSLemover for (i <- 0 until PtwWidth) { 33492e3bfefSLemover outArb(i).in(outArbCachePort).valid := cache.io.resp.valid && cache.io.resp.bits.hit && cache.io.resp.bits.req_info.source===i.U 33592e3bfefSLemover outArb(i).in(outArbCachePort).bits.entry := cache.io.resp.bits.toTlb 33692e3bfefSLemover outArb(i).in(outArbCachePort).bits.pf := !cache.io.resp.bits.toTlb.v 33792e3bfefSLemover outArb(i).in(outArbCachePort).bits.af := false.B 33892e3bfefSLemover outArb(i).in(outArbFsmPort).valid := ptw.io.resp.valid && ptw.io.resp.bits.source===i.U 33992e3bfefSLemover outArb(i).in(outArbFsmPort).bits := ptw.io.resp.bits.resp 34092e3bfefSLemover outArb(i).in(outArbMqPort).valid := llptw_out.valid && llptw_out.bits.req_info.source===i.U 34192e3bfefSLemover outArb(i).in(outArbMqPort).bits := pte_to_ptwResp(resp_pte(llptw_out.bits.id), llptw_out.bits.req_info.vpn, llptw_out.bits.af, true) 34292e3bfefSLemover } 34392e3bfefSLemover 34492e3bfefSLemover // io.tlb.map(_.resp) <> outArb.map(_.out) 34592e3bfefSLemover io.tlb.map(_.resp).zip(outArb.map(_.out)).map{ 34692e3bfefSLemover case (resp, out) => resp <> out 34792e3bfefSLemover } 34892e3bfefSLemover 34992e3bfefSLemover // sfence 35092e3bfefSLemover when (flush) { 35192e3bfefSLemover for (i <- 0 until MemReqWidth) { 35292e3bfefSLemover when (waiting_resp(i)) { 35392e3bfefSLemover flush_latch(i) := true.B 35492e3bfefSLemover } 35592e3bfefSLemover } 35692e3bfefSLemover } 35792e3bfefSLemover // mem -> control signal 35892e3bfefSLemover // waiting_resp and sfence_latch will be reset when mem_resp_done 35992e3bfefSLemover when (mem_resp_done) { 36092e3bfefSLemover waiting_resp(mem.d.bits.source) := false.B 36192e3bfefSLemover flush_latch(mem.d.bits.source) := false.B 36292e3bfefSLemover } 36392e3bfefSLemover 36492e3bfefSLemover def block_decoupled[T <: Data](source: DecoupledIO[T], sink: DecoupledIO[T], block_signal: Bool) = { 36592e3bfefSLemover sink.valid := source.valid && !block_signal 36692e3bfefSLemover source.ready := sink.ready && !block_signal 36792e3bfefSLemover sink.bits := source.bits 36892e3bfefSLemover } 36992e3bfefSLemover 37092e3bfefSLemover def get_part(data: Vec[UInt], index: UInt): UInt = { 37192e3bfefSLemover val inner_data = data.asTypeOf(Vec(data.getWidth / XLEN, UInt(XLEN.W))) 37292e3bfefSLemover inner_data(index) 37392e3bfefSLemover } 37492e3bfefSLemover 37592e3bfefSLemover def pte_to_ptwResp(pte: UInt, vpn: UInt, af: Bool, af_first: Boolean) : PtwResp = { 37692e3bfefSLemover val pte_in = pte.asTypeOf(new PteBundle()) 37792e3bfefSLemover val ptw_resp = Wire(new PtwResp()) 37892e3bfefSLemover ptw_resp.entry.ppn := pte_in.ppn 37992e3bfefSLemover ptw_resp.entry.level.map(_ := 2.U) 38092e3bfefSLemover ptw_resp.entry.perm.map(_ := pte_in.getPerm()) 38192e3bfefSLemover ptw_resp.entry.tag := vpn 38292e3bfefSLemover ptw_resp.pf := (if (af_first) !af else true.B) && pte_in.isPf(2.U) 38392e3bfefSLemover ptw_resp.af := (if (!af_first) pte_in.isPf(2.U) else true.B) && af 38492e3bfefSLemover ptw_resp.entry.v := !ptw_resp.pf 38592e3bfefSLemover ptw_resp.entry.prefetch := DontCare 38692e3bfefSLemover ptw_resp.entry.asid := satp.asid 38792e3bfefSLemover ptw_resp 38892e3bfefSLemover } 38992e3bfefSLemover 39092e3bfefSLemover def outReady(source: UInt, port: Int): Bool = { 39192e3bfefSLemover MuxLookup(source, true.B, 39292e3bfefSLemover (0 until PtwWidth).map(i => i.U -> outArb(i).in(port).ready)) 39392e3bfefSLemover } 39492e3bfefSLemover 39592e3bfefSLemover // debug info 39692e3bfefSLemover for (i <- 0 until PtwWidth) { 39792e3bfefSLemover XSDebug(p"[io.tlb(${i.U})] ${io.tlb(i)}\n") 39892e3bfefSLemover } 3997797f035SbugGenerator XSDebug(p"[sfence] ${io.sfence}\n") 40092e3bfefSLemover XSDebug(p"[io.csr.tlb] ${io.csr.tlb}\n") 40192e3bfefSLemover 40292e3bfefSLemover for (i <- 0 until PtwWidth) { 40392e3bfefSLemover XSPerfAccumulate(s"req_count${i}", io.tlb(i).req(0).fire()) 40492e3bfefSLemover XSPerfAccumulate(s"req_blocked_count_${i}", io.tlb(i).req(0).valid && !io.tlb(i).req(0).ready) 40592e3bfefSLemover } 40692e3bfefSLemover XSPerfAccumulate(s"req_blocked_by_mq", arb1.io.out.valid && missQueue.io.out.valid) 40792e3bfefSLemover for (i <- 0 until (MemReqWidth + 1)) { 40892e3bfefSLemover XSPerfAccumulate(s"mem_req_util${i}", PopCount(waiting_resp) === i.U) 40992e3bfefSLemover } 41092e3bfefSLemover XSPerfAccumulate("mem_cycle", PopCount(waiting_resp) =/= 0.U) 41192e3bfefSLemover XSPerfAccumulate("mem_count", mem.a.fire()) 41292e3bfefSLemover 41392e3bfefSLemover // print configs 414f1fe8698SLemover println(s"${l2tlbParams.name}: a ptw, a llptw with size ${l2tlbParams.llptwsize}, miss queue size ${MissQueueSize} l1:${l2tlbParams.l1Size} fa l2: nSets ${l2tlbParams.l2nSets} nWays ${l2tlbParams.l2nWays} l3: ${l2tlbParams.l3nSets} nWays ${l2tlbParams.l3nWays} blockBytes:${l2tlbParams.blockBytes}") 41592e3bfefSLemover 41692e3bfefSLemover // time out assert 41792e3bfefSLemover for (i <- 0 until MemReqWidth) { 41892e3bfefSLemover TimeOutAssert(waiting_resp(i), timeOutThreshold, s"ptw mem resp time out wait_resp${i}") 41992e3bfefSLemover TimeOutAssert(flush_latch(i), timeOutThreshold, s"ptw mem resp time out flush_latch${i}") 42092e3bfefSLemover } 42192e3bfefSLemover 42292e3bfefSLemover 42392e3bfefSLemover val perfEvents = Seq(llptw, cache, ptw).flatMap(_.getPerfEvents) 42492e3bfefSLemover generatePerfEvent() 4255afdf73cSHaoyuan Feng 4265afdf73cSHaoyuan Feng val L1TlbTable = ChiselDB.createTable("L1Tlb_hart" + p(XSCoreParamsKey).HartId.toString, new L1TlbDB) 4275afdf73cSHaoyuan Feng val ITlbReqDB, DTlbReqDB, ITlbRespDB, DTlbRespDB = Wire(new L1TlbDB) 4285afdf73cSHaoyuan Feng ITlbReqDB.vpn := io.tlb(0).req(0).bits.vpn 4295afdf73cSHaoyuan Feng DTlbReqDB.vpn := io.tlb(1).req(0).bits.vpn 4305afdf73cSHaoyuan Feng ITlbRespDB.vpn := io.tlb(0).resp.bits.entry.tag 4315afdf73cSHaoyuan Feng DTlbRespDB.vpn := io.tlb(1).resp.bits.entry.tag 4325afdf73cSHaoyuan Feng L1TlbTable.log(ITlbReqDB, io.tlb(0).req(0).fire, "ITlbReq", clock, reset) 4335afdf73cSHaoyuan Feng L1TlbTable.log(DTlbReqDB, io.tlb(1).req(0).fire, "DTlbReq", clock, reset) 4345afdf73cSHaoyuan Feng L1TlbTable.log(ITlbRespDB, io.tlb(0).resp.fire, "ITlbResp", clock, reset) 4355afdf73cSHaoyuan Feng L1TlbTable.log(DTlbRespDB, io.tlb(1).resp.fire, "DTlbResp", clock, reset) 4365afdf73cSHaoyuan Feng 4375afdf73cSHaoyuan Feng val PageCacheTable = ChiselDB.createTable("PageCache_hart" + p(XSCoreParamsKey).HartId.toString, new PageCacheDB) 4385afdf73cSHaoyuan Feng val PageCacheDB = Wire(new PageCacheDB) 4395afdf73cSHaoyuan Feng PageCacheDB.vpn := cache.io.resp.bits.toTlb.tag 4405afdf73cSHaoyuan Feng PageCacheDB.source := cache.io.resp.bits.req_info.source 4415afdf73cSHaoyuan Feng PageCacheDB.bypassed := cache.io.resp.bits.bypassed 4425afdf73cSHaoyuan Feng PageCacheDB.is_first := cache.io.resp.bits.isFirst 4435afdf73cSHaoyuan Feng PageCacheDB.prefetched := cache.io.resp.bits.toTlb.prefetch 4445afdf73cSHaoyuan Feng PageCacheDB.prefetch := cache.io.resp.bits.prefetch 4455afdf73cSHaoyuan Feng PageCacheDB.l2Hit := cache.io.resp.bits.toFsm.l2Hit 4465afdf73cSHaoyuan Feng PageCacheDB.l1Hit := cache.io.resp.bits.toFsm.l1Hit 4475afdf73cSHaoyuan Feng PageCacheDB.hit := cache.io.resp.bits.hit 4485afdf73cSHaoyuan Feng PageCacheTable.log(PageCacheDB, cache.io.resp.fire, "PageCache", clock, reset) 4495afdf73cSHaoyuan Feng 4505afdf73cSHaoyuan Feng val PTWTable = ChiselDB.createTable("PTW_hart" + p(XSCoreParamsKey).HartId.toString, new PTWDB) 4515afdf73cSHaoyuan Feng val PTWReqDB, PTWRespDB, LLPTWReqDB, LLPTWRespDB = Wire(new PTWDB) 4525afdf73cSHaoyuan Feng PTWReqDB.vpn := ptw.io.req.bits.req_info.vpn 4535afdf73cSHaoyuan Feng PTWReqDB.source := ptw.io.req.bits.req_info.source 4545afdf73cSHaoyuan Feng PTWRespDB.vpn := ptw.io.refill.req_info.vpn 4555afdf73cSHaoyuan Feng PTWRespDB.source := ptw.io.refill.req_info.source 4565afdf73cSHaoyuan Feng LLPTWReqDB.vpn := llptw.io.in.bits.req_info.vpn 4575afdf73cSHaoyuan Feng LLPTWReqDB.source := llptw.io.in.bits.req_info.source 4585afdf73cSHaoyuan Feng LLPTWRespDB.vpn := llptw.io.mem.refill.vpn 4595afdf73cSHaoyuan Feng LLPTWRespDB.source := llptw.io.mem.refill.source 4605afdf73cSHaoyuan Feng PTWTable.log(PTWReqDB, ptw.io.req.fire, "PTWReq", clock, reset) 4615afdf73cSHaoyuan Feng PTWTable.log(PTWRespDB, ptw.io.mem.resp.fire, "PTWResp", clock, reset) 4625afdf73cSHaoyuan Feng PTWTable.log(LLPTWReqDB, llptw.io.in.fire, "LLPTWReq", clock, reset) 4635afdf73cSHaoyuan Feng PTWTable.log(LLPTWRespDB, llptw.io.mem.resp.fire, "LLPTWResp", clock, reset) 4645afdf73cSHaoyuan Feng 4655afdf73cSHaoyuan Feng val L2TlbMissQueueTable = ChiselDB.createTable("L2TlbMissQueue_hart" + p(XSCoreParamsKey).HartId.toString, new L2TlbMissQueueDB) 4665afdf73cSHaoyuan Feng val L2TlbMissQueueInDB, L2TlbMissQueueOutDB = Wire(new L2TlbMissQueueDB) 4675afdf73cSHaoyuan Feng L2TlbMissQueueInDB.vpn := missQueue.io.in.bits.vpn 4685afdf73cSHaoyuan Feng L2TlbMissQueueOutDB.vpn := missQueue.io.out.bits.vpn 4695afdf73cSHaoyuan Feng L2TlbMissQueueTable.log(L2TlbMissQueueInDB, missQueue.io.in.fire, "L2TlbMissQueueIn", clock, reset) 4705afdf73cSHaoyuan Feng L2TlbMissQueueTable.log(L2TlbMissQueueOutDB, missQueue.io.out.fire, "L2TlbMissQueueOut", clock, reset) 47192e3bfefSLemover} 47292e3bfefSLemover 4737797f035SbugGenerator/** BlockHelper, block missqueue, not to send too many req to cache 4747797f035SbugGenerator * Parameter: 4757797f035SbugGenerator * enable: enable BlockHelper, mq should not send too many reqs 4767797f035SbugGenerator * start: when miss queue out fire and need, block miss queue's out 4777797f035SbugGenerator * block: block miss queue's out 4787797f035SbugGenerator * latency: last missqueue out's cache access latency 4797797f035SbugGenerator */ 4807797f035SbugGeneratorclass BlockHelper(latency: Int)(implicit p: Parameters) extends XSModule { 4817797f035SbugGenerator val io = IO(new Bundle { 4827797f035SbugGenerator val enable = Input(Bool()) 4837797f035SbugGenerator val start = Input(Bool()) 4847797f035SbugGenerator val block = Output(Bool()) 4857797f035SbugGenerator }) 4867797f035SbugGenerator 4877797f035SbugGenerator val count = RegInit(0.U(log2Ceil(latency).W)) 4887797f035SbugGenerator val valid = RegInit(false.B) 4897797f035SbugGenerator val work = RegInit(true.B) 4907797f035SbugGenerator 4917797f035SbugGenerator io.block := valid 4927797f035SbugGenerator 4937797f035SbugGenerator when (io.start && work) { valid := true.B } 4947797f035SbugGenerator when (valid) { count := count + 1.U } 4957797f035SbugGenerator when (count === (latency.U) || io.enable) { 4967797f035SbugGenerator valid := false.B 4977797f035SbugGenerator work := io.enable 4987797f035SbugGenerator count := 0.U 4997797f035SbugGenerator } 5007797f035SbugGenerator} 5017797f035SbugGenerator 50292e3bfefSLemoverclass PTEHelper() extends ExtModule { 50392e3bfefSLemover val clock = IO(Input(Clock())) 50492e3bfefSLemover val enable = IO(Input(Bool())) 50592e3bfefSLemover val satp = IO(Input(UInt(64.W))) 50692e3bfefSLemover val vpn = IO(Input(UInt(64.W))) 50792e3bfefSLemover val pte = IO(Output(UInt(64.W))) 50892e3bfefSLemover val level = IO(Output(UInt(8.W))) 50992e3bfefSLemover val pf = IO(Output(UInt(8.W))) 51092e3bfefSLemover} 51192e3bfefSLemover 5125afdf73cSHaoyuan Fengclass PTWDelayN[T <: Data](gen: T, n: Int, flush: Bool) extends Module { 5135afdf73cSHaoyuan Feng val io = IO(new Bundle() { 5145afdf73cSHaoyuan Feng val in = Input(gen) 5155afdf73cSHaoyuan Feng val out = Output(gen) 5165afdf73cSHaoyuan Feng val ptwflush = Input(flush.cloneType) 5175afdf73cSHaoyuan Feng }) 5185afdf73cSHaoyuan Feng val out = RegInit(VecInit(Seq.fill(n)(0.U.asTypeOf(gen)))) 5195afdf73cSHaoyuan Feng val t = RegInit(VecInit(Seq.fill(n)(0.U.asTypeOf(gen)))) 5205afdf73cSHaoyuan Feng out(0) := io.in 5215afdf73cSHaoyuan Feng if (n == 1) { 5225afdf73cSHaoyuan Feng io.out := out(0) 5235afdf73cSHaoyuan Feng } else { 5245afdf73cSHaoyuan Feng when (io.ptwflush) { 5255afdf73cSHaoyuan Feng for (i <- 0 until n) { 5265afdf73cSHaoyuan Feng t(i) := 0.U.asTypeOf(gen) 5275afdf73cSHaoyuan Feng out(i) := 0.U.asTypeOf(gen) 5285afdf73cSHaoyuan Feng } 5295afdf73cSHaoyuan Feng io.out := 0.U.asTypeOf(gen) 5305afdf73cSHaoyuan Feng } .otherwise { 5315afdf73cSHaoyuan Feng for (i <- 1 until n) { 5325afdf73cSHaoyuan Feng t(i-1) := out(i-1) 5335afdf73cSHaoyuan Feng out(i) := t(i-1) 5345afdf73cSHaoyuan Feng } 5355afdf73cSHaoyuan Feng io.out := out(n-1) 5365afdf73cSHaoyuan Feng } 5375afdf73cSHaoyuan Feng } 5385afdf73cSHaoyuan Feng} 5395afdf73cSHaoyuan Feng 5405afdf73cSHaoyuan Fengobject PTWDelayN { 5415afdf73cSHaoyuan Feng def apply[T <: Data](in: T, n: Int, flush: Bool): T = { 5425afdf73cSHaoyuan Feng val delay = Module(new PTWDelayN(in.cloneType, n, flush)) 5435afdf73cSHaoyuan Feng delay.io.in := in 5445afdf73cSHaoyuan Feng delay.io.ptwflush := flush 5455afdf73cSHaoyuan Feng delay.io.out 5465afdf73cSHaoyuan Feng } 5475afdf73cSHaoyuan Feng} 5485afdf73cSHaoyuan Feng 54992e3bfefSLemoverclass FakePTW()(implicit p: Parameters) extends XSModule with HasPtwConst { 55092e3bfefSLemover val io = IO(new L2TLBIO) 5515afdf73cSHaoyuan Feng val flush = VecInit(Seq.fill(PtwWidth)(false.B)) 5525afdf73cSHaoyuan Feng flush(0) := DelayN(io.sfence.valid || io.csr.tlb.satp.changed, itlbParams.fenceDelay) 5535afdf73cSHaoyuan Feng flush(1) := DelayN(io.sfence.valid || io.csr.tlb.satp.changed, ldtlbParams.fenceDelay) 55492e3bfefSLemover for (i <- 0 until PtwWidth) { 55592e3bfefSLemover val helper = Module(new PTEHelper()) 55692e3bfefSLemover helper.clock := clock 55792e3bfefSLemover helper.satp := io.csr.tlb.satp.ppn 5585afdf73cSHaoyuan Feng 5595afdf73cSHaoyuan Feng if (coreParams.softPTWDelay == 1) { 5605afdf73cSHaoyuan Feng helper.enable := io.tlb(i).req(0).fire 56192e3bfefSLemover helper.vpn := io.tlb(i).req(0).bits.vpn 5625afdf73cSHaoyuan Feng } else { 5635afdf73cSHaoyuan Feng helper.enable := PTWDelayN(io.tlb(i).req(0).fire, coreParams.softPTWDelay - 1, flush(i)) 5645afdf73cSHaoyuan Feng helper.vpn := PTWDelayN(io.tlb(i).req(0).bits.vpn, coreParams.softPTWDelay - 1, flush(i)) 5655afdf73cSHaoyuan Feng } 5665afdf73cSHaoyuan Feng 56792e3bfefSLemover val pte = helper.pte.asTypeOf(new PteBundle) 56892e3bfefSLemover val level = helper.level 56992e3bfefSLemover val pf = helper.pf 5705afdf73cSHaoyuan Feng val empty = RegInit(true.B) 5715afdf73cSHaoyuan Feng when (io.tlb(i).req(0).fire) { 5725afdf73cSHaoyuan Feng empty := false.B 5735afdf73cSHaoyuan Feng } .elsewhen (io.tlb(i).resp.fire || flush(i)) { 5745afdf73cSHaoyuan Feng empty := true.B 5755afdf73cSHaoyuan Feng } 57692e3bfefSLemover 5775afdf73cSHaoyuan Feng io.tlb(i).req(0).ready := empty || io.tlb(i).resp.fire 5785afdf73cSHaoyuan Feng io.tlb(i).resp.valid := PTWDelayN(io.tlb(i).req(0).fire, coreParams.softPTWDelay, flush(i)) 57992e3bfefSLemover assert(!io.tlb(i).resp.valid || io.tlb(i).resp.ready) 5805afdf73cSHaoyuan Feng io.tlb(i).resp.bits.entry.tag := PTWDelayN(io.tlb(i).req(0).bits.vpn, coreParams.softPTWDelay, flush(i)) 58192e3bfefSLemover io.tlb(i).resp.bits.entry.ppn := pte.ppn 58292e3bfefSLemover io.tlb(i).resp.bits.entry.perm.map(_ := pte.getPerm()) 58392e3bfefSLemover io.tlb(i).resp.bits.entry.level.map(_ := level) 58492e3bfefSLemover io.tlb(i).resp.bits.pf := pf 58592e3bfefSLemover io.tlb(i).resp.bits.af := DontCare // TODO: implement it 5865afdf73cSHaoyuan Feng io.tlb(i).resp.bits.entry.v := !pf 5875afdf73cSHaoyuan Feng io.tlb(i).resp.bits.entry.prefetch := DontCare 5885afdf73cSHaoyuan Feng io.tlb(i).resp.bits.entry.asid := io.csr.tlb.satp.asid 58992e3bfefSLemover } 59092e3bfefSLemover} 59192e3bfefSLemover 59292e3bfefSLemoverclass L2TLBWrapper()(implicit p: Parameters) extends LazyModule with HasXSParameter { 59392e3bfefSLemover val useSoftPTW = coreParams.softPTW 59492e3bfefSLemover val node = if (!useSoftPTW) TLIdentityNode() else null 59592e3bfefSLemover val ptw = if (!useSoftPTW) LazyModule(new L2TLB()) else null 59692e3bfefSLemover if (!useSoftPTW) { 59792e3bfefSLemover node := ptw.node 59892e3bfefSLemover } 59992e3bfefSLemover 60092e3bfefSLemover lazy val module = new LazyModuleImp(this) with HasPerfEvents { 60192e3bfefSLemover val io = IO(new L2TLBIO) 60292e3bfefSLemover val perfEvents = if (useSoftPTW) { 60392e3bfefSLemover val fake_ptw = Module(new FakePTW()) 60492e3bfefSLemover io <> fake_ptw.io 60592e3bfefSLemover Seq() 60692e3bfefSLemover } 60792e3bfefSLemover else { 60892e3bfefSLemover io <> ptw.module.io 60992e3bfefSLemover ptw.module.getPerfEvents 61092e3bfefSLemover } 61192e3bfefSLemover generatePerfEvent() 61292e3bfefSLemover } 61392e3bfefSLemover} 614