// "CONTINUOUS", otherwise, "DISCRETE".
// NOTE: The implicit assumption is that all the receivers
// belonging to the same IO port have the same signal type.
Receiver[][] localReceivers = inPort.getReceivers();
try {
Receiver localReceiver = localReceivers[0][0];
if (localReceiver instanceof StateReceiver) {
_signalTypeMap.setType(inPort, CONTINUOUS);
} else {
_signalTypeMap.setType(inPort, DISCRETE);
}
} catch (ArrayIndexOutOfBoundsException ex) {
throw new IllegalActionException(this, ex,
"The container \"" + container.getFullName()
+ "\" is a \"" + container.getClass().getName()
+ "\", which is not a CT Composite actor, yet "
+ "the port \"" + inPort.getFullName()
+ "\" appears to have no receivers? "
+ "Perhaps the port is not connected?");
}
} else {
// If the container is a CT composite actor,
// examine the "signalType" parameter specified manually
// by model designers, or by the upper level in
// hierarchy during its schedule construction.
// If no such parameter exists, defalut the signal type of
// the input ports to be "CONTINUOUS".
Parameter signalType = (Parameter) inPort
.getAttribute("signalType");
if (signalType != null) {
String type = ((StringToken) signalType.getToken())
.stringValue();
type = type.trim().toUpperCase();
if (type.equals("CONTINUOUS")) {
_signalTypeMap.setType(inPort, CONTINUOUS);
} else if (type.equals("DISCRETE")) {
_signalTypeMap.setType(inPort, DISCRETE);
} else {
throw new IllegalActionException(
inPort,
"Unrecognized signal type. "
+ "It should be a string of "
+ "either \"CONTINUOUS\" or \"DISCRETE\".");
}
} else {
// The default signal type of the input ports of a
// CTCompositeActor is continuous.
// FIXME: This is not accurate. There is a possibility
// that one of the input ports receives a discrete input
// while another input port receives a continuous input.
// FIXME: We may need iterations to solve this problem.
// Because there are only three types: CONTINUOUS, DISCRETE,
// and UNKNONW, where the UNKNOWN is the bottom. Two
// iterations are sufficient to solve the signal type of
// all ports.
_signalTypeMap.setType(inPort, CONTINUOUS);
}
}
// Propagate the signal types of the input ports of the contained
// actors.
_signalTypeMap.propagateTypeInside(inPort);
}
// Iterate all contained actors to classify each actor and
// resolve the signal types of its ports.
Iterator allActors = container.deepEntityList().iterator();
while (allActors.hasNext()) {
Actor a = (Actor) allActors.next();
if (_debugging & _verbose) {
_debug("Examine " + ((Nameable) a).getFullName()
+ " for signal types.");
}
// Now classify actors by their implemented interfaces.
if (a instanceof CompositeActor) {
if (a instanceof CTCompositeActor) {
// the actor is a CT subsystem
// We do not blindly add a CT sub system into the list
// of dynamic actors or the list of waveform generators.
// Instead, we check whether it contains some dynamic
// actors or waveform generators inside.
// The reason is that if a CT subsystem does not contain
// any of the above two actors, it cannot be treated as
// a source actor.
if (((CTCompositeActor) a).containsDynamicActors()) {
dynamicActors.add(a);
}
arithmeticActors.add(a);
ctSubsystems.add(a);
statefulActorSchedule.add(new Firing(a));
if (((CTCompositeActor) a).containsWaveformGenerators()) {
waveformGenerators.add(a);
}
eventGenerators.add(a);
} else {
// The actor is a subsystem but not a CT one,
// it can only be an arithmetic actor or a sink actor.
// We will clarify this actor based on the completely
// resolved signal type of its input and output ports later.
// Right now, we simply save it for future processing.
nonCTSubsystems.add(a);
}
} else {
// the actor is an atomic actor
if (a instanceof CTStatefulActor) {
statefulActorSchedule.add(new Firing(a));
}
if (a instanceof CTWaveformGenerator) {
waveformGenerators.add(a);
} else if (a instanceof CTEventGenerator) {
eventGenerators.add(a);
} else if (a instanceof CTDynamicActor) {
dynamicActors.add(a);
} else {
arithmeticActors.add(a);
}
}
// Now resolve signal types to find the continuous and
// discrete clusters of actors.
if (a instanceof SequenceActor) {
// Set all ports of a sequence actor with signal type "DISCRETE"
if (predecessorList(a).isEmpty()) {
throw new NotSchedulableException(((Nameable) a).getName()
+ " is a SequenceActor, which cannot be a"
+ " source actor in the CT domain.");
}
Iterator ports = ((Entity) a).portList().iterator();
while (ports.hasNext()) {
IOPort port = (IOPort) ports.next();
_signalTypeMap.setType(port, DISCRETE);
if (port.isOutput()) {
_signalTypeMap.propagateType(port);
}
}
} else if ((a instanceof CompositeActor)
&& !(a instanceof CTCompositeActor)) {
// This actor is an opaque composite actor but not a
// CT Composite actor.
// NOTE: For its output ports, we can tell the signal type
// from their receiver types. However, the signal types of
// its input ports have to be derived from the output ports
// of some other actors that reside at the same hierarchical
// level. So we only handle output ports here.
Iterator ports = ((Entity) a).portList().iterator();
while (ports.hasNext()) {
IOPort port = (IOPort) ports.next();
if (port.isOutput()) {
Receiver[][] insideReceivers = port
.getInsideReceivers();
// NOTE: The assumption is that all the receivers
// belonging to the same IO port have the same
// signal type, so if there is at least one
// receiver, then use its type. If there are no
// receivers, assume the type is continuous.
if (insideReceivers.length > 0
&& insideReceivers[0] != null
&& insideReceivers[0].length > 0) {
Receiver insideReceiver = insideReceivers[0][0];
if (insideReceiver instanceof StateReceiver) {
_signalTypeMap.setType(port, CONTINUOUS);
} else {
_signalTypeMap.setType(port, DISCRETE);