3.6. Working with Component Patterns
As you use the AADL for multiple projects, you will find it convenient to reuse such things as data sensors, processors, buses, control software, and layered control architecture that have been successfully used in other projects. This is especially true if you are working in a product-line development environment.
In previous examples, we have seen how AADL can be used to define component templates (i.e., component descriptions that are completed and refined later through extension). In some cases, it is desirable to explicitly specify the placeholders (i.e., parameters) and what must be provided within a template. For example, we may have a template that is an abstract component defining a dual redundancy pattern. In that case, a user is expected to supply a single classifier that is used for both redundant instances in the pattern.
In this section, we discuss the use of parameterized component templates patterns. In so doing, we declare incomplete component types and implementations; explicitly specify what is needed to complete a pattern by declaring a prototype as a pattern parameter; and illustrate how such parameterized templates are used.
3.6.1. Component Libraries and Reference Architectures
With the AADL, it is possible to archive components and proven system solutions and reuse them through extension declarations. For this purpose, we suggest partitioning archival elements into two sets: a component library and reference architecture archive. The partitioning separates concerns such that individual, relatively simple elements are archived separately from elements involving a complex component hierarchy.
A component library is a collection of component types and component implementations with limited subcomponents that represent individual elements of a system architecture. These may be generic or runtime specific. For example, in a component library you may have a processor type marine_certified and a collection of implementations that have different processor speeds, manufacturers, and internal memory sizes. Similarly, you may have an abstract type PID_controller and its implementations that represent proportional-integral-derivative control with varying capabilities. The abstract components can be extended into runtime specific components such as a process or thread. For software components, this is the most flexible category for archiving in a library.
In your work, you may have identified a number of proven architecture solutions that have been useful. You can compile these solutions (reference architectures) into an archive that can be used in other projects. These reference architectures define common building blocks and reflect a common topology and are common throughout embedded systems development. Examples include layered control and triple modular redundant reference architectures that can be used for high dependability control avionics as well as space systems. Reference architectures can be defined at different levels of abstraction. Reference architectures can be defined using runtime-specific categories or abstract components and prototypes.
As a third approach to modeling the PBA speed control system, we use a generic component library, a reference architecture archive, prototypes, extensions, refinements, and multiple packages as demonstrations of reusing generic patterns for components and system architectures. We refine the generic components into runtime specific components in developing the PBA-specific architecture.
A library and archive can be developed without using prototypes (i.e., using only extensions and refinements). However, using prototypes makes explicit the elements (e.g., port and subcomponent classifiers) that are being refined.
3.6.2. Establishing a Component Library
Listing 3-23 shows an example generic component library that consists of two packages: interfaces_library and controller_library. In these packages, we define generic application components as abstract components. The packages are partitioned based upon a separation of concerns (e.g., the interfaces_library package has generic representations for sensors, actuators, and user interfaces). Another generic package could include only execution hardware with standard processors, memory, and bus components.
For this example, only the generic_control type has an implementation with subcomponents. In this implementation, prototypes are used in defining the subcomponents. Note that the property Prototype_Substitution_Rule is assigned the value Type_Extension. This allows within refinements, the substitution of classifiers for prototypes that are of the same type or are an extension of the original type used for the prototype. Although most of the components in this library are abstract, runtime-specific categories can be used. For example, in the abstract type declaration for generic_interface, we define a data prototype out_data that is used to define the data type in the declaration of the out data port output.
Listing 3-23. Generic Component Library
--- generic component library --- package interfaces_library public abstract generic_sensor features output: out data port; end generic_sensor; abstract generic_interface prototypes out_data: data; features output: out data port out_data; disengage: out event port; end generic_interface; abstract generic_actuator features input: in data port; end generic_actuator; end interfaces_library; package controller_library public abstract generic_control features input: in data port; output: out data port; set_value: in data port; disengage: in event port; end generic_control; abstract implementation generic_control.partitioned prototypes rd: abstract generic_read_data; cl: abstract generic_control_laws; subcomponents r_data: abstract rd; c_laws: abstract cl; connections DC1: port input -> r_data.input; DC2: port r_data.output -> c_laws.input; DC3: port c_laws.output-> output; EC1: port disengage -> c_laws.disengage; DC4: port set_value -> c_laws.set_value; properties Prototype_Substitution_Rule => Type_Extension; end generic_control.partitioned; abstract generic_read_data features input: in data port; output: out data port; end generic_read_data; abstract implementation generic_read_data.impl end generic_read_data.impl; abstract generic_control_laws features input: in data port; set_value: in data port; disengage: in event port; output: out data port; end generic_control_laws; abstract implementation generic_control_laws.impl end generic_control_laws.impl; end controller_library;
3.6.3. Defining a Reference Architecture
A sample reference architecture archive is shown in Listing 3-24, in which we have defined a generic speed control implementation Complete.basic_speed_control_ref. This implementation uses prototypes. The prototypes used here are abstract. However, prototypes can be runtime specific. In this reference architecture, we use the prototypes as classifier placeholders for the subcomponent classifiers of the implementation. For example, the prototype ssg represents the generic_sensor type that is defined in the package interfaces_library. This prototype is used in the declaration of the subcomponent ss. In using the reference architecture for the PBA, we refine the prototype into a specific runtime implementation. In this case, since we have assigned the value Type_Extension to the Prototype_Substitution_Rule property, we can substitute implementations of extensions of the component type declared in the prototype bindings.
Listing 3-24. Reference Architectures
--- reference architecture archive --- package reference_arch public with interfaces_library, controller_library; system Complete end Complete; system implementation Complete.basic_speed_control_ref prototypes ssg: abstract interfaces_library::generic_sensor; csg: abstract controller_library::generic_control; iug: abstract interfaces_library::generic_interface; acg: abstract interfaces_library::generic_actuator; subcomponents ss: abstract ssg; ac: abstract acg; cs: abstract csg; iu: abstract iug; connections DC1: port ss.output -> cs.input; DC2: port cs.output -> ac.input; DC3: port iu.output -> cs.set_value; EC4: port iu.disengage-> cs.disengage; properties Prototype_Substitution_Rule => Type_Extension; end Complete.basic_speed_control_ref; end reference_arch;
3.6.4. Utilizing a Reference Architecture
We use the reference architecture described in the previous section to define a PBA architecture. This is shown in Listing 3-25, where the first declaration extends the abstract type Complete found in the package reference_arch. In this extension, the system category is substituted for abstract. Similarly, the abstract implementation Complete.basic_speed_control_ref is extended creating the system Complete.PBA_speed_control. In this extension, the prototypes for the subcomponents are bound to an actual classifier using a prototype binding (e.g., acg => device actuator.speed). In our example, we have fixed the classifier to be a device called actuator.speed, which will be used in the subcomponent declaration that refers to the prototype.
In the second part of Listing 3-25, each of the type and some implementation classifiers used in the prototype refinements are extended from the component library. In these extensions, PBA specific refinements can be made. For example, the data classifier speed_data is added to the out port of the sensor in the sensor type and to the input of the process type control. In addition, property associations are added in the control.speed implementation. One is the period for the threads in the process control.speed and the other is a contained property association, assigning a compute execution time to the control laws thread cl within the process control.speed.
Listing 3-25. Using a Reference Architecture
package mysystem public with reference_arch, interfaces_library, controller_library; system Complete extends reference_arch::Complete end Complete; system implementation Complete.PBA_speed_control extends reference_arch::Complete.basic_speed_control_ref (acg => device actuator.speed, ssg => device sensor.speed, csg => process control.speed, iug => device interface.pilot ) end Complete.PBA_speed_control; -- defining subcomponent substitutions --- device sensor extends interfaces_library::generic_sensor features output: refined to out data port speed_data; end sensor; data speed_data end speed_data; device implementation sensor.speed end sensor.speed; device actuator extends interfaces_library::generic_actuator features input: refined to in data port cmd_data; end actuator; data cmd_data end cmd_data; device implementation actuator.speed end actuator.speed; device interface extends interfaces_library::generic_interface end interface; device implementation interface.pilot end interface.pilot; process control extends controller_library::generic_control features input: refined to in data port speed_data; end control; process implementation control.speed extends controller_ library::generic_control.partitioned ( rd => thread read_speed_data.impl, cl => thread speed_control_laws.impl ) properties Period => 20 ms; Compute_Execution_Time => 2ms..5ms applies to cl; end control.speed; thread read_speed_data extends controller_library::generic_read_data end read_speed_data; thread implementation read_speed_data.impl extends controller_ library::generic_read_data.impl end read_speed_data.impl; thread speed_control_laws extends controller_library::generic_control_laws end speed_control_laws; thread implementation speed_control_laws.impl extends controller_library::generic_control_laws.impl end speed_control_laws.impl; end mysystem;