xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Multiplier.scala (revision 68eeafa8a2229450b289b44a3e3644291d5b8e3e)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import utils._
7import xiangshan.backend._
8import xiangshan.backend.fu.FunctionUnit._
9
10class MulDivCtrl extends Bundle{
11  val uop = new MicroOp
12  val sign = Bool()
13  val isW = Bool()
14  val isHi = Bool() // return hi bits of result ?
15}
16
17class MulDivOutput extends XSBundle {
18  val data = UInt(XLEN.W)
19  val uop = new MicroOp
20}
21
22class MulDivIO(val len: Int) extends XSBundle {
23  val in = Flipped(DecoupledIO(new Bundle() {
24    val src1, src2 = UInt(len.W)
25    val ctrl = new MulDivCtrl
26  }))
27  val out = DecoupledIO(new MulDivOutput)
28  val redirect = Flipped(ValidIO(new Redirect))
29}
30
31abstract class Multiplier
32(
33  val len: Int,
34  val latency: Int = 3
35) extends FunctionUnit(mulCfg) {
36  val io = IO(new MulDivIO(len))
37}
38
39trait HasPipelineReg { this: ArrayMultiplier =>
40
41  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
42  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
43  val ctrlVec = io.in.bits.ctrl +: Array.fill(latency)(Reg(new MulDivCtrl))
44  val flushVec = ctrlVec.zip(validVec).map(x => x._2 && x._1.uop.needFlush(io.redirect))
45
46  for(i <- 0 until latency){
47    rdyVec(i) := !validVec(i+1) || rdyVec(i+1)
48  }
49
50  for(i <- 1 to latency){
51    when(flushVec(i-1) || rdyVec(i) && !validVec(i-1)){
52      validVec(i) := false.B
53    }.elsewhen(rdyVec(i-1) && validVec(i-1) && !flushVec(i-1)){
54      validVec(i) := validVec(i-1)
55      ctrlVec(i) := ctrlVec(i-1)
56    }
57  }
58
59  io.in.ready := rdyVec(0)
60  io.out.valid := validVec.last && !flushVec.last
61  io.out.bits.uop := ctrlVec.last.uop
62
63  def PipelineReg[T<:Data](i: Int)(next: T) = RegEnable(
64    next,
65    enable = validVec(i-1) && rdyVec(i-1) && !flushVec(i-1)
66  )
67
68  def S1Reg[T<:Data](next: T):T = PipelineReg[T](1)(next)
69  def S2Reg[T<:Data](next: T):T = PipelineReg[T](2)(next)
70  def S3Reg[T<:Data](next: T):T = PipelineReg[T](3)(next)
71  def S4Reg[T<:Data](next: T):T = PipelineReg[T](4)(next)
72  def S5Reg[T<:Data](next: T):T = PipelineReg[T](5)(next)
73}
74
75class ArrayMultiplier
76(
77  len: Int,
78  latency: Int = 3,
79  realArray: Boolean = false
80) extends Multiplier(len, latency) with HasPipelineReg {
81
82  val mulRes = io.in.bits.src1.asSInt() * io.in.bits.src2.asSInt()
83
84  var dataVec = Seq(mulRes.asUInt())
85
86  for(i <- 1 to latency){
87    dataVec = dataVec :+ PipelineReg(i)(dataVec(i-1))
88  }
89
90  val xlen = io.out.bits.data.getWidth
91  val res = Mux(ctrlVec.last.isHi, dataVec.last(2*xlen-1, xlen), dataVec.last(xlen-1,0))
92  io.out.bits.data := Mux(ctrlVec.last.isW, SignExt(res(31,0),xlen), res)
93
94  XSDebug(p"validVec:${Binary(Cat(validVec))} flushVec:${Binary(Cat(flushVec))}\n")(this.name)
95
96  //  printf(p"t=${GTimer()} in: v${io.in.valid} r:${io.in.ready}\n")
97  //  printf(p"t=${GTimer()} out: v:${io.out.valid} r:${io.out.ready} vec:${Binary(Cat(validVec))}\n")
98}