saeaadl / aadlv2.2

SAE AADL core language, version 2.2
1 stars 0 forks source link

Call sequence 5.2 (L3) #45

Open jjhugues opened 4 years ago

jjhugues commented 4 years ago

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

subprogram spg
end spg;

thread t
    features
        f1: in event port;
        f2: in event port;
end t;

thread implementation t.i
    calls
        cs1: { job1: subprogram spg; };
        cs2: { job2: subprogram spg; };
    properties
        compute_entrypoint_call_sequence => reference (cs1) applies to f1;
        compute_entrypoint_call_sequence => reference (cs2) applies to f2;
end t.i;

end Call_Sequence_5_2_L3;

jjhugues commented 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.

joeseibel commented 4 years ago

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.

jjhugues commented 4 years ago

Agreed. But in the current situation the property is now partially useless.

For the record, I hope to suppress call sequence in v3

joeseibel commented 4 years ago

For reference, here is the OSATE issue about the implementation of the existing L3: https://github.com/osate/osate2/issues/1564

yoogx commented 4 years ago

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

jjhugues commented 4 years ago

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;
Etienne13 commented 3 years ago

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.

yoogx commented 3 years ago

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

Etienne13 commented 3 years ago

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.

jjhugues commented 3 years ago

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

Etienne13 commented 3 years ago

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)?

Etienne13 commented 3 years ago

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.

jjhugues commented 3 years ago

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.

jjhugues commented 2 years ago

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