11d8f4dcbSJay/*************************************************************************************** 21d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 31d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 41d8f4dcbSJay* 51d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 61d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 71d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 81d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 91d8f4dcbSJay* 101d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 111d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 121d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 131d8f4dcbSJay* 141d8f4dcbSJay* See the Mulan PSL v2 for more details. 151d8f4dcbSJay***************************************************************************************/ 161d8f4dcbSJay 171d8f4dcbSJaypackage xiangshan.frontend.icache 181d8f4dcbSJay 191d8f4dcbSJayimport chipsalliance.rocketchip.config.Parameters 201d8f4dcbSJayimport chisel3._ 211d8f4dcbSJayimport chisel3.util._ 221d8f4dcbSJayimport freechips.rocketchip.diplomacy.IdRange 231d8f4dcbSJayimport freechips.rocketchip.tilelink.ClientStates._ 241d8f4dcbSJayimport freechips.rocketchip.tilelink.TLPermissions._ 251d8f4dcbSJayimport freechips.rocketchip.tilelink._ 261d8f4dcbSJayimport xiangshan._ 271d8f4dcbSJayimport huancun.{AliasKey, DirtyKey} 281d8f4dcbSJayimport xiangshan.cache._ 291d8f4dcbSJayimport utils._ 303c02ee8fSwakafaimport utility._ 3141cb8b61SJeniusimport difftest._ 321d8f4dcbSJay 331d8f4dcbSJay 341d8f4dcbSJayabstract class ICacheMissUnitModule(implicit p: Parameters) extends XSModule 351d8f4dcbSJay with HasICacheParameters 361d8f4dcbSJay 371d8f4dcbSJayabstract class ICacheMissUnitBundle(implicit p: Parameters) extends XSBundle 381d8f4dcbSJay with HasICacheParameters 391d8f4dcbSJay 401d8f4dcbSJayclass ICacheMissReq(implicit p: Parameters) extends ICacheBundle 411d8f4dcbSJay{ 421d8f4dcbSJay val paddr = UInt(PAddrBits.W) 431d8f4dcbSJay val vaddr = UInt(VAddrBits.W) 441d8f4dcbSJay val waymask = UInt(nWays.W) 451d8f4dcbSJay 461d8f4dcbSJay def getVirSetIdx = get_idx(vaddr) 471d8f4dcbSJay def getPhyTag = get_phy_tag(paddr) 481d8f4dcbSJay} 491d8f4dcbSJay 501d8f4dcbSJay 511d8f4dcbSJayclass ICacheMissResp(implicit p: Parameters) extends ICacheBundle 521d8f4dcbSJay{ 531d8f4dcbSJay val data = UInt(blockBits.W) 5458dbdfc2SJay val corrupt = Bool() 551d8f4dcbSJay} 561d8f4dcbSJay 571d8f4dcbSJayclass ICacheMissBundle(implicit p: Parameters) extends ICacheBundle{ 581d8f4dcbSJay val req = Vec(2, Flipped(DecoupledIO(new ICacheMissReq))) 591d8f4dcbSJay val resp = Vec(2,ValidIO(new ICacheMissResp)) 601d8f4dcbSJay val flush = Input(Bool()) 611d8f4dcbSJay} 621d8f4dcbSJay 631d8f4dcbSJay 641d8f4dcbSJayclass ICacheMissEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends ICacheMissUnitModule 651d8f4dcbSJay with MemoryOpConstants 661d8f4dcbSJay{ 671d8f4dcbSJay val io = IO(new Bundle { 687052722fSJay val id = Input(UInt(log2Ceil(PortNumber).W)) 691d8f4dcbSJay 701d8f4dcbSJay val req = Flipped(DecoupledIO(new ICacheMissReq)) 711d8f4dcbSJay val resp = ValidIO(new ICacheMissResp) 721d8f4dcbSJay 731d8f4dcbSJay //tilelink channel 741d8f4dcbSJay val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 751d8f4dcbSJay val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 761d8f4dcbSJay 771d8f4dcbSJay val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 781d8f4dcbSJay val data_write = DecoupledIO(new ICacheDataWriteBundle) 791d8f4dcbSJay 80974a902cSguohongyu val ongoing_req = ValidIO(UInt(PAddrBits.W)) 81*2a6078bfSguohongyu val fencei = Input(Bool()) 821d8f4dcbSJay }) 831d8f4dcbSJay 841d8f4dcbSJay /** default value for control signals */ 851d8f4dcbSJay io.resp := DontCare 861d8f4dcbSJay io.mem_acquire.bits := DontCare 871d8f4dcbSJay io.mem_grant.ready := true.B 881d8f4dcbSJay io.meta_write.bits := DontCare 891d8f4dcbSJay io.data_write.bits := DontCare 901d8f4dcbSJay 9138160951Sguohongyu val s_idle :: s_send_mem_aquire :: s_wait_mem_grant :: s_write_back :: s_wait_resp :: Nil = Enum(5) 921d8f4dcbSJay val state = RegInit(s_idle) 931d8f4dcbSJay /** control logic transformation */ 941d8f4dcbSJay //request register 951d8f4dcbSJay val req = Reg(new ICacheMissReq) 961d8f4dcbSJay val req_idx = req.getVirSetIdx //virtual index 971d8f4dcbSJay val req_tag = req.getPhyTag //physical tag 981d8f4dcbSJay val req_waymask = req.waymask 9958dbdfc2SJay val req_corrupt = RegInit(false.B) 1001d8f4dcbSJay 1011d8f4dcbSJay val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant) 1021d8f4dcbSJay 103*2a6078bfSguohongyu val needflush_r = RegInit(false.B) 104*2a6078bfSguohongyu when (state === s_idle) { needflush_r := false.B } 105*2a6078bfSguohongyu when (state =/= s_idle && io.fencei) { needflush_r := true.B } 106*2a6078bfSguohongyu val needflush = needflush_r | io.fencei 107*2a6078bfSguohongyu 1081d8f4dcbSJay //cacheline register 1091d8f4dcbSJay val readBeatCnt = Reg(UInt(log2Up(refillCycles).W)) 1101d8f4dcbSJay val respDataReg = Reg(Vec(refillCycles, UInt(beatBits.W))) 1111d8f4dcbSJay 1121d8f4dcbSJay //initial 1131d8f4dcbSJay io.resp.bits := DontCare 1141d8f4dcbSJay io.mem_acquire.bits := DontCare 1151d8f4dcbSJay io.mem_grant.ready := true.B 1161d8f4dcbSJay io.meta_write.bits := DontCare 1171d8f4dcbSJay io.data_write.bits := DontCare 1181d8f4dcbSJay 1191d8f4dcbSJay io.req.ready := (state === s_idle) 1202a25dbb4SJay io.mem_acquire.valid := (state === s_send_mem_aquire) 1211d8f4dcbSJay 122974a902cSguohongyu io.ongoing_req.valid := (state =/= s_idle) 123974a902cSguohongyu io.ongoing_req.bits := addrAlign(req.paddr, blockBytes, PAddrBits) 12400240ba6SJay 1251d8f4dcbSJay //state change 1261d8f4dcbSJay switch(state) { 1271d8f4dcbSJay is(s_idle) { 1281d8f4dcbSJay when(io.req.fire()) { 1291d8f4dcbSJay readBeatCnt := 0.U 1301d8f4dcbSJay state := s_send_mem_aquire 1311d8f4dcbSJay req := io.req.bits 1321d8f4dcbSJay } 1331d8f4dcbSJay } 1341d8f4dcbSJay 1351d8f4dcbSJay // memory request 1361d8f4dcbSJay is(s_send_mem_aquire) { 1371d8f4dcbSJay when(io.mem_acquire.fire()) { 1381d8f4dcbSJay state := s_wait_mem_grant 1391d8f4dcbSJay } 1401d8f4dcbSJay } 1411d8f4dcbSJay 1421d8f4dcbSJay is(s_wait_mem_grant) { 1431d8f4dcbSJay when(edge.hasData(io.mem_grant.bits)) { 1441d8f4dcbSJay when(io.mem_grant.fire()) { 1451d8f4dcbSJay readBeatCnt := readBeatCnt + 1.U 1461d8f4dcbSJay respDataReg(readBeatCnt) := io.mem_grant.bits.data 14738160951Sguohongyu req_corrupt := io.mem_grant.bits.corrupt // TODO: seems has bug 1481d8f4dcbSJay when(readBeatCnt === (refillCycles - 1).U) { 1491d8f4dcbSJay assert(refill_done, "refill not done!") 1504da04e5bSguohongyu state := s_write_back 1511d8f4dcbSJay } 1521d8f4dcbSJay } 1531d8f4dcbSJay } 1541d8f4dcbSJay } 1551d8f4dcbSJay 1562a25dbb4SJay is(s_write_back) { 157*2a6078bfSguohongyu state := Mux(io.meta_write.fire() && io.data_write.fire() || needflush, s_wait_resp, s_write_back) 1582a25dbb4SJay } 1592a25dbb4SJay 1601d8f4dcbSJay is(s_wait_resp) { 1611d8f4dcbSJay io.resp.bits.data := respDataReg.asUInt 16258dbdfc2SJay io.resp.bits.corrupt := req_corrupt 1631d8f4dcbSJay when(io.resp.fire()) { 1641d8f4dcbSJay state := s_idle 1651d8f4dcbSJay } 1661d8f4dcbSJay } 1671d8f4dcbSJay } 1681d8f4dcbSJay 1691d8f4dcbSJay /** refill write and meta write */ 17038160951Sguohongyu 17138160951Sguohongyu val getBlock = edge.Get( 17238160951Sguohongyu fromSource = io.id, 17338160951Sguohongyu toAddress = addrAlign(req.paddr, blockBytes, PAddrBits), 17438160951Sguohongyu lgSize = (log2Up(cacheParams.blockBytes)).U 17538160951Sguohongyu )._2 17638160951Sguohongyu 1774da04e5bSguohongyu io.mem_acquire.bits := getBlock // getBlock 1781d8f4dcbSJay require(nSets <= 256) // icache size should not be more than 128KB 1791d8f4dcbSJay 1801d8f4dcbSJay //resp to ifu 1811d8f4dcbSJay io.resp.valid := state === s_wait_resp 1822a25dbb4SJay 183*2a6078bfSguohongyu io.meta_write.valid := (state === s_write_back && !needflush) 1844da04e5bSguohongyu io.meta_write.bits.generate(tag = req_tag, idx = req_idx, waymask = req_waymask, bankIdx = req_idx(0)) 1852a25dbb4SJay 186*2a6078bfSguohongyu io.data_write.valid := (state === s_write_back && !needflush) 18741cb8b61SJenius io.data_write.bits.generate(data = respDataReg.asUInt, 18841cb8b61SJenius idx = req_idx, 18941cb8b61SJenius waymask = req_waymask, 19041cb8b61SJenius bankIdx = req_idx(0), 19141cb8b61SJenius paddr = req.paddr) 1921d8f4dcbSJay 1931d8f4dcbSJay XSPerfAccumulate( 1941d8f4dcbSJay "entryPenalty" + Integer.toString(id, 10), 1951d8f4dcbSJay BoolStopWatch( 1961d8f4dcbSJay start = io.req.fire(), 1971d8f4dcbSJay stop = io.resp.valid, 1981d8f4dcbSJay startHighPriority = true) 1991d8f4dcbSJay ) 2001d8f4dcbSJay XSPerfAccumulate("entryReq" + Integer.toString(id, 10), io.req.fire()) 2015470b21eSguohongyu XSError(blockCounter(io.req.fire, io.resp.fire, 5000), "missEntry"+ io.id +"_block_5000_cycle,may_has_error\n") 2021d8f4dcbSJay} 2031d8f4dcbSJay 2041d8f4dcbSJay 2051d8f4dcbSJayclass ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheMissUnitModule 2061d8f4dcbSJay{ 2071d8f4dcbSJay val io = IO(new Bundle{ 20841cb8b61SJenius val hartId = Input(UInt(8.W)) 2091d8f4dcbSJay val req = Vec(2, Flipped(DecoupledIO(new ICacheMissReq))) 2101d8f4dcbSJay val resp = Vec(2, ValidIO(new ICacheMissResp)) 2111d8f4dcbSJay 2121d8f4dcbSJay val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 2131d8f4dcbSJay val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 2141d8f4dcbSJay 2151d8f4dcbSJay val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 2161d8f4dcbSJay val data_write = DecoupledIO(new ICacheDataWriteBundle) 2171d8f4dcbSJay 2187052722fSJay val prefetch_req = Flipped(DecoupledIO(new PIQReq)) 219974a902cSguohongyu val mshr_info = Vec(totalMSHRNum,ValidIO(UInt(PAddrBits.W))) 220b1ded4e8Sguohongyu val freePIQEntry = Output(UInt(log2Ceil(nPrefetchEntries).W)) 22100240ba6SJay 222b1ded4e8Sguohongyu val fencei = Input(Bool()) 2237052722fSJay 224b1ded4e8Sguohongyu val piq_write_ipbuffer = ValidIO(new IPFBufferWrite) 225b1ded4e8Sguohongyu 226b1ded4e8Sguohongyu val to_main_pipe = Vec(nPrefetchEntries, new PIQToMainPipe) 2271d8f4dcbSJay }) 2281d8f4dcbSJay // assign default values to output signals 2291d8f4dcbSJay io.mem_grant.ready := false.B 2301d8f4dcbSJay 2311d8f4dcbSJay val meta_write_arb = Module(new Arbiter(new ICacheMetaWriteBundle, PortNumber)) 2321d8f4dcbSJay val refill_arb = Module(new Arbiter(new ICacheDataWriteBundle, PortNumber)) 233b1ded4e8Sguohongyu val ipf_write_arb = Module(new Arbiter(new IPFBufferWrite, nPrefetchEntries)) 2341d8f4dcbSJay 2351d8f4dcbSJay io.mem_grant.ready := true.B 2361d8f4dcbSJay 2372a25dbb4SJay val entries = (0 until PortNumber) map { i => 2381d8f4dcbSJay val entry = Module(new ICacheMissEntry(edge, i)) 2391d8f4dcbSJay 2401d8f4dcbSJay entry.io.id := i.U 2411d8f4dcbSJay 2421d8f4dcbSJay // entry req 2431d8f4dcbSJay entry.io.req.valid := io.req(i).valid 2441d8f4dcbSJay entry.io.req.bits := io.req(i).bits 2451d8f4dcbSJay io.req(i).ready := entry.io.req.ready 2461d8f4dcbSJay 2471d8f4dcbSJay // entry resp 2481d8f4dcbSJay meta_write_arb.io.in(i) <> entry.io.meta_write 2491d8f4dcbSJay refill_arb.io.in(i) <> entry.io.data_write 2501d8f4dcbSJay 2511d8f4dcbSJay entry.io.mem_grant.valid := false.B 2521d8f4dcbSJay entry.io.mem_grant.bits := DontCare 2531d8f4dcbSJay when (io.mem_grant.bits.source === i.U) { 2541d8f4dcbSJay entry.io.mem_grant <> io.mem_grant 2551d8f4dcbSJay } 2561d8f4dcbSJay 2571d8f4dcbSJay io.resp(i) <> entry.io.resp 258974a902cSguohongyu io.mshr_info(i) <> entry.io.ongoing_req 259*2a6078bfSguohongyu entry.io.fencei := io.fencei 260d4112e88Sguohongyu// XSPerfAccumulate( 261d4112e88Sguohongyu// "entryPenalty" + Integer.toString(i, 10), 262d4112e88Sguohongyu// BoolStopWatch( 263d4112e88Sguohongyu// start = entry.io.req.fire(), 264d4112e88Sguohongyu// stop = entry.io.resp.fire(), 265d4112e88Sguohongyu// startHighPriority = true) 266d4112e88Sguohongyu// ) 267d4112e88Sguohongyu// XSPerfAccumulate("entryReq" + Integer.toString(i, 10), entry.io.req.fire()) 2681d8f4dcbSJay 2691d8f4dcbSJay entry 2701d8f4dcbSJay } 2711d8f4dcbSJay 2727052722fSJay val alloc = Wire(UInt(log2Ceil(nPrefetchEntries).W)) 273b1ded4e8Sguohongyu val toMainPipe = io.to_main_pipe.map(_.info) 2747052722fSJay 275de7689fcSJay val prefEntries = (PortNumber until PortNumber + nPrefetchEntries) map { i => 276b1ded4e8Sguohongyu val prefetchEntry = Module(new PIQEntry(edge, i)) 2777052722fSJay 278b1ded4e8Sguohongyu prefetchEntry.io.mem_grant.valid := false.B 279b1ded4e8Sguohongyu prefetchEntry.io.mem_grant.bits := DontCare 280b1ded4e8Sguohongyu prefetchEntry.io.fencei := io.fencei 2817052722fSJay 282b1ded4e8Sguohongyu ipf_write_arb.io.in(i - PortNumber) <> prefetchEntry.io.piq_write_ipbuffer 283b1ded4e8Sguohongyu 284b1ded4e8Sguohongyu when(io.mem_grant.bits.source === i.U) { 285b1ded4e8Sguohongyu prefetchEntry.io.mem_grant <> io.mem_grant 2867052722fSJay } 2877052722fSJay 288de7689fcSJay prefetchEntry.io.req.valid := io.prefetch_req.valid && ((i-PortNumber).U === alloc) 2897052722fSJay prefetchEntry.io.req.bits := io.prefetch_req.bits 2907052722fSJay 2917052722fSJay prefetchEntry.io.id := i.U 2927052722fSJay 293974a902cSguohongyu io.mshr_info(i) := prefetchEntry.io.ongoing_req 294974a902cSguohongyu 2957052722fSJay prefetchEntry 2967052722fSJay } 2977052722fSJay 2987052722fSJay alloc := PriorityEncoder(prefEntries.map(_.io.req.ready)) 2997052722fSJay io.prefetch_req.ready := ParallelOR(prefEntries.map(_.io.req.ready)) 300b1ded4e8Sguohongyu io.freePIQEntry := PriorityEncoder(prefEntries.map(_.io.req.ready)) 301b1ded4e8Sguohongyu (0 until nPrefetchEntries).foreach(i => toMainPipe(i) <> prefEntries(i).io.prefetch_entry_data) 302b1ded4e8Sguohongyu val tl_a_chanel = entries.map(_.io.mem_acquire) ++ prefEntries.map(_.io.mem_acquire) 3037052722fSJay TLArbiter.lowest(edge, io.mem_acquire, tl_a_chanel:_*) 3047052722fSJay 3051d8f4dcbSJay io.meta_write <> meta_write_arb.io.out 3061d8f4dcbSJay io.data_write <> refill_arb.io.out 3071d8f4dcbSJay 308b1ded4e8Sguohongyu io.piq_write_ipbuffer.valid := ipf_write_arb.io.out.valid 309b1ded4e8Sguohongyu io.piq_write_ipbuffer.bits := ipf_write_arb.io.out.bits 310b1ded4e8Sguohongyu ipf_write_arb.io.out.ready := true.B 311b1ded4e8Sguohongyu 312b1ded4e8Sguohongyu XSPerfAccumulate("refill_ipf_num", io.piq_write_ipbuffer.fire) 313b1ded4e8Sguohongyu 31441cb8b61SJenius if (env.EnableDifftest) { 315afa866b1Sguohongyu val diffipfrefill = Module(new DifftestRefillEvent) 316afa866b1Sguohongyu diffipfrefill.io.clock := clock 317afa866b1Sguohongyu diffipfrefill.io.coreid := io.hartId 318afa866b1Sguohongyu diffipfrefill.io.cacheid := 3.U 319afa866b1Sguohongyu diffipfrefill.io.valid := ipf_write_arb.io.out.valid 320afa866b1Sguohongyu diffipfrefill.io.addr := ipf_write_arb.io.out.bits.meta.paddr 321afa866b1Sguohongyu diffipfrefill.io.data := ipf_write_arb.io.out.bits.data.asTypeOf(diffipfrefill.io.data) 322afa866b1Sguohongyu } 323afa866b1Sguohongyu 324afa866b1Sguohongyu if (env.EnableDifftest) { 32541cb8b61SJenius val difftest = Module(new DifftestRefillEvent) 32641cb8b61SJenius difftest.io.clock := clock 32741cb8b61SJenius difftest.io.coreid := io.hartId 32841cb8b61SJenius difftest.io.cacheid := 0.U 32941cb8b61SJenius difftest.io.valid := refill_arb.io.out.valid 33041cb8b61SJenius difftest.io.addr := refill_arb.io.out.bits.paddr 33141cb8b61SJenius difftest.io.data := refill_arb.io.out.bits.data.asTypeOf(difftest.io.data) 33241cb8b61SJenius } 33341cb8b61SJenius 3341d8f4dcbSJay (0 until nWays).map{ w => 3351d8f4dcbSJay XSPerfAccumulate("line_0_refill_way_" + Integer.toString(w, 10), entries(0).io.meta_write.valid && OHToUInt(entries(0).io.meta_write.bits.waymask) === w.U) 3361d8f4dcbSJay XSPerfAccumulate("line_1_refill_way_" + Integer.toString(w, 10), entries(1).io.meta_write.valid && OHToUInt(entries(1).io.meta_write.bits.waymask) === w.U) 3371d8f4dcbSJay } 3381d8f4dcbSJay 3391d8f4dcbSJay} 3401d8f4dcbSJay 3411d8f4dcbSJay 3421d8f4dcbSJay 343