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 44 45 46 47 48 49 50 51 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
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))
  val flushVec = ctrlVec.zip(validVec).map(x => x._2 && x._1.uop.brTag.needFlush(io.redirect))

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

  for(i <- 1 to latency){
    when(flushVec(i) || rdyVec(i) && !validVec(i-1)){
      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")
}