1package xiangshan.backend.fu 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan._ 6import utils._ 7import xiangshan.backend._ 8import xiangshan.backend.decode.ImmUnion 9import xiangshan.backend.fu.FunctionUnit._ 10import xiangshan.backend.decode.isa._ 11 12trait HasRedirectOut { this: RawModule => 13 val redirectOutValid = IO(Output(Bool())) 14 val redirectOut = IO(Output(new Redirect)) 15} 16 17class JumpDataModule extends XSModule { 18 val io = IO(new Bundle() { 19 val src1 = Input(UInt(XLEN.W)) 20 val pc = Input(UInt(XLEN.W)) // sign-ext to XLEN 21 val immMin = Input(UInt(ImmUnion.maxLen.W)) 22 val func = Input(FuOpType()) 23 val isRVC = Input(Bool()) 24 val result, target = Output(UInt(XLEN.W)) 25 val isAuipc = Output(Bool()) 26 }) 27 val (src1, pc, immMin, func, isRVC) = (io.src1, io.pc, io.immMin, io.func, io.isRVC) 28 29 val isJalr = JumpOpType.jumpOpisJalr(func) 30 val isAuipc = JumpOpType.jumpOpisAuipc(func) 31 val offset = SignExt(ParallelMux(Seq( 32 isJalr -> ImmUnion.I.toImm32(immMin), 33 isAuipc -> ImmUnion.U.toImm32(immMin), 34 !(isJalr || isAuipc) -> ImmUnion.J.toImm32(immMin) 35 )), XLEN) 36 37 val snpc = Mux(isRVC, pc + 2.U, pc + 4.U) 38 val target = src1 + offset // NOTE: src1 is (pc/rf(rs1)), src2 is (offset) 39 40 io.target := target 41 io.result := Mux(JumpOpType.jumpOpisAuipc(func), target, snpc) 42 io.isAuipc := isAuipc 43} 44 45class Jump extends FunctionUnit with HasRedirectOut { 46 47 val (src1, jalr_target, pc, immMin, func, uop) = ( 48 io.in.bits.src(0), 49 io.in.bits.src(1)(VAddrBits - 1, 0), 50 SignExt(io.in.bits.uop.cf.pc, XLEN), 51 io.in.bits.uop.ctrl.imm, 52 io.in.bits.uop.ctrl.fuOpType, 53 io.in.bits.uop 54 ) 55 56 val redirectHit = uop.roqIdx.needFlush(io.redirectIn, io.flushIn) 57 val valid = io.in.valid 58 val isRVC = uop.cf.pd.isRVC 59 60 val jumpDataModule = Module(new JumpDataModule) 61 jumpDataModule.io.src1 := src1 62 jumpDataModule.io.pc := pc 63 jumpDataModule.io.immMin := immMin 64 jumpDataModule.io.func := func 65 jumpDataModule.io.isRVC := isRVC 66 67 redirectOutValid := valid && !jumpDataModule.io.isAuipc 68 redirectOut := DontCare 69 redirectOut.cfiUpdate.target := jumpDataModule.io.target 70 redirectOut.level := RedirectLevel.flushAfter 71 redirectOut.roqIdx := uop.roqIdx 72 redirectOut.ftqIdx := uop.cf.ftqPtr 73 redirectOut.ftqOffset := uop.cf.ftqOffset 74 redirectOut.cfiUpdate.predTaken := true.B 75 redirectOut.cfiUpdate.taken := true.B 76 redirectOut.cfiUpdate.target := jumpDataModule.io.target 77 redirectOut.cfiUpdate.isMisPred := jumpDataModule.io.target =/= jalr_target || !uop.cf.pred_taken 78 79 io.in.ready := io.out.ready 80 io.out.valid := valid 81 io.out.bits.uop <> io.in.bits.uop 82 io.out.bits.data := jumpDataModule.io.result 83 84 // NOTE: the debug info is for one-cycle exec, if FMV needs multi-cycle, may needs change it 85 XSDebug(io.in.valid, "In(%d %d) Out(%d %d) Redirect:(%d %d %d)\n", 86 io.in.valid, 87 io.in.ready, 88 io.out.valid, 89 io.out.ready, 90 io.redirectIn.valid, 91 io.redirectIn.bits.level, 92 redirectHit 93 ) 94} 95