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/Dumper/VisualizationDumper.h"
00035
00036 #include "Sim/Dumper/DumpState.h"
00037 #include "Sim/Op/Op.h"
00038 #include "Sim/Core/Core.h"
00039 #include "Sim/Dumper/DumpFileName.h"
00040 #include "Version.h"
00041
00042 using namespace Onikiri;
00043 using namespace std;
00044 using namespace boost;
00045
00046 static const char g_kanataFileFormatHeader[] = "Kanata";
00047
00048 VisualizationDumper::OpState::OpState() :
00049 dumpState( DS_INVALID ),
00050 visSerialID( INVALID_VIS_SERIAL ),
00051 inPipeline( false ),
00052 stalled( false ),
00053 lastRawStages()
00054 {
00055 }
00056
00057 static const String MakeKanataHeaderString()
00058 {
00059 String headerStr;
00060 headerStr.format(
00061 "%s\t%04x\n",
00062 g_kanataFileFormatHeader,
00063 ONIKIRI_KANATA_FILE_VERSION
00064 );
00065 return headerStr;
00066 }
00067
00068 VisualizationDumper::VisualizationDumper()
00069 {
00070 m_visLastPrintCycle = 0;
00071 m_visCurrentCycle = 0;
00072 m_enabled = false;
00073 m_skipInsns = 0;
00074 m_visSerialID = 0;
00075 }
00076
00077 VisualizationDumper::~VisualizationDumper()
00078 {
00079 }
00080
00081
00082
00083
00084
00085 VisualizationDumper::OpState* VisualizationDumper::GetOpState( OpIterator op )
00086 {
00087 return &m_coreStateTable[op->GetCore()].opState[op];
00088 }
00089
00090 DUMP_STATE VisualizationDumper::GetLastState( OpIterator op )
00091 {
00092 return GetOpState(op)->dumpState;
00093 }
00094
00095 void VisualizationDumper::SetLastState( OpIterator op, DUMP_STATE state )
00096 {
00097 GetOpState(op)->dumpState = state;
00098 }
00099
00100 u64 VisualizationDumper::GetVisSerialID( OpIterator op )
00101 {
00102 return GetOpState(op)->visSerialID;
00103 }
00104
00105 void VisualizationDumper::SetVisSerialID( OpIterator op, u64 visSerialID)
00106 {
00107 GetOpState(op)->visSerialID = visSerialID;
00108 }
00109
00110
00111 bool VisualizationDumper::IsEnabled()
00112 {
00113 return m_enabled;
00114 }
00115
00116
00117 bool VisualizationDumper::IsDumpSkipped( OpIterator op )
00118 {
00119 return ( GetTotalRetiredInsnCount() < m_skipInsns ) ? true : false;
00120 }
00121
00122
00123 const char* VisualizationDumper::ToStringFromDumpState( DUMP_STATE state )
00124 {
00125 return g_visualizerDumperStrTbl[state];
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 void VisualizationDumper::PrintOpInitLabel( const OpIterator op )
00135 {
00136 stringstream label;
00137 label <<
00138 hex << op->GetPC().address <<
00139 dec << " ";
00140
00141 OpInfo* opInfo = op->GetOpInfo();
00142
00143
00144 int dstNum = op->GetOpInfo()->GetDstNum();
00145 if( dstNum != 0 ){
00146 if( dstNum == 1 ){
00147 label << "r" << opInfo->GetDstOperand( 0 );
00148 }
00149 else{
00150 label << "(";
00151
00152 bool first = true;
00153 for( int i = 0; i < opInfo->GetDstNum(); i++ ){
00154 if( !first ){
00155 label << ", ";
00156 }
00157 label << "r" << opInfo->GetDstOperand( i );
00158 first = false;
00159 }
00160 label << ")";
00161 }
00162
00163 label << " = ";
00164 }
00165
00166
00167
00168
00169 label << opInfo->GetMnemonic() << "(";
00170
00171
00172 bool first = true;
00173 for (int j = 0; j < opInfo->GetSrcNum(); j++)
00174 {
00175 if (!first) label << ", ";
00176 label << "r" << opInfo->GetSrcOperand(j);
00177 first = false;
00178 }
00179 label << ")";
00180
00181 PrintOpLabel( op, POLT_LABEL, label.str() );
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 void VisualizationDumper::PrintOpInit(OpIterator op)
00195 {
00196
00197 u64 visSerialID = m_visSerialID;
00198 m_visSerialID++;
00199 SetVisSerialID( op, visSerialID );
00200
00201
00202 m_visStream <<
00203 "I\t" <<
00204 visSerialID << "\t" <<
00205 op->GetGlobalSerialID() << "\t" <<
00206 op->GetTID() << "\n";
00207
00208
00209 PrintOpInitLabel( op );
00210
00211
00212 OpState* opState = GetOpState( op );
00213 opState->inPipeline = true;
00214 opState->stalled = false;
00215 opState->lastRawStages.clear();
00216 }
00217
00218
00219
00220
00221 void VisualizationDumper::PrintOpLabel( const OpIterator op, OpLabelType type, const string& label )
00222 {
00223 m_visStream <<
00224 "L\t" <<
00225 GetVisSerialID( op ) << "\t" <<
00226 (type == POLT_LABEL ? '0' : '1' ) << "\t" <<
00227 label << "\n";
00228 }
00229
00230 void VisualizationDumper::PrintCycle()
00231 {
00232 stringstream stream;
00233 if (m_enabled && m_visLastPrintCycle != m_visCurrentCycle) {
00234 if (m_visLastPrintCycle == 0) {
00235 stream << "C=\t" << m_visCurrentCycle << "\n";
00236 } else {
00237 stream << "C\t" << (m_visCurrentCycle - m_visLastPrintCycle) << "\n";
00238 }
00239 m_visLastPrintCycle = m_visCurrentCycle;
00240 }
00241 m_visStream << stream.str();
00242 }
00243
00244
00245
00246 void VisualizationDumper::PrintNextPipelineStage( const OpIterator op, DUMP_STATE state )
00247 {
00248 m_visStream <<
00249 "S\t" <<
00250 GetVisSerialID( op ) << "\t" <<
00251 "0" << "\t" <<
00252 ToStringFromDumpState(state) << "\n";
00253 }
00254
00255
00256 void VisualizationDumper::PrintLastPipelineStage( const OpIterator op, DUMP_STATE lastState )
00257 {
00258 m_visStream <<
00259 "E\t" <<
00260 GetVisSerialID( op ) << "\t" <<
00261 "0" << "\t" <<
00262 ToStringFromDumpState(lastState) << "\n";
00263 }
00264
00265 void VisualizationDumper::PrintStallBody( OpIterator op, bool stall )
00266 {
00267 const char* tag = stall ? "S\t" : "E\t";
00268 m_visStream <<
00269 tag <<
00270 GetVisSerialID( op ) << "\t" <<
00271 "1\t" <<
00272 "stl\t" <<
00273 "\n";
00274 }
00275
00276
00277 void VisualizationDumper::PrintRawOutput(
00278 OpIterator op, bool begin, const char*stage, DumpLane lane
00279 ){
00280 if(!m_enabled)
00281 return;
00282 if( IsDumpSkipped( op ) )
00283 return;
00284
00285 OpState* opState = GetOpState( op );
00286 if( !opState->inPipeline )
00287 return;
00288
00289 OpState::Stage* info = &opState->lastRawStages[lane];
00290
00291 if( begin && info->in ){
00292 PrintRawOutput( op, false, info->name.c_str(), lane );
00293 }
00294
00295 PrintCycle();
00296
00297 const char* tag = begin ? "S\t" : "E\t";
00298 m_visStream <<
00299 tag <<
00300 GetVisSerialID( op ) << "\t" <<
00301 lane << "\t" <<
00302 stage << "\t" <<
00303 "\n";
00304
00305 info->in = begin;
00306 info->name = stage;
00307 }
00308
00309 void VisualizationDumper::PrintStall( const OpIterator op, bool stall )
00310 {
00311 if(!m_enabled)
00312 return;
00313 if( IsDumpSkipped( op ) )
00314 return;
00315 if( !GetOpState( op )->inPipeline )
00316 return;
00317
00318 OpState* state = GetOpState( op );
00319 ASSERT(
00320 state->stalled != stall,
00321 "%s\nOp serial ID: %lld",
00322 stall ?
00323 "Stall overlap." :
00324 "The op that is not stalled is finished from stall.",
00325 op->GetSerialID()
00326 );
00327 state->stalled = stall;
00328
00329 PrintCycle();
00330 PrintStallBody( op, stall );
00331 }
00332
00333 void VisualizationDumper::PrintStallBegin( const OpIterator op )
00334 {
00335 PrintStall( op, true );
00336 }
00337
00338 void VisualizationDumper::PrintStallEnd( const OpIterator op )
00339 {
00340 PrintStall( op, false );
00341 }
00342
00343
00344 void VisualizationDumper::PrintOpEndLabel( const OpIterator op )
00345 {
00346 OpInfo* opInfo = op->GetOpInfo();
00347 OpStatus opState = op->GetStatus();
00348 stringstream label;
00349
00350
00351 if( opState >= OpStatus::OS_RENAME ){
00352
00353
00354 int dstNum = opInfo->GetDstNum();
00355 if( dstNum != 0 ){
00356 if( dstNum == 1 ){
00357 label << "p" << op->GetDstReg(0) <<
00358 ":0x" << hex << op->GetDst(0) << dec;
00359 }
00360 else{
00361 bool first = true;
00362 label << "(";
00363 for (int i = 0; i < opInfo->GetDstNum(); i++){
00364 if( !first ){
00365 label << ", ";
00366 }
00367 label << "p" << op->GetDstReg(i) <<
00368 ":0x" << hex << op->GetDst(i) << dec;
00369 first = false;
00370 }
00371 label << ")\n";
00372 }
00373 label << " = ";
00374 }
00375
00376 }
00377
00378
00379 label << OpClassCode::ToString(op->GetOpClass().GetCode()) << "( ";
00380
00381
00382
00383
00384 if( opState >= OpStatus::OS_RENAME ){
00385 bool first = true;
00386 for( int j = 0; j < opInfo->GetSrcNum(); j++ ){
00387 if( !first ){
00388 label << ", ";
00389 }
00390 label <<
00391 "p" << op->GetSrcReg(j) <<
00392 ":0x" << hex << op->GetSrc(j) << dec;
00393 first = false;
00394 }
00395 }
00396
00397 label << " )";
00398
00399
00400 if( op->GetOpClass().IsMem() ){
00401 label <<
00402 " [addr: 0x" <<
00403 hex << op->GetMemAccess().address.address << dec << "]";
00404 }
00405
00406
00407
00408 PrintOpLabel( op, POLT_DETAIL, label.str() );
00409
00410 }
00411
00412 void VisualizationDumper::PrintOpEnd( const OpIterator op, DUMP_STATE state )
00413 {
00414
00415 OpState* opExState = GetOpState( op );
00416
00417 typedef map< DumpLane, OpState::Stage >::iterator iterator;
00418 for( iterator i = opExState->lastRawStages.begin();
00419 i != opExState->lastRawStages.end();
00420 ++i
00421 ){
00422 if( i->second.in ){
00423 PrintRawOutput( op, false, i->second.name.c_str(), i->first );
00424 }
00425 }
00426
00427 PrintOpEndLabel( op );
00428
00429
00430 m_visStream <<
00431 "R\t" <<
00432 GetVisSerialID( op ) << "\t" <<
00433 op->GetRetireID() << "\t" <<
00434 (state == DS_RETIRE ? "0" : "1") << "\n";
00435
00436
00437 GetOpState( op )->inPipeline = false;
00438 }
00439
00440
00441 void VisualizationDumper::Initialize(
00442 const String& suffix,
00443 PhysicalResourceArray<Core>& coreList
00444 ){
00445 m_visCurrentCycle = 0;
00446 m_visLastPrintCycle = 0;
00447
00448 LoadParam();
00449 if( IsEnabled() ){
00450 String fileName =
00451 g_env.GetHostWorkPath() +
00452 MakeDumpFileName( m_visFileName, suffix, m_gzipEnabled );
00453
00454 if (m_gzipEnabled){
00455 m_visStream.push(
00456 iostreams::gzip_compressor(
00457 iostreams::gzip_params(m_gzipLevel)
00458 )
00459 );
00460 }
00461
00462 m_visStream.push( iostreams::file_sink( fileName, ios::binary ) );
00463 m_visStream << MakeKanataHeaderString().c_str();
00464
00465
00466 for( int i = 0; i < coreList.GetSize(); i++ ){
00467 CoreState* coreState = &m_coreStateTable[ coreList[i] ];
00468 coreState->opState.Resize( *coreList[i]->GetOpArray() );
00469 for( int j = 0; j < coreList[i]->GetThreadCount(); j++ ){
00470 m_threadStateTable[ coreList[i]->GetThread(j) ].retiredInsnCount = 0;
00471 }
00472
00473 }
00474 }
00475 }
00476
00477
00478 void VisualizationDumper::Finalize()
00479 {
00480 ReleaseParam();
00481 }
00482
00483
00484
00485
00486 void VisualizationDumper::PrintOpState(OpIterator op, DUMP_STATE state)
00487 {
00488 if( !m_enabled )
00489 return;
00490
00491 if( IsDumpSkipped( op ) )
00492 return;
00493
00494 if( !GetOpState( op )->inPipeline && state != DS_FETCH )
00495 return;
00496
00497 PrintCycle();
00498
00499
00500 if(state == DS_FETCH ){
00501 PrintOpInit(op);
00502 }
00503 else{
00504
00505 PrintLastPipelineStage( op, GetLastState(op) );
00506 }
00507
00508 if( state == DS_RETIRE || state == DS_FLUSH ){
00509
00510 PrintOpEnd( op, state );
00511 } else {
00512
00513 PrintNextPipelineStage( op, state );
00514 SetLastState( op, state );
00515 }
00516 }
00517
00518
00519
00520 void VisualizationDumper::PrintOpDependency(
00521 const OpIterator producerOp,
00522 const OpIterator consumerOp,
00523 DumpDependency type
00524 ){
00525 if( !m_enabled )
00526 return;
00527 if( IsDumpSkipped( producerOp ) )
00528 return;
00529
00530 if( !GetOpState( consumerOp )->inPipeline || !GetOpState( producerOp )->inPipeline )
00531 return;
00532
00533 PrintCycle();
00534 m_visStream <<
00535 "W\t" <<
00536 GetVisSerialID( consumerOp ) << "\t" <<
00537 GetVisSerialID( producerOp ) << "\t" <<
00538 type << "\n";
00539 }
00540
00541
00542 void VisualizationDumper::SetCurrentCycle(const s64 cycle)
00543 {
00544 m_visCurrentCycle = cycle;
00545 }
00546
00547 void VisualizationDumper::SetCurrentInsnCount( Thread* thread, const s64 count )
00548 {
00549 m_threadStateTable[thread].retiredInsnCount = count;
00550 }
00551
00552 s64 VisualizationDumper::GetTotalRetiredInsnCount()
00553 {
00554 s64 count = 0;
00555 for( ThreadStateMap::iterator i = m_threadStateTable.begin(); i != m_threadStateTable.end(); ++i ){
00556 count += i->second.retiredInsnCount;
00557 }
00558 return count;
00559 }