xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision c6d439803a044ea209139672b25e35fe8d7f4aa0)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*
4* XiangShan is licensed under Mulan PSL v2.
5* You can use this software according to the terms and conditions of the Mulan PSL v2.
6* You may obtain a copy of Mulan PSL v2 at:
7*          http://license.coscl.org.cn/MulanPSL2
8*
9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12*
13* See the Mulan PSL v2 for more details.
14***************************************************************************************/
15
16package xiangshan.backend.fu
17
18import chipsalliance.rocketchip.config.Parameters
19import chisel3._
20import chisel3.util._
21import utils.{LookupTree, ParallelMux, SignExt, ZeroExt}
22import xiangshan._
23
24class AddModule(implicit p: Parameters) extends XSModule {
25  val io = IO(new Bundle() {
26    val src = Vec(2, Input(UInt(XLEN.W)))
27    val out = Output(UInt((XLEN+1).W))
28  })
29  io.out := io.src(0) +& io.src(1)
30}
31
32class SubModule(implicit p: Parameters) extends XSModule {
33  val io = IO(new Bundle() {
34    val src = Vec(2, Input(UInt(XLEN.W)))
35    val out = Output(UInt((XLEN+1).W))
36  })
37  io.out := (io.src(0) +& (~io.src(1)).asUInt()) + 1.U
38}
39
40class LeftShiftModule(implicit p: Parameters) extends XSModule {
41  val io = IO(new Bundle() {
42    val shamt = Input(UInt(6.W))
43    val sllSrc = Input(UInt(XLEN.W))
44    val sll = Output(UInt(XLEN.W))
45  })
46  io.sll := (io.sllSrc << io.shamt)(XLEN - 1, 0)
47}
48
49class RightShiftModule(implicit p: Parameters) extends XSModule {
50  val io = IO(new Bundle() {
51    val shamt = Input(UInt(6.W))
52    val srlSrc, sraSrc = Input(UInt(XLEN.W))
53    val srl_l, srl_w, sra_l, sra_w = Output(UInt(XLEN.W))
54  })
55  io.srl_l := io.srlSrc >> io.shamt
56  io.srl_w := io.srlSrc(31, 0) >> io.shamt
57  io.sra_l := (io.sraSrc.asSInt() >> io.shamt).asUInt()
58  io.sra_w := (Cat(Fill(32, io.sraSrc(31)), io.sraSrc(31, 0)).asSInt() >> io.shamt).asUInt()
59}
60
61class MiscResultSelect(implicit p: Parameters) extends XSModule {
62  val io = IO(new Bundle() {
63    val func = Input(UInt())
64    val sll, slt, sltu, xor, srl, or, and, sra = Input(UInt(XLEN.W))
65    val miscRes = Output(UInt(XLEN.W))
66
67  })
68  io.miscRes := ParallelMux(List(
69    ALUOpType.and  -> io.and,
70    ALUOpType.or   -> io.or,
71    ALUOpType.xor  -> io.xor,
72    ALUOpType.slt  -> ZeroExt(io.slt, XLEN),
73    ALUOpType.sltu -> ZeroExt(io.sltu, XLEN),
74    ALUOpType.srl  -> io.srl,
75    ALUOpType.sll  -> io.sll,
76    ALUOpType.sra  -> io.sra
77  ).map(x => (x._1 === io.func(3, 0), x._2)))
78}
79
80class AluResSel(implicit p: Parameters) extends XSModule {
81  val io = IO(new Bundle() {
82    val func = Input(UInt())
83    val isSub = Input(Bool())
84    val addRes, subRes, miscRes = Input(UInt(XLEN.W))
85    val aluRes = Output(UInt(XLEN.W))
86  })
87  val isAddSub = ALUOpType.isAddSub(io.func)
88  val res = Mux(ALUOpType.isAddSub(io.func),
89    Mux(io.isSub, io.subRes, io.addRes),
90    io.miscRes
91  )
92  val h32 = Mux(ALUOpType.isWordOp(io.func), Fill(32, res(31)), res(63, 32))
93  io.aluRes := Cat(h32, res(31, 0))
94}
95
96class AluDataModule(implicit p: Parameters) extends XSModule {
97  val io = IO(new Bundle() {
98    val src = Vec(2, Input(UInt(XLEN.W)))
99    val func = Input(FuOpType())
100    val pred_taken, isBranch = Input(Bool())
101    val result = Output(UInt(XLEN.W))
102    val taken, mispredict = Output(Bool())
103  })
104  val (src1, src2, func) = (io.src(0), io.src(1), io.func)
105
106  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
107  val addModule = Module(new AddModule)
108  addModule.io.src(0) := src1
109  addModule.io.src(1) := src2
110  val subModule = Module(new SubModule)
111  subModule.io.src(0) := src1
112  subModule.io.src(1) := src2
113  val addRes = addModule.io.out
114  val subRes = subModule.io.out
115  val xorRes = src1 ^ src2
116  val sltu = !subRes(XLEN)
117  val slt = xorRes(XLEN-1) ^ sltu
118
119  val isW = ALUOpType.isWordOp(func)
120  val shamt = Cat(!isW && src2(5), src2(4, 0))
121
122  val leftShiftModule = Module(new LeftShiftModule)
123  leftShiftModule.io.sllSrc := src1
124  leftShiftModule.io.shamt := shamt
125
126  val rightShiftModule = Module(new RightShiftModule)
127  rightShiftModule.io.shamt := shamt
128  rightShiftModule.io.srlSrc := src1
129  rightShiftModule.io.sraSrc := src1
130
131  val sll = leftShiftModule.io.sll
132  val srl = Mux(isW, rightShiftModule.io.srl_w, rightShiftModule.io.srl_l)
133  val sra = Mux(isW, rightShiftModule.io.sra_w, rightShiftModule.io.sra_l)
134
135  val miscResSel = Module(new MiscResultSelect)
136  miscResSel.io.func := func(3, 0)
137  miscResSel.io.sll := sll
138  miscResSel.io.slt := ZeroExt(slt, XLEN)
139  miscResSel.io.sltu := ZeroExt(sltu, XLEN)
140  miscResSel.io.xor := xorRes
141  miscResSel.io.srl := srl
142  miscResSel.io.or := (src1 | src2)
143  miscResSel.io.and := (src1 & src2)
144  miscResSel.io.sra := sra
145
146  val miscRes = miscResSel.io.miscRes
147
148  val aluResSel = Module(new AluResSel)
149  aluResSel.io.func := func
150  aluResSel.io.isSub := isAdderSub
151  aluResSel.io.addRes := addRes
152  aluResSel.io.subRes := subRes
153  aluResSel.io.miscRes := miscRes
154  val aluRes = aluResSel.io.aluRes
155
156  val branchOpTable = List(
157    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
158    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
159    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
160  )
161  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
162
163  io.result := aluRes
164  io.taken := taken
165  io.mispredict := (io.pred_taken ^ taken) && io.isBranch
166}
167
168class Alu(implicit p: Parameters) extends FunctionUnit with HasRedirectOut {
169
170  val (src1, src2, func, pc, uop) = (
171    io.in.bits.src(0),
172    io.in.bits.src(1),
173    io.in.bits.uop.ctrl.fuOpType,
174    SignExt(io.in.bits.uop.cf.pc, AddrBits),
175    io.in.bits.uop
176  )
177
178  val valid = io.in.valid
179  val isBranch = ALUOpType.isBranch(func)
180  val dataModule = Module(new AluDataModule)
181
182  dataModule.io.src(0) := src1
183  dataModule.io.src(1) := src2
184  dataModule.io.func := func
185  dataModule.io.pred_taken := uop.cf.pred_taken
186  dataModule.io.isBranch := isBranch
187
188  redirectOutValid := io.out.valid && isBranch
189  redirectOut := DontCare
190  redirectOut.level := RedirectLevel.flushAfter
191  redirectOut.roqIdx := uop.roqIdx
192  redirectOut.ftqIdx := uop.cf.ftqPtr
193  redirectOut.ftqOffset := uop.cf.ftqOffset
194  redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict
195  redirectOut.cfiUpdate.taken := dataModule.io.taken
196  redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken
197
198  io.in.ready := io.out.ready
199  io.out.valid := valid
200  io.out.bits.uop <> io.in.bits.uop
201  io.out.bits.data := dataModule.io.result
202}
203