FunctionUnit.scala 4.9 KB
Newer Older
L
LinJiawei 已提交
1 2 3 4 5 6 7 8 9 10 11
package xiangshan.backend.fu

import chisel3._
import chisel3.util._
import xiangshan._

/*
    XiangShan Function Unit
    A Exu can have one or more function units
 */

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
trait HasFuLatency {
  val latencyVal: Option[Int]
}

case class CertainLatency(value: Int) extends HasFuLatency{
  override val latencyVal: Option[Int] = Some(value)
}

case class UncertainLatency() extends HasFuLatency {
  override val latencyVal: Option[Int] = None
}

case class NexusLatency(value: Int) extends HasFuLatency {
  override val latencyVal: Option[Int] = Some(value)
}

28 29


L
LinJiawei 已提交
30 31 32 33 34 35 36
case class FuConfig
(
  fuType: UInt,
  numIntSrc: Int,
  numFpSrc: Int,
  writeIntRf: Boolean,
  writeFpRf: Boolean,
37 38
  hasRedirect: Boolean,
  latency: HasFuLatency = CertainLatency(0)
L
LinJiawei 已提交
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
) {
  def srcCnt: Int = math.max(numIntSrc, numFpSrc)
}

class FunctionUnitIO[TI <: Data, TO <: Data]
(
  cfg: FuConfig,
  len: Int,
  extIn: => TI = null,
  extOut: => TO = null
) extends XSBundle
{
  val in = Flipped(DecoupledIO(new Bundle() {
    val src = Vec(cfg.srcCnt, UInt(len.W))
    val uop = new MicroOp
    val ext = if(extIn == null) None else Some(extIn.cloneType)
55 56 57 58 59 60

    def connectToExuInput(exuIn: ExuInput): Unit = {
      val exuSrcIn = Seq(exuIn.src1, exuIn.src2, exuIn.src3)
      src.zip(exuSrcIn).foreach{case (x, y) => x := y}
      uop := exuIn.uop
    }
L
Add CSR  
LinJiawei 已提交
61
  }))
62

L
LinJiawei 已提交
63 64 65 66 67
  val out = DecoupledIO(new Bundle() {
    val data = UInt(XLEN.W)
    val uop = new MicroOp
    val ext = if(extOut == null) None else Some(extOut.cloneType)
  })
68

L
LinJiawei 已提交
69
  val redirectIn = Flipped(ValidIO(new Redirect))
70 71 72

  override def cloneType: FunctionUnitIO.this.type =
    new FunctionUnitIO(cfg, len, extIn, extOut).asInstanceOf[this.type]
L
LinJiawei 已提交
73 74 75 76 77 78 79
}

abstract class FunctionUnit[TI <: Data, TO <: Data]
(
  cfg: FuConfig,
  len: Int = 64,
  extIn: => TI = null,
80 81
  extOut: => TO = null,
  val latency: Int = 0
L
LinJiawei 已提交
82 83 84 85
) extends XSModule {

  val io = IO(new FunctionUnitIO[TI, TO](cfg, len, extIn, extOut))

L
Add CSR  
LinJiawei 已提交
86 87
}

88 89
trait HasPipelineReg[TI <: Data, TO <: Data] {
  this: FunctionUnit[TI, TO] =>
L
LinJiawei 已提交
90 91 92 93 94 95

  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
  val uopVec = io.in.bits.uop +: Array.fill(latency)(Reg(new MicroOp))


L
LinJiawei 已提交
96
  val flushVec = uopVec.zip(validVec).map(x => x._2 && x._1.roqIdx.needFlush(io.redirectIn))
L
LinJiawei 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

  for (i <- 0 until latency) {
    rdyVec(i) := !validVec(i + 1) || rdyVec(i + 1)
  }

  for (i <- 1 to latency) {
    when(flushVec(i - 1) || rdyVec(i) && !validVec(i - 1)) {
      validVec(i) := false.B
    }.elsewhen(rdyVec(i - 1) && validVec(i - 1) && !flushVec(i - 1)) {
      validVec(i) := validVec(i - 1)
      uopVec(i) := uopVec(i - 1)
    }
  }

  io.in.ready := rdyVec(0)
  io.out.valid := validVec.last && !flushVec.last
  io.out.bits.uop := uopVec.last

  def PipelineReg[TT <: Data](i: Int)(next: TT) = RegEnable(
    next,
    enable = validVec(i - 1) && rdyVec(i - 1) && !flushVec(i - 1)
  )

  def S1Reg[TT <: Data](next: TT): TT = PipelineReg[TT](1)(next)

  def S2Reg[TT <: Data](next: TT): TT = PipelineReg[TT](2)(next)

  def S3Reg[TT <: Data](next: TT): TT = PipelineReg[TT](3)(next)

  def S4Reg[TT <: Data](next: TT): TT = PipelineReg[TT](4)(next)

  def S5Reg[TT <: Data](next: TT): TT = PipelineReg[TT](5)(next)
}
L
LinJiawei 已提交
130 131

object FunctionUnit {
L
Add CSR  
LinJiawei 已提交
132 133 134 135

  val csrCfg =
    FuConfig(FuType.csr, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false)

L
LinJiawei 已提交
136 137 138 139 140 141 142 143 144 145
  val jmpCfg =
    FuConfig(FuType.jmp, 1, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true)

  val i2fCfg =
    FuConfig(FuType.i2f, 1, 0, writeIntRf = false, writeFpRf = true, hasRedirect = false)

  val aluCfg =
    FuConfig(FuType.alu, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = true)

  val mulCfg =
146
    FuConfig(FuType.mul, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false,
147
      UncertainLatency()// CertainLatency(3)
148
    )
L
LinJiawei 已提交
149 150

  val divCfg =
151 152 153
    FuConfig(FuType.div, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false,
      UncertainLatency()
    )
L
LinJiawei 已提交
154

155 156 157
  val fenceCfg = 
    FuConfig(FuType.fence, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false/*NOTE: need redirect but when commit*/)

158
  val lduCfg =
159 160 161
    FuConfig(FuType.ldu, 1, 0, writeIntRf = true, writeFpRf = true, hasRedirect = false,
      UncertainLatency()
    )
162 163

  val stuCfg =
164 165 166
    FuConfig(FuType.stu, 2, 1, writeIntRf = false, writeFpRf = false, hasRedirect = false,
      UncertainLatency()
    )
L
LinJiawei 已提交
167

168 169 170 171
  val mouCfg = 
    FuConfig(FuType.mou, 2, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,
      UncertainLatency()
  )
172

L
LinJiawei 已提交
173
  val fmacCfg =
174 175 176
    FuConfig(FuType.fmac, 0, 3, writeIntRf = false, writeFpRf = true, hasRedirect = false,
      CertainLatency(5)
    )
L
LinJiawei 已提交
177 178

  val fmiscCfg =
L
LinJiawei 已提交
179
    FuConfig(FuType.fmisc, 0, 2, writeIntRf = true, writeFpRf = true, hasRedirect = false,
180
      UncertainLatency()
181
    )
L
LinJiawei 已提交
182 183

  val fDivSqrtCfg =
184 185 186
    FuConfig(FuType.fDivSqrt, 0, 2, writeIntRf = false, writeFpRf = true, hasRedirect = false,
      UncertainLatency()
    )
187
}