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