00001
00002
00003
00004
00005 #include <iostream.h>
00006 #include <string.h>
00007 #include "legoUtil.H"
00008 #include "lmdes.h"
00009 #include "RU_manager.h"
00010 #include "machine.h"
00011 #include "l_alloc_new.h"
00012 #include "mdes2.h"
00013 #include "lmdes.h"
00014
00015
00016
00017 #ifdef _MACHINE_DEBUG_
00018 #define derr(s) cerr << s
00019 #else
00020 #define derr(s)
00021 #endif
00022
00023
00024
00025 #define SchedLengthErrMsg(X,Y,Z) \
00026 cerr << "\nERROR: machine::" << X << "\n"; \
00027 cerr << "\tcycle " << (Y) << " >= RT size " << MaxScheduleLength \
00028 << "\n"; \
00029 cerr << "\tOp " << (Z) << "\n"; \
00030 exit( -1 )
00031
00032 #define ComputeNumBuses(X) (X) < 1 ? totalSlots : (X)
00033
00034 enum TinkerOpType machine::TinkerOptype( legoOp *Op );
00035 double GetSuperblockWeight( legoOp *RRTop, machine *m );
00036
00037 static char *FunctionName;
00038
00039 L_Alloc_Pool *Operand_ready_pool = NULL;
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 static double GetOpFrequency( legoOp *op )
00050 {
00051 attrs *wtattr;
00052 legoOprd *oprd;
00053
00054 wtattr = FindLcAttribute ("orig_wt", op);
00055 if (wtattr == NULL) return -1.0;
00056
00057 oprd = wtattr->GetAttrOprdPtr();
00058 if (oprd == NULL || oprd->GetOprdType() != OT_LITERAL_D) return -1.0;
00059
00060 return oprd->GetLiteralDouble();
00061 }
00062
00063
00064
00065
00066 int machine::opLatency(int opCode )
00067 {
00068 int alt_id,lat;
00069 alt_id = mdes_heuristic_alt_id (opCode);
00070
00071 return(mdes_max_completion_time (opCode, alt_id));
00072 }
00073
00074
00075 int machine::opLatency( legoOp *Op )
00076 {
00077
00078 int opCode, alt_id;
00079 RU_Info *ru_info;
00080
00081 opCode = Op->GetBaseOpcode();
00082
00083 if (Op->GetSchedTime() == -1) {
00084 alt_id = mdes_heuristic_alt_id (opCode);
00085 }
00086 else {
00087 ru_info = Op->GetRUInfoPtr();
00088 alt_id = RU_SELECTED_ALT_ID(ru_info);
00089 }
00090
00091 return(mdes_max_completion_time (opCode, alt_id));
00092 }
00093
00094
00095
00096
00097 enum TinkerOpType machine::TinkerOptype( int opcode )
00098 {
00099 int lego_opc = opcode;
00100
00101 if((( lego_opc >= NO_OP ) && ( lego_opc <= XORCM_W )) ||
00102 (( lego_opc >= EXTS_B ) && ( lego_opc <= MOVE )) ||
00103 (( lego_opc >= LDCM ) && ( lego_opc <= CMPR_W_EV )) ||
00104 (( lego_opc >= CMPP ) && ( lego_opc <= CMPP_W_EV_AC_AC )) ||
00105 (( lego_opc >= PBRR ) && ( lego_opc <= PBRA )) ||
00106 lego_opc == DEFINE || lego_opc == ALLOC || lego_opc == LDPRED ||
00107 lego_opc == LIMM)
00108 return INT_OP;
00109 else if((( lego_opc >= FADD_S ) && ( lego_opc <= CONVDS )) ||
00110 (( lego_opc >= MOVEF_S ) && ( lego_opc <= MOVEF_D )) ||
00111 (( lego_opc >= FCMPR_S_FALSE ) && ( lego_opc <= FCMPR_D_TRUE )) ||
00112 (( lego_opc >= FCMPP_S_FALSE_UN_UN ) && ( lego_opc <= FCMPP_D_TRUE_AC_AC )) ||
00113 lego_opc == FLIMM)
00114 return FP_OP;
00115 else if ((( lego_opc >= L_B_V1_V1 ) && ( lego_opc <= FDSLD_INC_D_C3_C3 )) ||
00116 (( lego_opc >= MOVEGF_L ) && ( lego_opc <= MOVEGF_U )) ||
00117 (( lego_opc >= MOVEGF_L ) && ( lego_opc <= MOVEPG )) ||
00118 (( lego_opc >= DVLD_B ) && ( lego_opc <= FDVLD_D )))
00119 return MEM_OP;
00120 else if (( lego_opc >= BRDVI ) && ( lego_opc <= BRDVF ) ||
00121 ( lego_opc >= BRU ) && ( lego_opc <= BRW_F_F_F ) ||
00122 lego_opc == CONTROL_MERGE || lego_opc == MERGE ||
00123 lego_opc == DUMMY_BR || lego_opc == C_MERGE)
00124 return BR_OP;
00125 else {
00126 cerr << "TinkerOptype( opcode ): invalid opcode: " << lego_opc << "\n";
00127 exit(-1);
00128 }
00129 }
00130
00131
00132
00133
00134 enum TinkerOpType machine::TinkerOptype( legoOp *Op )
00135 {
00136 if(Op->GetOpcodePtr() == NULL)
00137 return TinkerOptype( Op->GetOpcode() );
00138 else
00139 {
00140
00141 if(Op->IsIntegerOp() || Op->IsDEFINEOp() || Op->IsCompareOp())
00142 return INT_OP;
00143 else if(Op->IsFloatOp())
00144 return FP_OP;
00145 else if(Op->IsLDOp() || Op->IsSTOp())
00146 return MEM_OP;
00147 else if(Op->IsBranchOp() || Op->IsDUMMYBROp() || Op->IsCMERGEOp())
00148 return BR_OP;
00149 else
00150 {
00151 cerr << "TinkerOptype( Op ): invalid base opcode: " <<
00152 Op->GetBaseOpcode() << "\n";
00153 exit(-1);
00154 }
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 int machine::isStoreOp( legoOp *Op )
00170 {
00171 return (Op->IsSTOp());
00172
00173
00174
00175
00176
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 int machine::isLoadOp( legoOp *Op )
00193 {
00194 return (Op->IsLDOp());
00195
00196
00197
00198
00199
00200
00201
00202
00203 }
00204
00205
00206
00207 int machine::isBranchOp( legoOp *Op )
00208 {
00209 if ( TinkerOptype( Op ) == BR_OP ) return 1;
00210 else return 0;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 int machine::isRealOp( legoOp *Op )
00228 {
00229 return Op->IsRealOp();
00230
00231
00232
00233 }
00234
00235
00236
00237 void machine::setIssueConfig()
00238 {
00239 int i, j;
00240
00241
00242 FunctionName = "setIssueConfig";
00243
00244
00245 totalSlots = mdes_total_slots();
00246
00247
00248
00249 RRT = new int[ totalSlots ][ MaxScheduleLength ];
00250
00251
00252 RRTop = new legoOp*[totalSlots][MaxScheduleLength];
00253
00254
00255 for ( i = 0; i < MaxScheduleLength; i++ )
00256 for ( j = 0; j < totalSlots; j++ ) {
00257 RRT[ j ][ i ] = EMPTY;
00258 RRTop[j][i] = NULL;
00259 }
00260
00261
00262 allocated = TRUE;
00263 }
00264
00265
00266
00267
00268 void machine::adjustIssueStatus( legoOp *Op, int cycle, int slot )
00269 {
00270 int start, stop, i, OpId;
00271 enum TinkerOpType opType;
00272
00273
00274 OpId = Op->GetOpId();
00275 if ( cycle >= MaxScheduleLength ) {
00276 SchedLengthErrMsg( "adjustIssueStatus", cycle, Op->GetOpId() );
00277 }
00278
00279 derr( ">> machine::adjustIssueStatus "
00280 << ", cycle " << cycle << "\n" );
00281
00282 RRT[ slot ][ cycle ] = OpId;
00283 RRTop[ slot ][ cycle ] = Op;
00284 LastIssueCycle = LastIssueCycle < cycle ? cycle : LastIssueCycle;
00285 derr( " placing " << OpId << " into slot " << slot << " <<\n" );
00286 return;
00287 }
00288
00289
00290
00291 void machine::adjustWritebackStatus( legoOp *Op, int cycle )
00292 {
00293 LastWritebackCycle = LastWritebackCycle < cycle ? cycle : LastWritebackCycle;
00294 }
00295
00296
00297
00298 void machine::resetIssueStatus( int cycle, int cluster )
00299 {
00300 int i;
00301
00302 if ( cycle >= MaxScheduleLength ) {
00303 cerr << "\nERROR: machine::resetIssueStatus\n";
00304 cerr << "\tcycle " << cycle << " >= RT size " << MaxScheduleLength
00305 << "\n";
00306 exit( -1 );
00307 }
00308
00309 for ( i = 0; i < totalSlots; i++ )
00310 RRT[ i ][ cycle ] = EMPTY;
00311 }
00312
00313
00314
00315
00316 void machine::resetIssueStatus( int cycle )
00317 {
00318 int i;
00319
00320
00321 if ( cycle >= MaxScheduleLength ) {
00322 cerr << "\nERROR: machine::resetIssueStatus\n";
00323 cerr << "\tcycle " << cycle << " >= RT size " << MaxScheduleLength
00324 << "\n";
00325 exit( -1 );
00326 }
00327
00328 if ( cycle < MaxScheduleLength )
00329 for ( i = 0; i < totalSlots; i++ )
00330 RRT[ i ][ cycle ] = EMPTY;
00331 }
00332
00333
00334
00335 void machine::resetMachine()
00336 {
00337 int i, j;
00338
00339 LastIssueCycle = LastWritebackCycle = 0;
00340 for ( i = 0; i < totalSlots; i++ )
00341 for ( j = 0; j < MaxScheduleLength; j++ ) {
00342 RRT[ i ][ j ] = EMPTY;
00343 RRTop[ i ][ j ] = NULL;
00344 }
00345 }
00346
00347
00348
00349 void machine::showIssueStatus( int cycle )
00350 {
00351 int i;
00352
00353
00354 if ( cycle >= MaxScheduleLength ) {
00355 cerr << "\nERROR: machine::showIssueStatus\n";
00356 cerr << "\tcycle " << cycle << " >= RT size " << MaxScheduleLength
00357 << "\n";
00358 exit( -1 );
00359 }
00360
00361 for ( i = 1; i < totalSlots; i++ ) {
00362 cerr.width( 5 );
00363 if ( RRT[ i ][ cycle ] == EMPTY ) cerr << "N";
00364 else cerr << RRT[ i ][ cycle ] ;
00365 }
00366 cerr << " |\n";
00367 }
00368
00369
00370
00371 void machine::printSchedule( int Cycle )
00372 {
00373 if ( Cycle >= MaxScheduleLength ) {
00374 cerr << "\nERROR: machine::printSchedule\n";
00375 cerr << "\tcycle " << Cycle << " >= RT size " << MaxScheduleLength
00376 << "\n";
00377 exit( -1 );
00378 }
00379
00380 PrintSchedule( Cycle );
00381 }
00382
00383
00384
00385 void machine::printSchedule()
00386 {
00387 PrintSchedule( LastWritebackCycle );
00388 }
00389
00390
00391
00392 void machine::PrintSchedule( int LastCycle )
00393 {
00394 int i;
00395 char *OutputStr;
00396
00397 cerr << "\nSlot assignments are in the order they are defined in the hmdes file. \n"
00398 << "For example: \n"
00399 << "$def !num_IALUs 2 \n$def !num_mem_units 1 \n$def !num_branch_units 1 \n"
00400 << "results in slot 1: IALU, slot 2: IALU, slot 3: MEM, and slot 4: BR \n";
00401 cerr << " Slot\n";
00402 cerr << " Cycle ";
00403 for ( i = 1; i < totalSlots; i++ ) {
00404 cerr << " ";
00405 cerr.width( 4 );
00406 cerr << i;
00407 }
00408 cerr << "\n";
00409
00410 for ( i = 1; i <= totalSlots; i++ )
00411 cerr << "-------";
00412 cerr << "--\n";
00413 for ( i = 1; i <= LastCycle; i++ ) {
00414 cerr << "* ";
00415 cerr.width( 4 );
00416 cerr << i << " ";
00417 showIssueStatus( i );
00418 }
00419 for ( i = 1; i <= totalSlots; i++ )
00420 cerr << "-------";
00421 cerr << "--\n";
00422 }
00423
00424
00425
00426 void machine::estimateSchedule (double *TotalOps, double *TotalCycles,
00427 int assumeDP = 0)
00428 {
00429 int i, j;
00430 int lastbranchcycle = 0;
00431 int nextlastbranchcycle = 0;
00432 int lastcycle;
00433 double totalcycles = 0.0;
00434 double retiredops = 0.0;
00435 double regionweight = 0.0, totalweight;
00436 opList *opl;
00437 int region_type;
00438
00439
00440 derr( ">> machine::estimateSchedule\n" );
00441
00442 lastcycle = Bypass == TRUE ? LastIssueCycle : LastWritebackCycle;
00443 if ( Bypass == TRUE ) derr( " Bypass TRUE\n" );
00444 derr( " lastcycle = " << lastcycle << "\n" );
00445 for (i=1; i <= lastcycle; i++) {
00446
00447 double max_br_weight = 0.0;
00448 int ignore;
00449
00450 derr( "\ncycle=" << i << "\n" );
00451 derr( "-----\n" );
00452
00453 for (j=1; j < totalSlots; j++) {
00454
00455 attrList *atl;
00456 attrs *a;
00457 int attr_count;
00458
00459 derr( " [j=" << j << "] " );
00460
00461 derr( " Processing op " << RRTop[j][i]->GetOpId() << "\n" );
00462 ignore = FindLcAttribute( "ignore-static-estimate", RRTop[j][i] ) == NULL
00463 ? 0 : 1;
00464
00465 if (RRT[j][i] != EMPTY && ignore == 0 ) {
00466 legoRegion* tttt = (legoRegion*)(RRTop[j][i]->GetParentBlockPtr());
00467
00468 derr( " Doing op " << RRTop[j][i]->GetOpId() );
00469 if ( !isRealOp( RRTop[ j ][ i ] ) ) {
00470 derr( "...skipping psuedo-op\n" );
00471 continue;
00472 }
00473 derr( "\n" );
00474
00475
00476
00477
00478
00479
00480 if (assumeDP && ((RRTop[j][i])->GetDuplicateOpsPtr() != NULL))
00481 {
00482 double maxdupweight = 0.0;
00483 totalweight = 0.0;
00484
00485 derr( " DP: Scanning Op " << (RRTop[j][i])->GetOpId() << "\n" );
00486 for (opl = (RRTop[j][i])->GetDuplicateOpsPtr(); opl != NULL;
00487 opl = opl->GetNextListPtr())
00488 {
00489 if (!(opl->GetValid()))
00490 {
00491 derr( " " << opl->GetOpId() << " is invalid.\n" );
00492 continue;
00493 }
00494 if (((legoRegion *) opl->GetOpPtr()->GetParentBlockPtr())
00495 ->GetParentPtr() !=
00496 ((legoRegion *) (RRTop[j][i])->GetParentBlockPtr())
00497 ->GetParentPtr())
00498 {
00499 derr( " " << opl->GetOpId()
00500 << " is not in the same treegion.\n" );
00501 continue;
00502 }
00503 if (opl->GetOpPtr()->GetSchedTime() != i)
00504 {
00505 derr( " " << opl->GetOpId() << " is not scheduled in "
00506 << i << "\n" );
00507 continue;
00508 }
00509
00510 regionweight = GetOpFrequency (opl->GetOpPtr());
00511 if (regionweight < 0.0)
00512 if ( (region_type=tttt->GetRegionType()) == RT_SB ||
00513 ( region_type == RT_HB &&
00514 FindFlag( SB, (legoRegion *)
00515 opl->GetOpPtr()->GetParentBlockPtr() ) != NULL ) )
00516 regionweight = GetSuperblockWeight (opl->GetOpPtr(), this);
00517 else
00518 regionweight = ((legoRegion *)
00519 (opl->GetOpPtr()->GetParentBlockPtr()))
00520 ->GetWeight();
00521 if (regionweight > maxdupweight)
00522 maxdupweight = regionweight;
00523 totalweight += regionweight;
00524 derr( " Total weight is now " << totalweight << " from op "
00525 << opl->GetOpPtr()->GetOpId() << "\n" );
00526 }
00527 regionweight = maxdupweight;
00528 derr( " Done scanning.\n" );
00529 }
00530 else
00531 {
00532 regionweight = GetOpFrequency (RRTop[j][i]);
00533 if (regionweight < 0.0)
00534 if (tttt->GetRegionType() == RT_BB)
00535 regionweight = tttt->GetWeight();
00536 else
00537 regionweight = GetSuperblockWeight (RRTop[j][i], this);
00538 totalweight = regionweight;
00539 }
00540
00541
00542 retiredops += totalweight;
00543 derr ( " Retired ops now at " << retiredops << "\n" );
00544
00545
00546
00547 derr( " Region weight now " << regionweight << "\n" );
00548
00549
00550 if (TinkerOptype (RRTop[j][i]) == BR_OP &&
00551 RRTop[j][i]->IsBRLOp() == false &&
00552 RRTop[j][i]->IsCMERGEOp() == false) {
00553
00554 if (regionweight > max_br_weight)
00555 max_br_weight = regionweight;
00556
00557
00558 if (lastbranchcycle < i)
00559 nextlastbranchcycle = i;
00560
00561 derr( " lastbranchcycle=" << lastbranchcycle
00562 << ", nextlastbranchcycle=" << nextlastbranchcycle << "\n" );
00563 }
00564 }
00565
00566 }
00567
00568 derr( " (1) max_br_weight=" << max_br_weight << "\n" );
00569
00570
00571
00572 if ( i == lastcycle && max_br_weight == 0 ) max_br_weight = regionweight;
00573 derr( " (2) max_br_weight=" << max_br_weight << "\n" );
00574 totalcycles += (i-lastbranchcycle)*max_br_weight;
00575 derr( " Total cycles " << totalcycles << ", total Ops " << retiredops
00576 << "\n" );
00577 lastbranchcycle = nextlastbranchcycle;
00578 }
00579
00580 (*TotalOps) = retiredops;
00581 (*TotalCycles) = totalcycles;
00582
00583
00584 derr( " ESTIMATE:retired Ops=" << retiredops << ", Total cycles="
00585 << totalcycles << ", OPC=" << retiredops/totalcycles << "\n" );
00586 derr( "<< machine::estimateSchedule\n" );
00587 }
00588
00589
00590
00591
00592 machine::ShowParameters( knobs *Knobs )
00593 {
00594 char flag, *string, uu;
00595 int latency = 0;
00596
00597
00598 Knobs->SetDefaultPanel( "machine" );
00599 Knobs->Read( "PlayDoh", flag );
00600 if ( (int ) flag ) cout << "> PlayDoh machine\n";
00601 Knobs->SetDefaultPanel( "machine" );
00602 Knobs->Read( "lmdesfile", string );
00603 cout << "> Machine model (lmdes file) : ";
00604 cout << string;
00605 cout << "\n";
00606 Knobs->Read( "bypass", flag );
00607 if ( (int) flag ) cout << "Full bypass";
00608 cout << "\n";
00609 }
00610
00611
00612
00613 void machine::initialize_lmdes(knobs *Knobs)
00614 {
00615 char *lmdesfile;
00616
00617 if (!lmdes_initialized()) {
00618
00619 Knobs->SetDefaultPanel ("machine");
00620 Knobs->Read ("lmdesfile", lmdesfile);
00621
00622 L_init_lmdes(lmdesfile, 1, 2, 3, 1);
00623
00624 Operand_ready_pool = L_create_alloc_pool ("operand_ready_times",
00625 mdes_latency_count()*sizeof(int), 100);
00626 }
00627
00628 setIssueConfig();
00629 clustering = FALSE;
00630 BusLatency = 0;
00631
00632 }
00633
00634
00635
00636 void machine::SetKnobs( knobs* Knobs )
00637 {
00638 char flag;
00639 char *string;
00640
00641 Knobs->SetDefaultPanel( "machine" );
00642 Knobs->Read( "bypass", flag );
00643 Bypass = (int) flag;
00644 derr( " Bypass: " << Bypass << "\n" );
00645
00646
00647 initialize_lmdes(Knobs);
00648
00649 }
00650
00651
00652
00653 machine::machine( knobs* Knobs )
00654 {
00655 allocated = FALSE;
00656 Bypass = TRUE;
00657 NumClusters = 1;
00658 ClusterWidth = 0;
00659
00660 SetKnobs( Knobs );
00661 K = Knobs;
00662 }
00663
00664
00665
00666 machine::machine()
00667 {
00668 int i;
00669
00670 allocated = FALSE;
00671 Bypass = TRUE;
00672 NumClusters = 1;
00673 ClusterWidth = 0;
00674
00675 }
00676
00677
00678 machine::~machine()
00679 {
00680 if ( allocated == TRUE ) {
00681
00682 int i;
00683
00684
00685 #if 0
00686 for ( i = 0; i < totalSlots; i++ ) {
00687 delete [] RRT[ i ];
00688 delete [] RRTop[ i ];
00689 }
00690 if ( clustering == TRUE )
00691 for ( i = 0; i < NumBuses; i++ )
00692 delete [] BusRRT[ i ];
00693 #else
00694 delete [] RRT;
00695 delete [] RRTop;
00696 if ( clustering == TRUE ) delete [] BusRRT;
00697 #endif
00698 }
00699 }
00700
00701
00702
00703
00704
00705 double GetSuperblockWeight( legoOp *RRTop, machine *m )
00706 {
00707 legoOp *blockop, *prevblockop;
00708 opList *opl;
00709
00710
00711 if ( RRTop->GetPrevLink() == NULL )
00712 return ((legoRegion *) (RRTop->GetParentBlockPtr()))->GetWeight();
00713
00714
00715 for (prevblockop = RRTop, blockop = RRTop->GetPrevLink();
00716 (m->TinkerOptype (blockop) != BR_OP || blockop->IsBRLOp()
00717 || blockop->IsCMERGEOp()) &&
00718 blockop->GetPrevLink() != NULL;
00719 prevblockop = blockop,
00720 blockop = blockop->GetPrevLink()) ;
00721
00722 derr( "Stopped walk at ops " << blockop->GetOpId() << " and "
00723 << prevblockop->GetOpId() << "\n" );
00724 if (m->TinkerOptype (blockop) == BR_OP && blockop->IsCMERGEOp() == false
00725 && blockop->IsBRLOp() == false)
00726 {
00727
00728 for (opl = blockop->GetOutListPtr(); opl != NULL;
00729 opl = opl->GetNextListPtr())
00730 if (opl->GetOpId() == prevblockop->GetOpId())
00731 {
00732 derr( "Found branch weight " << opl->GetWeight() << "\n" );
00733 return opl->GetWeight();
00734 }
00735 if (opl == NULL)
00736 cerr << "Can't find oplist from " << blockop->GetOpId()
00737 << " to " << prevblockop->GetOpId() << "\n";
00738 }
00739 else
00740 {
00741 derr( "Hit top - using weight " << ((legoRegion *) (blockop->GetParentBlockPtr()))->GetWeight()<< "\n" );
00742 return ((legoRegion *) (blockop->GetParentBlockPtr()))->GetWeight();
00743 }
00744 return 0.0;
00745 }