001/* A static integer arithmetic logic unit.
002
003 Copyright (c) 2007-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 */
028package ptolemy.actor.lib.tutorial;
029
030import ptolemy.actor.TypedAtomicActor;
031import ptolemy.actor.TypedIOPort;
032import ptolemy.data.IntToken;
033import ptolemy.data.Token;
034import ptolemy.data.expr.StringParameter;
035import ptolemy.data.type.BaseType;
036import ptolemy.kernel.CompositeEntity;
037import ptolemy.kernel.util.IllegalActionException;
038import ptolemy.kernel.util.NameDuplicationException;
039import ptolemy.kernel.util.Workspace;
040
041///////////////////////////////////////////////////////////////////
042//// StaticALU
043
044/**
045 <p>
046 A static integer arithmetic logic unit.
047 </p>
048
049 @author Man-Kit Leung
050 @version $Id$
051 @since Ptolemy II 6.0.2
052 @Pt.ProposedRating Red (mankit)
053 @Pt.AcceptedRating Red (mankit)
054 */
055public class StaticALU extends TypedAtomicActor {
056    /** Construct an actor in the specified container with the specified
057     *  name.
058     *  @param container The container.
059     *  @param name The name of this adder within the container.
060     *  @exception IllegalActionException If the actor cannot be contained
061     *   by the proposed container.
062     *  @exception NameDuplicationException If the name coincides with
063     *   an actor already in the container.
064     */
065    public StaticALU(CompositeEntity container, String name)
066            throws IllegalActionException, NameDuplicationException {
067        super(container, name);
068        A = new TypedIOPort(this, "A", true, false);
069        A.setTypeEquals(BaseType.INT);
070        B = new TypedIOPort(this, "B", true, false);
071        B.setTypeEquals(BaseType.INT);
072
073        operation = new StringParameter(this, "operation");
074        operation.setExpression("0 : (NOP)");
075        operation.addChoice("0 : (NOP)");
076        operation.addChoice("1 : (A + B)");
077        operation.addChoice("2 : (A - B)");
078        operation.addChoice("3 : (A * B)");
079        operation.addChoice("4 : (A / B)");
080
081        output = new TypedIOPort(this, "output", false, true);
082        output.setTypeEquals(BaseType.INT);
083
084    }
085
086    ///////////////////////////////////////////////////////////////////
087    ////                     ports and parameters                  ////
088
089    /** Input port for the first operand. The port type is integer.
090     */
091    public TypedIOPort A;
092
093    /** Input port for the second operand. The port type is integer.
094     */
095    public TypedIOPort B;
096
097    /** Input port for the operation code. The port type is integer.
098     * The value of the input tokens should not exceed the number of
099     * operations supported.
100     */
101    public StringParameter operation;
102
103    /** Output port.  The type is inferred from the connections.
104     */
105    public TypedIOPort output;
106
107    ///////////////////////////////////////////////////////////////////
108    ////                         public methods                    ////
109
110    /** Override the base class to set type constraints.
111     *  @param workspace The workspace for the new object.
112     *  @return A new instance of StaticALU.
113     *  @exception CloneNotSupportedException If a derived class contains
114     *   an attribute that cannot be cloned.
115     */
116    @Override
117    public Object clone(Workspace workspace) throws CloneNotSupportedException {
118        StaticALU newObject = (StaticALU) super.clone(workspace);
119        newObject.A.setTypeEquals(BaseType.INT);
120        newObject.B.setTypeEquals(BaseType.INT);
121        return newObject;
122    }
123
124    /** If there is at least one token on each of the input ports, the
125     *  first token from each port is consumed. The value of the token
126     *  from the operation input port determines which operation will be
127     *  perform on the tokens from input port A and B. The opcode is
128     *  defined as follow:
129     *      0 - NOP
130     *      1 - Addition (A + B)
131     *      2 - Subtraction (A - B)
132     *      3 - Multiplication (A * B)
133     *      4 - Division (A / B)
134     *  @exception IllegalActionException If the input operation code
135     *  is not supported.
136     */
137    @Override
138    public void fire() throws IllegalActionException {
139        super.fire();
140        Token result = null;
141
142        if (A.hasToken(0) && B.hasToken(0)) {
143            int opcode = Integer
144                    .parseInt(operation.getExpression().substring(0, 1));
145            IntToken tokenA = (IntToken) A.get(0);
146            IntToken tokenB = (IntToken) B.get(0);
147
148            switch (opcode) {
149            case 0: // NOP
150                result = IntToken.ZERO;
151                break;
152            case 1: // addition
153                result = tokenA.add(tokenB);
154                break;
155            case 2: // subtraction
156                result = tokenA.subtract(tokenB);
157                break;
158            case 3: // multiplication
159                result = tokenA.multiply(tokenB);
160                break;
161            case 4: // division
162                result = tokenA.divide(tokenB);
163                break;
164            default:
165                throw new IllegalActionException(this,
166                        "Unsupported operation code: " + opcode + ".\n");
167            }
168        }
169        output.send(0, result);
170    }
171}