xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision 2199a01c65d5a7bf503c4b40771336a50a6f1122)
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(val len: Int) extends XSBundle {
39  val data = UInt(len.W)
40  val uop = new MicroOp
41}
42
43
44class FunctionUnitIO(val 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(len))
51
52  val redirectIn = Flipped(ValidIO(new Redirect))
53}
54
55abstract class FunctionUnit(len: Int = 64) extends XSModule {
56
57  val io = IO(new FunctionUnitIO(len))
58
59}
60
61trait HasPipelineReg {
62  this: FunctionUnit =>
63
64  def latency: Int
65
66  require(latency > 0)
67
68  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
69  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
70  val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp))
71
72
73  // if flush(0), valid 0 will not given, so set flushVec(0) to false.B
74  val flushVec = validVec.zip(uopVec).map(x => x._1 && x._2.roqIdx.needFlush(io.redirectIn))
75
76  for (i <- 0 until latency) {
77    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
78  }
79
80  for (i <- 1 to latency) {
81    when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){
82      validVec(i) := validVec(i - 1)
83      uopVec(i) := uopVec(i - 1)
84    }.elsewhen(flushVec(i) || rdyVec(i)){
85      validVec(i) := false.B
86    }
87  }
88
89  io.in.ready := rdyVec(0)
90  io.out.valid := validVec.last
91  io.out.bits.uop := uopVec.last
92
93  def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
94
95  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
96    next,
97    enable = regEnable(i)
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 f2iSel(x: FunctionUnit): Bool = {
136    x.io.in.bits.uop.ctrl.rfWen
137  }
138
139  def i2fSel(x: FunctionUnit): Bool = {
140    x.io.in.bits.uop.ctrl.fpu.fromInt
141  }
142
143  def f2fSel(x: FunctionUnit): Bool = {
144    val ctrl = x.io.in.bits.uop.ctrl.fpu
145    ctrl.fpWen && !ctrl.div && !ctrl.sqrt
146  }
147
148  def fdivSqrtSel(x: FunctionUnit): Bool = {
149    val ctrl = x.io.in.bits.uop.ctrl.fpu
150    ctrl.div || ctrl.sqrt
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 = i2fSel,
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(4)
233  )
234
235  val f2iCfg = FuConfig(
236    fuGen = f2i _,
237    fuSel = f2iSel,
238    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
239  )
240
241  val f2fCfg = FuConfig(
242    fuGen = f2f _,
243    fuSel = f2fSel,
244    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
245  )
246
247  val fdivSqrtCfg = FuConfig(
248    fuGen = fdivSqrt _,
249    fuSel = fdivSqrtSel,
250    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
251  )
252
253  val lduCfg = FuConfig(
254    null, // DontCare
255    null,
256    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
257    UncertainLatency()
258  )
259
260  val stuCfg = FuConfig(
261    null,
262    null,
263    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
264    UncertainLatency()
265  )
266
267  val mouCfg = FuConfig(
268    null,
269    null,
270    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
271    UncertainLatency()
272  )
273}
274