001/* A polymorphic multiplexor. 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; 029 030import ptolemy.actor.TypedIOPort; 031import ptolemy.data.IntToken; 032import ptolemy.data.Token; 033import ptolemy.data.type.BaseType; 034import ptolemy.kernel.CompositeEntity; 035import ptolemy.kernel.util.IllegalActionException; 036import ptolemy.kernel.util.NameDuplicationException; 037import ptolemy.kernel.util.StringAttribute; 038 039/////////////////////////////////////////////////////////////////// 040//// Multiplexor 041 042/** 043 This actor selects from the channels on the 044 <i>input</i> port, copying the input from one channel to the output, 045 based on the most recently received value on the <i>select</i> input. 046 If the selected channel has no token, then no output is produced. 047 The <i>select</i> input is required to be an integer between 0 and 048 <i>n</i>-1, where <i>n</i> is the width of the <i>input</i> port. 049 If no token has been received on the <i>select</i> port, then null 050 is sent to the output. The <i>input</i> port may 051 receive Tokens of any type, but all channels must have the same type. 052 <p> 053 One token is consumed from each input channel that has a token. 054 Compare this with the Select actor, which only consumes a token on 055 the selected channel. 056 057 @author Jeff Tsay, Edward A. Lee, Stavros Tripakis 058 @version $Id$ 059 @since Ptolemy II 1.0 060 @Pt.ProposedRating Yellow (ctsay) 061 @Pt.AcceptedRating Yellow (cxh) 062 @see ptolemy.actor.lib.Select 063 */ 064public class Multiplexor extends Transformer { 065 /** Construct an actor in the specified container with the specified 066 * name. 067 * @param container The container. 068 * @param name The name of this actor within the container. 069 * @exception IllegalActionException If the actor cannot be contained 070 * by the proposed container. 071 * @exception NameDuplicationException If the name coincides with 072 * an actor already in the container. 073 */ 074 public Multiplexor(CompositeEntity container, String name) 075 throws IllegalActionException, NameDuplicationException { 076 super(container, name); 077 078 input.setMultiport(true); 079 080 select = new TypedIOPort(this, "select", true, false); 081 select.setTypeEquals(BaseType.INT); 082 new StringAttribute(select, "_cardinal").setExpression("SOUTH"); 083 } 084 085 /////////////////////////////////////////////////////////////////// 086 //// ports and parameters //// 087 088 /** Input for the index of the port to select. The type is IntToken. */ 089 public TypedIOPort select; 090 091 /////////////////////////////////////////////////////////////////// 092 //// public methods //// 093 094 /** Read a token from the <i>select</i> port and from each channel 095 * of the <i>input</i> port, and output a token on the selected 096 * channel. This method will throw a NoTokenException if any 097 * input channel does not have a token. 098 * 099 * @exception IllegalActionException If there is no director, or if 100 * the <i>select</i> input is out of range. 101 */ 102 @Override 103 public void fire() throws IllegalActionException { 104 super.fire(); 105 106 // Be sure to not use _channel if the select input 107 // is not known. That would be non-monotonic. 108 if (select.isKnown(0)) { 109 if (select.hasToken(0)) { 110 _selectChannel = (IntToken) select.get(0); 111 112 // Perform the in-range test here, where a new channel value is obtained: 113 int c = _selectChannel.intValue(); 114 if (c < 0 || c >= input.getWidth()) { 115 throw new IllegalActionException(this, 116 "Select input is out of range: " + c + "."); 117 } 118 } 119 120 // Be sure to read all inputs that are present, even 121 // if they aren't required in order to produce output. 122 // Tokens need to be consumed in dataflow and DE domains. 123 for (int i = 0; i < input.getWidth(); i++) { 124 if (input.isKnown(i)) { 125 Token token = null; 126 if (input.hasToken(i)) { 127 token = input.get(i); 128 } 129 if (_selectChannel != null 130 && _selectChannel.intValue() == i) { 131 // Note that if the input is known to be absent, 132 // then the following sends null. Dataflow receivers 133 // interpret this as sending nothing (nothing is queued). 134 // Fixed-point receivers (SR and Continuous) interpret 135 // this as an assertion that the output is absent. 136 output.send(0, token); 137 } 138 } 139 } 140 141 // If no select value has been seen, then we can 142 // assert that the output is empty. Note that this is only 143 // safe if the select input is known. 144 if (_selectChannel == null) { 145 output.send(0, null); 146 } 147 } 148 } 149 150 /** Initialize to the default, which is to use channel zero. 151 * @exception IllegalActionException If a derived class throws it. 152 */ 153 @Override 154 public void initialize() throws IllegalActionException { 155 super.initialize(); 156 _selectChannel = null; 157 } 158 159 /** Return false. 160 * @return False. 161 */ 162 @Override 163 public boolean isStrict() { 164 return false; 165 } 166 167 /////////////////////////////////////////////////////////////////// 168 //// private variables //// 169 170 /** The most recently read select input. */ 171 private IntToken _selectChannel; 172}