001/* An actor that performs a specified logic operation on the input. 002 003 Copyright (c) 1998-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.logic; 029 030import java.util.Locale; 031 032import ptolemy.actor.lib.Transformer; 033import ptolemy.data.BooleanToken; 034import ptolemy.data.Token; 035import ptolemy.data.expr.StringParameter; 036import ptolemy.data.type.BaseType; 037import ptolemy.kernel.CompositeEntity; 038import ptolemy.kernel.util.Attribute; 039import ptolemy.kernel.util.IllegalActionException; 040import ptolemy.kernel.util.InternalErrorException; 041import ptolemy.kernel.util.NameDuplicationException; 042 043// NOTE: If you update the list of functions, then you will want 044// to update the list in actor/lib/logic/logic.xml. 045/////////////////////////////////////////////////////////////////// 046//// LogicGate 047 048/** 049 <p>Produce an output token on each firing with a value that is 050 equal to the specified logic operator of the input(s). 051 The functions are:</p> 052 <ul> 053 <li> <b>and</b>: The logical and operator. 054 This is the default function for this actor.</li> 055 <li> <b>or</b>: The logical or operator.</li> 056 <li> <b>xor</b>: The logical xor operator.</li> 057 <li> <b>nand</b>: The logical nand operator. 058 Equivalent to the negation of <i>and</i>.</li> 059 <li> <b>nor</b>: The logical nor operator. 060 Equivalent to the negation of <i>or</i>.</li> 061 <li> <b>xnor</b>: The logical xnor operator. 062 Equivalent to the negation of <i>xor</i>.</li> 063 </ul> 064 <p> 065 NOTE: All operators have 066 a single input port, which is a multiport, and a single output port, which 067 is not a multiport. All ports have type boolean.</p> 068 <p> 069 This actor does not require that each input 070 channel have a token upon firing. As long as one channel contains a 071 token, output will be produced. If no input tokens are available at 072 all, then no output is produced. At most one token is consumed 073 on each input channel.</p> 074 075 @author Paul Whitaker 076 @version $Id$ 077 @since Ptolemy II 10.0 078 @Pt.ProposedRating Green (pwhitake) 079 @Pt.AcceptedRating Green (pwhitake) 080 */ 081public class LogicGate extends Transformer { 082 /** Construct an actor with the given container and name. Set the 083 * logic function to the default ("and"). Set the types of the ports 084 * to boolean. 085 * @param container The container. 086 * @param name The name of this actor. 087 * @exception IllegalActionException If the actor cannot be contained 088 * by the proposed container. 089 * @exception NameDuplicationException If the container already has an 090 * actor with this name. 091 */ 092 public LogicGate(CompositeEntity container, String name) 093 throws NameDuplicationException, IllegalActionException { 094 super(container, name); 095 096 // Parameters 097 logic = new StringParameter(this, "logic"); 098 logic.setExpression("and"); 099 logic.addChoice("and"); 100 logic.addChoice("or"); 101 logic.addChoice("xor"); 102 logic.addChoice("nand"); 103 logic.addChoice("nor"); 104 logic.addChoice("xnor"); 105 _function = _AND; 106 _negate = false; 107 108 // Ports 109 input.setMultiport(true); 110 output.setMultiport(false); 111 input.setTypeEquals(BaseType.BOOLEAN); 112 output.setTypeEquals(BaseType.BOOLEAN); 113 114 _attachText("_iconDescription", 115 "<svg>\n" + "<rect x=\"-30\" y=\"-15\" " 116 + "width=\"60\" height=\"30\" " 117 + "style=\"fill:white\"/>\n" + "</svg>\n"); 118 } 119 120 /////////////////////////////////////////////////////////////////// 121 //// ports and parameters //// 122 123 /** The function to compute. This is a string-valued attribute 124 * that defaults to "and". 125 */ 126 public StringParameter logic; 127 128 /////////////////////////////////////////////////////////////////// 129 //// public methods //// 130 131 /** Override the base class to determine which function is being 132 * specified. Read the value of the function attribute and set 133 * the cached value appropriately. 134 * @param attribute The attribute that changed. 135 * @exception IllegalActionException If the function is not recognized. 136 */ 137 @Override 138 public void attributeChanged(Attribute attribute) 139 throws IllegalActionException { 140 if (attribute == logic) { 141 String functionName = logic.getExpression().trim() 142 .toLowerCase(Locale.getDefault()); 143 144 if (functionName.equals("and")) { 145 _function = _AND; 146 _negate = false; 147 } else if (functionName.equals("or")) { 148 _function = _OR; 149 _negate = false; 150 } else if (functionName.equals("xor")) { 151 _function = _XOR; 152 _negate = false; 153 } else if (functionName.equals("nand")) { 154 _function = _AND; 155 _negate = true; 156 } else if (functionName.equals("nor")) { 157 _function = _OR; 158 _negate = true; 159 } else if (functionName.equals("xnor")) { 160 _function = _XOR; 161 _negate = true; 162 } else { 163 throw new IllegalActionException(this, 164 "Unrecognized logic function: " + functionName 165 + ". Valid functions are 'and', 'or', 'xor', " 166 + "'nand', 'nor', and 'xnor'."); 167 } 168 } else { 169 super.attributeChanged(attribute); 170 } 171 } 172 173 /** Consume at most one input token from each input channel, 174 * and produce a token on the output port. If there is no 175 * input on any channel, then produce no output. 176 * @exception IllegalActionException If there is no director. 177 */ 178 @Override 179 public void fire() throws IllegalActionException { 180 super.fire(); 181 BooleanToken value = null; 182 BooleanToken in = null; 183 184 for (int i = 0; i < input.getWidth(); i++) { 185 if (input.hasToken(i)) { 186 in = (BooleanToken) input.get(i); 187 188 if (in != null) { 189 value = _updateFunction(in, value); 190 } 191 } 192 } 193 194 if (value != null) { 195 if (_negate) { 196 value = value.not(); 197 } 198 199 output.send(0, value); 200 } 201 } 202 203 /////////////////////////////////////////////////////////////////// 204 //// protected methods //// 205 206 /** Calculate the function on the given arguments. 207 * @param in The new input value. Should never be null. 208 * @param old The old result value, or null if there is none. 209 * @return The result of applying the function. 210 * @exception IllegalActionException If thrown by BooleanToken operations. 211 */ 212 protected BooleanToken _updateFunction(BooleanToken in, BooleanToken old) 213 throws IllegalActionException { 214 Token result; 215 216 if (old == null) { 217 result = in; 218 } else { 219 switch (_function) { 220 case _AND: 221 result = old.and(in); 222 break; 223 224 case _OR: 225 result = old.or(in); 226 break; 227 228 case _XOR: 229 result = old.xor(in); 230 break; 231 232 default: 233 throw new InternalErrorException( 234 "Invalid value for _function private variable. " 235 + "LogicGate actor (" + getFullName() + ")" 236 + " on function type " + _function); 237 } 238 } 239 240 return (BooleanToken) result; 241 } 242 243 /////////////////////////////////////////////////////////////////// 244 //// protected variables //// 245 246 /** An indicator for the function to compute. 247 * Valid values are {@link #_AND}, {@link #_OR}, and {@link #_XOR}. 248 */ 249 protected int _function; 250 251 /** True if the intermediate results should be negated. */ 252 protected boolean _negate; 253 254 /** Perform a logical AND. */ 255 protected static final int _AND = 0; 256 257 /** Perform a logical OR. */ 258 protected static final int _OR = 1; 259 260 /** Perform a logical XOR. */ 261 protected static final int _XOR = 2; 262}