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