From d936a145da1401012521b6e3c7c5a8cad8df0492 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson <oscar.gustafsson@gmail.com> Date: Fri, 20 Jan 2023 14:51:57 +0100 Subject: [PATCH] Add support for increasing time resolution --- b_asic/operation.py | 9 ++++- b_asic/schedule.py | 32 +++++++++--------- test/test_schedule.py | 76 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 16 deletions(-) diff --git a/b_asic/operation.py b/b_asic/operation.py index c8a80b5f..29ea9fef 100644 --- a/b_asic/operation.py +++ b/b_asic/operation.py @@ -916,7 +916,8 @@ class AbstractOperation(Operation, AbstractGraphComponent): ) @property - def execution_time(self) -> Optional[int]: + def execution_time(self) -> Union[int, None]: + """Execution time of operation.""" return self._execution_time @execution_time.setter @@ -925,6 +926,12 @@ class AbstractOperation(Operation, AbstractGraphComponent): raise ValueError("Execution time cannot be negative") self._execution_time = execution_time + def _increase_time_resolution(self, factor: int): + if self._execution_time is not None: + self._execution_time *= factor + for port in [*self.inputs, *self.outputs]: + port.latency_offset *= factor + def get_plot_coordinates( self, ) -> Tuple[List[List[Number]], List[List[Number]]]: diff --git a/b_asic/schedule.py b/b_asic/schedule.py index e311774b..2c527883 100644 --- a/b_asic/schedule.py +++ b/b_asic/schedule.py @@ -30,14 +30,12 @@ class Schedule: _laps: Dict[GraphID, List[int]] _schedule_time: int _cyclic: bool - _resolution: int def __init__( self, sfg: SFG, schedule_time: Optional[int] = None, cyclic: bool = False, - resolution: int = 1, scheduling_alg: str = "ASAP", ): """Construct a Schedule from an SFG.""" @@ -45,8 +43,6 @@ class Schedule: self._start_times = {} self._laps = defaultdict(lambda: 0) self._cyclic = cyclic - self._resolution = resolution - if scheduling_alg == "ASAP": self._schedule_asap() else: @@ -182,12 +178,22 @@ class Schedule: def cyclic(self) -> bool: return self._cyclic - @property - def resolution(self) -> int: - return self._resolution - def increase_time_resolution(self, factor: int) -> "Schedule": - raise NotImplementedError + """ + Increase time resolution for a schedule. + + Parameters + ========== + + factor : int + The time resolution increment. + """ + self._start_times = { + k: factor * v for k, v in self._start_times.items() + } + for op_id, op_start_time in self._start_times.items(): + self._sfg.find_by_id(op_id)._increase_time_resolution(factor) + self._schedule_time *= factor def decrease_time_resolution(self, factor: int) -> "Schedule": raise NotImplementedError @@ -198,12 +204,8 @@ class Schedule: ), "No operation with the specified op_id in this schedule." (backward_slack, forward_slack) = self.slacks(op_id) - if time < 0: - if -time > backward_slack: - raise ValueError - else: - if time > forward_slack: - raise ValueError + if not -backward_slack <= time <= forward_slack: + raise ValueError tmp_start = self._start_times[op_id] + time new_start = tmp_start % self._schedule_time diff --git a/test/test_schedule.py b/test/test_schedule.py index 5f7963b1..7c47603e 100644 --- a/test/test_schedule.py +++ b/test/test_schedule.py @@ -21,6 +21,7 @@ class TestInit: "cmul1": 0, "out1": 0, } + assert schedule.schedule_time == 9 def test_complicated_single_outputs_normal_latency( self, precedence_sfg_delays @@ -55,6 +56,7 @@ class TestInit: "ADD4": 17, "OUT1": 21, } + assert schedule.schedule_time == 21 def test_complicated_single_outputs_complex_latencies( self, precedence_sfg_delays @@ -118,6 +120,8 @@ class TestInit: "OUT1": 17, } + assert schedule.schedule_time == 17 + def test_independent_sfg( self, sfg_two_inputs_two_outputs_independent_with_cmul ): @@ -146,6 +150,7 @@ class TestInit: "OUT1": 9, "OUT2": 10, } + assert schedule.schedule_time == 10 class TestSlacks: @@ -289,3 +294,74 @@ class TestRescheduling: schedule.move_operation( precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 10 ) + + +class TestTimeResolution: + def test_increase_time_resolution( + self, sfg_two_inputs_two_outputs_independent_with_cmul + ): + schedule = Schedule( + sfg_two_inputs_two_outputs_independent_with_cmul, + scheduling_alg="ASAP", + ) + old_schedule_time = schedule.schedule_time + + schedule.increase_time_resolution(2) + + start_times_names = {} + for op_id, start_time in schedule._start_times.items(): + op_name = ( + sfg_two_inputs_two_outputs_independent_with_cmul.find_by_id( + op_id + ).name + ) + start_times_names[op_name] = start_time + + assert start_times_names == { + "C1": 0, + "IN1": 0, + "IN2": 0, + "CMUL1": 0, + "CMUL2": 10, + "ADD1": 0, + "CMUL3": 14, + "OUT1": 18, + "OUT2": 20, + } + + assert 2 * old_schedule_time == schedule.schedule_time + + def test_increase_time_resolution_twice( + self, sfg_two_inputs_two_outputs_independent_with_cmul + ): + schedule = Schedule( + sfg_two_inputs_two_outputs_independent_with_cmul, + scheduling_alg="ASAP", + ) + old_schedule_time = schedule.schedule_time + + schedule.increase_time_resolution(2) + schedule.increase_time_resolution(3) + + start_times_names = {} + for op_id, start_time in schedule._start_times.items(): + op_name = ( + sfg_two_inputs_two_outputs_independent_with_cmul.find_by_id( + op_id + ).name + ) + start_times_names[op_name] = start_time + + assert start_times_names == { + "C1": 0, + "IN1": 0, + "IN2": 0, + "CMUL1": 0, + "CMUL2": 30, + "ADD1": 0, + "CMUL3": 42, + "OUT1": 54, + "OUT2": 60, + } + + assert 6 * old_schedule_time == schedule.schedule_time -- GitLab