xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision c7658a75968a011d92bf164a1a55872e64f06d44)
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  )
180
181  val csrCfg = FuConfig(
182    fuGen = csr _,
183    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr,
184    fuType = FuType.csr,
185    numIntSrc = 1,
186    numFpSrc = 0,
187    writeIntRf = true,
188    writeFpRf = false,
189    hasRedirect = false
190  )
191
192  val i2fCfg = FuConfig(
193    fuGen = i2f _,
194    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.i2f,
195    FuType.i2f,
196    numIntSrc = 1,
197    numFpSrc = 0,
198    writeIntRf = false,
199    writeFpRf = true,
200    hasRedirect = false,
201    CertainLatency(0)
202  )
203
204  val divCfg = FuConfig(
205    fuGen = divider _,
206    fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType),
207    FuType.div,
208    2,
209    0,
210    writeIntRf = true,
211    writeFpRf = false,
212    hasRedirect = false,
213    UncertainLatency()
214  )
215
216  val mulCfg = FuConfig(
217    fuGen = multiplier _,
218    fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType),
219    FuType.mul,
220    2,
221    0,
222    writeIntRf = true,
223    writeFpRf = false,
224    hasRedirect = false,
225    CertainLatency(3)
226  )
227
228  val fmacCfg = FuConfig(
229    fuGen = fmac _,
230    fuSel = _ => true.B,
231    FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(5)
232  )
233
234  val fcmpCfg = FuConfig(
235    fuGen = fcmp _,
236    fuSel = fmiscSel(FU_FCMP),
237    FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
238  )
239
240  val fmvCfg = FuConfig(
241    fuGen = fmv _,
242    fuSel = fmiscSel(FU_FMV),
243    FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = true, hasRedirect = false, CertainLatency(1)
244  )
245
246  val f2iCfg = FuConfig(
247    fuGen = f2i _,
248    fuSel = fmiscSel(FU_F2I),
249    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
250  )
251
252  val s2dCfg = FuConfig(
253    fuGen = f32toF64 _,
254    fuSel = fmiscSel(FU_S2D),
255    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
256  )
257
258  val d2sCfg = FuConfig(
259    fuGen = f64toF32 _,
260    fuSel = fmiscSel(FU_D2S),
261    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
262  )
263
264  val fdivSqrtCfg = FuConfig(
265    fuGen = fdivSqrt _,
266    fuSel = fmiscSel(FU_DIVSQRT),
267    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
268  )
269
270  val lduCfg = FuConfig(
271    null, // DontCare
272    null,
273    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
274    UncertainLatency()
275  )
276
277  val stuCfg = FuConfig(
278    null,
279    null,
280    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
281    UncertainLatency()
282  )
283
284  val mouCfg = FuConfig(
285    null,
286    null,
287    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
288    UncertainLatency()
289  )
290}
291