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_PIPELINE_PIPELINE_NODE_BASE_H 00033 #define SIM_PIPELINE_PIPELINE_NODE_BASE_H 00034 00035 #include "Utility/RuntimeError.h" 00036 00037 #include "Sim/Foundation/Resource/ResourceNode.h" 00038 #include "Sim/Pipeline/PipelineNodeIF.h" 00039 #include "Sim/Pipeline/Pipeline.h" 00040 #include "Sim/Pipeline/PipelineLatch.h" 00041 00042 namespace Onikiri 00043 { 00044 class Thread; 00045 class Core; 00046 00047 // A base class of Fetcher/Renamer/Dispatcher/Scheduler/Retirer 00048 class PipelineNodeBase : 00049 public ClockedResourceBase, 00050 public PipelineNodeIF, 00051 public PhysicalResourceNode 00052 { 00053 00054 public: 00055 00056 const char* Who() const 00057 { 00058 return PhysicalResourceNode::Who(); 00059 }; 00060 00061 PipelineNodeBase() : 00062 m_initialized( false ), 00063 m_enableLatch( true ), 00064 m_upperPipelineNode( NULL ), 00065 m_upperPipeline( NULL ), 00066 m_lowerPipelineNode( NULL ) 00067 { 00068 BaseT::AddChild( &m_latch ); // gcc needs 'BaseT::' 00069 BaseT::AddChild( &m_lowerPipeline ); 00070 m_lowerPipeline.AddUpperPipelineNode( this ); 00071 } 00072 00073 virtual ~PipelineNodeBase() 00074 { 00075 ASSERT( m_initialized, "Initialize() has not been called." ); 00076 } 00077 00078 virtual void Initialize( InitPhase phase ) 00079 { 00080 if( phase == INIT_POST_CONNECTION ){ 00081 if( m_thread.GetSize() == 0 ) { 00082 THROW_RUNTIME_ERROR("thread not set."); 00083 } 00084 if( m_core.GetSize() == 0 ) { 00085 THROW_RUNTIME_ERROR("core not set."); 00086 } 00087 } 00088 00089 m_initialized = true; 00090 } 00091 00092 // Stall handlers 00093 virtual void StallThisCycle() 00094 { 00095 BaseT::StallThisCycle(); 00096 00097 PipelineNodeIF* upper = GetUpperPipelineNode(); 00098 if( upper ){ 00099 upper->StallThisCycle(); 00100 } 00101 } 00102 00103 virtual void StallNextCycle( int cycle ) 00104 { 00105 BaseT::StallNextCycle( cycle ); 00106 00107 PipelineNodeIF* upper = GetUpperPipelineNode(); 00108 if( upper ){ 00109 upper->StallNextCycle( cycle ); 00110 } 00111 } 00112 00113 // Stall only upper pipelines and the latch. 00114 // A pipeline next to this node is not stalled. 00115 virtual void StallThisNodeAndUpperThisCycle() 00116 { 00117 PipelineNodeIF* upper = GetUpperPipelineNode(); 00118 if( upper ){ 00119 upper->StallThisCycle(); 00120 } 00121 if( m_enableLatch ){ 00122 m_latch.StallThisCycle(); 00123 } 00124 BaseT::StallThisCycleExcludingChildren(); // gcc needs 'BaseT::' 00125 } 00126 00127 // This method is called when an op exits on upper pipeline. 00128 // A pipeline that writes a buffer like Dispatcher 00129 // overwrites this method. 00130 virtual void ExitUpperPipeline( OpIterator op ) 00131 { 00132 if( m_enableLatch ){ 00133 m_latch.Receive( op ); 00134 } 00135 }; 00136 00137 // This method is called when an op exits an lower pipeline. 00138 virtual void ExitLowerPipeline( OpIterator op ) 00139 { 00140 }; 00141 00142 // Link pipeline nodes. 00143 virtual void SetUpperPipelineNode( PipelineNodeIF* upper ) 00144 { 00145 m_upperPipelineNode = upper; 00146 m_upperPipeline = upper->GetLowerPipeline(); 00147 upper->SetLowerPipelineNode( this ); 00148 } 00149 00150 virtual void SetLowerPipelineNode( PipelineNodeIF* lower ) 00151 { 00152 m_lowerPipelineNode = lower; 00153 } 00154 00155 // Pipeline 00156 virtual Pipeline* GetLowerPipeline() 00157 { 00158 return &m_lowerPipeline; 00159 } 00160 00161 // PipelineNode 00162 virtual PipelineNodeIF* GetLowerPipelineNode() 00163 { 00164 return m_lowerPipelineNode; 00165 } 00166 00167 // pCvCm[h 00168 virtual PipelineNodeIF* GetUpperPipelineNode() 00169 { 00170 return m_upperPipelineNode; 00171 } 00172 00173 // Returns whether this node can allocate entries or not. 00174 virtual bool CanAllocate( int ops ) 00175 { 00176 return true; 00177 } 00178 00179 // Add an external lower pipeline. 00180 virtual void AddLowerPipeline( Pipeline* pipe ) 00181 { 00182 this->AddChild( pipe ); // gcc needs 'BaseT::' 00183 pipe->AddUpperPipelineNode( this ); 00184 m_exLowerPipelines.push_back( pipe ); 00185 } 00186 00187 virtual void Commit( OpIterator op ){} 00188 virtual void Cancel( OpIterator op ){} 00189 00190 virtual void Flush( OpIterator op ) 00191 { 00192 if( m_enableLatch ){ 00193 m_latch.Delete( op ); 00194 } 00195 m_lowerPipeline.Flush( op ); 00196 for( size_t i = 0; i < m_exLowerPipelines.size(); i++ ){ 00197 m_exLowerPipelines[i]->Flush( op ); 00198 } 00199 } 00200 00201 virtual void Retire( OpIterator op ) 00202 { 00203 if( m_enableLatch ){ 00204 m_latch.Delete( op ); 00205 } 00206 m_lowerPipeline.Retire( op ); 00207 for( size_t i = 0; i < m_exLowerPipelines.size(); i++ ){ 00208 m_exLowerPipelines[i]->Retire( op ); 00209 } 00210 } 00211 00212 // Disable a pipeline latch if a latch is not used for optimization. 00213 void DisableLatch() 00214 { 00215 for( Children::iterator i = m_children.begin(); i != m_children.end(); ++i ){ 00216 if( *i == (ClockedResourceIF*)&m_latch ){ 00217 m_children.erase( i ); 00218 break; 00219 } 00220 } 00221 m_enableLatch = false; 00222 } 00223 00224 // accessors 00225 Core* GetCore( int index = 0 ) { return m_core[index]; } 00226 protected: 00227 bool m_initialized; 00228 bool m_enableLatch; 00229 typedef ClockedResourceBase BaseT; 00230 00231 PipelineLatch m_latch; 00232 PhysicalResourceArray<Thread> m_thread; 00233 PhysicalResourceArray<Core> m_core; 00234 00235 PipelineNodeIF* m_upperPipelineNode; 00236 Pipeline* m_upperPipeline; 00237 PipelineNodeIF* m_lowerPipelineNode; 00238 Pipeline m_lowerPipeline; 00239 std::vector<Pipeline*> m_exLowerPipelines; 00240 }; 00241 00242 }; // namespace Onikiri 00243 00244 #endif // SIM_PIPELINE_PIPELINE_NODE_BASE_H