f1ca37de59447603b513b8badb732db57f6fe04d
[charm.git] / examples / pose / HiSim / Main / TCsim.C
1 #include "BgSim_sim.h"
2 extern BgTimeLineRec* currTline;
3 extern int currTlineIdx;
4
5 #define ALLTHREAD -1
6
7 // the application name to simulate
8 extern roarray<char, 1024>  appname;
9
10 POSE_TimeType Task::convertToInt(double inp) 
11 {
12   long long out = (long long)(inp*factor);
13   if (out <0 && inp != -1.0) {
14     CmiPrintf("Invalid value in convertToInt() - %ld %f\n", out, inp);
15     CmiPrintf("Considering changing factor %e to a smaller value. \n", factor);
16     CmiAssert(out >= 0 || inp == -1);
17   }
18   return (out<0?0:out);
19 }
20
21
22 void Task::convertFrom(BgTimeLog* bglog, int procNum, int numWth) 
23 {
24   int i;
25
26   taskID.srcNode = bglog->msgId.node();
27   taskID.msgID = bglog->msgId.msgID();
28   taskID.index = bglog->seqno;
29
30   strncpy(name,bglog->name,19);  name[19]=0;
31   startTime = convertToInt(bglog->startTime);
32   receiveTime = convertToInt(bglog->recvTime);
33   execTime = convertToInt(bglog->execTime);
34   done = 0;
35
36   //CkPrintf("LOG rcv=%d start=%d\n", receiveTime, startTime);
37   bDepsLen = bglog->backwardDeps.length();
38   backwardDeps = NULL;
39   if (bDepsLen) {
40     backwardDeps = new TaskID[bDepsLen];
41     for(i=0;i<bDepsLen;i++){
42       backwardDeps[i].srcNode = -1;//bglog->backwardDeps[i]->srcnode;
43       backwardDeps[i].msgID = -1;//bglog->backwardDeps[i]->msgID;
44       backwardDeps[i].index = bglog->backwardDeps[i]->seqno;
45     }
46   }
47
48   fDepsLen = bglog->forwardDeps.length();
49   forwardDeps = NULL;
50   if (fDepsLen) {
51     forwardDeps = new TaskID[fDepsLen];
52     for(i=0;i<fDepsLen;i++){
53       forwardDeps[i].srcNode = -1;//bglog->forwardDeps[i]->srcnode;
54       forwardDeps[i].msgID = -1;//bglog->forwardDeps[i]->msgID;
55       forwardDeps[i].index = bglog->forwardDeps[i]->seqno;
56     }
57   }
58   
59   // these are the generated tasks?
60   taskMsgsLen = bglog->msgs.length();
61   taskmsgs = new TaskMsg[taskMsgsLen];
62   for(i=0; i< taskMsgsLen;i++){
63     taskmsgs[i].taskID.srcNode = procNum/numWth;
64     taskmsgs[i].taskID.msgID = bglog->msgs[i]->msgID;
65     taskmsgs[i].taskID.index = -1; 
66     taskmsgs[i].destNode = bglog->msgs[i]->dstPe;
67     taskmsgs[i].desttID = bglog->msgs[i]->tID;
68     taskmsgs[i].receiveTime = convertToInt(bglog->msgs[i]->recvTime);
69     taskmsgs[i].msgsize = bglog->msgs[i]->msgsize;
70     if (taskmsgs[i].desttID >= 0) CmiAssert(taskmsgs[i].desttID < numWth);
71     CmiAssert(taskmsgs[i].msgsize > 0);
72   }
73   
74   // trace projections events and bgPrint Events
75   printevtLen = projevtLen = 0;
76   projevts = NULL;
77   printevts = NULL;
78   for(i=0; i< bglog->evts.length();i++){
79     if (bglog->evts[i]->eType == BG_EVENT_PROJ)  projevtLen++;
80     if (bglog->evts[i]->eType == BG_EVENT_PRINT)  printevtLen++;
81   }
82   if (projevtLen)  projevts = new ProjEvent[projevtLen];
83   if (printevtLen)  printevts = new bgPrintEvent[printevtLen];
84
85   printevtLen = projevtLen = 0;
86   for(i=0; i< bglog->evts.length();i++){
87     // CmiPrintf("[%d] %d %d \n", procNum, bglog->evts[i]->eType, bglog->evts[i]->index);
88       if (bglog->evts[i]->eType == BG_EVENT_PROJ) {
89         projevts[projevtLen].index = bglog->evts[i]->index;
90         projevts[projevtLen].startTime = convertToInt(bglog->evts[i]->rTime);
91         projevtLen++;
92       }
93       if (bglog->evts[i]->eType == BG_EVENT_PRINT) {
94         printevts[printevtLen].data = (char *)bglog->evts[i]->data;
95         printevts[printevtLen].sTime = convertToInt(bglog->evts[i]->rTime);
96         printevtLen++;
97       }
98   }
99
100 }
101
102
103 void Task::pup(PUP::er &p) 
104 {
105   taskID.pup(p);
106   p|receiveTime; p|execTime; p|startTime;
107   p(name,20);
108   p|bDepsLen; p|fDepsLen;p|taskMsgsLen; p|printevtLen;p|projevtLen;
109   p|done;
110
111   if(p.isUnpacking()){
112     backwardDeps = new TaskID[bDepsLen];
113     forwardDeps = new TaskID[fDepsLen];
114     taskmsgs = new TaskMsg[taskMsgsLen];
115     projevts = new ProjEvent[projevtLen];
116     printevts = new bgPrintEvent[printevtLen];
117   }
118   for(int i=0;i<bDepsLen;i++)
119     backwardDeps[i].pup(p);
120   for(int i=0;i<fDepsLen;i++)
121     forwardDeps[i].pup(p);
122   for(int i=0;i<taskMsgsLen;i++)
123     taskmsgs[i].pup(p);
124   for(int i=0;i<printevtLen;i++)
125     p|printevts[i];
126   for(int i=0;i<projevtLen;i++)
127     p|projevts[i];
128 }
129
130 BGproc::BGproc() 
131 {
132   // implement as you wish
133   proj = NULL;
134   done = NULL;
135   taskList = NULL;
136 }
137
138 // read trace projections logs if there is any
139 void BGproc::loadProjections() 
140 {
141   int i;
142
143   proj = NULL;
144   binary = 0;
145   char str[1024];
146   char app[128];
147   for (i=0; i<128; i++) app[i] = appname[i];
148   sprintf(str, "%s.%d.log", app, procNum);
149   FILE *f = fopen(str, "r");
150   if (f) {
151     CmiPrintf("Loading projections file: %s\n", str);
152     // figure out the log size
153     if (!binary) {
154       fgets(str, 1024, f);              // skip header
155       sscanf(str, "PROJECTIONS-RECORD %d", &numLogs);
156     }
157     else {
158       fread(&numLogs, sizeof(int), 1, f);
159     }
160     CmiAssert(numLogs);
161     logs = new LogEntry[numLogs]; 
162     fromProjectionsFile p(f);
163 //    PUP::fromDisk p(f);
164     for (i=0; i<numLogs; i++) {
165       logs[i].pup(p);
166       // CmiPrintf("%d %d\n", i, logs[i].type);
167     }
168     fclose(f);
169     // new log
170     sprintf(str, "%s-bg.%d.log", app, procNum);
171     proj = fopen(str, "w");
172     if (!binary) {
173       fprintf(proj, "PROJECTIONS-RECORD %d\n", numLogs);
174     }
175     CmiAssert(proj);
176   }
177 }
178
179 BGproc::BGproc(BGprocMsg *m)
180 {
181   int i;
182
183   nodePID = m->nodePID;         // node pose index
184   useAntimethods();
185   if (-1==BgLoadTraceSummary("bgTrace", totalProcs, numX, numY, numZ, numCth, numWth, numPes)) CmiAbort("Failed");
186   
187   int* allNodeOffsets = BgLoadOffsets(totalProcs,numPes);
188   BgTimeLineRec tline;
189   procNum = myHandle;
190   currTline = &tline;
191   currTlineIdx = procNum;
192   BgReadProc(procNum,numWth,numPes,totalProcs,allNodeOffsets,tline);
193
194   delete [] allNodeOffsets;
195
196 #if 0    // detail
197   // dump bg timeline log to disk
198   BgWriteThreadTimeLine("detail", 0, 0, 0, procNum, tline.timeline);
199 #endif
200
201   //CkPrintf("bgProc %d has %d tasks\n", myHandle, tline.length());
202   numTasks = tline.length();
203   CmiAssert(numTasks>0);
204   taskList = new Task[tline.length()];
205   int startEvt = 0;             // start event, to skip startup
206   for(i=0;i<tline.length();i++) {
207     taskList[i].convertFrom(tline[i],myHandle,numWth);
208     if (config.skip_on && tline[i]->isStartEvent() && startEvt== 0) { 
209         CmiAssert(procNum==0); 
210         startEvt = i; 
211     }
212   }
213
214   buildHash();
215
216   // store the status of done tasks
217   done = new int[numTasks];
218   for (i = 0; i<numTasks; i++) done[i] = 0;
219
220   //  if (myHandle == 0) { 
221   // this is processor 0 therefore the one to start main
222   // get the taskID for the main task to start and invoke it
223
224   // read trace projections logs if there is any
225   loadProjections();
226
227   if (config.tproj_on) {
228     char str[1024];
229     char app[128];
230 //    for (int j=0; j<128; j++) app[j] = appname[j];
231     sprintf(str, "%s.%d.log", "foo", procNum);
232     lf = fopen(str, "w");
233     toProjectionsFile p(lf);
234     LogEntry *foo = new LogEntry(0.0, 6);
235     foo->pup(p);
236   }
237
238
239   // only pe 0 should start the sim
240   if (procNum == 0) {
241     TaskMsg *tm = new TaskMsg(-1,-1,startEvt);
242     POSE_invoke(executeTask(tm), BGproc, myHandle, taskList[startEvt].startTime);
243     CkPrintf("Info> timing factor %e ...\n", (double)factor);
244     CkPrintf("Info> invoking startup task from proc 0 ...\n");
245     if (config.skip_on)
246       CkPrintf("Info> Skipping startup to %d/%d\n", startEvt, tline.length());
247   }
248 #if 1
249     for (int i=startEvt; i<numTasks; i++) {
250       if (!strcmp(taskList[i].name, "addMsg") ||
251           !strcmp(taskList[i].name, "AMPI_START") ||
252           !strcmp(taskList[i].name, "AMPI_MIGRATE"))  
253       {
254         // skip if it has any backward dependency
255         if (taskList[i].bDepsLen != 0) continue;
256         TaskMsg *tm = new TaskMsg(taskList[i].taskID.srcNode,
257                        taskList[i].taskID.msgID,
258                        taskList[i].taskID.index,
259                        taskList[i].receiveTime,
260                        0,
261                        procNum/numWth,  procNum/numWth,
262                        procNum%numWth
263                        );
264         POSE_invoke(executeTask(tm), BGproc, myHandle, taskList[i].receiveTime);
265       }
266     }
267 #endif
268   //}
269   // FIXME:  free tline memory
270 }
271
272 BGproc::~BGproc()
273 {
274   // implement as you wish
275   if (done) delete [] done;
276 }
277
278 void BGproc::pup(PUP::er &p)
279
280   chpt<state_BGproc>::pup(p); 
281   // pup rest of data fields here
282   p|numX;p|numY;p|numZ;p|numCth;p|numWth;p|numPes;p|totalProcs;p|procNum;
283   p|nodePID;
284   p|numTasks;
285   if(p.isUnpacking())
286     taskList = new Task[numTasks];
287   for(int i=0;i<numTasks;i++)
288     taskList[i].pup(p);
289 }
290
291 // Event methods
292 void BGproc::executeTask(TaskMsg *m)
293 {
294 /*
295   CkPrintf("[%d Received TaskID: %d %d %d]\n", procNum, m->taskID.srcNode,
296            m->taskID.msgID, m->taskID.index, locateTask(m->taskID));
297   parent->CommitPrintf("Received %d from %d on %d at %d\n", m->taskID.msgID, 
298                        m->taskID.srcNode, parent->thisIndex, ovt);
299 */
300 //  CmiAssert(done[locateTask(m->taskID)] == 0);
301   int taskLoc = locateTask(m->taskID);
302   if (taskLoc == -1) {
303     // This may be ok if the message is at the end of execution
304     // user is warned here though
305     parent->CommitPrintf("WARNING: executeTask TASK NOT FOUND src:%d msg:%d on:%d\n", m->taskID.srcNode, m->taskID.msgID, parent->thisIndex);
306     return;
307   }
308   if (done[taskLoc] == 1) {
309     char str[1024];
310     sprintf(str, "[%d] Event #%d '%s' already done!\n", procNum, taskLoc, taskList[taskLoc].name);
311     parent->CommitError(str);
312     CkPrintf("POTENTIAL ERROR: [%d] Event %d '%s' already done! %d %d %d at %ld evID=", procNum, taskLoc, taskList[taskLoc].name, m->taskID.srcNode, m->taskID.msgID, m->taskID.index, m->timestamp); m->evID.dump(); CkPrintf("\n");
313     return;
314   }
315
316   POSE_TimeType oldRT = getReceiveTime(m->taskID);
317   POSE_TimeType newRT = m->timestamp;
318   //if(!(m->isNull()))
319   //updateReceiveTime(m);
320   if (dependenciesMet(&(m->taskID))) { // dependencies met; we can execute this
321     Task &task = taskList[taskLoc];
322     POSE_TimeType oldStartTime = task.startTime;
323     POSE_TimeType newStartTime = ovt;
324     task.newStartTime = newStartTime;   // store new start time and used later
325     //updateStartTime(&m->taskID, newStartTime);
326     markTask(&m->taskID);  // what is this doing?
327     //CmiPrintf("[%d] executeTask %d for %d %d %d at %d evID=", procNum, taskLoc, m->taskID.srcNode, m->taskID.msgID, m->taskID.index, m->timestamp); m->evID.dump(); CkPrintf("\n");
328     enableGenTasks(&m->taskID,oldStartTime,newStartTime);
329     elapse(getDuration((m->taskID)));
330     enableDependents(&m->taskID); // invoke dependent tasks
331     /*
332       parent->CommitPrintf("[%d:%s] IDX=%d, RT1=%d RT2=%d ST1=%d ST2=%d e=%d t=%d.\n",
333       procNum, taskList[taskLoc].name, taskLoc, oldRT, newRT, oldStartTime, 
334       newStartTime, getDuration(m->taskID), 
335       newStartTime+getDuration(m->taskID));
336     */
337     for(int i=0;i<task.printevtLen;i++){
338             char str[1000];
339             strcpy(str, "[%d:%s] ");
340             strcat(str, task.printevts[i].data);
341 /*
342             CkPrintf("uncommited ");
343             CkPrintf(str,procNum, taskList[taskLoc].name, (double)(task.printevts[i].sTime+newStartTime)/factor); 
344 */
345             parent->CommitPrintf(str,procNum, taskList[taskLoc].name, (double)(task.printevts[i].sTime+newStartTime)/factor); 
346     }
347 return;
348     // HACK:
349     // look forward and see if there is any standalone or addMsg events
350     for (int i=taskLoc+1; i<numTasks; i++) {
351       if (!strcmp(taskList[i].name, "standalone")) continue; 
352       if (!strcmp(taskList[i].name, "addMsg"))  {
353         TaskMsg *tm = new TaskMsg(taskList[i].taskID.srcNode,
354                        taskList[i].taskID.msgID,
355                        taskList[i].taskID.index,
356                        ovt + taskList[i].execTime,
357                        0,
358                        procNum/numWth,  procNum/numWth,
359                        procNum%numWth
360                        );
361         POSE_invoke(executeTask(tm), BGproc, myHandle, taskList[i].execTime);
362         continue;
363       }
364       break;
365     }
366   }
367 }
368
369 void BGproc::enableGenTasks(TaskID* taskID, POSE_TimeType oldStartTime, POSE_TimeType newStartTime)
370 {
371   TaskMsg* generatedTasks = getGeneratedTasks(taskID);
372   int numGenTasks = getNumGeneratedTasks(taskID);
373   TaskMsg *tm;
374
375   // Given the following inputs for destNode and destTID, we need to 
376   // send out messages either directly to the local node, or through
377   // the network.  To do this we have to specify correct information
378   // about the destination BGproc and the source and destination
379   // switch in the network
380
381   // destNode   destTID   Behavior
382   // ========== ========= ==============================================
383   // -1         -1        Broadcast to ALL worker threads of ALL nodes
384   // -1         K         SHOULD NOT HAPPEN???
385   // N          -1        Send to ALL worker threads of node N
386   // N          K         Send to worker thread K of node N
387   // -100-N     -1        Broadcast to all worker threads of all nodes
388   //                      except for N (no worker threads of N receive)
389   // -100-N     K         Broadcast to all worker threads of all nodes
390   //                      except worker K of node N
391
392   for (int i=0; i<numGenTasks; i++) {
393     // time units offset in future at which task i is generated
394     int taskOffset = generatedTasks[i].receiveTime - oldStartTime;
395     int myNode = parent->thisIndex/numWth;
396     int srcSwitch = myNode;
397     
398     CmiAssert(taskOffset >= 0);
399           
400     //generatedTasks[i].receiveTime = newStartTime + taskOffset;
401     //if(generatedTasks[i].receiveTime < 0) abort();  // Sanity check
402     CmiAssert(newStartTime + taskOffset >= 0);  // Sanity check
403
404     int destNodeCode = generatedTasks[i].getDestNode();
405     int destTID = generatedTasks[i].desttID; 
406
407     if (destNodeCode >= 0) { // send a msg to a specific node
408       if (destTID < -1) {
409         CkPrintf("ERROR: enableGenTasks: bad destTID %d destNodeCode %d\n",
410                  destTID, destNodeCode);
411         CmiAbort("");
412       }
413     }
414     else if (destNodeCode == -1) { // broadcast to all nodes
415       if (destTID != -1) {
416         CkPrintf("ERROR: enableGenTasks: bad destTID %d destNodeCode %d\n",
417                  destTID, destNodeCode);
418         CmiAbort("");
419       }
420     }
421     else if (destNodeCode <= -100) { // broadcast to all nodes with exceptions
422       if (destTID < -1) {
423         CkPrintf("ERROR: enableGenTasks: bad destTID %d destNodeCode %d\n",
424                  destTID, destNodeCode);
425         CmiAbort("");
426       }
427     }
428     else CkPrintf("ERROR: enableGenTasks: bad destNodeCode %d\n",destNodeCode);
429 /*
430     tm = &generatedTasks[i];
431     POSE_TimeType recvTime = tm->receiveTime;   // store old value
432 */
433     tm = new TaskMsg();
434     *tm = generatedTasks[i];
435     tm->receiveTime = newStartTime + taskOffset;
436     SendMessage(tm, myNode, srcSwitch, destNodeCode, destTID, taskOffset);
437 /*
438     tm->receiveTime = recvTime;    // we can not change it
439 */
440     delete tm;
441   }
442 }
443
444 void BGproc::SendMessage(TaskMsg *inMsg, int myNode, int srcSwitch,
445                          int destNodeCode, int destTID, int taskOffset)
446 {
447   int destSwitch, destNode, j;
448
449   if (destNodeCode >= 0) { // send msg to one node
450     destNode = destNodeCode;
451     destSwitch = destNode;
452     GeneralSend(inMsg, myNode, srcSwitch, destSwitch, destNodeCode,
453                destTID, destNode, taskOffset);
454   }
455   else if (destNodeCode == -1) { // send msg to all nodes
456     CmiAssert(destTID == -1);
457     for (j=0; j<totalProcs/numWth; j++) {
458       destNode = j;
459       destSwitch = destNode;
460       GeneralSend(inMsg, myNode, srcSwitch, destSwitch, destNodeCode,
461                  destTID, destNode, taskOffset);
462     }
463   }
464   else { // send msg to all nodes except destNodeExcept when destTID=-1
465     int destNodeExcept = -100 - destNodeCode;
466     for (j=0; j<totalProcs/numWth; j++) {
467       destNode = j;
468       destSwitch = destNode;
469       if ((destNode == destNodeExcept) && (destTID == -1))
470         continue; // exclude the whole node
471       // no fiddling with destTID necessary; receiver will handle
472       GeneralSend(inMsg, myNode, srcSwitch, destSwitch, destNodeCode,
473                  destTID, destNode, taskOffset);
474     }
475   }
476 }
477
478 void BGproc::GeneralSend(TaskMsg *inMsg, int myNode, int srcSwitch,
479                         int destSwitch, int destNodeCode, int destTID, 
480                         int destNode, int taskOffset)
481 {
482   if (config.netsim_on) {
483     if (srcSwitch == destSwitch) 
484       DirectSend(inMsg, myNode, srcSwitch, destSwitch, destNodeCode,
485                destTID, destNode, taskOffset);
486     else 
487       NetSend(inMsg, myNode, srcSwitch, destSwitch, destNodeCode,
488                destTID, destNode, taskOffset);
489   }
490   else 
491     DirectSend(inMsg, myNode, srcSwitch, destSwitch, destNodeCode,
492                destTID, destNode, taskOffset);
493 }
494
495 void BGproc::DirectSend(TaskMsg *inMsg, int myNode, int srcSwitch,
496                      int destSwitch, int destNodeCode, int destTID, 
497                      int destNode, int taskOffset)
498 {
499     TaskMsg *tm = new TaskMsg(inMsg->taskID.srcNode, inMsg->taskID.msgID,
500                      inMsg->taskID.index, inMsg->receiveTime,
501                      inMsg->msgsize, destNode, destNodeCode, destTID);
502     CmiAssert(destNode >= 0);
503     int destNodePID = destNode + totalProcs;    // to node PID
504     POSE_invoke(recvIncomingMsg(tm), BGnode, destNodePID, taskOffset);
505 }
506
507
508 void BGproc::NetSend(TaskMsg *inMsg, int myNode, int srcSwitch,
509                      int destSwitch, int destNodeCode, int destTID, 
510                      int destNode, int taskOffset)
511 {
512   NicMsg *m = new NicMsg;
513   m->src = inMsg->taskID.srcNode;
514   m->routeInfo.dst = destSwitch;
515   m->msgId = inMsg->taskID.msgID;
516   m->index = inMsg->taskID.index;
517   m->destNodeCode = destNodeCode;
518   m->destTID = destTID;
519   m->recvTime = inMsg->receiveTime;
520   m->totalLen = inMsg->msgsize;
521   m->origovt = ovt+taskOffset;
522   //CkPrintf("%d BgSim : Sent %d -> %d msgid %d len %d \n",ovt,m->src,m->dst,m->msgId,m->totalLen);
523
524   elapse(CPU_OVERHEAD);
525   POSE_invoke(recvMsg(m), NetInterface, config.nicStart+m->src, taskOffset+START_LATENCY);
526 //  elapse((int)(m->totalLen/config.switchC_BW)); 
527   elapse(CPU_OVERHEAD);
528  
529   //CkPrintf("[NETWORK: BGproc:%d BGnode:%d srcSwitch:%d destSwitch:%d destNodeCode:%d destTID:%d]\n", parent->thisIndex, myNode, srcSwitch, destSwitch, destNodeCode, destTID);
530   //parent->CommitPrintf("[NETWORK: BGproc:%d BGnode:%d srcSwitch:%d destSwitch:%d destNodeCode:%d destTID:%d]\n", parent->thisIndex, myNode, srcSwitch, destSwitch, destNodeCode, destTID);
531 }
532
533 void BGproc::executeTask_anti(TaskMsg *m)
534 {
535   restore(this);
536   if (usesAntimethods()) {
537     int taskLoc = locateTask(m->taskID);
538     if (taskLoc == -1) {
539       parent->CommitPrintf("WARNING: executeTask_anti TASK NOT FOUND src:%d msg:%d on:%d\n", m->taskID.srcNode, m->taskID.msgID, parent->thisIndex);
540       return;
541     }
542     CmiAssert(taskLoc >= 0);
543     //CmiPrintf("[%d] executeTask_anti %d for %d %d %d\n", procNum, taskLoc, m->taskID.srcNode, m->taskID.msgID, m->taskID.index);
544     done[taskLoc] = 0;
545   }
546 }
547
548 void BGproc::executeTask_commit(TaskMsg *m)
549 {
550   int taskLoc = locateTask(m->taskID);
551   if (taskLoc == -1) {
552     parent->CommitPrintf("WARNING: executeTask_commit TASK NOT FOUND src:%d msg:%d on:%d\n", m->taskID.srcNode, m->taskID.msgID, parent->thisIndex);
553     return;
554   }
555   Task &task = taskList[taskLoc];
556   //CkPrintf("[%d] commit %d for %d %d %d evID=", procNum, taskLoc, m->taskID.srcNode, m->taskID.msgID, m->taskID.index); m->evID.dump(); CkPrintf("\n");
557   //CmiAssert(done[taskLoc] == 1);
558   // trying to commit an unexecuted event (may happen in sequential mode)
559   if (done[taskLoc] == 0) return;
560
561   if (proj) {
562     // pup projections to logs
563     if (!binary)  {
564       toProjectionsFile p(proj);
565       for (int i=0; i<task.projevtLen; i++) {
566         int idx = task.projevts[i].index;
567         POSE_TimeType newStart = task.newStartTime +  task.projevts[i].startTime;
568         CmiAssert(idx < numLogs);
569         logs[idx].time = newStart/1e9;
570         logs[idx].pup(p);
571       }
572     }
573   }
574   else if (config.tproj_on) {
575     toProjectionsFile p(lf);
576     LogEntry *beginLog = new LogEntry((double)task.newStartTime/factor, 2);
577     LogEntry *endLog = new LogEntry(((double)(task.newStartTime+task.execTime))/factor, 3);
578     beginLog->pup(p);
579     endLog->pup(p);
580   }
581 }
582
583 void BGproc::terminus()
584 {
585   if (proj && !binary)  {
586     toProjectionsFile p(proj);
587     logs[numLogs-1].time = ovt/1e9;
588     logs[numLogs-1].pup(p);
589   }
590   else if (config.tproj_on) {
591     toProjectionsFile p(lf);
592     LogEntry *foo = new LogEntry(((double)ovt)/factor, 7);
593     foo->pup(p);
594     fclose(lf);
595   }
596   if (config.check_on) 
597   {
598   // error checking
599   int i, count=0;
600   for (i=0; i<numTasks; i++) if (done[i] == 0) count++;
601   if (count) {
602     CkPrintf("[%d] %d/%d uncommitted events: ", procNum, count, numTasks);
603     i=0;
604     while (i<numTasks) {
605       if (done[i] == 0) {
606         CkPrintf(" %d", i);
607         i++; count = 0;
608         while (i<numTasks && done[i] == 0) { i++; count++; }
609         if (count) CkPrintf("-%d", i-1);
610       }
611       i++;
612     }
613     CkPrintf("\n");
614   }
615   }
616 }
617
618
619 // local methods
620 void BGproc::buildHash(){
621   // make index starting from 1 so that we can use 0 to represent absence
622   for(int i=0;i<numTasks;i++){
623     msgTable.put(taskList[i].taskID) = i+1;
624   }
625 }
626
627 int BGproc::locateTask(TaskID* t){
628
629 //  if the index has been already set, use it directly
630   if (t->index >= 0) return t->index;
631 #if 1
632   int index = msgTable.get(*t);
633   if (index>0) {
634     t->index = index-1;
635     return t->index;
636   }
637 #else
638   for(int i=0;i<numTasks;i++){
639
640     if(*t == taskList[i].taskID) {
641       t->index = i;
642       return i;
643     }
644   }
645 #endif
646  
647   //parent->CommitPrintf("WARNING: TASK NOT FOUND src:%d msg:%d on:%d\n",
648   //           t->srcNode, t->msgID, parent->thisIndex);
649   //abort();
650   return -1;
651 }
652
653 void BGproc::markTask(TaskID* t) {
654   done[locateTask(t)] = 1;
655 }
656
657 // not used
658 void BGproc::updateReceiveTime(TaskMsg* m)
659 {
660   // update the task's receive time to timestamp, and set a flag to
661   // indicate the update was made. ignore subsequent receive time
662   // updates to this taskID
663
664   taskList[locateTask(&(m->taskID))].receiveTime = m->timestamp;
665 }
666
667 int BGproc::dependenciesMet(yourUniqueTaskIDtype taskID)
668 {
669   // tests to see if this taskID is dependent on other tasks that have
670   // not yet been executed.  If succeed, mark this task executed.
671
672   int idx = locateTask(taskID);
673   CmiAssert(idx != -1);
674
675   int bidx;
676   for(int i=0;i<taskList[idx].bDepsLen;i++){
677     bidx = locateTask(&taskList[idx].backwardDeps[i]);
678 //    if(!taskList[bidx].done)
679     if(!done[bidx])
680       return 0;
681   }
682   return 1;
683 }
684
685 // not used
686 void BGproc::updateStartTime(TaskID* taskID, POSE_TimeType newTime)
687 {
688   // update the task's start time to newTime
689   taskList[locateTask(taskID)].startTime = newTime;
690 }
691
692 void BGproc::enableDependents(TaskID* taskID)
693 {
694   TaskMsg *tm;
695   TaskID* ftid;
696   int taskIdx = locateTask(taskID);
697   CmiAssert(taskIdx != -1);
698   POSE_TimeType execT = taskList[taskIdx].execTime;
699   
700   int fDepsLen = taskList[taskIdx].fDepsLen;
701   for(int i=0;i<fDepsLen;i++){
702
703     ftid = &taskList[taskIdx].forwardDeps[i];
704     // CkPrintf("[Checking dependent task %d %d on %d\n", ftid->index, ftid->msgID, ftid->srcNode); 
705     if(dependenciesMet(ftid)){
706       // should not have done here
707       CmiAssert(done[locateTask(ftid)]==0);
708
709       tm = new TaskMsg(ftid->srcNode,
710                        ftid->msgID,
711                        ftid->index,
712                        ovt + execT,
713                        0,
714                        procNum/numWth,  procNum/numWth,
715                        procNum%numWth
716                        );
717       
718       //CkPrintf("[%d] dependent: executeTask call %d, for %d %d %d\n", procNum, locateTask(ftid), ftid->srcNode, ftid->msgID, ftid->index); 
719       POSE_invoke(executeTask(tm), BGproc, myHandle, 0);
720     }
721   }
722 }
723
724
725 TaskMsg* BGproc::getGeneratedTasks(yourUniqueTaskIDtype taskID)
726 {
727   return taskList[locateTask(taskID)].taskmsgs;
728 }
729
730
731 int BGproc::getNumGeneratedTasks(yourUniqueTaskIDtype taskID)
732 {
733   // get the number of generated tasks in the list of tasks generated
734   // by this one
735   return taskList[locateTask(taskID)].taskMsgsLen;
736 }
737
738 POSE_TimeType BGproc::getDuration(TaskID taskID)
739 {
740   // get the duration of this task
741   return taskList[locateTask(taskID)].execTime;
742 }
743
744  
745 POSE_TimeType BGproc::getReceiveTime(TaskID taskID)
746 {
747   // get the receive time of this task
748   return taskList[locateTask(taskID)].receiveTime;
749 }
750
751 BGnode::BGnode(BGnodeMsg *m)
752 {
753   useAntimethods();
754   procsPerNode = m->procsPerNode;
755   switchPID = m->switchID;
756   nodePID = parent->thisIndex;          // pose index
757   myNodeIndex = m->nodeIdx;             // index in node array
758   firstProcPID = myNodeIndex*procsPerNode;  // first BGproc PID
759   // CmiPrintf("BGnode (%d %d) with switchPID: %d firstPE: %d\n", nodePID, myNodeIndex, switchPID, firstProcPID);
760 }
761
762 void BGnode::pup(PUP::er &p)
763 {
764   p|procsPerNode;
765   p|switchPID;
766   p|nodePID;
767   p|myNodeIndex;
768   p|firstProcPID;
769 }
770
771 void BGnode::recvOutgoingMsg(TaskMsg *m)
772 {
773 #if 0
774   int destNodeCode = m->destNodeCode;
775   int destTID
776   int destNode;
777   int destSwitch, destProc = -1, j;
778
779   if (destNodeCode >= 0) { // send msg to one node
780     destNode = destNodeCode;
781     destSwitch = nodeToSwitchPID(destNode);
782     if (destTID >= 0)
783       destProc = destNode*numWth + destTID;
784     SimpleSend(inMsg, myProc, myNode, srcSwitch, destSwitch, destNodeCode,
785                destTID, destNode, destProc, taskOffset);
786   }
787   else if (destNodeCode == -1) { // send msg to all nodes
788     CmiAssert(destTID == -1);
789     for (j=0; j<totalProcs/numWth; j++) {
790       destNode = j;
791       destSwitch = totalProcs + destNode;
792       SimpleSend(inMsg, myProc, myNode, srcSwitch, destSwitch, destNodeCode,
793                  destTID, destNode, destProc, taskOffset);
794     }
795   }
796   else { // send msg to all nodes except destNodeExcept when destTID=-1
797     int destNodeExcept = -100 - destNodeCode;
798     for (j=0; j<totalProcs/numWth; j++) {
799       destNode = j;
800       destSwitch = totalProcs + destNode;
801       if ((destNode == destNodeExcept) && (destTID == -1))
802         continue; // exclude the whole node
803       // no fiddling with destTID necessary; receiver will handle
804       SimpleSend(inMsg, myProc, myNode, srcSwitch, destSwitch, destNodeCode,
805                  destTID, destNode, destProc, taskOffset);
806     }
807   }
808
809
810 //???
811   if (destNode>=0 && destNode == myNodeIndex) {
812     // slef
813   }
814   else {
815     // network
816   }
817 #endif
818 }
819                                                                                 
820 // message send to this node
821 // called by Switch or local node
822 void BGnode::recvIncomingMsg(TaskMsg *m)
823 { // this function should do ONE of the following:
824   // 1) send message to one worker thread on this node
825   // 2) send message to all worker threads on this node
826   // 3) send messages to all but one worker threads on this node
827   if (config.netsim_on) elapse(2*CPU_OVERHEAD);
828   CmiAssert(m->destNode == myNodeIndex);
829
830   int destNodeCode = m->destNodeCode;
831   int destTID = m->desttID;
832
833   TaskMsg *tm;
834   if ((destNodeCode >= 0) && (destTID >= 0)) { // case 1
835     int destNode = destNodeCode;
836     tm = new TaskMsg(m->taskID.srcNode, m->taskID.msgID,
837                      m->taskID.index, m->receiveTime,
838                      m->msgsize, destNode, destNodeCode, destTID);
839     int destProc = firstProcPID + destTID;
840     //    CkPrintf("[%d] incoming: executeTask call %d %d %d\n", destProc, m->taskID.srcNode, m->taskID.msgID, m->taskID.index); 
841     POSE_invoke(executeTask(tm), BGproc, destProc, 0);
842     //CkPrintf("[Incoming NODE: %d %d destProc:%d]\n", nodePID, myNodeIndex, destProc);
843     //parent->CommitPrintf("[Incoming NODE: %d %d destProc:%d]\n", nodePID, myNodeIndex, destProc);
844   }
845   else {        // case 2 and 3
846     int destProc = firstProcPID;
847     int destNodeExcept = -1;
848     if (destNodeCode < -1) destNodeExcept = -100 - destNodeCode;
849     CmiAssert(!(destNodeExcept == myNodeIndex && destTID == -1));
850     for (int j=0; j<procsPerNode; j++, destProc++) {
851       if (destTID != -1) 
852         if (myNodeIndex == destNodeExcept && j == destTID) continue;
853       tm = new TaskMsg(m->taskID.srcNode, m->taskID.msgID,
854                        m->taskID.index, m->receiveTime,
855                        m->msgsize, destNodeCode, destNodeCode, j);
856       //    CkPrintf("[%d] incoming: executeTask call %d %d %d\n", destProc, m->taskID.srcNode, m->taskID.msgID, m->taskID.index); 
857       POSE_invoke(executeTask(tm), BGproc, destProc, 0);
858       //CkPrintf("[Incoming NODE: %d %d bcast destNodeCode:%d destTID:%d destProc:%d]\n", nodePID, myNodeIndex, destNodeCode, destTID, destProc);
859       //parent->CommitPrintf("[Incoming NODE: %d %d bcast destNodeCode:%d destTID:%d destProc:%d]\n", nodePID, myNodeIndex, destNodeCode, destTID, destProc);
860       //myProc, myNode, destProc);
861     }
862   }
863 }
864
865 #define NUM_MSG 64
866 #define MSG_SIZE 16384
867 #define GAP 5
868
869 Transceiver::Transceiver(TransMsg *copyM)
870 {
871 id = copyM->id;
872 TransMsg *m;
873 m = new TransMsg;
874 POSE_local_invoke(sendMessage(m),0);
875 }
876
877 void Transceiver::sendMessage(TransMsg *copyM)
878 {
879 //  NodeMsg *m;
880   int i;
881
882   for(i=0;i<NUM_MSG;i++) {
883 /*  m  = new NodeMsg;
884   m->dstNode = (id+i+1)%num_nodes;
885   if(m->dstNode == id) continue;
886   m->msgId = i;
887   m->msgsize = MSG_SIZE;
888   m->orig_msglen = MSG_SIZE;
889   m->msgtype = ENVELOPE;
890   CkPrintf("%d %d I sent Message %d -> %d  msgid %d !!! \n",ovt,id,id,m->dstNode,m->msgId);
891   POSE_invoke(genMessages(m), Node, nodeStart+id, i*GAP);
892 */
893   }
894 }
895
896 void Transceiver::recvMessage(TransMsg *m)
897 {
898   CkPrintf("%d %d I received Message %d -> %d msgid %d !!! \n",ovt,id,m->origSrc,m->dstNode,m->msgId);
899 }