1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan.backend.fu 17 18import chipsalliance.rocketchip.config.Parameters 19import chisel3._ 20import chisel3.util._ 21import xiangshan._ 22import xiangshan.backend.fu.fpu._ 23 24trait HasFuLatency { 25 val latencyVal: Option[Int] 26} 27 28case class CertainLatency(value: Int) extends HasFuLatency { 29 override val latencyVal: Option[Int] = Some(value) 30} 31 32case class UncertainLatency() extends HasFuLatency { 33 override val latencyVal: Option[Int] = None 34} 35 36 37case class FuConfig 38( 39 fuGen: Parameters => FunctionUnit, 40 fuSel: FunctionUnit => Bool, 41 fuType: UInt, 42 numIntSrc: Int, 43 numFpSrc: Int, 44 writeIntRf: Boolean, 45 writeFpRf: Boolean, 46 hasRedirect: Boolean, 47 latency: HasFuLatency = CertainLatency(0), 48) { 49 def srcCnt: Int = math.max(numIntSrc, numFpSrc) 50} 51 52 53class FuOutput(val len: Int)(implicit p: Parameters) extends XSBundle { 54 val data = UInt(len.W) 55 val uop = new MicroOp 56} 57 58 59class FunctionUnitIO(val len: Int)(implicit p: Parameters) extends XSBundle { 60 val in = Flipped(DecoupledIO(new Bundle() { 61 val src = Vec(3, UInt(len.W)) 62 val uop = new MicroOp 63 })) 64 65 val out = DecoupledIO(new FuOutput(len)) 66 67 val redirectIn = Flipped(ValidIO(new Redirect)) 68 val flushIn = Input(Bool()) 69} 70 71abstract class FunctionUnit(len: Int = 64)(implicit p: Parameters) extends XSModule { 72 73 val io = IO(new FunctionUnitIO(len)) 74 75} 76 77trait HasPipelineReg { 78 this: FunctionUnit => 79 80 def latency: Int 81 82 require(latency > 0) 83 84 val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B)) 85 val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready 86 val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp)) 87 88 89 // if flush(0), valid 0 will not given, so set flushVec(0) to false.B 90 val flushVec = validVec.zip(uopVec).map(x => x._1 && x._2.roqIdx.needFlush(io.redirectIn, io.flushIn)) 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 uopVec(i) := uopVec(i - 1) 100 }.elsewhen(flushVec(i) || rdyVec(i)){ 101 validVec(i) := false.B 102 } 103 } 104 105 io.in.ready := rdyVec(0) 106 io.out.valid := validVec.last 107 io.out.bits.uop := uopVec.last 108 109 def regEnable(i: Int): Bool = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1) 110 111 def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable( 112 next, 113 enable = regEnable(i) 114 ) 115 116 def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next) 117 118 def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next) 119 120 def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next) 121 122 def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next) 123 124 def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next) 125} 126