xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision 9b09132d685224ae1fcf19bd30be8dae82d0e15a)
1cafb3558SLinJiaweipackage xiangshan.backend.fu
2cafb3558SLinJiawei
3cafb3558SLinJiaweiimport chisel3._
4cafb3558SLinJiaweiimport chisel3.util._
5cafb3558SLinJiaweiimport xiangshan._
652c3f215SLinJiaweiimport xiangshan.backend.MDUOpType
7e18c367fSLinJiaweiimport xiangshan.backend.fu.fpu._
8cafb3558SLinJiawei
93e60a357SLinJiaweitrait HasFuLatency {
103e60a357SLinJiawei  val latencyVal: Option[Int]
113e60a357SLinJiawei}
123e60a357SLinJiawei
133e60a357SLinJiaweicase class CertainLatency(value: Int) extends HasFuLatency {
143e60a357SLinJiawei  override val latencyVal: Option[Int] = Some(value)
153e60a357SLinJiawei}
163e60a357SLinJiawei
173e60a357SLinJiaweicase class UncertainLatency() extends HasFuLatency {
183e60a357SLinJiawei  override val latencyVal: Option[Int] = None
193e60a357SLinJiawei}
203e60a357SLinJiawei
2116df83adSZhangZifei
22cafb3558SLinJiaweicase class FuConfig
23cafb3558SLinJiawei(
2452c3f215SLinJiawei  fuGen: () => FunctionUnit,
2552c3f215SLinJiawei  fuSel: FunctionUnit => Bool,
26cafb3558SLinJiawei  fuType: UInt,
27cafb3558SLinJiawei  numIntSrc: Int,
28cafb3558SLinJiawei  numFpSrc: Int,
29cafb3558SLinJiawei  writeIntRf: Boolean,
30cafb3558SLinJiawei  writeFpRf: Boolean,
313e60a357SLinJiawei  hasRedirect: Boolean,
32c43ef4edSLinJiawei  latency: HasFuLatency = CertainLatency(0),
3314521086SLinJiawei) {
3414521086SLinJiawei  def srcCnt: Int = math.max(numIntSrc, numFpSrc)
35c84054caSLinJiawei}
36c84054caSLinJiawei
37e18c367fSLinJiawei
38e50fb2d7SLinJiaweiclass FuOutput(val len: Int) extends XSBundle {
39e50fb2d7SLinJiawei  val data = UInt(len.W)
40e18c367fSLinJiawei  val uop = new MicroOp
41e18c367fSLinJiawei}
42e18c367fSLinJiawei
43e18c367fSLinJiawei
44e50fb2d7SLinJiaweiclass FunctionUnitIO(val len: Int) extends XSBundle {
4514521086SLinJiawei  val in = Flipped(DecoupledIO(new Bundle() {
4652c3f215SLinJiawei    val src = Vec(3, UInt(len.W))
4714521086SLinJiawei    val uop = new MicroOp
4814521086SLinJiawei  }))
49ead41f51SLinJiawei
50e50fb2d7SLinJiawei  val out = DecoupledIO(new FuOutput(len))
51ead41f51SLinJiawei
5214521086SLinJiawei  val redirectIn = Flipped(ValidIO(new Redirect))
532d7c7105SYinan Xu  val flushIn = Input(Bool())
5414521086SLinJiawei}
5514521086SLinJiawei
5652c3f215SLinJiaweiabstract class FunctionUnit(len: Int = 64) extends XSModule {
5714521086SLinJiawei
5852c3f215SLinJiawei  val io = IO(new FunctionUnitIO(len))
5914521086SLinJiawei
6014521086SLinJiawei}
6114521086SLinJiawei
6252c3f215SLinJiaweitrait HasPipelineReg {
6352c3f215SLinJiawei  this: FunctionUnit =>
64e18c367fSLinJiawei
65f64ff6e8SLinJiawei  def latency: Int
6652c3f215SLinJiawei
6752c3f215SLinJiawei  require(latency > 0)
6814521086SLinJiawei
6914521086SLinJiawei  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
7014521086SLinJiawei  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
7114521086SLinJiawei  val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp))
7214521086SLinJiawei
7314521086SLinJiawei
74dfd9e0a8SLinJiawei  // if flush(0), valid 0 will not given, so set flushVec(0) to false.B
75*9b09132dSYinan Xu  val flushVec = validVec.zip(uopVec).map(x => x._1 && x._2.roqIdx.needFlush(io.redirectIn, io.flushIn))
7614521086SLinJiawei
7714521086SLinJiawei  for (i <- 0 until latency) {
7814521086SLinJiawei    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
7914521086SLinJiawei  }
8014521086SLinJiawei
8114521086SLinJiawei  for (i <- 1 to latency) {
8256477dc6SLinJiawei    when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){
8314521086SLinJiawei      validVec(i) := validVec(i - 1)
8414521086SLinJiawei      uopVec(i) := uopVec(i - 1)
8556477dc6SLinJiawei    }.elsewhen(flushVec(i) || rdyVec(i)){
8656477dc6SLinJiawei      validVec(i) := false.B
8714521086SLinJiawei    }
8814521086SLinJiawei  }
8914521086SLinJiawei
9014521086SLinJiawei  io.in.ready := rdyVec(0)
91dfd9e0a8SLinJiawei  io.out.valid := validVec.last
9214521086SLinJiawei  io.out.bits.uop := uopVec.last
9314521086SLinJiawei
9475f32f6bSLinJiawei  def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
9575f32f6bSLinJiawei
9614521086SLinJiawei  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
9714521086SLinJiawei    next,
9875f32f6bSLinJiawei    enable = regEnable(i)
9914521086SLinJiawei  )
10014521086SLinJiawei
10114521086SLinJiawei  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
10214521086SLinJiawei
10314521086SLinJiawei  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
10414521086SLinJiawei
10514521086SLinJiawei  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
10614521086SLinJiawei
10714521086SLinJiawei  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
10814521086SLinJiawei
10914521086SLinJiawei  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
11014521086SLinJiawei}
111cafb3558SLinJiawei
112e18c367fSLinJiaweiobject FunctionUnit extends HasXSParameter {
113c84054caSLinJiawei
1145018a303SLinJiawei  def divider = new SRT4Divider(XLEN)
11552c3f215SLinJiawei
1168a4dc19aSLinJiawei  def multiplier = new ArrayMultiplier(XLEN + 1, Seq(0, 2))
1173ff0763bSljw
118e18c367fSLinJiawei  def alu = new Alu
119c84054caSLinJiawei
120e18c367fSLinJiawei  def jmp = new Jump
12152c3f215SLinJiawei
122e18c367fSLinJiawei  def fence = new Fence
12352c3f215SLinJiawei
124e18c367fSLinJiawei  def csr = new CSR
12552c3f215SLinJiawei
1267f1506e3SLinJiawei  def i2f = new IntToFP
127cafb3558SLinJiawei
128e18c367fSLinJiawei  def fmac = new FMA
12952c3f215SLinJiawei
1307f1506e3SLinJiawei  def f2i = new FPToInt
13152c3f215SLinJiawei
1327f1506e3SLinJiawei  def f2f = new FPToFP
13352c3f215SLinJiawei
134e50fb2d7SLinJiawei  def fdivSqrt = new FDivSqrt
135b8f08ca0SZhangZifei
1367f1506e3SLinJiawei  def f2iSel(x: FunctionUnit): Bool = {
137e50fb2d7SLinJiawei    x.io.in.bits.uop.ctrl.rfWen
1387f1506e3SLinJiawei  }
1397f1506e3SLinJiawei
1407f1506e3SLinJiawei  def i2fSel(x: FunctionUnit): Bool = {
1417f1506e3SLinJiawei    x.io.in.bits.uop.ctrl.fpu.fromInt
1427f1506e3SLinJiawei  }
1437f1506e3SLinJiawei
1447f1506e3SLinJiawei  def f2fSel(x: FunctionUnit): Bool = {
1457f1506e3SLinJiawei    val ctrl = x.io.in.bits.uop.ctrl.fpu
1467f1506e3SLinJiawei    ctrl.fpWen && !ctrl.div && !ctrl.sqrt
1477f1506e3SLinJiawei  }
1487f1506e3SLinJiawei
1497f1506e3SLinJiawei  def fdivSqrtSel(x: FunctionUnit): Bool = {
1507f1506e3SLinJiawei    val ctrl = x.io.in.bits.uop.ctrl.fpu
1517f1506e3SLinJiawei    ctrl.div || ctrl.sqrt
1527f1506e3SLinJiawei  }
1537f1506e3SLinJiawei
15452c3f215SLinJiawei  val aluCfg = FuConfig(
15552c3f215SLinJiawei    fuGen = alu _,
15652c3f215SLinJiawei    fuSel = _ => true.B,
15752c3f215SLinJiawei    fuType = FuType.alu,
15852c3f215SLinJiawei    numIntSrc = 2,
15952c3f215SLinJiawei    numFpSrc = 0,
16052c3f215SLinJiawei    writeIntRf = true,
16152c3f215SLinJiawei    writeFpRf = false,
162c43ef4edSLinJiawei    hasRedirect = true,
16352c3f215SLinJiawei  )
16452c3f215SLinJiawei
16552c3f215SLinJiawei  val jmpCfg = FuConfig(
16652c3f215SLinJiawei    fuGen = jmp _,
16752c3f215SLinJiawei    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp,
16852c3f215SLinJiawei    fuType = FuType.jmp,
16952c3f215SLinJiawei    numIntSrc = 1,
17052c3f215SLinJiawei    numFpSrc = 0,
17152c3f215SLinJiawei    writeIntRf = true,
17252c3f215SLinJiawei    writeFpRf = false,
173c43ef4edSLinJiawei    hasRedirect = true,
17452c3f215SLinJiawei  )
17552c3f215SLinJiawei
17652c3f215SLinJiawei  val fenceCfg = FuConfig(
17752c3f215SLinJiawei    fuGen = fence _,
17852c3f215SLinJiawei    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence,
1790bdd9eadSZhangZifei    FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
1800bdd9eadSZhangZifei    UncertainLatency() // TODO: need rewrite latency structure, not just this value
18152c3f215SLinJiawei  )
18252c3f215SLinJiawei
18352c3f215SLinJiawei  val csrCfg = FuConfig(
18452c3f215SLinJiawei    fuGen = csr _,
18552c3f215SLinJiawei    fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr,
18652c3f215SLinJiawei    fuType = FuType.csr,
18752c3f215SLinJiawei    numIntSrc = 1,
18852c3f215SLinJiawei    numFpSrc = 0,
18952c3f215SLinJiawei    writeIntRf = true,
19052c3f215SLinJiawei    writeFpRf = false,
19152c3f215SLinJiawei    hasRedirect = false
19252c3f215SLinJiawei  )
19352c3f215SLinJiawei
19452c3f215SLinJiawei  val i2fCfg = FuConfig(
19552c3f215SLinJiawei    fuGen = i2f _,
1967f1506e3SLinJiawei    fuSel = i2fSel,
19752c3f215SLinJiawei    FuType.i2f,
19852c3f215SLinJiawei    numIntSrc = 1,
19952c3f215SLinJiawei    numFpSrc = 0,
20052c3f215SLinJiawei    writeIntRf = false,
20152c3f215SLinJiawei    writeFpRf = true,
20252c3f215SLinJiawei    hasRedirect = false,
20352c3f215SLinJiawei    CertainLatency(0)
20452c3f215SLinJiawei  )
20552c3f215SLinJiawei
20652c3f215SLinJiawei  val divCfg = FuConfig(
20752c3f215SLinJiawei    fuGen = divider _,
20852c3f215SLinJiawei    fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType),
20952c3f215SLinJiawei    FuType.div,
21052c3f215SLinJiawei    2,
21152c3f215SLinJiawei    0,
21252c3f215SLinJiawei    writeIntRf = true,
21352c3f215SLinJiawei    writeFpRf = false,
21452c3f215SLinJiawei    hasRedirect = false,
2153e60a357SLinJiawei    UncertainLatency()
2163e60a357SLinJiawei  )
2176624015fSLinJiawei
21852c3f215SLinJiawei  val mulCfg = FuConfig(
21952c3f215SLinJiawei    fuGen = multiplier _,
22052c3f215SLinJiawei    fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType),
22152c3f215SLinJiawei    FuType.mul,
22252c3f215SLinJiawei    2,
22352c3f215SLinJiawei    0,
22452c3f215SLinJiawei    writeIntRf = true,
22552c3f215SLinJiawei    writeFpRf = false,
22652c3f215SLinJiawei    hasRedirect = false,
22752c3f215SLinJiawei    CertainLatency(3)
22852c3f215SLinJiawei  )
22952c3f215SLinJiawei
23052c3f215SLinJiawei  val fmacCfg = FuConfig(
23152c3f215SLinJiawei    fuGen = fmac _,
23252c3f215SLinJiawei    fuSel = _ => true.B,
233e50fb2d7SLinJiawei    FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(4)
23452c3f215SLinJiawei  )
23552c3f215SLinJiawei
23652c3f215SLinJiawei  val f2iCfg = FuConfig(
23752c3f215SLinJiawei    fuGen = f2i _,
2387f1506e3SLinJiawei    fuSel = f2iSel,
23952c3f215SLinJiawei    FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2)
24052c3f215SLinJiawei  )
24152c3f215SLinJiawei
2427f1506e3SLinJiawei  val f2fCfg = FuConfig(
2437f1506e3SLinJiawei    fuGen = f2f _,
244e50fb2d7SLinJiawei    fuSel = f2fSel,
24552c3f215SLinJiawei    FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2)
24652c3f215SLinJiawei  )
24752c3f215SLinJiawei
24852c3f215SLinJiawei  val fdivSqrtCfg = FuConfig(
24952c3f215SLinJiawei    fuGen = fdivSqrt _,
2507f1506e3SLinJiawei    fuSel = fdivSqrtSel,
25152c3f215SLinJiawei    FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency()
25252c3f215SLinJiawei  )
25352c3f215SLinJiawei
25452c3f215SLinJiawei  val lduCfg = FuConfig(
25552c3f215SLinJiawei    null, // DontCare
25652c3f215SLinJiawei    null,
25752c3f215SLinJiawei    FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
2583e60a357SLinJiawei    UncertainLatency()
2593e60a357SLinJiawei  )
260cafb3558SLinJiawei
26152c3f215SLinJiawei  val stuCfg = FuConfig(
26252c3f215SLinJiawei    null,
26352c3f215SLinJiawei    null,
26452c3f215SLinJiawei    FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
26552c3f215SLinJiawei    UncertainLatency()
26652c3f215SLinJiawei  )
26752c3f215SLinJiawei
26852c3f215SLinJiawei  val mouCfg = FuConfig(
26952c3f215SLinJiawei    null,
27052c3f215SLinJiawei    null,
27152c3f215SLinJiawei    FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
2723e60a357SLinJiawei    UncertainLatency()
2733e60a357SLinJiawei  )
274cafb3558SLinJiawei}
275