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);
}
}
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);
}
}
}
}
}
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);
}
}
}
}
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);
}
}
}
Aggregations