xref: /XiangShan/src/main/scala/xiangshan/backend/fu/SRT4Divider.scala (revision e3da8bad334fc71ba0d72f0607e2e93245ddaece)
1c6d43980SLemover/***************************************************************************************
2*e3da8badSTang Haojin* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
3*e3da8badSTang Haojin* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
4f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory
5c6d43980SLemover*
6c6d43980SLemover* XiangShan is licensed under Mulan PSL v2.
7c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2.
8c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at:
9c6d43980SLemover*          http://license.coscl.org.cn/MulanPSL2
10c6d43980SLemover*
11c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14c6d43980SLemover*
15c6d43980SLemover* See the Mulan PSL v2 for more details.
16c6d43980SLemover***************************************************************************************/
17c6d43980SLemover
18a58e3351SLi Qianruo// The "SRT4DividerDataModule" in this file is a scala rewrite of SRT4 divider by Yifei He, see
19a58e3351SLi Qianruo// https://github.com/OpenXiangShan/XS-Verilog-Library/tree/main/int_div_radix_4_v1
20a58e3351SLi Qianruo// Email of original author: [email protected]
21a58e3351SLi Qianruo
225018a303SLinJiaweipackage xiangshan.backend.fu
235018a303SLinJiawei
248891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
255018a303SLinJiaweiimport chisel3._
265018a303SLinJiaweiimport chisel3.util._
273c02ee8fSwakafaimport utility.SignExt
287f1506e3SLinJiaweiimport xiangshan.backend.fu.util.CSA3_2
295018a303SLinJiawei
305018a303SLinJiawei/** A Radix-4 SRT Integer Divider
315018a303SLinJiawei  *
325018a303SLinJiawei  * 2 ~ (5 + (len+3)/2) cycles are needed for each division.
335018a303SLinJiawei  */
34afefbad5SLinJiaweiclass SRT4DividerDataModule(len: Int) extends Module {
35afefbad5SLinJiawei  val io = IO(new Bundle() {
362bd5334dSYinan Xu    val src = Vec(2, Input(UInt(len.W)))
37afefbad5SLinJiawei    val valid, sign, kill_w, kill_r, isHi, isW = Input(Bool())
38afefbad5SLinJiawei    val in_ready = Output(Bool())
39afefbad5SLinJiawei    val out_valid = Output(Bool())
40afefbad5SLinJiawei    val out_data = Output(UInt(len.W))
41afefbad5SLinJiawei    val out_ready = Input(Bool())
42afefbad5SLinJiawei  })
43afefbad5SLinJiawei
44a58e3351SLi Qianruo  // consts
45a58e3351SLi Qianruo  val lzc_width = log2Up(len)
46a58e3351SLi Qianruo  val itn_len = 1 + len + 2 + 1
47a58e3351SLi Qianruo  require(lzc_width == 6)
48a58e3351SLi Qianruo
49a58e3351SLi Qianruo  val (a, d, sign, valid, kill_w, kill_r, isHi, isW) =
502bd5334dSYinan Xu    (io.src(0), io.src(1), io.sign, io.valid, io.kill_w, io.kill_r, io.isHi, io.isW)
51afefbad5SLinJiawei  val in_fire = valid && io.in_ready
52afefbad5SLinJiawei  val out_fire = io.out_ready && io.out_valid
53afefbad5SLinJiawei  val newReq = in_fire
54a58e3351SLi Qianruo  val startHandShake = io.in_ready && valid
55a58e3351SLi Qianruo  val s_idle :: s_pre_0 :: s_pre_1 :: s_iter :: s_post_0 :: s_post_1 :: s_finish :: Nil = Enum(7)
565018a303SLinJiawei
57a58e3351SLi Qianruo  val state = RegInit(UIntToOH(s_idle, 7))
58afefbad5SLinJiawei
59a58e3351SLi Qianruo  val quot_neg_2 :: quot_neg_1 :: quot_0 :: quot_pos_1 :: quot_pos_2 :: Nil = Enum(5)
605018a303SLinJiawei
61a58e3351SLi Qianruo  val finished = state(s_finish)
62a58e3351SLi Qianruo
63a58e3351SLi Qianruo  // reused wire declarations
64a58e3351SLi Qianruo  val aIsZero = Wire(Bool())
65a58e3351SLi Qianruo  val dIsZero = Wire(Bool())
66a58e3351SLi Qianruo  val aTooSmall = Wire(Bool()) // this is output of reg!
67a58e3351SLi Qianruo  val noIter = Wire(Bool()) // this is output of reg!
68a58e3351SLi Qianruo  val finalIter = Wire(Bool())
69a58e3351SLi Qianruo  val aLZC = Wire(UInt((lzc_width + 1).W))
70a58e3351SLi Qianruo  val dLZC = Wire(UInt((lzc_width + 1).W))
71a58e3351SLi Qianruo  val aNormAbs = Wire(UInt((len + 1).W))
72a58e3351SLi Qianruo  val dNormAbs = Wire(UInt((len + 1).W))
73a58e3351SLi Qianruo  val aInverter = Wire(UInt(len.W)) // results of global inverter
74a58e3351SLi Qianruo  val dInverter = Wire(UInt(len.W))
75a58e3351SLi Qianruo
76a58e3351SLi Qianruo  val rPreShifted = Wire(UInt((len + 1).W))
77a58e3351SLi Qianruo
78a58e3351SLi Qianruo  val quotIter = Wire(UInt(len.W))
79a58e3351SLi Qianruo  val quotM1Iter = Wire(UInt(len.W))
80a58e3351SLi Qianruo  val qIterEnd = Wire(UInt(5.W))
81a58e3351SLi Qianruo
82a58e3351SLi Qianruo  val rNext = Wire(UInt(itn_len.W))
83a58e3351SLi Qianruo  val rNextPd = Wire(UInt(itn_len.W)) // non-redundant remainder plus d, 68, 67
84a58e3351SLi Qianruo  //reused ctrl regs
85a58e3351SLi Qianruo
86a58e3351SLi Qianruo  //reused other regs
87a58e3351SLi Qianruo  val aNormAbsReg = RegEnable(aNormAbs, startHandShake | state(s_pre_0) | state(s_post_0)) // reg for normalized a & d and rem & rem+d
88a58e3351SLi Qianruo  val dNormAbsReg = RegEnable(dNormAbs, startHandShake | state(s_pre_0) | state(s_post_0))
89a58e3351SLi Qianruo  val quotIterReg = RegEnable(quotIter, state(s_pre_1) | state(s_iter) | state(s_post_0))
90a58e3351SLi Qianruo  val quotM1IterReg = RegEnable(quotM1Iter, state(s_pre_1) | state(s_iter) | state(s_post_0))
91a58e3351SLi Qianruo
92afefbad5SLinJiawei  when(kill_r) {
93a58e3351SLi Qianruo    state := UIntToOH(s_idle, 7)
94a58e3351SLi Qianruo  } .elsewhen(state(s_idle) && in_fire && !kill_w) {
95a58e3351SLi Qianruo    state := UIntToOH(s_pre_0, 7)
96a58e3351SLi Qianruo  } .elsewhen(state(s_pre_0)) { // leading zero detection
97a58e3351SLi Qianruo    state := UIntToOH(s_pre_1, 7)
98a58e3351SLi Qianruo  } .elsewhen(state(s_pre_1)) { // shift a/b
99a58e3351SLi Qianruo    state := Mux(dIsZero | aTooSmall | noIter, UIntToOH(s_post_0, 7), UIntToOH(s_iter, 7))
100a58e3351SLi Qianruo  } .elsewhen(state(s_iter)) { // (ws[j+1], wc[j+1]) = 4(ws[j],wc[j]) - q(j+1)*d
101a58e3351SLi Qianruo    state := Mux(finalIter, UIntToOH(s_post_0, 7), UIntToOH(s_iter, 7))
102a58e3351SLi Qianruo  } .elsewhen(state(s_post_0)) { // if rem < 0, rem = rem + d
103a58e3351SLi Qianruo    state := UIntToOH(s_post_1, 7)
104a58e3351SLi Qianruo  } .elsewhen(state(s_post_1)) {
105a58e3351SLi Qianruo    state := UIntToOH(s_finish, 7)
106a58e3351SLi Qianruo  } .elsewhen(state(s_finish) && out_fire) {
107a58e3351SLi Qianruo    state := UIntToOH(s_idle, 7)
108a58e3351SLi Qianruo  } .otherwise {
109a58e3351SLi Qianruo    state := state
1105018a303SLinJiawei  }
1115018a303SLinJiawei
112a58e3351SLi Qianruo  // First cycle:
113a58e3351SLi Qianruo  // State is idle, we gain absolute value of a and b, using global inverter
114afefbad5SLinJiawei
115a58e3351SLi Qianruo  io.in_ready := state(s_idle)
1165018a303SLinJiawei
117a58e3351SLi Qianruo  aInverter := -Mux(state(s_idle), a, quotIterReg) // 64, 0
118a58e3351SLi Qianruo  dInverter := -Mux(state(s_idle), d, quotM1IterReg) // 64, 0
1195018a303SLinJiawei
120a58e3351SLi Qianruo  val aSign = io.sign && a(len - 1) // 1
121a58e3351SLi Qianruo  val dSign = io.sign && d(len - 1)
1225018a303SLinJiawei
123a58e3351SLi Qianruo  val aAbs = Mux(aSign, aInverter, a) // 64, 0
124a58e3351SLi Qianruo  val dAbs = Mux(dSign, dInverter, d)
125a58e3351SLi Qianruo  val aNorm = (aNormAbsReg(len - 1, 0) << aLZC(lzc_width - 1, 0))(len - 1, 0) // 64, 65
126a58e3351SLi Qianruo  val dNorm = (dNormAbsReg(len - 1, 0) << dLZC(lzc_width - 1, 0))(len - 1, 0)
1275018a303SLinJiawei
128a58e3351SLi Qianruo  aNormAbs := Mux1H(Seq(
129a58e3351SLi Qianruo    state(s_idle) -> Cat(0.U(1.W), aAbs), // 65, 0
130a58e3351SLi Qianruo    state(s_pre_0) -> Cat(0.U(1.W), aNorm), // 65, 0
131a58e3351SLi Qianruo    state(s_post_0) -> rNext(len + 3, 3) // remainder 65, 64. highest is sign bit
132a58e3351SLi Qianruo  ))
133a58e3351SLi Qianruo  dNormAbs := Mux1H(Seq(
134a58e3351SLi Qianruo    state(s_idle) -> Cat(0.U(1.W), dAbs),
135a58e3351SLi Qianruo    state(s_pre_0) -> Cat(0.U(1.W), dNorm),
136a58e3351SLi Qianruo    state(s_post_0) -> rNextPd(len + 3, 3)
1375018a303SLinJiawei    ))
1385018a303SLinJiawei
139a58e3351SLi Qianruo  // Second cycle, state is pre_0
140a58e3351SLi Qianruo  // calculate lzc and move div* and lzc diff check if no_iter_needed
1415018a303SLinJiawei
142935edac4STang Haojin  aLZC := PriorityEncoder(aNormAbsReg(len - 1, 0).asBools.reverse)
143935edac4STang Haojin  dLZC := PriorityEncoder(dNormAbsReg(len - 1, 0).asBools.reverse)
144a58e3351SLi Qianruo  val aLZCReg = RegEnable(aLZC, state(s_pre_0)) // 7, 0
145a58e3351SLi Qianruo  val dLZCReg = RegEnable(dLZC, state(s_pre_0))
146a58e3351SLi Qianruo
147a58e3351SLi Qianruo
148a58e3351SLi Qianruo
149a58e3351SLi Qianruo  val lzcWireDiff = Cat(0.U(1.W), dLZC(lzc_width - 1, 0)) - Cat(0.U(1.W), aLZC(lzc_width - 1, 0)) // 7, 0
150a58e3351SLi Qianruo  val lzcRegDiff = Cat(0.U(1.W), dLZCReg(lzc_width - 1, 0)) - Cat(0.U(1.W), aLZCReg(lzc_width - 1, 0))
151a58e3351SLi Qianruo  val lzcDiff = Mux(state(s_pre_0), lzcWireDiff, lzcRegDiff)
152a58e3351SLi Qianruo  aIsZero := aLZC(lzc_width) // this is state pre_0
153a58e3351SLi Qianruo  dIsZero := dLZCReg(lzc_width) // this is pre_1 and all stages after
154935edac4STang Haojin  val dIsOne = dLZC(lzc_width - 1, 0).andR // this is pre_0
155a58e3351SLi Qianruo  val noIterReg = RegEnable(dIsOne & aNormAbsReg(len - 1), state(s_pre_0)) // This means dividend has lzc 0 so iter is 17
156a58e3351SLi Qianruo  noIter := noIterReg
157a58e3351SLi Qianruo  val aTooSmallReg = RegEnable(aIsZero | lzcDiff(lzc_width), state(s_pre_0)) // a is zero or a smaller than d
158a58e3351SLi Qianruo  aTooSmall := aTooSmallReg
159a58e3351SLi Qianruo
160a58e3351SLi Qianruo  val quotSign = Mux(state(s_idle), aSign ^ dSign, true.B) // if not s_idle then must be s_pre_1 & dIsZero, and that we have
161a58e3351SLi Qianruo  val rSign = aSign
162a58e3351SLi Qianruo  val quotSignReg = RegEnable(quotSign, startHandShake | (state(s_pre_1) & dIsZero))
163a58e3351SLi Qianruo  val rSignReg = RegEnable(rSign, startHandShake)
164a58e3351SLi Qianruo
165a58e3351SLi Qianruo  val rShift = lzcDiff(0) // odd lzc diff, for SRT4
166a58e3351SLi Qianruo  val rightShifted = Wire(UInt(len.W))
167a58e3351SLi Qianruo  val rSumInit = Mux(aTooSmallReg | aIsZero, Cat(0.U(1.W), rightShifted, 0.U(3.W)), // right shift the dividend (which is already l-shifted)
168a58e3351SLi Qianruo                    Mux(noIterReg, 0.U(itn_len.W), //
169a58e3351SLi Qianruo                      Cat(0.U(3.W),
170a58e3351SLi Qianruo                          Mux(rShift, Cat(0.U(1.W), aNormAbsReg(len - 1, 0)), Cat(aNormAbsReg(len - 1, 0), 0.U(1.W)))
171a58e3351SLi Qianruo                        ) // Normal init value. 68, 67; For even lzcDiff, 0.001xxx0; for odd lzcDiff 0.0001xxx
1725018a303SLinJiawei                      )
173a58e3351SLi Qianruo                    ) // state is s_pre_1
174a58e3351SLi Qianruo  val rCarryInit = 0.U(itn_len.W)
1755018a303SLinJiawei
176a58e3351SLi Qianruo  val rightShifter = Module(new RightShifter(len, lzc_width))
177a58e3351SLi Qianruo  rightShifter.io.in := Mux(state(s_pre_1), aNormAbsReg(len - 1, 0), rPreShifted(len - 1, 0))
178a58e3351SLi Qianruo  rightShifter.io.shiftNum := Mux(state(s_pre_1), aLZCReg,
179a58e3351SLi Qianruo                                  Mux(aTooSmallReg | dIsZero, 0.U(lzc_width.W), dLZCReg))
180a58e3351SLi Qianruo  rightShifter.io.msb := state(s_post_1) & rSignReg & rPreShifted(len)
181a58e3351SLi Qianruo  rightShifted := rightShifter.io.out
182a58e3351SLi Qianruo
183a58e3351SLi Qianruo  // obtaining 1st quotient
184a58e3351SLi Qianruo  val rSumInitTrunc = Cat(0.U(1.W), rSumInit(itn_len - 4, itn_len - 4 - 4 + 1)) // 0.00___
18545f43e6eSTang Haojin  val mInitPos1 = MuxLookup(dNormAbsReg(len - 2, len - 2 - 3 + 1), "b00100".U(5.W))(
186*e3da8badSTang Haojin    Seq(
187a58e3351SLi Qianruo      0.U -> "b00100".U(5.W),
188a58e3351SLi Qianruo      1.U -> "b00100".U(5.W),
189a58e3351SLi Qianruo      2.U -> "b00100".U(5.W),
190a58e3351SLi Qianruo      3.U -> "b00110".U(5.W),
191a58e3351SLi Qianruo      4.U -> "b00110".U(5.W),
192a58e3351SLi Qianruo      5.U -> "b00110".U(5.W),
193a58e3351SLi Qianruo      6.U -> "b00110".U(5.W),
194a58e3351SLi Qianruo      7.U -> "b01000".U(5.W),
1950fb3674eSJiawei Lin    )
1965018a303SLinJiawei  )
19745f43e6eSTang Haojin  val mInitPos2 = MuxLookup(dNormAbsReg(len - 2, len - 2 - 3 + 1), "b01100".U(5.W))(
198*e3da8badSTang Haojin    Seq(
199a58e3351SLi Qianruo      0.U -> "b01100".U(5.W),
200a58e3351SLi Qianruo      1.U -> "b01110".U(5.W),
201a58e3351SLi Qianruo      2.U -> "b01111".U(5.W),
202a58e3351SLi Qianruo      3.U -> "b10000".U(5.W),
203a58e3351SLi Qianruo      4.U -> "b10010".U(5.W),
204a58e3351SLi Qianruo      5.U -> "b10100".U(5.W),
205a58e3351SLi Qianruo      6.U -> "b10110".U(5.W),
206a58e3351SLi Qianruo      7.U -> "b10110".U(5.W),
207a58e3351SLi Qianruo    )
208a58e3351SLi Qianruo  )
209a58e3351SLi Qianruo  val initCmpPos1 = rSumInitTrunc >= mInitPos1
210a58e3351SLi Qianruo  val initCmpPos2 = rSumInitTrunc >= mInitPos2
211a58e3351SLi Qianruo  val qInit = Mux(initCmpPos2, UIntToOH(quot_pos_2, 5), Mux(initCmpPos1, UIntToOH(quot_pos_1, 5), UIntToOH(quot_0, 5)))
212a58e3351SLi Qianruo  val qPrev = Mux(state(s_pre_1), qInit, qIterEnd)
213a58e3351SLi Qianruo  val qPrevReg = RegEnable(qPrev, state(s_pre_1) | state(s_iter))
214a58e3351SLi Qianruo  val specialDivisorReg = RegEnable(dNormAbsReg(len - 2, len - 2 - 3 + 1) === 0.U, state(s_pre_1)) // d=0.1000xxx
215a58e3351SLi Qianruo  // rCarry and rSum in Iteration
216a58e3351SLi Qianruo  val qXd = Mux1H(Seq(
217a58e3351SLi Qianruo    qPrevReg(quot_neg_2) -> Cat(dNormAbsReg(len - 1, 0), 0.U(4.W)), // 68, 67 1.xxxxx0000
218a58e3351SLi Qianruo    qPrevReg(quot_neg_1) -> Cat(0.U(1.W), dNormAbsReg(len - 1, 0), 0.U(3.W)), // 0.1xxxxx000
219a58e3351SLi Qianruo    qPrevReg(quot_0)     -> 0.U(itn_len.W),
220a58e3351SLi Qianruo    qPrevReg(quot_pos_1) -> ~Cat(0.U(1.W), dNormAbsReg(len - 1, 0), 0.U(3.W)), // don't forget to plus 1 later
221a58e3351SLi Qianruo    qPrevReg(quot_pos_2) -> ~Cat(dNormAbsReg(len - 1, 0), 0.U(4.W))  // don't forget to plus 1 later
2225018a303SLinJiawei  ))
223a58e3351SLi Qianruo  val csa = Module(new CSA3_2(itn_len))
2245018a303SLinJiawei
225a58e3351SLi Qianruo  val rSumIter = csa.io.out(0)
226a58e3351SLi Qianruo  val rCarryIter = Cat(csa.io.out(1)(itn_len - 2, 0), qPrevReg(quot_pos_1) | qPrevReg(quot_pos_2))
227a58e3351SLi Qianruo  val rSumReg = RegEnable(Mux(state(s_pre_1), rSumInit, rSumIter), state(s_pre_1) | state(s_iter)) // 68, 67
228a58e3351SLi Qianruo  val rCarryReg = RegEnable(Mux(state(s_pre_1), rCarryInit, rCarryIter), state(s_pre_1) | state(s_iter))
229a58e3351SLi Qianruo  csa.io.in(0) := rSumReg << 2
230a58e3351SLi Qianruo  csa.io.in(1) := rCarryReg << 2
231a58e3351SLi Qianruo  csa.io.in(2) := qXd
232a58e3351SLi Qianruo
233a58e3351SLi Qianruo  val qds = Module(new SRT4QDS(len, itn_len))
234a58e3351SLi Qianruo  qds.io.remSum := rSumReg
235a58e3351SLi Qianruo  qds.io.remCarry := rCarryReg
236a58e3351SLi Qianruo  qds.io.d := dNormAbsReg(len - 1, 0) // Maybe optimize here to lower power consumption?
237a58e3351SLi Qianruo  qds.io.specialDivisor := specialDivisorReg
238a58e3351SLi Qianruo  qds.io.qPrev := qPrevReg
239a58e3351SLi Qianruo  qIterEnd := qds.io.qIterEnd
240a58e3351SLi Qianruo
241a58e3351SLi Qianruo  //on the fly conversion
242a58e3351SLi Qianruo  val quotIterNext = Wire(UInt(len.W))
243a58e3351SLi Qianruo  val quotIterM1Next = Wire(UInt(len.W))
244a58e3351SLi Qianruo  quotIterNext := Mux1H(Seq(
245a58e3351SLi Qianruo    qPrevReg(quot_pos_2) -> (quotIterReg << 2 | "b10".U),
246a58e3351SLi Qianruo    qPrevReg(quot_pos_1) -> (quotIterReg << 2 | "b01".U),
247a58e3351SLi Qianruo    qPrevReg(quot_0)     -> (quotIterReg << 2 | "b00".U),
248a58e3351SLi Qianruo    qPrevReg(quot_neg_1) -> (quotM1IterReg << 2 | "b11".U),
249a58e3351SLi Qianruo    qPrevReg(quot_neg_2) -> (quotM1IterReg << 2 | "b10".U)
250a58e3351SLi Qianruo  ))
251a58e3351SLi Qianruo  quotIterM1Next := Mux1H(Seq(
252a58e3351SLi Qianruo    qPrevReg(quot_pos_2) -> (quotIterReg << 2 | "b01".U),
253a58e3351SLi Qianruo    qPrevReg(quot_pos_1) -> (quotIterReg << 2 | "b00".U),
254a58e3351SLi Qianruo    qPrevReg(quot_0)     -> (quotM1IterReg << 2 | "b11".U),
255a58e3351SLi Qianruo    qPrevReg(quot_neg_1) -> (quotM1IterReg << 2 | "b10".U),
256a58e3351SLi Qianruo    qPrevReg(quot_neg_2) -> (quotM1IterReg << 2 | "b01".U)
257a58e3351SLi Qianruo  ))
258a58e3351SLi Qianruo
259a58e3351SLi Qianruo
260a58e3351SLi Qianruo  quotIter := Mux(state(s_pre_1),
261a58e3351SLi Qianruo                      Mux(dIsZero, VecInit(Seq.fill(len)(true.B)).asUInt,
262a58e3351SLi Qianruo                        Mux(noIterReg, aNormAbsReg(len - 1, 0), 0.U(len.W))),
263a58e3351SLi Qianruo                      Mux(state(s_iter), quotIterNext,
264a58e3351SLi Qianruo                        Mux(quotSignReg, aInverter, quotIterReg)))
265a58e3351SLi Qianruo  quotM1Iter := Mux(state(s_pre_1),
266a58e3351SLi Qianruo                        0.U(len.W), Mux(state(s_iter), quotIterM1Next,
267a58e3351SLi Qianruo                          Mux(quotSignReg, dInverter, quotM1IterReg)))
268a58e3351SLi Qianruo
269a58e3351SLi Qianruo
270a58e3351SLi Qianruo  // iter num
271a58e3351SLi Qianruo  val iterNum = Wire(UInt((lzc_width - 1).W))
272a58e3351SLi Qianruo  val iterNumReg = RegEnable(iterNum, state(s_pre_1) | state(s_iter))
273a58e3351SLi Qianruo
274a58e3351SLi Qianruo  iterNum := Mux(state(s_pre_1), lzcDiff(lzc_width - 1, 1) +% lzcDiff(0), iterNumReg -% 1.U)
275a58e3351SLi Qianruo  finalIter := iterNumReg === 0.U
276a58e3351SLi Qianruo
277a58e3351SLi Qianruo  // Post Process
278a58e3351SLi Qianruo
279a58e3351SLi Qianruo  when(rSignReg) {
280a58e3351SLi Qianruo    rNext := ~rSumReg + ~rCarryReg + 2.U
281a58e3351SLi Qianruo    rNextPd := ~rSumReg + ~rCarryReg + ~Cat(0.U(1.W), dNormAbsReg(len - 1, 0), 0.U(3.W)) + 3.U
282a58e3351SLi Qianruo  } .otherwise {
283a58e3351SLi Qianruo    rNext := rSumReg + rCarryReg
284a58e3351SLi Qianruo    rNextPd := rSumReg + rCarryReg + Cat(0.U(1.W), dNormAbsReg(len - 1, 0), 0.U(3.W))
2855018a303SLinJiawei  }
2865018a303SLinJiawei
287a58e3351SLi Qianruo  val r = aNormAbsReg
288a58e3351SLi Qianruo  val rPd = dNormAbsReg
289935edac4STang Haojin  val rIsZero = ~(r.orR)
290a58e3351SLi Qianruo  val needCorr = (~dIsZero & ~noIterReg) & Mux(rSignReg, ~r(len) & ~rIsZero, r(len)) // when we get pos rem for d<0 or neg rem for d>0
291a58e3351SLi Qianruo  rPreShifted := Mux(needCorr, rPd, r)
292a58e3351SLi Qianruo  val rFinal = RegEnable(rightShifted, state(s_post_1))// right shifted remainder. shift by the number of bits divisor is shifted
293a58e3351SLi Qianruo  val qFinal = Mux(needCorr, quotM1IterReg, quotIterReg)
294a58e3351SLi Qianruo  val res = Mux(isHi, rFinal, qFinal)
295afefbad5SLinJiawei  io.out_data := Mux(isW,
2965018a303SLinJiawei    SignExt(res(31, 0), len),
2975018a303SLinJiawei    res
2985018a303SLinJiawei  )
299a58e3351SLi Qianruo  io.in_ready := state(s_idle)
300a58e3351SLi Qianruo  io.out_valid := state(s_finish) // state === s_finish
301afefbad5SLinJiawei}
3025018a303SLinJiawei
303a58e3351SLi Qianruoclass RightShifter(len: Int, lzc_width: Int) extends Module {
304a58e3351SLi Qianruo  val io = IO(new Bundle() {
305a58e3351SLi Qianruo    val shiftNum = Input(UInt(lzc_width.W))
306a58e3351SLi Qianruo    val in = Input(UInt(len.W))
307a58e3351SLi Qianruo    val msb = Input(Bool())
308a58e3351SLi Qianruo    val out = Output(UInt(len.W))
309a58e3351SLi Qianruo  })
310a58e3351SLi Qianruo  require(len == 64 || len == 32)
311a58e3351SLi Qianruo  val shift = io.shiftNum
312a58e3351SLi Qianruo  val msb = io.msb
313a58e3351SLi Qianruo  val s0 = Mux(shift(0), Cat(VecInit(Seq.fill(1)(msb)).asUInt, io.in(len - 1, 1)), io.in)
314a58e3351SLi Qianruo  val s1 = Mux(shift(1), Cat(VecInit(Seq.fill(2)(msb)).asUInt, s0(len - 1, 2)), s0)
315a58e3351SLi Qianruo  val s2 = Mux(shift(2), Cat(VecInit(Seq.fill(4)(msb)).asUInt, s1(len - 1, 4)), s1)
316a58e3351SLi Qianruo  val s3 = Mux(shift(3), Cat(VecInit(Seq.fill(8)(msb)).asUInt, s2(len - 1, 8)), s2)
317a58e3351SLi Qianruo  val s4 = Mux(shift(4), Cat(VecInit(Seq.fill(16)(msb)).asUInt, s3(len - 1, 16)), s3)
318a58e3351SLi Qianruo  val s5 = Wire(UInt(len.W))
319a58e3351SLi Qianruo  if (len == 64) {
320a58e3351SLi Qianruo    s5 := Mux(shift(5), Cat(VecInit(Seq.fill(32)(msb)).asUInt, s4(len - 1, 32)), s4)
321a58e3351SLi Qianruo  } else if (len == 32) {
322a58e3351SLi Qianruo    s5 := s4
323a58e3351SLi Qianruo  }
324a58e3351SLi Qianruo  io.out := s5
325a58e3351SLi Qianruo}
326a58e3351SLi Qianruo
327a58e3351SLi Qianruoobject mLookUpTable {
328a58e3351SLi Qianruo  // Usage :
329a58e3351SLi Qianruo  // result := decoder(QMCMinimizer, index, mLookupTable.xxx)
330a58e3351SLi Qianruo  val minus_m = Seq(
331*e3da8badSTang Haojin    Seq( // -m[-1]
332a58e3351SLi Qianruo      0.U -> "b00_11010".U,
333a58e3351SLi Qianruo      1.U -> "b00_11110".U,
334a58e3351SLi Qianruo      2.U -> "b01_00000".U,
335a58e3351SLi Qianruo      3.U -> "b01_00100".U,
336a58e3351SLi Qianruo      4.U -> "b01_00110".U,
337a58e3351SLi Qianruo      5.U -> "b01_01010".U,
338a58e3351SLi Qianruo      6.U -> "b01_01100".U,
339a58e3351SLi Qianruo      7.U -> "b01_10000".U
340a58e3351SLi Qianruo    ),
341*e3da8badSTang Haojin    Seq( // -m[0]
342a58e3351SLi Qianruo      0.U -> "b000_0101".U,
343a58e3351SLi Qianruo      1.U -> "b000_0110".U,
344a58e3351SLi Qianruo      2.U -> "b000_0110".U,
345a58e3351SLi Qianruo      3.U -> "b000_0110".U,
346a58e3351SLi Qianruo      4.U -> "b000_1001".U,
347a58e3351SLi Qianruo      5.U -> "b000_1000".U,
348a58e3351SLi Qianruo      6.U -> "b000_1000".U,
349a58e3351SLi Qianruo      7.U -> "b000_1000".U
350a58e3351SLi Qianruo    ),
351*e3da8badSTang Haojin    Seq( //-m[1]
352a58e3351SLi Qianruo      0.U -> "b111_1101".U,
353a58e3351SLi Qianruo      1.U -> "b111_1100".U,
354a58e3351SLi Qianruo      2.U -> "b111_1100".U,
355a58e3351SLi Qianruo      3.U -> "b111_1100".U,
356a58e3351SLi Qianruo      4.U -> "b111_1011".U,
357a58e3351SLi Qianruo      5.U -> "b111_1010".U,
358a58e3351SLi Qianruo      6.U -> "b111_1010".U,
359a58e3351SLi Qianruo      7.U -> "b111_1010".U
360a58e3351SLi Qianruo    ),
361*e3da8badSTang Haojin    Seq( //-m[2]
362a58e3351SLi Qianruo      0.U -> "b11_01000".U,
363a58e3351SLi Qianruo      1.U -> "b11_00100".U,
364a58e3351SLi Qianruo      2.U -> "b11_00010".U,
365a58e3351SLi Qianruo      3.U -> "b10_11110".U,
366a58e3351SLi Qianruo      4.U -> "b10_11100".U,
367a58e3351SLi Qianruo      5.U -> "b10_11000".U,
368a58e3351SLi Qianruo      6.U -> "b10_10110".U,
369a58e3351SLi Qianruo      7.U -> "b10_10010".U
370a58e3351SLi Qianruo    ))
371a58e3351SLi Qianruo}
372a58e3351SLi Qianruo
373a58e3351SLi Qianruoclass SRT4QDS(len: Int, itn_len: Int) extends Module {
374a58e3351SLi Qianruo  // srt4 quotientr digit selection
375a58e3351SLi Qianruo  val io = IO(new Bundle() {
376a58e3351SLi Qianruo    val remSum = Input(UInt(itn_len.W)) // 68, 67
377a58e3351SLi Qianruo    val remCarry = Input(UInt(itn_len.W))
378a58e3351SLi Qianruo    val d = Input(UInt(len.W)) // 64, 64
379a58e3351SLi Qianruo    val specialDivisor = Input(Bool())
380a58e3351SLi Qianruo    val qPrev = Input(UInt(5.W))
381a58e3351SLi Qianruo    val qIterEnd = Output(UInt(5.W))
382a58e3351SLi Qianruo  })
383a58e3351SLi Qianruo  val remSumX16 = io.remSum << 4 // 72, 67 Top 2 bits unused
384a58e3351SLi Qianruo  val remCarryX16 = io.remCarry << 4
385a58e3351SLi Qianruo  def trunc25(rem: UInt): UInt = {rem(itn_len, itn_len - 7 + 1)}
386a58e3351SLi Qianruo  def trunc34(rem: UInt): UInt = {rem(itn_len + 1, itn_len + 1 - 7 + 1)}
387a58e3351SLi Qianruo
388a58e3351SLi Qianruo  val quot_neg_2 :: quot_neg_1 :: quot_0 :: quot_pos_1 :: quot_pos_2 :: Nil = Enum(5)
389a58e3351SLi Qianruo
390a58e3351SLi Qianruo  val d = Cat(0.U(1.W), io.d, 0.U(3.W)) // 68, 67
391a58e3351SLi Qianruo  val (dX4, dX8, dXNeg4, dXNeg8) = (d << 2, d(itn_len - 2, 0) << 3, ~(d << 2), ~(d(itn_len - 2, 0) << 3)) // 70, 67
392a58e3351SLi Qianruo  val dForLookup = io.d(len - 2, len - 2 - 3 + 1)
393a58e3351SLi Qianruo
394a58e3351SLi Qianruo  val dXq = Mux1H(Seq(
395a58e3351SLi Qianruo    io.qPrev(quot_neg_2) -> dX8,
396a58e3351SLi Qianruo    io.qPrev(quot_neg_1) -> dX4,
397a58e3351SLi Qianruo    io.qPrev(quot_0) -> 0.U((itn_len + 2).W),
398a58e3351SLi Qianruo    io.qPrev(quot_pos_1) -> dXNeg4,
399a58e3351SLi Qianruo    io.qPrev(quot_pos_2) -> dXNeg8
400a58e3351SLi Qianruo  ))
401a58e3351SLi Qianruo  val signs = VecInit(Seq.tabulate(4){ // -1 0 1 2
402a58e3351SLi Qianruo    i => {
403a58e3351SLi Qianruo      val csa1 = Module(new CSA3_2(7))
404a58e3351SLi Qianruo      val csa2 = Module(new CSA3_2(7))
405a58e3351SLi Qianruo      if (i == 1 || i == 2) {
406a58e3351SLi Qianruo        csa1.io.in(0) := trunc34(remSumX16)
407a58e3351SLi Qianruo        csa1.io.in(1) := trunc34(remCarryX16)
408a58e3351SLi Qianruo        csa2.io.in(2) := trunc34(dXq)
409a58e3351SLi Qianruo      } else {
410a58e3351SLi Qianruo        csa1.io.in(0) := trunc25(remSumX16)
411a58e3351SLi Qianruo        csa1.io.in(1) := trunc25(remCarryX16)
412a58e3351SLi Qianruo        csa2.io.in(2) := trunc25(dXq)
413a58e3351SLi Qianruo      }
41445f43e6eSTang Haojin      csa1.io.in(2) := MuxLookup(dForLookup, "b0000000".U)(mLookUpTable.minus_m(i))
415a58e3351SLi Qianruo      csa2.io.in(0) := csa1.io.out(0)
416a58e3351SLi Qianruo      csa2.io.in(1) := csa1.io.out(1)(5, 0) << 1
417a58e3351SLi Qianruo      (csa2.io.out(0) + (csa2.io.out(1)(5, 0) << 1))(6)
418a58e3351SLi Qianruo    }
419a58e3351SLi Qianruo  })
420a58e3351SLi Qianruo  val qVec = Wire(Vec(5, Bool()))
421a58e3351SLi Qianruo  qVec(quot_neg_2) := signs(0) && signs(1) && signs(2)
422a58e3351SLi Qianruo  qVec(quot_neg_1) := ~signs(0) && signs(1) && signs(2)
423a58e3351SLi Qianruo  qVec(quot_0) := signs(2) && ~signs(1)
424a58e3351SLi Qianruo  qVec(quot_pos_1) := signs(3) && ~signs(2) && ~signs(1)
425a58e3351SLi Qianruo  qVec(quot_pos_2) := ~signs(3) && ~signs(2) && ~signs(1)
426a58e3351SLi Qianruo  io.qIterEnd := qVec.asUInt
427a58e3351SLi Qianruo  // assert(PopCount(qVec) === 1.U)
428a58e3351SLi Qianruo}
429a58e3351SLi Qianruo
430a58e3351SLi Qianruo
4312225d46eSJiawei Linclass SRT4Divider(len: Int)(implicit p: Parameters) extends AbstractDivider(len) {
432afefbad5SLinJiawei
433935edac4STang Haojin  val newReq = io.in.fire
434afefbad5SLinJiawei
435afefbad5SLinJiawei  val uop = io.in.bits.uop
436afefbad5SLinJiawei  val uopReg = RegEnable(uop, newReq)
437afefbad5SLinJiawei  val ctrlReg = RegEnable(ctrl, newReq)
438afefbad5SLinJiawei
439afefbad5SLinJiawei  val divDataModule = Module(new SRT4DividerDataModule(len))
440afefbad5SLinJiawei
441f4b2089aSYinan Xu  val kill_w = uop.robIdx.needFlush(io.redirectIn)
442f4b2089aSYinan Xu  val kill_r = !divDataModule.io.in_ready && uopReg.robIdx.needFlush(io.redirectIn)
443afefbad5SLinJiawei
4442bd5334dSYinan Xu  divDataModule.io.src(0) := io.in.bits.src(0)
4452bd5334dSYinan Xu  divDataModule.io.src(1) := io.in.bits.src(1)
446afefbad5SLinJiawei  divDataModule.io.valid := io.in.valid
447afefbad5SLinJiawei  divDataModule.io.sign := sign
448afefbad5SLinJiawei  divDataModule.io.kill_w := kill_w
449afefbad5SLinJiawei  divDataModule.io.kill_r := kill_r
450afefbad5SLinJiawei  divDataModule.io.isHi := ctrlReg.isHi
451afefbad5SLinJiawei  divDataModule.io.isW := ctrlReg.isW
452afefbad5SLinJiawei  divDataModule.io.out_ready := io.out.ready
453afefbad5SLinJiawei
454afefbad5SLinJiawei  io.in.ready := divDataModule.io.in_ready
455afefbad5SLinJiawei  io.out.valid := divDataModule.io.out_valid
456afefbad5SLinJiawei  io.out.bits.data := divDataModule.io.out_data
457afefbad5SLinJiawei  io.out.bits.uop := uopReg
4585018a303SLinJiawei}
459