11f0e2dc7SJiawei Lin/*************************************************************************************** 21f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 31f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Peng Cheng Laboratory 41f0e2dc7SJiawei Lin* 51f0e2dc7SJiawei Lin* XiangShan is licensed under Mulan PSL v2. 61f0e2dc7SJiawei Lin* You can use this software according to the terms and conditions of the Mulan PSL v2. 71f0e2dc7SJiawei Lin* You may obtain a copy of Mulan PSL v2 at: 81f0e2dc7SJiawei Lin* http://license.coscl.org.cn/MulanPSL2 91f0e2dc7SJiawei Lin* 101f0e2dc7SJiawei Lin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 111f0e2dc7SJiawei Lin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 121f0e2dc7SJiawei Lin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 131f0e2dc7SJiawei Lin* 141f0e2dc7SJiawei Lin* See the Mulan PSL v2 for more details. 151f0e2dc7SJiawei Lin***************************************************************************************/ 161f0e2dc7SJiawei Lin 171f0e2dc7SJiawei Linpackage xiangshan.cache 181f0e2dc7SJiawei Lin 191f0e2dc7SJiawei Linimport chisel3._ 201f0e2dc7SJiawei Linimport chisel3.util._ 2177af2baeSWilliam Wangimport freechips.rocketchip.tilelink.TLPermissions._ 221ca0e4f3SYinan Xuimport freechips.rocketchip.tilelink.{TLArbiter, TLBundleC, TLBundleD, TLEdgeOut} 237f37d55fSTang Haojinimport org.chipsalliance.cde.config.Parameters 2444f2941bSJiru Sunimport utils.HasTLDump 2544f2941bSJiru Sunimport utility.{XSDebug, XSPerfAccumulate, HasPerfEvents} 26bb2f3f51STang Haojin 271f0e2dc7SJiawei Lin 2884026448SWilliam Wangclass WritebackReqCtrl(implicit p: Parameters) extends DCacheBundle { 2977af2baeSWilliam Wang val param = UInt(cWidth.W) 301f0e2dc7SJiawei Lin val voluntary = Bool() 311f0e2dc7SJiawei Lin val hasData = Bool() 3272dab974Scz4e val corrupt = Bool() 331f0e2dc7SJiawei Lin val dirty = Bool() 341f0e2dc7SJiawei Lin 35ad3ba452Szhanglinjuan val delay_release = Bool() 36ad3ba452Szhanglinjuan val miss_id = UInt(log2Up(cfg.nMissEntries).W) 3784026448SWilliam Wang} 3884026448SWilliam Wang 3984026448SWilliam Wangclass WritebackReqWodata(implicit p: Parameters) extends WritebackReqCtrl { 4084026448SWilliam Wang val addr = UInt(PAddrBits.W) 41ad3ba452Szhanglinjuan 42*8b33cd30Sklin02 def dump(cond: Bool) = { 43*8b33cd30Sklin02 XSDebug(cond, "WritebackReq addr: %x param: %d voluntary: %b hasData: %b\n", 447a919e05SWilliam Wang addr, param, voluntary, hasData) 457a919e05SWilliam Wang } 467a919e05SWilliam Wang} 477a919e05SWilliam Wang 487a919e05SWilliam Wangclass WritebackReqData(implicit p: Parameters) extends DCacheBundle { 497a919e05SWilliam Wang val data = UInt((cfg.blockBytes * 8).W) 507a919e05SWilliam Wang} 517a919e05SWilliam Wang 527a919e05SWilliam Wangclass WritebackReq(implicit p: Parameters) extends WritebackReqWodata { 537a919e05SWilliam Wang val data = UInt((cfg.blockBytes * 8).W) 547a919e05SWilliam Wang 55*8b33cd30Sklin02 override def dump(cond: Bool) = { 56*8b33cd30Sklin02 XSDebug(cond, "WritebackReq addr: %x param: %d voluntary: %b hasData: %b data: %x\n", 571f0e2dc7SJiawei Lin addr, param, voluntary, hasData, data) 581f0e2dc7SJiawei Lin } 597a919e05SWilliam Wang 607a919e05SWilliam Wang def toWritebackReqWodata(): WritebackReqWodata = { 617a919e05SWilliam Wang val out = Wire(new WritebackReqWodata) 627a919e05SWilliam Wang out.addr := addr 6384026448SWilliam Wang out.param := param 6484026448SWilliam Wang out.voluntary := voluntary 6584026448SWilliam Wang out.hasData := hasData 6672dab974Scz4e out.corrupt := corrupt 6784026448SWilliam Wang out.dirty := dirty 6884026448SWilliam Wang out.delay_release := delay_release 6984026448SWilliam Wang out.miss_id := miss_id 7084026448SWilliam Wang out 7184026448SWilliam Wang } 7284026448SWilliam Wang 7384026448SWilliam Wang def toWritebackReqCtrl(): WritebackReqCtrl = { 7484026448SWilliam Wang val out = Wire(new WritebackReqCtrl) 757a919e05SWilliam Wang out.param := param 767a919e05SWilliam Wang out.voluntary := voluntary 777a919e05SWilliam Wang out.hasData := hasData 7872dab974Scz4e out.corrupt := corrupt 797a919e05SWilliam Wang out.dirty := dirty 807a919e05SWilliam Wang out.delay_release := delay_release 817a919e05SWilliam Wang out.miss_id := miss_id 827a919e05SWilliam Wang out 837a919e05SWilliam Wang } 847a919e05SWilliam Wang 857a919e05SWilliam Wang def toWritebackReqData(): WritebackReqData = { 867a919e05SWilliam Wang val out = Wire(new WritebackReqData) 877a919e05SWilliam Wang out.data := data 887a919e05SWilliam Wang out 897a919e05SWilliam Wang } 901f0e2dc7SJiawei Lin} 911f0e2dc7SJiawei Lin 92ad3ba452Szhanglinjuan// While a Release sleeps and waits for a refill to wake it up, 93ad3ba452Szhanglinjuan// main pipe might update meta & data during this time. 94ad3ba452Szhanglinjuan// So the meta & data to be released need to be updated too. 95ad3ba452Szhanglinjuanclass ReleaseUpdate(implicit p: Parameters) extends DCacheBundle { 96ad3ba452Szhanglinjuan // only consider store here 97ad3ba452Szhanglinjuan val addr = UInt(PAddrBits.W) 98ad3ba452Szhanglinjuan val mask = UInt(DCacheBanks.W) 99ad3ba452Szhanglinjuan val data = UInt((cfg.blockBytes * 8).W) 100ad3ba452Szhanglinjuan} 101ad3ba452Szhanglinjuan 102b8f6ff86SWilliam Wang// To reduce fanout, writeback queue entry data is updated 1 cycle 103935edac4STang Haojin// after ReleaseUpdate.fire 104b8f6ff86SWilliam Wangclass WBQEntryReleaseUpdate(implicit p: Parameters) extends DCacheBundle { 1057a919e05SWilliam Wang // only consider store here 1067a919e05SWilliam Wang val addr = UInt(PAddrBits.W) 1077a919e05SWilliam Wang val mask_delayed = UInt(DCacheBanks.W) 1087a919e05SWilliam Wang val data_delayed = UInt((cfg.blockBytes * 8).W) 1097a919e05SWilliam Wang val mask_orr = Bool() 1107a919e05SWilliam Wang} 1117a919e05SWilliam Wang 112b8f6ff86SWilliam Wang// When a probe TtoB req enter dcache main pipe, check if that cacheline 113b8f6ff86SWilliam Wang// is waiting for release. If it is so, change TtoB to TtoN, set dcache 114b8f6ff86SWilliam Wang// coh to N. 115b8f6ff86SWilliam Wangclass ProbeToBCheckReq(implicit p: Parameters) extends DCacheBundle { 116b8f6ff86SWilliam Wang val addr = UInt(PAddrBits.W) // paddr from mainpipe s1 117b8f6ff86SWilliam Wang} 118b8f6ff86SWilliam Wang 119b8f6ff86SWilliam Wangclass ProbeToBCheckResp(implicit p: Parameters) extends DCacheBundle { 120b8f6ff86SWilliam Wang val toN = Bool() // need to set dcache coh to N 121b8f6ff86SWilliam Wang} 122b8f6ff86SWilliam Wang 1231f0e2dc7SJiawei Linclass WritebackEntry(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule with HasTLDump 1241f0e2dc7SJiawei Lin{ 1251f0e2dc7SJiawei Lin val io = IO(new Bundle { 1261f0e2dc7SJiawei Lin val id = Input(UInt()) 127ffd3154dSCharlieLiu 1287a919e05SWilliam Wang val req = Flipped(DecoupledIO(new WritebackReqWodata)) 1297a919e05SWilliam Wang val req_data = Input(new WritebackReqData) 130a98b054bSWilliam Wang 1311f0e2dc7SJiawei Lin val mem_release = DecoupledIO(new TLBundleC(edge.bundle)) 1321f0e2dc7SJiawei Lin val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 133ffd3154dSCharlieLiu val primary_valid = Input(Bool()) 134ffd3154dSCharlieLiu val primary_ready = Output(Bool()) 135ffd3154dSCharlieLiu val primary_ready_dup = Vec(nDupWbReady, Output(Bool())) 1361f0e2dc7SJiawei Lin 1371f0e2dc7SJiawei Lin val block_addr = Output(Valid(UInt())) 1381f0e2dc7SJiawei Lin }) 1391f0e2dc7SJiawei Lin 140ffd3154dSCharlieLiu val s_invalid :: s_release_req :: s_release_resp ::Nil = Enum(3) 14177af2baeSWilliam Wang // ProbeAck: s_invalid -> s_release_req 14277af2baeSWilliam Wang // ProbeAck merge Release: s_invalid -> s_release_req 14377af2baeSWilliam Wang // Release: s_invalid -> s_sleep -> s_release_req -> s_release_resp 14477af2baeSWilliam Wang // Release merge ProbeAck: s_invalid -> s_sleep -> s_release_req 14577af2baeSWilliam Wang // (change Release into ProbeAck when Release is not fired) 14677af2baeSWilliam Wang // or: s_invalid -> s_sleep -> s_release_req -> s_release_resp -> s_release_req 14777af2baeSWilliam Wang // (send a ProbeAck after Release transaction is over) 148ffd3154dSCharlieLiu 1491f0e2dc7SJiawei Lin val state = RegInit(s_invalid) 150f94d088cSZiyue-Zhang val state_dup_0 = RegInit(s_invalid) 151f94d088cSZiyue-Zhang val state_dup_1 = RegInit(s_invalid) 1525adc4829SYanqin Li val state_dup_for_mp = RegInit(VecInit(Seq.fill(nDupWbReady)(s_invalid))) //TODO: clock gate 1531f0e2dc7SJiawei Lin 1541f0e2dc7SJiawei Lin val remain = RegInit(0.U(refillCycles.W)) 155f94d088cSZiyue-Zhang val remain_dup_0 = RegInit(0.U(refillCycles.W)) 156f94d088cSZiyue-Zhang val remain_dup_1 = RegInit(0.U(refillCycles.W)) 1571f0e2dc7SJiawei Lin val remain_set = WireInit(0.U(refillCycles.W)) 1581f0e2dc7SJiawei Lin val remain_clr = WireInit(0.U(refillCycles.W)) 1591f0e2dc7SJiawei Lin remain := (remain | remain_set) & ~remain_clr 160f94d088cSZiyue-Zhang remain_dup_0 := (remain_dup_0 | remain_set) & ~remain_clr 161f94d088cSZiyue-Zhang remain_dup_1 := (remain_dup_1 | remain_set) & ~remain_clr 1621f0e2dc7SJiawei Lin 1637a919e05SWilliam Wang // writeback queue data 1647a919e05SWilliam Wang val data = Reg(UInt((cfg.blockBytes * 8).W)) 1651f0e2dc7SJiawei Lin 16684026448SWilliam Wang // writeback queue paddr 16784026448SWilliam Wang val paddr_dup_0 = Reg(UInt(PAddrBits.W)) 16884026448SWilliam Wang val paddr_dup_1 = Reg(UInt(PAddrBits.W)) 16984026448SWilliam Wang val paddr_dup_2 = Reg(UInt(PAddrBits.W)) 17084026448SWilliam Wang 1717a919e05SWilliam Wang // pending data write 1727a919e05SWilliam Wang // !s_data_override means there is an in-progress data write 1737a919e05SWilliam Wang val s_data_override = RegInit(true.B) 1747a919e05SWilliam Wang // !s_data_merge means there is an in-progress data merge 175ffd3154dSCharlieLiu //val s_data_merge = RegInit(true.B) 1767a919e05SWilliam Wang 1777a919e05SWilliam Wang // there are valid request that can be sent to release bus 178ffd3154dSCharlieLiu //val busy = remain.orR && s_data_override && s_data_merge // have remain beats and data write finished 179ffd3154dSCharlieLiu val busy = remain.orR && s_data_override // have remain beats and data write finished 180ffd3154dSCharlieLiu val req = Reg(new WritebackReqWodata) 1811f0e2dc7SJiawei Lin 1821f0e2dc7SJiawei Lin // assign default signals to output signals 1831f0e2dc7SJiawei Lin io.req.ready := false.B 1841f0e2dc7SJiawei Lin io.mem_release.valid := false.B 1851f0e2dc7SJiawei Lin io.mem_release.bits := DontCare 1861f0e2dc7SJiawei Lin io.mem_grant.ready := false.B 1871f0e2dc7SJiawei Lin io.block_addr.valid := state =/= s_invalid 188ffd3154dSCharlieLiu io.block_addr.bits := req.addr 1891f0e2dc7SJiawei Lin 1907a919e05SWilliam Wang s_data_override := true.B // data_override takes only 1 cycle 191ffd3154dSCharlieLiu //s_data_merge := true.B // data_merge takes only 1 cycle 1921f0e2dc7SJiawei Lin 193*8b33cd30Sklin02 XSDebug(state =/= s_invalid, "WritebackEntry: %d state: %d block_addr: %x\n", io.id, state, io.block_addr.bits) 194ad3ba452Szhanglinjuan 1951f0e2dc7SJiawei Lin // -------------------------------------------------------------------------------- 1961f0e2dc7SJiawei Lin // s_invalid: receive requests 1971f0e2dc7SJiawei Lin // new req entering 198ffd3154dSCharlieLiu io.req.ready := state === s_invalid 19915ee59e4Swakafa val alloc = io.req.valid && io.primary_valid && io.primary_ready 20015ee59e4Swakafa when (alloc) { 2011f0e2dc7SJiawei Lin assert (remain === 0.U) 2021f0e2dc7SJiawei Lin req := io.req.bits 2037a919e05SWilliam Wang s_data_override := false.B 20484026448SWilliam Wang // only update paddr when allocate a new missqueue entry 20584026448SWilliam Wang paddr_dup_0 := io.req.bits.addr 20684026448SWilliam Wang paddr_dup_1 := io.req.bits.addr 20784026448SWilliam Wang paddr_dup_2 := io.req.bits.addr 208ffd3154dSCharlieLiu 209ad3ba452Szhanglinjuan remain_set := Mux(io.req.bits.hasData, ~0.U(refillCycles.W), 1.U(refillCycles.W)) 210ad3ba452Szhanglinjuan state := s_release_req 211f94d088cSZiyue-Zhang state_dup_0 := s_release_req 212f94d088cSZiyue-Zhang state_dup_1 := s_release_req 213c3a5fe5fShappy-lx state_dup_for_mp.foreach(_ := s_release_req) 2141f0e2dc7SJiawei Lin } 2151f0e2dc7SJiawei Lin 2161f0e2dc7SJiawei Lin // -------------------------------------------------------------------------------- 2171f0e2dc7SJiawei Lin // while there beats remaining to be sent, we keep sending 2181f0e2dc7SJiawei Lin // which beat to send in this cycle? 219f94d088cSZiyue-Zhang val beat = PriorityEncoder(remain_dup_0) 2201f0e2dc7SJiawei Lin 2211f0e2dc7SJiawei Lin val beat_data = Wire(Vec(refillCycles, UInt(beatBits.W))) 2221f0e2dc7SJiawei Lin for (i <- 0 until refillCycles) { 2237a919e05SWilliam Wang beat_data(i) := data((i + 1) * beatBits - 1, i * beatBits) 2241f0e2dc7SJiawei Lin } 2251f0e2dc7SJiawei Lin 2261f0e2dc7SJiawei Lin val probeResponse = edge.ProbeAck( 2271f0e2dc7SJiawei Lin fromSource = io.id, 22884026448SWilliam Wang toAddress = paddr_dup_1, 2291f0e2dc7SJiawei Lin lgSize = log2Ceil(cfg.blockBytes).U, 2301f0e2dc7SJiawei Lin reportPermissions = req.param 2311f0e2dc7SJiawei Lin ) 23272dab974Scz4e probeResponse.corrupt := req.corrupt 2331f0e2dc7SJiawei Lin 2341f0e2dc7SJiawei Lin val probeResponseData = edge.ProbeAck( 2351f0e2dc7SJiawei Lin fromSource = io.id, 23684026448SWilliam Wang toAddress = paddr_dup_1, 2371f0e2dc7SJiawei Lin lgSize = log2Ceil(cfg.blockBytes).U, 2381f0e2dc7SJiawei Lin reportPermissions = req.param, 23972dab974Scz4e data = beat_data(beat), 24072dab974Scz4e corrupt = req.corrupt 2411f0e2dc7SJiawei Lin ) 2421f0e2dc7SJiawei Lin 2431f0e2dc7SJiawei Lin val voluntaryRelease = edge.Release( 2441f0e2dc7SJiawei Lin fromSource = io.id, 24584026448SWilliam Wang toAddress = paddr_dup_2, 2461f0e2dc7SJiawei Lin lgSize = log2Ceil(cfg.blockBytes).U, 2471f0e2dc7SJiawei Lin shrinkPermissions = req.param 2481f0e2dc7SJiawei Lin )._2 24972dab974Scz4e voluntaryRelease.corrupt := req.corrupt 2501f0e2dc7SJiawei Lin 2511f0e2dc7SJiawei Lin val voluntaryReleaseData = edge.Release( 2521f0e2dc7SJiawei Lin fromSource = io.id, 25384026448SWilliam Wang toAddress = paddr_dup_2, 2541f0e2dc7SJiawei Lin lgSize = log2Ceil(cfg.blockBytes).U, 2551f0e2dc7SJiawei Lin shrinkPermissions = req.param, 25672dab974Scz4e data = beat_data(beat), 25772dab974Scz4e corrupt = req.corrupt 2581f0e2dc7SJiawei Lin )._2 2591f0e2dc7SJiawei Lin 26015ee59e4Swakafa // voluntaryReleaseData.echo.lift(DirtyKey).foreach(_ := req.dirty) 2611f0e2dc7SJiawei Lin when(busy) { 262fddcfe1fSwakafa assert(!req.dirty || req.hasData) 2631f0e2dc7SJiawei Lin } 2641f0e2dc7SJiawei Lin 2651f0e2dc7SJiawei Lin io.mem_release.valid := busy 2661f0e2dc7SJiawei Lin io.mem_release.bits := Mux(req.voluntary, 2671f0e2dc7SJiawei Lin Mux(req.hasData, voluntaryReleaseData, voluntaryRelease), 2681f0e2dc7SJiawei Lin Mux(req.hasData, probeResponseData, probeResponse)) 2691f0e2dc7SJiawei Lin 270ffd3154dSCharlieLiu 271935edac4STang Haojin when (io.mem_release.fire) {remain_clr := PriorityEncoderOH(remain_dup_1)} 2721f0e2dc7SJiawei Lin 2731f0e2dc7SJiawei Lin val (_, _, release_done, _) = edge.count(io.mem_release) 2741f0e2dc7SJiawei Lin 275ffd3154dSCharlieLiu when(state === s_release_req && release_done){ 276ffd3154dSCharlieLiu state := Mux(req.voluntary, s_release_resp, s_invalid) 27777af2baeSWilliam Wang when(req.voluntary){ 278c3a5fe5fShappy-lx state_dup_for_mp.foreach(_ := s_release_resp) 27977af2baeSWilliam Wang } .otherwise{ 280c3a5fe5fShappy-lx state_dup_for_mp.foreach(_ := s_invalid) 28177af2baeSWilliam Wang } 28277af2baeSWilliam Wang } 28377af2baeSWilliam Wang 284ffd3154dSCharlieLiu io.primary_ready := state === s_invalid 285ffd3154dSCharlieLiu io.primary_ready_dup.zip(state_dup_for_mp).foreach { case (rdy, st) => rdy := st === s_invalid } 2861f0e2dc7SJiawei Lin // -------------------------------------------------------------------------------- 2871f0e2dc7SJiawei Lin // receive ReleaseAck for Releases 288ffd3154dSCharlieLiu when (state === s_release_resp) { 2891f0e2dc7SJiawei Lin io.mem_grant.ready := true.B 290935edac4STang Haojin when (io.mem_grant.fire) { 2911f0e2dc7SJiawei Lin state := s_invalid 292c3a5fe5fShappy-lx state_dup_for_mp.foreach(_ := s_invalid) 29377af2baeSWilliam Wang } 2941f0e2dc7SJiawei Lin } 295b8f6ff86SWilliam Wang 2967a919e05SWilliam Wang // data update logic 29715ee59e4Swakafa when(!s_data_override && (req.hasData || RegNext(alloc))) { 2987a919e05SWilliam Wang data := io.req_data.data 2997a919e05SWilliam Wang } 3007a919e05SWilliam Wang 301ffd3154dSCharlieLiu // assert(!RegNext(!s_data_merge && !s_data_override)) 3027a919e05SWilliam Wang 3031f0e2dc7SJiawei Lin // performance counters 304935edac4STang Haojin XSPerfAccumulate("wb_req", io.req.fire) 3051f0e2dc7SJiawei Lin XSPerfAccumulate("wb_release", state === s_release_req && release_done && req.voluntary) 306ffd3154dSCharlieLiu XSPerfAccumulate("wb_probe_resp", state === s_release_req && release_done && !req.voluntary) 3071f0e2dc7SJiawei Lin XSPerfAccumulate("penalty_blocked_by_channel_C", io.mem_release.valid && !io.mem_release.ready) 308ffd3154dSCharlieLiu XSPerfAccumulate("penalty_waiting_for_channel_D", io.mem_grant.ready && !io.mem_grant.valid && state === s_release_resp) 3091f0e2dc7SJiawei Lin} 3101f0e2dc7SJiawei Lin 311ffd3154dSCharlieLiuclass WritebackQueue(edge: TLEdgeOut)(implicit p: Parameters) extends DCacheModule with HasTLDump with HasPerfEvents 312ffd3154dSCharlieLiu{ 3131f0e2dc7SJiawei Lin val io = IO(new Bundle { 3141f0e2dc7SJiawei Lin val req = Flipped(DecoupledIO(new WritebackReq)) 3156c7e5e86Szhanglinjuan val req_ready_dup = Vec(nDupWbReady, Output(Bool())) 3161f0e2dc7SJiawei Lin val mem_release = DecoupledIO(new TLBundleC(edge.bundle)) 3171f0e2dc7SJiawei Lin val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 3181f0e2dc7SJiawei Lin 319ffd3154dSCharlieLiu //val probe_ttob_check_req = Flipped(ValidIO(new ProbeToBCheckReq)) 320ffd3154dSCharlieLiu //val probe_ttob_check_resp = ValidIO(new ProbeToBCheckResp) 321b8f6ff86SWilliam Wang 32208b0bc30Shappy-lx // 5 miss_req to check: 3*LoadPipe + 1*MainPipe + 1*missReqArb_out 32308b0bc30Shappy-lx val miss_req_conflict_check = Vec(LoadPipelineWidth + 2, Flipped(Valid(UInt()))) 32408b0bc30Shappy-lx val block_miss_req = Vec(LoadPipelineWidth + 2, Output(Bool())) 3251f0e2dc7SJiawei Lin }) 3261f0e2dc7SJiawei Lin 327300ded30SWilliam Wang require(cfg.nReleaseEntries > cfg.nMissEntries) 328300ded30SWilliam Wang 329a98b054bSWilliam Wang val primary_ready_vec = Wire(Vec(cfg.nReleaseEntries, Bool())) 330ffd3154dSCharlieLiu val alloc = Cat(primary_ready_vec).orR 331ffd3154dSCharlieLiu 332ffd3154dSCharlieLiu val req = io.req 333ffd3154dSCharlieLiu val block_conflict = Wire(Bool()) 334ffd3154dSCharlieLiu 335ffd3154dSCharlieLiu req.ready := alloc && !block_conflict 3361f0e2dc7SJiawei Lin 3371f0e2dc7SJiawei Lin // assign default values to output signals 3381f0e2dc7SJiawei Lin io.mem_release.valid := false.B 3391f0e2dc7SJiawei Lin io.mem_release.bits := DontCare 3401f0e2dc7SJiawei Lin io.mem_grant.ready := false.B 3411f0e2dc7SJiawei Lin 342b8f6ff86SWilliam Wang // delay data write in writeback req for 1 cycle 3437a919e05SWilliam Wang val req_data = RegEnable(io.req.bits.toWritebackReqData(), io.req.valid) 3447a919e05SWilliam Wang 345ad3ba452Szhanglinjuan require(isPow2(cfg.nMissEntries)) 346300ded30SWilliam Wang val grant_source = io.mem_grant.bits.source 347a98b054bSWilliam Wang val entries = Seq.fill(cfg.nReleaseEntries)(Module(new WritebackEntry(edge))) 348a98b054bSWilliam Wang entries.zipWithIndex.foreach { 349a98b054bSWilliam Wang case (entry, i) => 350a98b054bSWilliam Wang val former_primary_ready = if(i == 0) 351a98b054bSWilliam Wang false.B 352a98b054bSWilliam Wang else 353a98b054bSWilliam Wang Cat((0 until i).map(j => entries(j).io.primary_ready)).orR 354300ded30SWilliam Wang val entry_id = (i + releaseIdBase).U 3551f0e2dc7SJiawei Lin 356300ded30SWilliam Wang entry.io.id := entry_id 3571f0e2dc7SJiawei Lin 3581f0e2dc7SJiawei Lin // entry req 3597ecd6591SCharlie Liu entry.io.req.valid := req.valid && !block_conflict 360a98b054bSWilliam Wang primary_ready_vec(i) := entry.io.primary_ready 361ffd3154dSCharlieLiu entry.io.req.bits := req.bits 3627a919e05SWilliam Wang entry.io.req_data := req_data 3631f0e2dc7SJiawei Lin 364a98b054bSWilliam Wang entry.io.primary_valid := alloc && 365a98b054bSWilliam Wang !former_primary_ready && 366a98b054bSWilliam Wang entry.io.primary_ready 367a98b054bSWilliam Wang 368300ded30SWilliam Wang entry.io.mem_grant.valid := (entry_id === grant_source) && io.mem_grant.valid 3691f0e2dc7SJiawei Lin entry.io.mem_grant.bits := io.mem_grant.bits 370ffd3154dSCharlieLiu //when (i.U === io.mem_grant.bits.source) { 371ffd3154dSCharlieLiu // io.mem_grant.ready := entry.io.mem_grant.ready 372ffd3154dSCharlieLiu //} 3731f0e2dc7SJiawei Lin } 374c3a5fe5fShappy-lx 375c3a5fe5fShappy-lx io.req_ready_dup.zipWithIndex.foreach { case (rdy, i) => 376ffd3154dSCharlieLiu rdy := Cat(entries.map(_.io.primary_ready_dup(i))).orR && !block_conflict 377c3a5fe5fShappy-lx } 378c3a5fe5fShappy-lx 37977af2baeSWilliam Wang io.mem_grant.ready := true.B 380ffd3154dSCharlieLiu block_conflict := VecInit(entries.map(e => e.io.block_addr.valid && e.io.block_addr.bits === io.req.bits.addr)).asUInt.orR 38108b0bc30Shappy-lx val miss_req_conflict = io.miss_req_conflict_check.map{ r => 38208b0bc30Shappy-lx VecInit(entries.map(e => e.io.block_addr.valid && e.io.block_addr.bits === r.bits)).asUInt.orR 38308b0bc30Shappy-lx } 38408b0bc30Shappy-lx io.block_miss_req.zipWithIndex.foreach{ case(blk, i) => 38508b0bc30Shappy-lx blk := io.miss_req_conflict_check(i).valid && miss_req_conflict(i) 38608b0bc30Shappy-lx } 3871f0e2dc7SJiawei Lin 3881f0e2dc7SJiawei Lin TLArbiter.robin(edge, io.mem_release, entries.map(_.io.mem_release):_*) 3891f0e2dc7SJiawei Lin 3901f0e2dc7SJiawei Lin // sanity check 3911f0e2dc7SJiawei Lin // print all input/output requests for debug purpose 3921f0e2dc7SJiawei Lin // print req 393*8b33cd30Sklin02 io.req.bits.dump(io.req.fire) 3941f0e2dc7SJiawei Lin 395*8b33cd30Sklin02 io.mem_grant.bits.dump(io.mem_release.fire) 3961f0e2dc7SJiawei Lin 397*8b33cd30Sklin02 // XSDebug(io.miss_req.valid, "miss_req: addr: %x\n", io.miss_req.bits) 398*8b33cd30Sklin02 // XSDebug(io.block_miss_req, "block_miss_req\n") 3991f0e2dc7SJiawei Lin 4001f0e2dc7SJiawei Lin // performance counters 401935edac4STang Haojin XSPerfAccumulate("wb_req", io.req.fire) 402cd365d4cSrvcoresjw 403b6d53cefSWilliam Wang val perfValidCount = RegNext(PopCount(entries.map(e => e.io.block_addr.valid))) 404cd365d4cSrvcoresjw val perfEvents = Seq( 405935edac4STang Haojin ("dcache_wbq_req ", io.req.fire), 406b6d53cefSWilliam Wang ("dcache_wbq_1_4_valid", (perfValidCount < (cfg.nReleaseEntries.U/4.U))), 407b6d53cefSWilliam Wang ("dcache_wbq_2_4_valid", (perfValidCount > (cfg.nReleaseEntries.U/4.U)) & (perfValidCount <= (cfg.nReleaseEntries.U/2.U))), 408b6d53cefSWilliam Wang ("dcache_wbq_3_4_valid", (perfValidCount > (cfg.nReleaseEntries.U/2.U)) & (perfValidCount <= (cfg.nReleaseEntries.U*3.U/4.U))), 409b6d53cefSWilliam Wang ("dcache_wbq_4_4_valid", (perfValidCount > (cfg.nReleaseEntries.U*3.U/4.U))), 410cd365d4cSrvcoresjw ) 4111ca0e4f3SYinan Xu generatePerfEvent() 412ffd3154dSCharlieLiu 4131f0e2dc7SJiawei Lin}