1/*************************************************************************************** 2 * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3 * Copyright (c) 2020-2021 Peng Cheng Laboratory 4 * 5 * XiangShan is licensed under Mulan PSL v2. 6 * You can use this software according to the terms and conditions of the Mulan PSL v2. 7 * You may obtain a copy of Mulan PSL v2 at: 8 * http://license.coscl.org.cn/MulanPSL2 9 * 10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13 * 14 * See the Mulan PSL v2 for more details. 15 ***************************************************************************************/ 16 17package xiangshan.backend.rob 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import difftest._ 23import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 24import utility._ 25import utils._ 26import xiangshan._ 27import xiangshan.backend.BackendParams 28import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput} 29import xiangshan.backend.fu.{FuConfig, FuType} 30import xiangshan.frontend.FtqPtr 31import xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr} 32import xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput} 33import xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo} 34import xiangshan.backend.fu.vector.Bundles.VType 35import xiangshan.backend.rename.SnapshotGenerator 36 37class ExceptionGen(params: BackendParams)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper { 38 val io = IO(new Bundle { 39 val redirect = Input(Valid(new Redirect)) 40 val flush = Input(Bool()) 41 val enq = Vec(RenameWidth, Flipped(ValidIO(new RobExceptionInfo))) 42 // csr + load + store + varith + vload + vstore 43 val wb = Vec(params.numException, Flipped(ValidIO(new RobExceptionInfo))) 44 val out = ValidIO(new RobExceptionInfo) 45 val state = ValidIO(new RobExceptionInfo) 46 }) 47 48 val wbExuParams = params.allExuParams.filter(_.exceptionOut.nonEmpty) 49 50 def getOldest(valid: Seq[Bool], bits: Seq[RobExceptionInfo]): RobExceptionInfo = { 51 def getOldest_recursion(valid: Seq[Bool], bits: Seq[RobExceptionInfo]): (Seq[Bool], Seq[RobExceptionInfo]) = { 52 assert(valid.length == bits.length) 53 if (valid.length == 1) { 54 (valid, bits) 55 } else if (valid.length == 2) { 56 val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0))))) 57 for (i <- res.indices) { 58 res(i).valid := valid(i) 59 res(i).bits := bits(i) 60 } 61 val oldest = Mux(!valid(1) || valid(0) && isAfter(bits(1).robIdx, bits(0).robIdx), res(0), res(1)) 62 (Seq(oldest.valid), Seq(oldest.bits)) 63 } else { 64 val left = getOldest_recursion(valid.take(valid.length / 2), bits.take(valid.length / 2)) 65 val right = getOldest_recursion(valid.drop(valid.length / 2), bits.drop(valid.length / 2)) 66 getOldest_recursion(left._1 ++ right._1, left._2 ++ right._2) 67 } 68 } 69 getOldest_recursion(valid, bits)._2.head 70 } 71 72 73 val currentValid = RegInit(false.B) 74 val current = Reg(new RobExceptionInfo) 75 76 // orR the exceptionVec 77 val lastCycleFlush = RegNext(io.flush) 78 val in_enq_valid = VecInit(io.enq.map(e => e.valid && e.bits.has_exception && !lastCycleFlush)) 79 80 // s0: compare wb in 6 groups 81 val csr_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(t => t.isCsr).nonEmpty).map(_._1) 82 val load_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.ldu).nonEmpty).map(_._1) 83 val store_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(t => t.isSta || t.fuType == FuType.mou).nonEmpty).map(_._1) 84 val varith_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.isVecArith).nonEmpty).map(_._1) 85 val vload_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.vldu).nonEmpty).map(_._1) 86 val vstore_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.vstu).nonEmpty).map(_._1) 87 88 val writebacks = Seq(csr_wb, load_wb, store_wb, varith_wb, vload_wb, vstore_wb) 89 val in_wb_valids = writebacks.map(_.map(w => w.valid && w.bits.has_exception && !lastCycleFlush)) 90 val wb_valid = in_wb_valids.zip(writebacks).map { case (valid, wb) => 91 valid.zip(wb.map(_.bits)).map { case (v, bits) => v && !(bits.robIdx.needFlush(io.redirect) || io.flush) }.reduce(_ || _) 92 } 93 val wb_bits = in_wb_valids.zip(writebacks).map { case (valid, wb) => getOldest(valid, wb.map(_.bits))} 94 95 val s0_out_valid = wb_valid.map(x => RegNext(x)) 96 val s0_out_bits = wb_bits.zip(wb_valid).map{ case(b, v) => RegEnable(b, v)} 97 98 // s1: compare last six and current flush 99 val s1_valid = VecInit(s0_out_valid.zip(s0_out_bits).map{ case (v, b) => v && !(b.robIdx.needFlush(io.redirect) || io.flush) }) 100 val s1_out_bits = RegEnable(getOldest(s0_out_valid, s0_out_bits), s1_valid.asUInt.orR) 101 val s1_out_valid = RegNext(s1_valid.asUInt.orR) 102 103 val enq_valid = RegNext(in_enq_valid.asUInt.orR && !io.redirect.valid && !io.flush) 104 val enq_bits = RegEnable(ParallelPriorityMux(in_enq_valid, io.enq.map(_.bits)), in_enq_valid.asUInt.orR && !io.redirect.valid && !io.flush) 105 106 // s2: compare the input exception with the current one 107 // priorities: 108 // (1) system reset 109 // (2) current is valid: flush, remain, merge, update 110 // (3) current is not valid: s1 or enq 111 val current_flush = current.robIdx.needFlush(io.redirect) || io.flush 112 val s1_flush = s1_out_bits.robIdx.needFlush(io.redirect) || io.flush 113 when (currentValid) { 114 when (current_flush) { 115 currentValid := Mux(s1_flush, false.B, s1_out_valid) 116 } 117 when (s1_out_valid && !s1_flush) { 118 when (isAfter(current.robIdx, s1_out_bits.robIdx)) { 119 current := s1_out_bits 120 }.elsewhen (current.robIdx === s1_out_bits.robIdx) { 121 current.exceptionVec := (s1_out_bits.exceptionVec.asUInt | current.exceptionVec.asUInt).asTypeOf(ExceptionVec()) 122 current.flushPipe := s1_out_bits.flushPipe || current.flushPipe 123 current.replayInst := s1_out_bits.replayInst || current.replayInst 124 current.singleStep := s1_out_bits.singleStep || current.singleStep 125 current.trigger := (s1_out_bits.trigger.asUInt | current.trigger.asUInt).asTypeOf(new TriggerCf) 126 } 127 } 128 }.elsewhen (s1_out_valid && !s1_flush) { 129 currentValid := true.B 130 current := s1_out_bits 131 }.elsewhen (enq_valid && !(io.redirect.valid || io.flush)) { 132 currentValid := true.B 133 current := enq_bits 134 } 135 136 io.out.valid := s1_out_valid || enq_valid && enq_bits.can_writeback 137 io.out.bits := Mux(s1_out_valid, s1_out_bits, enq_bits) 138 io.state.valid := currentValid 139 io.state.bits := current 140 141}