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