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

import chisel3._
import chisel3.util._
import xiangshan._
L
LinJiawei 已提交
6 7
import xiangshan.backend.exu.Exu.{jumpExeUnitCfg, ldExeUnitCfg, stExeUnitCfg}
import xiangshan.backend.exu.{AluExeUnit, ExuConfig, JumpExeUnit, MulDivExeUnit, Wb}
L
LinJiawei 已提交
8
import xiangshan.backend.fu.FenceToSbuffer
L
LinJiawei 已提交
9 10
import xiangshan.backend.issue.ReservationStationNew
import xiangshan.backend.regfile.Regfile
Y
Yinan Xu 已提交
11
import xiangshan.backend.fu.fpu.Fflags
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 44 45
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
  }
}

L
LinJiawei 已提交
46 47
class IntegerBlock
(
L
LinJiawei 已提交
48 49 50 51 52 53 54
  fastWakeUpIn: Seq[ExuConfig],
  slowWakeUpIn: Seq[ExuConfig],
  fastFpOut: Seq[ExuConfig],
  slowFpOut: Seq[ExuConfig],
  fastIntOut: Seq[ExuConfig],
  slowIntOut: Seq[ExuConfig]
) extends XSModule with HasExeBlockHelper with NeedImpl
L
LinJiawei 已提交
55
{
56 57 58
  val io = IO(new Bundle {
    val fromCtrlBlock = Flipped(new CtrlToIntBlockIO)
    val toCtrlBlock = new IntBlockToCtrlIO
L
LinJiawei 已提交
59

L
LinJiawei 已提交
60 61 62
    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 已提交
63

Y
Yinan Xu 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    val csrio = new Bundle {
      val fflags = Input(new Fflags) // from roq
      val dirty_fs = Input(Bool()) // from roq
      val exception = Flipped(ValidIO(new MicroOp)) // from roq
      val isInterrupt = Input(Bool()) // from roq
      val trapTarget = Output(UInt(VAddrBits.W)) // to roq
      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
    }
    val fenceio = new Bundle {
      val sfence = IO(Output(new SfenceBundle)) // to front,mem
      val fencei = IO(Output(Bool()))           // to icache
      val sbuffer = IO(new FenceToSbuffer)      // to mem
    }
80
  })
L
LinJiawei 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

  val redirect = io.fromCtrlBlock.redirect

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

  val aluExeUnits = Array.tabulate(exuParameters.AluCnt)(_ => Module(new AluExeUnit))
  val jmpExeUnit = Module(new JumpExeUnit)
  val mduExeUnits = Array.tabulate(exuParameters.MduCnt)(_ => Module(new MulDivExeUnit))

  val exeUnits = jmpExeUnit +: (aluExeUnits ++ mduExeUnits)

  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)

Y
Yinan Xu 已提交
103
  val reservationStations = exeUnits.map(_.config).zipWithIndex.map({ case (cfg, i) =>
L
LinJiawei 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    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)
    val writeBackData = inBlockWbData ++ io.wakeUpIn.fast.map(_.bits.data)
    val wakeupCnt = writeBackData.length

    val inBlockListenPorts = exeUnits.filter(e => e.config.hasUncertainlatency && readIntRf).map(_.io.toInt)
    val extraListenPorts = inBlockListenPorts ++ io.wakeUpIn.slow
    val extraListenPortsCnt = extraListenPorts.length

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

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

    val rs = Module(new ReservationStationNew(
      cfg, wakeupCnt, extraListenPortsCnt, fixedDelay = certainLatency, feedback = feedback
    ))

    rs.io.redirect <> redirect
    rs.io.numExist <> io.toCtrlBlock.numExist(i)
    rs.io.enqCtrl <> io.fromCtrlBlock.enqIqCtrl(i)
    rs.io.enqData <> io.fromCtrlBlock.enqIqData(i)

    rs.io.writeBackedData <> writeBackData
    for ((x, y) <- rs.io.extraListenPorts.zip(extraListenPorts)) {
      x.valid := y.fire()
      x.bits := y.bits
    }

    exeUnits(i).io.redirect <> redirect
    exeUnits(i).io.fromInt <> rs.io.deq
    rs.io.tlbFeedback := DontCare

    rs.suggestName(s"rs_${cfg.name}")

    rs
  })

Y
Yinan Xu 已提交
147 148
  for(rs <- reservationStations){
    val inBlockUops = reservationStations.filter(x =>
L
LinJiawei 已提交
149 150 151 152 153 154 155 156 157
      x.exuCfg.hasCertainLatency && x.exuCfg.writeIntRf
    ).map(x => {
      val raw = WireInit(x.io.selectedUop)
      raw.valid := x.io.selectedUop.valid && raw.bits.ctrl.rfWen
      raw
    })
    rs.io.broadcastedUops <> inBlockUops ++ io.wakeUpIn.fastUops
  }

Y
Yinan Xu 已提交
158
  io.wakeUpFpOut.fastUops <> reservationStations.filter(
L
LinJiawei 已提交
159 160 161 162 163 164 165 166 167 168 169
    rs => fpFastFilter(rs.exuCfg)
  ).map(_.io.selectedUop)

  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 已提交
170
  io.wakeUpIntOut.fastUops <> reservationStations.filter(
L
LinJiawei 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    rs => intFastFilter(rs.exuCfg)
  ).map(_.io.selectedUop)

  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 已提交
191 192
  jmpExeUnit.csrio <> io.csrio
  jmpExeUnit.fenceio <> io.fenceio
L
LinJiawei 已提交
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

  // read int rf from ctrl block
  intRf.io.readPorts <> io.fromCtrlBlock.readRf
  // write int rf arbiter
  val intWbArbiter = Module(new Wb(
    (exeUnits.map(_.config) ++ fastWakeUpIn ++ slowWakeUpIn).map(_.wbIntPriority),
    NRIntWritePorts
  ))
  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
  }
212
}