private void _propagatePort(CompositeActor container, IOPort currentPort,
Map entityToFiringsPerIteration, Map externalRates,
LinkedList remainingActors, LinkedList pendingActors,
Set clusteredActors, Set clusteredExternalPorts)
throws NotSchedulableException, IllegalActionException {
ComponentEntity currentActor = (ComponentEntity) currentPort
.getContainer();
// First check to make sure that this port is not connected to
// any other output ports on the outside.
// This results in a non-deterministic merge and is illegal.
// Do not do this test for output ports where we are propagating
// inwards instead of outwards.
if (currentPort.isOutput() && (currentPort.getContainer() != container)) {
Iterator connectedPorts = currentPort.deepConnectedPortList()
.iterator();
// Make sure any connected output ports are connected on
// the inside.
while (connectedPorts.hasNext()) {
IOPort connectedPort = (IOPort) connectedPorts.next();
// connectedPort might be connected on the inside to the
// currentPort, which is legal. The container argument
// is always the container of the director, so any port
// that has that container must be connected on the inside.
if (connectedPort.isOutput()
&& (connectedPort.getContainer() != container)) {
throw new NotSchedulableException(currentPort,
connectedPort,
"Output ports drive the same relation. "
+ "This is not legal in SDF.");
} else if (connectedPort.isInput()
&& (connectedPort.getContainer() == container)) {
throw new NotSchedulableException(currentPort,
connectedPort,
"Output port drives the same relation "
+ "as the external input port. "
+ "This is not legal in SDF.");
}
}
}
// Next check to make sure that if this port is an external
// input port, then it does not drive the same relation as some
// other output port or some other external input port.
// This results in a non-deterministic merge and is illegal.
if (currentPort.isInput() && (currentPort.getContainer() == container)) {
Iterator connectedPorts = currentPort.deepInsidePortList()
.iterator();
// Make sure any connected output ports are connected on
// the inside.
while (connectedPorts.hasNext()) {
IOPort connectedPort = (IOPort) connectedPorts.next();
// connectPort might be connected on the inside to the
// currentPort, which is legal. The container argument
// is always the container of the director, so any port
// that has that container must be connected on the inside.
if (connectedPort.isOutput()
&& (connectedPort.getContainer() != container)) {
throw new NotSchedulableException(currentPort,
connectedPort,
"External input port drive the same relation "
+ "as an output port. "
+ "This is not legal in SDF.");
} else if (connectedPort.isInput()
&& (connectedPort.getContainer() == container)) {
throw new NotSchedulableException(currentPort,
connectedPort,
"External input port drives the same relation "
+ "as another external input port. "
+ "This is not legal in SDF.");
}
}
}
Director director = (Director) getContainer();
CompositeActor model = (CompositeActor) director.getContainer();
// Get the rate of this port.
int currentRate;
if (currentActor == model) {
currentRate = 1;
} else {
currentRate = DFUtilities.getRate(currentPort);
}
// Port rates of less than zero are not valid.
if (currentRate < 0) {
throw new NotSchedulableException(currentPort,
"Rate cannot be less than zero. It was: " + currentRate);
}
// Propagate to anything that this port is connected to. For
// external ports, this is anything that is connected on the
// inside. For ports of actors that are being scheduled, this is
// anything that is connected on the outside.
Iterator connectedPorts;
if (currentPort.getContainer() == container) {
// Find all the ports that are deeply connected to
// current port on the inside.
if (_debugging && VERBOSE) {
// Move this inside and avoid FindBugs Dead Local Store
connectedPorts = currentPort.deepInsidePortList().iterator();
_debug("deepInsidePortList of " + currentPort);
while (connectedPorts.hasNext()) {
_debug(connectedPorts.next().toString());
}
}
connectedPorts = currentPort.deepInsidePortList().iterator();
} else {
connectedPorts = currentPort.deepConnectedPortList().iterator();
}
// For every port we are connected to.
while (connectedPorts.hasNext()) {
IOPort connectedPort = (IOPort) connectedPorts.next();
ComponentEntity connectedActor = (ComponentEntity) connectedPort
.getContainer();
if (_debugging && VERBOSE) {
_debug("Propagating " + currentPort + " to "
+ connectedActor.getName());
}
int connectedRate;
if (connectedActor == model) {