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