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