Skip to content
Snippets Groups Projects
Commit c4b4fdae authored by Angus Lothian's avatar Angus Lothian :dark_sunglasses: Committed by Ivar Härnqvist
Browse files

Add updated port and signal interface where connecting / disconnecting is done...

Add updated port and signal interface where connecting / disconnecting is done reflectibly between both signal and port, also add some more helper methods.
parent 3d178c98
Branches
Tags
3 merge requests!67WIP: B-ASIC version 1.0.0 hotfix,!65B-ASIC version 1.0.0,!15Add changes from sprint 1 and 2 to master
...@@ -5,6 +5,7 @@ TODO: More info. ...@@ -5,6 +5,7 @@ TODO: More info.
from b_asic.graph_component import GraphComponent, Name from b_asic.graph_component import GraphComponent, Name
class AbstractGraphComponent(GraphComponent): class AbstractGraphComponent(GraphComponent):
"""Abstract Graph Component class which is a component of a signal flow graph. """Abstract Graph Component class which is a component of a signal flow graph.
......
...@@ -4,7 +4,7 @@ TODO: More info. ...@@ -4,7 +4,7 @@ TODO: More info.
""" """
from abc import abstractmethod from abc import abstractmethod
from typing import List, Set, Dict, Optional, Any from typing import List, Dict, Optional, Any
from numbers import Number from numbers import Number
from b_asic.port import InputPort, OutputPort from b_asic.port import InputPort, OutputPort
...@@ -13,6 +13,8 @@ from b_asic.operation import Operation ...@@ -13,6 +13,8 @@ from b_asic.operation import Operation
from b_asic.simulation import SimulationState, OperationState from b_asic.simulation import SimulationState, OperationState
from b_asic.utilities import breadth_first_search from b_asic.utilities import breadth_first_search
from b_asic.abstract_graph_component import AbstractGraphComponent from b_asic.abstract_graph_component import AbstractGraphComponent
from b_asic.graph_component import Name
class AbstractOperation(Operation, AbstractGraphComponent): class AbstractOperation(Operation, AbstractGraphComponent):
"""Generic abstract operation class which most implementations will derive from. """Generic abstract operation class which most implementations will derive from.
...@@ -23,15 +25,16 @@ class AbstractOperation(Operation, AbstractGraphComponent): ...@@ -23,15 +25,16 @@ class AbstractOperation(Operation, AbstractGraphComponent):
_output_ports: List[OutputPort] _output_ports: List[OutputPort]
_parameters: Dict[str, Optional[Any]] _parameters: Dict[str, Optional[Any]]
def __init__(self, **kwds): def __init__(self, name: Name = ""):
super().__init__(**kwds) super().__init__(name)
self._input_ports = [] self._input_ports = []
self._output_ports = [] self._output_ports = []
self._parameters = {} self._parameters = {}
@abstractmethod @abstractmethod
def evaluate(self, inputs: list) -> list: def evaluate(self, inputs: list) -> list:
"""Evaluate the operation and generate a list of output values given a list of input values.""" """Evaluate the operation and generate a list of output values given a
list of input values."""
raise NotImplementedError raise NotImplementedError
def inputs(self) -> List[InputPort]: def inputs(self) -> List[InputPort]:
......
...@@ -29,10 +29,10 @@ class Constant(AbstractOperation): ...@@ -29,10 +29,10 @@ class Constant(AbstractOperation):
TODO: More info. TODO: More info.
""" """
def __init__(self, value: Number, **kwds): def __init__(self, value: Number = 0, name: Name = ""):
"""Construct a Constant.""" super().__init__(name)
super().__init__(**kwds)
self._output_ports = [OutputPort(1, self)] # TODO: Generate appropriate ID for ports. self._output_ports = [OutputPort(0, self)] # TODO: Generate appropriate ID for ports.
self._parameters["value"] = value self._parameters["value"] = value
def evaluate(self, inputs: list) -> list: def evaluate(self, inputs: list) -> list:
...@@ -48,11 +48,16 @@ class Addition(AbstractOperation): ...@@ -48,11 +48,16 @@ class Addition(AbstractOperation):
TODO: More info. TODO: More info.
""" """
def __init__(self, **kwds): def __init__(self, source1: OutputPort = None, source2: OutputPort = None, name: Name = ""):
"""Construct an Addition.""" super().__init__(name)
super().__init__(**kwds)
self._input_ports = [InputPort(1, self), InputPort(1, self)] # TODO: Generate appropriate ID for ports. self._input_ports = [InputPort(0, self), InputPort(1, self)] # TODO: Generate appropriate ID for ports.
self._output_ports = [OutputPort(1, self)] # TODO: Generate appropriate ID for ports. self._output_ports = [OutputPort(0, self)] # TODO: Generate appropriate ID for ports.
if source1 is not None:
self._input_ports[0].connect_to_port(source1)
if source2 is not None:
self._input_ports[1].connect_to_port(source2)
def evaluate(self, inputs: list) -> list: def evaluate(self, inputs: list) -> list:
return [inputs[0] + inputs[1]] return [inputs[0] + inputs[1]]
...@@ -67,13 +72,15 @@ class ConstantMultiplication(AbstractOperation): ...@@ -67,13 +72,15 @@ class ConstantMultiplication(AbstractOperation):
TODO: More info. TODO: More info.
""" """
def __init__(self, coefficient: Number, **kwds): def __init__(self, coefficient: Number, source1: OutputPort = None, name: Name = ""):
"""Construct a ConstantMultiplication.""" super().__init__(name)
super().__init__(**kwds) self._input_ports = [InputPort(0, self)] # TODO: Generate appropriate ID for ports.
self._input_ports = [InputPort(1), self] # TODO: Generate appropriate ID for ports. self._output_ports = [OutputPort(0, self)] # TODO: Generate appropriate ID for ports.
self._output_ports = [OutputPort(1, self)] # TODO: Generate appropriate ID for ports.
self._parameters["coefficient"] = coefficient self._parameters["coefficient"] = coefficient
if source1 is not None:
self._input_ports[0].connect_to_port(source1)
def evaluate(self, inputs: list) -> list: def evaluate(self, inputs: list) -> list:
return [inputs[0] * self.param("coefficient")] return [inputs[0] * self.param("coefficient")]
......
...@@ -18,17 +18,17 @@ class GraphComponent(ABC): ...@@ -18,17 +18,17 @@ class GraphComponent(ABC):
@property @property
@abstractmethod @abstractmethod
def type_name(self) -> TypeName: def type_name(self) -> TypeName:
"""Returns the type name of the graph component""" """Return the type name of the graph component"""
raise NotImplementedError raise NotImplementedError
@property @property
@abstractmethod @abstractmethod
def name(self) -> Name: def name(self) -> Name:
"""Returns the name of the graph component.""" """Return the name of the graph component."""
raise NotImplementedError raise NotImplementedError
@name.setter @name.setter
@abstractmethod @abstractmethod
def name(self, name: Name) -> None: def name(self, name: Name) -> None:
"""Sets the name of the graph component to the entered name.""" """Set the name of the graph component to the entered name."""
raise NotImplementedError raise NotImplementedError
...@@ -20,7 +20,7 @@ class GraphIDGenerator: ...@@ -20,7 +20,7 @@ class GraphIDGenerator:
self._next_id_number = defaultdict(lambda: 1) # Initalises every key element to 1 self._next_id_number = defaultdict(lambda: 1) # Initalises every key element to 1
def get_next_id(self, graph_id_type: GraphIDType) -> GraphID: def get_next_id(self, graph_id_type: GraphIDType) -> GraphID:
"""Returns the next graph id for a certain graph id type.""" """Return the next graph id for a certain graph id type."""
graph_id = graph_id_type + str(self._next_id_number[graph_id_type]) graph_id = graph_id_type + str(self._next_id_number[graph_id_type])
self._next_id_number[graph_id_type] += 1 # Increase the current id number self._next_id_number[graph_id_type] += 1 # Increase the current id number
return graph_id return graph_id
...@@ -43,13 +43,11 @@ class Operation(GraphComponent): ...@@ -43,13 +43,11 @@ class Operation(GraphComponent):
"""Get the input port at index i.""" """Get the input port at index i."""
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def output(self, i: int) -> "OutputPort": def output(self, i: int) -> "OutputPort":
"""Get the output port at index i.""" """Get the output port at index i."""
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def params(self) -> Dict[str, Optional[Any]]: def params(self) -> Dict[str, Optional[Any]]:
"""Get a dictionary of all parameter values.""" """Get a dictionary of all parameter values."""
......
...@@ -6,15 +6,16 @@ TODO: More info. ...@@ -6,15 +6,16 @@ TODO: More info.
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import NewType, Optional, List from typing import NewType, Optional, List
from b_asic.signal import Signal
from b_asic.operation import Operation from b_asic.operation import Operation
from b_asic.signal import Signal
PortId = NewType("PortId", int) PortId = NewType("PortId", int)
class Port(ABC): class Port(ABC):
"""Abstract port class. """Abstract port class.
TODO: More info.
Handles functionality for port id and saves the connection to the parent operation.
""" """
_port_id: PortId _port_id: PortId
...@@ -25,39 +26,62 @@ class Port(ABC): ...@@ -25,39 +26,62 @@ class Port(ABC):
self._operation = operation self._operation = operation
@property @property
def identifier(self) -> PortId: def id(self) -> PortId:
"""Get the unique identifier.""" """Return the unique portid."""
return self._port_id return self._port_id
@property @property
def operation(self) -> Operation: def operation(self) -> Operation:
"""Get the connected operation.""" """Return the connected operation."""
return self._operation return self._operation
@property @property
@abstractmethod @abstractmethod
def signals(self) -> List[Signal]: def signals(self) -> List[Signal]:
"""Get a list of all connected signals.""" """Return a list of all connected signals."""
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def signal(self, i: int = 0) -> Signal: def signal(self, i: int = 0) -> Signal:
"""Get the connected signal at index i.""" """Return the connected signal at index i.
Keyword argumens:
i: integer index of the signal requsted.
"""
raise NotImplementedError
@property
@abstractmethod
def connected_ports(self) -> List["Port"]:
"""Return a list of all connected Ports."""
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def signal_count(self) -> int: def signal_count(self) -> int:
"""Get the number of connected signals.""" """Return the number of connected signals."""
raise NotImplementedError
@abstractmethod
def connect_port(self, port: "Port") -> Signal:
"""Create and return a signal that is connected to this port and the entered
port and connect this port to the signal and the entered port to the signal."""
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def connect(self, signal: Signal) -> None: def connect_signal(self, signal: Signal) -> None:
"""Connect a signal.""" """Connect this port to the entered signal. If the entered signal isn't connected to
this port then connect the entered signal to the port aswell."""
raise NotImplementedError raise NotImplementedError
@abstractmethod @abstractmethod
def disconnect(self, i: int = 0) -> None: def disconnect_signal(self, i: int = 0) -> None:
"""Disconnect a signal.""" """Disconnect a signal from the port. If the port is still connected to the entered signal
then the port is disconnected from the the entered signal aswell."""
raise NotImplementedError
@abstractmethod
def is_connected_to_signal(self, signal: Signal) -> bool:
"""Return true if the port is connected to the entered signal else false."""
raise NotImplementedError raise NotImplementedError
...@@ -65,34 +89,51 @@ class InputPort(Port): ...@@ -65,34 +89,51 @@ class InputPort(Port):
"""Input port. """Input port.
TODO: More info. TODO: More info.
""" """
_source_signal: Optional[Signal]
_signal: Optional[Signal]
def __init__(self, port_id: PortId, operation: Operation): def __init__(self, port_id: PortId, operation: Operation):
super().__init__(port_id, operation) super().__init__(port_id, operation)
self._source_signal = None self._signal = None
@property @property
def signals(self) -> List[Signal]: def signals(self) -> List[Signal]:
return [] if self._source_signal is None else [self._source_signal] return [] if self._signal is None else [self._signal]
def signal(self, i: int = 0) -> Signal: def signal(self, i: int = 0) -> Signal:
assert 0 <= i < self.signal_count() # TODO: Error message. assert 0 <= i < self.signal_count(), "Signal index out of bound."
assert self._source_signal is not None # TODO: Error message. assert self._signal is not None, "No Signal connect to InputPort."
return self._source_signal return self._signal
@property
def connected_ports(self) -> List[Port]:
return [] if self._signal is None else [self._signal.source]
def signal_count(self) -> int: def signal_count(self) -> int:
return 0 if self._source_signal is None else 1 return 0 if self._signal is None else 1
def connect(self, signal: Signal) -> None: def connect_port(self, port: "OutputPort") -> Signal:
self._source_signal = signal assert self._signal is None, "Connecting new port to already connected input port."
signal.destination = self return Signal(port, self) # self._signal is set by the signal constructor
def disconnect(self, i: int = 0) -> None: def connect_signal(self, signal: Signal) -> None:
assert 0 <= i < self.signal_count() # TODO: Error message. assert self._signal is None, "Connecting new port to already connected input port."
self._source_signal.disconnect_source() self._signal = signal
self._source_signal = None if self is not signal.destination:
# Connect this inputport as destination for this signal if it isn't already.
signal.connect_destination(self)
# TODO: More stuff. def disconnect_signal(self, i: int = 0) -> None:
assert 0 <= i < self.signal_count(), "Signal Index out of range."
old_signal: Signal = self._signal
self._signal = None
if self is old_signal.destination:
# Disconnect the dest of the signal if this inputport currently is the dest
old_signal.disconnect_destination()
old_signal.disconnect_destination()
def is_connected_to_signal(self, signal: Signal) -> bool:
return self._signal is signal
class OutputPort(Port): class OutputPort(Port):
...@@ -100,30 +141,57 @@ class OutputPort(Port): ...@@ -100,30 +141,57 @@ class OutputPort(Port):
TODO: More info. TODO: More info.
""" """
_destination_signals: List[Signal] _signals: List[Signal]
def __init__(self, port_id: PortId, operation: Operation): def __init__(self, port_id: PortId, operation: Operation):
super().__init__(port_id, operation) super().__init__(port_id, operation)
self._destination_signals = [] self._signals = []
@property @property
def signals(self) -> List[Signal]: def signals(self) -> List[Signal]:
return self._destination_signals.copy() return self._signals.copy()
def signal(self, i: int = 0) -> Signal: def signal(self, i: int = 0) -> Signal:
assert 0 <= i < self.signal_count() # TODO: Error message. assert 0 <= i < self.signal_count(), "Signal index out of bounds."
return self._destination_signals[i] return self._signals[i]
def signal_count(self) -> int:
return len(self._destination_signals)
def connect(self, signal: Signal) -> None: @property
assert signal not in self._destination_signals # TODO: Error message. def connected_ports(self) -> List[Port]:
self._destination_signals.append(signal) return [signal.destination for signal in self._signals \
signal.source = self if signal.destination is not None]
def disconnect(self, i: int = 0) -> None:
assert 0 <= i < self.signal_count() # TODO: Error message.
del self._destination_signals[i]
# TODO: More stuff. def signal_count(self) -> int:
return len(self._signals)
def connect_port(self, port: InputPort) -> Signal:
return Signal(self, port) # Signal is added to self._signals in signal constructor
def connect_signal(self, signal: Signal) -> None:
assert not self.is_connected_to_signal(signal), \
"Attempting to connect to Signal already connected."
self._signals.append(signal)
if self is not signal.source:
# Connect this outputport to the signal if it isn't already
signal.connect_source(self)
def disconnect_signal(self, i: int = 0) -> None:
assert 0 <= i < self.signal_count(), "Signal index out of bounds."
old_signal: Signal = self._signals[i]
del self._signals[i]
if self is old_signal.source:
# Disconnect the source of the signal if this outputport currently is the source
old_signal.disconnect_source()
def disconnect_signal_by_ref(self, signal: Signal) -> None:
"""Remove the signal that was entered from the OutputPorts signals.
If the entered signal still is connected to this port then disconnect the
entered signal from the port aswell.
Keyword arguments:
- signal: Signal to remove.
"""
i: int = self._signals.index(signal)
self.disconnect_signal(i)
def is_connected_to_signal(self, signal: Signal) -> bool:
return signal in self._signals # O(n) complexity
"""@package docstring """@package docstring
B-ASIC Signal Module. B-ASIC Signal Module.
""" """
from typing import TYPE_CHECKING, Optional from typing import Optional, TYPE_CHECKING
from b_asic.graph_component import TypeName from b_asic.graph_component import TypeName
from b_asic.abstract_graph_component import AbstractGraphComponent from b_asic.abstract_graph_component import AbstractGraphComponent
from b_asic.graph_component import Name
if TYPE_CHECKING: if TYPE_CHECKING:
from b_asic import OutputPort, InputPort from b_asic.port import InputPort, OutputPort
class Signal(AbstractGraphComponent): class Signal(AbstractGraphComponent):
"""A connection between two ports.""" """A connection between two ports."""
_source: "OutputPort" _source: "OutputPort"
_destination: "InputPort" _destination: "InputPort"
def __init__(self, src: Optional["OutputPort"] = None, dest: Optional["InputPort"] = None, **kwds): def __init__(self, source: Optional["OutputPort"] = None, \
super().__init__(**kwds) destination: Optional["InputPort"] = None, name: Name = ""):
self._source = src
self._destination = dest super().__init__(name)
self._source = source
self._destination = destination
if source is not None:
self.connect_source(source)
if destination is not None:
self.connect_destination(destination)
@property @property
def source(self) -> "OutputPort": def source(self) -> "OutputPort":
"""Returns the source OutputPort of the signal.""" """Return the source OutputPort of the signal."""
return self._source return self._source
@property @property
def destination(self) -> "InputPort": def destination(self) -> "InputPort":
"""Returns the destination InputPort of the signal.""" """Return the destination "InputPort" of the signal."""
return self._destination return self._destination
@source.setter def connect_source(self, src: "OutputPort") -> None:
def source(self, src: "OutputPort") -> None: """Disconnect the previous source OutputPort of the signal and
"""Sets the value of the source OutputPort of the signal.""" 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.
"""
self.disconnect_source()
self._source = src self._source = src
if not src.is_connected_to_signal(self):
# If the new source isn't connected to this signal then connect it.
src.connect_signal(self)
@destination.setter def connect_destination(self, dest: "InputPort") -> None:
def destination(self, dest: "InputPort") -> None: """Disconnect the previous destination InputPort of the signal and
"""Sets the value of the destination InputPort of the signal.""" 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.
"""
self.disconnect_destination()
self._destination = dest self._destination = dest
if not dest.is_connected_to_signal(self):
# If the new destination isn't connected to tis signal then connect it.
dest.connect_signal(self)
@property @property
def type_name(self) -> TypeName: def type_name(self) -> TypeName:
return "s" return "s"
def disconnect_source(self) -> None: def disconnect_source(self) -> None:
"""Disconnects the source OutputPort of the signal.""" """Disconnect the source OutputPort of the signal. If the source port
self._source = None still is connected to this signal then also disconnect the source port."""
if self._source is not None:
old_source: "OutputPort" = self._source
self._source = None
if old_source.is_connected_to_signal(self):
# If the old destination port still is connected to this signal, then disconnect it.
old_source.disconnect_signal_by_ref(self)
def disconnect_destination(self) -> None: def disconnect_destination(self) -> None:
"""Disconnects the destination InputPort of the signal.""" """Disconnect the destination InputPort of the signal."""
self._destination = None if self._destination is not None:
old_destination: "InputPort" = self._destination
self._destination = None
if old_destination.is_connected_to_signal(self):
# If the old destination port still is connected to this signal, then disconnect it.
old_destination.disconnect_signal()
def is_connected(self) -> bool:
"""Returns true if the signal is connected to both a source and a destination,
else false."""
return self._source is not None and self._destination is not None
...@@ -50,8 +50,8 @@ class SFG(AbstractOperation): ...@@ -50,8 +50,8 @@ class SFG(AbstractOperation):
return [] # TODO: Implement return [] # TODO: Implement
def _add_graph_component(self, graph_component: GraphComponent) -> GraphID: def _add_graph_component(self, graph_component: GraphComponent) -> GraphID:
"""Adds the entered graph component to the SFG's dictionary of graph objects and """Add the entered graph component to the SFG's dictionary of graph objects and
returns a generated GraphID for it. return a generated GraphID for it.
Keyword arguments: Keyword arguments:
graph_component: Graph component to add to the graph. graph_component: Graph component to add to the graph.
...@@ -65,8 +65,8 @@ class SFG(AbstractOperation): ...@@ -65,8 +65,8 @@ class SFG(AbstractOperation):
return graph_id return graph_id
def find_by_id(self, graph_id: GraphID) -> Optional[GraphComponent]: def find_by_id(self, graph_id: GraphID) -> Optional[GraphComponent]:
"""Finds a graph object based on the entered Graph ID and returns it. If no graph """Find a graph object based on the entered Graph ID and return it. If no graph
object with the entered ID was found then returns None. object with the entered ID was found then return None.
Keyword arguments: Keyword arguments:
graph_id: Graph ID of the wanted object. graph_id: Graph ID of the wanted object.
...@@ -77,8 +77,8 @@ class SFG(AbstractOperation): ...@@ -77,8 +77,8 @@ class SFG(AbstractOperation):
return None return None
def find_by_name(self, name: Name) -> List[GraphComponent]: def find_by_name(self, name: Name) -> List[GraphComponent]:
"""Finds all graph objects that have the entered name and returns them """Find all graph objects that have the entered name and return them
in a list. If no graph object with the entered name was found then returns an in a list. If no graph object with the entered name was found then return an
empty list. empty list.
Keyword arguments: Keyword arguments:
......
...@@ -10,9 +10,9 @@ def operation(): ...@@ -10,9 +10,9 @@ def operation():
def create_operation(_type, dest_oper, index, **kwargs): def create_operation(_type, dest_oper, index, **kwargs):
oper = _type(**kwargs) oper = _type(**kwargs)
oper_signal = Signal() oper_signal = Signal()
oper._output_ports[0].connect(oper_signal) oper._output_ports[0].connect_signal(oper_signal)
dest_oper._input_ports[index].connect(oper_signal) dest_oper._input_ports[index].connect_signal(oper_signal)
return oper return oper
@pytest.fixture @pytest.fixture
...@@ -50,11 +50,11 @@ def large_operation_tree(): ...@@ -50,11 +50,11 @@ def large_operation_tree():
create_operation(Constant, add_oper_2, 1, value=5) create_operation(Constant, add_oper_2, 1, value=5)
add_oper_3 = Addition() add_oper_3 = Addition()
add_oper_signal = Signal(add_oper, add_oper_3) add_oper_signal = Signal(add_oper.output(0), add_oper_3.output(0))
add_oper._output_ports[0].connect(add_oper_signal) add_oper._output_ports[0].connect_signal(add_oper_signal)
add_oper_3._input_ports[0].connect(add_oper_signal) add_oper_3._input_ports[0].connect_signal(add_oper_signal)
add_oper_2_signal = Signal(add_oper_2, add_oper_3) add_oper_2_signal = Signal(add_oper_2.output(0), add_oper_3.output(0))
add_oper_2._output_ports[0].connect(add_oper_2_signal) add_oper_2._output_ports[0].connect_signal(add_oper_2_signal)
add_oper_3._input_ports[1].connect(add_oper_2_signal) add_oper_3._input_ports[1].connect_signal(add_oper_2_signal)
return const_oper return const_oper
import pytest
...@@ -2,19 +2,83 @@ ...@@ -2,19 +2,83 @@
B-ASIC test suite for Inputport B-ASIC test suite for Inputport
""" """
from b_asic import InputPort
import pytest import pytest
def test_connect_multiple_signals(signals): from b_asic import InputPort, OutputPort
""" from b_asic import Signal
test if only one signal can connect to an input port
""" @pytest.fixture
def inp_port():
return InputPort(0, None)
@pytest.fixture
def out_port():
return OutputPort(0, None)
@pytest.fixture
def out_port2():
return OutputPort(1, None)
@pytest.fixture
def dangling_sig():
return Signal()
@pytest.fixture
def s_w_source():
out_port = OutputPort(0, None)
return Signal(source=out_port)
@pytest.fixture
def sig_with_dest():
inp_port = InputPort(0, None)
return Signal(destination=out_port)
@pytest.fixture
def connected_sig():
out_port = OutputPort(0, None)
inp_port = InputPort(0, None) inp_port = InputPort(0, None)
return Signal(source=out_port, destination=inp_port)
def test_connect_port_then_disconnect(inp_port, out_port):
"""Test connect unused port to port."""
s1 = inp_port.connect_port(out_port)
assert inp_port.connected_ports == [out_port]
assert out_port.connected_ports == [inp_port]
assert inp_port.signals == [s1]
assert out_port.signals == [s1]
assert s1.source is out_port
assert s1.destination is inp_port
inp_port.disconnect_signal()
assert inp_port.connected_ports == []
assert out_port.connected_ports == []
assert inp_port.signals == []
assert out_port.signals == [s1]
assert s1.source is out_port
assert s1.destination is None
def test_connect_used_port_to_new_port(inp_port, out_port, out_port2):
"""Does connecting multiple ports to an inputport throw error?"""
inp_port.connect_port(out_port)
with pytest.raises(AssertionError):
inp_port.connect_port(out_port2)
def test_connect_signal_then_disconnect(inp_port, s_w_source):
inp_port.connect_signal(s_w_source)
assert inp_port.connected_ports == [s_w_source.source]
assert s_w_source.source.connected_ports == [inp_port]
assert inp_port.signals == [s_w_source]
assert s_w_source.source.signals == [s_w_source]
assert s_w_source.destination is inp_port
for s in signals: inp_port.disconnect_signal()
inp_port.connect(s)
assert inp_port.signal_count() == 1 assert inp_port.connected_ports == []
assert inp_port.signals[0] == signals[-1] assert s_w_source.source.connected_ports == []
assert inp_port.signals == []
assert s_w_source.source.signals == [s_w_source]
assert s_w_source.destination is None
""" """
B-ASIC test suite for InputPort B-ASIC test suite for OutputPort
TODO: More info TODO: More info
""" """
from b_asic import OutputPort from b_asic import InputPort, OutputPort
import pytest import pytest
def test_connect_multiple_signals(signals): @pytest.fixture
""" def inp_ports():
test if multiple signals can connect to an output port return [InputPort(_, None) for _ in range(0,3)]
"""
outp_port = OutputPort(0, None)
for s in signals: def test_connect_multiple_signals(inp_ports):
outp_port.connect(s) """Can multiple ports connect to an output port?"""
out_port = OutputPort(0, None)
assert outp_port.signal_count() == 3 for port in inp_ports:
assert outp_port.signals == signals out_port.connect_port(port)
assert out_port.signal_count() == len(inp_ports)
def test_disconnect_multiple_signals(inp_ports):
"""Can multiple ports disconnect from an output port?"""
out_port = OutputPort(0, None)
for port in inp_ports:
out_port.connect_port(port)
for _ in inp_ports:
out_port.disconnect_signal(0)
assert out_port.signal_count() == 0
\ No newline at end of file
"""
B-ASIC test suit for the signal module which consists of the Signal class.
"""
from b_asic.port import InputPort, OutputPort
from b_asic.signal import Signal
import pytest
def test_signal_creation_and_disconnction_and_connection_changing():
in_port = InputPort(0, None)
out_port = OutputPort(1, None)
s = Signal(out_port, in_port)
assert in_port.signals == [s]
assert out_port.signals == [s]
assert s.source is out_port
assert s.destination is in_port
in_port1 = InputPort(0, None)
s.connect_destination(in_port1)
assert in_port.signals == []
assert in_port1.signals == [s]
assert out_port.signals == [s]
assert s.source is out_port
assert s.destination is in_port1
s.disconnect_source()
assert out_port.signals == []
assert in_port1.signals == [s]
assert s.source is None
assert s.destination is in_port1
s.disconnect_destination()
assert out_port.signals == []
assert in_port1.signals == []
assert s.source is None
assert s.destination is None
out_port1 = OutputPort(0, None)
s.connect_source(out_port1)
assert out_port1.signals == [s]
assert s.source is out_port1
assert s.destination is None
s.connect_source(out_port)
assert out_port.signals == [s]
assert out_port1.signals == []
assert s.source is out_port
assert s.destination is None
s.connect_destination(in_port)
assert out_port.signals == [s]
assert in_port.signals == [s]
assert s.source is out_port
assert s.destination is in_port
import pytest
...@@ -24,6 +24,7 @@ def test_traverse_type(large_operation_tree): ...@@ -24,6 +24,7 @@ def test_traverse_type(large_operation_tree):
def test_traverse_loop(operation_tree): def test_traverse_loop(operation_tree):
add_oper_signal = Signal() add_oper_signal = Signal()
operation_tree._output_ports[0].connect(add_oper_signal) operation_tree._output_ports[0].connect_signal(add_oper_signal)
operation_tree._input_ports[0].connect(add_oper_signal) operation_tree._input_ports[0].disconnect_signal()
operation_tree._input_ports[0].connect_signal(add_oper_signal)
assert len(list(operation_tree.traverse())) == 2 assert len(list(operation_tree.traverse())) == 2
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment