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