"""@package docstring B-ASIC Signal Flow Graph Module. TODO: More info. """ from typing import List, Dict, Optional, DefaultDict from collections import defaultdict from b_asic.operation import Operation from b_asic.abstract_operation import AbstractOperation from b_asic.signal import Signal from b_asic.graph_id import GraphIDGenerator, GraphID from b_asic.graph_component import GraphComponent, Name, TypeName class SFG(AbstractOperation): """Signal flow graph. TODO: More info. """ _graph_components_by_id: Dict[GraphID, GraphComponent] _graph_components_by_name: DefaultDict[Name, List[GraphComponent]] _graph_id_generator: GraphIDGenerator def __init__(self, input_signals: List[Signal] = None, output_signals: List[Signal] = None, \ ops: List[Operation] = None, **kwds): super().__init__(**kwds) if input_signals is None: input_signals = [] if output_signals is None: output_signals = [] if ops is None: ops = [] self._graph_components_by_id = dict() # Maps Graph ID to objects self._graph_components_by_name = defaultdict(list) # Maps Name to objects self._graph_id_generator = GraphIDGenerator() for operation in ops: self._add_graph_component(operation) for input_signal in input_signals: self._add_graph_component(input_signal) # TODO: Construct SFG based on what inputs that were given # TODO: Traverse the graph between the inputs/outputs and add to self._operations. # TODO: Connect ports with signals with appropriate IDs. def evaluate(self, inputs: list) -> list: return [] # TODO: Implement def _add_graph_component(self, graph_component: GraphComponent) -> GraphID: """Adds the entered graph component to the SFG's dictionary of graph objects and returns a generated GraphID for it. Keyword arguments: graph_component: Graph component to add to the graph. """ # Add to name dict self._graph_components_by_name[graph_component.name].append(graph_component) # Add to ID dict graph_id: GraphID = self._graph_id_generator.get_next_id(graph_component.type_name) self._graph_components_by_id[graph_id] = graph_component return graph_id 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 object with the entered ID was found then returns None. Keyword arguments: graph_id: Graph ID of the wanted object. """ if graph_id in self._graph_components_by_id: return self._graph_components_by_id[graph_id] return None def find_by_name(self, name: Name) -> List[GraphComponent]: """Finds all graph objects that have the entered name and returns them in a list. If no graph object with the entered name was found then returns an empty list. Keyword arguments: name: Name of the wanted object. """ return self._graph_components_by_name[name] @property def type_name(self) -> TypeName: return "sfg"