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}