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