diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py index 0eeefb19e32c24794fca090578c5d25a5fd2e432..61449fc3e5cf87167ddfbd2203eb8eb2d3f03978 100644 --- a/b_asic/signal_flow_graph.py +++ b/b_asic/signal_flow_graph.py @@ -234,29 +234,30 @@ class SFG(AbstractOperation): results[self.key(index, prefix)] = value return value - def replace_sfg_with_inner_components(self) -> bool: - """ Replace this SFG with its component operations if itself is a component of another SFG. This SFG becomes unconnected - to the SFG it is a component off. Returns True if succesful, False otherwise. """ + def connect_external_signals_to_components(self) -> bool: + """ Connects any external signals to this SFG's internal operations. This SFG becomes unconnected to the SFG + it is a component off, causing it to become invalid afterwards. Returns True if succesful, False otherwise. """ if len(self.inputs) != len(self.input_operations): raise IndexError(f"Number of inputs does not match the number of input_operations in SFG.") if len(self.outputs) != len(self.output_operations): raise IndexError(f"Number of outputs does not match the number of output_operations SFG.") - - try: - # For each input_signal, connect it to the corresponding operation - for port, input_operation in zip(self.inputs, self.input_operations): - dest = input_operation.output(0).signals[0].destination - dest.clear() - port.signals[0].set_destination(dest) - # For each output_signal, connect it to the corresponding operation - for port, output_operation in zip(self.outputs, self.output_operations): - src = output_operation.input(0).signals[0].source - src.clear() - port.signals[0].set_source(src) - return True - except IndexError: + if len(self.input_signals) == 0: + return False + if len(self.output_signals) == 0: return False + # For each input_signal, connect it to the corresponding operation + for port, input_operation in zip(self.inputs, self.input_operations): + dest = input_operation.output(0).signals[0].destination + dest.clear() + port.signals[0].set_destination(dest) + # For each output_signal, connect it to the corresponding operation + for port, output_operation in zip(self.outputs, self.output_operations): + src = output_operation.input(0).signals[0].source + src.clear() + port.signals[0].set_source(src) + return True + @property def input_operations(self) -> Sequence[Operation]: """Get the internal input operations in the same order as their respective input ports.""" diff --git a/test/test_sfg.py b/test/test_sfg.py index 6a495365e20b316ba294efd201ae68ffde0d53c5..c188351f916ace6803b2f81eae24011e4aa4fcc7 100644 --- a/test/test_sfg.py +++ b/test/test_sfg.py @@ -255,9 +255,9 @@ class TestReplaceComponents: else: assert False -class TestReplaceSfgWithInnerComponentsSoloComp: +class TestConnectExternalSignalsToComponentsSoloComp: - def test_replace_sfg_with_inner_components_mac(self): + def test_connect_external_signals_to_components_mac(self): """ Replace a MAC with inner components in an SFG """ inp1 = Input("INP1") inp2 = Input("INP2") @@ -287,35 +287,35 @@ class TestReplaceSfgWithInnerComponentsSoloComp: test_sfg = SFG(inputs = [inp4, inp5], outputs = [out2]) assert test_sfg.evaluate(1,2) == 9 - mac_sfg.replace_sfg_with_inner_components() + mac_sfg.connect_external_signals_to_components() assert test_sfg.evaluate(1,2) == 9 - assert test_sfg.replace_sfg_with_inner_components() == False + assert test_sfg.connect_external_signals_to_components() == False - def test_replace_sfg_with_inner_components_operation_tree(self, operation_tree): + 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") test_sfg = SFG(outputs = [out1]) assert test_sfg.evaluate_output(0, []) == 5 - sfg1.replace_sfg_with_inner_components() + sfg1.connect_external_signals_to_components() assert test_sfg.evaluate_output(0, []) == 5 - assert test_sfg.replace_sfg_with_inner_components() == False + assert test_sfg.connect_external_signals_to_components() == False - def test_replace_sfg_with_inner_components_large_operation_tree(self, large_operation_tree): + 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") test_sfg = SFG(outputs = [out1]) assert test_sfg.evaluate_output(0, []) == 14 - sfg1.replace_sfg_with_inner_components() + sfg1.connect_external_signals_to_components() assert test_sfg.evaluate_output(0, []) == 14 - assert test_sfg.replace_sfg_with_inner_components() == False + assert test_sfg.connect_external_signals_to_components() == False -class TestReplaceSfgWithInnerComponentsMultipleComp: +class TestConnectExternalSignalsToComponentsMultipleComp: - def test_replace_sfg_with_inner_components_operation_tree(self, operation_tree): + 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)]) @@ -334,11 +334,11 @@ class TestReplaceSfgWithInnerComponentsMultipleComp: test_sfg = SFG(inputs = [inp1, inp2], outputs = [out1]) assert test_sfg.evaluate(1, 2) == 8 - sfg1.replace_sfg_with_inner_components() + sfg1.connect_external_signals_to_components() assert test_sfg.evaluate(1, 2) == 8 - assert test_sfg.replace_sfg_with_inner_components() == False + assert test_sfg.connect_external_signals_to_components() == False - def test_replace_sfg_with_inner_components_large_operation_tree(self, large_operation_tree): + 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)]) @@ -356,9 +356,9 @@ class TestReplaceSfgWithInnerComponentsMultipleComp: test_sfg = SFG(inputs = [inp1, inp2], outputs = [out1]) assert test_sfg.evaluate(1, 2) == 17 - sfg1.replace_sfg_with_inner_components() + sfg1.connect_external_signals_to_components() assert test_sfg.evaluate(1, 2) == 17 - assert test_sfg.replace_sfg_with_inner_components() == False + assert test_sfg.connect_external_signals_to_components() == False def create_sfg(self, op_tree): """ Create a simple SFG with either operation_tree or large_operation_tree """ @@ -378,7 +378,7 @@ class TestReplaceSfgWithInnerComponentsMultipleComp: return SFG(inputs = [inp1, inp2], outputs = [out1]) - def test_replace_sfg_with_inner_components_many_op(self, large_operation_tree): + 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") @@ -401,6 +401,6 @@ class TestReplaceSfgWithInnerComponentsMultipleComp: test_sfg = SFG(inputs = [inp1, inp2, inp3, inp4], outputs = [out1]) assert test_sfg.evaluate(1, 2, 3, 4) == 16 - sfg1.replace_sfg_with_inner_components() + sfg1.connect_external_signals_to_components() assert test_sfg.evaluate(1, 2, 3, 4) == 16 - assert test_sfg.replace_sfg_with_inner_components() == False \ No newline at end of file + assert test_sfg.connect_external_signals_to_components() == False \ No newline at end of file