xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/DebugLevel.scala (revision 7e0f64b082c1a723b90b720cc41cdfc5f5885444)
1package xiangshan.backend.fu.NewCSR
2
3import freechips.rocketchip.devices.debug.DebugModuleKey
4import org.chipsalliance.cde.config.Parameters
5import freechips.rocketchip.rocket.CSRs
6import chisel3._
7import chisel3.util._
8import utils.ConsecutiveOnes
9import xiangshan.backend.fu.NewCSR.CSRDefines._
10import xiangshan.backend.fu.NewCSR.CSRDefines.{
11  CSRWARLField => WARL,
12  CSRRWField => RW,
13  CSRROField => RO,
14}
15import xiangshan.backend.fu.NewCSR.CSRFunc._
16import xiangshan.backend.fu.NewCSR.CSREvents._
17import xiangshan.backend.fu.NewCSR.CSRBundles._
18import CSRConfig._
19import utility.SignExt
20import xiangshan.TriggerAction
21
22import scala.collection.immutable.SeqMap
23
24
25trait DebugLevel { self: NewCSR =>
26  val tselect = Module(new CSRModule("Tselect", new TselectBundle(TriggerNum)) {
27    when (this.w.wen && this.w.wdata < TriggerNum.U) {
28      reg := this.w.wdata
29    }.otherwise {
30      reg := reg
31    }
32  })
33    .setAddr(CSRs.tselect)
34
35  val tdata1 = Module(new CSRModule("Tdata1") with HasTdataSink {
36    regOut := tdataRead.tdata1
37  })
38    .setAddr(CSRs.tdata1)
39
40  val tdata2 = Module(new CSRModule("Tdata2") with HasTdataSink {
41    regOut := tdataRead.tdata2
42  })
43    .setAddr(CSRs.tdata2)
44
45  val tdata1RegVec: Seq[CSRModule[_]] = Range(0, TriggerNum).map(i =>
46    Module(new CSRModule(s"Trigger$i" + s"_Tdata1", new Tdata1Bundle) with HasdebugModeBundle {
47      when(wen){
48        reg := wdata.writeTdata1(debugMode, chainable).asUInt
49      }
50    })
51  )
52  val tdata2RegVec: Seq[CSRModule[_]] = Range(0, TriggerNum).map(i =>
53    Module(new CSRModule(s"Trigger$i" + s"_Tdata2", new Tdata2Bundle))
54  )
55
56  val tinfo = Module(new CSRModule("Tinfo", new TinfoBundle))
57    .setAddr(CSRs.tinfo)
58
59  val tcontrol = Module(new CSRModule("Tcontrol", new TcontrolBundle) with TrapEntryMEventSinkBundle with MretEventSinkBundle)
60    .setAddr(CSRs.tcontrol)
61
62  val dcsr = Module(new CSRModule("Dcsr", new DcsrBundle) with TrapEntryDEventSinkBundle with DretEventSinkBundle)
63    .setAddr(CSRs.dcsr)
64
65  val dpc = Module(new CSRModule("Dpc", new Epc) with TrapEntryDEventSinkBundle)
66    .setAddr(CSRs.dpc)
67
68  val dscratch0 = Module(new CSRModule("Dscratch0", new DscratchBundle))
69    .setAddr(CSRs.dscratch0)
70
71  val dscratch1 = Module(new CSRModule("Dscratch1", new DscratchBundle))
72    .setAddr(CSRs.dscratch1)
73
74  val debugCSRMods = Seq(
75    tdata1,
76    tdata2,
77    tselect,
78    tinfo,
79    tcontrol,
80    dcsr,
81    dpc,
82    dscratch0,
83    dscratch1,
84  )
85
86  val debugCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_ <: CSRBundle], UInt)] = SeqMap.from(
87    debugCSRMods.map(csr => csr.addr -> (csr.w -> csr.rdata)).iterator
88  )
89
90  val debugCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
91    debugCSRMods.map(csr => csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt).iterator
92  )
93
94  private val tdata1Rdata = Mux1H(
95    tdata1RegVec.zipWithIndex.map{case (mod, idx) => (tselect.rdata === idx.U) -> mod.rdata}
96  )
97
98  private val tdata2Rdata = Mux1H(
99    tdata2RegVec.zipWithIndex.map{case (mod, idx) => (tselect.rdata === idx.U) -> mod.rdata}
100  )
101
102  debugCSRMods.foreach { mod =>
103    mod match {
104      case m: HasTdataSink =>
105        m.tdataRead.tdata1 := tdata1Rdata
106        m.tdataRead.tdata2 := tdata2Rdata
107      case _ =>
108    }
109  }
110
111}
112
113// tselect
114class TselectBundle(triggerNum: Int) extends CSRBundle{
115  override val len: Int = log2Up(triggerNum)
116  val ALL = WARL(len - 1, 0, wNoEffectWhen(WriteTselect)).withReset(0.U)
117  def WriteTselect(wdata: UInt) = {
118    wdata >= triggerNum.U
119  }
120}
121
122// tdata1
123class Tdata1Bundle extends CSRBundle{
124  val TYPE    = Tdata1Type(63, 60, wNoFilter).withReset(Tdata1Type.Disabled)
125  val DMODE   = RW(59).withReset(0.U)
126  val DATA    = RW(58, 0).withReset(0.U)
127
128  def getTriggerAction: CSREnumType = {
129    val res = Wire(new Mcontrol)
130    res := this.asUInt
131    res.ACTION
132  }
133
134  def writeTdata1(debugMode: Bool, chainable: Bool): Tdata1Bundle = {
135    val res = Wire(new Tdata1Bundle)
136    res := this.asUInt
137    val dmode = this.DMODE.asBool && debugMode
138    res.TYPE := this.TYPE.legalize.asUInt
139    res.DMODE := dmode
140    when(this.TYPE.isLegal) {
141      val mcontrolRes = Wire(new Mcontrol)
142      mcontrolRes := this.DATA.asUInt
143      res.DATA := mcontrolRes.writeData(dmode, chainable).asUInt
144    }.otherwise{
145      res.DATA := 0.U
146    }
147   res
148  }
149}
150
151class Mcontrol extends CSRBundle{
152  override val len: Int = 59
153  // xiangshan don't support match = NAPOT
154  val MASKMAX = RO(58, 53).withReset(0.U)
155  val SIZEHI  = RW(22, 21).withReset(0.U)
156  val HIT     = RW(20).withReset(0.U)
157  val SELECT  = RW(19).withReset(0.U)
158  val TIMING  = RW(18).withReset(0.U)
159  val SIZELO  = RW(17, 16).withReset(0.U)
160  val ACTION  = TrigAction(15, 12, wNoFilter).withReset(TrigAction.BreakpointExp)
161  val CHAIN   = RW(11).withReset(0.U)
162  val MATCH   = TrigMatch(10, 7, wNoFilter).withReset(TrigMatch.EQ)
163  val M       = RW(6).withReset(0.U)
164  val S       = RW(4).withReset(0.U)
165  val U       = RW(3).withReset(0.U)
166  val EXECUTE = RW(2).withReset(0.U)
167  val STORE   = RW(1).withReset(0.U)
168  val LOAD    = RW(0).withReset(0.U)
169
170  def writeData(dmode: Bool, chainable: Bool): Mcontrol = {
171    val res = Wire(new Mcontrol)
172    res := this.asUInt
173    res.MASKMAX     := 0.U
174    res.SIZEHI      := 0.U
175    res.HIT         := false.B
176    res.SELECT      := this.EXECUTE.asBool && this.SELECT.asBool
177    res.TIMING      := false.B
178    res.SIZELO      := 0.U
179    res.ACTION      := this.ACTION.legalize(dmode).asUInt
180    res.CHAIN       := this.CHAIN.asBool && chainable
181    res.MATCH       := this.MATCH.legalize.asUInt
182    res
183  }
184  def isFetchTrigger: Bool = this.EXECUTE.asBool
185  def isMemAccTrigger: Bool = this.STORE || this.LOAD
186}
187
188
189object Tdata1Type extends CSREnum with WARLApply {
190  val None         = Value(0.U)
191  val Legacy       = Value(1.U)
192  val Mcontrol     = Value(2.U)
193  val Icount       = Value(3.U)
194  val Itrigger     = Value(4.U)
195  val Etrigger     = Value(5.U)
196  val Mcontrol6    = Value(6.U)
197  val Tmexttrigger = Value(7.U)
198  val Disabled     = Value(15.U)
199
200  override def isLegal(enumeration: CSREnumType): Bool = enumeration.isOneOf(Mcontrol)
201
202  override def legalize(enumeration: CSREnumType): CSREnumType = {
203    val res = WireInit(enumeration)
204    when(!enumeration.isLegal){
205      res := Disabled.asUInt
206    }
207    res
208  }
209}
210
211object TrigAction extends CSREnum with WARLApply {
212  val BreakpointExp = Value(0.U) // raise breakpoint exception
213  val DebugMode     = Value(1.U) // enter debug mode
214  val TraceOn       = Value(2.U)
215  val TraceOff      = Value(3.U)
216  val TraceNotify   = Value(4.U)
217
218  override def isLegal(enumeration: CSREnumType, dmode: Bool): Bool = enumeration.isOneOf(BreakpointExp) || enumeration.isOneOf(DebugMode) && dmode
219
220  override def legalize(enumeration: CSREnumType, dmode: Bool): CSREnumType = {
221    val res = WireInit(enumeration)
222    when(!enumeration.isLegal(dmode)){
223      res := BreakpointExp
224    }
225    res.asInstanceOf[CSREnumType]
226  }
227}
228
229object TrigMatch extends CSREnum with WARLApply {
230  val EQ        = Value(0.U)
231  val NAPOT     = Value(1.U)
232  val GE        = Value(2.U)
233  val LT        = Value(3.U)
234  val MASK_LO   = Value(4.U)
235  val MASK_HI   = Value(5.U)
236  val NE        = Value(8.U)  // not eq
237  val NNAPOT    = Value(9.U)  // not napot
238  val NMASK_LO  = Value(12.U) // not mask low
239  val NMASK_HI  = Value(13.U) // not mask high
240  def isRVSpecLegal(enumeration: CSREnumType) : Bool = enumeration.isOneOf(
241    EQ, NAPOT, GE, LT, MASK_LO, MASK_HI,
242    NE, NNAPOT, NMASK_LO, NMASK_HI,
243  )
244  override def isLegal(enumeration: CSREnumType): Bool = enumeration.isOneOf(EQ, GE, LT)
245
246  override def legalize(enumeration: CSREnumType): CSREnumType = {
247    val res = WireInit(enumeration)
248    when(!enumeration.isLegal){
249      res := EQ
250    }
251    res.asInstanceOf[CSREnumType]
252  }
253}
254
255
256// tdata2
257class Tdata2Bundle extends OneFieldBundle
258
259// Tinfo
260class TinfoBundle extends CSRBundle{
261  // Version isn't in version 0.13
262  val VERSION     = RO(31, 24).withReset(0.U)
263  // only support mcontrol
264  val MCONTROLEN  = RO(2).withReset(1.U)
265}
266
267class TcontrolBundle extends CSRBundle{
268  // M-mode previous trigger enable field
269  val MPTE = RW(7).withReset(0.U)
270  // M-mode trigger enable field
271  val MTE  = RW(3).withReset(0.U)
272}
273
274// Dscratch
275class DscratchBundle extends OneFieldBundle
276
277
278class DcsrBundle extends CSRBundle {
279  override val len: Int = 32
280  val DEBUGVER  = DcsrDebugVer(31, 28).withReset(DcsrDebugVer.Spec) // Debug implementation as it described in 0.13 draft // todo
281  // All ebreak Privileges are RW, instead of WARL, since XiangShan support U/S/VU/VS.
282  val EBREAKVS  =           RW(    17).withReset(0.U)
283  val EBREAKVU  =           RW(    16).withReset(0.U)
284  val EBREAKM   =           RW(    15).withReset(0.U)
285  val EBREAKS   =           RW(    13).withReset(0.U)
286  val EBREAKU   =           RW(    12).withReset(0.U)
287  // STEPIE is RW, instead of WARL, since XiangShan support interrupts being enabled single stepping.
288  val STEPIE    =           RW(    11).withReset(0.U)
289  val STOPCOUNT =           RO(    10).withReset(0.U) // Stop count updating has not been supported
290  val STOPTIME  =           RO(     9).withReset(0.U) // Stop time updating has not been supported
291  val CAUSE     =    DcsrCause( 8,  6).withReset(DcsrCause.None)
292  val V         =     VirtMode(     5).withReset(VirtMode.Off)
293  // MPRVEN is RW, instead of WARL, since XiangShan support use mstatus.mprv in debug mode
294  // Whether use mstatus.mprv
295  val MPRVEN    =           RW(     4).withReset(0.U)
296  // TODO: support non-maskable interrupt
297  val NMIP      =           RO(     3).withReset(0.U)
298  // MPRVEN is RW, instead of WARL, since XiangShan support use mstatus.mprv in debug mode
299  val STEP      =           RW(     2).withReset(0.U)
300  val PRV       =     PrivMode( 1,  0).withReset(PrivMode.M)
301}
302
303object DcsrDebugVer extends CSREnum with ROApply {
304  val None    = Value(0.U)
305  val Spec    = Value(4.U)
306  val Custom  = Value(15.U)
307}
308
309object DcsrCause extends CSREnum with ROApply {
310  val None         = Value(0.U)
311  val Ebreak       = Value(1.U)
312  val Trigger      = Value(2.U)
313  val Haltreq      = Value(3.U)
314  val Step         = Value(4.U)
315  val Resethaltreq = Value(5.U)
316  val Group        = Value(6.U)
317}
318
319trait HasTdataSink { self: CSRModule[_] =>
320  val tdataRead = IO(Input(new Bundle {
321    val tdata1 = UInt(XLEN.W) // Todo: check if use ireg bundle, and shrink the width
322    val tdata2 = UInt(XLEN.W)
323  }))
324}
325trait HasdebugModeBundle { self: CSRModule[_] =>
326  val debugMode = IO(Input(Bool()))
327  val chainable = IO(Input(Bool()))
328}
329
330/**
331 * debug Module MMIO Addr
332 */
333trait DebugMMIO {
334  implicit val p: Parameters
335
336  def debugMMIO = p(DebugModuleKey).get
337
338  def BASE = debugMMIO.baseAddress
339  def DebugEntry     = BASE + 0x800
340  def DebugException = BASE + 0x808
341  def HALTED         = BASE + 0x100
342  def GOING          = BASE + 0x104
343  def RESUMING       = BASE + 0x108
344  def EXCEPTION      = BASE + 0x10C
345  def WHERETO        = BASE + 0x300
346  def DATA           = BASE + 0x380
347  def IMPEBREAK      = DATA - 0x4
348  def PROGBUF        = DATA - 4 * debugMMIO.nProgramBufferWords
349  def ABSTRACT       = PROGBUF - 4 * (if(debugMMIO.atzero) 2 else 5)
350  def FLAGS          = BASE + 0x400
351}
352
353object TriggerUtil {
354  /**
355   * Check if chain vector is legal
356   * @param chainVec
357   * @param chainLen
358   * @return true.B if the max length of chain don't exceed the permitted length
359   */
360  def TriggerCheckChainLegal(chainVec: Seq[Bool], chainLen: Int): Bool = {
361    !ConsecutiveOnes(chainVec, chainLen)
362  }
363
364  /**
365   * Generate Trigger action
366   * @return triggerAction return
367   * @param  triggerCanFireVec
368   * @param  actionVec tdata.action
369   * @param  triggerCanRaiseBpExp from csr
370   */
371  def triggerActionGen(triggerAction: UInt, triggerCanFireVec: Vec[Bool], actionVec: Vec[UInt], triggerCanRaiseBpExp: Bool): Unit = {
372    // More than one triggers can hit at the same time, but only fire one.
373    // We select the first hit trigger to fire.
374    val hasTriggerFire    = triggerCanFireVec.asUInt.orR
375    val triggerFireOH     = PriorityEncoderOH(triggerCanFireVec)
376    val triggerFireAction = PriorityMux(triggerFireOH, actionVec).asUInt
377    val actionIsBPExp     = hasTriggerFire && (triggerFireAction === TrigAction.BreakpointExp.asUInt)
378    val actionIsDmode     = hasTriggerFire && (triggerFireAction === TrigAction.DebugMode.asUInt)
379    val breakPointExp     = actionIsBPExp && triggerCanRaiseBpExp
380
381    // todo: add more for trace
382    triggerAction := MuxCase(TriggerAction.None, Seq(
383      breakPointExp -> TriggerAction.BreakpointExp,
384      actionIsDmode -> TriggerAction.DebugMode,
385    ))
386  }
387}