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