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