xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Radix2Divider.scala (revision 8891a219bbc84f568e1d134854d8d5ed86d6d560)
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