1package xiangshan.backend.fu.NewCSR 2 3import chisel3._ 4import chisel3.util._ 5import freechips.rocketchip.rocket.CSRs 6import org.chipsalliance.cde.config.Parameters 7import top.{ArgParser, Generator} 8import xiangshan.backend.fu.NewCSR.CSRBundles.{PrivState, RobCommitCSR} 9import xiangshan.backend.fu.NewCSR.CSRDefines.{ContextStatus, PrivMode, VirtMode} 10import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ 11import xiangshan.backend.fu.NewCSR.CSREvents.{CSREvents, DretEventSinkBundle, EventUpdatePrivStateOutput, MretEventSinkBundle, SretEventSinkBundle, TrapEntryEventInput, TrapEntryHSEventSinkBundle, TrapEntryMEventSinkBundle, TrapEntryVSEventSinkBundle} 12import xiangshan.backend.fu.fpu.Bundles.Frm 13import xiangshan.backend.fu.vector.Bundles.{Vl, Vxrm, Vxsat} 14import xiangshan.{HasXSParameter, XSCoreParamsKey, XSTileKey} 15 16object CSRConfig { 17 final val GEILEN = 63 18 19 final val ASIDLEN = 16 // the length of ASID of XS implementation 20 21 final val ASIDMAX = 16 // the max value of ASIDLEN defined by spec 22 23 final val HIIDWidth = 12 // support Hvictl[27:16](IID) 24 25 final val VMIDLEN = 14 // the length of VMID of XS implementation 26 27 final val VMIDMAX = 14 // the max value of VMIDLEN defined by spec 28 29 // the width of VGEIN 30 final val VGEINWidth = 6 31 32 final val VaddrMaxWidth = 41 // only Sv39 and Sv39x4 33 34 final val XLEN = 64 // Todo: use XSParams 35 36 final val VLEN = 128 37 38 // Since we need macro to compute the width of CSR field, the input of macro should be the value that can be computed 39 // at compile time. The log2Up function cannot be used as meta-programming function, so we use litral value here 40 // log2Up(128 + 1), hold 0~128 41 final val VlWidth = 8 42} 43 44class NewCSR(implicit val p: Parameters) extends Module 45 with HasXSParameter 46 with MachineLevel 47 with SupervisorLevel 48 with HypervisorLevel 49 with VirtualSupervisorLevel 50 with Unprivileged 51 with CSRAIA 52 with HasExternalInterruptBundle 53 with SupervisorMachineAliasConnect 54 with CSREvents 55 with DebugLevel 56 with CSRCustom 57{ 58 59 import CSRConfig._ 60 61 val io = IO(new Bundle { 62 val in = Input(new Bundle { 63 val wen = Bool() 64 val ren = Bool() 65 val addr = UInt(12.W) 66 val wdata = UInt(64.W) 67 }) 68 val fromMem = Input(new Bundle { 69 val excpVA = UInt(VaddrMaxWidth.W) 70 val excpGPA = UInt(VaddrMaxWidth.W) // Todo: use guest physical address width 71 }) 72 val fromRob = Input(new Bundle { 73 val trap = ValidIO(new Bundle { 74 val pc = UInt(VaddrMaxWidth.W) 75 val instr = UInt(32.W) 76 val trapVec = UInt(64.W) 77 val singleStep = Bool() 78 val crossPageIPFFix = Bool() 79 val isInterrupt = Bool() 80 }) 81 val commit = Input(new RobCommitCSR) 82 }) 83 val mret = Input(Bool()) 84 val sret = Input(Bool()) 85 val dret = Input(Bool()) 86 val wfi = Input(Bool()) 87 88 val out = Output(new Bundle { 89 val EX_II = Bool() 90 val EX_VI = Bool() 91 val flushPipe = Bool() 92 val rData = UInt(64.W) 93 val targetPc = UInt(VaddrMaxWidth.W) 94 val regOut = UInt(64.W) 95 val privState = new PrivState 96 val interrupt = Bool() 97 val wfi_event = Bool() 98 val disableSfence = Bool() 99 // fp 100 val fpState = new Bundle { 101 val off = Bool() 102 val frm = Frm() 103 } 104 // vec 105 val vecState = new Bundle { 106 val vstart = Vl() 107 val vxsat = Vxsat() 108 val vxrm = Vxrm() 109 val vcsr = UInt(XLEN.W) 110 val vl = Vl() 111 val vtype = UInt(XLEN.W) 112 val vlenb = UInt(XLEN.W) 113 val off = Bool() 114 } 115 // perf 116 val isPerfCnt = Bool() 117 // debug 118 val debugMode = Bool() 119 val singleStepFlag = Bool() 120 }) 121 // tlb 122 val tlb = Output(new Bundle { 123 val satp = UInt(XLEN.W) 124 val mxr = Bool() 125 val sum = Bool() 126 val imode = UInt(2.W) 127 val dmode = UInt(2.W) 128 }) 129 // customCtrl 130 val customCtrl = Output(new Bundle { 131 val sbpctl = UInt(XLEN.W) 132 val spfctl = UInt(XLEN.W) 133 val slvpredctl = UInt(XLEN.W) 134 val smblockctl = UInt(XLEN.W) 135 val srnctl = UInt(XLEN.W) 136 val sdsid = UInt(XLEN.W) 137 val sfetchctl = Bool() 138 }) 139 }) 140 141 val toAIA = IO(Output(new CSRToAIABundle)) 142 val fromAIA = IO(Flipped(Output(new AIAToCSRBundle))) 143 144 dontTouch(toAIA) 145 dontTouch(fromAIA) 146 147 val wen = io.in.wen 148 val addr = io.in.addr 149 val wdata = io.in.wdata 150 151 val ren = io.in.ren 152 val raddr = io.in.addr 153 154 val hasTrap = io.fromRob.trap.valid 155 val trapVec = io.fromRob.trap.bits.trapVec 156 val trapPC = io.fromRob.trap.bits.pc 157 val trapIsInterrupt = io.fromRob.trap.bits.isInterrupt 158 val trapIsCrossPageIPF = io.fromRob.trap.bits.crossPageIPFFix 159 160 // CSR Privilege State 161 val PRVM = RegInit(PrivMode(0), PrivMode.M) 162 val V = RegInit(VirtMode(0), VirtMode.Off) 163 val debugMode = RegInit(false.B) 164 165 val permitMod = Module(new CSRPermitModule) 166 167 private val wenLegal = wen && !permitMod.io.out.illegal 168 169 val isCSRAccess = io.in.ren || io.in.wen 170 val isSret = io.sret 171 val isMret = io.mret 172 val isDret = io.dret 173 val isWfi = io.wfi 174 175 var csrRwMap = 176 machineLevelCSRMap ++ 177 supervisorLevelCSRMap ++ 178 hypervisorCSRMap ++ 179 virtualSupervisorCSRMap ++ 180 unprivilegedCSRMap ++ 181 debugCSRMap ++ 182 aiaCSRMap ++ 183 customCSRMap 184 185 val csrMods = 186 machineLevelCSRMods ++ 187 supervisorLevelCSRMods ++ 188 hypervisorCSRMods ++ 189 virtualSupervisorCSRMods ++ 190 unprivilegedCSRMods ++ 191 debugCSRMods ++ 192 aiaCSRMods ++ 193 customCSRMods 194 195 var csrOutMap = 196 machineLevelCSROutMap ++ 197 supervisorLevelCSROutMap ++ 198 hypervisorCSROutMap ++ 199 virtualSupervisorCSROutMap ++ 200 unprivilegedCSROutMap ++ 201 debugCSROutMap ++ 202 aiaCSROutMap ++ 203 customCSROutMap 204 205 val trapHandleMod = Module(new TrapHandleModule) 206 207 trapHandleMod.io.in.trapInfo.valid := hasTrap 208 trapHandleMod.io.in.trapInfo.bits.trapVec := trapVec.asUInt 209 trapHandleMod.io.in.trapInfo.bits.isInterrupt := trapIsInterrupt 210 trapHandleMod.io.in.privState.PRVM := PRVM 211 trapHandleMod.io.in.privState.V := V 212 trapHandleMod.io.in.mideleg := mideleg.regOut 213 trapHandleMod.io.in.medeleg := medeleg.regOut 214 trapHandleMod.io.in.hideleg := hideleg.regOut 215 trapHandleMod.io.in.hedeleg := hedeleg.regOut 216 trapHandleMod.io.in.mtvec := mtvec.regOut 217 trapHandleMod.io.in.stvec := stvec.regOut 218 trapHandleMod.io.in.vstvec := vstvec.regOut 219 220 val entryPrivState = trapHandleMod.io.out.entryPrivState 221 222 for ((id, (wBundle, _)) <- csrRwMap) { 223 wBundle.wen := wenLegal && addr === id.U 224 wBundle.wdata := wdata 225 } 226 227 // Todo: support set dirty only when fcsr has changed 228 private val writeFpState = wenLegal && Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _) 229 private val writeVecState = wenLegal && Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _) 230 231 permitMod.io.in.csrAccess.valid := isCSRAccess 232 permitMod.io.in.csrAccess.bits.wen := wen 233 permitMod.io.in.csrAccess.bits.addr := addr 234 235 permitMod.io.in.privState.V := V 236 permitMod.io.in.privState.PRVM := PRVM 237 238 permitMod.io.in.mret := isMret 239 permitMod.io.in.sret := isSret 240 241 permitMod.io.in.status.tsr := false.B 242 permitMod.io.in.status.vtsr := false.B 243 244 csrMods.foreach { mod => 245 mod match { 246 case m: HypervisorBundle => 247 m.hstatus := hstatus.regOut 248 m.hvip := hvip.regOut 249 m.hideleg := hideleg.regOut 250 m.hedeleg := hedeleg.regOut 251 m.hgeip := hgeip.regOut 252 m.hgeie := hgeie.regOut 253 m.hip := hip.regOut 254 m.hie := hie.regOut 255 case _ => 256 } 257 mod match { 258 case m: HasMachineInterruptBundle => 259 m.mvien := mvien.regOut 260 m.mvip := mvip.regOut 261 m.mip := mip.regOut 262 m.mie := mie.regOut 263 case _ => 264 } 265 mod match { 266 case m: HasMachineDelegBundle => 267 m.mideleg := mideleg.regOut 268 m.medeleg := medeleg.regOut 269 case _ => 270 } 271 mod match { 272 case m: HasMachineCounterControlBundle => 273 m.mcountinhibit := mcountinhibit.regOut 274 case _ => 275 } 276 mod match { 277 case m: HasExternalInterruptBundle => 278 m.platformIRP := this.platformIRP 279 case _ => 280 } 281 mod match { 282 case m: HasRobCommitBundle => 283 m.robCommit := io.fromRob.commit 284 m.robCommit.fsDirty := io.fromRob.commit.fsDirty || writeFpState 285 m.robCommit.vsDirty := io.fromRob.commit.vsDirty || writeVecState 286 case _ => 287 } 288 mod match { 289 case m: TrapEntryMEventSinkBundle => 290 m.trapToM := trapEntryMEvent.out 291 case _ => 292 } 293 mod match { 294 case m: TrapEntryHSEventSinkBundle => 295 m.trapToHS := trapEntryHSEvent.out 296 case _ => 297 } 298 mod match { 299 case m: TrapEntryVSEventSinkBundle => 300 m.trapToVS := trapEntryVSEvent.out 301 case _ => 302 } 303 mod match { 304 case m: MretEventSinkBundle => 305 m.retFromM := mretEvent.out 306 case _ => 307 } 308 mod match { 309 case m: SretEventSinkBundle => 310 m.retFromS := sretEvent.out 311 case _ => 312 } 313 mod match { 314 case m: DretEventSinkBundle => 315 m.retFromD := dretEvent.out 316 case _ => 317 } 318 mod match { 319 case m: HasAIABundle => 320 m.aiaToCSR.rdata.valid := fromAIA.rdata.valid 321 m.aiaToCSR.rdata.bits.data := fromAIA.rdata.bits.data 322 m.aiaToCSR.rdata.bits.illegal := fromAIA.rdata.bits.illegal 323 m.aiaToCSR.mtopei.valid := fromAIA.mtopei.valid 324 m.aiaToCSR.stopei.valid := fromAIA.stopei.valid 325 m.aiaToCSR.vstopei.valid := fromAIA.vstopei.valid 326 m.aiaToCSR.mtopei.bits := fromAIA.mtopei.bits 327 m.aiaToCSR.stopei.bits := fromAIA.stopei.bits 328 m.aiaToCSR.vstopei.bits := fromAIA.vstopei.bits 329 case _ => 330 } 331 } 332 333 csrMods.foreach { mod => 334 mod.commonIn.status := mstatus.mstatus 335 mod.commonIn.prvm := PRVM 336 mod.commonIn.v := V 337 mod.commonIn.hstatus := hstatus.rdata 338 println(s"${mod.modName}: ") 339 println(mod.dumpFields) 340 } 341 342 trapEntryMEvent.valid := entryPrivState.isModeM 343 trapEntryHSEvent.valid := entryPrivState.isModeHS 344 trapEntryVSEvent.valid := entryPrivState.isModeVS 345 346 Seq(trapEntryMEvent, trapEntryHSEvent, trapEntryVSEvent).foreach { eMod => 347 eMod.in match { 348 case in: TrapEntryEventInput => 349 in.causeNO := trapHandleMod.io.out.causeNO 350 in.trapPc := trapPC 351 in.isCrossPageIPF := trapIsCrossPageIPF 352 353 in.iMode.PRVM := PRVM 354 in.iMode.V := V 355 in.dMode.PRVM := Mux(mstatus.rdata.MPRV.asBool, mstatus.rdata.MPP, PRVM) 356 in.dMode.V := Mux(mstatus.rdata.MPRV.asBool, mstatus.rdata.MPV, V) 357 358 in.privState.PRVM := PRVM 359 in.privState.V := V 360 in.mstatus := mstatus.regOut 361 in.hstatus := hstatus.regOut 362 in.sstatus := mstatus.sstatus 363 in.vsstatus := vsstatus.regOut 364 in.pcFromXtvec := trapHandleMod.io.out.pcFromXtvec 365 366 in.satp := satp.rdata 367 in.vsatp := vsatp.rdata 368 369 in.memExceptionVAddr := io.fromMem.excpVA 370 in.memExceptionGPAddr := io.fromMem.excpGPA 371 } 372 } 373 374 mretEvent.valid := isMret 375 mretEvent.in match { 376 case in => 377 in.mstatus := mstatus.regOut 378 in.mepc := mepc.regOut 379 } 380 381 sretEvent.valid := isSret 382 sretEvent.in match { 383 case in => 384 in.privState.PRVM := PRVM 385 in.privState.V := V 386 in.sstatus := mstatus.sstatus 387 in.hstatus := hstatus.regOut 388 in.vsstatus := vsstatus.regOut 389 in.sepc := sepc.regOut 390 in.vsepc := vsepc.regOut 391 } 392 393 dretEvent.valid := isDret 394 dretEvent.in match { 395 case in => 396 in.dcsr := dcsr.regOut 397 in.dpc := dpc.regOut 398 in.mstatus := mstatus.regOut 399 } 400 401 PRVM := MuxCase( 402 PRVM, 403 events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map { 404 x => x.out match { 405 case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.PRVM) 406 } 407 } 408 ) 409 410 V := MuxCase( 411 V, 412 events.filter(_.out.isInstanceOf[EventUpdatePrivStateOutput]).map { 413 x => x.out match { 414 case xx: EventUpdatePrivStateOutput => (xx.privState.valid -> xx.privState.bits.V) 415 } 416 } 417 ) 418 419 // perf 420 val addrInPerfCnt = (addr >= CSRs.mcycle.U) && (addr <= CSRs.mhpmcounter31.U) || 421 (addr >= mcountinhibit.addr.U) && (addr <= mhpmevents.last.addr.U) || 422 (addr >= CSRs.cycle.U) && (addr <= CSRs.hpmcounter31.U) || 423 (addr === CSRs.mip.U) || 424 (addr === CSRs.hip.U) 425 // Todo: may be vsip and sip 426 427 // flush 428 val resetSatp = addr === satp.addr.U && wenLegal // write to satp will cause the pipeline be flushed 429 430 val wFcsrChangeRM = addr === fcsr.addr.U && wenLegal && wdata(7, 5) =/= fcsr.frm 431 val wFrmChangeRM = addr === CSRs.frm.U && wenLegal && wdata(2, 0) =/= fcsr.frm 432 val frmChange = wFcsrChangeRM || wFrmChangeRM 433 434 val wVcsrChangeRM = addr === CSRs.vcsr.U && wenLegal && wdata(2, 1) =/= vcsr.vxrm 435 val wVxrmChangeRM = addr === CSRs.vxrm.U && wenLegal && wdata(1, 0) =/= vcsr.vxrm 436 val vxrmChange = wVcsrChangeRM || wVxrmChangeRM 437 438 val flushPipe = resetSatp || frmChange || vxrmChange 439 440 // debug 441 val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable 442 debugMode := dretEvent.out.debugMode 443 debugIntrEnable := dretEvent.out.debugIntrEnable 444 val debugIntr = platformIRP.debugIP && debugIntrEnable 445 446 // interrupt 447 val disableInterrupt = debugMode || (dcsr.rdata.STEP.asBool && !dcsr.rdata.STEPIE.asBool) 448 val ideleg = mideleg.rdata.asUInt & mip.rdata.asUInt 449 def priviledgeEnableDetect(x: Bool): Bool = Mux(x, ((PRVM === PrivMode.S) && mstatus.rdata.SIE.asBool) || (PRVM < PrivMode.S), 450 ((PRVM === PrivMode.M) && mstatus.rdata.MIE.asBool) || (PRVM < PrivMode.M)) 451 452 val intrVecEnable = Wire(Vec(12, Bool())) 453 intrVecEnable.zip(ideleg.asBools).map{ case(x, y) => x := priviledgeEnableDetect(y) && !disableInterrupt} 454 val intrVec = Cat(debugIntr && !debugMode, mie.rdata.asUInt(11, 0) & mip.rdata.asUInt & intrVecEnable.asUInt) // Todo: asUInt(11,0) is ok? 455 val intrBitSet = intrVec.orR 456 457 // fence 458 // csr access check, special case 459 val tvmNotPermit = PRVM === PrivMode.S && mstatus.rdata.TVM.asBool 460 461 private val rdata = Mux1H(csrRwMap.map { case (id, (_, rBundle)) => 462 (raddr === id.U) -> rBundle.asUInt 463 }) 464 465 private val regOut = Mux1H(csrOutMap.map { case (id, regOut) => 466 (raddr === id.U) -> regOut 467 }) 468 469 private val hasEvent = mretEvent.out.targetPc.valid || sretEvent.out.targetPc.valid || dretEvent.out.targetPc.valid || 470 trapEntryMEvent.out.targetPc.valid || trapEntryHSEvent.out.targetPc.valid || trapEntryVSEvent.out.targetPc.valid 471 472 io.out.EX_II := false.B // Todo 473 io.out.EX_VI := false.B // Todo 474 io.out.flushPipe := flushPipe 475 476 io.out.rData := Mux(ren, rdata, 0.U) 477 io.out.regOut := regOut 478 io.out.targetPc := RegEnable(Mux1H(Seq( 479 mretEvent.out.targetPc.valid -> mretEvent.out.targetPc.bits, 480 sretEvent.out.targetPc.valid -> sretEvent.out.targetPc.bits, 481 dretEvent.out.targetPc.valid -> dretEvent.out.targetPc.bits, 482 trapEntryMEvent.out.targetPc.valid -> trapEntryMEvent.out.targetPc.bits, 483 trapEntryHSEvent.out.targetPc.valid -> trapEntryHSEvent.out.targetPc.bits, 484 trapEntryVSEvent.out.targetPc.valid -> trapEntryVSEvent.out.targetPc.bits, 485 )), hasEvent) 486 487 io.out.privState.PRVM := PRVM 488 io.out.privState.V := V 489 490 io.out.fpState.frm := fcsr.frm 491 io.out.fpState.off := mstatus.rdata.FS === ContextStatus.Off 492 io.out.vecState.vstart := vstart.rdata.asUInt 493 io.out.vecState.vxsat := vcsr.vxsat 494 io.out.vecState.vxrm := vcsr.vxrm 495 io.out.vecState.vcsr := vcsr.rdata.asUInt 496 io.out.vecState.vl := vl.rdata.asUInt 497 io.out.vecState.vtype := vtype.rdata.asUInt // Todo: check correct 498 io.out.vecState.vlenb := vlenb.rdata.asUInt 499 io.out.vecState.off := mstatus.rdata.VS === ContextStatus.Off 500 io.out.isPerfCnt := addrInPerfCnt 501 io.out.interrupt := intrBitSet 502 io.out.wfi_event := debugIntr || (mie.rdata.asUInt & mip.rdata.asUInt).orR 503 io.out.debugMode := debugMode 504 io.out.disableSfence := tvmNotPermit || PRVM === PrivMode.U 505 io.out.singleStepFlag := !debugMode && dcsr.rdata.STEP 506 507 // Todo: record the last address to avoid xireg is different with xiselect 508 toAIA.addr.valid := isCSRAccess && Seq(miselect, siselect, vsiselect).map( 509 _.addr.U === addr 510 ).reduce(_ || _) 511 toAIA.addr.bits.addr := addr 512 toAIA.addr.bits.prvm := PRVM 513 toAIA.addr.bits.v := V 514 toAIA.vgein := hstatus.rdata.VGEIN.asUInt 515 toAIA.wdata.valid := isCSRAccess && Seq(mireg, sireg, vsireg).map( 516 _.addr.U === addr 517 ).reduce(_ || _) 518 toAIA.wdata.bits.data := wdata 519 toAIA.mClaim := isCSRAccess && mtopei.addr.U === addr 520 toAIA.sClaim := isCSRAccess && stopei.addr.U === addr 521 toAIA.vsClaim := isCSRAccess && vstopei.addr.U === addr 522 523 // tlb 524 io.tlb.satp := satp.rdata.asUInt 525 io.tlb.mxr := mstatus.rdata.MXR.asBool 526 io.tlb.sum := mstatus.rdata.SUM.asBool 527 io.tlb.imode := PRVM.asUInt 528 io.tlb.dmode := Mux((debugMode && dcsr.rdata.MPRVEN.asBool || !debugMode) && mstatus.rdata.MPRV.asBool, mstatus.rdata.MPP.asUInt, PRVM.asUInt) 529 530 // customCtrl 531 io.customCtrl.sbpctl := sbpctl.rdata.asUInt 532 io.customCtrl.spfctl := spfctl.rdata.asUInt 533 io.customCtrl.slvpredctl := slvpredctl.rdata.asUInt 534 io.customCtrl.smblockctl := smblockctl.rdata.asUInt 535 io.customCtrl.srnctl := srnctl.rdata.asUInt 536 io.customCtrl.sdsid := sdsid.rdata.asUInt 537 io.customCtrl.sfetchctl := sfetchctl.rdata.ICACHE_PARITY_ENABLE.asBool 538} 539 540trait SupervisorMachineAliasConnect { self: NewCSR with MachineLevel with SupervisorLevel => 541 mip.fromMvip := mvip.toMip 542 mip.fromSip := sip.toMip 543 mie.fromSie := sie.toMie 544} 545 546object NewCSRMain extends App { 547 val (config, firrtlOpts, firtoolOpts) = ArgParser.parse( 548 args :+ "--disable-always-basic-diff" :+ "--dump-fir" :+ "--fpga-platform" :+ "--target" :+ "verilog") 549 550 val defaultConfig = config.alterPartial({ 551 // Get XSCoreParams and pass it to the "small module" 552 case XSCoreParamsKey => config(XSTileKey).head 553 }) 554 555 Generator.execute( 556 firrtlOpts :+ "--full-stacktrace" :+ "--target-dir" :+ "backend", 557 new NewCSR()(defaultConfig), 558 firtoolOpts 559 ) 560 561 println("done") 562}