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