xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Alu.scala (revision 694b0180118f79a40a1d26af0ea93ead726ab5e4)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import utils.{LookupTree, LookupTreeDefault, SignExt, XSDebug, ZeroExt}
6import xiangshan._
7import xiangshan.backend.ALUOpType
8
9class Alu extends FunctionUnit with HasRedirectOut {
10
11  val (src1, src2, offset, func, pc, uop) = (
12    io.in.bits.src(0),
13    io.in.bits.src(1),
14    io.in.bits.uop.ctrl.imm,
15    io.in.bits.uop.ctrl.fuOpType,
16    SignExt(io.in.bits.uop.cf.pc, AddrBits),
17    io.in.bits.uop
18  )
19
20  val redirectHit = uop.roqIdx.needFlush(io.redirectIn)
21  val valid = io.in.valid && !redirectHit
22
23  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw)
24  val adderRes = (src1 +& (src2 ^ Fill(XLEN, isAdderSub))) + isAdderSub
25  val xorRes = src1 ^ src2
26  val sltu = !adderRes(XLEN)
27  val slt = xorRes(XLEN-1) ^ sltu
28
29  val shsrc1 = LookupTreeDefault(func, src1, List(
30    ALUOpType.srlw -> ZeroExt(src1(31,0), 64),
31    ALUOpType.sraw -> SignExt(src1(31,0), 64)
32  ))
33  val shamt = Mux(ALUOpType.isWordOp(func), src2(4, 0), src2(5, 0))
34  val res = LookupTreeDefault(func(3, 0), adderRes, List(
35    ALUOpType.sll  -> ((shsrc1  << shamt)(XLEN-1, 0)),
36    ALUOpType.slt  -> ZeroExt(slt, XLEN),
37    ALUOpType.sltu -> ZeroExt(sltu, XLEN),
38    ALUOpType.xor  -> xorRes,
39    ALUOpType.srl  -> (shsrc1  >> shamt),
40    ALUOpType.or   -> (src1  |  src2),
41    ALUOpType.and  -> (src1  &  src2),
42    ALUOpType.sra  -> ((shsrc1.asSInt >> shamt).asUInt)
43  ))
44  val aluRes = Mux(ALUOpType.isWordOp(func), SignExt(res(31,0), 64), res)
45
46  val branchOpTable = List(
47    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
48    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
49    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
50  )
51
52  val isBranch = uop.cf.brUpdate.pd.isBr// ALUOpType.isBranch(func)
53  val isRVC = uop.cf.brUpdate.pd.isRVC//(io.in.bits.cf.instr(1,0) =/= "b11".U)
54  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
55  val target = Mux(isBranch, pc + offset, adderRes)(VAddrBits-1,0)
56  val snpc = Mux(isRVC, pc + 2.U, pc + 4.U)
57
58  redirectOutValid := io.out.valid && isBranch
59  redirectOut.pc := uop.cf.pc
60  redirectOut.target := Mux(!taken && isBranch, snpc, target)
61  redirectOut.brTag := uop.brTag
62  redirectOut.isException := false.B
63  redirectOut.isMisPred := DontCare // check this in brq
64  redirectOut.isFlushPipe := false.B
65  redirectOut.isReplay := false.B
66  redirectOut.roqIdx := uop.roqIdx
67
68  brUpdate := uop.cf.brUpdate
69  // override brUpdate
70  brUpdate.pc := uop.cf.pc
71  brUpdate.target := Mux(!taken && isBranch, snpc, target)
72  brUpdate.brTarget := target
73  brUpdate.taken := isBranch && taken
74  brUpdate.brTag := uop.brTag
75
76  io.in.ready := io.out.ready
77  io.out.valid := valid
78  io.out.bits.uop <> io.in.bits.uop
79  io.out.bits.data := aluRes
80
81  XSDebug(io.in.valid || io.redirectIn.valid,
82    "In(%d %d) Out(%d %d) Redirect:(%d %d %d %d) brTag:f:%d v:%d\n",
83    io.in.valid,
84    io.in.ready,
85    io.out.valid,
86    io.out.ready,
87    io.redirectIn.valid,
88    io.redirectIn.bits.isException,
89    io.redirectIn.bits.isFlushPipe,
90    redirectHit,
91    io.redirectIn.bits.brTag.flag,
92    io.redirectIn.bits.brTag.value
93  )
94  XSDebug(io.in.valid,
95    p"src1:${Hexadecimal(src1)} src2:${Hexadecimal(src2)} " +
96      p"offset:${Hexadecimal(offset)} func:${Binary(func)} " +
97      p"pc:${Hexadecimal(pc)} roqIdx:${uop.roqIdx}\n"
98  )
99  XSDebug(io.out.valid,
100    p"res:${Hexadecimal(io.out.bits.data)} aluRes:${Hexadecimal(aluRes)} " +
101      p"isRVC:${isRVC} isBranch:${isBranch} " +
102      p"target:${Hexadecimal(target)} taken:${taken}\n"
103  )
104}
105