Search in sources :

Example 1 with ScheduleWindow

use of org.osate.contribution.sei.arinc653.ScheduleWindow in project osate2 by osate.

the class FlowLatencyAnalysisSwitch method mapComponentInstance.

private void mapComponentInstance(final EndToEndFlowInstance etef, final FlowElementInstance flowElementInstance, LatencyReportEntry entry) {
    ComponentInstance componentInstance;
    final boolean hasLatency = flowElementInstance instanceof FlowSpecificationInstance || flowElementInstance instanceof ConnectionInstance || flowElementInstance instanceof EndToEndFlowInstance || latencyCats.contains(((ComponentInstance) flowElementInstance).getCategory());
    final RealRange expected = hasLatency ? PropertyUtils.getScaledRange(org.osate.aadl2.contrib.communication.CommunicationProperties::getLatency, flowElementInstance, TimeUnits.MS).orElse(RealRange.ZEROED) : RealRange.ZEROED;
    if (flowElementInstance instanceof FlowSpecificationInstance) {
        componentInstance = flowElementInstance.getComponentInstance();
    } else {
        componentInstance = (ComponentInstance) flowElementInstance;
    }
    FeatureInstance incomingConnectionFI = FlowLatencyUtil.getIncomingConnectionFeatureInstance(etef, flowElementInstance);
    /**
     * Get all the relevant properties.
     */
    double period = periodCats.contains(componentInstance.getCategory()) ? PropertyUtils.getScaled(TimingProperties::getPeriod, componentInstance, TimeUnits.MS).orElse(0.0) : 0.0;
    double deadline = deadlineCats.contains(componentInstance.getCategory()) ? PropertyUtils.getScaled(TimingProperties::getDeadline, componentInstance, TimeUnits.MS).orElse(0.0) : 0.0;
    boolean isAssignedDeadline = isAssignedDeadline(componentInstance);
    final boolean isThreadOrDevice = InstanceModelUtil.isThread(componentInstance) || InstanceModelUtil.isDevice(componentInstance) || InstanceModelUtil.isAbstract(componentInstance);
    final boolean isPeriodic = period > 0 && (isThreadOrDevice ? (!InstanceModelUtil.isSporadicComponent(componentInstance) && !InstanceModelUtil.isTimedComponent(componentInstance) && !InstanceModelUtil.isAperiodicComponent(componentInstance)) : true);
    final RealRange responseTime = getResponseTimeInMilliSec(flowElementInstance, componentInstance, isPeriodic);
    final RealRange executionTime = getExecutionTimeInMilliSec(flowElementInstance, componentInstance, isPeriodic);
    /**
     * The component is periodic. Therefore it will sample its input unless we have an immediate connection or delayed connection
     */
    boolean checkLastImmediate = false;
    if (isPeriodic) {
        // we have a periodic component that samples
        if (incomingConnectionFI != null) {
            // it is not the first component in the ETEF. We need to add sampling latency
            if (incomingConnectionFI.getCategory() == FeatureCategory.DATA_PORT || incomingConnectionFI.getCategory() == FeatureCategory.ABSTRACT_FEATURE) {
                // sampling incoming data
                // period is set, and if thread, abstract, or device needs to be dispatched as periodic
                // We sample only data ports. Event and event data ports have queuing latency
                LatencyContributorComponent samplingLatencyContributor = new LatencyContributorComponent(componentInstance, flowElementInstance, report.isMajorFrameDelay());
                samplingLatencyContributor.setSamplingPeriod(period);
                if ((InstanceModelUtil.isThread(componentInstance) || InstanceModelUtil.isDevice(componentInstance)) && !hasAssignedPropertyValue(componentInstance, "Dispatch_Protocol")) {
                    samplingLatencyContributor.reportInfo("Assume Periodic dispatch because period is set");
                }
                if (FlowLatencyUtil.isPreviousConnectionDelayed(etef, flowElementInstance)) {
                    samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.DELAYED);
                    samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.DELAYED);
                } else if (FlowLatencyUtil.isPreviousConnectionImmediate(etef, flowElementInstance)) {
                    // the cumulative does not exceed the deadline of the last.
                    if (!FlowLatencyUtil.isNextConnectionImmediate(etef, flowElementInstance)) {
                        checkLastImmediate = true;
                    }
                } else {
                    // sampled. We may under sample
                    ComponentInstance prevComp = FlowLatencyUtil.getPreviousComponent(etef, flowElementInstance);
                    double prevPeriod = prevComp != null ? PropertyUtils.getScaled(TimingProperties::getPeriod, prevComp, TimeUnits.MS).orElse(0.0) : 0;
                    if (period > 0 && prevPeriod > 0 && period % prevPeriod == 0.0) {
                        samplingLatencyContributor.setSamplingPeriod(prevPeriod);
                    } else {
                        samplingLatencyContributor.setSamplingPeriod(period);
                    }
                    samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.SAMPLED);
                    samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.SAMPLED);
                }
                entry.addContributor(samplingLatencyContributor);
            } else {
            // queuing latency handled later
            // do nothing here
            }
        } else {
            // The periodic component is the first component in the ETEF
            // record fact that first element is periodic so we can process synchronous behavior correctly
            LatencyContributorComponent samplingLatencyContributor = new LatencyContributorComponent(componentInstance, flowElementInstance, report.isMajorFrameDelay());
            samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.FIRST_PERIODIC);
            samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.FIRST_PERIODIC);
            entry.addContributor(samplingLatencyContributor);
        }
    } else {
        // the component is not executing periodically
        if (entry.getContributors().isEmpty()) {
            // insert first partition sampling for the aperiodic case. For other partitions it is inserted by connection processing
            ComponentInstance firstPartition = FlowLatencyUtil.getPartition(componentInstance);
            if (firstPartition != null) {
                double partitionLatency = FlowLatencyUtil.getPartitionPeriod(firstPartition);
                List<ScheduleWindow> schedule = FlowLatencyUtil.getModuleSchedule(firstPartition);
                double partitionDuration = FlowLatencyUtil.getPartitionDuration(firstPartition, schedule);
                LatencyContributorComponent platencyContributor = new LatencyContributorComponent(firstPartition, flowElementInstance, report.isMajorFrameDelay());
                if (!FlowLatencyUtil.isInSchedule(firstPartition, schedule)) {
                    platencyContributor.reportWarning("Partition not found in ARINC653 schedule of processor " + FlowLatencyUtil.getModule(firstPartition).getName());
                }
                if (partitionDuration > 0) {
                    platencyContributor.setSamplingPeriod(partitionLatency);
                    double frameOffset = FlowLatencyUtil.getPartitionFrameOffset(firstPartition, schedule);
                    platencyContributor.setPartitionOffset(frameOffset);
                    platencyContributor.setPartitionDuration(partitionDuration);
                    platencyContributor.setWorstCaseMethod(LatencyContributorMethod.PARTITION_SCHEDULE);
                    platencyContributor.setBestCaseMethod(LatencyContributorMethod.PARTITION_SCHEDULE);
                    entry.addContributor(platencyContributor);
                } else {
                    platencyContributor.setSamplingPeriod(partitionLatency);
                    platencyContributor.setWorstCaseMethod(LatencyContributorMethod.PARTITION_FRAME);
                    platencyContributor.setBestCaseMethod(LatencyContributorMethod.PARTITION_FRAME);
                    entry.addContributor(platencyContributor);
                }
            }
        }
    }
    /**
     * Selection of the worst case value, generic case.
     */
    LatencyContributorMethod bestmethod;
    LatencyContributorMethod worstmethod;
    double worstCaseValue = 0.0;
    double bestCaseValue = 0.0;
    worstmethod = LatencyContributorMethod.UNKNOWN;
    LatencyContributorComponent processingLatencyContributor = new LatencyContributorComponent(componentInstance, flowElementInstance, report.isMajorFrameDelay());
    if (responseTime.getMaximum() != 0.0) {
        worstCaseValue = responseTime.getMaximum();
        worstmethod = LatencyContributorMethod.RESPONSE_TIME;
    } else if (executionTime.getMaximum() != 0.0) {
        if (!report.isWorstCaseDeadline()) {
            // Use execution time for worst-case if preferences specify not deadline or no deadline is specified
            worstCaseValue = executionTime.getMaximum();
            worstmethod = LatencyContributorMethod.PROCESSING_TIME;
        } else if (!isAssignedDeadline) {
            worstCaseValue = executionTime.getMaximum();
            worstmethod = LatencyContributorMethod.PROCESSING_TIME;
            processingLatencyContributor.reportInfo("Using execution time as deadline was not set");
        }
    }
    if ((worstCaseValue == 0.0) && isAssignedDeadline && report.isWorstCaseDeadline()) {
        // use deadline if no execution time and deadline was explicitly assigned
        worstCaseValue = deadline;
        worstmethod = LatencyContributorMethod.DEADLINE;
    }
    if ((worstCaseValue == 0.0) && (expected.getMaximum() != 0.0)) {
        // use flow latency if neither deadline nor execution time
        worstCaseValue = expected.getMaximum();
        worstmethod = LatencyContributorMethod.SPECIFIED;
    } else if (worstCaseValue == 0.0 && deadline != 0.0) {
        // if no flow spec value then use default deadline == period
        worstCaseValue = deadline;
        worstmethod = LatencyContributorMethod.DEADLINE;
        processingLatencyContributor.reportInfo("Using deadline as execution time was not set");
    }
    /**
     * Selection of the best case value, generic cases.
     */
    bestmethod = LatencyContributorMethod.UNKNOWN;
    if (responseTime.getMinimum() != 0.0) {
        bestCaseValue = responseTime.getMinimum();
        bestmethod = LatencyContributorMethod.RESPONSE_TIME;
    } else if (executionTime.getMinimum() != 0.0) {
        bestCaseValue = executionTime.getMinimum();
        bestmethod = LatencyContributorMethod.PROCESSING_TIME;
    }
    if ((bestCaseValue == 0.0) && (expected.getMinimum() != 0.0)) {
        bestCaseValue = expected.getMinimum();
        bestmethod = LatencyContributorMethod.SPECIFIED;
    }
    // take into account queuing delay
    if (incomingConnectionFI != null) {
        double qs = 0;
        LatencyContributorComponent ql = new LatencyContributorComponent(componentInstance, flowElementInstance, report.isMajorFrameDelay());
        if (hasAssignedPropertyValue(incomingConnectionFI, org.osate.xtext.aadl2.properties.util.CommunicationProperties.QUEUE_SIZE)) {
            qs = CommunicationProperties.getQueueSize(incomingConnectionFI).orElse(0);
        } else if (incomingConnectionFI.getCategory() == FeatureCategory.DATA_PORT && isThreadOrDevice && (InstanceModelUtil.isSporadicComponent(componentInstance) || InstanceModelUtil.isTimedComponent(componentInstance) || InstanceModelUtil.isAperiodicComponent(componentInstance))) {
            // treat data port as a port of queue size 1 when not a sampling thread
            qs = 1;
            ql.reportInfo("Data port as queue size 1 for sporadic, aperiodic, timed dispatch");
        }
        if (qs != 0) {
            // take into account queuing delay on event and event data ports.
            double dl = 0.0;
            if (InstanceModelUtil.isSporadicComponent(componentInstance) || InstanceModelUtil.isPeriodicComponent(componentInstance)) {
                dl = period;
                ql.reportInfo("Sporadic or periodic has period delay per queue element");
            } else {
                dl = worstCaseValue;
            }
            double queuingDelay = qs * dl;
            ql.setMaximum(queuingDelay);
            if (report.isBestcaseEmptyQueue()) {
                ql.setMinimum(0.0);
                ql.reportInfo("Assume best case empty queue");
            } else {
                double mindl = (InstanceModelUtil.isSporadicComponent(componentInstance) || InstanceModelUtil.isPeriodicComponent(componentInstance) ? period : bestCaseValue);
                ql.setMinimum(qs * mindl);
                ql.reportInfo("Assume best case full queue");
            }
            ql.setWorstCaseMethod(LatencyContributorMethod.QUEUED);
            ql.setBestCaseMethod(LatencyContributorMethod.QUEUED);
            entry.addContributor(ql);
        }
    }
    processingLatencyContributor.setWorstCaseMethod(worstmethod);
    processingLatencyContributor.setBestCaseMethod(bestmethod);
    processingLatencyContributor.setMaximum(worstCaseValue);
    processingLatencyContributor.setMinimum(bestCaseValue);
    processingLatencyContributor.setExpectedMaximum(expected.getMaximum());
    processingLatencyContributor.setExpectedMinimum(expected.getMinimum());
    if (checkLastImmediate && deadline > 0.0) {
        processingLatencyContributor.setImmediateDeadline(deadline);
    }
    processingLatencyContributor.checkConsistency();
    entry.addContributor(processingLatencyContributor);
}
Also used : ConnectionInstance(org.osate.aadl2.instance.ConnectionInstance) RealRange(org.osate.pluginsupport.properties.RealRange) CommunicationProperties(org.osate.aadl2.contrib.communication.CommunicationProperties) FeatureInstance(org.osate.aadl2.instance.FeatureInstance) LatencyContributorMethod(org.osate.analysis.flows.model.LatencyContributor.LatencyContributorMethod) FlowSpecificationInstance(org.osate.aadl2.instance.FlowSpecificationInstance) ScheduleWindow(org.osate.contribution.sei.arinc653.ScheduleWindow) ComponentInstance(org.osate.aadl2.instance.ComponentInstance) LatencyContributorComponent(org.osate.analysis.flows.model.LatencyContributorComponent) EndToEndFlowInstance(org.osate.aadl2.instance.EndToEndFlowInstance) TimingProperties(org.osate.aadl2.contrib.timing.TimingProperties)

Example 2 with ScheduleWindow

use of org.osate.contribution.sei.arinc653.ScheduleWindow in project osate2 by osate.

the class FlowLatencyUtil method getModuleSchedule.

public static List<ScheduleWindow> getModuleSchedule(final ComponentInstance partition) {
    if (partition == null) {
        return null;
    } else {
        final ComponentInstance module = getModule(partition);
        if (module == null) {
            return null;
        } else {
            final ComponentCategory moduleCategory = module.getCategory();
            if (moduleCategory == ComponentCategory.PROCESSOR || moduleCategory == ComponentCategory.VIRTUAL_PROCESSOR || moduleCategory == ComponentCategory.ABSTRACT) {
                /* Only keep those windows that have a partition specified */
                final List<ScheduleWindow> windows = Arinc653.getModuleSchedule(module).orElse(Collections.emptyList());
                windows.removeIf(sw -> !sw.getPartition().isPresent());
                return windows;
            } else {
                return Collections.emptyList();
            }
        }
    }
}
Also used : ScheduleWindow(org.osate.contribution.sei.arinc653.ScheduleWindow) ComponentInstance(org.osate.aadl2.instance.ComponentInstance) ComponentCategory(org.osate.aadl2.ComponentCategory)

Example 3 with ScheduleWindow

use of org.osate.contribution.sei.arinc653.ScheduleWindow in project osate2 by osate.

the class FlowLatencyAnalysisSwitch method mapConnectionInstance.

private void mapConnectionInstance(final EndToEndFlowInstance etef, final FlowElementInstance flowElementInstance, LatencyReportEntry entry) {
    ConnectionInstance connectionInstance = (ConnectionInstance) flowElementInstance;
    final RealRange expected = PropertyUtils.getScaledRange(org.osate.aadl2.contrib.communication.CommunicationProperties::getLatency, flowElementInstance, TimeUnits.MS).orElse(RealRange.ZEROED);
    ComponentInstance componentInstanceSource = InstanceModelUtil.getRelatedComponentSource(connectionInstance);
    ComponentInstance componentInstanceDestination = InstanceModelUtil.getRelatedComponentDestination(connectionInstance);
    ComponentInstance srcHW = InstanceModelUtil.getHardwareComponent(componentInstanceSource);
    ComponentInstance dstHW = InstanceModelUtil.getHardwareComponent(componentInstanceDestination);
    ComponentInstance srcPartition = FlowLatencyUtil.getPartition(componentInstanceSource);
    ComponentInstance dstPartition = FlowLatencyUtil.getPartition(componentInstanceDestination);
    // if we exit a partition then we may have I/O Delay until the end of the partition window or the end of the major frame
    if (srcPartition != null && srcPartition != dstPartition) {
        double partitionLatency = FlowLatencyUtil.getPartitionPeriod(srcPartition);
        List<ScheduleWindow> schedule = FlowLatencyUtil.getModuleSchedule(srcPartition);
        double partitionDuration = FlowLatencyUtil.getPartitionDuration(srcPartition, schedule);
        if (partitionDuration > 0) {
            LatencyContributor ioLatencyContributor = new LatencyContributorComponent(srcPartition, flowElementInstance, report.isMajorFrameDelay());
            if (!FlowLatencyUtil.isInSchedule(srcPartition, schedule)) {
                ioLatencyContributor.reportWarning("Partition not found in ARINC653 schedule of processor " + FlowLatencyUtil.getModule(srcPartition).getName());
            }
            ioLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.PARTITION_OUTPUT);
            ioLatencyContributor.setBestCaseMethod(LatencyContributorMethod.PARTITION_OUTPUT);
            if (partitionLatency == 0) {
                ioLatencyContributor.setSamplingPeriod(partitionDuration);
                ioLatencyContributor.reportInfo("No partition period/rate. Using partition duration");
            } else {
                ioLatencyContributor.setSamplingPeriod(partitionLatency);
            }
            double frameOffset = FlowLatencyUtil.getPartitionFrameOffset(srcPartition, schedule);
            ioLatencyContributor.setPartitionOffset(frameOffset);
            ioLatencyContributor.setPartitionDuration(partitionDuration);
            entry.addContributor(ioLatencyContributor);
        }
    }
    // now we deal with communication latency
    LatencyContributor latencyContributor = new LatencyContributorConnection(connectionInstance, report.isMajorFrameDelay());
    processActualConnectionBindingsSampling(connectionInstance, latencyContributor);
    ComponentClassifier relatedConnectionData = (ComponentClassifier) FlowLatencyUtil.getConnectionData(connectionInstance);
    processActualConnectionBindingsTransmission(connectionInstance, relatedConnectionData == null ? 0.0 : AadlContribUtils.getDataSize(relatedConnectionData, SizeUnits.BYTES), latencyContributor);
    if (expected.getMaximum() > 0) {
        latencyContributor.setWorstCaseMethod(LatencyContributorMethod.SPECIFIED);
        latencyContributor.setExpectedMaximum(expected.getMaximum());
    }
    if (expected.getMinimum() > 0) {
        latencyContributor.setBestCaseMethod(LatencyContributorMethod.SPECIFIED);
        latencyContributor.setExpectedMinimum(expected.getMinimum());
    }
    if (latencyContributor.getSubContributors().isEmpty()) {
        if (expected.getMaximum() > 0) {
            latencyContributor.setMaximum(expected.getMaximum());
        }
        if (expected.getMinimum() > 0) {
            latencyContributor.setMinimum(expected.getMinimum());
        }
    } else {
        latencyContributor.reportInfo("Adding latency subtotal from protocols and hardware - shown with ()");
    }
    // set synchronous if on same processor
    if (srcHW != null && dstHW != null) {
        // we have two hardware components. One or both could be a device
        ComponentInstance srcTime = (ComponentInstance) TimingProperties.getReferenceTime(srcHW).orElse(null);
        ComponentInstance dstTime = (ComponentInstance) TimingProperties.getReferenceTime(dstHW).orElse(null);
        if (srcHW == dstHW) {
            latencyContributor.setSynchronous();
        } else if (srcTime != null && dstTime != null) {
            if (srcTime == dstTime) {
                latencyContributor.setSynchronous();
            } else {
                latencyContributor.setAsynchronous();
            }
        } else {
            latencyContributor.setSyncUnknown();
        }
    } else {
        // set synchronous if in same partition. This may be the case if the partitions are not bound yet to a processor
        if (dstPartition != null && srcPartition != null) {
            if (srcPartition == dstPartition) {
                latencyContributor.setSynchronous();
            } else {
                // no else part: partitions are unbound so we want to have both a sync and async analysis
                latencyContributor.setSyncUnknown();
            }
        }
    }
    entry.addContributor(latencyContributor);
    if (dstPartition != null && srcPartition != dstPartition) {
        // add partition latency if the destination is a partition and it is different from the source partition (or null)
        double partitionLatency = FlowLatencyUtil.getPartitionPeriod(dstPartition);
        List<ScheduleWindow> schedule = FlowLatencyUtil.getModuleSchedule(dstPartition);
        double partitionDuration = FlowLatencyUtil.getPartitionDuration(dstPartition, schedule);
        LatencyContributorComponent platencyContributor = new LatencyContributorComponent(dstPartition, flowElementInstance, report.isMajorFrameDelay());
        if (!FlowLatencyUtil.isInSchedule(dstPartition, schedule)) {
            platencyContributor.reportWarning("Partition not found in ARINC653 schedule of processor " + FlowLatencyUtil.getModule(dstPartition).getName());
        }
        if (partitionDuration > 0) {
            double frameOffset = FlowLatencyUtil.getPartitionFrameOffset(dstPartition, schedule);
            platencyContributor.setPartitionOffset(frameOffset);
            if (partitionLatency == 0) {
                platencyContributor.setSamplingPeriod(partitionDuration);
                platencyContributor.reportInfo("No partition period. Using partition duration");
            } else {
                platencyContributor.setSamplingPeriod(partitionLatency);
            }
            platencyContributor.setPartitionDuration(partitionDuration);
            platencyContributor.setWorstCaseMethod(LatencyContributorMethod.PARTITION_SCHEDULE);
            platencyContributor.setBestCaseMethod(LatencyContributorMethod.PARTITION_SCHEDULE);
            entry.addContributor(platencyContributor);
        } else {
            platencyContributor.setSamplingPeriod(partitionLatency);
            platencyContributor.setWorstCaseMethod(LatencyContributorMethod.PARTITION_FRAME);
            platencyContributor.setBestCaseMethod(LatencyContributorMethod.PARTITION_FRAME);
            entry.addContributor(platencyContributor);
        }
    }
}
Also used : ConnectionInstance(org.osate.aadl2.instance.ConnectionInstance) ComponentClassifier(org.osate.aadl2.ComponentClassifier) RealRange(org.osate.pluginsupport.properties.RealRange) LatencyContributor(org.osate.analysis.flows.model.LatencyContributor) ScheduleWindow(org.osate.contribution.sei.arinc653.ScheduleWindow) LatencyContributorConnection(org.osate.analysis.flows.model.LatencyContributorConnection) ComponentInstance(org.osate.aadl2.instance.ComponentInstance) LatencyContributorComponent(org.osate.analysis.flows.model.LatencyContributorComponent)

Aggregations

ComponentInstance (org.osate.aadl2.instance.ComponentInstance)3 ScheduleWindow (org.osate.contribution.sei.arinc653.ScheduleWindow)3 ConnectionInstance (org.osate.aadl2.instance.ConnectionInstance)2 LatencyContributorComponent (org.osate.analysis.flows.model.LatencyContributorComponent)2 RealRange (org.osate.pluginsupport.properties.RealRange)2 ComponentCategory (org.osate.aadl2.ComponentCategory)1 ComponentClassifier (org.osate.aadl2.ComponentClassifier)1 CommunicationProperties (org.osate.aadl2.contrib.communication.CommunicationProperties)1 TimingProperties (org.osate.aadl2.contrib.timing.TimingProperties)1 EndToEndFlowInstance (org.osate.aadl2.instance.EndToEndFlowInstance)1 FeatureInstance (org.osate.aadl2.instance.FeatureInstance)1 FlowSpecificationInstance (org.osate.aadl2.instance.FlowSpecificationInstance)1 LatencyContributor (org.osate.analysis.flows.model.LatencyContributor)1 LatencyContributorMethod (org.osate.analysis.flows.model.LatencyContributor.LatencyContributorMethod)1 LatencyContributorConnection (org.osate.analysis.flows.model.LatencyContributorConnection)1