1*730cfbc0SXuan Hupackage xiangshan.backend.exu 2*730cfbc0SXuan Hu 3*730cfbc0SXuan Huimport chipsalliance.rocketchip.config.Parameters 4*730cfbc0SXuan Huimport chisel3._ 5*730cfbc0SXuan Huimport chisel3.util._ 6*730cfbc0SXuan Huimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 7*730cfbc0SXuan Huimport utils._ 8*730cfbc0SXuan Huimport xiangshan.backend.fu.{CSRFileIO, FenceIO, FuncUnitInput} 9*730cfbc0SXuan Huimport xiangshan.backend.Bundles.{ExuInput, ExuOutput, MemExuInput, MemExuOutput} 10*730cfbc0SXuan Huimport xiangshan.{Redirect, XSBundle, XSModule} 11*730cfbc0SXuan Hu 12*730cfbc0SXuan Huclass ExeUnitIO(params: ExeUnitParams)(implicit p: Parameters) extends XSBundle { 13*730cfbc0SXuan Hu val flush = Flipped(ValidIO(new Redirect())) 14*730cfbc0SXuan Hu val in = Flipped(DecoupledIO(new ExuInput(params))) 15*730cfbc0SXuan Hu val out = DecoupledIO(new ExuOutput(params)) 16*730cfbc0SXuan Hu val csrio = if (params.hasCSR) Some(new CSRFileIO) else None 17*730cfbc0SXuan Hu val fenceio = if (params.hasFence) Some(new FenceIO) else None 18*730cfbc0SXuan Hu val frm = if (params.needSrcFrm) Some(Input(UInt(3.W))) else None 19*730cfbc0SXuan Hu} 20*730cfbc0SXuan Hu 21*730cfbc0SXuan Huclass ExeUnit(exuParams: ExeUnitParams)(implicit p: Parameters) extends LazyModule { 22*730cfbc0SXuan Hu lazy val module = new ExeUnitImp(this)(p, exuParams) 23*730cfbc0SXuan Hu} 24*730cfbc0SXuan Hu 25*730cfbc0SXuan Huclass ExeUnitImp( 26*730cfbc0SXuan Hu override val wrapper: ExeUnit 27*730cfbc0SXuan Hu)(implicit 28*730cfbc0SXuan Hu p: Parameters, exuParams: ExeUnitParams 29*730cfbc0SXuan Hu) extends LazyModuleImp(wrapper) { 30*730cfbc0SXuan Hu private val fuCfgs = exuParams.fuConfigs 31*730cfbc0SXuan Hu 32*730cfbc0SXuan Hu val io = IO(new ExeUnitIO(exuParams)) 33*730cfbc0SXuan Hu 34*730cfbc0SXuan Hu val funcUnits = fuCfgs.map(cfg => { 35*730cfbc0SXuan Hu val module = cfg.fuGen(p, cfg) 36*730cfbc0SXuan Hu module 37*730cfbc0SXuan Hu }) 38*730cfbc0SXuan Hu 39*730cfbc0SXuan Hu val busy = RegInit(false.B) 40*730cfbc0SXuan Hu val robIdx = RegEnable(io.in.bits.robIdx, io.in.fire) 41*730cfbc0SXuan Hu when (robIdx.needFlush(io.flush)) { 42*730cfbc0SXuan Hu busy := false.B 43*730cfbc0SXuan Hu }.elsewhen(io.out.fire) { 44*730cfbc0SXuan Hu busy := false.B 45*730cfbc0SXuan Hu }.elsewhen(io.in.fire) { 46*730cfbc0SXuan Hu busy := true.B 47*730cfbc0SXuan Hu } 48*730cfbc0SXuan Hu 49*730cfbc0SXuan Hu // rob flush --> funcUnits 50*730cfbc0SXuan Hu funcUnits.zipWithIndex.foreach { case (fu, i) => 51*730cfbc0SXuan Hu fu.io.flush <> io.flush 52*730cfbc0SXuan Hu } 53*730cfbc0SXuan Hu 54*730cfbc0SXuan Hu def acceptCond(input: ExuInput): Seq[Bool] = { 55*730cfbc0SXuan Hu input.params.fuConfigs.map(_.fuSel(input)) 56*730cfbc0SXuan Hu } 57*730cfbc0SXuan Hu 58*730cfbc0SXuan Hu val in1ToN = Module(new Dispatcher(new ExuInput(exuParams), funcUnits.length, acceptCond)) 59*730cfbc0SXuan Hu 60*730cfbc0SXuan Hu // ExeUnit.in <---> Dispatcher.in 61*730cfbc0SXuan Hu in1ToN.io.in.valid := io.in.valid && !busy 62*730cfbc0SXuan Hu in1ToN.io.in.bits := io.in.bits 63*730cfbc0SXuan Hu io.in.ready := !busy 64*730cfbc0SXuan Hu 65*730cfbc0SXuan Hu // Dispatcher.out <---> FunctionUnits 66*730cfbc0SXuan Hu in1ToN.io.out.zip(funcUnits.map(_.io.in)).foreach { 67*730cfbc0SXuan Hu case (source: DecoupledIO[ExuInput], sink: DecoupledIO[FuncUnitInput]) => 68*730cfbc0SXuan Hu sink.valid := source.valid 69*730cfbc0SXuan Hu source.ready := sink.ready 70*730cfbc0SXuan Hu 71*730cfbc0SXuan Hu sink.bits.src.zip(source.bits.src).foreach { case(fuSrc, exuSrc) => fuSrc := exuSrc } 72*730cfbc0SXuan Hu sink.bits.fuOpType := source.bits.fuOpType 73*730cfbc0SXuan Hu sink.bits.imm := source.bits.imm 74*730cfbc0SXuan Hu sink.bits.robIdx := source.bits.robIdx 75*730cfbc0SXuan Hu sink.bits.pdest := source.bits.pdest 76*730cfbc0SXuan Hu sink.bits.rfWen .foreach(x => x := source.bits.rfWen.get) 77*730cfbc0SXuan Hu sink.bits.fpWen .foreach(x => x := source.bits.fpWen.get) 78*730cfbc0SXuan Hu sink.bits.vecWen .foreach(x => x := source.bits.vecWen.get) 79*730cfbc0SXuan Hu sink.bits.fpu .foreach(x => x := source.bits.fpu.get) 80*730cfbc0SXuan Hu sink.bits.flushPipe .foreach(x => x := source.bits.flushPipe.get) 81*730cfbc0SXuan Hu sink.bits.pc .foreach(x => x := source.bits.pc.get) 82*730cfbc0SXuan Hu sink.bits.preDecode .foreach(x => x := source.bits.preDecode.get) 83*730cfbc0SXuan Hu sink.bits.ftqIdx .foreach(x => x := source.bits.ftqIdx.get) 84*730cfbc0SXuan Hu sink.bits.ftqOffset .foreach(x => x := source.bits.ftqOffset.get) 85*730cfbc0SXuan Hu sink.bits.predictInfo .foreach(x => x := source.bits.predictInfo.get) 86*730cfbc0SXuan Hu } 87*730cfbc0SXuan Hu 88*730cfbc0SXuan Hu private val fuOutValidOH = funcUnits.map(_.io.out.valid) 89*730cfbc0SXuan Hu private val fuOutBitsVec = funcUnits.map(_.io.out.bits) 90*730cfbc0SXuan Hu private val fuRedirectVec: Seq[Option[ValidIO[Redirect]]] = funcUnits.map(_.io.out.bits.redirect) 91*730cfbc0SXuan Hu 92*730cfbc0SXuan Hu // Assume that one fu can only write int or fp or vec, 93*730cfbc0SXuan Hu // otherwise, wenVec should be assigned to wen in fu. 94*730cfbc0SXuan Hu private val fuIntWenVec = funcUnits.map(_.cfg.writeIntRf.B) 95*730cfbc0SXuan Hu private val fuFpWenVec = funcUnits.map(_.cfg.writeFpRf.B) 96*730cfbc0SXuan Hu private val fuVecWenVec = funcUnits.map(_.cfg.writeVecRf.B) 97*730cfbc0SXuan Hu // FunctionUnits <---> ExeUnit.out 98*730cfbc0SXuan Hu io.out.valid := Cat(fuOutValidOH).orR 99*730cfbc0SXuan Hu funcUnits.foreach(fu => fu.io.out.ready := io.out.ready) 100*730cfbc0SXuan Hu 101*730cfbc0SXuan Hu // select one fu's result 102*730cfbc0SXuan Hu io.out.bits.data := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.data)) 103*730cfbc0SXuan Hu io.out.bits.robIdx := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.robIdx)) 104*730cfbc0SXuan Hu io.out.bits.pdest := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.pdest)) 105*730cfbc0SXuan Hu io.out.bits.intWen.foreach(x => x := Mux1H(fuOutValidOH, fuIntWenVec)) 106*730cfbc0SXuan Hu io.out.bits.fpWen.foreach(x => x := Mux1H(fuOutValidOH, fuFpWenVec)) 107*730cfbc0SXuan Hu io.out.bits.vecWen.foreach(x => x := Mux1H(fuOutValidOH, fuVecWenVec)) 108*730cfbc0SXuan Hu io.out.bits.redirect.foreach(x => x := Mux1H((fuOutValidOH zip fuRedirectVec).filter(_._2.isDefined).map(x => (x._1, x._2.get)))) 109*730cfbc0SXuan Hu io.out.bits.fflags.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.fflags.getOrElse(0.U.asTypeOf(io.out.bits.fflags.get))))) 110*730cfbc0SXuan Hu io.out.bits.exceptionVec.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.exceptionVec.getOrElse(0.U.asTypeOf(io.out.bits.exceptionVec.get))))) 111*730cfbc0SXuan Hu io.out.bits.flushPipe.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.flushPipe.getOrElse(0.U.asTypeOf(io.out.bits.flushPipe.get))))) 112*730cfbc0SXuan Hu io.out.bits.replay.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.replay.getOrElse(0.U.asTypeOf(io.out.bits.replay.get))))) 113*730cfbc0SXuan Hu io.out.bits.predecodeInfo.foreach(x => x := Mux1H(fuOutValidOH, fuOutBitsVec.map(_.preDecode.getOrElse(0.U.asTypeOf(io.out.bits.predecodeInfo.get))))) 114*730cfbc0SXuan Hu 115*730cfbc0SXuan Hu io.csrio.foreach(exuio => funcUnits.foreach(fu => fu.io.csrio.foreach(fuio => exuio <> fuio))) 116*730cfbc0SXuan Hu io.fenceio.foreach(exuio => funcUnits.foreach(fu => fu.io.fenceio.foreach(fuio => fuio <> exuio))) 117*730cfbc0SXuan Hu io.frm.foreach(exuio => funcUnits.foreach(fu => fu.io.frm.foreach(fuio => fuio <> exuio))) 118*730cfbc0SXuan Hu 119*730cfbc0SXuan Hu // debug info 120*730cfbc0SXuan Hu io.out.bits.debug := 0.U.asTypeOf(io.out.bits.debug) 121*730cfbc0SXuan Hu io.out.bits.debugInfo := 0.U.asTypeOf(io.out.bits.debugInfo) 122*730cfbc0SXuan Hu} 123*730cfbc0SXuan Hu 124*730cfbc0SXuan Huclass DispatcherIO[T <: Data](private val gen: T, n: Int) extends Bundle { 125*730cfbc0SXuan Hu val in = Flipped(DecoupledIO(gen)) 126*730cfbc0SXuan Hu 127*730cfbc0SXuan Hu val out = Vec(n, DecoupledIO(gen)) 128*730cfbc0SXuan Hu} 129*730cfbc0SXuan Hu 130*730cfbc0SXuan Huclass Dispatcher[T <: Data](private val gen: T, n: Int, acceptCond: T => Seq[Bool]) 131*730cfbc0SXuan Hu (implicit p: Parameters) 132*730cfbc0SXuan Hu extends Module { 133*730cfbc0SXuan Hu 134*730cfbc0SXuan Hu val io = IO(new DispatcherIO(gen, n)) 135*730cfbc0SXuan Hu 136*730cfbc0SXuan Hu private val acceptVec: Vec[Bool] = VecInit(acceptCond(io.in.bits)) 137*730cfbc0SXuan Hu 138*730cfbc0SXuan Hu XSError(io.in.valid && PopCount(acceptVec) > 1.U, s"s[ExeUnit] accept vec should no more than 1, ${Binary(acceptVec.asUInt)} ") 139*730cfbc0SXuan Hu XSError(io.in.valid && PopCount(acceptVec) === 0.U, "[ExeUnit] there is a inst not dispatched to any fu") 140*730cfbc0SXuan Hu 141*730cfbc0SXuan Hu io.out.zipWithIndex.foreach { case (out, i) => 142*730cfbc0SXuan Hu out.valid := acceptVec(i) && io.in.valid && out.ready 143*730cfbc0SXuan Hu out.bits := io.in.bits 144*730cfbc0SXuan Hu } 145*730cfbc0SXuan Hu 146*730cfbc0SXuan Hu io.in.ready := Cat(io.out.map(_.ready)).orR 147*730cfbc0SXuan Hu} 148*730cfbc0SXuan Hu 149*730cfbc0SXuan Huclass MemExeUnitIO (implicit p: Parameters) extends XSBundle { 150*730cfbc0SXuan Hu val flush = Flipped(ValidIO(new Redirect())) 151*730cfbc0SXuan Hu val in = Flipped(DecoupledIO(new MemExuInput())) 152*730cfbc0SXuan Hu val out = DecoupledIO(new MemExuOutput()) 153*730cfbc0SXuan Hu} 154*730cfbc0SXuan Hu 155*730cfbc0SXuan Huclass MemExeUnit(exuParams: ExeUnitParams)(implicit p: Parameters) extends XSModule { 156*730cfbc0SXuan Hu val io = IO(new MemExeUnitIO) 157*730cfbc0SXuan Hu require(exuParams.fuConfigs.size == 1, "[MemExeUnit] only support one fu yet") 158*730cfbc0SXuan Hu val fu = exuParams.fuConfigs.head.fuGen(p, exuParams.fuConfigs.head) 159*730cfbc0SXuan Hu fu.io.flush := io.flush 160*730cfbc0SXuan Hu fu.io.in.valid := io.in.valid 161*730cfbc0SXuan Hu io.in.ready := fu.io.in.ready 162*730cfbc0SXuan Hu 163*730cfbc0SXuan Hu fu.io.in.bits.robIdx := io.in.bits.uop.robIdx 164*730cfbc0SXuan Hu fu.io.in.bits.pdest := io.in.bits.uop.pdest 165*730cfbc0SXuan Hu fu.io.in.bits.fuOpType := io.in.bits.uop.fuOpType 166*730cfbc0SXuan Hu fu.io.in.bits.imm := io.in.bits.uop.imm 167*730cfbc0SXuan Hu fu.io.in.bits.src.zip(io.in.bits.src).foreach(x => x._1 := x._2) 168*730cfbc0SXuan Hu 169*730cfbc0SXuan Hu io.out.valid := fu.io.out.valid 170*730cfbc0SXuan Hu fu.io.out.ready := io.out.ready 171*730cfbc0SXuan Hu 172*730cfbc0SXuan Hu io.out.bits := 0.U.asTypeOf(io.out.bits) // dontCare other fields 173*730cfbc0SXuan Hu io.out.bits.data := fu.io.out.bits.data 174*730cfbc0SXuan Hu io.out.bits.uop.robIdx := fu.io.out.bits.robIdx 175*730cfbc0SXuan Hu io.out.bits.uop.pdest := fu.io.out.bits.pdest 176*730cfbc0SXuan Hu io.out.bits.uop.fuType := io.in.bits.uop.fuType 177*730cfbc0SXuan Hu io.out.bits.uop.fuOpType:= io.in.bits.uop.fuOpType 178*730cfbc0SXuan Hu io.out.bits.uop.sqIdx := io.in.bits.uop.sqIdx 179*730cfbc0SXuan Hu 180*730cfbc0SXuan Hu io.out.bits.debug := 0.U.asTypeOf(io.out.bits.debug) 181*730cfbc0SXuan Hu} 182