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