1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import xiangshan.backend.MDUOpType 7import xiangshan.backend.fu.fpu.FPUOpType.{FU_D2S, FU_DIVSQRT, FU_F2I, FU_FCMP, FU_FMV, FU_S2D} 8import xiangshan.backend.fu.fpu.divsqrt.DivSqrt 9import xiangshan.backend.fu.fpu._ 10import xiangshan.backend.fu.fpu.fma.FMA 11 12/* 13 XiangShan Function Unit 14 A Exu can have one or more function units 15 */ 16 17trait HasFuLatency { 18 val latencyVal: Option[Int] 19} 20 21case class CertainLatency(value: Int) extends HasFuLatency { 22 override val latencyVal: Option[Int] = Some(value) 23} 24 25case class UncertainLatency() extends HasFuLatency { 26 override val latencyVal: Option[Int] = None 27} 28 29 30case class FuConfig 31( 32 fuGen: () => FunctionUnit, 33 fuSel: FunctionUnit => Bool, 34 fuType: UInt, 35 numIntSrc: Int, 36 numFpSrc: Int, 37 writeIntRf: Boolean, 38 writeFpRf: Boolean, 39 hasRedirect: Boolean, 40 latency: HasFuLatency = CertainLatency(0) 41) { 42 def srcCnt: Int = math.max(numIntSrc, numFpSrc) 43} 44 45 46class FuOutput extends XSBundle { 47 val data = UInt(XLEN.W) 48 val uop = new MicroOp 49} 50 51 52class FunctionUnitIO(len: Int) extends XSBundle { 53 val in = Flipped(DecoupledIO(new Bundle() { 54 val src = Vec(3, UInt(len.W)) 55 val uop = new MicroOp 56 })) 57 58 val out = DecoupledIO(new FuOutput) 59 60 val redirectIn = Flipped(ValidIO(new Redirect)) 61 62 override def cloneType: FunctionUnitIO.this.type = 63 new FunctionUnitIO(len).asInstanceOf[this.type] 64} 65 66abstract class FunctionUnit(len: Int = 64) extends XSModule { 67 68 val io = IO(new FunctionUnitIO(len)) 69 70} 71 72trait HasPipelineReg { 73 this: FunctionUnit => 74 75 def latency: Int 76 77 require(latency > 0) 78 79 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 80 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 81 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 82 83 84 val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn)) 85 86 for (i <- 0 until latency) { 87 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 88 } 89 90 for (i <- 1 to latency) { 91 when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) { 92 validVec(i) := false.B 93 }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) { 94 validVec(i) := validVec(i - 1) 95 uopVec(i) := uopVec(i - 1) 96 } 97 } 98 99 io.in.ready := rdyVec(0) 100 io.out.valid := validVec.last && !flushVec.last 101 io.out.bits.uop := uopVec.last 102 103 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 104 next, 105 enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 106 ) 107 108 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 109 110 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 111 112 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 113 114 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 115 116 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 117} 118 119object FunctionUnit extends HasXSParameter { 120 121 def divider = new SRT4Divider(XLEN) 122 123 def multiplier = new ArrayMultiplier(XLEN + 1, Seq(0, 2)) 124 125 def alu = new Alu 126 127 def jmp = new Jump 128 129 def fence = new Fence 130 131 def csr = new CSR 132 133 def i2f = new IntToFloatSingleCycle 134 135 def fmac = new FMA 136 137 def fcmp = new FCMP 138 139 def fmv = new FMV(XLEN) 140 141 def f2i = new FloatToInt 142 143 def f32toF64 = new F32toF64 144 145 def f64toF32 = new F64toF32 146 147 def fdivSqrt = new DivSqrt 148 149 def fmiscSel(fu: String)(x: FunctionUnit): Bool = { 150 x.io.in.bits.uop.ctrl.fuOpType.head(4) === s"b$fu".U 151 } 152 153 val aluCfg = FuConfig( 154 fuGen = alu _, 155 fuSel = _ => true.B, 156 fuType = FuType.alu, 157 numIntSrc = 2, 158 numFpSrc = 0, 159 writeIntRf = true, 160 writeFpRf = false, 161 hasRedirect = true 162 ) 163 164 val jmpCfg = FuConfig( 165 fuGen = jmp _, 166 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp, 167 fuType = FuType.jmp, 168 numIntSrc = 1, 169 numFpSrc = 0, 170 writeIntRf = true, 171 writeFpRf = false, 172 hasRedirect = true 173 ) 174 175 val fenceCfg = FuConfig( 176 fuGen = fence _, 177 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence, 178 FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 179 UncertainLatency() // TODO: need rewrite latency structure, not just this value 180 ) 181 182 val csrCfg = FuConfig( 183 fuGen = csr _, 184 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr, 185 fuType = FuType.csr, 186 numIntSrc = 1, 187 numFpSrc = 0, 188 writeIntRf = true, 189 writeFpRf = false, 190 hasRedirect = false 191 ) 192 193 val i2fCfg = FuConfig( 194 fuGen = i2f _, 195 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.i2f, 196 FuType.i2f, 197 numIntSrc = 1, 198 numFpSrc = 0, 199 writeIntRf = false, 200 writeFpRf = true, 201 hasRedirect = false, 202 CertainLatency(0) 203 ) 204 205 val divCfg = FuConfig( 206 fuGen = divider _, 207 fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType), 208 FuType.div, 209 2, 210 0, 211 writeIntRf = true, 212 writeFpRf = false, 213 hasRedirect = false, 214 UncertainLatency() 215 ) 216 217 val mulCfg = FuConfig( 218 fuGen = multiplier _, 219 fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType), 220 FuType.mul, 221 2, 222 0, 223 writeIntRf = true, 224 writeFpRf = false, 225 hasRedirect = false, 226 CertainLatency(3) 227 ) 228 229 val fmacCfg = FuConfig( 230 fuGen = fmac _, 231 fuSel = _ => true.B, 232 FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(5) 233 ) 234 235 val fcmpCfg = FuConfig( 236 fuGen = fcmp _, 237 fuSel = (x: FunctionUnit) => fmiscSel(FU_FCMP)(x) && x.io.in.bits.uop.ctrl.rfWen, 238 FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2) 239 ) 240 241 val fminCfg = FuConfig( 242 fuGen = fcmp _, 243 fuSel = (x: FunctionUnit) => fmiscSel(FU_FCMP)(x) && x.io.in.bits.uop.ctrl.fpWen, 244 FuType.fmisc, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 245 ) 246 247 val fsgnjCfg = FuConfig( 248 fuGen = fmv _, 249 fuSel = (x: FunctionUnit) => fmiscSel(FU_FMV)(x) && x.io.in.bits.uop.ctrl.fpWen, 250 FuType.fmisc, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(1) 251 ) 252 253 val fmvCfg = FuConfig( 254 fuGen = fmv _, 255 fuSel = (x: FunctionUnit) => fmiscSel(FU_FMV)(x) && x.io.in.bits.uop.ctrl.rfWen, 256 FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(1) 257 ) 258 259 val f2iCfg = FuConfig( 260 fuGen = f2i _, 261 fuSel = fmiscSel(FU_F2I), 262 FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2) 263 ) 264 265 val s2dCfg = FuConfig( 266 fuGen = f32toF64 _, 267 fuSel = fmiscSel(FU_S2D), 268 FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 269 ) 270 271 val d2sCfg = FuConfig( 272 fuGen = f64toF32 _, 273 fuSel = fmiscSel(FU_D2S), 274 FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 275 ) 276 277 val fdivSqrtCfg = FuConfig( 278 fuGen = fdivSqrt _, 279 fuSel = fmiscSel(FU_DIVSQRT), 280 FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency() 281 ) 282 283 val lduCfg = FuConfig( 284 null, // DontCare 285 null, 286 FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false, 287 UncertainLatency() 288 ) 289 290 val stuCfg = FuConfig( 291 null, 292 null, 293 FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false, 294 UncertainLatency() 295 ) 296 297 val mouCfg = FuConfig( 298 null, 299 null, 300 FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 301 UncertainLatency() 302 ) 303} 304