src/Sim/Foundation/TimeWheel/ClockedResourceBase.h

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 #ifndef SIM_TIME_WHEEL_CLOCKED_RESOURCE_BASE_H
00033 #define SIM_TIME_WHEEL_CLOCKED_RESOURCE_BASE_H
00034 
00035 #include "Sim/Foundation/TimeWheel/ClockedResourceIF.h"
00036 
00037 namespace Onikiri 
00038 {
00039     
00040     class ClockedResourceBase : public ClockedResourceIF
00041     {
00042     public:
00043         enum PHASE
00044         {
00045             PHASE_BEGIN,
00046             PHASE_EVALUATE,
00047             PHASE_TRANSITION,
00048             PHASE_UPDATE,
00049             PHASE_END
00050         };
00051 
00052         struct ComparePriority 
00053         {
00054             bool operator()( const ClockedResourceIF* lhv, const ClockedResourceIF* rhv )
00055             { return lhv->GetPriority() > rhv->GetPriority(); }
00056         };
00057 
00058         ClockedResourceBase( const char* name = "" ) : 
00059             m_name( name ),
00060             m_reqStallThisCycle( false ),
00061             m_stallPeriod( 0 ),
00062             m_thisCycleStalled( false ),
00063             m_lastCycleStalled( false ),
00064             m_parent( NULL ),
00065             m_cycles( 0 ),
00066             m_stalledCycles( 0 ),
00067             m_phase( PHASE_BEGIN ),
00068             m_priority( RP_DEFAULT_UPDATE )
00069         {
00070         }
00071 
00072         ~ClockedResourceBase()
00073         {
00074         }
00075 
00076         //
00077         // These methods corresponds to 1-cycle behavior.
00078         //
00079 
00080         // Beginning of a cycle.
00081         virtual void Begin()
00082         {
00083             ASSERT( m_phase == PHASE_BEGIN );
00084 
00085             m_lastCycleStalled = m_thisCycleStalled;
00086             m_thisCycleStalled  = false;
00087             m_reqStallThisCycle = false;
00088 
00089             if( m_stallPeriod > 0 ) {
00090                 m_reqStallThisCycle = true;
00091                 --m_stallPeriod;
00092             }
00093 
00094             m_phase = PHASE_EVALUATE;
00095 
00096             Children::iterator end = m_children.end();
00097             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00098                 (*i)->Begin();
00099             }
00100             
00101             m_cycles++;
00102         }
00103 
00104         // Evaluate and decide to stall this cycle or not.
00105         virtual void Evaluate()
00106         {
00107             ASSERT( m_phase == PHASE_EVALUATE, "Do you call Begin() of a base class?" );
00108             m_phase = PHASE_TRANSITION;
00109 
00110             Children::iterator end = m_children.end();
00111             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00112                 (*i)->Evaluate();
00113             }
00114         }
00115 
00116         // Transition from Prepare and Process.
00117         // Fix whether stall is done at this cycle or not.
00118         virtual void Transition()
00119         {
00120             ASSERT( m_phase == PHASE_TRANSITION, "Do you call Evaluate() of a base class?"  );
00121 
00122             // Fix stall state
00123             m_thisCycleStalled = m_reqStallThisCycle;
00124             m_phase = PHASE_UPDATE;
00125 
00126             
00127             if( m_thisCycleStalled ){
00128                 // Stall this cycle.
00129                 m_stalledCycles++;
00130             }
00131 
00132             if( !m_lastCycleStalled && m_thisCycleStalled ){
00133                 BeginStall();   
00134             }
00135             else if ( m_lastCycleStalled && !m_thisCycleStalled ){
00136                 EndStall(); 
00137             }
00138 
00139             Children::iterator end = m_children.end();
00140             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00141                 (*i)->Transition();
00142             }
00143         }
00144 
00145         // Update resources.
00146         virtual void TriggerUpdate()
00147         {
00148             ASSERT( m_phase == PHASE_UPDATE, "Do you call Event() of a base class?" );
00149 
00150             if( !m_thisCycleStalled ){
00151                 Update();
00152             }
00153             m_phase = PHASE_END;
00154 
00155             Children::iterator end = m_children.end();
00156             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00157                 (*i)->TriggerUpdate();
00158             }
00159         }
00160 
00161         // End of a cycle
00162         virtual void End()
00163         {
00164             ASSERT( m_phase == PHASE_END, "Do you call Process() of a base class?"  );
00165             m_phase = PHASE_BEGIN;
00166 
00167             Children::iterator end = m_children.end();
00168             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00169                 (*i)->End();
00170             }
00171 
00172             if( !m_thisCycleStalled ){
00173                 // Proceed a time tick.
00174                 Tick();
00175             }
00176         }
00177 
00178         // This method can be called only in Prepare().
00179         virtual void StallThisCycle()
00180         {
00181             ASSERT(
00182                 m_phase == PHASE_EVALUATE || m_phase == PHASE_TRANSITION,
00183                 "IsStalledThisCycle() can be called only in PHASE_EVALUATE/TRANSITION."
00184             );
00185             m_reqStallThisCycle = true;
00186 
00187             Children::iterator end = m_children.end();
00188             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00189                 (*i)->StallThisCycle();
00190             }
00191         }
00192 
00193         void StallThisCycleExcludingChildren()
00194         {
00195             ASSERT(
00196                 m_phase == PHASE_EVALUATE || m_phase == PHASE_TRANSITION,
00197                 "IsStalledThisCycle() can be called only in PHASE_EVALUATE/TRANSITION."
00198             );
00199             m_reqStallThisCycle = true;
00200         }
00201 
00202         // This method can be called in any phases.
00203         virtual void StallNextCycle( int cycles )
00204         {
00205             m_stallPeriod = std::max( cycles, m_stallPeriod );
00206 
00207             Children::iterator end = m_children.end();
00208             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00209                 (*i)->StallNextCycle( cycles );
00210             }
00211         }
00212 
00213         // Cancel a stall period set by StallNextCycle.
00214         virtual void CacnelStallPeriod()
00215         {
00216             m_stallPeriod = 0;
00217 
00218             Children::iterator end = m_children.end();
00219             for( Children::iterator i = m_children.begin(); i != end; ++i ){
00220                 (*i)->CacnelStallPeriod();
00221             }
00222         }
00223 
00224         // Is this resource stalled in a this cycle
00225         bool IsStalledThisCycle()
00226         {
00227             ASSERT(
00228                 m_phase == PHASE_UPDATE || m_phase == PHASE_END,
00229                 "IsStalledThisCycle() can be called only in PHASE_PROCESS/END."
00230             );
00231             return m_thisCycleStalled;
00232         }
00233 
00234         // Is this resource stalled in a last cycle
00235         bool IsStalledLastCycle()
00236         {
00237             ASSERT(
00238                 m_phase != PHASE_BEGIN,
00239                 "IsStalledLastCycle() cannot be called in PHASE_BEGIN." 
00240             );
00241             return m_lastCycleStalled;
00242         }
00243 
00244         // Add a child resource
00245         virtual void AddChild( ClockedResourceIF* child )
00246         {
00247             m_children.push_back( child );
00248             child->SetParent( this );
00249         }
00250 
00251         // For debug
00252         virtual void SetParent( ClockedResourceIF* parent )
00253         {
00254             m_parent = parent;
00255             
00256             m_who = m_name + "(" + typeid(*this).name() + ")";
00257             if( m_parent ){
00258                 m_who += String().format( " <= %s(Parent)  ", m_parent->Who() );
00259             }
00260         }
00261 
00262         virtual int GetPriority() const 
00263         {
00264             return m_priority;
00265         }
00266 
00267         virtual const char* Who() const
00268         {
00269 
00270             return m_who.c_str();
00271         }
00272 
00273         // This method is called in Process() if a resource is not stalled.
00274         virtual void Update(){};
00275 
00276         // Proceed a time tick.
00277         // This method is called in Transition() before BeginStall/End is called
00278         // when it is fixed to stall this cycle.
00279         virtual void Tick(){};
00280 
00281         // Stall handlers, which are called in stall begin/end
00282         virtual void BeginStall(){};
00283         virtual void EndStall(){};
00284 
00285 
00286 
00287     protected:
00288 
00289         // Child resources
00290         typedef std::vector<ClockedResourceIF*> Children;
00291         Children m_children;
00292 
00293         PHASE GetCurrentPhase() const
00294         {
00295             return m_phase;
00296         }
00297 
00298         s64 GetCycles() const
00299         {
00300             return m_cycles;
00301         }
00302 
00303         s64 GetStalledCycles() const
00304         {
00305             return m_stalledCycles;
00306         }
00307 
00308         // Priority constants are defined in "Sim/ResourcePriority.h".
00309         void SetPriority( int priority )
00310         {
00311             m_priority = priority;
00312         }
00313 
00314 
00315     private:
00316         String m_name;
00317         String m_who;
00318 
00319         // Stall request
00320         bool m_reqStallThisCycle;   
00321         
00322         // Stall period
00323         int  m_stallPeriod;
00324         
00325         // true if stall is done at a last cycle.
00326         bool m_thisCycleStalled;
00327         bool m_lastCycleStalled;
00328 
00329         ClockedResourceIF* m_parent;
00330 
00331         s64 m_cycles;
00332 
00333         // Stalled cycles.
00334         s64  m_stalledCycles;
00335 
00336         // Cycle phase
00337         PHASE m_phase;
00338 
00339         // Priority
00340         int m_priority;
00341     };
00342 
00343 }; // namespace Onikiri
00344 
00345 #endif // SIM_TIME_WHEEL_CLOCKED_RESOURCE_BASE_H
00346 

Onikiri2に対してTue Jun 18 14:34:23 2013に生成されました。  doxygen 1.4.7