xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision d9469c00c0ff92207955dcdff2c9085ea391c88f)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import xiangshan.backend.MDUOpType
7import xiangshan.backend.fu.fpu.FPUOpType.{FU_D2S, FU_DIVSQRT, FU_F2I, FU_FCMP, FU_FMV, FU_S2D}
8import xiangshan.backend.fu.fpu.divsqrt.DivSqrt
9import xiangshan.backend.fu.fpu._
10import xiangshan.backend.fu.fpu.fma.FMA
11
12/*
13    XiangShan Function Unit
14    A Exu can have one or more function units
15 */
16
17trait HasFuLatency {
18  val latencyVal: Option[Int]
19}
20
21case class CertainLatency(value: Int) extends HasFuLatency {
22  override val latencyVal: Option[Int] = Some(value)
23}
24
25case class UncertainLatency() extends HasFuLatency {
26  override val latencyVal: Option[Int] = None
27}
28
29
30case class FuConfig
31(
32  fuGen: () => FunctionUnit,
33  fuSel: FunctionUnit => Bool,
34  fuType: UInt,
35  numIntSrc: Int,
36  numFpSrc: Int,
37  writeIntRf: Boolean,
38  writeFpRf: Boolean,
39  hasRedirect: Boolean,
40  latency: HasFuLatency = CertainLatency(0)
41) {
42  def srcCnt: Int = math.max(numIntSrc, numFpSrc)
43}
44
45
46class FuOutput extends XSBundle {
47  val data = UInt(XLEN.W)
48  val uop = new MicroOp
49}
50
51
52class FunctionUnitIO(len: Int) extends XSBundle {
53  val in = Flipped(DecoupledIO(new Bundle() {
54    val src = Vec(3, UInt(len.W))
55    val uop = new MicroOp
56  }))
57
58  val out = DecoupledIO(new FuOutput)
59
60  val redirectIn = Flipped(ValidIO(new Redirect))
61
62  override def cloneType: FunctionUnitIO.this.type =
63    new FunctionUnitIO(len).asInstanceOf[this.type]
64}
65
66abstract class FunctionUnit(len: Int = 64) extends XSModule {
67
68  val io = IO(new FunctionUnitIO(len))
69
70}
71
72trait HasPipelineReg {
73  this: FunctionUnit =>
74
75  def latency: Int
76
77  require(latency > 0)
78
79  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
80  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
81  val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp))
82
83
84  val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn))
85
86  for (i <- 0 until latency) {
87    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
88  }
89
90  for (i <- 1 to latency) {
91    when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) {
92      validVec(i) := false.B
93    }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) {
94      validVec(i) := validVec(i - 1)
95      uopVec(i) := uopVec(i - 1)
96    }
97  }
98
99  io.in.ready := rdyVec(0)
100  io.out.valid := validVec.last && !flushVec.last
101  io.out.bits.uop := uopVec.last
102
103  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
104    next,
105    enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
106  )
107
108  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
109
110  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
111
112  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
113
114  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
115
116  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
117}
118
119object FunctionUnit extends HasXSParameter {
120
121  def divider = new SRT4Divider(XLEN)
122
123  def multiplier = new ArrayMultiplier(XLEN + 1, Seq(0, 2))
124
125  def alu = new Alu
126
127  def jmp = new Jump
128
129  def fence = new Fence
130
131  def csr = new CSR
132
133  def i2f = new IntToFloatSingleCycle
134
135  def fmac = new FMA
136
137  def fcmp = new FCMP
138
139  def fmv = new FMV(XLEN)
140
141  def f2i = new FloatToInt
142
143  def f32toF64 = new F32toF64
144
145  def f64toF32 = new F64toF32
146
147  def fdivSqrt = new DivSqrt
148
149  def fmiscSel(fu: String)(x: FunctionUnit): Bool = {
150    x.io.in.bits.uop.ctrl.fuOpType.head(4) === s"b$fu".U
151  }
152
153  val aluCfg = FuConfig(
154    fuGen = alu _,
155    fuSel = _ => true.B,
156    fuType = FuType.alu,
157    numIntSrc = 2,
158    numFpSrc = 0,
159    writeIntRf = true,
160    writeFpRf = false,
161    hasRedirect = true
162  )
163
164  val jmpCfg = FuConfig(
165    fuGen = jmp _,
166    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp,
167    fuType = FuType.jmp,
168    numIntSrc = 1,
169    numFpSrc = 0,
170    writeIntRf = true,
171    writeFpRf = false,
172    hasRedirect = true
173  )
174
175  val fenceCfg = FuConfig(
176    fuGen = fence _,
177    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence,
178    FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
179    UncertainLatency() // TODO: need rewrite latency structure, not just this value
180  )
181
182  val csrCfg = FuConfig(
183    fuGen = csr _,
184    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr,
185    fuType = FuType.csr,
186    numIntSrc = 1,
187    numFpSrc = 0,
188    writeIntRf = true,
189    writeFpRf = false,
190    hasRedirect = false
191  )
192
193  val i2fCfg = FuConfig(
194    fuGen = i2f _,
195    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.i2f,
196    FuType.i2f,
197    numIntSrc = 1,
198    numFpSrc = 0,
199    writeIntRf = false,
200    writeFpRf = true,
201    hasRedirect = false,
202    CertainLatency(0)
203  )
204
205  val divCfg = FuConfig(
206    fuGen = divider _,
207    fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType),
208    FuType.div,
209    2,
210    0,
211    writeIntRf = true,
212    writeFpRf = false,
213    hasRedirect = false,
214    UncertainLatency()
215  )
216
217  val mulCfg = FuConfig(
218    fuGen = multiplier _,
219    fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType),
220    FuType.mul,
221    2,
222    0,
223    writeIntRf = true,
224    writeFpRf = false,
225    hasRedirect = false,
226    CertainLatency(3)
227  )
228
229  val fmacCfg = FuConfig(
230    fuGen = fmac _,
231    fuSel = _ => true.B,
232    FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(5)
233  )
234
235  val fcmpCfg = FuConfig(
236    fuGen = fcmp _,
237    fuSel = (x: FunctionUnit) => fmiscSel(FU_FCMP)(x) && x.io.in.bits.uop.ctrl.rfWen,
238    FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
239  )
240
241  val fminCfg = FuConfig(
242    fuGen = fcmp _,
243    fuSel = (x: FunctionUnit) => fmiscSel(FU_FCMP)(x) && x.io.in.bits.uop.ctrl.fpWen,
244    FuType.fmisc, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
245  )
246
247  val fsgnjCfg = FuConfig(
248    fuGen = fmv _,
249    fuSel = (x: FunctionUnit) => fmiscSel(FU_FMV)(x) && x.io.in.bits.uop.ctrl.fpWen,
250    FuType.fmisc, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(1)
251  )
252
253  val fmvCfg = FuConfig(
254    fuGen = fmv _,
255    fuSel = (x: FunctionUnit) => fmiscSel(FU_FMV)(x) && x.io.in.bits.uop.ctrl.rfWen,
256    FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(1)
257  )
258
259  val f2iCfg = FuConfig(
260    fuGen = f2i _,
261    fuSel = fmiscSel(FU_F2I),
262    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
263  )
264
265  val s2dCfg = FuConfig(
266    fuGen = f32toF64 _,
267    fuSel = fmiscSel(FU_S2D),
268    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
269  )
270
271  val d2sCfg = FuConfig(
272    fuGen = f64toF32 _,
273    fuSel = fmiscSel(FU_D2S),
274    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
275  )
276
277  val fdivSqrtCfg = FuConfig(
278    fuGen = fdivSqrt _,
279    fuSel = fmiscSel(FU_DIVSQRT),
280    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
281  )
282
283  val lduCfg = FuConfig(
284    null, // DontCare
285    null,
286    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
287    UncertainLatency()
288  )
289
290  val stuCfg = FuConfig(
291    null,
292    null,
293    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
294    UncertainLatency()
295  )
296
297  val mouCfg = FuConfig(
298    null,
299    null,
300    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
301    UncertainLatency()
302  )
303}
304