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