001/* A register with one trigger port that accepts read requests. 002 003 Copyright (c) 2004-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.domains.de.lib; 029 030import ptolemy.data.Token; 031import ptolemy.kernel.CompositeEntity; 032import ptolemy.kernel.util.IllegalActionException; 033import ptolemy.kernel.util.NameDuplicationException; 034 035/////////////////////////////////////////////////////////////////// 036//// Register 037 038/** 039 A register is a stateful actor with a trigger port that accepts 040 read requests. 041 <p> 042 In the fire() method, if there is an event on the <i>trigger</i> 043 input port, this actor will produce an output event. The value 044 of the output event will be the previously recorded event 045 from the <i>input</i> port, or the value of the <i>initialValue</i> 046 parameter if there has been no previous input event. If, however, 047 <i>initialValue</i> contains no value, then no output will be 048 produced. In the postfire() method, if there is an input event on 049 the <i>input</i> port, then its value is recorded to be used 050 in future firings as the value of the output. 051 <p> 052 The inputs can be of any token type, but the <i>output</i> port 053 is constrained to be of a type at least that of the <i>input</i> 054 port and the <i>initialValue</i> parameter. 055 <p> 056 This class extends MostRecent. Unlike its base class, this actor 057 can be used to break dependencies in a feedback loop in that 058 the input tokens are consumed from the input ports after the outputs 059 are generated. Another difference is that the Register actor can be 060 fired when either the trigger port or the input port has a token, while 061 the Sampler can only be fired when the trigger port receives a token. 062 <p> 063 Both the <i>input</i> port and the <i>output</i> port are multiports. 064 Generally, their widths should match. Otherwise, if the width of the 065 <i>input</i> is greater than the width of the <i>output</i>, the extra 066 input tokens will not appear on any output, although they will be 067 consumed from the input port. If the width of the <i>output</i> is 068 greater than that of the <i>input</i>, then the last few channels of 069 the <i>output</i> will never emit tokens. 070 <p> 071 Note: If the width of the input changes during execution, then the 072 most recent inputs are forgotten, as if the execution of the model 073 were starting over. 074 075 @author Edward A. Lee, Haiyang Zheng 076 @version $Id$ 077 @since Ptolemy II 4.1 078 @Pt.ProposedRating Yellow (eal) 079 @Pt.AcceptedRating Red (eal) 080 @see ptolemy.domains.de.lib.MostRecent 081 */ 082public class Register extends MostRecent { 083 /** Construct an actor with the given container and name. 084 * @param container The container. 085 * @param name The name of this actor. 086 * @exception IllegalActionException If the actor cannot be contained 087 * by the proposed container. 088 * @exception NameDuplicationException If the container already has an 089 * actor with this name. 090 */ 091 public Register(CompositeEntity container, String name) 092 throws NameDuplicationException, IllegalActionException { 093 super(container, name); 094 095 _attachText("_iconDescription", 096 "<svg>\n" + "<rect x=\"-10\" y=\"-20\" " 097 + "width=\"20\" height=\"40\" " 098 + "style=\"fill:white\"/>\n" + "</svg>\n"); 099 } 100 101 /////////////////////////////////////////////////////////////////// 102 //// public methods //// 103 104 /** Declare that the <i>output</i> 105 * does not depend on the <i>input</i> in a firing. 106 * @exception IllegalActionException If the causality interface 107 * cannot be computed. 108 * @see #getCausalityInterface() 109 */ 110 @Override 111 public void declareDelayDependency() throws IllegalActionException { 112 // Declare that output does not immediately depend on the input. 113 _declareDelayDependency(input, output, 0.0); 114 // Note the dependency between trigger and output port is not 115 // declared. This is because declaring a dependency 116 // of 0.0 really means (0.0, 1) (i.e., the output does not 117 // immediately depend on the trigger). However, in this case the 118 // output could immediately depend on the trigger port. 119 } 120 121 /** If there is a token in the <i>trigger</i> port, emit the previously 122 * seen inputs from the <i>input</i> port. If there has been no 123 * previous input tokens, but the <i>initialValue</i> parameter 124 * has been set, emit the value of the <i>initialValue</i> parameter. 125 * Otherwise, emit nothing. 126 * @exception IllegalActionException If there is no director. 127 */ 128 @Override 129 public void fire() throws IllegalActionException { 130 // Don't call "super.fire();", this actor extends another actor. 131 int inputWidth = input.getWidth(); 132 int outputWidth = output.getWidth(); 133 int commonWidth = Math.min(inputWidth, outputWidth); 134 135 // If the <i>initialValue</i> parameter was not set, or if the 136 // width of the input has changed. 137 if (_lastInputs == null || _lastInputs.length != inputWidth) { 138 _lastInputs = new Token[inputWidth]; 139 } 140 141 sendOutputIfTriggered(commonWidth); 142 } 143 144 /** Indicate that this actor can fire even if the inputs are not 145 * known. This enables the actor to be used in SR and Continuous. 146 * @return False. 147 */ 148 @Override 149 public boolean isStrict() { 150 return false; 151 } 152 153 /** Read and record the inputs. 154 * @return What the superclass returns. 155 * @exception IllegalActionException If the superclass throws it. 156 */ 157 @Override 158 public boolean postfire() throws IllegalActionException { 159 int inputWidth = input.getWidth(); 160 int outputWidth = output.getWidth(); 161 int commonWidth = Math.min(inputWidth, outputWidth); 162 readInputs(commonWidth, inputWidth); 163 return super.postfire(); 164 } 165 166 /** Return true if there is any token in the input or the trigger 167 * port. This ensures that if an input is provided without a 168 * trigger, it will get recorded. 169 * @exception IllegalActionException If the base class throws it. 170 */ 171 @Override 172 public boolean prefire() throws IllegalActionException { 173 boolean inputPresent = false; 174 175 if (input.isOutsideConnected()) { 176 for (int i = 0; i < input.getWidth(); i++) { 177 if (input.hasToken(0)) { 178 inputPresent = true; 179 break; 180 } 181 } 182 } 183 return inputPresent || super.prefire(); 184 } 185}