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