xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision 2199a01c65d5a7bf503c4b40771336a50a6f1122)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import utils.{LookupTree, LookupTreeDefault, ParallelMux, SignExt, XSDebug, ZeroExt}
6import xiangshan._
7import xiangshan.backend.ALUOpType
8
9class Alu extends FunctionUnit with HasRedirectOut {
10
11  val (src1, src2, func, pc, uop) = (
12    io.in.bits.src(0),
13    io.in.bits.src(1),
14    io.in.bits.uop.ctrl.fuOpType,
15    SignExt(io.in.bits.uop.cf.pc, AddrBits),
16    io.in.bits.uop
17  )
18
19  val offset = src2
20
21  val valid = io.in.valid
22
23  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
24  val addRes = src1 +& src2
25  val subRes = (src1 +& (~src2).asUInt()) + 1.U
26  val xorRes = src1 ^ src2
27  val sltu = !subRes(XLEN)
28  val slt = xorRes(XLEN-1) ^ sltu
29
30  val shsrc1 = LookupTreeDefault(func, src1, List(
31    ALUOpType.srlw -> ZeroExt(src1(31,0), 64),
32    ALUOpType.sraw -> SignExt(src1(31,0), 64)
33  ))
34  val shamt = Mux(ALUOpType.isWordOp(func), src2(4, 0), src2(5, 0))
35
36  val miscRes = ParallelMux(List(
37    ALUOpType.sll  -> (shsrc1 << shamt)(XLEN-1, 0),
38    ALUOpType.slt  -> ZeroExt(slt, XLEN),
39    ALUOpType.sltu -> ZeroExt(sltu, XLEN),
40    ALUOpType.xor  -> xorRes,
41    ALUOpType.srl  -> (shsrc1 >> shamt),
42    ALUOpType.or   -> (src1 | src2),
43    ALUOpType.and  -> (src1 & src2),
44    ALUOpType.sra  -> (shsrc1.asSInt >> shamt).asUInt
45  ).map(x => (x._1 === func(3, 0), x._2)))
46
47  val res = Mux(ALUOpType.isAddSub(func),
48    Mux(isAdderSub, subRes, addRes),
49    miscRes
50  )
51
52  val aluRes = Mux(ALUOpType.isWordOp(func), SignExt(res(31,0), 64), res)
53
54  val branchOpTable = List(
55    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
56    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
57    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
58  )
59
60  val isBranch = ALUOpType.isBranch(func)
61  val isRVC = uop.cf.brUpdate.pd.isRVC
62  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
63  val target = (pc + offset)(VAddrBits-1,0)
64  val snpc = Mux(isRVC, pc + 2.U, pc + 4.U)
65
66  redirectOutValid := io.out.valid && isBranch
67  // Only brTag, level, roqIdx are needed
68  // other infos are stored in brq
69  redirectOut := DontCare
70  redirectOut.brTag := uop.brTag
71  redirectOut.level := RedirectLevel.flushAfter
72  redirectOut.roqIdx := uop.roqIdx
73
74//  redirectOut.pc := DontCare//uop.cf.pc
75//  redirectOut.target := DontCare//Mux(!taken && isBranch, snpc, target)
76//  redirectOut.interrupt := DontCare//DontCare
77
78  // Only taken really needed, do we need brTag ?
79  brUpdate := DontCare
80  brUpdate.taken := isBranch && taken
81  brUpdate.brTag := uop.brTag
82
83//  brUpdate := uop.cf.brUpdate
84//  // override brUpdate
85//  brUpdate.pc := uop.cf.pc
86//  brUpdate.target := Mux(!taken && isBranch, snpc, target)
87//  brUpdate.brTarget := target
88//  brUpdate.taken := isBranch && taken
89//  brUpdate.brTag := uop.brTag
90
91  io.in.ready := io.out.ready
92  io.out.valid := valid
93  io.out.bits.uop <> io.in.bits.uop
94  io.out.bits.data := aluRes
95}
96