import pytest from b_asic.core_operations import ( MADS, Addition, Butterfly, ConstantMultiplication, Reciprocal, ) from b_asic.core_schedulers import ( ALAPScheduler, ASAPScheduler, EarliestDeadlineScheduler, HybridScheduler, LeastSlackTimeScheduler, MaxFanOutScheduler, ) from b_asic.schedule import Schedule from b_asic.sfg_generators import ( direct_form_1_iir, ldlt_matrix_inverse, radix_2_dif_fft, ) class TestASAPScheduler: def test_empty_sfg(self, sfg_empty): with pytest.raises( ValueError, match="Empty signal flow graph cannot be scheduled." ): Schedule(sfg_empty, scheduler=ASAPScheduler()) def test_direct_form_1_iir(self): sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3]) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 3) sfg.set_execution_time_of_type(Addition.type_name(), 1) schedule = Schedule(sfg, scheduler=ASAPScheduler()) assert schedule.start_times == { "in0": 0, "cmul0": 0, "cmul1": 0, "cmul2": 0, "cmul3": 0, "cmul4": 0, "add3": 2, "add1": 2, "add0": 5, "add2": 8, "out0": 11, } assert schedule.schedule_time == 11 def test_direct_form_2_iir(self, sfg_direct_form_iir_lp_filter): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) schedule = Schedule(sfg_direct_form_iir_lp_filter, scheduler=ASAPScheduler()) assert schedule.start_times == { "in0": 0, "cmul1": 0, "cmul4": 0, "cmul2": 0, "cmul3": 0, "add3": 4, "add1": 4, "add0": 9, "cmul0": 14, "add2": 18, "out0": 23, } assert schedule.schedule_time == 23 def test_direct_form_2_iir_with_scheduling_time( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=ASAPScheduler(), schedule_time=30 ) assert schedule.start_times == { "in0": 0, "cmul1": 0, "cmul4": 0, "cmul2": 0, "cmul3": 0, "add3": 4, "add1": 4, "add0": 9, "cmul0": 14, "add2": 18, "out0": 23, } assert schedule.schedule_time == 30 def test_radix_2_fft_8_points(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) schedule = Schedule(sfg, scheduler=ASAPScheduler()) assert schedule.start_times == { "in0": 0, "in1": 0, "in2": 0, "in3": 0, "in4": 0, "in5": 0, "in6": 0, "in7": 0, "bfly0": 0, "bfly6": 0, "bfly8": 0, "bfly11": 0, "cmul3": 1, "bfly7": 1, "cmul2": 1, "bfly1": 1, "cmul0": 1, "cmul4": 2, "bfly9": 2, "bfly5": 3, "bfly2": 3, "out0": 3, "out4": 3, "bfly10": 4, "cmul1": 4, "bfly3": 4, "out1": 5, "out2": 5, "out5": 5, "out6": 5, "bfly4": 6, "out3": 7, "out7": 7, } assert schedule.schedule_time == 7 class TestALAPScheduler: def test_empty_sfg(self, sfg_empty): with pytest.raises( ValueError, match="Empty signal flow graph cannot be scheduled." ): Schedule(sfg_empty, scheduler=ALAPScheduler()) def test_direct_form_1_iir(self): sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3]) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 3) sfg.set_execution_time_of_type(Addition.type_name(), 1) schedule = Schedule(sfg, scheduler=ALAPScheduler()) assert schedule.start_times == { "cmul3": 0, "cmul4": 0, "add1": 2, "in0": 3, "cmul0": 3, "cmul1": 3, "cmul2": 3, "add3": 5, "add0": 5, "add2": 8, "out0": 11, } assert schedule.schedule_time == 11 def test_direct_form_2_iir(self, sfg_direct_form_iir_lp_filter): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) schedule = Schedule(sfg_direct_form_iir_lp_filter, scheduler=ALAPScheduler()) assert schedule.start_times == { "cmul3": 0, "cmul4": 0, "add1": 4, "in0": 9, "cmul2": 9, "cmul1": 9, "add0": 9, "add3": 13, "cmul0": 14, "add2": 18, "out0": 23, } assert schedule.schedule_time == 23 def test_direct_form_2_iir_with_scheduling_time( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=ALAPScheduler(), schedule_time=30 ) assert schedule.start_times == { "cmul3": 7, "cmul4": 7, "add1": 11, "in0": 16, "cmul2": 16, "cmul1": 16, "add0": 16, "add3": 20, "cmul0": 21, "add2": 25, "out0": 30, } assert schedule.schedule_time == 30 def test_radix_2_fft_8_points(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) schedule = Schedule(sfg, scheduler=ALAPScheduler()) assert schedule.start_times == { "in3": 0, "in7": 0, "in1": 0, "in5": 0, "bfly6": 0, "bfly8": 0, "cmul2": 1, "cmul3": 1, "in2": 2, "in6": 2, "bfly11": 2, "bfly7": 3, "cmul0": 3, "bfly5": 3, "in0": 4, "in4": 4, "cmul4": 4, "cmul1": 4, "bfly0": 4, "bfly1": 5, "bfly2": 5, "bfly9": 6, "bfly10": 6, "bfly3": 6, "bfly4": 6, "out0": 7, "out1": 7, "out2": 7, "out3": 7, "out4": 7, "out5": 7, "out6": 7, "out7": 7, } assert schedule.schedule_time == 7 class TestEarliestDeadlineScheduler: def test_empty_sfg(self, sfg_empty): with pytest.raises( ValueError, match="Empty signal flow graph cannot be scheduled." ): Schedule(sfg_empty, scheduler=EarliestDeadlineScheduler()) def test_direct_form_1_iir(self): sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3]) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 3) sfg.set_execution_time_of_type(Addition.type_name(), 1) resources = {Addition.type_name(): 1, ConstantMultiplication.type_name(): 1} schedule = Schedule( sfg, scheduler=EarliestDeadlineScheduler(max_resources=resources) ) assert schedule.start_times == { "cmul4": 0, "cmul3": 1, "in0": 2, "cmul0": 2, "add1": 3, "cmul1": 3, "cmul2": 4, "add3": 6, "add0": 7, "add2": 10, "out0": 13, } assert schedule.schedule_time == 13 def test_direct_form_2_iir_inf_resources_no_exec_time( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=EarliestDeadlineScheduler() ) # should be the same as for ASAP due to infinite resources, except for input assert schedule.start_times == { "in0": 9, "cmul1": 0, "cmul4": 0, "cmul2": 0, "cmul3": 0, "add3": 4, "add1": 4, "add0": 9, "cmul0": 14, "add2": 18, "out0": 23, } assert schedule.schedule_time == 23 def test_direct_form_2_iir_1_add_1_mul_no_exec_time( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) max_resources = {ConstantMultiplication.type_name(): 1, Addition.type_name(): 1} schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=EarliestDeadlineScheduler(max_resources), ) assert schedule.start_times == { "cmul4": 0, "cmul3": 4, "cmul1": 8, "add1": 8, "cmul2": 12, "in0": 13, "add0": 13, "add3": 18, "cmul0": 18, "add2": 23, "out0": 28, } assert schedule.schedule_time == 28 def test_direct_form_2_iir_1_add_1_mul_exec_time_1( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 3 ) sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 2) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( ConstantMultiplication.type_name(), 1 ) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( Addition.type_name(), 1 ) max_resources = {ConstantMultiplication.type_name(): 1, Addition.type_name(): 1} schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=EarliestDeadlineScheduler(max_resources), ) assert schedule.start_times == { "cmul4": 0, "cmul3": 1, "cmul1": 2, "cmul2": 3, "add1": 4, "in0": 6, "add0": 6, "add3": 7, "cmul0": 8, "add2": 11, "out0": 13, } assert schedule.schedule_time == 13 def test_direct_form_2_iir_2_add_3_mul_exec_time_1( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 3 ) sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 2) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( ConstantMultiplication.type_name(), 1 ) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( Addition.type_name(), 1 ) max_resources = {ConstantMultiplication.type_name(): 3, Addition.type_name(): 2} schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=EarliestDeadlineScheduler(max_resources), ) assert schedule.start_times == { "cmul1": 0, "cmul4": 0, "cmul3": 0, "cmul2": 1, "add1": 3, "add3": 4, "in0": 5, "add0": 5, "cmul0": 7, "add2": 10, "out0": 12, } assert schedule.schedule_time == 12 def test_radix_2_fft_8_points(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) resources = {Butterfly.type_name(): 2, ConstantMultiplication.type_name(): 2} schedule = Schedule( sfg, scheduler=EarliestDeadlineScheduler(max_resources=resources) ) assert schedule.start_times == { "in1": 0, "in3": 0, "in5": 0, "in7": 0, "bfly6": 0, "bfly8": 0, "in2": 1, "in6": 1, "cmul2": 1, "cmul3": 1, "bfly11": 1, "bfly7": 1, "in0": 2, "in4": 2, "cmul0": 2, "bfly0": 2, "cmul4": 2, "bfly5": 3, "bfly1": 3, "cmul1": 4, "bfly2": 4, "bfly9": 4, "bfly10": 5, "bfly3": 5, "out0": 5, "out4": 5, "bfly4": 6, "out1": 6, "out2": 6, "out5": 6, "out6": 6, "out7": 7, "out3": 7, } assert schedule.schedule_time == 7 class TestLeastSlackTimeScheduler: def test_empty_sfg(self, sfg_empty): with pytest.raises( ValueError, match="Empty signal flow graph cannot be scheduled." ): Schedule(sfg_empty, scheduler=LeastSlackTimeScheduler()) def test_direct_form_1_iir(self): sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3]) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 3) sfg.set_execution_time_of_type(Addition.type_name(), 1) resources = {Addition.type_name(): 1, ConstantMultiplication.type_name(): 1} schedule = Schedule( sfg, scheduler=LeastSlackTimeScheduler(max_resources=resources) ) assert schedule.start_times == { "cmul4": 0, "cmul3": 1, "in0": 2, "cmul0": 2, "add1": 3, "cmul1": 3, "cmul2": 4, "add3": 6, "add0": 7, "add2": 10, "out0": 13, } assert schedule.schedule_time == 13 def test_direct_form_2_iir_inf_resources_no_exec_time( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=LeastSlackTimeScheduler() ) # should be the same as for ASAP due to infinite resources, except for input assert schedule.start_times == { "in0": 9, "cmul1": 0, "cmul4": 0, "cmul2": 0, "cmul3": 0, "add3": 4, "add1": 4, "add0": 9, "cmul0": 14, "add2": 18, "out0": 23, } assert schedule.schedule_time == 23 def test_direct_form_2_iir_1_add_1_mul_no_exec_time( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 5) sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 4 ) max_resources = {ConstantMultiplication.type_name(): 1, Addition.type_name(): 1} schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=LeastSlackTimeScheduler(max_resources), ) assert schedule.start_times == { "cmul4": 0, "cmul3": 4, "cmul1": 8, "add1": 8, "cmul2": 12, "in0": 13, "add0": 13, "add3": 18, "cmul0": 18, "add2": 23, "out0": 28, } assert schedule.schedule_time == 28 def test_direct_form_2_iir_1_add_1_mul_exec_time_1( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 3 ) sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 2) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( ConstantMultiplication.type_name(), 1 ) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( Addition.type_name(), 1 ) max_resources = {ConstantMultiplication.type_name(): 1, Addition.type_name(): 1} schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=LeastSlackTimeScheduler(max_resources), ) assert schedule.start_times == { "cmul4": 0, "cmul3": 1, "cmul1": 2, "cmul2": 3, "add1": 4, "in0": 6, "add0": 6, "add3": 7, "cmul0": 8, "add2": 11, "out0": 13, } assert schedule.schedule_time == 13 def test_direct_form_2_iir_2_add_3_mul_exec_time_1( self, sfg_direct_form_iir_lp_filter ): sfg_direct_form_iir_lp_filter.set_latency_of_type( ConstantMultiplication.type_name(), 3 ) sfg_direct_form_iir_lp_filter.set_latency_of_type(Addition.type_name(), 2) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( ConstantMultiplication.type_name(), 1 ) sfg_direct_form_iir_lp_filter.set_execution_time_of_type( Addition.type_name(), 1 ) max_resources = {ConstantMultiplication.type_name(): 3, Addition.type_name(): 2} schedule = Schedule( sfg_direct_form_iir_lp_filter, scheduler=LeastSlackTimeScheduler(max_resources), ) assert schedule.start_times == { "cmul1": 0, "cmul4": 0, "cmul3": 0, "cmul2": 1, "add1": 3, "add3": 4, "in0": 5, "add0": 5, "cmul0": 7, "add2": 10, "out0": 12, } assert schedule.schedule_time == 12 def test_radix_2_fft_8_points(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) resources = {Butterfly.type_name(): 2, ConstantMultiplication.type_name(): 2} schedule = Schedule( sfg, scheduler=LeastSlackTimeScheduler(max_resources=resources) ) assert schedule.start_times == { "in1": 0, "in3": 0, "in5": 0, "in7": 0, "bfly6": 0, "bfly8": 0, "in2": 1, "in6": 1, "cmul2": 1, "cmul3": 1, "bfly11": 1, "bfly7": 1, "in0": 2, "in4": 2, "cmul0": 2, "bfly0": 2, "cmul4": 2, "bfly5": 3, "bfly1": 3, "cmul1": 4, "bfly2": 4, "bfly9": 4, "bfly10": 5, "bfly3": 5, "out0": 5, "out4": 5, "bfly4": 6, "out1": 6, "out2": 6, "out5": 6, "out6": 6, "out7": 7, "out3": 7, } assert schedule.schedule_time == 7 class TestMaxFanOutScheduler: def test_empty_sfg(self, sfg_empty): with pytest.raises( ValueError, match="Empty signal flow graph cannot be scheduled." ): Schedule(sfg_empty, scheduler=MaxFanOutScheduler()) def test_direct_form_1_iir(self): sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3]) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 3) sfg.set_execution_time_of_type(Addition.type_name(), 1) resources = {Addition.type_name(): 1, ConstantMultiplication.type_name(): 1} schedule = Schedule(sfg, scheduler=MaxFanOutScheduler(max_resources=resources)) assert schedule.start_times == { "in0": 0, "cmul0": 0, "cmul1": 1, "cmul2": 2, "cmul4": 3, "cmul3": 4, "add3": 4, "add1": 6, "add0": 9, "add2": 12, "out0": 15, } assert schedule.schedule_time == 15 class TestHybridScheduler: def test_empty_sfg(self, sfg_empty): with pytest.raises( ValueError, match="Empty signal flow graph cannot be scheduled." ): Schedule(sfg_empty, scheduler=HybridScheduler()) def test_direct_form_1_iir(self): sfg = direct_form_1_iir([1, 2, 3], [1, 2, 3]) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 3) sfg.set_execution_time_of_type(Addition.type_name(), 1) resources = {Addition.type_name(): 1, ConstantMultiplication.type_name(): 1} schedule = Schedule(sfg, scheduler=HybridScheduler(max_resources=resources)) assert schedule.start_times == { "cmul4": 0, "cmul3": 1, "in0": 2, "cmul0": 2, "add1": 3, "cmul1": 3, "cmul2": 4, "add3": 6, "add0": 7, "add2": 10, "out0": 13, } assert schedule.schedule_time == 13 def test_radix_2_fft_8_points(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_latency_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) resources = {Butterfly.type_name(): 2, ConstantMultiplication.type_name(): 2} schedule = Schedule(sfg, scheduler=HybridScheduler(max_resources=resources)) assert schedule.start_times == { "in1": 0, "in3": 0, "in5": 0, "in7": 0, "bfly6": 0, "bfly8": 0, "in2": 1, "in6": 1, "cmul2": 1, "cmul3": 1, "bfly11": 1, "bfly7": 1, "in0": 2, "in4": 2, "cmul0": 2, "bfly0": 2, "cmul4": 2, "bfly5": 3, "bfly1": 3, "cmul1": 4, "bfly2": 4, "bfly9": 4, "bfly10": 5, "bfly3": 5, "out0": 5, "out4": 5, "bfly4": 6, "out1": 6, "out2": 6, "out5": 6, "out6": 6, "out7": 7, "out3": 7, } assert schedule.schedule_time == 7 def test_radix_2_fft_8_points_specified_IO_times_cyclic(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(Butterfly.type_name(), 3) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) resources = {Butterfly.type_name(): 1, ConstantMultiplication.type_name(): 1} input_times = { "in0": 0, "in1": 1, "in2": 2, "in3": 3, "in4": 4, "in5": 5, "in6": 6, "in7": 7, } output_times = { "out0": -2, "out1": -1, "out2": 0, "out3": 1, "out4": 2, "out5": 3, "out6": 4, "out7": 5, } schedule = Schedule( sfg, scheduler=HybridScheduler(resources, input_times, output_times), cyclic=True, ) assert schedule.start_times == { "in0": 0, "in1": 1, "in2": 2, "in3": 3, "in4": 4, "in5": 5, "in6": 6, "in7": 7, "bfly0": 4, "bfly8": 5, "bfly11": 6, "bfly6": 7, "cmul2": 8, "cmul0": 9, "bfly1": 9, "cmul3": 10, "bfly7": 10, "bfly2": 11, "bfly5": 12, "cmul4": 13, "bfly9": 13, "bfly10": 15, "cmul1": 15, "bfly3": 16, "bfly4": 17, "out0": 18, "out1": 19, "out2": 20, "out3": 1, "out4": 2, "out5": 3, "out6": 4, "out7": 5, } assert schedule.schedule_time == 20 def test_radix_2_fft_8_points_specified_IO_times_non_cyclic(self): sfg = radix_2_dif_fft(points=8) sfg.set_latency_of_type(Butterfly.type_name(), 3) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_execution_time_of_type(Butterfly.type_name(), 1) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) resources = {Butterfly.type_name(): 1, ConstantMultiplication.type_name(): 1} input_times = { "in0": 0, "in1": 1, "in2": 2, "in3": 3, "in4": 4, "in5": 5, "in6": 6, "in7": 7, } output_times = { "out0": -2, "out1": -1, "out2": 0, "out3": 1, "out4": 2, "out5": 3, "out6": 4, "out7": 5, } schedule = Schedule( sfg, scheduler=HybridScheduler(resources, input_times, output_times), cyclic=False, ) assert schedule.start_times == { "in0": 0, "in1": 1, "in2": 2, "in3": 3, "in4": 4, "in5": 5, "in6": 6, "in7": 7, "bfly0": 4, "bfly8": 5, "bfly11": 6, "bfly6": 7, "cmul2": 8, "cmul0": 9, "bfly1": 9, "cmul3": 10, "bfly7": 10, "bfly2": 11, "bfly5": 12, "cmul4": 13, "bfly9": 13, "bfly10": 15, "cmul1": 15, "bfly3": 16, "bfly4": 17, "out0": 18, "out1": 19, "out2": 20, "out3": 21, "out4": 22, "out5": 23, "out6": 24, "out7": 25, } assert schedule.schedule_time == 25 def test_ldlt_inverse_2x2(self): sfg = ldlt_matrix_inverse(N=2) sfg.set_latency_of_type(MADS.type_name(), 3) sfg.set_latency_of_type(Reciprocal.type_name(), 2) sfg.set_execution_time_of_type(MADS.type_name(), 1) sfg.set_execution_time_of_type(Reciprocal.type_name(), 1) resources = {MADS.type_name(): 1, Reciprocal.type_name(): 1} schedule = Schedule( sfg, scheduler=HybridScheduler(resources), ) assert schedule.start_times == { "in0": 0, "rec0": 0, "in1": 2, "dontcare1": 2, "mads0": 2, "in2": 5, "mads3": 5, "rec1": 8, "dontcare0": 10, "mads2": 10, "mads1": 13, "out2": 10, "out1": 13, "out0": 16, } assert schedule.schedule_time == 16 def test_ldlt_inverse_2x2_specified_IO_times_cyclic(self): sfg = ldlt_matrix_inverse(N=2) sfg.set_latency_of_type(MADS.type_name(), 3) sfg.set_latency_of_type(Reciprocal.type_name(), 2) sfg.set_execution_time_of_type(MADS.type_name(), 1) sfg.set_execution_time_of_type(Reciprocal.type_name(), 1) resources = {MADS.type_name(): 1, Reciprocal.type_name(): 1} input_times = { "in0": 0, "in1": 1, "in2": 2, } output_times = { "out0": 0, "out1": 1, "out2": 2, } schedule = Schedule( sfg, scheduler=HybridScheduler(resources, input_times, output_times), cyclic=True, ) assert schedule.start_times == { "in0": 0, "in1": 1, "in2": 2, "rec0": 0, "dontcare1": 2, "mads0": 2, "mads3": 5, "rec1": 8, "dontcare0": 10, "mads2": 10, "mads1": 13, "out0": 16, "out1": 1, "out2": 2, } assert schedule.schedule_time == 16 def test_max_invalid_resources(self): sfg = ldlt_matrix_inverse(N=2) sfg.set_latency_of_type(MADS.type_name(), 3) sfg.set_latency_of_type(Reciprocal.type_name(), 2) sfg.set_execution_time_of_type(MADS.type_name(), 1) sfg.set_execution_time_of_type(Reciprocal.type_name(), 1) resources = 2 with pytest.raises(ValueError, match="max_resources must be a dictionary."): Schedule(sfg, scheduler=HybridScheduler(resources)) resources = "test" with pytest.raises(ValueError, match="max_resources must be a dictionary."): Schedule(sfg, scheduler=HybridScheduler(resources)) resources = [] with pytest.raises(ValueError, match="max_resources must be a dictionary."): Schedule(sfg, scheduler=HybridScheduler(resources)) resources = {1: 1} with pytest.raises( ValueError, match="max_resources key must be a valid type_name." ): Schedule(sfg, scheduler=HybridScheduler(resources)) resources = {MADS.type_name(): "test"} with pytest.raises(ValueError, match="max_resources value must be an integer."): Schedule(sfg, scheduler=HybridScheduler(resources))