Newer
Older

Ivar Härnqvist
committed
from typing import Optional, Iterable, TYPE_CHECKING
Angus Lothian
committed

Ivar Härnqvist
committed
from b_asic.graph_component import GraphComponent, AbstractGraphComponent, TypeName, Name
Angus Lothian
committed
Angus Lothian
committed
from b_asic.port import InputPort, OutputPort
Angus Lothian
committed
Angus Lothian
committed
class Signal(AbstractGraphComponent):
Angus Lothian
committed
_source: Optional["OutputPort"]
_destination: Optional["InputPort"]

Ivar Härnqvist
committed
def __init__(self, source: Optional["OutputPort"] = None, destination: Optional["InputPort"] = None, bits: Optional[int] = None, name: Name = ""):
Angus Lothian
committed
super().__init__(name)
Angus Lothian
committed
if source is not None:
Angus Lothian
committed
self.set_source(source)
Angus Lothian
committed
if destination is not None:
Angus Lothian
committed
self.set_destination(destination)

Ivar Härnqvist
committed
self.set_param("bits", bits)
@classmethod
def type_name(cls) -> TypeName:

Ivar Härnqvist
committed
return "s"
@property
def neighbors(self) -> Iterable[GraphComponent]:
return [p.operation for p in [self.source, self.destination] if p is not None]
Angus Lothian
committed
"""Return the source OutputPort of the signal."""
Angus Lothian
committed
"""Return the destination "InputPort" of the signal."""
Angus Lothian
committed
def set_source(self, src: "OutputPort") -> None:
Angus Lothian
committed
"""Disconnect the previous source OutputPort of the signal and
connect to the entered source OutputPort. Also connect the entered
source port to the signal if it hasn't already been connected.
Keyword arguments:
- src: OutputPort to connect as source to the signal.
"""
if src is not self._source:
self.remove_source()
self._source = src
if self not in src.signals:
src.add_signal(self)
Angus Lothian
committed
def set_destination(self, dest: "InputPort") -> None:
Angus Lothian
committed
"""Disconnect the previous destination InputPort of the signal and
connect to the entered destination InputPort. Also connect the entered
destination port to the signal if it hasn't already been connected.
Keywords argments:
- dest: InputPort to connect as destination to the signal.
"""
if dest is not self._destination:
self.remove_destination()
self._destination = dest
if self not in dest.signals:
dest.add_signal(self)
Angus Lothian
committed
def remove_source(self) -> None:
Angus Lothian
committed
"""Disconnect the source OutputPort of the signal. If the source port
still is connected to this signal then also disconnect the source port."""
Angus Lothian
committed
self._source = None
Angus Lothian
committed
def remove_destination(self) -> None:
Angus Lothian
committed
"""Disconnect the destination InputPort of the signal."""
Angus Lothian
committed
self._destination = None
if self in dest.signals:
dest.remove_signal(self)
Angus Lothian
committed
def dangling(self) -> bool:
"""Returns true if the signal is missing either a source or a destination,
Angus Lothian
committed
else false."""
return self._source is None or self._destination is None

Ivar Härnqvist
committed
@property
def bits(self) -> Optional[int]:
"""Get the number of bits that this operations using this signal as an input should truncate received values to.
None = unlimited."""
return self.param("bits")
@bits.setter
def bits(self, bits: Optional[int]) -> None:
"""Set the number of bits that operations using this signal as an input should truncate received values to.
None = unlimited."""
assert bits is None or (isinstance(bits, int)
and bits >= 0), "Bits must be non-negative."
self.set_param("bits", bits)