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