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