3 from nmigen_soc
.periph
import ConstantMap
5 from . import Peripheral
, IRQLine
8 __all__
= ["InterruptController", "GenericInterruptController"]
11 class InterruptController(Peripheral
):
12 """Interrupt controller base class."""
13 def __init__(self
, *args
, **kwargs
):
14 super().__init
__(*args
, **kwargs
)
15 self
.__irq
_lines
= set()
16 self
.__irq
_map
= dict()
19 def constant_map(self
):
20 return ConstantMap(**{
21 line
.name
.upper(): index
for index
, line
in self
.iter_irqs()
24 def add_irq(self
, line
, index
):
29 line : :class:`IRQLine`
36 Raises :exn:`ValueError` if ``line`` is added twice, or if ``index`` is already used.
38 if not isinstance(line
, IRQLine
):
39 raise TypeError("IRQ line must be an instance of IRQLine, not {!r}"
41 if not isinstance(index
, int) or index
< 0:
42 raise ValueError("IRQ index must be a non-negative integer, not {!r}"
44 if line
in self
.__irq
_lines
:
45 raise ValueError("IRQ line {!r} has already been mapped to IRQ index {}"
46 .format(line
, self
.find_index(line
)))
47 if index
in self
.__irq
_map
:
48 raise ValueError("IRQ index {} has already been mapped to IRQ line {!r}"
49 .format(index
, self
.__irq
_map
[index
]))
50 self
.__irq
_lines
.add(line
)
51 self
.__irq
_map
[index
] = line
58 A tuple ``index, line`` describing an IRQ line and its index.
60 yield from sorted(self
.__irq
_map
.items())
62 def find_index(self
, line
):
63 """Find the index at which an IRQ line is mapped.
67 line : :class:`IRQLine`
72 The index at which ``line`` is mapped, if present.
76 Raises :exn:`KeyError` if ``line`` is not present.
78 for irq_index
, irq_line
in self
.iter_irqs():
84 class GenericInterruptController(InterruptController
, Elaboratable
):
85 """Generic interrupt controller.
87 An interrupt "controller" acting as a passthrough for IRQ lines. Useful for CPU cores that do
88 interrupt management themselves.
102 def __init__(self
, *, width
):
103 super().__init
__(src_loc_at
=2)
104 if not isinstance(width
, int) or width
<= 0:
105 raise ValueError("Width must be a strictly positive integer, not {!r}"
108 self
.ip
= Signal(width
)
110 def add_irq(self
, line
, index
):
111 __doc__
= InterruptController
.add_irq
.__doc
__
112 if not isinstance(index
, int) or index
not in range(0, self
.width
):
113 raise ValueError("IRQ index must be an integer ranging from 0 to {}, not {!r}"
114 .format(self
.width
- 1, index
))
115 super().add_irq(line
, index
)
117 def elaborate(self
, platform
):
120 for irq_index
, irq_line
in self
.iter_irqs():
121 m
.d
.comb
+= self
.ip
[irq_index
].eq(irq_line
)