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