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