1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6 7/* 8 XiangShan Function Unit 9 A Exu can have one or more function units 10 */ 11 12trait HasFuLatency { 13 val latencyVal: Option[Int] 14} 15 16case class CertainLatency(value: Int) extends HasFuLatency{ 17 override val latencyVal: Option[Int] = Some(value) 18} 19 20case class UncertainLatency() extends HasFuLatency { 21 override val latencyVal: Option[Int] = None 22} 23 24case class NexusLatency(value: Int) extends HasFuLatency { 25 override val latencyVal: Option[Int] = Some(value) 26} 27 28 29 30case class FuConfig 31( 32 fuType: UInt, 33 numIntSrc: Int, 34 numFpSrc: Int, 35 writeIntRf: Boolean, 36 writeFpRf: Boolean, 37 hasRedirect: Boolean, 38 latency: HasFuLatency = CertainLatency(0) 39) { 40 def srcCnt: Int = math.max(numIntSrc, numFpSrc) 41} 42 43class FunctionUnitIO[TI <: Data, TO <: Data] 44( 45 cfg: FuConfig, 46 len: Int, 47 extIn: => TI = null, 48 extOut: => TO = null 49) extends XSBundle 50{ 51 val in = Flipped(DecoupledIO(new Bundle() { 52 val src = Vec(cfg.srcCnt, UInt(len.W)) 53 val uop = new MicroOp 54 val ext = if(extIn == null) None else Some(extIn.cloneType) 55 56 def connectToExuInput(exuIn: ExuInput): Unit = { 57 val exuSrcIn = Seq(exuIn.src1, exuIn.src2, exuIn.src3) 58 src.zip(exuSrcIn).foreach{case (x, y) => x := y} 59 uop := exuIn.uop 60 } 61 })) 62 63 val out = DecoupledIO(new Bundle() { 64 val data = UInt(XLEN.W) 65 val uop = new MicroOp 66 val ext = if(extOut == null) None else Some(extOut.cloneType) 67 }) 68 69 val redirectIn = Flipped(ValidIO(new Redirect)) 70 71 override def cloneType: FunctionUnitIO.this.type = 72 new FunctionUnitIO(cfg, len, extIn, extOut).asInstanceOf[this.type] 73} 74 75abstract class FunctionUnit[TI <: Data, TO <: Data] 76( 77 cfg: FuConfig, 78 len: Int = 64, 79 extIn: => TI = null, 80 extOut: => TO = null, 81 val latency: Int = 0 82) extends XSModule { 83 84 val io = IO(new FunctionUnitIO[TI, TO](cfg, len, extIn, extOut)) 85 86} 87 88trait HasPipelineReg[TI <: Data, TO <: Data] { 89 this: FunctionUnit[TI, TO] => 90 91 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 92 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 93 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 94 95 96 val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn)) 97 98 for (i <- 0 until latency) { 99 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 100 } 101 102 for (i <- 1 to latency) { 103 when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) { 104 validVec(i) := false.B 105 }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) { 106 validVec(i) := validVec(i - 1) 107 uopVec(i) := uopVec(i - 1) 108 } 109 } 110 111 io.in.ready := rdyVec(0) 112 io.out.valid := validVec.last && !flushVec.last 113 io.out.bits.uop := uopVec.last 114 115 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 116 next, 117 enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 118 ) 119 120 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 121 122 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 123 124 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 125 126 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 127 128 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 129} 130 131object FunctionUnit { 132 133 val csrCfg = 134 FuConfig(FuType.csr, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false) 135 136 val jmpCfg = 137 FuConfig(FuType.jmp, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true) 138 139 val i2fCfg = 140 FuConfig(FuType.i2f, 1, 0, writeIntRf = false, writeFpRf = true, hasRedirect = false) 141 142 val aluCfg = 143 FuConfig(FuType.alu, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true) 144 145 val mulCfg = 146 FuConfig(FuType.mul, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false, 147 UncertainLatency()// CertainLatency(3) 148 ) 149 150 val divCfg = 151 FuConfig(FuType.div, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false, 152 UncertainLatency() 153 ) 154 155 val fenceCfg = 156 FuConfig(FuType.fence, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false/*NOTE: need redirect but when commit*/) 157 158 val lduCfg = 159 FuConfig(FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false, 160 UncertainLatency() 161 ) 162 163 val stuCfg = 164 FuConfig(FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false, 165 UncertainLatency() 166 ) 167 168 val mouCfg = 169 FuConfig(FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false, 170 UncertainLatency() 171 ) 172 173 val fmacCfg = 174 FuConfig(FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false, 175 CertainLatency(5) 176 ) 177 178 val fmiscCfg = 179 FuConfig(FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = true, hasRedirect = false, 180 UncertainLatency() 181 ) 182 183 val fDivSqrtCfg = 184 FuConfig(FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false, 185 UncertainLatency() 186 ) 187} 188