1c6d43980SLemover/*************************************************************************************** 2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover* 5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover* http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover* 10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover* 14c6d43980SLemover* See the Mulan PSL v2 for more details. 15c6d43980SLemover***************************************************************************************/ 16c6d43980SLemover 175018a303SLinJiaweipackage xiangshan.backend.fu 185018a303SLinJiawei 19*8891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 205018a303SLinJiaweiimport chisel3._ 215018a303SLinJiaweiimport chisel3.util._ 225018a303SLinJiaweiimport xiangshan._ 235018a303SLinJiaweiimport utils._ 243c02ee8fSwakafaimport utility._ 255018a303SLinJiawei 262225d46eSJiawei Linabstract class AbstractDivider(len: Int)(implicit p: Parameters) extends FunctionUnit(len){ 275018a303SLinJiawei val ctrl = IO(Input(new MulDivCtrl)) 285018a303SLinJiawei val sign = ctrl.sign 295018a303SLinJiawei} 305018a303SLinJiawei 312225d46eSJiawei Linclass Radix2Divider(len: Int)(implicit p: Parameters) extends AbstractDivider(len) { 325018a303SLinJiawei 335018a303SLinJiawei def abs(a: UInt, sign: Bool): (Bool, UInt) = { 345018a303SLinJiawei val s = a(len - 1) && sign 355018a303SLinJiawei (s, Mux(s, -a, a)) 365018a303SLinJiawei } 375018a303SLinJiawei 385018a303SLinJiawei val s_idle :: s_log2 :: s_shift :: s_compute :: s_finish :: Nil = Enum(5) 395018a303SLinJiawei val state = RegInit(s_idle) 40935edac4STang Haojin val newReq = (state === s_idle) && io.in.fire 415018a303SLinJiawei 425018a303SLinJiawei val (a, b) = (io.in.bits.src(0), io.in.bits.src(1)) 435018a303SLinJiawei val divBy0 = b === 0.U(len.W) 445018a303SLinJiawei val divBy0Reg = RegEnable(divBy0, newReq) 455018a303SLinJiawei 465018a303SLinJiawei val shiftReg = Reg(UInt((1 + len * 2).W)) 475018a303SLinJiawei val hi = shiftReg(len * 2, len) 485018a303SLinJiawei val lo = shiftReg(len - 1, 0) 495018a303SLinJiawei 505018a303SLinJiawei val uop = io.in.bits.uop 515018a303SLinJiawei 525018a303SLinJiawei val (aSign, aVal) = abs(a, sign) 535018a303SLinJiawei val (bSign, bVal) = abs(b, sign) 545018a303SLinJiawei val aSignReg = RegEnable(aSign, newReq) 555018a303SLinJiawei val qSignReg = RegEnable((aSign ^ bSign) && !divBy0, newReq) 565018a303SLinJiawei val bReg = RegEnable(bVal, newReq) 575018a303SLinJiawei val aValx2Reg = RegEnable(Cat(aVal, "b0".U), newReq) 585018a303SLinJiawei val ctrlReg = RegEnable(ctrl, newReq) 595018a303SLinJiawei val uopReg = RegEnable(uop, newReq) 605018a303SLinJiawei 615018a303SLinJiawei val cnt = Counter(len) 62f4b2089aSYinan Xu when (newReq && !io.in.bits.uop.robIdx.needFlush(io.redirectIn)) { 635018a303SLinJiawei state := s_log2 645018a303SLinJiawei } .elsewhen (state === s_log2) { 655018a303SLinJiawei // `canSkipShift` is calculated as following: 665018a303SLinJiawei // bEffectiveBit = Log2(bVal, XLEN) + 1.U 675018a303SLinJiawei // aLeadingZero = 64.U - aEffectiveBit = 64.U - (Log2(aVal, XLEN) + 1.U) 685018a303SLinJiawei // canSkipShift = aLeadingZero + bEffectiveBit 695018a303SLinJiawei // = 64.U - (Log2(aVal, XLEN) + 1.U) + Log2(bVal, XLEN) + 1.U 705018a303SLinJiawei // = 64.U + Log2(bVal, XLEN) - Log2(aVal, XLEN) 715018a303SLinJiawei // = (64.U | Log2(bVal, XLEN)) - Log2(aVal, XLEN) // since Log2(bVal, XLEN) < 64.U 725018a303SLinJiawei val canSkipShift = (64.U | Log2(bReg)) - Log2(aValx2Reg) 735018a303SLinJiawei // When divide by 0, the quotient should be all 1's. 745018a303SLinJiawei // Therefore we can not shift in 0s here. 755018a303SLinJiawei // We do not skip any shift to avoid this. 765018a303SLinJiawei cnt.value := Mux(divBy0Reg, 0.U, Mux(canSkipShift >= (len-1).U, (len-1).U, canSkipShift)) 775018a303SLinJiawei state := s_shift 785018a303SLinJiawei } .elsewhen (state === s_shift) { 795018a303SLinJiawei shiftReg := aValx2Reg << cnt.value 805018a303SLinJiawei state := s_compute 815018a303SLinJiawei } .elsewhen (state === s_compute) { 825018a303SLinJiawei val enough = hi.asUInt >= bReg.asUInt 835018a303SLinJiawei shiftReg := Cat(Mux(enough, hi - bReg, hi)(len - 1, 0), lo, enough) 845018a303SLinJiawei cnt.inc() 855018a303SLinJiawei when (cnt.value === (len-1).U) { state := s_finish } 865018a303SLinJiawei } .elsewhen (state === s_finish) { 875018a303SLinJiawei when(io.out.ready){ 885018a303SLinJiawei state := s_idle 895018a303SLinJiawei } 905018a303SLinJiawei } 915018a303SLinJiawei 92f4b2089aSYinan Xu val kill = state=/=s_idle && uopReg.robIdx.needFlush(io.redirectIn) 93ff8496b2SLinJiawei when(kill){ 945018a303SLinJiawei state := s_idle 955018a303SLinJiawei } 965018a303SLinJiawei 975018a303SLinJiawei val r = hi(len, 1) 985018a303SLinJiawei val resQ = Mux(qSignReg, -lo, lo) 995018a303SLinJiawei val resR = Mux(aSignReg, -r, r) 1005018a303SLinJiawei 1015018a303SLinJiawei val xlen = io.out.bits.data.getWidth 1025018a303SLinJiawei val res = Mux(ctrlReg.isHi, resR, resQ) 1035018a303SLinJiawei io.out.bits.data := Mux(ctrlReg.isW, SignExt(res(31,0),xlen), res) 1045018a303SLinJiawei io.out.bits.uop := uopReg 1055018a303SLinJiawei 106d0d8f03aSYinan Xu io.out.valid := state === s_finish 1075018a303SLinJiawei io.in.ready := state === s_idle 1085018a303SLinJiawei} 109