xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala (revision 6306fe335c2bca9aa17b8975c11e0e6116b494fd)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import freechips.rocketchip.rocket.CSRs
6import difftest._
7import org.chipsalliance.cde.config.Parameters
8import top.{ArgParser, Generator}
9import utility.{DataHoldBypass, SignExt, ZeroExt}
10import utils.OptionWrapper
11import xiangshan.backend.fu.NewCSR.CSRBundles.{CSRCustomState, PrivState, RobCommitCSR}
12import xiangshan.backend.fu.NewCSR.CSRDefines.{ContextStatus, PrivMode, SatpMode, VirtMode}
13import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._
14import xiangshan.backend.fu.NewCSR.CSREvents.{CSREvents, DretEventSinkBundle, EventUpdatePrivStateOutput, MretEventSinkBundle, SretEventSinkBundle, TrapEntryDEventSinkBundle, TrapEntryEventInput, TrapEntryHSEventSinkBundle, TrapEntryMEventSinkBundle, TrapEntryVSEventSinkBundle}
15import xiangshan.backend.fu.fpu.Bundles.Frm
16import xiangshan.backend.fu.vector.Bundles.{Vl, Vstart, Vxrm, Vxsat}
17import xiangshan.{FrontendTdataDistributeIO, HasXSParameter, MemTdataDistributeIO, XSCoreParamsKey, XSTileKey}
18import xiangshan._
19import xiangshan.backend.fu.util.CSRConst
20
21import scala.collection.immutable.SeqMap
22
23object CSRConfig {
24  final val GEILEN = 63
25
26  final val ASIDLEN = 16 // the length of ASID of XS implementation
27
28  final val ASIDMAX = 16 // the max value of ASIDLEN defined by spec
29
30  final val HIIDWidth = 12 // support Hvictl[27:16](IID)
31
32  final val VMIDLEN = 14 // the length of VMID of XS implementation
33
34  final val VMIDMAX = 14 // the max value of VMIDLEN defined by spec
35
36  // the width of VGEIN
37  final val VGEINWidth = 6
38
39  final val VaddrMaxWidth = 41 // only Sv39 and Sv39x4
40
41  final val XLEN = 64 // Todo: use XSParams
42
43  final val VLEN = 128
44
45  // Since we need macro to compute the width of CSR field, the input of macro should be the value that can be computed
46  // at compile time. The log2Up function cannot be used as meta-programming function, so we use litral value here
47  // log2Up(128 + 1), hold 0~128
48  final val VlWidth = 8
49
50  final val PAddrWidth = 36
51
52  final val AddrWidthInPage = 12
53
54  final val PMPAddrWidth = 36
55
56  final val PMPOffBits = 2
57
58  final val PMPAddrBits = PMPAddrWidth - PMPOffBits
59
60  // trigger
61  final val triggerNum    = 4     // Todo: use XSParams
62  final val tselectWidth  = 2     // log2Up(triggerNum)
63}
64
65class NewCSR(implicit val p: Parameters) extends Module
66  with HasXSParameter
67  with MachineLevel
68  with SupervisorLevel
69  with HypervisorLevel
70  with VirtualSupervisorLevel
71  with Unprivileged
72  with CSRAIA
73  with HasExternalInterruptBundle
74  with SupervisorMachineAliasConnect
75  with CSREvents
76  with DebugLevel
77  with CSRCustom
78  with CSRPMP
79{
80
81  import CSRConfig._
82
83  val io = IO(new Bundle {
84    val fromTop = Input(new Bundle {
85      val hartId = UInt(hartIdLen.W)
86    })
87    val in = Input(new Bundle {
88      val wen = Bool()
89      val ren = Bool()
90      val addr = UInt(12.W)
91      val wdata = UInt(64.W)
92    })
93    val fromMem = Input(new Bundle {
94      val excpVA  = UInt(VaddrMaxWidth.W)
95      val excpGPA = UInt(VaddrMaxWidth.W) // Todo: use guest physical address width
96    })
97    val fromRob = Input(new Bundle {
98      val trap = ValidIO(new Bundle {
99        val pc = UInt(VaddrMaxWidth.W)
100        val instr = UInt(32.W)
101        val trapVec = UInt(64.W)
102        val singleStep = Bool()
103        val triggerCf = new TriggerCf
104        val crossPageIPFFix = Bool()
105        val isInterrupt = Bool()
106      })
107      val commit = Input(new RobCommitCSR)
108    })
109    val mret = Input(Bool())
110    val sret = Input(Bool())
111    val dret = Input(Bool())
112    val wfi  = Input(Bool())
113    val ebreak = Input(Bool())
114
115    val out = Output(new Bundle {
116      val EX_II = Bool()
117      val EX_VI = Bool()
118      val flushPipe = Bool()
119      val rData = UInt(64.W)
120      val targetPc = UInt(VaddrMaxWidth.W)
121      val regOut = UInt(64.W)
122      val privState = new PrivState
123      val interrupt = Bool()
124      val wfiEvent = Bool()
125      val tvm = Bool()
126      val vtvm = Bool()
127      // fp
128      val fpState = new Bundle {
129        val off = Bool()
130        val frm = Frm()
131      }
132      // vec
133      val vecState = new Bundle {
134        val vstart = Vstart()
135        val vxsat = Vxsat()
136        val vxrm = Vxrm()
137        val vcsr = UInt(XLEN.W)
138        val vl = Vl()
139        val vtype = UInt(XLEN.W)
140        val vlenb = UInt(XLEN.W)
141        val off = Bool()
142      }
143      // perf
144      val isPerfCnt = Bool()
145      // debug
146      val debugMode = Bool()
147      val singleStepFlag = Bool()
148      // trigger
149      val frontendTrigger = new FrontendTdataDistributeIO()
150      val memTrigger = new MemTdataDistributeIO()
151      // custom
152      val custom = new CSRCustomState
153    })
154    // tlb
155    val tlb = Output(new Bundle {
156      val satpASIDChanged = Bool()
157      val vsatpASIDChanged = Bool()
158      val hgatpVMIDChanged = Bool()
159      val satp = new SatpBundle
160      val vsatp = new SatpBundle
161      val hgatp = new HgatpBundle
162      val mxr = Bool()
163      val sum = Bool()
164      val vmxr = Bool()
165      val vsum = Bool()
166      val spvp = Bool()
167      val imode = UInt(2.W)
168      val dmode = UInt(2.W)
169    })
170  })
171
172  val toAIA   = IO(Output(new CSRToAIABundle))
173  val fromAIA = IO(Flipped(Output(new AIAToCSRBundle)))
174
175  dontTouch(toAIA)
176  dontTouch(fromAIA)
177
178  val wen   = io.in.wen
179  val addr  = io.in.addr
180  val wdata = io.in.wdata
181
182  val ren   = io.in.ren
183  val raddr = io.in.addr
184
185  val hasTrap = io.fromRob.trap.valid
186  val trapVec = io.fromRob.trap.bits.trapVec
187  val trapPC = io.fromRob.trap.bits.pc
188  val trapIsInterrupt = io.fromRob.trap.bits.isInterrupt
189  val trapIsCrossPageIPF = io.fromRob.trap.bits.crossPageIPFFix
190  val triggerCf = io.fromRob.trap.bits.triggerCf
191
192  // debug_intrrupt
193  val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable
194  val debugIntr = platformIRP.debugIP && debugIntrEnable
195
196  // CSR Privilege State
197  val PRVM = RegInit(PrivMode(0), PrivMode.M)
198  val V = RegInit(VirtMode(0), VirtMode.Off)
199  val debugMode = RegInit(false.B)
200
201  private val privState = Wire(new PrivState)
202  privState.PRVM := PRVM
203  privState.V := V
204
205  private val isModeM              = privState.isModeM
206  private val (isModeHS, isModeHU) = (privState.isModeHS, privState.isModeHU)
207  private val (isModeVS, isModeVU) = (privState.isModeVS, privState.isModeVU)
208
209  val permitMod = Module(new CSRPermitModule)
210
211  private val wenLegal = permitMod.io.out.hasLegalWen
212
213  val legalSret = permitMod.io.out.hasLegalSret
214  val legalMret = permitMod.io.out.hasLegalMret
215  val isDret = io.dret // Todo: check permission
216  val isWfi  = permitMod.io.out.hasLegalWfi
217
218  var csrRwMap: SeqMap[Int, (CSRAddrWriteBundle[_], Data)] =
219    machineLevelCSRMap ++
220    supervisorLevelCSRMap ++
221    hypervisorCSRMap ++
222    virtualSupervisorCSRMap ++
223    unprivilegedCSRMap ++
224    debugCSRMap ++
225    aiaCSRMap ++
226    customCSRMap ++
227    pmpCSRMap
228
229  val csrMods: Seq[CSRModule[_]] =
230    machineLevelCSRMods ++
231    supervisorLevelCSRMods ++
232    hypervisorCSRMods ++
233    virtualSupervisorCSRMods ++
234    unprivilegedCSRMods ++
235    debugCSRMods ++
236    aiaCSRMods ++
237    customCSRMods ++
238    pmpCSRMods
239
240  var csrOutMap: SeqMap[Int, UInt] =
241    machineLevelCSROutMap ++
242    supervisorLevelCSROutMap ++
243    hypervisorCSROutMap ++
244    virtualSupervisorCSROutMap ++
245    unprivilegedCSROutMap ++
246    debugCSROutMap ++
247    aiaCSROutMap ++
248    customCSROutMap ++
249    pmpCSROutMap
250
251  // interrupt
252  val intrMod = Module(new InterruptFilter)
253  intrMod.io.in.privState := privState
254  intrMod.io.in.mstatusMIE := mstatus.regOut.MIE.asBool
255  intrMod.io.in.sstatusSIE := mstatus.regOut.SIE.asBool
256  intrMod.io.in.vsstatusSIE := vsstatus.regOut.SIE.asBool
257  intrMod.io.in.mip := mip.rdata.asUInt
258  intrMod.io.in.mie := mie.rdata.asUInt
259  intrMod.io.in.mideleg := mideleg.rdata.asUInt
260  intrMod.io.in.sip := sip.rdata.asUInt
261  intrMod.io.in.sie := sie.rdata.asUInt
262  intrMod.io.in.hip := hip.rdata.asUInt
263  intrMod.io.in.hie := hie.rdata.asUInt
264  intrMod.io.in.hideleg := hideleg.rdata.asUInt
265  intrMod.io.in.vsip := vsip.rdata.asUInt
266  intrMod.io.in.vsie := vsie.rdata.asUInt
267  intrMod.io.in.hvictl := hvictl.rdata.asUInt
268  intrMod.io.in.hstatus := hstatus.rdata.asUInt
269  intrMod.io.in.mtopei := mtopei.rdata.asUInt
270  intrMod.io.in.stopei := stopei.rdata.asUInt
271  intrMod.io.in.vstopei := vstopei.rdata.asUInt
272  intrMod.io.in.hviprio1 := hviprio1.rdata.asUInt
273  intrMod.io.in.hviprio2 := hviprio2.rdata.asUInt
274  intrMod.io.in.miprios := Cat(miregiprios.map(_.rdata).reverse)
275  intrMod.io.in.hsiprios := Cat(siregiprios.map(_.rdata).reverse)
276  // val disableInterrupt = debugMode || (dcsr.rdata.STEP.asBool && !dcsr.rdata.STEPIE.asBool)
277  // val intrVec = Cat(debugIntr && !debugMode, mie.rdata.asUInt(11, 0) & mip.rdata.asUInt & intrVecEnable.asUInt) // Todo: asUInt(11,0) is ok?
278
279  val intrVec = RegEnable(intrMod.io.out.interruptVec.bits, 0.U, intrMod.io.out.interruptVec.valid)
280
281  val trapHandleMod = Module(new TrapHandleModule)
282
283  trapHandleMod.io.in.trapInfo.valid := hasTrap
284  trapHandleMod.io.in.trapInfo.bits.trapVec := trapVec.asUInt
285  trapHandleMod.io.in.trapInfo.bits.intrVec := intrVec
286  trapHandleMod.io.in.trapInfo.bits.isInterrupt := trapIsInterrupt
287  trapHandleMod.io.in.privState := privState
288  trapHandleMod.io.in.mideleg := mideleg.regOut
289  trapHandleMod.io.in.medeleg := medeleg.regOut
290  trapHandleMod.io.in.hideleg := hideleg.regOut
291  trapHandleMod.io.in.hedeleg := hedeleg.regOut
292  trapHandleMod.io.in.mtvec := mtvec.regOut
293  trapHandleMod.io.in.stvec := stvec.regOut
294  trapHandleMod.io.in.vstvec := vstvec.regOut
295
296  val entryPrivState = trapHandleMod.io.out.entryPrivState
297
298  // PMP
299  val pmpEntryMod = Module(new PMPEntryHandleModule)
300  pmpEntryMod.io.in.pmpCfg  := cfgs.map(_.regOut.asInstanceOf[PMPCfgBundle])
301  pmpEntryMod.io.in.pmpAddr := pmpaddr.map(_.regOut.asInstanceOf[PMPAddrBundle])
302  pmpEntryMod.io.in.ren   := ren
303  pmpEntryMod.io.in.wen   := wen
304  pmpEntryMod.io.in.addr  := addr
305  pmpEntryMod.io.in.wdata := wdata
306
307  for ((id, (wBundle, _)) <- csrRwMap) {
308    if (vsMapS.contains(id)) {
309      // VS access CSR by S: privState.isModeVS && addrMappedToVS === sMapVS(id).U
310      wBundle.wen := wenLegal && ((isModeVS && addr === vsMapS(id).U) || (!isModeVS && addr === id.U))
311      wBundle.wdata := wdata
312    } else if (sMapVS.contains(id)) {
313      wBundle.wen := wenLegal && !isModeVS && addr === id.U
314      wBundle.wdata := wdata
315    } else {
316      wBundle.wen := wenLegal && addr === id.U
317      wBundle.wdata := wdata
318    }
319  }
320
321  // Todo: support set dirty only when fcsr has changed
322  private val writeFpState = wenLegal && Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _)
323  private val writeVecState = wenLegal && Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _)
324
325  permitMod.io.in.csrAccess.ren := ren
326  permitMod.io.in.csrAccess.wen := wen
327  permitMod.io.in.csrAccess.addr := addr
328
329
330  permitMod.io.in.privState := privState
331  permitMod.io.in.debugMode := debugMode
332
333  permitMod.io.in.mret := io.mret
334  permitMod.io.in.sret := io.sret
335  permitMod.io.in.wfi  := io.wfi
336
337  permitMod.io.in.status.tsr := mstatus.regOut.TSR.asBool
338  permitMod.io.in.status.vtsr := hstatus.regOut.VTSR.asBool
339
340  permitMod.io.in.status.tw := mstatus.regOut.TW.asBool
341  permitMod.io.in.status.vtw := hstatus.regOut.VTW.asBool
342
343  permitMod.io.in.status.tvm  := mstatus.regOut.TVM.asBool
344  permitMod.io.in.status.vtvm := hstatus.regOut.VTVM.asBool
345
346  miregiprios.foreach { mod =>
347    mod.w.wen := (addr === mireg.addr.U) && (miselect.regOut.ALL.asUInt === mod.addr.U)
348    mod.w.wdata := wdata
349  }
350
351  siregiprios.foreach { mod =>
352    mod.w.wen := (addr === sireg.addr.U) && (siselect.regOut.ALL.asUInt === mod.addr.U)
353    mod.w.wdata := wdata
354  }
355
356  mhartid.hartid := this.io.fromTop.hartId
357
358  cfgs.zipWithIndex.foreach { case (mod, i) =>
359    mod.w.wen := wen && (addr === (0x3A0 + i / 8 * 2).U)
360    mod.w.wdata := pmpEntryMod.io.out.pmpCfgWData(8*((i%8)+1)-1,8*(i%8))
361  }
362
363  pmpaddr.zipWithIndex.foreach{ case(mod, i) =>
364    mod.w.wen := wen && (addr === (0x3B0 + i).U)
365    mod.w.wdata := pmpEntryMod.io.out.pmpAddrWData(i)
366  }
367
368  csrMods.foreach { mod =>
369    mod match {
370      case m: HypervisorBundle =>
371        m.hstatus := hstatus.regOut
372        m.hvip := hvip.regOut
373        m.hideleg := hideleg.regOut
374        m.hedeleg := hedeleg.regOut
375        m.hgeip := hgeip.regOut
376        m.hgeie := hgeie.regOut
377        m.hip := hip.regOut
378        m.hie := hie.regOut
379      case _ =>
380    }
381    mod match {
382      case m: HasMachineInterruptBundle =>
383        m.mvien := mvien.regOut
384        m.mvip := mvip.regOut
385        m.mip := mip.regOut
386        m.mie := mie.regOut
387      case _ =>
388    }
389    mod match {
390      case m: HasMachineDelegBundle =>
391        m.mideleg := mideleg.regOut
392        m.medeleg := medeleg.regOut
393      case _ =>
394    }
395    mod match {
396      case m: HasMachineCounterControlBundle =>
397        m.mcountinhibit := mcountinhibit.regOut
398      case _ =>
399    }
400    mod match {
401      case m: HasExternalInterruptBundle =>
402        m.platformIRP := this.platformIRP
403      case _ =>
404    }
405    mod match {
406      case m: HasRobCommitBundle =>
407        m.robCommit := io.fromRob.commit
408        m.robCommit.fsDirty := io.fromRob.commit.fsDirty || writeFpState
409        m.robCommit.vsDirty := io.fromRob.commit.vsDirty || writeVecState
410      case _ =>
411    }
412    mod match {
413      case m: TrapEntryDEventSinkBundle =>
414        m.trapToD := trapEntryDEvent.out
415      case _ =>
416    }
417    mod match {
418      case m: TrapEntryMEventSinkBundle =>
419        m.trapToM := trapEntryMEvent.out
420      case _ =>
421    }
422    mod match {
423      case m: TrapEntryHSEventSinkBundle =>
424        m.trapToHS := trapEntryHSEvent.out
425      case _ =>
426    }
427    mod match {
428      case m: TrapEntryVSEventSinkBundle =>
429        m.trapToVS := trapEntryVSEvent.out
430      case _ =>
431    }
432    mod match {
433      case m: MretEventSinkBundle =>
434        m.retFromM := mretEvent.out
435      case _ =>
436    }
437    mod match {
438      case m: SretEventSinkBundle =>
439        m.retFromS := sretEvent.out
440      case _ =>
441    }
442    mod match {
443      case m: DretEventSinkBundle =>
444        m.retFromD := dretEvent.out
445      case _ =>
446    }
447    mod match {
448      case m: HasAIABundle =>
449        m.aiaToCSR.rdata.valid := fromAIA.rdata.valid
450        m.aiaToCSR.rdata.bits.data := fromAIA.rdata.bits.data
451        m.aiaToCSR.rdata.bits.illegal := fromAIA.rdata.bits.illegal
452        m.aiaToCSR.mtopei.valid := fromAIA.mtopei.valid
453        m.aiaToCSR.stopei.valid := fromAIA.stopei.valid
454        m.aiaToCSR.vstopei.valid := fromAIA.vstopei.valid
455        m.aiaToCSR.mtopei.bits := fromAIA.mtopei.bits
456        m.aiaToCSR.stopei.bits := fromAIA.stopei.bits
457        m.aiaToCSR.vstopei.bits := fromAIA.vstopei.bits
458      case _ =>
459    }
460    mod match {
461      case m: HasInterruptFilterSink =>
462        m.topIR.mtopi  := intrMod.io.out.mtopi
463        m.topIR.stopi  := intrMod.io.out.stopi
464        m.topIR.vstopi := intrMod.io.out.vstopi
465      case _ =>
466    }
467    mod match {
468      case m: HasISelectBundle =>
469        m.privState := privState
470        m.miselect := miselect.regOut
471        m.siselect := siselect.regOut
472        m.mireg := mireg.regOut.asUInt
473        m.sireg := sireg.regOut.asUInt
474      case _ =>
475    }
476    mod match {
477      case m: HasPMPAddrSink =>
478        m.addrRData := pmpEntryMod.io.out.pmpAddrRData
479      case _ =>
480    }
481  }
482
483  csrMods.foreach { mod =>
484    println(s"${mod.modName}: ")
485    println(mod.dumpFields)
486  }
487
488  trapEntryMEvent .valid := hasTrap && entryPrivState.isModeM
489  trapEntryHSEvent.valid := hasTrap && entryPrivState.isModeHS
490  trapEntryVSEvent.valid := hasTrap && entryPrivState.isModeVS
491
492
493  Seq(trapEntryMEvent, trapEntryHSEvent, trapEntryVSEvent, trapEntryDEvent).foreach { eMod =>
494    eMod.in match {
495      case in: TrapEntryEventInput =>
496        in.causeNO := trapHandleMod.io.out.causeNO
497        in.trapPc := trapPC
498        in.isCrossPageIPF := trapIsCrossPageIPF
499
500        in.iMode.PRVM := PRVM
501        in.iMode.V := V
502        in.dMode.PRVM := Mux(mstatus.regOut.MPRV.asBool, mstatus.regOut.MPP, PRVM)
503        in.dMode.V := Mux(mstatus.regOut.MPRV.asBool, mstatus.regOut.MPV, V)
504
505        in.privState := privState
506        in.mstatus := mstatus.regOut
507        in.hstatus := hstatus.regOut
508        in.sstatus := mstatus.sstatus
509        in.vsstatus := vsstatus.regOut
510        in.pcFromXtvec := trapHandleMod.io.out.pcFromXtvec
511
512        in.satp  := satp.regOut
513        in.vsatp := vsatp.regOut
514        in.hgatp := hgatp.regOut
515
516        in.memExceptionVAddr := io.fromMem.excpVA
517        in.memExceptionGPAddr := io.fromMem.excpGPA
518    }
519  }
520
521  mretEvent.valid := legalMret
522  mretEvent.in match {
523    case in =>
524      in.mstatus := mstatus.regOut
525      in.mepc := mepc.regOut
526  }
527
528  sretEvent.valid := legalSret
529  sretEvent.in match {
530    case in =>
531      in.privState := privState
532      in.sstatus := mstatus.sstatus
533      in.hstatus := hstatus.regOut
534      in.vsstatus := vsstatus.regOut
535      in.sepc := sepc.regOut
536      in.vsepc := vsepc.regOut
537  }
538
539  dretEvent.valid := isDret
540  dretEvent.in match {
541    case in =>
542      in.dcsr := dcsr.regOut
543      in.dpc  := dpc.regOut
544      in.mstatus := mstatus.regOut
545  }
546
547  PRVM := MuxCase(
548    PRVM,
549    events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map {
550      x => x.out match {
551        case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.PRVM)
552      }
553    }
554  )
555
556  V := MuxCase(
557    V,
558    events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map {
559      x => x.out match {
560        case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.V)
561      }
562    }
563  )
564
565  debugMode := MuxCase(
566    debugMode,
567    Seq(
568      dretEvent.out.debugMode.valid -> dretEvent.out.debugMode.bits,
569      trapEntryDEvent.out.debugMode.valid -> trapEntryDEvent.out.debugMode.bits
570    )
571  )
572
573  debugIntrEnable := MuxCase(
574    debugIntrEnable,
575    Seq(
576      dretEvent.out.debugIntrEnable.valid -> dretEvent.out.debugIntrEnable.bits,
577      trapEntryDEvent.out.debugIntrEnable.valid -> trapEntryDEvent.out.debugIntrEnable.bits
578    )
579  )
580
581  // perf
582  val addrInPerfCnt = (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) ||
583    (addr >= mcountinhibit.addr.U) && (addr <= mhpmevents.last.addr.U) ||
584    (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) ||
585    (addr === CSRs.mip.U) ||
586    (addr === CSRs.hip.U) ||
587    Cat(aiaCSRMap.keys.toSeq.sorted.map(_.U === addr)).orR ||
588    (addr === CSRs.stimecmp.U) ||
589    (addr === CSRs.mcounteren.U) ||
590    (addr === CSRs.scounteren.U) ||
591    (addr === CSRs.menvcfg.U)
592  // Todo: may be vsip and sip
593
594  // flush
595  val resetSatp = Cat(Seq(satp, vsatp, hgatp).map(_.addr.U === addr)).orR && wenLegal // write to satp will cause the pipeline be flushed
596
597  val wFcsrChangeRM = addr === fcsr.addr.U && wenLegal && wdata(7, 5) =/= fcsr.frm
598  val wFrmChangeRM  = addr === CSRs.frm.U  && wenLegal && wdata(2, 0) =/= fcsr.frm
599  val frmChange = wFcsrChangeRM || wFrmChangeRM
600
601  val wVcsrChangeRM = addr === CSRs.vcsr.U && wenLegal && wdata(2, 1) =/= vcsr.vxrm
602  val wVxrmChangeRM = addr === CSRs.vxrm.U && wenLegal && wdata(1, 0) =/= vcsr.vxrm
603  val vxrmChange = wVcsrChangeRM || wVxrmChangeRM
604
605  val triggerFrontendChange = Wire(Bool())
606  val flushPipe = resetSatp || frmChange || vxrmChange || triggerFrontendChange
607
608  // fence
609  val tvm = mstatus.regOut.TVM.asBool
610  val vtvm = hstatus.regOut.VTVM.asBool
611
612  private val rdata = Mux1H(csrRwMap.map { case (id, (_, rBundle)) =>
613    (raddr === id.U) -> rBundle.asUInt
614  })
615
616  private val regOut = Mux1H(csrOutMap.map { case (id, regOut) =>
617    (raddr === id.U) -> regOut
618  })
619
620  private val needTargetUpdate = mretEvent.out.targetPc.valid || sretEvent.out.targetPc.valid || dretEvent.out.targetPc.valid ||
621    trapEntryMEvent.out.targetPc.valid || trapEntryHSEvent.out.targetPc.valid || trapEntryVSEvent.out.targetPc.valid || trapEntryDEvent.out.targetPc.valid
622
623  private val noCSRIllegal = (ren || wen) && Cat(csrRwMap.keys.toSeq.sorted.map(csrAddr => !(addr === csrAddr.U))).andR
624
625  io.out.EX_II := permitMod.io.out.EX_II || noCSRIllegal
626  io.out.EX_VI := permitMod.io.out.EX_VI
627  io.out.flushPipe := flushPipe
628
629  io.out.rData := Mux(ren, rdata, 0.U)
630  io.out.regOut := regOut
631  io.out.targetPc := DataHoldBypass(
632    Mux(trapEntryDEvent.out.targetPc.valid,
633      trapEntryDEvent.out.targetPc.bits,
634      Mux1H(Seq(
635        mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits,
636        sretEvent.out.targetPc.valid -> sretEvent.out.targetPc.bits,
637        dretEvent.out.targetPc.valid -> dretEvent.out.targetPc.bits,
638        trapEntryMEvent.out.targetPc.valid -> trapEntryMEvent.out.targetPc.bits,
639        trapEntryHSEvent.out.targetPc.valid -> trapEntryHSEvent.out.targetPc.bits,
640        trapEntryVSEvent.out.targetPc.valid -> trapEntryVSEvent.out.targetPc.bits)
641      )
642    ),
643  needTargetUpdate)
644
645  io.out.privState := privState
646
647  io.out.fpState.frm := fcsr.frm
648  io.out.fpState.off := mstatus.regOut.FS === ContextStatus.Off
649  io.out.vecState.vstart := vstart.rdata.asUInt
650  io.out.vecState.vxsat := vcsr.vxsat
651  io.out.vecState.vxrm := vcsr.vxrm
652  io.out.vecState.vcsr := vcsr.rdata.asUInt
653  io.out.vecState.vl := vl.rdata.asUInt
654  io.out.vecState.vtype := vtype.rdata.asUInt // Todo: check correct
655  io.out.vecState.vlenb := vlenb.rdata.asUInt
656  io.out.vecState.off := mstatus.regOut.VS === ContextStatus.Off
657  io.out.isPerfCnt := addrInPerfCnt
658  io.out.interrupt := intrMod.io.out.interruptVec.valid
659  io.out.wfiEvent := debugIntr || (mie.rdata.asUInt & mip.rdata.asUInt).orR
660  io.out.debugMode := debugMode
661  io.out.singleStepFlag := !debugMode && dcsr.regOut.STEP
662  io.out.tvm := tvm
663  io.out.vtvm := vtvm
664
665  /**
666   * debug_begin
667   */
668  // debug_intr
669  val hasIntr = hasTrap && trapIsInterrupt
670  val hasDebugIntr = hasIntr && intrVec(CSRConst.IRQ_DEBUG)
671
672  // debug_exception_ebreak
673  val hasExp = hasTrap && !trapIsInterrupt
674  val breakPoint = trapVec(ExceptionNO.breakPoint).asBool
675  val hasBreakPoint = hasExp && breakPoint
676  val ebreakEnterDebugMode =
677    (privState.isModeM && dcsr.regOut.EBREAKM.asBool) ||
678      (privState.isModeHS && dcsr.regOut.EBREAKS.asBool) ||
679      (privState.isModeHU && dcsr.regOut.EBREAKU.asBool)
680  val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode
681
682  // debug_exception_trigger
683  val triggerFrontendHitVec = triggerCf.frontendHit
684  val triggerMemHitVec = triggerCf.backendHit
685  val triggerHitVec = triggerFrontendHitVec.asUInt | triggerMemHitVec.asUInt // Todo: update mcontrol.hit
686  val triggerFrontendCanFireVec = triggerCf.frontendCanFire.asUInt
687  val triggerMemCanFireVec = triggerCf.backendCanFire.asUInt
688  val triggerCanFireVec = triggerFrontendCanFireVec | triggerMemCanFireVec
689  val tdata1WireVec = tdata1RegVec.map{ mod => {
690      val tdata1Wire = Wire(new Tdata1Bundle)
691      tdata1Wire := mod.rdata
692      tdata1Wire
693  }}
694  val tdata2WireVec = tdata2RegVec.map{ mod => {
695      val tdata2Wire = Wire(new Tdata2Bundle)
696      tdata2Wire := mod.rdata
697      tdata2Wire
698  }}
699  val mcontrolWireVec = tdata1WireVec.map{ mod => {
700    val mcontrolWire = Wire(new Mcontrol)
701    mcontrolWire := mod.DATA.asUInt
702    mcontrolWire
703  }}
704
705  // More than one triggers can hit at the same time, but only fire one
706  // We select the first hit trigger to fire
707  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
708  val triggerFireAction = PriorityMux(triggerFireOH, tdata1WireVec.map(_.getTriggerAction)).asUInt
709  val hasTriggerFire = hasExp && triggerCf.canFire
710  val hasDebugTriggerException = hasTriggerFire && (triggerFireAction === TrigAction.DebugMode.asUInt)
711
712  // debug_exception_single
713  val hasSingleStep = hasExp && io.fromRob.trap.bits.singleStep
714
715  val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep
716  val hasDebugTrap = hasDebugException || hasDebugIntr
717
718  trapEntryDEvent.valid                       := hasDebugTrap && !debugMode
719  trapEntryDEvent.in.hasDebugIntr             := hasDebugIntr
720  trapEntryDEvent.in.debugMode                := debugMode
721  trapEntryDEvent.in.hasTrap                  := hasTrap
722  trapEntryDEvent.in.hasSingleStep            := hasSingleStep
723  trapEntryDEvent.in.hasTriggerFire           := hasTriggerFire
724  trapEntryDEvent.in.hasDebugEbreakException  := hasDebugEbreakException
725  trapEntryDEvent.in.breakPoint               := breakPoint
726
727  trapHandleMod.io.in.trapInfo.bits.singleStep  := hasSingleStep
728  trapHandleMod.io.in.trapInfo.bits.triggerFire := hasTriggerFire
729
730  intrMod.io.in.debugMode := debugMode
731  intrMod.io.in.debugIntr := debugIntr
732  intrMod.io.in.dcsr      := dcsr.rdata.asUInt
733
734  val tselect1H = UIntToOH(tselect.rdata.asUInt, TriggerNum).asBools
735  val chainVec = mcontrolWireVec.map(_.CHAIN.asBool)
736  val newTriggerChainVec = tselect1H.zip(chainVec).map{case(a, b) => a | b}
737  val newTriggerChainIsLegal = TriggerUtil.TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength)
738
739  val tdata1Update  = addr === tdata1.addr.U && wenLegal
740  val tdata2Update  = addr === tdata2.addr.U && wenLegal
741  val triggerUpdate = tdata1Update || tdata2Update
742
743  tdata1RegVec.foreach { mod =>
744    mod match {
745      case m: HasdebugModeBundle =>
746        m.debugMode := debugMode
747        m.chainable := newTriggerChainIsLegal
748      case _ =>
749    }
750  }
751  tdata1RegVec.zip(tdata2RegVec).zipWithIndex.map { case ((mod1, mod2), idx) => {
752      mod1.w.wen    := tdata1Update && (tselect.rdata === idx.U)
753      mod1.w.wdata  := wdata
754      mod2.w.wen    := tdata2Update && (tselect.rdata === idx.U)
755      mod2.w.wdata  := wdata
756    }
757  }
758
759  val tdata1Wdata = Wire(new Tdata1Bundle)
760  tdata1Wdata := wdata
761  val mcontrolWdata = Wire(new Mcontrol)
762  mcontrolWdata := tdata1Wdata.DATA.asUInt
763  val tdata1TypeWdata = tdata1Wdata.TYPE
764
765  val tdata1Selected = Wire(new Tdata1Bundle)
766  tdata1Selected := tdata1.rdata.asUInt
767  val mcontrolSelected = Wire(new Mcontrol)
768  mcontrolSelected := tdata1Selected.DATA.asUInt
769  val tdata2Selected = Wire(new Tdata2Bundle)
770  tdata2Selected := tdata2.rdata.asUInt
771
772  val frontendTriggerUpdate =
773    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isFetchTrigger ||
774      mcontrolSelected.isFetchTrigger && triggerUpdate
775
776  val memTriggerUpdate =
777    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isMemAccTrigger ||
778      mcontrolSelected.isMemAccTrigger && triggerUpdate
779
780  val triggerEnableVec = tdata1WireVec.zip(mcontrolWireVec).map { case(tdata1, mcontrol) =>
781    tdata1.TYPE.isLegal && (
782      mcontrol.M && privState.isModeM ||
783        mcontrol.S && (privState.isModeHS) ||
784        mcontrol.U && privState.isModeHU)
785  }
786
787  val fetchTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
788    case (tEnable, mod) => tEnable && mod.isFetchTrigger
789  }
790  val memAccTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
791    case (tEnable, mod) => tEnable && mod.isMemAccTrigger
792  }
793
794  triggerFrontendChange := frontendTriggerUpdate
795
796  io.out.frontendTrigger.tUpdate.valid       := RegNext(RegNext(frontendTriggerUpdate))
797  io.out.frontendTrigger.tUpdate.bits.addr   := tselect.rdata.asUInt
798  io.out.frontendTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
799  io.out.frontendTrigger.tEnableVec          := fetchTriggerEnableVec
800  io.out.memTrigger.tUpdate.valid            := RegNext(RegNext(memTriggerUpdate))
801  io.out.memTrigger.tUpdate.bits.addr        := tselect.rdata.asUInt
802  io.out.memTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
803  io.out.memTrigger.tEnableVec               := memAccTriggerEnableVec
804  /**
805   * debug_end
806   */
807
808  /**
809   * [[io.out.custom]] connection
810   */
811  io.out.custom.l1I_pf_enable           := spfctl.regOut.L1I_PF_ENABLE.asBool
812  io.out.custom.l2_pf_enable            := spfctl.regOut.L2_PF_ENABLE.asBool
813  io.out.custom.l1D_pf_enable           := spfctl.regOut.L1D_PF_ENABLE.asBool
814  io.out.custom.l1D_pf_train_on_hit     := spfctl.regOut.L1D_PF_TRAIN_ON_HIT.asBool
815  io.out.custom.l1D_pf_enable_agt       := spfctl.regOut.L1D_PF_ENABLE_AGT.asBool
816  io.out.custom.l1D_pf_enable_pht       := spfctl.regOut.L1D_PF_ENABLE_PHT.asBool
817  io.out.custom.l1D_pf_active_threshold := spfctl.regOut.L1D_PF_ACTIVE_THRESHOLD.asUInt
818  io.out.custom.l1D_pf_active_stride    := spfctl.regOut.L1D_PF_ACTIVE_STRIDE.asUInt
819  io.out.custom.l1D_pf_enable_stride    := spfctl.regOut.L1D_PF_ENABLE_STRIDE.asBool
820  io.out.custom.l2_pf_store_only        := spfctl.regOut.L2_PF_STORE_ONLY.asBool
821
822  io.out.custom.icache_parity_enable    := sfetchctl.regOut.ICACHE_PARITY_ENABLE.asBool
823
824  io.out.custom.lvpred_disable          := slvpredctl.regOut.LVPRED_DISABLE.asBool
825  io.out.custom.no_spec_load            := slvpredctl.regOut.NO_SPEC_LOAD.asBool
826  io.out.custom.storeset_wait_store     := slvpredctl.regOut.STORESET_WAIT_STORE.asBool
827  io.out.custom.storeset_no_fast_wakeup := slvpredctl.regOut.STORESET_NO_FAST_WAKEUP.asBool
828  io.out.custom.lvpred_timeout          := slvpredctl.regOut.LVPRED_TIMEOUT.asUInt
829
830  io.out.custom.bp_ctrl.ubtb_enable     := sbpctl.regOut.UBTB_ENABLE .asBool
831  io.out.custom.bp_ctrl.btb_enable      := sbpctl.regOut.BTB_ENABLE  .asBool
832  io.out.custom.bp_ctrl.bim_enable      := sbpctl.regOut.BIM_ENABLE  .asBool
833  io.out.custom.bp_ctrl.tage_enable     := sbpctl.regOut.TAGE_ENABLE .asBool
834  io.out.custom.bp_ctrl.sc_enable       := sbpctl.regOut.SC_ENABLE   .asBool
835  io.out.custom.bp_ctrl.ras_enable      := sbpctl.regOut.RAS_ENABLE  .asBool
836  io.out.custom.bp_ctrl.loop_enable     := sbpctl.regOut.LOOP_ENABLE .asBool
837
838  io.out.custom.sbuffer_threshold                := smblockctl.regOut.SBUFFER_THRESHOLD.asUInt
839  io.out.custom.ldld_vio_check_enable            := smblockctl.regOut.LDLD_VIO_CHECK_ENABLE.asBool
840  io.out.custom.soft_prefetch_enable             := smblockctl.regOut.SOFT_PREFETCH_ENABLE.asBool
841  io.out.custom.cache_error_enable               := smblockctl.regOut.CACHE_ERROR_ENABLE.asBool
842  io.out.custom.uncache_write_outstanding_enable := smblockctl.regOut.UNCACHE_WRITE_OUTSTANDING_ENABLE.asBool
843
844  io.out.custom.fusion_enable           := srnctl.regOut.FUSION_ENABLE.asBool
845  io.out.custom.wfi_enable              := srnctl.regOut.WFI_ENABLE.asBool
846
847  // Todo: record the last address to avoid xireg is different with xiselect
848  toAIA.addr.valid := wenLegal && Seq(miselect, siselect, vsiselect).map(
849    _.addr.U === addr
850  ).reduce(_ || _)
851  toAIA.addr.bits.addr := addr
852  toAIA.addr.bits.prvm := PRVM
853  toAIA.addr.bits.v := V
854  toAIA.vgein := hstatus.regOut.VGEIN.asUInt
855  toAIA.wdata.valid := wenLegal && Seq(mireg, sireg, vsireg).map(
856    _.addr.U === addr
857  ).reduce(_ || _)
858  toAIA.wdata.bits.data := wdata
859  toAIA.mClaim := wenLegal && mtopei.addr.U === addr
860  toAIA.sClaim := wenLegal && stopei.addr.U === addr
861  toAIA.vsClaim := wenLegal && vstopei.addr.U === addr
862
863  // tlb
864  io.tlb.satpASIDChanged  := wenLegal && addr === CSRs. satp.U && satp .regOut.ASID =/= wdata.asTypeOf(new SatpBundle).ASID
865  io.tlb.vsatpASIDChanged := wenLegal && addr === CSRs.vsatp.U && vsatp.regOut.ASID =/= wdata.asTypeOf(new SatpBundle).ASID
866  io.tlb.hgatpVMIDChanged := wenLegal && addr === CSRs.hgatp.U && hgatp.regOut.VMID =/= wdata.asTypeOf(new HgatpBundle).VMID
867  io.tlb.satp := satp.rdata
868  io.tlb.vsatp := vsatp.rdata
869  io.tlb.hgatp := hgatp.rdata
870  io.tlb.mxr  :=  mstatus.regOut.MXR.asBool
871  io.tlb.sum  :=  mstatus.regOut.SUM.asBool
872  io.tlb.vmxr := vsstatus.regOut.MXR.asBool
873  io.tlb.vsum := vsstatus.regOut.SUM.asBool
874  io.tlb.spvp :=  hstatus.regOut.SPVP.asBool
875
876  io.tlb.imode := PRVM.asUInt
877  io.tlb.dmode := Mux((debugMode && dcsr.regOut.MPRVEN.asBool || !debugMode) && mstatus.regOut.MPRV.asBool, mstatus.regOut.MPP.asUInt, PRVM.asUInt)
878
879  // Always instantiate basic difftest modules.
880  if (env.AlwaysBasicDiff || env.EnableDifftest) {
881    val hartId = io.fromTop.hartId
882    val trapValid = io.fromRob.trap.valid
883    val trapNO = trapHandleMod.io.out.causeNO.ExceptionCode.asUInt
884    val interrupt = trapHandleMod.io.out.causeNO.Interrupt.asBool
885    val interruptNO = Mux(interrupt, trapNO, 0.U)
886    val exceptionNO = Mux(!interrupt, trapNO, 0.U)
887    val ivmHS = isModeHS &&  satp.regOut.MODE =/= SatpMode.Bare
888    val ivmVS = isModeVS && vsatp.regOut.MODE =/= SatpMode.Bare
889    // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57
890    val exceptionPC = Mux(ivmHS || ivmVS, SignExt(trapPC, XLEN), ZeroExt(trapPC, XLEN))
891
892    val diffArchEvent = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true)
893    diffArchEvent.coreid := hartId
894    diffArchEvent.valid := trapValid
895    diffArchEvent.interrupt := interruptNO
896    diffArchEvent.exception := exceptionNO
897    diffArchEvent.exceptionPC := exceptionPC
898    if (env.EnableDifftest) {
899      diffArchEvent.exceptionInst := io.fromRob.trap.bits.instr
900    }
901
902    val diffCSRState = DifftestModule(new DiffCSRState)
903    diffCSRState.coreid         := hartId
904    diffCSRState.privilegeMode  := privState.PRVM.asUInt
905    diffCSRState.mstatus        := mstatus.rdata.asUInt
906    diffCSRState.sstatus        := mstatus.sstatus.asUInt
907    diffCSRState.mepc           := mepc.rdata.asUInt
908    diffCSRState.sepc           := sepc.rdata.asUInt
909    diffCSRState.mtval          := mtval.rdata.asUInt
910    diffCSRState.stval          := stval.rdata.asUInt
911    diffCSRState.mtvec          := mtvec.rdata.asUInt
912    diffCSRState.stvec          := stvec.rdata.asUInt
913    diffCSRState.mcause         := mcause.rdata.asUInt
914    diffCSRState.scause         := scause.rdata.asUInt
915    diffCSRState.satp           := satp.rdata.asUInt
916    diffCSRState.mip            := mip.regOut.asUInt
917    diffCSRState.mie            := mie.rdata.asUInt
918    diffCSRState.mscratch       := mscratch.rdata.asUInt
919    diffCSRState.sscratch       := sscratch.rdata.asUInt
920    diffCSRState.mideleg        := mideleg.rdata.asUInt
921    diffCSRState.medeleg        := medeleg.rdata.asUInt
922
923    val diffDebugMode = DifftestModule(new DiffDebugMode)
924    diffDebugMode.coreid    := hartId
925    diffDebugMode.debugMode := debugMode
926    diffDebugMode.dcsr      := dcsr.rdata.asUInt
927    diffDebugMode.dpc       := dpc.rdata.asUInt
928    diffDebugMode.dscratch0 := dscratch0.rdata.asUInt
929    diffDebugMode.dscratch1 := dscratch1.rdata.asUInt
930
931    val diffVecCSRState = DifftestModule(new DiffVecCSRState)
932    diffVecCSRState.coreid := hartId
933    diffVecCSRState.vstart := vstart.rdata.asUInt
934    diffVecCSRState.vxsat := vcsr.vxsat.asUInt
935    diffVecCSRState.vxrm := vcsr.vxrm.asUInt
936    diffVecCSRState.vcsr := vcsr.rdata.asUInt
937    diffVecCSRState.vl := vl.rdata.asUInt
938    diffVecCSRState.vtype := vtype.rdata.asUInt
939    diffVecCSRState.vlenb := vlenb.rdata.asUInt
940
941    val diffHCSRState = DifftestModule(new DiffHCSRState)
942    diffHCSRState.coreid      := hartId
943    diffHCSRState.virtMode    := privState.V.asBool
944    diffHCSRState.mtval2      := mtval2.rdata.asUInt
945    diffHCSRState.mtinst      := mtinst.rdata.asUInt
946    diffHCSRState.hstatus     := hstatus.rdata.asUInt
947    diffHCSRState.hideleg     := hideleg.rdata.asUInt
948    diffHCSRState.hedeleg     := hedeleg.rdata.asUInt
949    diffHCSRState.hcounteren  := hcounteren.rdata.asUInt
950    diffHCSRState.htval       := htval.rdata.asUInt
951    diffHCSRState.htinst      := htinst.rdata.asUInt
952    diffHCSRState.hgatp       := hgatp.rdata.asUInt
953    diffHCSRState.vsstatus    := vsstatus.rdata.asUInt
954    diffHCSRState.vstvec      := vstvec.rdata.asUInt
955    diffHCSRState.vsepc       := vsepc.rdata.asUInt
956    diffHCSRState.vscause     := vscause.rdata.asUInt
957    diffHCSRState.vstval      := vstval.rdata.asUInt
958    diffHCSRState.vsatp       := vsatp.rdata.asUInt
959    diffHCSRState.vsscratch   := vsscratch.rdata.asUInt
960
961  }
962}
963
964trait SupervisorMachineAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel =>
965  mip.fromMvip := mvip.toMip
966  mip.fromSip := sip.toMip
967  mie.fromSie := sie.toMie
968}
969
970object NewCSRMain extends App {
971  val (config, firrtlOpts, firtoolOpts) = ArgParser.parse(
972    args :+ "--disable-always-basic-diff" :+ "--dump-fir" :+ "--fpga-platform" :+ "--target" :+ "verilog")
973
974  val defaultConfig = config.alterPartial({
975    // Get XSCoreParams and pass it to the "small module"
976    case XSCoreParamsKey => config(XSTileKey).head
977  })
978
979  Generator.execute(
980    firrtlOpts :+ "--full-stacktrace" :+ "--target-dir" :+ "backend",
981    new NewCSR()(defaultConfig),
982    firtoolOpts
983  )
984
985  println("done")
986}