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