Skip to content
Snippets Groups Projects
Commit 8c5f98cc authored by angloth's avatar angloth
Browse files

Add temporary working printing of Schema without correct forwards and backwards slack

parent df381f3e
No related branches found
No related tags found
No related merge requests found
Pipeline #16052 passed
......@@ -3,7 +3,9 @@ This module contains the Schema class.
TODO: More info
"""
from typing import Dict, List
from io import StringIO
from typing import Dict, List, Set
import math
from b_asic.signal_flow_graph import SFG
from b_asic.graph_component import GraphID
......@@ -19,6 +21,10 @@ class Schema:
_schedule_time: int
_cyclic: bool
_resolution: int
_max_end_op_id: GraphID
_max_end_time: int
_input_laps: Dict[GraphID, List[int]]
_non_schedulable_ops: Set[GraphID]
def __init__(self, sfg: SFG, schedule_time: int = None, cyclic: bool = False, resolution: int = 1, scheduling_alg: str = "ASAP"):
......@@ -31,44 +37,116 @@ class Schema:
if scheduling_alg == "ASAP":
self._schedule_asap()
else:
raise NotImplementedError(f"No algorithm with name: {scheduling_alg} defined.")
raise ValueError(f"No algorithm with name: {scheduling_alg} defined.")
max_end_time = 0
# Set latest time of the schema.
self._latest_op_time = 0
for op_id, op_start_time in self._start_times.items():
op = self._sfg.find_by_id(op_id)
for outport in op.outputs:
max_end_time = max(max_end_time, op_start_time + outport.latency_offset)
if op_start_time + outport.latency_offset > self._latest_op_time:
self._max_end_op_id = op_id
self._max_end_time = op_start_time + outport.latency_offset
if not self._cyclic:
if schedule_time is None:
self._schedule_time = max_end_time
elif schedule_time < max_end_time:
raise ValueError("Too short schedule time for non-cyclic Schedule entered.")
self.set_schedule_time(self._max_end_time)
else:
self.set_schedule_time(schedule_time)
else:
raise NotImplementedError("Cyclic schedules not implemented yet.")
def __str__(self):
string_io = StringIO()
for op in self._sfg.get_operations_topological_order():
if op.graph_id in self._start_times:
string_io.write("name: " + op.name + ", \tid: " + op.graph_id + ", \t")
string_io.write("start_time: " + str(self._start_times[op.graph_id]) + ", \t")
string_io.write("backwards_slack: " + str(self.backwards_slack(op.graph_id)) + ", \t")
string_io.write("forwards_slack: " + str(self.forwards_slack(op.graph_id)) + "\n")
return string_io.getvalue()
@property
def schedule_time(self) -> int:
"""Get the schedule time of the Schema."""
return self._schedule_time
def set_schedule_time(self, schedule_time: int) -> None:
"""Set the schedule time to the specified value, if the specified value is shorter then
what is required by the schedule then raises a ValueError."""
if not self._cyclic:
if schedule_time >= self._max_end_time:
self._schedule_time = schedule_time
else:
raise ValueError("Specified schedule time is shorter then the max length of the ")
else:
raise NotImplementedError("Cyclic schedules not implemented yet.")
def start_time_of_operation(self, op_id: GraphID):
def get_start_time_of_operation(self, op_id: GraphID) -> int:
"""Get the start time of the operation with the specified by the op_id."""
assert op_id in self._start_times, "No operation with the specified op_id in this schema."
return self._start_times[op_id]
def forward_slack(self, op_id):
raise NotImplementedError
def get_laps_of_operation_input_port(self, op_id: GraphID, input_index: int) -> int:
"""Get the laps of input port with the entered index of the operation with the specified op_id."""
assert op_id in self._laps, "No operation with the specidied op_id in this schema."
assert input_index >= 0 and input_index < len(
self._laps[op_id]), "Input index for the specified operation out of bounds."
return self._laps[op_id][input_index]
def change_start_time_of_operation(self, op_id: GraphID, relative_change: int = None, new_start_time: int = None) -> None:
"""Changes the start time of the operation with the specified op_id either by the
relative_change if specified or to the new_start_time if that is specified. If both
are specified then the new_start_time value is used.
A negative relative_change represents decreasing the operations start time.
If the change to the start time would break dependencies then the change is cancelled
and a message is printed to the user in the terminal.
"""
assert op_id in self._start_times, "No operation with the specified op_id in this schema."
if new_start_time is not None:
relative_change = new_start_time - self._start_times[op_id]
if relative_change is not None:
if relative_change > 0:
forwards_slack = self.forwards_slack(op_id)
if relative_change > forwards_slack:
print(f"The specified relative change of {relative_change} is larger than the forwards \
slack of the operation of {forwards_slack}.")
return
else:
backwards_slack = self.backwards_slack(op_id)
if abs(relative_change) > backwards_slack:
print(f"The specified relative change of {abs(relative_change)} is larger than the forwards \
slack of the operation of {forwards_slack}.")
return
self._start_times[op_id] += relative_change
else:
raise ValueError("At least one of the parameters relative_change or new_start_time has to be specified.")
def backwards_slack(self, op_id: GraphID) -> int:
return 0
op_start_time = self.get_start_time_of_operation(op_id)
min_backwards_slack = math.inf
for i, inp in enumerate(self._sfg.find_by_id(op_id).inputs):
inp_time = op_start_time + inp.latency_offset
def backward_slack(self, op_id):
raise NotImplementedError
source_op_time = self.get_start_time_of_operation(inp.connected_source.operation.graph_id)
source_outp_time = source_op_time + inp.connected_source.latency_offset
def print_slacks(self):
raise NotImplementedError
def forwards_slack(self, op_id: GraphID) -> int:
return 0
assert op_id in self._start_times, "No operation with specified op_id in this schema."
def _schedule_asap(self):
def _schedule_asap(self) -> None:
pl = self._sfg.get_precedence_list()
if len(pl) < 2:
print("Empty signal flow graph cannot be scheduled.")
return
non_schedulable_ops = set((outp.operation.graph_id for outp in pl[0]))
self._non_schedulable_ops = set((outp.operation.graph_id for outp in pl[0]))
for outport in pl[1]:
op = outport.operation
......@@ -83,13 +161,12 @@ class Schema:
# Schedule the operation if it doesn't have a start time yet.
op_start_time = 0
for inport in op.inputs:
print(inport.operation.graph_id)
assert len(inport.signals) == 1, "Error in scheduling, dangling input port detected."
assert inport.signals[0].source is not None, "Error in scheduling, signal with no source detected."
source_port = inport.signals[0].source
source_end_time = None
if source_port.operation.graph_id in non_schedulable_ops:
if source_port.operation.graph_id in self._non_schedulable_ops:
source_end_time = 0
else:
source_op_time = self._start_times[source_port.operation.graph_id]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment