1package xiangshan.backend.fu 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import xiangshan._ 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: Parameters => 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)(implicit p: Parameters) extends XSBundle { 39 val data = UInt(len.W) 40 val uop = new MicroOp 41} 42 43 44class FunctionUnitIO(val len: Int)(implicit p: Parameters) 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)(implicit p: Parameters) 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