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