From 84899e7f9e78fc82d0e71b16d70162271630e591 Mon Sep 17 00:00:00 2001 From: Hugo Winbladh <hugwi268@student.liu.se> Date: Mon, 19 Jun 2023 10:14:35 +0000 Subject: [PATCH] Change GraphID numbering to be zero-based --- b_asic/signal_flow_graph.py | 2 +- examples/firstorderiirfilter.py | 104 ++++++------ examples/fivepointwinograddft.py | 86 +++++----- examples/folding_example_with_architecture.py | 16 +- .../secondorderdirectformiir_architecture.py | 22 +-- examples/threepointwinograddft.py | 62 +++---- examples/twotapfirsfg.py | 44 ++--- .../test__get_figure_no_execution_times.png | Bin 26502 -> 25949 bytes .../test_draw_matrix_transposer_4.png | Bin 27461 -> 27461 bytes .../baseline/test_draw_process_collection.png | Bin 15002 -> 15002 bytes .../test_left_edge_cell_assignment.png | Bin 23058 -> 23058 bytes test/fixtures/schedule.py | 18 +- test/test_architecture.py | 28 ++-- test/test_graph_id_generator.py | 8 +- test/test_process.py | 4 +- test/test_schedule.py | 156 +++++++++--------- test/test_sfg.py | 98 +++++------ test/test_simulation.py | 66 ++++---- 18 files changed, 357 insertions(+), 357 deletions(-) diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py index a9599e10..b4c55607 100644 --- a/b_asic/signal_flow_graph.py +++ b/b_asic/signal_flow_graph.py @@ -64,8 +64,8 @@ class GraphIDGenerator: def next_id(self, type_name: TypeName, used_ids: MutableSet = set()) -> GraphID: """Get the next graph id for a certain graph id type.""" - self._next_id_number[type_name] += 1 new_id = type_name + str(self._next_id_number[type_name]) + self._next_id_number[type_name] += 1 while new_id in used_ids: self._next_id_number[type_name] += 1 new_id = type_name + str(self._next_id_number[type_name]) diff --git a/examples/firstorderiirfilter.py b/examples/firstorderiirfilter.py index 4dea6dcf..3a2ed744 100644 --- a/examples/firstorderiirfilter.py +++ b/examples/firstorderiirfilter.py @@ -78,59 +78,59 @@ firstorderiir.print_precedence_graph() # # .. graphviz:: # -# digraph { -# rankdir=LR -# subgraph cluster_0 { -# label=N0 -# "in1.0" [label=in1 height=0.1 shape=rectangle width=0.1] -# "t1.0" [label=t1 height=0.1 shape=rectangle width=0.1] -# } -# subgraph cluster_1 { -# label=N1 -# "cmul2.0" [label=cmul2 height=0.1 shape=rectangle width=0.1] -# "cmul1.0" [label=cmul1 height=0.1 shape=rectangle width=0.1] -# } -# subgraph cluster_2 { -# label=N2 -# "add1.0" [label=add1 height=0.1 shape=rectangle width=0.1] -# } -# subgraph cluster_3 { -# label=N3 -# "add2.0" [label=add2 height=0.1 shape=rectangle width=0.1] -# } -# "in1.0" -> add1 -# add1 [label=add1 shape=ellipse] -# in1 -> "in1.0" -# in1 [label=in1 shape=cds] -# "t1.0" -> cmul2 -# cmul2 [label=cmul2 shape=ellipse] -# "t1.0" -> cmul1 -# cmul1 [label=cmul1 shape=ellipse] -# t1Out -> "t1.0" -# t1Out [label=t1 shape=square] -# "cmul2.0" -> add2 -# add2 [label=add2 shape=ellipse] -# cmul2 -> "cmul2.0" -# cmul2 [label=cmul2 shape=ellipse] -# "cmul1.0" -> add1 -# add1 [label=add1 shape=ellipse] -# cmul1 -> "cmul1.0" -# cmul1 [label=cmul1 shape=ellipse] -# "add1.0" -> t1In -# t1In [label=t1 shape=square] -# "add1.0" -> add2 -# add2 [label=add2 shape=ellipse] -# add1 -> "add1.0" -# add1 [label=add1 shape=ellipse] -# "add2.0" -> out1 -# out1 [label=out1 shape=cds] -# add2 -> "add2.0" -# add2 [label=add2 shape=ellipse] -# } -# +# digraph { +# rankdir=LR +# subgraph cluster_0 { +# label=N0 +# "in0.0" [label=in0 height=0.1 shape=rectangle width=0.1] +# "t0.0" [label=t0 height=0.1 shape=rectangle width=0.1] +# } +# subgraph cluster_1 { +# label=N1 +# "cmul1.0" [label=cmul1 height=0.1 shape=rectangle width=0.1] +# "cmul0.0" [label=cmul0 height=0.1 shape=rectangle width=0.1] +# } +# subgraph cluster_2 { +# label=N2 +# "add0.0" [label=add0 height=0.1 shape=rectangle width=0.1] +# } +# subgraph cluster_3 { +# label=N3 +# "add1.0" [label=add1 height=0.1 shape=rectangle width=0.1] +# } +# "in0.0" -> add0 +# add0 [label=add0 shape=ellipse] +# in0 -> "in0.0" +# in0 [label=in0 shape=cds] +# "t0.0" -> cmul1 +# cmul1 [label=cmul1 shape=ellipse] +# "t0.0" -> cmul0 +# cmul0 [label=cmul0 shape=ellipse] +# t0Out -> "t0.0" +# t0Out [label=t0 shape=square] +# "cmul1.0" -> add1 +# add1 [label=add1 shape=ellipse] +# cmul1 -> "cmul1.0" +# cmul1 [label=cmul1 shape=ellipse] +# "cmul0.0" -> add0 +# add0 [label=add0 shape=ellipse] +# cmul0 -> "cmul0.0" +# cmul0 [label=cmul0 shape=ellipse] +# "add0.0" -> t0In +# t0In [label=t0 shape=square] +# "add0.0" -> add1 +# add1 [label=add1 shape=ellipse] +# add0 -> "add0.0" +# add0 [label=add0 shape=ellipse] +# "add1.0" -> out0 +# out0 [label=out0 shape=cds] +# add1 -> "add1.0" +# add1 [label=add1 shape=ellipse] +# } +# # As seen, each operation has an id, in addition to the optional name. # This can be used to access the operation. For example, -firstorderiir.find_by_id('cmul1') +firstorderiir.find_by_id('cmul0') # %% # Note that this operation differs from ``a1`` defined above as the operations are @@ -170,7 +170,7 @@ sim.results import matplotlib.pyplot as plt # noqa: E402 plt.plot(sim.results['0'], label="Output") -plt.plot(sim.results['add1'], label="After first addition") +plt.plot(sim.results['add0'], label="After first addition") plt.legend() plt.show() diff --git a/examples/fivepointwinograddft.py b/examples/fivepointwinograddft.py index dea0cd55..0787445e 100644 --- a/examples/fivepointwinograddft.py +++ b/examples/fivepointwinograddft.py @@ -80,54 +80,54 @@ schedule.show() # Reschedule to only use one AddSub and one multiplier schedule.set_schedule_time(10) -schedule.move_operation('out5', 12) -schedule.move_operation('out4', 11) -schedule.move_operation('out3', 10) -schedule.move_operation('out2', 9) -schedule.move_operation('out1', 12) -schedule.move_operation('bfly4', 10) -schedule.move_operation('bfly3', 9) -schedule.move_operation('bfly2', 7) -schedule.move_operation('addsub5', 5) -schedule.move_operation('addsub3', 5) +schedule.move_operation('out4', 12) +schedule.move_operation('out3', 11) +schedule.move_operation('out2', 10) +schedule.move_operation('out1', 9) +schedule.move_operation('out0', 12) +schedule.move_operation('bfly3', 10) +schedule.move_operation('bfly2', 9) +schedule.move_operation('bfly1', 7) +schedule.move_operation('addsub4', 5) schedule.move_operation('addsub2', 5) -schedule.move_operation('cmul5', 4) -schedule.move_operation('cmul3', 4) -schedule.move_operation('cmul1', 5) -schedule.move_operation('addsub1', 6) -schedule.move_operation('cmul2', 6) -schedule.move_operation('addsub4', 4) -schedule.move_operation('bfly1', 4) -schedule.move_operation('cmul4', 6) -schedule.move_operation('bfly6', 4) +schedule.move_operation('addsub1', 5) +schedule.move_operation('cmul4', 4) +schedule.move_operation('cmul2', 4) +schedule.move_operation('cmul0', 5) +schedule.move_operation('addsub0', 6) +schedule.move_operation('cmul1', 6) +schedule.move_operation('addsub3', 4) +schedule.move_operation('bfly0', 4) +schedule.move_operation('cmul3', 6) schedule.move_operation('bfly5', 4) -schedule.move_operation('in2', 1) -schedule.move_operation('in3', 2) -schedule.move_operation('in4', 3) -schedule.move_operation('in5', 4) -schedule.move_operation('bfly6', -1) -schedule.move_operation('bfly4', 1) -schedule.move_operation('cmul3', 1) -schedule.move_operation('cmul5', 1) -schedule.move_operation('bfly1', 1) +schedule.move_operation('bfly4', 4) +schedule.move_operation('in1', 1) +schedule.move_operation('in2', 2) +schedule.move_operation('in3', 3) +schedule.move_operation('in4', 4) +schedule.move_operation('bfly5', -1) +schedule.move_operation('bfly3', 1) +schedule.move_operation('cmul2', 1) +schedule.move_operation('cmul4', 1) +schedule.move_operation('bfly0', 1) +schedule.move_operation('addsub0', -1) +schedule.move_operation('cmul1', -3) +schedule.move_operation('cmul3', -2) +schedule.move_operation('cmul4', -1) +schedule.move_operation('addsub4', 1) +schedule.move_operation('addsub1', 2) +schedule.move_operation('cmul0', 1) +schedule.move_operation('bfly0', -1) +schedule.move_operation('addsub0', -1) +schedule.move_operation('bfly2', -1) +schedule.move_operation('cmul2', -1) +schedule.move_operation('cmul4', 1) +schedule.move_operation('addsub2', -1) +schedule.move_operation('addsub4', -1) schedule.move_operation('addsub1', -1) -schedule.move_operation('cmul2', -3) -schedule.move_operation('cmul4', -2) -schedule.move_operation('cmul5', -1) -schedule.move_operation('addsub5', 1) -schedule.move_operation('addsub2', 2) -schedule.move_operation('cmul1', 1) schedule.move_operation('bfly1', -1) -schedule.move_operation('addsub1', -1) +schedule.move_operation('bfly2', -2) schedule.move_operation('bfly3', -1) -schedule.move_operation('cmul3', -1) -schedule.move_operation('cmul5', 1) -schedule.move_operation('addsub3', -1) -schedule.move_operation('addsub5', -1) -schedule.move_operation('addsub2', -1) -schedule.move_operation('bfly2', -1) -schedule.move_operation('bfly3', -2) -schedule.move_operation('bfly4', -1) schedule.show() # %% diff --git a/examples/folding_example_with_architecture.py b/examples/folding_example_with_architecture.py index 289b9d1c..9baf92e0 100644 --- a/examples/folding_example_with_architecture.py +++ b/examples/folding_example_with_architecture.py @@ -53,17 +53,17 @@ schedule.show(title='Original schedule') # %% # Reschedule to only require one adder and one multiplier -schedule.move_operation('out1', 2) -schedule.move_operation('add3', 2) -schedule.move_operation('cmul3', -3) -schedule.move_operation('add4', 3) +schedule.move_operation('out0', 2) +schedule.move_operation('add2', 2) schedule.move_operation('cmul2', -3) +schedule.move_operation('add3', 3) +schedule.move_operation('cmul1', -3) schedule.set_schedule_time(4) -schedule.move_operation('cmul2', 1) -schedule.move_operation('cmul1', 1) -schedule.move_operation('in1', 3) -schedule.move_operation('cmul3', -1) schedule.move_operation('cmul1', 1) +schedule.move_operation('cmul0', 1) +schedule.move_operation('in0', 3) +schedule.move_operation('cmul2', -1) +schedule.move_operation('cmul0', 1) schedule.show(title='Improved schedule') # %% diff --git a/examples/secondorderdirectformiir_architecture.py b/examples/secondorderdirectformiir_architecture.py index 72d23961..a60c760d 100644 --- a/examples/secondorderdirectformiir_architecture.py +++ b/examples/secondorderdirectformiir_architecture.py @@ -47,11 +47,11 @@ schedule.show(title='Original schedule') # %% # Reschedule to only require one adder and one multiplier. -schedule.move_operation('add4', 2) -schedule.move_operation('cmul5', -4) -schedule.move_operation('cmul4', -5) -schedule.move_operation('cmul6', -2) -schedule.move_operation('cmul3', 1) +schedule.move_operation('add3', 2) +schedule.move_operation('cmul4', -4) +schedule.move_operation('cmul3', -5) +schedule.move_operation('cmul5', -2) +schedule.move_operation('cmul2', 1) schedule.show(title='Improved schedule') # %% @@ -100,11 +100,11 @@ arch = Architecture( arch # %% -# To reduce the amount of interconnect, the ``cuml3.0`` variable can be moved from +# To reduce the amount of interconnect, the ``cuml2.0`` variable can be moved from # ``memory0`` to ``memory2``. In this way, ``memory0`` only gets variables from the # adder and an input multiplexer can be avoided. The memories must be assigned again as # the contents have changed. -arch.move_process('cmul3.0', 'memory0', 'memory2') +arch.move_process('cmul2.0', 'memory0', 'memory2') memories[0].assign() memories[2].assign() @@ -117,9 +117,9 @@ memories[2].show_content("New assigned memory2") arch # %% -# It is of course also possible to move ``add4.0`` to ``memory2`` to save one memory +# It is of course also possible to move ``add3.0`` to ``memory2`` to save one memory # cell. It is possible to pass ``assign=True`` to perform assignment after moving. -arch.move_process('add4.0', 'memory0', 'memory2', assign=True) +arch.move_process('add3.0', 'memory0', 'memory2', assign=True) memories[0].show_content("New assigned memory0") memories[2].show_content("New assigned memory2") @@ -129,9 +129,9 @@ memories[2].show_content("New assigned memory2") arch # %% -# Finally, by noting that ``cmul1.0`` is the only variable from ``memory1`` going to +# Finally, by noting that ``cmul0.0`` is the only variable from ``memory1`` going to # ``in0`` of ``adder``, another multiplexer can be reduced by: -arch.move_process('cmul1.0', 'memory1', 'memory2', assign=True) +arch.move_process('cmul0.0', 'memory1', 'memory2', assign=True) memories[1].show_content("New assigned memory1") memories[2].show_content("New assigned memory2") diff --git a/examples/threepointwinograddft.py b/examples/threepointwinograddft.py index ff5cfa5a..38338b08 100644 --- a/examples/threepointwinograddft.py +++ b/examples/threepointwinograddft.py @@ -59,40 +59,40 @@ schedule.show() # Reschedule to only use one AddSub and one multiplier schedule.set_schedule_time(10) -schedule.move_operation('out2', 3) -schedule.move_operation('out3', 4) -schedule.move_operation('addsub5', 2) -schedule.move_operation('addsub4', 3) -schedule.move_operation('addsub3', 2) -schedule.move_operation('cmul2', 2) -schedule.move_operation('cmul1', 2) -schedule.move_operation('out1', 5) -schedule.move_operation('addsub1', 3) -schedule.move_operation('addsub6', 2) +schedule.move_operation('out1', 3) +schedule.move_operation('out2', 4) +schedule.move_operation('addsub4', 2) +schedule.move_operation('addsub3', 3) schedule.move_operation('addsub2', 2) -schedule.move_operation('in2', 1) -schedule.move_operation('in3', 2) -schedule.move_operation('cmul2', 1) -schedule.move_operation('out3', 6) +schedule.move_operation('cmul1', 2) +schedule.move_operation('cmul0', 2) +schedule.move_operation('out0', 5) +schedule.move_operation('addsub0', 3) +schedule.move_operation('addsub5', 2) +schedule.move_operation('addsub1', 2) +schedule.move_operation('in1', 1) +schedule.move_operation('in2', 2) +schedule.move_operation('cmul1', 1) schedule.move_operation('out2', 6) schedule.move_operation('out1', 6) -schedule.move_operation('addsub6', 1) -schedule.move_operation('addsub4', 3) -schedule.move_operation('addsub5', 4) -schedule.move_operation('addsub4', 1) -schedule.move_operation('addsub5', 4) -schedule.move_operation('cmul2', 3) -schedule.move_operation('addsub4', 2) -schedule.move_operation('cmul2', 3) -schedule.move_operation('addsub3', 5) +schedule.move_operation('out0', 6) +schedule.move_operation('addsub5', 1) +schedule.move_operation('addsub3', 3) +schedule.move_operation('addsub4', 4) +schedule.move_operation('addsub3', 1) +schedule.move_operation('addsub4', 4) +schedule.move_operation('cmul1', 3) +schedule.move_operation('addsub3', 2) +schedule.move_operation('cmul1', 3) +schedule.move_operation('addsub2', 5) schedule.set_schedule_time(6) -schedule.move_operation('addsub1', 1) -schedule.move_operation('addsub4', -1) -schedule.move_operation('cmul2', -2) -schedule.move_operation('addsub4', -1) -schedule.move_operation('addsub1', -1) +schedule.move_operation('addsub0', 1) +schedule.move_operation('addsub3', -1) +schedule.move_operation('cmul1', -2) schedule.move_operation('addsub3', -1) -schedule.move_operation('addsub5', -4) +schedule.move_operation('addsub0', -1) +schedule.move_operation('addsub2', -1) +schedule.move_operation('addsub4', -4) schedule.show() # Extract memory variables and operation executions @@ -139,8 +139,8 @@ arch # %% # Move memory variables -arch.move_process('addsub2.0', memories[2], memories[1]) -arch.move_process('addsub4.0', memories[1], memories[2], assign=True) +arch.move_process('addsub1.0', memories[2], memories[1]) +arch.move_process('addsub3.0', memories[1], memories[2], assign=True) memories[1].assign() memories[1].show_content(title="Assigned memory1") diff --git a/examples/twotapfirsfg.py b/examples/twotapfirsfg.py index 87a90e1c..3d8b6b7e 100644 --- a/examples/twotapfirsfg.py +++ b/examples/twotapfirsfg.py @@ -14,40 +14,40 @@ from b_asic import ( ) # Inputs: -in1 = Input(name="in_1") +in0 = Input(name="in_0") # Outputs: -out1 = Output(name="out1") +out0 = Output(name="out0") # Operations: -t1 = Delay(initial_value=0, name="t1") -cmul1 = ConstantMultiplication( - value=0.5, name="cmul1", latency_offsets={'in0': None, 'out0': None} +t0 = Delay(initial_value=0, name="t0") +cmul0 = ConstantMultiplication( + value=0.5, name="cmul0", latency_offsets={'in0': None, 'out0': None} ) -add1 = Addition( - name="add1", latency_offsets={'in0': None, 'in1': None, 'out0': None} +add0 = Addition( + name="add0", latency_offsets={'in0': None, 'in1': None, 'out0': None} ) -cmul2 = ConstantMultiplication( - value=0.5, name="cmul2", latency_offsets={'in0': None, 'out0': None} +cmul1 = ConstantMultiplication( + value=0.5, name="cmul1", latency_offsets={'in0': None, 'out0': None} ) # Signals: -Signal(source=t1.output(0), destination=cmul1.input(0)) -Signal(source=in1.output(0), destination=t1.input(0)) -Signal(source=in1.output(0), destination=cmul2.input(0)) -Signal(source=cmul1.output(0), destination=add1.input(0)) -Signal(source=add1.output(0), destination=out1.input(0)) -Signal(source=cmul2.output(0), destination=add1.input(1)) -twotapfir = SFG(inputs=[in1], outputs=[out1], name='twotapfir') +Signal(source=t0.output(0), destination=cmul0.input(0)) +Signal(source=in0.output(0), destination=t0.input(0)) +Signal(source=in0.output(0), destination=cmul1.input(0)) +Signal(source=cmul0.output(0), destination=add0.input(0)) +Signal(source=add0.output(0), destination=out0.input(0)) +Signal(source=cmul1.output(0), destination=add0.input(1)) +twotapfir = SFG(inputs=[in0], outputs=[out0], name='twotapfir') # SFG Properties: prop = {'name': twotapfir} positions = { - 't1': (-209, 19), - 'cmul1': (-95, 76), - 'add1': (0, 95), - 'cmul2': (-209, 114), - 'out1': (76, 95), - 'in1': (-323, 19), + 't0': (-209, 19), + 'cmul0': (-95, 76), + 'add0': (0, 95), + 'cmul1': (-209, 114), + 'out0': (76, 95), + 'in0': (-323, 19), } diff --git a/test/baseline/test__get_figure_no_execution_times.png b/test/baseline/test__get_figure_no_execution_times.png index 684557d2a3b49951e2e3f8cb919724308035f1f7..bfe81db6ffd39001bbe01f50e4a13530bf38d16c 100644 GIT binary patch literal 25949 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 Rf`Ng7!PC{xWt~$(698e{_WJ+; literal 26502 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 HP6<r_`NL0e diff --git a/test/baseline/test_draw_matrix_transposer_4.png b/test/baseline/test_draw_matrix_transposer_4.png index c8ee191a8593d0420a55a3883a76ed86290e2256..7c2c59a58eefde33df86de184688f3cdbe3a8b93 100644 GIT binary patch delta 45 zcmX?ljq&I;#tCi;=6Z%Y3K=CO1;tkS`nicE1v&X8Ihjd%`9<max4AglH>Tas0sxGv B5sd%< delta 45 zcmX?ljq&I;#tCi;W_rdt3K=CO1;tkS`nicE1v&X8Ihjd%`9<ma=fCdzx-sp3766$+ B6OjM_ diff --git a/test/baseline/test_draw_process_collection.png b/test/baseline/test_draw_process_collection.png index 4b82425c023beadbf4b822c9c236852738ee2fce..538978b1a5702794e5fce020425b7b019c39ead3 100644 GIT binary patch delta 43 ycmbPLI;(Von}WHXp^idENl8JmmA-y%Vo5<xeo0Pdl3spMy8dl0j`oddCRPAg&<~gZ delta 43 zcmbPLI;(Von}V61v5rDUNl8JmmA-y%Vo5<xeo0Pdl3spMy8ijE`@U{WGqC~yWoHqb diff --git a/test/baseline/test_left_edge_cell_assignment.png b/test/baseline/test_left_edge_cell_assignment.png index 45420a64ac885227c686564337c2be329830e71e..45e5846b3da869fecc614a3009a42273dd1a9ae4 100644 GIT binary patch delta 45 zcmbQVg>ljr#tCi;=6Z%Y3K=CO1;tkS`nicE1v&X8Ihjd%`9<max4AglH>RzL1ORW8 B5T5`5 delta 45 zcmbQVg>ljr#tCi;W_rdt3K=CO1;tkS`nicE1v&X8Ihjd%`9<ma=fCdzx-o4{BmjIX B5~BbB diff --git a/test/fixtures/schedule.py b/test/fixtures/schedule.py index f6ec65bf..e11b95c9 100644 --- a/test/fixtures/schedule.py +++ b/test/fixtures/schedule.py @@ -38,14 +38,14 @@ def schedule_direct_form_iir_lp_filter(sfg_direct_form_iir_lp_filter: SFG): ConstantMultiplication.type_name(), 1 ) schedule = Schedule(sfg_direct_form_iir_lp_filter, algorithm="ASAP", cyclic=True) - schedule.move_operation('cmul4', -1) schedule.move_operation('cmul3', -1) - schedule.move_operation('cmul4', -10) - schedule.move_operation('cmul4', 1) - schedule.move_operation('cmul3', -8) - schedule.move_operation('add4', 1) - schedule.move_operation('add4', 1) - schedule.move_operation('cmul2', 1) - schedule.move_operation('cmul2', 1) - schedule.move_operation('cmul4', 2) + schedule.move_operation('cmul2', -1) + schedule.move_operation('cmul3', -10) + schedule.move_operation('cmul3', 1) + schedule.move_operation('cmul2', -8) + schedule.move_operation('add3', 1) + schedule.move_operation('add3', 1) + schedule.move_operation('cmul1', 1) + schedule.move_operation('cmul1', 1) + schedule.move_operation('cmul3', 2) return schedule diff --git a/test/test_architecture.py b/test/test_architecture.py index 3b0d9180..d2917d08 100644 --- a/test/test_architecture.py +++ b/test/test_architecture.py @@ -212,29 +212,29 @@ def test_move_process(schedule_direct_form_iir_lp_filter: Schedule): ) # Some movement that must work - assert memories[1].collection.from_name('cmul4.0') - architecture.move_process('cmul4.0', memories[1], memories[0]) - assert memories[0].collection.from_name('cmul4.0') + assert memories[1].collection.from_name('cmul3.0') + architecture.move_process('cmul3.0', memories[1], memories[0]) + assert memories[0].collection.from_name('cmul3.0') - assert memories[1].collection.from_name('in1.0') - architecture.move_process('in1.0', memories[1], memories[0]) - assert memories[0].collection.from_name('in1.0') + assert memories[1].collection.from_name('in0.0') + architecture.move_process('in0.0', memories[1], memories[0]) + assert memories[0].collection.from_name('in0.0') - assert processing_elements[1].collection.from_name('add1') - architecture.move_process('add1', processing_elements[1], processing_elements[0]) - assert processing_elements[0].collection.from_name('add1') + assert processing_elements[1].collection.from_name('add0') + architecture.move_process('add0', processing_elements[1], processing_elements[0]) + assert processing_elements[0].collection.from_name('add0') # Processes leave the resources they have moved from with pytest.raises(KeyError): - memories[1].collection.from_name('cmul4.0') + memories[1].collection.from_name('cmul3.0') with pytest.raises(KeyError): - memories[1].collection.from_name('in1.0') + memories[1].collection.from_name('in0.0') with pytest.raises(KeyError): - processing_elements[1].collection.from_name('add1') + processing_elements[1].collection.from_name('add0') # Processes can only be moved when the source and destination process-types match - with pytest.raises(TypeError, match="cmul4.0 not of type"): - architecture.move_process('cmul4.0', memories[0], processing_elements[0]) + with pytest.raises(TypeError, match="cmul3.0 not of type"): + architecture.move_process('cmul3.0', memories[0], processing_elements[0]) with pytest.raises(KeyError, match="invalid_name not in"): architecture.move_process('invalid_name', memories[0], processing_elements[1]) diff --git a/test/test_graph_id_generator.py b/test/test_graph_id_generator.py index 029fe6e7..5c57c10a 100644 --- a/test/test_graph_id_generator.py +++ b/test/test_graph_id_generator.py @@ -15,17 +15,17 @@ def graph_id_generator(): class TestGetNextId: def test_empty_string_generator(self, graph_id_generator): """Test the graph id generator for an empty string type.""" + assert graph_id_generator.next_id("") == "0" assert graph_id_generator.next_id("") == "1" - assert graph_id_generator.next_id("") == "2" def test_normal_string_generator(self, graph_id_generator): """ "Test the graph id generator for a normal string type.""" + assert graph_id_generator.next_id("add") == "add0" assert graph_id_generator.next_id("add") == "add1" - assert graph_id_generator.next_id("add") == "add2" def test_different_strings_generator(self, graph_id_generator): """Test the graph id generator for different strings.""" + assert graph_id_generator.next_id("sub") == "sub0" + assert graph_id_generator.next_id("mul") == "mul0" assert graph_id_generator.next_id("sub") == "sub1" assert graph_id_generator.next_id("mul") == "mul1" - assert graph_id_generator.next_id("sub") == "sub2" - assert graph_id_generator.next_id("mul") == "mul2" diff --git a/test/test_process.py b/test/test_process.py index 7ed15179..92a4eed1 100644 --- a/test/test_process.py +++ b/test/test_process.py @@ -28,9 +28,9 @@ def test_MemoryVariables(secondorder_iir_schedule): mem_vars = pc.collection pattern = re.compile( "MemoryVariable\\(3, <b_asic.port.OutputPort object at 0x[a-fA-F0-9]+>," - " {<b_asic.port.InputPort object at 0x[a-fA-F0-9]+>: 4}, 'cmul1.0'\\)" + " {<b_asic.port.InputPort object at 0x[a-fA-F0-9]+>: 4}, 'cmul0.0'\\)" ) - mem_var = [m for m in mem_vars if m.name == 'cmul1.0'][0] + mem_var = [m for m in mem_vars if m.name == 'cmul0.0'][0] assert pattern.match(repr(mem_var)) assert mem_var.execution_time == 4 assert mem_var.start_time == 3 diff --git a/test/test_schedule.py b/test/test_schedule.py index c7305ecb..088cd60b 100644 --- a/test/test_schedule.py +++ b/test/test_schedule.py @@ -20,10 +20,10 @@ class TestInit: schedule = Schedule(sfg_simple_filter) assert schedule._start_times == { - "in1": 0, - "add1": 4, - "cmul1": 0, - "out1": 0, + "in0": 0, + "add0": 4, + "cmul0": 0, + "out0": 0, } assert schedule.schedule_time == 9 @@ -293,19 +293,19 @@ class TestSlacks: captured = capsys.readouterr() assert captured.out == """Graph ID | Backward | Forward ---------|----------|--------- +add0 | 0 | 0 add1 | 0 | 0 add2 | 0 | 0 -add3 | 0 | 0 -add4 | 0 | 7 -cmul1 | 0 | 1 +add3 | 0 | 7 +cmul0 | 0 | 1 +cmul1 | 0 | 0 cmul2 | 0 | 0 -cmul3 | 0 | 0 -cmul4 | 4 | 0 +cmul3 | 4 | 0 +cmul4 | 16 | 0 cmul5 | 16 | 0 -cmul6 | 16 | 0 -cmul7 | 4 | 0 -in1 | oo | 0 -out1 | 0 | oo +cmul6 | 4 | 0 +in0 | oo | 0 +out0 | 0 | oo """ assert captured.err == "" @@ -318,19 +318,19 @@ out1 | 0 | oo captured = capsys.readouterr() assert captured.out == """Graph ID | Backward | Forward ---------|----------|--------- -cmul1 | 0 | 1 +cmul0 | 0 | 1 +add0 | 0 | 0 add1 | 0 | 0 -add2 | 0 | 0 +cmul1 | 0 | 0 cmul2 | 0 | 0 -cmul3 | 0 | 0 -add4 | 0 | 7 -add3 | 0 | 0 -out1 | 0 | oo -cmul4 | 4 | 0 -cmul7 | 4 | 0 +add3 | 0 | 7 +add2 | 0 | 0 +out0 | 0 | oo +cmul3 | 4 | 0 +cmul6 | 4 | 0 +cmul4 | 16 | 0 cmul5 | 16 | 0 -cmul6 | 16 | 0 -in1 | oo | 0 +in0 | oo | 0 """ assert captured.err == "" @@ -420,7 +420,7 @@ class TestRescheduling: schedule = Schedule(precedence_sfg_delays, algorithm="ASAP") with pytest.raises( ValueError, - match="Operation 'add4' got incorrect move: -4. Must be between 0 and 7.", + 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 @@ -433,7 +433,7 @@ class TestRescheduling: schedule = Schedule(precedence_sfg_delays, algorithm="ASAP") with pytest.raises( ValueError, - match="Operation 'add4' got incorrect move: 10. Must be between 0 and 7.", + 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 @@ -444,23 +444,23 @@ class TestRescheduling: precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) schedule = Schedule(precedence_sfg_delays, algorithm="ASAP") - assert schedule.backward_slack('cmul6') == 16 - assert schedule.forward_slack('cmul6') == 0 - schedule.move_operation_asap('cmul6') - assert schedule.start_time_of_operation('in1') == 0 - assert schedule.laps['cmul6'] == 0 - assert schedule.backward_slack('cmul6') == 0 - assert schedule.forward_slack('cmul6') == 16 + 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, algorithm="ASAP") - old_laps = schedule.laps['in1'] - schedule.move_operation_asap('in1') - assert schedule.start_time_of_operation('in1') == 0 - assert schedule.laps['in1'] == old_laps + 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() @@ -473,51 +473,51 @@ class TestRescheduling: schedule = Schedule(sfg, cyclic=True) # Check initial conditions - assert schedule.laps[sfg.find_by_id("add1").input(0).signals[0].graph_id] == 1 - assert schedule.laps[sfg.find_by_id("add1").input(1).signals[0].graph_id] == 0 - assert schedule._start_times["add1"] == 0 - assert schedule.laps[sfg.find_by_id("out1").input(0).signals[0].graph_id] == 0 - assert schedule._start_times["out1"] == 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._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 # Move and scheduling algorithm behaves differently - schedule.move_operation("out1", 0) - assert schedule.laps[sfg.find_by_id("out1").input(0).signals[0].graph_id] == 0 - assert schedule.laps[sfg.find_by_id("add1").input(0).signals[0].graph_id] == 1 - assert schedule.laps[sfg.find_by_id("add1").input(1).signals[0].graph_id] == 0 - assert schedule._start_times["out1"] == 1 - assert schedule._start_times["add1"] == 0 + 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("out1").input(0).signals[0].graph_id] == 0 - assert schedule.laps[sfg.find_by_id("add1").input(0).signals[0].graph_id] == 1 - assert schedule.laps[sfg.find_by_id("add1").input(1).signals[0].graph_id] == 0 - assert schedule._start_times["out1"] == 1 - assert schedule._start_times["add1"] == 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 # Move out one time unit - schedule.move_operation("out1", 1) - assert schedule.laps[sfg.find_by_id("out1").input(0).signals[0].graph_id] == 0 - assert schedule.laps[sfg.find_by_id("add1").input(0).signals[0].graph_id] == 1 - assert schedule.laps[sfg.find_by_id("add1").input(1).signals[0].graph_id] == 0 - assert schedule._start_times["out1"] == 2 - assert schedule._start_times["add1"] == 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 # Move add one time unit - schedule.move_operation("add1", 1) - assert schedule.laps[sfg.find_by_id("add1").input(0).signals[0].graph_id] == 1 - assert schedule.laps[sfg.find_by_id("add1").input(1).signals[0].graph_id] == 0 - assert schedule.laps[sfg.find_by_id("out1").input(0).signals[0].graph_id] == 0 - assert schedule._start_times["add1"] == 1 - assert schedule._start_times["out1"] == 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"] == 1 + assert schedule._start_times["out0"] == 2 # Move add back one time unit - schedule.move_operation("add1", -1) - assert schedule.laps[sfg.find_by_id("add1").input(0).signals[0].graph_id] == 1 - assert schedule.laps[sfg.find_by_id("add1").input(1).signals[0].graph_id] == 0 - assert schedule.laps[sfg.find_by_id("out1").input(0).signals[0].graph_id] == 0 - assert schedule._start_times["add1"] == 0 - assert schedule._start_times["out1"] == 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 class TestTimeResolution: @@ -673,7 +673,7 @@ class TestErrors: def test_no_latency(self, sfg_simple_filter): with pytest.raises( ValueError, - match="Input port 0 of operation add1 has no latency-offset.", + match="Input port 0 of operation add0 has no latency-offset.", ): Schedule(sfg_simple_filter) @@ -686,7 +686,7 @@ class TestErrors: sfg = SFG([in1, in2], [out1, out2]) with pytest.raises( ValueError, - match="Output port 1 of operation bfly1 has no latency-offset.", + match="Output port 1 of operation bfly0 has no latency-offset.", ): Schedule(sfg) in1 = Input() @@ -702,7 +702,7 @@ class TestErrors: sfg = SFG([in1, in2], [out1, out2]) with pytest.raises( ValueError, - match="Output port 0 of operation bfly1 has no latency-offset.", + match="Output port 0 of operation bfly0 has no latency-offset.", ): Schedule(sfg) @@ -764,8 +764,8 @@ class TestYLocations: # Assign locations schedule.show() print(schedule._y_locations) - assert schedule._y_locations == {'in1': 0, 'cmul1': 1, 'add1': 2, 'out1': 3} - schedule.move_y_location('add1', 1, insert=True) - assert schedule._y_locations == {'in1': 0, 'cmul1': 2, 'add1': 1, 'out1': 3} - schedule.move_y_location('out1', 1) - assert schedule._y_locations == {'in1': 0, 'cmul1': 2, 'add1': 1, 'out1': 1} + 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} diff --git a/test/test_sfg.py b/test/test_sfg.py index 2258081c..df775bc8 100644 --- a/test/test_sfg.py +++ b/test/test_sfg.py @@ -303,7 +303,7 @@ class TestComponents: class TestReplaceOperation: def test_replace_addition_by_id(self, operation_tree): sfg = SFG(outputs=[Output(operation_tree)]) - component_id = "add1" + component_id = "add0" sfg = sfg.replace_operation(Multiplication(name="Multi"), graph_id=component_id) assert component_id not in sfg._components_by_id.keys() @@ -311,7 +311,7 @@ class TestReplaceOperation: def test_replace_addition_large_tree(self, large_operation_tree): sfg = SFG(outputs=[Output(large_operation_tree)]) - component_id = "add3" + component_id = "add2" sfg = sfg.replace_operation(Multiplication(name="Multi"), graph_id=component_id) assert "Multi" in sfg._components_by_name.keys() @@ -319,7 +319,7 @@ class TestReplaceOperation: def test_replace_no_input_component(self, operation_tree): sfg = SFG(outputs=[Output(operation_tree)]) - component_id = "c1" + component_id = "c0" const_ = sfg.find_by_id(component_id) sfg = sfg.replace_operation(Constant(1), graph_id=component_id) @@ -327,7 +327,7 @@ class TestReplaceOperation: def test_no_match_on_replace(self, large_operation_tree): sfg = SFG(outputs=[Output(large_operation_tree)]) - component_id = "addd1" + component_id = "addd0" with pytest.raises( ValueError, match="No operation matching the criteria found" @@ -338,7 +338,7 @@ class TestReplaceOperation: def test_not_equal_input(self, large_operation_tree): sfg = SFG(outputs=[Output(large_operation_tree)]) - component_id = "c1" + component_id = "c0" with pytest.raises( TypeError, @@ -374,13 +374,13 @@ class TestInsertComponent: assert sfg.find_by_name("constant4")[0].output(0).signals[ 0 - ].destination.operation is sfg.find_by_id("add3") + ].destination.operation is sfg.find_by_id("add2") assert _sfg.find_by_name("constant4")[0].output(0).signals[ 0 - ].destination.operation is not _sfg.find_by_id("add3") - assert _sfg.find_by_id("sqrt1").output(0).signals[ + ].destination.operation is not _sfg.find_by_id("add2") + assert _sfg.find_by_id("sqrt0").output(0).signals[ 0 - ].destination.operation is _sfg.find_by_id("add3") + ].destination.operation is _sfg.find_by_id("add2") def test_insert_invalid_component_in_sfg(self, large_operation_tree): sfg = SFG(outputs=[Output(large_operation_tree)]) @@ -388,7 +388,7 @@ class TestInsertComponent: # Should raise an exception for not matching input count to output count. add4 = Addition() with pytest.raises(TypeError, match="Source operation output count"): - sfg.insert_operation(add4, "c1") + sfg.insert_operation(add4, "c0") def test_insert_at_output(self, large_operation_tree): sfg = SFG(outputs=[Output(large_operation_tree)]) @@ -396,11 +396,11 @@ class TestInsertComponent: # Should raise an exception for trying to insert an operation after an output. sqrt = SquareRoot() with pytest.raises(TypeError, match="Source operation cannot be an"): - _ = sfg.insert_operation(sqrt, "out1") + _ = sfg.insert_operation(sqrt, "out0") def test_insert_multiple_output_ports(self, butterfly_operation_tree): sfg = SFG(outputs=list(map(Output, butterfly_operation_tree.outputs))) - _sfg = sfg.insert_operation(Butterfly(name="n_bfly"), "bfly3") + _sfg = sfg.insert_operation(Butterfly(name="n_bfly"), "bfly2") assert sfg.evaluate() != _sfg.evaluate() @@ -987,7 +987,7 @@ class TestTopologicalOrderOperations: class TestRemove: def test_remove_single_input_outputs(self, sfg_simple_filter): - new_sfg = sfg_simple_filter.remove_operation("cmul1") + new_sfg = sfg_simple_filter.remove_operation("cmul0") assert { op.name @@ -1181,19 +1181,19 @@ class TestGetComponentsOfType: class TestPrecedenceGraph: def test_precedence_graph(self, sfg_simple_filter): res = ( - 'digraph {\n\trankdir=LR\n\tsubgraph cluster_0 {\n\t\tlabel=N0\n\t\t"in1.0"' - ' [label=in1 height=0.1 shape=rectangle width=0.1]\n\t\t"t1.0" [label=t1' + 'digraph {\n\trankdir=LR\n\tsubgraph cluster_0 {\n\t\tlabel=N0\n\t\t"in0.0"' + ' [label=in0 height=0.1 shape=rectangle width=0.1]\n\t\t"t0.0" [label=t0' ' height=0.1 shape=rectangle width=0.1]\n\t}\n\tsubgraph cluster_1' - ' {\n\t\tlabel=N1\n\t\t"cmul1.0" [label=cmul1 height=0.1 shape=rectangle' - ' width=0.1]\n\t}\n\tsubgraph cluster_2 {\n\t\tlabel=N2\n\t\t"add1.0"' - ' [label=add1 height=0.1 shape=rectangle width=0.1]\n\t}\n\t"in1.0" ->' - ' add1\n\tadd1 [label=add1 shape=ellipse]\n\tin1 -> "in1.0"\n\tin1' - ' [label=in1 shape=cds]\n\t"t1.0" -> cmul1\n\tcmul1 [label=cmul1' - ' shape=ellipse]\n\t"t1.0" -> out1\n\tout1 [label=out1 shape=cds]\n\tt1Out' - ' -> "t1.0"\n\tt1Out [label=t1 shape=square]\n\t"cmul1.0" -> add1\n\tadd1' - ' [label=add1 shape=ellipse]\n\tcmul1 -> "cmul1.0"\n\tcmul1 [label=cmul1' - ' shape=ellipse]\n\t"add1.0" -> t1In\n\tt1In [label=t1' - ' shape=square]\n\tadd1 -> "add1.0"\n\tadd1 [label=add1 shape=ellipse]\n}' + ' {\n\t\tlabel=N1\n\t\t"cmul0.0" [label=cmul0 height=0.1 shape=rectangle' + ' width=0.1]\n\t}\n\tsubgraph cluster_2 {\n\t\tlabel=N2\n\t\t"add0.0"' + ' [label=add0 height=0.1 shape=rectangle width=0.1]\n\t}\n\t"in0.0" ->' + ' add0\n\tadd0 [label=add0 shape=ellipse]\n\tin0 -> "in0.0"\n\tin0' + ' [label=in0 shape=cds]\n\t"t0.0" -> cmul0\n\tcmul0 [label=cmul0' + ' shape=ellipse]\n\t"t0.0" -> out0\n\tout0 [label=out0 shape=cds]\n\tt0Out' + ' -> "t0.0"\n\tt0Out [label=t0 shape=square]\n\t"cmul0.0" -> add0\n\tadd0' + ' [label=add0 shape=ellipse]\n\tcmul0 -> "cmul0.0"\n\tcmul0 [label=cmul0' + ' shape=ellipse]\n\t"add0.0" -> t0In\n\tt0In [label=t0' + ' shape=square]\n\tadd0 -> "add0.0"\n\tadd0 [label=add0 shape=ellipse]\n}' ) assert sfg_simple_filter.precedence_graph.source in (res, res + "\n") @@ -1202,10 +1202,10 @@ class TestPrecedenceGraph: class TestSFGGraph: def test_sfg(self, sfg_simple_filter): res = ( - 'digraph {\n\trankdir=LR splines=spline\n\tin1 [shape=cds]\n\tin1 -> add1' - ' [headlabel=0]\n\tout1 [shape=cds]\n\tt1 -> out1\n\tadd1' - ' [shape=ellipse]\n\tcmul1 -> add1 [headlabel=1]\n\tcmul1' - ' [shape=ellipse]\n\tadd1 -> t1\n\tt1 [shape=square]\n\tt1 -> cmul1\n}' + 'digraph {\n\trankdir=LR splines=spline\n\tin0 [shape=cds]\n\tin0 -> add0' + ' [headlabel=0]\n\tout0 [shape=cds]\n\tt0 -> out0\n\tadd0' + ' [shape=ellipse]\n\tcmul0 -> add0 [headlabel=1]\n\tcmul0' + ' [shape=ellipse]\n\tadd0 -> t0\n\tt0 [shape=square]\n\tt0 -> cmul0\n}' ) assert sfg_simple_filter.sfg_digraph(branch_node=False).source in ( res, @@ -1214,11 +1214,11 @@ class TestSFGGraph: def test_sfg_show_id(self, sfg_simple_filter): res = ( - 'digraph {\n\trankdir=LR splines=spline\n\tin1 [shape=cds]\n\tin1 -> add1' - ' [label=s1 headlabel=0]\n\tout1 [shape=cds]\n\tt1 -> out1' - ' [label=s2]\n\tadd1 [shape=ellipse]\n\tcmul1 -> add1 [label=s3' - ' headlabel=1]\n\tcmul1 [shape=ellipse]\n\tadd1 -> t1 [label=s4]\n\tt1' - ' [shape=square]\n\tt1 -> cmul1 [label=s5]\n}' + 'digraph {\n\trankdir=LR splines=spline\n\tin0 [shape=cds]\n\tin0 -> add0' + ' [label=s0 headlabel=0]\n\tout0 [shape=cds]\n\tt0 -> out0' + ' [label=s1]\n\tadd0 [shape=ellipse]\n\tcmul0 -> add0 [label=s2' + ' headlabel=1]\n\tcmul0 [shape=ellipse]\n\tadd0 -> t0 [label=s3]\n\tt0' + ' [shape=square]\n\tt0 -> cmul0 [label=s4]\n}' ) assert sfg_simple_filter.sfg_digraph( @@ -1230,12 +1230,12 @@ class TestSFGGraph: def test_sfg_branch(self, sfg_simple_filter): res = ( - 'digraph {\n\trankdir=LR splines=spline\n\tin1 [shape=cds]\n\tin1 -> add1' - ' [headlabel=0]\n\tout1 [shape=cds]\n\t"t1.0" -> out1\n\t"t1.0"' - ' [shape=point]\n\tt1 -> "t1.0" [arrowhead=none]\n\tadd1' - ' [shape=ellipse]\n\tcmul1 -> add1 [headlabel=1]\n\tcmul1' - ' [shape=ellipse]\n\tadd1 -> t1\n\tt1 [shape=square]\n\t"t1.0" ->' - ' cmul1\n}' + 'digraph {\n\trankdir=LR splines=spline\n\tin0 [shape=cds]\n\tin0 -> add0' + ' [headlabel=0]\n\tout0 [shape=cds]\n\t"t0.0" -> out0\n\t"t0.0"' + ' [shape=point]\n\tt0 -> "t0.0" [arrowhead=none]\n\tadd0' + ' [shape=ellipse]\n\tcmul0 -> add0 [headlabel=1]\n\tcmul0' + ' [shape=ellipse]\n\tadd0 -> t0\n\tt0 [shape=square]\n\t"t0.0" ->' + ' cmul0\n}' ) assert sfg_simple_filter.sfg_digraph().source in ( @@ -1245,10 +1245,10 @@ class TestSFGGraph: def test_sfg_no_port_numbering(self, sfg_simple_filter): res = ( - 'digraph {\n\trankdir=LR splines=spline\n\tin1 [shape=cds]\n\tin1 ->' - ' add1\n\tout1 [shape=cds]\n\tt1 -> out1\n\tadd1 [shape=ellipse]\n\tcmul1' - ' -> add1\n\tcmul1 [shape=ellipse]\n\tadd1 -> t1\n\tt1 [shape=square]\n\tt1' - ' -> cmul1\n}' + 'digraph {\n\trankdir=LR splines=spline\n\tin0 [shape=cds]\n\tin0 ->' + ' add0\n\tout0 [shape=cds]\n\tt0 -> out0\n\tadd0 [shape=ellipse]\n\tcmul0' + ' -> add0\n\tcmul0 [shape=ellipse]\n\tadd0 -> t0\n\tt0 [shape=square]\n\tt0' + ' -> cmul0\n}' ) assert sfg_simple_filter.sfg_digraph( @@ -1384,7 +1384,7 @@ class TestSFGErrors: ValueError, match="Different number of input and output ports of operation with", ): - sfg.remove_operation('add1') + sfg.remove_operation('add0') def test_inputs_required_for_output(self): in1 = Input() @@ -1591,13 +1591,13 @@ class TestInsertComponentAfter: assert sfg.find_by_name("constant4")[0].output(0).signals[ 0 - ].destination.operation is sfg.find_by_id("add3") + ].destination.operation is sfg.find_by_id("add2") assert _sfg.find_by_name("constant4")[0].output(0).signals[ 0 - ].destination.operation is not _sfg.find_by_id("add3") - assert _sfg.find_by_id("sqrt1").output(0).signals[ + ].destination.operation is not _sfg.find_by_id("add2") + assert _sfg.find_by_id("sqrt0").output(0).signals[ 0 - ].destination.operation is _sfg.find_by_id("add3") + ].destination.operation is _sfg.find_by_id("add2") def test_insert_component_after_mimo_operation_error( self, large_operation_tree_names diff --git a/test/test_simulation.py b/test/test_simulation.py index cdcb86c0..aa9340a2 100644 --- a/test/test_simulation.py +++ b/test/test_simulation.py @@ -18,31 +18,31 @@ class TestRunFor: assert simulation.results["0"][100] == 304 assert simulation.results["1"][100] == 505 - assert simulation.results["in1"][0] == 3 - assert simulation.results["in2"][0] == 1 - assert simulation.results["add1"][0] == 4 - assert simulation.results["add2"][0] == 5 + assert simulation.results["in0"][0] == 3 + assert simulation.results["in1"][0] == 1 + assert simulation.results["add0"][0] == 4 + assert simulation.results["add1"][0] == 5 assert simulation.results["0"][0] == 4 assert simulation.results["1"][0] == 5 - assert simulation.results["in1"][1] == 4 - assert simulation.results["in2"][1] == 3 - assert simulation.results["add1"][1] == 7 - assert simulation.results["add2"][1] == 10 + assert simulation.results["in0"][1] == 4 + assert simulation.results["in1"][1] == 3 + assert simulation.results["add0"][1] == 7 + assert simulation.results["add1"][1] == 10 assert simulation.results["0"][1] == 7 assert simulation.results["1"][1] == 10 + assert simulation.results["in0"][2] == 5 assert simulation.results["in1"][2] == 5 - assert simulation.results["in2"][2] == 5 - assert simulation.results["add1"][2] == 10 - assert simulation.results["add2"][2] == 15 + assert simulation.results["add0"][2] == 10 + assert simulation.results["add1"][2] == 15 assert simulation.results["0"][2] == 10 assert simulation.results["1"][2] == 15 - assert simulation.results["in1"][3] == 6 - assert simulation.results["in2"][3] == 7 - assert simulation.results["add1"][3] == 13 - assert simulation.results["add2"][3] == 20 + assert simulation.results["in0"][3] == 6 + assert simulation.results["in1"][3] == 7 + assert simulation.results["add0"][3] == 13 + assert simulation.results["add1"][3] == 20 assert simulation.results["0"][3] == 13 assert simulation.results["1"][3] == 20 @@ -58,38 +58,38 @@ class TestRunFor: assert output[0] == 9 assert output[1] == 11 + assert isinstance(simulation.results["in0"], np.ndarray) assert isinstance(simulation.results["in1"], np.ndarray) - assert isinstance(simulation.results["in2"], np.ndarray) + assert isinstance(simulation.results["add0"], np.ndarray) assert isinstance(simulation.results["add1"], np.ndarray) - assert isinstance(simulation.results["add2"], np.ndarray) assert isinstance(simulation.results["0"], np.ndarray) assert isinstance(simulation.results["1"], np.ndarray) - assert simulation.results["in1"][0] == 5 - assert simulation.results["in2"][0] == 7 - assert simulation.results["add1"][0] == 12 - assert simulation.results["add2"][0] == 19 + assert simulation.results["in0"][0] == 5 + assert simulation.results["in1"][0] == 7 + assert simulation.results["add0"][0] == 12 + assert simulation.results["add1"][0] == 19 assert simulation.results["0"][0] == 12 assert simulation.results["1"][0] == 19 - assert simulation.results["in1"][1] == 9 - assert simulation.results["in2"][1] == 3 - assert simulation.results["add1"][1] == 12 - assert simulation.results["add2"][1] == 15 + assert simulation.results["in0"][1] == 9 + assert simulation.results["in1"][1] == 3 + assert simulation.results["add0"][1] == 12 + assert simulation.results["add1"][1] == 15 assert simulation.results["0"][1] == 12 assert simulation.results["1"][1] == 15 - assert simulation.results["in1"][2] == 25 - assert simulation.results["in2"][2] == 3 - assert simulation.results["add1"][2] == 28 - assert simulation.results["add2"][2] == 31 + assert simulation.results["in0"][2] == 25 + assert simulation.results["in1"][2] == 3 + assert simulation.results["add0"][2] == 28 + assert simulation.results["add1"][2] == 31 assert simulation.results["0"][2] == 28 assert simulation.results["1"][2] == 31 - assert simulation.results["in1"][3] == -5 - assert simulation.results["in2"][3] == 54 - assert simulation.results["add1"][3] == 49 - assert simulation.results["add2"][3] == 103 + assert simulation.results["in0"][3] == -5 + assert simulation.results["in1"][3] == 54 + assert simulation.results["add0"][3] == 49 + assert simulation.results["add1"][3] == 103 assert simulation.results["0"][3] == 49 assert simulation.results["1"][3] == 103 -- GitLab