xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuncUnit.scala (revision 3f6c8c2c7f193660d0823208dbcd36d7cec65f50)
1package xiangshan.backend.fu
2
3import chipsalliance.rocketchip.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.fpu.Bundles.Fflags
14import xiangshan.backend.fu.vector.Bundles.Vxsat
15
16class FuncUnitCtrlInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
17  val fuOpType    = FuOpType()
18  val robIdx      = new RobPtr
19  val pdest       = UInt(PhyRegIdxWidth.W)
20  val rfWen       = OptionWrapper(cfg.writeIntRf, Bool())
21  val fpWen       = OptionWrapper(cfg.writeFpRf,  Bool())
22  val vecWen      = OptionWrapper(cfg.writeVecRf, Bool())
23  val flushPipe   = OptionWrapper(cfg.flushPipe,  Bool())
24  val preDecode   = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo)
25  val ftqIdx      = OptionWrapper(cfg.needPc || cfg.replayInst, new FtqPtr)
26  val ftqOffset   = OptionWrapper(cfg.needPc || cfg.replayInst, UInt(log2Up(PredictWidth).W))
27  val predictInfo = OptionWrapper(cfg.hasRedirect, new Bundle {
28    val target    = UInt(VAddrData().dataWidth.W)
29    val taken     = Bool()
30  })
31  val fpu         = OptionWrapper(cfg.needFPUCtrl, new FPUCtrlSignals)
32  val vpu         = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals)
33}
34
35class FuncUnitCtrlOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
36  val robIdx        = new RobPtr
37  val pdest         = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs
38  val rfWen         = OptionWrapper(cfg.writeIntRf, Bool())
39  val fpWen         = OptionWrapper(cfg.writeFpRf,  Bool())
40  val vecWen        = OptionWrapper(cfg.writeVecRf, Bool())
41  val exceptionVec  = OptionWrapper(cfg.exceptionOut.nonEmpty, ExceptionVec())
42  val flushPipe     = OptionWrapper(cfg.flushPipe,  Bool())
43  val replay        = OptionWrapper(cfg.replayInst, Bool())
44  val preDecode     = OptionWrapper(cfg.hasPredecode, new PreDecodeInfo)
45  val fpu           = OptionWrapper(cfg.needFPUCtrl, new FPUCtrlSignals) // only used in FMA
46  val vpu           = OptionWrapper(cfg.needVecCtrl, new VPUCtrlSignals)
47}
48
49class FuncUnitDataInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
50  val src       = MixedVec(cfg.genSrcDataVec)
51  val imm       = UInt(cfg.dataBits.W)
52  val pc        = OptionWrapper(cfg.needPc, UInt(VAddrData().dataWidth.W))
53}
54
55class FuncUnitDataOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
56  val data      = UInt(cfg.dataBits.W)
57  val fflags    = OptionWrapper(cfg.writeFflags, Fflags())
58  val vxsat     = OptionWrapper(cfg.writeVxsat, Vxsat())
59  val pc        = OptionWrapper(cfg.isFence, UInt(VAddrData().dataWidth.W))
60  val redirect  = OptionWrapper(cfg.hasRedirect, ValidIO(new Redirect))
61}
62
63class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
64  val ctrl = new FuncUnitCtrlInput(cfg)
65  val data = new FuncUnitDataInput(cfg)
66}
67
68class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
69  val ctrl = new FuncUnitCtrlOutput(cfg)
70  val res = new FuncUnitDataOutput(cfg)
71}
72
73class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
74  val flush = Flipped(ValidIO(new Redirect))
75  val in = Flipped(DecoupledIO(new FuncUnitInput(cfg)))
76  val out = DecoupledIO(new FuncUnitOutput(cfg))
77  val csrio = if (cfg.isCsr) Some(new CSRFileIO) else None
78  val fenceio = if (cfg.isFence) Some(new FenceIO) else None
79  val frm = if (cfg.needSrcFrm) Some(Input(UInt(3.W))) else None
80}
81
82abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule {
83  val io = IO(new FuncUnitIO(cfg))
84
85  // should only be used in non-piped fu
86  def connectNonPipedCtrlSingal: Unit = {
87    io.out.bits.ctrl.robIdx   := DataHoldBypass(io.in.bits.ctrl.robIdx, io.in.fire)
88    io.out.bits.ctrl.pdest    := DataHoldBypass(io.in.bits.ctrl.pdest, io.in.fire)
89    io.out.bits.ctrl.preDecode.foreach(_ := DataHoldBypass(io.in.bits.ctrl.preDecode.get, io.in.fire))
90    io.out.bits.ctrl.fpu      .foreach(_ := DataHoldBypass(io.in.bits.ctrl.fpu.get,    io.in.fire))
91  }
92}
93
94/**
95  * @author LinJiaWei, Yinan Xu
96  */
97trait HasPipelineReg { this: FuncUnit =>
98  def latency: Int
99
100  require(latency > 0)
101
102  val validVec = io.in.valid +: Seq.fill(latency)(RegInit(false.B))
103  val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ io.out.ready
104//  val ctrlVec = io.in.bits.ctrl +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl)))
105//  val dataVec = io.in.bits.data +: Seq.fill(latency)(Reg(chiselTypeOf(io.in.bits.data)))
106
107  val robIdxVec = io.in.bits.ctrl.robIdx +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl.robIdx)))
108  val pdestVec = io.in.bits.ctrl.pdest +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.ctrl.pdest)))
109
110  val pcVec = io.in.bits.data.pc.map(x => x) +: Array.fill(latency)( io.in.bits.data.pc.map(x => Reg(chiselTypeOf(x)))) // Reg(chiselTypeOf(io.in.bits.pc.get))
111  val preDecodeVec = io.in.bits.ctrl.preDecode.map(x => x) +: Array.fill(latency)(io.in.bits.ctrl.preDecode.map(x => Reg(chiselTypeOf(x))))
112  val fpuVec = io.in.bits.ctrl.fpu.map(x => x) +: Array.fill(latency)(io.in.bits.ctrl.fpu.map(x => Reg(chiselTypeOf(x))))
113
114  // if flush(0), valid 0 will not given, so set flushVec(0) to false.B
115  val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush))
116
117  for (i <- 0 until latency) {
118    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
119  }
120
121  for (i <- 1 until latency) {
122    when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){
123      validVec(i) := validVec(i - 1)
124      robIdxVec(i) := robIdxVec(i - 1)
125      pdestVec(i) := pdestVec(i - 1)
126      pcVec(i).zip(pcVec(i - 1)).foreach{case (l,r) => l := r}
127      preDecodeVec(i).zip(preDecodeVec(i - 1)).foreach{case (l,r) => l := r}
128      fpuVec(i).zip(fpuVec(i - 1)).foreach{case (l,r) => l := r}
129    }.elsewhen(flushVec(i) || rdyVec(i)){
130      validVec(i) := false.B
131    }
132  }
133
134  io.in.ready := rdyVec(0)
135  io.out.valid := validVec.last
136  io.out.bits.ctrl.robIdx := robIdxVec.last
137  io.out.bits.ctrl.pdest := pdestVec.last
138  io.out.bits.res.pc.zip(pcVec.last).foreach{case (l,r) => l := r}
139  io.out.bits.ctrl.preDecode.zip(preDecodeVec.last).foreach{case (l,r) => l := r}
140  io.out.bits.ctrl.fpu.zip(fpuVec.last).foreach{case (l,r) => l := r}
141
142  def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
143
144  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
145    next,
146    regEnable(i)
147  )
148
149  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
150
151  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
152
153  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
154
155  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
156
157  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
158
159}
160
161
162