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 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 74 val flushVec = validVec.zip(uopVec).map(x => x._1 && x._2.roqIdx.needFlush(io.redirectIn)) 75 76 for (i <- 0 until latency) { 77 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 78 } 79 80 for (i <- 1 to latency) { 81 when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){ 82 validVec(i) := validVec(i - 1) 83 uopVec(i) := uopVec(i - 1) 84 }.elsewhen(flushVec(i) || rdyVec(i)){ 85 validVec(i) := false.B 86 } 87 } 88 89 io.in.ready := rdyVec(0) 90 io.out.valid := validVec.last 91 io.out.bits.uop := uopVec.last 92 93 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 94 95 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 96 next, 97 enable = regEnable(i) 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 f2iSel(x: FunctionUnit): Bool = { 136 x.io.in.bits.uop.ctrl.rfWen 137 } 138 139 def i2fSel(x: FunctionUnit): Bool = { 140 x.io.in.bits.uop.ctrl.fpu.fromInt 141 } 142 143 def f2fSel(x: FunctionUnit): Bool = { 144 val ctrl = x.io.in.bits.uop.ctrl.fpu 145 ctrl.fpWen && !ctrl.div && !ctrl.sqrt 146 } 147 148 def fdivSqrtSel(x: FunctionUnit): Bool = { 149 val ctrl = x.io.in.bits.uop.ctrl.fpu 150 ctrl.div || ctrl.sqrt 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 = i2fSel, 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(4) 233 ) 234 235 val f2iCfg = FuConfig( 236 fuGen = f2i _, 237 fuSel = f2iSel, 238 FuType.fmisc, 0, 1, writeIntRf = true, writeFpRf = false, hasRedirect = false, CertainLatency(2) 239 ) 240 241 val f2fCfg = FuConfig( 242 fuGen = f2f _, 243 fuSel = f2fSel, 244 FuType.fmisc, 0, 1, writeIntRf = false, writeFpRf = true, hasRedirect = false, CertainLatency(2) 245 ) 246 247 val fdivSqrtCfg = FuConfig( 248 fuGen = fdivSqrt _, 249 fuSel = fdivSqrtSel, 250 FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, UncertainLatency() 251 ) 252 253 val lduCfg = FuConfig( 254 null, // DontCare 255 null, 256 FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false, 257 UncertainLatency() 258 ) 259 260 val stuCfg = FuConfig( 261 null, 262 null, 263 FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false, 264 UncertainLatency() 265 ) 266 267 val mouCfg = FuConfig( 268 null, 269 null, 270 FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 271 UncertainLatency() 272 ) 273} 274