"""@package docstring B-ASIC Port Module. TODO: More info. """ from abc import ABC, abstractmethod from typing import NewType, Optional, List from b_asic.signal import Signal from b_asic.operation import Operation PortId = NewType("PortId", int) class Port(ABC): """Abstract port class. TODO: More info. """ _port_id: PortId _operation: Operation def __init__(self, port_id: PortId, operation: Operation): self._port_id = port_id self._operation = operation @property def identifier(self) -> PortId: """Get the unique identifier.""" return self._port_id @property def operation(self) -> Operation: """Get the connected operation.""" return self._operation @property @abstractmethod def signals(self) -> List[Signal]: """Get a list of all connected signals.""" raise NotImplementedError @abstractmethod def signal(self, i: int = 0) -> Signal: """Get the connected signal at index i.""" raise NotImplementedError @abstractmethod def signal_count(self) -> int: """Get the number of connected signals.""" raise NotImplementedError @abstractmethod def connect(self, signal: Signal) -> None: """Connect a signal.""" raise NotImplementedError @abstractmethod def disconnect(self, i: int = 0) -> None: """Disconnect a signal.""" raise NotImplementedError class InputPort(Port): """Input port. TODO: More info. """ _source_signal: Optional[Signal] def __init__(self, port_id: PortId, operation: Operation): super().__init__(port_id, operation) self._source_signal = None @property def signals(self) -> List[Signal]: return [] if self._source_signal is None else [self._source_signal] def signal(self, i: int = 0) -> Signal: assert 0 <= i < self.signal_count() # TODO: Error message. assert self._source_signal is not None # TODO: Error message. return self._source_signal def signal_count(self) -> int: return 0 if self._source_signal is None else 1 def connect(self, signal: Signal) -> None: self._source_signal = signal signal.destination = self def disconnect(self, i: int = 0) -> None: assert 0 <= i < self.signal_count() # TODO: Error message. self._source_signal.disconnect_source() self._source_signal = None # TODO: More stuff. class OutputPort(Port): """Output port. TODO: More info. """ _destination_signals: List[Signal] def __init__(self, port_id: PortId, operation: Operation): super().__init__(port_id, operation) self._destination_signals = [] @property def signals(self) -> List[Signal]: return self._destination_signals.copy() def signal(self, i: int = 0) -> Signal: assert 0 <= i < self.signal_count() # TODO: Error message. return self._destination_signals[i] def signal_count(self) -> int: return len(self._destination_signals) def connect(self, signal: Signal) -> None: assert signal not in self._destination_signals # TODO: Error message. self._destination_signals.append(signal) signal.source = self def disconnect(self, i: int = 0) -> None: assert 0 <= i < self.signal_count() # TODO: Error message. del self._destination_signals[i] # TODO: More stuff.