xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision f320e0f01bd645f0a3045a8a740e60dd770734a9)
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.{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 MiscResultSelect(implicit p: Parameters) extends XSModule {
63  val io = IO(new Bundle() {
64    val func = Input(UInt())
65    val sll, slt, sltu, xor, srl, or, and, sra = Input(UInt(XLEN.W))
66    val miscRes = Output(UInt(XLEN.W))
67
68  })
69  io.miscRes := ParallelMux(List(
70    ALUOpType.and  -> io.and,
71    ALUOpType.or   -> io.or,
72    ALUOpType.xor  -> io.xor,
73    ALUOpType.slt  -> ZeroExt(io.slt, XLEN),
74    ALUOpType.sltu -> ZeroExt(io.sltu, XLEN),
75    ALUOpType.srl  -> io.srl,
76    ALUOpType.sll  -> io.sll,
77    ALUOpType.sra  -> io.sra
78  ).map(x => (x._1 === io.func(3, 0), x._2)))
79}
80
81class AluResSel(implicit p: Parameters) extends XSModule {
82  val io = IO(new Bundle() {
83    val func = Input(UInt())
84    val isSub = Input(Bool())
85    val addRes, subRes, miscRes = Input(UInt(XLEN.W))
86    val aluRes = Output(UInt(XLEN.W))
87  })
88  val isAddSub = ALUOpType.isAddSub(io.func)
89  val res = Mux(ALUOpType.isAddSub(io.func),
90    Mux(io.isSub, io.subRes, io.addRes),
91    io.miscRes
92  )
93  val h32 = Mux(ALUOpType.isWordOp(io.func), Fill(32, res(31)), res(63, 32))
94  io.aluRes := Cat(h32, res(31, 0))
95}
96
97class AluDataModule(implicit p: Parameters) extends XSModule {
98  val io = IO(new Bundle() {
99    val src = Vec(2, Input(UInt(XLEN.W)))
100    val func = Input(FuOpType())
101    val pred_taken, isBranch = Input(Bool())
102    val result = Output(UInt(XLEN.W))
103    val taken, mispredict = Output(Bool())
104  })
105  val (src1, src2, func) = (io.src(0), io.src(1), io.func)
106
107  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
108  val addModule = Module(new AddModule)
109  addModule.io.src(0) := src1
110  addModule.io.src(1) := src2
111  val subModule = Module(new SubModule)
112  subModule.io.src(0) := src1
113  subModule.io.src(1) := src2
114  val addRes = addModule.io.out
115  val subRes = subModule.io.out
116  val xorRes = src1 ^ src2
117  val sltu = !subRes(XLEN)
118  val slt = xorRes(XLEN-1) ^ sltu
119
120  val isW = ALUOpType.isWordOp(func)
121  val shamt = Cat(!isW && src2(5), src2(4, 0))
122
123  val leftShiftModule = Module(new LeftShiftModule)
124  leftShiftModule.io.sllSrc := src1
125  leftShiftModule.io.shamt := shamt
126
127  val rightShiftModule = Module(new RightShiftModule)
128  rightShiftModule.io.shamt := shamt
129  rightShiftModule.io.srlSrc := src1
130  rightShiftModule.io.sraSrc := src1
131
132  val sll = leftShiftModule.io.sll
133  val srl = Mux(isW, rightShiftModule.io.srl_w, rightShiftModule.io.srl_l)
134  val sra = Mux(isW, rightShiftModule.io.sra_w, rightShiftModule.io.sra_l)
135
136  val miscResSel = Module(new MiscResultSelect)
137  miscResSel.io.func := func(3, 0)
138  miscResSel.io.sll := sll
139  miscResSel.io.slt := ZeroExt(slt, XLEN)
140  miscResSel.io.sltu := ZeroExt(sltu, XLEN)
141  miscResSel.io.xor := xorRes
142  miscResSel.io.srl := srl
143  miscResSel.io.or := (src1 | src2)
144  miscResSel.io.and := (src1 & src2)
145  miscResSel.io.sra := sra
146
147  val miscRes = miscResSel.io.miscRes
148
149  val aluResSel = Module(new AluResSel)
150  aluResSel.io.func := func
151  aluResSel.io.isSub := isAdderSub
152  aluResSel.io.addRes := addRes
153  aluResSel.io.subRes := subRes
154  aluResSel.io.miscRes := miscRes
155  val aluRes = aluResSel.io.aluRes
156
157  val branchOpTable = List(
158    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
159    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
160    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
161  )
162  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
163
164  io.result := aluRes
165  io.taken := taken
166  io.mispredict := (io.pred_taken ^ taken) && io.isBranch
167}
168
169class Alu(implicit p: Parameters) extends FunctionUnit with HasRedirectOut {
170
171  val (src1, src2, func, pc, uop) = (
172    io.in.bits.src(0),
173    io.in.bits.src(1),
174    io.in.bits.uop.ctrl.fuOpType,
175    SignExt(io.in.bits.uop.cf.pc, AddrBits),
176    io.in.bits.uop
177  )
178
179  val valid = io.in.valid
180  val isBranch = ALUOpType.isBranch(func)
181  val dataModule = Module(new AluDataModule)
182
183  dataModule.io.src(0) := src1
184  dataModule.io.src(1) := src2
185  dataModule.io.func := func
186  dataModule.io.pred_taken := uop.cf.pred_taken
187  dataModule.io.isBranch := isBranch
188
189  redirectOutValid := io.out.valid && isBranch
190  redirectOut := DontCare
191  redirectOut.level := RedirectLevel.flushAfter
192  redirectOut.roqIdx := uop.roqIdx
193  redirectOut.ftqIdx := uop.cf.ftqPtr
194  redirectOut.ftqOffset := uop.cf.ftqOffset
195  redirectOut.cfiUpdate.isMisPred := dataModule.io.mispredict
196  redirectOut.cfiUpdate.taken := dataModule.io.taken
197  redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken
198
199  io.in.ready := io.out.ready
200  io.out.valid := valid
201  io.out.bits.uop <> io.in.bits.uop
202  io.out.bits.data := dataModule.io.result
203}
204