PageRenderTime 267ms CodeModel.GetById 3ms app.highlight 238ms RepoModel.GetById 15ms app.codeStats 0ms

/ScoreRuntime.cc

https://github.com/nachiket/ScoreRuntime
C++ | 1124 lines | 781 code | 214 blank | 129 comment | 275 complexity | 1cfcc8fa4495a439cffa48c85ccb72c7 MD5 | raw file
   1//////////////////////////////////////////////////////////////////////////////
   2//
   3// Copyright (c) 1999 The Regents of the University of California 
   4// Permission to use, copy, modify, and distribute this software and
   5// its documentation for any purpose, without fee, and without a
   6// written agreement is hereby granted, provided that the above copyright 
   7// notice and this paragraph and the following two paragraphs appear in
   8// all copies. 
   9//
  10// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
  12// LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
  13// EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
  14// SUCH DAMAGE. 
  15//
  16// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  17// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON
  19// AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
  20// PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
  21//
  22//////////////////////////////////////////////////////////////////////////////
  23//
  24// BRASS source file
  25//
  26// SCORE runtime support
  27// $Revision: 1.80 $
  28//
  29//////////////////////////////////////////////////////////////////////////////
  30
  31#include <iostream>
  32#include <stdlib.h>
  33#include <string.h>
  34#include <sys/types.h>
  35#include <sys/stat.h>
  36#include <sys/ipc.h>
  37#include <sys/msg.h>
  38#include <fcntl.h>
  39#include <unistd.h>
  40#include <errno.h>
  41#include <pthread.h>
  42#include <signal.h>
  43#include "ScoreSimulator.h"
  44#include "ScoreScheduler.h"
  45#include "ScoreVisualization.h"
  46#include "ScoreRuntime.h"
  47#include "ScoreConfig.h"
  48#include "ScorePlock.h"
  49#include <stdio.h>
  50
  51///-----------choose scheduler type----------
  52#if defined(DYNAMIC_SCHEDULER)
  53#include "ScoreSchedulerDynamic.h"
  54#elif defined(STATIC_SCHEDULER)
  55#include "ScoreSchedulerStatic.h"
  56#elif defined(RANDOM_SCHEDULER)
  57#include "ScoreSchedulerRandom.h"
  58#else
  59#error "scheduler type was not chosen correctly"
  60#endif
  61
  62///------------------------------------------
  63
  64
  65// this is an instantiation of the simulator (ScoreSimulator) class.
  66ScoreSimulator *simulator = NULL;
  67
  68// this is an instantiation of the scheduler (ScoreScheduler) class.
  69ScoreScheduler *scheduler = NULL;
  70
  71// this is an instantiation of the visualization manager.
  72ScoreVisualization *visualization = NULL;
  73
  74// this is a pointer to the filename that will contain
  75// frames of simulator state
  76char *visualFile = NULL;
  77extern bool visualFile_complete;
  78
  79bool outputNetlist = false;
  80bool uniqNetlistRes = false;
  81char *netlistDirName = 0;
  82
  83#if GET_FEEDBACK
  84// this describes what should feedback module be doing
  85ScoreFeedbackMode gFeedbackMode = NOTHING;
  86int gFeedbackSampleFreq = 10000;
  87FILE *schedTemplateFile = 0;
  88char *gFeedbackFilePrefix = 0;
  89#endif
  90
  91bool PROFILE_VERBOSE = true;
  92
  93// this is the IPC channel id the IPC thread reads from.
  94static int ipcID = -1;
  95
  96// used to communicate between the scheduler and simulator.
  97SCORE_STREAM toSimulator = NULL;
  98SCORE_STREAM fromSimulator = NULL;
  99
 100// this is used to make sure only 1 thread is in the cleanup code at a time!
 101pthread_mutex_t cleanupMutex;
 102pthread_mutex_t cleanupHandlerMutex;
 103
 104
 105// flags.
 106char exitOnIdle;
 107char noDeadlockDetection;
 108char noImplicitDoneNodes;
 109char stitchBufferDontCare;
 110
 111
 112char isPseudoIdeal;
 113
 114// the file which is used to account for reconfiguration commands on ts by ts
 115// basis. After the SCORE_EVENT_IDLE is sent to the sim, the file is closed
 116FILE *gReconfigAcctFile = 0;
 117
 118
 119// this stores the pointer to the old SIGINT interrupt handler.
 120static void (*oldSIGINTHandler)(int) = NULL;
 121
 122
 123// this is ONE done semaphore to be used as a critical section for 
 124// all stream done/free synchronizations (may be we do not need it)
 125int gDoneSemId = -1;
 126
 127#if 0
 128#define PRINT_SIZE(__s__)  fprintf(stderr, "%s = %d\n", # __s__, sizeof(__s__))
 129#else 
 130#define PRINT_SIZE(__s__)
 131#endif
 132
 133#if TRACK_LAST_VISITED_NODE
 134extern ScoreGraphNode *lastVisitedSimNode;
 135#endif
 136
 137void  createNetlistDirs();
 138
 139// this will initialize/register the scheduler as well as spawn the 2
 140// scheduler threads.
 141int main(int argc, char *argv[]) {
 142
 143  PRINT_SIZE(ScoreStream);
 144  PRINT_SIZE(ScoreStreamStitch);
 145  PRINT_SIZE(ScoreSegment);
 146  PRINT_SIZE(ScoreGraphNode);
 147  PRINT_SIZE(ScorePage);
 148  PRINT_SIZE(ScoreSchedulerDynamic);
 149  PRINT_SIZE(ScoreSimulator);
 150
 151  pthread_t ipcThread, mainSchedulerThread, mainSimulatorThread;
 152  key_t ipcKey;
 153  char *visualizationLogfileName = NULL;
 154  int i;
 155
 156  if (USE_POLLING_STREAMS) { 
 157    assert(gDoneSemId == -1);
 158    assert(ScoreStream::doneSemId == -1);
 159    
 160    static union semun arg;
 161    static ushort start_val;
 162    start_val = 1;
 163    arg.array = &start_val;
 164    // create gDoneSemId semaphore
 165    if ((gDoneSemId = semget(0xfeedbabe, 1, IPC_EXCL | IPC_CREAT | 0666))
 166	!= -1) {
 167      if (semctl(gDoneSemId, 0, SETALL, arg) == -1) {
 168	perror("gDoneSemId -- semctl -- initialization");
 169	exit(errno);
 170      }
 171    }
 172    else {
 173      perror("gDoneSemId -- semget -- creation ");
 174      exit(errno);
 175    }
 176
 177    ScoreStream::doneSemId = gDoneSemId;
 178
 179    //cerr << "gDoneSemId = " << gDoneSemId << endl;
 180    
 181    
 182  }
 183
 184  // register out cleanup signal handler to make sure stuff is cleaned up
 185  // properly before we exit (even if you control-C us!)!
 186  oldSIGINTHandler = signal(SIGINT, &cleanupSigHandler);
 187
 188  // get the command-line arguments.
 189  // FIX ME! SHOULD DO ERROR CHECKING!
 190  // FIX ME! MAY WANT TO MAKE OTHER THINGS PARAMETERIZABLE LATER!
 191  i = 1;
 192  exitOnIdle = 0;
 193  noDeadlockDetection = 0;
 194  noImplicitDoneNodes = 0;
 195  stitchBufferDontCare = 0;
 196  isPseudoIdeal = 0;
 197  while (i < argc) {
 198    char *currentArg = argv[i];
 199
 200    i++;
 201
 202    if ((strcmp(currentArg, "-help") == 0) ||
 203        (strcmp(currentArg, "-h") == 0)) {
 204      cout << "USAGE: " << argv[0] << " [OPTIONS]" << endl;
 205      cout << "   -h\n" <<
 206	"      this help message!" << endl;
 207      cout << "   -pp X\n" <<
 208        "      # of physical compute pages (CP)" << endl;
 209      cout << "   -ps X\n" <<
 210        "      # of physical memory segments (CMB)" << endl;
 211      cout << "   -sz X\n" <<
 212	"      size of each physical memory segment" << endl;
 213      cout << "   -vl X\n" <<
 214	"      turn on \"tony-style\" visualization logs (specify filename)" << endl;
 215      cout << "   -eoi\n" <<
 216	"      exit on idle" << endl;
 217      cout << "   -ndld\n" <<
 218	"      do not run deadlock (bufferlock) detection" << endl;
 219      cout << "   -nidn\n" <<
 220        "      do not make nodes implicitly done" << endl;
 221      cout << "   -sbdc\n" <<
 222        "      this tells the scheduler not to consider stitch buffers in a cluster node list until there are only stitch buffers there" << endl;
 223      cout << "   -score_timeslice X\n" <<
 224	"      # of cycles per timeslice" << endl;
 225      cout << "   -score_fake_scheduler_time X\n" <<
 226        "      # of cycles to fake for the scheduler time" << endl;
 227      cout << "   -sim_cost_getarraystatus X\n" <<
 228	"      # of cycles to get array status" << endl;
 229      cout << "   -sim_cost_startpage X\n" <<
 230	"      # of cycles to start a page" << endl;
 231      cout << "   -sim_cost_stoppage X\n" <<
 232	"      # of cycles to stop a page" << endl;
 233      cout << "   -sim_cost_startsegment X\n" <<
 234	"      # of cycles to start a segment" << endl;
 235      cout << "   -sim_cost_stopsegment X\n" <<
 236	"      # of cycles to stop a segment" << endl;
 237      cout << "   -sim_cost_dumppagestate X\n" <<
 238	"      # of cycles to dump page state to CMB" << endl;
 239      cout << "   -sim_cost_dumppagefifo X\n" <<
 240	"      # of cycles to dump page FIFO to CMB" << endl;
 241      cout << "   -sim_cost_loadpageconfig X\n" <<
 242	"      # of cycles to load page config from CMB" << endl;
 243      cout << "   -sim_cost_loadpagestate X\n" <<
 244	"      # of cycles to load page state from CMB" << endl;
 245      cout << "   -sim_cost_loadpagefifo X\n" <<
 246	"      # of cycles to load page FIFO from CMB" << endl;
 247      cout << "   -sim_cost_getsegmentpointers X\n" <<
 248	"      # of cycles to get the segment pointers" << endl;
 249      cout << "   -sim_cost_dumpsegmentfifo X\n" <<
 250	"      # of cycles to dump segment FIFO to CMB" << endl;
 251      cout << "   -sim_cost_setsegmentconfigpointers X\n" <<
 252	"      # of cycles to set the segment pointers" << endl;
 253      cout << "   -sim_cost_changesegmentmode X\n" <<
 254	"      # of cycles to change the segment mode" << endl;
 255      cout << "   -sim_cost_changesegmenttraandpboandmax X\n" <<
 256	"      # of cycles to change the TRA/PBO/MAX of segment" << endl;
 257      cout << "   -sim_cost_resetsegmentdoneflag X\n" <<
 258	"      # of cycles to reset the segment done flag" << endl;
 259      cout << "   -sim_cost_loadsegmentfifo X\n" <<
 260	"      # of cycles to load segment FIFO from CMB" << endl;
 261      cout << "   -sim_cost_memxferprimarytocmb X\n" <<
 262	"      # of cycles to transfer one byte from main memory to CMB" << endl;
 263      cout << "   -sim_cost_memxfercmbtoprimary X\n" <<
 264	"      # of cycles to transfer one byte from CMB to main memory" << endl;
 265      cout << "   -sim_cost_memxfercmbtocmb X\n" <<
 266	"      # of cycles to transfer one byte from CMB to CMB" << endl;
 267      cout << "   -sim_cost_connectstream X\n" <<
 268	"      # of cycles to connect two nodes via a stream" << endl;
 269      cout << "   -vf X\n" <<
 270	"      turn on \"yury-style\" visualization graphs (specify filename)"
 271	   << endl;
 272      cout << "   -vf_c X\n" << 
 273	"      turn on \"yury-style\" COMPLETE visualization graphs (specify filename)"
 274	   << endl;
 275      cout << "   -netlist\n" <<
 276	"      make netlists reflecting current placement on each timeslice\n";
 277      cout << "   -stall_threshold X\n" <<
 278        "      # of cycles a page/segment must be stalled before it is considered freeable" << endl;
 279      cout << "   -clusterfreeable_ratio X\n" <<
 280        "      ratio of nodes in a cluster that must be freeable for the cluster to be freeable" << endl;
 281      cout << "   -datasegmentblock_loadsize X\n" <<
 282        "      # of bytes of consecutive data resident at one time for a segment (and stitch buffers)" << endl;
 283      cout << "   -pageconfig_size X\n" <<
 284        "      # of bytes to store the configuration bits for a page" << endl;
 285      cout << "   -pagestate_size X\n" <<
 286        "      # of bytes to store the state bits for a page" << endl;
 287      cout << "   -pagefifo_size X\n" <<
 288        "      # of bytes to store the contents of the input FIFOs for a page" << endl;
 289      cout << "   -memsegfifo_size X\n" <<
 290        "      # of bytes to store the contents of the input FIFOs for a segment" << endl;
 291      cout << "   -num_consecutive_deadlocks_to_kill X\n" <<
 292        "      # of consecutive timeslices deadlock has to be detected before the runtime exits" << endl;
 293      cout << "   -ispseudoideal\n" <<
 294        "      pseudo-ideal setting (sched cost 0; sim cost 0; timeslice 1)" << endl;
 295#if ASPLOS2000
 296      cout << "   -numpageincp X\n" <<
 297	"      # of page nodes in a CP" << endl;
 298#endif
 299      cout << "   -makefeedback\n" <<
 300	"      forces creation of the feedback files for the user applications" << endl;
 301      cout << "   -readfeedback\n" <<
 302	"      instructs runtime to read existing feedback files for user applications" << endl;
 303      cout << "   -random_seed\n" <<
 304	"      specify randomized seed to be used in random num generator for scheduling\n";
 305      cout << "   -make_template <filename>\n" << 
 306	"      instructs the runtime to make a scheduling template for a process\n";
 307      cout << "   -reconfig_stats <filename>\n" <<
 308	"      instructs the simulator to emit reconfiguration statistics for each timeslice\n";
 309      cout << "   -sample_rates\n" <<
 310	"      sample rates a specified intervals\n";
 311      cout << "   -sample_freq <num>\n" <<
 312        "      specify sampling rate frequency\n";
 313      cout << "   -feedback_file_prefix <prefix>\n" <<
 314	"      specify the prefix given to feedback file\n";
 315      exit(0);
 316    } else if ((strcmp(currentArg, "-numphysicalpages") == 0) ||
 317	(strcmp(currentArg, "-pp") == 0)) {
 318      char *currentParameter = argv[i];
 319
 320      i++;
 321
 322      numPhysicalPages = atoi(currentParameter);
 323    } else if ((strcmp(currentArg, "-numphysicalsegments") == 0) ||
 324	       (strcmp(currentArg, "-ps") == 0)) {
 325      char *currentParameter = argv[i];
 326
 327      i++;
 328
 329      numPhysicalSegments = atoi(currentParameter);
 330    } else if ((strcmp(currentArg, "-physicalsegmentsize") == 0) ||
 331	       (strcmp(currentArg, "-sz") == 0)) {
 332      char *currentParameter = argv[i];
 333
 334      i++;
 335
 336      physicalSegmentSize = atoi(currentParameter);
 337    } else if ((strcmp(currentArg, "-visualizationlog") == 0) ||
 338	       (strcmp(currentArg, "-vl") == 0)) {
 339      char *currentParameter = argv[i];
 340
 341      i++;
 342      if (TONY_GRAPH) {
 343	visualizationLogfileName = currentParameter;
 344      } else {
 345	cout << "Compiler flag TONY_GRAPH not turned on" << endl;
 346	cout << "-vl option will be ignored" << endl;
 347      }
 348    } else if ((strcmp(currentArg, "-exitonidle") == 0) ||
 349               (strcmp(currentArg, "-eoi") == 0)) {
 350      exitOnIdle = 1;
 351    } else if ((strcmp(currentArg, "-nodeadlockdetection") == 0) ||
 352               (strcmp(currentArg, "-ndld") == 0)) {
 353      noDeadlockDetection = 1;
 354    } else if ((strcmp(currentArg, "-noimplicitlydonenodes") == 0) ||
 355               (strcmp(currentArg, "-nidn") == 0)) {
 356      noImplicitDoneNodes = 1;
 357    } else if ((strcmp(currentArg, "-ispseudoideal") == 0) ||
 358               (strcmp(currentArg, "-ipi") == 0)) {
 359      isPseudoIdeal = 1;
 360      // FIX ME!
 361      SCORE_TIMESLICE = 100000;
 362      SCORE_STALL_THRESHOLD = 50000;
 363      SCORE_FAKE_SCHEDULER_TIME = 0;
 364      SIM_COST_GETARRAYSTATUS = 0;
 365      SIM_COST_STARTPAGE = 0;
 366      SIM_COST_STOPPAGE = 0;
 367      SIM_COST_STARTSEGMENT = 0;
 368      SIM_COST_STOPSEGMENT = 0;
 369      SIM_COST_DUMPPAGESTATE = 0;
 370      SIM_COST_DUMPPAGEFIFO = 0;
 371      SIM_COST_LOADPAGECONFIG = 0;
 372      SIM_COST_LOADPAGESTATE = 0;
 373      SIM_COST_LOADPAGEFIFO = 0;
 374      SIM_COST_GETSEGMENTPOINTERS = 0;
 375      SIM_COST_DUMPSEGMENTFIFO = 0;
 376      SIM_COST_SETSEGMENTCONFIGPOINTERS = 0;
 377      SIM_COST_CHANGESEGMENTMODE = 0;
 378      SIM_COST_CHANGESEGMENTTRAANDPBOANDMAX = 0;
 379      SIM_COST_RESETSEGMENTDONEFLAG = 0;
 380      SIM_COST_LOADSEGMENTFIFO = 0;
 381      SIM_COST_MEMXFERPRIMARYTOCMB = 0;
 382      SIM_COST_MEMXFERCMBTOPRIMARY = 0;
 383      SIM_COST_MEMXFERCMBTOCMB = 0;
 384      SIM_COST_CONNECTSTREAM = 0;
 385    } else if ((strcmp(currentArg, "-stitchbufferdontcare") == 0) ||
 386               (strcmp(currentArg, "-sbdc") == 0)) {
 387      stitchBufferDontCare = 1;
 388    } else if (strcmp(currentArg, "-score_timeslice") == 0) {
 389      char *currentParameter = argv[i];
 390
 391      i++;
 392
 393      SCORE_TIMESLICE = atoi(currentParameter);
 394    } else if (strcmp(currentArg, "-score_fake_scheduler_time") == 0) {
 395      char *currentParameter = argv[i];
 396
 397      i++;
 398
 399      SCORE_FAKE_SCHEDULER_TIME = atoi(currentParameter);
 400    } else if (strcmp(currentArg, "-sim_cost_getarraystatus") == 0) {
 401      char *currentParameter = argv[i];
 402
 403      i++;
 404
 405      SIM_COST_GETARRAYSTATUS = atoi(currentParameter);
 406    } else if (strcmp(currentArg, "-sim_cost_startpage") == 0) {
 407      char *currentParameter = argv[i];
 408
 409      i++;
 410
 411      SIM_COST_STARTPAGE = atoi(currentParameter);
 412    } else if (strcmp(currentArg, "-sim_cost_stoppage") == 0) {
 413      char *currentParameter = argv[i];
 414
 415      i++;
 416
 417      SIM_COST_STOPPAGE = atoi(currentParameter);
 418    } else if (strcmp(currentArg, "-sim_cost_startsegment") == 0) {
 419      char *currentParameter = argv[i];
 420
 421      i++;
 422
 423      SIM_COST_STARTSEGMENT = atoi(currentParameter);
 424    } else if (strcmp(currentArg, "-sim_cost_stopsegment") == 0) {
 425      char *currentParameter = argv[i];
 426
 427      i++;
 428
 429      SIM_COST_STOPSEGMENT = atoi(currentParameter);
 430    } else if (strcmp(currentArg, "-sim_cost_dumppagestate") == 0) {
 431      char *currentParameter = argv[i];
 432
 433      i++;
 434
 435      SIM_COST_DUMPPAGESTATE = atoi(currentParameter);
 436    } else if (strcmp(currentArg, "-sim_cost_dumppagefifo") == 0) {
 437      char *currentParameter = argv[i];
 438
 439      i++;
 440
 441      SIM_COST_DUMPPAGEFIFO = atoi(currentParameter);
 442    } else if (strcmp(currentArg, "-sim_cost_loadpageconfig") == 0) {
 443      char *currentParameter = argv[i];
 444
 445      i++;
 446
 447      SIM_COST_LOADPAGECONFIG = atoi(currentParameter);
 448    } else if (strcmp(currentArg, "-sim_cost_loadpagestate") == 0) {
 449      char *currentParameter = argv[i];
 450
 451      i++;
 452
 453      SIM_COST_LOADPAGESTATE = atoi(currentParameter);
 454    } else if (strcmp(currentArg, "-sim_cost_loadpagefifo") == 0) {
 455      char *currentParameter = argv[i];
 456
 457      i++;
 458
 459      SIM_COST_LOADPAGEFIFO = atoi(currentParameter);
 460    } else if (strcmp(currentArg, "-sim_cost_getsegmentpointers") == 0) {
 461      char *currentParameter = argv[i];
 462
 463      i++;
 464
 465      SIM_COST_GETSEGMENTPOINTERS = atoi(currentParameter);
 466    } else if (strcmp(currentArg, "-sim_cost_dumpsegmentfifo") == 0) {
 467      char *currentParameter = argv[i];
 468
 469      i++;
 470
 471      SIM_COST_DUMPSEGMENTFIFO = atoi(currentParameter);
 472    } else if (strcmp(currentArg, "-sim_cost_setsegmentconfigpointers") == 0) {
 473      char *currentParameter = argv[i];
 474
 475      i++;
 476
 477      SIM_COST_SETSEGMENTCONFIGPOINTERS = atoi(currentParameter);
 478    } else if (strcmp(currentArg, "-sim_cost_changesegmentmode") == 0) {
 479      char *currentParameter = argv[i];
 480
 481      i++;
 482
 483      SIM_COST_CHANGESEGMENTMODE = atoi(currentParameter);
 484    } else if (strcmp(currentArg, "-sim_cost_changesegmenttraandpboandmax") == 0) {
 485      char *currentParameter = argv[i];
 486
 487      i++;
 488
 489      SIM_COST_CHANGESEGMENTTRAANDPBOANDMAX = atoi(currentParameter);
 490    } else if (strcmp(currentArg, "-sim_cost_resetsegmentdoneflag") == 0) {
 491      char *currentParameter = argv[i];
 492
 493      i++;
 494
 495      SIM_COST_RESETSEGMENTDONEFLAG = atoi(currentParameter);
 496    } else if (strcmp(currentArg, "-sim_cost_loadsegmentfifo") == 0) {
 497      char *currentParameter = argv[i];
 498
 499      i++;
 500
 501      SIM_COST_LOADSEGMENTFIFO = atoi(currentParameter);
 502    } else if (strcmp(currentArg, "-sim_cost_memxferprimarytocmb") == 0) {
 503      char *currentParameter = argv[i];
 504
 505      i++;
 506
 507      SIM_COST_MEMXFERPRIMARYTOCMB = atof(currentParameter);
 508    } else if (strcmp(currentArg, "-sim_cost_memxfercmbtoprimary") == 0) {
 509      char *currentParameter = argv[i];
 510
 511      i++;
 512
 513      SIM_COST_MEMXFERCMBTOPRIMARY = atof(currentParameter);
 514    } else if (strcmp(currentArg, "-sim_cost_memxfercmbtocmb") == 0) {
 515      char *currentParameter = argv[i];
 516
 517      i++;
 518
 519      SIM_COST_MEMXFERCMBTOCMB = atof(currentParameter);
 520    } else if (strcmp(currentArg, "-sim_cost_connectstream") == 0) {
 521      char *currentParameter = argv[i];
 522
 523      i++;
 524
 525      SIM_COST_CONNECTSTREAM = atoi(currentParameter);
 526    } else if ((strcmp(currentArg, "-visualfile") == 0) ||
 527               (strcmp(currentArg, "-vf") == 0) || 
 528	       (strcmp(currentArg, "-vf_c") == 0)) {
 529      char *currentParameter = argv[i];
 530      
 531      i ++;
 532
 533      if (!VISUALIZE_STATE) {
 534	cerr << "ScoreRuntime was NOT compiled with VISUALIZE_STATE=1" << endl;
 535	exit (1);
 536      }
 537      
 538      FILE *fp_tmp = NULL;
 539      
 540      if ((fp_tmp = fopen (currentParameter, "wb")) == NULL) {
 541        cerr << "WARNING: unable to open " << currentParameter << 
 542	  ". The simulation will proceed without visualization." << endl;
 543      } 
 544      else { 
 545        fclose (fp_tmp);
 546        visualFile = new char [strlen(currentParameter) + 1];
 547
 548        memset (visualFile, '\0', strlen(currentParameter) + 1);
 549	
 550        strcpy (visualFile, currentParameter);
 551      }
 552
 553      visualFile_complete = (strcmp(currentArg, "-vf_c") == 0);
 554    } if (!strcmp(currentArg, "-netlist")) {
 555
 556      if (!VISUALIZE_STATE) {
 557	cerr << "ScoreRuntime was NOT compiled with VISUALIZE_STATE=1" << endl;
 558	exit (1);
 559      }
 560
 561      outputNetlist = true;
 562
 563    } if (!strcmp(currentArg, "-time_netlist")) {
 564
 565      if (!VISUALIZE_STATE) {
 566	cerr << "ScoreRuntime was NOT compiled with VISUALIZE_STATE=1" << endl;
 567	exit (1);
 568      }
 569
 570      outputNetlist = true;
 571      uniqNetlistRes = true;
 572
 573    } else if (strcmp(currentArg, "-stall_threshold") == 0) {
 574      char *currentParameter = argv[i];
 575
 576      i++;
 577
 578      SCORE_STALL_THRESHOLD = atoi(currentParameter);
 579    } else if (strcmp(currentArg, "-clusterfreeable_ratio") == 0) {
 580      char *currentParameter = argv[i];
 581
 582      i++;
 583
 584      SCORE_CLUSTERFREEABLE_RATIO = atof(currentParameter);
 585    } else if (strcmp(currentArg, "-datasegmentblock_loadsize") == 0) {
 586      char *currentParameter = argv[i];
 587
 588      i++;
 589
 590      SCORE_DATASEGMENTBLOCK_LOADSIZE = atoi(currentParameter);
 591    } else if (strcmp(currentArg, "-pageconfig_size") == 0) {
 592      char *currentParameter = argv[i];
 593
 594      i++;
 595
 596      SCORE_PAGECONFIG_SIZE = atoi(currentParameter);
 597    } else if (strcmp(currentArg, "-pagestate_size") == 0) {
 598      char *currentParameter = argv[i];
 599
 600      i++;
 601
 602      SCORE_PAGESTATE_SIZE = atoi(currentParameter);
 603    } else if (strcmp(currentArg, "-pagefifo_size") == 0) {
 604      char *currentParameter = argv[i];
 605
 606      i++;
 607
 608      SCORE_PAGEFIFO_SIZE = atoi(currentParameter);
 609    } else if (strcmp(currentArg, "-memsegfifo_size") == 0) {
 610      char *currentParameter = argv[i];
 611
 612      i++;
 613
 614      SCORE_MEMSEGFIFO_SIZE = atoi(currentParameter);
 615    } else if (strcmp(currentArg, "-num_consecutive_deadlocks_to_kill") == 0) {
 616      char *currentParameter = argv[i];
 617
 618      i++;
 619
 620      SCORE_NUM_CONSECUTIVE_DEADLOCKS_TO_KILL = atoi(currentParameter);
 621#if ASPLOS2000
 622    } else if (strcmp(currentArg, "-numpageincp") == 0) {
 623      char *currentParameter = argv[i];
 624
 625      i++;
 626
 627      SCORE_NUM_PAGENODES_IN_CP = atoi(currentParameter);
 628#endif
 629#if GET_FEEDBACK
 630    } else if (strcmp(currentArg, "-makefeedback") == 0) {
 631      gFeedbackMode = MAKEFEEDBACK;
 632    } else if (strcmp(currentArg, "-readfeedback") == 0) {
 633      gFeedbackMode = READFEEDBACK;
 634    } else if (strcmp(currentArg, "-sample_rates") == 0) {
 635      gFeedbackMode = SAMPLERATES;
 636    } else if (strcmp(currentArg, "-sample_freq") == 0) {
 637      char *fr = argv[i++];
 638      sscanf(fr, "%d", &gFeedbackSampleFreq);
 639      assert(gFeedbackSampleFreq > 0);
 640    } else if (strcmp(currentArg, "-make_template") == 0) {
 641      char *filename = argv[i++];
 642      if (!(schedTemplateFile = fopen(filename, "w"))) {
 643	cerr << "RUNTIME ERROR: unable to open " << filename << " for write\n";
 644	exit(1);
 645      }
 646      gFeedbackMode = MAKEFEEDBACK;
 647    } else if (strcmp(currentArg, "-feedback_file_prefix") == 0) {
 648      gFeedbackFilePrefix = new char [strlen(argv[i]) + 1];
 649      strcpy(gFeedbackFilePrefix, argv[i++]);
 650#endif
 651#ifdef RANDOM_SCHEDULER
 652    } else if (strcmp(currentArg, "-r") == 0) {
 653      cerr << "DO NOT USE -r OPTION\nIt is only for debugging\n";
 654      exit(1);
 655      char *currentParameter = argv[i];
 656      i++;
 657      
 658      int count = atoi(currentParameter);
 659      for ( ; count > 0; count --)
 660	random();
 661    } else if (strcmp(currentArg, "-random_seed") == 0 ||
 662	       strcmp(currentArg, "-rs") == 0) {
 663      char *currentParameter = argv[i];
 664      i ++;
 665      char *end;
 666
 667      unsigned int seed = (unsigned int) strtoul(currentParameter, &end, 10);
 668      srandom(seed);
 669#endif
 670    } else if (strcmp(currentArg, "-quiet_prof") == 0) {
 671      PROFILE_VERBOSE = false;
 672
 673    } else if (strcmp(currentArg, "-reconfig_stats") == 0) {
 674      char *currentParameter = argv[i];
 675      i ++;
 676#if RECONFIG_ACCT
 677      if ((gReconfigAcctFile = fopen(currentParameter, "w")) == NULL) {
 678	cerr << "ERROR: unable to open " << currentParameter << endl;
 679	exit(1);
 680      }
 681#else 
 682      cerr << "ERROR: the ScoreRuntime was not compiled with RECONFIG_ACCT = 1\n";
 683      exit(1);
 684#endif
 685    }
 686  }
 687
 688  // create appropriate directory structure for netlists
 689  createNetlistDirs();
 690
 691
 692#if ASPLOS2000
 693  numPhysicalPages = numPhysicalPages * SCORE_NUM_PAGENODES_IN_CP;
 694#endif
 695
 696  SCORE_SEGMENTTABLE_LEVEL0SIZE =
 697    SCORE_PAGE_ALIGN(SCORE_DATASEGMENTBLOCK_LOADSIZE +
 698                     SCORE_MEMSEGFIFO_SIZE);
 699  SCORE_SEGMENTTABLE_LEVEL1SIZE =
 700    SCORE_PAGE_ALIGN(SCORE_PAGECONFIG_SIZE +
 701                     SCORE_PAGESTATE_SIZE +
 702                     SCORE_PAGEFIFO_SIZE);
 703
 704  // register the cleanup routine to run at exit.
 705  if (pthread_mutex_init(&cleanupMutex, NULL) != 0) {
 706    cerr << "SCORERUNTIMEERR: Could not initialize the cleanup mutex!" << endl;
 707    exit(1);
 708  }
 709  if (pthread_mutex_init(&cleanupHandlerMutex, NULL) != 0) {
 710    cerr << "SCORERUNTIMEERR: Could not initialize the cleanup handler " <<
 711      "mutex!" << endl;
 712    exit(1);
 713  }
 714  if (atexit(&cleanup) != 0) {
 715    cerr << "Could not register the cleanup routine!" << endl;
 716    exit(1);
 717  }
 718
 719  // create a visualization manager and start a visualization log if requested.
 720  if (visualizationLogfileName != NULL) {
 721    visualization = 
 722      new ScoreVisualization(numPhysicalPages, numPhysicalSegments);
 723    visualization->startVisualization(visualizationLogfileName);
 724  }
 725
 726  // get and register the IPC channel id.
 727  ipcKey = ftok(".", 0);
 728  if (ipcKey == -1) {
 729    cerr << "Could not get IPC message key!" << endl;
 730    exit(1);
 731  }
 732  ipcID = msgget(ipcKey, IPC_CREAT|0666);
 733  if (set_schedulerid(ipcID) == -1) {
 734    exit(1);
 735  }
 736
 737
 738/* 
 739  // Nachiket removed this to avoid perfctr bs
 740  ScoreThreadCounter *shmptr = new ScoreThreadCounter(RUNTIME);
 741
 742  // instantiate the streams used to talk between the scheduler and simulator.
 743  toSimulator = NEW_SCORE_STREAM_ARRAY();
 744  if (toSimulator == NULL) {
 745    cerr << "Insufficient memory to create toSimulator stream!" << endl;
 746    exit(1);
 747  }
 748  SCORE_MARKSTREAM(toSimulator,shmptr); 
 749
 750  fromSimulator = NEW_SCORE_STREAM_ARRAY();
 751  if (fromSimulator == NULL) {
 752    cerr << "Insufficient memory to create fromSimulator stream!" << endl;
 753    exit(1);
 754  }
 755  SCORE_MARKSTREAM(fromSimulator,shmptr); 
 756*/
 757
 758  if (VERBOSEDEBUG || DEBUG) {
 759    cout << "=========================================" << endl;
 760    
 761    cout << "ipcID: " << ipcID << endl;
 762    
 763    cout << "numPhysicalPages: " << numPhysicalPages << endl;
 764    cout << "numPhysicalSegments: " << numPhysicalSegments << endl;
 765    cout << "physicalSegmentSize: " << physicalSegmentSize << endl;
 766    
 767    cout << "=========================================" << endl;
 768  }
 769
 770  // instantiate the IPC, main scheduler, and main simulator threads.
 771  if (VERBOSEDEBUG || DEBUG) {
 772    cout << "Forking off IPC thread..." << endl;
 773  }
 774  if (pthread_create(&ipcThread, NULL, ipc_thread_run, NULL) != 0) {
 775    cerr << "Could not create IPC thread!" << endl;
 776    exit(1);
 777  }
 778
 779  if (VERBOSEDEBUG || DEBUG) {
 780    cout << "Forking off main scheduler thread..." << endl;
 781  }
 782
 783  pthread_attr_t schThreadAttribute;
 784  pthread_attr_init(&schThreadAttribute);
 785
 786  if (pthread_create(&mainSchedulerThread, &schThreadAttribute, 
 787		     mainScheduler_thread_run, NULL) != 0) {
 788    cerr << "Could not create main scheduler thread!" << endl;
 789    exit(1);
 790  }
 791
 792  if (VERBOSEDEBUG || DEBUG) {
 793    cout << "Forking off main simulator thread..." << endl;
 794  }
 795
 796  // creating simulator is different because we want to 
 797  // tell the OS scheduler to keep track of context switch time
 798  // for this thread
 799
 800  pthread_attr_t simThreadAttribute;
 801  pthread_attr_init(&simThreadAttribute);
 802
 803  if (pthread_create(&mainSimulatorThread, &simThreadAttribute, 
 804		     mainSimulator_thread_run, NULL) != 0) {
 805    cerr << "Could not create main simulator thread!" << endl;
 806    exit(1);
 807  }
 808
 809  // join with the outstanding threads.
 810  if (pthread_join(ipcThread, NULL) != 0) {
 811    cerr << "Could not join with IPC thread!" << endl;
 812    exit(1);
 813  }
 814  if (pthread_join(mainSchedulerThread, NULL) != 0) {
 815    cerr << "Could not join with main scheduler thread!" << endl;
 816    exit(1);
 817  }
 818  if (pthread_join(mainSimulatorThread, NULL) != 0) {
 819    cerr << "Could not join with main simulator thread!" << endl;
 820    exit(1);
 821  }
 822
 823  return(0);
 824}
 825
 826
 827// this is the routine run by the IPC thread.
 828void *ipc_thread_run(void *data) {
 829  rmsgbuf *msgp = NULL;
 830
 831
 832  // allocate the message buffer.
 833  msgp = new struct rmsgbuf();
 834  if (msgp == NULL) {
 835    cerr << "Insufficient memory to instantiate IPC buffer!" << endl;
 836    exit(1);
 837  }
 838
 839  // go into a loop to get messages from users.
 840  while (1) {
 841    int msgsz = -1;
 842
 843    // receive the next message.
 844    msgsz = msgrcv(ipcID, msgp, sizeof(rmsgbuf),
 845                   SCORE_INSTANTIATE_MESSAGE_TYPE, 0);
 846
 847    // process the message.
 848    if (msgsz == -1) {
 849      // if EINTR was received, let the error go silently. it is probably
 850      // being run under GDB.
 851      if (errno != EINTR) {
 852	cerr << "Error receiving IPC message! (errno = " << errno << ")" << 
 853	  endl;
 854	exit(-1);
 855      }
 856    } else {
 857      int slen;
 858      int alen;
 859      char *sname;
 860      char *argbuf;
 861      msqid_ds queueStat;
 862          
 863      // get the queue status.
 864      msgctl(ipcID, IPC_STAT, &queueStat);
 865
 866      // get the components from the message.
 867      memcpy(&alen, msgp->mtext, 4);
 868      memcpy(&slen, msgp->mtext+4, 4);
 869      sname = new char[slen+1];
 870      memcpy(sname, msgp->mtext+8, slen);
 871      *(sname+slen) = '\0';
 872      argbuf = new char[alen];
 873      memcpy(argbuf, msgp->mtext+8+slen, alen);
 874      
 875      // send the shared object and argument information to the scheduler
 876      // to deal with.
 877      if (scheduler->addOperator(sname, argbuf, queueStat.msg_lspid) != 0) {
 878	cerr << "Error adding operator to scheduler! " <<
 879	     "(sname=" << sname << ", argbuf=" << argbuf << ")" << endl;
 880      }
 881
 882      // cleanup.
 883      delete sname;
 884      sname = NULL;
 885      delete argbuf;
 886      argbuf = NULL;
 887    }
 888  }
 889
 890  // deallocate the message buffer.
 891  delete msgp;
 892  msgp = NULL;
 893
 894  pthread_exit(0);
 895  return(NULL);
 896}
 897
 898
 899// this is the routine run by the main scheduler thread.
 900void *mainScheduler_thread_run(void *data) {
 901
 902  set_proc(PLOCK_SCHEDULER_CPU, "mainScheduler_thread_run");
 903
 904  // instantiate the scheduler class.
 905  if (VERBOSEDEBUG || DEBUG) {
 906    cout << "Instantiating ScoreScheduler..." << endl;
 907  }
 908  ///-----------choose scheduler type----------
 909#if defined(DYNAMIC_SCHEDULER)
 910  scheduler = new ScoreSchedulerDynamic(exitOnIdle, noDeadlockDetection,
 911                                 noImplicitDoneNodes, stitchBufferDontCare);
 912#elif defined(STATIC_SCHEDULER)
 913  cerr << "******************STATIC INIT*************\n";
 914  scheduler = new ScoreSchedulerStatic(exitOnIdle, noDeadlockDetection,
 915                                 noImplicitDoneNodes, stitchBufferDontCare);
 916#elif defined(RANDOM_SCHEDULER)
 917  scheduler = new ScoreSchedulerRandom(exitOnIdle, noDeadlockDetection,
 918                                 noImplicitDoneNodes, stitchBufferDontCare);
 919#else
 920#error "scheduler type was not chosen correctly"
 921#endif
 922
 923///------------------------------------------
 924  if (scheduler == NULL) {
 925    cerr << "Insufficient memory to instantiate the scheduler!" << endl;
 926    exit(1);
 927  }
 928
 929  while (1) {
 930    if (waitForNextTimeslice() != 0) {
 931      exit(1);
 932    }
 933
 934    // call schedule to do scheduling.
 935    scheduler->doSchedule();
 936  }
 937
 938  pthread_exit(0);
 939  return(NULL);
 940}
 941
 942
 943// this is the routine run by the main simulator thread.
 944void *mainSimulator_thread_run(void *data) {
 945
 946  set_proc(PLOCK_SIMULATOR_CPU, "mainSimulator_thread_run");
 947
 948  // instantiate the simulator class.
 949  if (VERBOSEDEBUG || DEBUG) {
 950    cout << "Instantiating ScoreSimulator..." << endl;
 951  }
 952  simulator = new ScoreSimulator(toSimulator, fromSimulator);
 953  if (simulator == NULL) {
 954    cerr << "Insufficient memory to instantiate the simulator!" << endl;
 955    exit(1);
 956  }
 957
 958  // run the simulator.
 959  simulator->run();
 960
 961  pthread_exit(0);
 962  return(NULL);
 963}
 964
 965
 966// this will set the scheduler IPC id with /proc/schedulerid.
 967// Return: -1 upon error, 0 if successful.
 968int set_schedulerid(int id) {
 969  int file = -1;
 970
 971
 972  file = open("/proc/schedulerid", O_WRONLY);
 973
 974  if (file < 0) {
 975    cerr << "Could not open /proc/schedulerid! (errno = " << 
 976             errno << ")" << endl;
 977    return(-1);
 978  }
 979
 980  if (write(file, &id, 4) != 4) {
 981    cerr << "Could not write scheduler IPC id! (errno = " <<
 982            errno << ")" << endl;
 983    return(-1);
 984  }
 985
 986  close(file);
 987  return(0);
 988}
 989
 990
 991// this performs the necessary cleanup on exiting.
 992void cleanup() {
 993  pthread_mutex_lock(&cleanupMutex);
 994
 995  // unregister the scheduler.
 996  set_schedulerid(-1);
 997
 998// need to somehow protect the this access since the simulator might be
 999// in the middle of accessing the streams.
1000#if 0
1001  // if the scheduler<->simulator streams were allocated, deallocate them.
1002  if (toSimulator != NULL) {
1003    // FIX ME! DO I HAVE TO CLOSE/FREE BEFORE DELETING?
1004    STREAM_CLOSE(toSimulator);
1005    STREAM_FREE(toSimulator);
1006    toSimulator = NULL;
1007  }
1008  if (fromSimulator != NULL) {
1009    // FIX ME! DO I HAVE TO CLOSE/FREE BEFORE DELETING?
1010    STREAM_CLOSE(fromSimulator);
1011    STREAM_FREE(fromSimulator);
1012    fromSimulator = NULL;
1013  }
1014#endif
1015
1016  // if there was a visualization, close it.
1017  if (visualization != NULL) {
1018    visualization->stopVisualization_noclose();
1019    delete(visualization);
1020    visualization = NULL;
1021  }
1022
1023  pthread_mutex_unlock(&cleanupMutex);
1024}
1025
1026
1027// this is a cleanup signal handler. it will attempt to cleanup stuff before
1028// the program is killed.
1029void cleanupSigHandler(int signum) {
1030  //cerr << "Clean up sig handler-- begin -- need acquire\n";
1031
1032  pthread_mutex_lock(&cleanupHandlerMutex);
1033
1034  //cerr << "Clean up sig handler-- begin\n";
1035
1036#if TRACK_LAST_VISITED_NODE
1037  fprintf(stderr, "*** lastVisitedSimNode:\n");
1038  if (lastVisitedSimNode) {
1039    lastVisitedSimNode->print(stderr);
1040  } else {
1041    fprintf(stderr, "NULL\n");
1042  }
1043#endif
1044
1045  // force a cleanup call.
1046  cleanup();
1047
1048  //cerr << "Clean up sig handler-- end\n";
1049
1050  pthread_mutex_unlock(&cleanupHandlerMutex);
1051
1052  //cerr << "Clean up sig handler-- end -- all done\n";
1053
1054  // force a "hard" exit.
1055  _exit(1);
1056}
1057
1058
1059
1060////////////////////////////////////////////////////////////////////////
1061// createNetlistDirs();
1062//   all netlists will be placed into netlist/netlist_cps_cmbs.time/
1063//   this routine creates the directory structure.
1064////////////////////////////////////////////////////////////////////////
1065void createNetlistDirs()
1066{
1067  if (!outputNetlist) {
1068    assert(!netlistDirName);
1069    return;
1070  }
1071
1072  // check whether netlist directory exists
1073  struct stat info;
1074        
1075  errno = 0;
1076
1077  mode_t dirPerm =
1078    S_IREAD | S_IWRITE | S_IEXEC | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
1079  
1080  if (stat("netlist", &info)) { // check the existance of netlist directory
1081    if (errno == ENOENT) { // directory netlist does not exist
1082      if (mkdir("netlist", dirPerm)) {
1083	perror("error creating netlist directory:");
1084	exit(1);
1085      }
1086    } else {
1087      perror("error with stat(\"netlist\",...)");
1088      exit(1);
1089    }
1090  }
1091
1092  if (!S_ISDIR(info.st_mode) && !errno) {
1093    fprintf(stderr, "error: netlist is NOT a directory\n");
1094    exit(1);
1095  }
1096
1097  time_t now = time(0);
1098  char targetDirName[100];
1099
1100  sprintf(targetDirName, "netlist/netlist_cp%d_cmb%d.%ld", 
1101	  numPhysicalPages, numPhysicalSegments, now);
1102
1103  errno = 0;
1104  if (stat(targetDirName, &info)) {
1105    if (errno == ENOENT) { // need to create directory
1106      if (mkdir(targetDirName, dirPerm)) {
1107	perror("error creating netlist/netlist_... directory");
1108	exit(1);
1109      }
1110    } else {
1111      perror("error stat netlist/netlist_... directory");
1112    }
1113  }
1114
1115  if (!S_ISDIR(info.st_mode) && !errno) {
1116    fprintf(stderr, "error: %s is NOT a directory\n", targetDirName);
1117    exit(1);
1118  }
1119
1120  netlistDirName = new char[strlen(targetDirName) + 1];
1121
1122  strcpy(netlistDirName, targetDirName);
1123}
1124