xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/Debug.scala (revision b03c55a5df5dc8793cb44b42dd60141566e57e78)
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.backend.fu.util.SdtrigExt
10import xiangshan._
11
12class Debug(implicit val p: Parameters) extends Module with HasXSParameter {
13  val io = IO(new DebugIO)
14
15  private val trapInfo        = io.in.trapInfo
16  private val hasTrap         = trapInfo.valid
17  private val trapIsInterrupt = trapInfo.bits.isInterrupt
18  private val intrVec         = trapInfo.bits.intrVec
19  private val trapVec         = trapInfo.bits.trapVec
20  private val singleStep      = trapInfo.bits.singleStep
21  private val triggerCf       = io.in.trapInfo.bits.triggerCf
22
23  private val privState = io.in.privState
24  private val debugMode = io.in.debugMode
25
26  private val dcsr = io.in.dcsr
27  private val tcontrol = io.in.tcontrol
28  private val tselect = io.in.tselect
29  private val tdata1Selected = io.in.tdata1Selected
30  private val tdata2Selected = io.in.tdata2Selected
31  private val tdata1Vec = io.in.tdata1Vec
32
33  private val tdata1Update  = io.in.tdata1Update
34  private val tdata2Update  = io.in.tdata2Update
35  private val tdata1Wdata   = io.in.tdata1Wdata
36
37  /**
38   * ways to entry Dmode:
39   *    1. debug intr(from external debug module)
40   *    2. ebreak inst in nonDmode
41   *    3. trigger fire in nonDmode
42   *    4. single step(debug module set dcsr.step before hart resume)
43   */
44  // debug_intr
45  val hasIntr = hasTrap && trapIsInterrupt
46  val hasDebugIntr = hasIntr && intrVec(CSRConst.IRQ_DEBUG)
47
48  // debug_exception_ebreak
49  val hasExp = hasTrap && !trapIsInterrupt
50  val breakPoint = trapVec(ExceptionNO.breakPoint).asBool
51  val hasBreakPoint = hasExp && breakPoint
52  val ebreakEnterDebugMode =
53    (privState.isModeM && dcsr.EBREAKM.asBool) ||
54      (privState.isModeHS && dcsr.EBREAKS.asBool) ||
55      (privState.isModeHU && dcsr.EBREAKU.asBool) ||
56      (privState.isModeVS && dcsr.EBREAKVS.asBool) ||
57      (privState.isModeVU && dcsr.EBREAKVU.asBool)
58  val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode
59
60  // debug_exception_trigger
61  val triggerFrontendHitVec = triggerCf.frontendHit
62  val triggerMemHitVec = triggerCf.backendHit
63  val triggerHitVec = triggerFrontendHitVec.asUInt | triggerMemHitVec.asUInt // Todo: update mcontrol.hit
64  val triggerFrontendCanFireVec = triggerCf.frontendCanFire.asUInt
65  val triggerMemCanFireVec = triggerCf.backendCanFire.asUInt
66  val triggerCanFireVec = triggerFrontendCanFireVec | triggerMemCanFireVec
67
68  val mcontrolWireVec = tdata1Vec.map{ mod => {
69    val mcontrolWire = Wire(new Mcontrol)
70    mcontrolWire := mod.DATA.asUInt
71    mcontrolWire
72  }}
73
74  // More than one triggers can hit at the same time, but only fire one
75  // We select the first hit trigger to fire
76  val triggerCanRaiseBpExp = Mux(privState.isModeM && !debugMode, tcontrol.MTE.asBool, true.B)
77  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
78  val triggerFireAction = PriorityMux(triggerFireOH, tdata1Vec.map(_.getTriggerAction)).asUInt
79  val hasTriggerFire = hasExp && triggerCf.canFire
80  val hasDebugTriggerException = hasTriggerFire && (triggerFireAction === TrigAction.DebugMode.asUInt)
81  val triggerCanFire = hasTriggerFire && (triggerFireAction === TrigAction.BreakpointExp.asUInt) && triggerCanRaiseBpExp // todo: Should trigger be fire in dmode?
82
83  // debug_exception_single
84  val hasSingleStep = hasExp && singleStep
85
86  val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep
87  val hasDebugTrap = hasDebugException || hasDebugIntr
88
89  val tselect1H = UIntToOH(tselect.asUInt, TriggerNum).asBools
90  val chainVec = mcontrolWireVec.map(_.CHAIN.asBool)
91  val newTriggerChainVec = tselect1H.zip(chainVec).map{case(a, b) => a | b}
92  val newTriggerChainIsLegal = TriggerUtil.TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength)
93
94  val triggerUpdate = tdata1Update || tdata2Update
95
96  val mcontrolWdata = Wire(new Mcontrol)
97  mcontrolWdata := tdata1Wdata.DATA.asUInt
98  val tdata1TypeWdata = tdata1Wdata.TYPE
99
100  val mcontrolSelected = Wire(new Mcontrol)
101  mcontrolSelected := tdata1Selected.DATA.asUInt
102
103  val frontendTriggerUpdate =
104    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isFetchTrigger ||
105      mcontrolSelected.isFetchTrigger && triggerUpdate
106
107  val memTriggerUpdate =
108    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isMemAccTrigger ||
109      mcontrolSelected.isMemAccTrigger && triggerUpdate
110
111  val triggerEnableVec = tdata1Vec.zip(mcontrolWireVec).map { case(tdata1, mcontrol) =>
112    tdata1.TYPE.isLegal && (
113      mcontrol.M && privState.isModeM  ||
114        mcontrol.S && privState.isModeHS ||
115        mcontrol.U && privState.isModeHU)
116  }
117
118  val fetchTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
119    case (tEnable, mod) => tEnable && mod.isFetchTrigger
120  }
121  val memAccTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
122    case (tEnable, mod) => tEnable && mod.isMemAccTrigger
123  }
124
125  io.out.frontendTrigger.tUpdate.valid       := RegNext(RegNext(frontendTriggerUpdate))
126  io.out.frontendTrigger.tUpdate.bits.addr   := tselect.asUInt
127  io.out.frontendTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
128  io.out.frontendTrigger.tEnableVec          := fetchTriggerEnableVec
129
130  io.out.memTrigger.tUpdate.valid            := RegNext(RegNext(memTriggerUpdate))
131  io.out.memTrigger.tUpdate.bits.addr        := tselect.asUInt
132  io.out.memTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
133  io.out.memTrigger.tEnableVec               := memAccTriggerEnableVec
134  io.out.memTrigger.triggerCanRaiseBpExp     := triggerCanRaiseBpExp
135
136  io.out.triggerFrontendChange  := frontendTriggerUpdate
137  io.out.newTriggerChainIsLegal := newTriggerChainIsLegal
138
139  io.out.hasDebugTrap            := hasDebugTrap
140  io.out.hasDebugIntr            := hasDebugIntr
141  io.out.triggerCanFire          := triggerCanFire
142  io.out.hasSingleStep           := hasSingleStep
143  io.out.hasTriggerFire          := hasTriggerFire
144  io.out.hasDebugEbreakException := hasDebugEbreakException
145  io.out.breakPoint              := breakPoint
146}
147
148class DebugIO(implicit val p: Parameters) extends Bundle with HasXSParameter {
149  val in = Input(new Bundle {
150    val trapInfo = ValidIO(new Bundle {
151      val trapVec = UInt(64.W)
152      val intrVec = UInt(64.W)
153      val isInterrupt = Bool()
154      val singleStep = Bool()
155      val triggerCf = new TriggerCf
156    })
157
158    val privState = new PrivState
159    val debugMode = Bool()
160
161    val dcsr = new DcsrBundle
162    val tcontrol = new TcontrolBundle
163    val tselect = new TselectBundle(TriggerNum)
164    val tdata1Selected = new Tdata1Bundle
165    val tdata2Selected = new Tdata2Bundle
166    val tdata1Vec = Vec(TriggerNum, new Tdata1Bundle)
167
168    val tdata1Update = Bool()
169    val tdata2Update = Bool()
170    val tdata1Wdata = new Tdata1Bundle
171  })
172
173  val out = Output(new Bundle{
174    // trigger
175    val triggerFrontendChange = Bool()
176    val newTriggerChainIsLegal = Bool()
177    val memTrigger = new MemTdataDistributeIO()
178    val frontendTrigger = new FrontendTdataDistributeIO()
179
180    val hasDebugTrap = Bool()
181    val hasDebugIntr = Bool()
182    val hasSingleStep = Bool()
183    val hasTriggerFire = Bool()
184    val triggerCanFire = Bool()
185    val hasDebugEbreakException = Bool()
186    val breakPoint = Bool()
187  })
188}
189
190class CsrTriggerBundle(implicit val p: Parameters) extends Bundle with HasXSParameter {
191  val tdataVec = Vec(TriggerNum, new MatchTriggerIO)
192  val tEnableVec = Vec(TriggerNum, Bool())
193  val triggerCanRaiseBpExp = Bool()
194}
195class StoreTrigger(implicit val p: Parameters)extends Module with HasXSParameter with SdtrigExt {
196  val io = IO(new Bundle(){
197    val fromCsrTrigger = Input(new CsrTriggerBundle)
198
199    val fromStore = Input(new Bundle {
200      val vaddr = UInt(VAddrBits.W)
201    })
202
203    val toStore = Output(new Bundle{
204      val triggerHitVec = Vec(TriggerNum,  Bool())
205      val triggerCanFireVec = Vec(TriggerNum, Bool())
206      val breakPointExp = Bool()
207    })
208  })
209  val tdataVec      = io.fromCsrTrigger.tdataVec
210  val tEnableVec    = io.fromCsrTrigger.tEnableVec
211  val triggerCanRaiseBpExp = io.fromCsrTrigger.triggerCanRaiseBpExp
212  val vaddr = io.fromStore.vaddr
213
214  val triggerTimingVec = VecInit(tdataVec.map(_.timing))
215  val triggerChainVec = VecInit(tdataVec.map(_.chain))
216
217  val triggerHitVec = WireInit(VecInit(Seq.fill(TriggerNum)(false.B)))
218  val triggerCanFireVec = WireInit(VecInit(Seq.fill(TriggerNum)(false.B)))
219
220  for (i <- 0 until TriggerNum) {
221    triggerHitVec(i) := !tdataVec(i).select && TriggerCmp(
222      vaddr,
223      tdataVec(i).tdata2,
224      tdataVec(i).matchType,
225      tEnableVec(i) && tdataVec(i).store
226    )
227  }
228  TriggerCheckCanFire(TriggerNum, triggerCanFireVec, triggerHitVec, triggerTimingVec, triggerChainVec)
229
230  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
231  val triggerFireAction = PriorityMux(triggerFireOH, tdataVec.map(_.action)).asUInt
232  val breakPointExp = ((triggerFireAction === TrigAction.BreakpointExp.asUInt) && triggerCanRaiseBpExp ||
233    (triggerFireAction === TrigAction.DebugMode.asUInt)) && triggerCanFireVec.asUInt.orR
234
235  io.toStore.triggerHitVec     := triggerHitVec
236  io.toStore.triggerCanFireVec := triggerCanFireVec
237  io.toStore.breakPointExp     := breakPointExp
238}