xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision e50fb2d7049496d910e0b1bd14c914d80fa03bd3)
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  val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn))
74
75  for (i <- 0 until latency) {
76    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
77  }
78
79  for (i <- 1 to latency) {
80    when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) {
81      validVec(i) := false.B
82    }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) {
83      validVec(i) := validVec(i - 1)
84      uopVec(i) := uopVec(i - 1)
85    }
86  }
87
88  io.in.ready := rdyVec(0)
89  io.out.valid := validVec.last && !flushVec.last
90  io.out.bits.uop := uopVec.last
91
92  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
93    next,
94    enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
95  )
96
97  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
98
99  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
100
101  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
102
103  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
104
105  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
106}
107
108object FunctionUnit extends HasXSParameter {
109
110  def divider = new SRT4Divider(XLEN)
111
112  def multiplier = new ArrayMultiplier(XLEN + 1, Seq(0, 2))
113
114  def alu = new Alu
115
116  def jmp = new Jump
117
118  def fence = new Fence
119
120  def csr = new CSR
121
122  def i2f = new IntToFP
123
124  def fmac = new FMA
125
126  def f2i = new FPToInt
127
128  def f2f = new FPToFP
129
130  def fdivSqrt = new FDivSqrt
131
132  def f2iSel(x: FunctionUnit): Bool = {
133    x.io.in.bits.uop.ctrl.rfWen
134  }
135
136  def i2fSel(x: FunctionUnit): Bool = {
137    x.io.in.bits.uop.ctrl.fpu.fromInt
138  }
139
140  def f2fSel(x: FunctionUnit): Bool = {
141    val ctrl = x.io.in.bits.uop.ctrl.fpu
142    ctrl.fpWen && !ctrl.div && !ctrl.sqrt
143  }
144
145  def fdivSqrtSel(x: FunctionUnit): Bool = {
146    val ctrl = x.io.in.bits.uop.ctrl.fpu
147    ctrl.div || ctrl.sqrt
148  }
149
150  val aluCfg = FuConfig(
151    fuGen = alu _,
152    fuSel = _ => true.B,
153    fuType = FuType.alu,
154    numIntSrc = 2,
155    numFpSrc = 0,
156    writeIntRf = true,
157    writeFpRf = false,
158    hasRedirect = true
159  )
160
161  val jmpCfg = FuConfig(
162    fuGen = jmp _,
163    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp,
164    fuType = FuType.jmp,
165    numIntSrc = 1,
166    numFpSrc = 0,
167    writeIntRf = true,
168    writeFpRf = false,
169    hasRedirect = true
170  )
171
172  val fenceCfg = FuConfig(
173    fuGen = fence _,
174    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence,
175    FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
176    UncertainLatency() // TODO: need rewrite latency structure, not just this value
177  )
178
179  val csrCfg = FuConfig(
180    fuGen = csr _,
181    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr,
182    fuType = FuType.csr,
183    numIntSrc = 1,
184    numFpSrc = 0,
185    writeIntRf = true,
186    writeFpRf = false,
187    hasRedirect = false
188  )
189
190  val i2fCfg = FuConfig(
191    fuGen = i2f _,
192    fuSel = i2fSel,
193    FuType.i2f,
194    numIntSrc = 1,
195    numFpSrc = 0,
196    writeIntRf = false,
197    writeFpRf = true,
198    hasRedirect = false,
199    CertainLatency(0)
200  )
201
202  val divCfg = FuConfig(
203    fuGen = divider _,
204    fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType),
205    FuType.div,
206    2,
207    0,
208    writeIntRf = true,
209    writeFpRf = false,
210    hasRedirect = false,
211    UncertainLatency()
212  )
213
214  val mulCfg = FuConfig(
215    fuGen = multiplier _,
216    fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType),
217    FuType.mul,
218    2,
219    0,
220    writeIntRf = true,
221    writeFpRf = false,
222    hasRedirect = false,
223    CertainLatency(3)
224  )
225
226  val fmacCfg = FuConfig(
227    fuGen = fmac _,
228    fuSel = _ => true.B,
229    FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(4)
230  )
231
232  val f2iCfg = FuConfig(
233    fuGen = f2i _,
234    fuSel = f2iSel,
235    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
236  )
237
238  val f2fCfg = FuConfig(
239    fuGen = f2f _,
240    fuSel = f2fSel,
241    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
242  )
243
244  val fdivSqrtCfg = FuConfig(
245    fuGen = fdivSqrt _,
246    fuSel = fdivSqrtSel,
247    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
248  )
249
250  val lduCfg = FuConfig(
251    null, // DontCare
252    null,
253    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
254    UncertainLatency()
255  )
256
257  val stuCfg = FuConfig(
258    null,
259    null,
260    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
261    UncertainLatency()
262  )
263
264  val mouCfg = FuConfig(
265    null,
266    null,
267    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
268    UncertainLatency()
269  )
270}
271