6.4 Specification-Based End-To-End Flow Analysis
The objective of this analysis plug-in is to demonstrate the ability to perform quantitative analysis with precise results on low-fidelity architecture models. The particular use scenario for this plug-in is an avionics display system for which we are trying to determine an upper bound on the arrival rate of certain events. The particular event stream we are interested in is the request for different page content by the pilot by selecting a different page from the multi- function display menu. The request is issued by the pilot pushing a virtual button on the display for the menu entry of interest. The application logic is designed such that a new request can only be issued once the requested page has been shown. Therefore, by determining the minimum latency for changing the page content we can bound the arrival rate of such page requests.
6.4.1 The Display System Model Scenario
We can perform this analysis on a model of the avionics system that only represents subsystems. Figure 37 illustrates the relevant subsystems and the end-to-end flow specification in terms of port group connections and subsystem flow specifications. The end-to-end flow start with the Cockpit display goes through several subsystems to the flight director and returns the resulting new page along the reverse path. We used port groups to indicate that possibly multiple port connections may exist between two subsystems. From a flow specification perspective the details of such connections are irrelevant.

Figure 37: A Subsystem End-To-End Flow
The corresponding textual AADL model is shown below defining the avionics display system implementation that contains the subsystems and the end-to-end flow specification. Note the Latency property on the end-to-end flow.
system implementation Flight_System.impl
subcomponents
Pilot_Display: device Display.MFD;
Pilot_DM: system Display_Manager.impl;
PCM: system Page_Content_Manager.impl;
FM: system Flight_Manager.impl;
FD: system Flight_Director.impl;

connections
menu_cmd_to_DM: data port Pilot_Display.Menu_Cmd_Pushed ->
Pilot_DM.Menu_selection_from_Display;
menu_cmd_to_PCM: event data port Pilot_DM.New_Page_Request_To_PCM ->
PCM.New_Page_Request_From_DM;
menu_cmd_to_FM: event data port PCM.New_Page_Request_To_FM ->
FM.New_Page_Request_From_PCM;
menu_cmd_to_FD: event data port FM.New_Page_Request_To_FD ->
FD.New_Page_Request_From_FM;
page_to_FM: event data port FD.New_Page_Content_To_FM ->
FM.New_Page_Content_from_FD;
page_to_PCM: event data port FM.New_Page_Content_To_PCM ->
PCM.New_Page_Content_from_FM;
page_to_DM: event data port PCM.New_Page_Content_To_DM ->
Pilot_DM.New_Page_Content_from_PCM;
page_to_Display: data port Pilot_DM.New_Page_Image_To_Display ->
Pilot_Display.Page_To_Show;

flows
get_new_page: end to end flow
pilot_Display.Menu_Entry_Selected -> menu_cmd_to_DM ->
Pilot_DM.cmd_request -> menu_cmd_to_PCM ->
PCM.cmd_request -> menu_cmd_to_FM ->
FM.cmd_request -> menu_cmd_to_FD ->
FD.process_page_request -> page_to_FM ->
FM.show_page -> page_to_PCM ->
PCM.show_page -> page_to_DM ->
Pilot_DM.show_page -> page_to_Display ->
Pilot_Display.Show_Page
{ latency => 300 ms; };
end Flight_System.impl;
In this particular design each subsystem is implemented as a partition in a time partitioned system. This means that each partition and the threads contained in its execute once per minor frame, i.e., once per partition period. As a result, each time the flow crosses a partition boundary a frame delay latency is added corresponding to the partition period. To model this fact we introduce a new property that can be associated with systems called Partition_Latency and give it a default value of 50 ms. By assigning a default value we do not have to explicitly specify a partition period value for each subsystem.
property set SEI is
Partition_Latency: Time => 50 ms applies to ( system );
end SEI;
6.4.2 The Partition Latency Analysis
The partition latency analysis operates as follows. It first takes into account that the display device has some latency in processing the button push. This processing is modeled as flow latency in the display device. Then we take into account each time the flow crosses from one partition to another. Finally, the last subcomponent listed in the flow is the display device and we account for the time it takes to refresh the display itself.
The partition latency analysis plug-in is similar to the flow specification validation plug-in. In this case we redefine the caseEndToEndFlow method to process a sequence of flow elements.
First we handle the display device by setting its latency as the initial result value (or to zero if no latency value exists).
public Object caseEndToEndFlow(EndToEndFlow etef) {
EList fel = etef.getFlowElement();
double result = 0;
Subcomponent sc = null;
if (fel.isEmpty()) return DONE;
Iterator it = fel.iterator();
FlowElement fe = (FlowElement)it.next();
sc = fe.getFlowContext();
FlowSpec fefs = fe.getFlowSpec();
IntegerValue fefspv = (IntegerValue) fefs.getSimplePropertyValue(
PredeclaredProperties.LATENCY);
double latency = 0;
if (fefspv != null) {
result = fefspv.getScaledValue(PredeclaredProperties.MICROSEC);
}
Then we are iterating over the remaining flow elements to add any latency due to the connection and the partition crossing latencies. This is done by adding the partition latency property value for every subsequent system subcomponent we encounter.
while (it.hasNext()){
fe = (FlowElement)it.next();
if (fe.isSubcomponentFlowSpecReference()) {
sc = fe.getFlowContext();
pl = (IntegerValue) sc.getSimplePropertyValue(
CheckFlowLatency.partitionLatency);
if (pl != null) {
partlatency = ((IntegerValue) pl).getScaledValue(
PredeclaredProperties.MICROSEC);
result = result + partlatency;
} else {
reportInfo(sc, sc.getComponentType().getCategory().getName() +
" subcomponent has no partiton latency");
}
}
}
The property definition for the partition latency has been initialized in the initPropertyReferences method. This improves the efficiency of the analysis since the property definition does not have to be repeatedly looked up from string names.
protected void initPropertyReferences() {
partitionLatency =
lookupPropertyDefinition("SEI", "Partition_Latency");
}
Once the end-to-end latency is determined it is compared to the latency or expected latency specified for the end-to-end flow.
PropertyValue epv =
etef.getSimplePropertyValue(PredeclaredProperties.LATENCY);
if (epv == null) {
epv = etef.getSimplePropertyValue(
PredeclaredProperties.EXPECTED_LATENCY);
}
if (epv != null) {
double val = ((IntegerValue) epv).getScaledValue(
PredeclaredProperties.MICROSEC);
reportInfo(etef,"Expected end-to-end flow latency is " +
AadlUtil.usValueToMS(val) + " ms");
if (result > val) {
reportError(etef,"End-to-end flow latency " +
AadlUtil.usValueToMS(result) +
" ms exceeds specified latency " +
AadlUtil.usValueToMS(val) + " us");
}
}
6.4.3 Partition Latency Analysis Refinement
The latency calculated in the above plug-in provides a lower bound on the end-to-end latency. This partition latency analysis can be refined in the following way. We can take into account any flow specification latency that may have been specified for each subsystem. If that flow specification latency exceeds the partition latency of the succeeding partition it increases the latency to the next frame. Flow specification latency may be larger than a partition period because the flow within a subsystem may involve multiple threads and the threads may communicate through a delayed connection or the thread executes at a period larger than a partition, thus, spans multiple partition periods.
The high-lighted portions of the code segment shown below accomplish this.
In the first high-lighted section we add any communication latency to the accumulated computational latency.
In the second section we have encountered a partition and we need to determine the latency to be added due to partition. If the partition latency is greater than the computational latency from previous components then the partition latency is added; if the computational latency is larger and the partition latency is non-zero then we round up to the next frame of the partition; and if the partition latency is zero, then we add the computational latency.
In the third high-lighted section we determine the flow specification latency for the current subcomponent.
In the fourth high-lighted section, we determine the computational latency contributed by the current subcomponent as a partition to be passed on for the next subcomponent. The larger of the flow specification latency the partition latency is passed on.
In the fifth high-lighted section we determine the computational latency contributed by the current subcomponent if it is not a partition. In this case the larger of its flow specification latency or partition latency is added to the computational latency from the previous subcomponent.
In the final highlighted section we add any computational latency not accounted for before as the last step of calculating the end-to-end latency.
if (conn != null) {
PropertyValue cpv = conn.getSimplePropertyValue(
PredeclaredProperties.LATENCY);
if (cpv != null) {
double val = ((IntegerValue) cpv).getScaledValue(
PredeclaredProperties.MICROSEC);
prevlatency = prevlatency + val;
}
}
} else {
sc = fe.getFlowContext();
pl = (IntegerValue) sc.getSimplePropertyValue(
CheckFlowLatency.partitionLatency);
partlatency = 0;
if (pl != null) {
partlatency = ((IntegerValue) pl).getScaledValue(
PredeclaredProperties.MICROSEC);
result = result +
(partlatency >= prevlatency ? partlatency :
(partlatency == 0 ? prevlatency :
(((int) prevlatency/partlatency) + 1) * partlatency));
} else {
reportInfo(sc, sc.getComponentType().getCategory().getName() +
" subcomponent has no partiton latency");
}
fefs = fe.getFlowSpec();
fefspv = (IntegerValue) fefs.getSimplePropertyValue(
PredeclaredProperties.LATENCY);
latency = 0;
if (fefspv != null) {
latency = fefspv.getScaledValue(PredeclaredProperties.MICROSEC);
}
if (partlatency != 0) {
prevlatency = (latency > partlatency) ? latency : partlatency;
} else {
prevlatency = prevlatency +
((latency > partlatency) ? latency : partlatency);
}
}
}
/* account for partition feeding a non-partition at the end */
result = result + prevlatency;