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