drain.hh revision 9342
19342SAndreas.Sandberg@arm.com/* 29342SAndreas.Sandberg@arm.com * Copyright (c) 2012 ARM Limited 39342SAndreas.Sandberg@arm.com * All rights reserved 49342SAndreas.Sandberg@arm.com * 59342SAndreas.Sandberg@arm.com * The license below extends only to copyright in the software and shall 69342SAndreas.Sandberg@arm.com * not be construed as granting a license to any other intellectual 79342SAndreas.Sandberg@arm.com * property including but not limited to intellectual property relating 89342SAndreas.Sandberg@arm.com * to a hardware implementation of the functionality of the software 99342SAndreas.Sandberg@arm.com * licensed hereunder. You may use the software subject to the license 109342SAndreas.Sandberg@arm.com * terms below provided that you ensure that this notice is replicated 119342SAndreas.Sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 129342SAndreas.Sandberg@arm.com * modified or unmodified, in source code or in binary form. 139342SAndreas.Sandberg@arm.com * 149342SAndreas.Sandberg@arm.com * Redistribution and use in source and binary forms, with or without 159342SAndreas.Sandberg@arm.com * modification, are permitted provided that the following conditions are 169342SAndreas.Sandberg@arm.com * met: redistributions of source code must retain the above copyright 179342SAndreas.Sandberg@arm.com * notice, this list of conditions and the following disclaimer; 189342SAndreas.Sandberg@arm.com * redistributions in binary form must reproduce the above copyright 199342SAndreas.Sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 209342SAndreas.Sandberg@arm.com * documentation and/or other materials provided with the distribution; 219342SAndreas.Sandberg@arm.com * neither the name of the copyright holders nor the names of its 229342SAndreas.Sandberg@arm.com * contributors may be used to endorse or promote products derived from 239342SAndreas.Sandberg@arm.com * this software without specific prior written permission. 249342SAndreas.Sandberg@arm.com * 259342SAndreas.Sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269342SAndreas.Sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 279342SAndreas.Sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 289342SAndreas.Sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 299342SAndreas.Sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309342SAndreas.Sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 319342SAndreas.Sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 329342SAndreas.Sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 339342SAndreas.Sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 349342SAndreas.Sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359342SAndreas.Sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369342SAndreas.Sandberg@arm.com * 379342SAndreas.Sandberg@arm.com * Authors: Andreas Sandberg 389342SAndreas.Sandberg@arm.com */ 399342SAndreas.Sandberg@arm.com 409342SAndreas.Sandberg@arm.com#ifndef __SIM_DRAIN_HH__ 419342SAndreas.Sandberg@arm.com#define __SIM_DRAIN_HH__ 429342SAndreas.Sandberg@arm.com 439342SAndreas.Sandberg@arm.com#include <cassert> 449342SAndreas.Sandberg@arm.com#include <vector> 459342SAndreas.Sandberg@arm.com 469342SAndreas.Sandberg@arm.com#include "base/flags.hh" 479342SAndreas.Sandberg@arm.com 489342SAndreas.Sandberg@arm.comclass Event; 499342SAndreas.Sandberg@arm.com 509342SAndreas.Sandberg@arm.com/** 519342SAndreas.Sandberg@arm.com * This class coordinates draining of a System. 529342SAndreas.Sandberg@arm.com * 539342SAndreas.Sandberg@arm.com * When draining a System, we need to make sure that all SimObjects in 549342SAndreas.Sandberg@arm.com * that system have drained their state before declaring the operation 559342SAndreas.Sandberg@arm.com * to be successful. This class keeps track of how many objects are 569342SAndreas.Sandberg@arm.com * still in the process of draining their state. Once it determines 579342SAndreas.Sandberg@arm.com * that all objects have drained their state, it exits the simulation 589342SAndreas.Sandberg@arm.com * loop. 599342SAndreas.Sandberg@arm.com * 609342SAndreas.Sandberg@arm.com * @note A System might not be completely drained even though the 619342SAndreas.Sandberg@arm.com * DrainManager has caused the simulation loop to exit. Draining needs 629342SAndreas.Sandberg@arm.com * to be restarted until all Drainable objects declare that they don't 639342SAndreas.Sandberg@arm.com * need further simulation to be completely drained. See Drainable for 649342SAndreas.Sandberg@arm.com * more information. 659342SAndreas.Sandberg@arm.com */ 669342SAndreas.Sandberg@arm.comclass DrainManager 679342SAndreas.Sandberg@arm.com{ 689342SAndreas.Sandberg@arm.com public: 699342SAndreas.Sandberg@arm.com DrainManager(); 709342SAndreas.Sandberg@arm.com virtual ~DrainManager(); 719342SAndreas.Sandberg@arm.com 729342SAndreas.Sandberg@arm.com /** 739342SAndreas.Sandberg@arm.com * Get the number of objects registered with this DrainManager 749342SAndreas.Sandberg@arm.com * that are currently draining their state. 759342SAndreas.Sandberg@arm.com * 769342SAndreas.Sandberg@arm.com * @return Number of objects currently draining. 779342SAndreas.Sandberg@arm.com */ 789342SAndreas.Sandberg@arm.com unsigned int getCount() const { return _count; } 799342SAndreas.Sandberg@arm.com 809342SAndreas.Sandberg@arm.com void setCount(int count) { _count = count; } 819342SAndreas.Sandberg@arm.com 829342SAndreas.Sandberg@arm.com /** 839342SAndreas.Sandberg@arm.com * Notify the DrainManager that a Drainable object has finished 849342SAndreas.Sandberg@arm.com * draining. 859342SAndreas.Sandberg@arm.com */ 869342SAndreas.Sandberg@arm.com void signalDrainDone() { 879342SAndreas.Sandberg@arm.com assert(_count > 0); 889342SAndreas.Sandberg@arm.com if (--_count == 0) 899342SAndreas.Sandberg@arm.com drainCycleDone(); 909342SAndreas.Sandberg@arm.com } 919342SAndreas.Sandberg@arm.com 929342SAndreas.Sandberg@arm.com protected: 939342SAndreas.Sandberg@arm.com /** 949342SAndreas.Sandberg@arm.com * Callback when all registered Drainable objects have completed a 959342SAndreas.Sandberg@arm.com * drain cycle. 969342SAndreas.Sandberg@arm.com */ 979342SAndreas.Sandberg@arm.com virtual void drainCycleDone(); 989342SAndreas.Sandberg@arm.com 999342SAndreas.Sandberg@arm.com /** Number of objects still draining. */ 1009342SAndreas.Sandberg@arm.com unsigned int _count; 1019342SAndreas.Sandberg@arm.com}; 1029342SAndreas.Sandberg@arm.com 1039342SAndreas.Sandberg@arm.com/** 1049342SAndreas.Sandberg@arm.com * Interface for objects that might require draining before 1059342SAndreas.Sandberg@arm.com * checkpointing. 1069342SAndreas.Sandberg@arm.com * 1079342SAndreas.Sandberg@arm.com * An object's internal state needs to be drained when creating a 1089342SAndreas.Sandberg@arm.com * checkpoint, switching between CPU models, or switching between 1099342SAndreas.Sandberg@arm.com * timing models. Once the internal state has been drained from 1109342SAndreas.Sandberg@arm.com * <i>all</i> objects in the system, the objects are serialized to 1119342SAndreas.Sandberg@arm.com * disc or the configuration change takes place. The process works as 1129342SAndreas.Sandberg@arm.com * follows (see simulate.py for details): 1139342SAndreas.Sandberg@arm.com * 1149342SAndreas.Sandberg@arm.com * <ol> 1159342SAndreas.Sandberg@arm.com * <li>An instance of a DrainManager is created to keep track of how 1169342SAndreas.Sandberg@arm.com * many objects need to be drained. The object maintains an 1179342SAndreas.Sandberg@arm.com * internal counter that is decreased every time its 1189342SAndreas.Sandberg@arm.com * CountedDrainEvent::signalDrainDone() method is called. When the 1199342SAndreas.Sandberg@arm.com * counter reaches zero, the simulation is stopped. 1209342SAndreas.Sandberg@arm.com * 1219342SAndreas.Sandberg@arm.com * <li>Call Drainable::drain() for every object in the 1229342SAndreas.Sandberg@arm.com * system. Draining has completed if all of them return 1239342SAndreas.Sandberg@arm.com * zero. Otherwise, the sum of the return values is loaded into 1249342SAndreas.Sandberg@arm.com * the counter of the DrainManager. A pointer to the drain 1259342SAndreas.Sandberg@arm.com * manager is passed as an argument to the drain() method. 1269342SAndreas.Sandberg@arm.com * 1279342SAndreas.Sandberg@arm.com * <li>Continue simulation. When an object has finished draining its 1289342SAndreas.Sandberg@arm.com * internal state, it calls CountedDrainEvent::signalDrainDone() 1299342SAndreas.Sandberg@arm.com * on the manager. When the counter in the manager reaches zero, 1309342SAndreas.Sandberg@arm.com * the simulation stops. 1319342SAndreas.Sandberg@arm.com * 1329342SAndreas.Sandberg@arm.com * <li>Check if any object still needs draining, if so repeat the 1339342SAndreas.Sandberg@arm.com * process above. 1349342SAndreas.Sandberg@arm.com * 1359342SAndreas.Sandberg@arm.com * <li>Serialize objects, switch CPU model, or change timing model. 1369342SAndreas.Sandberg@arm.com * 1379342SAndreas.Sandberg@arm.com * <li>Call Drainable::drainResume() and continue the simulation. 1389342SAndreas.Sandberg@arm.com * </ol> 1399342SAndreas.Sandberg@arm.com * 1409342SAndreas.Sandberg@arm.com */ 1419342SAndreas.Sandberg@arm.comclass Drainable 1429342SAndreas.Sandberg@arm.com{ 1439342SAndreas.Sandberg@arm.com public: 1449342SAndreas.Sandberg@arm.com /** 1459342SAndreas.Sandberg@arm.com * Object drain/handover states 1469342SAndreas.Sandberg@arm.com * 1479342SAndreas.Sandberg@arm.com * An object starts out in the Running state. When the simulator 1489342SAndreas.Sandberg@arm.com * prepares to take a snapshot or prepares a CPU for handover, it 1499342SAndreas.Sandberg@arm.com * calls the drain() method to transfer the object into the 1509342SAndreas.Sandberg@arm.com * Draining or Drained state. If any object enters the Draining 1519342SAndreas.Sandberg@arm.com * state (drain() returning >0), simulation continues until it all 1529342SAndreas.Sandberg@arm.com * objects have entered the Drained state. 1539342SAndreas.Sandberg@arm.com * 1549342SAndreas.Sandberg@arm.com * Before resuming simulation, the simulator calls resume() to 1559342SAndreas.Sandberg@arm.com * transfer the object to the Running state. 1569342SAndreas.Sandberg@arm.com * 1579342SAndreas.Sandberg@arm.com * \note Even though the state of an object (visible to the rest 1589342SAndreas.Sandberg@arm.com * of the world through getState()) could be used to determine if 1599342SAndreas.Sandberg@arm.com * all objects have entered the Drained state, the protocol is 1609342SAndreas.Sandberg@arm.com * actually a bit more elaborate. See drain() for details. 1619342SAndreas.Sandberg@arm.com */ 1629342SAndreas.Sandberg@arm.com enum State { 1639342SAndreas.Sandberg@arm.com Running, /** Running normally */ 1649342SAndreas.Sandberg@arm.com Draining, /** Draining buffers pending serialization/handover */ 1659342SAndreas.Sandberg@arm.com Drained /** Buffers drained, ready for serialization/handover */ 1669342SAndreas.Sandberg@arm.com }; 1679342SAndreas.Sandberg@arm.com 1689342SAndreas.Sandberg@arm.com Drainable(); 1699342SAndreas.Sandberg@arm.com virtual ~Drainable(); 1709342SAndreas.Sandberg@arm.com 1719342SAndreas.Sandberg@arm.com /** 1729342SAndreas.Sandberg@arm.com * Determine if an object needs draining and register a 1739342SAndreas.Sandberg@arm.com * DrainManager. 1749342SAndreas.Sandberg@arm.com * 1759342SAndreas.Sandberg@arm.com * When draining the state of an object, the simulator calls drain 1769342SAndreas.Sandberg@arm.com * with a pointer to a drain manager. If the object does not need 1779342SAndreas.Sandberg@arm.com * further simulation to drain internal buffers, it switched to 1789342SAndreas.Sandberg@arm.com * the Drained state and returns 0, otherwise it switches to the 1799342SAndreas.Sandberg@arm.com * Draining state and returns the number of times that it will 1809342SAndreas.Sandberg@arm.com * call Event::process() on the drain event. Most objects are 1819342SAndreas.Sandberg@arm.com * expected to return either 0 or 1. 1829342SAndreas.Sandberg@arm.com * 1839342SAndreas.Sandberg@arm.com * @note An object that has entered the Drained state can be 1849342SAndreas.Sandberg@arm.com * disturbed by other objects in the system and consequently be 1859342SAndreas.Sandberg@arm.com * forced to enter the Draining state again. The simulator 1869342SAndreas.Sandberg@arm.com * therefore repeats the draining process until all objects return 1879342SAndreas.Sandberg@arm.com * 0 on the first call to drain(). 1889342SAndreas.Sandberg@arm.com * 1899342SAndreas.Sandberg@arm.com * @param drainManager DrainManager to use to inform the simulator 1909342SAndreas.Sandberg@arm.com * when draining has completed. 1919342SAndreas.Sandberg@arm.com * 1929342SAndreas.Sandberg@arm.com * @return 0 if the object is ready for serialization now, >0 if 1939342SAndreas.Sandberg@arm.com * it needs further simulation. 1949342SAndreas.Sandberg@arm.com */ 1959342SAndreas.Sandberg@arm.com virtual unsigned int drain(DrainManager *drainManager) = 0; 1969342SAndreas.Sandberg@arm.com 1979342SAndreas.Sandberg@arm.com /** 1989342SAndreas.Sandberg@arm.com * Resume execution after a successful drain. 1999342SAndreas.Sandberg@arm.com * 2009342SAndreas.Sandberg@arm.com * @note This method is normally only called from the simulation 2019342SAndreas.Sandberg@arm.com * scripts. 2029342SAndreas.Sandberg@arm.com */ 2039342SAndreas.Sandberg@arm.com virtual void drainResume(); 2049342SAndreas.Sandberg@arm.com 2059342SAndreas.Sandberg@arm.com State getDrainState() const { return _drainState; } 2069342SAndreas.Sandberg@arm.com 2079342SAndreas.Sandberg@arm.com protected: 2089342SAndreas.Sandberg@arm.com void setDrainState(State new_state) { _drainState = new_state; } 2099342SAndreas.Sandberg@arm.com 2109342SAndreas.Sandberg@arm.com 2119342SAndreas.Sandberg@arm.com private: 2129342SAndreas.Sandberg@arm.com State _drainState; 2139342SAndreas.Sandberg@arm.com 2149342SAndreas.Sandberg@arm.com}; 2159342SAndreas.Sandberg@arm.com 2169342SAndreas.Sandberg@arm.com#endif 217