Multiplier.scala 2.8 KB
Newer Older
L
LinJiawei 已提交
1 2 3 4 5
package xiangshan.backend.fu

import chisel3._
import chisel3.util._
import xiangshan._
L
LinJiawei 已提交
6
import utils._
L
LinJiawei 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
import xiangshan.backend._
import xiangshan.backend.fu.FunctionUnit._

class MulDivCtrl extends Bundle{
  val uop = new MicroOp
  val sign = Bool()
  val isW = Bool()
  val isHi = Bool() // return hi bits of result ?
}

class MulDivOutput extends XSBundle {
  val data = UInt(XLEN.W)
  val uop = new MicroOp
}

class MulDivIO(val len: Int) extends XSBundle {
  val in = Flipped(DecoupledIO(new Bundle() {
    val src1, src2 = UInt(len.W)
    val ctrl = new MulDivCtrl
  }))
  val out = DecoupledIO(new MulDivOutput)
  val redirect = Flipped(ValidIO(new Redirect))
}

abstract class Multiplier
(
  val len: Int,
  val latency: Int = 3
) extends FunctionUnit(mulCfg) {
  val io = IO(new MulDivIO(len))
}

trait HasPipelineReg { this: ArrayMultiplier =>

  val validVec = io.in.valid +: Array.fill(latency)(RegInit(false.B))
  val rdyVec = Array.fill(latency)(Wire(Bool())) :+ io.out.ready
  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))
L
LinJiawei 已提交
45 46 47 48 49 50

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

  for(i <- 1 to latency){
G
GouLingrui 已提交
51
    when(flushVec(i-1) || rdyVec(i) && !validVec(i-1)){
L
LinJiawei 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
      validVec(i) := false.B
    }.elsewhen(rdyVec(i-1) && validVec(i-1) && !flushVec(i-1)){
      validVec(i) := validVec(i-1)
      ctrlVec(i) := ctrlVec(i-1)
    }
  }

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

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

  def S1Reg[T<:Data](next: T):T = PipelineReg[T](1)(next)
  def S2Reg[T<:Data](next: T):T = PipelineReg[T](2)(next)
  def S3Reg[T<:Data](next: T):T = PipelineReg[T](3)(next)
  def S4Reg[T<:Data](next: T):T = PipelineReg[T](4)(next)
  def S5Reg[T<:Data](next: T):T = PipelineReg[T](5)(next)
}

class ArrayMultiplier
(
  len: Int,
  latency: Int = 3,
  realArray: Boolean = false
) extends Multiplier(len, latency) with HasPipelineReg {

  val mulRes = io.in.bits.src1.asSInt() * io.in.bits.src2.asSInt()

  var dataVec = Seq(mulRes.asUInt())

  for(i <- 1 to latency){
    dataVec = dataVec :+ PipelineReg(i)(dataVec(i-1))
  }

  val xlen = io.out.bits.data.getWidth
  val res = Mux(ctrlVec.last.isHi, dataVec.last(2*xlen-1, xlen), dataVec.last(xlen-1,0))
  io.out.bits.data := Mux(ctrlVec.last.isW, SignExt(res(31,0),xlen), res)

  XSDebug(p"validVec:${Binary(Cat(validVec))} flushVec:${Binary(Cat(flushVec))}\n")(this.name)

  //  printf(p"t=${GTimer()} in: v${io.in.valid} r:${io.in.ready}\n")
  //  printf(p"t=${GTimer()} out: v:${io.out.valid} r:${io.out.ready} vec:${Binary(Cat(validVec))}\n")
}