xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/InterruptFilter.scala (revision 6e51c65d89f7dbebfd522096487f810f744740fc)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import utility.{DelayN, GatedValidRegNext}
6import utils._
7import xiangshan.ExceptionNO
8import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, PrivState, XtvecBundle}
9import xiangshan.backend.fu.NewCSR.CSRDefines.{PrivMode, XtvecMode}
10import xiangshan.backend.fu.NewCSR.InterruptNO
11
12
13class InterruptFilter extends Module {
14  val io = IO(new InterruptFilterIO)
15
16  val privState = io.in.privState
17  val mstatusMIE = io.in.mstatusMIE
18  val sstatusSIE = io.in.sstatusSIE
19  val vsstatusSIE = io.in.vsstatusSIE
20  val mip = io.in.mip
21  val mie = io.in.mie
22  val mideleg = io.in.mideleg
23  val sip = io.in.sip
24  val sie = io.in.sie
25  val hip = io.in.hip
26  val hie = io.in.hie
27  val hideleg = io.in.hideleg
28  val vsip = io.in.vsip
29  val vsie = io.in.vsie
30  val hvictl = io.in.hvictl
31  val hstatus = io.in.hstatus
32  val mtopei = io.in.mtopei
33  val stopei = io.in.stopei
34  val vstopei = io.in.vstopei
35  val hviprio1 = io.in.hviprio1
36  val hviprio2 = io.in.hviprio2
37  val miprios = io.in.miprios
38  val hsiprios = io.in.hsiprios
39  val hviprios = Cat(hviprio2.asUInt, hviprio1.asUInt)
40  val fromAIAValid = io.in.fromAIA.meip || io.in.fromAIA.seip
41  val platformValid = io.in.platform.meip || io.in.platform.seip
42
43  /**
44   * Sort by implemented interrupt default priority
45   * index low, priority high
46   */
47  val vsipFields = Wire(new VSipBundle); vsipFields := vsip
48  val vsieFields = Wire(new VSieBundle); vsieFields := vsie
49
50  private val hsip = hip.asUInt | sip.asUInt
51  private val hsie = hie.asUInt | sie.asUInt
52
53  val mtopiIsNotZero: Bool = (mip & mie & (~mideleg).asUInt) =/= 0.U
54  val stopiIsNotZero: Bool = (hsip & hsie & (~hideleg).asUInt) =/= 0.U
55
56  val NoSEIMask = (~(BigInt(1) << InterruptNO.SEI).U(64.W)).asUInt
57  val mtopigather = mip & mie & (~mideleg).asUInt
58  val hstopigather = hsip & hsie & (~hideleg).asUInt
59  val vstopigather = vsip & vsie & NoSEIMask
60
61  val flag = RegInit(false.B)
62  when (platformValid) {
63    flag := true.B
64  }.elsewhen(fromAIAValid) {
65    flag := false.B
66  }
67
68  val mipriosSort = Wire(Vec(InterruptNO.interruptDefaultPrio.size, new IpriosSort))
69  mipriosSort.zip(InterruptNO.interruptDefaultPrio).zipWithIndex.foreach { case ((iprio, defaultPrio), i) =>
70    iprio.idx := i.U
71    when (mtopigather(defaultPrio)) {
72      iprio.enable := true.B
73      when (defaultPrio.U === InterruptNO.MEI.U) {
74        iprio.isZero := platformValid || flag
75        val mtopeiGreaterThan255 = mtopei.IPRIO.asUInt(10, 8).orR
76        iprio.greaterThan255 := mtopeiGreaterThan255
77        iprio.prioNum := mtopei.IPRIO.asUInt(7, 0)
78      }.otherwise {
79        iprio.isZero := !miprios(7 + 8 * defaultPrio, 8 * defaultPrio).orR
80        iprio.greaterThan255 := false.B
81        iprio.prioNum := miprios(7 + 8 * defaultPrio, 8 * defaultPrio)
82      }
83    }.otherwise {
84      iprio.enable := false.B
85      iprio.isZero := false.B
86      iprio.greaterThan255 := false.B
87      iprio.prioNum := 0.U
88    }
89  }
90  val hsipriosSort = Wire(Vec(InterruptNO.interruptDefaultPrio.size, new IpriosSort))
91  hsipriosSort.zip(InterruptNO.interruptDefaultPrio).zipWithIndex.foreach { case ((iprio, defaultPrio), i) =>
92    iprio.idx := i.U
93    when (hstopigather(defaultPrio)) {
94      iprio.enable := true.B
95      when (defaultPrio.U === InterruptNO.SEI.U) {
96        iprio.isZero := platformValid || flag
97        val stopeiGreaterThan255 = stopei.IPRIO.asUInt(10, 8).orR
98        iprio.greaterThan255 := stopeiGreaterThan255
99        iprio.prioNum := stopei.IPRIO.asUInt(7, 0)
100      }.otherwise {
101        iprio.isZero := !hsiprios(7 + 8 * defaultPrio, 8 * defaultPrio).orR
102        iprio.greaterThan255 := false.B
103        iprio.prioNum := hsiprios(7 + 8 * defaultPrio, 8 * defaultPrio)
104      }
105    }.otherwise {
106      iprio.enable := false.B
107      iprio.isZero := false.B
108      iprio.greaterThan255 := false.B
109      iprio.prioNum := 0.U
110    }
111  }
112  val hvipriosSort = Wire(Vec(InterruptNO.interruptDefaultPrio.size, new IpriosSort))
113  hvipriosSort.zip(InterruptNO.interruptDefaultPrio).zipWithIndex.foreach { case ((iprio, defaultPrio), i) =>
114    iprio.idx := i.U
115    when(vstopigather(defaultPrio)) {
116      iprio.enable := true.B
117      iprio.isZero := true.B
118      iprio.greaterThan255 := false.B
119      iprio.prioNum := 0.U
120    }.otherwise {
121      iprio.enable := false.B
122      iprio.isZero := false.B
123      iprio.greaterThan255 := false.B
124      iprio.prioNum := 0.U
125    }
126  }
127  when(vstopigather(1).asBool) {
128    hvipriosSort(findIndex(1.U)).isZero := !hviprio1.PrioSSI.asUInt.orR
129    hvipriosSort(findIndex(1.U)).prioNum := hviprio1.PrioSSI.asUInt
130  }
131
132  when(vstopigather(5).asBool) {
133    hvipriosSort(findIndex(5.U)).isZero := !hviprio1.PrioSTI.asUInt.orR
134    hvipriosSort(findIndex(5.U)).prioNum := hviprio1.PrioSTI.asUInt
135  }
136
137  for (i <- 0 to 10) {
138    when(vstopigather(i + 13).asBool) {
139      hvipriosSort(findIndex((i + 13).U)).isZero := !hviprios(7 + 8 * (i + 5), 8 * (i + 5)).orR
140      hvipriosSort(findIndex((i + 13).U)).prioNum := hviprios(7 + 8 * (i + 5), 8 * (i + 5))
141    }
142  }
143
144  def findNum(input: UInt): UInt = {
145    val select = Mux1H(UIntToOH(input), InterruptNO.interruptDefaultPrio.map(_.U))
146    select
147  }
148
149  def findIndex(input: UInt): UInt = {
150    val select = WireInit(0.U(log2Up(InterruptNO.interruptDefaultPrio.length).W))
151    InterruptNO.interruptDefaultPrio.zipWithIndex.foreach { case (value, i) =>
152      when (input === value.U) {
153        select := i.U
154      }
155    }
156    select
157  }
158
159  // value lower, priority higher
160  def minSelect(iprios: Vec[IpriosSort], xei: UInt): Vec[IpriosSort] = {
161    iprios.size match {
162      case 1 =>
163        iprios
164      case 2 =>
165        val left = iprios(0)
166        val right = iprios(1)
167        val minIprio = Mux1H(Seq(
168          (left.enable && !right.enable) -> left,
169          (!left.enable && right.enable) -> right,
170          (left.enable && right.enable) -> Mux1H(Seq(
171            (left.isZero && right.isZero) -> left,
172            (left.isZero && !right.isZero) -> Mux(left.idx <= xei, left, right),
173            (!left.isZero && right.isZero) -> Mux(right.idx <= xei, right, left),
174            (!left.isZero && !right.isZero) -> Mux1H(Seq(
175              (left.greaterThan255 && !right.greaterThan255) -> right,
176              (!left.greaterThan255 && right.greaterThan255) -> left,
177              (!left.greaterThan255 && !right.greaterThan255) -> Mux(left.prioNum <= right.prioNum, left, right),
178            ))
179          ))
180        ))
181        VecInit(minIprio)
182      case _ =>
183        val leftIprio = minSelect(VecInit(iprios.take((iprios.size + 1) / 2)), xei)
184        val rightIprio = minSelect(VecInit(iprios.drop((iprios.size + 1) / 2)), xei)
185        minSelect(VecInit(leftIprio ++ rightIprio), xei)
186    }
187  }
188
189  def highIprio(iprios: Vec[IpriosSort], xei: UInt): IpriosSort = {
190    val result = minSelect(iprios, xei)
191    result(0)
192  }
193
194  def sliceIpriosSort(ipriosSort: Vec[IpriosSort]): Vec[Vec[IpriosSort]] = {
195    val ipriosSortTmp = Wire(Vec(8, Vec(8, new IpriosSort)))
196    for (i <- 0 until 8) {
197      val end = math.min(8 * (i + 1), InterruptNO.interruptDefaultPrio.size)
198      val ipriosSlice = ipriosSort.slice(8 * i, end)
199      val paddingSlice = ipriosSlice ++ Seq.fill(8 - ipriosSlice.length)(0.U.asTypeOf(new IpriosSort))
200      ipriosSortTmp(i) := VecInit(paddingSlice)
201    }
202    ipriosSortTmp
203  }
204
205  private val mipriosSortTmp  = sliceIpriosSort(mipriosSort)
206  private val hsipriosSortTmp = sliceIpriosSort(hsipriosSort)
207  private val hvipriosSortTmp = sliceIpriosSort(hvipriosSort)
208
209  private val meiPrioIdx = InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.MEI).U
210  private val seiPrioIdx = InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.SEI).U
211  private val vseiPrioIdx = InterruptNO.getPrioIdxInGroup(_.interruptDefaultPrio)(_.VSEI).U
212
213  private val mipriosTmp = Wire(Vec(8, new IpriosSort))
214  mipriosSortTmp.zipWithIndex.foreach { case (iprios, i) =>
215    val ipriosTmp = highIprio(iprios, meiPrioIdx)
216    mipriosTmp(i) := ipriosTmp
217  }
218
219  private val hsipriosTmp = Wire(Vec(8, new IpriosSort))
220  hsipriosSortTmp.zipWithIndex.foreach { case (iprios, i) =>
221    val ipriosTmp = highIprio(iprios, seiPrioIdx)
222    hsipriosTmp(i) := ipriosTmp
223  }
224
225  private val hvipriosTmp = Wire(Vec(8, new IpriosSort))
226  hvipriosSortTmp.zipWithIndex.foreach { case (iprios, i) =>
227    val ipriosTmp = highIprio(iprios, vseiPrioIdx)
228    hvipriosTmp(i) := ipriosTmp
229  }
230
231  private val mipriosReg = Reg(Vec(8, new IpriosSort))
232  private val hsipriosReg = Reg(Vec(8, new IpriosSort))
233  private val hvipriosReg = Reg(Vec(8, new IpriosSort))
234
235  for (i <- 0 until 8) {
236    mipriosReg(i) := mipriosTmp(i)
237    hsipriosReg(i) := hsipriosTmp(i)
238    hvipriosReg(i) := hvipriosTmp(i)
239  }
240
241  private val mipriosRegTmp = highIprio(mipriosReg, meiPrioIdx)
242  private val hsipriosRegTmp = highIprio(hsipriosReg, seiPrioIdx)
243  private val hvipriosRegTmp = highIprio(hvipriosReg, vseiPrioIdx)
244
245  private val mIidIdxReg = mipriosRegTmp.idx
246  private val hsIidIdxReg = hsipriosRegTmp.idx
247  private val vsIidIdxReg = hvipriosRegTmp.idx
248
249  private val mIidNum  = findNum(mIidIdxReg)
250  private val hsIidNum = findNum(hsIidIdxReg)
251  private val vsIidNum = findNum(vsIidIdxReg)
252
253  private val mIidDefaultPrioHighMEI: Bool = mIidIdxReg < meiPrioIdx
254  private val mIidDefaultPrioLowMEI : Bool = mIidIdxReg > meiPrioIdx
255
256  private val hsIidDefaultPrioHighSEI: Bool = hsIidIdxReg < seiPrioIdx
257  private val hsIidDefaultPrioLowSEI : Bool = hsIidIdxReg > seiPrioIdx
258
259  // update mtopi
260  io.out.mtopi.IID := Mux(mtopiIsNotZero, mIidNum, 0.U)
261  io.out.mtopi.IPRIO := Mux(mtopiIsNotZero,
262    Mux1H(Seq(
263      (!mipriosRegTmp.isZero && !mipriosRegTmp.greaterThan255) -> mipriosRegTmp.prioNum,
264      (mipriosRegTmp.greaterThan255 || mipriosRegTmp.isZero && mIidDefaultPrioLowMEI) -> 255.U,
265      (mipriosRegTmp.isZero && mIidDefaultPrioHighMEI) -> 0.U,
266    )),
267    0.U
268  )
269
270  // upadte stopi
271  io.out.stopi.IID := Mux(stopiIsNotZero, hsIidNum, 0.U)
272  io.out.stopi.IPRIO := Mux(stopiIsNotZero,
273    Mux1H(Seq(
274      (!hsipriosRegTmp.isZero && !hsipriosRegTmp.greaterThan255) -> hsipriosRegTmp.prioNum,
275      (hsipriosRegTmp.greaterThan255 || hsipriosRegTmp.isZero && hsIidDefaultPrioLowSEI) -> 255.U,
276      (hsipriosRegTmp.isZero && hsIidDefaultPrioHighSEI) -> 0.U,
277    )),
278    0.U
279  )
280
281  // refactor this code & has some problem
282  val Candidate1: Bool = vsip.SEIP && vsie.SEIE && (hstatus.VGEIN.asUInt =/= 0.U) && (vstopei.asUInt =/= 0.U)
283  val Candidate2: Bool = vsip.SEIP && vsie.SEIE && (hstatus.VGEIN.asUInt === 0.U) && (hvictl.IID.asUInt === 9.U) && (hvictl.IPRIO.asUInt =/= 0.U)
284  val Candidate3: Bool = vsip.SEIP && vsie.SEIE && !Candidate1 && !Candidate2
285  val Candidate4: Bool = (hvictl.VTI.asUInt === 0.U) && vstopigather.orR
286  val Candidate5: Bool = (hvictl.VTI.asUInt === 1.U) && (hvictl.IID.asUInt =/= 9.U)
287  val CandidateNoValid: Bool = !Candidate1 && !Candidate2 && !Candidate3 && !Candidate4 && !Candidate5
288
289  assert(PopCount(Cat(Candidate1, Candidate2, Candidate3)) < 2.U, "Only one Candidate could be select from Candidate1/2/3 in VS-level!")
290  assert(PopCount(Cat(Candidate4, Candidate5)) < 2.U, "Only one Candidate could be select from Candidate4/5 in VS-level!")
291  assert(PopCount(Cat(Candidate2, Candidate5)) < 2.U, "Candidate2 and candidate5 cannot be true at the same time. ")
292
293  val Candidate123 = Candidate1 || Candidate2 || Candidate3
294  val Candidate45 = Candidate4 || Candidate5
295
296  // Candidate2,Candidate5 不可能同时成立
297  val onlyC1Enable = Candidate1 & !Candidate45
298  val onlyC2Enable = Candidate2 & !Candidate45
299  val onlyC3Enable = Candidate3 & !Candidate123
300  val onlyC4Enable = Candidate4 & !Candidate123
301  val onlyC5Enable = Candidate5 & !Candidate123
302  val C1C4Enable   = Candidate1 & Candidate4
303  val C1C5Enable   = Candidate1 & Candidate5
304  val C2C4Enable   = Candidate2 & Candidate4
305  val C3C4Enable   = Candidate3 & Candidate4
306  val C3C5Enable   = Candidate3 & Candidate5
307
308  val iidOnlyC1 = Wire(UInt(12.W))
309  val iidOnlyC4 = Wire(UInt(12.W))
310  val iidOnlyC5 = Wire(UInt(12.W))
311  val iprioOnlyC1 = Wire(UInt(8.W))
312  val iprioOnlyC2 = Wire(UInt(8.W))
313  val iprioOnlyC3 = Wire(UInt(8.W))
314  val iprioOnlyC4 = Wire(UInt(8.W))
315  val iprioOnlyC5 = Wire(UInt(8.W))
316  val iidC1C4 = Wire(UInt(12.W))
317  val iidC1C5 = Wire(UInt(12.W))
318  val iidC2C4 = Wire(UInt(12.W))
319  val iidC3C4 = Wire(UInt(12.W))
320  val iidC3C5 = Wire(UInt(12.W))
321  val iprioC1C4 = Wire(UInt(8.W))
322  val iprioC1C5 = Wire(UInt(8.W))
323  val iprioC2C4 = Wire(UInt(8.W))
324  val iprioC3C4 = Wire(UInt(8.W))
325  val iprioC3C5 = Wire(UInt(8.W))
326
327  iidOnlyC1 := InterruptNO.SEI.U
328  iidOnlyC4 := vsIidNum
329  iidOnlyC5 := hvictl.IID.asUInt
330
331  val iidC4Idx = Wire(UInt(12.W))
332  iidC4Idx := vsIidIdxReg
333
334  val iprioC1   = Wire(UInt(11.W))
335  val iprioC2C5 = Wire(UInt(11.W))
336  val iprioC4   = Wire(UInt(11.W))
337  val iprioC1Tmp = Wire(UInt(8.W))
338  val iprioC4Tmp = Wire(UInt(8.W))
339  val iprioC3C5Tmp = Wire(UInt(8.W))
340
341  val hvictlDPR = Mux(hvictl.DPR.asBool, 255.U, 0.U)
342  val C1GreaterThan255 = vstopei.IPRIO.asUInt(10, 8).orR
343  val C4IsZero = !hvipriosRegTmp.prioNum.orR
344  val C2C5IsZero = !hvictl.IPRIO.asUInt.orR
345  val C4HighVSEI = iidC4Idx < findIndex(InterruptNO.VSEI.U)
346  val SEIHighC4 = findIndex(InterruptNO.SEI.U) < iidC4Idx
347  val iprioC1GreaterThan255 = Mux(C1GreaterThan255, 255.U, iprioC1Tmp)
348
349  iprioC1 := vstopei.IPRIO.asUInt
350  iprioC2C5 := hvictl.IPRIO.asUInt
351  iprioC4 := hvipriosRegTmp.prioNum
352
353  iprioC1Tmp := iprioC1(7, 0)
354  iprioC4Tmp := Mux(C4IsZero, Mux(C4HighVSEI, 0.U, 255.U), iprioC4)
355  iprioC3C5Tmp := Mux(C2C5IsZero, hvictlDPR, iprioC2C5)
356
357  iprioOnlyC1 := iprioC1GreaterThan255
358  iprioOnlyC2 := iprioC2C5
359  iprioOnlyC3 := 255.U
360  iprioOnlyC4 := iprioC4Tmp
361  iprioOnlyC5 := iprioC3C5Tmp
362
363  // C1,C4 enable
364  when(C4IsZero) {
365    iidC1C4 := Mux(C4HighVSEI, iidOnlyC4, iidOnlyC1)
366    iprioC1C4 := Mux(C4HighVSEI, 0.U, iprioC1GreaterThan255)
367  }.elsewhen(iprioC1 < iprioC4) {
368    iidC1C4 := iidOnlyC1
369    iprioC1C4 := iprioC1Tmp
370  }.elsewhen(iprioC1 === iprioC4) {
371    iidC1C4 := Mux(SEIHighC4, iidOnlyC1, iidOnlyC4)
372    iprioC1C4 := Mux(SEIHighC4, iprioC1Tmp, iprioC4)
373  }.otherwise {
374    iidC1C4 := iidOnlyC4
375    iprioC1C4 := iprioC4
376  }
377
378  // C1,C5 enable
379  iidC1C5 := Mux(hvictl.DPR.asBool, iidOnlyC1, iidOnlyC5)
380  when(C2C5IsZero) {
381    iprioC1C5 := Mux(hvictl.DPR.asBool, iprioC1GreaterThan255, 0.U)
382  }.elsewhen(iprioC1 < iprioC2C5) {
383    iidC1C5 := iidOnlyC1
384    iprioC1C5 := iprioC1Tmp
385  }.elsewhen(iprioC1 === iprioC2C5) {
386    iprioC1C5 := Mux(hvictl.DPR.asBool, iprioC1Tmp, iprioC2C5)
387  }.otherwise {
388    iidC1C5 := iidOnlyC5
389    iprioC1C5 := iprioC3C5Tmp
390  }
391
392  // C2,C4 enable
393  when(C4IsZero) {
394    iidC2C4 := Mux(C4HighVSEI, iidOnlyC4, iidOnlyC1)
395    iprioC2C4 := Mux(C4HighVSEI, 0.U, iprioC2C5)
396  }.elsewhen(iprioC2C5 < iprioC4) {
397    iidC2C4 := iidOnlyC1
398    iprioC2C4 := iprioC2C5
399  }.elsewhen(iprioC2C5 === iprioC4) {
400    iidC2C4 := Mux(SEIHighC4, iidOnlyC1, iidOnlyC4)
401    iprioC2C4 := Mux(SEIHighC4, iprioC2C5, iprioC4)
402  }.otherwise {
403    iidC2C4 := iidOnlyC4
404    iprioC2C4 := iprioC4
405  }
406
407  // C3,C4 enable
408  iidC3C4 := Mux(C4IsZero, Mux(C4HighVSEI, iidOnlyC4, iidOnlyC1), iidOnlyC4)
409  iprioC3C4 := iprioC4Tmp
410  // C3,C5 enable
411  iidC3C5 := Mux(C2C5IsZero, Mux(hvictl.DPR.asBool, iidOnlyC5, iidOnlyC1), iidOnlyC5)
412  iprioC3C5 := iprioC3C5Tmp
413
414  // update vstopi
415  io.out.vstopi.IID := Mux(CandidateNoValid,
416    0.U,
417    Mux1H(Seq(
418      (Candidate123 & !Candidate45) -> iidOnlyC1,
419      onlyC4Enable -> iidOnlyC4,
420      onlyC5Enable -> iidOnlyC5,
421      C1C4Enable -> iidC1C4,
422      C1C5Enable -> iidC1C5,
423      C2C4Enable -> iidC2C4,
424      C3C4Enable -> iidC3C4,
425      C3C5Enable -> iidC3C5,
426    ))
427  )
428  io.out.vstopi.IPRIO := Mux(CandidateNoValid,
429    0.U,
430    Mux(!hvictl.IPRIOM.asBool, 1.U,
431      Mux1H(Seq(
432        onlyC1Enable -> iprioOnlyC1,
433        onlyC2Enable -> iprioOnlyC2,
434        onlyC3Enable -> iprioOnlyC3,
435        onlyC4Enable -> iprioOnlyC4,
436        onlyC5Enable -> iprioOnlyC5,
437        C1C4Enable -> iprioC1C4,
438        C1C5Enable -> iprioC1C5,
439        C2C4Enable -> iprioC2C4,
440        C3C4Enable -> iprioC3C4,
441        C3C5Enable -> iprioC3C5,
442      ))
443    )
444  )
445
446  val mIRVecTmp = Mux(
447    privState.isModeM && mstatusMIE || privState < PrivState.ModeM,
448    io.out.mtopi.IID.asUInt,
449    0.U
450  )
451
452  val hsIRVecTmp = Mux(
453    privState.isModeHS && sstatusSIE || privState < PrivState.ModeHS,
454    io.out.stopi.IID.asUInt,
455    0.U
456  )
457
458  val vsIRVecTmp = Mux(
459    privState.isModeVS && vsstatusSIE || privState < PrivState.ModeVS,
460    io.out.vstopi.IID.asUInt,
461    0.U
462  )
463
464  val mIRNotZero  = mIRVecTmp.orR
465  val hsIRNotZero = hsIRVecTmp.orR
466  val vsIRNotZero = vsIRVecTmp.orR
467
468  val irToHS = !mIRNotZero && hsIRNotZero
469  val irToVS = !mIRNotZero && !hsIRNotZero && vsIRNotZero
470
471  val mIRVec  = mIRVecTmp
472  val hsIRVec = Mux(irToHS, hsIRVecTmp, 0.U)
473  val vsIRVec = Mux(irToVS, UIntToOH(vsIRVecTmp, 64), 0.U)
474
475  val vsMapHostIRVecTmp = Cat((0 until vsIRVec.getWidth).map { num =>
476    // 2,6,10
477    if (InterruptNO.getVS.contains(num)) {
478      // 1,5,9
479      val sNum = num - 1
480      vsIRVec(sNum)
481    }
482    // 1,5,9
483    else if (InterruptNO.getHS.contains(num)) {
484      0.U(1.W)
485    }
486    else {
487      vsIRVec(num)
488    }
489  }.reverse)
490
491  val vsMapHostIRVec = OHToUInt(vsMapHostIRVecTmp)
492
493  dontTouch(vsMapHostIRVec)
494
495  val nmiVecTmp = Wire(Vec(64, Bool()))
496  nmiVecTmp.zipWithIndex.foreach { case (irq, i) =>
497    if (NonMaskableIRNO.interruptDefaultPrio.contains(i)) {
498      val higherIRSeq = NonMaskableIRNO.getIRQHigherThan(i)
499      irq := (
500        higherIRSeq.nonEmpty.B && Cat(higherIRSeq.map(num => !io.in.nmiVec(num))).andR ||
501          higherIRSeq.isEmpty.B
502        ) && io.in.nmiVec(i)
503      dontTouch(irq)
504    } else
505      irq := false.B
506  }
507  val nmiVec = OHToUInt(nmiVecTmp)
508
509  // support debug interrupt
510  // support smrnmi when NMIE is 0, all interrupt disable
511  val disableDebugIntr = io.in.debugMode || (io.in.dcsr.STEP.asBool && !io.in.dcsr.STEPIE.asBool)
512  val enableDebugIntr = io.in.debugIntr && !disableDebugIntr
513
514  val disableAllIntr = disableDebugIntr || !io.in.mnstatusNMIE
515
516  val normalIntrVec = mIRVec | hsIRVec | vsMapHostIRVec
517  val intrVec = Mux(disableAllIntr, 0.U, Mux(io.in.nmi, nmiVec, normalIntrVec))
518
519  // virtual interrupt with hvictl injection
520  val vsIRModeCond = privState.isModeVS && vsstatusSIE || privState < PrivState.ModeVS
521  val SelectCandidate5 = onlyC5Enable || C3C5Enable ||
522                         C1C5Enable && (iprioC1 === iprioC2C5 && !hvictl.DPR.asBool || iprioC1 > iprioC2C5)
523  // delay at least 6 cycles to maintain the atomic of sret/mret
524  // 65bit indict current interrupt is NMI
525  val intrVecReg = RegInit(0.U(8.W))
526  val debugIntrReg = RegInit(false.B)
527  val nmiReg = RegInit(false.B)
528  val viIsHvictlInjectReg = RegInit(false.B)
529  val irToHSReg = RegInit(false.B)
530  val irToVSReg = RegInit(false.B)
531  intrVecReg := intrVec
532  debugIntrReg := enableDebugIntr
533  nmiReg := io.in.nmi
534  viIsHvictlInjectReg := vsIRModeCond && SelectCandidate5
535  irToHSReg := irToHS
536  irToVSReg := irToVS
537  val delayedIntrVec = DelayN(intrVecReg, 5)
538  val delayedDebugIntr = DelayN(debugIntrReg, 5)
539  val delayedNMI = DelayN(nmiReg, 5)
540  val delayedVIIsHvictlInjectReg = DelayN(viIsHvictlInjectReg, 5)
541  val delayedIRToHS = DelayN(irToHSReg, 5)
542  val delayedIRToVS = DelayN(irToVSReg, 5)
543
544  io.out.interruptVec.valid := delayedIntrVec.orR || delayedDebugIntr || delayedVIIsHvictlInjectReg
545  io.out.interruptVec.bits := delayedIntrVec
546  io.out.debug := delayedDebugIntr
547  io.out.nmi := delayedNMI
548  io.out.virtualInterruptIsHvictlInject := delayedVIIsHvictlInjectReg & !delayedNMI
549  io.out.irToHS := delayedIRToHS & !delayedNMI
550  io.out.irToVS := delayedIRToVS & !delayedNMI
551
552  dontTouch(hsip)
553  dontTouch(hsie)
554  dontTouch(mIRVec)
555  dontTouch(hsIRVec)
556  dontTouch(vsIRVec)
557}
558
559class InterruptFilterIO extends Bundle {
560  val in = Input(new Bundle {
561    val privState = new PrivState
562    val mstatusMIE  = Bool()
563    val sstatusSIE  = Bool()
564    val vsstatusSIE = Bool()
565    val mip = new MipBundle
566    val mie = new MieBundle
567    val mideleg = new MidelegBundle
568    val sip = new SipBundle
569    val sie = new SieBundle
570    val hip = new HipBundle
571    val hie = new HieBundle
572    val hideleg = new HidelegBundle
573    val vsip = new VSipBundle
574    val vsie = new VSieBundle
575    val hvictl = new HvictlBundle
576    val hstatus = new HstatusBundle
577    val mtopei = new TopEIBundle
578    val stopei = new TopEIBundle
579    val vstopei = new TopEIBundle
580    val hviprio1 = new Hviprio1Bundle
581    val hviprio2 = new Hviprio2Bundle
582    val debugIntr = Bool()
583    val debugMode = Bool()
584    val dcsr = new DcsrBundle
585
586    val miprios = UInt((64*8).W)
587    val hsiprios = UInt((64*8).W)
588    //smrnmi
589    val nmi = Bool()
590    val nmiVec = UInt(64.W)
591    val mnstatusNMIE = Bool()
592    val platform = new Bundle {
593      val meip = Bool()
594      val seip = Bool()
595    }
596    val fromAIA = new Bundle {
597      val meip = Bool()
598      val seip = Bool()
599    }
600  })
601
602  val out = Output(new Bundle {
603    val debug = Bool()
604    val nmi = Bool()
605    val interruptVec = ValidIO(UInt(8.W))
606    val mtopi  = new TopIBundle
607    val stopi  = new TopIBundle
608    val vstopi = new TopIBundle
609    val virtualInterruptIsHvictlInject = Bool()
610    val irToHS = Bool()
611    val irToVS = Bool()
612  })
613}
614
615
616class IpriosSort extends Bundle {
617  val idx = UInt(6.W)
618  val enable = Bool()
619  val isZero = Bool()
620  val greaterThan255 = Bool()
621  val prioNum = UInt(8.W)
622}
623