xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuncUnit.scala (revision d91483a658064c7276ee0181b0c527a3e2a7d2ee)
1package xiangshan.backend.fu
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.DataHoldBypass
7import xiangshan._
8import xiangshan.backend.rob.RobPtr
9import xiangshan.frontend.{FtqPtr, PreDecodeInfo}
10import xiangshan.backend.datapath.DataConfig._
11
12class FuncUnitInput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
13  val fuOpType  = FuOpType()
14  val src       = MixedVec(cfg.genSrcDataVec)
15  val imm       = UInt(cfg.dataBits.W)
16  val robIdx    = new RobPtr
17  val pdest     = UInt(PhyRegIdxWidth.W)
18  val rfWen     = if (cfg.writeIntRf)   Some(Bool())                        else None
19  val fpWen     = if (cfg.writeFpRf)    Some(Bool())                        else None
20  val vecWen    = if (cfg.writeVecRf)   Some(Bool())                        else None
21  val fpu       = if (cfg.needFPUCtrl)  Some(new FPUCtrlSignals)            else None
22
23  val flushPipe = if (cfg.flushPipe)    Some(Bool())                        else None
24  val pc        = if (cfg.needPc)       Some(UInt(VAddrData().dataWidth.W)) else None
25  val preDecode = if (cfg.hasPredecode) Some(new PreDecodeInfo)             else None
26  val ftqIdx    = if (cfg.needPc || cfg.replayInst)
27                                        Some(new FtqPtr)                    else None
28  val ftqOffset = if (cfg.needPc || cfg.replayInst)
29                                        Some(UInt(log2Up(PredictWidth).W))  else None
30  val predictInfo = if (cfg.hasRedirect)Some(new Bundle {
31    val target = UInt(VAddrData().dataWidth.W)
32    val taken = Bool()
33  }) else None
34}
35
36class FuncUnitOutput(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
37  val data         = UInt(cfg.dataBits.W)
38  val pdest        = UInt(PhyRegIdxWidth.W) // Todo: use maximum of pregIdxWidth of different pregs
39  val robIdx       = new RobPtr
40  val redirect     = if (cfg.hasRedirect) Some(ValidIO(new Redirect))        else None
41  val fflags       = if (cfg.writeFflags) Some(UInt(5.W))                    else None
42  val exceptionVec = if (cfg.exceptionOut.nonEmpty) Some(ExceptionVec())     else None
43  val flushPipe    = if (cfg.flushPipe)   Some(Bool())                       else None
44  val replay       = if (cfg.replayInst)  Some(Bool())                       else None
45  val pc           = if (cfg.isFence)     Some(UInt(VAddrData().dataWidth.W))else None
46  val fpu          = if (cfg.needFPUCtrl) Some(new FPUCtrlSignals)           else None // only used in FMA
47  val preDecode    = if (cfg.hasPredecode)Some(new PreDecodeInfo)            else None
48}
49
50class FuncUnitIO(cfg: FuConfig)(implicit p: Parameters) extends XSBundle {
51  val flush = Flipped(ValidIO(new Redirect))
52  val in = Flipped(DecoupledIO(new FuncUnitInput(cfg)))
53  val out = DecoupledIO(new FuncUnitOutput(cfg))
54  val csrio = if (cfg.isCsr) Some(new CSRFileIO) else None
55  val fenceio = if (cfg.isFence) Some(new FenceIO) else None
56  val frm = if (cfg.needSrcFrm) Some(Input(UInt(3.W))) else None
57}
58
59abstract class FuncUnit(val cfg: FuConfig)(implicit p: Parameters) extends XSModule {
60  val io = IO(new FuncUnitIO(cfg))
61
62  // should only be used in non-piped fu
63  def connectNonPipedCtrlSingal: Unit = {
64    io.out.bits.robIdx := DataHoldBypass(io.in.bits.robIdx, io.in.fire)
65    io.out.bits.pdest := DataHoldBypass(io.in.bits.pdest, io.in.fire)
66    io.out.bits.pc.foreach(_ := io.in.bits.pc.get)
67    io.out.bits.preDecode.foreach(_ := io.in.bits.preDecode.get)
68    io.out.bits.fpu.foreach(_ := DataHoldBypass(io.in.bits.fpu.get, io.in.fire))
69  }
70}
71
72/**
73  * @author LinJiaWei, Yinan Xu
74  */
75trait HasPipelineReg { this: FuncUnit =>
76  def latency: Int
77
78  require(latency > 0)
79
80  val validVec = io.in.valid +: Seq.fill(latency)(RegInit(false.B))
81  val rdyVec = Seq.fill(latency)(Wire(Bool())) :+ io.out.ready
82  val robIdxVec = io.in.bits.robIdx +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.robIdx)))
83  val pdestVec = io.in.bits.pdest +: Array.fill(latency)(Reg(chiselTypeOf(io.in.bits.pdest)))
84
85  val pcVec = io.in.bits.pc.map(x => x) +: Array.fill(latency)( io.in.bits.pc.map(x => Reg(chiselTypeOf(x)))) // Reg(chiselTypeOf(io.in.bits.pc.get))
86  val preDecodeVec = io.in.bits.preDecode.map(x => x) +: Array.fill(latency)(io.in.bits.preDecode.map(x => Reg(chiselTypeOf(x))))
87  val fpuVec = io.in.bits.fpu.map(x => x) +: Array.fill(latency)(io.in.bits.fpu.map(x => Reg(chiselTypeOf(x))))
88
89  // if flush(0), valid 0 will not given, so set flushVec(0) to false.B
90  val flushVec = validVec.zip(robIdxVec).map(x => x._1 && x._2.needFlush(io.flush))
91
92  for (i <- 0 until latency) {
93    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
94  }
95
96  for (i <- 1 to latency) {
97    when(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)){
98      validVec(i) := validVec(i - 1)
99      robIdxVec(i) := robIdxVec(i - 1)
100      pdestVec(i) := pdestVec(i - 1)
101      pcVec(i).zip(pcVec(i - 1)).foreach{case (l,r) => l := r}
102      preDecodeVec(i).zip(preDecodeVec(i - 1)).foreach{case (l,r) => l := r}
103      fpuVec(i).zip(fpuVec(i - 1)).foreach{case (l,r) => l := r}
104    }.elsewhen(flushVec(i) || rdyVec(i)){
105      validVec(i) := false.B
106    }
107  }
108
109  io.in.ready := rdyVec(0)
110  io.out.valid := validVec.last
111  io.out.bits.robIdx := robIdxVec.last
112  io.out.bits.pdest := pdestVec.last
113  io.out.bits.pc.zip(pcVec.last).foreach{case (l,r) => l := r}
114  io.out.bits.preDecode.zip(preDecodeVec.last).foreach{case (l,r) => l := r}
115  io.out.bits.fpu.zip(fpuVec.last).foreach{case (l,r) => l := r}
116
117  def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
118
119  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
120    next,
121    regEnable(i)
122  )
123
124  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)
125
126  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)
127
128  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)
129
130  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)
131
132  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
133
134}
135
136
137