IntegerBlock.scala 9.6 KB
Newer Older
1 2 3 4
package xiangshan.backend

import chisel3._
import chisel3.util._
5
import utils.XSPerf
6
import xiangshan._
7
import xiangshan.backend.exu.Exu.{jumpExeUnitCfg, ldExeUnitCfg, stExeUnitCfg}
8
import xiangshan.backend.exu._
9
import xiangshan.backend.issue.ReservationStation
10
import xiangshan.backend.fu.{FenceToSbuffer, CSRFileIO}
L
LinJiawei 已提交
11
import xiangshan.backend.regfile.Regfile
12

L
LinJiawei 已提交
13 14
class WakeUpBundle(numFast: Int, numSlow: Int) extends XSBundle {
  val fastUops = Vec(numFast, Flipped(ValidIO(new MicroOp)))
15
  val fast = Vec(numFast, Flipped(ValidIO(new ExuOutput))) //one cycle later than fastUops
L
LinJiawei 已提交
16 17 18 19 20 21
  val slow = Vec(numSlow, Flipped(DecoupledIO(new ExuOutput)))

  override def cloneType = (new WakeUpBundle(numFast, numSlow)).asInstanceOf[this.type]

}

22
class IntBlockToCtrlIO extends XSBundle {
L
LinJiawei 已提交
23 24 25 26
  // write back regfile signals after arbiter
  // used to update busytable and roq state
  val wbRegs = Vec(NRIntWritePorts, ValidIO(new ExuOutput))
  // write back to brq
27
  val exuRedirect = Vec(exuParameters.AluCnt + exuParameters.JmpCnt, ValidIO(new ExuOutput))
28 29 30
  val numExist = Vec(exuParameters.IntExuCnt, Output(UInt(log2Ceil(IssQueSize).W)))
}

L
LinJiawei 已提交
31
trait HasExeBlockHelper {
32 33 34 35
  def fpUopValid(x: ValidIO[MicroOp]): ValidIO[MicroOp] = {
    val uop = WireInit(x)
    uop.valid := x.valid && x.bits.ctrl.fpWen
    uop
L
LinJiawei 已提交
36
  }
37 38 39 40
  def fpOutValid(x: ValidIO[ExuOutput]): ValidIO[ExuOutput] = {
    val out = WireInit(x)
    out.valid := x.valid && x.bits.uop.ctrl.fpWen
    out
L
LinJiawei 已提交
41
  }
42
  def fpOutValid(x: DecoupledIO[ExuOutput], connectReady: Boolean = false): DecoupledIO[ExuOutput] = {
43
    val out = WireInit(x)
44
    if(connectReady) x.ready := out.ready
45 46
    out.valid := x.valid && x.bits.uop.ctrl.fpWen
    out
L
LinJiawei 已提交
47
  }
48 49 50 51
  def intUopValid(x: ValidIO[MicroOp]): ValidIO[MicroOp] = {
    val uop = WireInit(x)
    uop.valid := x.valid && x.bits.ctrl.rfWen
    uop
L
LinJiawei 已提交
52
  }
53 54
  def intOutValid(x: ValidIO[ExuOutput]): ValidIO[ExuOutput] = {
    val out = WireInit(x)
55
    out.valid := x.valid && !x.bits.uop.ctrl.fpWen
56
    out
57
  }
58
  def intOutValid(x: DecoupledIO[ExuOutput], connectReady: Boolean = false): DecoupledIO[ExuOutput] = {
59
    val out = WireInit(x)
60
    if(connectReady) x.ready := out.ready
61
    out.valid := x.valid && !x.bits.uop.ctrl.fpWen
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
    out
  }
  def decoupledIOToValidIO[T <: Data](d: DecoupledIO[T]): Valid[T] = {
    val v = Wire(Valid(d.bits.cloneType))
    v.valid := d.valid
    v.bits := d.bits
    v
  }

  def validIOToDecoupledIO[T <: Data](v: Valid[T]): DecoupledIO[T] = {
    val d = Wire(DecoupledIO(v.bits.cloneType))
    d.valid := v.valid
    d.ready := true.B
    d.bits := v.bits
    d
77
  }
L
LinJiawei 已提交
78 79
}

L
LinJiawei 已提交
80 81
class IntegerBlock
(
L
LinJiawei 已提交
82 83
  fastWakeUpIn: Seq[ExuConfig],
  slowWakeUpIn: Seq[ExuConfig],
84 85 86
  fastWakeUpOut: Seq[ExuConfig],
  slowWakeUpOut: Seq[ExuConfig]
) extends XSModule with HasExeBlockHelper {
87 88 89
  val io = IO(new Bundle {
    val fromCtrlBlock = Flipped(new CtrlToIntBlockIO)
    val toCtrlBlock = new IntBlockToCtrlIO
90
    val toMemBlock = new IntBlockToMemBlockIO
L
LinJiawei 已提交
91

L
LinJiawei 已提交
92
    val wakeUpIn = new WakeUpBundle(fastWakeUpIn.size, slowWakeUpIn.size)
93
    val wakeUpOut = Flipped(new WakeUpBundle(fastWakeUpOut.size, slowWakeUpOut.size))
L
LinJiawei 已提交
94

95
    val csrio = new CSRFileIO
Y
Yinan Xu 已提交
96
    val fenceio = new Bundle {
Y
Yinan Xu 已提交
97
      val sfence = Output(new SfenceBundle) // to front,mem
98 99
      val fencei = Output(Bool()) // to icache
      val sbuffer = new FenceToSbuffer // to mem
Y
Yinan Xu 已提交
100
    }
101
  })
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
  val difftestIO = IO(new Bundle() {
    val fromCSR = new Bundle() {
      val intrNO = Output(UInt(64.W))
      val cause = Output(UInt(64.W))
      val priviledgeMode = Output(UInt(2.W))
      val mstatus = Output(UInt(64.W))
      val sstatus = Output(UInt(64.W))
      val mepc = Output(UInt(64.W))
      val sepc = Output(UInt(64.W))
      val mtval = Output(UInt(64.W))
      val stval = Output(UInt(64.W))
      val mtvec = Output(UInt(64.W))
      val stvec = Output(UInt(64.W))
      val mcause = Output(UInt(64.W))
      val scause = Output(UInt(64.W))
      val satp = Output(UInt(64.W))
      val mip = Output(UInt(64.W))
      val mie = Output(UInt(64.W))
      val mscratch = Output(UInt(64.W))
      val sscratch = Output(UInt(64.W))
      val mideleg = Output(UInt(64.W))
      val medeleg = Output(UInt(64.W))
    }
  })
  difftestIO <> DontCare
L
LinJiawei 已提交
127 128

  val redirect = io.fromCtrlBlock.redirect
129
  val flush = io.fromCtrlBlock.flush
L
LinJiawei 已提交
130 131 132 133 134 135 136 137 138 139

  val intRf = Module(new Regfile(
    numReadPorts = NRIntReadPorts,
    numWirtePorts = NRIntWritePorts,
    hasZero = true,
    len = XLEN
  ))

  val jmpExeUnit = Module(new JumpExeUnit)
  val mduExeUnits = Array.tabulate(exuParameters.MduCnt)(_ => Module(new MulDivExeUnit))
L
LinJiawei 已提交
140
  val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit))
L
LinJiawei 已提交
141

L
LinJiawei 已提交
142
  val exeUnits = jmpExeUnit +: (mduExeUnits ++ aluExeUnits)
L
LinJiawei 已提交
143 144 145 146 147 148 149

  def needWakeup(cfg: ExuConfig): Boolean =
    (cfg.readIntRf && cfg.writeIntRf) || (cfg.readFpRf && cfg.writeFpRf)

  def needData(a: ExuConfig, b: ExuConfig): Boolean =
    (a.readIntRf && b.writeIntRf) || (a.readFpRf && b.writeFpRf)

150 151
  // val readPortIndex = RegNext(io.fromCtrlBlock.readPortIndex)
  val readPortIndex = Seq(1, 2, 3, 0, 1, 2, 3)
Y
Yinan Xu 已提交
152
  val reservationStations = exeUnits.map(_.config).zipWithIndex.map({ case (cfg, i) =>
L
LinJiawei 已提交
153 154 155 156 157 158 159
    var certainLatency = -1
    if (cfg.hasCertainLatency) {
      certainLatency = cfg.latency.latencyVal.get
    }

    val readIntRf = cfg.readIntRf

160 161 162
    val inBlockWbData = exeUnits.filter(e => e.config.hasCertainLatency).map(a => (a.config, a.io.out.bits.data))
    val fastDatas = inBlockWbData ++ fastWakeUpIn.zip(io.wakeUpIn.fast.map(_.bits.data))
    val fastPortsCnt = fastDatas.length
L
LinJiawei 已提交
163

164 165
    val inBlockListenPorts = exeUnits.filter(e => e.config.hasUncertainlatency).map(a => (a.config, a.io.out))
    val slowPorts = (inBlockListenPorts ++ slowWakeUpIn.zip(io.wakeUpIn.slow)).map(a => (a._1, decoupledIOToValidIO(a._2)))
166
    val extraListenPortsCnt = slowPorts.length
L
LinJiawei 已提交
167 168 169

    val feedback = (cfg == ldExeUnitCfg) || (cfg == stExeUnitCfg)

170
    println(s"${i}: exu:${cfg.name} fastPortsCnt: ${fastPortsCnt} slowPorts: ${extraListenPortsCnt} delay:${certainLatency} feedback:${feedback}")
L
LinJiawei 已提交
171

172 173 174 175 176 177 178
    val rs = Module(new ReservationStation(cfg, XLEN + 1,
      fastDatas.map(_._1),
      slowPorts.map(_._1),
      fixedDelay = certainLatency,
      fastWakeup = certainLatency >= 0,
      feedback = feedback
    ))
Z
ZhangZifei 已提交
179

180
    rs.io.redirect <> redirect
Z
ZhangZifei 已提交
181
    rs.io.flush <> flush // TODO: remove it
182 183
    rs.io.numExist <> io.toCtrlBlock.numExist(i)
    rs.io.fromDispatch <> io.fromCtrlBlock.enqIqCtrl(i)
184

185
    rs.io.srcRegValue := DontCare
186 187
    val src1Value = VecInit((0 until 4).map(i => intRf.io.readPorts(i * 2).data))
    val src2Value = VecInit((0 until 4).map(i => intRf.io.readPorts(i * 2 + 1).data))
188 189
    rs.io.srcRegValue(0) := src1Value(readPortIndex(i))
    if (cfg.intSrcCnt > 1) rs.io.srcRegValue(1) := src2Value(readPortIndex(i))
L
LinJiawei 已提交
190
    if (cfg == Exu.jumpExeUnitCfg) {
Z
ZhangZifei 已提交
191 192
      rs.io.jumpPc := io.fromCtrlBlock.jumpPc
      rs.io.jalr_target := io.fromCtrlBlock.jalr_target
L
LinJiawei 已提交
193
    }
Z
ZhangZifei 已提交
194

195 196
    rs.io.fastDatas <> fastDatas.map(_._2)
    rs.io.slowPorts <> slowPorts.map(_._2)
L
LinJiawei 已提交
197 198

    exeUnits(i).io.redirect <> redirect
199
    exeUnits(i).io.fromInt <> rs.io.deq
200
    exeUnits(i).io.flush <> flush
201
    // rs.io.memfeedback := DontCare
L
LinJiawei 已提交
202

203
    rs.suggestName(s"rs_${cfg.name}")
L
LinJiawei 已提交
204

205
    rs
L
LinJiawei 已提交
206 207
  })

208
  for (rs <- reservationStations) {
Y
Yinan Xu 已提交
209
    val inBlockUops = reservationStations.filter(x =>
L
LinJiawei 已提交
210 211
      x.exuCfg.hasCertainLatency && x.exuCfg.writeIntRf
    ).map(x => {
212 213
      val raw = WireInit(x.io.fastUopOut)
      raw.valid := x.io.fastUopOut.valid && raw.bits.ctrl.rfWen
L
LinJiawei 已提交
214 215
      raw
    })
216
    rs.io.fastUopsIn <> inBlockUops ++ io.wakeUpIn.fastUops
L
LinJiawei 已提交
217 218
  }

219 220 221
  io.wakeUpOut.fastUops <> reservationStations.filter(
    rs => rs.exuCfg.hasCertainLatency
  ).map(_.io.fastUopOut).map(intUopValid)
L
LinJiawei 已提交
222

223 224 225
  io.wakeUpOut.fast <> exeUnits.filter(
    x => x.config.hasCertainLatency
  ).map(_.io.out).map(decoupledIOToValidIO)
L
LinJiawei 已提交
226

227 228
  io.wakeUpOut.slow <> exeUnits.filter(
    x => x.config.hasUncertainlatency
229
  ).map(x => WireInit(x.io.out))
L
LinJiawei 已提交
230 231 232

  // send misprediction to brq
  io.toCtrlBlock.exuRedirect.zip(
233 234
    exeUnits.filter(_.config.hasRedirect).map(_.io.out)
  ).foreach {
L
LinJiawei 已提交
235 236 237 238 239
    case (x, y) =>
      x.valid := y.fire() && y.bits.redirectValid
      x.bits := y.bits
  }

Y
Yinan Xu 已提交
240 241
  jmpExeUnit.csrio <> io.csrio
  jmpExeUnit.fenceio <> io.fenceio
242
  if (!env.FPGAPlatform) {
243 244
    jmpExeUnit.difftestIO.fromCSR <> difftestIO.fromCSR
  }
L
LinJiawei 已提交
245 246

  // read int rf from ctrl block
247
  intRf.io.readPorts.zipWithIndex.map { case (r, i) => r.addr := io.fromCtrlBlock.readRf(i) }
248
  (0 until NRMemReadPorts).foreach(i => io.toMemBlock.readIntRf(i).data := intRf.io.readPorts(i + 8).data)
L
LinJiawei 已提交
249 250
  // write int rf arbiter
  val intWbArbiter = Module(new Wb(
L
LinJiawei 已提交
251 252 253
    (exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn),
    NRIntWritePorts,
    isFp = false
L
LinJiawei 已提交
254
  ))
255
  intWbArbiter.io.in <> exeUnits.map(e => {
256
    val w = WireInit(e.io.out)
257 258 259 260 261
    if(e.config.writeFpRf){
      w.valid := e.io.out.valid && !e.io.out.bits.uop.ctrl.fpWen && io.wakeUpOut.slow(0).ready
    } else {
      w.valid := e.io.out.valid
    }
262
    w
263
  }) ++ io.wakeUpIn.slow.map(x => intOutValid(x, connectReady = true))
264

265 266
  XSPerf("competition", intWbArbiter.io.in.map(i => !i.ready && i.valid).foldRight(0.U)(_+_))  
  
267 268 269 270 271 272 273 274 275
  exeUnits.zip(intWbArbiter.io.in).foreach{
    case (exu, wInt) =>
      if(exu.config.writeFpRf){
        val wakeUpOut = io.wakeUpOut.slow(0) // jmpExeUnit
        val writeFpReady = wakeUpOut.fire() && wakeUpOut.bits.uop.ctrl.fpWen
        exu.io.out.ready := wInt.fire() || writeFpReady || !exu.io.out.valid
      } else {
        exu.io.out.ready := wInt.fire() || !exu.io.out.valid
      }
276
  }
L
LinJiawei 已提交
277 278 279 280

  // set busytable and update roq
  io.toCtrlBlock.wbRegs <> intWbArbiter.io.out

281
  intRf.io.writePorts.zip(intWbArbiter.io.out).foreach {
L
LinJiawei 已提交
282 283 284 285 286
    case (rf, wb) =>
      rf.wen := wb.valid && wb.bits.uop.ctrl.rfWen
      rf.addr := wb.bits.uop.pdest
      rf.data := wb.bits.data
  }
287
}