xref: /XiangShan/src/main/scala/xiangshan/backend/exu/ExeUnit.scala (revision 730cfbc0bf03569aa07dd82ba3fb41eb7413e13c)
1*730cfbc0SXuan Hupackage xiangshan.backend.exu
2*730cfbc0SXuan Hu
3*730cfbc0SXuan Huimport chipsalliance.rocketchip.config.Parameters
4*730cfbc0SXuan Huimport chisel3._
5*730cfbc0SXuan Huimport chisel3.util._
6*730cfbc0SXuan Huimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
7*730cfbc0SXuan Huimport utils._
8*730cfbc0SXuan Huimport xiangshan.backend.fu.{CSRFileIO, FenceIO, FuncUnitInput}
9*730cfbc0SXuan Huimport xiangshan.backend.Bundles.{ExuInput, ExuOutput, MemExuInput, MemExuOutput}
10*730cfbc0SXuan Huimport xiangshan.{Redirect, XSBundle, XSModule}
11*730cfbc0SXuan Hu
12*730cfbc0SXuan Huclass ExeUnitIO(params: ExeUnitParams)(implicit p: Parameters) extends XSBundle {
13*730cfbc0SXuan Hu  val flush = Flipped(ValidIO(new Redirect()))
14*730cfbc0SXuan Hu  val in = Flipped(DecoupledIO(new ExuInput(params)))
15*730cfbc0SXuan Hu  val out = DecoupledIO(new ExuOutput(params))
16*730cfbc0SXuan Hu  val csrio = if (params.hasCSR) Some(new CSRFileIO) else None
17*730cfbc0SXuan Hu  val fenceio = if (params.hasFence) Some(new FenceIO) else None
18*730cfbc0SXuan Hu  val frm = if (params.needSrcFrm) Some(Input(UInt(3.W))) else None
19*730cfbc0SXuan Hu}
20*730cfbc0SXuan Hu
21*730cfbc0SXuan Huclass ExeUnit(exuParams: ExeUnitParams)(implicit p: Parameters) extends LazyModule {
22*730cfbc0SXuan Hu  lazy val module = new ExeUnitImp(this)(p, exuParams)
23*730cfbc0SXuan Hu}
24*730cfbc0SXuan Hu
25*730cfbc0SXuan Huclass ExeUnitImp(
26*730cfbc0SXuan Hu  override val wrapper: ExeUnit
27*730cfbc0SXuan Hu)(implicit
28*730cfbc0SXuan Hu  p: Parameters, exuParams: ExeUnitParams
29*730cfbc0SXuan Hu) extends LazyModuleImp(wrapper) {
30*730cfbc0SXuan Hu  private val fuCfgs = exuParams.fuConfigs
31*730cfbc0SXuan Hu
32*730cfbc0SXuan Hu  val io = IO(new ExeUnitIO(exuParams))
33*730cfbc0SXuan Hu
34*730cfbc0SXuan Hu  val funcUnits = fuCfgs.map(cfg => {
35*730cfbc0SXuan Hu    val module = cfg.fuGen(p, cfg)
36*730cfbc0SXuan Hu    module
37*730cfbc0SXuan Hu  })
38*730cfbc0SXuan Hu
39*730cfbc0SXuan Hu  val busy = RegInit(false.B)
40*730cfbc0SXuan Hu  val robIdx = RegEnable(io.in.bits.robIdx, io.in.fire)
41*730cfbc0SXuan Hu  when (robIdx.needFlush(io.flush)) {
42*730cfbc0SXuan Hu    busy := false.B
43*730cfbc0SXuan Hu  }.elsewhen(io.out.fire) {
44*730cfbc0SXuan Hu    busy := false.B
45*730cfbc0SXuan Hu  }.elsewhen(io.in.fire) {
46*730cfbc0SXuan Hu    busy := true.B
47*730cfbc0SXuan Hu  }
48*730cfbc0SXuan Hu
49*730cfbc0SXuan Hu  // rob flush --> funcUnits
50*730cfbc0SXuan Hu  funcUnits.zipWithIndex.foreach { case (fu, i) =>
51*730cfbc0SXuan Hu    fu.io.flush <> io.flush
52*730cfbc0SXuan Hu  }
53*730cfbc0SXuan Hu
54*730cfbc0SXuan Hu  def acceptCond(input: ExuInput): Seq[Bool] = {
55*730cfbc0SXuan Hu    input.params.fuConfigs.map(_.fuSel(input))
56*730cfbc0SXuan Hu  }
57*730cfbc0SXuan Hu
58*730cfbc0SXuan Hu  val in1ToN = Module(new Dispatcher(new ExuInput(exuParams), funcUnits.length, acceptCond))
59*730cfbc0SXuan Hu
60*730cfbc0SXuan Hu  // ExeUnit.in <---> Dispatcher.in
61*730cfbc0SXuan Hu  in1ToN.io.in.valid := io.in.valid && !busy
62*730cfbc0SXuan Hu  in1ToN.io.in.bits := io.in.bits
63*730cfbc0SXuan Hu  io.in.ready := !busy
64*730cfbc0SXuan Hu
65*730cfbc0SXuan Hu  // Dispatcher.out <---> FunctionUnits
66*730cfbc0SXuan Hu  in1ToN.io.out.zip(funcUnits.map(_.io.in)).foreach {
67*730cfbc0SXuan Hu    case (source: DecoupledIO[ExuInput], sink: DecoupledIO[FuncUnitInput]) =>
68*730cfbc0SXuan Hu      sink.valid := source.valid
69*730cfbc0SXuan Hu      source.ready := sink.ready
70*730cfbc0SXuan Hu
71*730cfbc0SXuan Hu      sink.bits.src.zip(source.bits.src).foreach { case(fuSrc, exuSrc) => fuSrc := exuSrc }
72*730cfbc0SXuan Hu      sink.bits.fuOpType    := source.bits.fuOpType
73*730cfbc0SXuan Hu      sink.bits.imm         := source.bits.imm
74*730cfbc0SXuan Hu      sink.bits.robIdx      := source.bits.robIdx
75*730cfbc0SXuan Hu      sink.bits.pdest       := source.bits.pdest
76*730cfbc0SXuan Hu      sink.bits.rfWen       .foreach(x => x := source.bits.rfWen.get)
77*730cfbc0SXuan Hu      sink.bits.fpWen       .foreach(x => x := source.bits.fpWen.get)
78*730cfbc0SXuan Hu      sink.bits.vecWen      .foreach(x => x := source.bits.vecWen.get)
79*730cfbc0SXuan Hu      sink.bits.fpu         .foreach(x => x := source.bits.fpu.get)
80*730cfbc0SXuan Hu      sink.bits.flushPipe   .foreach(x => x := source.bits.flushPipe.get)
81*730cfbc0SXuan Hu      sink.bits.pc          .foreach(x => x := source.bits.pc.get)
82*730cfbc0SXuan Hu      sink.bits.preDecode   .foreach(x => x := source.bits.preDecode.get)
83*730cfbc0SXuan Hu      sink.bits.ftqIdx      .foreach(x => x := source.bits.ftqIdx.get)
84*730cfbc0SXuan Hu      sink.bits.ftqOffset   .foreach(x => x := source.bits.ftqOffset.get)
85*730cfbc0SXuan Hu      sink.bits.predictInfo .foreach(x => x := source.bits.predictInfo.get)
86*730cfbc0SXuan Hu  }
87*730cfbc0SXuan Hu
88*730cfbc0SXuan Hu  private val fuOutValidOH = funcUnits.map(_.io.out.valid)
89*730cfbc0SXuan Hu  private val fuOutBitsVec = funcUnits.map(_.io.out.bits)
90*730cfbc0SXuan Hu  private val fuRedirectVec: Seq[Option[ValidIO[Redirect]]] = funcUnits.map(_.io.out.bits.redirect)
91*730cfbc0SXuan Hu
92*730cfbc0SXuan Hu  // Assume that one fu can only write int or fp or vec,
93*730cfbc0SXuan Hu  // otherwise, wenVec should be assigned to wen in fu.
94*730cfbc0SXuan Hu  private val fuIntWenVec = funcUnits.map(_.cfg.writeIntRf.B)
95*730cfbc0SXuan Hu  private val fuFpWenVec = funcUnits.map(_.cfg.writeFpRf.B)
96*730cfbc0SXuan Hu  private val fuVecWenVec = funcUnits.map(_.cfg.writeVecRf.B)
97*730cfbc0SXuan Hu  // FunctionUnits <---> ExeUnit.out
98*730cfbc0SXuan Hu  io.out.valid := Cat(fuOutValidOH).orR
99*730cfbc0SXuan Hu  funcUnits.foreach(fu => fu.io.out.ready := io.out.ready)
100*730cfbc0SXuan Hu
101*730cfbc0SXuan Hu  // select one fu's result
102*730cfbc0SXuan Hu  io.out.bits.data := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.data))
103*730cfbc0SXuan Hu  io.out.bits.robIdx := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.robIdx))
104*730cfbc0SXuan Hu  io.out.bits.pdest := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.pdest))
105*730cfbc0SXuan Hu  io.out.bits.intWen.foreach(x => x := Mux1H(fuOutValidOH, fuIntWenVec))
106*730cfbc0SXuan Hu  io.out.bits.fpWen.foreach(x => x := Mux1H(fuOutValidOH, fuFpWenVec))
107*730cfbc0SXuan Hu  io.out.bits.vecWen.foreach(x => x := Mux1H(fuOutValidOH, fuVecWenVec))
108*730cfbc0SXuan Hu  io.out.bits.redirect.foreach(x => x := Mux1H((fuOutValidOH zip fuRedirectVec).filter(_._2.isDefined).map(x => (x._1, x._2.get))))
109*730cfbc0SXuan Hu  io.out.bits.fflags.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.fflags.getOrElse(0.U.asTypeOf(io.out.bits.fflags.get)))))
110*730cfbc0SXuan Hu  io.out.bits.exceptionVec.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.exceptionVec.getOrElse(0.U.asTypeOf(io.out.bits.exceptionVec.get)))))
111*730cfbc0SXuan Hu  io.out.bits.flushPipe.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.flushPipe.getOrElse(0.U.asTypeOf(io.out.bits.flushPipe.get)))))
112*730cfbc0SXuan Hu  io.out.bits.replay.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.replay.getOrElse(0.U.asTypeOf(io.out.bits.replay.get)))))
113*730cfbc0SXuan Hu  io.out.bits.predecodeInfo.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.preDecode.getOrElse(0.U.asTypeOf(io.out.bits.predecodeInfo.get)))))
114*730cfbc0SXuan Hu
115*730cfbc0SXuan Hu  io.csrio.foreach(exuio => funcUnits.foreach(fu => fu.io.csrio.foreach(fuio => exuio <> fuio)))
116*730cfbc0SXuan Hu  io.fenceio.foreach(exuio => funcUnits.foreach(fu => fu.io.fenceio.foreach(fuio => fuio <> exuio)))
117*730cfbc0SXuan Hu  io.frm.foreach(exuio => funcUnits.foreach(fu => fu.io.frm.foreach(fuio => fuio <> exuio)))
118*730cfbc0SXuan Hu
119*730cfbc0SXuan Hu  // debug info
120*730cfbc0SXuan Hu  io.out.bits.debug     := 0.U.asTypeOf(io.out.bits.debug)
121*730cfbc0SXuan Hu  io.out.bits.debugInfo := 0.U.asTypeOf(io.out.bits.debugInfo)
122*730cfbc0SXuan Hu}
123*730cfbc0SXuan Hu
124*730cfbc0SXuan Huclass DispatcherIO[T <: Data](private val gen: T, n: Int) extends Bundle {
125*730cfbc0SXuan Hu  val in = Flipped(DecoupledIO(gen))
126*730cfbc0SXuan Hu
127*730cfbc0SXuan Hu  val out = Vec(n, DecoupledIO(gen))
128*730cfbc0SXuan Hu}
129*730cfbc0SXuan Hu
130*730cfbc0SXuan Huclass Dispatcher[T <: Data](private val gen: T, n: Int, acceptCond: T => Seq[Bool])
131*730cfbc0SXuan Hu  (implicit p: Parameters)
132*730cfbc0SXuan Hu  extends Module {
133*730cfbc0SXuan Hu
134*730cfbc0SXuan Hu  val io = IO(new DispatcherIO(gen, n))
135*730cfbc0SXuan Hu
136*730cfbc0SXuan Hu  private val acceptVec: Vec[Bool] = VecInit(acceptCond(io.in.bits))
137*730cfbc0SXuan Hu
138*730cfbc0SXuan Hu  XSError(io.in.valid && PopCount(acceptVec) > 1.U, s"s[ExeUnit] accept vec should no more than 1, ${Binary(acceptVec.asUInt)} ")
139*730cfbc0SXuan Hu  XSError(io.in.valid && PopCount(acceptVec) === 0.U, "[ExeUnit] there is a inst not dispatched to any fu")
140*730cfbc0SXuan Hu
141*730cfbc0SXuan Hu  io.out.zipWithIndex.foreach { case (out, i) =>
142*730cfbc0SXuan Hu    out.valid := acceptVec(i) && io.in.valid && out.ready
143*730cfbc0SXuan Hu    out.bits := io.in.bits
144*730cfbc0SXuan Hu  }
145*730cfbc0SXuan Hu
146*730cfbc0SXuan Hu  io.in.ready := Cat(io.out.map(_.ready)).orR
147*730cfbc0SXuan Hu}
148*730cfbc0SXuan Hu
149*730cfbc0SXuan Huclass MemExeUnitIO (implicit p: Parameters) extends XSBundle {
150*730cfbc0SXuan Hu  val flush = Flipped(ValidIO(new Redirect()))
151*730cfbc0SXuan Hu  val in = Flipped(DecoupledIO(new MemExuInput()))
152*730cfbc0SXuan Hu  val out = DecoupledIO(new MemExuOutput())
153*730cfbc0SXuan Hu}
154*730cfbc0SXuan Hu
155*730cfbc0SXuan Huclass MemExeUnit(exuParams: ExeUnitParams)(implicit p: Parameters) extends XSModule {
156*730cfbc0SXuan Hu  val io = IO(new MemExeUnitIO)
157*730cfbc0SXuan Hu  require(exuParams.fuConfigs.size == 1, "[MemExeUnit] only support one fu yet")
158*730cfbc0SXuan Hu  val fu = exuParams.fuConfigs.head.fuGen(p, exuParams.fuConfigs.head)
159*730cfbc0SXuan Hu  fu.io.flush             := io.flush
160*730cfbc0SXuan Hu  fu.io.in.valid          := io.in.valid
161*730cfbc0SXuan Hu  io.in.ready             := fu.io.in.ready
162*730cfbc0SXuan Hu
163*730cfbc0SXuan Hu  fu.io.in.bits.robIdx    := io.in.bits.uop.robIdx
164*730cfbc0SXuan Hu  fu.io.in.bits.pdest     := io.in.bits.uop.pdest
165*730cfbc0SXuan Hu  fu.io.in.bits.fuOpType  := io.in.bits.uop.fuOpType
166*730cfbc0SXuan Hu  fu.io.in.bits.imm       := io.in.bits.uop.imm
167*730cfbc0SXuan Hu  fu.io.in.bits.src.zip(io.in.bits.src).foreach(x => x._1 := x._2)
168*730cfbc0SXuan Hu
169*730cfbc0SXuan Hu  io.out.valid            := fu.io.out.valid
170*730cfbc0SXuan Hu  fu.io.out.ready         := io.out.ready
171*730cfbc0SXuan Hu
172*730cfbc0SXuan Hu  io.out.bits             := 0.U.asTypeOf(io.out.bits) // dontCare other fields
173*730cfbc0SXuan Hu  io.out.bits.data        := fu.io.out.bits.data
174*730cfbc0SXuan Hu  io.out.bits.uop.robIdx  := fu.io.out.bits.robIdx
175*730cfbc0SXuan Hu  io.out.bits.uop.pdest   := fu.io.out.bits.pdest
176*730cfbc0SXuan Hu  io.out.bits.uop.fuType  := io.in.bits.uop.fuType
177*730cfbc0SXuan Hu  io.out.bits.uop.fuOpType:= io.in.bits.uop.fuOpType
178*730cfbc0SXuan Hu  io.out.bits.uop.sqIdx   := io.in.bits.uop.sqIdx
179*730cfbc0SXuan Hu
180*730cfbc0SXuan Hu  io.out.bits.debug       := 0.U.asTypeOf(io.out.bits.debug)
181*730cfbc0SXuan Hu}
182