Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection_Pattern ignored when instantiating data access connection #2057

Closed
philip-alldredge opened this issue Nov 11, 2019 · 7 comments · Fixed by #2071
Closed

Connection_Pattern ignored when instantiating data access connection #2057

philip-alldredge opened this issue Nov 11, 2019 · 7 comments · Fixed by #2071
Assignees
Milestone

Comments

@philip-alldredge
Copy link
Collaborator

Summary

In some case when wrapping a process which contains connections with a connection pattern, the Connection_Pattern is ignored and the appropriate connection instances are not created.

Expected and Current Behavior

In such a case, I expect the connection instances to be similar. Currently when instantiating the top level system, the Connection_Pattern property value does not seem to be handled properly. This results in fewer connection instances and a validation error.

When instantiating the process, the expected connection instances are created. When instantiating the system that contains the process, the connections are not created.

Steps to Reproduce

  1. Instantiate top.impl
  2. Receive error: Too few indices for connection destination for d1 -> threads[1].da1. Instance model does not contain appropriate connection instances.
package connection_pattern_issue
public
	with Base_Types;

	system top
	end top;

	system implementation top.impl
		subcomponents
			p1: process process1.impl;
	end top.impl;

	process process1
	end process1;

	process implementation process1.impl
		subcomponents
			d1: data Base_Types::Boolean;
			threads: thread thread1[8];
		connections
			process1_impl_new_connection: data access d1 -> threads.da1 { Connection_Pattern => ((One_To_All)); };
	end process1.impl;

	thread thread1
		features
			da1: requires data access Base_Types::Boolean;
	end thread1;
end connection_pattern_issue;

Environment

  • OSATE Version: 2.6.0 and 2.4.0
  • Operating System: Windows 10
@AaronGreenhouse
Copy link
Contributor

Modified the example a little to contrast the behavior with port connections:

package connection_pattern_issue
public
    system top
    end top;

    system implementation top.impl
        subcomponents
            p1: process process1.impl;
    end top.impl;

    process process1
    end process1;

    process implementation process1.impl
        subcomponents
            d1: data ;
            src: thread thread0;
            threads: thread thread1[8];
    	connections
    		xxx: port src.op -> threads.ep { Connection_Pattern => ((One_To_All)); };
            process1_impl_new_connection: data access d1 -> threads.da1 { Connection_Pattern => ((One_To_All)); };
    end process1.impl;

	thread thread0
		features
			op: out event port;
	end thread0;

    thread thread1
        features
            da1: requires data access;
            ep: in event port;
    end thread1;
end connection_pattern_issue;

When top.impl is instantiated, the port connection is properly expanded across the thread array and there are 8 connection instances corresponding to it. The data access connection is not expanded and instead has the above referenced error message.

Screen Shot 2019-11-19 at 2.38.05 PM.png

@AaronGreenhouse
Copy link
Contributor

The problem seems to be that InstantiateModel.processConnections() uses Aadl2InstanceUtil.isOpposite() to determine if the connection flows in the opposite direction, and this returns the wrong result for access connections.

	public static boolean isOpposite(ConnectionInstance conni) {
		ConnectionReference topref = getTopConnectionReference(conni);
		Connection conn = topref.getConnection();
		ConnectionInstanceEnd srcend = topref.getSource();
		ComponentInstance srcCI = srcend.getContainingComponentInstance();
		Subcomponent srcSub = srcCI.getSubcomponent();
		Context srcelem = conn.getAllSourceContext();
		return srcSub != srcelem;
	}

This returns true for the access connection. If I force the isOpposite flag to be false in InstantiateModel.processConnections() then the connections are expanded correctly.

@AaronGreenhouse
Copy link
Contributor

I have a feeling this won't work with port connections that go from data subcomponents to data ports either.

@AaronGreenhouse
Copy link
Contributor

Works correctly for this case (data component is the destination in the declarative connection), but only accidentally. The isOpposite() check is wrong, but because it always returns true in the case that an end of the connection is component, it gives the correct result.

package data_port_to_data
public
    system top
    end top;

    system implementation top.impl
        subcomponents
            p1: process process1.impl;
    end top.impl;

    process process1
    end process1;

    thread thread1
        features
            dp: in out data port;
    end thread1;

    process implementation process1.impl
        subcomponents
            thr: thread thread1;
            d1: data [8];
    	connections
           yyy: port thr.dp <-> d1 { Connection_Pattern => ((One_To_All)); };
    end process1.impl;
end data_port_to_data;

But flip it aroud, putting the data component as the connection source, and things don't work correctly because isOpposite() still returns true on the source, which is now incorrect.

package data_to_data_port
public
    system top
    end top;

    system implementation top.impl
        subcomponents
            p1: process process1.impl;
    end top.impl;

    process process1
    end process1;

    thread thread1
        features
            dp: in out data port;
    end thread1;

    process implementation process1.impl
        subcomponents
            thr: thread thread1 [8];
            d1: data ;
    	connections
           yyy: port d1 <-> thr.dp { Connection_Pattern => ((One_To_All)); };
    end process1.impl;
end data_to_data_port;

@AaronGreenhouse
Copy link
Contributor

I'm skeptical that isOpposite() works correctly for feature groups as well. Need to try that too.

@AaronGreenhouse
Copy link
Contributor

AaronGreenhouse commented Nov 21, 2019

Changed isOpposite() to

	public static boolean isOpposite(ConnectionInstance conni) {
		final ConnectionReference topref = getTopConnectionReference(conni);
		final Connection conn = topref.getConnection();
		final ConnectionInstanceEnd srcend = topref.getSource();
		if (srcend instanceof ComponentInstance) {
			final Subcomponent srcSub = ((ComponentInstance) srcend).getSubcomponent();
			final ConnectionEnd srcelem = conn.getAllSource();
			return srcSub != srcelem;
		} else { // FeatureInstance
			// XXX: what about ModeTransitionInstance?
			final ComponentInstance srcCI = srcend.getContainingComponentInstance();
			final Subcomponent srcSub = srcCI.getSubcomponent();
			final Context srcelem = conn.getAllSourceContext();
			return srcSub != srcelem;
		}
	}

Seems to have fixed the problem.

@lwrage
Copy link
Contributor

lwrage commented Dec 10, 2019

There is a simpler way: call isReverse() on the connection reference this is true when the connection goes in the connection instance direction is the opposite of the declaration direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants