Search in sources :

Example 1 with LatencyContributor

use of org.osate.analysis.flows.model.LatencyContributor in project osate2 by osate.

the class FlowLatencyAnalysisSwitch method processTransmissionTime.

/**
 * add latency sub-contribution due to transmission by bus (or virtual bus)
 * works for an instance object and for a classifier.
 * We determine the transmission latency from the data size and transmission time property.
 * If not present we get it from the latency property.
 * If neither is present and we are a connection or virtual bus we do not add a latency.
 * If we are HW component, we add unknown latency.
 * targetMedium: a connection instance, or the binding target (virtual bus or bus)
 * transmissionDataSize: the size of data to be transmitted.
 * latencyContributor: the place where we add a subcontributor.
 */
private void processTransmissionTime(NamedElement targetMedium, double datasizeinbyte, LatencyContributor latencyContributor, final ConnectionInstance onBehalfOfConnection) {
    // XXX: [Code Coverage] targetMedium cannot be null.
    if (targetMedium != null) {
        final RealRange busLatency = PropertyUtils.getScaledRange(org.osate.aadl2.contrib.communication.CommunicationProperties::getLatency, targetMedium, TimeUnits.MS).orElse(RealRange.ZEROED);
        final RealRange busTransferTime = getTimeToTransferData(targetMedium, datasizeinbyte);
        if (busLatency.getMaximum() == 0 && busTransferTime.getMaximum() == 0) {
            // connection or protocol has nothing to contribute
            return;
        }
        LatencyContributor subContributor = new LatencyContributorComponent(targetMedium, report.isMajorFrameDelay());
        subContributor.setExpectedMaximum(busLatency.getMaximum());
        subContributor.setExpectedMinimum(busLatency.getMinimum());
        if (busTransferTime.getMaximum() > 0) {
            subContributor.setMaximum(busTransferTime.getMaximum());
            subContributor.reportInfo("Using data transfer time");
            if (datasizeinbyte == 0.0) {
                subContributor.reportInfo("Data size = 0. Possibly data type on port missing");
            }
            subContributor.setWorstCaseMethod(LatencyContributorMethod.TRANSMISSION_TIME);
            // Record the latency for use by asynchronous bus waiting times
            if (targetMedium instanceof ComponentInstance) {
                computedMaxTransmissionLatencies.put(new Pair<>((ComponentInstance) targetMedium, onBehalfOfConnection), busTransferTime.getMaximum());
            }
        } else if (busLatency.getMaximum() > 0) {
            subContributor.setMaximum(busLatency.getMaximum());
            subContributor.setWorstCaseMethod(LatencyContributorMethod.SPECIFIED);
            subContributor.reportInfo("Using specified bus latency");
            // Record the latency for use by asynchronous bus waiting times
            if (targetMedium instanceof ComponentInstance) {
                computedMaxTransmissionLatencies.put(new Pair<>((ComponentInstance) targetMedium, onBehalfOfConnection), busTransferTime.getMaximum());
            }
        } else {
            // XXX: [Code Coverage] Only executable if maxBusTransferTime or maxBusLatency is negative.
            subContributor.setWorstCaseMethod(LatencyContributorMethod.UNKNOWN);
        }
        if (busTransferTime.getMinimum() > 0) {
            subContributor.setMinimum(busTransferTime.getMinimum());
            subContributor.setBestCaseMethod(LatencyContributorMethod.TRANSMISSION_TIME);
        } else if (busLatency.getMinimum() > 0) {
            subContributor.setMinimum(busLatency.getMinimum());
            subContributor.setBestCaseMethod(LatencyContributorMethod.SPECIFIED);
        } else {
            // XXX: [Code Coverage] Only executable if minBusTransferTime or minBusLatency is negative.
            subContributor.setBestCaseMethod(LatencyContributorMethod.UNKNOWN);
        }
        latencyContributor.addSubContributor(subContributor);
    }
}
Also used : RealRange(org.osate.pluginsupport.properties.RealRange) ComponentInstance(org.osate.aadl2.instance.ComponentInstance) LatencyContributor(org.osate.analysis.flows.model.LatencyContributor) LatencyContributorComponent(org.osate.analysis.flows.model.LatencyContributorComponent)

Example 2 with LatencyContributor

use of org.osate.analysis.flows.model.LatencyContributor in project osate2 by osate.

the class FlowLatencyAnalysisSwitch method fillInQueuingTimes.

private void fillInQueuingTimes(final SystemInstance system) {
    // Nothing to do if there are no asynchronous buses
    if (!asyncBuses.isEmpty()) {
        // Get all the connections bound to a bus and group them together by the bus they are bound to
        final Map<ComponentInstance, Set<ConnectionInstance>> sortedConnections = sortBoundConnections(system);
        /*
			 * Go through the list of all the asynchronous buses
			 */
        for (final NamedElement ne : asyncBuses) {
            // only proceed if it is a bus instance and not a classifier (from Required_Virtual_Bus_Class)
            if (ne instanceof ComponentInstance) {
                final ComponentInstance bus = (ComponentInstance) ne;
                // Get all the connections bound to that bus
                final Set<ConnectionInstance> boundConnections = sortedConnections.getOrDefault(bus, Collections.emptySet());
                // Get all the transmission times and compute the total
                double totalTime = 0.0;
                final Map<ConnectionInstance, Double> transmissionTimes = new HashMap<>();
                for (final ConnectionInstance ci : boundConnections) {
                    final Double time = computedMaxTransmissionLatencies.getOrDefault(new Pair<ComponentInstance, ConnectionInstance>(bus, ci), 0.0);
                    transmissionTimes.put(ci, time);
                    totalTime += time;
                }
                /*
					 * Go through the list of connections again, and subtract the time associated
					 * with the current connection to find the max waiting time for each connection.
					 * (That each for each connection ci, we will have the sum of all the times
					 * for the _other_ connections bound to same bus. This gives us the max
					 * time that connection ci may have to wait to use the bus.)
					 */
                for (final ConnectionInstance ci : boundConnections) {
                    final Double ciTime = transmissionTimes.get(ci);
                    final double maxWaitingTime = totalTime - ciTime;
                    // Finally we can stick this into the latency contributor
                    final LatencyContributor latencyContributor = connectionsToContributors.get(new Pair<>(bus, ci));
                    final LatencyContributor queuingLatencyContributor = new LatencyContributorComponent(bus, report.isMajorFrameDelay());
                    queuingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.QUEUED);
                    queuingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.QUEUED);
                    queuingLatencyContributor.setMinimum(0.0);
                    if (report.isDisableQueuingLatency()) {
                        // Hide the queuing time
                        queuingLatencyContributor.setMaximum(0.0);
                        queuingLatencyContributor.reportInfo("Ignoring queuing time of " + maxWaitingTime + "ms");
                    } else {
                        // Report the queuing time
                        queuingLatencyContributor.setMaximum(maxWaitingTime);
                    }
                    latencyContributor.addSubContributor(queuingLatencyContributor);
                    // add the sampling latency
                    LatencyContributor samplingLatencyContributor = new LatencyContributorComponent(bus, report.isMajorFrameDelay());
                    samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);
                    samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);
                    samplingLatencyContributor.setSamplingPeriod(0.0);
                    latencyContributor.addSubContributor(samplingLatencyContributor);
                }
            }
        }
    }
}
Also used : ConnectionInstance(org.osate.aadl2.instance.ConnectionInstance) EnumSet(java.util.EnumSet) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) HashMap(java.util.HashMap) LatencyContributor(org.osate.analysis.flows.model.LatencyContributor) ComponentInstance(org.osate.aadl2.instance.ComponentInstance) LatencyContributorComponent(org.osate.analysis.flows.model.LatencyContributorComponent) NamedElement(org.osate.aadl2.NamedElement)

Example 3 with LatencyContributor

use of org.osate.analysis.flows.model.LatencyContributor in project osate2 by osate.

the class FlowLatencyAnalysisSwitch method processSamplingAndQueuingTimes.

/*
	 * boundBusOrRequiredClassifier is a ComponentInstance if it is a bus bound to connection instance, or a
	 * ComponentClassifier if it is a virtual bus required by a connection connnection or vb.
	 *
	 * bindingConnection is the ConnectionInstance that boundBusOrRequiredClassifier is bound to if
	 * boundBusOrRequiredClassifier is a componentInstance. Otherwise it is null.
	 */
private void processSamplingAndQueuingTimes(final NamedElement boundBusOrRequiredClassifier, final ConnectionInstance bindingConnection, final LatencyContributor latencyContributor) {
    // XXX: [Code Coverage] boundBus cannot be null.
    if (boundBusOrRequiredClassifier != null) {
        final ComponentCategory cc = boundBusOrRequiredClassifier instanceof ComponentInstance ? ((ComponentInstance) boundBusOrRequiredClassifier).getCategory() : ((ComponentClassifier) boundBusOrRequiredClassifier).getCategory();
        double period = hasPeriod.contains(cc) ? PropertyUtils.getScaled(TimingProperties::getPeriod, boundBusOrRequiredClassifier, TimeUnits.MS).orElse(0.0) : 0.0;
        if (period > 0) {
            // add sampling latency due to the protocol or bus being periodic
            LatencyContributor samplingLatencyContributor = new LatencyContributorComponent(boundBusOrRequiredClassifier, report.isMajorFrameDelay());
            samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);
            samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);
            samplingLatencyContributor.setSamplingPeriod(period);
            latencyContributor.addSubContributor(samplingLatencyContributor);
            // add queuing latency: always zero in this case
            LatencyContributor queuingLatencyContributor = new LatencyContributorComponent(boundBusOrRequiredClassifier, report.isMajorFrameDelay());
            queuingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.QUEUED);
            queuingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.QUEUED);
            queuingLatencyContributor.setMinimum(0.0);
            queuingLatencyContributor.setMaximum(0.0);
            latencyContributor.addSubContributor(queuingLatencyContributor);
        } else {
            /*
				 * Issue 1148
				 *
				 * if "boundBus" is really a bound component instance, and not a required component classifier,
				 * then we remember the bus as asynchronous. Later in fillInQueuingTimes() we go through this list,
				 * and then find all the connection instances bound to this bus. For each connection,
				 * we compute the sum of the max transmission times of the OTHER connections bound to the bus. This
				 * we set as the worse case queuing time. (Best case is 0.)
				 *
				 * We also remember the bus--connection pair that needs the queuing latency by storing its latency contributor.
				 */
            if (bindingConnection != null) {
                final ComponentInstance boundBus = (ComponentInstance) boundBusOrRequiredClassifier;
                /* Set the bus order and then add it to the ordered set */
                if (!busOrder.containsKey(boundBus)) {
                    busOrder.put(boundBus, nextBusId++);
                    asyncBuses.add(boundBus);
                }
                connectionsToContributors.put(new Pair<>(boundBus, bindingConnection), latencyContributor);
            }
        }
    }
}
Also used : ComponentInstance(org.osate.aadl2.instance.ComponentInstance) LatencyContributor(org.osate.analysis.flows.model.LatencyContributor) LatencyContributorComponent(org.osate.analysis.flows.model.LatencyContributorComponent) ComponentCategory(org.osate.aadl2.ComponentCategory) TimingProperties(org.osate.aadl2.contrib.timing.TimingProperties)

Example 4 with LatencyContributor

use of org.osate.analysis.flows.model.LatencyContributor 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)4 LatencyContributor (org.osate.analysis.flows.model.LatencyContributor)4 LatencyContributorComponent (org.osate.analysis.flows.model.LatencyContributorComponent)4 ConnectionInstance (org.osate.aadl2.instance.ConnectionInstance)2 RealRange (org.osate.pluginsupport.properties.RealRange)2 EnumSet (java.util.EnumSet)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1 ComponentCategory (org.osate.aadl2.ComponentCategory)1 ComponentClassifier (org.osate.aadl2.ComponentClassifier)1 NamedElement (org.osate.aadl2.NamedElement)1 TimingProperties (org.osate.aadl2.contrib.timing.TimingProperties)1 LatencyContributorConnection (org.osate.analysis.flows.model.LatencyContributorConnection)1 ScheduleWindow (org.osate.contribution.sei.arinc653.ScheduleWindow)1