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 12case class FuConfig 13( 14 fuType: UInt, 15 numIntSrc: Int, 16 numFpSrc: Int, 17 writeIntRf: Boolean, 18 writeFpRf: Boolean, 19 hasRedirect: Boolean 20) { 21 def srcCnt: Int = math.max(numIntSrc, numFpSrc) 22} 23 24class FunctionUnitIO[TI <: Data, TO <: Data] 25( 26 cfg: FuConfig, 27 len: Int, 28 extIn: => TI = null, 29 extOut: => TO = null 30) extends XSBundle 31{ 32 val in = Flipped(DecoupledIO(new Bundle() { 33 val src = Vec(cfg.srcCnt, UInt(len.W)) 34 val uop = new MicroOp 35 val ext = if(extIn == null) None else Some(extIn.cloneType) 36 37 def connectToExuInput(exuIn: ExuInput): Unit = { 38 val exuSrcIn = Seq(exuIn.src1, exuIn.src2, exuIn.src3) 39 src.zip(exuSrcIn).foreach{case (x, y) => x := y} 40 uop := exuIn.uop 41 } 42 })) 43 44 val out = DecoupledIO(new Bundle() { 45 val data = UInt(XLEN.W) 46 val uop = new MicroOp 47 val ext = if(extOut == null) None else Some(extOut.cloneType) 48 }) 49 50 val redirectIn = Flipped(ValidIO(new Redirect)) 51 52 override def cloneType: FunctionUnitIO.this.type = 53 new FunctionUnitIO(cfg, len, extIn, extOut).asInstanceOf[this.type] 54} 55 56abstract class FunctionUnit[TI <: Data, TO <: Data] 57( 58 cfg: FuConfig, 59 len: Int = 64, 60 extIn: => TI = null, 61 extOut: => TO = null, 62 val latency: Int = 0 63) extends XSModule { 64 65 val io = IO(new FunctionUnitIO[TI, TO](cfg, len, extIn, extOut)) 66 67} 68 69trait HasPipelineReg[TI <: Data, TO <: Data] { 70 this: FunctionUnit[TI, TO] => 71 72 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 73 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 74 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 75 76 77 val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn)) 78 79 for (i <- 0 until latency) { 80 rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1) 81 } 82 83 for (i <- 1 to latency) { 84 when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) { 85 validVec(i) := false.B 86 }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) { 87 validVec(i) := validVec(i - 1) 88 uopVec(i) := uopVec(i - 1) 89 } 90 } 91 92 io.in.ready := rdyVec(0) 93 io.out.valid := validVec.last && !flushVec.last 94 io.out.bits.uop := uopVec.last 95 96 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 97 next, 98 enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 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 { 113 114 val csrCfg = 115 FuConfig(FuType.csr, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false) 116 117 val jmpCfg = 118 FuConfig(FuType.jmp, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true) 119 120 val i2fCfg = 121 FuConfig(FuType.i2f, 1, 0, writeIntRf = false, writeFpRf = true, hasRedirect = false) 122 123 val aluCfg = 124 FuConfig(FuType.alu, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true) 125 126 val mulCfg = 127 FuConfig(FuType.mul, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false) 128 129 val divCfg = 130 FuConfig(FuType.div, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false) 131 132 val fenceCfg = 133 FuConfig(FuType.fence, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false/*NOTE: need redirect but when commit*/) 134 135 val lduCfg = 136 FuConfig(FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false) 137 138 val stuCfg = 139 FuConfig(FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false) 140 141 // use ldu's write back port, so set writeIntRf to false 142 val mouCfg = 143 FuConfig(FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false) 144 145 val fmacCfg = 146 FuConfig(FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false) 147 148 val fmiscCfg = 149 FuConfig(FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = true, hasRedirect = false) 150 151 val fDivSqrtCfg = 152 FuConfig(FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false) 153} 154