xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/Debug.scala (revision 4ac3bf33570163c435a73e5b5f246c01ce5d5172)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import org.chipsalliance.cde.config.Parameters
6
7import xiangshan.backend.fu.NewCSR.CSRBundles.PrivState
8import xiangshan.backend.fu.util.CSRConst
9import xiangshan._
10
11class Debug(implicit val p: Parameters) extends Module with HasXSParameter {
12  val io = IO(new DebugIO)
13
14  private val trapInfo        = io.in.trapInfo
15  private val hasTrap         = trapInfo.valid
16  private val trapIsInterrupt = trapInfo.bits.isInterrupt
17  private val intrVec         = trapInfo.bits.intrVec
18  private val trapVec         = trapInfo.bits.trapVec
19  private val singleStep      = trapInfo.bits.singleStep
20  private val triggerCf       = io.in.trapInfo.bits.triggerCf
21
22  private val privState = io.in.privState
23  private val debugMode = io.in.debugMode
24
25  private val dcsr = io.in.dcsr
26  private val tcontrol = io.in.tcontrol
27  private val tselect = io.in.tselect
28  private val tdata1Selected = io.in.tdata1Selected
29  private val tdata2Selected = io.in.tdata2Selected
30  private val tdata1Vec = io.in.tdata1Vec
31
32  private val tdata1Update  = io.in.tdata1Update
33  private val tdata2Update  = io.in.tdata2Update
34  private val tdata1Wdata   = io.in.tdata1Wdata
35
36  /**
37   * ways to entry Dmode:
38   *    1. debug intr(from external debug module)
39   *    2. ebreak inst in nonDmode
40   *    3. trigger fire in nonDmode
41   *    4. single step(debug module set dcsr.step before hart resume)
42   */
43  // debug_intr
44  val hasIntr = hasTrap && trapIsInterrupt
45  val hasDebugIntr = hasIntr && intrVec(CSRConst.IRQ_DEBUG)
46
47  // debug_exception_ebreak
48  val hasExp = hasTrap && !trapIsInterrupt
49  val breakPoint = trapVec(ExceptionNO.breakPoint).asBool
50  val hasBreakPoint = hasExp && breakPoint
51  val ebreakEnterDebugMode =
52    (privState.isModeM && dcsr.EBREAKM.asBool) ||
53      (privState.isModeHS && dcsr.EBREAKS.asBool) ||
54      (privState.isModeHU && dcsr.EBREAKU.asBool) ||
55      (privState.isModeVS && dcsr.EBREAKVS.asBool) ||
56      (privState.isModeVU && dcsr.EBREAKVU.asBool)
57  val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode
58
59  // debug_exception_trigger
60  val triggerFrontendHitVec = triggerCf.frontendHit
61  val triggerMemHitVec = triggerCf.backendHit
62  val triggerHitVec = triggerFrontendHitVec.asUInt | triggerMemHitVec.asUInt // Todo: update mcontrol.hit
63  val triggerFrontendCanFireVec = triggerCf.frontendCanFire.asUInt
64  val triggerMemCanFireVec = triggerCf.backendCanFire.asUInt
65  val triggerCanFireVec = triggerFrontendCanFireVec | triggerMemCanFireVec
66
67  val mcontrolWireVec = tdata1Vec.map{ mod => {
68    val mcontrolWire = Wire(new Mcontrol)
69    mcontrolWire := mod.DATA.asUInt
70    mcontrolWire
71  }}
72
73  // More than one triggers can hit at the same time, but only fire one
74  // We select the first hit trigger to fire
75  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
76  val triggerFireAction = PriorityMux(triggerFireOH, tdata1Vec.map(_.getTriggerAction)).asUInt
77  val hasTriggerFire = hasExp && triggerCf.canFire
78  val hasDebugTriggerException = hasTriggerFire && (triggerFireAction === TrigAction.DebugMode.asUInt)
79  val triggerCanFire = hasTriggerFire && (triggerFireAction === TrigAction.BreakpointExp.asUInt) &&
80    Mux(privState.isModeM && !debugMode, tcontrol.MTE.asBool, true.B) // todo: Should trigger be fire in dmode?
81
82  // debug_exception_single
83  val hasSingleStep = hasExp && singleStep
84
85  val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep
86  val hasDebugTrap = hasDebugException || hasDebugIntr
87
88  val tselect1H = UIntToOH(tselect.asUInt, TriggerNum).asBools
89  val chainVec = mcontrolWireVec.map(_.CHAIN.asBool)
90  val newTriggerChainVec = tselect1H.zip(chainVec).map{case(a, b) => a | b}
91  val newTriggerChainIsLegal = TriggerUtil.TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength)
92
93  val triggerUpdate = tdata1Update || tdata2Update
94
95  val mcontrolWdata = Wire(new Mcontrol)
96  mcontrolWdata := tdata1Wdata.DATA.asUInt
97  val tdata1TypeWdata = tdata1Wdata.TYPE
98
99  val mcontrolSelected = Wire(new Mcontrol)
100  mcontrolSelected := tdata1Selected.DATA.asUInt
101
102  val frontendTriggerUpdate =
103    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isFetchTrigger ||
104      mcontrolSelected.isFetchTrigger && triggerUpdate
105
106  val memTriggerUpdate =
107    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isMemAccTrigger ||
108      mcontrolSelected.isMemAccTrigger && triggerUpdate
109
110  val triggerEnableVec = tdata1Vec.zip(mcontrolWireVec).map { case(tdata1, mcontrol) =>
111    tdata1.TYPE.isLegal && (
112      mcontrol.M && privState.isModeM  ||
113        mcontrol.S && privState.isModeHS ||
114        mcontrol.U && privState.isModeHU)
115  }
116
117  val fetchTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
118    case (tEnable, mod) => tEnable && mod.isFetchTrigger
119  }
120  val memAccTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
121    case (tEnable, mod) => tEnable && mod.isMemAccTrigger
122  }
123
124  io.out.frontendTrigger.tUpdate.valid       := RegNext(RegNext(frontendTriggerUpdate))
125  io.out.frontendTrigger.tUpdate.bits.addr   := tselect.asUInt
126  io.out.frontendTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
127  io.out.frontendTrigger.tEnableVec          := fetchTriggerEnableVec
128  io.out.memTrigger.tUpdate.valid            := RegNext(RegNext(memTriggerUpdate))
129  io.out.memTrigger.tUpdate.bits.addr        := tselect.asUInt
130  io.out.memTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
131  io.out.memTrigger.tEnableVec               := memAccTriggerEnableVec
132
133  io.out.triggerFrontendChange  := frontendTriggerUpdate
134  io.out.newTriggerChainIsLegal := newTriggerChainIsLegal
135
136  io.out.hasDebugTrap            := hasDebugTrap
137  io.out.hasDebugIntr            := hasDebugIntr
138  io.out.triggerCanFire          := triggerCanFire
139  io.out.hasSingleStep           := hasSingleStep
140  io.out.hasTriggerFire          := hasTriggerFire
141  io.out.hasDebugEbreakException := hasDebugEbreakException
142  io.out.breakPoint              := breakPoint
143}
144
145class DebugIO(implicit val p: Parameters) extends Bundle with HasXSParameter {
146  val in = Input(new Bundle {
147    val trapInfo = ValidIO(new Bundle {
148      val trapVec = UInt(64.W)
149      val intrVec = UInt(64.W)
150      val isInterrupt = Bool()
151      val singleStep = Bool()
152      val triggerCf = new TriggerCf
153    })
154
155    val privState = new PrivState
156    val debugMode = Bool()
157
158    val dcsr = new DcsrBundle
159    val tcontrol = new TcontrolBundle
160    val tselect = new TselectBundle(TriggerNum)
161    val tdata1Selected = new Tdata1Bundle
162    val tdata2Selected = new Tdata2Bundle
163    val tdata1Vec = Vec(TriggerNum, new Tdata1Bundle)
164
165    val tdata1Update = Bool()
166    val tdata2Update = Bool()
167    val tdata1Wdata = new Tdata1Bundle
168  })
169
170  val out = Output(new Bundle{
171    // trigger
172    val triggerFrontendChange = Bool()
173    val newTriggerChainIsLegal = Bool()
174    val memTrigger = new MemTdataDistributeIO()
175    val frontendTrigger = new FrontendTdataDistributeIO()
176
177    val hasDebugTrap = Bool()
178    val hasDebugIntr = Bool()
179    val hasSingleStep = Bool()
180    val hasTriggerFire = Bool()
181    val triggerCanFire = Bool()
182    val hasDebugEbreakException = Bool()
183    val breakPoint = Bool()
184  })
185}