/* Causality interface for FSM actors. Copyright (c) 2003-2014 The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. PT_COPYRIGHT_VERSION_2 COPYRIGHTENDKEY */ package ptolemy.domains.modal.kernel; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import ptolemy.actor.Actor; import ptolemy.actor.IOPort; import ptolemy.actor.TypedActor; import ptolemy.actor.parameters.ParameterPort; import ptolemy.actor.util.CausalityInterface; import ptolemy.actor.util.CausalityInterfaceForComposites; import ptolemy.actor.util.Dependency; import ptolemy.data.BooleanToken; import ptolemy.data.expr.ASTPtRootNode; import ptolemy.data.expr.ParseTreeFreeVariableCollector; import ptolemy.data.expr.PtParser; import ptolemy.kernel.util.IllegalActionException; import ptolemy.kernel.util.NamedObj; /////////////////////////////////////////////////////////////////// ////FSMCausalityInterface /** This class infers the causality interface of an FSMActor by checking the guards and actions of the transitions. If any transition in the model has an output action that writes to a port and a guard that references an input port, then there is a direct dependency of that output on that input. Otherwise, there is no dependency. Note that this is a conservative analysis in that it may indicate a dependency when there is none. For example, if all outgoing transitions from a state produce the same output value, and a transition is always taken, then irrespective of the guards, the output has no dependency on the inputs. A precise analysis, however, is much more difficult (probably undecidable).
All input ports that affect the state (i.e. that are mentioned in
any guard) must be in an equivalence class. Otherwise, we cannot
reliably make a decision about what the next state is. In addition,
if any input in a refinement affects an output, that input must
also be in this equivalence class. Otherwise, the scheduler
will assume there is no relationship between these inputs and
could provide an event that triggers a state transition in an
earlier firing than an event that triggers an output from the
current refinement.
@author Edward A. Lee
@version $Id: FSMCausalityInterface.java 70402 2014-10-23 00:52:20Z cxh $
@since Ptolemy II 8.0
@Pt.ProposedRating Yellow (eal)
@Pt.AcceptedRating Red (eal)
*/
public class FSMCausalityInterface extends CausalityInterfaceForComposites {
/** Construct a causality interface for the specified actor.
* @param actor The actor for which this is a causality interface.
* This is required to be an instance of CompositeEntity.
* @param defaultDependency The default dependency of an output
* port on an input port.
* @exception IllegalArgumentException If the actor parameter is not
* an instance of CompositeEntity.
*/
public FSMCausalityInterface(Actor actor, Dependency defaultDependency)
throws IllegalArgumentException {
super(actor, defaultDependency);
if (!(actor instanceof FSMActor)) {
throw new IllegalArgumentException("Cannot create an instance of "
+ "FSMCausalityInterface for " + actor.getFullName()
+ ", which is not an FSMActor.");
}
}
///////////////////////////////////////////////////////////////////
//// public methods ////
/** Return the dependency between the specified input port
* and the specified output port. This is done by checking
* the guards and actions of all the transitions.
* When called for the first time since a change in the model
* structure, this method performs the complete analysis of
* the FSM and caches the result. Subsequent calls just
* look up the result.
* @param input The input port.
* @param output The output port, or null to update the
* dependencies (and record equivalence classes) without
* requiring there to be an output port.
* @return The dependency between the specified input port
* and the specified output port, or null if a null output
* is port specified.
* @exception IllegalActionException If a guard expression cannot be parsed.
*/
@Override
public Dependency getDependency(IOPort input, IOPort output)
throws IllegalActionException {
// Cast is safe because this is checked in the constructor
FSMActor actor = (FSMActor) _actor;
// If the dependency is not up-to-date, then update it.
long workspaceVersion = actor.workspace().getVersion();
if (_dependencyVersion != workspaceVersion) {
// Need to update dependencies. The cached version
// is obsolete.
boolean stateDependentCausality = ((BooleanToken) actor.stateDependentCausality
.getToken()).booleanValue();
try {
actor.workspace().getReadAccess();
_reverseDependencies = new HashMap