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(val len: Int) extends XSBundle { 39 val data = UInt(len.W) 40 val uop = new MicroOp 41} 42 43 44class FunctionUnitIO(val 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(len)) 51 52 val redirectIn = Flipped(ValidIO(new Redirect)) 53 val flushIn = Input(Bool()) 54} 55 56abstract class FunctionUnit(len: Int = 64) extends XSModule { 57 58 val io = IO(new FunctionUnitIO(len)) 59 60} 61 62trait HasPipelineReg { 63 this: FunctionUnit => 64 65 def latency: Int 66 67 require(latency > 0) 68 69 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 70 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 71 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 72 73 74 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 75 val flushVec = WireInit(false.B) +: 76 validVec.zip(uopVec).tail.map(x => x._1 && x._2.roqIdx.needFlush(io.redirectIn, io.flushIn)) 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 93 io.out.bits.uop := uopVec.last 94 95 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 96 97 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 98 next, 99 enable = regEnable(i) 100 ) 101 102 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 103 104 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 105 106 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 107 108 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 109 110 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 111} 112 113object FunctionUnit extends HasXSParameter { 114 115 def divider = new SRT4Divider(XLEN) 116 117 def multiplier = new ArrayMultiplier(XLEN + 1, Seq(0, 2)) 118 119 def alu = new Alu 120 121 def jmp = new Jump 122 123 def fence = new Fence 124 125 def csr = new CSR 126 127 def i2f = new IntToFP 128 129 def fmac = new FMA 130 131 def f2i = new FPToInt 132 133 def f2f = new FPToFP 134 135 def fdivSqrt = new FDivSqrt 136 137 def f2iSel(x: FunctionUnit): Bool = { 138 x.io.in.bits.uop.ctrl.rfWen 139 } 140 141 def i2fSel(x: FunctionUnit): Bool = { 142 x.io.in.bits.uop.ctrl.fpu.fromInt 143 } 144 145 def f2fSel(x: FunctionUnit): Bool = { 146 val ctrl = x.io.in.bits.uop.ctrl.fpu 147 ctrl.fpWen && !ctrl.div && !ctrl.sqrt 148 } 149 150 def fdivSqrtSel(x: FunctionUnit): Bool = { 151 val ctrl = x.io.in.bits.uop.ctrl.fpu 152 ctrl.div || ctrl.sqrt 153 } 154 155 val aluCfg = FuConfig( 156 fuGen = alu _, 157 fuSel = _ => true.B, 158 fuType = FuType.alu, 159 numIntSrc = 2, 160 numFpSrc = 0, 161 writeIntRf = true, 162 writeFpRf = false, 163 hasRedirect = true, 164 ) 165 166 val jmpCfg = FuConfig( 167 fuGen = jmp _, 168 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.jmp, 169 fuType = FuType.jmp, 170 numIntSrc = 1, 171 numFpSrc = 0, 172 writeIntRf = true, 173 writeFpRf = false, 174 hasRedirect = true, 175 ) 176 177 val fenceCfg = FuConfig( 178 fuGen = fence _, 179 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.fence, 180 FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 181 UncertainLatency() // TODO: need rewrite latency structure, not just this value 182 ) 183 184 val csrCfg = FuConfig( 185 fuGen = csr _, 186 fuSel = (x: FunctionUnit) => x.io.in.bits.uop.ctrl.fuType === FuType.csr, 187 fuType = FuType.csr, 188 numIntSrc = 1, 189 numFpSrc = 0, 190 writeIntRf = true, 191 writeFpRf = false, 192 hasRedirect = false 193 ) 194 195 val i2fCfg = FuConfig( 196 fuGen = i2f _, 197 fuSel = i2fSel, 198 FuType.i2f, 199 numIntSrc = 1, 200 numFpSrc = 0, 201 writeIntRf = false, 202 writeFpRf = true, 203 hasRedirect = false, 204 CertainLatency(0) 205 ) 206 207 val divCfg = FuConfig( 208 fuGen = divider _, 209 fuSel = (x: FunctionUnit) => MDUOpType.isDiv(x.io.in.bits.uop.ctrl.fuOpType), 210 FuType.div, 211 2, 212 0, 213 writeIntRf = true, 214 writeFpRf = false, 215 hasRedirect = false, 216 UncertainLatency() 217 ) 218 219 val mulCfg = FuConfig( 220 fuGen = multiplier _, 221 fuSel = (x: FunctionUnit) => MDUOpType.isMul(x.io.in.bits.uop.ctrl.fuOpType), 222 FuType.mul, 223 2, 224 0, 225 writeIntRf = true, 226 writeFpRf = false, 227 hasRedirect = false, 228 CertainLatency(3) 229 ) 230 231 val fmacCfg = FuConfig( 232 fuGen = fmac _, 233 fuSel = _ => true.B, 234 FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(4) 235 ) 236 237 val f2iCfg = FuConfig( 238 fuGen = f2i _, 239 fuSel = f2iSel, 240 FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2) 241 ) 242 243 val f2fCfg = FuConfig( 244 fuGen = f2f _, 245 fuSel = f2fSel, 246 FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 247 ) 248 249 val fdivSqrtCfg = FuConfig( 250 fuGen = fdivSqrt _, 251 fuSel = fdivSqrtSel, 252 FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency() 253 ) 254 255 val lduCfg = FuConfig( 256 null, // DontCare 257 null, 258 FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false, 259 UncertainLatency() 260 ) 261 262 val stuCfg = FuConfig( 263 null, 264 null, 265 FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false, 266 UncertainLatency() 267 ) 268 269 val mouCfg = FuConfig( 270 null, 271 null, 272 FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 273 UncertainLatency() 274 ) 275} 276