diff --git a/test/conftest.py b/test/conftest.py index 48b49489424817e1439f6b2b6eb3d7cd63b29a75..637da5fa37a3609c3a4d5e29d8d2c1dca80576da 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,5 +1,6 @@ -from test.fixtures.signal import signal, signals from test.fixtures.operation_tree import * from test.fixtures.port import * +from test.fixtures.signal import signal, signals from test.fixtures.signal_flow_graph import * + import pytest diff --git a/test/fixtures/operation_tree.py b/test/fixtures/operation_tree.py index 7a04400969874ab49e6c024420aa9234c81a3b93..8b2ae8c36fc7383237c35ae6fbf5e3318cd361d6 100644 --- a/test/fixtures/operation_tree.py +++ b/test/fixtures/operation_tree.py @@ -1,12 +1,13 @@ import pytest -from b_asic import Addition, Constant, Signal, Butterfly +from b_asic import Addition, Butterfly, Constant, Signal @pytest.fixture def operation(): return Constant(2) + @pytest.fixture def operation_tree(): """Valid addition operation connected with 2 constants. @@ -20,6 +21,7 @@ def operation_tree(): """ return Addition(Constant(2), Constant(3)) + @pytest.fixture def large_operation_tree(): """Valid addition operation connected with a large operation tree with 2 other additions and 4 constants. @@ -39,7 +41,10 @@ def large_operation_tree(): | 5---+ """ - return Addition(Addition(Constant(2), Constant(3)), Addition(Constant(4), Constant(5))) + return Addition( + Addition(Constant(2), Constant(3)), Addition(Constant(4), Constant(5)) + ) + @pytest.fixture def large_operation_tree_names(): @@ -61,7 +66,11 @@ def large_operation_tree_names(): | 5---+ """ - return Addition(Addition(Constant(2, name="constant2"), Constant(3, name="constant3")), Addition(Constant(4, name="constant4"), Constant(5, name="constant5"))) + return Addition( + Addition(Constant(2, name="constant2"), Constant(3, name="constant3")), + Addition(Constant(4, name="constant4"), Constant(5, name="constant5")), + ) + @pytest.fixture def butterfly_operation_tree(): @@ -74,7 +83,16 @@ def butterfly_operation_tree(): | | | | | | 4 ---+ +--- (2 - 4) ---+ +--- (6 - (-2)) ---+ +--- (4 - 8) ---> out2 = -4 """ - return Butterfly(*(Butterfly(*(Butterfly(Constant(2), Constant(4), name="bfly3").outputs), name="bfly2").outputs), name="bfly1") + return Butterfly( + *( + Butterfly( + *(Butterfly(Constant(2), Constant(4), name="bfly3").outputs), + name="bfly2" + ).outputs + ), + name="bfly1" + ) + @pytest.fixture def operation_graph_with_cycle(): diff --git a/test/fixtures/port.py b/test/fixtures/port.py index 4cce4f69b1f11b44426d1bd39702dba4e11c0efe..df4bff0376765fd2140af143adca851693840ae9 100644 --- a/test/fixtures/port.py +++ b/test/fixtures/port.py @@ -1,20 +1,48 @@ import pytest -from b_asic import InputPort, OutputPort +from b_asic import InputPort, OutputPort, Signal @pytest.fixture def input_port(): return InputPort(None, 0) + @pytest.fixture def output_port(): return OutputPort(None, 0) + @pytest.fixture def list_of_input_ports(): return [InputPort(None, i) for i in range(0, 3)] + @pytest.fixture def list_of_output_ports(): return [OutputPort(None, i) for i in range(0, 3)] + + +@pytest.fixture +def output_port2(): + return OutputPort(None, 1) + + +@pytest.fixture +def dangling_sig(): + return Signal() + + +@pytest.fixture +def s_w_source(output_port): + return Signal(source=output_port) + + +@pytest.fixture +def sig_with_dest(inp_port): + return Signal(destination=inp_port) + + +@pytest.fixture +def connected_sig(inp_port, output_port): + return Signal(source=output_port, destination=inp_port) diff --git a/test/fixtures/signal.py b/test/fixtures/signal.py index 4dba99e24bce16aba67cba58057b3cde76f0923d..64aff3071a059173598a0ae8b9304e7a84b9b52b 100644 --- a/test/fixtures/signal.py +++ b/test/fixtures/signal.py @@ -8,6 +8,7 @@ def signal(): """Return a signal with no connections.""" return Signal() + @pytest.fixture def signals(): """Return 3 signals with no connections.""" diff --git a/test/fixtures/signal_flow_graph.py b/test/fixtures/signal_flow_graph.py index bc8285a3a9904e961306d018ffd95b602b14b836..eb876cec25ae8c6a2e743af6b8c2542d17f8863d 100644 --- a/test/fixtures/signal_flow_graph.py +++ b/test/fixtures/signal_flow_graph.py @@ -1,12 +1,27 @@ +from typing import Optional + import pytest -from b_asic import SFG, Input, Output, Constant, Delay, Addition, ConstantMultiplication, Butterfly, AbstractOperation, Name, TypeName, SignalSourceProvider -from typing import Optional +from b_asic import ( + SFG, + AbstractOperation, + Addition, + Butterfly, + Constant, + ConstantMultiplication, + Delay, + Input, + Name, + Output, + SignalSourceProvider, + TypeName, +) @pytest.fixture def sfg_two_inputs_two_outputs(): - """Valid SFG with two inputs and two outputs. + """ + Valid SFG with two inputs and two outputs. . . in1-------+ +--------->out1 . | | . @@ -33,7 +48,8 @@ def sfg_two_inputs_two_outputs(): @pytest.fixture def sfg_two_inputs_two_outputs_independent(): - """Valid SFG with two inputs and two outputs, where the first output only depends + """ + Valid SFG with two inputs and two outputs, where the first output only depends on the first input and the second output only depends on the second input. . . in1-------------------->out1 @@ -61,7 +77,8 @@ def sfg_two_inputs_two_outputs_independent(): @pytest.fixture def sfg_two_inputs_two_outputs_independent_with_cmul(): - """Valid SFG with two inputs and two outputs, where the first output only depends + """ + Valid SFG with two inputs and two outputs, where the first output only depends on the first input and the second output only depends on the second input. . . in1--->cmul1--->cmul2--->out1 @@ -87,7 +104,8 @@ def sfg_two_inputs_two_outputs_independent_with_cmul(): @pytest.fixture def sfg_nested(): - """Valid SFG with two inputs and one output. + """ + Valid SFG with two inputs and one output. out1 = in1 + (in1 + in1 * in2) * (in1 + in2 * (in1 + in1 * in2)) """ mac_in1 = Input() @@ -107,17 +125,20 @@ def sfg_nested(): @pytest.fixture def sfg_delay(): - """Valid SFG with one input and one output. + """ + Valid SFG with one input and one output. out1 = in1' """ in1 = Input() t1 = Delay(in1) out1 = Output(t1) - return SFG(inputs = [in1], outputs = [out1]) + return SFG(inputs=[in1], outputs=[out1]) + @pytest.fixture def sfg_accumulator(): - """Valid SFG with two inputs and one output. + """ + Valid SFG with two inputs and one output. data_out = (data_in' + data_in) * (1 - reset) """ data_in = Input() @@ -125,12 +146,13 @@ def sfg_accumulator(): t = Delay() t << (t + data_in) * (1 - reset) data_out = Output(t) - return SFG(inputs = [data_in, reset], outputs = [data_out]) + return SFG(inputs=[data_in, reset], outputs=[data_out]) @pytest.fixture def sfg_simple_accumulator(): - """Valid SFG with two inputs and one output. + """ + Valid SFG with two inputs and one output. . . in1----->add1-----+----->out1 . ^ | . @@ -143,11 +165,13 @@ def sfg_simple_accumulator(): add1 = in1 + t1 t1 << add1 out1 = Output(add1) - return SFG(inputs = [in1], outputs = [out1]) + return SFG(inputs=[in1], outputs=[out1]) + @pytest.fixture def sfg_simple_filter(): - """A valid SFG that is used as a filter in the first lab for TSTE87. + """ + A valid SFG that is used as a filter in the first lab for TSTE87. . . . +--cmul1<--+ . . | | . @@ -164,19 +188,25 @@ def sfg_simple_filter(): out1 = Output(t1, "OUT1") return SFG(inputs=[in1], outputs=[out1], name="simple_filter") + @pytest.fixture def sfg_custom_operation(): """A valid SFG containing a custom operation.""" + class CustomOperation(AbstractOperation): - def __init__(self, src0: Optional[SignalSourceProvider] = None, name: Name = ""): - super().__init__(input_count = 1, output_count = 2, name = name, input_sources = [src0]) + def __init__( + self, src0: Optional[SignalSourceProvider] = None, name: Name = "" + ): + super().__init__( + input_count=1, output_count=2, name=name, input_sources=[src0] + ) @classmethod def type_name(self) -> TypeName: return "custom" def evaluate(self, a): - return a * 2, 2 ** a + return a * 2, 2**a in1 = Input() custom1 = CustomOperation(in1) @@ -187,7 +217,8 @@ def sfg_custom_operation(): @pytest.fixture def precedence_sfg_delays(): - """A sfg with delays and interesting layout for precedence list generation. + """ + A sfg with delays and interesting layout for precedence list generation. . . IN1>--->C0>--->ADD1>--->Q1>---+--->A0>--->ADD4>--->OUT1 . ^ | ^ . diff --git a/test/test_core_operations.py b/test/test_core_operations.py index f074e8356f4e5fc3dec654f25f5441a0025cea68..fb957213fc1baf1858693af1492951368432ea30 100644 --- a/test/test_core_operations.py +++ b/test/test_core_operations.py @@ -1,13 +1,26 @@ -""" -B-ASIC test suite for the core operations. -""" +"""B-ASIC test suite for the core operations.""" + +from b_asic import ( + Absolute, + Addition, + AddSub, + Butterfly, + ComplexConjugate, + Constant, + ConstantMultiplication, + Division, + Max, + Min, + Multiplication, + SquareRoot, + Subtraction, + SymmetricTwoportAdaptor, +) -from b_asic import (Constant, Addition, Subtraction, AddSub, Multiplication, - ConstantMultiplication, Division, SquareRoot, - ComplexConjugate, Max, Min, Absolute, Butterfly, - SymmetricTwoportAdaptor) class TestConstant: + """Tests for Constant class.""" + def test_constant_positive(self): test_operation = Constant(3) assert test_operation.evaluate_output(0, []) == 3 @@ -17,11 +30,13 @@ class TestConstant: assert test_operation.evaluate_output(0, []) == -3 def test_constant_complex(self): - test_operation = Constant(3+4j) - assert test_operation.evaluate_output(0, []) == 3+4j + test_operation = Constant(3 + 4j) + assert test_operation.evaluate_output(0, []) == 3 + 4j class TestAddition: + """Tests for Addition class.""" + def test_addition_positive(self): test_operation = Addition() assert test_operation.evaluate_output(0, [3, 5]) == 8 @@ -32,10 +47,12 @@ class TestAddition: def test_addition_complex(self): test_operation = Addition() - assert test_operation.evaluate_output(0, [3+5j, 4+6j]) == 7+11j + assert test_operation.evaluate_output(0, [3 + 5j, 4 + 6j]) == 7 + 11j class TestSubtraction: + """Tests for Subtraction class.""" + def test_subtraction_positive(self): test_operation = Subtraction() assert test_operation.evaluate_output(0, [5, 3]) == 2 @@ -46,10 +63,12 @@ class TestSubtraction: def test_subtraction_complex(self): test_operation = Subtraction() - assert test_operation.evaluate_output(0, [3+5j, 4+6j]) == -1-1j + assert test_operation.evaluate_output(0, [3 + 5j, 4 + 6j]) == -1 - 1j class TestAddSub: + """Tests for AddSub class.""" + def test_addition_positive(self): test_operation = AddSub(is_add=True) assert test_operation.evaluate_output(0, [3, 5]) == 8 @@ -60,7 +79,7 @@ class TestAddSub: def test_addition_complex(self): test_operation = AddSub(is_add=True) - assert test_operation.evaluate_output(0, [3+5j, 4+6j]) == 7+11j + assert test_operation.evaluate_output(0, [3 + 5j, 4 + 6j]) == 7 + 11j def test_addsub_subtraction_positive(self): test_operation = AddSub(is_add=False) @@ -72,10 +91,12 @@ class TestAddSub: def test_addsub_subtraction_complex(self): test_operation = AddSub(is_add=False) - assert test_operation.evaluate_output(0, [3+5j, 4+6j]) == -1-1j + assert test_operation.evaluate_output(0, [3 + 5j, 4 + 6j]) == -1 - 1j class TestMultiplication: + """Tests for Multiplication class.""" + def test_multiplication_positive(self): test_operation = Multiplication() assert test_operation.evaluate_output(0, [5, 3]) == 15 @@ -86,10 +107,12 @@ class TestMultiplication: def test_multiplication_complex(self): test_operation = Multiplication() - assert test_operation.evaluate_output(0, [3+5j, 4+6j]) == -18+38j + assert test_operation.evaluate_output(0, [3 + 5j, 4 + 6j]) == -18 + 38j class TestDivision: + """Tests for Division class.""" + def test_division_positive(self): test_operation = Division() assert test_operation.evaluate_output(0, [30, 5]) == 6 @@ -100,10 +123,15 @@ class TestDivision: def test_division_complex(self): test_operation = Division() - assert test_operation.evaluate_output(0, [60+40j, 10+20j]) == 2.8-1.6j + assert ( + test_operation.evaluate_output(0, [60 + 40j, 10 + 20j]) + == 2.8 - 1.6j + ) class TestSquareRoot: + """Tests for SquareRoot class.""" + def test_squareroot_positive(self): test_operation = SquareRoot() assert test_operation.evaluate_output(0, [36]) == 6 @@ -114,20 +142,24 @@ class TestSquareRoot: def test_squareroot_complex(self): test_operation = SquareRoot() - assert test_operation.evaluate_output(0, [48+64j]) == 8+4j + assert test_operation.evaluate_output(0, [48 + 64j]) == 8 + 4j class TestComplexConjugate: + """Tests for ComplexConjugate class.""" + def test_complexconjugate_positive(self): test_operation = ComplexConjugate() - assert test_operation.evaluate_output(0, [3+4j]) == 3-4j + assert test_operation.evaluate_output(0, [3 + 4j]) == 3 - 4j def test_test_complexconjugate_negative(self): test_operation = ComplexConjugate() - assert test_operation.evaluate_output(0, [-3-4j]) == -3+4j + assert test_operation.evaluate_output(0, [-3 - 4j]) == -3 + 4j class TestMax: + """Tests for Max class.""" + def test_max_positive(self): test_operation = Max() assert test_operation.evaluate_output(0, [30, 5]) == 30 @@ -138,6 +170,8 @@ class TestMax: class TestMin: + """Tests for Min class.""" + def test_min_positive(self): test_operation = Min() assert test_operation.evaluate_output(0, [30, 5]) == 5 @@ -148,6 +182,8 @@ class TestMin: class TestAbsolute: + """Tests for Absolute class.""" + def test_absolute_positive(self): test_operation = Absolute() assert test_operation.evaluate_output(0, [30]) == 30 @@ -158,10 +194,12 @@ class TestAbsolute: def test_absolute_complex(self): test_operation = Absolute() - assert test_operation.evaluate_output(0, [3+4j]) == 5.0 + assert test_operation.evaluate_output(0, [3 + 4j]) == 5.0 class TestConstantMultiplication: + """Tests for ConstantMultiplication class.""" + def test_constantmultiplication_positive(self): test_operation = ConstantMultiplication(5) assert test_operation.evaluate_output(0, [20]) == 100 @@ -171,11 +209,13 @@ class TestConstantMultiplication: assert test_operation.evaluate_output(0, [-5]) == -25 def test_constantmultiplication_complex(self): - test_operation = ConstantMultiplication(3+2j) - assert test_operation.evaluate_output(0, [3+4j]) == 1+18j + test_operation = ConstantMultiplication(3 + 2j) + assert test_operation.evaluate_output(0, [3 + 4j]) == 1 + 18j class TestButterfly: + """Tests for Butterfly class.""" + def test_butterfly_positive(self): test_operation = Butterfly() assert test_operation.evaluate_output(0, [2, 3]) == 5 @@ -188,11 +228,13 @@ class TestButterfly: def test_buttefly_complex(self): test_operation = Butterfly() - assert test_operation.evaluate_output(0, [2+1j, 3-2j]) == 5-1j - assert test_operation.evaluate_output(1, [2+1j, 3-2j]) == -1+3j + assert test_operation.evaluate_output(0, [2 + 1j, 3 - 2j]) == 5 - 1j + assert test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == -1 + 3j class TestSymmetricTwoportAdaptor: + """Tests for SymmetricTwoportAdaptor class.""" + def test_symmetrictwoportadaptor_positive(self): test_operation = SymmetricTwoportAdaptor(0.5) assert test_operation.evaluate_output(0, [2, 3]) == 3.5 @@ -205,8 +247,12 @@ class TestSymmetricTwoportAdaptor: def test_symmetrictwoportadaptor_complex(self): test_operation = SymmetricTwoportAdaptor(0.5) - assert test_operation.evaluate_output(0, [2+1j, 3-2j]) == 3.5-3.5j - assert test_operation.evaluate_output(1, [2+1j, 3-2j]) == 2.5-0.5j + assert ( + test_operation.evaluate_output(0, [2 + 1j, 3 - 2j]) == 3.5 - 3.5j + ) + assert ( + test_operation.evaluate_output(1, [2 + 1j, 3 - 2j]) == 2.5 - 0.5j + ) class TestDepends: diff --git a/test/test_fast_simulation.py b/test/test_fast_simulation.py index 6ddd666d362023760f982a570a106b3ab7cb742f..d27738473bdcfabedce5e8f4bcabcd8d3590ef4a 100644 --- a/test/test_fast_simulation.py +++ b/test/test_fast_simulation.py @@ -1,14 +1,24 @@ -import pytest import numpy as np +import pytest -from b_asic import SFG, Output, FastSimulation, Addition, Subtraction, Constant, Butterfly +from b_asic import ( + SFG, + Addition, + Butterfly, + Constant, + FastSimulation, + Output, + Subtraction, +) class TestRunFor: def test_with_lambdas_as_input(self, sfg_two_inputs_two_outputs): - simulation = FastSimulation(sfg_two_inputs_two_outputs, [lambda n: n + 3, lambda n: 1 + n * 2]) + simulation = FastSimulation( + sfg_two_inputs_two_outputs, [lambda n: n + 3, lambda n: 1 + n * 2] + ) - output = simulation.run_for(101, save_results = True) + output = simulation.run_for(101, save_results=True) assert output[0] == 304 assert output[1] == 505 @@ -46,10 +56,12 @@ class TestRunFor: def test_with_numpy_arrays_as_input(self, sfg_two_inputs_two_outputs): input0 = np.array([5, 9, 25, -5, 7]) - input1 = np.array([7, 3, 3, 54, 2]) - simulation = FastSimulation(sfg_two_inputs_two_outputs, [input0, input1]) + input1 = np.array([7, 3, 3, 54, 2]) + simulation = FastSimulation( + sfg_two_inputs_two_outputs, [input0, input1] + ) - output = simulation.run_for(5, save_results = True) + output = simulation.run_for(5, save_results=True) assert output[0] == 9 assert output[1] == 11 @@ -94,16 +106,20 @@ class TestRunFor: def test_with_numpy_array_overflow(self, sfg_two_inputs_two_outputs): input0 = np.array([5, 9, 25, -5, 7]) - input1 = np.array([7, 3, 3, 54, 2]) - simulation = FastSimulation(sfg_two_inputs_two_outputs, [input0, input1]) + input1 = np.array([7, 3, 3, 54, 2]) + simulation = FastSimulation( + sfg_two_inputs_two_outputs, [input0, input1] + ) simulation.run_for(5) with pytest.raises(IndexError): simulation.step() def test_run_whole_numpy_array(self, sfg_two_inputs_two_outputs): input0 = np.array([5, 9, 25, -5, 7]) - input1 = np.array([7, 3, 3, 54, 2]) - simulation = FastSimulation(sfg_two_inputs_two_outputs, [input0, input1]) + input1 = np.array([7, 3, 3, 54, 2]) + simulation = FastSimulation( + sfg_two_inputs_two_outputs, [input0, input1] + ) simulation.run() assert len(simulation.results["0"]) == 5 assert len(simulation.results["1"]) == 5 @@ -113,7 +129,7 @@ class TestRunFor: def test_delay(self, sfg_delay): simulation = FastSimulation(sfg_delay) simulation.set_input(0, [5, -2, 25, -6, 7, 0]) - simulation.run_for(6, save_results = True) + simulation.run_for(6, save_results=True) assert simulation.results["0"][0] == 0 assert simulation.results["0"][1] == 5 @@ -123,30 +139,44 @@ class TestRunFor: assert simulation.results["0"][5] == 7 def test_find_result_key(self, precedence_sfg_delays): - sim = FastSimulation(precedence_sfg_delays, [[0, 4, 542, 42, 31.314, 534.123, -453415, 5431]]) + sim = FastSimulation( + precedence_sfg_delays, + [[0, 4, 542, 42, 31.314, 534.123, -453415, 5431]], + ) sim.run() - assert sim.results[precedence_sfg_delays.find_result_keys_by_name("ADD2")[0]][4] == 31220 - assert sim.results[precedence_sfg_delays.find_result_keys_by_name("A1")[0]][2] == 80 + assert ( + sim.results[ + precedence_sfg_delays.find_result_keys_by_name("ADD2")[0] + ][4] + == 31220 + ) + assert ( + sim.results[ + precedence_sfg_delays.find_result_keys_by_name("A1")[0] + ][2] + == 80 + ) + class TestRun: def test_save_results(self, sfg_two_inputs_two_outputs): simulation = FastSimulation(sfg_two_inputs_two_outputs, [2, 3]) assert not simulation.results - simulation.run_for(10, save_results = False) + simulation.run_for(10, save_results=False) assert not simulation.results simulation.run_for(10) assert len(simulation.results["0"]) == 10 assert len(simulation.results["1"]) == 10 - simulation.run_for(10, save_results = True) + simulation.run_for(10, save_results=True) assert len(simulation.results["0"]) == 20 assert len(simulation.results["1"]) == 20 - simulation.run_for(10, save_results = False) + simulation.run_for(10, save_results=False) assert len(simulation.results["0"]) == 20 assert len(simulation.results["1"]) == 20 - simulation.run_for(13, save_results = True) + simulation.run_for(13, save_results=True) assert len(simulation.results["0"]) == 33 assert len(simulation.results["1"]) == 33 - simulation.step(save_results = False) + simulation.step(save_results=False) assert len(simulation.results["0"]) == 33 assert len(simulation.results["1"]) == 33 simulation.step() @@ -168,7 +198,7 @@ class TestRun: def test_accumulator(self, sfg_accumulator): data_in = np.array([5, -2, 25, -6, 7, 0]) - reset = np.array([0, 0, 0, 1, 0, 0]) + reset = np.array([0, 0, 0, 1, 0, 0]) simulation = FastSimulation(sfg_accumulator, [data_in, reset]) output0 = simulation.step() output1 = simulation.step() @@ -187,13 +217,26 @@ class TestRun: data_in = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] simulation = FastSimulation(sfg_simple_accumulator, [data_in]) simulation.run() - assert list(simulation.results["0"]) == [0, 1, 3, 6, 10, 15, 21, 28, 36, 45] + assert list(simulation.results["0"]) == [ + 0, + 1, + 3, + 6, + 10, + 15, + 21, + 28, + 36, + 45, + ] def test_simple_filter(self, sfg_simple_filter): input0 = np.array([1, 2, 3, 4, 5]) simulation = FastSimulation(sfg_simple_filter, [input0]) - simulation.run_for(len(input0), save_results = True) - assert all(simulation.results["0"] == np.array([0, 1.0, 2.5, 4.25, 6.125])) + simulation.run_for(len(input0), save_results=True) + assert all( + simulation.results["0"] == np.array([0, 1.0, 2.5, 4.25, 6.125]) + ) def test_custom_operation(self, sfg_custom_operation): simulation = FastSimulation(sfg_custom_operation, [lambda n: n + 1]) @@ -227,6 +270,8 @@ class TestLarge: for _ in range(499): prev_op_sub = Subtraction(prev_op_sub, Constant(2)) butterfly = Butterfly(prev_op_add, prev_op_sub) - sfg = SFG(outputs=[Output(butterfly.output(0)), Output(butterfly.output(1))]) + sfg = SFG( + outputs=[Output(butterfly.output(0)), Output(butterfly.output(1))] + ) simulation = FastSimulation(sfg, []) assert list(simulation.step()) == [0, 2000] diff --git a/test/test_graph_id_generator.py b/test/test_graph_id_generator.py index 72c923b63b6af74296cca86cd432da7e488d55b6..029fe6e7c93cd1baff630591959940e2bef384dd 100644 --- a/test/test_graph_id_generator.py +++ b/test/test_graph_id_generator.py @@ -4,12 +4,14 @@ B-ASIC test suite for graph id generator. import pytest -from b_asic import GraphIDGenerator, GraphID +from b_asic import GraphIDGenerator + @pytest.fixture def graph_id_generator(): return GraphIDGenerator() + class TestGetNextId: def test_empty_string_generator(self, graph_id_generator): """Test the graph id generator for an empty string type.""" @@ -17,7 +19,7 @@ class TestGetNextId: 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.""" + """ "Test the graph id generator for a normal string type.""" assert graph_id_generator.next_id("add") == "add1" assert graph_id_generator.next_id("add") == "add2" diff --git a/test/test_gui.py b/test/test_gui.py index 1e493bac943d01272bfd4489bcfb565f5497defd..cbd73be198ba9fb5a6cca1bb711a14f891829a96 100644 --- a/test/test_gui.py +++ b/test/test_gui.py @@ -3,7 +3,7 @@ import pytest try: import b_asic.GUI as GUI except ImportError: - pytestmark = pytest.mark.skip('Qt not setup') + pytestmark = pytest.mark.skip("Qt not setup") def test_start(qtbot): diff --git a/test/test_inputport.py b/test/test_inputport.py index f4668938ce3aa90e052115d57e3d3d52c9d9e3eb..3d3e057c1ea033822e91d113db5692b13f4b1ab9 100644 --- a/test/test_inputport.py +++ b/test/test_inputport.py @@ -4,27 +4,6 @@ B-ASIC test suite for Inputport import pytest -from b_asic import InputPort, OutputPort, Signal - -@pytest.fixture -def output_port2(): - return OutputPort(None, 1) - -@pytest.fixture -def dangling_sig(): - return Signal() - -@pytest.fixture -def s_w_source(output_port): - return Signal(source=output_port) - -@pytest.fixture -def sig_with_dest(inp_port): - return Signal(destination=inp_port) - -@pytest.fixture -def connected_sig(inp_port, output_port): - return Signal(source=output_port, destination=inp_port) def test_connect_then_disconnect(input_port, output_port): """Test connect unused port to port.""" @@ -44,12 +23,14 @@ def test_connect_then_disconnect(input_port, output_port): assert s1.source is output_port assert s1.destination is None + def test_connect_used_port_to_new_port(input_port, output_port, output_port2): """Multiple connections to an input port should throw an error.""" input_port.connect(output_port) with pytest.raises(Exception): input_port.connect(output_port2) + def test_add_signal_then_disconnect(input_port, s_w_source): """Can signal be connected then disconnected properly?""" input_port.add_signal(s_w_source) diff --git a/test/test_operation.py b/test/test_operation.py index 33f51bd1a2378600ee460635eb3deeacc58e9fc9..e09aa5fa55bb1758c4fd18bf2e6d2d459b08ba1b 100644 --- a/test/test_operation.py +++ b/test/test_operation.py @@ -2,10 +2,17 @@ B-ASIC test suite for the AbstractOperation class. """ -import pytest - -from b_asic import Addition, Subtraction, Multiplication, ConstantMultiplication, Division, Constant, Butterfly, \ - MAD, SquareRoot +from b_asic import ( + MAD, + Addition, + Butterfly, + Constant, + ConstantMultiplication, + Division, + Multiplication, + SquareRoot, + Subtraction, +) class TestOperationOverloading: @@ -106,8 +113,18 @@ class TestTraverse: def test_traverse_type(self, large_operation_tree): result = list(large_operation_tree.traverse()) - assert len(list(filter(lambda type_: isinstance(type_, Addition), result))) == 3 - assert len(list(filter(lambda type_: isinstance(type_, Constant), result))) == 4 + assert ( + len( + list(filter(lambda type_: isinstance(type_, Addition), result)) + ) + == 3 + ) + assert ( + len( + list(filter(lambda type_: isinstance(type_, Constant), result)) + ) + == 4 + ) def test_traverse_loop(self, operation_graph_with_cycle): assert len(list(operation_graph_with_cycle.traverse())) == 8 @@ -147,19 +164,36 @@ class TestLatency: bfly = Butterfly(latency=5) assert bfly.latency == 5 - assert bfly.latency_offsets == {'in0': 0, 'in1': 0, 'out0': 5, 'out1': 5} + assert bfly.latency_offsets == { + "in0": 0, + "in1": 0, + "out0": 5, + "out1": 5, + } def test_latency_offsets_constructor(self): - bfly = Butterfly(latency_offsets={'in0': 2, 'in1': 3, 'out0': 5, 'out1': 10}) + bfly = Butterfly( + latency_offsets={"in0": 2, "in1": 3, "out0": 5, "out1": 10} + ) assert bfly.latency == 8 - assert bfly.latency_offsets == {'in0': 2, 'in1': 3, 'out0': 5, 'out1': 10} + assert bfly.latency_offsets == { + "in0": 2, + "in1": 3, + "out0": 5, + "out1": 10, + } def test_latency_and_latency_offsets_constructor(self): - bfly = Butterfly(latency=5, latency_offsets={'in1': 2, 'out0': 9}) + bfly = Butterfly(latency=5, latency_offsets={"in1": 2, "out0": 9}) assert bfly.latency == 9 - assert bfly.latency_offsets == {"in0": 0, "in1": 2, "out0": 9, "out1": 5} + assert bfly.latency_offsets == { + "in0": 0, + "in1": 2, + "out0": 9, + "out1": 5, + } def test_set_latency(self): bfly = Butterfly() @@ -167,14 +201,24 @@ class TestLatency: bfly.set_latency(9) assert bfly.latency == 9 - assert bfly.latency_offsets == {"in0": 0, "in1": 0, "out0": 9, "out1": 9} + assert bfly.latency_offsets == { + "in0": 0, + "in1": 0, + "out0": 9, + "out1": 9, + } def test_set_latency_offsets(self): bfly = Butterfly() - bfly.set_latency_offsets({'in0': 3, 'out1': 5}) + bfly.set_latency_offsets({"in0": 3, "out1": 5}) - assert bfly.latency_offsets == {'in0': 3, "in1": None, "out0": None, 'out1': 5} + assert bfly.latency_offsets == { + "in0": 3, + "in1": None, + "out0": None, + "out1": 5, + } class TestExecutionTime: @@ -190,11 +234,18 @@ class TestExecutionTime: class TestCopyOperation: def test_copy_butterfly_latency_offsets(self): - bfly = Butterfly(latency_offsets={'in0': 4, 'in1': 2, 'out0': 10, 'out1': 9}) + bfly = Butterfly( + latency_offsets={"in0": 4, "in1": 2, "out0": 10, "out1": 9} + ) bfly_copy = bfly.copy_component() - assert bfly_copy.latency_offsets == {'in0': 4, 'in1': 2, 'out0': 10, 'out1': 9} + assert bfly_copy.latency_offsets == { + "in0": 4, + "in1": 2, + "out0": 10, + "out1": 9, + } def test_copy_execution_time(self): add = Addition() @@ -205,7 +256,7 @@ class TestCopyOperation: assert add_copy.execution_time == 2 -class TestPlotCoordinates(): +class TestPlotCoordinates: def test_simple_case(self): cmult = ConstantMultiplication(0.5) cmult.execution_time = 1 @@ -216,15 +267,27 @@ class TestPlotCoordinates(): assert exe == [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]] def test_complicated_case(self): - bfly = Butterfly(latency_offsets={'in0': 2, 'in1': 3, 'out0': 5, 'out1': 10}) + bfly = Butterfly( + latency_offsets={"in0": 2, "in1": 3, "out0": 5, "out1": 10} + ) bfly.execution_time = 7 lat, exe = bfly.get_plot_coordinates() - assert lat == [[2, 0], [2, 0.5], [3, 0.5], [3, 1], [10, 1], [10, 0.5], [5, 0.5], [5, 0], [2, 0]] + assert lat == [ + [2, 0], + [2, 0.5], + [3, 0.5], + [3, 1], + [10, 1], + [10, 0.5], + [5, 0.5], + [5, 0], + [2, 0], + ] assert exe == [[0, 0], [0, 1], [7, 1], [7, 0], [0, 0]] -class TestIOCoordinates(): +class TestIOCoordinates: def test_simple_case(self): cmult = ConstantMultiplication(0.5) cmult.execution_time = 1 @@ -235,7 +298,9 @@ class TestIOCoordinates(): assert o_c == [[3, 0.5]] def test_complicated_case(self): - bfly = Butterfly(latency_offsets={'in0': 2, 'in1': 3, 'out0': 5, 'out1': 10}) + bfly = Butterfly( + latency_offsets={"in0": 2, "in1": 3, "out0": 5, "out1": 10} + ) bfly.execution_time = 7 i_c, o_c = bfly.get_io_coordinates() diff --git a/test/test_outputport.py b/test/test_outputport.py index 7cc250ee083bdecb5ee04c3c28e56518a5bb6331..8548cbbed19e1931584ba6762d4fe4da5e9017f6 100644 --- a/test/test_outputport.py +++ b/test/test_outputport.py @@ -3,7 +3,8 @@ B-ASIC test suite for OutputPort. """ import pytest -from b_asic import OutputPort, InputPort, Signal +from b_asic import Signal + class TestConnect: def test_multiple_ports(self, output_port, list_of_input_ports): @@ -21,6 +22,7 @@ class TestConnect: assert output_port.signal_count == 1 + class TestAddSignal: def test_dangling(self, output_port): s = Signal() @@ -29,6 +31,7 @@ class TestAddSignal: assert output_port.signal_count == 1 assert output_port.signals == [s] + class TestClear: def test_others_clear(self, output_port, list_of_input_ports): for port in list_of_input_ports: @@ -49,6 +52,7 @@ class TestClear: assert output_port.signal_count == 0 assert output_port.signals == [] + class TestRemoveSignal: def test_one_signal(self, output_port, input_port): s = input_port.connect(output_port) diff --git a/test/test_schedule.py b/test/test_schedule.py index f75e85023144317965d58801228d5a783f959dc8..5f7963b1dddc2d1890b8f6ea2daf08d9a19988ce 100644 --- a/test/test_schedule.py +++ b/test/test_schedule.py @@ -3,21 +3,32 @@ B-ASIC test suite for the schedule module and Schedule class. """ import pytest -from b_asic import Schedule, Addition, ConstantMultiplication +from b_asic import Addition, ConstantMultiplication, Schedule class TestInit: def test_simple_filter_normal_latency(self, sfg_simple_filter): sfg_simple_filter.set_latency_of_type(Addition.type_name(), 5) - sfg_simple_filter.set_latency_of_type(ConstantMultiplication.type_name(), 4) + sfg_simple_filter.set_latency_of_type( + ConstantMultiplication.type_name(), 4 + ) schedule = Schedule(sfg_simple_filter) - assert schedule._start_times == {"in1": 0, "add1": 4, "cmul1": 0, "out1": 0} + assert schedule._start_times == { + "in1": 0, + "add1": 4, + "cmul1": 0, + "out1": 0, + } - def test_complicated_single_outputs_normal_latency(self, precedence_sfg_delays): + def test_complicated_single_outputs_normal_latency( + self, precedence_sfg_delays + ): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") @@ -29,23 +40,60 @@ class TestInit: op_name = precedence_sfg_delays.find_by_id(op_id).name start_times_names[op_name] = start_time - assert start_times_names == {"IN1": 0, "C0": 0, "B1": 0, "B2": 0, "ADD2": 3, "ADD1": 7, "Q1": 11, - "A0": 14, "A1": 0, "A2": 0, "ADD3": 3, "ADD4": 17, "OUT1": 21} - - def test_complicated_single_outputs_complex_latencies(self, precedence_sfg_delays): - precedence_sfg_delays.set_latency_offsets_of_type(ConstantMultiplication.type_name(), {'in0': 3, 'out0': 5}) - - precedence_sfg_delays.find_by_name("B1")[0].set_latency_offsets({'in0': 4, 'out0': 7}) - precedence_sfg_delays.find_by_name("B2")[0].set_latency_offsets({'in0': 1, 'out0': 4}) - precedence_sfg_delays.find_by_name("ADD2")[0].set_latency_offsets({'in0': 4, 'in1': 2, 'out0': 4}) - precedence_sfg_delays.find_by_name("ADD1")[0].set_latency_offsets({'in0': 1, 'in1': 2, 'out0': 4}) - precedence_sfg_delays.find_by_name("Q1")[0].set_latency_offsets({'in0': 3, 'out0': 6}) - precedence_sfg_delays.find_by_name("A0")[0].set_latency_offsets({'in0': 0, 'out0': 2}) - - precedence_sfg_delays.find_by_name("A1")[0].set_latency_offsets({'in0': 0, 'out0': 5}) - precedence_sfg_delays.find_by_name("A2")[0].set_latency_offsets({'in0': 2, 'out0': 3}) - precedence_sfg_delays.find_by_name("ADD3")[0].set_latency_offsets({'in0': 2, 'in1': 1, 'out0': 4}) - precedence_sfg_delays.find_by_name("ADD4")[0].set_latency_offsets({'in0': 6, 'in1': 7, 'out0': 9}) + assert start_times_names == { + "IN1": 0, + "C0": 0, + "B1": 0, + "B2": 0, + "ADD2": 3, + "ADD1": 7, + "Q1": 11, + "A0": 14, + "A1": 0, + "A2": 0, + "ADD3": 3, + "ADD4": 17, + "OUT1": 21, + } + + def test_complicated_single_outputs_complex_latencies( + self, precedence_sfg_delays + ): + precedence_sfg_delays.set_latency_offsets_of_type( + ConstantMultiplication.type_name(), {"in0": 3, "out0": 5} + ) + + precedence_sfg_delays.find_by_name("B1")[0].set_latency_offsets( + {"in0": 4, "out0": 7} + ) + precedence_sfg_delays.find_by_name("B2")[0].set_latency_offsets( + {"in0": 1, "out0": 4} + ) + precedence_sfg_delays.find_by_name("ADD2")[0].set_latency_offsets( + {"in0": 4, "in1": 2, "out0": 4} + ) + precedence_sfg_delays.find_by_name("ADD1")[0].set_latency_offsets( + {"in0": 1, "in1": 2, "out0": 4} + ) + precedence_sfg_delays.find_by_name("Q1")[0].set_latency_offsets( + {"in0": 3, "out0": 6} + ) + precedence_sfg_delays.find_by_name("A0")[0].set_latency_offsets( + {"in0": 0, "out0": 2} + ) + + precedence_sfg_delays.find_by_name("A1")[0].set_latency_offsets( + {"in0": 0, "out0": 5} + ) + precedence_sfg_delays.find_by_name("A2")[0].set_latency_offsets( + {"in0": 2, "out0": 3} + ) + precedence_sfg_delays.find_by_name("ADD3")[0].set_latency_offsets( + {"in0": 2, "in1": 1, "out0": 4} + ) + precedence_sfg_delays.find_by_name("ADD4")[0].set_latency_offsets( + {"in0": 6, "in1": 7, "out0": 9} + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") @@ -54,63 +102,147 @@ class TestInit: op_name = precedence_sfg_delays.find_by_id(op_id).name start_times_names[op_name] = start_time - assert start_times_names == {'IN1': 0, 'C0': 0, 'B1': 0, 'B2': 0, 'ADD2': 3, 'ADD1': 5, 'Q1': 6, 'A0': 12, - 'A1': 0, 'A2': 0, 'ADD3': 3, 'ADD4': 8, 'OUT1': 17} - - def test_independent_sfg(self, sfg_two_inputs_two_outputs_independent_with_cmul): - schedule = Schedule(sfg_two_inputs_two_outputs_independent_with_cmul, scheduling_alg="ASAP") + assert start_times_names == { + "IN1": 0, + "C0": 0, + "B1": 0, + "B2": 0, + "ADD2": 3, + "ADD1": 5, + "Q1": 6, + "A0": 12, + "A1": 0, + "A2": 0, + "ADD3": 3, + "ADD4": 8, + "OUT1": 17, + } + + def test_independent_sfg( + self, sfg_two_inputs_two_outputs_independent_with_cmul + ): + schedule = Schedule( + sfg_two_inputs_two_outputs_independent_with_cmul, + scheduling_alg="ASAP", + ) start_times_names = {} for op_id, start_time in schedule._start_times.items(): - op_name = sfg_two_inputs_two_outputs_independent_with_cmul.find_by_id(op_id).name + op_name = ( + sfg_two_inputs_two_outputs_independent_with_cmul.find_by_id( + op_id + ).name + ) start_times_names[op_name] = start_time - assert start_times_names == {'C1': 0, 'IN1': 0, 'IN2': 0, 'CMUL1': 0, 'CMUL2': 5, - "ADD1": 0, "CMUL3": 7, 'OUT1': 9, 'OUT2': 10} + assert start_times_names == { + "C1": 0, + "IN1": 0, + "IN2": 0, + "CMUL1": 0, + "CMUL2": 5, + "ADD1": 0, + "CMUL3": 7, + "OUT1": 9, + "OUT2": 10, + } class TestSlacks: - def test_forward_backward_slack_normal_latency(self, precedence_sfg_delays): + def test_forward_backward_slack_normal_latency( + self, precedence_sfg_delays + ): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") - assert schedule.forward_slack(precedence_sfg_delays.find_by_name("ADD3")[0].graph_id) == 7 - assert schedule.backward_slack(precedence_sfg_delays.find_by_name("ADD3")[0].graph_id) == 0 - - assert schedule.forward_slack(precedence_sfg_delays.find_by_name("A2")[0].graph_id) == 0 - assert schedule.backward_slack(precedence_sfg_delays.find_by_name("A2")[0].graph_id) == 16 + assert ( + schedule.forward_slack( + precedence_sfg_delays.find_by_name("ADD3")[0].graph_id + ) + == 7 + ) + assert ( + schedule.backward_slack( + precedence_sfg_delays.find_by_name("ADD3")[0].graph_id + ) + == 0 + ) + + assert ( + schedule.forward_slack( + precedence_sfg_delays.find_by_name("A2")[0].graph_id + ) + == 0 + ) + assert ( + schedule.backward_slack( + precedence_sfg_delays.find_by_name("A2")[0].graph_id + ) + == 16 + ) def test_slacks_normal_latency(self, precedence_sfg_delays): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") - assert schedule.slacks(precedence_sfg_delays.find_by_name("ADD3")[0].graph_id) == (0, 7) - assert schedule.slacks(precedence_sfg_delays.find_by_name("A2")[0].graph_id) == (16, 0) + assert schedule.slacks( + precedence_sfg_delays.find_by_name("ADD3")[0].graph_id + ) == (0, 7) + assert schedule.slacks( + precedence_sfg_delays.find_by_name("A2")[0].graph_id + ) == (16, 0) class TestRescheduling: def test_move_operation(self, precedence_sfg_delays): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 4) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") - schedule.move_operation(precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 4) - schedule.move_operation(precedence_sfg_delays.find_by_name("A2")[0].graph_id, 2) + schedule.move_operation( + precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 4 + ) + schedule.move_operation( + precedence_sfg_delays.find_by_name("A2")[0].graph_id, 2 + ) start_times_names = {} for op_id, start_time in schedule._start_times.items(): op_name = precedence_sfg_delays.find_by_id(op_id).name start_times_names[op_name] = start_time - assert start_times_names == {"IN1": 0, "C0": 0, "B1": 0, "B2": 0, "ADD2": 3, "ADD1": 7, "Q1": 11, - "A0": 14, "A1": 0, "A2": 2, "ADD3": 7, "ADD4": 17, "OUT1": 21} - - def test_move_operation_slack_after_rescheduling(self, precedence_sfg_delays): + assert start_times_names == { + "IN1": 0, + "C0": 0, + "B1": 0, + "B2": 0, + "ADD2": 3, + "ADD1": 7, + "Q1": 11, + "A0": 14, + "A1": 0, + "A2": 2, + "ADD3": 7, + "ADD4": 17, + "OUT1": 21, + } + + def test_move_operation_slack_after_rescheduling( + self, precedence_sfg_delays + ): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") add3_id = precedence_sfg_delays.find_by_name("ADD3")[0].graph_id @@ -130,18 +262,30 @@ class TestRescheduling: assert schedule.forward_slack(a2_id) == 2 assert schedule.backward_slack(a2_id) == 18 - def test_move_operation_incorrect_move_backward(self, precedence_sfg_delays): + def test_move_operation_incorrect_move_backward( + self, precedence_sfg_delays + ): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") with pytest.raises(ValueError): - schedule.move_operation(precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, -4) + schedule.move_operation( + precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, -4 + ) - def test_move_operation_incorrect_move_forward(self, precedence_sfg_delays): + def test_move_operation_incorrect_move_forward( + self, precedence_sfg_delays + ): precedence_sfg_delays.set_latency_of_type(Addition.type_name(), 1) - precedence_sfg_delays.set_latency_of_type(ConstantMultiplication.type_name(), 3) + precedence_sfg_delays.set_latency_of_type( + ConstantMultiplication.type_name(), 3 + ) schedule = Schedule(precedence_sfg_delays, scheduling_alg="ASAP") with pytest.raises(ValueError): - schedule.move_operation(precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 10) + schedule.move_operation( + precedence_sfg_delays.find_by_name("ADD3")[0].graph_id, 10 + ) diff --git a/test/test_scheduler_gui.py b/test/test_scheduler_gui.py index 4d6a41d9d6ba38b4b2292aeafb10379d466321b4..3a045f851007bc17939666c8e7907c76d572ca72 100644 --- a/test/test_scheduler_gui.py +++ b/test/test_scheduler_gui.py @@ -3,7 +3,7 @@ import pytest try: import b_asic.scheduler_gui as GUI except ImportError: - pytestmark = pytest.mark.skip('Qt not setup') + pytestmark = pytest.mark.skip("Qt not setup") def test_start(qtbot): diff --git a/test/test_sfg.py b/test/test_sfg.py index d2d1c0b1fde9529f978f558b140e7ec43bbba230..8c80b85a5f406edc9a3aabcc7a4b0849df062a96 100644 --- a/test/test_sfg.py +++ b/test/test_sfg.py @@ -1,16 +1,27 @@ -from os import path, remove -import pytest +import io import random import string -import io import sys +from os import path, remove -from b_asic import SFG, Signal, Input, Output, Delay, FastSimulation -from b_asic.core_operations import Constant, Addition, Subtraction, Multiplication, \ - Division, Min, Max, SquareRoot, ComplexConjugate, Absolute, ConstantMultiplication, \ - Butterfly +import pytest -from b_asic.save_load_structure import sfg_to_python, python_to_sfg +from b_asic import SFG, FastSimulation, Input, Output, Signal +from b_asic.core_operations import ( + Absolute, + Addition, + Butterfly, + ComplexConjugate, + Constant, + ConstantMultiplication, + Division, + Max, + Min, + Multiplication, + SquareRoot, + Subtraction, +) +from b_asic.save_load_structure import python_to_sfg, sfg_to_python class TestInit: @@ -65,15 +76,21 @@ class TestPrintSfg: out1 = Output(add1, "OUT1") sfg = SFG(inputs=[inp1, inp2], outputs=[out1], name="SFG1") - assert sfg.__str__() == \ - "id: no_id, \tname: SFG1, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + \ - "Internal Operations:\n" + \ - "----------------------------------------------------------------------------------------------------\n" + \ - str(sfg.find_by_name("INP1")[0]) + "\n" + \ - str(sfg.find_by_name("INP2")[0]) + "\n" + \ - str(sfg.find_by_name("ADD1")[0]) + "\n" + \ - str(sfg.find_by_name("OUT1")[0]) + "\n" + \ - "----------------------------------------------------------------------------------------------------\n" + assert ( + sfg.__str__() + == "id: no_id, \tname: SFG1, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + + "Internal Operations:\n" + + "----------------------------------------------------------------------------------------------------\n" + + str(sfg.find_by_name("INP1")[0]) + + "\n" + + str(sfg.find_by_name("INP2")[0]) + + "\n" + + str(sfg.find_by_name("ADD1")[0]) + + "\n" + + str(sfg.find_by_name("OUT1")[0]) + + "\n" + + "----------------------------------------------------------------------------------------------------\n" + ) def test_add_mul(self): inp1 = Input("INP1") @@ -84,17 +101,25 @@ class TestPrintSfg: out1 = Output(mul1, "OUT1") sfg = SFG(inputs=[inp1, inp2, inp3], outputs=[out1], name="mac_sfg") - assert sfg.__str__() == \ - "id: no_id, \tname: mac_sfg, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + \ - "Internal Operations:\n" + \ - "----------------------------------------------------------------------------------------------------\n" + \ - str(sfg.find_by_name("INP1")[0]) + "\n" + \ - str(sfg.find_by_name("INP2")[0]) + "\n" + \ - str(sfg.find_by_name("ADD1")[0]) + "\n" + \ - str(sfg.find_by_name("INP3")[0]) + "\n" + \ - str(sfg.find_by_name("MUL1")[0]) + "\n" + \ - str(sfg.find_by_name("OUT1")[0]) + "\n" + \ - "----------------------------------------------------------------------------------------------------\n" + assert ( + sfg.__str__() + == "id: no_id, \tname: mac_sfg, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + + "Internal Operations:\n" + + "----------------------------------------------------------------------------------------------------\n" + + str(sfg.find_by_name("INP1")[0]) + + "\n" + + str(sfg.find_by_name("INP2")[0]) + + "\n" + + str(sfg.find_by_name("ADD1")[0]) + + "\n" + + str(sfg.find_by_name("INP3")[0]) + + "\n" + + str(sfg.find_by_name("MUL1")[0]) + + "\n" + + str(sfg.find_by_name("OUT1")[0]) + + "\n" + + "----------------------------------------------------------------------------------------------------\n" + ) def test_constant(self): inp1 = Input("INP1") @@ -104,27 +129,40 @@ class TestPrintSfg: sfg = SFG(inputs=[inp1], outputs=[out1], name="sfg") - assert sfg.__str__() == \ - "id: no_id, \tname: sfg, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + \ - "Internal Operations:\n" + \ - "----------------------------------------------------------------------------------------------------\n" + \ - str(sfg.find_by_name("CONST")[0]) + "\n" + \ - str(sfg.find_by_name("INP1")[0]) + "\n" + \ - str(sfg.find_by_name("ADD1")[0]) + "\n" + \ - str(sfg.find_by_name("OUT1")[0]) + "\n" + \ - "----------------------------------------------------------------------------------------------------\n" + assert ( + sfg.__str__() + == "id: no_id, \tname: sfg, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + + "Internal Operations:\n" + + "----------------------------------------------------------------------------------------------------\n" + + str(sfg.find_by_name("CONST")[0]) + + "\n" + + str(sfg.find_by_name("INP1")[0]) + + "\n" + + str(sfg.find_by_name("ADD1")[0]) + + "\n" + + str(sfg.find_by_name("OUT1")[0]) + + "\n" + + "----------------------------------------------------------------------------------------------------\n" + ) def test_simple_filter(self, sfg_simple_filter): - assert sfg_simple_filter.__str__() == \ - "id: no_id, \tname: simple_filter, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + \ - "Internal Operations:\n" + \ - "----------------------------------------------------------------------------------------------------\n" + \ - str(sfg_simple_filter.find_by_name("IN1")[0]) + "\n" + \ - str(sfg_simple_filter.find_by_name("ADD1")[0]) + "\n" + \ - str(sfg_simple_filter.find_by_name("T1")[0]) + "\n" + \ - str(sfg_simple_filter.find_by_name("CMUL1")[0]) + "\n" + \ - str(sfg_simple_filter.find_by_name("OUT1")[0]) + "\n" + \ - "----------------------------------------------------------------------------------------------------\n" + assert ( + sfg_simple_filter.__str__() + == "id: no_id, \tname: simple_filter, \tinputs: {0: '-'}, \toutputs: {0: '-'}\n" + + "Internal Operations:\n" + + "----------------------------------------------------------------------------------------------------\n" + + str(sfg_simple_filter.find_by_name("IN1")[0]) + + "\n" + + str(sfg_simple_filter.find_by_name("ADD1")[0]) + + "\n" + + str(sfg_simple_filter.find_by_name("T1")[0]) + + "\n" + + str(sfg_simple_filter.find_by_name("CMUL1")[0]) + + "\n" + + str(sfg_simple_filter.find_by_name("OUT1")[0]) + + "\n" + + "----------------------------------------------------------------------------------------------------\n" + ) class TestDeepCopy: @@ -163,8 +201,12 @@ class TestDeepCopy: mul1.input(1).connect(add2, "S6") out1.input(0).connect(mul1, "S7") - mac_sfg = SFG(inputs=[inp1, inp2], outputs=[out1], - id_number_offset=100, name="mac_sfg") + mac_sfg = SFG( + inputs=[inp1, inp2], + outputs=[out1], + id_number_offset=100, + name="mac_sfg", + ) mac_sfg_new = mac_sfg(name="mac_sfg2") assert mac_sfg.name == "mac_sfg" @@ -229,7 +271,21 @@ class TestComponents: mac_sfg = SFG(inputs=[inp1, inp2], outputs=[out1], name="mac_sfg") assert {comp.name for comp in mac_sfg.components} == { - "INP1", "INP2", "INP3", "ADD1", "ADD2", "MUL1", "OUT1", "S1", "S2", "S3", "S4", "S5", "S6", "S7"} + "INP1", + "INP2", + "INP3", + "ADD1", + "ADD2", + "MUL1", + "OUT1", + "S1", + "S2", + "S3", + "S4", + "S5", + "S6", + "S7", + } class TestReplaceComponents: @@ -238,7 +294,8 @@ class TestReplaceComponents: component_id = "add1" sfg = sfg.replace_component( - Multiplication(name="Multi"), graph_id=component_id) + Multiplication(name="Multi"), graph_id=component_id + ) assert component_id not in sfg._components_by_id.keys() assert "Multi" in sfg._components_by_name.keys() @@ -247,7 +304,8 @@ class TestReplaceComponents: component_id = "add3" sfg = sfg.replace_component( - Multiplication(name="Multi"), graph_id=component_id) + Multiplication(name="Multi"), graph_id=component_id + ) assert "Multi" in sfg._components_by_name.keys() assert component_id not in sfg._components_by_id.keys() @@ -265,7 +323,8 @@ class TestReplaceComponents: try: sfg = sfg.replace_component( - Multiplication(name="Multi"), graph_id=component_id) + Multiplication(name="Multi"), graph_id=component_id + ) except AssertionError: assert True else: @@ -277,7 +336,8 @@ class TestReplaceComponents: try: sfg = sfg.replace_component( - Multiplication(name="Multi"), graph_id=component_id) + Multiplication(name="Multi"), graph_id=component_id + ) except AssertionError: assert True else: @@ -285,7 +345,6 @@ class TestReplaceComponents: class TestConstructSFG: - def test_1k_additions(self): prev_op = Addition(Constant(1), Constant(1)) for _ in range(999): @@ -312,8 +371,9 @@ class TestConstructSFG: for _ in range(499): prev_op_sub = Subtraction(prev_op_sub, Constant(2)) butterfly = Butterfly(prev_op_add, prev_op_sub) - sfg = SFG(outputs=[Output(butterfly.output(0)), - Output(butterfly.output(1))]) + sfg = SFG( + outputs=[Output(butterfly.output(0)), Output(butterfly.output(1))] + ) sim = FastSimulation(sfg) sim.step() assert sim.results["0"][0].real == 0 @@ -365,13 +425,13 @@ class TestConstructSFG: assert sim.results["0"][0].real == 1.539926526059492 def test_1k_complex_conjugates(self): - prev_op = ComplexConjugate(Constant(10+5j)) + prev_op = ComplexConjugate(Constant(10 + 5j)) for _ in range(999): prev_op = ComplexConjugate(prev_op) sfg = SFG(outputs=[Output(prev_op)]) sim = FastSimulation(sfg) sim.step() - assert sim.results["0"] == [10+5j] + assert sim.results["0"] == [10 + 5j] def test_1k_absolutes(self): prev_op = Absolute(Constant(-3.14159)) @@ -393,30 +453,44 @@ class TestConstructSFG: class TestInsertComponent: - def test_insert_component_in_sfg(self, large_operation_tree_names): sfg = SFG(outputs=[Output(large_operation_tree_names)]) sqrt = SquareRoot() _sfg = sfg.insert_operation( - sqrt, sfg.find_by_name("constant4")[0].graph_id) + sqrt, sfg.find_by_name("constant4")[0].graph_id + ) assert _sfg.evaluate() != sfg.evaluate() assert any([isinstance(comp, SquareRoot) for comp in _sfg.operations]) - assert not any([isinstance(comp, SquareRoot) - for comp in sfg.operations]) - - assert not isinstance(sfg.find_by_name("constant4")[0].output( - 0).signals[0].destination.operation, SquareRoot) - assert isinstance(_sfg.find_by_name("constant4")[0].output( - 0).signals[0].destination.operation, SquareRoot) - - assert sfg.find_by_name("constant4")[0].output( - 0).signals[0].destination.operation is sfg.find_by_id("add3") - 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[0].destination.operation is _sfg.find_by_id("add3") + assert not any( + [isinstance(comp, SquareRoot) for comp in sfg.operations] + ) + + assert not isinstance( + sfg.find_by_name("constant4")[0] + .output(0) + .signals[0] + .destination.operation, + SquareRoot, + ) + assert isinstance( + _sfg.find_by_name("constant4")[0] + .output(0) + .signals[0] + .destination.operation, + SquareRoot, + ) + + assert sfg.find_by_name("constant4")[0].output(0).signals[ + 0 + ].destination.operation is sfg.find_by_id("add3") + 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[ + 0 + ].destination.operation is _sfg.find_by_id("add3") def test_insert_invalid_component_in_sfg(self, large_operation_tree): sfg = SFG(outputs=[Output(large_operation_tree)]) @@ -432,7 +506,7 @@ class TestInsertComponent: # Should raise an exception for trying to insert an operation after an output. sqrt = SquareRoot() with pytest.raises(Exception): - _sfg = sfg.insert_operation(sqrt, "out1") + _ = sfg.insert_operation(sqrt, "out1") def test_insert_multiple_output_ports(self, butterfly_operation_tree): sfg = SFG(outputs=list(map(Output, butterfly_operation_tree.outputs))) @@ -444,28 +518,56 @@ class TestInsertComponent: assert len(_sfg.find_by_name("n_bfly")) == 1 # Correctly connected old output -> new input - assert _sfg.find_by_name("bfly3")[0].output( - 0).signals[0].destination.operation is _sfg.find_by_name("n_bfly")[0] - assert _sfg.find_by_name("bfly3")[0].output( - 1).signals[0].destination.operation is _sfg.find_by_name("n_bfly")[0] + assert ( + _sfg.find_by_name("bfly3")[0] + .output(0) + .signals[0] + .destination.operation + is _sfg.find_by_name("n_bfly")[0] + ) + assert ( + _sfg.find_by_name("bfly3")[0] + .output(1) + .signals[0] + .destination.operation + is _sfg.find_by_name("n_bfly")[0] + ) # Correctly connected new input -> old output - assert _sfg.find_by_name("n_bfly")[0].input( - 0).signals[0].source.operation is _sfg.find_by_name("bfly3")[0] - assert _sfg.find_by_name("n_bfly")[0].input( - 1).signals[0].source.operation is _sfg.find_by_name("bfly3")[0] + assert ( + _sfg.find_by_name("n_bfly")[0].input(0).signals[0].source.operation + is _sfg.find_by_name("bfly3")[0] + ) + assert ( + _sfg.find_by_name("n_bfly")[0].input(1).signals[0].source.operation + is _sfg.find_by_name("bfly3")[0] + ) # Correctly connected new output -> next input - assert _sfg.find_by_name("n_bfly")[0].output( - 0).signals[0].destination.operation is _sfg.find_by_name("bfly2")[0] - assert _sfg.find_by_name("n_bfly")[0].output( - 1).signals[0].destination.operation is _sfg.find_by_name("bfly2")[0] + assert ( + _sfg.find_by_name("n_bfly")[0] + .output(0) + .signals[0] + .destination.operation + is _sfg.find_by_name("bfly2")[0] + ) + assert ( + _sfg.find_by_name("n_bfly")[0] + .output(1) + .signals[0] + .destination.operation + is _sfg.find_by_name("bfly2")[0] + ) # Correctly connected next input -> new output - assert _sfg.find_by_name("bfly2")[0].input( - 0).signals[0].source.operation is _sfg.find_by_name("n_bfly")[0] - assert _sfg.find_by_name("bfly2")[0].input( - 1).signals[0].source.operation is _sfg.find_by_name("n_bfly")[0] + assert ( + _sfg.find_by_name("bfly2")[0].input(0).signals[0].source.operation + is _sfg.find_by_name("n_bfly")[0] + ) + assert ( + _sfg.find_by_name("bfly2")[0].input(1).signals[0].source.operation + is _sfg.find_by_name("n_bfly")[0] + ) class TestFindComponentsWithTypeName: @@ -488,79 +590,152 @@ class TestFindComponentsWithTypeName: mac_sfg = SFG(inputs=[inp1, inp2], outputs=[out1], name="mac_sfg") - assert {comp.name for comp in mac_sfg.find_by_type_name( - inp1.type_name())} == {"INP1", "INP2", "INP3"} + assert { + comp.name for comp in mac_sfg.find_by_type_name(inp1.type_name()) + } == { + "INP1", + "INP2", + "INP3", + } - assert {comp.name for comp in mac_sfg.find_by_type_name( - add1.type_name())} == {"ADD1", "ADD2"} + assert { + comp.name for comp in mac_sfg.find_by_type_name(add1.type_name()) + } == { + "ADD1", + "ADD2", + } - assert {comp.name for comp in mac_sfg.find_by_type_name( - mul1.type_name())} == {"MUL1"} + assert { + comp.name for comp in mac_sfg.find_by_type_name(mul1.type_name()) + } == {"MUL1"} - assert {comp.name for comp in mac_sfg.find_by_type_name( - out1.type_name())} == {"OUT1"} + assert { + comp.name for comp in mac_sfg.find_by_type_name(out1.type_name()) + } == {"OUT1"} - assert {comp.name for comp in mac_sfg.find_by_type_name( - Signal.type_name())} == {"S1", "S2", "S3", "S4", "S5", "S6", "S7"} + assert { + comp.name for comp in mac_sfg.find_by_type_name(Signal.type_name()) + } == {"S1", "S2", "S3", "S4", "S5", "S6", "S7"} class TestGetPrecedenceList: - def test_inputs_delays(self, precedence_sfg_delays): precedence_list = precedence_sfg_delays.get_precedence_list() assert len(precedence_list) == 7 - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[0]]) == {"IN1", "T1", "T2"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[0] + ] + ) == {"IN1", "T1", "T2"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[1]]) == {"C0", "B1", "B2", "A1", "A2"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[1] + ] + ) == {"C0", "B1", "B2", "A1", "A2"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[2]]) == {"ADD2", "ADD3"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[2] + ] + ) == {"ADD2", "ADD3"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[3]]) == {"ADD1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[3] + ] + ) == {"ADD1"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[4]]) == {"Q1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[4] + ] + ) == {"Q1"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[5]]) == {"A0"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[5] + ] + ) == {"A0"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[6]]) == {"ADD4"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[6] + ] + ) == {"ADD4"} - def test_inputs_constants_delays_multiple_outputs(self, precedence_sfg_delays_and_constants): + def test_inputs_constants_delays_multiple_outputs( + self, precedence_sfg_delays_and_constants + ): - precedence_list = precedence_sfg_delays_and_constants.get_precedence_list() + precedence_list = ( + precedence_sfg_delays_and_constants.get_precedence_list() + ) assert len(precedence_list) == 7 - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[0]]) == {"IN1", "T1", "CONST1"} - - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[1]]) == {"C0", "B1", "B2", "A1", "A2"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[0] + ] + ) == {"IN1", "T1", "CONST1"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[2]]) == {"ADD2", "ADD3"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[1] + ] + ) == {"C0", "B1", "B2", "A1", "A2"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[3]]) == {"ADD1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[2] + ] + ) == {"ADD2", "ADD3"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[4]]) == {"Q1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[3] + ] + ) == {"ADD1"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[5]]) == {"A0"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[4] + ] + ) == {"Q1"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[6]]) == {"BFLY1.0", "BFLY1.1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[5] + ] + ) == {"A0"} - def test_precedence_multiple_outputs_same_precedence(self, sfg_two_inputs_two_outputs): + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[6] + ] + ) == {"BFLY1.0", "BFLY1.1"} + + def test_precedence_multiple_outputs_same_precedence( + self, sfg_two_inputs_two_outputs + ): sfg_two_inputs_two_outputs.name = "NESTED_SFG" in1 = Input("IN1") @@ -579,16 +754,30 @@ class TestGetPrecedenceList: assert len(precedence_list) == 3 - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[0]]) == {"IN1", "IN2"} - - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[1]]) == {"CMUL1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[0] + ] + ) == {"IN1", "IN2"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[2]]) == {"NESTED_SFG.0", "NESTED_SFG.1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[1] + ] + ) == {"CMUL1"} - def test_precedence_sfg_multiple_outputs_different_precedences(self, sfg_two_inputs_two_outputs_independent): + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[2] + ] + ) == {"NESTED_SFG.0", "NESTED_SFG.1"} + + def test_precedence_sfg_multiple_outputs_different_precedences( + self, sfg_two_inputs_two_outputs_independent + ): sfg_two_inputs_two_outputs_independent.name = "NESTED_SFG" in1 = Input("IN1") @@ -606,14 +795,26 @@ class TestGetPrecedenceList: assert len(precedence_list) == 3 - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[0]]) == {"IN1", "IN2"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[0] + ] + ) == {"IN1", "IN2"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[1]]) == {"CMUL1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[1] + ] + ) == {"CMUL1"} - assert set([port.operation.key(port.index, port.operation.name) - for port in precedence_list[2]]) == {"NESTED_SFG.0", "NESTED_SFG.1"} + assert set( + [ + port.operation.key(port.index, port.operation.name) + for port in precedence_list[2] + ] + ) == {"NESTED_SFG.0", "NESTED_SFG.1"} class TestPrintPrecedence: @@ -629,49 +830,96 @@ class TestPrintPrecedence: captured_output = captured_output.getvalue() - assert captured_output == \ - "-" * 120 + "\n" + \ - "1.1 \t" + str(sfg.find_by_name("IN1")[0]) + "\n" + \ - "1.2 \t" + str(sfg.find_by_name("T1")[0]) + "\n" + \ - "1.3 \t" + str(sfg.find_by_name("T2")[0]) + "\n" + \ - "-" * 120 + "\n" + \ - "2.1 \t" + str(sfg.find_by_name("C0")[0]) + "\n" + \ - "2.2 \t" + str(sfg.find_by_name("A1")[0]) + "\n" + \ - "2.3 \t" + str(sfg.find_by_name("B1")[0]) + "\n" + \ - "2.4 \t" + str(sfg.find_by_name("A2")[0]) + "\n" + \ - "2.5 \t" + str(sfg.find_by_name("B2")[0]) + "\n" + \ - "-" * 120 + "\n" + \ - "3.1 \t" + str(sfg.find_by_name("ADD3")[0]) + "\n" + \ - "3.2 \t" + str(sfg.find_by_name("ADD2")[0]) + "\n" + \ - "-" * 120 + "\n" + \ - "4.1 \t" + str(sfg.find_by_name("ADD1")[0]) + "\n" + \ - "-" * 120 + "\n" + \ - "5.1 \t" + str(sfg.find_by_name("Q1")[0]) + "\n" + \ - "-" * 120 + "\n" + \ - "6.1 \t" + str(sfg.find_by_name("A0")[0]) + "\n" + \ - "-" * 120 + "\n" + \ - "7.1 \t" + str(sfg.find_by_name("ADD4")[0]) + "\n" + \ - "-" * 120 + "\n" + assert ( + captured_output + == "-" * 120 + + "\n" + + "1.1 \t" + + str(sfg.find_by_name("IN1")[0]) + + "\n" + + "1.2 \t" + + str(sfg.find_by_name("T1")[0]) + + "\n" + + "1.3 \t" + + str(sfg.find_by_name("T2")[0]) + + "\n" + + "-" * 120 + + "\n" + + "2.1 \t" + + str(sfg.find_by_name("C0")[0]) + + "\n" + + "2.2 \t" + + str(sfg.find_by_name("A1")[0]) + + "\n" + + "2.3 \t" + + str(sfg.find_by_name("B1")[0]) + + "\n" + + "2.4 \t" + + str(sfg.find_by_name("A2")[0]) + + "\n" + + "2.5 \t" + + str(sfg.find_by_name("B2")[0]) + + "\n" + + "-" * 120 + + "\n" + + "3.1 \t" + + str(sfg.find_by_name("ADD3")[0]) + + "\n" + + "3.2 \t" + + str(sfg.find_by_name("ADD2")[0]) + + "\n" + + "-" * 120 + + "\n" + + "4.1 \t" + + str(sfg.find_by_name("ADD1")[0]) + + "\n" + + "-" * 120 + + "\n" + + "5.1 \t" + + str(sfg.find_by_name("Q1")[0]) + + "\n" + + "-" * 120 + + "\n" + + "6.1 \t" + + str(sfg.find_by_name("A0")[0]) + + "\n" + + "-" * 120 + + "\n" + + "7.1 \t" + + str(sfg.find_by_name("ADD4")[0]) + + "\n" + + "-" * 120 + + "\n" + ) class TestDepends: def test_depends_sfg(self, sfg_two_inputs_two_outputs): - assert set(sfg_two_inputs_two_outputs.inputs_required_for_output(0)) == { - 0, 1} - assert set(sfg_two_inputs_two_outputs.inputs_required_for_output(1)) == { - 0, 1} + assert set( + sfg_two_inputs_two_outputs.inputs_required_for_output(0) + ) == {0, 1} + assert set( + sfg_two_inputs_two_outputs.inputs_required_for_output(1) + ) == {0, 1} - def test_depends_sfg_independent(self, sfg_two_inputs_two_outputs_independent): + def test_depends_sfg_independent( + self, sfg_two_inputs_two_outputs_independent + ): assert set( - sfg_two_inputs_two_outputs_independent.inputs_required_for_output(0)) == {0} + sfg_two_inputs_two_outputs_independent.inputs_required_for_output( + 0 + ) + ) == {0} assert set( - sfg_two_inputs_two_outputs_independent.inputs_required_for_output(1)) == {1} + sfg_two_inputs_two_outputs_independent.inputs_required_for_output( + 1 + ) + ) == {1} class TestConnectExternalSignalsToComponentsSoloComp: - def test_connect_external_signals_to_components_mac(self): - """ Replace a MAC with inner components in an SFG """ + """Replace a MAC with inner components in an SFG""" inp1 = Input("INP1") inp2 = Input("INP2") inp3 = Input("INP3") @@ -704,8 +952,10 @@ class TestConnectExternalSignalsToComponentsSoloComp: assert test_sfg.evaluate(1, 2) == 9 assert not test_sfg.connect_external_signals_to_components() - def test_connect_external_signals_to_components_operation_tree(self, operation_tree): - """ Replaces an SFG with only a operation_tree component with its inner components """ + def test_connect_external_signals_to_components_operation_tree( + self, operation_tree + ): + """Replaces an SFG with only a operation_tree component with its inner components""" sfg1 = SFG(outputs=[Output(operation_tree)]) out1 = Output(None, "OUT1") out1.input(0).connect(sfg1.outputs[0], "S1") @@ -715,8 +965,10 @@ class TestConnectExternalSignalsToComponentsSoloComp: assert test_sfg.evaluate_output(0, []) == 5 assert not test_sfg.connect_external_signals_to_components() - def test_connect_external_signals_to_components_large_operation_tree(self, large_operation_tree): - """ Replaces an SFG with only a large_operation_tree component with its inner components """ + def test_connect_external_signals_to_components_large_operation_tree( + self, large_operation_tree + ): + """Replaces an SFG with only a large_operation_tree component with its inner components""" sfg1 = SFG(outputs=[Output(large_operation_tree)]) out1 = Output(None, "OUT1") out1.input(0).connect(sfg1.outputs[0], "S1") @@ -728,9 +980,10 @@ class TestConnectExternalSignalsToComponentsSoloComp: class TestConnectExternalSignalsToComponentsMultipleComp: - - def test_connect_external_signals_to_components_operation_tree(self, operation_tree): - """ Replaces a operation_tree in an SFG with other components """ + def test_connect_external_signals_to_components_operation_tree( + self, operation_tree + ): + """Replaces a operation_tree in an SFG with other components""" sfg1 = SFG(outputs=[Output(operation_tree)]) inp1 = Input("INP1") @@ -752,8 +1005,10 @@ class TestConnectExternalSignalsToComponentsMultipleComp: assert test_sfg.evaluate(1, 2) == 8 assert not test_sfg.connect_external_signals_to_components() - def test_connect_external_signals_to_components_large_operation_tree(self, large_operation_tree): - """ Replaces a large_operation_tree in an SFG with other components """ + def test_connect_external_signals_to_components_large_operation_tree( + self, large_operation_tree + ): + """Replaces a large_operation_tree in an SFG with other components""" sfg1 = SFG(outputs=[Output(large_operation_tree)]) inp1 = Input("INP1") @@ -775,7 +1030,7 @@ class TestConnectExternalSignalsToComponentsMultipleComp: assert not test_sfg.connect_external_signals_to_components() def create_sfg(self, op_tree): - """ Create a simple SFG with either operation_tree or large_operation_tree """ + """Create a simple SFG with either operation_tree or large_operation_tree""" sfg1 = SFG(outputs=[Output(op_tree)]) inp1 = Input("INP1") @@ -792,8 +1047,10 @@ class TestConnectExternalSignalsToComponentsMultipleComp: return SFG(inputs=[inp1, inp2], outputs=[out1]) - def test_connect_external_signals_to_components_many_op(self, large_operation_tree): - """ Replaces an sfg component in a larger SFG with several component operations """ + def test_connect_external_signals_to_components_many_op( + self, large_operation_tree + ): + """Replaces an sfg component in a larger SFG with several component operations""" inp1 = Input("INP1") inp2 = Input("INP2") inp3 = Input("INP3") @@ -823,43 +1080,98 @@ class TestConnectExternalSignalsToComponentsMultipleComp: class TestTopologicalOrderOperations: def test_feedback_sfg(self, sfg_simple_filter): - topological_order = sfg_simple_filter.get_operations_topological_order() + topological_order = ( + sfg_simple_filter.get_operations_topological_order() + ) assert [comp.name for comp in topological_order] == [ - "IN1", "ADD1", "T1", "CMUL1", "OUT1"] - - def test_multiple_independent_inputs(self, sfg_two_inputs_two_outputs_independent): - topological_order = sfg_two_inputs_two_outputs_independent.get_operations_topological_order() + "IN1", + "ADD1", + "T1", + "CMUL1", + "OUT1", + ] + + def test_multiple_independent_inputs( + self, sfg_two_inputs_two_outputs_independent + ): + topological_order = ( + sfg_two_inputs_two_outputs_independent.get_operations_topological_order() + ) assert [comp.name for comp in topological_order] == [ - "IN1", "OUT1", "IN2", "C1", "ADD1", "OUT2"] + "IN1", + "OUT1", + "IN2", + "C1", + "ADD1", + "OUT2", + ] def test_complex_graph(self, precedence_sfg_delays): - topological_order = precedence_sfg_delays.get_operations_topological_order() + topological_order = ( + precedence_sfg_delays.get_operations_topological_order() + ) - assert [comp.name for comp in topological_order] == \ - ['IN1', 'C0', 'ADD1', 'Q1', 'A0', 'T1', 'B1', 'A1', - 'T2', 'B2', 'ADD2', 'A2', 'ADD3', 'ADD4', 'OUT1'] + assert [comp.name for comp in topological_order] == [ + "IN1", + "C0", + "ADD1", + "Q1", + "A0", + "T1", + "B1", + "A1", + "T2", + "B2", + "ADD2", + "A2", + "ADD3", + "ADD4", + "OUT1", + ] class TestRemove: def test_remove_single_input_outputs(self, sfg_simple_filter): new_sfg = sfg_simple_filter.remove_operation("cmul1") - assert set(op.name for op in sfg_simple_filter.find_by_name( - "T1")[0].subsequent_operations) == {"CMUL1", "OUT1"} - assert set(op.name for op in new_sfg.find_by_name("T1")[ - 0].subsequent_operations) == {"ADD1", "OUT1"} + assert set( + op.name + for op in sfg_simple_filter.find_by_name("T1")[ + 0 + ].subsequent_operations + ) == {"CMUL1", "OUT1"} + assert set( + op.name + for op in new_sfg.find_by_name("T1")[0].subsequent_operations + ) == {"ADD1", "OUT1"} - assert set(op.name for op in sfg_simple_filter.find_by_name( - "ADD1")[0].preceding_operations) == {"CMUL1", "IN1"} - assert set(op.name for op in new_sfg.find_by_name( - "ADD1")[0].preceding_operations) == {"T1", "IN1"} + assert set( + op.name + for op in sfg_simple_filter.find_by_name("ADD1")[ + 0 + ].preceding_operations + ) == {"CMUL1", "IN1"} + assert set( + op.name + for op in new_sfg.find_by_name("ADD1")[0].preceding_operations + ) == {"T1", "IN1"} assert "S1" in set( - [sig.name for sig in sfg_simple_filter.find_by_name("T1")[0].output(0).signals]) + [ + sig.name + for sig in sfg_simple_filter.find_by_name("T1")[0] + .output(0) + .signals + ] + ) assert "S2" in set( - [sig.name for sig in new_sfg.find_by_name("T1")[0].output(0).signals]) + [ + sig.name + for sig in new_sfg.find_by_name("T1")[0].output(0).signals + ] + ) def test_remove_multiple_inputs_outputs(self, butterfly_operation_tree): out1 = Output(butterfly_operation_tree.output(0), "OUT1") @@ -872,10 +1184,12 @@ class TestRemove: assert sfg.find_by_name("bfly3")[0].output(0).signal_count == 1 assert new_sfg.find_by_name("bfly3")[0].output(0).signal_count == 1 - sfg_dest_0 = sfg.find_by_name( - "bfly3")[0].output(0).signals[0].destination - new_sfg_dest_0 = new_sfg.find_by_name( - "bfly3")[0].output(0).signals[0].destination + sfg_dest_0 = ( + sfg.find_by_name("bfly3")[0].output(0).signals[0].destination + ) + new_sfg_dest_0 = ( + new_sfg.find_by_name("bfly3")[0].output(0).signals[0].destination + ) assert sfg_dest_0.index == 0 assert new_sfg_dest_0.index == 0 @@ -885,10 +1199,12 @@ class TestRemove: assert sfg.find_by_name("bfly3")[0].output(1).signal_count == 1 assert new_sfg.find_by_name("bfly3")[0].output(1).signal_count == 1 - sfg_dest_1 = sfg.find_by_name( - "bfly3")[0].output(1).signals[0].destination - new_sfg_dest_1 = new_sfg.find_by_name( - "bfly3")[0].output(1).signals[0].destination + sfg_dest_1 = ( + sfg.find_by_name("bfly3")[0].output(1).signals[0].destination + ) + new_sfg_dest_1 = ( + new_sfg.find_by_name("bfly3")[0].output(1).signals[0].destination + ) assert sfg_dest_1.index == 1 assert new_sfg_dest_1.index == 1 @@ -899,8 +1215,9 @@ class TestRemove: assert new_sfg.find_by_name("bfly1")[0].input(0).signal_count == 1 sfg_source_0 = sfg.find_by_name("bfly1")[0].input(0).signals[0].source - new_sfg_source_0 = new_sfg.find_by_name( - "bfly1")[0].input(0).signals[0].source + new_sfg_source_0 = ( + new_sfg.find_by_name("bfly1")[0].input(0).signals[0].source + ) assert sfg_source_0.index == 0 assert new_sfg_source_0.index == 0 @@ -908,8 +1225,9 @@ class TestRemove: assert new_sfg_source_0.operation.name == "bfly3" sfg_source_1 = sfg.find_by_name("bfly1")[0].input(1).signals[0].source - new_sfg_source_1 = new_sfg.find_by_name( - "bfly1")[0].input(1).signals[0].source + new_sfg_source_1 = ( + new_sfg.find_by_name("bfly1")[0].input(1).signals[0].source + ) assert sfg_source_1.index == 1 assert new_sfg_source_1.index == 1 @@ -927,8 +1245,9 @@ class TestSaveLoadSFG: def get_path(self, existing=False): path_ = "".join(random.choices(string.ascii_uppercase, k=4)) + ".py" while path.exists(path_) if not existing else not path.exists(path_): - path_ = "".join(random.choices( - string.ascii_uppercase, k=4)) + ".py" + path_ = ( + "".join(random.choices(string.ascii_uppercase, k=4)) + ".py" + ) return path_ @@ -992,7 +1311,8 @@ class TestSaveLoadSFG: precedence_sfg_registers_and_constants_, _ = python_to_sfg(path_) assert str(precedence_sfg_delays_and_constants) == str( - precedence_sfg_registers_and_constants_) + precedence_sfg_registers_and_constants_ + ) remove(path_) @@ -1004,54 +1324,76 @@ class TestSaveLoadSFG: class TestGetComponentsOfType: def test_get_no_operations_of_type(self, sfg_two_inputs_two_outputs): - assert [op.name for op in sfg_two_inputs_two_outputs.find_by_type_name(Multiplication.type_name())] \ - == [] + assert [ + op.name + for op in sfg_two_inputs_two_outputs.find_by_type_name( + Multiplication.type_name() + ) + ] == [] def test_get_multple_operations_of_type(self, sfg_two_inputs_two_outputs): - assert [op.name for op in sfg_two_inputs_two_outputs.find_by_type_name(Addition.type_name())] \ - == ["ADD1", "ADD2"] - - assert [op.name for op in sfg_two_inputs_two_outputs.find_by_type_name(Input.type_name())] \ - == ["IN1", "IN2"] - - assert [op.name for op in sfg_two_inputs_two_outputs.find_by_type_name(Output.type_name())] \ - == ["OUT1", "OUT2"] + assert [ + op.name + for op in sfg_two_inputs_two_outputs.find_by_type_name( + Addition.type_name() + ) + ] == ["ADD1", "ADD2"] + + assert [ + op.name + for op in sfg_two_inputs_two_outputs.find_by_type_name( + Input.type_name() + ) + ] == ["IN1", "IN2"] + + assert [ + op.name + for op in sfg_two_inputs_two_outputs.find_by_type_name( + Output.type_name() + ) + ] == ["OUT1", "OUT2"] class TestPrecedenceGraph: def test_precedence_graph(self, sfg_simple_filter): - res = 'digraph {\n\trankdir=LR\n\tsubgraph cluster_0 ' \ - '{\n\t\tlabel=N1\n\t\t"in1.0" [label=in1]\n\t\t"t1.0" [label=t1]' \ - '\n\t}\n\tsubgraph cluster_1 {\n\t\tlabel=N2\n\t\t"cmul1.0" ' \ - '[label=cmul1]\n\t}\n\tsubgraph cluster_2 ' \ - '{\n\t\tlabel=N3\n\t\t"add1.0" [label=add1]\n\t}\n\t"in1.0" ' \ - '-> add1\n\tadd1 [label=add1 shape=square]\n\tin1 -> "in1.0"' \ - '\n\tin1 [label=in1 shape=square]\n\t"t1.0" -> cmul1\n\tcmul1 ' \ - '[label=cmul1 shape=square]\n\t"t1.0" -> out1\n\tout1 ' \ - '[label=out1 shape=square]\n\tt1Out -> "t1.0"\n\tt1Out ' \ - '[label=t1 shape=square]\n\t"cmul1.0" -> add1\n\tadd1 ' \ - '[label=add1 shape=square]\n\tcmul1 -> "cmul1.0"\n\tcmul1 ' \ - '[label=cmul1 shape=square]\n\t"add1.0" -> t1In\n\tt1In ' \ - '[label=t1 shape=square]\n\tadd1 -> "add1.0"\n\tadd1 ' \ - '[label=add1 shape=square]\n}' + res = ( + "digraph {\n\trankdir=LR\n\tsubgraph cluster_0 " + '{\n\t\tlabel=N1\n\t\t"in1.0" [label=in1]\n\t\t"t1.0" [label=t1]' + '\n\t}\n\tsubgraph cluster_1 {\n\t\tlabel=N2\n\t\t"cmul1.0" ' + "[label=cmul1]\n\t}\n\tsubgraph cluster_2 " + '{\n\t\tlabel=N3\n\t\t"add1.0" [label=add1]\n\t}\n\t"in1.0" ' + '-> add1\n\tadd1 [label=add1 shape=square]\n\tin1 -> "in1.0"' + '\n\tin1 [label=in1 shape=square]\n\t"t1.0" -> cmul1\n\tcmul1 ' + '[label=cmul1 shape=square]\n\t"t1.0" -> out1\n\tout1 ' + '[label=out1 shape=square]\n\tt1Out -> "t1.0"\n\tt1Out ' + '[label=t1 shape=square]\n\t"cmul1.0" -> add1\n\tadd1 ' + '[label=add1 shape=square]\n\tcmul1 -> "cmul1.0"\n\tcmul1 ' + '[label=cmul1 shape=square]\n\t"add1.0" -> t1In\n\tt1In ' + '[label=t1 shape=square]\n\tadd1 -> "add1.0"\n\tadd1 ' + "[label=add1 shape=square]\n}" + ) assert sfg_simple_filter.precedence_graph().source == res class TestSFGGraph: def test_sfg(self, sfg_simple_filter): - res = 'digraph {\n\trankdir=LR\n\tin1\n\tin1 -> ' \ - 'add1\n\tout1\n\tt1 -> out1\n\tadd1\n\tcmul1 -> ' \ - 'add1\n\tcmul1\n\tadd1 -> t1\n\tt1 [shape=square]\n\tt1 ' \ - '-> cmul1\n}' + res = ( + "digraph {\n\trankdir=LR\n\tin1\n\tin1 -> " + "add1\n\tout1\n\tt1 -> out1\n\tadd1\n\tcmul1 -> " + "add1\n\tcmul1\n\tadd1 -> t1\n\tt1 [shape=square]\n\tt1 " + "-> cmul1\n}" + ) assert sfg_simple_filter.sfg().source == res def test_sfg_show_id(self, sfg_simple_filter): - res = 'digraph {\n\trankdir=LR\n\tin1\n\tin1 -> add1 ' \ - '[label=s1]\n\tout1\n\tt1 -> out1 [label=s2]\n\tadd1' \ - '\n\tcmul1 -> add1 [label=s3]\n\tcmul1\n\tadd1 -> t1 ' \ - '[label=s4]\n\tt1 [shape=square]\n\tt1 -> cmul1 [label=s5]\n}' + res = ( + "digraph {\n\trankdir=LR\n\tin1\n\tin1 -> add1 " + "[label=s1]\n\tout1\n\tt1 -> out1 [label=s2]\n\tadd1" + "\n\tcmul1 -> add1 [label=s3]\n\tcmul1\n\tadd1 -> t1 " + "[label=s4]\n\tt1 [shape=square]\n\tt1 -> cmul1 [label=s5]\n}" + ) assert sfg_simple_filter.sfg(show_id=True).source == res diff --git a/test/test_signal.py b/test/test_signal.py index 3a681b321e995586bbf30d7ab1f984e475ef6169..295cbb79476ee210f4de6e0dfc0b1c1e1cf08416 100644 --- a/test/test_signal.py +++ b/test/test_signal.py @@ -61,6 +61,7 @@ def test_signal_creation_and_disconnction_and_connection_changing(): assert s.source is out_port assert s.destination is in_port + class Bits: def test_pos_int(self, signal): signal.bits = 10 @@ -76,7 +77,7 @@ class Bits: def test_bits_complex(self, signal): with pytest.raises(Exception): - signal.bits = (2+4j) + signal.bits = 2 + 4j def test_bits_float(self, signal): with pytest.raises(Exception): diff --git a/test/test_simulation.py b/test/test_simulation.py index b5c46721e79544a1675eae010bacf18eb28319a1..65d3b5522c28ed557670950f57db81f413b85d84 100644 --- a/test/test_simulation.py +++ b/test/test_simulation.py @@ -1,14 +1,16 @@ -import pytest import numpy as np +import pytest -from b_asic import SFG, Output, Simulation +from b_asic import Simulation class TestRunFor: def test_with_lambdas_as_input(self, sfg_two_inputs_two_outputs): - simulation = Simulation(sfg_two_inputs_two_outputs, [lambda n: n + 3, lambda n: 1 + n * 2]) + simulation = Simulation( + sfg_two_inputs_two_outputs, [lambda n: n + 3, lambda n: 1 + n * 2] + ) - output = simulation.run_for(101, save_results = True) + output = simulation.run_for(101, save_results=True) assert output[0] == 304 assert output[1] == 505 @@ -46,10 +48,10 @@ class TestRunFor: def test_with_numpy_arrays_as_input(self, sfg_two_inputs_two_outputs): input0 = np.array([5, 9, 25, -5, 7]) - input1 = np.array([7, 3, 3, 54, 2]) + input1 = np.array([7, 3, 3, 54, 2]) simulation = Simulation(sfg_two_inputs_two_outputs, [input0, input1]) - output = simulation.run_for(5, save_results = True) + output = simulation.run_for(5, save_results=True) assert output[0] == 9 assert output[1] == 11 @@ -94,7 +96,7 @@ class TestRunFor: def test_with_numpy_array_overflow(self, sfg_two_inputs_two_outputs): input0 = np.array([5, 9, 25, -5, 7]) - input1 = np.array([7, 3, 3, 54, 2]) + input1 = np.array([7, 3, 3, 54, 2]) simulation = Simulation(sfg_two_inputs_two_outputs, [input0, input1]) simulation.run_for(5) with pytest.raises(IndexError): @@ -102,7 +104,7 @@ class TestRunFor: def test_run_whole_numpy_array(self, sfg_two_inputs_two_outputs): input0 = np.array([5, 9, 25, -5, 7]) - input1 = np.array([7, 3, 3, 54, 2]) + input1 = np.array([7, 3, 3, 54, 2]) simulation = Simulation(sfg_two_inputs_two_outputs, [input0, input1]) simulation.run() assert len(simulation.results["0"]) == 5 @@ -113,7 +115,7 @@ class TestRunFor: def test_delay(self, sfg_delay): simulation = Simulation(sfg_delay) simulation.set_input(0, [5, -2, 25, -6, 7, 0]) - simulation.run_for(6, save_results = True) + simulation.run_for(6, save_results=True) assert simulation.results["0"][0] == 0 assert simulation.results["0"][1] == 5 @@ -123,30 +125,44 @@ class TestRunFor: assert simulation.results["0"][5] == 7 def test_find_result_key(self, precedence_sfg_delays): - sim = Simulation(precedence_sfg_delays, [[0, 4, 542, 42, 31.314, 534.123, -453415, 5431]]) + sim = Simulation( + precedence_sfg_delays, + [[0, 4, 542, 42, 31.314, 534.123, -453415, 5431]], + ) sim.run() - assert sim.results[precedence_sfg_delays.find_result_keys_by_name("ADD2")[0]][4] == 31220 - assert sim.results[precedence_sfg_delays.find_result_keys_by_name("A1")[0]][2] == 80 + assert ( + sim.results[ + precedence_sfg_delays.find_result_keys_by_name("ADD2")[0] + ][4] + == 31220 + ) + assert ( + sim.results[ + precedence_sfg_delays.find_result_keys_by_name("A1")[0] + ][2] + == 80 + ) + class TestRun: def test_save_results(self, sfg_two_inputs_two_outputs): simulation = Simulation(sfg_two_inputs_two_outputs, [2, 3]) assert not simulation.results - simulation.run_for(10, save_results = False) + simulation.run_for(10, save_results=False) assert not simulation.results simulation.run_for(10) assert len(simulation.results["0"]) == 10 assert len(simulation.results["1"]) == 10 - simulation.run_for(10, save_results = True) + simulation.run_for(10, save_results=True) assert len(simulation.results["0"]) == 20 assert len(simulation.results["1"]) == 20 - simulation.run_for(10, save_results = False) + simulation.run_for(10, save_results=False) assert len(simulation.results["0"]) == 20 assert len(simulation.results["1"]) == 20 - simulation.run_for(13, save_results = True) + simulation.run_for(13, save_results=True) assert len(simulation.results["0"]) == 33 assert len(simulation.results["1"]) == 33 - simulation.step(save_results = False) + simulation.step(save_results=False) assert len(simulation.results["0"]) == 33 assert len(simulation.results["1"]) == 33 simulation.step() @@ -168,7 +184,7 @@ class TestRun: def test_accumulator(self, sfg_accumulator): data_in = np.array([5, -2, 25, -6, 7, 0]) - reset = np.array([0, 0, 0, 1, 0, 0]) + reset = np.array([0, 0, 0, 1, 0, 0]) simulation = Simulation(sfg_accumulator, [data_in, reset]) output0 = simulation.step() output1 = simulation.step() @@ -187,13 +203,26 @@ class TestRun: data_in = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] simulation = Simulation(sfg_simple_accumulator, [data_in]) simulation.run() - assert list(simulation.results["0"]) == [0, 1, 3, 6, 10, 15, 21, 28, 36, 45] + assert list(simulation.results["0"]) == [ + 0, + 1, + 3, + 6, + 10, + 15, + 21, + 28, + 36, + 45, + ] def test_simple_filter(self, sfg_simple_filter): input0 = np.array([1, 2, 3, 4, 5]) simulation = Simulation(sfg_simple_filter, [input0]) - simulation.run_for(len(input0), save_results = True) - assert all(simulation.results["0"] == np.array([0, 1.0, 2.5, 4.25, 6.125])) + simulation.run_for(len(input0), save_results=True) + assert all( + simulation.results["0"] == np.array([0, 1.0, 2.5, 4.25, 6.125]) + ) def test_custom_operation(self, sfg_custom_operation): simulation = Simulation(sfg_custom_operation, [lambda n: n + 1])