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