xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuncUnit.scala (revision 550efd167a12656ee17ca93e5aa938ea7d63fa23)
1package xiangshan.backend.fu
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.DataHoldBypass
7import utils.OptionWrapper
8import xiangshan._
9import xiangshan.backend.Bundles.VPUCtrlSignals
10import xiangshan.backend.rob.RobPtr
11import xiangshan.frontend.{FtqPtr, PreDecodeInfo}
12import xiangshan.backend.datapath.DataConfig._
13import xiangshan.backend.fu.vector.Bundles.Vxsat
14import xiangshan.ExceptionNO.illegalInstr
15import xiangshan.backend.fu.vector.Bundles.VType
16
17class FuncUnitCtrlInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
18  val fuOpType    = FuOpType()
19  val robIdx      = new RobPtr
20  val pdest       = UInt(PhyRegIdxWidth.W)
21  val rfWen       = OptionWrapper(cfg.needIntWen, Bool())
22  val fpWen       = OptionWrapper(cfg.needFpWen,  Bool())
23  val vecWen      = OptionWrapper(cfg.needVecWen, Bool())
24  val flushPipe   = OptionWrapper(cfg.flushPipe,  Bool())
25  val preDecode   = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo)
26  val ftqIdx      = OptionWrapper(cfg.needPc || cfg.replayInst || cfg.isSta, new FtqPtr)
27  val ftqOffset   = OptionWrapper(cfg.needPc || cfg.replayInst || cfg.isSta, UInt(log2Up(PredictWidth).W))
28  val predictInfo = OptionWrapper(cfg.hasRedirect, new Bundle {
29    val target    = UInt(VAddrData().dataWidth.W)
30    val taken     = Bool()
31  })
32  val fpu         = OptionWrapper(cfg.writeFflags, new FPUCtrlSignals)
33  val vpu         = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals)
34}
35
36class FuncUnitCtrlOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
37  val robIdx        = new RobPtr
38  val pdest         = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs
39  val rfWen         = OptionWrapper(cfg.needIntWen, Bool())
40  val fpWen         = OptionWrapper(cfg.needFpWen,  Bool())
41  val vecWen        = OptionWrapper(cfg.needVecWen, Bool())
42  val exceptionVec  = OptionWrapper(cfg.exceptionOut.nonEmpty, ExceptionVec())
43  val flushPipe     = OptionWrapper(cfg.flushPipe,  Bool())
44  val replay        = OptionWrapper(cfg.replayInst, Bool())
45  val preDecode     = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo)
46  val fpu           = OptionWrapper(cfg.writeFflags, new FPUCtrlSignals)
47  val vpu           = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals)
48}
49
50class FuncUnitDataInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
51  val src       = MixedVec(cfg.genSrcDataVec)
52  val imm       = UInt(cfg.dataBits.W)
53  val pc        = OptionWrapper(cfg.needPc, UInt(VAddrData().dataWidth.W))
54
55  def getSrcVConfig : UInt = src(cfg.vconfigIdx)
56  def getSrcMask    : UInt = src(cfg.maskSrcIdx)
57}
58
59class FuncUnitDataOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
60  val data      = UInt(cfg.dataBits.W)
61  val fflags    = OptionWrapper(cfg.writeFflags, UInt(5.W))
62  val vxsat     = OptionWrapper(cfg.writeVxsat, Vxsat())
63  val pc        = OptionWrapper(cfg.isFence, UInt(VAddrData().dataWidth.W))
64  val redirect  = OptionWrapper(cfg.hasRedirect, ValidIO(new Redirect))
65}
66
67class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
68  val ctrl = new FuncUnitCtrlInput(cfg)
69  val data = new FuncUnitDataInput(cfg)
70  val perfDebugInfo = new PerfDebugInfo()
71}
72
73class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
74  val ctrl = new FuncUnitCtrlOutput(cfg)
75  val res = new FuncUnitDataOutput(cfg)
76  val perfDebugInfo = new PerfDebugInfo()
77}
78
79class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
80  val flush = Flipped(ValidIO(new Redirect))
81  val in = Flipped(DecoupledIO(new FuncUnitInput(cfg)))
82  val out = DecoupledIO(new FuncUnitOutput(cfg))
83  val csrio = OptionWrapper(cfg.isCsr, new CSRFileIO)
84  val fenceio = OptionWrapper(cfg.isFence, new FenceIO)
85  val frm = OptionWrapper(cfg.needSrcFrm, Input(UInt(3.W)))
86  val vxrm = OptionWrapper(cfg.needSrcVxrm, Input(UInt(2.W)))
87  val vtype = OptionWrapper(cfg.writeVConfig, new VType)
88  val vlIsZero = OptionWrapper(cfg.writeVConfig, Output(Bool()))
89  val vlIsVlmax = OptionWrapper(cfg.writeVConfig, Output(Bool()))
90}
91
92abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule {
93  val io = IO(new FuncUnitIO(cfg))
94
95  // should only be used in non-piped fu
96  def connectNonPipedCtrlSingal: Unit = {
97    io.out.bits.ctrl.robIdx := RegEnable(io.in.bits.ctrl.robIdx, io.in.fire)
98    io.out.bits.ctrl.pdest  := RegEnable(io.in.bits.ctrl.pdest, io.in.fire)
99    io.out.bits.ctrl.rfWen  .foreach(_ := RegEnable(io.in.bits.ctrl.rfWen.get, io.in.fire))
100    io.out.bits.ctrl.fpWen  .foreach(_ := RegEnable(io.in.bits.ctrl.fpWen.get, io.in.fire))
101    io.out.bits.ctrl.vecWen .foreach(_ := RegEnable(io.in.bits.ctrl.vecWen.get, io.in.fire))
102    // io.out.bits.ctrl.flushPipe should be connected in fu
103    io.out.bits.ctrl.preDecode.foreach(_ := RegEnable(io.in.bits.ctrl.preDecode.get, io.in.fire))
104    io.out.bits.ctrl.fpu      .foreach(_ := RegEnable(io.in.bits.ctrl.fpu.get, io.in.fire))
105    io.out.bits.ctrl.vpu      .foreach(_ := RegEnable(io.in.bits.ctrl.vpu.get, io.in.fire))
106    io.out.bits.perfDebugInfo := RegEnable(io.in.bits.perfDebugInfo, io.in.fire)
107  }
108
109  def connect0LatencyCtrlSingal: Unit = {
110    io.out.bits.ctrl.robIdx := io.in.bits.ctrl.robIdx
111    io.out.bits.ctrl.pdest := io.in.bits.ctrl.pdest
112    io.out.bits.ctrl.rfWen.foreach(_ := io.in.bits.ctrl.rfWen.get)
113    io.out.bits.ctrl.fpWen.foreach(_ := io.in.bits.ctrl.fpWen.get)
114    io.out.bits.ctrl.vecWen.foreach(_ := io.in.bits.ctrl.vecWen.get)
115    // io.out.bits.ctrl.flushPipe should be connected in fu
116    io.out.bits.ctrl.preDecode.foreach(_ := io.in.bits.ctrl.preDecode.get)
117    io.out.bits.ctrl.fpu.foreach(_ := io.in.bits.ctrl.fpu.get)
118    io.out.bits.ctrl.vpu.foreach(_ := io.in.bits.ctrl.vpu.get)
119    io.out.bits.perfDebugInfo := io.in.bits.perfDebugInfo
120  }
121}
122
123/**
124  * @author LinJiaWei, Yinan Xu
125  */
126trait HasPipelineReg { this: FuncUnit =>
127  def latency: Int
128
129  val latdiff :Int = cfg.latency.extraLatencyVal.getOrElse(0)
130  val preLat :Int = latency - latdiff
131  require(latency >= 0 && latdiff >=0)
132
133  def pipelineReg(init: FuncUnitInput , valid:Bool, ready: Bool,latency: Int, flush:ValidIO[Redirect]): (Seq[FuncUnitInput],Seq[Bool],Seq[Bool])={
134    val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ ready
135    val validVec = valid +: Seq.fill(latency)(RegInit(false.B))
136    val ctrlVec = init.ctrl +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl)))
137    val dataVec = init.data +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.data)))
138    val perfVec = init.perfDebugInfo +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.perfDebugInfo)))
139
140
141
142    val robIdxVec = ctrlVec.map(_.robIdx)
143
144    // if flush(0), valid 0 will not given, so set flushVec(0) to false.B
145    val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(flush))
146
147    for (i <- 0 until latency) {
148      rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1).asTypeOf(Bool())
149    }
150    for (i <- 1 to latency) {
151      when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) {
152        validVec(i) := validVec(i - 1)
153        ctrlVec(i) := ctrlVec(i - 1)
154        dataVec(i) := dataVec(i - 1)
155        perfVec(i) := perfVec(i - 1)
156      }.elsewhen(flushVec(i) || rdyVec(i)) {
157        validVec(i) := false.B
158      }
159    }
160
161    (ctrlVec.zip(dataVec).zip(perfVec).map{
162      case(( ctrl,data), perf) => {
163        val out = Wire(new FuncUnitInput(cfg))
164        out.ctrl := ctrl
165        out.data := data
166        out.perfDebugInfo := perf
167        out
168      }
169    },validVec, rdyVec)
170  }
171  val (pipeReg : Seq[FuncUnitInput],validVec ,rdyVec ) = pipelineReg(io.in.bits, io.in.valid,io.out.ready,preLat, io.flush)
172  val ctrlVec = pipeReg.map(_.ctrl)
173  val dataVec = pipeReg.map(_.data)
174  val perfVec = pipeReg.map(_.perfDebugInfo)
175  val robIdxVec = ctrlVec.map(_.robIdx)
176  val pipeflushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush))
177
178
179  val fixtiminginit = Wire(new FuncUnitInput(cfg))
180  fixtiminginit.ctrl := ctrlVec.last
181  fixtiminginit.data := dataVec.last
182  fixtiminginit.perfDebugInfo := perfVec.last
183
184  // fixtiming pipelinereg
185  val (fixpipeReg : Seq[FuncUnitInput], fixValidVec, fixRdyVec) = pipelineReg(fixtiminginit, validVec.last,rdyVec.head ,latdiff, io.flush)
186  val fixCtrlVec = fixpipeReg.map(_.ctrl)
187  val fixDataVec = fixpipeReg.map(_.data)
188  val fixPerfVec = fixpipeReg.map(_.perfDebugInfo)
189  val fixrobIdxVec = ctrlVec.map(_.robIdx)
190  val fixflushVec = fixValidVec.zip(fixrobIdxVec).map(x => x._1 && x._2.needFlush(io.flush))
191  val flushVec = pipeflushVec ++ fixflushVec
192  val pcVec = fixDataVec.map(_.pc)
193
194  io.in.ready := fixRdyVec.head
195  io.out.valid := fixValidVec.last
196  io.out.bits.res.pc.zip(pcVec.last).foreach { case (l, r) => l := r }
197
198  io.out.bits.ctrl.robIdx := fixCtrlVec.last.robIdx
199  io.out.bits.ctrl.pdest := fixCtrlVec.last.pdest
200  io.out.bits.ctrl.rfWen.foreach(_ := fixCtrlVec.last.rfWen.get)
201  io.out.bits.ctrl.fpWen.foreach(_ := fixCtrlVec.last.fpWen.get)
202  io.out.bits.ctrl.vecWen.foreach(_ := fixCtrlVec.last.vecWen.get)
203  io.out.bits.ctrl.fpu.foreach(_ := fixCtrlVec.last.fpu.get)
204  io.out.bits.ctrl.vpu.foreach(_ := fixCtrlVec.last.vpu.get)
205  io.out.bits.perfDebugInfo := fixPerfVec.last
206
207  // vstart illegal
208  if (cfg.exceptionOut.nonEmpty) {
209    val outVstart = fixCtrlVec.last.vpu.get.vstart
210    val vstartIllegal = outVstart =/= 0.U
211    io.out.bits.ctrl.exceptionVec.get := 0.U.asTypeOf(io.out.bits.ctrl.exceptionVec.get)
212    io.out.bits.ctrl.exceptionVec.get(illegalInstr) := vstartIllegal
213  }
214
215  def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
216
217  def PipelineReg[TT <: Data](i: Int)(next: TT) = {
218    val lat = preLat min i
219    RegEnable(
220      next,
221      regEnable(lat)
222    )
223  }
224
225  def SNReg[TT <: Data](in: TT, n: Int): TT ={
226    val lat = preLat min n
227    var next = in
228    for (i <- 1 to lat) {
229      next = PipelineReg[TT](i)(next)
230    }
231    next
232  }
233
234  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
235
236  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
237
238  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
239
240  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
241
242  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
243
244}
245
246abstract class PipedFuncUnit(override val cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
247  with HasPipelineReg {
248  override def latency: Int = cfg.latency.latencyVal.get
249}
250