xref: /XiangShan/src/main/scala/xiangshan/backend/fu/SRT16Divider.scala (revision a58e33519795596dc4f85fe66907cbc7dde2d66a)
1*a58e3351SLi Qianruo/***************************************************************************************
2*a58e3351SLi Qianruo* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*a58e3351SLi Qianruo* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*a58e3351SLi Qianruo*
5*a58e3351SLi Qianruo* XiangShan is licensed under Mulan PSL v2.
6*a58e3351SLi Qianruo* You can use this software according to the terms and conditions of the Mulan PSL v2.
7*a58e3351SLi Qianruo* You may obtain a copy of Mulan PSL v2 at:
8*a58e3351SLi Qianruo*          http://license.coscl.org.cn/MulanPSL2
9*a58e3351SLi Qianruo*
10*a58e3351SLi Qianruo* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*a58e3351SLi Qianruo* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*a58e3351SLi Qianruo* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*a58e3351SLi Qianruo*
14*a58e3351SLi Qianruo* See the Mulan PSL v2 for more details.
15*a58e3351SLi Qianruo***************************************************************************************/
16*a58e3351SLi Qianruo
17*a58e3351SLi Qianruo// This file contains components originally written by Yifei He, see
18*a58e3351SLi Qianruo// https://github.com/OpenXiangShan/XS-Verilog-Library/tree/main/int_div_radix_4_v1
19*a58e3351SLi Qianruo// Email of original author: [email protected]
20*a58e3351SLi Qianruo
21*a58e3351SLi Qianruopackage xiangshan.backend.fu
22*a58e3351SLi Qianruo
23*a58e3351SLi Qianruoimport chipsalliance.rocketchip.config.Parameters
24*a58e3351SLi Qianruoimport chisel3._
25*a58e3351SLi Qianruoimport chisel3.util._
26*a58e3351SLi Qianruoimport utils.SignExt
27*a58e3351SLi Qianruoimport xiangshan.backend.fu.util.CSA3_2
28*a58e3351SLi Qianruo
29*a58e3351SLi Qianruoclass SRT16DividerDataModule(len: Int) extends Module {
30*a58e3351SLi Qianruo  val io = IO(new Bundle() {
31*a58e3351SLi Qianruo    val src = Vec(2, Input(UInt(len.W)))
32*a58e3351SLi Qianruo    val valid, sign, kill_w, kill_r, isHi, isW = Input(Bool())
33*a58e3351SLi Qianruo    val in_ready = Output(Bool())
34*a58e3351SLi Qianruo    val out_valid = Output(Bool())
35*a58e3351SLi Qianruo    val out_data = Output(UInt(len.W))
36*a58e3351SLi Qianruo    val out_ready = Input(Bool())
37*a58e3351SLi Qianruo  })
38*a58e3351SLi Qianruo
39*a58e3351SLi Qianruo  // consts
40*a58e3351SLi Qianruo  val lzc_width = log2Up(len)
41*a58e3351SLi Qianruo  val itn_len = 1 + len + 2 + 1
42*a58e3351SLi Qianruo
43*a58e3351SLi Qianruo  val (a, d, sign, valid, kill_w, kill_r, isHi, isW) =
44*a58e3351SLi Qianruo    (io.src(0), io.src(1), io.sign, io.valid, io.kill_w, io.kill_r, io.isHi, io.isW)
45*a58e3351SLi Qianruo  val in_fire = valid && io.in_ready
46*a58e3351SLi Qianruo  val out_fire = io.out_ready && io.out_valid
47*a58e3351SLi Qianruo  val newReq = in_fire
48*a58e3351SLi Qianruo  val s_idle :: s_pre_0 :: s_pre_1 :: s_iter :: s_post_0 :: s_post_1 :: s_finish :: Nil = Enum(7)
49*a58e3351SLi Qianruo  val quot_neg_2 :: quot_neg_1 :: quot_0 :: quot_pos_1 :: quot_pos_2 :: Nil = Enum(5)
50*a58e3351SLi Qianruo
51*a58e3351SLi Qianruo
52*a58e3351SLi Qianruo  val state = RegInit(UIntToOH(s_idle, 7))
53*a58e3351SLi Qianruo
54*a58e3351SLi Qianruo  // reused wires
55*a58e3351SLi Qianruo//  val aNormAbs = Wire(UInt((len + 1).W)) // Inputs of xNormAbs regs below
56*a58e3351SLi Qianruo//  val dNormAbs = Wire(UInt((len + 1).W))
57*a58e3351SLi Qianruo  val quotIter = Wire(UInt(len.W))
58*a58e3351SLi Qianruo  val quotM1Iter = Wire(UInt(len.W))
59*a58e3351SLi Qianruo  val aLZC = Wire(UInt((lzc_width + 1).W))
60*a58e3351SLi Qianruo  val dLZC = Wire(UInt((lzc_width + 1).W))
61*a58e3351SLi Qianruo
62*a58e3351SLi Qianruo  val rNext = Wire(UInt(itn_len.W))
63*a58e3351SLi Qianruo  val rNextPd = Wire(UInt(itn_len.W))
64*a58e3351SLi Qianruo
65*a58e3351SLi Qianruo  val aInverter = Wire(UInt(len.W)) // results of global inverter
66*a58e3351SLi Qianruo  val dInverter = Wire(UInt(len.W))
67*a58e3351SLi Qianruo
68*a58e3351SLi Qianruo  val finalIter = Wire(Bool())
69*a58e3351SLi Qianruo  val special = Wire(Bool())
70*a58e3351SLi Qianruo
71*a58e3351SLi Qianruo  // reused regs
72*a58e3351SLi Qianruo//  val aNormAbsReg = RegEnable(aNormAbs, newReq | state(s_pre_0) | state(s_post_0)) // reg for normalized a & d and rem & rem+d
73*a58e3351SLi Qianruo//  val dNormAbsReg = RegEnable(dNormAbs, newReq | state(s_pre_0) | state(s_post_0))
74*a58e3351SLi Qianruo  val quotIterReg = RegEnable(quotIter, state(s_pre_1) | state(s_iter) | state(s_post_0))
75*a58e3351SLi Qianruo  val quotM1IterReg = RegEnable(quotM1Iter, state(s_pre_1) | state(s_iter) | state(s_post_0))
76*a58e3351SLi Qianruo  val specialReg = RegEnable(special, state(s_pre_1))
77*a58e3351SLi Qianruo  val aReg = RegEnable(a, in_fire)
78*a58e3351SLi Qianruo
79*a58e3351SLi Qianruo  when(kill_r) {
80*a58e3351SLi Qianruo    state := UIntToOH(s_idle, 7)
81*a58e3351SLi Qianruo  } .elsewhen(state(s_idle) && in_fire && !kill_w) {
82*a58e3351SLi Qianruo    state := UIntToOH(s_pre_0, 7)
83*a58e3351SLi Qianruo  } .elsewhen(state(s_pre_0)) { // leading zero detection
84*a58e3351SLi Qianruo    state := UIntToOH(s_pre_1, 7)
85*a58e3351SLi Qianruo  } .elsewhen(state(s_pre_1)) { // shift a/b
86*a58e3351SLi Qianruo    state := Mux(special, UIntToOH(s_post_1, 7), UIntToOH(s_iter, 7))
87*a58e3351SLi Qianruo  } .elsewhen(state(s_iter)) { // (ws[j+1], wc[j+1]) = 4(ws[j],wc[j]) - q(j+1)*d
88*a58e3351SLi Qianruo    state := Mux(finalIter, UIntToOH(s_post_0, 7), UIntToOH(s_iter, 7))
89*a58e3351SLi Qianruo  } .elsewhen(state(s_post_0)) { // if rem < 0, rem = rem + d
90*a58e3351SLi Qianruo    state := UIntToOH(s_post_1, 7)
91*a58e3351SLi Qianruo  } .elsewhen(state(s_post_1)) {
92*a58e3351SLi Qianruo    state := UIntToOH(s_finish, 7)
93*a58e3351SLi Qianruo  } .elsewhen(state(s_finish) && out_fire) {
94*a58e3351SLi Qianruo    state := UIntToOH(s_idle, 7)
95*a58e3351SLi Qianruo  } .otherwise {
96*a58e3351SLi Qianruo    state := state
97*a58e3351SLi Qianruo  }
98*a58e3351SLi Qianruo
99*a58e3351SLi Qianruo  io.in_ready := state(s_idle)
100*a58e3351SLi Qianruo  aInverter := -Mux(state(s_idle), a, quotIterReg) // 64, 0
101*a58e3351SLi Qianruo  dInverter := -Mux(state(s_idle), d, quotM1IterReg) // 64, 0
102*a58e3351SLi Qianruo
103*a58e3351SLi Qianruo  val aSign = io.sign && a(len - 1) // 1
104*a58e3351SLi Qianruo  val dSign = io.sign && d(len - 1)
105*a58e3351SLi Qianruo
106*a58e3351SLi Qianruo  val aAbs = Mux(aSign, aInverter, a) // 64, 0
107*a58e3351SLi Qianruo  val dAbs = Mux(dSign, dInverter, d)
108*a58e3351SLi Qianruo  val aAbsReg = RegEnable(aAbs, newReq)
109*a58e3351SLi Qianruo  val dAbsReg = RegEnable(dAbs, newReq)
110*a58e3351SLi Qianruo
111*a58e3351SLi Qianruo  val aNorm = (aAbsReg(len - 1, 0) << aLZC(lzc_width - 1, 0))(len - 1, 0) // 64, 65
112*a58e3351SLi Qianruo  val dNorm = (dAbsReg(len - 1, 0) << dLZC(lzc_width - 1, 0))(len - 1, 0)
113*a58e3351SLi Qianruo
114*a58e3351SLi Qianruo  val aNormReg = RegEnable(aNorm, state(s_pre_0))
115*a58e3351SLi Qianruo  val dNormReg = RegEnable(dNorm, state(s_pre_0))
116*a58e3351SLi Qianruo
117*a58e3351SLi Qianruo//  aNormAbs := Mux1H(Seq(
118*a58e3351SLi Qianruo//    state(s_idle) -> Cat(0.U(1.W), aAbs), // 65, 0
119*a58e3351SLi Qianruo//    state(s_pre_0) -> Cat(0.U(1.W), aNorm), // 65, 0
120*a58e3351SLi Qianruo//    state(s_post_0) -> rNext(len + 3, 3) // remainder 65, 64. highest is sign bit
121*a58e3351SLi Qianruo//  ))
122*a58e3351SLi Qianruo//  dNormAbs := Mux1H(Seq(
123*a58e3351SLi Qianruo//    state(s_idle) -> Cat(0.U(1.W), dAbs),
124*a58e3351SLi Qianruo//    state(s_pre_0) -> Cat(0.U(1.W), dNorm),
125*a58e3351SLi Qianruo//    state(s_post_0) -> rNextPd(len + 3, 3)
126*a58e3351SLi Qianruo//    ))
127*a58e3351SLi Qianruo
128*a58e3351SLi Qianruo  // Second cycle, state is pre_0
129*a58e3351SLi Qianruo  // calculate lzc and move div* and lzc diff check if no_iter_needed
130*a58e3351SLi Qianruo
131*a58e3351SLi Qianruo  aLZC := PriorityEncoder(aAbsReg(len - 1, 0).asBools().reverse)
132*a58e3351SLi Qianruo  dLZC := PriorityEncoder(dAbsReg(len - 1, 0).asBools().reverse)
133*a58e3351SLi Qianruo  val aLZCReg = RegEnable(aLZC, state(s_pre_0)) // 7, 0
134*a58e3351SLi Qianruo  val dLZCReg = RegEnable(dLZC, state(s_pre_0))
135*a58e3351SLi Qianruo
136*a58e3351SLi 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
137*a58e3351SLi Qianruo  val lzcRegDiff = Cat(0.U(1.W), dLZCReg(lzc_width - 1, 0)) - Cat(0.U(1.W), aLZCReg(lzc_width - 1, 0))
138*a58e3351SLi Qianruo//  val lzcDiff = Mux(state(s_pre_0), lzcWireDiff, lzcRegDiff)
139*a58e3351SLi Qianruo
140*a58e3351SLi Qianruo  // special case:
141*a58e3351SLi Qianruo  // divisor is 1 or -1; dividend has less bits than divisor; divisor is zero
142*a58e3351SLi Qianruo  // s_pre_0:
143*a58e3351SLi Qianruo  val dIsOne = dLZC(lzc_width - 1, 0).andR()
144*a58e3351SLi Qianruo  val dIsZero = ~dNormReg.orR()
145*a58e3351SLi Qianruo  val aIsZero = RegEnable(aLZC(lzc_width), state(s_pre_0))
146*a58e3351SLi Qianruo  val aTooSmall = RegEnable(aLZC(lzc_width) | lzcWireDiff(lzc_width), state(s_pre_0))
147*a58e3351SLi Qianruo  special := dIsOne | dIsZero | aTooSmall
148*a58e3351SLi Qianruo
149*a58e3351SLi Qianruo  val quotSpecial = Mux(dIsZero, VecInit(Seq.fill(len)(true.B)).asUInt,
150*a58e3351SLi Qianruo                            Mux(aTooSmall, 0.U,
151*a58e3351SLi Qianruo                              Mux(dSign && ~(aReg.andR()), -aReg, aReg) //  signed 2^(len-1)
152*a58e3351SLi Qianruo                            ))
153*a58e3351SLi Qianruo  val remSpecial = Mux(dIsZero, aReg,
154*a58e3351SLi Qianruo                            Mux(aTooSmall, aReg, 0.U))
155*a58e3351SLi Qianruo  val quotSpecialReg = RegEnable(quotSpecial, state(s_pre_1))
156*a58e3351SLi Qianruo  val remSpecialReg = RegEnable(remSpecial, state(s_pre_1))
157*a58e3351SLi Qianruo
158*a58e3351SLi Qianruo  // s_pre_1
159*a58e3351SLi 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
160*a58e3351SLi Qianruo  val rSign = aSign
161*a58e3351SLi Qianruo  val quotSignReg = RegEnable(quotSign, in_fire | (state(s_pre_1) & dIsZero))
162*a58e3351SLi Qianruo  val rSignReg = RegEnable(rSign, in_fire)
163*a58e3351SLi Qianruo
164*a58e3351SLi Qianruo  val rShift = lzcRegDiff(0)
165*a58e3351SLi Qianruo  val oddIter = lzcRegDiff(1) ^ lzcRegDiff(0)
166*a58e3351SLi Qianruo  val iterNum = Wire(UInt((lzc_width - 2).W))
167*a58e3351SLi Qianruo  val iterNumReg = RegEnable(iterNum, state(s_pre_1) | state(s_iter))
168*a58e3351SLi Qianruo  iterNum := Mux(state(s_pre_1), (lzcRegDiff + 1.U) >> 2, iterNumReg -% 1.U)
169*a58e3351SLi Qianruo  finalIter := iterNumReg === 0.U
170*a58e3351SLi Qianruo
171*a58e3351SLi Qianruo  val rSumInit = Cat(0.U(3.W), Mux(rShift, Cat(0.U(1.W), aNormReg), Cat(aNormReg, 0.U(1.W)))) //(1, 67), 0.001xxx
172*a58e3351SLi Qianruo  val rCarryInit = 0.U(itn_len.W)
173*a58e3351SLi Qianruo
174*a58e3351SLi Qianruo  val rSumInitTrunc = Cat(0.U(1.W), rSumInit(itn_len - 4, itn_len - 4 - 4 + 1)) // 0.00___
175*a58e3351SLi Qianruo  val mInitPos1 = MuxLookup(dNormReg(len-2, len-4), "b00100".U(5.W),
176*a58e3351SLi Qianruo    Array(
177*a58e3351SLi Qianruo      0.U -> "b00100".U(5.W),
178*a58e3351SLi Qianruo      1.U -> "b00100".U(5.W),
179*a58e3351SLi Qianruo      2.U -> "b00100".U(5.W),
180*a58e3351SLi Qianruo      3.U -> "b00110".U(5.W),
181*a58e3351SLi Qianruo      4.U -> "b00110".U(5.W),
182*a58e3351SLi Qianruo      5.U -> "b00110".U(5.W),
183*a58e3351SLi Qianruo      6.U -> "b00110".U(5.W),
184*a58e3351SLi Qianruo      7.U -> "b01000".U(5.W),
185*a58e3351SLi Qianruo    )
186*a58e3351SLi Qianruo  )
187*a58e3351SLi Qianruo  val mInitPos2 = MuxLookup(dNormReg(len-2, len-4), "b01100".U(5.W),
188*a58e3351SLi Qianruo    Array(
189*a58e3351SLi Qianruo      0.U -> "b01100".U(5.W),
190*a58e3351SLi Qianruo      1.U -> "b01110".U(5.W),
191*a58e3351SLi Qianruo      2.U -> "b01111".U(5.W),
192*a58e3351SLi Qianruo      3.U -> "b10000".U(5.W),
193*a58e3351SLi Qianruo      4.U -> "b10010".U(5.W),
194*a58e3351SLi Qianruo      5.U -> "b10100".U(5.W),
195*a58e3351SLi Qianruo      6.U -> "b10110".U(5.W),
196*a58e3351SLi Qianruo      7.U -> "b10110".U(5.W),
197*a58e3351SLi Qianruo    )
198*a58e3351SLi Qianruo  )
199*a58e3351SLi Qianruo  val initCmpPos1 = rSumInitTrunc >= mInitPos1
200*a58e3351SLi Qianruo  val initCmpPos2 = rSumInitTrunc >= mInitPos2
201*a58e3351SLi Qianruo  val qInit = Mux(initCmpPos2, UIntToOH(quot_pos_2, 5), Mux(initCmpPos1, UIntToOH(quot_pos_1, 5), UIntToOH(quot_0, 5)))
202*a58e3351SLi Qianruo
203*a58e3351SLi Qianruo  // in pre_1 we also obtain m_i + 16u * d for all u
204*a58e3351SLi Qianruo  // udNeg -> (rud, r2ud) -> (rudPmNeg, r2udPmNeg)
205*a58e3351SLi Qianruo  val dPos = Cat(0.U(1.W), dNormReg)                          // +d, 0.1xxx, (1, 64)
206*a58e3351SLi Qianruo  val dNeg = -Cat(0.U(1.W), dNormReg) // -d, 1.xxxx, (1, 64)
207*a58e3351SLi Qianruo  // val m = Wire(Vec(4, UInt(7.W)))     // we have to sigext them to calculate rqd-m_k
208*a58e3351SLi Qianruo
209*a58e3351SLi Qianruo  // index 0 is for q=-2 and 4 is for q=2!!!
210*a58e3351SLi Qianruo  val mNeg = Wire(Vec(4, UInt(12.W))) // selected m, extended to (6, 6) bits
211*a58e3351SLi Qianruo  val rudNeg = Wire(Vec(5, UInt(10.W))) // (4, 6)
212*a58e3351SLi Qianruo  val r2udNeg = Wire(Vec(5, UInt(12.W))) // (6, 6)
213*a58e3351SLi Qianruo
214*a58e3351SLi Qianruo  // Selection Block with improved timing
215*a58e3351SLi Qianruo  val rudPmNeg = Wire(Vec(5, Vec(4, UInt(10.W)))) // -(r*u*d+m_k), (5, 5) bits
216*a58e3351SLi Qianruo  val r2ws = Wire(UInt(10.W)) // r^2*ws (5, 5) bits
217*a58e3351SLi Qianruo  val r2wc = Wire(UInt(10.W))
218*a58e3351SLi Qianruo  // calculating exact values of w
219*a58e3351SLi Qianruo  val udNeg = Wire(Vec(5, UInt(itn_len.W))) // (3, 65), 1 signExt'ed Bit
220*a58e3351SLi Qianruo  // val r3udNeg = Wire(Vec(5, UInt(13.W)))
221*a58e3351SLi Qianruo
222*a58e3351SLi Qianruo  // Speculative Block
223*a58e3351SLi Qianruo  val r2udPmNeg = Wire(Vec(5, Vec(4, UInt(13.W)))) // -(r^2*d*d+m_k), (7, 6) bits. 1st index for q 2nd for m
224*a58e3351SLi Qianruo  val r3ws = Wire(UInt(13.W)) // r^3*ws, (7, 6) bits
225*a58e3351SLi Qianruo  val r3wc = Wire(UInt(13.W))
226*a58e3351SLi Qianruo  val qSpec = Wire(Vec(5, UInt(5.W))) // 5 speculative results of qNext2
227*a58e3351SLi Qianruo  // output wires
228*a58e3351SLi Qianruo  val qNext = Wire(UInt(5.W))
229*a58e3351SLi Qianruo  val qNext2 = Wire(UInt(5.W))
230*a58e3351SLi Qianruo  val rCarryIter = Wire(UInt(itn_len.W)) // (1, 67)
231*a58e3351SLi Qianruo  val rSumIter = Wire(UInt(itn_len.W))
232*a58e3351SLi Qianruo  // val r3wsIter = Wire(UInt(13.W))
233*a58e3351SLi Qianruo  // val r3wcIter = Wire(UInt(13.W))
234*a58e3351SLi Qianruo  // Input Regs of whole Spec + Sel + sum adder block
235*a58e3351SLi Qianruo  val qPrevReg = RegEnable(Mux(state(s_pre_1), qInit, qNext2), state(s_pre_1) | state(s_iter))
236*a58e3351SLi Qianruo  val rSumReg = RegEnable(Mux(state(s_pre_1), rSumInit, rSumIter), state(s_pre_1) | state(s_iter)) // (1, 67)
237*a58e3351SLi Qianruo  val rCarryReg = RegEnable(Mux(state(s_pre_1), rCarryInit, rCarryIter), state(s_pre_1) | state(s_iter))
238*a58e3351SLi Qianruo
239*a58e3351SLi Qianruo  // Give values to the regs and wires above...
240*a58e3351SLi Qianruo  val dForLookup = dPos(len-2, len-4)
241*a58e3351SLi Qianruo  mNeg := VecInit(Cat(SignExt(MuxLookup(dNormReg(len-2, len-4), "b00000000".U(7.W), mLookUpTable2.minus_m(0)), 11), 0.U(1.W)), // (2, 5) -> (6, 6)
242*a58e3351SLi Qianruo                  Cat(SignExt(MuxLookup(dNormReg(len-2, len-4), "b00000000".U(7.W), mLookUpTable2.minus_m(1)), 10) ,0.U(2.W)), // (3, 4) -> (6, 6)
243*a58e3351SLi Qianruo                  Cat(SignExt(MuxLookup(dNormReg(len-2, len-4), "b00000000".U(7.W), mLookUpTable2.minus_m(2)), 10) ,0.U(2.W)),
244*a58e3351SLi Qianruo                  Cat(SignExt(MuxLookup(dNormReg(len-2, len-4), "b00000000".U(7.W), mLookUpTable2.minus_m(3)), 11) ,0.U(1.W))
245*a58e3351SLi Qianruo  )
246*a58e3351SLi Qianruo  udNeg := VecInit( Cat(SignExt(dPos, 66), 0.U(2.W)),
247*a58e3351SLi Qianruo                    Cat(SignExt(dPos, 67), 0.U(1.W)),
248*a58e3351SLi Qianruo                    0.U,
249*a58e3351SLi Qianruo                    Cat(SignExt(dNeg, 67), 0.U(1.W)),
250*a58e3351SLi Qianruo                    Cat(SignExt(dNeg, 66), 0.U(2.W))
251*a58e3351SLi Qianruo  )
252*a58e3351SLi Qianruo
253*a58e3351SLi Qianruo  rudNeg := VecInit(Seq.tabulate(5){i => udNeg(i)(itn_len-2, itn_len-11)})
254*a58e3351SLi Qianruo  r2udNeg := VecInit(Seq.tabulate(5){i => udNeg(i)(itn_len-2, itn_len-13)})
255*a58e3351SLi Qianruo  // r3udNeg := VecInit(Seq.tabulate(5){i => udNeg(i)(itn_len-2, itn_len-13)})
256*a58e3351SLi Qianruo  rudPmNeg := VecInit(Seq.tabulate(5){i => VecInit(Seq.tabulate(4){ j => SignExt(rudNeg(i)(9, 1), 10) + mNeg(j)(10, 1)})})
257*a58e3351SLi Qianruo  r2udPmNeg := VecInit(Seq.tabulate(5){i => VecInit(Seq.tabulate(4){ j => SignExt(r2udNeg(i), 13) + SignExt(mNeg(j), 13)})})
258*a58e3351SLi Qianruo  r3ws := rSumReg(itn_len-1, itn_len-13)
259*a58e3351SLi Qianruo  r3wc := rCarryReg(itn_len-1, itn_len-13)
260*a58e3351SLi Qianruo
261*a58e3351SLi Qianruo  r2ws := rSumReg(itn_len-1, itn_len-10)
262*a58e3351SLi Qianruo  r2wc := rCarryReg(itn_len-1, itn_len-10)
263*a58e3351SLi Qianruo
264*a58e3351SLi Qianruo  val udNegReg = RegEnable(udNeg, state(s_pre_1))
265*a58e3351SLi Qianruo//  val rudNegReg = RegEnable(rudNeg, state(s_pre_1))
266*a58e3351SLi Qianruo  val rudPmNegReg = RegEnable(rudPmNeg, state(s_pre_1))
267*a58e3351SLi Qianruo  val r2udPmNegReg = RegEnable(r2udPmNeg, state(s_pre_1))
268*a58e3351SLi Qianruo
269*a58e3351SLi Qianruo  def DetectSign(signs: UInt, name: String): UInt = {
270*a58e3351SLi Qianruo    val qVec = Wire(Vec(5, Bool())).suggestName(name)
271*a58e3351SLi Qianruo    qVec(quot_neg_2) := signs(0) && signs(1) && signs(2)
272*a58e3351SLi Qianruo    qVec(quot_neg_1) := ~signs(0) && signs(1) && signs(2)
273*a58e3351SLi Qianruo    qVec(quot_0) := signs(2) && ~signs(1)
274*a58e3351SLi Qianruo    qVec(quot_pos_1) := signs(3) && ~signs(2) && ~signs(1)
275*a58e3351SLi Qianruo    qVec(quot_pos_2) := ~signs(3) && ~signs(2) && ~signs(1)
276*a58e3351SLi Qianruo    qVec.asUInt
277*a58e3351SLi Qianruo  }
278*a58e3351SLi Qianruo  // Selection block
279*a58e3351SLi Qianruo  val signs = VecInit(Seq.tabulate(4){ i => {
280*a58e3351SLi Qianruo    val csa = Module(new CSA3_2(10)).suggestName(s"csa_sel_${i}")
281*a58e3351SLi Qianruo    csa.io.in(0) := r2ws
282*a58e3351SLi Qianruo    csa.io.in(1) := r2wc
283*a58e3351SLi Qianruo    csa.io.in(2) := Mux1H(qPrevReg, rudPmNegReg.toSeq)(i) // rudPmNeg(OHToUInt(qPrevReg))(i)
284*a58e3351SLi Qianruo
285*a58e3351SLi Qianruo      (csa.io.out(0) + (csa.io.out(1)(8, 0) << 1))(9)
286*a58e3351SLi Qianruo    }})
287*a58e3351SLi Qianruo  qNext := DetectSign(signs.asUInt, s"sel_q")
288*a58e3351SLi Qianruo  val csaWide1 = Module(new CSA3_2(itn_len)).suggestName("csa_sel_wide_1")
289*a58e3351SLi Qianruo  val csaWide2 = Module(new CSA3_2(itn_len)).suggestName("csa_sel_wide_2")
290*a58e3351SLi Qianruo  csaWide1.io.in(0) := rSumReg << 2
291*a58e3351SLi Qianruo  csaWide1.io.in(1) := rCarryReg << 2
292*a58e3351SLi Qianruo  csaWide1.io.in(2) := Mux1H(qPrevReg, udNegReg.toSeq) << 2//udNeg(OHToUInt(qPrevReg)) << 2
293*a58e3351SLi Qianruo  csaWide2.io.in(0) := csaWide1.io.out(0) << 2
294*a58e3351SLi Qianruo  csaWide2.io.in(1) := (csaWide1.io.out(1) << 1)(itn_len-1, 0) << 2
295*a58e3351SLi Qianruo  csaWide2.io.in(2) := Mux1H(qNext, udNegReg.toSeq) << 2 // udNeg(OHToUInt(qNext)) << 2
296*a58e3351SLi Qianruo  rSumIter := Mux(~oddIter & finalIter, csaWide1.io.out(0), csaWide2.io.out(0))
297*a58e3351SLi Qianruo  rCarryIter := Mux(~oddIter & finalIter, (csaWide1.io.out(1) << 1)(itn_len-1, 0), (csaWide2.io.out(1) << 1)(itn_len-1, 0))
298*a58e3351SLi Qianruo  // r3wsIter := r3udNeg(OHToUInt(qNext))
299*a58e3351SLi Qianruo  // r3wcIter := (csaWide1.io.out(0)(itn_len-3, itn_len-16) + (csaWide1.io.out(1) << 1)(itn_len-3, itn_len-16))(13,1)
300*a58e3351SLi Qianruo  // Speculative block
301*a58e3351SLi Qianruo  qSpec := VecInit(Seq.tabulate(5){ q_spec => {
302*a58e3351SLi Qianruo      val csa1 = Module(new CSA3_2(13)).suggestName(s"csa_spec_${q_spec}")
303*a58e3351SLi Qianruo      csa1.io.in(0) := r3ws
304*a58e3351SLi Qianruo      csa1.io.in(1) := r3wc
305*a58e3351SLi Qianruo      csa1.io.in(2) := SignExt(udNegReg(q_spec)(itn_len-2, itn_len-11), 13) // (4, 6) -> (7, 6)
306*a58e3351SLi Qianruo      val signs2 = VecInit(Seq.tabulate(4){ i => {
307*a58e3351SLi Qianruo        val csa2 = Module(new CSA3_2(13)).suggestName(s"csa_spec_${q_spec}_${i}")
308*a58e3351SLi Qianruo        csa2.io.in(0) := csa1.io.out(0)
309*a58e3351SLi Qianruo        csa2.io.in(1) := (csa1.io.out(1) << 1)(12, 0)
310*a58e3351SLi Qianruo        csa2.io.in(2) := Mux1H(qPrevReg, r2udPmNegReg.toSeq)(i) // r2udPmNeg(OHToUInt(qPrevReg))(i)
311*a58e3351SLi Qianruo        (csa2.io.out(0) + (csa2.io.out(1)(11, 0) << 1))(12)
312*a58e3351SLi Qianruo      }})
313*a58e3351SLi Qianruo      val qVec2 = DetectSign(signs2.asUInt, s"spec_q_${q_spec}")
314*a58e3351SLi Qianruo      qVec2
315*a58e3351SLi Qianruo  }})
316*a58e3351SLi Qianruo  // qNext2 := qSpec(OHToUInt(qNext)) // TODO: Use Mux1H!!
317*a58e3351SLi Qianruo
318*a58e3351SLi Qianruo  qNext2 := Mux1H(qNext, qSpec.toSeq)
319*a58e3351SLi Qianruo
320*a58e3351SLi Qianruo  // on the fly quotient conversion
321*a58e3351SLi Qianruo  val quotHalfIter = Wire(UInt(64.W))
322*a58e3351SLi Qianruo  val quotM1HalfIter = Wire(UInt(64.W))
323*a58e3351SLi Qianruo  val quotIterNext = Wire(UInt(64.W))
324*a58e3351SLi Qianruo  val quotM1IterNext = Wire(UInt(64.W))
325*a58e3351SLi Qianruo  def OTFC(q: UInt, quot: UInt, quotM1: UInt): (UInt, UInt) = {
326*a58e3351SLi Qianruo    val quotNext = Mux1H(Seq(
327*a58e3351SLi Qianruo    q(quot_pos_2) -> (quot << 2 | "b10".U),
328*a58e3351SLi Qianruo    q(quot_pos_1) -> (quot << 2 | "b01".U),
329*a58e3351SLi Qianruo    q(quot_0)     -> (quot << 2 | "b00".U),
330*a58e3351SLi Qianruo    q(quot_neg_1) -> (quotM1 << 2 | "b11".U),
331*a58e3351SLi Qianruo    q(quot_neg_2) -> (quotM1 << 2 | "b10".U)
332*a58e3351SLi Qianruo    ))
333*a58e3351SLi Qianruo    val quotM1Next = Mux1H(Seq(
334*a58e3351SLi Qianruo    q(quot_pos_2) -> (quot << 2 | "b01".U),
335*a58e3351SLi Qianruo    q(quot_pos_1) -> (quot << 2 | "b00".U),
336*a58e3351SLi Qianruo    q(quot_0)     -> (quotM1 << 2 | "b11".U),
337*a58e3351SLi Qianruo    q(quot_neg_1) -> (quotM1 << 2 | "b10".U),
338*a58e3351SLi Qianruo    q(quot_neg_2) -> (quotM1 << 2 | "b01".U)
339*a58e3351SLi Qianruo    ))
340*a58e3351SLi Qianruo    (quotNext(len-1, 0), quotM1Next(len-1, 0))
341*a58e3351SLi Qianruo  }
342*a58e3351SLi Qianruo  quotHalfIter := OTFC(qPrevReg, quotIterReg, quotM1IterReg)._1
343*a58e3351SLi Qianruo  quotM1HalfIter := OTFC(qPrevReg, quotIterReg, quotM1IterReg)._2
344*a58e3351SLi Qianruo  quotIterNext := Mux(~oddIter && finalIter, quotHalfIter, OTFC(qNext, quotHalfIter, quotM1HalfIter)._1)
345*a58e3351SLi Qianruo  quotM1IterNext := Mux(~oddIter && finalIter, quotM1HalfIter, OTFC(qNext, quotHalfIter, quotM1HalfIter)._2)
346*a58e3351SLi Qianruo  // quotIter := Mux(state(s_pre_1),  0.U(len.W),
347*a58e3351SLi Qianruo  //                     Mux(state(s_iter), quotIterNext,
348*a58e3351SLi Qianruo  //                       Mux(quotSignReg, aInverter, quotIterReg)))
349*a58e3351SLi Qianruo  // quotM1Iter := Mux(state(s_pre_1),
350*a58e3351SLi Qianruo  //                       0.U(len.W), Mux(state(s_iter), quotM1IterNext,
351*a58e3351SLi Qianruo  //                         Mux(quotSignReg, dInverter, quotM1IterReg)))
352*a58e3351SLi Qianruo
353*a58e3351SLi Qianruo  quotIter := Mux(state(s_iter), quotIterNext,
354*a58e3351SLi Qianruo                    Mux(state(s_pre_1), 0.U(len.W),
355*a58e3351SLi Qianruo                      Mux(quotSignReg, aInverter, quotIterReg)))
356*a58e3351SLi Qianruo  quotM1Iter := Mux(state(s_iter), quotM1IterNext,
357*a58e3351SLi Qianruo                      Mux(state(s_pre_1), 0.U(len.W),
358*a58e3351SLi Qianruo                        Mux(quotSignReg, dInverter, quotM1IterReg)))
359*a58e3351SLi Qianruo  // finally, to the recovery stages!
360*a58e3351SLi Qianruo
361*a58e3351SLi Qianruo  when(rSignReg) {
362*a58e3351SLi Qianruo    rNext := ~rSumReg + ~rCarryReg + 2.U
363*a58e3351SLi Qianruo    rNextPd := ~rSumReg + ~rCarryReg + ~Cat(0.U(1.W), dNormReg, 0.U(3.W)) + 3.U
364*a58e3351SLi Qianruo  } .otherwise {
365*a58e3351SLi Qianruo    rNext := rSumReg + rCarryReg
366*a58e3351SLi Qianruo    rNextPd := rSumReg + rCarryReg + Cat(0.U(1.W), dNormReg, 0.U(3.W))
367*a58e3351SLi Qianruo  }
368*a58e3351SLi Qianruo  val rNextReg = RegEnable(rNext(len + 3, 3), state(s_post_0))
369*a58e3351SLi Qianruo  val rNextPdReg = RegEnable(rNextPd(len + 3, 3), state(s_post_0))
370*a58e3351SLi Qianruo  dontTouch(rNextReg)
371*a58e3351SLi Qianruo  // post_1
372*a58e3351SLi Qianruo  val r = rNextReg
373*a58e3351SLi Qianruo  val rPd = rNextPdReg
374*a58e3351SLi Qianruo  val rIsZero = ~(r.orR())
375*a58e3351SLi Qianruo  val needCorr = Mux(rSignReg, ~r(len) & r.orR(), r(len)) // when we get pos rem for a<0 or neg rem for a>0
376*a58e3351SLi Qianruo  val rPreShifted = Mux(needCorr, rPd, r)
377*a58e3351SLi Qianruo  val rightShifter = Module(new RightShifter(len, lzc_width))
378*a58e3351SLi Qianruo  rightShifter.io.in := rPreShifted
379*a58e3351SLi Qianruo  rightShifter.io.shiftNum := dLZCReg
380*a58e3351SLi Qianruo  rightShifter.io.msb := rSignReg
381*a58e3351SLi Qianruo  val rShifted = rightShifter.io.out
382*a58e3351SLi Qianruo  val rFinal = RegEnable(Mux(specialReg, remSpecialReg, rShifted), state(s_post_1))// right shifted remainder. shift by the number of bits divisor is shifted
383*a58e3351SLi Qianruo  val qFinal = RegEnable(Mux(specialReg, quotSpecialReg, Mux(needCorr, quotM1IterReg, quotIterReg)), state(s_post_1))
384*a58e3351SLi Qianruo
385*a58e3351SLi Qianruo  val res = Mux(isHi, rFinal, qFinal)
386*a58e3351SLi Qianruo  io.out_data := Mux(isW,
387*a58e3351SLi Qianruo    SignExt(res(31, 0), len),
388*a58e3351SLi Qianruo    res
389*a58e3351SLi Qianruo  )
390*a58e3351SLi Qianruo  io.in_ready := state(s_idle)
391*a58e3351SLi Qianruo  io.out_valid := state(s_finish)
392*a58e3351SLi Qianruo
393*a58e3351SLi Qianruo}
394*a58e3351SLi Qianruo
395*a58e3351SLi Qianruoobject mLookUpTable2 {
396*a58e3351SLi Qianruo  // Usage :
397*a58e3351SLi Qianruo  // result := decoder(QMCMinimizer, index, mLookupTable.xxx)
398*a58e3351SLi Qianruo  val minus_m = Seq(
399*a58e3351SLi Qianruo    Array( // -m[-1]
400*a58e3351SLi Qianruo      0.U -> "b00_11010".U(7.W),
401*a58e3351SLi Qianruo      1.U -> "b00_11110".U(7.W),
402*a58e3351SLi Qianruo      2.U -> "b01_00000".U(7.W),
403*a58e3351SLi Qianruo      3.U -> "b01_00100".U(7.W),
404*a58e3351SLi Qianruo      4.U -> "b01_00110".U(7.W),
405*a58e3351SLi Qianruo      5.U -> "b01_01010".U(7.W),
406*a58e3351SLi Qianruo      6.U -> "b01_01100".U(7.W),
407*a58e3351SLi Qianruo      7.U -> "b01_10000".U(7.W)
408*a58e3351SLi Qianruo    ),
409*a58e3351SLi Qianruo    Array( // -m[0]
410*a58e3351SLi Qianruo      0.U -> "b000_0100".U(7.W),
411*a58e3351SLi Qianruo      1.U -> "b000_0110".U(7.W),
412*a58e3351SLi Qianruo      2.U -> "b000_0110".U(7.W),
413*a58e3351SLi Qianruo      3.U -> "b000_0110".U(7.W),
414*a58e3351SLi Qianruo      4.U -> "b000_1000".U(7.W),
415*a58e3351SLi Qianruo      5.U -> "b000_1000".U(7.W),
416*a58e3351SLi Qianruo      6.U -> "b000_1000".U(7.W),
417*a58e3351SLi Qianruo      7.U -> "b000_1000".U(7.W)
418*a58e3351SLi Qianruo    ),
419*a58e3351SLi Qianruo    Array( //-m[1]
420*a58e3351SLi Qianruo      0.U -> "b111_1101".U(7.W),
421*a58e3351SLi Qianruo      1.U -> "b111_1100".U(7.W),
422*a58e3351SLi Qianruo      2.U -> "b111_1100".U(7.W),
423*a58e3351SLi Qianruo      3.U -> "b111_1100".U(7.W),
424*a58e3351SLi Qianruo      4.U -> "b111_1011".U(7.W),
425*a58e3351SLi Qianruo      5.U -> "b111_1010".U(7.W),
426*a58e3351SLi Qianruo      6.U -> "b111_1010".U(7.W),
427*a58e3351SLi Qianruo      7.U -> "b111_1010".U(7.W)
428*a58e3351SLi Qianruo    ),
429*a58e3351SLi Qianruo    Array( //-m[2]
430*a58e3351SLi Qianruo      0.U -> "b11_01000".U(7.W),
431*a58e3351SLi Qianruo      1.U -> "b11_00100".U(7.W),
432*a58e3351SLi Qianruo      2.U -> "b11_00010".U(7.W),
433*a58e3351SLi Qianruo      3.U -> "b10_11110".U(7.W),
434*a58e3351SLi Qianruo      4.U -> "b10_11100".U(7.W),
435*a58e3351SLi Qianruo      5.U -> "b10_11000".U(7.W),
436*a58e3351SLi Qianruo      6.U -> "b10_10110".U(7.W),
437*a58e3351SLi Qianruo      7.U -> "b10_10010".U(7.W)
438*a58e3351SLi Qianruo    ))
439*a58e3351SLi Qianruo}
440*a58e3351SLi Qianruo
441*a58e3351SLi Qianruoclass SRT16Divider(len: Int)(implicit p: Parameters) extends AbstractDivider(len) {
442*a58e3351SLi Qianruo
443*a58e3351SLi Qianruo  val newReq = io.in.fire()
444*a58e3351SLi Qianruo
445*a58e3351SLi Qianruo  val uop = io.in.bits.uop
446*a58e3351SLi Qianruo  val uopReg = RegEnable(uop, newReq)
447*a58e3351SLi Qianruo  val ctrlReg = RegEnable(ctrl, newReq)
448*a58e3351SLi Qianruo
449*a58e3351SLi Qianruo  val divDataModule = Module(new SRT16DividerDataModule(len))
450*a58e3351SLi Qianruo
451*a58e3351SLi Qianruo  val kill_w = uop.roqIdx.needFlush(io.redirectIn, io.flushIn)
452*a58e3351SLi Qianruo  val kill_r = !divDataModule.io.in_ready && uopReg.roqIdx.needFlush(io.redirectIn, io.flushIn)
453*a58e3351SLi Qianruo
454*a58e3351SLi Qianruo  divDataModule.io.src(0) := io.in.bits.src(0)
455*a58e3351SLi Qianruo  divDataModule.io.src(1) := io.in.bits.src(1)
456*a58e3351SLi Qianruo  divDataModule.io.valid := io.in.valid
457*a58e3351SLi Qianruo  divDataModule.io.sign := sign
458*a58e3351SLi Qianruo  divDataModule.io.kill_w := kill_w
459*a58e3351SLi Qianruo  divDataModule.io.kill_r := kill_r
460*a58e3351SLi Qianruo  divDataModule.io.isHi := ctrlReg.isHi
461*a58e3351SLi Qianruo  divDataModule.io.isW := ctrlReg.isW
462*a58e3351SLi Qianruo  divDataModule.io.out_ready := io.out.ready
463*a58e3351SLi Qianruo
464*a58e3351SLi Qianruo  io.in.ready := divDataModule.io.in_ready
465*a58e3351SLi Qianruo  io.out.valid := divDataModule.io.out_valid
466*a58e3351SLi Qianruo  io.out.bits.data := divDataModule.io.out_data
467*a58e3351SLi Qianruo  io.out.bits.uop := uopReg
468*a58e3351SLi Qianruo}
469