hdl, back: add and use SignalSet/SignalDict.

This commit is contained in:
whitequark 2018-12-17 17:21:12 +00:00
parent 8c4de99c0d
commit 8d1639a5a8
8 changed files with 87 additions and 54 deletions

View file

@ -13,7 +13,7 @@ __all__ = [
"Array", "ArrayProxy",
"Signal", "ClockSignal", "ResetSignal",
"Statement", "Assign", "Switch", "Delay", "Tick", "Passive",
"ValueKey", "ValueDict", "ValueSet",
"ValueKey", "ValueDict", "ValueSet", "SignalKey", "SignalDict", "SignalSet",
]
@ -28,14 +28,14 @@ class DUID:
class Value(metaclass=ABCMeta):
@staticmethod
def wrap(obj):
"""Ensures that the passed object is a Migen value. Booleans and integers
"""Ensures that the passed object is an nMigen value. Booleans and integers
are automatically wrapped into ``Const``."""
if isinstance(obj, Value):
return obj
elif isinstance(obj, (bool, int)):
return Const(obj)
else:
raise TypeError("Object '{!r}' is not a Migen value".format(obj))
raise TypeError("Object '{!r}' is not an nMigen value".format(obj))
def __init__(self, src_loc_at=0):
super().__init__()
@ -47,7 +47,7 @@ class Value(metaclass=ABCMeta):
self.src_loc = (tb[0].filename, tb[0].lineno)
def __bool__(self):
raise TypeError("Attempted to convert Migen value to boolean")
raise TypeError("Attempted to convert nMigen value to boolean")
def __invert__(self):
return Operator("~", [self])
@ -801,7 +801,7 @@ class Statement:
if isinstance(obj, Statement):
return _StatementList([obj])
else:
raise TypeError("Object '{!r}' is not a Migen statement".format(obj))
raise TypeError("Object '{!r}' is not an nMigen statement".format(obj))
class Assign(Statement):
@ -936,7 +936,8 @@ class _MappedKeyDict(MutableMapping, _MappedKeyCollection):
def __repr__(self):
pairs = ["({!r}, {!r})".format(k, v) for k, v in self.items()]
return "{}([{}])".format(type(self).__name__, ", ".join(pairs))
return "{}.{}([{}])".format(type(self).__module__, type(self).__name__,
", ".join(pairs))
class _MappedKeySet(MutableSet, _MappedKeyCollection):
@ -967,7 +968,8 @@ class _MappedKeySet(MutableSet, _MappedKeyCollection):
return len(self._storage)
def __repr__(self):
return "{}({})".format(type(self).__name__, ", ".join(repr(x) for x in self))
return "{}.{}({})".format(type(self).__module__, type(self).__name__,
", ".join(repr(x) for x in self))
class ValueKey:
@ -1060,3 +1062,34 @@ class ValueDict(_MappedKeyDict):
class ValueSet(_MappedKeySet):
_map_key = ValueKey
_unmap_key = lambda self, key: key.value
class SignalKey:
def __init__(self, signal):
if not isinstance(signal, Signal):
raise TypeError("Object '{!r}' is not an nMigen signal")
self.signal = signal
def __hash__(self):
return hash(self.signal.duid)
def __eq__(self, other):
return isinstance(other, SignalKey) and self.signal.duid == other.signal.duid
def __lt__(self, other):
if not isinstance(other, SignalKey):
raise TypeError("Object '{!r}' cannot be compared to a SignalKey")
return self.signal.duid < other.signal.duid
def __repr__(self):
return "<{}.SignalKey {!r}>".format(__name__, self.signal)
class SignalDict(_MappedKeyDict):
_map_key = SignalKey
_unmap_key = lambda self, key: key.signal
class SignalSet(_MappedKeySet):
_map_key = SignalKey
_unmap_key = lambda self, key: key.signal

View file

@ -102,7 +102,7 @@ class Module(_ModuleBuilderRoot):
self._ctrl_context = None
self._ctrl_stack = []
self._driving = ValueDict()
self._driving = SignalDict()
self._submodules = []
self._domains = []

View file

@ -15,7 +15,7 @@ class DriverConflict(UserWarning):
class Fragment:
def __init__(self):
self.ports = ValueDict()
self.ports = SignalDict()
self.drivers = OrderedDict()
self.statements = []
self.domains = OrderedDict()
@ -31,7 +31,7 @@ class Fragment:
def add_driver(self, signal, domain=None):
if domain not in self.drivers:
self.drivers[domain] = ValueSet()
self.drivers[domain] = SignalSet()
self.drivers[domain].add(signal)
def iter_drivers(self):
@ -51,7 +51,7 @@ class Fragment:
yield domain, signal
def iter_signals(self):
signals = ValueSet()
signals = SignalSet()
signals |= self.ports.keys()
for domain, domain_signals in self.drivers.items():
if domain is not None:
@ -81,7 +81,7 @@ class Fragment:
def _resolve_driver_conflicts(self, hierarchy=("top",), mode="warn"):
assert mode in ("silent", "warn", "error")
driver_subfrags = ValueDict()
driver_subfrags = SignalDict()
# For each signal driven by this fragment and/or its subfragments, determine which
# subfragments also drive it.
@ -147,7 +147,7 @@ class Fragment:
return self._resolve_driver_conflicts(hierarchy, mode)
# Nothing was flattened, we're done!
return ValueSet(driver_subfrags.keys())
return SignalSet(driver_subfrags.keys())
def _propagate_domains_up(self, hierarchy=("top",)):
from .xfrm import DomainRenamer
@ -229,8 +229,8 @@ class Fragment:
def _propagate_ports(self, ports):
# Collect all signals we're driving (on LHS of statements), and signals we're using
# (on RHS of statements, or in clock domains).
self_driven = union(s._lhs_signals() for s in self.statements) or ValueSet()
self_used = union(s._rhs_signals() for s in self.statements) or ValueSet()
self_driven = union(s._lhs_signals() for s in self.statements) or SignalSet()
self_used = union(s._rhs_signals() for s in self.statements) or SignalSet()
for domain, _ in self.iter_sync():
cd = self.domains[domain]
self_used.add(cd.clk)