MemBlock.scala 10.0 KB
Newer Older
1 2 3 4 5
package xiangshan.backend

import chisel3._
import chisel3.util._
import xiangshan._
L
LinJiawei 已提交
6
import xiangshan.backend.exu.Exu.{loadExuConfigs, storeExuConfigs}
7
import xiangshan.backend.roq.RoqPtr
8
import xiangshan.backend.exu._
9 10 11
import xiangshan.cache._
import xiangshan.mem._
import xiangshan.backend.fu.FenceToSbuffer
Z
ZhangZifei 已提交
12
import xiangshan.backend.issue.{ReservationStationCtrl, ReservationStationData}
13
import xiangshan.backend.fu.FunctionUnit.{lduCfg, mouCfg, stuCfg}
14 15

class LsBlockToCtrlIO extends XSBundle {
L
LinJiawei 已提交
16
  val stOut = Vec(exuParameters.StuCnt, ValidIO(new ExuOutput)) // write to roq
17 18 19 20
  val numExist = Vec(exuParameters.LsExuCnt, Output(UInt(log2Ceil(IssQueSize).W)))
  val replay = ValidIO(new Redirect)
}

21 22 23 24 25 26 27 28
class MemBlockToDcacheIO extends XSBundle {
  val loadUnitToDcacheVec = Vec(exuParameters.LduCnt, new DCacheLoadIO)
  val loadMiss = new DCacheLineIO
  val atomics  = new DCacheWordIO
  val sbufferToDcache = new DCacheLineIO
  val uncache = new DCacheWordIO
}

L
LinJiawei 已提交
29 30
class MemBlock
(
31 32 33 34 35 36
  fastWakeUpIn: Seq[ExuConfig],
  slowWakeUpIn: Seq[ExuConfig],
  fastFpOut: Seq[ExuConfig],
  slowFpOut: Seq[ExuConfig],
  fastIntOut: Seq[ExuConfig],
  slowIntOut: Seq[ExuConfig]
Y
Yinan Xu 已提交
37
) extends XSModule with HasExeBlockHelper {
L
LinJiawei 已提交
38

39 40 41
  val io = IO(new Bundle {
    val fromCtrlBlock = Flipped(new CtrlToLsBlockIO)
    val toCtrlBlock = new LsBlockToCtrlIO
L
LinJiawei 已提交
42

43 44 45
    val wakeUpIn = new WakeUpBundle(fastWakeUpIn.size, slowWakeUpIn.size)
    val wakeUpFpOut = Flipped(new WakeUpBundle(fastFpOut.size, slowFpOut.size))
    val wakeUpIntOut = Flipped(new WakeUpBundle(fastIntOut.size, slowIntOut.size))
L
LinJiawei 已提交
46

47 48 49
    val ptw = new TlbPtwIO
    // TODO: dcache should be inside MemBlock
    val dcache = new MemBlockToDcacheIO
Y
Yinan Xu 已提交
50 51 52 53 54 55 56 57 58
    val sfence = Input(new SfenceBundle)
    val tlbCsr = Input(new TlbCsrBundle)
    val fenceToSbuffer = Flipped(new FenceToSbuffer)

    val lsqio = new Bundle {
      val exceptionAddr = new ExceptionAddrIO // to csr
      val commits = Flipped(Vec(CommitWidth, Valid(new RoqCommit))) // to lsq
      val roqDeqPtr = Input(new RoqPtr) // to lsq
    }
59 60
  })

L
LinJiawei 已提交
61 62 63 64 65 66 67 68 69
  val redirect = io.fromCtrlBlock.redirect

  val loadUnits = Seq.fill(exuParameters.LduCnt)(Module(new LoadUnit))
  val storeUnits = Seq.fill(exuParameters.StuCnt)(Module(new StoreUnit))
  val exeUnits = loadUnits ++ storeUnits

  val atomicsUnit = Module(new AtomicsUnit)

  val loadWritebackOverride  = Mux(atomicsUnit.io.out.valid, atomicsUnit.io.out.bits, loadUnits.head.io.ldout.bits)
Y
Yinan Xu 已提交
70 71 72
  val ldOut0 = Wire(Decoupled(new ExuOutput))
  ldOut0.valid := atomicsUnit.io.out.valid || loadUnits.head.io.ldout.valid
  ldOut0.bits  := loadWritebackOverride
L
LinJiawei 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
  atomicsUnit.io.out.ready := ldOut0.ready
  loadUnits.head.io.ldout.ready := ldOut0.ready

  val exeWbReqs = ldOut0 +: loadUnits.tail.map(_.io.ldout)

  val reservationStations = (loadExuConfigs ++ storeExuConfigs).zipWithIndex.map({ case (cfg, i) =>
    var certainLatency = -1
    if (cfg.hasCertainLatency) {
      certainLatency = cfg.latency.latencyVal.get
    }

    val readIntRf = cfg.readIntRf
    val readFpRf = cfg.readFpRf

    // load has uncertain latency, so only use external wake up data
    val writeBackData = fastWakeUpIn.zip(io.wakeUpIn.fast)
      .filter(x => (x._1.writeIntRf && readIntRf) || (x._1.writeFpRf && readFpRf))
      .map(_._2.bits.data)
    val wakeupCnt = writeBackData.length

    val inBlockListenPorts = exeWbReqs
    val extraListenPorts = inBlockListenPorts ++
      slowWakeUpIn.zip(io.wakeUpIn.slow)
        .filter(x => (x._1.writeIntRf && readIntRf) || (x._1.writeFpRf && readFpRf))
        .map(_._2)

    val extraListenPortsCnt = extraListenPorts.length

    // if tlb miss, replay
    val feedback = true

    println(s"${i}: exu:${cfg.name} wakeupCnt: ${wakeupCnt} extraListenPorts: ${extraListenPortsCnt} delay:${certainLatency} feedback:${feedback}")

Z
ZhangZifei 已提交
106 107
    val rsCtrl = Module(new ReservationStationCtrl(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback))
    val rsData = Module(new ReservationStationData(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback))
L
LinJiawei 已提交
108

Z
ZhangZifei 已提交
109 110 111 112 113 114
    rsCtrl.io.data <> rsData.io.ctrl
    rsCtrl.io.redirect <> redirect // TODO: remove it
    rsCtrl.io.numExist <> io.toCtrlBlock.numExist(i)
    rsCtrl.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
    rsData.io.enqData <> io.fromCtrlBlock.enqIqData(i)
    rsData.io.redirect <> redirect
L
LinJiawei 已提交
115

Z
ZhangZifei 已提交
116 117
    rsData.io.writeBackedData <> writeBackData
    for ((x, y) <- rsData.io.extraListenPorts.zip(extraListenPorts)) {
L
LinJiawei 已提交
118 119 120 121
      x.valid := y.fire()
      x.bits := y.bits
    }

Z
ZhangZifei 已提交
122 123 124
    // exeUnits(i).io.redirect <> redirect
    // exeUnits(i).io.fromInt <> rsData.io.deq
    rsData.io.feedback := DontCare
L
LinJiawei 已提交
125

Z
ZhangZifei 已提交
126 127
    rsCtrl.suggestName(s"rsc_${cfg.name}")
    rsData.suggestName(s"rsd_${cfg.name}")
L
LinJiawei 已提交
128

Z
ZhangZifei 已提交
129
    rsData
L
LinJiawei 已提交
130 131 132 133 134 135 136 137
  })

  for(rs <- reservationStations){
    rs.io.broadcastedUops <> fastWakeUpIn.zip(io.wakeUpIn.fastUops)
      .filter(x => (x._1.writeIntRf && rs.exuCfg.readIntRf) || (x._1.writeFpRf && rs.exuCfg.readFpRf))
      .map(_._2)
  }

L
LinJiawei 已提交
138 139 140 141
  // TODO: make this better
  io.wakeUpIn.fast.foreach(_.ready := true.B)
  io.wakeUpIn.slow.foreach(_.ready := true.B)

L
LinJiawei 已提交
142 143 144 145 146 147 148 149 150 151 152 153
  io.wakeUpFpOut.slow <> exeWbReqs.map(x => {
    val raw = WireInit(x)
    raw.valid := x.valid && x.bits.uop.ctrl.fpWen
    raw
  })

  io.wakeUpIntOut.slow <> exeWbReqs.map(x => {
    val raw = WireInit(x)
    raw.valid := x.valid && x.bits.uop.ctrl.rfWen
    raw
  })

L
LinJiawei 已提交
154 155 156
  // load always ready
  exeWbReqs.foreach(_.ready := true.B)

L
LinJiawei 已提交
157
  val dtlb = Module(new TLB(Width = DTLBWidth, isDtlb = true))
Y
Yinan Xu 已提交
158
  val lsq = Module(new LsqWrappper)
L
LinJiawei 已提交
159 160 161 162 163 164
  val sbuffer = Module(new NewSbuffer)
  // if you wants to stress test dcache store, use FakeSbuffer
  // val sbuffer = Module(new FakeSbuffer)

  // dtlb
  io.ptw <> dtlb.io.ptw
Y
Yinan Xu 已提交
165 166
  dtlb.io.sfence <> io.sfence
  dtlb.io.csr <> io.tlbCsr
L
LinJiawei 已提交
167 168 169

  // LoadUnit
  for (i <- 0 until exuParameters.LduCnt) {
Y
Yinan Xu 已提交
170
    loadUnits(i).io.redirect      <> io.fromCtrlBlock.redirect
Z
ZhangZifei 已提交
171
    loadUnits(i).io.tlbFeedback   <> reservationStations(i).io.feedback
Y
Yinan Xu 已提交
172
    loadUnits(i).io.dtlb          <> dtlb.io.requestor(i)
L
LinJiawei 已提交
173 174 175 176 177
    // get input form dispatch
    loadUnits(i).io.ldin          <> reservationStations(i).io.deq
    // dcache access
    loadUnits(i).io.dcache        <> io.dcache.loadUnitToDcacheVec(i)
    // forward
Y
Yinan Xu 已提交
178
    loadUnits(i).io.lsq.forward   <> lsq.io.forward(i)
L
LinJiawei 已提交
179 180
    loadUnits(i).io.sbuffer       <> sbuffer.io.forward(i)

Y
Yinan Xu 已提交
181 182 183
    // passdown to lsq
    lsq.io.loadIn(i)              <> loadUnits(i).io.lsq.loadIn
    lsq.io.ldout(i)               <> loadUnits(i).io.lsq.ldout
L
LinJiawei 已提交
184 185 186 187
  }

  // StoreUnit
  for (i <- 0 until exuParameters.StuCnt) {
Y
Yinan Xu 已提交
188
    storeUnits(i).io.redirect     <> io.fromCtrlBlock.redirect
Z
ZhangZifei 已提交
189
    storeUnits(i).io.tlbFeedback  <> reservationStations(exuParameters.LduCnt + i).io.feedback
Y
Yinan Xu 已提交
190
    storeUnits(i).io.dtlb         <> dtlb.io.requestor(exuParameters.LduCnt + i)
L
LinJiawei 已提交
191
    // get input form dispatch
Y
Yinan Xu 已提交
192
    storeUnits(i).io.stin         <> reservationStations(exuParameters.LduCnt + i).io.deq
Y
Yinan Xu 已提交
193 194
    // passdown to lsq
    storeUnits(i).io.lsq          <> lsq.io.storeIn(i)
195 196 197 198 199 200 201 202 203 204 205
    io.toCtrlBlock.stOut(i).valid := storeUnits(i).io.stout.valid
    io.toCtrlBlock.stOut(i).bits  := storeUnits(i).io.stout.bits
	  storeUnits(i).io.stout.ready := true.B
  }

  // mmio store writeback will use store writeback port 0
  lsq.io.mmioStout.ready := false.B
  when(lsq.io.mmioStout.valid && !storeUnits(0).io.stout.valid) {
    io.toCtrlBlock.stOut(0).valid := true.B
    lsq.io.mmioStout.ready := true.B
    io.toCtrlBlock.stOut(0).bits  := lsq.io.mmioStout.bits
L
LinJiawei 已提交
206 207
  }

Y
Yinan Xu 已提交
208 209
  // Lsq
  lsq.io.commits     <> io.lsqio.commits
210
  lsq.io.enq         <> io.fromCtrlBlock.enqLsq
Y
Yinan Xu 已提交
211 212 213 214 215
  lsq.io.brqRedirect := io.fromCtrlBlock.redirect
  lsq.io.roqDeqPtr   := io.lsqio.roqDeqPtr
  io.toCtrlBlock.replay <> lsq.io.rollback
  lsq.io.dcache      <> io.dcache.loadMiss
  lsq.io.uncache     <> io.dcache.uncache
L
LinJiawei 已提交
216

Y
Yinan Xu 已提交
217 218
  // LSQ to store buffer
  lsq.io.sbuffer     <> sbuffer.io.in
L
LinJiawei 已提交
219 220

  // Sbuffer
Y
Yinan Xu 已提交
221
  sbuffer.io.dcache    <> io.dcache.sbufferToDcache
L
LinJiawei 已提交
222 223

  // flush sbuffer
Y
Yinan Xu 已提交
224
  val fenceFlush = io.fenceToSbuffer.flushSb
L
LinJiawei 已提交
225
  val atomicsFlush = atomicsUnit.io.flush_sbuffer.valid
Y
Yinan Xu 已提交
226
  io.fenceToSbuffer.sbIsEmpty := sbuffer.io.flush.empty
L
LinJiawei 已提交
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
  // if both of them tries to flush sbuffer at the same time
  // something must have gone wrong
  assert(!(fenceFlush && atomicsFlush))
  sbuffer.io.flush.valid := fenceFlush || atomicsFlush

  // TODO: make 0/1 configurable
  // AtomicsUnit
  // AtomicsUnit will override other control signials,
  // as atomics insts (LR/SC/AMO) will block the pipeline
  val st0_atomics = reservationStations(2).io.deq.valid && reservationStations(2).io.deq.bits.uop.ctrl.fuType === FuType.mou
  val st1_atomics = reservationStations(3).io.deq.valid && reservationStations(3).io.deq.bits.uop.ctrl.fuType === FuType.mou
  // amo should always go through store issue queue 0
  assert(!st1_atomics)

  atomicsUnit.io.dtlb.resp.valid := false.B
  atomicsUnit.io.dtlb.resp.bits  := DontCare
Z
ZhangZifei 已提交
243
  atomicsUnit.io.dtlb.req.ready := dtlb.io.requestor(0).req.ready
L
LinJiawei 已提交
244 245 246 247 248 249 250 251 252 253

  // dispatch 0 takes priority
  atomicsUnit.io.in.valid := st0_atomics
  atomicsUnit.io.in.bits  := reservationStations(2).io.deq.bits
  when (st0_atomics) {
    reservationStations(0).io.deq.ready := atomicsUnit.io.in.ready
    storeUnits(0).io.stin.valid := false.B
  }

  when(atomicsUnit.io.dtlb.req.valid) {
Y
Yinan Xu 已提交
254
    dtlb.io.requestor(0) <> atomicsUnit.io.dtlb
L
LinJiawei 已提交
255 256 257 258 259 260 261 262
    // take load unit 0's tlb port
    // make sure not to disturb loadUnit
    assert(!loadUnits(0).io.dtlb.req.valid)
    loadUnits(0).io.dtlb.resp.valid := false.B
  }

  when(atomicsUnit.io.tlbFeedback.valid) {
    assert(!storeUnits(0).io.tlbFeedback.valid)
Z
ZhangZifei 已提交
263
    atomicsUnit.io.tlbFeedback <> reservationStations(exuParameters.LduCnt + 0).io.feedback
L
LinJiawei 已提交
264 265 266 267 268 269 270 271 272 273 274 275 276
  }

  atomicsUnit.io.dcache        <> io.dcache.atomics
  atomicsUnit.io.flush_sbuffer.empty := sbuffer.io.flush.empty

  atomicsUnit.io.redirect <> io.fromCtrlBlock.redirect

  when(atomicsUnit.io.out.valid){
    // take load unit 0's write back port
    assert(!loadUnits(0).io.ldout.valid)
    loadUnits(0).io.ldout.ready := false.B
  }

Y
Yinan Xu 已提交
277 278 279
  lsq.io.exceptionAddr.lsIdx := io.lsqio.exceptionAddr.lsIdx
  lsq.io.exceptionAddr.isStore := io.lsqio.exceptionAddr.isStore
  io.lsqio.exceptionAddr.vaddr := Mux(atomicsUnit.io.exceptionAddr.valid, atomicsUnit.io.exceptionAddr.bits, lsq.io.exceptionAddr.vaddr)
280

Z
ZhangZifei 已提交
281
}