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