xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Radix2Divider.scala (revision 708ceed4afe43fb0ea3a52407e46b2794c573634)
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 chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan._
23import utils._
24
25abstract class AbstractDivider(len: Int)(implicit p: Parameters) extends FunctionUnit(len){
26  val ctrl = IO(Input(new MulDivCtrl))
27  val sign = ctrl.sign
28}
29
30class Radix2Divider(len: Int)(implicit p: Parameters) extends AbstractDivider(len) {
31
32  def abs(a: UInt, sign: Bool): (Bool, UInt) = {
33    val s = a(len - 1) && sign
34    (s, Mux(s, -a, a))
35  }
36
37  val s_idle :: s_log2 :: s_shift :: s_compute :: s_finish :: Nil = Enum(5)
38  val state = RegInit(s_idle)
39  val newReq = (state === s_idle) && io.in.fire()
40
41  val (a, b) = (io.in.bits.src(0), io.in.bits.src(1))
42  val divBy0 = b === 0.U(len.W)
43  val divBy0Reg = RegEnable(divBy0, newReq)
44
45  val shiftReg = Reg(UInt((1 + len * 2).W))
46  val hi = shiftReg(len * 2, len)
47  val lo = shiftReg(len - 1, 0)
48
49  val uop = io.in.bits.uop
50
51  val (aSign, aVal) = abs(a, sign)
52  val (bSign, bVal) = abs(b, sign)
53  val aSignReg = RegEnable(aSign, newReq)
54  val qSignReg = RegEnable((aSign ^ bSign) && !divBy0, newReq)
55  val bReg = RegEnable(bVal, newReq)
56  val aValx2Reg = RegEnable(Cat(aVal, "b0".U), newReq)
57  val ctrlReg = RegEnable(ctrl, newReq)
58  val uopReg = RegEnable(uop, newReq)
59
60  val cnt = Counter(len)
61  when (newReq && !io.in.bits.uop.roqIdx.needFlush(io.redirectIn, io.flushIn)) {
62    state := s_log2
63  } .elsewhen (state === s_log2) {
64    // `canSkipShift` is calculated as following:
65    //   bEffectiveBit = Log2(bVal, XLEN) + 1.U
66    //   aLeadingZero = 64.U - aEffectiveBit = 64.U - (Log2(aVal, XLEN) + 1.U)
67    //   canSkipShift = aLeadingZero + bEffectiveBit
68    //     = 64.U - (Log2(aVal, XLEN) + 1.U) + Log2(bVal, XLEN) + 1.U
69    //     = 64.U + Log2(bVal, XLEN) - Log2(aVal, XLEN)
70    //     = (64.U | Log2(bVal, XLEN)) - Log2(aVal, XLEN)  // since Log2(bVal, XLEN) < 64.U
71    val canSkipShift = (64.U | Log2(bReg)) - Log2(aValx2Reg)
72    // When divide by 0, the quotient should be all 1's.
73    // Therefore we can not shift in 0s here.
74    // We do not skip any shift to avoid this.
75    cnt.value := Mux(divBy0Reg, 0.U, Mux(canSkipShift >= (len-1).U, (len-1).U, canSkipShift))
76    state := s_shift
77  } .elsewhen (state === s_shift) {
78    shiftReg := aValx2Reg << cnt.value
79    state := s_compute
80  } .elsewhen (state === s_compute) {
81    val enough = hi.asUInt >= bReg.asUInt
82    shiftReg := Cat(Mux(enough, hi - bReg, hi)(len - 1, 0), lo, enough)
83    cnt.inc()
84    when (cnt.value === (len-1).U) { state := s_finish }
85  } .elsewhen (state === s_finish) {
86    when(io.out.ready){
87      state := s_idle
88    }
89  }
90
91  val kill = state=/=s_idle && uopReg.roqIdx.needFlush(io.redirectIn, io.flushIn)
92  when(kill){
93    state := s_idle
94  }
95
96  val r = hi(len, 1)
97  val resQ = Mux(qSignReg, -lo, lo)
98  val resR = Mux(aSignReg, -r, r)
99
100  val xlen = io.out.bits.data.getWidth
101  val res = Mux(ctrlReg.isHi, resR, resQ)
102  io.out.bits.data := Mux(ctrlReg.isW, SignExt(res(31,0),xlen), res)
103  io.out.bits.uop := uopReg
104
105  io.out.valid := state === s_finish
106  io.in.ready := state === s_idle
107}
108