Skip to content

Commit

Permalink
Update to follow RFCs 37 and 38.
Browse files Browse the repository at this point in the history
Memory maps and event maps are now assigned to Interface objects instead of
Signature objects (which can no longer hold mutable state), as things were
before 9ffaf94.

See amaranth-lang#62.
  • Loading branch information
jfng committed Dec 12, 2023
1 parent ad9f7d4 commit 4e6e607
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 379 deletions.
82 changes: 31 additions & 51 deletions amaranth_soc/csr/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ def __init__(self, *, addr_width, data_width):

self._addr_width = addr_width
self._data_width = data_width
self._memory_map = None

members = {
"addr": Out(self.addr_width),
Expand All @@ -217,27 +216,6 @@ def addr_width(self):
def data_width(self):
return self._data_width

@property
def memory_map(self):
if self._memory_map is None:
raise AttributeError(f"{self!r} does not have a memory map")
return self._memory_map

@memory_map.setter
def memory_map(self, memory_map):
if self.frozen:
raise ValueError(f"Signature has been frozen. Cannot set its memory map")
if memory_map is not None:
if not isinstance(memory_map, MemoryMap):
raise TypeError(f"Memory map must be an instance of MemoryMap, not {memory_map!r}")
if memory_map.addr_width != self.addr_width:
raise ValueError(f"Memory map has address width {memory_map.addr_width}, which is not "
f"the same as bus interface address width {self.addr_width}")
if memory_map.data_width != self.data_width:
raise ValueError(f"Memory map has data width {memory_map.data_width}, which is not the "
f"same as bus interface data width {self.data_width}")
self._memory_map = memory_map

@classmethod
def check_parameters(cls, *, addr_width, data_width):
"""Validate signature parameters.
Expand All @@ -264,7 +242,6 @@ def create(self, *, path=None, src_loc_at=0):
An :class:`Interface` object using this signature.
"""
return Interface(addr_width=self.addr_width, data_width=self.data_width,
memory_map=self._memory_map, # if None, do not raise an exception
path=path, src_loc_at=1 + src_loc_at)

def __eq__(self, other):
Expand Down Expand Up @@ -304,19 +281,22 @@ class Interface(wiring.PureInterface):
Address width. See :class:`Signature`.
data_width : :class:`int`
Data width. See :class:`Signature`.
memory_map: :class:`MemoryMap`
Memory map of the bus. Optional. See :class:`Signature`.
path : iter(:class:`str`)
Path to this CSR interface. Optional. See :class:`wiring.PureInterface`.
Attributes
----------
memory_map: :class:`MemoryMap`
Memory map of the bus. Optional.
Raises
------
See :meth:`Signature.check_parameters`.
"""
def __init__(self, *, addr_width, data_width, memory_map=None, path=None, src_loc_at=0):
def __init__(self, *, addr_width, data_width, path=None, src_loc_at=0):
sig = Signature(addr_width=addr_width, data_width=data_width)
sig.memory_map = memory_map
super().__init__(sig, path=path, src_loc_at=1 + src_loc_at)
self._memory_map = None

@property
def addr_width(self):
Expand All @@ -328,7 +308,21 @@ def data_width(self):

@property
def memory_map(self):
return self.signature.memory_map
if self._memory_map is None:
raise AttributeError(f"{self!r} does not have a memory map")
return self._memory_map

@memory_map.setter
def memory_map(self, memory_map):
if not isinstance(memory_map, MemoryMap):
raise TypeError(f"Memory map must be an instance of MemoryMap, not {memory_map!r}")
if memory_map.addr_width != self.addr_width:
raise ValueError(f"Memory map has address width {memory_map.addr_width}, which is not "
f"the same as bus interface address width {self.addr_width}")
if memory_map.data_width != self.data_width:
raise ValueError(f"Memory map has data width {memory_map.data_width}, which is not the "
f"same as bus interface data width {self.data_width}")
self._memory_map = memory_map

def __repr__(self):
return f"csr.Interface({self.signature!r})"
Expand Down Expand Up @@ -561,18 +555,11 @@ def chunks(self):
CSR bus providing access to registers.
"""
def __init__(self, *, addr_width, data_width, alignment=0, name=None, shadow_overlaps=None):
bus_signature = Signature(addr_width=addr_width, data_width=data_width)
bus_signature.memory_map = MemoryMap(addr_width=addr_width, data_width=data_width,
alignment=alignment, name=name)

self._signature = wiring.Signature({"bus": In(bus_signature)})
self._r_shadow = Multiplexer._Shadow(data_width, shadow_overlaps, name="r_shadow")
self._w_shadow = Multiplexer._Shadow(data_width, shadow_overlaps, name="w_shadow")
super().__init__()

@property
def signature(self):
return self._signature
super().__init__({"bus": In(Signature(addr_width=addr_width, data_width=data_width))})
self.bus.memory_map = MemoryMap(addr_width=addr_width, data_width=data_width,
alignment=alignment, name=name)
self._r_shadow = Multiplexer._Shadow(data_width, shadow_overlaps, name="r_shadow")
self._w_shadow = Multiplexer._Shadow(data_width, shadow_overlaps, name="w_shadow")

def align_to(self, alignment):
"""Align the implicit address of the next register.
Expand Down Expand Up @@ -704,17 +691,10 @@ class Decoder(wiring.Component):
CSR bus providing access to subordinate buses.
"""
def __init__(self, *, addr_width, data_width, alignment=0, name=None):
bus_signature = Signature(addr_width=addr_width, data_width=data_width)
bus_signature.memory_map = MemoryMap(addr_width=addr_width, data_width=data_width,
alignment=alignment, name=name)

self._signature = wiring.Signature({"bus": In(bus_signature)})
self._subs = dict()
super().__init__()

@property
def signature(self):
return self._signature
super().__init__({"bus": In(Signature(addr_width=addr_width, data_width=data_width))})
self.bus.memory_map = MemoryMap(addr_width=addr_width, data_width=data_width,
alignment=alignment, name=name)
self._subs = dict()

def align_to(self, alignment):
"""Align the implicit address of the next window.
Expand Down
17 changes: 8 additions & 9 deletions amaranth_soc/csr/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from . import Element, Multiplexer
from .. import event
from ..memory import MemoryMap


__all__ = ["EventMonitor"]
Expand Down Expand Up @@ -53,25 +54,23 @@ def __init__(self, event_map, *, trigger="level", data_width, alignment=0, name=
raise ValueError(f"Alignment must be a non-negative integer, not {alignment!r}")

self._monitor = event.Monitor(event_map, trigger=trigger)
self._enable = Element(event_map.size, "rw", path=("enable",))
self._pending = Element(event_map.size, "rw", path=("pending",))
self._enable = Element(event_map.size, "rw")
self._pending = Element(event_map.size, "rw")

elem_size = ceil(event_map.size / data_width)
addr_width = 1 + max(log2_int(elem_size, need_pow2=False), alignment)
self._mux = Multiplexer(addr_width=addr_width, data_width=data_width,
alignment=alignment, name=name)
alignment=alignment)
self._mux.add(self._enable, name="enable")
self._mux.add(self._pending, name="pending")

self._signature = wiring.Signature({
super().__init__({
"src": Out(self._monitor.src.signature),
"bus": In(self._mux.bus.signature),
})
super().__init__()

@property
def signature(self):
return self._signature
self.bus.memory_map = MemoryMap(addr_width=addr_width, data_width=data_width,
alignment=alignment, name=name)
self.bus.memory_map.add_window(self._mux.bus.memory_map)

def elaborate(self, platform):
m = Module()
Expand Down
26 changes: 10 additions & 16 deletions amaranth_soc/csr/wishbone.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,19 @@ def __init__(self, csr_bus, *, data_width=None, name=None):
if data_width is None:
data_width = csr_bus.data_width

wb_signature = wishbone.Signature(
addr_width=max(0, csr_bus.addr_width - log2_int(data_width // csr_bus.data_width)),
data_width=data_width,
granularity=csr_bus.data_width)

wb_signature.memory_map = MemoryMap(addr_width=csr_bus.addr_width,
data_width=csr_bus.data_width,
name=name)
wb_sig = wishbone.Signature(addr_width=max(0, csr_bus.addr_width -
log2_int(data_width // csr_bus.data_width)),
data_width=data_width, granularity=csr_bus.data_width)

super().__init__({"wb_bus": In(wb_sig)})

self.wb_bus.memory_map = MemoryMap(addr_width=csr_bus.addr_width,
data_width=csr_bus.data_width, name=name)
# Since granularity of the Wishbone interface matches the data width of the CSR bus,
# no width conversion is performed, even if the Wishbone data width is greater.
wb_signature.memory_map.add_window(csr_bus.memory_map)
self.wb_bus.memory_map.add_window(csr_bus.memory_map)

self._signature = wiring.Signature({"wb_bus": In(wb_signature)})
self._csr_bus = csr_bus
super().__init__()

@property
def signature(self):
return self._signature
self._csr_bus = csr_bus

@property
def csr_bus(self):
Expand Down
63 changes: 22 additions & 41 deletions amaranth_soc/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,16 @@ class Signature(wiring.Signature):
"""
def __init__(self, *, trigger="level"):
self.check_parameters(trigger=trigger)

self._trigger = Source.Trigger(trigger)
self._event_map = None

members = {
super().__init__({
"i": Out(1),
"trg": In(1),
}
super().__init__(members)
})
self._trigger = Source.Trigger(trigger)

@property
def trigger(self):
return self._trigger

@property
def event_map(self):
if self._event_map is None:
raise AttributeError(f"{self!r} does not have an event map")
return self._event_map

@event_map.setter
def event_map(self, event_map):
if self.frozen:
raise ValueError(f"Signature has been frozen. Cannot set its event map")
if event_map is not None:
if not isinstance(event_map, EventMap):
raise TypeError(f"Event map must be an instance of EventMap, not {event_map!r}")
event_map.freeze()
self._event_map = event_map

def check_parameters(cls, *, trigger):
"""Validate signature parameters.
Expand All @@ -89,9 +69,7 @@ def create(self, *, path=None, src_loc_at=0):
-------
A :class:`Source` object using this signature.
"""
return Source(trigger=self.trigger,
event_map=self._event_map, # if None, do not raise an exception
path=path, src_loc_at=1 + src_loc_at)
return Source(trigger=self.trigger, path=path, src_loc_at=1 + src_loc_at)

def __eq__(self, other):
"""Compare signatures.
Expand Down Expand Up @@ -121,18 +99,26 @@ def __repr__(self):
------
See :meth:`Source.Signature.check_parameters`.
"""
def __init__(self, *, trigger="level", event_map=None, path=None, src_loc_at=0):
sig = Source.Signature(trigger=trigger)
sig.event_map = event_map
super().__init__(sig, path=path, src_loc_at=1 + src_loc_at)
def __init__(self, *, trigger="level", path=None, src_loc_at=0):
super().__init__(Source.Signature(trigger=trigger), path=path, src_loc_at=1 + src_loc_at)
self._event_map = None

@property
def trigger(self):
return self.signature.trigger

@property
def event_map(self):
return self.signature.event_map
if self._event_map is None:
raise AttributeError(f"{self!r} does not have an event map")
return self._event_map

@event_map.setter
def event_map(self, event_map):
if not isinstance(event_map, EventMap):
raise TypeError(f"Event map must be an instance of EventMap, not {event_map!r}")
event_map.freeze()
self._event_map = event_map

def __repr__(self):
return f"event.Source({self.signature!r})"
Expand Down Expand Up @@ -242,20 +228,15 @@ class Monitor(wiring.Component):
Clear selected pending events.
"""
def __init__(self, event_map, *, trigger="level"):
src_signature = Source.Signature(trigger=trigger)
src_signature.event_map = event_map

self._signature = wiring.Signature({
"src": Out(src_signature),
if not isinstance(event_map, EventMap):
raise TypeError(f"Event map must be an instance of EventMap, not {event_map!r}")
super().__init__({
"src": Out(Source.Signature(trigger=trigger)),
"enable": In(event_map.size),
"pending": In(event_map.size),
"clear": In(event_map.size),
})
super().__init__()

@property
def signature(self):
return self._signature
self.src.event_map = event_map

def elaborate(self, platform):
m = Module()
Expand Down
Loading

0 comments on commit 4e6e607

Please sign in to comment.