xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/NewCSR.scala (revision a7a6d0a6adb97825acea8ab65b97b616782d63de)
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  miregiprios.foreach { mod =>
344    mod.w.wen := (addr === mireg.addr.U) && (miselect.regOut.ALL.asUInt === mod.addr.U)
345    mod.w.wdata := wdata
346  }
347
348  siregiprios.foreach { mod =>
349    mod.w.wen := (addr === sireg.addr.U) && (siselect.regOut.ALL.asUInt === mod.addr.U)
350    mod.w.wdata := wdata
351  }
352
353  mhartid.hartid := this.io.fromTop.hartId
354
355  cfgs.zipWithIndex.foreach { case (mod, i) =>
356    mod.w.wen := wen && (addr === (0x3A0 + i / 8 * 2).U)
357    mod.w.wdata := pmpEntryMod.io.out.pmpCfgWData(8*((i%8)+1)-1,8*(i%8))
358  }
359
360  pmpaddr.zipWithIndex.foreach{ case(mod, i) =>
361    mod.w.wen := wen && (addr === (0x3B0 + i).U)
362    mod.w.wdata := pmpEntryMod.io.out.pmpAddrWData(i)
363  }
364
365  csrMods.foreach { mod =>
366    mod match {
367      case m: HypervisorBundle =>
368        m.hstatus := hstatus.regOut
369        m.hvip := hvip.regOut
370        m.hideleg := hideleg.regOut
371        m.hedeleg := hedeleg.regOut
372        m.hgeip := hgeip.regOut
373        m.hgeie := hgeie.regOut
374        m.hip := hip.regOut
375        m.hie := hie.regOut
376      case _ =>
377    }
378    mod match {
379      case m: HasMachineInterruptBundle =>
380        m.mvien := mvien.regOut
381        m.mvip := mvip.regOut
382        m.mip := mip.regOut
383        m.mie := mie.regOut
384      case _ =>
385    }
386    mod match {
387      case m: HasMachineDelegBundle =>
388        m.mideleg := mideleg.regOut
389        m.medeleg := medeleg.regOut
390      case _ =>
391    }
392    mod match {
393      case m: HasMachineCounterControlBundle =>
394        m.mcountinhibit := mcountinhibit.regOut
395      case _ =>
396    }
397    mod match {
398      case m: HasExternalInterruptBundle =>
399        m.platformIRP := this.platformIRP
400      case _ =>
401    }
402    mod match {
403      case m: HasRobCommitBundle =>
404        m.robCommit := io.fromRob.commit
405        m.robCommit.fsDirty := io.fromRob.commit.fsDirty || writeFpState
406        m.robCommit.vsDirty := io.fromRob.commit.vsDirty || writeVecState
407      case _ =>
408    }
409    mod match {
410      case m: TrapEntryDEventSinkBundle =>
411        m.trapToD := trapEntryDEvent.out
412      case _ =>
413    }
414    mod match {
415      case m: TrapEntryMEventSinkBundle =>
416        m.trapToM := trapEntryMEvent.out
417      case _ =>
418    }
419    mod match {
420      case m: TrapEntryHSEventSinkBundle =>
421        m.trapToHS := trapEntryHSEvent.out
422      case _ =>
423    }
424    mod match {
425      case m: TrapEntryVSEventSinkBundle =>
426        m.trapToVS := trapEntryVSEvent.out
427      case _ =>
428    }
429    mod match {
430      case m: MretEventSinkBundle =>
431        m.retFromM := mretEvent.out
432      case _ =>
433    }
434    mod match {
435      case m: SretEventSinkBundle =>
436        m.retFromS := sretEvent.out
437      case _ =>
438    }
439    mod match {
440      case m: DretEventSinkBundle =>
441        m.retFromD := dretEvent.out
442      case _ =>
443    }
444    mod match {
445      case m: HasAIABundle =>
446        m.aiaToCSR.rdata.valid := fromAIA.rdata.valid
447        m.aiaToCSR.rdata.bits.data := fromAIA.rdata.bits.data
448        m.aiaToCSR.rdata.bits.illegal := fromAIA.rdata.bits.illegal
449        m.aiaToCSR.mtopei.valid := fromAIA.mtopei.valid
450        m.aiaToCSR.stopei.valid := fromAIA.stopei.valid
451        m.aiaToCSR.vstopei.valid := fromAIA.vstopei.valid
452        m.aiaToCSR.mtopei.bits := fromAIA.mtopei.bits
453        m.aiaToCSR.stopei.bits := fromAIA.stopei.bits
454        m.aiaToCSR.vstopei.bits := fromAIA.vstopei.bits
455      case _ =>
456    }
457    mod match {
458      case m: HasInterruptFilterSink =>
459        m.topIR.mtopi  := intrMod.io.out.mtopi
460        m.topIR.stopi  := intrMod.io.out.stopi
461        m.topIR.vstopi := intrMod.io.out.vstopi
462      case _ =>
463    }
464    mod match {
465      case m: HasISelectBundle =>
466        m.privState := privState
467        m.miselect := miselect.regOut
468        m.siselect := siselect.regOut
469        m.mireg := mireg.regOut.asUInt
470        m.sireg := sireg.regOut.asUInt
471      case _ =>
472    }
473    mod match {
474      case m: HasPMPAddrSink =>
475        m.addrRData := pmpEntryMod.io.out.pmpAddrRData
476      case _ =>
477    }
478  }
479
480  csrMods.foreach { mod =>
481    println(s"${mod.modName}: ")
482    println(mod.dumpFields)
483  }
484
485  trapEntryMEvent .valid := hasTrap && entryPrivState.isModeM
486  trapEntryHSEvent.valid := hasTrap && entryPrivState.isModeHS
487  trapEntryVSEvent.valid := hasTrap && entryPrivState.isModeVS
488
489
490  Seq(trapEntryMEvent, trapEntryHSEvent, trapEntryVSEvent, trapEntryDEvent).foreach { eMod =>
491    eMod.in match {
492      case in: TrapEntryEventInput =>
493        in.causeNO := trapHandleMod.io.out.causeNO
494        in.trapPc := trapPC
495        in.isCrossPageIPF := trapIsCrossPageIPF
496
497        in.iMode.PRVM := PRVM
498        in.iMode.V := V
499        in.dMode.PRVM := Mux(mstatus.regOut.MPRV.asBool, mstatus.regOut.MPP, PRVM)
500        in.dMode.V := Mux(mstatus.regOut.MPRV.asBool, mstatus.regOut.MPV, V)
501
502        in.privState := privState
503        in.mstatus := mstatus.regOut
504        in.hstatus := hstatus.regOut
505        in.sstatus := mstatus.sstatus
506        in.vsstatus := vsstatus.regOut
507        in.pcFromXtvec := trapHandleMod.io.out.pcFromXtvec
508
509        in.satp  := satp.regOut
510        in.vsatp := vsatp.regOut
511        in.hgatp := hgatp.regOut
512
513        in.memExceptionVAddr := io.fromMem.excpVA
514        in.memExceptionGPAddr := io.fromMem.excpGPA
515    }
516  }
517
518  mretEvent.valid := legalMret
519  mretEvent.in match {
520    case in =>
521      in.mstatus := mstatus.regOut
522      in.mepc := mepc.regOut
523  }
524
525  sretEvent.valid := legalSret
526  sretEvent.in match {
527    case in =>
528      in.privState := privState
529      in.sstatus := mstatus.sstatus
530      in.hstatus := hstatus.regOut
531      in.vsstatus := vsstatus.regOut
532      in.sepc := sepc.regOut
533      in.vsepc := vsepc.regOut
534  }
535
536  dretEvent.valid := isDret
537  dretEvent.in match {
538    case in =>
539      in.dcsr := dcsr.regOut
540      in.dpc  := dpc.regOut
541      in.mstatus := mstatus.regOut
542  }
543
544  PRVM := MuxCase(
545    PRVM,
546    events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map {
547      x => x.out match {
548        case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.PRVM)
549      }
550    }
551  )
552
553  V := MuxCase(
554    V,
555    events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map {
556      x => x.out match {
557        case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.V)
558      }
559    }
560  )
561
562  debugMode := MuxCase(
563    debugMode,
564    Seq(
565      dretEvent.out.debugMode.valid -> dretEvent.out.debugMode.bits,
566      trapEntryDEvent.out.debugMode.valid -> trapEntryDEvent.out.debugMode.bits
567    )
568  )
569
570  debugIntrEnable := MuxCase(
571    debugIntrEnable,
572    Seq(
573      dretEvent.out.debugIntrEnable.valid -> dretEvent.out.debugIntrEnable.bits,
574      trapEntryDEvent.out.debugIntrEnable.valid -> trapEntryDEvent.out.debugIntrEnable.bits
575    )
576  )
577
578  // perf
579  val addrInPerfCnt = (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) ||
580    (addr >= mcountinhibit.addr.U) && (addr <= mhpmevents.last.addr.U) ||
581    (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) ||
582    (addr === CSRs.mip.U) ||
583    (addr === CSRs.hip.U) ||
584    Cat(aiaCSRMap.keys.toSeq.sorted.map(_.U === addr)).orR ||
585    (addr === CSRs.stimecmp.U) ||
586    (addr === CSRs.mcounteren.U) ||
587    (addr === CSRs.scounteren.U) ||
588    (addr === CSRs.menvcfg.U)
589  // Todo: may be vsip and sip
590
591  // flush
592  val resetSatp = Cat(Seq(satp, vsatp, hgatp).map(_.addr.U === addr)).orR && wenLegal // write to satp will cause the pipeline be flushed
593
594  val wFcsrChangeRM = addr === fcsr.addr.U && wenLegal && wdata(7, 5) =/= fcsr.frm
595  val wFrmChangeRM  = addr === CSRs.frm.U  && wenLegal && wdata(2, 0) =/= fcsr.frm
596  val frmChange = wFcsrChangeRM || wFrmChangeRM
597
598  val wVcsrChangeRM = addr === CSRs.vcsr.U && wenLegal && wdata(2, 1) =/= vcsr.vxrm
599  val wVxrmChangeRM = addr === CSRs.vxrm.U && wenLegal && wdata(1, 0) =/= vcsr.vxrm
600  val vxrmChange = wVcsrChangeRM || wVxrmChangeRM
601
602  val triggerFrontendChange = Wire(Bool())
603  val flushPipe = resetSatp || frmChange || vxrmChange || triggerFrontendChange
604
605  // fence
606  val tvm = mstatus.regOut.TVM.asBool
607  val vtvm = hstatus.regOut.VTVM.asBool
608
609  private val rdata = Mux1H(csrRwMap.map { case (id, (_, rBundle)) =>
610    (raddr === id.U) -> rBundle.asUInt
611  })
612
613  private val regOut = Mux1H(csrOutMap.map { case (id, regOut) =>
614    (raddr === id.U) -> regOut
615  })
616
617  private val needTargetUpdate = mretEvent.out.targetPc.valid || sretEvent.out.targetPc.valid || dretEvent.out.targetPc.valid ||
618    trapEntryMEvent.out.targetPc.valid || trapEntryHSEvent.out.targetPc.valid || trapEntryVSEvent.out.targetPc.valid || trapEntryDEvent.out.targetPc.valid
619
620  private val noCSRIllegal = (ren || wen) && Cat(csrRwMap.keys.toSeq.sorted.map(csrAddr => !(addr === csrAddr.U))).andR
621
622  io.out.EX_II := permitMod.io.out.EX_II || noCSRIllegal
623  io.out.EX_VI := permitMod.io.out.EX_VI
624  io.out.flushPipe := flushPipe
625
626  io.out.rData := Mux(ren, rdata, 0.U)
627  io.out.regOut := regOut
628  io.out.targetPc := DataHoldBypass(
629    Mux(trapEntryDEvent.out.targetPc.valid,
630      trapEntryDEvent.out.targetPc.bits,
631      Mux1H(Seq(
632        mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits,
633        sretEvent.out.targetPc.valid -> sretEvent.out.targetPc.bits,
634        dretEvent.out.targetPc.valid -> dretEvent.out.targetPc.bits,
635        trapEntryMEvent.out.targetPc.valid -> trapEntryMEvent.out.targetPc.bits,
636        trapEntryHSEvent.out.targetPc.valid -> trapEntryHSEvent.out.targetPc.bits,
637        trapEntryVSEvent.out.targetPc.valid -> trapEntryVSEvent.out.targetPc.bits)
638      )
639    ),
640  needTargetUpdate)
641
642  io.out.privState := privState
643
644  io.out.fpState.frm := fcsr.frm
645  io.out.fpState.off := mstatus.regOut.FS === ContextStatus.Off
646  io.out.vecState.vstart := vstart.rdata.asUInt
647  io.out.vecState.vxsat := vcsr.vxsat
648  io.out.vecState.vxrm := vcsr.vxrm
649  io.out.vecState.vcsr := vcsr.rdata.asUInt
650  io.out.vecState.vl := vl.rdata.asUInt
651  io.out.vecState.vtype := vtype.rdata.asUInt // Todo: check correct
652  io.out.vecState.vlenb := vlenb.rdata.asUInt
653  io.out.vecState.off := mstatus.regOut.VS === ContextStatus.Off
654  io.out.isPerfCnt := addrInPerfCnt
655  io.out.interrupt := intrMod.io.out.interruptVec.valid
656  io.out.wfiEvent := debugIntr || (mie.rdata.asUInt & mip.rdata.asUInt).orR
657  io.out.debugMode := debugMode
658  io.out.singleStepFlag := !debugMode && dcsr.regOut.STEP
659  io.out.tvm := tvm
660  io.out.vtvm := vtvm
661
662  /**
663   * debug_begin
664   */
665  // debug_intr
666  val hasIntr = hasTrap && trapIsInterrupt
667  val hasDebugIntr = hasIntr && intrVec(CSRConst.IRQ_DEBUG)
668
669  // debug_exception_ebreak
670  val hasExp = hasTrap && !trapIsInterrupt
671  val breakPoint = trapVec(ExceptionNO.breakPoint).asBool
672  val hasBreakPoint = hasExp && breakPoint
673  val ebreakEnterDebugMode =
674    (privState.isModeM && dcsr.regOut.EBREAKM.asBool) ||
675      (privState.isModeHS && dcsr.regOut.EBREAKS.asBool) ||
676      (privState.isModeHU && dcsr.regOut.EBREAKU.asBool)
677  val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode
678
679  // debug_exception_trigger
680  val triggerFrontendHitVec = triggerCf.frontendHit
681  val triggerMemHitVec = triggerCf.backendHit
682  val triggerHitVec = triggerFrontendHitVec.asUInt | triggerMemHitVec.asUInt // Todo: update mcontrol.hit
683  val triggerFrontendCanFireVec = triggerCf.frontendCanFire.asUInt
684  val triggerMemCanFireVec = triggerCf.backendCanFire.asUInt
685  val triggerCanFireVec = triggerFrontendCanFireVec | triggerMemCanFireVec
686  val tdata1WireVec = tdata1RegVec.map{ mod => {
687      val tdata1Wire = Wire(new Tdata1Bundle)
688      tdata1Wire := mod.rdata
689      tdata1Wire
690  }}
691  val tdata2WireVec = tdata2RegVec.map{ mod => {
692      val tdata2Wire = Wire(new Tdata2Bundle)
693      tdata2Wire := mod.rdata
694      tdata2Wire
695  }}
696  val mcontrolWireVec = tdata1WireVec.map{ mod => {
697    val mcontrolWire = Wire(new Mcontrol)
698    mcontrolWire := mod.DATA.asUInt
699    mcontrolWire
700  }}
701
702  // More than one triggers can hit at the same time, but only fire one
703  // We select the first hit trigger to fire
704  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
705  val triggerFireAction = PriorityMux(triggerFireOH, tdata1WireVec.map(_.getTriggerAction)).asUInt
706  val hasTriggerFire = hasExp && triggerCf.canFire
707  val hasDebugTriggerException = hasTriggerFire && (triggerFireAction === TrigAction.DebugMode.asUInt)
708
709  // debug_exception_single
710  val hasSingleStep = hasExp && io.fromRob.trap.bits.singleStep
711
712  val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep
713  val hasDebugTrap = hasDebugException || hasDebugIntr
714
715  trapEntryDEvent.valid                       := hasDebugTrap && !debugMode
716  trapEntryDEvent.in.hasDebugIntr             := hasDebugIntr
717  trapEntryDEvent.in.debugMode                := debugMode
718  trapEntryDEvent.in.hasTrap                  := hasTrap
719  trapEntryDEvent.in.hasSingleStep            := hasSingleStep
720  trapEntryDEvent.in.hasTriggerFire           := hasTriggerFire
721  trapEntryDEvent.in.hasDebugEbreakException  := hasDebugEbreakException
722  trapEntryDEvent.in.breakPoint               := breakPoint
723
724  trapHandleMod.io.in.trapInfo.bits.singleStep  := hasSingleStep
725  trapHandleMod.io.in.trapInfo.bits.triggerFire := hasTriggerFire
726
727  intrMod.io.in.debugMode := debugMode
728  intrMod.io.in.debugIntr := debugIntr
729  intrMod.io.in.dcsr      := dcsr.rdata.asUInt
730
731  val tselect1H = UIntToOH(tselect.rdata.asUInt, TriggerNum).asBools
732  val chainVec = mcontrolWireVec.map(_.CHAIN.asBool)
733  val newTriggerChainVec = tselect1H.zip(chainVec).map{case(a, b) => a | b}
734  val newTriggerChainIsLegal = TriggerUtil.TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength)
735
736  val tdata1Update  = addr === tdata1.addr.U && wenLegal
737  val tdata2Update  = addr === tdata2.addr.U && wenLegal
738  val triggerUpdate = tdata1Update || tdata2Update
739
740  tdata1RegVec.foreach { mod =>
741    mod match {
742      case m: HasdebugModeBundle =>
743        m.debugMode := debugMode
744        m.chainable := newTriggerChainIsLegal
745      case _ =>
746    }
747  }
748  tdata1RegVec.zip(tdata2RegVec).zipWithIndex.map { case ((mod1, mod2), idx) => {
749      mod1.w.wen    := tdata1Update && (tselect.rdata === idx.U)
750      mod1.w.wdata  := wdata
751      mod2.w.wen    := tdata2Update && (tselect.rdata === idx.U)
752      mod2.w.wdata  := wdata
753    }
754  }
755
756  val tdata1Wdata = Wire(new Tdata1Bundle)
757  tdata1Wdata := wdata
758  val mcontrolWdata = Wire(new Mcontrol)
759  mcontrolWdata := tdata1Wdata.DATA.asUInt
760  val tdata1TypeWdata = tdata1Wdata.TYPE
761
762  val tdata1Selected = Wire(new Tdata1Bundle)
763  tdata1Selected := tdata1.rdata.asUInt
764  val mcontrolSelected = Wire(new Mcontrol)
765  mcontrolSelected := tdata1Selected.DATA.asUInt
766  val tdata2Selected = Wire(new Tdata2Bundle)
767  tdata2Selected := tdata2.rdata.asUInt
768
769  val frontendTriggerUpdate =
770    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isFetchTrigger ||
771      mcontrolSelected.isFetchTrigger && triggerUpdate
772
773  val memTriggerUpdate =
774    tdata1Update && tdata1TypeWdata.isLegal && mcontrolWdata.isMemAccTrigger ||
775      mcontrolSelected.isMemAccTrigger && triggerUpdate
776
777  val triggerEnableVec = tdata1WireVec.zip(mcontrolWireVec).map { case(tdata1, mcontrol) =>
778    tdata1.TYPE.isLegal && (
779      mcontrol.M && privState.isModeM ||
780        mcontrol.S && (privState.isModeHS) ||
781        mcontrol.U && privState.isModeHU)
782  }
783
784  val fetchTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
785    case (tEnable, mod) => tEnable && mod.isFetchTrigger
786  }
787  val memAccTriggerEnableVec = triggerEnableVec.zip(mcontrolWireVec).map {
788    case (tEnable, mod) => tEnable && mod.isMemAccTrigger
789  }
790
791  triggerFrontendChange := frontendTriggerUpdate
792
793  io.out.frontendTrigger.tUpdate.valid       := RegNext(RegNext(frontendTriggerUpdate))
794  io.out.frontendTrigger.tUpdate.bits.addr   := tselect.rdata.asUInt
795  io.out.frontendTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
796  io.out.frontendTrigger.tEnableVec          := fetchTriggerEnableVec
797  io.out.memTrigger.tUpdate.valid            := RegNext(RegNext(memTriggerUpdate))
798  io.out.memTrigger.tUpdate.bits.addr        := tselect.rdata.asUInt
799  io.out.memTrigger.tUpdate.bits.tdata.GenTdataDistribute(tdata1Selected, tdata2Selected)
800  io.out.memTrigger.tEnableVec               := memAccTriggerEnableVec
801  /**
802   * debug_end
803   */
804
805  /**
806   * [[io.out.custom]] connection
807   */
808  io.out.custom.l1I_pf_enable           := spfctl.regOut.L1I_PF_ENABLE.asBool
809  io.out.custom.l2_pf_enable            := spfctl.regOut.L2_PF_ENABLE.asBool
810  io.out.custom.l1D_pf_enable           := spfctl.regOut.L1D_PF_ENABLE.asBool
811  io.out.custom.l1D_pf_train_on_hit     := spfctl.regOut.L1D_PF_TRAIN_ON_HIT.asBool
812  io.out.custom.l1D_pf_enable_agt       := spfctl.regOut.L1D_PF_ENABLE_AGT.asBool
813  io.out.custom.l1D_pf_enable_pht       := spfctl.regOut.L1D_PF_ENABLE_PHT.asBool
814  io.out.custom.l1D_pf_active_threshold := spfctl.regOut.L1D_PF_ACTIVE_THRESHOLD.asUInt
815  io.out.custom.l1D_pf_active_stride    := spfctl.regOut.L1D_PF_ACTIVE_STRIDE.asUInt
816  io.out.custom.l1D_pf_enable_stride    := spfctl.regOut.L1D_PF_ENABLE_STRIDE.asBool
817  io.out.custom.l2_pf_store_only        := spfctl.regOut.L2_PF_STORE_ONLY.asBool
818
819  io.out.custom.icache_parity_enable    := sfetchctl.regOut.ICACHE_PARITY_ENABLE.asBool
820
821  io.out.custom.lvpred_disable          := slvpredctl.regOut.LVPRED_DISABLE.asBool
822  io.out.custom.no_spec_load            := slvpredctl.regOut.NO_SPEC_LOAD.asBool
823  io.out.custom.storeset_wait_store     := slvpredctl.regOut.STORESET_WAIT_STORE.asBool
824  io.out.custom.storeset_no_fast_wakeup := slvpredctl.regOut.STORESET_NO_FAST_WAKEUP.asBool
825  io.out.custom.lvpred_timeout          := slvpredctl.regOut.LVPRED_TIMEOUT.asUInt
826
827  io.out.custom.bp_ctrl.ubtb_enable     := sbpctl.regOut.UBTB_ENABLE .asBool
828  io.out.custom.bp_ctrl.btb_enable      := sbpctl.regOut.BTB_ENABLE  .asBool
829  io.out.custom.bp_ctrl.bim_enable      := sbpctl.regOut.BIM_ENABLE  .asBool
830  io.out.custom.bp_ctrl.tage_enable     := sbpctl.regOut.TAGE_ENABLE .asBool
831  io.out.custom.bp_ctrl.sc_enable       := sbpctl.regOut.SC_ENABLE   .asBool
832  io.out.custom.bp_ctrl.ras_enable      := sbpctl.regOut.RAS_ENABLE  .asBool
833  io.out.custom.bp_ctrl.loop_enable     := sbpctl.regOut.LOOP_ENABLE .asBool
834
835  io.out.custom.sbuffer_threshold                := smblockctl.regOut.SBUFFER_THRESHOLD.asUInt
836  io.out.custom.ldld_vio_check_enable            := smblockctl.regOut.LDLD_VIO_CHECK_ENABLE.asBool
837  io.out.custom.soft_prefetch_enable             := smblockctl.regOut.SOFT_PREFETCH_ENABLE.asBool
838  io.out.custom.cache_error_enable               := smblockctl.regOut.CACHE_ERROR_ENABLE.asBool
839  io.out.custom.uncache_write_outstanding_enable := smblockctl.regOut.UNCACHE_WRITE_OUTSTANDING_ENABLE.asBool
840
841  io.out.custom.fusion_enable           := srnctl.regOut.FUSION_ENABLE.asBool
842  io.out.custom.wfi_enable              := srnctl.regOut.WFI_ENABLE.asBool
843  io.out.custom.svinval_enable          := srnctl.regOut.SVINVAL_ENABLE.asBool
844
845  // Todo: record the last address to avoid xireg is different with xiselect
846  toAIA.addr.valid := wenLegal && Seq(miselect, siselect, vsiselect).map(
847    _.addr.U === addr
848  ).reduce(_ || _)
849  toAIA.addr.bits.addr := addr
850  toAIA.addr.bits.prvm := PRVM
851  toAIA.addr.bits.v := V
852  toAIA.vgein := hstatus.regOut.VGEIN.asUInt
853  toAIA.wdata.valid := wenLegal && Seq(mireg, sireg, vsireg).map(
854    _.addr.U === addr
855  ).reduce(_ || _)
856  toAIA.wdata.bits.data := wdata
857  toAIA.mClaim := wenLegal && mtopei.addr.U === addr
858  toAIA.sClaim := wenLegal && stopei.addr.U === addr
859  toAIA.vsClaim := wenLegal && vstopei.addr.U === addr
860
861  // tlb
862  io.tlb.satpASIDChanged  := wenLegal && addr === CSRs. satp.U && satp .regOut.ASID =/= wdata.asTypeOf(new SatpBundle).ASID
863  io.tlb.vsatpASIDChanged := wenLegal && addr === CSRs.vsatp.U && vsatp.regOut.ASID =/= wdata.asTypeOf(new SatpBundle).ASID
864  io.tlb.hgatpVMIDChanged := wenLegal && addr === CSRs.hgatp.U && hgatp.regOut.VMID =/= wdata.asTypeOf(new HgatpBundle).VMID
865  io.tlb.satp := satp.rdata
866  io.tlb.vsatp := vsatp.rdata
867  io.tlb.hgatp := hgatp.rdata
868  io.tlb.mxr  :=  mstatus.regOut.MXR.asBool
869  io.tlb.sum  :=  mstatus.regOut.SUM.asBool
870  io.tlb.vmxr := vsstatus.regOut.MXR.asBool
871  io.tlb.vsum := vsstatus.regOut.SUM.asBool
872  io.tlb.spvp :=  hstatus.regOut.SPVP.asBool
873
874  io.tlb.imode := PRVM.asUInt
875  io.tlb.dmode := Mux((debugMode && dcsr.regOut.MPRVEN.asBool || !debugMode) && mstatus.regOut.MPRV.asBool, mstatus.regOut.MPP.asUInt, PRVM.asUInt)
876
877  // Always instantiate basic difftest modules.
878  if (env.AlwaysBasicDiff || env.EnableDifftest) {
879    val hartId = io.fromTop.hartId
880    val trapValid = io.fromRob.trap.valid
881    val trapNO = trapHandleMod.io.out.causeNO.ExceptionCode.asUInt
882    val interrupt = trapHandleMod.io.out.causeNO.Interrupt.asBool
883    val interruptNO = Mux(interrupt, trapNO, 0.U)
884    val exceptionNO = Mux(!interrupt, trapNO, 0.U)
885    val ivmHS = isModeHS &&  satp.regOut.MODE =/= SatpMode.Bare
886    val ivmVS = isModeVS && vsatp.regOut.MODE =/= SatpMode.Bare
887    // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57
888    val exceptionPC = Mux(ivmHS || ivmVS, SignExt(trapPC, XLEN), ZeroExt(trapPC, XLEN))
889
890    val diffArchEvent = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true)
891    diffArchEvent.coreid := hartId
892    diffArchEvent.valid := trapValid
893    diffArchEvent.interrupt := interruptNO
894    diffArchEvent.exception := exceptionNO
895    diffArchEvent.exceptionPC := exceptionPC
896    if (env.EnableDifftest) {
897      diffArchEvent.exceptionInst := io.fromRob.trap.bits.instr
898    }
899
900    val diffCSRState = DifftestModule(new DiffCSRState)
901    diffCSRState.coreid         := hartId
902    diffCSRState.privilegeMode  := privState.PRVM.asUInt
903    diffCSRState.mstatus        := mstatus.rdata.asUInt
904    diffCSRState.sstatus        := mstatus.sstatus.asUInt
905    diffCSRState.mepc           := mepc.rdata.asUInt
906    diffCSRState.sepc           := sepc.rdata.asUInt
907    diffCSRState.mtval          := mtval.rdata.asUInt
908    diffCSRState.stval          := stval.rdata.asUInt
909    diffCSRState.mtvec          := mtvec.rdata.asUInt
910    diffCSRState.stvec          := stvec.rdata.asUInt
911    diffCSRState.mcause         := mcause.rdata.asUInt
912    diffCSRState.scause         := scause.rdata.asUInt
913    diffCSRState.satp           := satp.rdata.asUInt
914    diffCSRState.mip            := mip.regOut.asUInt
915    diffCSRState.mie            := mie.rdata.asUInt
916    diffCSRState.mscratch       := mscratch.rdata.asUInt
917    diffCSRState.sscratch       := sscratch.rdata.asUInt
918    diffCSRState.mideleg        := mideleg.rdata.asUInt
919    diffCSRState.medeleg        := medeleg.rdata.asUInt
920
921    val diffDebugMode = DifftestModule(new DiffDebugMode)
922    diffDebugMode.coreid    := hartId
923    diffDebugMode.debugMode := debugMode
924    diffDebugMode.dcsr      := dcsr.rdata.asUInt
925    diffDebugMode.dpc       := dpc.rdata.asUInt
926    diffDebugMode.dscratch0 := dscratch0.rdata.asUInt
927    diffDebugMode.dscratch1 := dscratch1.rdata.asUInt
928
929    val diffVecCSRState = DifftestModule(new DiffVecCSRState)
930    diffVecCSRState.coreid := hartId
931    diffVecCSRState.vstart := vstart.rdata.asUInt
932    diffVecCSRState.vxsat := vcsr.vxsat.asUInt
933    diffVecCSRState.vxrm := vcsr.vxrm.asUInt
934    diffVecCSRState.vcsr := vcsr.rdata.asUInt
935    diffVecCSRState.vl := vl.rdata.asUInt
936    diffVecCSRState.vtype := vtype.rdata.asUInt
937    diffVecCSRState.vlenb := vlenb.rdata.asUInt
938
939    val diffHCSRState = DifftestModule(new DiffHCSRState)
940    diffHCSRState.coreid      := hartId
941    diffHCSRState.virtMode    := privState.V.asBool
942    diffHCSRState.mtval2      := mtval2.rdata.asUInt
943    diffHCSRState.mtinst      := mtinst.rdata.asUInt
944    diffHCSRState.hstatus     := hstatus.rdata.asUInt
945    diffHCSRState.hideleg     := hideleg.rdata.asUInt
946    diffHCSRState.hedeleg     := hedeleg.rdata.asUInt
947    diffHCSRState.hcounteren  := hcounteren.rdata.asUInt
948    diffHCSRState.htval       := htval.rdata.asUInt
949    diffHCSRState.htinst      := htinst.rdata.asUInt
950    diffHCSRState.hgatp       := hgatp.rdata.asUInt
951    diffHCSRState.vsstatus    := vsstatus.rdata.asUInt
952    diffHCSRState.vstvec      := vstvec.rdata.asUInt
953    diffHCSRState.vsepc       := vsepc.rdata.asUInt
954    diffHCSRState.vscause     := vscause.rdata.asUInt
955    diffHCSRState.vstval      := vstval.rdata.asUInt
956    diffHCSRState.vsatp       := vsatp.rdata.asUInt
957    diffHCSRState.vsscratch   := vsscratch.rdata.asUInt
958
959  }
960}
961
962trait SupervisorMachineAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel =>
963  mip.fromMvip := mvip.toMip
964  mip.fromSip := sip.toMip
965  mie.fromSie := sie.toMie
966}
967
968object NewCSRMain extends App {
969  val (config, firrtlOpts, firtoolOpts) = ArgParser.parse(
970    args :+ "--disable-always-basic-diff" :+ "--dump-fir" :+ "--fpga-platform" :+ "--target" :+ "verilog")
971
972  val defaultConfig = config.alterPartial({
973    // Get XSCoreParams and pass it to the "small module"
974    case XSCoreParamsKey => config(XSTileKey).head
975  })
976
977  Generator.execute(
978    firrtlOpts :+ "--full-stacktrace" :+ "--target-dir" :+ "backend",
979    new NewCSR()(defaultConfig),
980    firtoolOpts
981  )
982
983  println("done")
984}