xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision b81fc38e8510d919ccf70419de6ea10b06295596)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6
7/*
8    XiangShan Function Unit
9    A Exu can have one or more function units
10 */
11
12case class FuConfig
13(
14  fuType: UInt,
15  numIntSrc: Int,
16  numFpSrc: Int,
17  writeIntRf: Boolean,
18  writeFpRf: Boolean,
19  hasRedirect: Boolean
20) {
21  def srcCnt: Int = math.max(numIntSrc, numFpSrc)
22}
23
24class FunctionUnitIO[TI <: Data, TO <: Data]
25(
26  cfg: FuConfig,
27  len: Int,
28  extIn: => TI = null,
29  extOut: => TO = null
30) extends XSBundle
31{
32  val in = Flipped(DecoupledIO(new Bundle() {
33    val src = Vec(cfg.srcCnt, UInt(len.W))
34    val uop = new MicroOp
35    val ext = if(extIn == null) None else Some(extIn.cloneType)
36
37    def connectToExuInput(exuIn: ExuInput): Unit = {
38      val exuSrcIn = Seq(exuIn.src1, exuIn.src2, exuIn.src3)
39      src.zip(exuSrcIn).foreach{case (x, y) => x := y}
40      uop := exuIn.uop
41    }
42  }))
43
44  val out = DecoupledIO(new Bundle() {
45    val data = UInt(XLEN.W)
46    val uop = new MicroOp
47    val ext = if(extOut == null) None else Some(extOut.cloneType)
48  })
49
50  val redirectIn = Flipped(ValidIO(new Redirect))
51
52  override def cloneType: FunctionUnitIO.this.type =
53    new FunctionUnitIO(cfg, len, extIn, extOut).asInstanceOf[this.type]
54}
55
56abstract class FunctionUnit[TI <: Data, TO <: Data]
57(
58  cfg: FuConfig,
59  len: Int = 64,
60  extIn: => TI = null,
61  extOut: => TO = null,
62  val latency: Int = 0
63) extends XSModule {
64
65  val io = IO(new FunctionUnitIO[TI, TO](cfg, len, extIn, extOut))
66
67}
68
69trait HasPipelineReg[TI <: Data, TO <: Data] {
70  this: FunctionUnit[TI, TO] =>
71
72  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
73  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
74  val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp))
75
76
77  val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn))
78
79  for (i <- 0 until latency) {
80    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
81  }
82
83  for (i <- 1 to latency) {
84    when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) {
85      validVec(i) := false.B
86    }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) {
87      validVec(i) := validVec(i - 1)
88      uopVec(i) := uopVec(i - 1)
89    }
90  }
91
92  io.in.ready := rdyVec(0)
93  io.out.valid := validVec.last && !flushVec.last
94  io.out.bits.uop := uopVec.last
95
96  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
97    next,
98    enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
99  )
100
101  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
102
103  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
104
105  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
106
107  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
108
109  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
110}
111
112object FunctionUnit {
113
114  val csrCfg =
115    FuConfig(FuType.csr, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false)
116
117  val jmpCfg =
118    FuConfig(FuType.jmp, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true)
119
120  val i2fCfg =
121    FuConfig(FuType.i2f, 1, 0, writeIntRf = false, writeFpRf = true, hasRedirect = false)
122
123  val aluCfg =
124    FuConfig(FuType.alu, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true)
125
126  val mulCfg =
127    FuConfig(FuType.mul, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false)
128
129  val divCfg =
130    FuConfig(FuType.div, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false)
131
132  val fenceCfg =
133    FuConfig(FuType.fence, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false/*NOTE: need redirect but when commit*/)
134
135  val lduCfg =
136    FuConfig(FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false)
137
138  val stuCfg =
139    FuConfig(FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false)
140
141  // use ldu's write back port, so set writeIntRf to false
142  val mouCfg =
143    FuConfig(FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false)
144
145  val fmacCfg =
146    FuConfig(FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false)
147
148  val fmiscCfg =
149    FuConfig(FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = true, hasRedirect = false)
150
151  val fDivSqrtCfg =
152    FuConfig(FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false)
153}
154