xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision dc597826530cb6803c2396d6ab0e5eb176b732e0)
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 utils.{LookupTreeDefault, LookupTree, ParallelMux, SignExt, 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  io.addw := io.srcw + io.src(1)(31,0)
34}
35
36class SubModule(implicit p: Parameters) extends XSModule {
37  val io = IO(new Bundle() {
38    val src = Vec(2, Input(UInt(XLEN.W)))
39    val sub = Output(UInt((XLEN+1).W))
40  })
41  io.sub := (io.src(0) +& (~io.src(1)).asUInt()) + 1.U
42}
43
44class LeftShiftModule(implicit p: Parameters) extends XSModule {
45  val io = IO(new Bundle() {
46    val shamt = Input(UInt(6.W))
47    val revShamt = Input(UInt(6.W))
48    val sllSrc = Input(UInt(XLEN.W))
49    val sll = Output(UInt(XLEN.W))
50    val revSll = Output(UInt(XLEN.W))
51  })
52  io.sll := io.sllSrc << io.shamt
53  io.revSll := io.sllSrc << io.revShamt
54}
55
56class LeftShiftWordModule(implicit p: Parameters) extends XSModule {
57  val io = IO(new Bundle() {
58    val shamt = Input(UInt(5.W))
59    val revShamt = Input(UInt(5.W))
60    val sllSrc = Input(UInt((XLEN/2).W))
61    val sllw = Output(UInt((XLEN/2).W))
62    val revSllw = Output(UInt((XLEN/2).W))
63  })
64  io.sllw := io.sllSrc << io.shamt
65  io.revSllw := io.sllSrc << io.revShamt
66}
67
68class RightShiftModule(implicit p: Parameters) extends XSModule {
69  val io = IO(new Bundle() {
70    val shamt = Input(UInt(6.W))
71    val revShamt = Input(UInt(6.W))
72    val srlSrc, sraSrc = Input(UInt(XLEN.W))
73    val srl, sra = Output(UInt(XLEN.W))
74    val revSrl = Output(UInt(XLEN.W))
75  })
76  io.srl  := io.srlSrc >> io.shamt
77  io.sra  := (io.sraSrc.asSInt() >> io.shamt).asUInt()
78  io.revSrl  := io.srlSrc >> io.revShamt
79}
80
81class RightShiftWordModule(implicit p: Parameters) extends XSModule {
82  val io = IO(new Bundle() {
83    val shamt = Input(UInt(5.W))
84    val revShamt = Input(UInt(5.W))
85    val srlSrc, sraSrc = Input(UInt((XLEN/2).W))
86    val srlw, sraw = Output(UInt((XLEN/2).W))
87    val revSrlw = Output(UInt((XLEN/2).W))
88  })
89
90  io.srlw := io.srlSrc >> io.shamt
91  io.sraw := (io.sraSrc.asSInt() >> io.shamt).asUInt()
92  io.revSrlw := io.srlSrc >> io.revShamt
93}
94
95
96class MiscResultSelect(implicit p: Parameters) extends XSModule {
97  val io = IO(new Bundle() {
98    val func = Input(UInt())
99    val andn, orn, xnor, and, or, xor, sextb, sexth, zexth, rev8, orcb = Input(UInt(XLEN.W))
100    val miscRes = Output(UInt(XLEN.W))
101  })
102
103  val miscRes = ParallelMux(List(
104    ALUOpType.andn -> io.andn,
105    ALUOpType.and  -> io.and,
106    ALUOpType.orn  -> io.orn,
107    ALUOpType.or   -> io.or,
108    ALUOpType.xnor -> io.xnor,
109    ALUOpType.xor  -> io.xor,
110    ALUOpType.sext_b -> io.sextb,
111    ALUOpType.sext_h -> io.sexth,
112    ALUOpType.zext_h -> io.zexth,
113    ALUOpType.orc_b  -> io.orcb,
114    ALUOpType.rev8   -> io.rev8
115  ).map(x => (x._1(3, 0) === io.func(3, 0), x._2)))
116
117  io.miscRes := miscRes
118}
119
120class ShiftResultSelect(implicit p: Parameters) extends XSModule {
121  val io = IO(new Bundle() {
122    val func = Input(UInt())
123    val sll, srl, sra, rol, ror, bclr, bset, binv, bext = Input(UInt(XLEN.W))
124    val shiftRes = Output(UInt(XLEN.W))
125  })
126
127  val leftBit  = Mux(io.func(1), io.binv, Mux(io.func(0), io.bset, io.bclr))
128  val leftRes  = Mux(io.func(2), leftBit, io.sll)
129  val rightRes = Mux(io.func(2), io.sra, Mux(io.func(1), io.bext, io.srl))
130
131  io.shiftRes := Mux(io.func(4), Mux(io.func(3), io.ror, io.rol), Mux(io.func(3), rightRes, leftRes))
132}
133
134class WordResultSelect(implicit p: Parameters) extends XSModule {
135  val io = IO(new Bundle() {
136    val func = Input(UInt())
137    val sllw, srlw, sraw, rolw, rorw, addw, subw = Input(UInt((XLEN/2).W))
138    val wordRes = Output(UInt(XLEN.W))
139  })
140
141  val addsubRes = Mux(io.func(6), io.subw, io.addw)
142  val shiftRes = Mux(io.func(4),
143                  Mux(io.func(3), io.rorw, io.rolw),
144                  Mux(io.func(3),
145                    Mux(io.func(2), io.sraw, io.srlw),
146                    io.sllw))
147  val wordRes = Mux(io.func(6,5) === 2.U, shiftRes, addsubRes)
148  io.wordRes := SignExt(wordRes, XLEN)
149}
150
151
152class AluResSel(implicit p: Parameters) extends XSModule {
153  val io = IO(new Bundle() {
154    val func = Input(UInt())
155    val addRes, shiftRes, miscRes, compareRes, wordRes = Input(UInt(XLEN.W))
156    val aluRes = Output(UInt(XLEN.W))
157  })
158
159  val res = Mux(io.func(7), io.wordRes, Mux(io.func(6),
160    Mux(io.func(5), io.compareRes, io.shiftRes),
161    Mux(io.func(5), io.addRes, io.miscRes)
162  ))
163  io.aluRes := res
164}
165
166class AluDataModule(implicit p: Parameters) extends XSModule {
167  val io = IO(new Bundle() {
168    val src = Vec(2, Input(UInt(XLEN.W)))
169    val func = Input(FuOpType())
170    val pred_taken, isBranch = Input(Bool())
171    val result = Output(UInt(XLEN.W))
172    val taken, mispredict = Output(Bool())
173  })
174  val (src1, src2, func) = (io.src(0), io.src(1), io.func)
175
176  val isW = ALUOpType.isWordOp(func)
177
178  val addModule = Module(new AddModule)
179  val shaddShamt = func(2,1)
180  val add  = addModule.io.add
181  val addw = addModule.io.addw
182  addModule.io.src(0) := (Cat(Fill(32, func(0)), Fill(32,1.U)) & src1) << shaddShamt
183  addModule.io.src(1) := src2
184  addModule.io.srcw := src1(31,0)
185
186
187
188  val subModule = Module(new SubModule)
189  val sub  = subModule.io.sub
190  val subw = subModule.io.sub
191  subModule.io.src(0) := src1
192  subModule.io.src(1) := src2
193
194  val shamt = src2(5, 0)
195  val revShamt = ~src2(5,0) + 1.U
196
197  val leftShiftModule = Module(new LeftShiftModule)
198  val sll = leftShiftModule.io.sll
199  val revSll = leftShiftModule.io.revSll
200  leftShiftModule.io.sllSrc := Cat(Fill(32, func(0)), Fill(32,1.U)) & src1
201  leftShiftModule.io.shamt := shamt
202  leftShiftModule.io.revShamt := revShamt
203
204  val leftShiftWordModule = Module(new LeftShiftWordModule)
205  val sllw = leftShiftWordModule.io.sllw
206  val revSllw = leftShiftWordModule.io.revSllw
207  leftShiftWordModule.io.sllSrc := src1
208  leftShiftWordModule.io.shamt := shamt
209  leftShiftWordModule.io.revShamt := revShamt
210
211  val rightShiftModule = Module(new RightShiftModule)
212  val srl = rightShiftModule.io.srl
213  val revSrl = rightShiftModule.io.revSrl
214  val sra = rightShiftModule.io.sra
215  rightShiftModule.io.shamt := shamt
216  rightShiftModule.io.revShamt := revShamt
217  rightShiftModule.io.srlSrc := src1
218  rightShiftModule.io.sraSrc := src1
219
220  val rightShiftWordModule = Module(new RightShiftWordModule)
221  val srlw = rightShiftWordModule.io.srlw
222  val revSrlw = rightShiftWordModule.io.revSrlw
223  val sraw = rightShiftWordModule.io.sraw
224  rightShiftWordModule.io.shamt := shamt
225  rightShiftWordModule.io.revShamt := revShamt
226  rightShiftWordModule.io.srlSrc := src1
227  rightShiftWordModule.io.sraSrc := src1
228
229  val rol = revSrl | sll
230  val ror = srl | revSll
231  val rolw = revSrlw | sllw
232  val rorw = srlw | revSllw
233
234  val bitShift = 1.U << src2(5, 0)
235  val bset = src1 | bitShift
236  val bclr = src1 & ~bitShift
237  val binv = src1 ^ bitShift
238  val bext = srl(0)
239
240  val andn    = ~(src1 & src2)
241  val orn     = ~(src1 | src2)
242  val xnor    = ~(src1 ^ src2)
243  val and     = ~andn
244  val or      = ~orn
245  val xor     = ~xnor
246  val sgtu    = sub(XLEN)
247  val sltu    = !sgtu
248  val slt     = xor(XLEN-1) ^ sltu
249  // val maxMin  = Mux(slt ^ func(0), src2, src1)
250  // val maxMinU = Mux(sltu^ func(0), src2, src1)
251  val maxMin  = Mux(slt ^ func(0), src2, src1)
252  val maxMinU = Mux((sgtu && func(0)) || ~(sgtu && func(0)), src2, src1)
253  val sextb   = SignExt(src1(7, 0), XLEN)
254  val sexth   = SignExt(src1(15, 0), XLEN)
255  val zexth   = ZeroExt(src1(15, 0), XLEN)
256  val rev8    = Cat(src1(7,0), src1(15,8), src1(23,16), src1(31,24),
257                    src1(39,32), src1(47,40), src1(55,48), src1(63,56))
258  val orcb    = Cat(Reverse(src1(63,56)), Reverse(src1(55,48)), Reverse(src1(47,40)), Reverse(src1(39,32)),
259                    Reverse(src1(31,24)), Reverse(src1(23,16)), Reverse(src1(15,8)), Reverse(src1(7,0)))
260
261  val branchOpTable = List(
262    ALUOpType.getBranchType(ALUOpType.beq)  -> !xor.orR,
263    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
264    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
265  )
266  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
267
268
269  // Result Select
270
271  val compareRes = Mux(func(2), Mux(func(1), maxMin, maxMinU), Mux(func(1), slt, Mux(func(0), sltu, sub)))
272
273  val shiftResSel = Module(new ShiftResultSelect)
274  shiftResSel.io.func := func(4,0)
275  shiftResSel.io.sll  := sll
276  shiftResSel.io.srl  := srl
277  shiftResSel.io.sra  := sra
278  shiftResSel.io.rol  := rol
279  shiftResSel.io.ror  := ror
280  shiftResSel.io.bclr := bclr
281  shiftResSel.io.binv := binv
282  shiftResSel.io.bset := bset
283  shiftResSel.io.bext := bext
284  val shiftRes = shiftResSel.io.shiftRes
285
286  val miscResSel = Module(new MiscResultSelect)
287  miscResSel.io.func    := func(3, 0)
288  miscResSel.io.andn    := andn
289  miscResSel.io.orn     := orn
290  miscResSel.io.xnor    := xnor
291  miscResSel.io.and     := and
292  miscResSel.io.or      := or
293  miscResSel.io.xor     := xor
294  miscResSel.io.sextb   := sextb
295  miscResSel.io.sexth   := sexth
296  miscResSel.io.zexth   := zexth
297  miscResSel.io.rev8    := rev8
298  miscResSel.io.orcb    := orcb
299  val miscRes = miscResSel.io.miscRes
300
301  val wordResSel = Module(new WordResultSelect)
302  wordResSel.io.func := func
303  wordResSel.io.addw := addw
304  wordResSel.io.subw := subw
305  wordResSel.io.sllw := sllw
306  wordResSel.io.srlw := srlw
307  wordResSel.io.sraw := sraw
308  wordResSel.io.rolw := rolw
309  wordResSel.io.rorw := rorw
310  val wordRes = wordResSel.io.wordRes
311
312  val aluResSel = Module(new AluResSel)
313  aluResSel.io.func := func
314  aluResSel.io.addRes := add
315  aluResSel.io.compareRes := compareRes
316  aluResSel.io.shiftRes := shiftRes
317  aluResSel.io.miscRes := miscRes
318  aluResSel.io.wordRes := wordRes
319  val aluRes = aluResSel.io.aluRes
320
321  io.result := aluRes
322  io.taken := taken
323  io.mispredict := (io.pred_taken ^ taken) && io.isBranch
324}
325
326class Alu(implicit p: Parameters) extends FUWithRedirect {
327
328  val (src1, src2, func, pc, uop) = (
329    io.in.bits.src(0),
330    io.in.bits.src(1),
331    io.in.bits.uop.ctrl.fuOpType,
332    SignExt(io.in.bits.uop.cf.pc, AddrBits),
333    io.in.bits.uop
334  )
335
336  val valid = io.in.valid
337  val isBranch = ALUOpType.isBranch(func)
338  val dataModule = Module(new AluDataModule)
339
340  dataModule.io.src(0) := src1
341  dataModule.io.src(1) := src2
342  dataModule.io.func := func
343  dataModule.io.pred_taken := uop.cf.pred_taken
344  dataModule.io.isBranch := isBranch
345
346  redirectOutValid := io.out.valid && isBranch
347  redirectOut := DontCare
348  redirectOut.level := RedirectLevel.flushAfter
349  redirectOut.roqIdx := uop.roqIdx
350  redirectOut.ftqIdx := uop.cf.ftqPtr
351  redirectOut.ftqOffset := uop.cf.ftqOffset
352  redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict
353  redirectOut.cfiUpdate.taken := dataModule.io.taken
354  redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken
355
356  io.in.ready := io.out.ready
357  io.out.valid := valid
358  io.out.bits.uop <> io.in.bits.uop
359  io.out.bits.data := dataModule.io.result
360}
361