xref: /XiangShan/src/main/scala/device/AXI4Plic.scala (revision bb2f3f51dd67f6e16e0cc1ffe43368c9fc7e4aef)
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