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