1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.fu 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import utility._ 25 26abstract class AbstractDivider(len: Int)(implicit p: Parameters) extends FunctionUnit(len){ 27 val ctrl = IO(Input(new MulDivCtrl)) 28 val sign = ctrl.sign 29} 30 31class Radix2Divider(len: Int)(implicit p: Parameters) extends AbstractDivider(len) { 32 33 def abs(a: UInt, sign: Bool): (Bool, UInt) = { 34 val s = a(len - 1) && sign 35 (s, Mux(s, -a, a)) 36 } 37 38 val s_idle :: s_log2 :: s_shift :: s_compute :: s_finish :: Nil = Enum(5) 39 val state = RegInit(s_idle) 40 val newReq = (state === s_idle) && io.in.fire 41 42 val (a, b) = (io.in.bits.src(0), io.in.bits.src(1)) 43 val divBy0 = b === 0.U(len.W) 44 val divBy0Reg = RegEnable(divBy0, newReq) 45 46 val shiftReg = Reg(UInt((1 + len * 2).W)) 47 val hi = shiftReg(len * 2, len) 48 val lo = shiftReg(len - 1, 0) 49 50 val uop = io.in.bits.uop 51 52 val (aSign, aVal) = abs(a, sign) 53 val (bSign, bVal) = abs(b, sign) 54 val aSignReg = RegEnable(aSign, newReq) 55 val qSignReg = RegEnable((aSign ^ bSign) && !divBy0, newReq) 56 val bReg = RegEnable(bVal, newReq) 57 val aValx2Reg = RegEnable(Cat(aVal, "b0".U), newReq) 58 val ctrlReg = RegEnable(ctrl, newReq) 59 val uopReg = RegEnable(uop, newReq) 60 61 val cnt = Counter(len) 62 when (newReq && !io.in.bits.uop.robIdx.needFlush(io.redirectIn)) { 63 state := s_log2 64 } .elsewhen (state === s_log2) { 65 // `canSkipShift` is calculated as following: 66 // bEffectiveBit = Log2(bVal, XLEN) + 1.U 67 // aLeadingZero = 64.U - aEffectiveBit = 64.U - (Log2(aVal, XLEN) + 1.U) 68 // canSkipShift = aLeadingZero + bEffectiveBit 69 // = 64.U - (Log2(aVal, XLEN) + 1.U) + Log2(bVal, XLEN) + 1.U 70 // = 64.U + Log2(bVal, XLEN) - Log2(aVal, XLEN) 71 // = (64.U | Log2(bVal, XLEN)) - Log2(aVal, XLEN) // since Log2(bVal, XLEN) < 64.U 72 val canSkipShift = (64.U | Log2(bReg)) - Log2(aValx2Reg) 73 // When divide by 0, the quotient should be all 1's. 74 // Therefore we can not shift in 0s here. 75 // We do not skip any shift to avoid this. 76 cnt.value := Mux(divBy0Reg, 0.U, Mux(canSkipShift >= (len-1).U, (len-1).U, canSkipShift)) 77 state := s_shift 78 } .elsewhen (state === s_shift) { 79 shiftReg := aValx2Reg << cnt.value 80 state := s_compute 81 } .elsewhen (state === s_compute) { 82 val enough = hi.asUInt >= bReg.asUInt 83 shiftReg := Cat(Mux(enough, hi - bReg, hi)(len - 1, 0), lo, enough) 84 cnt.inc() 85 when (cnt.value === (len-1).U) { state := s_finish } 86 } .elsewhen (state === s_finish) { 87 when(io.out.ready){ 88 state := s_idle 89 } 90 } 91 92 val kill = state=/=s_idle && uopReg.robIdx.needFlush(io.redirectIn) 93 when(kill){ 94 state := s_idle 95 } 96 97 val r = hi(len, 1) 98 val resQ = Mux(qSignReg, -lo, lo) 99 val resR = Mux(aSignReg, -r, r) 100 101 val xlen = io.out.bits.data.getWidth 102 val res = Mux(ctrlReg.isHi, resR, resQ) 103 io.out.bits.data := Mux(ctrlReg.isW, SignExt(res(31,0),xlen), res) 104 io.out.bits.uop := uopReg 105 106 io.out.valid := state === s_finish 107 io.in.ready := state === s_idle 108} 109