drain.hh revision 10910
19342SAndreas.Sandberg@arm.com/* 210910Sandreas.sandberg@arm.com * Copyright (c) 2012, 2015 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 4810910Sandreas.sandberg@arm.comclass Drainable; 4910910Sandreas.sandberg@arm.com 5010910Sandreas.sandberg@arm.com#ifndef SWIG // SWIG doesn't support strongly typed enums 5110910Sandreas.sandberg@arm.com/** 5210910Sandreas.sandberg@arm.com * Object drain/handover states 5310910Sandreas.sandberg@arm.com * 5410910Sandreas.sandberg@arm.com * An object starts out in the Running state. When the simulator 5510910Sandreas.sandberg@arm.com * prepares to take a snapshot or prepares a CPU for handover, it 5610910Sandreas.sandberg@arm.com * calls the drain() method to transfer the object into the Draining 5710910Sandreas.sandberg@arm.com * or Drained state. If any object enters the Draining state 5810910Sandreas.sandberg@arm.com * (Drainable::drain() returning >0), simulation continues until it 5910910Sandreas.sandberg@arm.com * all objects have entered the Drained state. 6010910Sandreas.sandberg@arm.com * 6110910Sandreas.sandberg@arm.com * Before resuming simulation, the simulator calls resume() to 6210910Sandreas.sandberg@arm.com * transfer the object to the Running state. 6310910Sandreas.sandberg@arm.com * 6410910Sandreas.sandberg@arm.com * \note Even though the state of an object (visible to the rest of 6510910Sandreas.sandberg@arm.com * the world through Drainable::getState()) could be used to determine 6610910Sandreas.sandberg@arm.com * if all objects have entered the Drained state, the protocol is 6710910Sandreas.sandberg@arm.com * actually a bit more elaborate. See Drainable::drain() for details. 6810910Sandreas.sandberg@arm.com */ 6910910Sandreas.sandberg@arm.comenum class DrainState { 7010910Sandreas.sandberg@arm.com Running, /** Running normally */ 7110910Sandreas.sandberg@arm.com Draining, /** Draining buffers pending serialization/handover */ 7210910Sandreas.sandberg@arm.com Drained /** Buffers drained, ready for serialization/handover */ 7310910Sandreas.sandberg@arm.com}; 7410910Sandreas.sandberg@arm.com#endif 759342SAndreas.Sandberg@arm.com 769342SAndreas.Sandberg@arm.com/** 779342SAndreas.Sandberg@arm.com * This class coordinates draining of a System. 789342SAndreas.Sandberg@arm.com * 799342SAndreas.Sandberg@arm.com * When draining a System, we need to make sure that all SimObjects in 809342SAndreas.Sandberg@arm.com * that system have drained their state before declaring the operation 819342SAndreas.Sandberg@arm.com * to be successful. This class keeps track of how many objects are 829342SAndreas.Sandberg@arm.com * still in the process of draining their state. Once it determines 839342SAndreas.Sandberg@arm.com * that all objects have drained their state, it exits the simulation 849342SAndreas.Sandberg@arm.com * loop. 859342SAndreas.Sandberg@arm.com * 869342SAndreas.Sandberg@arm.com * @note A System might not be completely drained even though the 879342SAndreas.Sandberg@arm.com * DrainManager has caused the simulation loop to exit. Draining needs 889342SAndreas.Sandberg@arm.com * to be restarted until all Drainable objects declare that they don't 899342SAndreas.Sandberg@arm.com * need further simulation to be completely drained. See Drainable for 909342SAndreas.Sandberg@arm.com * more information. 919342SAndreas.Sandberg@arm.com */ 929342SAndreas.Sandberg@arm.comclass DrainManager 939342SAndreas.Sandberg@arm.com{ 949342SAndreas.Sandberg@arm.com public: 959342SAndreas.Sandberg@arm.com DrainManager(); 969342SAndreas.Sandberg@arm.com virtual ~DrainManager(); 979342SAndreas.Sandberg@arm.com 989342SAndreas.Sandberg@arm.com /** 999342SAndreas.Sandberg@arm.com * Get the number of objects registered with this DrainManager 1009342SAndreas.Sandberg@arm.com * that are currently draining their state. 1019342SAndreas.Sandberg@arm.com * 1029342SAndreas.Sandberg@arm.com * @return Number of objects currently draining. 1039342SAndreas.Sandberg@arm.com */ 1049342SAndreas.Sandberg@arm.com unsigned int getCount() const { return _count; } 1059342SAndreas.Sandberg@arm.com 1069342SAndreas.Sandberg@arm.com void setCount(int count) { _count = count; } 1079342SAndreas.Sandberg@arm.com 1089342SAndreas.Sandberg@arm.com /** 1099342SAndreas.Sandberg@arm.com * Notify the DrainManager that a Drainable object has finished 1109342SAndreas.Sandberg@arm.com * draining. 1119342SAndreas.Sandberg@arm.com */ 1129342SAndreas.Sandberg@arm.com void signalDrainDone() { 1139342SAndreas.Sandberg@arm.com assert(_count > 0); 1149342SAndreas.Sandberg@arm.com if (--_count == 0) 1159342SAndreas.Sandberg@arm.com drainCycleDone(); 1169342SAndreas.Sandberg@arm.com } 1179342SAndreas.Sandberg@arm.com 1189342SAndreas.Sandberg@arm.com protected: 1199342SAndreas.Sandberg@arm.com /** 1209342SAndreas.Sandberg@arm.com * Callback when all registered Drainable objects have completed a 1219342SAndreas.Sandberg@arm.com * drain cycle. 1229342SAndreas.Sandberg@arm.com */ 1239342SAndreas.Sandberg@arm.com virtual void drainCycleDone(); 1249342SAndreas.Sandberg@arm.com 1259342SAndreas.Sandberg@arm.com /** Number of objects still draining. */ 1269342SAndreas.Sandberg@arm.com unsigned int _count; 1279342SAndreas.Sandberg@arm.com}; 1289342SAndreas.Sandberg@arm.com 1299342SAndreas.Sandberg@arm.com/** 1309342SAndreas.Sandberg@arm.com * Interface for objects that might require draining before 1319342SAndreas.Sandberg@arm.com * checkpointing. 1329342SAndreas.Sandberg@arm.com * 1339342SAndreas.Sandberg@arm.com * An object's internal state needs to be drained when creating a 1349342SAndreas.Sandberg@arm.com * checkpoint, switching between CPU models, or switching between 1359342SAndreas.Sandberg@arm.com * timing models. Once the internal state has been drained from 1369342SAndreas.Sandberg@arm.com * <i>all</i> objects in the system, the objects are serialized to 1379342SAndreas.Sandberg@arm.com * disc or the configuration change takes place. The process works as 1389342SAndreas.Sandberg@arm.com * follows (see simulate.py for details): 1399342SAndreas.Sandberg@arm.com * 1409342SAndreas.Sandberg@arm.com * <ol> 1419342SAndreas.Sandberg@arm.com * <li>An instance of a DrainManager is created to keep track of how 1429342SAndreas.Sandberg@arm.com * many objects need to be drained. The object maintains an 1439342SAndreas.Sandberg@arm.com * internal counter that is decreased every time its 1449342SAndreas.Sandberg@arm.com * CountedDrainEvent::signalDrainDone() method is called. When the 1459342SAndreas.Sandberg@arm.com * counter reaches zero, the simulation is stopped. 1469342SAndreas.Sandberg@arm.com * 1479342SAndreas.Sandberg@arm.com * <li>Call Drainable::drain() for every object in the 1489342SAndreas.Sandberg@arm.com * system. Draining has completed if all of them return 1499342SAndreas.Sandberg@arm.com * zero. Otherwise, the sum of the return values is loaded into 1509342SAndreas.Sandberg@arm.com * the counter of the DrainManager. A pointer to the drain 1519342SAndreas.Sandberg@arm.com * manager is passed as an argument to the drain() method. 1529342SAndreas.Sandberg@arm.com * 1539342SAndreas.Sandberg@arm.com * <li>Continue simulation. When an object has finished draining its 1549342SAndreas.Sandberg@arm.com * internal state, it calls CountedDrainEvent::signalDrainDone() 1559342SAndreas.Sandberg@arm.com * on the manager. When the counter in the manager reaches zero, 1569342SAndreas.Sandberg@arm.com * the simulation stops. 1579342SAndreas.Sandberg@arm.com * 1589342SAndreas.Sandberg@arm.com * <li>Check if any object still needs draining, if so repeat the 1599342SAndreas.Sandberg@arm.com * process above. 1609342SAndreas.Sandberg@arm.com * 1619342SAndreas.Sandberg@arm.com * <li>Serialize objects, switch CPU model, or change timing model. 1629342SAndreas.Sandberg@arm.com * 1639342SAndreas.Sandberg@arm.com * <li>Call Drainable::drainResume() and continue the simulation. 1649342SAndreas.Sandberg@arm.com * </ol> 1659342SAndreas.Sandberg@arm.com * 1669342SAndreas.Sandberg@arm.com */ 1679342SAndreas.Sandberg@arm.comclass Drainable 1689342SAndreas.Sandberg@arm.com{ 1699342SAndreas.Sandberg@arm.com public: 1709342SAndreas.Sandberg@arm.com Drainable(); 1719342SAndreas.Sandberg@arm.com virtual ~Drainable(); 1729342SAndreas.Sandberg@arm.com 1739342SAndreas.Sandberg@arm.com /** 1749342SAndreas.Sandberg@arm.com * Determine if an object needs draining and register a 1759342SAndreas.Sandberg@arm.com * DrainManager. 1769342SAndreas.Sandberg@arm.com * 1779342SAndreas.Sandberg@arm.com * When draining the state of an object, the simulator calls drain 1789342SAndreas.Sandberg@arm.com * with a pointer to a drain manager. If the object does not need 1799342SAndreas.Sandberg@arm.com * further simulation to drain internal buffers, it switched to 1809342SAndreas.Sandberg@arm.com * the Drained state and returns 0, otherwise it switches to the 1819342SAndreas.Sandberg@arm.com * Draining state and returns the number of times that it will 1829342SAndreas.Sandberg@arm.com * call Event::process() on the drain event. Most objects are 1839342SAndreas.Sandberg@arm.com * expected to return either 0 or 1. 1849342SAndreas.Sandberg@arm.com * 1859342SAndreas.Sandberg@arm.com * @note An object that has entered the Drained state can be 1869342SAndreas.Sandberg@arm.com * disturbed by other objects in the system and consequently be 1879342SAndreas.Sandberg@arm.com * forced to enter the Draining state again. The simulator 1889342SAndreas.Sandberg@arm.com * therefore repeats the draining process until all objects return 1899342SAndreas.Sandberg@arm.com * 0 on the first call to drain(). 1909342SAndreas.Sandberg@arm.com * 1919342SAndreas.Sandberg@arm.com * @param drainManager DrainManager to use to inform the simulator 1929342SAndreas.Sandberg@arm.com * when draining has completed. 1939342SAndreas.Sandberg@arm.com * 1949342SAndreas.Sandberg@arm.com * @return 0 if the object is ready for serialization now, >0 if 1959342SAndreas.Sandberg@arm.com * it needs further simulation. 1969342SAndreas.Sandberg@arm.com */ 1979342SAndreas.Sandberg@arm.com virtual unsigned int drain(DrainManager *drainManager) = 0; 1989342SAndreas.Sandberg@arm.com 1999342SAndreas.Sandberg@arm.com /** 2009342SAndreas.Sandberg@arm.com * Resume execution after a successful drain. 2019342SAndreas.Sandberg@arm.com * 2029342SAndreas.Sandberg@arm.com * @note This method is normally only called from the simulation 2039342SAndreas.Sandberg@arm.com * scripts. 2049342SAndreas.Sandberg@arm.com */ 2059342SAndreas.Sandberg@arm.com virtual void drainResume(); 2069342SAndreas.Sandberg@arm.com 2079346SAndreas.Sandberg@arm.com /** 2089346SAndreas.Sandberg@arm.com * Write back dirty buffers to memory using functional writes. 2099346SAndreas.Sandberg@arm.com * 2109346SAndreas.Sandberg@arm.com * After returning, an object implementing this method should have 2119346SAndreas.Sandberg@arm.com * written all its dirty data back to memory. This method is 2129346SAndreas.Sandberg@arm.com * typically used to prepare a system with caches for 2139346SAndreas.Sandberg@arm.com * checkpointing. 2149346SAndreas.Sandberg@arm.com */ 2159346SAndreas.Sandberg@arm.com virtual void memWriteback() {}; 2169346SAndreas.Sandberg@arm.com 2179346SAndreas.Sandberg@arm.com /** 2189346SAndreas.Sandberg@arm.com * Invalidate the contents of memory buffers. 2199346SAndreas.Sandberg@arm.com * 2209346SAndreas.Sandberg@arm.com * When the switching to hardware virtualized CPU models, we need 2219346SAndreas.Sandberg@arm.com * to make sure that we don't have any cached state in the system 2229346SAndreas.Sandberg@arm.com * that might become stale when we return. This method is used to 2239346SAndreas.Sandberg@arm.com * flush all such state back to main memory. 2249346SAndreas.Sandberg@arm.com * 2259346SAndreas.Sandberg@arm.com * @warn This does <i>not</i> cause any dirty state to be written 2269346SAndreas.Sandberg@arm.com * back to memory. 2279346SAndreas.Sandberg@arm.com */ 2289346SAndreas.Sandberg@arm.com virtual void memInvalidate() {}; 2299346SAndreas.Sandberg@arm.com 23010910Sandreas.sandberg@arm.com DrainState getDrainState() const { return _drainState; } 2319342SAndreas.Sandberg@arm.com 2329342SAndreas.Sandberg@arm.com protected: 23310910Sandreas.sandberg@arm.com void setDrainState(DrainState new_state) { _drainState = new_state; } 2349342SAndreas.Sandberg@arm.com 2359342SAndreas.Sandberg@arm.com private: 23610910Sandreas.sandberg@arm.com DrainState _drainState; 2379342SAndreas.Sandberg@arm.com}; 2389342SAndreas.Sandberg@arm.com 2399554Sandreas.hansson@arm.comDrainManager *createDrainManager(); 2409554Sandreas.hansson@arm.comvoid cleanupDrainManager(DrainManager *drain_manager); 2419554Sandreas.hansson@arm.com 2429342SAndreas.Sandberg@arm.com#endif 243