xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Jump.scala (revision c6d439803a044ea209139672b25e35fe8d7f4aa0)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*
4* XiangShan is licensed under Mulan PSL v2.
5* You can use this software according to the terms and conditions of the Mulan PSL v2.
6* You may obtain a copy of Mulan PSL v2 at:
7*          http://license.coscl.org.cn/MulanPSL2
8*
9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
12*
13* See the Mulan PSL v2 for more details.
14***************************************************************************************/
15
16package xiangshan.backend.fu
17
18import chipsalliance.rocketchip.config.Parameters
19import chisel3._
20import chisel3.util._
21import xiangshan._
22import utils._
23import xiangshan.backend._
24import xiangshan.backend.decode.ImmUnion
25import xiangshan.backend.decode.isa._
26
27trait HasRedirectOut { this: XSModule =>
28  val redirectOutValid = IO(Output(Bool()))
29  val redirectOut = IO(Output(new Redirect))
30}
31
32class JumpDataModule(implicit p: Parameters) extends XSModule {
33  val io = IO(new Bundle() {
34    val src = Input(UInt(XLEN.W))
35    val pc = Input(UInt(XLEN.W)) // sign-ext to XLEN
36    val immMin = Input(UInt(ImmUnion.maxLen.W))
37    val func = Input(FuOpType())
38    val isRVC = Input(Bool())
39    val result, target = Output(UInt(XLEN.W))
40    val isAuipc = Output(Bool())
41  })
42  val (src1, pc, immMin, func, isRVC) = (io.src, io.pc, io.immMin, io.func, io.isRVC)
43
44  val isJalr = JumpOpType.jumpOpisJalr(func)
45  val isAuipc = JumpOpType.jumpOpisAuipc(func)
46  val offset = SignExt(ParallelMux(Seq(
47    isJalr -> ImmUnion.I.toImm32(immMin),
48    isAuipc -> ImmUnion.U.toImm32(immMin),
49    !(isJalr || isAuipc) -> ImmUnion.J.toImm32(immMin)
50  )), XLEN)
51
52  val snpc = Mux(isRVC, pc + 2.U, pc + 4.U)
53  val target = src1 + offset // NOTE: src1 is (pc/rf(rs1)), src2 is (offset)
54
55  io.target := target
56  io.result := Mux(JumpOpType.jumpOpisAuipc(func), target, snpc)
57  io.isAuipc := isAuipc
58}
59
60class Jump(implicit p: Parameters) extends FunctionUnit with HasRedirectOut {
61
62  val (src1, jalr_target, pc, immMin, func, uop) = (
63    io.in.bits.src(0),
64    io.in.bits.src(1)(VAddrBits - 1, 0),
65    SignExt(io.in.bits.uop.cf.pc, XLEN),
66    io.in.bits.uop.ctrl.imm,
67    io.in.bits.uop.ctrl.fuOpType,
68    io.in.bits.uop
69  )
70
71  val redirectHit = uop.roqIdx.needFlush(io.redirectIn, io.flushIn)
72  val valid = io.in.valid
73  val isRVC = uop.cf.pd.isRVC
74
75  val jumpDataModule = Module(new JumpDataModule)
76  jumpDataModule.io.src := src1
77  jumpDataModule.io.pc := pc
78  jumpDataModule.io.immMin := immMin
79  jumpDataModule.io.func := func
80  jumpDataModule.io.isRVC := isRVC
81
82  redirectOutValid := valid && !jumpDataModule.io.isAuipc
83  redirectOut := DontCare
84  redirectOut.level := RedirectLevel.flushAfter
85  redirectOut.roqIdx := uop.roqIdx
86  redirectOut.ftqIdx := uop.cf.ftqPtr
87  redirectOut.ftqOffset := uop.cf.ftqOffset
88  redirectOut.cfiUpdate.predTaken := true.B
89  redirectOut.cfiUpdate.taken := true.B
90  redirectOut.cfiUpdate.target := jumpDataModule.io.target
91  redirectOut.cfiUpdate.isMisPred := jumpDataModule.io.target(VAddrBits - 1, 0) =/= jalr_target || !uop.cf.pred_taken
92
93  io.in.ready := io.out.ready
94  io.out.valid := valid
95  io.out.bits.uop <> io.in.bits.uop
96  io.out.bits.data := jumpDataModule.io.result
97
98  // NOTE: the debug info is for one-cycle exec, if FMV needs multi-cycle, may needs change it
99  XSDebug(io.in.valid, "In(%d %d) Out(%d %d) Redirect:(%d %d %d)\n",
100    io.in.valid,
101    io.in.ready,
102    io.out.valid,
103    io.out.ready,
104    io.redirectIn.valid,
105    io.redirectIn.bits.level,
106    redirectHit
107  )
108}
109