xref: /XiangShan/src/main/scala/xiangshan/mem/lsqueue/LoadQueueData.scala (revision a266fd760946e285e90980eccf1f5400529724be)
17057673cSWilliam Wangpackage xiangshan.mem
27057673cSWilliam Wang
37057673cSWilliam Wangimport chisel3._
47057673cSWilliam Wangimport chisel3.util._
57057673cSWilliam Wangimport utils._
67057673cSWilliam Wangimport xiangshan._
77057673cSWilliam Wangimport xiangshan.cache._
87057673cSWilliam Wangimport xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants}
97057673cSWilliam Wangimport xiangshan.backend.LSUOpType
107057673cSWilliam Wangimport xiangshan.mem._
117057673cSWilliam Wangimport xiangshan.backend.roq.RoqPtr
127057673cSWilliam Wang
137057673cSWilliam Wangclass LQDataEntry extends XSBundle {
147057673cSWilliam Wang  // val vaddr = UInt(VAddrBits.W)
157057673cSWilliam Wang  val paddr = UInt(PAddrBits.W)
167057673cSWilliam Wang  val mask = UInt(8.W)
177057673cSWilliam Wang  val data = UInt(XLEN.W)
187057673cSWilliam Wang  val exception = UInt(16.W) // TODO: opt size
197057673cSWilliam Wang  val fwdMask = Vec(8, Bool())
207057673cSWilliam Wang}
217057673cSWilliam Wang
227057673cSWilliam Wang
237d91f790SWilliam Wangclass LoadQueueData(size: Int, wbNumRead: Int, wbNumWrite: Int) extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper {
247057673cSWilliam Wang  val io = IO(new Bundle() {
257d91f790SWilliam Wang    val wb = new Bundle() {
267d91f790SWilliam Wang      val wen = Vec(wbNumWrite, Input(Bool()))
277d91f790SWilliam Wang      val waddr = Input(Vec(wbNumWrite, UInt(log2Up(size).W)))
287d91f790SWilliam Wang      val wdata = Input(Vec(wbNumWrite, new LQDataEntry))
297d91f790SWilliam Wang      val raddr = Input(Vec(wbNumRead, UInt(log2Up(size).W)))
307d91f790SWilliam Wang      val rdata = Output(Vec(wbNumRead, new LQDataEntry))
317d91f790SWilliam Wang    }
327057673cSWilliam Wang    val uncache = new Bundle() {
337057673cSWilliam Wang      val wen = Input(Bool())
347d91f790SWilliam Wang      val waddr = Input(UInt(log2Up(size).W))
357d91f790SWilliam Wang      val wdata = Input(UInt(XLEN.W)) // only write back uncache data
367d91f790SWilliam Wang      val raddr = Input(UInt(log2Up(size).W))
377d91f790SWilliam Wang      val rdata = Output(new LQDataEntry)
387057673cSWilliam Wang    }
397057673cSWilliam Wang    val refill = new Bundle() {
407d91f790SWilliam Wang      val valid = Input(Bool())
417d91f790SWilliam Wang      val paddr = Input(UInt(PAddrBits.W))
427057673cSWilliam Wang      val data = Input(UInt((cfg.blockBytes * 8).W))
437d91f790SWilliam Wang      val refillMask = Input(Vec(size, Bool()))
447d91f790SWilliam Wang      val matchMask = Output(Vec(size, Bool()))
457057673cSWilliam Wang    }
467d91f790SWilliam Wang    val violation = Vec(StorePipelineWidth, new Bundle() {
477d91f790SWilliam Wang      val paddr = Input(UInt(PAddrBits.W))
487d91f790SWilliam Wang      val mask = Input(UInt(8.W))
497d91f790SWilliam Wang      val violationMask = Output(Vec(size, Bool()))
507d91f790SWilliam Wang    })
517d91f790SWilliam Wang    val debug = Output(Vec(size, new LQDataEntry))
527057673cSWilliam Wang
537d91f790SWilliam Wang    def wbWrite(channel: Int, waddr: UInt, wdata: LQDataEntry): Unit = {
547d91f790SWilliam Wang      require(channel < wbNumWrite && wbNumWrite >= 0)
557057673cSWilliam Wang      // need extra "this.wb(channel).wen := true.B"
567d91f790SWilliam Wang      this.wb.waddr(channel) := waddr
577d91f790SWilliam Wang      this.wb.wdata(channel) := wdata
587057673cSWilliam Wang    }
597057673cSWilliam Wang
607d91f790SWilliam Wang    def uncacheWrite(waddr: UInt, wdata: UInt): Unit = {
617057673cSWilliam Wang      // need extra "this.uncache.wen := true.B"
627d91f790SWilliam Wang      this.uncache.waddr := waddr
637057673cSWilliam Wang      this.uncache.wdata := wdata
647057673cSWilliam Wang    }
657057673cSWilliam Wang
667057673cSWilliam Wang    // def refillWrite(ldIdx: Int): Unit = {
677057673cSWilliam Wang    // }
687057673cSWilliam Wang    // use "this.refill.wen(ldIdx) := true.B" instead
697057673cSWilliam Wang  })
707057673cSWilliam Wang
717057673cSWilliam Wang  val data = Reg(Vec(size, new LQDataEntry))
727057673cSWilliam Wang
73*a266fd76SWilliam Wang  // read data
74*a266fd76SWilliam Wang  (0 until wbNumRead).map(i => {
75*a266fd76SWilliam Wang    io.wb.rdata(i) := data(io.wb.raddr(i))
76*a266fd76SWilliam Wang  })
77*a266fd76SWilliam Wang
78*a266fd76SWilliam Wang  io.uncache.rdata := data(io.uncache.raddr)
79*a266fd76SWilliam Wang
807057673cSWilliam Wang  // writeback to lq/sq
817d91f790SWilliam Wang  (0 until wbNumWrite).map(i => {
827d91f790SWilliam Wang    when(io.wb.wen(i)){
837d91f790SWilliam Wang      data(io.wb.waddr(i)) := io.wb.wdata(i)
847057673cSWilliam Wang    }
857057673cSWilliam Wang  })
867057673cSWilliam Wang
877057673cSWilliam Wang  when(io.uncache.wen){
887d91f790SWilliam Wang    data(io.uncache.waddr).data := io.uncache.wdata
897057673cSWilliam Wang  }
907057673cSWilliam Wang
917057673cSWilliam Wang  // refill missed load
927057673cSWilliam Wang  def mergeRefillData(refill: UInt, fwd: UInt, fwdMask: UInt): UInt = {
937057673cSWilliam Wang    val res = Wire(Vec(8, UInt(8.W)))
947057673cSWilliam Wang    (0 until 8).foreach(i => {
957057673cSWilliam Wang      res(i) := Mux(fwdMask(i), fwd(8 * (i + 1) - 1, 8 * i), refill(8 * (i + 1) - 1, 8 * i))
967057673cSWilliam Wang    })
977057673cSWilliam Wang    res.asUInt
987057673cSWilliam Wang  }
997057673cSWilliam Wang
1007057673cSWilliam Wang  // split dcache result into words
1017057673cSWilliam Wang  val words = VecInit((0 until blockWords) map { i => io.refill.data(DataBits * (i + 1) - 1, DataBits * i)})
1027057673cSWilliam Wang
1037d91f790SWilliam Wang  // gen paddr match mask
1047057673cSWilliam Wang  (0 until size).map(i => {
1057d91f790SWilliam Wang    io.refill.matchMask(i) := get_block_addr(data(i).paddr) === get_block_addr(io.refill.paddr)
1067d91f790SWilliam Wang  })
1077d91f790SWilliam Wang
1087d91f790SWilliam Wang  // refill data according to matchMask, refillMask and refill.valid
1097d91f790SWilliam Wang  (0 until size).map(i => {
1107d91f790SWilliam Wang    when(io.refill.valid && io.refill.matchMask(i) && io.refill.refillMask(i)){
1117057673cSWilliam Wang      val refillData = words(get_word(data(i).paddr))
1127057673cSWilliam Wang      data(i).data := mergeRefillData(refillData, data(i).data.asUInt, data(i).fwdMask.asUInt)
1137057673cSWilliam Wang      XSDebug("miss resp: pos %d addr %x data %x + %x(%b)\n", i.U, data(i).paddr, refillData, data(i).data.asUInt, data(i).fwdMask.asUInt)
1147057673cSWilliam Wang    }
1157057673cSWilliam Wang  })
1167057673cSWilliam Wang
1177d91f790SWilliam Wang  // mem access violation check, gen violationMask
1187d91f790SWilliam Wang  (0 until StorePipelineWidth).map(i => {
1197d91f790SWilliam Wang    io.violation(i).violationMask := VecInit((0 until size).map(j => {
1207d91f790SWilliam Wang      val addrMatch = io.violation(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
1217d91f790SWilliam Wang      val violationVec = (0 until 8).map(k => data(j).mask(k) && io.violation(i).mask(k))
1227d91f790SWilliam Wang      Cat(violationVec).orR() && addrMatch
1237d91f790SWilliam Wang    }))
1247d91f790SWilliam Wang  })
1257d91f790SWilliam Wang
1267d91f790SWilliam Wang  // debug data read
1277d91f790SWilliam Wang  io.debug := data
1287057673cSWilliam Wang}
129