xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/Debug.scala (revision cc6e4cb5a6a1ecfabed10188df08fdae32ba5841)
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}