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