diff --git a/psymple/ported_objects.py b/psymple/ported_objects.py index dd5fcc8..86ae440 100644 --- a/psymple/ported_objects.py +++ b/psymple/ported_objects.py @@ -627,7 +627,7 @@ def compile(self, prefix_names=False): # We create a compiled output port assg = ParameterAssignment(destination.symbol, source.symbol) compiled.output_ports[destination.name] = CompiledOutputPort( - source, assg + destination, assg ) else: raise WiringError( @@ -703,8 +703,22 @@ def compile(self, prefix_names=False): compiled.internal_variable_assignments[name] = port.assignment compiled.sub_symbol_identifications() + + # Align the dictionary keys with the names of the symbols + # whose assignments the dictionary is storing. + # This has to happen after all the wiring compilation, + # because the wires refer to the child + port name within the child, + # so the child name cannot be part of the dictionary key while + # the wiring is compiled. + compiled.remap_dict_keys() + if prefix_names: + # After this, all variables/parameters appearing everywhere + # are prefixed by the name of the ported object. + # This, however, does not apply to the dictionary keys, + # see above for the reasoning compiled.sub_prefixed_symbols() + return compiled @@ -756,6 +770,19 @@ def sub_prefixed_symbols(self): new_symbol = sym.Symbol(HIERARCHY_SEPARATOR.join([self.name, name])) self.sub_everywhere(old_symbol, new_symbol) + def remap_dict_keys(self): + # Remap dictionary keys to add prefix + for containers in [ + self.input_ports, + self.output_ports, + self.variable_ports, + self.internal_variable_assignments, + self.internal_parameter_assignments + ]: + re_keyed = {content.name : content for name, content in containers.items()} + containers.clear() + containers.update(re_keyed) + def sub_everywhere(self, old_symbol, new_symbol): assert isinstance(old_symbol, sym.Symbol) assert isinstance(new_symbol, sym.Symbol) diff --git a/tests/test_ported.py b/tests/test_ported.py index 575dbd3..8006152 100644 --- a/tests/test_ported.py +++ b/tests/test_ported.py @@ -383,6 +383,24 @@ def test_output_forwarding(self): 2 * sym.Symbol("rabbits"), ) + def test_output_nesting(self): + # TODO: Add checks + A_func = FunctionalPortedObject("func") + A_func.add_input_port(InputPort("X", default_value = 5)) + A_func.add_assignment(ParameterAssignment("Y", "X")) + + A = CompositePortedObject("A") + A.add_child(A_func) + A.add_output_port(OutputPort("Y")) + A.add_directed_wire("func.Y", "Y") + + B = CompositePortedObject("B") + B.add_output_port(OutputPort("BY")) + B.add_child(A) + B.add_directed_wire("A.Y", "BY") + + compiled = B.compile() + def test_parameters(self): fpo = FunctionalPortedObject("double") fpo.add_input_port(InputPort("old")) @@ -423,6 +441,30 @@ def test_parameters(self): sym.Symbol("double.new") * sym.Symbol("rabbits"), ) + def test_key_remapping(self): + # TODO: Add checks + func_1 = FunctionalPortedObject("func_1") + func_1.add_input_port(InputPort("X", default_value = 5)) + func_1.add_assignment(ParameterAssignment("Y", "X")) + + A = CompositePortedObject("A") + A.add_child(func_1) + A.add_input_port(InputPort("X", default_value = 3)) + A.add_output_port(OutputPort("Y")) + A.add_directed_wire("X", "func_1.X") + A.add_directed_wire("func_1.Y", "Y") + + B = CompositePortedObject("B") + B.add_child(A) + B.add_input_port(InputPort("X", default_value = 1)) + B.add_output_port(OutputPort("Y")) + B.add_directed_wire("X", "A.X") + B.add_directed_wire("A.Y", "Y") + + C = CompositePortedObject("C") + C.add_child(B) + + compiled = C.compile() class TestSimulation(unittest.TestCase): def test_no_params(self):