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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 literal 26502 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 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