1c6d43980SLemover/*************************************************************************************** 2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover* 5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover* http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover* 10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover* 14c6d43980SLemover* See the Mulan PSL v2 for more details. 15c6d43980SLemover***************************************************************************************/ 16c6d43980SLemover 17c699b48aSwangkaifanpackage device 18c699b48aSwangkaifan 19c699b48aSwangkaifanimport chisel3._ 20c699b48aSwangkaifanimport chisel3.util._ 218891a219SYinan Xuimport org.chipsalliance.cde.config._ 22c699b48aSwangkaifanimport freechips.rocketchip.diplomacy._ 23*bb2f3f51STang Haojinimport utils.HasTLDump 24*bb2f3f51STang Haojinimport utility.{RegMap, MaskExpand, XSDebug} 25c699b48aSwangkaifan 26c699b48aSwangkaifan/* base + 0x000000: Reserved (interrupt source 0 does not exist) 27c699b48aSwangkaifan base + 0x000004: Interrupt source 1 priority 28c699b48aSwangkaifan base + 0x000008: Interrupt source 2 priority 29c699b48aSwangkaifan ... 30c699b48aSwangkaifan base + 0x000FFC: Interrupt source 1023 priority 31c699b48aSwangkaifan base + 0x001000: Interrupt Pending bit 0-31 32c699b48aSwangkaifan base + 0x00107C: Interrupt Pending bit 992-1023 33c699b48aSwangkaifan ... 34c699b48aSwangkaifan base + 0x002000: Enable bits for sources 0-31 on context 0 35c699b48aSwangkaifan base + 0x002004: Enable bits for sources 32-63 on context 0 36c699b48aSwangkaifan ... 37c699b48aSwangkaifan base + 0x00207F: Enable bits for sources 992-1023 on context 0 38c699b48aSwangkaifan base + 0x002080: Enable bits for sources 0-31 on context 1 39c699b48aSwangkaifan base + 0x002084: Enable bits for sources 32-63 on context 1 40c699b48aSwangkaifan ... 41c699b48aSwangkaifan base + 0x0020FF: Enable bits for sources 992-1023 on context 1 42c699b48aSwangkaifan base + 0x002100: Enable bits for sources 0-31 on context 2 43c699b48aSwangkaifan base + 0x002104: Enable bits for sources 32-63 on context 2 44c699b48aSwangkaifan ... 45c699b48aSwangkaifan base + 0x00217F: Enable bits for sources 992-1023 on context 2 46c699b48aSwangkaifan ... 47c699b48aSwangkaifan base + 0x1F1F80: Enable bits for sources 0-31 on context 15871 48c699b48aSwangkaifan base + 0x1F1F84: Enable bits for sources 32-63 on context 15871 49c699b48aSwangkaifan base + 0x1F1FFF: Enable bits for sources 992-1023 on context 15871 50c699b48aSwangkaifan ... 51c699b48aSwangkaifan base + 0x1FFFFC: Reserved 52c699b48aSwangkaifan base + 0x200000: Priority threshold for context 0 53c699b48aSwangkaifan base + 0x200004: Claim/complete for context 0 54c699b48aSwangkaifan base + 0x200008: Reserved 55c699b48aSwangkaifan ... 56c699b48aSwangkaifan base + 0x200FFC: Reserved 57c699b48aSwangkaifan base + 0x201000: Priority threshold for context 1 58c699b48aSwangkaifan base + 0x201004: Claim/complete for context 1 59c699b48aSwangkaifan ... 60c699b48aSwangkaifan base + 0x3FFE000: Priority threshold for context 15871 61c699b48aSwangkaifan base + 0x3FFE004: Claim/complete for context 15871 62c699b48aSwangkaifan base + 0x3FFE008: Reserved 63c699b48aSwangkaifan ... 64c699b48aSwangkaifan base + 0x3FFFFFC: Reserved */ 65c699b48aSwangkaifan 66c699b48aSwangkaifanobject PLICConsts 67c699b48aSwangkaifan{ 68c699b48aSwangkaifan def maxDevices = 1023 69c699b48aSwangkaifan def maxHarts = 15872 70c699b48aSwangkaifan def priorityBase = 0x0 71c699b48aSwangkaifan def pendingBase = 0x1000 72c699b48aSwangkaifan def enableBase = 0x2000 73c699b48aSwangkaifan def hartBase = 0x200000 74c699b48aSwangkaifan 75c699b48aSwangkaifan def claimOffset = 4 76c699b48aSwangkaifan def priorityBytes = 4 77c699b48aSwangkaifan 78c699b48aSwangkaifan def enableOffset(i: Int) = i * ((maxDevices+7)/8) 79c699b48aSwangkaifan def hartOffset(i: Int) = i * 0x1000 80c699b48aSwangkaifan def enableBase(i: Int):Int = enableOffset(i) + enableBase 81c699b48aSwangkaifan def hartBase(i: Int):Int = hartOffset(i) + hartBase 82c699b48aSwangkaifan 83c699b48aSwangkaifan def size(maxHarts: Int): Int = { 84c699b48aSwangkaifan require(maxHarts > 0 && maxHarts <= maxHarts, s"Must be: maxHarts=$maxHarts > 0 && maxHarts <= PLICConsts.maxHarts=${PLICConsts.maxHarts}") 85c699b48aSwangkaifan 1 << log2Ceil(hartBase(maxHarts)) 86c699b48aSwangkaifan } 87c699b48aSwangkaifan 88c699b48aSwangkaifan require(hartBase >= enableBase(maxHarts)) 89c699b48aSwangkaifan} 90c699b48aSwangkaifan 912225d46eSJiawei Linclass PlicIO(val numCores: Int, val numExtIntrs: Int) extends Bundle{ 922225d46eSJiawei Lin val intrVec = Input(UInt(numExtIntrs.W)) 932225d46eSJiawei Lin val meip = Output(Vec(numCores, Bool())) 94c699b48aSwangkaifan} 95c699b48aSwangkaifan 96c699b48aSwangkaifanclass AXI4Plic 97c699b48aSwangkaifan( 984a26299eSwangkaifan address: Seq[AddressSet], 992225d46eSJiawei Lin numCores: Int, 1002225d46eSJiawei Lin numExtIntrs: Int, 1014a26299eSwangkaifan sim: Boolean = false 102c699b48aSwangkaifan)(implicit p: Parameters) 1032225d46eSJiawei Lin extends AXI4SlaveModule(address, executable = false, _extra = new PlicIO(numCores, numExtIntrs)) 104c699b48aSwangkaifan{ 105c699b48aSwangkaifan override lazy val module = new AXI4SlaveModuleImp[PlicIO](this) { 1062225d46eSJiawei Lin require(numCores <= PLICConsts.maxDevices) 1072225d46eSJiawei Lin require(numExtIntrs <= PLICConsts.maxHarts) 108c699b48aSwangkaifan val addressSpaceSize = 0x4000000 109c699b48aSwangkaifan val addressBits = log2Up(addressSpaceSize) 110c699b48aSwangkaifan 111c699b48aSwangkaifan def getOffset(addr: UInt) = addr(addressBits - 1, 0) 112c699b48aSwangkaifan 1132225d46eSJiawei Lin val priority = List.fill(numExtIntrs)(Reg(UInt(32.W))) 114c699b48aSwangkaifan val priorityMap = priority.zipWithIndex.map { case (r, intr) => RegMap((intr + 1) * 4, r) }.toMap 115c699b48aSwangkaifan 1162225d46eSJiawei Lin val nrIntrWord = (numExtIntrs + 31) / 32 // roundup 117c699b48aSwangkaifan // pending bits are updated in the unit of bit by PLIC, 118c699b48aSwangkaifan // so define it as vectors of bits, instead of UInt(32.W) 119c699b48aSwangkaifan val pending = List.fill(nrIntrWord)(RegInit(0.U.asTypeOf(Vec(32, Bool())))) 120c699b48aSwangkaifan val pendingMap = pending.zipWithIndex.map { case (r, intrWord) => 121c699b48aSwangkaifan RegMap(0x1000 + intrWord * 4, Cat(r.reverse), RegMap.Unwritable) 122c699b48aSwangkaifan }.toMap 123c699b48aSwangkaifan 1242225d46eSJiawei Lin val enable = List.fill(numCores)(List.fill(nrIntrWord)(RegInit(0.U(32.W)))) 125c699b48aSwangkaifan val enableMap = enable.zipWithIndex.map { case (l, hart) => 126c699b48aSwangkaifan l.zipWithIndex.map { case (r, intrWord) => RegMap(0x2000 + hart * 0x80 + intrWord * 4, r) } 127c699b48aSwangkaifan }.reduce(_ ++ _).toMap 128c699b48aSwangkaifan 1292225d46eSJiawei Lin val threshold = List.fill(numCores)(Reg(UInt(32.W))) 130c699b48aSwangkaifan val thresholdMap = threshold.zipWithIndex.map { 131c699b48aSwangkaifan case (r, hart) => RegMap(0x200000 + hart * 0x1000, r) 132c699b48aSwangkaifan }.toMap 133c699b48aSwangkaifan 1342225d46eSJiawei Lin val inHandle = RegInit(0.U.asTypeOf(Vec(numExtIntrs + 1, Bool()))) 135c699b48aSwangkaifan 136c699b48aSwangkaifan def completionFn(wdata: UInt) = { 137c699b48aSwangkaifan inHandle(wdata(31, 0)) := false.B 138c699b48aSwangkaifan 0.U 139c699b48aSwangkaifan } 140c699b48aSwangkaifan 1412225d46eSJiawei Lin val claimCompletion = List.fill(numCores)(Reg(UInt(32.W))) 142c699b48aSwangkaifan val claimCompletionMap = claimCompletion.zipWithIndex.map { 143c699b48aSwangkaifan case (r, hart) => { 144c699b48aSwangkaifan val addr = 0x200004 + hart * 0x1000 145935edac4STang Haojin when(in.r.fire && (getOffset(raddr) === addr.U)) { 146c699b48aSwangkaifan inHandle(r) := true.B 147c699b48aSwangkaifan } 148c699b48aSwangkaifan RegMap(addr, r, completionFn) 149c699b48aSwangkaifan } 150c699b48aSwangkaifan }.toMap 151c699b48aSwangkaifan 1522225d46eSJiawei Lin val intrVecReg = Wire(UInt(numExtIntrs.W)) 153c0bc1ee4SYinan Xu intrVecReg := RegNext(RegNext(RegNext(io.extra.get.intrVec))) 154c0bc1ee4SYinan Xu intrVecReg.asBools.zipWithIndex.map { case (intr, i) => { 155c699b48aSwangkaifan val id = i + 1 156c699b48aSwangkaifan when(intr) { 157c699b48aSwangkaifan pending(id / 32)(id % 32) := true.B 158c699b48aSwangkaifan } 159c699b48aSwangkaifan when(inHandle(id)) { 160c699b48aSwangkaifan pending(id / 32)(id % 32) := false.B 161c699b48aSwangkaifan } 162c699b48aSwangkaifan } 163c699b48aSwangkaifan } 164c699b48aSwangkaifan 165c699b48aSwangkaifan val pendingVec = Cat(pending.map(x => Cat(x.reverse))) 166c699b48aSwangkaifan claimCompletion.zipWithIndex.map { case (r, hart) => { 167c699b48aSwangkaifan val takenVec = pendingVec & Cat(enable(hart)) 168c699b48aSwangkaifan r := Mux(takenVec === 0.U, 0.U, PriorityEncoder(takenVec)) 169c699b48aSwangkaifan } 170c699b48aSwangkaifan } 171c699b48aSwangkaifan 172c699b48aSwangkaifan val mapping = priorityMap ++ pendingMap ++ enableMap ++ thresholdMap ++ claimCompletionMap 173c699b48aSwangkaifan 174c699b48aSwangkaifan val rdata = Wire(UInt(32.W)) 175c699b48aSwangkaifan RegMap.generate(mapping, getOffset(raddr), rdata, 176935edac4STang Haojin getOffset(waddr), in.w.fire, in.w.bits.data, MaskExpand(in.w.bits.strb >> waddr(2, 0))) 177c699b48aSwangkaifan // narrow read 178c699b48aSwangkaifan in.r.bits.data := Fill(2, rdata) 179c699b48aSwangkaifan 180c699b48aSwangkaifan io.extra.get.meip.zipWithIndex.map { case (ip, hart) => ip := claimCompletion(hart) =/= 0.U } 181c699b48aSwangkaifan } 182c699b48aSwangkaifan} 183