xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision bbb63ef495edfa8cd3f3d87dcc88e596662b4206)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.ExcitingUtils.ConnectionType
5import chisel3.util._
6import chisel3.util.experimental.BoringUtils
7import fpu.Fflags
8import noop.MMUIO
9import utils._
10import xiangshan._
11import xiangshan.backend._
12import xiangshan.backend.fu.FunctionUnit._
13import utils.XSDebug
14
15trait HasCSRConst {
16  // User Trap Setup
17  val Ustatus       = 0x000
18  val Uie           = 0x004
19  val Utvec         = 0x005
20
21  // User Trap Handling
22  val Uscratch      = 0x040
23  val Uepc          = 0x041
24  val Ucause        = 0x042
25  val Utval         = 0x043
26  val Uip           = 0x044
27
28  // User Floating-Point CSRs (not implemented)
29  val Fflags        = 0x001
30  val Frm           = 0x002
31  val Fcsr          = 0x003
32
33  // User Counter/Timers
34  val Cycle         = 0xC00
35  val Time          = 0xC01
36  val Instret       = 0xC02
37
38  // Supervisor Trap Setup
39  val Sstatus       = 0x100
40  val Sedeleg       = 0x102
41  val Sideleg       = 0x103
42  val Sie           = 0x104
43  val Stvec         = 0x105
44  val Scounteren    = 0x106
45
46  // Supervisor Trap Handling
47  val Sscratch      = 0x140
48  val Sepc          = 0x141
49  val Scause        = 0x142
50  val Stval         = 0x143
51  val Sip           = 0x144
52
53  // Supervisor Protection and Translation
54  val Satp          = 0x180
55
56  // Machine Information Registers
57  val Mvendorid     = 0xF11
58  val Marchid       = 0xF12
59  val Mimpid        = 0xF13
60  val Mhartid       = 0xF14
61
62  // Machine Trap Setup
63  val Mstatus       = 0x300
64  val Misa          = 0x301
65  val Medeleg       = 0x302
66  val Mideleg       = 0x303
67  val Mie           = 0x304
68  val Mtvec         = 0x305
69  val Mcounteren    = 0x306
70
71  // Machine Trap Handling
72  val Mscratch      = 0x340
73  val Mepc          = 0x341
74  val Mcause        = 0x342
75  val Mtval         = 0x343
76  val Mip           = 0x344
77
78  // Machine Memory Protection
79  // TBD
80  val Pmpcfg0       = 0x3A0
81  val Pmpcfg1       = 0x3A1
82  val Pmpcfg2       = 0x3A2
83  val Pmpcfg3       = 0x3A3
84  val PmpaddrBase   = 0x3B0
85
86  // Machine Counter/Timers
87  // Currently, we uses perfcnt csr set instead of standard Machine Counter/Timers
88  // 0xB80 - 0x89F are also used as perfcnt csr
89
90  // Machine Counter Setup (not implemented)
91  // Debug/Trace Registers (shared with Debug Mode) (not implemented)
92  // Debug Mode Registers (not implemented)
93
94  def privEcall  = 0x000.U
95  def privEbreak = 0x001.U
96  def privMret   = 0x302.U
97  def privSret   = 0x102.U
98  def privUret   = 0x002.U
99
100  def ModeM     = 0x3.U
101  def ModeH     = 0x2.U
102  def ModeS     = 0x1.U
103  def ModeU     = 0x0.U
104
105  def IRQ_UEIP  = 0
106  def IRQ_SEIP  = 1
107  def IRQ_MEIP  = 3
108
109  def IRQ_UTIP  = 4
110  def IRQ_STIP  = 5
111  def IRQ_MTIP  = 7
112
113  def IRQ_USIP  = 8
114  def IRQ_SSIP  = 9
115  def IRQ_MSIP  = 11
116
117  val IntPriority = Seq(
118    IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
119    IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
120    IRQ_UEIP, IRQ_USIP, IRQ_UTIP
121  )
122
123  def csrAccessPermissionCheck(addr: UInt, wen: Bool, mode: UInt): Bool = {
124    val readOnly = addr(11,10) === "b11".U
125    val lowestAccessPrivilegeLevel = addr(9,8)
126    mode >= lowestAccessPrivilegeLevel && !(wen && readOnly)
127  }
128}
129
130trait HasExceptionNO {
131  def instrAddrMisaligned = 0
132  def instrAccessFault    = 1
133  def illegalInstr        = 2
134  def breakPoint          = 3
135  def loadAddrMisaligned  = 4
136  def loadAccessFault     = 5
137  def storeAddrMisaligned = 6
138  def storeAccessFault    = 7
139  def ecallU              = 8
140  def ecallS              = 9
141  def ecallM              = 11
142  def instrPageFault      = 12
143  def loadPageFault       = 13
144  def storePageFault      = 15
145
146  val ExcPriority = Seq(
147      breakPoint, // TODO: different BP has different priority
148      instrPageFault,
149      instrAccessFault,
150      illegalInstr,
151      instrAddrMisaligned,
152      ecallM, ecallS, ecallU,
153      storePageFault,
154      loadPageFault,
155      storeAccessFault,
156      loadAccessFault,
157      storeAddrMisaligned,
158      loadAddrMisaligned
159  )
160}
161
162class FpuCsrIO extends XSBundle {
163  val fflags = Output(new Fflags)
164  val isIllegal = Output(Bool())
165  val dirty_fs = Output(Bool())
166  val frm = Input(UInt(3.W))
167}
168
169class CSRIO extends FunctionUnitIO {
170  val cfIn = Input(new CtrlFlow)
171  val redirect = Output(new Redirect)
172  val redirectValid = Output(Bool())
173  val fpu_csr = Flipped(new FpuCsrIO)
174  val cfOut = Output(new CtrlFlow)
175  // from rob
176  val exception = Flipped(ValidIO(new MicroOp))
177  // for exception check
178  val instrValid = Input(Bool())
179  val flushPipe = Output(Bool())
180  // for differential testing
181//  val intrNO = Output(UInt(XLEN.W))
182  val wenFix = Output(Bool())
183}
184
185class CSR extends FunctionUnit(csrCfg) with HasCSRConst{
186  val io = IO(new CSRIO)
187
188  io.cfOut := io.cfIn
189
190  val (valid, src1, src2, func) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.func)
191  def access(valid: Bool, src1: UInt, src2: UInt, func: UInt): UInt = {
192    this.valid := valid
193    this.src1 := src1
194    this.src2 := src2
195    this.func := func
196    io.out.bits
197  }
198
199  // CSR define
200
201  class Priv extends Bundle {
202    val m = Output(Bool())
203    val h = Output(Bool())
204    val s = Output(Bool())
205    val u = Output(Bool())
206  }
207
208  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
209
210  class MstatusStruct extends Bundle {
211    val sd = Output(UInt(1.W))
212
213    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
214    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
215    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
216    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
217
218    val tsr = Output(UInt(1.W))
219    val tw = Output(UInt(1.W))
220    val tvm = Output(UInt(1.W))
221    val mxr = Output(UInt(1.W))
222    val sum = Output(UInt(1.W))
223    val mprv = Output(UInt(1.W))
224    val xs = Output(UInt(2.W))
225    val fs = Output(UInt(2.W))
226    val mpp = Output(UInt(2.W))
227    val hpp = Output(UInt(2.W))
228    val spp = Output(UInt(1.W))
229    val pie = new Priv
230    val ie = new Priv
231    assert(this.getWidth == XLEN)
232  }
233
234  class SatpStruct extends Bundle {
235    val mode = UInt(4.W)
236    val asid = UInt(16.W)
237    val ppn  = UInt(44.W)
238  }
239
240  class Interrupt extends Bundle {
241    val e = new Priv
242    val t = new Priv
243    val s = new Priv
244  }
245
246  // Machine-Level CSRs
247
248  val mtvec = RegInit(UInt(XLEN.W), 0.U)
249  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
250  val mcause = RegInit(UInt(XLEN.W), 0.U)
251  val mtval = RegInit(UInt(XLEN.W), 0.U)
252  val mepc = Reg(UInt(XLEN.W))
253
254  val mie = RegInit(0.U(XLEN.W))
255  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
256  val mipReg  = RegInit(0.U.asTypeOf(new Interrupt).asUInt)
257  val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1)
258  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
259
260  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}
261  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}
262  var extList = List('a', 's', 'i', 'u')
263  if(HasMExtension){ extList = extList :+ 'm'}
264  if(HasCExtension){ extList = extList :+ 'c'}
265  if(HasFPU){ extList = extList ++ List('f', 'd')}
266  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
267  val misa = RegInit(UInt(XLEN.W), misaInitVal)
268  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
269  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
270
271  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
272  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
273  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
274  val mhartid = RegInit(UInt(XLEN.W), 0.U) // the hardware thread running the code
275  val mstatus = RegInit(UInt(XLEN.W), "h00001800".U)
276  // val mstatus = RegInit(UInt(XLEN.W), "h8000c0100".U)
277  // mstatus Value Table
278  // | sd   |
279  // | pad1 |
280  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
281  // | uxl  | hardlinked to 00
282  // | pad0 |
283  // | tsr  |
284  // | tw   |
285  // | tvm  |
286  // | mxr  |
287  // | sum  |
288  // | mprv |
289  // | xs   | 00 |
290  // | fs   | 00 |
291  // | mpp  | 00 |
292  // | hpp  | 00 |
293  // | spp  | 0 |
294  // | pie  | 0000 | pie.h is used as UBE
295  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
296  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
297  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
298    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
299    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
300    mstatusNew
301  }
302
303  val mstatusMask = ~ZeroExt((
304    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
305    GenMask(37) | // MBE
306    GenMask(36) | // SBE
307    GenMask(6)    // UBE
308  ), 64)
309
310  val medeleg = RegInit(UInt(XLEN.W), 0.U)
311  val mideleg = RegInit(UInt(XLEN.W), 0.U)
312  val mscratch = RegInit(UInt(XLEN.W), 0.U)
313
314  val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U)
315  val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U)
316  val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U)
317  val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U)
318  val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U)
319  val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U)
320  val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U)
321  val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U)
322
323  // Superviser-Level CSRs
324
325  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
326  val sstatusWmask = "hc6122".U
327  // Sstatus Write Mask
328  // -------------------------------------------------------
329  //    19           9   5     2
330  // 0  1100 0000 0001 0010 0010
331  // 0  c    0    1    2    2
332  // -------------------------------------------------------
333  val sstatusRmask = sstatusWmask | "h8000000300018000".U
334  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
335  val stvec = RegInit(UInt(XLEN.W), 0.U)
336  // val sie = RegInit(0.U(XLEN.W))
337  val sieMask = "h222".U & mideleg
338  val sipMask  = "h222".U & mideleg
339  val satp = RegInit(0.U(XLEN.W))
340  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
341  val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0
342  // val satp = RegInit(UInt(XLEN.W), 0.U)
343  val sepc = RegInit(UInt(XLEN.W), 0.U)
344  val scause = RegInit(UInt(XLEN.W), 0.U)
345  val stval = Reg(UInt(XLEN.W))
346  val sscratch = RegInit(UInt(XLEN.W), 0.U)
347  val scounteren = RegInit(UInt(XLEN.W), 0.U)
348
349  val tlbBundle = Wire(new TlbCsrBundle)
350  // val sfence    = Wire(new SfenceBundle)
351  tlbBundle.satp := satp.asTypeOf(new SatpStruct)
352  // sfence := 0.U.asTypeOf(new SfenceBundle)
353  BoringUtils.addSource(tlbBundle, "TLBCSRIO")
354  // BoringUtils.addSource(sfence, "SfenceBundle") // FIXME: move to MOU
355
356  // User-Level CSRs
357  val uepc = Reg(UInt(XLEN.W))
358
359  // fcsr
360  class FcsrStruct extends Bundle{
361    val reserved = UInt((XLEN-3-5).W)
362    val frm = UInt(3.W)
363    val fflags = UInt(5.W)
364    assert(this.getWidth == XLEN)
365  }
366  val fcsr = RegInit(0.U(XLEN.W))
367  // set mstatus->sd and mstatus->fs when true
368  val csrw_dirty_fp_state = WireInit(false.B)
369
370  def frm_wfn(wdata: UInt): UInt = {
371    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
372    csrw_dirty_fp_state := true.B
373    fcsrOld.frm := wdata(2,0)
374    fcsrOld.asUInt()
375  }
376  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
377
378  def fflags_wfn(wdata: UInt): UInt = {
379    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
380    csrw_dirty_fp_state := true.B
381    fcsrOld.fflags := wdata(4,0)
382    fcsrOld.asUInt()
383  }
384  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
385
386  def fcsr_wfn(wdata: UInt): UInt = {
387    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
388    csrw_dirty_fp_state := true.B
389    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
390  }
391
392  val fcsrMapping = Map(
393    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn, rfn = fflags_rfn),
394    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
395    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
396  )
397
398  // Atom LR/SC Control Bits
399//  val setLr = WireInit(Bool(), false.B)
400//  val setLrVal = WireInit(Bool(), false.B)
401//  val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
402//  val lr = RegInit(Bool(), false.B)
403//  val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
404//  BoringUtils.addSink(setLr, "set_lr")
405//  BoringUtils.addSink(setLrVal, "set_lr_val")
406//  BoringUtils.addSink(setLrAddr, "set_lr_addr")
407//  BoringUtils.addSource(lr, "lr")
408//  BoringUtils.addSource(lrAddr, "lr_addr")
409//
410//  when(setLr){
411//    lr := setLrVal
412//    lrAddr := setLrAddr
413//  }
414
415  // Hart Priviledge Mode
416  val priviledgeMode = RegInit(UInt(2.W), ModeM)
417
418  // perfcnt
419  val hasPerfCnt = !env.FPGAPlatform
420  val nrPerfCnts = if (hasPerfCnt) 0x80 else 0x3
421  val perfCnts = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
422  val perfCntsLoMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb00 + i, perfCnts(i)))
423  val perfCntsHiMapping = (0 until nrPerfCnts).map(i => MaskedRegMap(0xb80 + i, perfCnts(i)(63, 32)))
424
425  // CSR reg map
426  val mapping = Map(
427
428    // User Trap Setup
429    // MaskedRegMap(Ustatus, ustatus),
430    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
431    // MaskedRegMap(Utvec, utvec),
432
433    // User Trap Handling
434    // MaskedRegMap(Uscratch, uscratch),
435    // MaskedRegMap(Uepc, uepc),
436    // MaskedRegMap(Ucause, ucause),
437    // MaskedRegMap(Utval, utval),
438    // MaskedRegMap(Uip, uip),
439
440    // User Counter/Timers
441    // MaskedRegMap(Cycle, cycle),
442    // MaskedRegMap(Time, time),
443    // MaskedRegMap(Instret, instret),
444
445    // Supervisor Trap Setup
446    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
447
448    // MaskedRegMap(Sedeleg, Sedeleg),
449    // MaskedRegMap(Sideleg, Sideleg),
450    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
451    MaskedRegMap(Stvec, stvec),
452    MaskedRegMap(Scounteren, scounteren),
453
454    // Supervisor Trap Handling
455    MaskedRegMap(Sscratch, sscratch),
456    MaskedRegMap(Sepc, sepc),
457    MaskedRegMap(Scause, scause),
458    MaskedRegMap(Stval, stval),
459    MaskedRegMap(Sip, mip.asUInt, sipMask, MaskedRegMap.Unwritable, sipMask),
460
461    // Supervisor Protection and Translation
462    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
463
464    // Machine Information Registers
465    MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable),
466    MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable),
467    MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable),
468    MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable),
469
470    // Machine Trap Setup
471    // MaskedRegMap(Mstatus, mstatus, "hffffffffffffffee".U, (x=>{printf("mstatus write: %x time: %d\n", x, GTimer()); x})),
472    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
473    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
474    MaskedRegMap(Medeleg, medeleg, "hf3ff".U),
475    MaskedRegMap(Mideleg, mideleg, "h222".U),
476    MaskedRegMap(Mie, mie),
477    MaskedRegMap(Mtvec, mtvec),
478    MaskedRegMap(Mcounteren, mcounteren),
479
480    // Machine Trap Handling
481    MaskedRegMap(Mscratch, mscratch),
482    MaskedRegMap(Mepc, mepc),
483    MaskedRegMap(Mcause, mcause),
484    MaskedRegMap(Mtval, mtval),
485    MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable),
486
487    // Machine Memory Protection
488    MaskedRegMap(Pmpcfg0, pmpcfg0),
489    MaskedRegMap(Pmpcfg1, pmpcfg1),
490    MaskedRegMap(Pmpcfg2, pmpcfg2),
491    MaskedRegMap(Pmpcfg3, pmpcfg3),
492    MaskedRegMap(PmpaddrBase + 0, pmpaddr0),
493    MaskedRegMap(PmpaddrBase + 1, pmpaddr1),
494    MaskedRegMap(PmpaddrBase + 2, pmpaddr2),
495    MaskedRegMap(PmpaddrBase + 3, pmpaddr3)
496
497  ) ++
498    perfCntsLoMapping ++ (if (XLEN == 32) perfCntsHiMapping else Nil) ++
499    (if(HasFPU) fcsrMapping else Nil)
500
501  val addr = src2(11, 0)
502  val rdata = Wire(UInt(XLEN.W))
503  val csri = ZeroExt(io.cfIn.instr(19,15), XLEN) //unsigned imm for csri. [TODO]
504  val wdata = LookupTree(func, List(
505    CSROpType.wrt  -> src1,
506    CSROpType.set  -> (rdata | src1),
507    CSROpType.clr  -> (rdata & (~src1).asUInt()),
508    CSROpType.wrti -> csri,//TODO: csri --> src2
509    CSROpType.seti -> (rdata | csri),
510    CSROpType.clri -> (rdata & (~csri).asUInt())
511  ))
512
513  // satp wen check
514  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
515
516  // general CSR wen check
517  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
518  val permitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
519  // Writeable check is ingored.
520  // Currently, write to illegal csr addr will be ignored
521  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
522  io.out.bits := rdata
523
524  // Fix Mip/Sip write
525  val fixMapping = Map(
526    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
527    MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask)
528  )
529  val rdataDummy = Wire(UInt(XLEN.W))
530  MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata)
531
532  when(io.fpu_csr.fflags.asUInt() =/= 0.U){
533    fcsr := fflags_wfn(io.fpu_csr.fflags.asUInt())
534  }
535  // set fs and sd in mstatus
536  when(csrw_dirty_fp_state || io.fpu_csr.dirty_fs){
537    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
538    mstatusNew.fs := "b11".U
539    mstatusNew.sd := true.B
540    mstatus := mstatusNew.asUInt()
541  }
542  io.fpu_csr.frm := fcsr.asTypeOf(new FcsrStruct).frm
543
544  // CSR inst decode
545  val isEbreak = addr === privEbreak && func === CSROpType.jmp
546  val isEcall = addr === privEcall && func === CSROpType.jmp
547  val isMret = addr === privMret   && func === CSROpType.jmp
548  val isSret = addr === privSret   && func === CSROpType.jmp
549  val isUret = addr === privUret   && func === CSROpType.jmp
550
551  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", io.cfIn.pc, addr, rdata, wdata, func)
552  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
553
554  // Illegal priviledged operation list
555  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
556
557  // Illegal priviledged instruction check
558  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
559  val isIllegalAccess = !permitted
560  val isIllegalPrivOp = illegalSModeSret
561
562  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
563  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
564  // imem
565  // val imemPtev = true.B
566  // val imemPteu = true.B
567  // val imemPtex = true.B
568  // val imemReq = true.B
569  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
570  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
571  // assert(!hasInstrPageFault)
572
573  // dmem
574  // val dmemPtev = true.B
575  // val dmemPteu = true.B
576  // val dmemReq = true.B
577  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
578  // val dmemIsStore = true.B
579
580  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
581  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
582  // assert(!hasLoadPageFault)
583  // assert(!hasStorePageFault)
584
585  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
586  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
587  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
588  tlbBundle.priv.imode := priviledgeMode
589  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
590
591  val hasInstrPageFault = io.exception.bits.cf.exceptionVec(instrPageFault) && io.exception.valid
592  val hasLoadPageFault = io.exception.bits.cf.exceptionVec(loadPageFault) && io.exception.valid
593  val hasStorePageFault = io.exception.bits.cf.exceptionVec(storePageFault) && io.exception.valid
594  val hasStoreAddrMisaligned = io.exception.bits.cf.exceptionVec(storeAddrMisaligned) && io.exception.valid
595  val hasLoadAddrMisaligned = io.exception.bits.cf.exceptionVec(loadAddrMisaligned) && io.exception.valid
596
597  // mtval write logic
598  val lsroqExceptionAddr = WireInit(0.U(VAddrBits.W))
599  if(EnableUnifiedLSQ){
600    ExcitingUtils.addSource(io.exception.bits.lsroqIdx, "EXECPTION_LSROQIDX")
601    ExcitingUtils.addSink(lsroqExceptionAddr, "EXECPTION_VADDR")
602  } else {
603    val lsIdx = WireInit(0.U.asTypeOf(new LSIdx()))
604    lsIdx.lqIdx := io.exception.bits.lqIdx
605    lsIdx.sqIdx := io.exception.bits.sqIdx
606    ExcitingUtils.addSource(lsIdx, "EXECPTION_LSROQIDX")
607    val lqExceptionAddr = WireInit(0.U(VAddrBits.W))
608    val sqExceptionAddr = WireInit(0.U(VAddrBits.W))
609    ExcitingUtils.addSink(lqExceptionAddr, "EXECPTION_LOAD_VADDR")
610    ExcitingUtils.addSink(sqExceptionAddr, "EXECPTION_STORE_VADDR")
611    lsroqExceptionAddr := Mux(CommitType.lsInstIsStore(io.exception.bits.ctrl.commitType), sqExceptionAddr, lqExceptionAddr)
612  }
613
614  val atomExceptionAddr = WireInit(0.U(VAddrBits.W))
615  val atomOverrideXtval = WireInit(false.B)
616  ExcitingUtils.addSink(atomExceptionAddr, "ATOM_EXECPTION_VADDR")
617  ExcitingUtils.addSink(atomOverrideXtval, "ATOM_OVERRIDE_XTVAL")
618  val memExceptionAddr = Mux(atomOverrideXtval, atomExceptionAddr, lsroqExceptionAddr)
619  when(hasInstrPageFault || hasLoadPageFault || hasStorePageFault){
620    val tval = Mux(
621      hasInstrPageFault,
622      Mux(
623        io.exception.bits.cf.crossPageIPFFix,
624        SignExt(io.exception.bits.cf.pc + 2.U, XLEN),
625        SignExt(io.exception.bits.cf.pc, XLEN)
626      ),
627      SignExt(memExceptionAddr, XLEN)
628    )
629    when(priviledgeMode === ModeM){
630      mtval := tval
631    }.otherwise{
632      stval := tval
633    }
634  }
635
636  when(hasLoadAddrMisaligned || hasStoreAddrMisaligned)
637  {
638    mtval := SignExt(memExceptionAddr, XLEN)
639  }
640
641  // Exception and Intr
642
643  // interrupts
644
645  val ideleg =  (mideleg & mip.asUInt)
646  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
647    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
648
649  val intrVecEnable = Wire(Vec(12, Bool()))
650  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
651  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
652  val intrBitSet = intrVec.orR()
653  ExcitingUtils.addSource(intrBitSet, "intrBitSetIDU")
654  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
655  val raiseIntr = intrBitSet && io.exception.valid
656  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", io.exception.bits.cf.pc, intrNO)
657
658  val mtip = WireInit(false.B)
659  val msip = WireInit(false.B)
660  val meip = WireInit(false.B)
661  ExcitingUtils.addSink(mtip, "mtip")
662  ExcitingUtils.addSink(msip, "msip")
663  ExcitingUtils.addSink(meip, "meip")
664  mipWire.t.m := mtip
665  mipWire.s.m := msip
666  mipWire.e.m := meip
667
668  // exceptions
669  val csrExceptionVec = Wire(Vec(16, Bool()))
670  csrExceptionVec.map(_ := false.B)
671  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
672  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
673  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
674  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
675  // Trigger an illegal instr exception when:
676  // * unimplemented csr is being read/written
677  // * csr access is illegal
678  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
679  csrExceptionVec(loadPageFault) := hasLoadPageFault
680  csrExceptionVec(storePageFault) := hasStorePageFault
681  val iduExceptionVec = io.cfIn.exceptionVec
682  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
683  io.cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
684  io.wenFix := DontCare
685
686  val raiseExceptionVec = io.exception.bits.cf.exceptionVec.asUInt()
687  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
688  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
689  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
690  ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
691  ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
692
693  val raiseExceptionIntr = io.exception.valid
694  val retTarget = Wire(UInt(VAddrBits.W))
695  val trapTarget = Wire(UInt(VAddrBits.W))
696  ExcitingUtils.addSource(trapTarget, "trapTarget")
697  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
698  io.redirect := DontCare
699  io.redirectValid := valid && func === CSROpType.jmp && !isEcall
700  io.redirect.target := retTarget
701  io.flushPipe := resetSatp
702
703  XSDebug(io.redirectValid, "redirect to %x, pc=%x\n", io.redirect.target, io.cfIn.pc)
704
705  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",io.exception.bits.cf.pc, intrNO, io.exception.bits.cf.intrVec.asUInt, exceptionNO, raiseExceptionVec.asUInt)
706  XSDebug(raiseExceptionIntr, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", io.exception.bits.cf.pc, mstatus, mideleg, medeleg, priviledgeMode)
707
708  // Branch control
709
710  val deleg = Mux(raiseIntr, mideleg , medeleg)
711  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
712  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
713  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
714
715  trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
716  retTarget := DontCare
717  // val illegalEret = TODO
718
719  when (valid && isMret) {
720    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
721    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
722    mstatusNew.ie.m := mstatusOld.pie.m
723    priviledgeMode := mstatusOld.mpp
724    mstatusNew.pie.m := true.B
725    mstatusNew.mpp := ModeU
726    mstatusNew.mprv := 0.U
727    mstatus := mstatusNew.asUInt
728//    lr := false.B
729    retTarget := mepc(VAddrBits-1, 0)
730  }
731
732  when (valid && isSret && !illegalSModeSret) {
733    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
734    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
735    mstatusNew.ie.s := mstatusOld.pie.s
736    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
737    mstatusNew.pie.s := true.B
738    mstatusNew.spp := ModeU
739    mstatus := mstatusNew.asUInt
740    mstatusNew.mprv := 0.U
741    // lr := false.B
742    retTarget := sepc(VAddrBits-1, 0)
743  }
744
745  when (valid && isUret) {
746    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
747    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
748    // mstatusNew.mpp.m := ModeU //TODO: add mode U
749    mstatusNew.ie.u := mstatusOld.pie.u
750    priviledgeMode := ModeU
751    mstatusNew.pie.u := true.B
752    mstatus := mstatusNew.asUInt
753    retTarget := uepc(VAddrBits-1, 0)
754  }
755
756  when (raiseExceptionIntr) {
757    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
758    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
759
760    when (delegS) {
761      scause := causeNO
762      sepc := SignExt(io.exception.bits.cf.pc, XLEN)
763      mstatusNew.spp := priviledgeMode
764      mstatusNew.pie.s := mstatusOld.ie.s
765      mstatusNew.ie.s := false.B
766      priviledgeMode := ModeS
767      when(tvalWen){stval := 0.U}
768      // trapTarget := stvec(VAddrBits-1. 0)
769    }.otherwise {
770      mcause := causeNO
771      mepc := SignExt(io.exception.bits.cf.pc, XLEN)
772      mstatusNew.mpp := priviledgeMode
773      mstatusNew.pie.m := mstatusOld.ie.m
774      mstatusNew.ie.m := false.B
775      priviledgeMode := ModeM
776      when(tvalWen){mtval := 0.U}
777      // trapTarget := mtvec(VAddrBits-1. 0)
778    }
779
780    mstatus := mstatusNew.asUInt
781  }
782
783  io.in.ready := true.B
784  io.out.valid := valid
785
786
787  XSDebug(io.redirectValid, "Rediret %x raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
788    io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
789  XSDebug(raiseExceptionIntr && delegS, "Red(%d, %x) raiseExcepIntr:%d isSret:%d retTarget:%x sepc:%x delegs:%d deleg:%x cfInpc:%x valid:%d instrValid:%x \n",
790    io.redirectValid, io.redirect.target, raiseExceptionIntr, isSret, retTarget, sepc, delegS, deleg, io.cfIn.pc, valid, io.instrValid)
791  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", io.cfIn.pc)
792
793
794  // perfcnt
795
796  val perfCntList = Map(
797//    "Mcycle"      -> (0xb00, "perfCntCondMcycle"     ),
798//    "Minstret"    -> (0xb02, "perfCntCondMinstret"   ),
799    "MbpInstr"    -> (0xb03, "perfCntCondMbpInstr"   ),
800    "MbpRight"    -> (0xb04, "perfCntCondMbpRight"   ),
801    "MbpWrong"    -> (0xb05, "perfCntCondMbpWrong"   ),
802    "MbpBRight"   -> (0xb06, "perfCntCondMbpBRight"   ),
803    "MbpBWrong"   -> (0xb07, "perfCntCondMbpBWrong"   ),
804    "MbpJRight"   -> (0xb08, "perfCntCondMbpJRight"   ),
805    "MbpJWrong"   -> (0xb09, "perfCntCondMbpJWrong"   ),
806    "MbpIRight"   -> (0xb0a, "perfCntCondMbpIRight"   ),
807    "MbpIWrong"   -> (0xb0b, "perfCntCondMbpIWrong"   ),
808    "MbpRRight"   -> (0xb0c, "perfCntCondMbpRRight"   ),
809    "MbpRWrong"   -> (0xb0d, "perfCntCondMbpRWrong"   ),
810    "DpqReplay"   -> (0xb0e, "perfCntCondDpqReplay"   ),
811    "RoqWalk"     -> (0xb0f, "perfCntCondRoqWalk"     ),
812    "RoqWaitInt"  -> (0xb10, "perfCntCondRoqWaitInt"  ),
813    "RoqWaitFp"   -> (0xb11, "perfCntCondRoqWaitFp"   ),
814    "RoqWaitLoad" -> (0xb12, "perfCntCondRoqWaitLoad" ),
815    "RoqWaitStore"-> (0xb13, "perfCntCondRoqWaitStore"),
816    "Dp1Empty"    -> (0xb14, "perfCntCondDp1Empty"    ),
817    "DTlbReqCnt0" -> (0xb15, "perfCntDtlbReqCnt0"     ),
818    "DTlbReqCnt1" -> (0xb16, "perfCntDtlbReqCnt1"     ),
819    "DTlbReqCnt2" -> (0xb17, "perfCntDtlbReqCnt2"     ),
820    "DTlbReqCnt3" -> (0xb18, "perfCntDtlbReqCnt3"     ),
821    "DTlbMissCnt0"-> (0xb19, "perfCntDtlbMissCnt0"    ),
822    "DTlbMissCnt1"-> (0xb20, "perfCntDtlbMissCnt1"    ),
823    "DTlbMissCnt2"-> (0xb21, "perfCntDtlbMissCnt2"    ),
824    "DTlbMissCnt3"-> (0xb22, "perfCntDtlbMissCnt3"    ),
825    "ITlbReqCnt0" -> (0xb23, "perfCntItlbReqCnt0"     ),
826    "ITlbMissCnt0"-> (0xb24, "perfCntItlbMissCnt0"    ),
827    "PtwReqCnt"   -> (0xb25, "perfCntPtwReqCnt"       ),
828    "PtwCycleCnt" -> (0xb26, "perfCntPtwCycleCnt"     ),
829    "PtwL2TlbHit" -> (0xb27, "perfCntPtwL2TlbHit"     ),
830    "ICacheReq"   -> (0xb28, "perfCntIcacheReqCnt"     ),
831    "ICacheMiss"   -> (0xb29, "perfCntIcacheMissCnt"     )
832//    "Custom1"     -> (0xb1b, "Custom1"             ),
833//    "Custom2"     -> (0xb1c, "Custom2"             ),
834//    "Custom3"     -> (0xb1d, "Custom3"             ),
835//    "Custom4"     -> (0xb1e, "Custom4"             ),
836//    "Custom5"     -> (0xb1f, "Custom5"             ),
837//    "Custom6"     -> (0xb20, "Custom6"             ),
838//    "Custom7"     -> (0xb21, "Custom7"             ),
839//    "Custom8"     -> (0xb22, "Custom8"             ),
840//    "Ml2cacheHit" -> (0xb23, "perfCntCondMl2cacheHit")
841  )
842  val perfCntCond = List.fill(0x80)(WireInit(false.B))
843  (perfCnts zip perfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
844
845//  ExcitingUtils.addSource(WireInit(true.B), "perfCntCondMcycle", ConnectionType.Perf)
846  perfCntList.foreach {
847    case (_, (address, boringId)) =>
848      if(hasPerfCnt){
849        ExcitingUtils.addSink(perfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
850      }
851//      if (!hasPerfCnt) {
852//        // do not enable perfcnts except for Mcycle and Minstret
853//        if (address != perfCntList("Mcycle")._1 && address != perfCntList("Minstret")._1) {
854//          perfCntCond(address & 0x7f) := false.B
855//        }
856//      }
857  }
858
859  val xstrap = WireInit(false.B)
860  if(!env.FPGAPlatform && EnableBPU){
861    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
862  }
863  def readWithScala(addr: Int): UInt = mapping(addr)._1
864
865  if (!env.FPGAPlatform) {
866
867    // display all perfcnt when nooptrap is executed
868    when (xstrap) {
869      printf("======== PerfCnt =========\n")
870      perfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, boringId)) =>
871        printf("%d <- " + str + "\n", readWithScala(address))
872      }
873    }
874
875    // for differential testing
876//    BoringUtils.addSource(RegNext(priviledgeMode), "difftestMode")
877//    BoringUtils.addSource(RegNext(mstatus), "difftestMstatus")
878//    BoringUtils.addSource(RegNext(mstatus & sstatusRmask), "difftestSstatus")
879//    BoringUtils.addSource(RegNext(mepc), "difftestMepc")
880//    BoringUtils.addSource(RegNext(sepc), "difftestSepc")
881//    BoringUtils.addSource(RegNext(mcause), "difftestMcause")
882//    BoringUtils.addSource(RegNext(scause), "difftestScause")
883    BoringUtils.addSource(priviledgeMode, "difftestMode")
884    BoringUtils.addSource(mstatus, "difftestMstatus")
885    BoringUtils.addSource(mstatus & sstatusRmask, "difftestSstatus")
886    BoringUtils.addSource(mepc, "difftestMepc")
887    BoringUtils.addSource(sepc, "difftestSepc")
888    BoringUtils.addSource(mtval, "difftestMtval")
889    BoringUtils.addSource(stval, "difftestStval")
890    BoringUtils.addSource(mtvec, "difftestMtvec")
891    BoringUtils.addSource(stvec, "difftestStvec")
892    BoringUtils.addSource(mcause, "difftestMcause")
893    BoringUtils.addSource(scause, "difftestScause")
894    BoringUtils.addSource(satp, "difftestSatp")
895    BoringUtils.addSource(mipReg, "difftestMip")
896    BoringUtils.addSource(mie, "difftestMie")
897    BoringUtils.addSource(mscratch, "difftestMscratch")
898    BoringUtils.addSource(sscratch, "difftestSscratch")
899    BoringUtils.addSource(mideleg, "difftestMideleg")
900    BoringUtils.addSource(medeleg, "difftestMedeleg")
901  } else {
902//    BoringUtils.addSource(readWithScala(perfCntList("Minstret")._1), "ilaInstrCnt")
903  }
904}
905