xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision d8a66f7ecacc2b3538a1083b0716b7066c77ba3f)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import utils.{LookupTree, ParallelMux, SignExt, ZeroExt}
6import xiangshan._
7import xiangshan.backend.ALUOpType
8
9class AddModule extends XSModule {
10  val io = IO(new Bundle() {
11    val src1, src2 = Input(UInt(XLEN.W))
12    val out = Output(UInt((XLEN+1).W))
13  })
14  io.out := io.src1 +& io.src2
15}
16
17class SubModule extends XSModule {
18  val io = IO(new Bundle() {
19    val src1, src2 = Input(UInt(XLEN.W))
20    val out = Output(UInt((XLEN+1).W))
21  })
22  io.out := (io.src1 +& (~io.src2).asUInt()) + 1.U
23}
24
25class LeftShiftModule extends XSModule {
26  val io = IO(new Bundle() {
27    val shamt = Input(UInt(6.W))
28    val sllSrc = Input(UInt(XLEN.W))
29    val sll = Output(UInt(XLEN.W))
30  })
31  io.sll := (io.sllSrc << io.shamt)(XLEN - 1, 0)
32}
33
34class RightShiftModule extends XSModule {
35  val io = IO(new Bundle() {
36    val shamt = Input(UInt(6.W))
37    val srlSrc, sraSrc = Input(UInt(XLEN.W))
38    val srl, sra = Output(UInt(XLEN.W))
39  })
40  io.srl := io.srlSrc >> io.shamt
41  io.sra := (io.sraSrc.asSInt() >> io.shamt).asUInt()
42}
43
44class ShiftModule extends XSModule {
45  val io = IO(new Bundle() {
46    val shamt = Input(UInt(6.W))
47    val shsrc1 = Input(UInt(XLEN.W))
48    val sll, srl, sra = Output(UInt(XLEN.W))
49  })
50  io.sll := (io.shsrc1 << io.shamt)(XLEN-1, 0)
51  io.srl := io.shsrc1 >> io.shamt
52  io.sra := (io.shsrc1.asSInt >> io.shamt).asUInt
53}
54
55class MiscResultSelect extends XSModule {
56  val io = IO(new Bundle() {
57    val func = Input(UInt())
58    val sll, slt, sltu, xor, srl, or, and, sra = Input(UInt(XLEN.W))
59    val miscRes = Output(UInt(XLEN.W))
60
61  })
62  io.miscRes := ParallelMux(List(
63    ALUOpType.and  -> io.and,
64    ALUOpType.or   -> io.or,
65    ALUOpType.xor  -> io.xor,
66    ALUOpType.slt  -> ZeroExt(io.slt, XLEN),
67    ALUOpType.sltu -> ZeroExt(io.sltu, XLEN),
68    ALUOpType.srl  -> io.srl,
69    ALUOpType.sll  -> io.sll,
70    ALUOpType.sra  -> io.sra
71  ).map(x => (x._1 === io.func(3, 0), x._2)))
72}
73
74class AluResSel extends XSModule {
75  val io = IO(new Bundle() {
76    val func = Input(UInt())
77    val isSub = Input(Bool())
78    val addRes, subRes, miscRes = Input(UInt(XLEN.W))
79    val aluRes = Output(UInt(XLEN.W))
80  })
81  val isAddSub = ALUOpType.isAddSub(io.func)
82  val res = Mux(ALUOpType.isAddSub(io.func),
83    Mux(io.isSub, io.subRes, io.addRes),
84    io.miscRes
85  )
86  val h32 = Mux(ALUOpType.isWordOp(io.func), Fill(32, res(31)), res(63, 32))
87  io.aluRes := Cat(h32, res(31, 0))
88}
89
90class Alu extends FunctionUnit with HasRedirectOut {
91
92  val (src1, src2, func, pc, uop) = (
93    io.in.bits.src(0),
94    io.in.bits.src(1),
95    io.in.bits.uop.ctrl.fuOpType,
96    SignExt(io.in.bits.uop.cf.pc, AddrBits),
97    io.in.bits.uop
98  )
99
100  val valid = io.in.valid
101
102  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
103  val addModule = Module(new AddModule)
104  addModule.io.src1 := src1
105  addModule.io.src2 := src2
106  val subModule = Module(new SubModule)
107  subModule.io.src1 := src1
108  subModule.io.src2 := src2
109  val addRes = addModule.io.out
110  val subRes = subModule.io.out
111  val xorRes = src1 ^ src2
112  val sltu = !subRes(XLEN)
113  val slt = xorRes(XLEN-1) ^ sltu
114
115  val isW = ALUOpType.isWordOp(func)
116  val shamt = Cat(!isW && src2(5), src2(4, 0))
117
118  val leftShiftModule = Module(new LeftShiftModule)
119  leftShiftModule.io.sllSrc := src1
120  leftShiftModule.io.shamt := shamt
121
122  val rightShiftModule = Module(new RightShiftModule)
123  rightShiftModule.io.shamt := shamt
124  rightShiftModule.io.srlSrc := Cat(
125    Mux(isW, 0.U(32.W), src1(63, 32)),
126    src1(31, 0)
127  )
128  rightShiftModule.io.sraSrc := Cat(
129    Mux(isW, Fill(32, src1(31)), src1(63, 32)),
130    src1(31, 0)
131  )
132
133  val sll = leftShiftModule.io.sll
134  val srl = rightShiftModule.io.srl
135  val sra = rightShiftModule.io.sra
136
137  val miscResSel = Module(new MiscResultSelect)
138  miscResSel.io.func := func(3, 0)
139  miscResSel.io.sll := sll
140  miscResSel.io.slt := ZeroExt(slt, XLEN)
141  miscResSel.io.sltu := ZeroExt(sltu, XLEN)
142  miscResSel.io.xor := xorRes
143  miscResSel.io.srl := srl
144  miscResSel.io.or := (src1 | src2)
145  miscResSel.io.and := (src1 & src2)
146  miscResSel.io.sra := sra
147
148  val miscRes = miscResSel.io.miscRes
149
150  val aluResSel = Module(new AluResSel)
151  aluResSel.io.func := func
152  aluResSel.io.isSub := isAdderSub
153  aluResSel.io.addRes := addRes
154  aluResSel.io.subRes := subRes
155  aluResSel.io.miscRes := miscRes
156  val aluRes = aluResSel.io.aluRes
157
158  val branchOpTable = List(
159    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
160    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
161    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
162  )
163
164  val isBranch = ALUOpType.isBranch(func)
165  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
166
167  redirectOutValid := io.out.valid && isBranch
168  redirectOut := DontCare
169  redirectOut.level := RedirectLevel.flushAfter
170  redirectOut.roqIdx := uop.roqIdx
171  redirectOut.ftqIdx := uop.cf.ftqPtr
172  redirectOut.ftqOffset := uop.cf.ftqOffset
173  redirectOut.cfiUpdate.isMisPred := (uop.cf.pred_taken ^ taken) && isBranch
174  redirectOut.cfiUpdate.taken := taken
175  redirectOut.cfiUpdate.predTaken := uop.cf.pred_taken
176
177  io.in.ready := io.out.ready
178  io.out.valid := valid
179  io.out.bits.uop <> io.in.bits.uop
180  io.out.bits.data := aluRes
181}
182