1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import utils._ 7 8abstract class AbstractDivider(len: Int) extends FunctionUnit( 9 FuConfig(FuType.div, 2, 0, writeIntRf = true, writeFpRf = false, hasRedirect = false, UncertainLatency()), 10 len 11){ 12 val ctrl = IO(Input(new MulDivCtrl)) 13 val sign = ctrl.sign 14} 15 16class Radix2Divider(len: Int) extends AbstractDivider(len) { 17 18 def abs(a: UInt, sign: Bool): (Bool, UInt) = { 19 val s = a(len - 1) && sign 20 (s, Mux(s, -a, a)) 21 } 22 23 val s_idle :: s_log2 :: s_shift :: s_compute :: s_finish :: Nil = Enum(5) 24 val state = RegInit(s_idle) 25 val newReq = (state === s_idle) && io.in.fire() 26 27 val (a, b) = (io.in.bits.src(0), io.in.bits.src(1)) 28 val divBy0 = b === 0.U(len.W) 29 val divBy0Reg = RegEnable(divBy0, newReq) 30 31 val shiftReg = Reg(UInt((1 + len * 2).W)) 32 val hi = shiftReg(len * 2, len) 33 val lo = shiftReg(len - 1, 0) 34 35 val uop = io.in.bits.uop 36 37 val (aSign, aVal) = abs(a, sign) 38 val (bSign, bVal) = abs(b, sign) 39 val aSignReg = RegEnable(aSign, newReq) 40 val qSignReg = RegEnable((aSign ^ bSign) && !divBy0, newReq) 41 val bReg = RegEnable(bVal, newReq) 42 val aValx2Reg = RegEnable(Cat(aVal, "b0".U), newReq) 43 val ctrlReg = RegEnable(ctrl, newReq) 44 val uopReg = RegEnable(uop, newReq) 45 46 val cnt = Counter(len) 47 when (newReq) { 48 state := s_log2 49 } .elsewhen (state === s_log2) { 50 // `canSkipShift` is calculated as following: 51 // bEffectiveBit = Log2(bVal, XLEN) + 1.U 52 // aLeadingZero = 64.U - aEffectiveBit = 64.U - (Log2(aVal, XLEN) + 1.U) 53 // canSkipShift = aLeadingZero + bEffectiveBit 54 // = 64.U - (Log2(aVal, XLEN) + 1.U) + Log2(bVal, XLEN) + 1.U 55 // = 64.U + Log2(bVal, XLEN) - Log2(aVal, XLEN) 56 // = (64.U | Log2(bVal, XLEN)) - Log2(aVal, XLEN) // since Log2(bVal, XLEN) < 64.U 57 val canSkipShift = (64.U | Log2(bReg)) - Log2(aValx2Reg) 58 // When divide by 0, the quotient should be all 1's. 59 // Therefore we can not shift in 0s here. 60 // We do not skip any shift to avoid this. 61 cnt.value := Mux(divBy0Reg, 0.U, Mux(canSkipShift >= (len-1).U, (len-1).U, canSkipShift)) 62 state := s_shift 63 } .elsewhen (state === s_shift) { 64 shiftReg := aValx2Reg << cnt.value 65 state := s_compute 66 } .elsewhen (state === s_compute) { 67 val enough = hi.asUInt >= bReg.asUInt 68 shiftReg := Cat(Mux(enough, hi - bReg, hi)(len - 1, 0), lo, enough) 69 cnt.inc() 70 when (cnt.value === (len-1).U) { state := s_finish } 71 } .elsewhen (state === s_finish) { 72 when(io.out.ready){ 73 state := s_idle 74 } 75 } 76 77 val kill = state=/=s_idle && uopReg.roqIdx.needFlush(io.redirectIn) 78 when(kill){ 79 state := s_idle 80 } 81 82 val r = hi(len, 1) 83 val resQ = Mux(qSignReg, -lo, lo) 84 val resR = Mux(aSignReg, -r, r) 85 86 val xlen = io.out.bits.data.getWidth 87 val res = Mux(ctrlReg.isHi, resR, resQ) 88 io.out.bits.data := Mux(ctrlReg.isW, SignExt(res(31,0),xlen), res) 89 io.out.bits.uop := uopReg 90 91 io.out.valid := state === s_finish && !kill 92 io.in.ready := state === s_idle 93}