From b7624227b29a435388bb3f8f8442cd1656b4d786 Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Tue, 11 Apr 2023 17:06:18 +0200
Subject: [PATCH] Add support for operator processcollections

---
 b_asic/process.py                    | 12 ++++++------
 b_asic/resources.py                  | 28 ++++++++++++++++++++++++++-
 b_asic/schedule.py                   | 29 +++++++++++++++++++++++-----
 examples/secondorderdirectformiir.py |  2 ++
 4 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/b_asic/process.py b/b_asic/process.py
index e75d12a0..67ab222c 100644
--- a/b_asic/process.py
+++ b/b_asic/process.py
@@ -29,8 +29,8 @@ class Process:
         self._start_time = start_time
         self._execution_time = execution_time
         if name is None:
-            self._name = f"Proc. {PlainMemoryVariable._name_cnt}"
-            PlainMemoryVariable._name_cnt += 1
+            self._name = f"Proc. {Process._name_cnt}"
+            Process._name_cnt += 1
         else:
             self._name = name
 
@@ -87,12 +87,12 @@ class OperatorProcess(Process):
         execution_time = operation.execution_time
         if execution_time is None:
             raise ValueError(
-                "Operation {operation!r} does not have an execution time specified!"
+                f"Operation {operation!r} does not have an execution time specified!"
             )
         super().__init__(
             start_time,
             execution_time,
-            name=name,
+            name=name or operation.name or operation.graph_id,
         )
         self._operation = operation
 
@@ -109,8 +109,8 @@ class MemoryVariable(Process):
     write_port : :class:`~b_asic.port.OutputPort`
         The OutputPort that the memory variable originates from.
     reads : dict
-        Dictionary with :class:`~b_asic.port.InputPort` that reads the memory variable as key and
-        for how long after the *write_time* it will read.
+        Dictionary with :class:`~b_asic.port.InputPort` that reads the memory variable
+        as key and for how long after the *write_time* it will read.
     name : str, optional
         The name of the process.
     """
diff --git a/b_asic/resources.py b/b_asic/resources.py
index b81c7163..4003d1e8 100644
--- a/b_asic/resources.py
+++ b/b_asic/resources.py
@@ -9,7 +9,8 @@ from matplotlib.axes import Axes
 from matplotlib.ticker import MaxNLocator
 
 from b_asic._preferences import LATENCY_COLOR
-from b_asic.process import MemoryVariable, PlainMemoryVariable, Process
+from b_asic.process import MemoryVariable, OperatorProcess, PlainMemoryVariable, Process
+from b_asic.types import TypeName
 
 # Default latency coloring RGB tuple
 _LATENCY_COLOR = tuple(c / 255 for c in LATENCY_COLOR)
@@ -1120,3 +1121,28 @@ class ProcessCollection:
                 write_ports=write_ports,
                 total_ports=total_ports,
             )
+
+    def get_by_type_name(self, type_name: TypeName) -> "ProcessCollection":
+        """
+        Return a ProcessCollection with only a given type of operations.
+
+        Parameters
+        ----------
+        type_name : TypeName
+            The type_name of the operation.
+
+        Returns
+        -------
+        ProcessCollection
+
+        """
+        return ProcessCollection(
+            {
+                process
+                for process in self._collection
+                if isinstance(process, OperatorProcess)
+                and process._operation.type_name() == type_name
+            },
+            self._schedule_time,
+            self._cyclic,
+        )
diff --git a/b_asic/schedule.py b/b_asic/schedule.py
index 45da224b..628117c4 100644
--- a/b_asic/schedule.py
+++ b/b_asic/schedule.py
@@ -31,7 +31,7 @@ from b_asic._preferences import (
 from b_asic.graph_component import GraphID
 from b_asic.operation import Operation
 from b_asic.port import InputPort, OutputPort
-from b_asic.process import MemoryVariable
+from b_asic.process import MemoryVariable, OperatorProcess
 from b_asic.resources import ProcessCollection
 from b_asic.signal_flow_graph import SFG
 from b_asic.special_operations import Delay, Input, Output
@@ -294,13 +294,13 @@ class Schedule:
 
     @property
     def start_times(self) -> Dict[GraphID, int]:
-        """The start times of the operations in the current schedule."""
+        """The start times of the operations in the schedule."""
         return self._start_times
 
     @property
     def laps(self) -> Dict[GraphID, int]:
         """
-        The number of laps for the start times of the operations in the current schedule.
+        The number of laps for the start times of the operations in the schedule.
         """
         return self._laps
 
@@ -674,8 +674,8 @@ class Schedule:
                 ] + cast(int, source_port.latency_offset)
         self._remove_delays()
 
-    def _get_memory_variables_list(self) -> List['MemoryVariable']:
-        ret: List['MemoryVariable'] = []
+    def _get_memory_variables_list(self) -> List[MemoryVariable]:
+        ret: List[MemoryVariable] = []
         for graph_id, start_time in self._start_times.items():
             slacks = self._forward_slacks(graph_id)
             for outport, signals in slacks.items():
@@ -707,6 +707,25 @@ class Schedule:
             set(self._get_memory_variables_list()), self.schedule_time
         )
 
+    def get_operations(self) -> ProcessCollection:
+        """
+        Return a :class:`~b_asic.resources.ProcessCollection` containing all
+        operations.
+
+        Returns
+        -------
+        ProcessCollection
+
+        """
+        return ProcessCollection(
+            {
+                OperatorProcess(start_time, self._sfg.find_by_id(graph_id))
+                for graph_id, start_time in self._start_times.items()
+            },
+            self.schedule_time,
+            self.cyclic,
+        )
+
     def _get_y_position(
         self, graph_id, operation_height=1.0, operation_gap=None
     ) -> float:
diff --git a/examples/secondorderdirectformiir.py b/examples/secondorderdirectformiir.py
index e78a48f3..413bf2da 100644
--- a/examples/secondorderdirectformiir.py
+++ b/examples/secondorderdirectformiir.py
@@ -35,6 +35,8 @@ sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2)
 sfg.set_latency_of_type(Addition.type_name(), 1)
 sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1)
 sfg.set_execution_time_of_type(Addition.type_name(), 1)
+sfg.set_execution_time_of_type(Input.type_name(), 1)
+sfg.set_execution_time_of_type(Output.type_name(), 1)
 
 # %%
 # Create schedule
-- 
GitLab