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._ 218891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 2237225120Ssfencevmaimport utils._ 233c02ee8fSwakafaimport utility._ 2437225120Ssfencevmaimport xiangshan._ 25*e04c5f64SYanqin Liimport xiangshan.mem._ 261f0e2dc7SJiawei Linimport freechips.rocketchip.diplomacy.{IdRange, LazyModule, LazyModuleImp, TransferSizes} 271f0e2dc7SJiawei Linimport freechips.rocketchip.tilelink.{TLArbiter, TLBundleA, TLBundleD, TLClientNode, TLEdgeOut, TLMasterParameters, TLMasterPortParameters} 2837225120Ssfencevma 2937225120Ssfencevmaclass UncacheFlushBundle extends Bundle { 3037225120Ssfencevma val valid = Output(Bool()) 3137225120Ssfencevma val empty = Input(Bool()) 3237225120Ssfencevma} 331f0e2dc7SJiawei Lin 34cfdd605fSYanqin Liclass UncacheEntry(implicit p: Parameters) extends DCacheBundle { 35cfdd605fSYanqin Li val cmd = UInt(M_SZ.W) 36cfdd605fSYanqin Li val addr = UInt(PAddrBits.W) 37*e04c5f64SYanqin Li val vaddr = UInt(VAddrBits.W) 38cfdd605fSYanqin Li val data = UInt(XLEN.W) 39*e04c5f64SYanqin Li val mask = UInt(DataBytes.W) 40cfdd605fSYanqin Li val id = UInt(uncacheIdxBits.W) 41cfdd605fSYanqin Li val nc = Bool() 42cfdd605fSYanqin Li val atomic = Bool() 431f0e2dc7SJiawei Lin 44cfdd605fSYanqin Li // FIXME lyq: data and resp_data can be merged? 45cfdd605fSYanqin Li val resp_data = UInt(XLEN.W) 46cfdd605fSYanqin Li val resp_nderr = Bool() 471f0e2dc7SJiawei Lin 48*e04c5f64SYanqin Li // FIXME lyq: Confirm the forward logic. if no forward, it can be removed 49*e04c5f64SYanqin Li val fwd_data = UInt(XLEN.W) 50*e04c5f64SYanqin Li val fwd_mask = UInt(DataBytes.W) 51*e04c5f64SYanqin Li 52cfdd605fSYanqin Li def set(x: UncacheWordReq): Unit = { 53cfdd605fSYanqin Li cmd := x.cmd 54cfdd605fSYanqin Li addr := x.addr 55*e04c5f64SYanqin Li vaddr := x.vaddr 56cfdd605fSYanqin Li data := x.data 57cfdd605fSYanqin Li mask := x.mask 58cfdd605fSYanqin Li id := x.id 59cfdd605fSYanqin Li nc := x.nc 60cfdd605fSYanqin Li atomic := x.atomic 6158cb1b0bSzhanglinjuan resp_nderr := false.B 62cfdd605fSYanqin Li resp_data := 0.U 63*e04c5f64SYanqin Li fwd_data := 0.U 64*e04c5f64SYanqin Li fwd_mask := 0.U 65cfdd605fSYanqin Li } 66cfdd605fSYanqin Li 67cfdd605fSYanqin Li def update(x: TLBundleD): Unit = { 68cfdd605fSYanqin Li resp_data := x.data 69cfdd605fSYanqin Li resp_nderr := x.denied 70cfdd605fSYanqin Li } 71cfdd605fSYanqin Li 72*e04c5f64SYanqin Li def update(forwardData: UInt, forwardMask: UInt): Unit = { 73*e04c5f64SYanqin Li fwd_data := forwardData 74*e04c5f64SYanqin Li fwd_mask := forwardMask 75*e04c5f64SYanqin Li } 76*e04c5f64SYanqin Li 77cfdd605fSYanqin Li def toUncacheWordResp(): UncacheWordResp = { 78*e04c5f64SYanqin Li val resp_fwd_data = VecInit((0 until DataBytes).map(j => 79*e04c5f64SYanqin Li Mux(fwd_mask(j), fwd_data(8*(j+1)-1, 8*j), resp_data(8*(j+1)-1, 8*j)) 80*e04c5f64SYanqin Li )).asUInt 81cfdd605fSYanqin Li val r = Wire(new UncacheWordResp) 82cfdd605fSYanqin Li r := DontCare 83*e04c5f64SYanqin Li r.data := resp_fwd_data 84cfdd605fSYanqin Li r.id := id 85cfdd605fSYanqin Li r.nderr := resp_nderr 86cfdd605fSYanqin Li r.nc := nc 87cfdd605fSYanqin Li r.is2lq := cmd === MemoryOpConstants.M_XRD 88cfdd605fSYanqin Li r.miss := false.B 89cfdd605fSYanqin Li r.replay := false.B 90cfdd605fSYanqin Li r.tag_error := false.B 91cfdd605fSYanqin Li r.error := false.B 92cfdd605fSYanqin Li r 931f0e2dc7SJiawei Lin } 941f0e2dc7SJiawei Lin} 951f0e2dc7SJiawei Lin 96cfdd605fSYanqin Liclass UncacheEntryState(implicit p: Parameters) extends DCacheBundle { 97cfdd605fSYanqin Li // FIXME lyq: state is multi bools or UInt()? 98cfdd605fSYanqin Li // valid (-> waitSame) -> inflight -> waitReturn 99cfdd605fSYanqin Li val valid = Bool() 100cfdd605fSYanqin Li val inflight = Bool() // uncache -> L2 101cfdd605fSYanqin Li val waitSame = Bool() 102cfdd605fSYanqin Li val waitReturn = Bool() // uncache -> LSQ 1031f0e2dc7SJiawei Lin 104cfdd605fSYanqin Li def init: Unit = { 105cfdd605fSYanqin Li valid := false.B 106cfdd605fSYanqin Li inflight := false.B 107cfdd605fSYanqin Li waitSame := false.B 108cfdd605fSYanqin Li waitReturn := false.B 1091f0e2dc7SJiawei Lin } 1101f0e2dc7SJiawei Lin 111cfdd605fSYanqin Li def isValid(): Bool = valid 112cfdd605fSYanqin Li def isInflight(): Bool = inflight 113cfdd605fSYanqin Li def isWaitReturn(): Bool = waitReturn 114cfdd605fSYanqin Li def isWaitSame(): Bool = waitSame 115cfdd605fSYanqin Li def can2Uncache(): Bool = valid && !inflight && !waitSame && !waitReturn 116cfdd605fSYanqin Li def can2Lsq(): Bool = valid && waitReturn 1171f0e2dc7SJiawei Lin 118cfdd605fSYanqin Li def setValid(x: Bool): Unit = { valid := x} 119cfdd605fSYanqin Li def setInflight(x: Bool): Unit = { inflight := x} 120cfdd605fSYanqin Li def setWaitReturn(x: Bool): Unit = { waitReturn := x } 121cfdd605fSYanqin Li def setWaitSame(x: Bool): Unit = { waitSame := x} 1221f0e2dc7SJiawei Lin 123cfdd605fSYanqin Li def updateUncacheResp(): Unit = { 124cfdd605fSYanqin Li assert(inflight, "The request was not sent and a response was received") 125cfdd605fSYanqin Li inflight := false.B 126cfdd605fSYanqin Li waitReturn := true.B 1271f0e2dc7SJiawei Lin } 128cfdd605fSYanqin Li def updateReturn(): Unit = { 129cfdd605fSYanqin Li valid := false.B 130cfdd605fSYanqin Li inflight := false.B 131cfdd605fSYanqin Li waitSame := false.B 132cfdd605fSYanqin Li waitReturn := false.B 1331f0e2dc7SJiawei Lin } 1341f0e2dc7SJiawei Lin} 1351f0e2dc7SJiawei Lin 1361f0e2dc7SJiawei Linclass UncacheIO(implicit p: Parameters) extends DCacheBundle { 13737225120Ssfencevma val hartId = Input(UInt()) 13837225120Ssfencevma val enableOutstanding = Input(Bool()) 13937225120Ssfencevma val flush = Flipped(new UncacheFlushBundle) 1406786cfb7SWilliam Wang val lsq = Flipped(new UncacheWordIO) 141*e04c5f64SYanqin Li val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO)) 1421f0e2dc7SJiawei Lin} 1431f0e2dc7SJiawei Lin 1441f0e2dc7SJiawei Lin// convert DCacheIO to TileLink 1451f0e2dc7SJiawei Lin// for Now, we only deal with TL-UL 1461f0e2dc7SJiawei Lin 14737225120Ssfencevmaclass Uncache()(implicit p: Parameters) extends LazyModule with HasXSParameter { 14895e60e55STang Haojin override def shouldBeInlined: Boolean = false 14937225120Ssfencevma def idRange: Int = UncacheBufferSize 1501f0e2dc7SJiawei Lin 1511f0e2dc7SJiawei Lin val clientParameters = TLMasterPortParameters.v1( 1521f0e2dc7SJiawei Lin clients = Seq(TLMasterParameters.v1( 1531f0e2dc7SJiawei Lin "uncache", 15437225120Ssfencevma sourceId = IdRange(0, idRange) 1551f0e2dc7SJiawei Lin )) 1561f0e2dc7SJiawei Lin ) 1571f0e2dc7SJiawei Lin val clientNode = TLClientNode(Seq(clientParameters)) 1581f0e2dc7SJiawei Lin 1591f0e2dc7SJiawei Lin lazy val module = new UncacheImp(this) 1601f0e2dc7SJiawei Lin} 1611f0e2dc7SJiawei Lin 162cfdd605fSYanqin Li/* Uncache Buffer */ 16337225120Ssfencevmaclass UncacheImp(outer: Uncache)extends LazyModuleImp(outer) 1641f0e2dc7SJiawei Lin with HasTLDump 16537225120Ssfencevma with HasXSParameter 16637225120Ssfencevma with HasPerfEvents 1671f0e2dc7SJiawei Lin{ 168cfdd605fSYanqin Li private val INDEX_WIDTH = log2Up(UncacheBufferSize) 169cfdd605fSYanqin Li println(s"Uncahe Buffer Size: $UncacheBufferSize entries") 1701f0e2dc7SJiawei Lin val io = IO(new UncacheIO) 1711f0e2dc7SJiawei Lin 1721f0e2dc7SJiawei Lin val (bus, edge) = outer.clientNode.out.head 1731f0e2dc7SJiawei Lin 1741f0e2dc7SJiawei Lin val req = io.lsq.req 1751f0e2dc7SJiawei Lin val resp = io.lsq.resp 1761f0e2dc7SJiawei Lin val mem_acquire = bus.a 1771f0e2dc7SJiawei Lin val mem_grant = bus.d 1781f0e2dc7SJiawei Lin val req_ready = WireInit(false.B) 1791f0e2dc7SJiawei Lin 1801f0e2dc7SJiawei Lin // assign default values to output signals 1811f0e2dc7SJiawei Lin bus.b.ready := false.B 1821f0e2dc7SJiawei Lin bus.c.valid := false.B 1831f0e2dc7SJiawei Lin bus.c.bits := DontCare 1841f0e2dc7SJiawei Lin bus.d.ready := false.B 1851f0e2dc7SJiawei Lin bus.e.valid := false.B 1861f0e2dc7SJiawei Lin bus.e.bits := DontCare 187cfdd605fSYanqin Li io.lsq.req.ready := req_ready 18837225120Ssfencevma io.lsq.resp.valid := false.B 18937225120Ssfencevma io.lsq.resp.bits := DontCare 1901f0e2dc7SJiawei Lin 19137225120Ssfencevma 192cfdd605fSYanqin Li /****************************************************************** 193cfdd605fSYanqin Li * Data Structure 194cfdd605fSYanqin Li ******************************************************************/ 19537225120Ssfencevma 196cfdd605fSYanqin Li val entries = Reg(Vec(UncacheBufferSize, new UncacheEntry)) 197cfdd605fSYanqin Li val states = RegInit(VecInit(Seq.fill(UncacheBufferSize)(0.U.asTypeOf(new UncacheEntryState)))) 198cfdd605fSYanqin Li val fence = RegInit(Bool(), false.B) 199cfdd605fSYanqin Li val s_idle :: s_refill_req :: s_refill_resp :: s_send_resp :: Nil = Enum(4) 200cfdd605fSYanqin Li val uState = RegInit(s_idle) 2011f0e2dc7SJiawei Lin 202cfdd605fSYanqin Li def sizeMap[T <: Data](f: Int => T) = VecInit((0 until UncacheBufferSize).map(f)) 203*e04c5f64SYanqin Li def isStore(e: UncacheEntry): Bool = e.cmd === MemoryOpConstants.M_XWR 204*e04c5f64SYanqin Li def isStore(x: UInt): Bool = x === MemoryOpConstants.M_XWR 205*e04c5f64SYanqin Li 206*e04c5f64SYanqin Li // drain buffer 207*e04c5f64SYanqin Li val empty = Wire(Bool()) 208*e04c5f64SYanqin Li val f0_needDrain = Wire(Bool()) 209*e04c5f64SYanqin Li val do_uarch_drain = RegNext(f0_needDrain) 2101f0e2dc7SJiawei Lin 211cfdd605fSYanqin Li val q0_entry = Wire(new UncacheEntry) 212cfdd605fSYanqin Li val q0_canSentIdx = Wire(UInt(INDEX_WIDTH.W)) 213cfdd605fSYanqin Li val q0_canSent = Wire(Bool()) 214*e04c5f64SYanqin Li 215*e04c5f64SYanqin Li 216cfdd605fSYanqin Li /****************************************************************** 217cfdd605fSYanqin Li * uState for non-outstanding 218cfdd605fSYanqin Li ******************************************************************/ 21937225120Ssfencevma 220cfdd605fSYanqin Li switch(uState){ 221cfdd605fSYanqin Li is(s_idle){ 22237225120Ssfencevma when(req.fire){ 223cfdd605fSYanqin Li uState := s_refill_req 22437225120Ssfencevma } 225cfdd605fSYanqin Li } 226cfdd605fSYanqin Li is(s_refill_req){ 22737225120Ssfencevma when(mem_acquire.fire){ 228cfdd605fSYanqin Li uState := s_refill_resp 22937225120Ssfencevma } 23037225120Ssfencevma } 231cfdd605fSYanqin Li is(s_refill_resp){ 23237225120Ssfencevma when(mem_grant.fire){ 233cfdd605fSYanqin Li uState := s_send_resp 23437225120Ssfencevma } 23537225120Ssfencevma } 236cfdd605fSYanqin Li is(s_send_resp){ 237cfdd605fSYanqin Li when(resp.fire){ 238cfdd605fSYanqin Li uState := s_idle 239cfdd605fSYanqin Li } 24037225120Ssfencevma } 24137225120Ssfencevma } 24237225120Ssfencevma 243cfdd605fSYanqin Li 244cfdd605fSYanqin Li /****************************************************************** 245cfdd605fSYanqin Li * Enter Buffer 246cfdd605fSYanqin Li * Version 0 (better timing) 247cfdd605fSYanqin Li * e0 judge: alloc/merge write vec 248cfdd605fSYanqin Li * e1 alloc 249cfdd605fSYanqin Li * 250cfdd605fSYanqin Li * Version 1 (better performance) 251cfdd605fSYanqin Li * solved in one cycle for achieving the original performance. 252cfdd605fSYanqin Li ******************************************************************/ 253cfdd605fSYanqin Li 254cfdd605fSYanqin Li /** 255cfdd605fSYanqin Li TODO lyq: how to merge 256cfdd605fSYanqin Li 1. same addr 257cfdd605fSYanqin Li 2. same cmd 258cfdd605fSYanqin Li 3. valid 259cfdd605fSYanqin Li FIXME lyq: not merge now due to the following issues 260cfdd605fSYanqin Li 1. load cann't be merged 261cfdd605fSYanqin Li 2. how to merge store and response precisely 262cfdd605fSYanqin Li */ 263cfdd605fSYanqin Li 264cfdd605fSYanqin Li val e0_fire = req.fire 265cfdd605fSYanqin Li val e0_req = req.bits 266*e04c5f64SYanqin Li /** 267*e04c5f64SYanqin Li TODO lyq: prohibit or wait or forward? 268*e04c5f64SYanqin Li NOW: strict block by same address; otherwise: exhaustive consideration is needed. 269*e04c5f64SYanqin Li - ld->ld wait 270*e04c5f64SYanqin Li - ld->st forward 271*e04c5f64SYanqin Li - st->ld forward 272*e04c5f64SYanqin Li - st->st block 273*e04c5f64SYanqin Li */ 274*e04c5f64SYanqin Li val e0_existSameVec = sizeMap(j => 275*e04c5f64SYanqin Li e0_req.addr === entries(j).addr && states(j).isValid() 276*e04c5f64SYanqin Li ) 277*e04c5f64SYanqin Li val e0_invalidVec = sizeMap(i => !states(i).isValid() && !e0_existSameVec(i)) 278*e04c5f64SYanqin Li val (e0_allocIdx, e0_canAlloc) = PriorityEncoderWithFlag(e0_invalidVec) 279*e04c5f64SYanqin Li val e0_alloc = e0_canAlloc && e0_fire 280*e04c5f64SYanqin Li req_ready := e0_invalidVec.asUInt.orR && !do_uarch_drain 281cfdd605fSYanqin Li 282*e04c5f64SYanqin Li when (e0_alloc) { 283*e04c5f64SYanqin Li entries(e0_allocIdx).set(e0_req) 284*e04c5f64SYanqin Li states(e0_allocIdx).setValid(true.B) 285cfdd605fSYanqin Li 286cfdd605fSYanqin Li // judge whether wait same block: e0 & q0 287cfdd605fSYanqin Li val waitSameVec = sizeMap(j => 288cfdd605fSYanqin Li e0_req.addr === entries(j).addr && states(j).isValid() && states(j).isInflight() 289cfdd605fSYanqin Li ) 290cfdd605fSYanqin Li val waitQ0 = e0_req.addr === q0_entry.addr && q0_canSent 291cfdd605fSYanqin Li when (waitSameVec.reduce(_ || _) || waitQ0) { 292*e04c5f64SYanqin Li states(e0_allocIdx).setWaitSame(true.B) 293cfdd605fSYanqin Li } 294*e04c5f64SYanqin Li 295cfdd605fSYanqin Li } 296cfdd605fSYanqin Li 297cfdd605fSYanqin Li 298cfdd605fSYanqin Li /****************************************************************** 299cfdd605fSYanqin Li * Uncache Req 300cfdd605fSYanqin Li * Version 0 (better timing) 301cfdd605fSYanqin Li * q0: choose which one is sent 302cfdd605fSYanqin Li * q0: sent 303cfdd605fSYanqin Li * 304cfdd605fSYanqin Li * Version 1 (better performance) 305cfdd605fSYanqin Li * solved in one cycle for achieving the original performance. 306cfdd605fSYanqin Li * NOTE: "Enter Buffer" & "Uncache Req" not a continuous pipeline, 307cfdd605fSYanqin Li * because there is no guarantee that mem_aquire will be always ready. 308cfdd605fSYanqin Li ******************************************************************/ 309cfdd605fSYanqin Li 310cfdd605fSYanqin Li val q0_canSentVec = sizeMap(i => 311*e04c5f64SYanqin Li (io.enableOutstanding || uState === s_refill_req) && 312cfdd605fSYanqin Li states(i).can2Uncache() 313cfdd605fSYanqin Li ) 314cfdd605fSYanqin Li val q0_res = PriorityEncoderWithFlag(q0_canSentVec) 315cfdd605fSYanqin Li q0_canSentIdx := q0_res._1 316cfdd605fSYanqin Li q0_canSent := q0_res._2 317cfdd605fSYanqin Li q0_entry := entries(q0_canSentIdx) 318cfdd605fSYanqin Li 319cfdd605fSYanqin Li val size = PopCount(q0_entry.mask) 320cfdd605fSYanqin Li val (lgSize, legal) = PriorityMuxWithFlag(Seq( 321cfdd605fSYanqin Li 1.U -> 0.U, 322cfdd605fSYanqin Li 2.U -> 1.U, 323cfdd605fSYanqin Li 4.U -> 2.U, 324cfdd605fSYanqin Li 8.U -> 3.U 325cfdd605fSYanqin Li ).map(m => (size===m._1) -> m._2)) 326cfdd605fSYanqin Li assert(!(q0_canSent && !legal)) 327cfdd605fSYanqin Li 328cfdd605fSYanqin Li val q0_load = edge.Get( 329cfdd605fSYanqin Li fromSource = q0_canSentIdx, 330cfdd605fSYanqin Li toAddress = q0_entry.addr, 331cfdd605fSYanqin Li lgSize = lgSize 332cfdd605fSYanqin Li )._2 333cfdd605fSYanqin Li 334cfdd605fSYanqin Li val q0_store = edge.Put( 335cfdd605fSYanqin Li fromSource = q0_canSentIdx, 336cfdd605fSYanqin Li toAddress = q0_entry.addr, 337cfdd605fSYanqin Li lgSize = lgSize, 338cfdd605fSYanqin Li data = q0_entry.data, 339cfdd605fSYanqin Li mask = q0_entry.mask 340cfdd605fSYanqin Li )._2 341cfdd605fSYanqin Li 342cfdd605fSYanqin Li val q0_isStore = q0_entry.cmd === MemoryOpConstants.M_XWR 343cfdd605fSYanqin Li 344cfdd605fSYanqin Li mem_acquire.valid := q0_canSent 345cfdd605fSYanqin Li mem_acquire.bits := Mux(q0_isStore, q0_store, q0_load) 346cfdd605fSYanqin Li when(mem_acquire.fire){ 347cfdd605fSYanqin Li states(q0_canSentIdx).setInflight(true.B) 348cfdd605fSYanqin Li 349cfdd605fSYanqin Li // q0 should judge whether wait same block 350cfdd605fSYanqin Li (0 until UncacheBufferSize).map(j => 351cfdd605fSYanqin Li when(q0_entry.addr === entries(j).addr && states(j).isValid() && !states(j).isWaitReturn()){ 352cfdd605fSYanqin Li states(j).setWaitSame(true.B) 353cfdd605fSYanqin Li } 354cfdd605fSYanqin Li ) 355cfdd605fSYanqin Li } 356cfdd605fSYanqin Li 357cfdd605fSYanqin Li 358cfdd605fSYanqin Li /****************************************************************** 359cfdd605fSYanqin Li * Uncache Resp 360cfdd605fSYanqin Li ******************************************************************/ 361cfdd605fSYanqin Li 362cfdd605fSYanqin Li val (_, _, refill_done, _) = edge.addr_inc(mem_grant) 363cfdd605fSYanqin Li 364cfdd605fSYanqin Li mem_grant.ready := true.B 365cfdd605fSYanqin Li when (mem_grant.fire) { 366cfdd605fSYanqin Li val id = mem_grant.bits.source 367cfdd605fSYanqin Li entries(id).update(mem_grant.bits) 368cfdd605fSYanqin Li states(id).updateUncacheResp() 369cfdd605fSYanqin Li assert(refill_done, "Uncache response should be one beat only!") 370cfdd605fSYanqin Li 371cfdd605fSYanqin Li // remove state of wait same block 372cfdd605fSYanqin Li (0 until UncacheBufferSize).map(j => 373cfdd605fSYanqin Li when(entries(id).addr === entries(j).addr && states(j).isValid() && states(j).isWaitSame()){ 374cfdd605fSYanqin Li states(j).setWaitSame(false.B) 375cfdd605fSYanqin Li } 376cfdd605fSYanqin Li ) 377cfdd605fSYanqin Li } 378cfdd605fSYanqin Li 379cfdd605fSYanqin Li 380cfdd605fSYanqin Li /****************************************************************** 381cfdd605fSYanqin Li * Return to LSQ 382cfdd605fSYanqin Li ******************************************************************/ 383cfdd605fSYanqin Li 384cfdd605fSYanqin Li val r0_canSentVec = sizeMap(i => states(i).can2Lsq()) 385cfdd605fSYanqin Li val (r0_canSentIdx, r0_canSent) = PriorityEncoderWithFlag(r0_canSentVec) 386cfdd605fSYanqin Li resp.valid := r0_canSent 387cfdd605fSYanqin Li resp.bits := entries(r0_canSentIdx).toUncacheWordResp() 388cfdd605fSYanqin Li when(resp.fire){ 389cfdd605fSYanqin Li states(r0_canSentIdx).updateReturn() 390cfdd605fSYanqin Li } 391cfdd605fSYanqin Li 392cfdd605fSYanqin Li 393cfdd605fSYanqin Li /****************************************************************** 394cfdd605fSYanqin Li * Buffer Flush 395cfdd605fSYanqin Li * // FIXME lyq: how to deal 396cfdd605fSYanqin Li * 1. when io.flush.valid is true 397cfdd605fSYanqin Li * 2. when io.lsq.req.bits.atomic is true 398cfdd605fSYanqin Li ******************************************************************/ 399*e04c5f64SYanqin Li empty := !VecInit(states.map(_.isValid())).asUInt.orR 400*e04c5f64SYanqin Li io.flush.empty := empty 401cfdd605fSYanqin Li 402*e04c5f64SYanqin Li 403*e04c5f64SYanqin Li /****************************************************************** 404*e04c5f64SYanqin Li * Load Data Forward 405*e04c5f64SYanqin Li * 406*e04c5f64SYanqin Li * 0. ld in ldu pipeline 407*e04c5f64SYanqin Li * f0: tag match, fast resp 408*e04c5f64SYanqin Li * f1: data resp 409*e04c5f64SYanqin Li * 410*e04c5f64SYanqin Li * 1. ld in buffer (in "Enter Buffer") 411*e04c5f64SYanqin Li * ld(en) -> st(in): ld entry.update, state.updateUncacheResp 412*e04c5f64SYanqin Li * st(en) -> ld(in): ld entry.update, state.updateUncacheResp 413*e04c5f64SYanqin Li * NOW: strict block by same address; there is no such forward. 414*e04c5f64SYanqin Li * 415*e04c5f64SYanqin Li ******************************************************************/ 416*e04c5f64SYanqin Li 417*e04c5f64SYanqin Li val f0_validMask = sizeMap(i => isStore(entries(i)) && states(i).isValid()) 418*e04c5f64SYanqin Li val f0_tagMismatchVec = Wire(Vec(LoadPipelineWidth, Bool())) 419*e04c5f64SYanqin Li f0_needDrain := f0_tagMismatchVec.asUInt.orR && !empty 420*e04c5f64SYanqin Li 421*e04c5f64SYanqin Li for ((forward, i) <- io.forward.zipWithIndex) { 422*e04c5f64SYanqin Li val f0_vtagMatches = sizeMap(w => entries(w).vaddr === forward.vaddr) 423*e04c5f64SYanqin Li val f0_ptagMatches = sizeMap(w => entries(w).addr === forward.paddr) 424*e04c5f64SYanqin Li f0_tagMismatchVec(i) := forward.valid && sizeMap(w => 425*e04c5f64SYanqin Li f0_vtagMatches(w) =/= f0_ptagMatches(w) && f0_validMask(w) 426*e04c5f64SYanqin Li ).asUInt.orR 427*e04c5f64SYanqin Li when (f0_tagMismatchVec(i)) { 428*e04c5f64SYanqin Li XSDebug("forward tag mismatch: pmatch %x vmatch %x vaddr %x paddr %x\n", 429*e04c5f64SYanqin Li RegNext(f0_ptagMatches.asUInt), 430*e04c5f64SYanqin Li RegNext(f0_vtagMatches.asUInt), 431*e04c5f64SYanqin Li RegNext(forward.vaddr), 432*e04c5f64SYanqin Li RegNext(forward.paddr) 433*e04c5f64SYanqin Li ) 434*e04c5f64SYanqin Li } 435*e04c5f64SYanqin Li 436*e04c5f64SYanqin Li val f0_validTagMatches = sizeMap(w => f0_ptagMatches(w) && f0_validMask(w) && forward.valid) 437*e04c5f64SYanqin Li 438*e04c5f64SYanqin Li val f0_fwdMaskCandidates = VecInit(entries.map(e => e.mask)) 439*e04c5f64SYanqin Li val f0_fwdDataCandidates = VecInit(entries.map(e => e.data)) 440*e04c5f64SYanqin Li val f0_fwdMask = shiftMaskToHigh( 441*e04c5f64SYanqin Li forward.paddr, 442*e04c5f64SYanqin Li Mux1H(f0_validTagMatches, f0_fwdMaskCandidates) 443*e04c5f64SYanqin Li ).asTypeOf(Vec(VDataBytes, Bool())) 444*e04c5f64SYanqin Li val f0_fwdData = shiftDataToHigh( 445*e04c5f64SYanqin Li forward.paddr, 446*e04c5f64SYanqin Li Mux1H(f0_validTagMatches, f0_fwdDataCandidates) 447*e04c5f64SYanqin Li ).asTypeOf(Vec(VDataBytes, UInt(8.W))) 448*e04c5f64SYanqin Li 449*e04c5f64SYanqin Li val f1_fwdValid = RegNext(forward.valid) 450*e04c5f64SYanqin Li val f1_fwdMask = RegEnable(f0_fwdMask, forward.valid) 451*e04c5f64SYanqin Li val f1_fwdData = RegEnable(f0_fwdData, forward.valid) 452*e04c5f64SYanqin Li 453*e04c5f64SYanqin Li forward.addrInvalid := false.B // addr in ubuffer is always ready 454*e04c5f64SYanqin Li forward.dataInvalid := false.B // data in ubuffer is always ready 455*e04c5f64SYanqin Li forward.matchInvalid := f0_tagMismatchVec(i) // paddr / vaddr cam result does not match 456*e04c5f64SYanqin Li for (j <- 0 until VDataBytes) { 457*e04c5f64SYanqin Li forward.forwardMaskFast(j) := f0_fwdMask(j) 458*e04c5f64SYanqin Li 459*e04c5f64SYanqin Li forward.forwardMask(j) := false.B 460*e04c5f64SYanqin Li forward.forwardData(j) := DontCare 461*e04c5f64SYanqin Li when(f1_fwdMask(j) && f1_fwdValid) { 462*e04c5f64SYanqin Li forward.forwardMask(j) := true.B 463*e04c5f64SYanqin Li forward.forwardData(j) := f1_fwdData(j) 464*e04c5f64SYanqin Li } 465*e04c5f64SYanqin Li } 466*e04c5f64SYanqin Li 467*e04c5f64SYanqin Li } 4681f0e2dc7SJiawei Lin 4691f0e2dc7SJiawei Lin 470cfdd605fSYanqin Li /****************************************************************** 471cfdd605fSYanqin Li * Debug / Performance 472cfdd605fSYanqin Li ******************************************************************/ 473cfdd605fSYanqin Li 474cfdd605fSYanqin Li /* Debug Counters */ 4751f0e2dc7SJiawei Lin // print all input/output requests for debug purpose 4761f0e2dc7SJiawei Lin // print req/resp 477935edac4STang Haojin XSDebug(req.fire, "req cmd: %x addr: %x data: %x mask: %x\n", 4781f0e2dc7SJiawei Lin req.bits.cmd, req.bits.addr, req.bits.data, req.bits.mask) 479935edac4STang Haojin XSDebug(resp.fire, "data: %x\n", req.bits.data) 4801f0e2dc7SJiawei Lin // print tilelink messages 4811f0e2dc7SJiawei Lin when(mem_acquire.valid){ 4821f0e2dc7SJiawei Lin XSDebug("mem_acquire valid, ready=%d ", mem_acquire.ready) 4831f0e2dc7SJiawei Lin mem_acquire.bits.dump 4841f0e2dc7SJiawei Lin } 485935edac4STang Haojin when (mem_grant.fire) { 4861f0e2dc7SJiawei Lin XSDebug("mem_grant fire ") 4871f0e2dc7SJiawei Lin mem_grant.bits.dump 4881f0e2dc7SJiawei Lin } 48937225120Ssfencevma 490cfdd605fSYanqin Li /* Performance Counters */ 491*e04c5f64SYanqin Li XSPerfAccumulate("uncache_mmio_store", io.lsq.req.fire && isStore(io.lsq.req.bits.cmd) && !io.lsq.req.bits.nc) 492*e04c5f64SYanqin Li XSPerfAccumulate("uncache_mmio_load", io.lsq.req.fire && !isStore(io.lsq.req.bits.cmd) && !io.lsq.req.bits.nc) 493*e04c5f64SYanqin Li XSPerfAccumulate("uncache_nc_store", io.lsq.req.fire && isStore(io.lsq.req.bits.cmd) && io.lsq.req.bits.nc) 494*e04c5f64SYanqin Li XSPerfAccumulate("uncache_nc_load", io.lsq.req.fire && !isStore(io.lsq.req.bits.cmd) && io.lsq.req.bits.nc) 495cfdd605fSYanqin Li XSPerfAccumulate("uncache_outstanding", uState =/= s_refill_req && mem_acquire.fire) 496*e04c5f64SYanqin Li XSPerfAccumulate("vaddr_match_failed", PopCount(f0_tagMismatchVec)) 497cfdd605fSYanqin Li 49837225120Ssfencevma val perfEvents = Seq( 499*e04c5f64SYanqin Li ("uncache_mmio_store", io.lsq.req.fire && isStore(io.lsq.req.bits.cmd) && !io.lsq.req.bits.nc), 500*e04c5f64SYanqin Li ("uncache_mmio_load", io.lsq.req.fire && !isStore(io.lsq.req.bits.cmd) && !io.lsq.req.bits.nc), 501*e04c5f64SYanqin Li ("uncache_nc_store", io.lsq.req.fire && isStore(io.lsq.req.bits.cmd) && io.lsq.req.bits.nc), 502*e04c5f64SYanqin Li ("uncache_nc_load", io.lsq.req.fire && !isStore(io.lsq.req.bits.cmd) && io.lsq.req.bits.nc), 503cfdd605fSYanqin Li ("uncache_outstanding", uState =/= s_refill_req && mem_acquire.fire) 50437225120Ssfencevma ) 50537225120Ssfencevma 50637225120Ssfencevma generatePerfEvent() 50737225120Ssfencevma // End 5081f0e2dc7SJiawei Lin} 509