1*c699b48aSwangkaifanpackage device 2*c699b48aSwangkaifan 3*c699b48aSwangkaifanimport chisel3._ 4*c699b48aSwangkaifanimport chisel3.util._ 5*c699b48aSwangkaifanimport chipsalliance.rocketchip.config._ 6*c699b48aSwangkaifanimport freechips.rocketchip.diplomacy._ 7*c699b48aSwangkaifanimport utils.MaskExpand 8*c699b48aSwangkaifanimport utils.{HasTLDump, XSDebug, RegMap} 9*c699b48aSwangkaifan 10*c699b48aSwangkaifan/* base + 0x000000: Reserved (interrupt source 0 does not exist) 11*c699b48aSwangkaifan base + 0x000004: Interrupt source 1 priority 12*c699b48aSwangkaifan base + 0x000008: Interrupt source 2 priority 13*c699b48aSwangkaifan ... 14*c699b48aSwangkaifan base + 0x000FFC: Interrupt source 1023 priority 15*c699b48aSwangkaifan base + 0x001000: Interrupt Pending bit 0-31 16*c699b48aSwangkaifan base + 0x00107C: Interrupt Pending bit 992-1023 17*c699b48aSwangkaifan ... 18*c699b48aSwangkaifan base + 0x002000: Enable bits for sources 0-31 on context 0 19*c699b48aSwangkaifan base + 0x002004: Enable bits for sources 32-63 on context 0 20*c699b48aSwangkaifan ... 21*c699b48aSwangkaifan base + 0x00207F: Enable bits for sources 992-1023 on context 0 22*c699b48aSwangkaifan base + 0x002080: Enable bits for sources 0-31 on context 1 23*c699b48aSwangkaifan base + 0x002084: Enable bits for sources 32-63 on context 1 24*c699b48aSwangkaifan ... 25*c699b48aSwangkaifan base + 0x0020FF: Enable bits for sources 992-1023 on context 1 26*c699b48aSwangkaifan base + 0x002100: Enable bits for sources 0-31 on context 2 27*c699b48aSwangkaifan base + 0x002104: Enable bits for sources 32-63 on context 2 28*c699b48aSwangkaifan ... 29*c699b48aSwangkaifan base + 0x00217F: Enable bits for sources 992-1023 on context 2 30*c699b48aSwangkaifan ... 31*c699b48aSwangkaifan base + 0x1F1F80: Enable bits for sources 0-31 on context 15871 32*c699b48aSwangkaifan base + 0x1F1F84: Enable bits for sources 32-63 on context 15871 33*c699b48aSwangkaifan base + 0x1F1FFF: Enable bits for sources 992-1023 on context 15871 34*c699b48aSwangkaifan ... 35*c699b48aSwangkaifan base + 0x1FFFFC: Reserved 36*c699b48aSwangkaifan base + 0x200000: Priority threshold for context 0 37*c699b48aSwangkaifan base + 0x200004: Claim/complete for context 0 38*c699b48aSwangkaifan base + 0x200008: Reserved 39*c699b48aSwangkaifan ... 40*c699b48aSwangkaifan base + 0x200FFC: Reserved 41*c699b48aSwangkaifan base + 0x201000: Priority threshold for context 1 42*c699b48aSwangkaifan base + 0x201004: Claim/complete for context 1 43*c699b48aSwangkaifan ... 44*c699b48aSwangkaifan base + 0x3FFE000: Priority threshold for context 15871 45*c699b48aSwangkaifan base + 0x3FFE004: Claim/complete for context 15871 46*c699b48aSwangkaifan base + 0x3FFE008: Reserved 47*c699b48aSwangkaifan ... 48*c699b48aSwangkaifan base + 0x3FFFFFC: Reserved */ 49*c699b48aSwangkaifan 50*c699b48aSwangkaifanobject PLICConsts 51*c699b48aSwangkaifan{ 52*c699b48aSwangkaifan def maxDevices = 1023 53*c699b48aSwangkaifan def maxHarts = 15872 54*c699b48aSwangkaifan def priorityBase = 0x0 55*c699b48aSwangkaifan def pendingBase = 0x1000 56*c699b48aSwangkaifan def enableBase = 0x2000 57*c699b48aSwangkaifan def hartBase = 0x200000 58*c699b48aSwangkaifan 59*c699b48aSwangkaifan def claimOffset = 4 60*c699b48aSwangkaifan def priorityBytes = 4 61*c699b48aSwangkaifan 62*c699b48aSwangkaifan def enableOffset(i: Int) = i * ((maxDevices+7)/8) 63*c699b48aSwangkaifan def hartOffset(i: Int) = i * 0x1000 64*c699b48aSwangkaifan def enableBase(i: Int):Int = enableOffset(i) + enableBase 65*c699b48aSwangkaifan def hartBase(i: Int):Int = hartOffset(i) + hartBase 66*c699b48aSwangkaifan 67*c699b48aSwangkaifan def size(maxHarts: Int): Int = { 68*c699b48aSwangkaifan require(maxHarts > 0 && maxHarts <= maxHarts, s"Must be: maxHarts=$maxHarts > 0 && maxHarts <= PLICConsts.maxHarts=${PLICConsts.maxHarts}") 69*c699b48aSwangkaifan 1 << log2Ceil(hartBase(maxHarts)) 70*c699b48aSwangkaifan } 71*c699b48aSwangkaifan 72*c699b48aSwangkaifan require(hartBase >= enableBase(maxHarts)) 73*c699b48aSwangkaifan} 74*c699b48aSwangkaifan 75*c699b48aSwangkaifanclass PlicIO extends Bundle with xiangshan.HasXSParameter { 76*c699b48aSwangkaifan val intrVec = Input(UInt(NrExtIntr.W)) 77*c699b48aSwangkaifan val meip = Output(Vec(top.Parameters.get.socParameters.NumCores, Bool())) 78*c699b48aSwangkaifan} 79*c699b48aSwangkaifan 80*c699b48aSwangkaifanclass AXI4Plic 81*c699b48aSwangkaifan( 82*c699b48aSwangkaifan sim: Boolean = false, 83*c699b48aSwangkaifan address: Seq[AddressSet] 84*c699b48aSwangkaifan)(implicit p: Parameters) 85*c699b48aSwangkaifan extends AXI4SlaveModule(address, executable = false, _extra = new PlicIO) with xiangshan.HasXSParameter 86*c699b48aSwangkaifan{ 87*c699b48aSwangkaifan override lazy val module = new AXI4SlaveModuleImp[PlicIO](this) { 88*c699b48aSwangkaifan val NumCores = top.Parameters.get.socParameters.NumCores 89*c699b48aSwangkaifan require(NrExtIntr <= PLICConsts.maxDevices) 90*c699b48aSwangkaifan require(NumCores <= PLICConsts.maxHarts) 91*c699b48aSwangkaifan val addressSpaceSize = 0x4000000 92*c699b48aSwangkaifan val addressBits = log2Up(addressSpaceSize) 93*c699b48aSwangkaifan 94*c699b48aSwangkaifan def getOffset(addr: UInt) = addr(addressBits - 1, 0) 95*c699b48aSwangkaifan 96*c699b48aSwangkaifan val priority = List.fill(NrExtIntr)(Reg(UInt(32.W))) 97*c699b48aSwangkaifan val priorityMap = priority.zipWithIndex.map { case (r, intr) => RegMap((intr + 1) * 4, r) }.toMap 98*c699b48aSwangkaifan 99*c699b48aSwangkaifan val nrIntrWord = (NrExtIntr + 31) / 32 // roundup 100*c699b48aSwangkaifan // pending bits are updated in the unit of bit by PLIC, 101*c699b48aSwangkaifan // so define it as vectors of bits, instead of UInt(32.W) 102*c699b48aSwangkaifan val pending = List.fill(nrIntrWord)(RegInit(0.U.asTypeOf(Vec(32, Bool())))) 103*c699b48aSwangkaifan val pendingMap = pending.zipWithIndex.map { case (r, intrWord) => 104*c699b48aSwangkaifan RegMap(0x1000 + intrWord * 4, Cat(r.reverse), RegMap.Unwritable) 105*c699b48aSwangkaifan }.toMap 106*c699b48aSwangkaifan 107*c699b48aSwangkaifan val enable = List.fill(NumCores)(List.fill(nrIntrWord)(RegInit(0.U(32.W)))) 108*c699b48aSwangkaifan val enableMap = enable.zipWithIndex.map { case (l, hart) => 109*c699b48aSwangkaifan l.zipWithIndex.map { case (r, intrWord) => RegMap(0x2000 + hart * 0x80 + intrWord * 4, r) } 110*c699b48aSwangkaifan }.reduce(_ ++ _).toMap 111*c699b48aSwangkaifan 112*c699b48aSwangkaifan val threshold = List.fill(NumCores)(Reg(UInt(32.W))) 113*c699b48aSwangkaifan val thresholdMap = threshold.zipWithIndex.map { 114*c699b48aSwangkaifan case (r, hart) => RegMap(0x200000 + hart * 0x1000, r) 115*c699b48aSwangkaifan }.toMap 116*c699b48aSwangkaifan 117*c699b48aSwangkaifan val inHandle = RegInit(0.U.asTypeOf(Vec(NrExtIntr + 1, Bool()))) 118*c699b48aSwangkaifan 119*c699b48aSwangkaifan def completionFn(wdata: UInt) = { 120*c699b48aSwangkaifan inHandle(wdata(31, 0)) := false.B 121*c699b48aSwangkaifan 0.U 122*c699b48aSwangkaifan } 123*c699b48aSwangkaifan 124*c699b48aSwangkaifan val claimCompletion = List.fill(NumCores)(Reg(UInt(32.W))) 125*c699b48aSwangkaifan val claimCompletionMap = claimCompletion.zipWithIndex.map { 126*c699b48aSwangkaifan case (r, hart) => { 127*c699b48aSwangkaifan val addr = 0x200004 + hart * 0x1000 128*c699b48aSwangkaifan when(in.r.fire() && (getOffset(raddr) === addr.U)) { 129*c699b48aSwangkaifan inHandle(r) := true.B 130*c699b48aSwangkaifan } 131*c699b48aSwangkaifan RegMap(addr, r, completionFn) 132*c699b48aSwangkaifan } 133*c699b48aSwangkaifan }.toMap 134*c699b48aSwangkaifan 135*c699b48aSwangkaifan io.extra.get.intrVec.asBools.zipWithIndex.map { case (intr, i) => { 136*c699b48aSwangkaifan val id = i + 1 137*c699b48aSwangkaifan when(intr) { 138*c699b48aSwangkaifan pending(id / 32)(id % 32) := true.B 139*c699b48aSwangkaifan } 140*c699b48aSwangkaifan when(inHandle(id)) { 141*c699b48aSwangkaifan pending(id / 32)(id % 32) := false.B 142*c699b48aSwangkaifan } 143*c699b48aSwangkaifan } 144*c699b48aSwangkaifan } 145*c699b48aSwangkaifan 146*c699b48aSwangkaifan val pendingVec = Cat(pending.map(x => Cat(x.reverse))) 147*c699b48aSwangkaifan claimCompletion.zipWithIndex.map { case (r, hart) => { 148*c699b48aSwangkaifan val takenVec = pendingVec & Cat(enable(hart)) 149*c699b48aSwangkaifan r := Mux(takenVec === 0.U, 0.U, PriorityEncoder(takenVec)) 150*c699b48aSwangkaifan } 151*c699b48aSwangkaifan } 152*c699b48aSwangkaifan 153*c699b48aSwangkaifan val mapping = priorityMap ++ pendingMap ++ enableMap ++ thresholdMap ++ claimCompletionMap 154*c699b48aSwangkaifan 155*c699b48aSwangkaifan val rdata = Wire(UInt(32.W)) 156*c699b48aSwangkaifan RegMap.generate(mapping, getOffset(raddr), rdata, 157*c699b48aSwangkaifan getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(in.w.bits.strb >> waddr(2, 0))) 158*c699b48aSwangkaifan // narrow read 159*c699b48aSwangkaifan in.r.bits.data := Fill(2, rdata) 160*c699b48aSwangkaifan 161*c699b48aSwangkaifan io.extra.get.meip.zipWithIndex.map { case (ip, hart) => ip := claimCompletion(hart) =/= 0.U } 162*c699b48aSwangkaifan } 163*c699b48aSwangkaifan} 164