1e9e6cd09SYanqin Li/*************************************************************************************** 2e9e6cd09SYanqin Li * Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3e9e6cd09SYanqin Li * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 4e9e6cd09SYanqin Li * Copyright (c) 2020-2021 Peng Cheng Laboratory 5e9e6cd09SYanqin Li * 6e9e6cd09SYanqin Li * XiangShan is licensed under Mulan PSL v2. 7e9e6cd09SYanqin Li * You can use this software according to the terms and conditions of the Mulan PSL v2. 8e9e6cd09SYanqin Li * You may obtain a copy of Mulan PSL v2 at: 9e9e6cd09SYanqin Li * http://license.coscl.org.cn/MulanPSL2 10e9e6cd09SYanqin Li * 11e9e6cd09SYanqin Li * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 12e9e6cd09SYanqin Li * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 13e9e6cd09SYanqin Li * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 14e9e6cd09SYanqin Li * 15e9e6cd09SYanqin Li * See the Mulan PSL v2 for more details. 16e9e6cd09SYanqin Li ***************************************************************************************/ 17e9e6cd09SYanqin Lipackage xiangshan.mem 18e9e6cd09SYanqin Li 19e9e6cd09SYanqin Liimport chisel3._ 20e9e6cd09SYanqin Liimport chisel3.util._ 21e9e6cd09SYanqin Liimport org.chipsalliance.cde.config._ 22e9e6cd09SYanqin Liimport xiangshan._ 23e9e6cd09SYanqin Liimport xiangshan.backend.rob.{RobPtr, RobLsqIO} 24e9e6cd09SYanqin Liimport xiangshan.ExceptionNO._ 25e9e6cd09SYanqin Liimport xiangshan.cache._ 26e9e6cd09SYanqin Liimport utils._ 27e9e6cd09SYanqin Liimport utility._ 28e9e6cd09SYanqin Liimport xiangshan.backend.Bundles 29e9e6cd09SYanqin Liimport xiangshan.backend.Bundles.{DynInst, MemExuOutput} 30e9e6cd09SYanqin Liimport xiangshan.backend.fu.FuConfig.LduCfg 31e10e20c6SYanqin Liimport xiangshan.backend.HasMemBlockParameters 32e9e6cd09SYanqin Li 33e9e6cd09SYanqin Liclass UncacheEntry(entryIndex: Int)(implicit p: Parameters) extends XSModule 34e9e6cd09SYanqin Li with HasCircularQueuePtrHelper 35e9e6cd09SYanqin Li with HasLoadHelper 36e9e6cd09SYanqin Li{ 37e9e6cd09SYanqin Li val io = IO(new Bundle() { 38e9e6cd09SYanqin Li /* control */ 39e9e6cd09SYanqin Li val redirect = Flipped(Valid(new Redirect)) 40e9e6cd09SYanqin Li // redirect flush 41e9e6cd09SYanqin Li val flush = Output(Bool()) 42e9e6cd09SYanqin Li // mmio commit 43e9e6cd09SYanqin Li val rob = Flipped(new RobLsqIO) 44e9e6cd09SYanqin Li // mmio select 45e9e6cd09SYanqin Li val mmioSelect = Output(Bool()) 46e9e6cd09SYanqin Li 47e9e6cd09SYanqin Li /* transaction */ 48e9e6cd09SYanqin Li // from ldu 49e9e6cd09SYanqin Li val req = Flipped(Valid(new LqWriteBundle)) 50e9e6cd09SYanqin Li // to ldu: mmio, data 51e9e6cd09SYanqin Li val mmioOut = DecoupledIO(new MemExuOutput) 52e9e6cd09SYanqin Li val mmioRawData = Output(new LoadDataFromLQBundle) 53e9e6cd09SYanqin Li // to ldu: nc with data 54e9e6cd09SYanqin Li val ncOut = DecoupledIO(new LsPipelineBundle) 55e9e6cd09SYanqin Li // <=> uncache 56e9e6cd09SYanqin Li val uncache = new UncacheWordIO 57e9e6cd09SYanqin Li // exception generated by outer bus 58e9e6cd09SYanqin Li val exception = Valid(new LqWriteBundle) 59e9e6cd09SYanqin Li }) 60e9e6cd09SYanqin Li 61e9e6cd09SYanqin Li val req_valid = RegInit(false.B) 62e9e6cd09SYanqin Li val isNC = RegInit(false.B) 63e9e6cd09SYanqin Li val req = Reg(new LqWriteBundle) 64e9e6cd09SYanqin Li 65e9e6cd09SYanqin Li val s_idle :: s_req :: s_resp :: s_wait :: Nil = Enum(4) 66e9e6cd09SYanqin Li val uncacheState = RegInit(s_idle) 67e9e6cd09SYanqin Li val uncacheData = Reg(io.uncache.resp.bits.data.cloneType) 68e9e6cd09SYanqin Li val nderr = RegInit(false.B) 69e9e6cd09SYanqin Li 70e9e6cd09SYanqin Li val writeback = Mux(req.nc, io.ncOut.fire, io.mmioOut.fire) 71e9e6cd09SYanqin Li 72e9e6cd09SYanqin Li /** 73e9e6cd09SYanqin Li * Flush 74e9e6cd09SYanqin Li * 75e9e6cd09SYanqin Li * 1. direct flush during idle 76e9e6cd09SYanqin Li * 2. otherwise delayed flush until receiving uncache resp 77e9e6cd09SYanqin Li */ 78e9e6cd09SYanqin Li val needFlushReg = RegInit(false.B) 79e9e6cd09SYanqin Li val needFlush = req_valid && req.uop.robIdx.needFlush(io.redirect) 80e9e6cd09SYanqin Li val flush = (needFlush && uncacheState===s_idle) || (io.uncache.resp.fire && needFlushReg) 81e9e6cd09SYanqin Li when(flush){ 82e9e6cd09SYanqin Li needFlushReg := false.B 83e9e6cd09SYanqin Li }.elsewhen(needFlush){ 84e9e6cd09SYanqin Li needFlushReg := true.B 85e9e6cd09SYanqin Li } 86e9e6cd09SYanqin Li 87e9e6cd09SYanqin Li /* enter req */ 88e9e6cd09SYanqin Li when (flush) { 89e9e6cd09SYanqin Li req_valid := false.B 90e9e6cd09SYanqin Li } .elsewhen (io.req.valid) { 91e9e6cd09SYanqin Li req_valid := true.B 92e9e6cd09SYanqin Li req := io.req.bits 93e9e6cd09SYanqin Li nderr := false.B 94e9e6cd09SYanqin Li } .elsewhen (writeback) { 95e9e6cd09SYanqin Li req_valid := false.B 96e9e6cd09SYanqin Li } 978b33cd30Sklin02 XSError(!flush && io.req.valid && req_valid, p"LoadQueueUncache: You can not write an valid entry: $entryIndex") 98e9e6cd09SYanqin Li 99e9e6cd09SYanqin Li /** 100e9e6cd09SYanqin Li * Memory mapped IO / NC operations 101e9e6cd09SYanqin Li * 102e9e6cd09SYanqin Li * States: 103e9e6cd09SYanqin Li * (1) s_idle: wait for mmio reaching ROB's head / nc req valid from loadunit 104e9e6cd09SYanqin Li * (2) s_req: wait to be sent to uncache channel until req selected and uncache ready 105e9e6cd09SYanqin Li * (3) s_resp: wait for response from uncache channel 106e9e6cd09SYanqin Li * (4) s_wait: wait for loadunit to receive writeback req 107e9e6cd09SYanqin Li */ 108e9e6cd09SYanqin Li val pendingld = GatedValidRegNext(io.rob.pendingMMIOld) 109e9e6cd09SYanqin Li val pendingPtr = GatedRegNext(io.rob.pendingPtr) 110e9e6cd09SYanqin Li val canSendReq = req_valid && !needFlush && Mux( 111e9e6cd09SYanqin Li req.nc, true.B, 112e9e6cd09SYanqin Li pendingld && req.uop.robIdx === pendingPtr 113e9e6cd09SYanqin Li ) 114e9e6cd09SYanqin Li switch (uncacheState) { 115e9e6cd09SYanqin Li is (s_idle) { 116e9e6cd09SYanqin Li when (canSendReq) { 117e9e6cd09SYanqin Li uncacheState := s_req 118e9e6cd09SYanqin Li } 119e9e6cd09SYanqin Li } 120e9e6cd09SYanqin Li is (s_req) { 121e9e6cd09SYanqin Li when (io.uncache.req.fire) { 122e9e6cd09SYanqin Li uncacheState := s_resp 123e9e6cd09SYanqin Li } 124e9e6cd09SYanqin Li } 125e9e6cd09SYanqin Li is (s_resp) { 126e9e6cd09SYanqin Li when (io.uncache.resp.fire) { 127e9e6cd09SYanqin Li when (needFlushReg) { 128e9e6cd09SYanqin Li uncacheState := s_idle 129e9e6cd09SYanqin Li }.otherwise{ 130e9e6cd09SYanqin Li uncacheState := s_wait 131e9e6cd09SYanqin Li } 132e9e6cd09SYanqin Li } 133e9e6cd09SYanqin Li } 134e9e6cd09SYanqin Li is (s_wait) { 135e9e6cd09SYanqin Li when (writeback) { 136e9e6cd09SYanqin Li uncacheState := s_idle 137e9e6cd09SYanqin Li } 138e9e6cd09SYanqin Li } 139e9e6cd09SYanqin Li } 140e9e6cd09SYanqin Li 141e9e6cd09SYanqin Li /* control */ 142e9e6cd09SYanqin Li io.flush := flush 143e9e6cd09SYanqin Li io.rob.mmio := DontCare 144e9e6cd09SYanqin Li io.rob.uop := DontCare 145e9e6cd09SYanqin Li io.mmioSelect := (uncacheState =/= s_idle) && req.mmio 146e9e6cd09SYanqin Li 147e9e6cd09SYanqin Li /* uncahce req */ 148e9e6cd09SYanqin Li io.uncache.req.valid := uncacheState === s_req 149e9e6cd09SYanqin Li io.uncache.req.bits := DontCare 150e9e6cd09SYanqin Li io.uncache.req.bits.cmd := MemoryOpConstants.M_XRD 151e9e6cd09SYanqin Li io.uncache.req.bits.data := DontCare 152e9e6cd09SYanqin Li io.uncache.req.bits.addr := req.paddr 153e9e6cd09SYanqin Li io.uncache.req.bits.vaddr:= req.vaddr 154e9e6cd09SYanqin Li io.uncache.req.bits.mask := Mux(req.paddr(3), req.mask(15, 8), req.mask(7, 0)) 155e9e6cd09SYanqin Li io.uncache.req.bits.id := entryIndex.U 156e9e6cd09SYanqin Li io.uncache.req.bits.instrtype := DontCare 157e9e6cd09SYanqin Li io.uncache.req.bits.replayCarry := DontCare 158e9e6cd09SYanqin Li io.uncache.req.bits.atomic := req.atomic 159e9e6cd09SYanqin Li io.uncache.req.bits.nc := req.nc 160e9e6cd09SYanqin Li 161e9e6cd09SYanqin Li io.uncache.resp.ready := true.B 162e9e6cd09SYanqin Li 163e9e6cd09SYanqin Li /* uncahce resp */ 164e9e6cd09SYanqin Li when (io.uncache.resp.fire) { 165e9e6cd09SYanqin Li uncacheData := io.uncache.resp.bits.data 166e9e6cd09SYanqin Li nderr := io.uncache.resp.bits.nderr 167e9e6cd09SYanqin Li } 168e9e6cd09SYanqin Li 169e9e6cd09SYanqin Li /* uncahce writeback */ 170e9e6cd09SYanqin Li val selUop = req.uop 171e9e6cd09SYanqin Li val func = selUop.fuOpType 172e9e6cd09SYanqin Li val raddr = req.paddr 173e9e6cd09SYanqin Li val rdataSel = LookupTree(raddr(2, 0), List( 174e9e6cd09SYanqin Li "b000".U -> uncacheData(63, 0), 175e9e6cd09SYanqin Li "b001".U -> uncacheData(63, 8), 176e9e6cd09SYanqin Li "b010".U -> uncacheData(63, 16), 177e9e6cd09SYanqin Li "b011".U -> uncacheData(63, 24), 178e9e6cd09SYanqin Li "b100".U -> uncacheData(63, 32), 179e9e6cd09SYanqin Li "b101".U -> uncacheData(63, 40), 180e9e6cd09SYanqin Li "b110".U -> uncacheData(63, 48), 181e9e6cd09SYanqin Li "b111".U -> uncacheData(63, 56) 182e9e6cd09SYanqin Li )) 183e9e6cd09SYanqin Li val rdataPartialLoad = rdataHelper(selUop, rdataSel) 184e9e6cd09SYanqin Li 185e9e6cd09SYanqin Li io.mmioOut.valid := false.B 186e9e6cd09SYanqin Li io.mmioOut.bits := DontCare 187e9e6cd09SYanqin Li io.mmioRawData := DontCare 188e9e6cd09SYanqin Li io.ncOut.valid := false.B 189e9e6cd09SYanqin Li io.ncOut.bits := DontCare 190e9e6cd09SYanqin Li 191e9e6cd09SYanqin Li when(req.nc){ 192e9e6cd09SYanqin Li io.ncOut.valid := (uncacheState === s_wait) 193e9e6cd09SYanqin Li io.ncOut.bits := DontCare 194e9e6cd09SYanqin Li io.ncOut.bits.uop := selUop 195e9e6cd09SYanqin Li io.ncOut.bits.uop.lqIdx := req.uop.lqIdx 196e9e6cd09SYanqin Li io.ncOut.bits.uop.exceptionVec(loadAccessFault) := nderr 197e9e6cd09SYanqin Li io.ncOut.bits.data := rdataPartialLoad 198e9e6cd09SYanqin Li io.ncOut.bits.paddr := req.paddr 199e9e6cd09SYanqin Li io.ncOut.bits.vaddr := req.vaddr 200e9e6cd09SYanqin Li io.ncOut.bits.nc := true.B 201e9e6cd09SYanqin Li io.ncOut.bits.mask := Mux(req.paddr(3), req.mask(15, 8), req.mask(7, 0)) 202e9e6cd09SYanqin Li io.ncOut.bits.schedIndex := req.schedIndex 203e9e6cd09SYanqin Li io.ncOut.bits.isvec := req.isvec 204e9e6cd09SYanqin Li io.ncOut.bits.is128bit := req.is128bit 205e9e6cd09SYanqin Li io.ncOut.bits.vecActive := req.vecActive 206e9e6cd09SYanqin Li }.otherwise{ 207e9e6cd09SYanqin Li io.mmioOut.valid := (uncacheState === s_wait) 208e9e6cd09SYanqin Li io.mmioOut.bits := DontCare 209e9e6cd09SYanqin Li io.mmioOut.bits.uop := selUop 210e9e6cd09SYanqin Li io.mmioOut.bits.uop.lqIdx := req.uop.lqIdx 211e9e6cd09SYanqin Li io.mmioOut.bits.uop.exceptionVec(loadAccessFault) := nderr 212e9e6cd09SYanqin Li io.mmioOut.bits.data := rdataPartialLoad 213e9e6cd09SYanqin Li io.mmioOut.bits.debug.isMMIO := true.B 214e9e6cd09SYanqin Li io.mmioOut.bits.debug.isNC := false.B 215e9e6cd09SYanqin Li io.mmioOut.bits.debug.paddr := req.paddr 216e9e6cd09SYanqin Li io.mmioOut.bits.debug.vaddr := req.vaddr 217e9e6cd09SYanqin Li io.mmioRawData.lqData := uncacheData 218e9e6cd09SYanqin Li io.mmioRawData.uop := req.uop 219e9e6cd09SYanqin Li io.mmioRawData.addrOffset := req.paddr 220e9e6cd09SYanqin Li } 221e9e6cd09SYanqin Li 222e9e6cd09SYanqin Li io.exception.valid := writeback 223e9e6cd09SYanqin Li io.exception.bits := req 224e9e6cd09SYanqin Li io.exception.bits.uop.exceptionVec(loadAccessFault) := nderr 225e9e6cd09SYanqin Li 226e9e6cd09SYanqin Li /* debug log */ 2278b33cd30Sklin02 XSDebug(io.uncache.req.fire, 2288b33cd30Sklin02 "uncache req: pc %x addr %x data %x op %x mask %x\n", 229e9e6cd09SYanqin Li req.uop.pc, 230e9e6cd09SYanqin Li io.uncache.req.bits.addr, 231e9e6cd09SYanqin Li io.uncache.req.bits.data, 232e9e6cd09SYanqin Li io.uncache.req.bits.cmd, 233e9e6cd09SYanqin Li io.uncache.req.bits.mask 234e9e6cd09SYanqin Li ) 2358b33cd30Sklin02 XSInfo(io.ncOut.fire, 2368b33cd30Sklin02 "int load miss write to cbd robidx %d lqidx %d pc 0x%x mmio %x\n", 237e9e6cd09SYanqin Li io.ncOut.bits.uop.robIdx.asUInt, 238e9e6cd09SYanqin Li io.ncOut.bits.uop.lqIdx.asUInt, 239e9e6cd09SYanqin Li io.ncOut.bits.uop.pc, 240e9e6cd09SYanqin Li true.B 241e9e6cd09SYanqin Li ) 2428b33cd30Sklin02 XSInfo(io.mmioOut.fire, 2438b33cd30Sklin02 "int load miss write to cbd robidx %d lqidx %d pc 0x%x mmio %x\n", 244e9e6cd09SYanqin Li io.mmioOut.bits.uop.robIdx.asUInt, 245e9e6cd09SYanqin Li io.mmioOut.bits.uop.lqIdx.asUInt, 246e9e6cd09SYanqin Li io.mmioOut.bits.uop.pc, 247e9e6cd09SYanqin Li true.B 248e9e6cd09SYanqin Li ) 249e9e6cd09SYanqin Li 250e9e6cd09SYanqin Li} 251e9e6cd09SYanqin Li 252e9e6cd09SYanqin Liclass LoadQueueUncache(implicit p: Parameters) extends XSModule 253e9e6cd09SYanqin Li with HasCircularQueuePtrHelper 254e9e6cd09SYanqin Li with HasMemBlockParameters 255e9e6cd09SYanqin Li{ 256e9e6cd09SYanqin Li val io = IO(new Bundle() { 257e9e6cd09SYanqin Li /* control */ 258e9e6cd09SYanqin Li val redirect = Flipped(Valid(new Redirect)) 259e9e6cd09SYanqin Li // mmio commit 260e9e6cd09SYanqin Li val rob = Flipped(new RobLsqIO) 261e9e6cd09SYanqin Li 262e9e6cd09SYanqin Li /* transaction */ 263e9e6cd09SYanqin Li // enqueue: from ldu s3 264e9e6cd09SYanqin Li val req = Vec(LoadPipelineWidth, Flipped(Decoupled(new LqWriteBundle))) 265e9e6cd09SYanqin Li // writeback: mmio to ldu s0, s3 266e9e6cd09SYanqin Li val mmioOut = Vec(LoadPipelineWidth, DecoupledIO(new MemExuOutput)) 267e9e6cd09SYanqin Li val mmioRawData = Vec(LoadPipelineWidth, Output(new LoadDataFromLQBundle)) 268e9e6cd09SYanqin Li // writeback: nc to ldu s0--s3 269e9e6cd09SYanqin Li val ncOut = Vec(LoadPipelineWidth, Decoupled(new LsPipelineBundle)) 270e9e6cd09SYanqin Li // <=>uncache 271e9e6cd09SYanqin Li val uncache = new UncacheWordIO 272e9e6cd09SYanqin Li 273e9e6cd09SYanqin Li /* except */ 274e9e6cd09SYanqin Li // rollback from frontend when buffer is full 275e9e6cd09SYanqin Li val rollback = Output(Valid(new Redirect)) 276e9e6cd09SYanqin Li // exception generated by outer bus 277e9e6cd09SYanqin Li val exception = Valid(new LqWriteBundle) 278e9e6cd09SYanqin Li }) 279e9e6cd09SYanqin Li 280e9e6cd09SYanqin Li /****************************************************************** 281e9e6cd09SYanqin Li * Structure 282e9e6cd09SYanqin Li ******************************************************************/ 283e9e6cd09SYanqin Li val entries = Seq.tabulate(LoadUncacheBufferSize)(i => Module(new UncacheEntry(i))) 284e9e6cd09SYanqin Li 285e9e6cd09SYanqin Li val freeList = Module(new FreeList( 286e9e6cd09SYanqin Li size = LoadUncacheBufferSize, 287e9e6cd09SYanqin Li allocWidth = LoadPipelineWidth, 288e9e6cd09SYanqin Li freeWidth = 4, 289e9e6cd09SYanqin Li enablePreAlloc = true, 290e9e6cd09SYanqin Li moduleName = "LoadQueueUncache freelist" 291e9e6cd09SYanqin Li )) 292e9e6cd09SYanqin Li freeList.io := DontCare 293e9e6cd09SYanqin Li 294e9e6cd09SYanqin Li // set default IO 295e9e6cd09SYanqin Li entries.foreach { 296e9e6cd09SYanqin Li case (e) => 297e9e6cd09SYanqin Li e.io.req.valid := false.B 298e9e6cd09SYanqin Li e.io.req.bits := DontCare 299e9e6cd09SYanqin Li e.io.uncache.req.ready := false.B 300e9e6cd09SYanqin Li e.io.uncache.resp.valid := false.B 301e9e6cd09SYanqin Li e.io.uncache.resp.bits := DontCare 302e9e6cd09SYanqin Li e.io.ncOut.ready := false.B 303e9e6cd09SYanqin Li e.io.mmioOut.ready := false.B 304e9e6cd09SYanqin Li } 305e9e6cd09SYanqin Li io.uncache.req.valid := false.B 306e9e6cd09SYanqin Li io.uncache.req.bits := DontCare 307e9e6cd09SYanqin Li io.uncache.resp.ready := false.B 308e9e6cd09SYanqin Li for (w <- 0 until LoadPipelineWidth) { 309e9e6cd09SYanqin Li io.mmioOut(w).valid := false.B 310e9e6cd09SYanqin Li io.mmioOut(w).bits := DontCare 311e9e6cd09SYanqin Li io.mmioRawData(w) := DontCare 312e9e6cd09SYanqin Li io.ncOut(w).valid := false.B 313e9e6cd09SYanqin Li io.ncOut(w).bits := DontCare 314e9e6cd09SYanqin Li } 315e9e6cd09SYanqin Li 316e9e6cd09SYanqin Li 317e9e6cd09SYanqin Li /****************************************************************** 318e9e6cd09SYanqin Li * Enqueue 319e9e6cd09SYanqin Li * 320e9e6cd09SYanqin Li * s1: hold 321e9e6cd09SYanqin Li * s2: confirm enqueue and write entry 322e9e6cd09SYanqin Li * valid: no redirect, no exception, no replay, is mmio/nc 323e9e6cd09SYanqin Li * ready: freelist can allocate 324e9e6cd09SYanqin Li ******************************************************************/ 325e9e6cd09SYanqin Li 326e9e6cd09SYanqin Li val s1_req = VecInit(io.req.map(_.bits)) 327e9e6cd09SYanqin Li val s1_valid = VecInit(io.req.map(_.valid)) 328e9e6cd09SYanqin Li val s2_enqueue = Wire(Vec(LoadPipelineWidth, Bool())) 329e9e6cd09SYanqin Li io.req.zipWithIndex.foreach{ case (r, i) => 330e9e6cd09SYanqin Li r.ready := !s2_enqueue(i) || freeList.io.canAllocate(i) 331e9e6cd09SYanqin Li } 332e9e6cd09SYanqin Li 333e9e6cd09SYanqin Li // s2: enqueue 334e9e6cd09SYanqin Li val s2_req = (0 until LoadPipelineWidth).map(i => {RegEnable(s1_req(i), s1_valid(i))}) 335e9e6cd09SYanqin Li val s2_valid = (0 until LoadPipelineWidth).map(i => { 336e9e6cd09SYanqin Li RegNext(s1_valid(i)) && 337e9e6cd09SYanqin Li !s2_req(i).uop.robIdx.needFlush(RegNext(io.redirect)) && 338e9e6cd09SYanqin Li !s2_req(i).uop.robIdx.needFlush(io.redirect) 339e9e6cd09SYanqin Li }) 340e9e6cd09SYanqin Li val s2_has_exception = s2_req.map(x => ExceptionNO.selectByFu(x.uop.exceptionVec, LduCfg).asUInt.orR) 341e9e6cd09SYanqin Li val s2_need_replay = s2_req.map(_.rep_info.need_rep) 342e9e6cd09SYanqin Li 343e9e6cd09SYanqin Li for (w <- 0 until LoadPipelineWidth) { 344e9e6cd09SYanqin Li s2_enqueue(w) := s2_valid(w) && !s2_has_exception(w) && !s2_need_replay(w) && (s2_req(w).mmio || s2_req(w).nc) 345e9e6cd09SYanqin Li } 346e9e6cd09SYanqin Li 347e9e6cd09SYanqin Li val s2_enqValidVec = Wire(Vec(LoadPipelineWidth, Bool())) 348e9e6cd09SYanqin Li val s2_enqIndexVec = Wire(Vec(LoadPipelineWidth, UInt())) 349e9e6cd09SYanqin Li 350e9e6cd09SYanqin Li for (w <- 0 until LoadPipelineWidth) { 351e9e6cd09SYanqin Li freeList.io.allocateReq(w) := true.B 352e9e6cd09SYanqin Li } 353e9e6cd09SYanqin Li 354e9e6cd09SYanqin Li // freeList real-allocate 355e9e6cd09SYanqin Li for (w <- 0 until LoadPipelineWidth) { 356e9e6cd09SYanqin Li freeList.io.doAllocate(w) := s2_enqValidVec(w) 357e9e6cd09SYanqin Li } 358e9e6cd09SYanqin Li 359e9e6cd09SYanqin Li for (w <- 0 until LoadPipelineWidth) { 360e9e6cd09SYanqin Li val offset = PopCount(s2_enqueue.take(w)) 361*54b55f34SYanqin Li s2_enqValidVec(w) := s2_enqueue(w) && freeList.io.canAllocate(offset) 362e9e6cd09SYanqin Li s2_enqIndexVec(w) := freeList.io.allocateSlot(offset) 363e9e6cd09SYanqin Li } 364e9e6cd09SYanqin Li 365e9e6cd09SYanqin Li 366e9e6cd09SYanqin Li /****************************************************************** 367e9e6cd09SYanqin Li * Uncache Transaction 368e9e6cd09SYanqin Li * 369e9e6cd09SYanqin Li * 1. uncache req 370e9e6cd09SYanqin Li * 2. uncache resp 371e9e6cd09SYanqin Li * 3. writeback 372e9e6cd09SYanqin Li ******************************************************************/ 373e9e6cd09SYanqin Li private val NC_WB_MOD = NCWBPorts.length 374e9e6cd09SYanqin Li 375e9e6cd09SYanqin Li val uncacheReq = Wire(DecoupledIO(io.uncache.req.bits.cloneType)) 376e9e6cd09SYanqin Li val mmioSelect = entries.map(e => e.io.mmioSelect).reduce(_ || _) 377e9e6cd09SYanqin Li val mmioReq = Wire(DecoupledIO(io.uncache.req.bits.cloneType)) 378e9e6cd09SYanqin Li // TODO lyq: It's best to choose in robIdx order / the order in which they enter 379e9e6cd09SYanqin Li val ncReqArb = Module(new RRArbiterInit(io.uncache.req.bits.cloneType, LoadUncacheBufferSize)) 380e9e6cd09SYanqin Li 381e9e6cd09SYanqin Li val mmioOut = Wire(DecoupledIO(io.mmioOut(0).bits.cloneType)) 382e9e6cd09SYanqin Li val mmioRawData = Wire(io.mmioRawData(0).cloneType) 383e9e6cd09SYanqin Li val ncOut = Wire(chiselTypeOf(io.ncOut)) 384e9e6cd09SYanqin Li val ncOutValidVec = VecInit(entries.map(e => e.io.ncOut.valid)) 385e9e6cd09SYanqin Li val ncOutValidVecRem = SubVec.getMaskRem(ncOutValidVec, NC_WB_MOD) 386e9e6cd09SYanqin Li 387e9e6cd09SYanqin Li // init 388e9e6cd09SYanqin Li uncacheReq.valid := false.B 389e9e6cd09SYanqin Li uncacheReq.bits := DontCare 390e9e6cd09SYanqin Li mmioReq.valid := false.B 391e9e6cd09SYanqin Li mmioReq.bits := DontCare 392e9e6cd09SYanqin Li mmioOut.valid := false.B 393e9e6cd09SYanqin Li mmioOut.bits := DontCare 394e9e6cd09SYanqin Li mmioRawData := DontCare 395e9e6cd09SYanqin Li for (i <- 0 until LoadUncacheBufferSize) { 396e9e6cd09SYanqin Li ncReqArb.io.in(i).valid := false.B 397e9e6cd09SYanqin Li ncReqArb.io.in(i).bits := DontCare 398e9e6cd09SYanqin Li } 399e9e6cd09SYanqin Li for (i <- 0 until LoadPipelineWidth) { 400e9e6cd09SYanqin Li ncOut(i).valid := false.B 401e9e6cd09SYanqin Li ncOut(i).bits := DontCare 402e9e6cd09SYanqin Li } 403e9e6cd09SYanqin Li 404e9e6cd09SYanqin Li entries.zipWithIndex.foreach { 405e9e6cd09SYanqin Li case (e, i) => 406e9e6cd09SYanqin Li // enqueue 407e9e6cd09SYanqin Li for (w <- 0 until LoadPipelineWidth) { 408e9e6cd09SYanqin Li when (s2_enqValidVec(w) && (i.U === s2_enqIndexVec(w))) { 409e9e6cd09SYanqin Li e.io.req.valid := true.B 410e9e6cd09SYanqin Li e.io.req.bits := s2_req(w) 411e9e6cd09SYanqin Li } 412e9e6cd09SYanqin Li } 413e9e6cd09SYanqin Li 414e9e6cd09SYanqin Li // control 415e9e6cd09SYanqin Li e.io.redirect <> io.redirect 416e9e6cd09SYanqin Li e.io.rob <> io.rob 417e9e6cd09SYanqin Li 418e9e6cd09SYanqin Li // uncache req, writeback 419e9e6cd09SYanqin Li when (e.io.mmioSelect) { 420e9e6cd09SYanqin Li mmioReq.valid := e.io.uncache.req.valid 421e9e6cd09SYanqin Li mmioReq.bits := e.io.uncache.req.bits 422e9e6cd09SYanqin Li e.io.uncache.req.ready := mmioReq.ready 423e9e6cd09SYanqin Li 424e9e6cd09SYanqin Li e.io.mmioOut.ready := mmioOut.ready 425e9e6cd09SYanqin Li mmioOut.valid := e.io.mmioOut.valid 426e9e6cd09SYanqin Li mmioOut.bits := e.io.mmioOut.bits 427e9e6cd09SYanqin Li mmioRawData := e.io.mmioRawData 428e9e6cd09SYanqin Li 429e9e6cd09SYanqin Li }.otherwise{ 430e9e6cd09SYanqin Li ncReqArb.io.in(i).valid := e.io.uncache.req.valid 431e9e6cd09SYanqin Li ncReqArb.io.in(i).bits := e.io.uncache.req.bits 432e9e6cd09SYanqin Li e.io.uncache.req.ready := ncReqArb.io.in(i).ready 433e9e6cd09SYanqin Li 434e9e6cd09SYanqin Li (0 until NC_WB_MOD).map { w => 435e9e6cd09SYanqin Li val (idx, ncOutValid) = PriorityEncoderWithFlag(ncOutValidVecRem(w)) 436e9e6cd09SYanqin Li val port = NCWBPorts(w) 437e9e6cd09SYanqin Li when((i.U === idx) && ncOutValid) { 438e9e6cd09SYanqin Li ncOut(port).valid := ncOutValid 439e9e6cd09SYanqin Li ncOut(port).bits := e.io.ncOut.bits 440e9e6cd09SYanqin Li e.io.ncOut.ready := ncOut(port).ready 441e9e6cd09SYanqin Li } 442e9e6cd09SYanqin Li } 443e9e6cd09SYanqin Li 444e9e6cd09SYanqin Li } 445e9e6cd09SYanqin Li 446e9e6cd09SYanqin Li // uncache resp 447e9e6cd09SYanqin Li when (i.U === io.uncache.resp.bits.id) { 448e9e6cd09SYanqin Li e.io.uncache.resp <> io.uncache.resp 449e9e6cd09SYanqin Li } 450e9e6cd09SYanqin Li 451e9e6cd09SYanqin Li } 452e9e6cd09SYanqin Li 453e9e6cd09SYanqin Li mmioReq.ready := false.B 454e9e6cd09SYanqin Li ncReqArb.io.out.ready := false.B 455e9e6cd09SYanqin Li when(mmioSelect){ 456e9e6cd09SYanqin Li uncacheReq <> mmioReq 457e9e6cd09SYanqin Li }.otherwise{ 458e9e6cd09SYanqin Li uncacheReq <> ncReqArb.io.out 459e9e6cd09SYanqin Li } 460e9e6cd09SYanqin Li 461e9e6cd09SYanqin Li // uncache Request 462e9e6cd09SYanqin Li AddPipelineReg(uncacheReq, io.uncache.req, false.B) 463e9e6cd09SYanqin Li 464e9e6cd09SYanqin Li // uncache Writeback 465e9e6cd09SYanqin Li AddPipelineReg(mmioOut, io.mmioOut(UncacheWBPort), false.B) 466e9e6cd09SYanqin Li io.mmioRawData(UncacheWBPort) := RegEnable(mmioRawData, mmioOut.fire) 467e9e6cd09SYanqin Li 468e9e6cd09SYanqin Li (0 until LoadPipelineWidth).foreach { i => AddPipelineReg(ncOut(i), io.ncOut(i), false.B) } 469e9e6cd09SYanqin Li 470e9e6cd09SYanqin Li // uncache exception 471e9e6cd09SYanqin Li io.exception.valid := Cat(entries.map(_.io.exception.valid)).orR 472e9e6cd09SYanqin Li io.exception.bits := ParallelPriorityMux(entries.map(e => 473e9e6cd09SYanqin Li (e.io.exception.valid, e.io.exception.bits) 474e9e6cd09SYanqin Li )) 475e9e6cd09SYanqin Li 476e9e6cd09SYanqin Li // rob 477e9e6cd09SYanqin Li for (i <- 0 until LoadPipelineWidth) { 478e9e6cd09SYanqin Li io.rob.mmio(i) := RegNext(s1_valid(i) && s1_req(i).mmio) 479e9e6cd09SYanqin Li io.rob.uop(i) := RegEnable(s1_req(i).uop, s1_valid(i)) 480e9e6cd09SYanqin Li } 481e9e6cd09SYanqin Li 482e9e6cd09SYanqin Li 483e9e6cd09SYanqin Li /****************************************************************** 484e9e6cd09SYanqin Li * Deallocate 485e9e6cd09SYanqin Li ******************************************************************/ 486e9e6cd09SYanqin Li // UncacheBuffer deallocate 487e9e6cd09SYanqin Li val freeMaskVec = Wire(Vec(LoadUncacheBufferSize, Bool())) 488e9e6cd09SYanqin Li 489e9e6cd09SYanqin Li // init 490e9e6cd09SYanqin Li freeMaskVec.map(e => e := false.B) 491e9e6cd09SYanqin Li 492e9e6cd09SYanqin Li // dealloc logic 493e9e6cd09SYanqin Li entries.zipWithIndex.foreach { 494e9e6cd09SYanqin Li case (e, i) => 495e9e6cd09SYanqin Li when ((e.io.mmioSelect && e.io.mmioOut.fire) || e.io.ncOut.fire || e.io.flush) { 496e9e6cd09SYanqin Li freeMaskVec(i) := true.B 497e9e6cd09SYanqin Li } 498e9e6cd09SYanqin Li } 499e9e6cd09SYanqin Li 500e9e6cd09SYanqin Li freeList.io.free := freeMaskVec.asUInt 501e9e6cd09SYanqin Li 502e9e6cd09SYanqin Li 503e9e6cd09SYanqin Li /****************************************************************** 504e9e6cd09SYanqin Li * Uncache rollback detection 505e9e6cd09SYanqin Li * 506e9e6cd09SYanqin Li * When uncache loads enqueue, it searches uncache loads, They can not enqueue and need re-execution. 507e9e6cd09SYanqin Li * 508e9e6cd09SYanqin Li * Cycle 0: uncache enqueue. 509e9e6cd09SYanqin Li * Cycle 1: Select oldest uncache loads. 510e9e6cd09SYanqin Li * Cycle 2: Redirect Fire. 511e9e6cd09SYanqin Li * Choose the oldest load from LoadPipelineWidth oldest loads. 512e9e6cd09SYanqin Li * Prepare redirect request according to the detected rejection. 513e9e6cd09SYanqin Li * Fire redirect request (if valid) 514e9e6cd09SYanqin Li * 515e9e6cd09SYanqin Li * Load_S3 .... Load_S3 516e9e6cd09SYanqin Li * stage 0: lq lq 517e9e6cd09SYanqin Li * | | (can not enqueue) 518e9e6cd09SYanqin Li * stage 1: lq lq 519e9e6cd09SYanqin Li * | | 520e9e6cd09SYanqin Li * --------------- 521e9e6cd09SYanqin Li * | 522e9e6cd09SYanqin Li * stage 2: lq 523e9e6cd09SYanqin Li * | 524e9e6cd09SYanqin Li * rollback req 525e9e6cd09SYanqin Li * 526e9e6cd09SYanqin Li ******************************************************************/ 527e9e6cd09SYanqin Li def selectOldestRedirect(xs: Seq[Valid[Redirect]]): Vec[Bool] = { 528e9e6cd09SYanqin Li val compareVec = (0 until xs.length).map(i => (0 until i).map(j => isAfter(xs(j).bits.robIdx, xs(i).bits.robIdx))) 529e9e6cd09SYanqin Li val resultOnehot = VecInit((0 until xs.length).map(i => Cat((0 until xs.length).map(j => 530e9e6cd09SYanqin Li (if (j < i) !xs(j).valid || compareVec(i)(j) 531e9e6cd09SYanqin Li else if (j == i) xs(i).valid 532e9e6cd09SYanqin Li else !xs(j).valid || !compareVec(j)(i)) 533e9e6cd09SYanqin Li )).andR)) 534e9e6cd09SYanqin Li resultOnehot 535e9e6cd09SYanqin Li } 536e9e6cd09SYanqin Li val reqNeedCheck = VecInit((0 until LoadPipelineWidth).map(w => 537e9e6cd09SYanqin Li s2_enqueue(w) && !s2_enqValidVec(w) 538e9e6cd09SYanqin Li )) 539e9e6cd09SYanqin Li val reqSelUops = VecInit(s2_req.map(_.uop)) 540e9e6cd09SYanqin Li val allRedirect = (0 until LoadPipelineWidth).map(i => { 541e9e6cd09SYanqin Li val redirect = Wire(Valid(new Redirect)) 542e9e6cd09SYanqin Li redirect.valid := reqNeedCheck(i) 543e9e6cd09SYanqin Li redirect.bits := DontCare 544e9e6cd09SYanqin Li redirect.bits.isRVC := reqSelUops(i).preDecodeInfo.isRVC 545e9e6cd09SYanqin Li redirect.bits.robIdx := reqSelUops(i).robIdx 546e9e6cd09SYanqin Li redirect.bits.ftqIdx := reqSelUops(i).ftqPtr 547e9e6cd09SYanqin Li redirect.bits.ftqOffset := reqSelUops(i).ftqOffset 548e9e6cd09SYanqin Li redirect.bits.level := RedirectLevel.flush 549e9e6cd09SYanqin Li redirect.bits.cfiUpdate.target := reqSelUops(i).pc // TODO: check if need pc 550e9e6cd09SYanqin Li redirect.bits.debug_runahead_checkpoint_id := reqSelUops(i).debugInfo.runahead_checkpoint_id 551e9e6cd09SYanqin Li redirect 552e9e6cd09SYanqin Li }) 553e9e6cd09SYanqin Li val oldestOneHot = selectOldestRedirect(allRedirect) 554e9e6cd09SYanqin Li val oldestRedirect = Mux1H(oldestOneHot, allRedirect) 555e9e6cd09SYanqin Li val lastCycleRedirect = Wire(Valid(new Redirect)) 556e9e6cd09SYanqin Li lastCycleRedirect.valid := RegNext(io.redirect.valid) 557e9e6cd09SYanqin Li lastCycleRedirect.bits := RegEnable(io.redirect.bits, io.redirect.valid) 558e9e6cd09SYanqin Li val lastLastCycleRedirect = Wire(Valid(new Redirect)) 559e9e6cd09SYanqin Li lastLastCycleRedirect.valid := RegNext(lastCycleRedirect.valid) 560e9e6cd09SYanqin Li lastLastCycleRedirect.bits := RegEnable(lastCycleRedirect.bits, lastCycleRedirect.valid) 561e9e6cd09SYanqin Li io.rollback.valid := GatedValidRegNext(oldestRedirect.valid && 562e9e6cd09SYanqin Li !oldestRedirect.bits.robIdx.needFlush(io.redirect) && 563e9e6cd09SYanqin Li !oldestRedirect.bits.robIdx.needFlush(lastCycleRedirect) && 564e9e6cd09SYanqin Li !oldestRedirect.bits.robIdx.needFlush(lastLastCycleRedirect)) 565e9e6cd09SYanqin Li io.rollback.bits := RegEnable(oldestRedirect.bits, oldestRedirect.valid) 566e9e6cd09SYanqin Li 567e9e6cd09SYanqin Li 568e9e6cd09SYanqin Li /****************************************************************** 569e9e6cd09SYanqin Li * Perf Counter 570e9e6cd09SYanqin Li ******************************************************************/ 571e9e6cd09SYanqin Li val validCount = freeList.io.validCount 572e9e6cd09SYanqin Li val allowEnqueue = !freeList.io.empty 573e9e6cd09SYanqin Li QueuePerf(LoadUncacheBufferSize, validCount, !allowEnqueue) 574e9e6cd09SYanqin Li 575e9e6cd09SYanqin Li XSPerfAccumulate("mmio_uncache_req", io.uncache.req.fire && !io.uncache.req.bits.nc) 576e9e6cd09SYanqin Li XSPerfAccumulate("mmio_writeback_success", io.mmioOut(0).fire) 577e9e6cd09SYanqin Li XSPerfAccumulate("mmio_writeback_blocked", io.mmioOut(0).valid && !io.mmioOut(0).ready) 578e9e6cd09SYanqin Li XSPerfAccumulate("nc_uncache_req", io.uncache.req.fire && io.uncache.req.bits.nc) 579e9e6cd09SYanqin Li XSPerfAccumulate("nc_writeback_success", io.ncOut(0).fire) 580e9e6cd09SYanqin Li XSPerfAccumulate("nc_writeback_blocked", io.ncOut(0).valid && !io.ncOut(0).ready) 581e9e6cd09SYanqin Li XSPerfAccumulate("uncache_full_rollback", io.rollback.valid) 582e9e6cd09SYanqin Li 583e9e6cd09SYanqin Li val perfEvents: Seq[(String, UInt)] = Seq( 584e9e6cd09SYanqin Li ("mmio_uncache_req", io.uncache.req.fire && !io.uncache.req.bits.nc), 585e9e6cd09SYanqin Li ("mmio_writeback_success", io.mmioOut(0).fire), 586e9e6cd09SYanqin Li ("mmio_writeback_blocked", io.mmioOut(0).valid && !io.mmioOut(0).ready), 587e9e6cd09SYanqin Li ("nc_uncache_req", io.uncache.req.fire && io.uncache.req.bits.nc), 588e9e6cd09SYanqin Li ("nc_writeback_success", io.ncOut(0).fire), 589e9e6cd09SYanqin Li ("nc_writeback_blocked", io.ncOut(0).valid && !io.ncOut(0).ready), 590e9e6cd09SYanqin Li ("uncache_full_rollback", io.rollback.valid) 591e9e6cd09SYanqin Li ) 592e9e6cd09SYanqin Li // end 593e9e6cd09SYanqin Li} 594