1package xiangshan.backend.fu.NewCSR 2 3import chisel3._ 4import chisel3.util.BitPat.bitPatToUInt 5import chisel3.util._ 6import freechips.rocketchip.rocket.CSRs 7import utility.{SignExt, ZeroExt} 8import xiangshan.backend.fu.NewCSR.CSRBundles._ 9import xiangshan.backend.fu.NewCSR.CSRDefines.{VirtMode, CSRROField => RO, CSRRWField => RW, CSRWARLField => WARL, CSRWLRLField => WLRL, _} 10import xiangshan.backend.fu.NewCSR.CSREvents.{SretEventSinkBundle, TrapEntryVSEventSinkBundle} 11import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._ 12import xiangshan.backend.fu.NewCSR.CSRBundleImplicitCast._ 13import xiangshan.backend.fu.NewCSR.CSRConfig.PPNLength 14import xiangshan.backend.fu.NewCSR.ChiselRecordForField._ 15 16import scala.collection.immutable.SeqMap 17 18trait VirtualSupervisorLevel { self: NewCSR with SupervisorLevel with HypervisorLevel => 19 20 val vsstatus = Module( 21 new CSRModule("VSstatus", new SstatusBundle) 22 with SretEventSinkBundle 23 with TrapEntryVSEventSinkBundle 24 with HasRobCommitBundle 25 { 26 when ((robCommit.fsDirty || writeFCSR) && isVirtMode) { 27 assert(reg.FS =/= ContextStatus.Off, "The vsstatus.FS should not be Off when set dirty, please check decode") 28 reg.FS := ContextStatus.Dirty 29 } 30 31 when ((robCommit.vsDirty || writeVCSR) && isVirtMode) { 32 assert(reg.VS =/= ContextStatus.Off, "The vsstatus.VS should not be Off when set dirty, please check decode") 33 reg.VS := ContextStatus.Dirty 34 } 35 } 36 ) 37 .setAddr(CSRs.vsstatus) 38 39 val vsie = Module(new CSRModule("VSie", new VSieBundle) 40 with HypervisorBundle 41 with HasIpIeBundle 42 { 43 val toMie = IO(new VSieToMie) 44 val toSie = IO(new VSieToSie) 45 46 val mieIsAlias = hideleg & mideleg 47 val sieIsAlias = hideleg & ~mideleg & mvien 48 val usingReg = ~hideleg & hvien 49 50 val originAliasIE = (mieIsAlias & mie) | (sieIsAlias & sie) 51 val shiftedIE = Cat(originAliasIE(63, InterruptNO.COI), 0.U(1.W), originAliasIE(InterruptNO.SGEI, InterruptNO.SSI)) 52 val shiftedUsingReg = Cat(usingReg(63, InterruptNO.COI), 0.U(1.W), usingReg(InterruptNO.SGEI, InterruptNO.SSI)) 53 54 regOut := 55 shiftedIE | 56 (shiftedUsingReg & reg) 57 58 bundle.getVS.map(_.lsb).foreach { vsNum => 59 // vsie.SSIE(1) map mie.VSSIE(1) 60 val sNum = vsNum - 1 61 val wtMie = toMie.getByNum(vsNum) 62 val wtSie = toSie.getByNum(vsNum) 63 val r = reg(sNum) 64 65 wtMie.specifyField( 66 _.valid := mieIsAlias(vsNum) && wtMie.bits.isRW.B && wen, 67 _.bits := mieIsAlias(vsNum) && wtMie.bits.isRW.B && wen &< wdata(sNum), 68 ) 69 70 wtSie.specifyField( 71 _.valid := sieIsAlias(vsNum) && wtSie.bits.isRW.B && wen, 72 _.bits := sieIsAlias(vsNum) && wtSie.bits.isRW.B && wen &< wdata(sNum), 73 ) 74 75 when (wen && usingReg(vsNum) && r.isRW.B) { 76 r := wdata(sNum) 77 }.otherwise { 78 r := r 79 } 80 } 81 82 bundle.getNonVS.map(_.lsb).foreach { num => 83 val wtMie = toMie.getByNum(num) 84 val wtSie = toSie.getByNum(num) 85 86 val r = reg(num) 87 88 wtMie.specifyField( 89 _.valid := mieIsAlias(num) && wtMie.bits.isRW.B && wen, 90 _.bits := mieIsAlias(num) && wtMie.bits.isRW.B && wen &< wdata(num), 91 ) 92 93 wtSie.specifyField( 94 _.valid := sieIsAlias(num) && wtSie.bits.isRW.B && wen, 95 _.bits := sieIsAlias(num) && wtSie.bits.isRW.B && wen &< wdata(num), 96 ) 97 98 when(wen && usingReg(num) && r.isRW.B) { 99 r := wdata(num) 100 }.otherwise { 101 r := r 102 } 103 } 104 105 regOut.getFields.foreach { field => 106 if (field.isHardWired) { 107 field := field.getHardWireValue 108 } 109 } 110 }).setAddr(CSRs.vsie) 111 112 val vstvec = Module(new CSRModule("VStvec", new XtvecBundle)) 113 .setAddr(CSRs.vstvec) 114 115 val vsscratch = Module(new CSRModule("VSscratch")) 116 .setAddr(CSRs.vsscratch) 117 118 val vsepc = Module( 119 new CSRModule("VSepc", new Epc) 120 with TrapEntryVSEventSinkBundle 121 { 122 rdata := SignExt(Cat(reg.epc.asUInt, 0.U(1.W)), XLEN) 123 } 124 ) 125 .setAddr(CSRs.vsepc) 126 127 val vscause = Module( 128 new CSRModule("VScause", new CauseBundle) 129 with TrapEntryVSEventSinkBundle 130 ) 131 .setAddr(CSRs.vscause) 132 133 // Todo: shrink the width of vstval to the maximum width Virtual Address 134 val vstval = Module( 135 new CSRModule("VStval", new XtvalBundle) 136 with TrapEntryVSEventSinkBundle 137 ) 138 .setAddr(CSRs.vstval) 139 140 val vsip = Module(new CSRModule("VSip", new VSipBundle) 141 with HypervisorBundle 142 with HasIpIeBundle 143 { 144 val toMip = IO(new VSipToMip).connectZeroNonRW 145 val toMvip = IO(new VSipToMvip).connectZeroNonRW 146 val toHvip = IO(new VSipToHvip).connectZeroNonRW 147 148 val originIP = mideleg & hideleg & mip | (~mideleg & hideleg & mvien & mvip) | (~hideleg & hvien & hvip) 149 val shiftedIP = Cat(originIP(63, InterruptNO.COI), 0.U(1.W), originIP(InterruptNO.SGEI, InterruptNO.SSI)) 150 151 regOut := shiftedIP 152 regOut.getM.foreach(_ := 0.U) 153 regOut.getVS.foreach(_ := 0.U) 154 regOut.SGEIP := 0.U 155 156 toHvip.VSSIP.valid := wen && hideleg.VSSI 157 toHvip.VSSIP.bits := wdata.SSIP 158 159 wdata.getLocal lazyZip 160 (toMip.getLocal lazyZip toMvip.getLocal lazyZip toHvip.getLocal) lazyZip 161 (mideleg.getLocal lazyZip hideleg.getLocal lazyZip mvien.getLocal) foreach { 162 case (wLCIP, (toMipLCIP, toMvipLCIP, toHvipLCIP), (midelegBit, hidelegBit, mvienBit)) => 163 toMipLCIP .valid := wen && midelegBit && hidelegBit 164 toMvipLCIP.valid := wen && !midelegBit && hidelegBit && mvienBit 165 toHvipLCIP.valid := wen && !hidelegBit && mvienBit 166 toMipLCIP .bits := wLCIP 167 toMvipLCIP.bits := wLCIP 168 toHvipLCIP.bits := wLCIP 169 } 170 171 regOut.getFields.foreach { field => 172 if (field.isHardWired) { 173 field := field.getHardWireValue 174 } 175 } 176 }).setAddr(CSRs.vsip) 177 178 val vstimecmp = Module(new CSRModule("VStimecmp", new CSRBundle { 179 val vstimecmp = RW(63, 0).withReset(bitPatToUInt(BitPat.Y(64))) 180 })) 181 .setAddr(CSRs.vstimecmp) 182 183 val vsatp = Module(new CSRModule("VSatp", new SatpBundle) with VirtualSupervisorBundle { 184 val ppnMask = Fill(PPNLength, 1.U(1.W)) 185 val ppnMaskHgatpIsBare = ZeroExt(ppnMask.take(PAddrBits - PageOffsetWidth), PPNLength) 186 val ppnMaskHgatpIsSv39x4 = ZeroExt(ppnMask.take(39 + 2 - PageOffsetWidth), PPNLength) 187 val ppnMaskHgatpIsSv48x4 = ZeroExt(ppnMask.take(48 + 2 - PageOffsetWidth), PPNLength) 188 189 val effectivePPNMask = Mux1H(Seq( 190 (hgatp.MODE === HgatpMode.Bare) -> ppnMaskHgatpIsBare, 191 (hgatp.MODE === HgatpMode.Sv39x4) -> ppnMaskHgatpIsSv39x4, 192 (hgatp.MODE === HgatpMode.Sv48x4) -> ppnMaskHgatpIsSv48x4, 193 )) 194 // Ref: 13.2.18. Virtual Supervisor Address Translation and Protection Register (vsatp) 195 // When V=0, a write to vsatp with an unsupported MODE value is either ignored as it is for satp, or the 196 // fields of vsatp are treated as WARL in the normal way. 197 // However, when V=1, a write to satp with an unsupported MODE value is ignored and no write to vsatp is effected. 198 // if satp is written with an unsupported MODE, the entire write has no effect; no fields in satp are modified. 199 // 200 // We treat all circumstances as if V=1. That is if vsatp is written with an unsupported MODE, 201 // the entire write has no effect; no fields in satp are modified. 202 when(wen && wdata.MODE.isLegal) { 203 reg := wdata 204 reg.PPN := wdata.PPN & effectivePPNMask 205 }.elsewhen(wen && !v && !wdata.MODE.isLegal) { 206 reg.PPN := wdata.PPN & effectivePPNMask 207 reg.ASID := wdata.ASID 208 }.otherwise { 209 reg := reg 210 } 211 }).setAddr(CSRs.vsatp) 212 213 val virtualSupervisorCSRMods = Seq( 214 vsstatus, 215 vsie, 216 vstvec, 217 vsscratch, 218 vsepc, 219 vscause, 220 vstval, 221 vsip, 222 vstimecmp, 223 vsatp, 224 ) 225 226 virtualSupervisorCSRMods.foreach(mod => 227 require(mod.addr > 0, s"The address of ${mod.modName} has not been set, you can use setAddr(CSRAddr) to set it.")) 228 229 val virtualSupervisorCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from( 230 virtualSupervisorCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata))) 231 ) 232 233 val virtualSupervisorCSROutMap: SeqMap[Int, UInt] = SeqMap.from( 234 virtualSupervisorCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt)) 235 ) 236 237 import freechips.rocketchip.rocket.CSRs 238 239 val sMapVS = SeqMap( 240 CSRs.sstatus -> CSRs.vsstatus, 241 CSRs.sie -> CSRs.vsie, 242 CSRs.stvec -> CSRs.vstvec, 243 CSRs.sscratch -> CSRs.vsscratch, 244 CSRs.sepc -> CSRs.vsepc, 245 CSRs.scause -> CSRs.vscause, 246 CSRs.stval -> CSRs.vstval, 247 CSRs.sip -> CSRs.vsip, 248 CSRs.stimecmp -> CSRs.vstimecmp, 249 CSRs.siselect -> CSRs.vsiselect, 250 CSRs.sireg -> CSRs.vsireg, 251 CSRs.stopei -> CSRs.vstopei, 252 CSRs.satp -> CSRs.vsatp, 253 CSRs.stopi -> CSRs.vstopi, 254 ) 255 256 val vsMapS: SeqMap[Int, Int] = SeqMap.from(sMapVS.map(x => (x._2 -> x._1))) 257} 258 259class VSipBundle extends InterruptPendingBundle { 260 // All pending bits in vsip are aliases of mip/mvip/hvip or read-only 0 261 this.getM.foreach(_.setHardWired(0.U)) 262 this.getVS.foreach(_.setHardWired(0.U)) 263 this.SGEIP.setHardWired(0.U) 264} 265 266class VSieBundle extends InterruptEnableBundle { 267 this.getLocal.foreach(_.setRW().withReset(0.U)) 268 this.getM .foreach(_.setHardWired(0.U)) 269 this.getVS.foreach(_.setHardWired(0.U)) 270 this.SGEIE.setHardWired(0.U) 271} 272 273class VSipToMvip extends IpValidBundle { 274 this.getLocal.foreach(_.bits.setRW()) 275} 276 277class VSipToHvip extends IpValidBundle { 278 this.VSSIP.bits.setRW() 279 this.getLocal.foreach(_.bits.setRW()) 280} 281 282class VSieToMie extends IeValidBundle { 283 this.getVS.foreach(_.bits.setRW()) 284 this.getLocal.foreach(_.bits.setRW()) 285} 286 287class VSieToSie extends IeValidBundle { 288 this.getVS.foreach(_.bits.setRW()) 289 this.getLocal.foreach(_.bits.setRW()) 290} 291 292class VSipToHip extends Bundle { 293 val SSIP = ValidIO(RW(0)) 294 val STIP = ValidIO(RW(0)) 295 val SEIP = ValidIO(RW(0)) 296} 297 298trait VirtualSupervisorBundle { self: CSRModule[_] => 299 val v = IO(Input(Bool())) 300 val hgatp = IO(Input(new HgatpBundle)) 301} 302