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