xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision 4daa5bf3c3f27e7fd090866d52405b21e107eb8d)
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 org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import utility.{LookupTree, LookupTreeDefault, ParallelMux, SignExt, ZeroExt}
23import xiangshan._
24import utils._
25
26class AddModule(implicit p: Parameters) extends XSModule {
27  val io = IO(new Bundle() {
28    val src = Vec(2, Input(UInt(XLEN.W)))
29    val srcw = Input(UInt((XLEN/2).W))
30    val add = Output(UInt(XLEN.W))
31    val addw = Output(UInt((XLEN/2).W))
32  })
33  io.add := io.src(0) + io.src(1)
34  // TODO: why this extra adder?
35  io.addw := io.srcw + io.src(1)(31,0)
36}
37
38class SubModule(implicit p: Parameters) extends XSModule {
39  val io = IO(new Bundle() {
40    val src = Vec(2, Input(UInt(XLEN.W)))
41    val sub = Output(UInt((XLEN+1).W))
42  })
43  io.sub := (io.src(0) +& (~io.src(1)).asUInt) + 1.U
44}
45
46class LeftShiftModule(implicit p: Parameters) extends XSModule {
47  val io = IO(new Bundle() {
48    val shamt = Input(UInt(6.W))
49    val revShamt = Input(UInt(6.W))
50    val sllSrc = Input(UInt(XLEN.W))
51    val sll = Output(UInt(XLEN.W))
52    val revSll = Output(UInt(XLEN.W))
53  })
54  io.sll := io.sllSrc << io.shamt
55  io.revSll := io.sllSrc << io.revShamt
56}
57
58class LeftShiftWordModule(implicit p: Parameters) extends XSModule {
59  val io = IO(new Bundle() {
60    val shamt = Input(UInt(5.W))
61    val revShamt = Input(UInt(5.W))
62    val sllSrc = Input(UInt((XLEN/2).W))
63    val sllw = Output(UInt((XLEN/2).W))
64    val revSllw = Output(UInt((XLEN/2).W))
65  })
66  io.sllw := io.sllSrc << io.shamt
67  io.revSllw := io.sllSrc << io.revShamt
68}
69
70class RightShiftModule(implicit p: Parameters) extends XSModule {
71  val io = IO(new Bundle() {
72    val shamt = Input(UInt(6.W))
73    val revShamt = Input(UInt(6.W))
74    val srlSrc, sraSrc = Input(UInt(XLEN.W))
75    val srl, sra = Output(UInt(XLEN.W))
76    val revSrl = Output(UInt(XLEN.W))
77  })
78  io.srl  := io.srlSrc >> io.shamt
79  io.sra  := (io.sraSrc.asSInt >> io.shamt).asUInt
80  io.revSrl  := io.srlSrc >> io.revShamt
81}
82
83class RightShiftWordModule(implicit p: Parameters) extends XSModule {
84  val io = IO(new Bundle() {
85    val shamt = Input(UInt(5.W))
86    val revShamt = Input(UInt(5.W))
87    val srlSrc, sraSrc = Input(UInt((XLEN/2).W))
88    val srlw, sraw = Output(UInt((XLEN/2).W))
89    val revSrlw = Output(UInt((XLEN/2).W))
90  })
91
92  io.srlw := io.srlSrc >> io.shamt
93  io.sraw := (io.sraSrc.asSInt >> io.shamt).asUInt
94  io.revSrlw := io.srlSrc >> io.revShamt
95}
96
97
98class MiscResultSelect(implicit p: Parameters) extends XSModule {
99  val io = IO(new Bundle() {
100    val func = Input(UInt(6.W))
101    val and, or, xor, orcb, orh48, sextb, packh, sexth, packw, revb, rev8, pack = Input(UInt(XLEN.W))
102    val src = Input(UInt(XLEN.W))
103    val miscRes = Output(UInt(XLEN.W))
104  })
105
106  val logicRes = VecInit(Seq(
107    io.and,
108    io.or,
109    io.xor,
110    io.orcb
111  ))(io.func(2, 1))
112  val miscRes = VecInit(Seq(io.sextb, io.packh, io.sexth, io.packw))(io.func(1, 0))
113  val logicBase = Mux(io.func(3), miscRes, logicRes)
114
115  val revRes = VecInit(Seq(io.revb, io.rev8, io.pack, io.orh48))(io.func(1, 0))
116  val customRes = VecInit(Seq(
117    Cat(0.U(31.W), io.src(31, 0), 0.U(1.W)),
118    Cat(0.U(30.W), io.src(31, 0), 0.U(2.W)),
119    Cat(0.U(29.W), io.src(31, 0), 0.U(3.W)),
120    Cat(0.U(56.W), io.src(15, 8))))(io.func(1, 0))
121  val logicAdv = Mux(io.func(3), customRes, revRes)
122
123  val mask = Cat(Fill(15, io.func(0)), 1.U(1.W))
124  val maskedLogicRes = mask & logicRes
125
126  io.miscRes := Mux(io.func(5), maskedLogicRes, Mux(io.func(4), logicAdv, logicBase))
127}
128
129class ConditionalZeroModule(implicit p: Parameters) extends XSModule {
130  val io = IO(new Bundle() {
131    val condition = Input(UInt(XLEN.W))
132    val value = Input(UInt(XLEN.W))
133    val isNez = Input(Bool())
134    val condRes = Output(UInt(XLEN.W))
135  })
136
137  val condition_zero = io.condition === 0.U
138  val use_zero = !io.isNez &&  condition_zero ||
139                  io.isNez && !condition_zero
140
141  io.condRes := Mux(use_zero, 0.U, io.value)
142}
143
144class ShiftResultSelect(implicit p: Parameters) extends XSModule {
145  val io = IO(new Bundle() {
146    val func = Input(UInt(4.W))
147    val sll, srl, sra, rol, ror, bclr, bset, binv, bext = Input(UInt(XLEN.W))
148    val shiftRes = Output(UInt(XLEN.W))
149  })
150
151  // val leftBit  = Mux(io.func(1), io.binv, Mux(io.func(0), io.bset, io.bclr))
152  // val leftRes  = Mux(io.func(2), leftBit, io.sll)
153  // val rightRes = Mux(io.func(1) && io.func(0), io.sra, Mux(io.func(1), io.bext, io.srl))
154  val resultSource = VecInit(Seq(
155    io.sll,
156    io.sll,
157    io.bclr,
158    io.bset,
159    io.binv,
160    io.srl,
161    io.bext,
162    io.sra
163  ))
164  val simple = resultSource(io.func(2, 0))
165
166  io.shiftRes := Mux(io.func(3), Mux(io.func(1), io.ror, io.rol), simple)
167}
168
169class WordResultSelect(implicit p: Parameters) extends XSModule {
170  val io = IO(new Bundle() {
171    val func = Input(UInt())
172    val sllw, srlw, sraw, rolw, rorw, addw, subw = Input(UInt((XLEN/2).W))
173    val wordRes = Output(UInt(XLEN.W))
174  })
175
176  val addsubRes = Mux(!io.func(2) && io.func(1) && !io.func(0), io.subw, io.addw)
177  val shiftRes = Mux(io.func(2), Mux(io.func(0), io.rorw, io.rolw),
178                  Mux(io.func(1), io.sraw, Mux(io.func(0), io.srlw, io.sllw)))
179  val wordRes = Mux(io.func(3), shiftRes, addsubRes)
180  io.wordRes := SignExt(wordRes, XLEN)
181}
182
183
184class AluResSel(implicit p: Parameters) extends XSModule {
185  val io = IO(new Bundle() {
186    val func = Input(UInt(3.W))
187    val addRes, shiftRes, miscRes, compareRes, wordRes, condRes = Input(UInt(XLEN.W))
188    val aluRes = Output(UInt(XLEN.W))
189  })
190
191  val res = Mux(io.func(2, 1) === 0.U, Mux(io.func(0), io.wordRes, io.shiftRes),
192                                       Mux(!io.func(2), Mux(io.func(0), io.compareRes, io.addRes),
193                                                        Mux(io.func(1, 0) === 3.U, io.condRes, io.miscRes)))
194  io.aluRes := res
195}
196
197class AluDataModule(implicit p: Parameters) extends XSModule {
198  val io = IO(new Bundle() {
199    val src = Vec(2, Input(UInt(XLEN.W)))
200    val func = Input(FuOpType())
201    val result = Output(UInt(XLEN.W))
202  })
203  val (src1, src2, func) = (io.src(0), io.src(1), io.func)
204
205  val shamt = src2(5, 0)
206  val revShamt = ~src2(5,0) + 1.U
207
208  // slliuw, sll
209  val leftShiftModule = Module(new LeftShiftModule)
210  val sll = leftShiftModule.io.sll
211  val revSll = leftShiftModule.io.revSll
212  leftShiftModule.io.sllSrc := Cat(Fill(32, func(0)), Fill(32, 1.U)) & src1
213  leftShiftModule.io.shamt := shamt
214  leftShiftModule.io.revShamt := revShamt
215
216  // bclr, bset, binv
217  val bitShift = 1.U << src2(5, 0)
218  val bclr = src1 & ~bitShift
219  val bset = src1 | bitShift
220  val binv = src1 ^ bitShift
221
222  // srl, sra, bext
223  val rightShiftModule = Module(new RightShiftModule)
224  val srl = rightShiftModule.io.srl
225  val revSrl = rightShiftModule.io.revSrl
226  val sra = rightShiftModule.io.sra
227  rightShiftModule.io.shamt := shamt
228  rightShiftModule.io.revShamt := revShamt
229  rightShiftModule.io.srlSrc := src1
230  rightShiftModule.io.sraSrc := src1
231  val bext = srl(0)
232
233  val rol = revSrl | sll
234  val ror = srl | revSll
235
236  // addw
237  val addModule = Module(new AddModule)
238  addModule.io.srcw := Mux(!func(2) && func(0), Mux(func(1), SignExt(src2(11, 0), XLEN), ZeroExt(src1(0), XLEN)), src1(31, 0))
239  val addwResultAll = VecInit(Seq(
240    ZeroExt(addModule.io.addw(0), XLEN),
241    ZeroExt(addModule.io.addw(7, 0), XLEN),
242    ZeroExt(addModule.io.addw(15, 0), XLEN),
243    SignExt(addModule.io.addw(15, 0), XLEN)
244  ))
245  val addw = Mux(func(2), addwResultAll(func(1, 0)), addModule.io.addw)
246
247  // subw
248  val subModule = Module(new SubModule)
249  val subw = subModule.io.sub
250
251  // sllw
252  val leftShiftWordModule = Module(new LeftShiftWordModule)
253  val sllw = leftShiftWordModule.io.sllw
254  val revSllw = leftShiftWordModule.io.revSllw
255  leftShiftWordModule.io.sllSrc := src1
256  leftShiftWordModule.io.shamt := shamt
257  leftShiftWordModule.io.revShamt := revShamt
258
259  val rightShiftWordModule = Module(new RightShiftWordModule)
260  val srlw = rightShiftWordModule.io.srlw
261  val revSrlw = rightShiftWordModule.io.revSrlw
262  val sraw = rightShiftWordModule.io.sraw
263  rightShiftWordModule.io.shamt := shamt
264  rightShiftWordModule.io.revShamt := revShamt
265  rightShiftWordModule.io.srlSrc := src1
266  rightShiftWordModule.io.sraSrc := src1
267
268  val rolw = revSrlw | sllw
269  val rorw = srlw | revSllw
270
271  // add
272  val wordMaskAddSource = Cat(Fill(32, func(0)), Fill(32, 1.U)) & src1
273  val shaddSource = VecInit(Seq(
274    Cat(wordMaskAddSource(62, 0), 0.U(1.W)),
275    Cat(wordMaskAddSource(61, 0), 0.U(2.W)),
276    Cat(wordMaskAddSource(60, 0), 0.U(3.W)),
277    Cat(wordMaskAddSource(59, 0), 0.U(4.W))
278  ))
279  val sraddSource = VecInit(Seq(
280    ZeroExt(src1(63, 29), XLEN),
281    ZeroExt(src1(63, 30), XLEN),
282    ZeroExt(src1(63, 31), XLEN),
283    ZeroExt(src1(63, 32), XLEN)
284  ))
285  // TODO: use decoder or other libraries to optimize timing
286  // Now we assume shadd has the worst timing.
287  addModule.io.src(0) := Mux(func(3), shaddSource(func(2, 1)),
288    Mux(func(2), sraddSource(func(1, 0)),
289    Mux(func(1), Mux(func(0), SignExt(src2(11, 0), XLEN), ZeroExt(src1(0), XLEN)), wordMaskAddSource))
290  )
291  addModule.io.src(1) := Mux(func(3, 0) === "b0011".U, Cat(src2(63, 12), 0.U(12.W)), src2)
292  val add = addModule.io.add
293
294  // sub
295  val sub  = subModule.io.sub
296  subModule.io.src(0) := src1
297  subModule.io.src(1) := src2
298  val sltu    = !sub(XLEN)
299  val slt     = src1(XLEN - 1) ^ src2(XLEN - 1) ^ sltu
300  val maxMin  = Mux(slt ^ func(0), src2, src1)
301  val maxMinU = Mux(sltu ^ func(0), src2, src1)
302  val compareRes = Mux(func(2), Mux(func(1), maxMin, maxMinU), Mux(func(1), slt, Mux(func(0), sltu, sub)))
303
304  // logic
305  val logicSrc2 = Mux(!func(5) && func(0), ~src2, src2)
306  val and     = src1 & logicSrc2
307  val or      = src1 | logicSrc2
308  val xor     = src1 ^ logicSrc2
309  val orcb    = Cat((0 until 8).map(i => Fill(8, src1(i * 8 + 7, i * 8).orR)).reverse)
310  val orh48   = Cat(src1(63, 8), 0.U(8.W)) | src2
311
312  val sextb = SignExt(src1(7, 0), XLEN)
313  val packh = Cat(src2(7,0), src1(7,0))
314  val sexth = SignExt(src1(15, 0), XLEN)
315  val packw = SignExt(Cat(src2(15, 0), src1(15, 0)), XLEN)
316
317  val revb = Cat((0 until 8).map(i => Reverse(src1(8 * i + 7, 8 * i))).reverse)
318  val pack = Cat(src2(31, 0), src1(31, 0))
319  val rev8 = Cat((0 until 8).map(i => src1(8 * i + 7, 8 * i)))
320
321
322  // Result Select
323  val shiftResSel = Module(new ShiftResultSelect)
324  shiftResSel.io.func := func(3, 0)
325  shiftResSel.io.sll  := sll
326  shiftResSel.io.srl  := srl
327  shiftResSel.io.sra  := sra
328  shiftResSel.io.rol  := rol
329  shiftResSel.io.ror  := ror
330  shiftResSel.io.bclr := bclr
331  shiftResSel.io.binv := binv
332  shiftResSel.io.bset := bset
333  shiftResSel.io.bext := bext
334  val shiftRes = shiftResSel.io.shiftRes
335
336  val miscResSel = Module(new MiscResultSelect)
337  miscResSel.io.func    := func(5, 0)
338  miscResSel.io.and     := and
339  miscResSel.io.or      := or
340  miscResSel.io.xor     := xor
341  miscResSel.io.orcb    := orcb
342  miscResSel.io.orh48   := orh48
343  miscResSel.io.sextb   := sextb
344  miscResSel.io.packh   := packh
345  miscResSel.io.sexth   := sexth
346  miscResSel.io.packw   := packw
347  miscResSel.io.revb    := revb
348  miscResSel.io.rev8    := rev8
349  miscResSel.io.pack    := pack
350  miscResSel.io.src     := src1
351  val miscRes = miscResSel.io.miscRes
352
353  val condModule = Module(new ConditionalZeroModule)
354  condModule.io.value     := src1
355  condModule.io.condition := src2
356  condModule.io.isNez     := func(1)
357  val condRes = condModule.io.condRes
358
359
360  val wordResSel = Module(new WordResultSelect)
361  wordResSel.io.func := func
362  wordResSel.io.addw := addw
363  wordResSel.io.subw := subw
364  wordResSel.io.sllw := sllw
365  wordResSel.io.srlw := srlw
366  wordResSel.io.sraw := sraw
367  wordResSel.io.rolw := rolw
368  wordResSel.io.rorw := rorw
369  val wordRes = wordResSel.io.wordRes
370
371  val aluResSel = Module(new AluResSel)
372  aluResSel.io.func := func(6, 4)
373  aluResSel.io.addRes := add
374  aluResSel.io.compareRes := compareRes
375  aluResSel.io.shiftRes := shiftRes
376  aluResSel.io.miscRes := miscRes
377  aluResSel.io.wordRes := wordRes
378  aluResSel.io.condRes := condRes
379  val aluRes = aluResSel.io.aluRes
380
381  io.result := aluRes
382
383  XSDebug(func === ALUOpType.lui32add, p"[alu] func lui32: src1=${Hexadecimal(src1)} src2=${Hexadecimal(src2)} alures=${Hexadecimal(aluRes)}\n")
384  XSDebug(func === ALUOpType.lui32add, p"[alu] func lui32: add_src1=${Hexadecimal(addModule.io.src(0))} add_src2=${Hexadecimal(addModule.io.src(1))} addres=${Hexadecimal(add)}\n")
385
386  XSDebug(func === ALUOpType.lui32addw, p"[alu] func lui32w: src1=${Hexadecimal(src1)} src2=${Hexadecimal(src2)} alures=${Hexadecimal(aluRes)}\n")
387  XSDebug(func === ALUOpType.lui32addw, p"[alu] func lui32w: add_src1=${Hexadecimal(addModule.io.srcw)} add_src2=${Hexadecimal(addModule.io.src(1)(31,0))} addres=${Hexadecimal(addw)}\n")
388}
389