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