src/Sim/Pipeline/Renamer/Renamer.cpp

説明を見る。
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 #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         // member `FbN
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 // arrayopCo|C^os
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 // l[s
00145 void Renamer::Rename( OpIterator op )
00146 {
00147     // WOHook
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 // Create an entry of MemOrderManager
00162 void Renamer::CreateMemOrderManagerEntry( OpIterator op )
00163 {
00164     if( op->GetOpClass().IsMem() ){
00165         op->GetThread()->GetMemOrderManager()->Allocate( op );
00166     }
00167 }
00168 
00169 // Predict latency of an op.
00170 // Latency prediction is done on renaming stages.
00171 void Renamer::Steer( OpIterator op )
00172 {
00173     // Steering
00174     HOOK_SECTION_OP( s_steerHook, op )
00175     {
00176         Scheduler* sched = m_steerer->Steer( op );
00177         op->SetScheduler( sched );
00178     }
00179 
00180     // Process after renaming 
00181     // - Steer ops to schedulers.
00182     // - Predict latency of an op.
00183     //   Latency prediction is done on renaming stages.
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     // Stall rename stages if there are any threads that can not allocate RMT etc.. entries.
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     // regDepPred `FbN
00227     if( !m_regDepPred[localTID]->CanAllocate( renamingOps->data(), numOps ) ) {
00228         ++m_stallCycles.regDepPred;
00229         return false;
00230     }
00231 
00232     // memDepPred `FbN
00233     if( !m_memDepPred[localTID]->CanAllocate( renamingOps->data(), numOps ) ) {
00234         ++m_stallCycles.memDepPred;
00235         return false;
00236     }
00237 
00238     // memOrderManager `FbN
00239     if( !m_memOrderManager[localTID]->CanAllocate( renamingOps->data(), numOps ) ) {
00240         ++m_stallCycles.memOrderManager;
00241         return false;
00242     }
00243 
00244     return true;
00245 }
00246 
00247 // Processing a NOP.
00248 // NOP is not dispatched.
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     // Set an op finished.
00260     op->SetStatus( OpStatus::OS_NOP );
00261     g_dumper.Dump( DS_COMMITTABLE, op );
00262 }
00263 
00264 // Enter an op to a renamer pipeline.
00265 // An op is send to a dispatcher automatically when the op exits a renamer pipeline.
00266 // A dispatcher is set to a renamer by the dispatcher itself in SetUpperPipelineNode
00267 // that calls SetLowerPipelineNode of the renamer.
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 // ClockedResource
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         // Stall this node and upper pipelines.
00289         // Do not stall ops where renaming is already 
00290         // started before this cycle.
00291         StallThisNodeAndUpperThisCycle();
00292     } 
00293 }
00294 
00295 // Dispatch all ops in the latch if a renamer is not stalled.
00296 void Renamer::Update()
00297 {
00298 
00299     for( PipelineLatch::iterator i = m_latch.begin(); i != m_latch.end(); /*Do not ++i*/ ){
00300 
00301         RenamingOpArray ops;
00302 
00303         // Pack micro-ops that belong to one instruction to 'ops'
00304         // for processing one instruction as a unit.
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         // Process NOP
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         // Create a checkpoint
00320         ForEachOp1( &ops, true/*before*/, &Renamer::BackupOnCheckpoint );
00321 
00322         // rename
00323         ForEachOp( &ops, &Renamer::Rename );
00324 
00325         // Create a checkpoint
00326         ForEachOp1( &ops, false/*before*/, &Renamer::BackupOnCheckpoint );
00327 
00328         // Create an entry of MemOrderManager
00329         ForEachOp( &ops, &Renamer::CreateMemOrderManagerEntry );
00330 
00331         // Do latency prediction
00332         ForEachOp( &ops, &Renamer::Steer );
00333 
00334         // All processes are done and now enter ops to pipeline.
00335         ForEachOp( &ops, &Renamer::EnterPipeline );
00336 
00337     }
00338 
00339 }
00340 
00341 void Renamer::Commit( OpIterator op )
00342 {
00343     m_latPred->Commit( op );
00344 }

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