Lsroq.scala 32.8 KB
Newer Older
Y
Yinan Xu 已提交
1
package xiangshan.mem
W
William Wang 已提交
2 3 4

import chisel3._
import chisel3.util._
5
import utils._
Y
Yinan Xu 已提交
6 7
import xiangshan._
import xiangshan.cache._
8
import xiangshan.cache.{DCacheWordIO, DCacheLineIO, TlbRequestIO, MemoryOpConstants}
9
import xiangshan.backend.LSUOpType
L
linjiawei 已提交
10
import xiangshan.backend.fu.fpu.boxF32ToF64
Y
Yinan Xu 已提交
11
import xiangshan.backend.roq.RoqPtr
W
William Wang 已提交
12 13

class LsRoqEntry extends XSBundle {
W
William Wang 已提交
14
  val vaddr = UInt(VAddrBits.W) // TODO: need opt
W
William Wang 已提交
15 16
  val paddr = UInt(PAddrBits.W)
  val op = UInt(6.W)
W
William Wang 已提交
17
  val mask = UInt(8.W)
W
William Wang 已提交
18
  val data = UInt(XLEN.W)
19
  val exception = UInt(16.W) // TODO: opt size
W
William Wang 已提交
20
  val mmio = Bool()
21 22
  val fwdMask = Vec(8, Bool())
  val fwdData = Vec(8, UInt(8.W))
W
William Wang 已提交
23 24
}

25 26 27 28 29 30
// inflight miss block reqs
class InflightBlockInfo extends XSBundle {
  val block_addr = UInt(PAddrBits.W)
  val valid = Bool()
}

Y
Yinan Xu 已提交
31
// Load/Store Roq (Lsroq) for XiangShan Out of Order LSU
Y
Yinan Xu 已提交
32
class Lsroq extends XSModule with HasDCacheParameters with HasCircularQueuePtrHelper{
W
William Wang 已提交
33 34
  val io = IO(new Bundle() {
    val dp1Req = Vec(RenameWidth, Flipped(DecoupledIO(new MicroOp)))
Y
Yinan Xu 已提交
35
    val lsroqIdxs = Output(Vec(RenameWidth, UInt(LsroqIdxWidth.W)))
36
    val oldestStore = Output(Valid(new RoqPtr))
W
William Wang 已提交
37
    val brqRedirect = Input(Valid(new Redirect))
W
William Wang 已提交
38 39
    val loadIn = Vec(LoadPipelineWidth, Flipped(Valid(new LsPipelineBundle)))
    val storeIn = Vec(StorePipelineWidth, Flipped(Valid(new LsPipelineBundle)))
40
    val sbuffer = Vec(StorePipelineWidth, Decoupled(new DCacheWordReq))
W
William Wang 已提交
41 42
    val ldout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store
    val stout = Vec(2, DecoupledIO(new ExuOutput)) // writeback store
W
William Wang 已提交
43
    val forward = Vec(LoadPipelineWidth, Flipped(new LoadForwardQueryIO))
44
    val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit)))
W
William Wang 已提交
45
    val rollback = Output(Valid(new Redirect))
46 47
    val dcache = new DCacheLineIO
    val uncache = new DCacheWordIO
Y
Yinan Xu 已提交
48
    val roqDeqPtr = Input(new RoqPtr)
49
    val exceptionAddr = new ExceptionAddrIO
50
    // val refill = Flipped(Valid(new DCacheLineReq ))
W
William Wang 已提交
51
  })
52
  
Y
Yinan Xu 已提交
53 54 55 56 57 58 59 60
  val uop = Reg(Vec(LsroqSize, new MicroOp))
  val data = Reg(Vec(LsroqSize, new LsRoqEntry))
  val allocated = RegInit(VecInit(List.fill(LsroqSize)(false.B))) // lsroq entry has been allocated
  val valid = RegInit(VecInit(List.fill(LsroqSize)(false.B))) // data is valid
  val writebacked = RegInit(VecInit(List.fill(LsroqSize)(false.B))) // inst has been writebacked to CDB
  val commited = Reg(Vec(LsroqSize, Bool())) // inst has been writebacked to CDB
  val store = Reg(Vec(LsroqSize, Bool())) // inst is a store inst
  val miss = Reg(Vec(LsroqSize, Bool())) // load inst missed, waiting for miss queue to accept miss request
W
William Wang 已提交
61 62
  val listening = Reg(Vec(LsroqSize, Bool())) // waiting for refill result
  val pending = Reg(Vec(LsroqSize, Bool())) // mmio pending: inst is an mmio inst, it will not be executed until it reachs the end of roq
63
  
Y
Yinan Xu 已提交
64 65 66 67
  val ringBufferHeadExtended = RegInit(0.U(LsroqIdxWidth.W))
  val ringBufferTailExtended = RegInit(0.U(LsroqIdxWidth.W))
  val ringBufferHead = ringBufferHeadExtended(InnerLsroqIdxWidth - 1, 0)
  val ringBufferTail = ringBufferTailExtended(InnerLsroqIdxWidth - 1, 0)
68 69 70
  val ringBufferSameFlag = ringBufferHeadExtended(InnerLsroqIdxWidth) === ringBufferTailExtended(InnerLsroqIdxWidth)
  val ringBufferEmpty = ringBufferHead === ringBufferTail && ringBufferSameFlag
  val ringBufferFull = ringBufferHead === ringBufferTail && !ringBufferSameFlag
W
William Wang 已提交
71
  val ringBufferAllowin = !ringBufferFull
72
  
73 74 75
  val storeCommit = (0 until CommitWidth).map(i => io.commits(i).valid && !io.commits(i).bits.isWalk && io.commits(i).bits.uop.ctrl.commitType === CommitType.STORE)
  val loadCommit = (0 until CommitWidth).map(i => io.commits(i).valid && !io.commits(i).bits.isWalk && io.commits(i).bits.uop.ctrl.commitType === CommitType.LOAD)
  val mcommitIdx = (0 until CommitWidth).map(i => io.commits(i).bits.uop.lsroqIdx(InnerLsroqIdxWidth-1,0))
76 77 78 79 80 81

  val tailMask = (((1.U((LsroqSize + 1).W)) << ringBufferTail).asUInt - 1.U)(LsroqSize - 1, 0)
  val headMask = (((1.U((LsroqSize + 1).W)) << ringBufferHead).asUInt - 1.U)(LsroqSize - 1, 0)
  val enqDeqMask1 = tailMask ^ headMask
  val enqDeqMask = Mux(ringBufferSameFlag, enqDeqMask1, ~enqDeqMask1)

82
  // TODO: misc arbitor
83

W
William Wang 已提交
84 85 86 87
  // Enqueue at dispatch
  val validDispatch = VecInit((0 until RenameWidth).map(io.dp1Req(_).valid)).asUInt
  XSDebug("(ready, valid): ")
  for (i <- 0 until RenameWidth) {
L
LinJiawei 已提交
88
    val offset = if (i == 0) 0.U else PopCount(validDispatch(i - 1, 0))
Y
Yinan Xu 已提交
89 90
    val lsroqIdx = ringBufferHeadExtended + offset
    val index = lsroqIdx(InnerLsroqIdxWidth - 1, 0)
L
LinJiawei 已提交
91
    when(io.dp1Req(i).fire()) {
Y
Yinan Xu 已提交
92 93 94 95 96 97 98 99 100 101
      uop(index) := io.dp1Req(i).bits
      allocated(index) := true.B
      valid(index) := false.B
      writebacked(index) := false.B
      commited(index) := false.B
      store(index) := false.B
      miss(index) := false.B
      listening(index) := false.B
      pending(index) := false.B
      // data(index).bwdMask := 0.U(8.W).asBools
W
William Wang 已提交
102
    }
L
LinJiawei 已提交
103
    if (i == 0) {
Y
Yinan Xu 已提交
104
      io.dp1Req(i).ready := ringBufferAllowin && !allocated(index)
L
LinJiawei 已提交
105
    } else {
Y
Yinan Xu 已提交
106
      io.dp1Req(i).ready := ringBufferAllowin && !allocated(index) && io.dp1Req(i - 1).ready
107
    }
Y
Yinan Xu 已提交
108
    io.lsroqIdxs(i) := lsroqIdx
W
William Wang 已提交
109 110 111 112 113
    XSDebug(false, true.B, "(%d, %d) ", io.dp1Req(i).ready, io.dp1Req(i).valid)
  }
  XSDebug(false, true.B, "\n")

  val firedDispatch = VecInit((0 until CommitWidth).map(io.dp1Req(_).fire())).asUInt
L
LinJiawei 已提交
114
  when(firedDispatch.orR) {
W
William Wang 已提交
115
    ringBufferHeadExtended := ringBufferHeadExtended + PopCount(firedDispatch)
Y
Yinan Xu 已提交
116
    XSInfo("dispatched %d insts to lsroq\n", PopCount(firedDispatch))
W
William Wang 已提交
117 118 119 120
  }

  // writeback load
  (0 until LoadPipelineWidth).map(i => {
L
LinJiawei 已提交
121 122
    when(io.loadIn(i).fire()) {
      when(io.loadIn(i).bits.miss) {
123
        XSInfo(io.loadIn(i).valid, "load miss write to lsroq idx %d pc 0x%x vaddr %x paddr %x data %x mask %x forwardData %x forwardMask: %x mmio %x roll %x exc %x\n",
Y
Yinan Xu 已提交
124
          io.loadIn(i).bits.uop.lsroqIdx,
W
William Wang 已提交
125 126 127 128
          io.loadIn(i).bits.uop.cf.pc,
          io.loadIn(i).bits.vaddr,
          io.loadIn(i).bits.paddr,
          io.loadIn(i).bits.data,
129 130 131
          io.loadIn(i).bits.mask,
          io.loadIn(i).bits.forwardData.asUInt,
          io.loadIn(i).bits.forwardMask.asUInt,
W
William Wang 已提交
132
          io.loadIn(i).bits.mmio,
133 134 135 136 137
          io.loadIn(i).bits.rollback,
          io.loadIn(i).bits.uop.cf.exceptionVec.asUInt
          )
        }.otherwise {
          XSInfo(io.loadIn(i).valid, "load hit write to cbd idx %d pc 0x%x vaddr %x paddr %x data %x mask %x forwardData %x forwardMask: %x mmio %x roll %x exc %x\n",
Y
Yinan Xu 已提交
138
          io.loadIn(i).bits.uop.lsroqIdx,
139 140 141 142
          io.loadIn(i).bits.uop.cf.pc,
          io.loadIn(i).bits.vaddr,
          io.loadIn(i).bits.paddr,
          io.loadIn(i).bits.data,
143 144 145
          io.loadIn(i).bits.mask,
          io.loadIn(i).bits.forwardData.asUInt,
          io.loadIn(i).bits.forwardMask.asUInt,
146
          io.loadIn(i).bits.mmio,
147 148 149 150 151 152 153 154
          io.loadIn(i).bits.rollback,
          io.loadIn(i).bits.uop.cf.exceptionVec.asUInt
          )
        }
        valid(io.loadIn(i).bits.uop.lsroqIdx) := !io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio
        writebacked(io.loadIn(i).bits.uop.lsroqIdx) := !io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio
        // allocated(io.loadIn(i).bits.uop.lsroqIdx) := io.loadIn(i).bits.miss // if hit, lsroq entry can be recycled
        data(io.loadIn(i).bits.uop.lsroqIdx).paddr := io.loadIn(i).bits.paddr
W
William Wang 已提交
155
        data(io.loadIn(i).bits.uop.lsroqIdx).vaddr := io.loadIn(i).bits.vaddr
156 157 158 159 160 161
        data(io.loadIn(i).bits.uop.lsroqIdx).mask := io.loadIn(i).bits.mask
        data(io.loadIn(i).bits.uop.lsroqIdx).data := io.loadIn(i).bits.data // for mmio / misc / debug
        data(io.loadIn(i).bits.uop.lsroqIdx).mmio := io.loadIn(i).bits.mmio
        data(io.loadIn(i).bits.uop.lsroqIdx).fwdMask := io.loadIn(i).bits.forwardMask
        data(io.loadIn(i).bits.uop.lsroqIdx).fwdData := io.loadIn(i).bits.forwardData
        data(io.loadIn(i).bits.uop.lsroqIdx).exception := io.loadIn(i).bits.uop.cf.exceptionVec.asUInt
162 163 164
        val dcacheMissed = io.loadIn(i).bits.miss && !io.loadIn(i).bits.mmio
        miss(io.loadIn(i).bits.uop.lsroqIdx) := dcacheMissed
        listening(io.loadIn(i).bits.uop.lsroqIdx) := dcacheMissed
165 166
        store(io.loadIn(i).bits.uop.lsroqIdx) := false.B
        pending(io.loadIn(i).bits.uop.lsroqIdx) := io.loadIn(i).bits.mmio
167
      }
168
    })
169 170 171 172 173 174

    // find first store req that has not been writebacked
    val storeNotWritebacked = VecInit((0 until LsroqSize).map(i => store(i) && !writebacked(i)))
    val firstStore = getFirstOne(storeNotWritebacked, tailMask)
    io.oldestStore.valid := false.B
    io.oldestStore.bits := DontCare
175 176 177 178 179
    // writeback store
    (0 until StorePipelineWidth).map(i => {
      when(io.storeIn(i).fire()) {
        valid(io.storeIn(i).bits.uop.lsroqIdx) := !io.storeIn(i).bits.mmio
        data(io.storeIn(i).bits.uop.lsroqIdx).paddr := io.storeIn(i).bits.paddr
W
William Wang 已提交
180
        data(io.storeIn(i).bits.uop.lsroqIdx).vaddr := io.storeIn(i).bits.vaddr
181 182 183 184 185 186 187 188
        data(io.storeIn(i).bits.uop.lsroqIdx).mask := io.storeIn(i).bits.mask
        data(io.storeIn(i).bits.uop.lsroqIdx).data := io.storeIn(i).bits.data
        data(io.storeIn(i).bits.uop.lsroqIdx).mmio := io.storeIn(i).bits.mmio
        data(io.storeIn(i).bits.uop.lsroqIdx).exception := io.storeIn(i).bits.uop.cf.exceptionVec.asUInt
        miss(io.storeIn(i).bits.uop.lsroqIdx) := io.storeIn(i).bits.miss
        store(io.storeIn(i).bits.uop.lsroqIdx) := true.B
        pending(io.storeIn(i).bits.uop.lsroqIdx) := io.storeIn(i).bits.mmio
        XSInfo("store write to lsroq idx %d pc 0x%x vaddr %x paddr %x data %x miss %x mmio %x roll %x exc %x\n",
189 190 191 192 193 194 195 196 197
          io.storeIn(i).bits.uop.lsroqIdx(InnerLsroqIdxWidth - 1, 0),
          io.storeIn(i).bits.uop.cf.pc,
          io.storeIn(i).bits.vaddr,
          io.storeIn(i).bits.paddr,
          io.storeIn(i).bits.data,
          io.storeIn(i).bits.miss,
          io.storeIn(i).bits.mmio,
          io.storeIn(i).bits.rollback,
          io.storeIn(i).bits.uop.cf.exceptionVec.asUInt
198
        )
199 200 201 202
        when (io.storeIn(i).bits.uop.lsroqIdx(InnerLsroqIdxWidth - 1, 0) === firstStore) {
          io.oldestStore.valid := true.B
          io.oldestStore.bits := io.storeIn(i).bits.uop.roqIdx
        }
203
      }
W
William Wang 已提交
204 205
  })

W
William Wang 已提交
206
  // cache miss request
207 208 209 210
  val inflightReqs = RegInit(VecInit(Seq.fill(cfg.nLoadMissEntries)(0.U.asTypeOf(new InflightBlockInfo))))
  val inflightReqFull = inflightReqs.map(req => req.valid).reduce(_&&_)
  val reqBlockIndex = PriorityEncoder(~VecInit(inflightReqs.map(req => req.valid)).asUInt)

W
William Wang 已提交
211
  val missRefillSelVec = VecInit(
212 213 214 215 216
    (0 until LsroqSize).map{ i =>
      val inflight = inflightReqs.map(req => req.valid && req.block_addr === get_block_addr(data(i).paddr)).reduce(_||_)
      allocated(i) && miss(i) && !inflight
    })

217
  val missRefillSel = getFirstOne(missRefillSelVec, tailMask)
218
  val missRefillBlockAddr = get_block_addr(data(missRefillSel).paddr)
219 220
  io.dcache.req.valid := missRefillSelVec.asUInt.orR
  io.dcache.req.bits.cmd := MemoryOpConstants.M_XRD
221
  io.dcache.req.bits.addr := missRefillBlockAddr
222
  io.dcache.req.bits.data := DontCare
223
  io.dcache.req.bits.mask := DontCare
224

225
  io.dcache.req.bits.meta.id       := DontCare // TODO: // FIXME
226
  io.dcache.req.bits.meta.vaddr    := DontCare // data(missRefillSel).vaddr
227
  io.dcache.req.bits.meta.paddr    := missRefillBlockAddr
228 229 230
  io.dcache.req.bits.meta.uop      := uop(missRefillSel)
  io.dcache.req.bits.meta.mmio     := false.B // data(missRefillSel).mmio
  io.dcache.req.bits.meta.tlb_miss := false.B
231
  io.dcache.req.bits.meta.mask     := DontCare
232 233 234 235 236 237 238
  io.dcache.req.bits.meta.replay   := false.B

  io.dcache.resp.ready := true.B

  assert(!(data(missRefillSel).mmio && io.dcache.req.valid))

  when(io.dcache.req.fire()) {
W
William Wang 已提交
239 240
    miss(missRefillSel) := false.B
    listening(missRefillSel) := true.B
241 242 243 244 245

    // mark this block as inflight
    inflightReqs(reqBlockIndex).valid := true.B
    inflightReqs(reqBlockIndex).block_addr := missRefillBlockAddr
    assert(!inflightReqs(reqBlockIndex).valid)
W
William Wang 已提交
246 247
  }

248 249 250 251 252 253 254 255 256 257 258
  when(io.dcache.resp.fire()) {
    val inflight = inflightReqs.map(req => req.valid && req.block_addr === get_block_addr(io.dcache.resp.bits.meta.paddr)).reduce(_||_)
    assert(inflight)
    for (i <- 0 until cfg.nLoadMissEntries) {
      when (inflightReqs(i).valid && inflightReqs(i).block_addr === get_block_addr(io.dcache.resp.bits.meta.paddr)) {
        inflightReqs(i).valid := false.B
      }
    }
  }


259
  when(io.dcache.req.fire()){
Y
Yinan Xu 已提交
260 261 262 263
    XSDebug("miss req: pc:0x%x roqIdx:%d lsroqIdx:%d (p)addr:0x%x vaddr:0x%x\n",
      io.dcache.req.bits.meta.uop.cf.pc, io.dcache.req.bits.meta.uop.roqIdx.asUInt, io.dcache.req.bits.meta.uop.lsroqIdx,
      io.dcache.req.bits.addr, io.dcache.req.bits.meta.vaddr
    )
264 265 266
  }

  when(io.dcache.resp.fire()){
Y
Yinan Xu 已提交
267 268 269 270
    XSDebug("miss resp: pc:0x%x roqIdx:%d lsroqIdx:%d (p)addr:0x%x data %x\n",
      io.dcache.resp.bits.meta.uop.cf.pc, io.dcache.resp.bits.meta.uop.roqIdx.asUInt, io.dcache.resp.bits.meta.uop.lsroqIdx,
      io.dcache.resp.bits.meta.paddr, io.dcache.resp.bits.data
    )
271 272
  }

273
  // Refill 64 bit in a cycle
274
  // Refill data comes back from io.dcache.resp
275 276
  def mergeRefillData(refill: UInt, fwd: UInt, fwdMask: UInt): UInt = {
    val res = Wire(Vec(8, UInt(8.W)))
L
LinJiawei 已提交
277 278
    (0 until 8).foreach(i => {
      res(i) := Mux(fwdMask(i), fwd(8 * (i + 1) - 1, 8 * i), refill(8 * (i + 1) - 1, 8 * i))
279 280
    })
    res.asUInt
W
William Wang 已提交
281 282
  }

Y
Yinan Xu 已提交
283
  (0 until LsroqSize).map(i => {
284 285 286 287 288 289 290 291
    val blockMatch = get_block_addr(data(i).paddr) === io.dcache.resp.bits.meta.paddr
    when(allocated(i) && listening(i) && blockMatch && io.dcache.resp.fire()) {
      // split them into words
      val words = VecInit((0 until blockWords) map { i =>
        io.dcache.resp.bits.data(DataBits * (i + 1) - 1, DataBits * i)
      })

      val refillData = words(get_word(data(i).paddr))
292
      data(i).data := mergeRefillData(refillData, data(i).fwdData.asUInt, data(i).fwdMask.asUInt)
W
William Wang 已提交
293 294
      valid(i) := true.B
      listening(i) := false.B
295
      XSDebug("miss resp: pos %d addr %x data %x + %x(%b)\n", i.U, data(i).paddr, refillData, data(i).fwdData.asUInt, data(i).fwdMask.asUInt) 
W
William Wang 已提交
296 297
    }
  })
W
William Wang 已提交
298 299 300

  // writeback up to 2 missed load insts to CDB
  // just randomly pick 2 missed load (data refilled), write them back to cdb
Y
Yinan Xu 已提交
301
  val loadWbSelVec = VecInit((0 until LsroqSize).map(i => {
W
William Wang 已提交
302
    allocated(i) && valid(i) && !writebacked(i) && !store(i)
L
LinJiawei 已提交
303
  })).asUInt() // use uint instead vec to reduce verilog lines
304
  val loadWbSel = Wire(Vec(LoadPipelineWidth, UInt(log2Up(LsroqSize).W)))
L
LinJiawei 已提交
305 306 307 308
  val lselvec0 = PriorityEncoderOH(loadWbSelVec)
  val lselvec1 = PriorityEncoderOH(loadWbSelVec & (~lselvec0).asUInt)
  loadWbSel(0) := OHToUInt(lselvec0)
  loadWbSel(1) := OHToUInt(lselvec1)
309
  (0 until LoadPipelineWidth).map(i => {
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
    // data select
    val rdata = data(loadWbSel(i)).data
    val func = uop(loadWbSel(i)).ctrl.fuOpType
    val raddr = data(loadWbSel(i)).paddr
    val rdataSel = LookupTree(raddr(2, 0), List(
      "b000".U -> rdata(63, 0),
      "b001".U -> rdata(63, 8),
      "b010".U -> rdata(63, 16),
      "b011".U -> rdata(63, 24),
      "b100".U -> rdata(63, 32),
      "b101".U -> rdata(63, 40),
      "b110".U -> rdata(63, 48),
      "b111".U -> rdata(63, 56)
    ))
    val rdataPartialLoad = LookupTree(func, List(
        LSUOpType.lb   -> SignExt(rdataSel(7, 0) , XLEN),
        LSUOpType.lh   -> SignExt(rdataSel(15, 0), XLEN),
        LSUOpType.lw   -> SignExt(rdataSel(31, 0), XLEN),
L
linjiawei 已提交
328
        LSUOpType.flw  -> boxF32ToF64(rdataSel(31, 0)),
329 330 331
        LSUOpType.ld   -> SignExt(rdataSel(63, 0), XLEN),
        LSUOpType.lbu  -> ZeroExt(rdataSel(7, 0) , XLEN),
        LSUOpType.lhu  -> ZeroExt(rdataSel(15, 0), XLEN),
A
Allen 已提交
332
        LSUOpType.lwu  -> ZeroExt(rdataSel(31, 0), XLEN)
333
    ))
W
William Wang 已提交
334
    io.ldout(i).bits.uop := uop(loadWbSel(i))
335
    io.ldout(i).bits.uop.cf.exceptionVec := data(loadWbSel(i)).exception.asBools
L
LinJiawei 已提交
336
    io.ldout(i).bits.uop.lsroqIdx := loadWbSel(i)
337
    io.ldout(i).bits.data := rdataPartialLoad
L
linjiawei 已提交
338
    io.ldout(i).bits.fflags := DontCare
W
William Wang 已提交
339 340 341 342 343
    io.ldout(i).bits.redirectValid := false.B
    io.ldout(i).bits.redirect := DontCare
    io.ldout(i).bits.brUpdate := DontCare
    io.ldout(i).bits.debug.isMMIO := data(loadWbSel(i)).mmio
    io.ldout(i).valid := loadWbSelVec(loadWbSel(i))
L
LinJiawei 已提交
344
    when(io.ldout(i).fire()) {
345
      writebacked(loadWbSel(i)) := true.B
346 347 348 349 350 351 352
      XSInfo(io.loadIn(i).valid, "load miss write to cbd idx %d pc 0x%x paddr %x data %x mmio %x\n",
        io.ldout(i).bits.uop.lsroqIdx,
        io.ldout(i).bits.uop.cf.pc,
        data(loadWbSel(i)).paddr,
        data(loadWbSel(i)).data,
        data(loadWbSel(i)).mmio
      )
W
William Wang 已提交
353 354 355 356
    }
  })

  // writeback up to 2 store insts to CDB
357
  // choose the first two valid store requests from deqPtr
Y
Yinan Xu 已提交
358
  val storeWbSelVec = VecInit((0 until LsroqSize).map(i => {
W
William Wang 已提交
359
    allocated(i) && valid(i) && !writebacked(i) && store(i)
360
  }))
Y
Yinan Xu 已提交
361
  val storeWbSel = Wire(Vec(StorePipelineWidth, UInt(log2Up(LsroqSize).W)))
362
  val storeWbValid = Wire(Vec(StorePipelineWidth, Bool()))
363
  storeWbSel(0) := getFirstOne(storeWbSelVec, tailMask)
364 365
  val firstSelMask = UIntToOH(storeWbSel(0))
  val secondWbSelVec = VecInit((0 until LsroqSize).map(i => storeWbSelVec(i) && !firstSelMask(i)))
366
  storeWbSel(1) := getFirstOne(secondWbSelVec, tailMask)
367 368
  storeWbValid(0) := Cat(storeWbSelVec).orR
  storeWbValid(1) := Cat(secondWbSelVec).orR
W
William Wang 已提交
369 370

  (0 until StorePipelineWidth).map(i => {
W
William Wang 已提交
371
    io.stout(i).bits.uop := uop(storeWbSel(i))
L
LinJiawei 已提交
372
    io.stout(i).bits.uop.lsroqIdx := storeWbSel(i)
373
    io.stout(i).bits.uop.cf.exceptionVec := data(storeWbSel(i)).exception.asBools
W
William Wang 已提交
374
    io.stout(i).bits.data := data(storeWbSel(i)).data
L
linjiawei 已提交
375
    io.stout(i).bits.fflags := DontCare
W
William Wang 已提交
376 377
    io.stout(i).bits.redirectValid := false.B
    io.stout(i).bits.redirect := DontCare
L
LinJiawei 已提交
378
    io.stout(i).bits.brUpdate := DontCare
W
William Wang 已提交
379
    io.stout(i).bits.debug.isMMIO := data(storeWbSel(i)).mmio
380
    io.stout(i).valid := storeWbSelVec(storeWbSel(i)) && storeWbValid(i)
L
LinJiawei 已提交
381
    when(io.stout(i).fire()) {
W
William Wang 已提交
382 383
      writebacked(storeWbSel(i)) := true.B
    }
W
William Wang 已提交
384
  })
W
William Wang 已提交
385 386 387

  // remove retired insts from lsroq, add retired store to sbuffer

W
William Wang 已提交
388
  // move tailPtr
389 390 391
  // allocatedMask: dequeuePtr can go to the next 1-bit
  val allocatedMask = VecInit((0 until LsroqSize).map(i => allocated(i) || !enqDeqMask(i)))
  // find the first one from deqPtr (ringBufferTail)
392
  val nextTail1 = getFirstOneWithFlag(allocatedMask, tailMask, ringBufferTailExtended(InnerLsroqIdxWidth))
393 394
  val nextTail = Mux(Cat(allocatedMask).orR, nextTail1, ringBufferHeadExtended)
  ringBufferTailExtended := nextTail
W
William Wang 已提交
395 396 397

  // send commited store inst to sbuffer
  // select up to 2 writebacked store insts
398 399
  // scommitPending, scommitIn, scommitOut are for debug only
  val commitedStoreQueue = Module(new MIMOQueue(
Y
Yinan Xu 已提交
400 401
    UInt(InnerLsroqIdxWidth.W),
    entries = LsroqSize,
402 403 404 405 406 407
    inCnt = 6,
    outCnt = 2,
    mem = false,
    perf = true
  ))

W
William Wang 已提交
408 409 410 411 412 413
  // scommit counter for debugging
  val scommitPending = RegInit(0.U(log2Up(LsroqSize).W))
  val scommitIn = PopCount(VecInit(storeCommit).asUInt)
  val scommitOut = PopCount(VecInit((0 until 2).map(i => commitedStoreQueue.io.deq(i).fire())).asUInt)
  scommitPending := scommitPending + scommitIn - scommitOut

414 415
  commitedStoreQueue.io.flush := false.B

416
  // When store commited, mark it as commited (will not be influenced by redirect),
Y
Yinan Xu 已提交
417
  // then add store's lsroq ptr into commitedStoreQueue
418
  (0 until CommitWidth).map(i => {
419 420 421
    when(storeCommit(i)) {
      commited(mcommitIdx(i)) := true.B
      XSDebug("store commit %d: idx %d %x\n", i.U, mcommitIdx(i), uop(mcommitIdx(i)).cf.pc)
422
    }
423 424
    commitedStoreQueue.io.enq(i).valid := storeCommit(i)
    commitedStoreQueue.io.enq(i).bits := mcommitIdx(i)
Y
Yinan Xu 已提交
425
    // We assume commitedStoreQueue.io.enq(i).ready === true.B,
426
    // for commitedStoreQueue.size = 64
427
  })
W
William Wang 已提交
428

429 430 431 432 433 434 435 436
  // When load commited, mark it as !allocated, this entry will be recycled later
  (0 until CommitWidth).map(i => {
    when(loadCommit(i)) {
      allocated(mcommitIdx(i)) := false.B
      XSDebug("load commit %d: idx %d %x\n", i.U, mcommitIdx(i), uop(mcommitIdx(i)).cf.pc)
    }
  })

437
  // get no more than 2 commited store from storeCommitedQueue
W
William Wang 已提交
438
  // send selected store inst to sbuffer
W
William Wang 已提交
439
  (0 until 2).map(i => {
440
    val ptr = commitedStoreQueue.io.deq(i).bits
441 442
    val mmio = data(ptr).mmio
    io.sbuffer(i).valid := commitedStoreQueue.io.deq(i).valid && !mmio
443 444
    io.sbuffer(i).bits.cmd  := MemoryOpConstants.M_XWR
    io.sbuffer(i).bits.addr := data(ptr).paddr
W
William Wang 已提交
445 446
    io.sbuffer(i).bits.data := data(ptr).data
    io.sbuffer(i).bits.mask := data(ptr).mask
W
William Wang 已提交
447
    io.sbuffer(i).bits.meta          := DontCare
448 449
    io.sbuffer(i).bits.meta.tlb_miss := false.B
    io.sbuffer(i).bits.meta.uop      := uop(ptr)
450
    io.sbuffer(i).bits.meta.mmio     := mmio
451
    io.sbuffer(i).bits.meta.mask     := data(ptr).mask
W
William Wang 已提交
452

453 454 455 456
    commitedStoreQueue.io.deq(i).ready := io.sbuffer(i).fire() || mmio

    // update lsroq meta if store inst is send to sbuffer
    when(commitedStoreQueue.io.deq(i).valid && (mmio || io.sbuffer(i).ready)) {
457
      allocated(commitedStoreQueue.io.deq(i).bits) := false.B
W
William Wang 已提交
458 459 460
    }
  })

W
William Wang 已提交
461
  // load forward query
462
  // check over all lsroq entries and forward data from the first matched store
W
William Wang 已提交
463 464 465
  (0 until LoadPipelineWidth).map(i => {
    io.forward(i).forwardMask := 0.U(8.W).asBools
    io.forward(i).forwardData := DontCare
466 467 468 469 470 471

    // Compare ringBufferTail (deqPtr) and forward.lsroqIdx, we have two cases:
    // (1) if they have the same flag, we need to check range(tail, lsroqIdx)
    // (2) if they have different flags, we need to check range(tail, lsroqSize) and range(0, lsroqIdx)
    // Forward1: Mux(same_flag, range(tail, lsroqIdx), range(tail, lsroqSize))
    // Forward2: Mux(same_flag, 0.U,                   range(0, lsroqIdx)    )
472
    // i.e. forward1 is the target entries with the same flag bits and forward2 otherwise
L
LinJiawei 已提交
473 474 475 476 477
    val forwardMask1 = WireInit(VecInit(Seq.fill(8)(false.B)))
    val forwardData1 = WireInit(VecInit(Seq.fill(8)(0.U(8.W))))
    val forwardMask2 = WireInit(VecInit(Seq.fill(8)(false.B)))
    val forwardData2 = WireInit(VecInit(Seq.fill(8)(0.U(8.W))))

478 479 480 481 482
    val differentFlag = ringBufferTailExtended(InnerLsroqIdxWidth) =/= io.forward(i).lsroqIdx(InnerLsroqIdxWidth)
    val forwardMask = ((1.U((LsroqSize + 1).W)) << io.forward(i).lsroqIdx(InnerLsroqIdxWidth - 1, 0)).asUInt - 1.U
    val needForward1 = Mux(differentFlag, ~tailMask, tailMask ^ forwardMask)
    val needForward2 = Mux(differentFlag, forwardMask, 0.U(LsroqSize.W))

483 484 485 486 487 488 489
    // entry with larger index should have higher priority since it's data is younger
    for (j <- 0 until LsroqSize) {
      val needCheck = valid(j) && allocated(j) && store(j) &&
        io.forward(i).paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
      (0 until XLEN / 8).foreach(k => {
        when (needCheck && data(j).mask(k)) {
          when (needForward1(j)) {
L
LinJiawei 已提交
490 491 492
            forwardMask1(k) := true.B
            forwardData1(k) := data(j).data(8 * (k + 1) - 1, 8 * k)
          }
493 494 495 496 497 498 499
          when (needForward2(j)) {
            forwardMask2(k) := true.B
            forwardData2(k) := data(j).data(8 * (k + 1) - 1, 8 * k)
          }
          XSDebug(needForward1(j) || needForward2(j),
            p"forwarding $k-th byte ${Hexadecimal(data(j).data(8 * (k + 1) - 1, 8 * k))} " +
            p"from ptr $j pc ${Hexadecimal(uop(j).cf.pc)}\n")
500 501 502 503
        }
      })
    }

W
William Wang 已提交
504
    // merge forward lookup results
505
    // forward2 is younger than forward1 and should have higher priority
506
    (0 until XLEN / 8).map(k => {
W
William Wang 已提交
507
      io.forward(i).forwardMask(k) := forwardMask1(k) || forwardMask2(k)
508
      io.forward(i).forwardData(k) := Mux(forwardMask2(k), forwardData2(k), forwardData1(k))
W
William Wang 已提交
509
    })
W
William Wang 已提交
510 511
  })

W
William Wang 已提交
512
  // rollback check
W
William Wang 已提交
513 514
  val rollback = Wire(Vec(StorePipelineWidth, Valid(new Redirect)))

515
  def getFirstOne(mask: Vec[Bool], startMask: UInt) = {
516
    val length = mask.length
517
    val highBits = (0 until length).map(i => mask(i) & ~startMask(i))
Y
Yinan Xu 已提交
518 519
    val highBitsUint = Cat(highBits.reverse)
    PriorityEncoder(Mux(highBitsUint.orR(), highBitsUint, mask.asUInt))
520
  }
W
William Wang 已提交
521

522
  def getFirstOneWithFlag(mask: Vec[Bool], startMask: UInt, startFlag: UInt) = {
523
    val length = mask.length
524
    val highBits = (0 until length).map(i => mask(i) & ~startMask(i))
525 526 527 528 529 530
    val highBitsUint = Cat(highBits.reverse)
    val changeDirection = !highBitsUint.orR()
    val index = PriorityEncoder(Mux(!changeDirection, highBitsUint, mask.asUInt))
    Cat(startFlag ^ changeDirection, index)
  }

531 532 533 534
  def getOldestInTwo(valid: Seq[Bool], uop: Seq[MicroOp]) = {
    assert(valid.length == uop.length)
    assert(valid.length == 2)
    Mux(valid(0) && valid(1),
Y
Yinan Xu 已提交
535
      Mux(isAfter(uop(0).roqIdx, uop(1).roqIdx), uop(1), uop(0)),
536 537 538 539 540 541 542 543 544
      Mux(valid(0) && !valid(1), uop(0), uop(1)))
  }

  def getAfterMask(valid: Seq[Bool], uop: Seq[MicroOp]) = {
    assert(valid.length == uop.length)
    val length = valid.length
    (0 until length).map(i => {
      (0 until length).map(j => {
        Mux(valid(i) && valid(j),
Y
Yinan Xu 已提交
545
          isAfter(uop(i).roqIdx, uop(j).roqIdx),
546 547 548 549
          Mux(!valid(i), true.B, false.B))
      })
    })
  }
W
William Wang 已提交
550

Y
Yinan Xu 已提交
551 552 553 554 555 556 557
  def rangeMask(start: UInt, end: UInt): UInt = {
    val startMask = (1.U((LsroqSize + 1).W) << start(InnerLsroqIdxWidth - 1, 0)).asUInt - 1.U
    val endMask = (1.U((LsroqSize + 1).W) << end(InnerLsroqIdxWidth - 1, 0)).asUInt - 1.U
    val xorMask = startMask(LsroqSize - 1, 0) ^ endMask(LsroqSize - 1, 0)
    Mux(start(InnerLsroqIdxWidth) === end(InnerLsroqIdxWidth), xorMask, ~xorMask)
  }

W
William Wang 已提交
558
  // store backward query and rollback
L
LinJiawei 已提交
559 560
  //  val needCheck = Seq.fill(8)(WireInit(true.B))
  (0 until StorePipelineWidth).foreach(i => {
W
William Wang 已提交
561
    rollback(i) := DontCare
562

L
LinJiawei 已提交
563
    when(io.storeIn(i).valid) {
Y
Yinan Xu 已提交
564
      val startIndex = io.storeIn(i).bits.uop.lsroqIdx(InnerLsroqIdxWidth - 1, 0)
565 566 567 568
      val lsroqIdxMask = ((1.U((LsroqSize + 1).W) << startIndex).asUInt - 1.U)(LsroqSize - 1, 0)
      val xorMask = lsroqIdxMask ^ headMask
      val sameFlag = io.storeIn(i).bits.uop.lsroqIdx(InnerLsroqIdxWidth) === ringBufferHeadExtended(InnerLsroqIdxWidth)
      val toEnqPtrMask = Mux(sameFlag, xorMask, ~xorMask)
569
      val lsroqViolationVec = VecInit((0 until LsroqSize).map(j => {
Y
Yinan Xu 已提交
570 571
        val addrMatch = allocated(j) &&
          io.storeIn(i).bits.paddr(PAddrBits - 1, 3) === data(j).paddr(PAddrBits - 1, 3)
572
        val entryNeedCheck = toEnqPtrMask(j) && addrMatch && !store(j) && (valid(j) || listening(j) || miss(j))
Y
Yinan Xu 已提交
573 574 575
        // TODO: update refilled data
        val violationVec = (0 until 8).map(k => data(j).mask(k) && io.storeIn(i).bits.mask(k))
        Cat(violationVec).orR() && entryNeedCheck
576 577
      }))
      val lsroqViolation = lsroqViolationVec.asUInt().orR()
578
      val lsroqViolationIndex = getFirstOne(lsroqViolationVec, lsroqIdxMask)
579
      val lsroqViolationUop = uop(lsroqViolationIndex)
Y
Yinan Xu 已提交
580
      XSDebug(lsroqViolation, p"${Binary(Cat(lsroqViolationVec))}, $startIndex, $lsroqViolationIndex\n")
W
William Wang 已提交
581

W
William Wang 已提交
582
      // when l/s writeback to roq together, check if rollback is needed
583
      val wbViolationVec = VecInit((0 until LoadPipelineWidth).map(j => {
L
LinJiawei 已提交
584
        io.loadIn(j).valid &&
Y
Yinan Xu 已提交
585
          isAfter(io.loadIn(j).bits.uop.roqIdx, io.storeIn(i).bits.uop.roqIdx) &&
L
LinJiawei 已提交
586
          io.storeIn(i).bits.paddr(PAddrBits - 1, 3) === io.loadIn(j).bits.paddr(PAddrBits - 1, 3) &&
587
          (io.storeIn(i).bits.mask & io.loadIn(j).bits.mask).orR
588
      }))
Y
Yinan Xu 已提交
589
      val wbViolation = wbViolationVec.asUInt().orR()
590
      val wbViolationUop = getOldestInTwo(wbViolationVec, io.loadIn.map(_.bits.uop))
Y
Yinan Xu 已提交
591
      XSDebug(wbViolation, p"${Binary(Cat(wbViolationVec))}, $wbViolationUop\n")
L
LinJiawei 已提交
592

593 594
      // check if rollback is needed for load in l1
      val l1ViolationVec = VecInit((0 until LoadPipelineWidth).map(j => {
595
        io.forward(j).valid && // L4 valid\
Y
Yinan Xu 已提交
596
          isAfter(io.forward(j).uop.roqIdx, io.storeIn(i).bits.uop.roqIdx) &&
L
LinJiawei 已提交
597
          io.storeIn(i).bits.paddr(PAddrBits - 1, 3) === io.forward(j).paddr(PAddrBits - 1, 3) &&
598
          (io.storeIn(i).bits.mask & io.forward(j).mask).orR
599
      }))
600 601 602
      val l1Violation = l1ViolationVec.asUInt().orR()
      val l1ViolationUop = getOldestInTwo(l1ViolationVec, io.forward.map(_.uop))
      XSDebug(l1Violation, p"${Binary(Cat(l1ViolationVec))}, $l1ViolationUop\n")
603

604 605
      val rollbackValidVec = Seq(lsroqViolation, wbViolation, l1Violation)
      val rollbackUopVec = Seq(lsroqViolationUop, wbViolationUop, l1ViolationUop)
606 607 608 609 610 611 612
      rollback(i).valid := Cat(rollbackValidVec).orR
      val mask = getAfterMask(rollbackValidVec, rollbackUopVec)
      val oneAfterZero = mask(1)(0)
      val rollbackUop = Mux(oneAfterZero && mask(2)(0),
        rollbackUopVec(0),
        Mux(!oneAfterZero && mask(2)(1), rollbackUopVec(1), rollbackUopVec(2)))
      rollback(i).bits.roqIdx := rollbackUop.roqIdx - 1.U
W
William Wang 已提交
613

614 615 616
      rollback(i).bits.isReplay := true.B
      rollback(i).bits.isMisPred := false.B
      rollback(i).bits.isException := false.B
617
      rollback(i).bits.isFlushPipe := false.B
L
LinJiawei 已提交
618

619 620 621 622 623 624
      XSDebug(
        l1Violation,
        "need rollback (l4 load) pc %x roqidx %d target %x\n",
        io.storeIn(i).bits.uop.cf.pc, io.storeIn(i).bits.uop.roqIdx.asUInt, l1ViolationUop.roqIdx.asUInt
      )

L
LinJiawei 已提交
625
      XSDebug(
Y
Yinan Xu 已提交
626
        lsroqViolation,
Y
Yinan Xu 已提交
627
        "need rollback (ld wb before store) pc %x roqidx %d target %x\n",
Y
Yinan Xu 已提交
628
        io.storeIn(i).bits.uop.cf.pc, io.storeIn(i).bits.uop.roqIdx.asUInt, lsroqViolationUop.roqIdx.asUInt
L
LinJiawei 已提交
629 630 631
      )
      XSDebug(
        wbViolation,
Y
Yinan Xu 已提交
632
        "need rollback (ld/st wb together) pc %x roqidx %d target %x\n",
Y
Yinan Xu 已提交
633
        io.storeIn(i).bits.uop.cf.pc, io.storeIn(i).bits.uop.roqIdx.asUInt, wbViolationUop.roqIdx.asUInt
L
LinJiawei 已提交
634
      )
635
    }.otherwise {
L
LinJiawei 已提交
636
      rollback(i).valid := false.B
637
    }
W
William Wang 已提交
638 639
  })

L
LinJiawei 已提交
640 641 642 643 644
  def rollbackSel(a: Valid[Redirect], b: Valid[Redirect]): ValidIO[Redirect] = {
    Mux(
      a.valid,
      Mux(
        b.valid,
Y
Yinan Xu 已提交
645
        Mux(isAfter(a.bits.roqIdx, b.bits.roqIdx), b, a), // a,b both valid, sel oldest
L
LinJiawei 已提交
646 647 648 649 650 651 652
        a // sel a
      ),
      b // sel b
    )
  }

  io.rollback := ParallelOperation(rollback, rollbackSel)
W
William Wang 已提交
653

W
William Wang 已提交
654 655
  // Memory mapped IO / other uncached operations

656 657
  // setup misc mem access req
  // mask / paddr / data can be get from lsroq.data
L
linjiawei 已提交
658
  val commitType = io.commits(0).bits.uop.ctrl.commitType 
W
William Wang 已提交
659
  io.uncache.req.valid := pending(ringBufferTail) && allocated(ringBufferTail) &&
L
linjiawei 已提交
660
    (commitType === CommitType.STORE || commitType === CommitType.LOAD) && 
L
LinJiawei 已提交
661
    io.roqDeqPtr === uop(ringBufferTail).roqIdx && 
662 663
    !io.commits(0).bits.isWalk

664 665 666 667 668
  io.uncache.req.bits.cmd  := Mux(store(ringBufferTail), MemoryOpConstants.M_XWR, MemoryOpConstants.M_XRD)
  io.uncache.req.bits.addr := data(ringBufferTail).paddr 
  io.uncache.req.bits.data := data(ringBufferTail).data
  io.uncache.req.bits.mask := data(ringBufferTail).mask

669
  io.uncache.req.bits.meta.id       := DontCare // TODO: // FIXME
670 671 672 673 674 675 676 677 678 679 680
  io.uncache.req.bits.meta.vaddr    := DontCare
  io.uncache.req.bits.meta.paddr    := data(ringBufferTail).paddr
  io.uncache.req.bits.meta.uop      := uop(ringBufferTail)
  io.uncache.req.bits.meta.mmio     := true.B // data(ringBufferTail).mmio
  io.uncache.req.bits.meta.tlb_miss := false.B
  io.uncache.req.bits.meta.mask     := data(ringBufferTail).mask
  io.uncache.req.bits.meta.replay   := false.B

  io.uncache.resp.ready := true.B

  when(io.uncache.req.fire()){
681 682
    pending(ringBufferTail) := false.B
  }
W
William Wang 已提交
683

684
  when(io.uncache.resp.fire()){
685
    valid(ringBufferTail) := true.B
686
    data(ringBufferTail).data := io.uncache.resp.bits.data(XLEN-1, 0)
687 688
    // TODO: write back exception info
  }
W
William Wang 已提交
689

690
  when(io.uncache.req.fire()){
L
linjiawei 已提交
691 692 693 694 695 696 697
    XSDebug("uncache req: pc %x addr %x data %x op %x mask %x\n",
      uop(ringBufferTail).cf.pc,
      io.uncache.req.bits.addr,
      io.uncache.req.bits.data,
      io.uncache.req.bits.cmd,
      io.uncache.req.bits.mask
    )
698 699 700 701 702 703
  }

  when(io.uncache.resp.fire()){
    XSDebug("uncache resp: data %x\n", io.dcache.resp.bits.data) 
  }

W
William Wang 已提交
704
  // Read vaddr for mem exception
705
  io.exceptionAddr.vaddr := data(io.exceptionAddr.lsIdx.lsroqIdx(InnerLsroqIdxWidth - 1, 0)).vaddr
W
William Wang 已提交
706

W
William Wang 已提交
707 708
  // misprediction recovery / exception redirect
  // invalidate lsroq term using robIdx
709 710
  val needCancel = Wire(Vec(LsroqSize, Bool()))
  for (i <- 0 until LsroqSize) {
Y
Yinan Xu 已提交
711
    needCancel(i) := uop(i).roqIdx.needFlush(io.brqRedirect) && allocated(i) && !commited(i)
712
    when(needCancel(i)) {
W
William Wang 已提交
713 714 715 716 717 718
      when(io.brqRedirect.bits.isReplay){
        valid(i) := false.B
        store(i) := false.B
        writebacked(i) := false.B
        listening(i) := false.B
        miss(i) := false.B
W
William Wang 已提交
719
        pending(i) := false.B
W
William Wang 已提交
720 721 722 723
      }.otherwise{
        allocated(i) := false.B
      }
    }
724 725 726 727
  }
  when (io.brqRedirect.valid && io.brqRedirect.bits.isMisPred) {
    ringBufferHeadExtended := ringBufferHeadExtended - PopCount(needCancel)
  }
W
William Wang 已提交
728

W
William Wang 已提交
729
  // assert(!io.rollback.valid)
L
LinJiawei 已提交
730
  when(io.rollback.valid) {
Y
Yinan Xu 已提交
731
    XSDebug("Mem rollback: pc %x roqidx %d\n", io.rollback.bits.pc, io.rollback.bits.roqIdx.asUInt)
W
William Wang 已提交
732
  }
W
William Wang 已提交
733 734

  // debug info
Y
Yinan Xu 已提交
735
  XSDebug("head %d:%d tail %d:%d scommit %d\n", ringBufferHeadExtended(InnerLsroqIdxWidth), ringBufferHead, ringBufferTailExtended(InnerLsroqIdxWidth), ringBufferTail, scommitPending)
W
William Wang 已提交
736 737

  def PrintFlag(flag: Bool, name: String): Unit = {
L
LinJiawei 已提交
738
    when(flag) {
W
William Wang 已提交
739
      XSDebug(false, true.B, name)
L
LinJiawei 已提交
740
    }.otherwise {
W
William Wang 已提交
741 742 743 744
      XSDebug(false, true.B, " ")
    }
  }

Y
Yinan Xu 已提交
745
  for (i <- 0 until LsroqSize) {
L
LinJiawei 已提交
746
    if (i % 4 == 0) XSDebug("")
W
William Wang 已提交
747 748
    XSDebug(false, true.B, "%x ", uop(i).cf.pc)
    PrintFlag(allocated(i), "a")
W
William Wang 已提交
749 750
    PrintFlag(allocated(i) && valid(i), "v")
    PrintFlag(allocated(i) && writebacked(i), "w")
751
    PrintFlag(allocated(i) && commited(i), "c")
W
William Wang 已提交
752 753 754
    PrintFlag(allocated(i) && store(i), "s")
    PrintFlag(allocated(i) && miss(i), "m")
    PrintFlag(allocated(i) && listening(i), "l")
W
William Wang 已提交
755
    PrintFlag(allocated(i) && pending(i), "p")
W
William Wang 已提交
756
    XSDebug(false, true.B, " ")
L
LinJiawei 已提交
757
    if (i % 4 == 3) XSDebug(false, true.B, "\n")
W
William Wang 已提交
758
  }
W
William Wang 已提交
759

W
William Wang 已提交
760
}