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

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

L
LinJiawei 已提交
13 14 15 16 17 18 19 20 21
class WakeUpBundle(numFast: Int, numSlow: Int) extends XSBundle {
  val fastUops = Vec(numFast, Flipped(ValidIO(new MicroOp)))
  val fast = Vec(numFast, Flipped(DecoupledIO(new ExuOutput))) //one cycle later than fastUops
  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 27
  // write back regfile signals after arbiter
  // used to update busytable and roq state
  val wbRegs = Vec(NRIntWritePorts, ValidIO(new ExuOutput))
  // write back to brq
  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 32 33 34 35 36 37 38 39 40 41 42 43
trait HasExeBlockHelper {
  def fpFastFilter(cfg: ExuConfig): Boolean = {
    cfg.hasCertainLatency && cfg.writeFpRf
  }
  def fpSlowFilter(cfg: ExuConfig): Boolean = {
    cfg.hasUncertainlatency && cfg.writeFpRf
  }
  def intFastFilter(cfg: ExuConfig): Boolean = {
    cfg.hasCertainLatency && cfg.writeIntRf
  }
  def intSlowFilter(cfg: ExuConfig): Boolean = {
    cfg.hasUncertainlatency && cfg.writeIntRf
  }
44 45 46 47 48 49 50 51 52 53
  def fpValid(x: ValidIO[MicroOp]): ValidIO[MicroOp] = {
	val uop = WireInit(x)
	uop.valid := x.valid && x.bits.ctrl.fpWen
	uop
  }
  def intValid(x: ValidIO[MicroOp]): ValidIO[MicroOp] = {
	val uop = WireInit(x)
	uop.valid := x.valid && x.bits.ctrl.rfWen
	uop
  }
L
LinJiawei 已提交
54 55
}

L
LinJiawei 已提交
56 57
class IntegerBlock
(
L
LinJiawei 已提交
58 59 60 61 62 63
  fastWakeUpIn: Seq[ExuConfig],
  slowWakeUpIn: Seq[ExuConfig],
  fastFpOut: Seq[ExuConfig],
  slowFpOut: Seq[ExuConfig],
  fastIntOut: Seq[ExuConfig],
  slowIntOut: Seq[ExuConfig]
Y
Yinan Xu 已提交
64
) extends XSModule with HasExeBlockHelper
L
LinJiawei 已提交
65
{
66 67 68
  val io = IO(new Bundle {
    val fromCtrlBlock = Flipped(new CtrlToIntBlockIO)
    val toCtrlBlock = new IntBlockToCtrlIO
69
    val toMemBlock = new IntBlockToMemBlockIO
L
LinJiawei 已提交
70

L
LinJiawei 已提交
71 72 73
    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 已提交
74

Y
Yinan Xu 已提交
75
    val csrio = new Bundle {
76
      val fflags = Flipped(Valid(UInt(5.W))) // from roq
Y
Yinan Xu 已提交
77
      val dirty_fs = Input(Bool()) // from roq
Y
Yinan Xu 已提交
78
      val frm = Output(UInt(3.W)) // to float
79
      val exception = Flipped(ValidIO(new RoqExceptionInfo))
Y
Yinan Xu 已提交
80
      val trapTarget = Output(UInt(VAddrBits.W)) // to roq
L
LinJiawei 已提交
81
      val isXRet = Output(Bool())
Y
Yinan Xu 已提交
82 83 84 85
      val interrupt = Output(Bool()) // to roq
      val memExceptionVAddr = Input(UInt(VAddrBits.W)) // from lsq
      val externalInterrupt = new ExternalInterruptIO  // from outside
      val tlb = Output(new TlbCsrBundle) // from tlb
86 87 88
      val perfinfo = new Bundle {
        val retiredInstr = Input(UInt(3.W))
      }
Y
Yinan Xu 已提交
89 90
    }
    val fenceio = new Bundle {
Y
Yinan Xu 已提交
91 92 93
      val sfence = Output(new SfenceBundle) // to front,mem
      val fencei = Output(Bool())           // to icache
      val sbuffer = new FenceToSbuffer      // to mem
Y
Yinan Xu 已提交
94
    }
95
  })
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  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 已提交
121 122

  val redirect = io.fromCtrlBlock.redirect
123
  val flush = io.fromCtrlBlock.flush
L
LinJiawei 已提交
124 125 126 127 128 129 130 131 132 133

  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 已提交
134
  val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit))
L
LinJiawei 已提交
135

L
LinJiawei 已提交
136
  val exeUnits = jmpExeUnit +: (mduExeUnits ++ aluExeUnits)
L
LinJiawei 已提交
137 138 139 140 141 142 143

  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)

144
  val readPortIndex = RegNext(io.fromCtrlBlock.readPortIndex)
Y
Yinan Xu 已提交
145
  val reservationStations = exeUnits.map(_.config).zipWithIndex.map({ case (cfg, i) =>
L
LinJiawei 已提交
146 147 148 149 150 151 152 153
    var certainLatency = -1
    if (cfg.hasCertainLatency) {
      certainLatency = cfg.latency.latencyVal.get
    }

    val readIntRf = cfg.readIntRf

    val inBlockWbData = exeUnits.filter(e => e.config.hasCertainLatency && readIntRf).map(_.io.toInt.bits.data)
154 155
    val fastDatas = inBlockWbData ++ io.wakeUpIn.fast.map(_.bits.data)
    val wakeupCnt = fastDatas.length
L
LinJiawei 已提交
156 157

    val inBlockListenPorts = exeUnits.filter(e => e.config.hasUncertainlatency && readIntRf).map(_.io.toInt)
158 159
    val slowPorts = inBlockListenPorts ++ io.wakeUpIn.slow
    val extraListenPortsCnt = slowPorts.length
L
LinJiawei 已提交
160 161 162

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

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

165
    val rs = Module(new ReservationStation(cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, fastWakeup = certainLatency >= 0, feedback = feedback))
Z
ZhangZifei 已提交
166

167
    rs.io.redirect <> redirect
Z
ZhangZifei 已提交
168
    rs.io.flush <> flush // TODO: remove it
169 170
    rs.io.numExist <> io.toCtrlBlock.numExist(i)
    rs.io.fromDispatch <> io.fromCtrlBlock.enqIqCtrl(i)
171

172
    rs.io.srcRegValue := DontCare
173 174
    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))
175 176
    rs.io.srcRegValue(0) := src1Value(readPortIndex(i))
    if (cfg.intSrcCnt > 1) rs.io.srcRegValue(1) := src2Value(readPortIndex(i))
L
LinJiawei 已提交
177
    if (cfg == Exu.jumpExeUnitCfg) {
Z
ZhangZifei 已提交
178 179
      rs.io.jumpPc := io.fromCtrlBlock.jumpPc
      rs.io.jalr_target := io.fromCtrlBlock.jalr_target
L
LinJiawei 已提交
180
    }
Z
ZhangZifei 已提交
181

182 183
    rs.io.fastDatas <> fastDatas
    for ((x, y) <- rs.io.slowPorts.zip(slowPorts)) {
L
LinJiawei 已提交
184 185 186 187 188
      x.valid := y.fire()
      x.bits := y.bits
    }

    exeUnits(i).io.redirect <> redirect
189
    exeUnits(i).io.fromInt <> rs.io.deq
190
    exeUnits(i).io.flush <> flush
191
    // rs.io.memfeedback := DontCare
L
LinJiawei 已提交
192

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

195
    rs
L
LinJiawei 已提交
196 197
  })

Y
Yinan Xu 已提交
198 199
  for(rs <- reservationStations){
    val inBlockUops = reservationStations.filter(x =>
L
LinJiawei 已提交
200 201
      x.exuCfg.hasCertainLatency && x.exuCfg.writeIntRf
    ).map(x => {
202 203
      val raw = WireInit(x.io.fastUopOut)
      raw.valid := x.io.fastUopOut.valid && raw.bits.ctrl.rfWen
L
LinJiawei 已提交
204 205
      raw
    })
206
    rs.io.fastUopsIn <> inBlockUops ++ io.wakeUpIn.fastUops
L
LinJiawei 已提交
207 208
  }

Y
Yinan Xu 已提交
209
  io.wakeUpFpOut.fastUops <> reservationStations.filter(
L
LinJiawei 已提交
210
    rs => fpFastFilter(rs.exuCfg)
211
  ).map(_.io.fastUopOut).map(fpValid)
L
LinJiawei 已提交
212 213 214 215 216 217 218 219 220

  io.wakeUpFpOut.fast <> exeUnits.filter(
    x => fpFastFilter(x.config)
  ).map(_.io.toFp)

  io.wakeUpFpOut.slow <> exeUnits.filter(
    x => fpSlowFilter(x.config)
  ).map(_.io.toFp)

Y
Yinan Xu 已提交
221
  io.wakeUpIntOut.fastUops <> reservationStations.filter(
L
LinJiawei 已提交
222
    rs => intFastFilter(rs.exuCfg)
223
  ).map(_.io.fastUopOut).map(intValid)
L
LinJiawei 已提交
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

  io.wakeUpIntOut.fast <> exeUnits.filter(
    x => intFastFilter(x.config)
  ).map(_.io.toInt)

  io.wakeUpIntOut.slow <> exeUnits.filter(
    x => intSlowFilter(x.config)
  ).map(_.io.toInt)

  // send misprediction to brq
  io.toCtrlBlock.exuRedirect.zip(
    exeUnits.filter(_.config.hasRedirect).map(_.io.toInt)
  ).foreach{
    case (x, y) =>
      x.valid := y.fire() && y.bits.redirectValid
      x.bits := y.bits
  }

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

  // read int rf from ctrl block
Y
Yinan Xu 已提交
249
  intRf.io.readPorts.zipWithIndex.map{ case(r, i) => r.addr := io.fromCtrlBlock.readRf(i) }
250
  (0 until NRMemReadPorts).foreach(i => io.toMemBlock.readIntRf(i).data := intRf.io.readPorts(i + 8).data)
L
LinJiawei 已提交
251 252
  // write int rf arbiter
  val intWbArbiter = Module(new Wb(
L
LinJiawei 已提交
253 254 255
    (exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn),
    NRIntWritePorts,
    isFp = false
L
LinJiawei 已提交
256 257 258 259 260 261 262 263 264 265 266 267
  ))
  intWbArbiter.io.in <> exeUnits.map(_.io.toInt) ++ io.wakeUpIn.fast ++ io.wakeUpIn.slow

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

  intRf.io.writePorts.zip(intWbArbiter.io.out).foreach{
    case (rf, wb) =>
      rf.wen := wb.valid && wb.bits.uop.ctrl.rfWen
      rf.addr := wb.bits.uop.pdest
      rf.data := wb.bits.data
  }
268
}