xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FunctionUnit.scala (revision 3fce4f48e1f4c43253ff1758dbd05b8b71627990)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import xiangshan.backend.fu.fpu.divsqrt.DivSqrt
7import xiangshan.backend.fu.fpu._
8import xiangshan.backend.fu.fpu.fma.FMA
9
10/*
11    XiangShan Function Unit
12    A Exu can have one or more function units
13 */
14
15trait HasFuLatency {
16  val latencyVal: Option[Int]
17}
18
19case class CertainLatency(value: Int) extends HasFuLatency{
20  override val latencyVal: Option[Int] = Some(value)
21}
22
23case class UncertainLatency() extends HasFuLatency {
24  override val latencyVal: Option[Int] = None
25}
26
27
28
29case class FuConfig
30(
31  fuType: UInt,
32  numIntSrc: Int,
33  numFpSrc: Int,
34  writeIntRf: Boolean,
35  writeFpRf: Boolean,
36  hasRedirect: Boolean,
37  latency: HasFuLatency = CertainLatency(0)
38) {
39  def srcCnt: Int = math.max(numIntSrc, numFpSrc)
40}
41
42
43
44class FuOutput extends XSBundle {
45  val data = UInt(XLEN.W)
46  val uop = new MicroOp
47}
48
49
50class FunctionUnitIO[TI <: Data, TO <: Data]
51(
52  cfg: FuConfig,
53  len: Int
54) extends XSBundle
55{
56  val in = Flipped(DecoupledIO(new Bundle() {
57    val src = Vec(cfg.srcCnt, UInt(len.W))
58    val uop = new MicroOp
59
60    def connectToExuInput(exuIn: ExuInput): Unit = {
61      val exuSrcIn = Seq(exuIn.src1, exuIn.src2, exuIn.src3)
62      src.zip(exuSrcIn).foreach{case (x, y) => x := y}
63      uop := exuIn.uop
64    }
65  }))
66
67  val out = DecoupledIO(new FuOutput)
68
69  val redirectIn = Flipped(ValidIO(new Redirect))
70
71  override def cloneType: FunctionUnitIO.this.type =
72    new FunctionUnitIO(cfg, len).asInstanceOf[this.type]
73}
74
75abstract class FunctionUnit
76(
77  val cfg: FuConfig,
78  val len: Int = 64
79) extends XSModule {
80
81  val io = IO(new FunctionUnitIO(cfg, len))
82
83}
84
85trait HasPipelineReg { this: FunctionUnit =>
86
87  require(cfg.latency.latencyVal.nonEmpty && cfg.latency.latencyVal.get > 0)
88  val latency = cfg.latency.latencyVal.get
89
90  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
91  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
92  val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp))
93
94
95  val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn))
96
97  for (i <- 0 until latency) {
98    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
99  }
100
101  for (i <- 1 to latency) {
102    when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) {
103      validVec(i) := false.B
104    }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) {
105      validVec(i) := validVec(i - 1)
106      uopVec(i) := uopVec(i - 1)
107    }
108  }
109
110  io.in.ready := rdyVec(0)
111  io.out.valid := validVec.last && !flushVec.last
112  io.out.bits.uop := uopVec.last
113
114  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
115    next,
116    enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
117  )
118
119  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
120
121  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
122
123  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
124
125  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
126
127  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
128}
129
130object FunctionUnit extends HasXSParameter {
131
132  def divider = new SRT4Divider(XLEN)
133  def multiplier = new ArrayMultiplier(XLEN+1, Seq(0, 2))
134
135  def alu = new Alu
136
137  def jmp = new Jump
138  def fence = new Fence
139  def csr = new CSR
140  def i2f = new IntToFloatSingleCycle
141
142  def fmac = new FMA
143  def fcmp = new FCMP
144  def fmv = new FMV(XLEN)
145  def f2i = new FloatToInt
146  def f32toF64 = new F32toF64
147  def f64toF32 = new F64toF32
148  def fdivSqrt = new DivSqrt
149
150  def fmiscSel(fu: String)(x: FPUSubModule): Bool = {
151    x.io.in.bits.uop.ctrl.fuOpType.head(4) === s"b$fu".U
152  }
153
154  val lduCfg =
155    FuConfig(FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
156      UncertainLatency()
157    )
158
159  val stuCfg =
160    FuConfig(FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
161      UncertainLatency()
162    )
163
164  val mouCfg =
165    FuConfig(FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
166      UncertainLatency()
167  )
168}
169