001/* IOPort for SDF
002
003 Copyright (c) 1997-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027
028 */
029package ptolemy.domains.sdf.kernel;
030
031import ptolemy.actor.TypedIOPort;
032import ptolemy.data.IntToken;
033import ptolemy.data.expr.Parameter;
034import ptolemy.kernel.ComponentEntity;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.InternalErrorException;
037import ptolemy.kernel.util.NameDuplicationException;
038import ptolemy.kernel.util.Workspace;
039
040///////////////////////////////////////////////////////////////////
041//// SDFIOPort
042
043/**
044 This class extends IOPort with convenience methods for handling the token
045 production and consumption rates.  These are merely convenience methods,
046 as the pertinent attributes can be added to any IOPort and the SDF domain
047 will respect them.
048 <p>
049 It is not recommended to use this port as a port for composite actors
050 because the presence of the rate parameters will prevent the inner SDF
051 scheduler from propagating it rates to the outside.  That is, if the
052 parameters are present, the scheduler does not override them.
053
054 @author Stephen Neuendorffer
055 @version $Id$
056 @since Ptolemy II 0.2
057 @Pt.ProposedRating Yellow (neuendor)
058 @Pt.AcceptedRating Yellow (johnr)
059 @deprecated It is preferable to declare the rate parameters directly
060 in the actors, instead of using this class.  This allows the
061 dependence of rates to be understood by various SDF schedulers.
062 */
063@Deprecated
064public final class SDFIOPort extends TypedIOPort {
065    /** Construct an SDFIOPort with no container and no name that is
066     *  neither an input nor an output.
067     */
068    public SDFIOPort() {
069        super();
070        _initialize();
071    }
072
073    /** Construct a port in the specified workspace with an empty
074     *  string as a name. You can then change the name with setName().
075     *  If the workspace argument
076     *  is null, then use the default workspace.
077     *  The object is added to the workspace directory.
078     *  Increment the version number of the workspace.
079     *  @param workspace The workspace that will list the port.
080     * @exception IllegalActionException If port parameters cannot be initialized.
081     */
082    public SDFIOPort(Workspace workspace) throws IllegalActionException {
083        super(workspace);
084        _initialize();
085    }
086
087    /** Construct an SDFIOPort with a containing actor and a name
088     *  that is neither an input nor an output.  The specified container
089     *  must implement the Actor interface, or an exception will be thrown.
090     *
091     *  @param container The container actor.
092     *  @param name The name of the port.
093     *  @exception IllegalActionException If the port is not of an acceptable
094     *   class for the container, or if the container does not implement the
095     *   Actor interface.
096     *  @exception NameDuplicationException If the name coincides with
097     *   a port already in the container.
098     */
099    public SDFIOPort(ComponentEntity container, String name)
100            throws IllegalActionException, NameDuplicationException {
101        super(container, name);
102        _initialize();
103    }
104
105    /** Construct an SDFIOPort with a container and a name that is
106     *  either an input, an output, or both, depending on the third
107     *  and fourth arguments. The specified container must implement
108     *  the Actor interface or an exception will be thrown.
109     *
110     *  @param container The container actor.
111     *  @param name The name of the port.
112     *  @param isInput True if this is to be an input port.
113     *  @param isOutput True if this is to be an output port.
114     *  @exception IllegalActionException If the port is not of an acceptable
115     *   class for the container, or if the container does not implement the
116     *   Actor interface.
117     *  @exception NameDuplicationException If the name coincides with
118     *   a port already in the container.
119     */
120    public SDFIOPort(ComponentEntity container, String name, boolean isInput,
121            boolean isOutput)
122            throws IllegalActionException, NameDuplicationException {
123        this(container, name);
124        setInput(isInput);
125        setOutput(isOutput);
126    }
127
128    ///////////////////////////////////////////////////////////////////
129    ////                         public parameters                 ////
130
131    /** The number of tokens consumed on this port each firing. */
132    public Parameter tokenConsumptionRate;
133
134    /** The number of tokens produced on this port during initialization. */
135    public Parameter tokenInitProduction;
136
137    /** The number of tokens produced on this port each firing. */
138    public Parameter tokenProductionRate;
139
140    ///////////////////////////////////////////////////////////////////
141    ////                         public methods                    ////
142
143    /** Clone the port into the specified workspace. This calls the
144     *  base class and then creates new parameters.  The new
145     *  port will have the same parameter values as the old.
146     *  @param workspace The workspace for the new object.
147     *  @return A new SDFIOPort.
148     *  @exception CloneNotSupportedException If one of the attributes
149     *   cannot be cloned.
150     */
151    @Override
152    public Object clone(Workspace workspace) throws CloneNotSupportedException {
153        SDFIOPort newObject = (SDFIOPort) super.clone(workspace);
154        newObject.tokenConsumptionRate = (Parameter) newObject
155                .getAttribute("tokenConsumptionRate");
156        newObject.tokenInitProduction = (Parameter) newObject
157                .getAttribute("tokenInitProduction");
158        newObject.tokenProductionRate = (Parameter) newObject
159                .getAttribute("tokenProductionRate");
160        return newObject;
161    }
162
163    /** Get the number of tokens that are consumed
164     *  on every channel of this port.
165     *
166     *  @return The number of tokens consumed on this port, as specified in
167     *  the tokenConsumptionRate Parameter.
168     *  @exception IllegalActionException If calling getToken() throws it.
169     *  @see #setTokenConsumptionRate(int)
170     */
171    public int getTokenConsumptionRate() throws IllegalActionException {
172        return ((IntToken) tokenConsumptionRate.getToken()).intValue();
173    }
174
175    /** Get the number of tokens that are produced
176     *  on this port during initialization.
177     *
178     *  @return The number of tokens produced on the port, as specified in
179     *  the tokenInitProduction parameter.
180     *  @exception IllegalActionException If calling getToken() throws it.
181     *  @see #setTokenInitProduction(int)
182     */
183    public int getTokenInitProduction() throws IllegalActionException {
184        return ((IntToken) tokenInitProduction.getToken()).intValue();
185    }
186
187    /** Get the number of tokens that are produced
188     *  on the designated port of this Actor during each firing.
189     *
190     *  @return The number of tokens produced on the port, as specified in
191     *  the tokenProductionRate parameter.
192     *  @exception IllegalActionException If calling getToken() throws it.
193     *  @see #setTokenProductionRate(int)
194     */
195    public int getTokenProductionRate() throws IllegalActionException {
196        return ((IntToken) tokenProductionRate.getToken()).intValue();
197    }
198
199    /**
200     * Set whether or not this port is an input.  In addition to the base
201     * class operation, set the port rate parameters to reasonable values.
202     * If setting the port to be an input, then set the consumption rate to
203     * be 1.  If setting the port to not be an input, then set the consumption
204     * rate to be 0.
205     *  @exception IllegalActionException If changing the port status is
206     *   not permitted.
207     */
208    @Override
209    public void setInput(boolean isInput) throws IllegalActionException {
210        super.setInput(isInput);
211
212        try {
213            if (isInput) {
214                tokenConsumptionRate.setToken(new IntToken(1));
215            } else {
216                tokenConsumptionRate.setToken(new IntToken(0));
217            }
218        } catch (Exception e) {
219            // This should never happen
220            throw new InternalErrorException(e.getMessage());
221        }
222    }
223
224    /**
225     * Set whether or not this port is an output.  In addition to the base
226     * class operation, set the port rate parameters to reasonable values.
227     * If setting the port to be an output, then set the consumption rate to
228     * be 1.  If setting the port to not be an output, then set the consumption
229     * rate to be 0.
230     *  @exception IllegalActionException If changing the port status is
231     *   not permitted.
232     */
233    @Override
234    public void setOutput(boolean isOutput) throws IllegalActionException {
235        super.setOutput(isOutput);
236
237        try {
238            if (isOutput) {
239                tokenProductionRate.setToken(new IntToken(1));
240            } else {
241                tokenProductionRate.setToken(new IntToken(0));
242                tokenInitProduction.setToken(new IntToken(0));
243            }
244        } catch (Exception e) {
245            // This should never happen.
246            throw new InternalErrorException(e.getMessage());
247        }
248    }
249
250    /** Set the number of tokens that are consumed
251     *  on the appropriate port of this Actor during each firing
252     *  by setting the value of the tokenConsumptionRate parameter.
253     *
254     *  @param rate The number of tokens that are consumed
255     *  @exception IllegalActionException If the rate is less than zero,
256     *  or the port is not an input port.
257     *  @see #getTokenConsumptionRate()
258     */
259    public void setTokenConsumptionRate(int rate)
260            throws IllegalActionException {
261        if (rate < 0) {
262            throw new IllegalActionException("Rate must be >= 0");
263        }
264
265        if (!isInput()) {
266            throw new IllegalActionException(this,
267                    "Port " + "is not an input port.");
268        }
269
270        tokenConsumptionRate.setToken(new IntToken(rate));
271    }
272
273    /** Set the number of tokens that are produced
274     *  on the appropriate port of this Actor during initialize
275     *  by setting the value of the tokenInitProduction parameter.
276     *
277     *  @param count The number of tokens that are produced
278     *  @exception IllegalActionException If the count is less than zero,
279     *  or the port is not an output port.
280     *  @see #getTokenInitProduction()
281     */
282    public void setTokenInitProduction(int count)
283            throws IllegalActionException {
284        if (count < 0) {
285            throw new IllegalActionException("Count must be >= 0");
286        }
287
288        if (!isOutput()) {
289            throw new IllegalActionException(this,
290                    "Port " + "is not an Output Port.");
291        }
292
293        tokenInitProduction.setToken(new IntToken(count));
294    }
295
296    /** Set the number of tokens that are produced
297     *  on the appropriate port of this Actor during each firing
298     *  by setting the value of the tokenProductionRate parameter.
299     *
300     *  @param rate The number of tokens that are produced.
301     *  @exception IllegalActionException If port is not contained
302     *  in this actor, the rate is less than zero, or the port is
303     *  not an output port.
304     *  @see #getTokenProductionRate()
305     */
306    public void setTokenProductionRate(int rate) throws IllegalActionException {
307        if (rate < 0) {
308            throw new IllegalActionException("Rate must be >= 0");
309        }
310
311        if (!isOutput()) {
312            throw new IllegalActionException(this,
313                    "Port " + "is not an Output Port.");
314        }
315
316        tokenProductionRate.setToken(new IntToken(rate));
317    }
318
319    ///////////////////////////////////////////////////////////////////
320    ////                         private methods                   ////
321
322    /**
323     * Initialize local data members.
324     */
325    private void _initialize() {
326        try {
327            tokenConsumptionRate = new Parameter(this, "tokenConsumptionRate",
328                    new IntToken(0));
329            tokenInitProduction = new Parameter(this, "tokenInitProduction",
330                    new IntToken(0));
331            tokenProductionRate = new Parameter(this, "tokenProductionRate",
332                    new IntToken(0));
333        } catch (Throwable throwable) {
334            // This should never happen.
335            throw new InternalErrorException(this, throwable, "");
336        }
337    }
338}