(1) A subcomponent represents a component contained within another component, i.e., declared within a component implementation. Subcomponents contained in a component implementation may be instantiations of component implementations that contain subcomponents themselves. This results in a component containment hierarchy that ultimately describes the whole actual system as a system instance. Figure 4 provides an illustration of a containment hierarchy using the graphical AADL notation (see Appendix D ). In this example, Sys1 represents a system. The implementation of the system contains subcomponents named C3 and C4. Component C3, a subcomponent in Sys1’s implementation, contains subcomponents named C1 and C2. Component C4, another subcomponent in Sys1’s implementation, contains a second set of subcomponents named C1 and C2. The two subcomponents named C1 and those named C2 do not violate the unique name requirement. They are unique with respect to the local namespace of their containing component’s local namespace.
Figure 4 Component Containment Hierarchy
(2) A subcomponent declaration may resolve required subcomponent access declared in the component type of the subcomponent. For details on required subcomponent access see Section 8.4.
(3) A subcomponent can be declared to apply to specific modes (rather than all modes) defined within the component implementation.
(4) Subcomponents can be refined as part of component implementation extensions. Refinement allows classifier references to be completed, abstract subcomponents to be refined into one of the concrete categories, and subcomponent property values to be associated. The resulting refined subcomponents can be refined themselves.
(5) An array of subcomponents can be declared to represent a set of subcomponents with the same component type. This array may have one or more dimensions.
Syntax
subcomponent ::=
defining_subcomponent_identifier :
component_category
[ unique_component_classifier_reference [prototype_bindings]
| prototype_identifier ]
[ array_dimensions [ array_element_implementation_list ] ]
[ { { subcomponent_property_association
| contained_property_association }+ } ]
[ component_in_modes ] ;
subcomponent_refinement ::=
defining_subcomponent_identifier : refined to
component_category
[ unique_component_classifier_reference [ prototype_bindings ]
| prototype_identifier ]
[ array_dimensions [ array_element_implementation_list ] ]
[ { { subcomponent_property_association
| contained_property_association }+ } ]
[ component_in_modes ] ;
unique_component_classifier_reference ::=
( unique_component_type_reference
| unique_component_implementation_reference )
array_dimensions ::=
{ array_dimension }+
array_dimension ::=
[ [ array_dimension_size ] ]
array_dimension_size ::=
numeral | unique_property_constant_identifier | unique_property_identifier
array_element_implementation_list ::=
( unique_component_implementation_reference [ prototype_bindings ]
{ , unique_component_implementation_reference [ prototype_bindings ] }* )
-- array selection used in contained property association and references
array_selection_identifier ::=
identifier array_selection
array_selection ::=
{ [ selection_range ] }+
selection_range ::=
numeral [ .. numeral ]
NOTES:
The above grammar rules characterize the common syntax for subcomponent of all component categories. The sections defining each of the component categories will specify further restrictions on the syntax.
Naming Rules
(N1) The defining identifier of a subcomponent declaration placed in a component implementation must be unique within the local namespace of the component implementation that contains the subcomponent.
(N2) The defining identifier of a subcomponent refinement must exist as a defining subcomponent identifier in the local namespace of an ancestor component implementation.
(N3) The component type identifier or the component implementation name of a component classifier reference must exist in the package namespace.
(N4) The prototype identifier of a prototype reference must exist in the local name space of the component implementation.
(N5) The prototype referenced by the prototype binding declarations must exist in the local namespace of the component classifier being referenced.
(N6) The modes named in the in modes statement of a subcomponent must refer to modes in the component implementation that contains the subcomponent or its component type. The modes named in the in modes statement of a property association of a subcomponent must refer to modes of the subcomponent, or in the case of a contained property association to modes of the last component in the component path (see Section 11.3).
Legality Rules
(L1) The category of the subcomponent declaration must match the category of its corresponding component classifier reference or its prototype reference, i.e., they must be identical, or in the case of a classifier reference the referenced classifier category may be abstract.
(L2) The component classifier reference of a subcomponent declaration may include prototype bindings for a subset or all of the component classifier prototypes. This represents an unnamed component classifier extension of the referenced classifier.
(L4) The Classifier_Substitution_Rule property specifies the rule to be applied when a refinement supplies a classifier and the original subcomponent declaration already has a component classifier. This property can be applied to individual subcomponents or features, or it can be inherited from classifiers. The following rules are supported:
· Classifier_Match: The component type of the refinement must be identical to the component type of the classifier being refined. If the original declaration specifies a component implementation, then any implementation of that type can replace this original implementation. This is the default rule.
· Type_Extension: Any component classifier whose component type is an extension of the component type of the classifier in the subcomponent being refined is an acceptable substitute.
· Signature_Match: The component type of the refinement must match the signature of the component type of the classifier being refined.
(L5) In the case of a signature match, the component type of the subcomponent being refined must have a subset of the features of the component type in the refinement. The features are compared by name matching; the feature categories and direction (in data port, provides data access, etc.) must be the same and any feature classifier must match according to rules defined for Classifier_Match. In addition, if flow specifications are present in the component type being refined, then the component type of the refinement must have at least the same set of flow specifications. Flow specifications with the same name must have the same source and destination ports.
(L6) The component category and optional component classifier or prototype reference can be followed by a set of array dimensions to define the subcomponent as an array of actual subcomponents.
(L7) The array size specification for the dimensions is optional. In this case the array declaration is considered incomplete. If the size of the array dimension is specified it must be specified for all dimensions in the same declaration.
(L8) When refining a subcomponent array the number of dimensions of the array cannot be changed, but the array size can be specified for each dimension if it was not specified in the subcomponent declaration being refined.
(L9) When the subcomponent is declared as an array with array dimension sizes then a list of component implementations can be supplied, one for each element of the array. Different implementations of the same component type can be chosen. The number of elements in the list must correspond to the number of elements in the component array. In the case of multi-dimensional arrays, the list elements are assigned by incrementing the index of the last dimension first.
(L10) Selecting index ranges in one or more dimensions of an array is only possible if the size of the array for these dimensions is already defined. The index range of a dimension is from 1 to the size of the dimension. Specification of array index ranges is limited to the applies to subclause of contained property associations. Specification of a single array element is limited to the applies to subclause of contained property associations and to the values of reference properties.
(L11) An array element implementation list is valid only if (a) the subcomponent classifier is a component type and (b) all component implementations in the list are implementations of the specified type.
Consistency Rules
(C1)The classifier of a subcomponent cannot recursively contain subcomponents with the same component classifier. In other words, there cannot be a cyclic containment dependency between components.
Standard Properties
Classifier_Substitution_Rule: inherit enumeration (Classifier_Match, Type_Extension, Signature_Match)
Acceptable_Array_Size: list of Size_Range
Semantics
(6) Subcomponents declared in a component implementation are considered to be contained in the component implementation. Contained subcomponents are instantiated when the containing component implementation is instantiated. Thus, the component containment hierarchy describes the hierarchical structure of the actual system.
(7) A component implementation can contain incomplete subcomponent declarations, i.e., subcomponent declarations with no component classifier references, or if the component classifier reference only consists of a component type name for a component type with more than one component implementation. A subcomponent declaration is also incomplete when it consists of the declaration of an array of subcomponents for which the array sizes are not specified. This is particularly useful during early design stages where details may not be known or decided. Such incomplete subcomponent declarations can be refined in component implementation extensions.
(8) A subcomponent declaration can be parameterized by referring to a prototype. In this case the component category and component classifier bound to the prototype is used when the system is instantiated.
(9) A subcomponent declaration can reference a component classifier with prototype bindings. The prototype binding can refer to other classifiers or to a prototype of the component type or implementation that contains the subcomponent. In the latter case, the prototype actual is passed down levels of the component hierarchy and effectively allows the system subcomponents to be configured from a higher level component.
(10) A component classifier reference with prototype bindings that refer to component classifiers effectively is an unnamed extension of the classifier being referenced. In other words, it could have been declared as a component type or component implementation extension with a new defining identifier and this identifier could have been referenced in the subcomponent declaration. Two unnamed component classifier extensions are not considered to be extensions of each other.
(11) The optional component_in_modes subclause specifies the modes in which the subcomponent is active. An component_in_modes in a subcomponent refinement replaces previously specified subsets of modes. A subcomponent or subcomponent refinement without component_in_modes specifies that the subcomponent is active in all modes. The component_in_modes refer to modes of the component implementation that contains the subcomponent or to the modes of its component type. The component_in_modes may map mode identifiers of the containing component to the mode identifiers specified in the requires modes clause of the subcomponent’s component type (see Section 12).
(12) A subcomponent can have property values associated to itself, or a contained property association can be declared for one of the subcomponents in its containment hierarchy, as well as those subcomponents’ features, modes, subprogram call sequences, connections, and flows, or model elements in any annex subclause of a subcomponent (see Section 11.3). Subcomponent refinements may declare property associations – that override the property values declared in the subcomponent being refined. Property associations can have in_modes statements that refer to modes of the component implementation that contains the subcomponent, or in the case of contained property associations also to modes of the last subcomponent named in the path of the applies to (see Section 11.3).
(13) The arrays of subcomponents are used to simplify the declaration of a multiplicity of subcomponents with the same classifier without declaring each of them separately. If a size of a subcomponent array is not known the array is incomplete and is assumed to have one element for the purpose of system instances of incomplete models. A subcomponent array can only be refined by adding array sizes to the dimensions if they are without a size.
(14) All elements of a subcomponent array have the same component classifier, i.e., they are of the same kind. A subcomponent array can also be declared to have the same component type, but its elements vary in their implementation, e.g., to represent variants in an N-Version redundancy pattern.
(15) A property association declared with a subcomponent array applies to each element in the array. Contained property associations declared in the enclosing component implementation can be used to associate different property values to different elements or subsets of the subcomponent array.
Processing Requirements and Permissions
(16) If the subcomponent declaration references a component type and the type has a single implementation then a method of processing (tool) is permitted to generate a complete system instance by choosing the single implementation even if it is not named. If the referenced component type has multiple implementations then the implementation must be explicitly referenced. However, some project may impose design constraints that require modelers to completely specify such classifier references.
Examples
(17) The example illustrates modeling of source text data types as data component types without any implementation details. It illustrates the use of package to group data component type declarations. It illustrates both component classifier references to component types and to component implementations. It illustrates the use of ports as well as required and provided data access, and required subprogram access. In that context it illustrates the ways of resolving required access. The Data Modeling Annex (Annex Document B) provides guidance on how to effectively represent data models of applications in AADL.
package Sampling
public
data Sample
properties
Source_Data_Size => 16 Bytes;
end Sample;
data Sample_Set
properties
Source_Data_Size => 1 MByte;
end Sample_Set;
data implementation Sample_Set.impl
subcomponents
Data_Set: data Sample ;
end Sample_Set.impl;
data Dynamic_Sample_Set extends Sample_Set
end Dynamic_Sample_Set;
data implementation Dynamic_Sample_Set.impl extends Sample_Set.impl
properties
Source_Data_Size => 8 Bytes applies to Data_Set;
end Dynamic_Sample_Set.impl;
end Sampling;
package SamplingTasks
public
with Sampling;
thread Init_Samples
features
OrigSet : requires data access Sampling::Sample_Set;
SampleSet : requires data access Sampling::Sample_Set;
end Init_Samples;
thread Collect_Samples
features
Input_Sample : in event data port Sampling::Sample;
SampleSet : requires data access Sampling::Sample_Set;
Filtering_Routine: requires subprogram access Sample_Subprogram;
end Collect_Samples;
thread implementation Collect_Samples.Batch_Update
properties
Source_Name => ″InSample″ applies to Input_Sample;
end Collect_Samples.Batch_Update;
thread Distribute_Samples
features
SampleSet : requires data access Sampling::Sample_Set;
UpdatedSamples : out event data port Sampling::Sample;
end Distribute_Samples;
process Sample_Manager
features
Input_Sample: in event data port Sampling::Sample;
External_Samples: requires data access Sampling::Sample_Set;
Result_Sample: out event data port Sampling::Sample;
end Sample_Manager;
process implementation Sample_Manager.Slow_Update
subcomponents
Samples: data Sampling::Sample_Set;
Init_Samples : thread Init_Samples;
-- the required access is resolved to a subcomponent declaration
Collect_Samples: thread Collect_Samples.Batch_Update;
Distribute: thread Distribute_Samples;
Sample_Filter: subprogram Sample_Subprogram.Simple;
connections
ISSSConn: data access Samples <-> Init_Samples.SampleSet;
ISOSConn: data access External_Samples <-> Init_Samples.OrigSet;
CSSSConn: data access Samples <-> Collect_Samples.SampleSet;
CSISConn: port Input_Sample -> Collect_Samples.Input_Sample;
DSSConn: data access Samples <-> Distribute.SampleSet;
DUSConn: port Distribute.UpdatedSamples -> Result_Sample;
CSFRConn: subprogram access Sample_Filter <-> Collect_Samples.Filtering_Routine;
end Sample_Manager.Slow_Update;
subprogram Sample_Subprogram
end Sample_Subprogram;
subprogram implementation Sample_Subprogram.Simple
end Sample_Subprogram.Simple;
end SamplingTasks;
(18) This example illustrates the use of arrays in defining a triple redundancy pattern with a voter. The pattern is defined as an abstract component (see Section 4.6) that uses data ports. The connections are defined with a connection pattern property to indicate how the elements of the source array are connected to the destination. Each instance of MyProcess is connected to a separate port of the Voter. Note that the number of replicates could be kept flexible by specifying the array dimension size through a property.
package Redundancy
public
abstract Triple
features
input: in data port;
output: out data port;
end Triple;
abstract implementation Triple.impl
subcomponents
MyProcess: abstract Calculate [3];
MyVoter: abstract Voter;
connections
extinput: port input -> MyProcess.input
{ Connection_Pattern => (( One_To_All )); };
tovoter: port MyProcess.output -> MyVoter.input
{ Connection_Pattern => (( One_To_One )); };
extoutput: port MyVoter.output -> output;
end Triple.impl;
abstract Calculate
features
input: in data port;
output: out data port;
end Calculate;
abstract Voter
features
input: in data port [3];
output: out data port;
end Voter;
end Redundancy;