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