Newer
Older
Angus Lothian
committed
"""
B-ASIC test suite for the schedule module and Schedule class.
Angus Lothian
committed
"""
Angus Lothian
committed
from b_asic.core_operations import Addition, Butterfly, ConstantMultiplication
from b_asic.process import OperatorProcess
from b_asic.schedule import Schedule
Simon Bjurek
committed
from b_asic.scheduler import ALAPScheduler, ASAPScheduler
from b_asic.sfg_generators import direct_form_1_iir, direct_form_fir
from b_asic.signal_flow_graph import SFG
from b_asic.special_operations import Delay, Input, Output
Angus Lothian
committed
class TestInit:
def test_simple_filter_normal_latency(self, sfg_simple_filter):
sfg_simple_filter.set_latency_of_type(Addition.type_name(), 5)
sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 4)
Angus Lothian
committed
schedule = Schedule(sfg_simple_filter, scheduler=ASAPScheduler())
Angus Lothian
committed
"in0": 0,
"add0": 4,
"cmul0": 0,
"out0": 0,
assert schedule.schedule_time == 9
Angus Lothian
committed
with pytest.raises(
ValueError, match="No operation with graph_id 'foo' in schedule"
):
schedule.start_time_of_operation("foo")
def test_complicated_single_outputs_normal_latency(self, precedence_sfg_delays):
Angus Lothian
committed
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
Angus Lothian
committed
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
Angus Lothian
committed
for op_id, start_time in schedule._start_times.items():
Angus Lothian
committed
op_name = precedence_sfg_delays.find_by_id(op_id).name
start_times_names[op_name] = start_time
assert start_times_names == {
"IN1": 0,
"C0": 0,
"B1": 0,
"B2": 0,
"ADD2": 3,
"ADD1": 7,
"Q1": 11,
"A0": 14,
"A1": 0,
"A2": 0,
"ADD3": 3,
"ADD4": 17,
"OUT1": 21,
}
assert schedule.schedule_time == 21
def test_complicated_single_outputs_normal_latency_alap(
self, precedence_sfg_delays
):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ALAPScheduler())
start_times_names = {}
op_name = precedence_sfg_delays.find_by_id(op_id).name
start_times_names[op_name] = schedule.start_time_of_operation(op_id)
assert start_times_names == {
"IN1": 4,
"C0": 4,
"B1": 0,
"B2": 0,
"ADD2": 3,
"ADD1": 7,
"Q1": 11,
"A0": 14,
"A1": 10,
"A2": 10,
"ADD3": 13,
"ADD4": 17,
"OUT1": 21,
}
assert schedule.schedule_time == 21
def test_complicated_single_outputs_normal_latency_alap_with_schedule_time(
self, precedence_sfg_delays
):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(
precedence_sfg_delays, schedule_time=25, scheduler=ALAPScheduler()
)
start_times_names = {}
for op_id in schedule.start_times:
op_name = precedence_sfg_delays.find_by_id(op_id).name
start_times_names[op_name] = schedule.start_time_of_operation(op_id)
assert start_times_names == {
"IN1": 8 - 4,
"C0": 8 - 4,
"B1": 4 - 4,
"B2": 4 - 4,
"ADD2": 7 - 4,
"ADD1": 11 - 4,
"Q1": 15 - 4,
"A0": 18 - 4,
"A1": 14 - 4,
"A2": 14 - 4,
"ADD3": 17 - 4,
"ADD4": 21 - 4,
"OUT1": 25 - 4,
def test_complicated_single_outputs_normal_latency_alap_too_short_schedule_time(
self, precedence_sfg_delays
):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
with pytest.raises(ValueError, match="Too short schedule time. Minimum is 21."):
Schedule(precedence_sfg_delays, schedule_time=19, scheduler=ALAPScheduler())
def test_complicated_single_outputs_normal_latency_from_fixture(
self, secondorder_iir_schedule
):
start_times_names = {
secondorder_iir_schedule.sfg.find_by_id(op_id).name: start_time
for op_id, start_time in secondorder_iir_schedule._start_times.items()
}
assert start_times_names == {
"IN1": 0,
"C0": 0,
"B1": 0,
"B2": 0,
"ADD2": 3,
"ADD1": 7,
"Q1": 11,
"A0": 14,
"A1": 0,
"A2": 0,
"ADD3": 3,
"ADD4": 17,
"OUT1": 21,
}
assert secondorder_iir_schedule.schedule_time == 21
def test_complicated_single_outputs_complex_latencies(self, precedence_sfg_delays):
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
precedence_sfg_delays.set_latency_offsets_of_type(
ConstantMultiplication.type_name(), {"in0": 3, "out0": 5}
)
precedence_sfg_delays.find_by_name("B1")[0].set_latency_offsets(
{"in0": 4, "out0": 7}
)
precedence_sfg_delays.find_by_name("B2")[0].set_latency_offsets(
{"in0": 1, "out0": 4}
)
precedence_sfg_delays.find_by_name("ADD2")[0].set_latency_offsets(
{"in0": 4, "in1": 2, "out0": 4}
)
precedence_sfg_delays.find_by_name("ADD1")[0].set_latency_offsets(
{"in0": 1, "in1": 2, "out0": 4}
)
precedence_sfg_delays.find_by_name("Q1")[0].set_latency_offsets(
{"in0": 3, "out0": 6}
)
precedence_sfg_delays.find_by_name("A0")[0].set_latency_offsets(
{"in0": 0, "out0": 2}
)
precedence_sfg_delays.find_by_name("A1")[0].set_latency_offsets(
{"in0": 0, "out0": 5}
)
precedence_sfg_delays.find_by_name("A2")[0].set_latency_offsets(
{"in0": 2, "out0": 3}
)
precedence_sfg_delays.find_by_name("ADD3")[0].set_latency_offsets(
{"in0": 2, "in1": 1, "out0": 4}
)
precedence_sfg_delays.find_by_name("ADD4")[0].set_latency_offsets(
{"in0": 6, "in1": 7, "out0": 9}
)
Angus Lothian
committed
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
Angus Lothian
committed
for op_id, start_time in schedule._start_times.items():
Angus Lothian
committed
op_name = precedence_sfg_delays.find_by_id(op_id).name
start_times_names[op_name] = start_time
assert start_times_names == {
"IN1": 0,
"C0": 0,
"B1": 0,
"B2": 0,
"ADD2": 3,
"ADD1": 5,
"Q1": 6,
"A0": 12,
"A1": 0,
"A2": 0,
"ADD3": 3,
"ADD4": 8,
"OUT1": 17,
}
assert schedule.schedule_time == 17
def test_independent_sfg(self, sfg_two_inputs_two_outputs_independent_with_cmul):
schedule = Schedule(
sfg_two_inputs_two_outputs_independent_with_cmul,
Angus Lothian
committed
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
Angus Lothian
committed
start_times_names[op_name] = start_time
assert start_times_names == {
"C1": 0,
"IN1": 0,
"IN2": 0,
"CMUL1": 0,
"CMUL2": 5,
"ADD1": 0,
"CMUL3": 7,
"OUT1": 9,
"OUT2": 10,
}
assert schedule.schedule_time == 10
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
def test_provided_schedule(self):
sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3])
sfg.set_latency_of_type(Addition.type_name(), 1)
sfg.set_latency_of_type(ConstantMultiplication.type_name(), 3)
sfg.set_execution_time_of_type(Addition.type_name(), 1)
sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1)
start_times = {
"in0": 1,
"cmul0": 1,
"cmul1": 0,
"cmul2": 0,
"cmul3": 0,
"cmul4": 0,
"add3": 3,
"add1": 3,
"add0": 4,
"add2": 5,
"out0": 6,
}
laps = {
's8': 1,
's10': 2,
's15': 1,
's17': 2,
's0': 0,
's3': 0,
's12': 0,
's11': 0,
's14': 0,
's13': 0,
's6': 0,
's4': 0,
's5': 0,
's2': 0,
}
schedule = Schedule(sfg, start_times=start_times, laps=laps)
assert schedule.start_times == start_times
assert schedule.laps == laps
assert schedule.schedule_time == 6
def test_forward_backward_slack_normal_latency(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
assert (
schedule.forward_slack(
precedence_sfg_delays.find_by_name("ADD3")[0].graph_id
)
== 7
)
assert (
schedule.backward_slack(
precedence_sfg_delays.find_by_name("ADD3")[0].graph_id
)
== 0
)
assert (
schedule.forward_slack(precedence_sfg_delays.find_by_name("A2")[0].graph_id)
== 0
)
assert (
schedule.backward_slack(
precedence_sfg_delays.find_by_name("A2")[0].graph_id
)
== 16
)
def test_slacks_normal_latency(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
assert schedule.slacks(
precedence_sfg_delays.find_by_name("ADD3")[0].graph_id
) == (0, 7)
assert schedule.slacks(
precedence_sfg_delays.find_by_name("A2")[0].graph_id
) == (16, 0)
def test_print_slacks(self, capsys, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
schedule.print_slacks()
captured = capsys.readouterr()
assert captured.out == (
"Graph ID | Backward | Forward\n"
"---------|----------|---------\n"
"add0 | 0 | 0\n"
"add1 | 0 | 0\n"
"add2 | 0 | 0\n"
"add3 | 0 | 7\n"
"cmul0 | 0 | 1\n"
"cmul1 | 0 | 0\n"
"cmul2 | 0 | 0\n"
"cmul3 | 4 | 0\n"
"cmul4 | 16 | 0\n"
"cmul5 | 16 | 0\n"
"cmul6 | 4 | 0\n"
"in0 | oo | 0\n"
"out0 | 0 | oo\n"
assert captured.err == ""
def test_print_slacks_sorting(self, capsys, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
schedule.print_slacks(1)
captured = capsys.readouterr()
assert captured.out == (
"Graph ID | Backward | Forward\n"
"---------|----------|---------\n"
"cmul0 | 0 | 1\n"
"add0 | 0 | 0\n"
"add1 | 0 | 0\n"
"cmul1 | 0 | 0\n"
"cmul2 | 0 | 0\n"
"add3 | 0 | 7\n"
"add2 | 0 | 0\n"
"out0 | 0 | oo\n"
"cmul3 | 4 | 0\n"
"cmul6 | 4 | 0\n"
"cmul4 | 16 | 0\n"
"cmul5 | 16 | 0\n"
"in0 | oo | 0\n"
assert captured.err == ""
def test_slacks_errors(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
with pytest.raises(
ValueError, match="No operation with graph_id 'foo' in schedule"
):
schedule.forward_slack("foo")
with pytest.raises(
ValueError, match="No operation with graph_id 'foo' in schedule"
):
schedule.backward_slack("foo")
with pytest.raises(
ValueError, match="No operation with graph_id 'foo' in schedule"
):
schedule.slacks("foo")
class TestRescheduling:
def test_move_operation(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
schedule.move_operation(
precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 4
)
schedule.move_operation(precedence_sfg_delays.find_by_name("A2")[0].graph_id, 2)
for op_id, start_time in schedule._start_times.items():
op_name = precedence_sfg_delays.find_by_id(op_id).name
start_times_names[op_name] = start_time
assert start_times_names == {
"IN1": 0,
"C0": 0,
"B1": 0,
"B2": 0,
"ADD2": 3,
"ADD1": 7,
"Q1": 11,
"A0": 14,
"A1": 0,
"A2": 2,
"ADD3": 7,
"ADD4": 17,
"OUT1": 21,
}
with pytest.raises(
ValueError, match="No operation with graph_id 'foo' in schedule"
):
schedule.move_operation("foo", 0)
def test_move_operation_slack_after_rescheduling(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
add3_id = precedence_sfg_delays.find_by_name("ADD3")[0].graph_id
schedule.move_operation(add3_id, 4)
assert schedule.forward_slack(add3_id) == 3
assert schedule.backward_slack(add3_id) == 4
a2_id = precedence_sfg_delays.find_by_name("A2")[0].graph_id
assert schedule.forward_slack(a2_id) == 4
assert schedule.backward_slack(a2_id) == 16
assert schedule.forward_slack(add3_id) == 3
assert schedule.backward_slack(add3_id) == 2
assert schedule.forward_slack(a2_id) == 2
assert schedule.backward_slack(a2_id) == 18
def test_move_operation_incorrect_move_backward(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
match="Operation 'add3' got incorrect move: -4. Must be between 0 and 7.",
schedule.move_operation(
precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, -4
)
def test_move_operation_incorrect_move_forward(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
match="Operation 'add3' got incorrect move: 10. Must be between 0 and 7.",
schedule.move_operation(
precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 10
)
def test_move_operation_asap(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
assert schedule.backward_slack('cmul5') == 16
assert schedule.forward_slack('cmul5') == 0
schedule.move_operation_asap('cmul5')
assert schedule.start_time_of_operation('in0') == 0
assert schedule.laps['cmul5'] == 0
assert schedule.backward_slack('cmul5') == 0
assert schedule.forward_slack('cmul5') == 16
def test_move_input_asap_does_not_mess_up_laps(self, precedence_sfg_delays):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
old_laps = schedule.laps['in0']
schedule.move_operation_asap('in0')
assert schedule.start_time_of_operation('in0') == 0
assert schedule.laps['in0'] == old_laps
def test_move_operation_acc(self):
in0 = Input()
d = Delay()
a = d + in0
out0 = Output(a)
sfg = SFG([in0], [out0])
sfg.set_latency_of_type(Addition.type_name(), 1)
schedule = Schedule(sfg, scheduler=ASAPScheduler(), cyclic=True)
assert schedule.laps[sfg.find_by_id("add0").input(0).signals[0].graph_id] == 1
assert schedule.laps[sfg.find_by_id("add0").input(1).signals[0].graph_id] == 0
assert schedule._start_times["add0"] == 0
assert schedule.laps[sfg.find_by_id("out0").input(0).signals[0].graph_id] == 0
assert schedule._start_times["out0"] == 1
schedule.move_operation("out0", 0)
assert schedule.laps[sfg.find_by_id("out0").input(0).signals[0].graph_id] == 0
assert schedule.laps[sfg.find_by_id("add0").input(0).signals[0].graph_id] == 1
assert schedule.laps[sfg.find_by_id("add0").input(1).signals[0].graph_id] == 0
assert schedule._start_times["out0"] == 1
assert schedule._start_times["add0"] == 0
# Increase schedule time
schedule.set_schedule_time(2)
assert schedule.laps[sfg.find_by_id("out0").input(0).signals[0].graph_id] == 0
assert schedule.laps[sfg.find_by_id("add0").input(0).signals[0].graph_id] == 1
assert schedule.laps[sfg.find_by_id("add0").input(1).signals[0].graph_id] == 0
assert schedule._start_times["out0"] == 1
assert schedule._start_times["add0"] == 0
schedule.move_operation("out0", 1)
assert schedule.laps[sfg.find_by_id("out0").input(0).signals[0].graph_id] == 0
assert schedule.laps[sfg.find_by_id("add0").input(0).signals[0].graph_id] == 1
assert schedule.laps[sfg.find_by_id("add0").input(1).signals[0].graph_id] == 0
assert schedule._start_times["out0"] == 2
assert schedule._start_times["add0"] == 0
schedule.move_operation("add0", 1)
assert schedule.laps[sfg.find_by_id("add0").input(0).signals[0].graph_id] == 1
assert schedule.laps[sfg.find_by_id("add0").input(1).signals[0].graph_id] == 0
assert schedule.laps[sfg.find_by_id("out0").input(0).signals[0].graph_id] == 0
assert schedule._start_times["add0"] == 1
assert schedule._start_times["out0"] == 2
schedule.move_operation("add0", -1)
assert schedule.laps[sfg.find_by_id("add0").input(0).signals[0].graph_id] == 1
assert schedule.laps[sfg.find_by_id("add0").input(1).signals[0].graph_id] == 0
assert schedule.laps[sfg.find_by_id("out0").input(0).signals[0].graph_id] == 0
assert schedule._start_times["add0"] == 0
assert schedule._start_times["out0"] == 2
def test_reintroduce_delays(
self, precedence_sfg_delays, sfg_direct_form_iir_lp_filter
):
precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1)
precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3)
sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 1)
sfg_direct_form_iir_lp_filter.set_latency_of_type(
ConstantMultiplication.type_name(), 3
)
schedule = Schedule(precedence_sfg_delays, scheduler=ASAPScheduler())
sfg = schedule.sfg
assert precedence_sfg_delays.evaluate(5) == sfg.evaluate(5)
schedule = Schedule(sfg_direct_form_iir_lp_filter, scheduler=ASAPScheduler())
sfg = schedule.sfg
assert sfg_direct_form_iir_lp_filter.evaluate(5) == sfg.evaluate(5)
Hugo Winbladh
committed
fir_sfg = direct_form_fir(
list(range(1, 10)),
mult_properties={'latency': 2, 'execution_time': 1},
add_properties={'latency': 2, 'execution_time': 1},
)
schedule = Schedule(fir_sfg, scheduler=ASAPScheduler())
Hugo Winbladh
committed
sfg = schedule.sfg
assert fir_sfg.evaluate(5) == sfg.evaluate(5)
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,
)
old_schedule_time = schedule.schedule_time
assert schedule.get_possible_time_resolution_decrements() == [1]
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
assert schedule.get_possible_time_resolution_decrements() == [1, 2]
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,
)
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 = sfg_two_inputs_two_outputs_independent_with_cmul.find_by_id(op_id)
start_times_names[op.name] = (start_time, op.latency, op.execution_time)
assert start_times_names == {
"CMUL1": (0, 30, 18),
"CMUL2": (30, 24, 6),
"ADD1": (0, 42, 12),
"CMUL3": (42, 18, 6),
}
assert 6 * old_schedule_time == schedule.schedule_time
assert schedule.get_possible_time_resolution_decrements() == [
1,
2,
3,
6,
]
def test_increase_decrease_time_resolution(
self, sfg_two_inputs_two_outputs_independent_with_cmul
):
schedule = Schedule(
sfg_two_inputs_two_outputs_independent_with_cmul,
)
old_schedule_time = schedule.schedule_time
assert schedule.get_possible_time_resolution_decrements() == [1]
schedule.increase_time_resolution(6)
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,
}
with pytest.raises(ValueError, match="Not possible to decrease resolution"):
schedule.decrease_time_resolution(4)
schedule.decrease_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": 10,
"ADD1": 0,
"CMUL3": 14,
"OUT1": 18,
"OUT2": 20,
}
assert 2 * old_schedule_time == schedule.schedule_time
assert schedule.get_possible_time_resolution_decrements() == [1, 2]
class TestProcesses:
def test__get_memory_variables_list(self, secondorder_iir_schedule):
mvl = secondorder_iir_schedule._get_memory_variables_list()
assert len(mvl) == 12
pc = secondorder_iir_schedule.get_memory_variables()
assert len(pc) == 12
def test_get_operations(self, secondorder_iir_schedule_with_execution_times):
pc = secondorder_iir_schedule_with_execution_times.get_operations()
assert len(pc) == 13
assert all(isinstance(operand, OperatorProcess) for operand in pc.collection)
@matplotlib.testing.decorators.image_comparison(
['test__get_figure_no_execution_times.png'], remove_text=True
)
def test__get_figure_no_execution_times(self, secondorder_iir_schedule):
return secondorder_iir_schedule._get_figure()
class TestErrors:
def test_no_latency(self, sfg_simple_filter):
with pytest.raises(
ValueError,
match="Input port 0 of operation add0 has no latency-offset.",
Schedule(sfg_simple_filter, scheduler=ASAPScheduler())
def test_no_output_latency(self):
in1 = Input()
in2 = Input()
bfly = Butterfly(in1, in2, latency_offsets={"in0": 4, "in1": 2, "out0": 10})
out1 = Output(bfly.output(0))
out2 = Output(bfly.output(1))
sfg = SFG([in1, in2], [out1, out2])
with pytest.raises(
ValueError,
match="Output port 1 of operation bfly0 has no latency-offset.",
Schedule(sfg, scheduler=ASAPScheduler())
bfly1 = Butterfly(in1, in2, latency_offsets={"in0": 4, "in1": 2, "out1": 10})
bfly2 = Butterfly(
bfly1.output(0),
bfly1.output(1),
latency_offsets={"in0": 4, "in1": 2, "out0": 10, "out1": 8},
)
out1 = Output(bfly2.output(0))
out2 = Output(bfly2.output(1))
sfg = SFG([in1, in2], [out1, out2])
with pytest.raises(
ValueError,
match="Output port 0 of operation bfly0 has no latency-offset.",
Schedule(sfg, scheduler=ASAPScheduler())
def test_too_short_schedule_time(self, sfg_simple_filter):
sfg_simple_filter.set_latency_of_type(Addition.type_name(), 5)
sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 4)
with pytest.raises(ValueError, match="Too short schedule time. Minimum is 9."):
Schedule(sfg_simple_filter, scheduler=ASAPScheduler(), schedule_time=3)
schedule = Schedule(sfg_simple_filter, scheduler=ASAPScheduler())
with pytest.raises(
ValueError,
match=re.escape("New schedule time (3) too short, minimum: 9."),
):
schedule.set_schedule_time(3)
# def test_incorrect_scheduling_algorithm(self, sfg_simple_filter):
# sfg_simple_filter.set_latency_of_type(Addition.type_name(), 1)
# sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 2)
# with pytest.raises(
# NotImplementedError, match="No algorithm with name: foo defined."
# ):
# Schedule(sfg_simple_filter, algorithm="foo")
def test_no_sfg(self):
with pytest.raises(TypeError, match="An SFG must be provided"):
Schedule(1)
def test_provided_no_start_times(self, sfg_simple_filter):
sfg_simple_filter.set_latency_of_type(Addition.type_name(), 1)
sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 2)
with pytest.raises(
ValueError, match="Must provide start_times when using 'provided'"
):
def test_provided_no_laps(self, sfg_simple_filter):
sfg_simple_filter.set_latency_of_type(Addition.type_name(), 1)
sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 2)
with pytest.raises(ValueError, match="Must provide laps when using 'provided'"):
Schedule(sfg_simple_filter, start_times={'in0': 0})
class TestGetUsedTypeNames:
def test_secondorder_iir_schedule(self, secondorder_iir_schedule):
assert secondorder_iir_schedule.get_used_type_names() == [
'add',
'cmul',
'in',
'out',
]
class TestYLocations:
def test_provided_no_laps(self, sfg_simple_filter):
sfg_simple_filter.set_latency_of_type(Addition.type_name(), 1)
sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 2)
schedule = Schedule(sfg_simple_filter, ASAPScheduler())
assert schedule._y_locations == {"in0": 0, "cmul0": 1, "add0": 2, "out0": 3}
schedule.move_y_location("add0", 1, insert=True)
assert schedule._y_locations == {"in0": 0, "cmul0": 2, "add0": 1, "out0": 3}
schedule.move_y_location("out0", 1)
assert schedule._y_locations == {"in0": 0, "cmul0": 2, "add0": 1, "out0": 1}
def test_reset(self, sfg_simple_filter):
sfg_simple_filter.set_latency_of_type(Addition.type_name(), 1)
sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 2)
schedule = Schedule(sfg_simple_filter, ASAPScheduler())
assert schedule._y_locations == {"in0": 0, "cmul0": 1, "add0": 2, "out0": 3}
schedule.reset_y_locations()
assert schedule._y_locations["in0"] is None
assert schedule._y_locations["cmul0"] is None
assert schedule._y_locations["add0"] is None
assert schedule._y_locations["add0"] is None
assert schedule._y_locations["out0"] is None
assert schedule._y_locations["foo"] is None