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