00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <pch.h>
00033
00034 #include "Sim/Pipeline/Renamer/Renamer.h"
00035
00036 #include "Sim/Dumper/Dumper.h"
00037
00038 #include "Sim/Foundation/Hook/Hook.h"
00039 #include "Sim/Foundation/Hook/HookUtil.h"
00040 #include "Sim/Predictor/DepPred/RegDepPred/RegDepPredIF.h"
00041 #include "Sim/Predictor/DepPred/MemDepPred/MemDepPredIF.h"
00042 #include "Sim/Memory/MemOrderManager/MemOrderManager.h"
00043 #include "Sim/Thread/Thread.h"
00044 #include "Sim/Core/Core.h"
00045
00046 #include "Sim/Foundation/Checkpoint/CheckpointMaster.h"
00047 #include "Sim/ISAInfo.h"
00048 #include "Sim/Dependency/PhyReg/PhyReg.h"
00049 #include "Sim/Register/RegisterFile.h"
00050 #include "Sim/Op/Op.h"
00051 #include "Sim/Pipeline/Dispatcher/Steerer/SteererIF.h"
00052 #include "Sim/Predictor/LatPred/LatPred.h"
00053
00054 using namespace std;
00055 using namespace boost;
00056 using namespace Onikiri;
00057
00058 namespace Onikiri
00059 {
00060 HookPoint< Renamer > Renamer::s_renameEvaluateHook;
00061 HookPoint< Renamer > Renamer::s_renameUpdateHook;
00062 HookPoint< Renamer > Renamer::s_steerHook;
00063 }
00064
00065
00066 Renamer::Renamer() :
00067 m_renameLatency(0),
00068 m_steerer(0),
00069 m_latPred(0),
00070 m_numRenamedOps(0)
00071 {
00072 }
00073
00074 Renamer::~Renamer()
00075 {
00076 }
00077
00078 void Renamer::Initialize(InitPhase phase)
00079 {
00080 PipelineNodeBase::Initialize(phase);
00081
00082 if( phase == INIT_PRE_CONNECTION ){
00083 LoadParam();
00084 }
00085 else if( phase == INIT_POST_CONNECTION ){
00086
00087 int threadCount = GetCore()->GetThreadCount();
00088 if( m_regDepPred.GetSize() != threadCount ||
00089 m_memDepPred.GetSize() != threadCount ||
00090 m_memOrderManager.GetSize() != threadCount
00091 ){
00092 THROW_RUNTIME_ERROR(
00093 "The counts of the "
00094 "'regDepPred' (%d), m_memDepPred(%d), memOrderManager(%d) "
00095 "are not equal to the thread coount of the core(%d)." ,
00096 m_regDepPred.GetSize(),
00097 m_memDepPred.GetSize(),
00098 m_memOrderManager.GetSize(),
00099 threadCount
00100 );
00101 }
00102
00103
00104 if( m_renameLatency == 0 ){
00105 THROW_RUNTIME_ERROR( "rename latency is zero." );
00106 }
00107 }
00108 }
00109
00110 void Renamer::Finalize()
00111 {
00112 m_stallCycles.total = GetStalledCycles();
00113
00114 m_stallCycles.others =
00115 m_stallCycles.total -
00116 m_stallCycles.regDepPred -
00117 m_stallCycles.memDepPred -
00118 m_stallCycles.memOrderManager;
00119
00120 ReleaseParam();
00121 }
00122
00123
00124 inline void Renamer::ForEachOp(
00125 RenamingOpArray* c,
00126 void (Renamer::*func)(OpIterator) )
00127 {
00128 for( RenamingOpArray::iterator i = c->begin(); i != c->end(); ++i ){
00129 (this->*func)(*i);
00130 }
00131 }
00132
00133 template <typename T1>
00134 inline void Renamer::ForEachOp1(
00135 RenamingOpArray* c,
00136 T1 arg1,
00137 void (Renamer::*func)(OpIterator, T1) )
00138 {
00139 for( RenamingOpArray::iterator i = c->begin(); i != c->end(); ++i ){
00140 (this->*func)( *i, arg1 );
00141 }
00142 }
00143
00144
00145 void Renamer::Rename( OpIterator op )
00146 {
00147
00148 HOOK_SECTION_OP( s_renameUpdateHook, op ){
00149 int tid = op->GetLocalTID();
00150
00151 m_regDepPred[ tid ]->Resolve( op );
00152 m_regDepPred[ tid ]->Allocate( op );
00153
00154 m_memDepPred[ tid ]->Resolve( op );
00155 m_memDepPred[ tid ]->Allocate( op );
00156 }
00157
00158 m_numRenamedOps++;
00159 }
00160
00161
00162 void Renamer::CreateMemOrderManagerEntry( OpIterator op )
00163 {
00164 if( op->GetOpClass().IsMem() ){
00165 op->GetThread()->GetMemOrderManager()->Allocate( op );
00166 }
00167 }
00168
00169
00170
00171 void Renamer::Steer( OpIterator op )
00172 {
00173
00174 HOOK_SECTION_OP( s_steerHook, op )
00175 {
00176 Scheduler* sched = m_steerer->Steer( op );
00177 op->SetScheduler( sched );
00178 }
00179
00180
00181
00182
00183
00184 m_latPred->Predict( op );
00185 }
00186
00187 void Renamer::BackupOnCheckpoint( OpIterator op, bool before )
00188 {
00189 Core* core = op->GetCore();
00190 PC pc = op->GetPC();
00191 OpInfo* opInfo = op->GetOpInfo();
00192
00193 if( before && core->IsRequiredCheckpointBefore( pc, opInfo ) ){
00194 CheckpointMaster* master = op->GetThread()->GetCheckpointMaster();
00195 master->Backup( op->GetBeforeCheckpoint(), CheckpointMaster::SLOT_RENAME );
00196 }
00197
00198 if( !before && core->IsRequiredCheckpointAfter( pc, opInfo ) ){
00199 CheckpointMaster* master = op->GetThread()->GetCheckpointMaster();
00200 master->Backup( op->GetAfterCheckpoint(), CheckpointMaster::SLOT_RENAME );
00201 }
00202 }
00203
00204 bool Renamer::CanRename( RenamingOpArray* renamingOps )
00205 {
00206 if( renamingOps->size() == 0 ){
00207 THROW_RUNTIME_ERROR("Renaming 0 op.");
00208 }
00209
00210
00211 int numOps = 0;
00212 int numMemOps = 0;
00213 int localTID = renamingOps->at(0)->GetLocalTID();
00214
00215 for( RenamingOpArray::iterator i = renamingOps->begin(); i != renamingOps->end(); ++i ){
00216 ASSERT(
00217 (*i)->GetLocalTID() == localTID,
00218 "Mixed thread ops can not be renamed in one cycle."
00219 );
00220 numOps++;
00221 if( (*i)->GetOpClass().IsMem() ) {
00222 numMemOps++;
00223 }
00224 }
00225
00226
00227 if( !m_regDepPred[localTID]->CanAllocate( renamingOps->data(), numOps ) ) {
00228 ++m_stallCycles.regDepPred;
00229 return false;
00230 }
00231
00232
00233 if( !m_memDepPred[localTID]->CanAllocate( renamingOps->data(), numOps ) ) {
00234 ++m_stallCycles.memDepPred;
00235 return false;
00236 }
00237
00238
00239 if( !m_memOrderManager[localTID]->CanAllocate( renamingOps->data(), numOps ) ) {
00240 ++m_stallCycles.memOrderManager;
00241 return false;
00242 }
00243
00244 return true;
00245 }
00246
00247
00248
00249 void Renamer::ProcessNOP( OpIterator op )
00250 {
00251 ASSERT( op->GetDstRegNum() == 0, "NOP has a destination operand." );
00252
00253 Core* core = op->GetCore();
00254 if( core->GetCheckpointingPolicy() == CP_ALL ){
00255 BackupOnCheckpoint( op, true );
00256 BackupOnCheckpoint( op, false );
00257 }
00258
00259
00260 op->SetStatus( OpStatus::OS_NOP );
00261 g_dumper.Dump( DS_COMMITTABLE, op );
00262 }
00263
00264
00265
00266
00267
00268 void Renamer::EnterPipeline( OpIterator op )
00269 {
00270 GetLowerPipeline()->EnterPipeline( op, m_renameLatency - 1, GetLowerPipelineNode() );
00271 op->SetStatus( OpStatus::OS_RENAME );
00272 g_dumper.Dump( DS_RENAME, op );
00273 }
00274
00275
00276 void Renamer::Evaluate()
00277 {
00278 BaseType::Evaluate();
00279 RenamingOpArray renamingOps;
00280
00281 for( PipelineLatch::iterator i = m_latch.begin(); i != m_latch.end(); ++i ){
00282 HOOK_SECTION_OP( s_renameEvaluateHook, *i ){
00283 renamingOps.push_back( *i );
00284 }
00285 }
00286
00287 if( renamingOps.size() > 0 && !CanRename( &renamingOps ) ){
00288
00289
00290
00291 StallThisNodeAndUpperThisCycle();
00292 }
00293 }
00294
00295
00296 void Renamer::Update()
00297 {
00298
00299 for( PipelineLatch::iterator i = m_latch.begin(); i != m_latch.end(); ){
00300
00301 RenamingOpArray ops;
00302
00303
00304
00305 PC orgPC = (*i)->GetPC();
00306 do{
00307 ops.push_back( *i );
00308 i = m_latch.erase( i );
00309 }
00310 while( i != m_latch.end() && orgPC == (*i)->GetPC() );
00311
00312
00313 if( ops[0]->GetOpClass().IsNop() ) {
00314 ASSERT( ops.size() == 1, "NOP is divided to multiple ops." );
00315 ProcessNOP( ops[0] );
00316 continue;
00317 }
00318
00319
00320 ForEachOp1( &ops, true, &Renamer::BackupOnCheckpoint );
00321
00322
00323 ForEachOp( &ops, &Renamer::Rename );
00324
00325
00326 ForEachOp1( &ops, false, &Renamer::BackupOnCheckpoint );
00327
00328
00329 ForEachOp( &ops, &Renamer::CreateMemOrderManagerEntry );
00330
00331
00332 ForEachOp( &ops, &Renamer::Steer );
00333
00334
00335 ForEachOp( &ops, &Renamer::EnterPipeline );
00336
00337 }
00338
00339 }
00340
00341 void Renamer::Commit( OpIterator op )
00342 {
00343 m_latPred->Commit( op );
00344 }