Open jjhugues opened 4 years ago
Proposed resolution:
5.2 (L3) For any dispatch situation, only one subprogram call sequence can be executed in a given mode. Either the thread has one active call sequence in a given mode; or multiple call sequences are defined in one mode, and used separately when dispatching an event on specific in event (data) ports.
The first thing that I notice about the proposed legality rule is that it cannot be checked on the declarative model, but only the instance model. This is due to the fact that there could be contained property associations higher up in the containment hierarchy which impact the dispatch situation.
Agreed. But in the current situation the property is now partially useless.
For the record, I hope to suppress call sequence in v3
For reference, here is the OSATE issue about the implementation of the existing L3: https://github.com/osate/osate2/issues/1564
As discussed in Toulouse, one solution could be to simply propose a different modelling pattern to the user by using subprogram implementations that embed these call sequences
Proposed resolution
or
or
The corresponding model is
subprogram spg
end spg;
subprogram job
end job;
subprogram implementation job.i
calls
cs1: {
job1: subprogram spg;
};
end job.i;
thread t
features
f1: in event port;
f2: in event port;
end t;
thread implementation t.i
properties
compute_entrypoint => classifier (job.i) applies to f1;
compute_entrypoint => classifier (job.i) applies to f2;
end t.i;
A side effect of forbidding multiple call sequences is that initialization, finalization, and compute entrypoint calls sequences also have to follow a more complicated design pattern.
Instead of writing this:
package test_multiple_cep
public
thread t
features
p_in: in event port;
end t;
thread implementation t.impl
calls
cs1: { c11: subprogram s1;};
cs2: { c21: subprogram s2;};
properties
Compute_Entrypoint_Call_Sequence => reference(cs1);
Initialize_Entrypoint_Call_Sequence => reference (cs2);
end t.impl;
subprogram s1
end s1;
subprogram s2
end s2;
end test_multiple_cep;
we now have to write:
package test_multiple_cep2
public
thread t
features
p_in: in event port;
end t;
thread implementation t.impl
subcomponents
s1: subprogram s_exec.impl;
s2: subprogram s_init.impl;
properties
Compute_Entrypoint_Call_Sequence => reference(s1.cs1);
Initialize_Entrypoint_Call_Sequence => reference (s2.cs2);
end t.impl;
subprogram s1
end s1;
subprogram s2
end s2;
subprogram s_init
end s_init;
subprogram implementation s_init.impl
calls
cs2: { c21: subprogram s2;};
end s_init.impl;
subprogram s_exec
end s_exec;
subprogram implementation s_exec.impl
calls
cs1: { c11: subprogram s1;};
end s_exec.impl;
end test_multiple_cep2;
Not sure the latter modelling pattern is better.
You do not take advantage of the call sequence here, you can reduce your example to
thread implementation t.impl
properties
Compute_Entrypoint => classifier (s1);
Initialize_Entrypoint => classifier (s2);
end t.impl;
having a subprogram as subcomponents of a thread does not really make sense, since the OS, the compiler can reorganise the memory in many subtle ways. I remember I changed some text in v3 to relax rules in this area
I see your point. And if I had taken advantage of call sequences, I would probably have defined parameter (or port) connections... which would be cleaner to separate into the different subprogram implementations (s_exec.impl and s_init.impl in my example).
About using subprogram subcomponents, the intent was just to use syntactic sugar to experiment the definition of both initialization and compute entry point call sequences.
but a call sequence at thread level only allows you to list subprograms, not to connect them call sequence in a subprogram are fine. but subprogram subcomponents achieve the same, without the need to a specific syntax. This is the rationale to remove call sequences in v3.
For v2, the intent is to keep them, but better capture the design limits and alternatives
See what I meant by "connections" in the following example.
I was actually going in the direction of the proposed resolution by writing it would be cleaner not to allow this (because the declaration of connections can rapidly become messy):
thread t
features
p_in: in event port;
end t;
thread implementation t.impl
calls
cs1: { c11: subprogram s1; c12: subprogram s2;};
cs2: { c21: subprogram s2; c22: subprogram s2;};
cs3: { c31: subprogram s2; c32: subprogram s2;};
connections
c1: parameter C11.a -> c12.b;
c2: parameter C21.a -> c22.b;
c3: parameter C31.a -> c32.b;
-- for the sake of showing it gets messy:
c4: parameter C11.a -> c31.b; -- weired...
properties
Compute_Entrypoint_Call_Sequence => reference(cs1) applies to p_in;
Compute_Entrypoint_Call_Sequence => reference(cs2);
Initialize_Entrypoint_Call_Sequence => reference (cs3);
end t.impl;
subprogram s1
features
a: out parameter Base_Types::Integer;
end s1;
subprogram s2
features
b: out parameter Base_Types::Integer;
end s2;
BTW, should parameter connection span accross call sequences of different modes? What if my connection c4 was defined between calls of two different sequences (one per mode)?
I am still puzzled by this resolution. Could you please highlight the type of situations/models we need to avoid with 5.2 (L3) and why? Not sure to understand the rationale of the legality rule in the first place.
I do not have the history for this rule.
I guess the intent of L3 is to ensure one can analyze a model and resolve their is only on CS active given a context. The current implementation as a legality rule is forcing this drastic solution.
As pointed out by @joeseibel there is an issue to resolve this on the declarative model.
Turning that into a consistency rule during instantiation might solve this issue: in our examples so far, the CS are bound to entrypoint properties, which disambiguate the situation. Therefore, a consistency rule may say that there can be only one CS unbound CS in a given mode in a thread, if we define an unbound CS as a CS not referred to through one property
The current proposed solution is to consider this is not a big issue and document the limits since we have work-around. This is what has been discussed during the Apr 20 meeting. I understand we may want to revisit this decision.
After further reading, 5.2 (L3) only applies to subprograms, not threads. The check implemented for https://github.com/osate/osate2/issues/1564 is being revisited in https://github.com/osate/osate2/issues/2718
5.2 (L3) Only one subprogram call sequence can apply to a given mode.
This forbids having two call sequences in a model, each bound to a different port using the compute_entrypoint_call_sequence property. See example below
package Call_Sequence_5_2_L3 public
end Call_Sequence_5_2_L3;