1package xiangshan.backend.fu.NewCSR 2 3import chisel3._ 4import chisel3.util._ 5import org.chipsalliance.cde.config.Parameters 6import xiangshan.backend.fu.NewCSR.CSRBundles.PrivState 7import xiangshan.backend.fu.util.CSRConst 8import xiangshan.backend.fu.util.SdtrigExt 9import xiangshan._ 10 11class Debug(implicit val p: Parameters) extends Module with HasXSParameter { 12 val io = IO(new DebugIO) 13 14 private val trapInfo = io.in.trapInfo 15 private val hasTrap = trapInfo.valid 16 private val trapIsInterrupt = trapInfo.bits.isInterrupt 17 private val intrVec = trapInfo.bits.intrVec 18 private val trapVec = trapInfo.bits.trapVec 19 private val singleStep = trapInfo.bits.singleStep 20 private val trigger = io.in.trapInfo.bits.trigger 21 22 private val privState = io.in.privState 23 private val debugMode = io.in.debugMode 24 25 private val dcsr = io.in.dcsr 26 private val tcontrol = io.in.tcontrol 27 private val tselect = io.in.tselect 28 private val tdata1Selected = io.in.tdata1Selected 29 private val tdata2Selected = io.in.tdata2Selected 30 private val tdata1Vec = io.in.tdata1Vec 31 32 private val tdata1Update = io.in.tdata1Update 33 private val tdata2Update = io.in.tdata2Update 34 private val tdata1Wdata = io.in.tdata1Wdata 35 36 /** 37 * ways to entry Dmode: 38 * 1. debug intr(from external debug module) 39 * 2. ebreak inst in nonDmode 40 * 3. trigger fire in nonDmode 41 * 4. single step(debug module set dcsr.step before hart resume) 42 */ 43 // debug_intr 44 val hasIntr = hasTrap && trapIsInterrupt 45 val hasDebugIntr = hasIntr && intrVec(CSRConst.IRQ_DEBUG) 46 47 // debug_exception_ebreak 48 val hasExp = hasTrap && !trapIsInterrupt 49 val breakPoint = trapVec(ExceptionNO.breakPoint).asBool 50 val isEbreak = hasExp && breakPoint && !TriggerAction.isExp(trigger) 51 val ebreakEnterDebugMode = 52 (privState.isModeM && dcsr.EBREAKM.asBool) || 53 (privState.isModeHS && dcsr.EBREAKS.asBool) || 54 (privState.isModeHU && dcsr.EBREAKU.asBool) || 55 (privState.isModeVS && dcsr.EBREAKVS.asBool) || 56 (privState.isModeVU && dcsr.EBREAKVU.asBool) 57 val hasDebugEbreakException = isEbreak && ebreakEnterDebugMode 58 59 // debug_exception_trigger 60 val mcontrol6WireVec = tdata1Vec.map{ mod => { 61 val mcontrol6Wire = Wire(new Mcontrol6) 62 mcontrol6Wire := mod.DATA.asUInt 63 mcontrol6Wire 64 }} 65 66 val triggerCanRaiseBpExp = Mux(privState.isModeM, tcontrol.MTE.asBool, true.B) 67 val triggerEnterDebugMode = hasExp && TriggerAction.isDmode(trigger) 68 69 // debug_exception_single 70 val hasSingleStep = hasExp && singleStep 71 72 val hasDebugException = hasDebugEbreakException || triggerEnterDebugMode || hasSingleStep 73 val hasDebugTrap = hasDebugException || hasDebugIntr 74 75 val tselect1H = UIntToOH(tselect.asUInt, TriggerNum).asBools 76 val chainVec = mcontrol6WireVec.map(_.CHAIN.asBool) 77 val newTriggerChainVec = tselect1H.zip(chainVec).map{case(a, b) => a | b} 78 val newTriggerChainIsLegal = TriggerUtil.TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength) 79 80 val triggerUpdate = tdata1Update || tdata2Update 81 82 val mcontrol6Wdata = Wire(new Mcontrol6) 83 mcontrol6Wdata := tdata1Wdata.DATA.asUInt 84 val tdata1TypeWdata = tdata1Wdata.TYPE 85 86 val mcontrol6Selected = Wire(new Mcontrol6) 87 mcontrol6Selected := tdata1Selected.DATA.asUInt 88 89 val frontendTriggerUpdate = 90 tdata1Update && tdata1TypeWdata.isLegal && mcontrol6Wdata.isFetchTrigger || 91 mcontrol6Selected.isFetchTrigger && triggerUpdate 92 93 val memTriggerUpdate = 94 tdata1Update && tdata1TypeWdata.isLegal && mcontrol6Wdata.isMemAccTrigger || 95 mcontrol6Selected.isMemAccTrigger && triggerUpdate 96 97 val triggerEnableVec = tdata1Vec.zip(mcontrol6WireVec).map { case(tdata1, mcontrol6) => 98 tdata1.TYPE.isLegal && ( 99 mcontrol6.M && privState.isModeM || 100 mcontrol6.S && privState.isModeHS || 101 mcontrol6.U && privState.isModeHU || 102 mcontrol6.VS && privState.isModeVS || 103 mcontrol6.VU && privState.isModeVU) 104 } 105 106 val fetchTriggerEnableVec = triggerEnableVec.zip(mcontrol6WireVec).map { 107 case (tEnable, mod) => tEnable && mod.isFetchTrigger 108 } 109 val memAccTriggerEnableVec = triggerEnableVec.zip(mcontrol6WireVec).map { 110 case (tEnable, mod) => tEnable && mod.isMemAccTrigger 111 } 112 113 io.out.frontendTrigger.tUpdate.valid := RegNext(RegNext(frontendTriggerUpdate)) 114 io.out.frontendTrigger.tUpdate.bits.addr := tselect.asUInt 115 io.out.frontendTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected) 116 io.out.frontendTrigger.tEnableVec := fetchTriggerEnableVec 117 io.out.frontendTrigger.triggerCanRaiseBpExp := triggerCanRaiseBpExp 118 io.out.frontendTrigger.debugMode := debugMode 119 120 io.out.memTrigger.tUpdate.valid := RegNext(RegNext(memTriggerUpdate)) 121 io.out.memTrigger.tUpdate.bits.addr := tselect.asUInt 122 io.out.memTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected) 123 io.out.memTrigger.tEnableVec := memAccTriggerEnableVec 124 io.out.memTrigger.triggerCanRaiseBpExp := triggerCanRaiseBpExp 125 io.out.memTrigger.debugMode := debugMode 126 127 io.out.triggerFrontendChange := frontendTriggerUpdate 128 io.out.newTriggerChainIsLegal := newTriggerChainIsLegal 129 130 io.out.hasDebugTrap := hasDebugTrap 131 io.out.hasDebugIntr := hasDebugIntr 132 io.out.hasSingleStep := hasSingleStep 133 io.out.triggerEnterDebugMode := triggerEnterDebugMode 134 io.out.hasDebugEbreakException := hasDebugEbreakException 135 io.out.breakPoint := breakPoint 136} 137 138class DebugIO(implicit val p: Parameters) extends Bundle with HasXSParameter { 139 val in = Input(new Bundle { 140 val trapInfo = ValidIO(new Bundle { 141 val trapVec = UInt(64.W) 142 val intrVec = UInt(64.W) 143 val isInterrupt = Bool() 144 val singleStep = Bool() 145 val trigger = TriggerAction() 146 }) 147 148 val privState = new PrivState 149 val debugMode = Bool() 150 151 val dcsr = new DcsrBundle 152 val tcontrol = new TcontrolBundle 153 val tselect = new TselectBundle(TriggerNum) 154 val tdata1Selected = new Tdata1Bundle 155 val tdata2Selected = new Tdata2Bundle 156 val tdata1Vec = Vec(TriggerNum, new Tdata1Bundle) 157 158 val tdata1Update = Bool() 159 val tdata2Update = Bool() 160 val tdata1Wdata = new Tdata1Bundle 161 }) 162 163 val out = Output(new Bundle{ 164 // trigger 165 val triggerFrontendChange = Bool() 166 val newTriggerChainIsLegal = Bool() 167 val memTrigger = new MemTdataDistributeIO() 168 val frontendTrigger = new FrontendTdataDistributeIO() 169 170 val hasDebugTrap = Bool() 171 val hasDebugIntr = Bool() 172 val hasSingleStep = Bool() 173 val triggerEnterDebugMode = Bool() 174 val hasDebugEbreakException = Bool() 175 val breakPoint = Bool() 176 }) 177} 178 179class CsrTriggerBundle(implicit val p: Parameters) extends Bundle with HasXSParameter { 180 val tdataVec = Vec(TriggerNum, new MatchTriggerIO) 181 val tEnableVec = Vec(TriggerNum, Bool()) 182 val debugMode = Bool() 183 val triggerCanRaiseBpExp = Bool() 184} 185 186object MemType { 187 val LOAD = true 188 val STORE = false 189} 190 191 192class BaseTriggerIO(implicit p: Parameters) extends XSBundle{ 193 val fromCsrTrigger = Input(new CsrTriggerBundle) 194 195 val fromLoadStore = Input(new Bundle { 196 val vaddr = UInt(VAddrBits.W) 197 val isVectorUnitStride = Bool() 198 val mask = UInt((VLEN/8).W) 199 }) 200 201 val toLoadStore = Output(new Bundle{ 202 val triggerAction = TriggerAction() 203 val triggerVaddr = UInt(VAddrBits.W) 204 val triggerMask = UInt((VLEN/8).W) 205 }) 206} 207 208 209abstract class BaseTrigger()(implicit val p: Parameters) extends Module with HasXSParameter with SdtrigExt { 210 lazy val io = IO(new BaseTriggerIO) 211 212 def getTriggerHitVec(): Vec[Bool] 213 def highBitsEq(): Vec[Bool] 214 215 val tdataVec = io.fromCsrTrigger.tdataVec 216 val tEnableVec = io.fromCsrTrigger.tEnableVec 217 val triggerCanRaiseBpExp = io.fromCsrTrigger.triggerCanRaiseBpExp 218 val debugMode = io.fromCsrTrigger.debugMode 219 val vaddr = io.fromLoadStore.vaddr 220 221 val triggerTimingVec = VecInit(tdataVec.map(_.timing)) 222 val triggerChainVec = VecInit(tdataVec.map(_.chain)) 223 224 // Trigger can't hit/fire in debug mode. 225 val triggerHitVec = getTriggerHitVec() 226 val triggerCanFireVec = WireInit(VecInit(Seq.fill(TriggerNum)(false.B))) 227 // for vector unit-stride, match Type only support equal 228 val lowBitWidth = log2Up(VLEN/8) 229 val isVectorStride = io.fromLoadStore.isVectorUnitStride 230 val mask = io.fromLoadStore.mask 231 232 val highEq = highBitsEq() 233 234 val lowMatch = tdataVec.map(tdata => UIntToOH(tdata.tdata2(lowBitWidth-1, 0)) & mask) 235 val lowEq = VecInit(lowMatch.map(lm => lm.orR)) 236 237 val hitVecVectorStride = VecInit(highEq.zip(lowEq).map{case(hi, lo) => hi && lo}) 238 239 TriggerCheckCanFire(TriggerNum, triggerCanFireVec, Mux(isVectorStride, hitVecVectorStride, triggerHitVec), triggerTimingVec, triggerChainVec) 240 val triggerFireOH = PriorityEncoderOH(triggerCanFireVec) 241 val triggerVaddr = PriorityMux(triggerFireOH, VecInit(tdataVec.map(_.tdata2))).asUInt 242 val triggerMask = PriorityMux(triggerFireOH, VecInit(tdataVec.map(x => UIntToOH(x.tdata2(lowBitWidth-1, 0))))).asUInt 243 244 val actionVec = VecInit(tdataVec.map(_.action)) 245 val triggerAction = Wire(TriggerAction()) 246 TriggerUtil.triggerActionGen(triggerAction, triggerCanFireVec, actionVec, triggerCanRaiseBpExp) 247 248 io.toLoadStore.triggerAction := triggerAction 249 io.toLoadStore.triggerVaddr := triggerVaddr 250 io.toLoadStore.triggerMask := triggerMask 251} 252 253 254class MemTrigger(memType: Boolean = MemType.LOAD)(override implicit val p: Parameters) extends BaseTrigger { 255 256 override def getTriggerHitVec(): Vec[Bool] = { 257 val triggerHitVec = WireInit(VecInit(Seq.fill(TriggerNum)(false.B))) 258 for (i <- 0 until TriggerNum) { 259 triggerHitVec(i) := !tdataVec(i).select && !debugMode && TriggerCmp( 260 vaddr, 261 tdataVec(i).tdata2, 262 tdataVec(i).matchType, 263 tEnableVec(i) && (if(memType == MemType.LOAD) tdataVec(i).load else tdataVec(i).store) 264 ) 265 } 266 triggerHitVec 267 } 268 269 override def highBitsEq(): Vec[Bool] = { 270 VecInit(tdataVec.zip(tEnableVec).map{ case(tdata, en) => 271 !tdata.select && !debugMode && en && 272 (if(memType == MemType.LOAD) tdata.load else tdata.store) && 273 (vaddr >> lowBitWidth) === (tdata.tdata2 >> lowBitWidth) 274 }) 275 } 276} 277 278class VSegmentTrigger(override implicit val p: Parameters) extends BaseTrigger { 279 280 class VSegmentTriggerIO extends BaseTriggerIO{ 281 val memType = Input(Bool()) 282 } 283 284 override lazy val io = IO(new VSegmentTriggerIO) 285 286 override def getTriggerHitVec(): Vec[Bool] = { 287 val triggerHitVec = WireInit(VecInit(Seq.fill(TriggerNum)(false.B))) 288 for (i <- 0 until TriggerNum) { 289 triggerHitVec(i) := !tdataVec(i).select && !debugMode && TriggerCmp( 290 vaddr, 291 tdataVec(i).tdata2, 292 tdataVec(i).matchType, 293 tEnableVec(i) && Mux(io.memType === MemType.LOAD.asBool, tdataVec(i).load, tdataVec(i).store) 294 ) 295 } 296 triggerHitVec 297 } 298 299 override def highBitsEq(): Vec[Bool] = { 300 VecInit(tdataVec.zip(tEnableVec).map{ case(tdata, en) => 301 !tdata.select && !debugMode && en && 302 Mux(io.memType === MemType.LOAD.asBool, tdata.load, tdata.store) && 303 (vaddr >> lowBitWidth) === (tdata.tdata2 >> lowBitWidth) 304 }) 305 } 306}