001/* Director for the synchronous dataflow model of computation which 002 finds an optimized schedule. 003 004 Copyright (c) 1997-2014 The Regents of the University of California. 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 BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.domains.sdf.optimize; 029 030import java.util.Iterator; 031 032import ptolemy.actor.Actor; 033import ptolemy.actor.FiringEvent; 034import ptolemy.actor.sched.Firing; 035import ptolemy.actor.sched.Schedule; 036import ptolemy.actor.util.PeriodicDirectorHelper; 037import ptolemy.data.expr.Parameter; 038import ptolemy.data.type.BaseType; 039import ptolemy.domains.sdf.kernel.SDFDirector; 040import ptolemy.kernel.CompositeEntity; 041import ptolemy.kernel.util.Attribute; 042import ptolemy.kernel.util.IllegalActionException; 043import ptolemy.kernel.util.InvalidStateException; 044import ptolemy.kernel.util.NameDuplicationException; 045 046/////////////////////////////////////////////////////////////////// 047////OptimizingSDFDirector 048 049/** 050Director for the synchronous dataflow (SDF) model of computation which finds 051an optimized schedule according to a defined criterion. 052 053<h1>Class comments</h1> 054An OptimizingSDFDirector is the class that controls execution of actors under the 055SDF domain, while using an optimal schedule. For this it uses the OptimizingSDFScheduler 056class. 057<p> 058See {@link ptolemy.domains.sdf.kernel.SDFDirector}, 059{@link ptolemy.domains.sdf.kernel.SDFScheduler} and 060{@link ptolemy.domains.sdf.optimize.OptimizingSDFScheduler} for more information. 061</p><p> 062The <i>optimizationCriterion</i> parameter of this director 063selects the optimization criterion. 064</p> 065@see ptolemy.domains.sdf.kernel.SDFScheduler 066@see ptolemy.domains.sdf.kernel.SDFDirector 067@see ptolemy.domains.sdf.optimize.OptimizingSDFScheduler 068 069@author Marc Geilen 070@version $Id$ 071@since Ptolemy II 10.0 072@Pt.ProposedRating Red (mgeilen) 073@Pt.AcceptedRating Red () 074 */ 075 076public class OptimizingSDFDirector extends SDFDirector { 077 078 /** 079 * Enumeration type to define the supported optimization criteria. 080 */ 081 public enum OptimizationCriteria { 082 /** 083 * Optimize for minimum number of frame buffers. 084 */ 085 BUFFERS, 086 /** 087 * Optimize execution time (estimate). 088 */ 089 EXECUTIONTIME 090 } 091 092 /** 093 * Parameter defining the optimization criterion. 094 */ 095 public Parameter optimizationCriterion; 096 097 /** 098 * Construct on OptimizingSDFDirector in the given container with the given name. 099 * The container argument must not be null, or a 100 * NullPointerException will be thrown. 101 * If the name argument is null, then the name is set to the 102 * empty string. Increment the version number of the workspace. 103 * The OptimizingSDFDirector will have a default scheduler of type 104 * OptimizingSDFScheduler. 105 * 106 * @param container Container of the director. 107 * @param name Name of this director. 108 * @exception IllegalActionException If the director is not compatible 109 * with the specified container. May be thrown in a derived class. 110 * @exception NameDuplicationException If the container is not a 111 * CompositeActor and the name collides with an entity in the container. 112 */ 113 public OptimizingSDFDirector(CompositeEntity container, String name) 114 throws IllegalActionException, NameDuplicationException { 115 super(container, name); 116 // FIXME: super(container, name) above calls SDFDirector._init in which the scheduler is set to an 117 // SDFScheduler, but we need an OptimizingSDFScheduler (set in OptimizingSDFDirector._init) 118 // before setting the value of the OptimizationCriterion parameter 119 // Perhaps getting the preferred Scheduler type could be factored out, but I don't want to 120 // touch the SDFDirector code. 121 122 // initialize the parameter 123 optimizationCriterion = new Parameter(this, "OptimizationCriterion"); 124 optimizationCriterion.setTypeEquals(BaseType.STRING); 125 optimizationCriterion.addChoice("\"Buffers\""); 126 optimizationCriterion.addChoice("\"Execution Time\""); 127 128 // initialize 129 _init(); 130 131 } 132 133 /** Calculate the current schedule, if necessary, and iterate the 134 * contained actors in the order given by the schedule. 135 * method copied from super class SDFDirector. Modifies only the firing 136 * by firing the BufferingProfile if the interface is defined. 137 * Factoring out difference might be a good idea. 138 * 139 * @exception IllegalActionException If any actor executed by this 140 * actor return false in prefire. 141 * @exception InvalidStateException If this director does not have a 142 * container. 143 */ 144 @Override 145 public void fire() throws IllegalActionException { 146 // Don't call "super.fire();" here because if you do then 147 // everything happens twice. 148 149 OptimizingSDFScheduler scheduler = (OptimizingSDFScheduler) getScheduler(); 150 151 if (scheduler == null) { 152 throw new IllegalActionException( 153 "Attempted to fire " + "system with no scheduler"); 154 } 155 156 // This will throw IllegalActionException if this director 157 // does not have a container. 158 Schedule schedule = scheduler.getSchedule(); 159 Iterator firings = schedule.firingIterator(); 160 161 while (firings.hasNext() && !_stopRequested) { 162 Firing firing = (Firing) firings.next(); 163 Actor actor = firing.getActor(); 164 int iterationCount = firing.getIterationCount(); 165 166 if (_debugging) { 167 _debug(new FiringEvent(this, actor, FiringEvent.BEFORE_ITERATE, 168 iterationCount)); 169 } 170 171 int returnValue; 172 // check if the actor has the interface BufferingProfile 173 if (actor instanceof BufferingProfile) { 174 BufferingProfile bp = (BufferingProfile) actor; 175 // Then the firing must be a BufferProfileFiring 176 BufferingProfileFiring f = (BufferingProfileFiring) firing; 177 returnValue = bp.iterate(iterationCount, f.fireExclusive); 178 } else { 179 returnValue = actor.iterate(iterationCount); 180 } 181 182 if (returnValue == STOP_ITERATING) { 183 _postfireReturns = false; 184 } else if (returnValue == NOT_READY) { 185 // See de/test/auto/knownFailedTests/DESDFClockTest.xml 186 throw new IllegalActionException(this, actor, "Actor " 187 + "is not ready to fire. Perhaps " + actor.getName() 188 + ".prefire() returned false? " 189 + "Try debugging the actor by selecting " 190 + "\"Listen to Actor\". Also, for SDF check moml for " 191 + "tokenConsumptionRate on input."); 192 } 193 194 if (_debugging) { 195 _debug(new FiringEvent(this, actor, FiringEvent.AFTER_ITERATE, 196 iterationCount)); 197 } 198 } 199 } 200 201 /** React to a change in an attribute. If the changed attribute 202 * matches a parameter of the director, then the corresponding 203 * local copy of the parameter value will be updated. 204 * @param attribute The changed parameter. 205 * @exception IllegalActionException If the parameter set is not valid. 206 */ 207 @Override 208 public void attributeChanged(Attribute attribute) 209 throws IllegalActionException { 210 // NOTE: Invalidate the schedules only if the values of these 211 // parameters have changed. 212 if (attribute == optimizationCriterion) { 213 _setOptimizationCriterionValue(); 214 } 215 super.attributeChanged(attribute); 216 } 217 218 /////////////////////////////////////////////////////////////////// 219 //// private fields //// 220 221 /** Initialize the object. In this case, we give the OptimizingSDFDirector a 222 * default scheduler of the class OptimizingSDFScheduler, an iterations 223 * parameter and a vectorizationFactor parameter. 224 */ 225 private void _init() 226 throws IllegalActionException, NameDuplicationException { 227 228 // set the schedule to an instance of OptimizingSDFScheduler 229 OptimizingSDFScheduler scheduler = new OptimizingSDFScheduler(this, 230 uniqueName("OptimizingSDFScheduler"), 231 _optimizationCriterionValue); 232 233 // set the default value of the parameter 234 optimizationCriterion.setExpression("\"Buffers\""); 235 236 // if necessary, copy the string parameter to the enumerated value 237 _setOptimizationCriterionValue(); 238 239 // set the constrainBufferSizes parameter 240 scheduler.constrainBufferSizes.setExpression("constrainBufferSizes"); 241 setScheduler(scheduler); 242 243 // Subclasses may set this to null and handle this themselves. 244 _periodicDirectorHelper = new PeriodicDirectorHelper(this); 245 } 246 247 /** 248 * Set the _optimizationCriterionValue to the proper value corresponding to the 249 * OptimizationCriterion string parameter 250 * @exception IllegalActionException if the criterion used is unknown 251 */ 252 private void _setOptimizationCriterionValue() 253 throws IllegalActionException { 254 OptimizingSDFScheduler os = (OptimizingSDFScheduler) getScheduler(); 255 if (optimizationCriterion.getValueAsString().equals("\"Buffers\"")) { 256 _optimizationCriterionValue = OptimizationCriteria.BUFFERS; 257 } else if (optimizationCriterion.getValueAsString() 258 .equals("\"Execution Time\"")) { 259 _optimizationCriterionValue = OptimizationCriteria.EXECUTIONTIME; 260 } else { 261 throw new IllegalActionException("Unknown optimization criterion"); 262 } 263 if (os != null) { 264 os.optimizationCriterion = _optimizationCriterionValue; 265 } 266 // invalidate the schedule, because the criterion has changed 267 invalidateSchedule(); 268 } 269 270 private OptimizationCriteria _optimizationCriterionValue = OptimizationCriteria.BUFFERS; 271 272}