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