Add a flag to provide timer for the case of no objs in Meta-Balancer
[charm.git] / src / xlat-i / sdag / CEntry.C
1 #include "CEntry.h"
2 #include "xi-symbol.h"
3 #include "CStateVar.h"
4
5 using std::list;
6
7 namespace xi {
8
9 void CEntry::generateDeps(XStr& op)
10 {
11   for(list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn) {
12     op << "    __cDep->addDepends(" << (*cn)->nodeNum << "," << entryNum << ");\n";
13   }
14 }
15
16 void CEntry::generateCode(XStr& decls, XStr& defs)
17 {
18   CStateVar *sv;
19   int i;
20   int isVoid = 1;
21   int lastWasVoid;
22   i = 0;
23   decls << "  void ";
24
25   templateGuardBegin(false, defs);
26   defs << "void " << decl_entry->getContainer()->baseName() << "::";
27
28   XStr signature;
29   signature <<  *entry << "(";
30   for(list<CStateVar*>::iterator it = myParameters.begin();
31       it != myParameters.end(); ++it, ++i) {
32     sv = *it;
33     isVoid = sv->isVoid;
34     if ((sv->isMsg != 1) && (sv->isVoid != 1)) {
35        if (i >0)
36          signature <<", ";
37        signature << sv->type << " ";
38        if (sv->arrayLength != 0)
39          signature << "*";
40        else if (sv->byRef != 0) {
41          signature <<"&";
42        }
43        if (sv->numPtrs != 0) {
44          for(int k = 0; k< sv->numPtrs; k++)
45             signature << "*";
46        }
47        if (sv->name != 0)
48          signature << sv->name;
49     }
50     else if (sv->isVoid != 1){
51       if (i < 1) 
52          signature << sv->type << " " << sv->name << "_msg";
53       else
54          printf("ERROR: A message must be the only parameter in an entry function\n");
55     }
56     else
57       signature <<"void";
58   }
59   signature << ")";
60
61   decls << signature << ";\n";
62
63   defs << signature << "{\n";
64   defs << "    CWhenTrigger *tr;\n";
65   defs << "    void* _bgParentLog = NULL;\n";
66 #if CMK_BIGSIM_CHARM
67   defs <<  "    CkElapse(0.01e-6);\n";
68   SdagConstruct::generateTlineEndCall(defs);
69 #endif
70
71   defs << "    CMsgBuffer* cmsgbuf;\n";
72   defs << "    if (!__cDep.get()) _sdag_init();\n";
73
74   int hasArrays = 0;
75   int paramMarshalling = 0;
76   int count = 0;
77   i = 0;
78   if (isVoid == 1) {
79      defs << "    __cDep->bufferMessage("<<entryNum<<", (void *) CkAllocSysMsg(), (void*) _bgParentLog, 0);\n";
80      defs << "    tr = __cDep->getTrigger("<<entryNum<<", 0);\n";
81   }
82   else {
83      for(list<CStateVar*>::iterator it = myParameters.begin();
84          it != myParameters.end(); ++it, ++i) {
85        sv = *it;
86         if ((i==0) && (sv->isMsg !=1)) {
87            defs <<"    int impl_off=0; int impl_arrstart=0;\n";
88            paramMarshalling = 1;
89         }
90         if(sv->arrayLength != 0) {
91            hasArrays++ ;
92            if (sv->numPtrs > 0)
93               printf("ERROR: can't pass pointers across processors \n -- Indicate the array length with []'s, or pass a reference\n");
94            defs << "    int impl_off_" << sv->name << ", impl_cnt_" << sv->name << ";\n";
95            defs << "    impl_off_" << sv->name << "=impl_off=CK_ALIGN(impl_off,sizeof(" << sv->type << "));\n";
96            defs << "    impl_off+=(impl_cnt_" << sv->name << "=sizeof(" << sv->type << ")*(" << sv->arrayLength << "));\n";
97         }
98         if (paramMarshalling ==0) {
99            defs << "    CmiReference(UsrToEnv(" << sv->name << "_msg));\n";
100            if(refNumNeeded) {
101               defs << "    int refnum = CkGetRefNum(" <<sv->name << "_msg);\n";
102               defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum << ",(void *) " << sv->name << "_msg , (void *) _bgParentLog, refnum);\n";
103               defs << "    tr = __cDep->getTrigger(" << entryNum<<", refnum);\n";
104            } else {
105               defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum << ", (void *) " << sv->name << "_msg,  (void *) _bgParentLog, 0);\n";
106               defs << "    tr = __cDep->getTrigger(" << entryNum<<", 0);\n";
107            } 
108         }
109         count++;
110      }
111    }
112    if (paramMarshalling == 1) {
113      defs <<"    {\n";
114      defs <<"      PUP::sizer implP1;\n";
115      i = 0;
116  
117      for(list<CStateVar*>::iterator it = myParameters.begin();
118          it != myParameters.end(); ++it, ++i) {
119        sv = *it;
120         if(sv->arrayLength != 0)
121            defs << "      implP1|impl_off_" << sv->name << ";\n";
122         else if(sv->byRef != 0)
123            defs << "      implP1|(" <<sv->type << " &)" <<sv->name << ";\n";
124         else   
125            defs << "      implP1|" << sv->name << ";\n";
126      }
127  
128      if (hasArrays > 0)
129      { //round up pup'd data length--that's the first array
130         defs <<"      impl_arrstart=CK_ALIGN(implP1.size(),16);\n";
131         defs <<"      impl_off+=impl_arrstart;\n";
132      }
133      else  //No arrays--no padding
134         defs <<"      impl_off+=implP1.size();\n";
135   
136      defs <<"    }\n";
137
138      //Now that we know the size, allocate the packing buffer
139      defs <<"    CkMarshallMsg *impl_msg1=CkAllocateMarshallMsg(impl_off,NULL);\n";
140      //Second pass: write the data
141      defs <<"    {\n";
142      defs <<"      PUP::toMem implP1((void *)impl_msg1->msgBuf);\n";
143      i = 0;
144  
145      for(list<CStateVar*>::iterator it = myParameters.begin();
146          it != myParameters.end(); ++it, ++i) {
147        sv = *it;
148         if(sv->arrayLength != 0)
149            defs << "      implP1|impl_off_" << sv->name << ";\n";
150         else if(sv->byRef != 0)
151            defs << "      implP1|(" << sv->type << " &)" << sv->name << ";\n";
152         else   
153            defs << "      implP1|" << sv->name << ";\n";
154      }
155      defs <<"    }\n";
156      if (hasArrays > 0)
157      { //Marshall each array
158        defs <<"    char *impl_buf1=impl_msg1->msgBuf+impl_arrstart;\n";
159        i = 0;
160      for(list<CStateVar*>::iterator it = myParameters.begin();
161          it != myParameters.end(); ++it, ++i) {
162        sv = *it;
163          if(sv->arrayLength != 0) {
164            defs << "    memcpy(impl_buf1+impl_off_" << sv->name << "," << sv->name << ",impl_cnt_" << sv->name << ");\n";
165          }
166        }
167      }
168      
169      // When a reference number is needed and there are parameters
170      // that need marshalling (in other words the parameters of the
171      // entry method are not messages) then the first parameter of the
172      // entry method is an integer that specifies the reference number
173      const char* refNumArg = refNumNeeded ? (*myParameters.begin())->name->charstar() : "0";
174
175      defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum
176         << ", (void *) impl_msg1, (void*) _bgParentLog, "
177         << refNumArg <<  ");\n";
178      defs << "    tr = __cDep->getTrigger(" << entryNum << ", "
179         << refNumArg << ");\n";
180    }
181
182   defs << "    if (tr == 0)\n";
183   defs << "      return;\n";
184
185   SdagConstruct::generateTraceEndCall(defs);
186 #if CMK_BIGSIM_CHARM
187   SdagConstruct::generateEndExec(defs);
188 #endif
189
190   if(whenList.size() == 1) {
191     defs << "    {\n";
192     (*whenList.begin())->generateWhenCode(defs);
193     defs << "    }\n";
194   }
195   else {   
196     defs << "    switch(tr->whenID) {\n";
197     for(list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn)
198     {
199       defs << "      case " << (*cn)->nodeNum << ":\n";
200       defs << "      {\n";
201       // This emits a `return;', so no `break' is needed
202       (*cn)->generateWhenCode(defs);
203       defs << "      }\n";
204     }
205     defs << "    }\n";
206   } 
207
208   // actual code ends
209   defs << "}\n\n";
210   templateGuardEnd(defs);
211 }
212
213 }