xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision 151e3043e07d88e292b08809ece8169d87f54470)
1e18c367fSLinJiaweipackage xiangshan.backend.fu
2e18c367fSLinJiawei
3e18c367fSLinJiaweiimport chisel3._
4e18c367fSLinJiaweiimport chisel3.util._
53ef996e9SLinJiaweiimport utils.{LookupTree, LookupTreeDefault, ParallelMux, SignExt, XSDebug, ZeroExt}
6e18c367fSLinJiaweiimport xiangshan._
7e18c367fSLinJiaweiimport xiangshan.backend.ALUOpType
8e18c367fSLinJiawei
952c3f215SLinJiaweiclass Alu extends FunctionUnit with HasRedirectOut {
10e18c367fSLinJiawei
11b0ae3ac4SLinJiawei  val (src1, src2, func, pc, uop) = (
12e18c367fSLinJiawei    io.in.bits.src(0),
13e18c367fSLinJiawei    io.in.bits.src(1),
14e18c367fSLinJiawei    io.in.bits.uop.ctrl.fuOpType,
15e18c367fSLinJiawei    SignExt(io.in.bits.uop.cf.pc, AddrBits),
16e18c367fSLinJiawei    io.in.bits.uop
17e18c367fSLinJiawei  )
18e18c367fSLinJiawei
19b0ae3ac4SLinJiawei  val offset = src2
20b0ae3ac4SLinJiawei
21dfd9e0a8SLinJiawei  val valid = io.in.valid
22e18c367fSLinJiawei
23e18c367fSLinJiawei  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
243ef996e9SLinJiawei  val addRes = src1 +& src2
253ef996e9SLinJiawei  val subRes = (src1 +& (~src2).asUInt()) + 1.U
26e18c367fSLinJiawei  val xorRes = src1 ^ src2
273ef996e9SLinJiawei  val sltu = !subRes(XLEN)
28e18c367fSLinJiawei  val slt = xorRes(XLEN-1) ^ sltu
29e18c367fSLinJiawei
30e18c367fSLinJiawei  val shsrc1 = LookupTreeDefault(func, src1, List(
31e18c367fSLinJiawei    ALUOpType.srlw -> ZeroExt(src1(31,0), 64),
32e18c367fSLinJiawei    ALUOpType.sraw -> SignExt(src1(31,0), 64)
33e18c367fSLinJiawei  ))
34e18c367fSLinJiawei  val shamt = Mux(ALUOpType.isWordOp(func), src2(4, 0), src2(5, 0))
353ef996e9SLinJiawei
363ef996e9SLinJiawei  val miscRes = ParallelMux(List(
373ef996e9SLinJiawei    ALUOpType.sll  -> (shsrc1 << shamt)(XLEN-1, 0),
38e18c367fSLinJiawei    ALUOpType.slt  -> ZeroExt(slt, XLEN),
39e18c367fSLinJiawei    ALUOpType.sltu -> ZeroExt(sltu, XLEN),
40e18c367fSLinJiawei    ALUOpType.xor  -> xorRes,
41e18c367fSLinJiawei    ALUOpType.srl  -> (shsrc1 >> shamt),
42e18c367fSLinJiawei    ALUOpType.or   -> (src1 | src2),
43e18c367fSLinJiawei    ALUOpType.and  -> (src1 & src2),
443ef996e9SLinJiawei    ALUOpType.sra  -> (shsrc1.asSInt >> shamt).asUInt
453ef996e9SLinJiawei  ).map(x => (x._1 === func(3, 0), x._2)))
463ef996e9SLinJiawei
473ef996e9SLinJiawei  val res = Mux(ALUOpType.isAddSub(func),
483ef996e9SLinJiawei    Mux(isAdderSub, subRes, addRes),
493ef996e9SLinJiawei    miscRes
503ef996e9SLinJiawei  )
513ef996e9SLinJiawei
52e18c367fSLinJiawei  val aluRes = Mux(ALUOpType.isWordOp(func), SignExt(res(31,0), 64), res)
53e18c367fSLinJiawei
54e18c367fSLinJiawei  val branchOpTable = List(
55e18c367fSLinJiawei    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
56e18c367fSLinJiawei    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
57e18c367fSLinJiawei    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
58e18c367fSLinJiawei  )
59e18c367fSLinJiawei
60869210c7SYinan Xu  val isBranch = ALUOpType.isBranch(func)
613ef996e9SLinJiawei  val isRVC = uop.cf.brUpdate.pd.isRVC
62e18c367fSLinJiawei  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
633ef996e9SLinJiawei  val target = (pc + offset)(VAddrBits-1,0)
64e18c367fSLinJiawei  val snpc = Mux(isRVC, pc + 2.U, pc + 4.U)
65e18c367fSLinJiawei
66e18c367fSLinJiawei  redirectOutValid := io.out.valid && isBranch
67*151e3043SLinJiawei  // Only brTag, level, roqIdx are needed
68*151e3043SLinJiawei  // other infos are stored in brq
69*151e3043SLinJiawei  redirectOut := DontCare
70e18c367fSLinJiawei  redirectOut.brTag := uop.brTag
71bfb958a3SYinan Xu  redirectOut.level := RedirectLevel.flushAfter
72e18c367fSLinJiawei  redirectOut.roqIdx := uop.roqIdx
73e18c367fSLinJiawei
74*151e3043SLinJiawei//  redirectOut.pc := DontCare//uop.cf.pc
75*151e3043SLinJiawei//  redirectOut.target := DontCare//Mux(!taken && isBranch, snpc, target)
76*151e3043SLinJiawei//  redirectOut.interrupt := DontCare//DontCare
77*151e3043SLinJiawei
78*151e3043SLinJiawei  // Only taken really needed, do we need brTag ?
79*151e3043SLinJiawei  brUpdate := DontCare
80e18c367fSLinJiawei  brUpdate.taken := isBranch && taken
81e18c367fSLinJiawei  brUpdate.brTag := uop.brTag
82e18c367fSLinJiawei
83*151e3043SLinJiawei//  brUpdate := uop.cf.brUpdate
84*151e3043SLinJiawei//  // override brUpdate
85*151e3043SLinJiawei//  brUpdate.pc := uop.cf.pc
86*151e3043SLinJiawei//  brUpdate.target := Mux(!taken && isBranch, snpc, target)
87*151e3043SLinJiawei//  brUpdate.brTarget := target
88*151e3043SLinJiawei//  brUpdate.taken := isBranch && taken
89*151e3043SLinJiawei//  brUpdate.brTag := uop.brTag
90*151e3043SLinJiawei
91e18c367fSLinJiawei  io.in.ready := io.out.ready
92e18c367fSLinJiawei  io.out.valid := valid
93e18c367fSLinJiawei  io.out.bits.uop <> io.in.bits.uop
94e18c367fSLinJiawei  io.out.bits.data := aluRes
95e18c367fSLinJiawei}
96