001/* BusDisassembler - split input bus channels onto output port channels
002
003 Copyright (c) 2002-2014 The Regents of the University of California and
004 Research in Motion Limited.
005 All rights reserved.
006 Permission is hereby granted, without written agreement and without
007 license or royalty fees, to use, copy, modify, and distribute this
008 software and its documentation for any purpose, provided that the above
009 copyright notice and the following two paragraphs appear in all copies
010 of this software.
011
012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA OR RESEARCH IN MOTION
013 LIMITED BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
014 INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
015 SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
016 OR RESEARCH IN MOTION LIMITED HAVE BEEN ADVISED OF THE POSSIBILITY OF
017 SUCH DAMAGE.
018
019 THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION LIMITED
020 SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
022 PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
023 BASIS, AND THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION
024 LIMITED HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
025 ENHANCEMENTS, OR MODIFICATIONS.
026 PT_COPYRIGHT_VERSION_2
027 COPYRIGHTENDKEY
028
029 */
030package ptolemy.actor.lib;
031
032import java.util.Iterator;
033
034import ptolemy.actor.TypedAtomicActor;
035import ptolemy.actor.TypedIOPort;
036import ptolemy.data.Token;
037import ptolemy.kernel.CompositeEntity;
038import ptolemy.kernel.util.IllegalActionException;
039import ptolemy.kernel.util.NameDuplicationException;
040
041///////////////////////////////////////////////////////////////////
042//// BusDisassembler
043
044/**
045 Split the input bus relation into individual (possibly bus) output port
046 relations. If the width of the first output port is W1, it receives the
047 tokens from the first W1 channels of the input bus, the next output port
048 receives its width worth share from subsequent channels of the input bus
049 until either the input bus channels or all output port channels are
050 exhausted.<p>
051
052 Note: The width of a single relation (e.g. connected to an output port)
053 may be controlled by adding a <em>width</em> parameter with an IntToken value
054 representing the desired relation width.<p>
055
056 @author Zoltan Kemenczy
057 @version $Id$
058 @since Ptolemy II 2.1
059 @Pt.ProposedRating Red (zkemenczy)
060 @Pt.AcceptedRating Red (cxh)
061 @see ptolemy.actor.IORelation
062 */
063public class BusDisassembler extends TypedAtomicActor {
064    /** Construct a BusDisassembler with the given container and name.
065     *  @param container The container.
066     *  @param name The name of this actor.
067     *  @exception IllegalActionException If this actor cannot be contained
068     *   by the proposed container.
069     *  @exception NameDuplicationException If the container already has an
070     *   actor with this name.
071     */
072    public BusDisassembler(CompositeEntity container, String name)
073            throws NameDuplicationException, IllegalActionException {
074        super(container, name);
075        input = new TypedIOPort(this, "input", true, false);
076        input.setMultiport(true);
077        _attachText("_iconDescription",
078                "<svg>\n" + "<rect x=\"0\" y=\"0\" width=\"6\" "
079                        + "height=\"40\" style=\"fill:black\"/>\n"
080                        + "</svg>\n");
081    }
082
083    ///////////////////////////////////////////////////////////////////
084    ////                     ports and parameters                  ////
085
086    /** The input port. */
087    public TypedIOPort input;
088
089    ///////////////////////////////////////////////////////////////////
090    ////                         public methods                    ////
091    @Override
092    public void fire() throws IllegalActionException {
093        super.fire();
094        int inputWidth = input.getWidth();
095        Iterator<TypedIOPort> outputPorts = outputPortList().iterator();
096        TypedIOPort outputPort = outputPorts.hasNext() ? outputPorts.next()
097                : null;
098        int outputWidth = outputPort != null ? outputPort.getWidth() : 0;
099        int j = 0;
100
101        for (int i = 0; i < inputWidth; i++) {
102            if (input.hasToken(i)) {
103                Token t = input.get(i);
104
105                if (outputPort != null) {
106                    outputPort.send(j, t);
107                }
108            }
109
110            if (outputPort != null) {
111                if (j < outputWidth - 1) {
112                    j++;
113                } else {
114                    outputPort = outputPorts.hasNext() ? outputPorts.next()
115                            : null;
116                    outputWidth = outputPort != null ? outputPort.getWidth()
117                            : 0;
118                    j = 0;
119                }
120            }
121        }
122    }
123
124    @Override
125    public void preinitialize() throws IllegalActionException {
126        super.preinitialize();
127
128        if (inputPortList().size() > 1) {
129            throw new IllegalActionException(this,
130                    "can have only one input port.");
131        }
132    }
133}