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