Skip to content

Connectors

Connectors connect the interfaces (ports) of components, defining the flow of messages and determining which components communicate with each other. Connectors are defined in the body of the component type. A connector looks like

SOURCE -> TARGET;

where

  • SOURCE is the (qualified) name of the source port (reference)

  • TARGET is the (qualified) name of the target port (reference)

A port can only be targeted by a single connector but can be the source of multiple connectors. For convenience, a connector can define multiple targets. The targets are given as a comma-separated list, which looks like

SOURCE -> TARGET1, TARGET2;

which is a shorthand notation for

SOURCE -> TARGET1; 
SOURCE -> TARGET2; 

Compatibility

Ports can be connected if the direction, timing, and type are compatible.

Direction

The source of a connector can be:

  • an incoming port of the component

  • an outgoing port of a subcomponent

The target of a connector can be

  • an outgoing port of the component

  • an incoming port of a subcomponent

We distinguish three kinds of connectors:

  • A connector from an incoming port of the component to an incoming port of a subcomponent, forwarding messages received by the component to one of its subcomponents. E.g., i -> sub.j; forwards message received by port i to port j of subcomponent sub.

  • A connector from an outgoing port of a subcomponent to an outgoing port of the component, forwarding messages sent by the subcomponent. E.g., sub.o -> p; forwards messages sent by subcomponent sub on port o via port p.

  • A connector from an outgoing port of a subcomponent to an incoming port of a subcomponent (potentially the same subcomponent), sometimes called a hidden connector. E.g., sub1.o -> sub2.i; connects port o of subcomponent sub1 to port i of subcomponent sub2.

Timing

Regarding timing, two rules apply:

  • The source of an event port can be any other timing.
  • The source of a sync port has to be sync as well.

Types

Types are compatible if the target type is a subtype of the source type.

Feedback

If subcomponents form a communication circle along the direction of connectors, then a subcomponent may communicate with itself, either directly or indirectly across other subcomponents. We call this a feedback loop.

In a direct feedback loop, the output of a component is directly connected to the input of the component. The component communicates directly with itself.

sub.o -> sub.i; 

In an indirect feedback loop, the output of a component is connected to the input of the component indirectly across one to multiple subcomponents. The component communicates indirectly with itself.

sub1.o -> sub2.i;
sub2.o -> sub3.i;
sub3.o -> sub1.i;

Communication is abstracted to be instantaneous. However, for the propagation of timing events in feedback loops, we need delay. Otherwise, the component's output at some point in time would depend on itself.

Where the delay happens in the communication circle is irrelevant, just there needs to be some kind of delay.

Delay can be introduced directly on the behavior definition of an atomic component by marking it delayed. Or using explicit delay components that delay all messages they receive. As part of the standard language library, these components are available in all models.

package montiarc.lang;

/**
 * This component delays messages by one unit of time. It does not change the
 * messages' contents. Messages are emitted in the order they are received.
 * The component does not omit any message and does not create new messages.
 */
component Delay<T> {

  port in T i;
  port out T o;

  <<delayed>> automaton {
    initial state S;
    S -> S i / {
      o = i;
    };
  }

}
package montiarc.lang;

/**
 * This component delays messages by one unit of time. It does not change the
 * messages' contents. Messages are emitted in the order they are received.
 * The component does not omit any message and, besides the initial message,
 * does not create new messages. To uphold the contract of synchronous ports,
 * the component emits a message in the first time slice. The parameter iv
 * specifies that message.
 *
 * @param iv the message to be send in the first time slice
 */
component TSDelay<T>(T iv) {

  port sync in T i;
  port sync out T o;

  init {
    o = iv;
  }

  <<delayed>> compute {
    o = i;
  }

}

These delay components can then be added anywhere in the communication circle during decomposition:

Delay<Type> delay;
sub1.o -> sub2.i;
sub2.o -> delay.i; 
delay.o -> sub3.i;
sub3.o -> sub1.i;