2 #include "xi-Parameter.h"
4 #include "xi-SdagCollection.h"
7 #include "sdag/constructs/When.h"
14 extern int fortranMode;
15 extern int internalMode;
16 const char *python_doc;
18 XStr Entry::proxyName(void) {return container->proxyName();}
19 XStr Entry::indexName(void) {return container->indexName();}
21 void Entry::print(XStr& str)
36 str << " stacksize = ";
37 stacksize->print(str);
44 if (isConstructor() && retType && !retType->isVoid())
45 XLAT_ERROR_NOCOL("constructors cannot return a value",
48 if (!isConstructor() && !retType)
49 XLAT_ERROR_NOCOL("non-constructor entry methods must specify a return type (probably void)",
52 if (isConstructor() && (isSync() || isIget())) {
53 XLAT_ERROR_NOCOL("constructors cannot have the 'sync' attribute",
58 if (param->isCkArgMsgPtr() && (!isConstructor() || !container->isMainChare()))
59 XLAT_ERROR_NOCOL("CkArgMsg can only be used in mainchare's constructor",
62 if (isExclusive() && isConstructor())
63 XLAT_ERROR_NOCOL("constructors cannot be 'exclusive'",
66 if (isImmediate() && !container->isNodeGroup())
67 XLAT_ERROR_NOCOL("[immediate] entry methods are only allowed on 'nodegroup' types",
70 if (isLocal() && (container->isChare() || container->isNodeGroup()))
71 XLAT_ERROR_NOCOL("[local] entry methods are only allowed on 'array' and 'group' types",
75 if (!isThreaded() && stacksize)
76 XLAT_ERROR_NOCOL("the 'stacksize' attribute is only applicable to methods declared 'threaded'",
79 if (retType && !isSync() && !isIget() && !isLocal() && !retType->isVoid())
80 XLAT_ERROR_NOCOL("non-void return type in a non-sync/non-local entry method\n"
81 "To return non-void, you need to declare the method as [sync], which means it has blocking semantics,"
85 if (!isLocal() && param)
86 param->checkParamList();
88 if (isPython() && !container->isPython())
89 XLAT_ERROR_NOCOL("python entry method declared in non-python chare",
92 // check the parameter passed to the function, it must be only an integer
93 if (isPython() && (!param || param->next || !param->param->getType()->isBuiltin() || !((BuiltinType*)param->param->getType())->isInt()))
94 XLAT_ERROR_NOCOL("python entry methods take only one parameter, which is of type 'int'",
97 if (isExclusive() && !container->isNodeGroup())
98 XLAT_ERROR_NOCOL("only nodegroup methods can be 'exclusive'",
101 // (?) Check that every when statement has a corresponding entry method
102 // declaration. Otherwise, print all candidates tested (as in clang, gcc.)
104 list<CEntry*> whenEntryList;
105 sdagCon->generateEntryList(whenEntryList, NULL);
107 for (list<CEntry*>::iterator en = whenEntryList.begin(); en != whenEntryList.end(); ++en) {
108 container->lookforCEntry(*en);
114 void Entry::lookforCEntry(CEntry *centry)
117 if (strcmp(name, *centry->entry) != 0) return;
119 centry->addCandidate(this);
122 if (param && !centry->paramlist) return;
123 if (!param && centry->paramlist) return;
124 if (param && !(*param == *centry->paramlist)) return;
127 centry->decl_entry = this;
130 Entry::Entry(int l, int a, Type *r, const char *n, ParamList *p, Value *sz, SdagConstruct *sc, const char *e, int fl, int ll) :
131 attribs(a), retType(r), stacksize(sz), sdagCon(sc), name((char *)n), targs(0), intExpr(e), param(p), genClosureTypeName(0), genClosureTypeNameProxy(0), genClosureTypeNameProxyTemp(0), entryPtr(0), first_line_(fl), last_line_(ll)
133 line=l; container=NULL;
136 if (param && param->isMarshalled() && !isThreaded()) attribs|=SNOKEEP;
138 if (isPython()) pythonDoc = python_doc;
139 ParamList *plist = p;
140 while (plist != NULL) {
142 if (plist->param) plist->param->entry = this;
147 void Entry::setChare(Chare *c) {
149 // mainchare constructor parameter is not allowed
150 /* ****************** REMOVED 10/8/2002 ************************
151 if (isConstructor()&&container->isMainChare() && param != NULL)
152 if (!param->isCkArgMsgPtr())
153 die("MainChare Constructor doesn't allow parameter!", line);
154 Removed old treatment for CkArgMsg to allow argc, argv or void
155 constructors for mainchares.
156 * **************************************************************/
157 if (isConstructor() && param->isVoid()) {
158 if (container->isMainChare()) {
159 //Main chare always magically takes CkArgMsg
160 Type *t = new PtrType(new NamedType("CkArgMsg"));
161 param=new ParamList(new Parameter(line,t));
162 std::cerr << "Charmxi> " << line << ": Deprecation warning: mainchare constructors should explicitly take CkArgMsg* if that's how they're implemented.\n";
164 if (container->isArray()) {
165 Array *a = dynamic_cast<Array*>(c);
166 a->hasVoidConstructor = true;
170 entryCount=c->nextEntry();
172 //Make a special "callmarshall" method, for communication optimizations to use:
173 hasCallMarshall=param->isMarshalled() && !isThreaded() && !isSync() && !isExclusive() && !fortranMode;
176 container->setSdag(1);
178 list<CEntry*> whenEntryList;
179 sdagCon->generateEntryList(whenEntryList, NULL);
181 for (list<CEntry*>::iterator i = whenEntryList.begin(); i != whenEntryList.end(); ++i) {
182 container->lookforCEntry(*i);
187 void Entry::preprocessSDAG()
189 if (isSdag() || isWhenEntry) {
190 if (container->isNodeGroup())
192 attribs |= SLOCKED; // Make the method [exclusive] to preclude races on SDAG control structures
197 // "parameterType *msg" or "void".
198 // Suitable for use as the only parameter
199 XStr Entry::paramType(int withDefaultVals,int withEO,int useConst)
202 param->print(str,withDefaultVals,useConst);
203 if (withEO) str<<eo(withDefaultVals,!param->isVoid());
207 // "parameterType *msg," if there is a non-void parameter,
208 // else empty. Suitable for use with another parameter following.
209 XStr Entry::paramComma(int withDefaultVals,int withEO)
212 if (!param->isVoid()) {
213 str << paramType(withDefaultVals,withEO);
218 XStr Entry::eo(int withDefaultVals,int priorComma) {
220 if (param->isMarshalled()) {//FIXME: add options for void methods, too...
221 if (priorComma) str<<", ";
222 str<<"const CkEntryOptions *impl_e_opts";
223 if (withDefaultVals) str<<"=NULL";
228 void Entry::collectSdagCode(SdagCollection *sc)
235 XStr Entry::marshallMsg(void)
238 XStr epName = epStr();
239 param->marshall(ret, epName);
243 XStr Entry::epStr(bool isForRedn, bool templateCall)
247 str<<"redn_wrapper_";
250 if (param->isMessage()) {
251 str<<param->getBaseName();
252 str.replace(':', '_');
254 else if (param->isVoid())
257 str<<"marshall"<<entryCount;
259 if (tspec && templateCall) {
261 tspec->genShort(str);
268 XStr Entry::epIdx(int fromProxy, bool isForRedn)
272 str << indexName()<<"::";
273 // If the chare is also templated, then we must avoid a parsing ambiguity
277 str << "idx_" << epStr(isForRedn, true) << "()";
281 XStr Entry::epRegFn(int fromProxy, bool isForRedn)
285 str << indexName() << "::";
286 str << "reg_" << epStr(isForRedn, true) << "()";
290 XStr Entry::chareIdx(int fromProxy)
294 str << indexName()<<"::";
299 XStr Entry::syncPreCall(void) {
301 if(retType->isVoid())
302 str << " void *impl_msg_typed_ret = ";
303 else if(retType->isMessage())
304 str << " "<< retType <<" impl_msg_typed_ret = ("<< retType <<")";
306 str << " CkMarshallMsg *impl_msg_typed_ret = (CkMarshallMsg *)";
310 XStr Entry::syncPostCall(void) {
312 if(retType->isVoid())
313 str << " CkFreeSysMsg(impl_msg_typed_ret); \n";
314 else if (!retType->isMessage()){
315 str <<" char *impl_buf_ret=impl_msg_typed_ret->msgBuf; \n";
316 str <<" PUP::fromMem implPS(impl_buf_ret); \n";
317 str <<" "<<retType<<" retval; implPS|retval; \n";
318 str <<" CkFreeMsg(impl_msg_typed_ret); \n";
319 str <<" return retval; \n";
322 str <<" return impl_msg_typed_ret;\n";
329 /*************************** Chare Entry Points ******************************/
331 void Entry::genChareDecl(XStr& str)
333 if(isConstructor()) {
334 genChareStaticConstructorDecl(str);
336 // entry method declaration
337 str << " " << generateTemplateSpec(tspec) << "\n"
338 << " " << retType << " " << name << "(" << paramType(1,1) << ");\n";
342 void Entry::genChareDefs(XStr& str)
344 if(isConstructor()) {
345 genChareStaticConstructorDefs(str);
347 XStr params; params<<epIdx()<<", impl_msg, &ckGetChareID()";
348 // entry method definition
349 XStr retStr; retStr<<retType;
350 str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<")\n";
351 str << "{\n ckCheck();\n"<<marshallMsg();
353 str << syncPreCall() << "CkRemoteCall("<<params<<");\n";
354 str << syncPostCall();
355 } else {//Regular, non-sync message
356 str << " if (ckIsDelegated()) {\n";
357 str << " int destPE=CkChareMsgPrep("<<params<<");\n";
358 str << " if (destPE!=-1) ckDelegatedTo()->ChareSend(ckDelegatedPtr(),"<<params<<",destPE);\n";
362 if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
363 if (isInline()) opts << "+CK_MSG_INLINE";
364 str << " else CkSendMsg("<<params<<opts<<");\n";
370 void Entry::genChareStaticConstructorDecl(XStr& str)
372 str << " static CkChareID ckNew("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
373 str << " static void ckNew("<<paramComma(1)<<"CkChareID* pcid, int onPE=CK_PE_ANY"<<eo(1)<<");\n";
374 if (!param->isVoid())
375 str << " "<<container->proxyName(0)<<"("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
378 void Entry::genChareStaticConstructorDefs(XStr& str)
380 str << makeDecl("CkChareID",1)<<"::ckNew("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
381 str << "{\n"<<marshallMsg();
382 str << " CkChareID impl_ret;\n";
383 str << " CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
384 str << " return impl_ret;\n";
387 str << makeDecl("void",1)<<"::ckNew("<<paramComma(0)<<"CkChareID* pcid, int impl_onPE"<<eo(0)<<")\n";
388 str << "{\n"<<marshallMsg();
389 str << " CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, pcid, impl_onPE);\n";
392 if (!param->isVoid()) {
393 str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
394 str << "{\n"<<marshallMsg();
395 str << " CkChareID impl_ret;\n";
396 str << " CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
397 str << " ckSetChareID(impl_ret);\n";
402 /***************************** Array Entry Points **************************/
404 void Entry::genArrayDecl(XStr& str)
406 if(isConstructor()) {
407 str << " " << generateTemplateSpec(tspec) << "\n";
408 genArrayStaticConstructorDecl(str);
410 if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
411 str << " " << generateTemplateSpec(tspec) << "\n";
413 str << " "<<"CkFutureID"<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
415 str << " "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<") ;\n";
417 str << " "<<retType<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
421 void Entry::genArrayDefs(XStr& str)
423 if(isIget() && !container->isForElement()) return;
426 genArrayStaticConstructorDefs(str);
428 {//Define array entry method
429 const char *ifNot="CkArray_IfNotThere_buffer";
430 if (isCreateHere()) ifNot="CkArray_IfNotThere_createhere";
431 if (isCreateHome()) ifNot="CkArray_IfNotThere_createhome";
433 if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
435 XStr retStr; retStr<<retType;
437 str << makeDecl("CkFutureID ",1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
439 str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1,0)<<") \n";
441 str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
442 str << "{\n ckCheck();\n";
445 inlineCall << " _TRACE_BEGIN_EXECUTE_DETAILED(0,ForArrayEltMsg,(" << epIdx()
446 << "),CkMyPe(), 0, ((CkArrayIndex&)ckGetIndex()).getProjectionID(((CkGroupID)ckGetArrayID()).idx), obj);\n";
448 inlineCall << " _TRACE_BEGIN_APPWORK();\n";
449 inlineCall << "#if CMK_LBDB_ON\n"
450 << " LDObjHandle objHandle;\n"
451 << " int objstopped=0;\n"
452 << " objHandle = obj->timingBeforeCall(&objstopped);\n"
455 "#if CMK_CHARMDEBUG\n"
456 " CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
459 if (!retType->isVoid())
460 inlineCall << retType << " retValue = ";
461 inlineCall << "obj->" << name << "(";
462 param->unmarshall(inlineCall);
463 inlineCall << ");\n";
465 "#if CMK_CHARMDEBUG\n"
466 " CpdAfterEp("<<epIdx()<<");\n"
468 inlineCall << "#if CMK_LBDB_ON\n obj->timingAfterCall(objHandle,&objstopped);\n#endif\n";
470 inlineCall << " _TRACE_END_APPWORK();\n";
471 if (!isNoTrace()) inlineCall << " _TRACE_END_EXECUTE();\n";
472 if (!retType->isVoid()) {
473 inlineCall << " return retValue;\n";
475 inlineCall << " return;\n";
479 prepareMsg << marshallMsg();
480 prepareMsg << " UsrToEnv(impl_msg)->setMsgtype(ForArrayEltMsg);\n";
481 prepareMsg << " CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;\n";
482 prepareMsg << " impl_amsg->array_setIfNotThere("<<ifNot<<");\n";
485 if (isInline() && container->isForElement()) {
486 str << " " << container->baseName() << " *obj = ckLocal();\n";
487 str << " if (obj) {\n"
493 str << " "<< container->baseName() << " *obj = ckLocal();\n";
494 str << "#if CMK_ERROR_CHECKING\n";
495 str << " if (obj==NULL) CkAbort(\"Trying to call a LOCAL entry method on a non-local element\");\n";
500 str << " CkFutureID f=CkCreateAttachedFutureSend(impl_amsg,"<<epIdx()<<",ckGetArrayID(),ckGetIndex(),&CProxyElement_ArrayBase::ckSendWrapper);"<<"\n";
504 str << syncPreCall() << "ckSendSync(impl_amsg, "<<epIdx()<<");\n";
505 str << syncPostCall();
511 if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
512 if (isInline()) opts << "+CK_MSG_INLINE";
514 if (container->isForElement() || container->isForSection()) {
515 str << " ckSend(impl_amsg, "<<epIdx()<<opts<<");\n";
518 str << " ckBroadcast(impl_amsg, "<<epIdx()<<opts<<");\n";
522 str << " return f;\n";
528 void Entry::genArrayStaticConstructorDecl(XStr& str)
530 if (!container->isArray())
531 die("Internal error - array declarations called for on non-array Chare type");
533 if (container->getForWhom() == forIndividual)
534 str<< //Element insertion routine
535 " void insert("<<paramComma(1,0)<<"int onPE=-1"<<eo(1)<<");";
536 else if (container->getForWhom() == forAll) {
537 //With options to specify size (including potentially empty, covering the param->isVoid() case)
538 str << " static CkArrayID ckNew(" << paramComma(1,0) << "const CkArrayOptions &opts = CkArrayOptions()" << eo(1) << ");\n";
539 str << " static void ckNew(" << paramComma(1,0) << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb" << eo(1) << ");\n";
541 XStr dim = ((Array*)container)->dim();
542 if (dim == (const char*)"1D") {
543 str << " static CkArrayID ckNew(" << paramComma(1,0) << "const int s1" << eo(1)<<");\n";
544 str << " static void ckNew(" << paramComma(1,0) << "const int s1, CkCallback _ck_array_creation_cb" << eo(1) <<");\n";
545 } else if (dim == (const char*)"2D") {
546 str << " static CkArrayID ckNew(" << paramComma(1,0) << "const int s1, const int s2"<<eo(1)<<");\n";
547 str << " static void ckNew(" << paramComma(1,0) << "const int s1, const int s2, CkCallback _ck_array_creation_cb" << eo(1) <<");\n";
548 } else if (dim == (const char*)"3D") {
549 str << " static CkArrayID ckNew(" << paramComma(1,0) << "const int s1, const int s2, const int s3" << eo(1)<<");\n";
550 str << " static void ckNew(" << paramComma(1,0) << "const int s1, const int s2, const int s3, CkCallback _ck_array_creation_cb" << eo(1) <<");\n";
551 /*} else if (dim==(const char*)"4D") {
552 str<<" static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4"<<eo(1)<<");\n";
553 } else if (dim==(const char*)"5D") {
554 str<<" static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n";
555 } else if (dim==(const char*)"6D") {
556 str<<" static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5, const short s6"<<eo(1)<<");\n"; */
559 else if (container->getForWhom() == forSection) { }
562 void Entry::genArrayStaticConstructorDefs(XStr& str)
564 if (!container->isArray())
565 die("Internal error - array definitions called for on non-array Chare type");
567 if (container->getForWhom() == forIndividual)
569 makeDecl("void",1)<<"::insert("<<paramComma(0,0)<<"int onPE"<<eo(0)<<")\n"
570 "{ \n"<<marshallMsg()<<
571 " UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
572 " ckInsert((CkArrayMessage *)impl_msg,"<<epIdx()<<",onPE);\n}\n";
573 else if (container->getForWhom() == forAll) {
574 XStr syncPrototype, asyncPrototype, head, syncTail, asyncTail;
575 syncPrototype << makeDecl("CkArrayID", 1) << "::ckNew";
576 asyncPrototype << makeDecl("void", 1) << "::ckNew";
581 syncTail << " UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
582 << " return ckCreateArray((CkArrayMessage *)impl_msg, "
583 << epIdx() << ", opts);\n"
586 asyncTail << " UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
587 << " CkSendAsyncCreateArray(" << epIdx() << ", _ck_array_creation_cb, opts, impl_msg);\n"
590 str << syncPrototype << "(" << paramComma(0) << "const CkArrayOptions &opts" << eo(0) << ")\n"
592 str << asyncPrototype << "(" << paramComma(0) << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb"<< eo(0) << ")\n"
593 << head << asyncTail;
595 XStr dim = ((Array*)container)->dim();
596 XStr sizeParams, sizeArgs;
599 if (dim == (const char*)"1D") {
600 sizeParams << "const int s1";
602 } else if (dim == (const char*)"2D") {
603 sizeParams << "const int s1, const int s2";
604 sizeArgs << "s1, s2";
605 } else if (dim == (const char*)"3D") {
606 sizeParams << "const int s1, const int s2, const int s3";
607 sizeArgs << "s1, s2, s3";
610 else if (dim==(const char*)"4D") {
611 sizeParams << "const short s1, const short s2, const short s3, const short s4";
612 sizeArgs << "s1, s2, s3, s4";
613 } else if (dim==(const char*)"5D") {
614 sizeParams << "const short s1, const short s2, const short s3, const short s4, "
616 sizeArgs << "s1, s2, s3, s4, s5";
617 } else if (dim==(const char*)"6D") {
618 sizeParams << "const short s1, const short s2, const short s3, const short s4, "
619 << "const short s5, const short s6";
620 sizeArgs << "s1, s2, s3, s4, s5, s6";
628 str << syncPrototype << "(" << paramComma(0) << sizeParams << eo(0) << ")\n"
629 << head << " CkArrayOptions opts(" << sizeArgs << ");\n" << syncTail;
630 str << asyncPrototype << "(" << paramComma(0) << sizeParams << ", CkCallback _ck_array_creation_cb" << eo(0) << ")\n"
631 << head << " CkArrayOptions opts(" << sizeArgs << ");\n" << asyncTail;
637 /******************************** Group Entry Points *********************************/
639 void Entry::genGroupDecl(XStr& str)
641 if(isConstructor()) {
642 str << " " << generateTemplateSpec(tspec) << "\n";
643 genGroupStaticConstructorDecl(str);
645 if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
646 str << " " << generateTemplateSpec(tspec) << "\n";
648 str << " "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<");\n";
650 str << " "<<retType<<" "<<name<<"("<<paramType(1,1)<<");\n";
651 // entry method on multiple PEs declaration
652 if(!container->isForElement() && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
653 str << " " << generateTemplateSpec(tspec) << "\n";
654 str << " "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(1)<<");\n";
655 str << " " << generateTemplateSpec(tspec) << "\n";
656 str << " "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(1)<<");\n";
661 void Entry::genGroupDefs(XStr& str)
663 //Selects between NodeGroup and Group
664 char *node = (char *)(container->isNodeGroup()?"Node":"");
666 if(isConstructor()) {
667 genGroupStaticConstructorDefs(str);
669 int forElement=container->isForElement();
670 XStr params; params<<epIdx()<<", impl_msg";
671 XStr paramg; paramg<<epIdx()<<", impl_msg, ckGetGroupID()";
672 XStr parampg; parampg<<epIdx()<<", impl_msg, ckGetGroupPe(), ckGetGroupID()";
673 // append options parameter
674 XStr opts; opts<<",0";
675 if (isImmediate()) opts << "+CK_MSG_IMMEDIATE";
676 if (isInline()) opts << "+CK_MSG_INLINE";
677 if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
679 if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
681 XStr retStr; retStr<<retType;
684 msgTypeStr<<paramType(0,1,0);
686 msgTypeStr<<paramType(0,1);
687 str << makeDecl(retStr,1)<<"::"<<name<<"("<<msgTypeStr<<")\n";
688 str << "{\n ckCheck();\n";
689 if (!isLocal()) str <<marshallMsg();
692 XStr unmarshallStr; param->unmarshall(unmarshallStr);
693 str << " "<<container->baseName()<<" *obj = ckLocalBranch();\n";
694 str << " CkAssert(obj);\n";
695 if (!isNoTrace()) str << " _TRACE_BEGIN_EXECUTE_DETAILED(0,ForBocMsg,("<<epIdx()<<"),CkMyPe(),0,NULL, NULL);\n";
697 str << " _TRACE_BEGIN_APPWORK();\n";
700 " // if there is a running obj being measured, stop it temporarily\n"
701 " LDObjHandle objHandle;\n"
702 " int objstopped = 0;\n"
703 " LBDatabase *the_lbdb = (LBDatabase *)CkLocalBranch(_lbdb);\n"
704 " if (the_lbdb->RunningObject(&objHandle)) {\n"
706 " the_lbdb->ObjectStop(objHandle);\n"
710 "#if CMK_CHARMDEBUG\n"
711 " CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
713 if (!retType->isVoid()) str << retType << " retValue = ";
714 str << "obj->"<<name<<"("<<unmarshallStr<<");\n";
715 str << "#if CMK_CHARMDEBUG\n"
716 " CpdAfterEp("<<epIdx()<<");\n"
718 str << "#if CMK_LBDB_ON\n"
719 " if (objstopped) the_lbdb->ObjectStart(objHandle);\n"
722 str << " _TRACE_END_APPWORK();\n";
723 if (!isNoTrace()) str << " _TRACE_END_EXECUTE();\n";
724 if (!retType->isVoid()) str << " return retValue;\n";
725 } else if(isSync()) {
726 str << syncPreCall() <<
727 "CkRemote"<<node<<"BranchCall("<<paramg<<", ckGetGroupPe());\n";
728 str << syncPostCall();
729 } else { // Non-sync, non-local entry method
732 str << " if (ckIsDelegated()) {\n";
733 str << " Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
734 str << " ckDelegatedTo()->"<<node<<"GroupSend(ckDelegatedPtr(),"<<parampg<<");\n";
735 str << " } else CkSendMsg"<<node<<"Branch"<<"("<<parampg<<opts<<");\n";
737 else if (container->isForSection())
739 str << " if (ckIsDelegated()) {\n";
740 str << " Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
741 str << " ckDelegatedTo()->"<<node<<"GroupSectionSend(ckDelegatedPtr(),"<<params<<", ckGetNumSections(), ckGetSectionIDs());\n";
742 str << " } else {\n";
743 str << " void *impl_msg_tmp = (ckGetNumSections()>1) ? CkCopyMsg((void **) &impl_msg) : impl_msg;\n";
744 str << " for (int i=0; i<ckGetNumSections(); ++i) {\n";
745 str << " impl_msg_tmp= (i<ckGetNumSections()-1) ? CkCopyMsg((void **) &impl_msg):impl_msg;\n";
746 str << " CkSendMsg"<<node<<"BranchMulti("<<epIdx()<<", impl_msg_tmp, ckGetGroupIDn(i), ckGetNumElements(i), ckGetElements(i)"<<opts<<");\n";
752 str << " if (ckIsDelegated()) {\n";
753 str << " Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
754 str << " ckDelegatedTo()->"<<node<<"GroupBroadcast(ckDelegatedPtr(),"<<paramg<<");\n";
755 str << " } else CkBroadcastMsg"<<node<<"Branch("<<paramg<<opts<<");\n";
760 // entry method on multiple PEs declaration
761 if(!forElement && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
762 str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(0)<<") {\n";
763 str << marshallMsg();
764 str << " CkSendMsg"<<node<<"BranchMulti("<<paramg<<", npes, pes"<<opts<<");\n";
766 str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(0)<<") {\n";
767 str << marshallMsg();
768 str << " CkSendMsg"<<node<<"BranchGroup("<<paramg<<", grp"<<opts<<");\n";
774 void Entry::genGroupStaticConstructorDecl(XStr& str)
776 if (container->isForElement()) return;
777 if (container->isForSection()) return;
779 str << " static CkGroupID ckNew("<<paramType(1,1)<<");\n";
780 if (!param->isVoid()) {
781 str << " "<<container->proxyName(0)<<"("<<paramType(1,1)<<");\n";
785 void Entry::genGroupStaticConstructorDefs(XStr& str)
787 if (container->isForElement()) return;
788 if (container->isForSection()) return;
790 //Selects between NodeGroup and Group
791 char *node = (char *)(container->isNodeGroup()?"Node":"");
792 str << makeDecl("CkGroupID",1)<<"::ckNew("<<paramType(0,1)<<")\n";
793 str << "{\n"<<marshallMsg();
794 str << " UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
795 if (param->isMarshalled()) {
796 str << " if (impl_e_opts)\n";
797 str << " UsrToEnv(impl_msg)->setGroupDep(impl_e_opts->getGroupDepID());\n";
799 str << " return CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg);\n";
802 if (!param->isVoid()) {
803 str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramType(0,1)<<")\n";
804 str << "{\n"<<marshallMsg();
805 str << " UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
806 if (param->isMarshalled()) {
807 str << " if (impl_e_opts)\n";
808 str << " UsrToEnv(impl_msg)->setGroupDep(impl_e_opts->getGroupDepID());\n";
810 str << " ckSetGroupID(CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg));\n";
815 /******************* Python Entry Point Code **************************/
816 void Entry::genPythonDecls(XStr& str) {
817 str <<"/* STATIC DECLS: "; print(str); str << " */\n";
819 str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg);\n";
823 void Entry::genPythonDefs(XStr& str) {
824 str <<"/* DEFS: "; print(str); str << " */\n";
827 str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg) {\n";
828 str << " PyObject *dict = PyModule_GetDict(PyImport_AddModule(\"__main__\"));\n";
829 str << " int pyNumber = PyInt_AsLong(PyDict_GetItemString(dict,\"__charmNumber__\"));\n";
830 str << " PythonObject *pythonObj = (PythonObject *)PyLong_AsVoidPtr(PyDict_GetItemString(dict,\"__charmObject__\"));\n";
831 str << " "<<container->baseName()<<" *object = static_cast<"<<container->baseName()<<" *>(pythonObj);\n";
832 str << " object->pyWorkers[pyNumber].arg=arg;\n";
833 str << " object->pyWorkers[pyNumber].result=&CtvAccess(pythonReturnValue);\n";
834 str << " object->pyWorkers[pyNumber].pythread=PyThreadState_Get();\n";
835 str << " CtvAccess(pythonReturnValue) = 0;\n";
837 str << " //pyWorker->thisProxy."<<name<<"(pyNumber);\n";
838 str << " object->"<<name<<"(pyNumber);\n";
840 str << " //CthSuspend();\n";
842 str << " if (CtvAccess(pythonReturnValue)) {\n";
843 str << " return CtvAccess(pythonReturnValue);\n";
844 str << " } else {\n";
845 str << " Py_INCREF(Py_None); return Py_None;\n";
851 void Entry::genPythonStaticDefs(XStr& str) {
853 str << " {\""<<name<<"\",_Python_"<<container->baseName()<<"_"<<name<<",METH_VARARGS},\n";
857 void Entry::genPythonStaticDocs(XStr& str) {
859 str << "\n \""<<name<<" -- \"";
860 if (pythonDoc) str <<(char*)pythonDoc;
866 /******************* Accelerator (Accel) Entry Point Code ********************/
868 void Entry::genAccelFullParamList(XStr& str, int makeRefs) {
870 if (!isAccel()) return;
872 ParamList* curParam = NULL;
875 // Parameters (which are read only by default)
877 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
878 while (curParam != NULL) {
880 if (!isFirst) { str << ", "; }
882 Parameter* param = curParam->param;
884 if (param->isArray()) {
885 str << param->getType()->getBaseName() << "* " << param->getName();
887 str << param->getType()->getBaseName() << " " << param->getName();
891 curParam = curParam->next;
895 curParam = accelParam;
896 while (curParam != NULL) {
898 if (!isFirst) { str << ", "; }
900 Parameter* param = curParam->param;
901 int bufType = param->getAccelBufferType();
902 int needWrite = makeRefs && ((bufType == Parameter::ACCEL_BUFFER_TYPE_READWRITE) || (bufType == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY));
903 if (param->isArray()) {
904 str << param->getType()->getBaseName() << "* " << param->getName();
906 str << param->getType()->getBaseName() << ((needWrite) ? (" &") : (" ")) << param->getName();
910 curParam = curParam->next;
913 // Implied object pointer
914 if (!isFirst) { str << ", "; }
915 str << container->baseName() << "* impl_obj";
918 void Entry::genAccelFullCallList(XStr& str) {
919 if (!isAccel()) return;
923 // Marshalled parameters to entry method
924 ParamList* curParam = param;
925 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
926 while (curParam != NULL) {
927 if (!isFirstFlag) str << ", ";
929 str << curParam->param->getName();
930 curParam = curParam->next;
933 // General variables (prefix with "impl_obj->" for member variables of the current object)
934 curParam = accelParam;
935 while (curParam != NULL) {
936 if (!isFirstFlag) str << ", ";
938 str << (*(curParam->param->getAccelInstName()));
939 curParam = curParam->next;
943 if (!isFirstFlag) str << ", ";
948 void Entry::genAccelIndexWrapperDecl_general(XStr& str) {
949 str << " static void _accelCall_general_" << epStr() << "(";
950 genAccelFullParamList(str, 1);
954 void Entry::genAccelIndexWrapperDef_general(XStr& str) {
955 str << makeDecl("void") << "::_accelCall_general_" << epStr() << "(";
956 genAccelFullParamList(str, 1);
960 //str << " // DMK - DEBUG\n";
961 //str << " CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
962 // << makeDecl("void") << "::_accelCall_general_" << epStr()
963 // << "(...) - Called...\\n\");\n\n";
965 str << (*accelCodeBody);
968 str << " impl_obj->" << (*accelCallbackName) << "();\n";
972 void Entry::genAccelIndexWrapperDecl_spe(XStr& str) {
974 // Function to issue work request
975 str << " static void _accelCall_spe_" << epStr() << "(";
976 genAccelFullParamList(str, 0);
979 // Callback function that is a member of CkIndex_xxx
980 str << " static void _accelCall_spe_callback_" << epStr() << "(void* userPtr);\n";
983 // DMK - Accel Support
988 void Entry::genAccelIndexWrapperDef_spe(XStr& str) {
990 XStr containerType = container->baseName();
992 // Some blank space for readability
996 ///// Generate struct that will be passed to callback function /////
998 str << "typedef struct __spe_callback_struct_" << epStr() << " {\n"
999 << " " << containerType << "* impl_obj;\n"
1000 << " WRHandle wrHandle;\n"
1001 << " void* scalar_buf_ptr;\n";
1003 // Pointers for marshalled parameter buffers
1004 ParamList* curParam = param;
1005 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1006 while (curParam != NULL) {
1007 if (curParam->param->isArray()) {
1008 str << " void* param_buf_ptr_" << curParam->param->getName() << ";\n";
1010 curParam = curParam->next;
1012 curParam = accelParam;
1013 while (curParam != NULL) {
1014 if (curParam->param->isArray()) {
1015 str << " void* accelParam_buf_ptr_" << curParam->param->getName() << ";\n";
1017 curParam = curParam->next;
1020 str << "} SpeCallbackStruct_" << epStr() << ";\n\n";
1023 ///// Generate callback function /////
1025 str << "void _accelCall_spe_callback_" << container->baseName() << "_" << epStr() << "(void* userPtr) {\n"
1026 << " " << container->indexName() << "::_accelCall_spe_callback_" << epStr() << "(userPtr);\n"
1029 str << makeDecl("void") << "::_accelCall_spe_callback_" << epStr() << "(void* userPtr) {\n";
1030 str << " SpeCallbackStruct_" << epStr() << "* cbStruct = (SpeCallbackStruct_" << epStr() << "*)userPtr;\n";
1031 str << " " << containerType << "* impl_obj = cbStruct->impl_obj;\n";
1033 // Write scalars that are 'out' or 'inout' from the scalar buffer back into memory
1035 if (accel_numScalars > 0) {
1037 // Get the pointer to the scalar buffer
1038 int dmaList_scalarBufIndex = 0;
1039 if (accel_dmaList_scalarNeedsWrite) {
1040 dmaList_scalarBufIndex += accel_dmaList_numReadOnly;
1042 str << " char* __scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n";
1046 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1047 while (curParam != NULL) {
1048 if (!(curParam->param->isArray())) {
1049 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1051 curParam = curParam->next;
1054 // Read only accel parameters
1055 curParam = accelParam;
1056 while (curParam != NULL) {
1057 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1058 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1060 curParam = curParam->next;
1063 // Read write accel parameters
1064 curParam = accelParam;
1065 while (curParam != NULL) {
1066 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1067 str << " " << (*(curParam->param->getAccelInstName())) << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1068 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1070 curParam = curParam->next;
1073 // Write only accel parameters
1074 curParam = accelParam;
1075 while (curParam != NULL) {
1076 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1077 str << " " << (*(curParam->param->getAccelInstName())) << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1078 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1080 curParam = curParam->next;
1084 // Call the callback function
1085 str << " (cbStruct->impl_obj)->" << (*accelCallbackName) << "();\n";
1088 str << " if (cbStruct->scalar_buf_ptr != NULL) { free_aligned(cbStruct->scalar_buf_ptr); }\n";
1090 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1091 while (curParam != NULL) {
1092 if (curParam->param->isArray()) {
1093 str << " if (cbStruct->param_buf_ptr_" << curParam->param->getName() << " != NULL) { "
1094 << "free_aligned(cbStruct->param_buf_ptr_" << curParam->param->getName() << "); "
1097 curParam = curParam->next;
1099 str << " delete cbStruct;\n";
1104 ///// Generate function to issue work request /////
1106 str << makeDecl("void") << "::_accelCall_spe_" << epStr() << "(";
1107 genAccelFullParamList(str, 0);
1111 //str << " // DMK - DEBUG\n"
1112 // << " CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
1113 // << makeDecl("void") << "::_accelCall_spe_" << epStr()
1114 // << "(...) - Called... (funcIndex:%d)\\n\", accel_spe_func_index__" << epStr() << ");\n\n";
1117 str << " // Allocate a user structure to be passed to the callback function\n"
1118 << " SpeCallbackStruct_" << epStr() << "* cbStruct = new SpeCallbackStruct_" << epStr() << ";\n"
1119 << " cbStruct->impl_obj = impl_obj;\n"
1120 << " cbStruct->wrHandle = INVALID_WRHandle; // NOTE: Set actual value later...\n"
1121 << " cbStruct->scalar_buf_ptr = NULL;\n";
1122 // Set all parameter buffer pointers in the callback structure to NULL
1124 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1125 while (curParam != NULL) {
1126 if (curParam->param->isArray()) {
1127 str << " cbStruct->param_buf_ptr_" << curParam->param->getName() << " = NULL;\n";
1129 curParam = curParam->next;
1131 curParam = accelParam;
1132 while (curParam != NULL) {
1133 if (curParam->param->isArray()) {
1134 str << " cbStruct->accelParam_buf_ptr_" << curParam->param->getName() << " = NULL;\n";
1136 curParam = curParam->next;
1141 // Create the DMA list
1142 int dmaList_curIndex = 0;
1143 int numDMAListEntries = accel_numArrays;
1144 if (accel_numScalars > 0) { numDMAListEntries++; }
1145 if (numDMAListEntries <= 0) {
1146 XLAT_ERROR_NOCOL("accel entry with no parameters",
1150 // DMK - NOTE : TODO : FIXME - For now, force DMA lists to only be the static length or less.
1151 // Fix this in the future to handle any length supported by hardware. Also, for now,
1152 // #if this check since non-Cell architectures do not have SPE_DMA_LIST_LENGTH defined and
1153 // this code should not be called unless this is a Cell architecture.
1155 if (numDMAListEntries > SPE_DMA_LIST_LENGTH) {
1156 die("Accel entries do not support parameter lists of length > SPE_DMA_LIST_LENGTH yet... fix me...");
1160 // Do a pass of all the parameters, determine the size of all scalars (to pack them)
1161 if (accel_numScalars > 0) {
1162 str << " // Create a single buffer to hold all the scalar values\n";
1163 str << " int scalar_buf_len = 0;\n";
1165 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1166 while (curParam != NULL) {
1167 if (!(curParam->param->isArray())) {
1168 str << " scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1170 curParam = curParam->next;
1172 curParam = accelParam;
1173 while (curParam != NULL) {
1174 if (!(curParam->param->isArray())) {
1175 str << " scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1177 curParam = curParam->next;
1179 str << " scalar_buf_len = ROUNDUP_128(scalar_buf_len);\n"
1180 << " cbStruct->scalar_buf_ptr = malloc_aligned(scalar_buf_len, 128);\n"
1181 << " char* scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n\n";
1185 // Declare the DMA list
1186 str << " // Declare and populate the DMA list for the work request\n";
1187 str << " DMAListEntry dmaList[" << numDMAListEntries << "];\n\n";
1190 // Parameters: read only by default & arrays need to be copied since message will be deleted
1192 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1193 while (curParam != NULL) {
1195 // Check to see if the scalar buffer needs slipped into the dma list here
1196 if (accel_numScalars > 0) {
1197 if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1198 ((dmaList_curIndex == accel_dmaList_numReadOnly) && (accel_dmaList_scalarNeedsWrite))
1201 str << " /*** Scalar Buffer ***/\n"
1202 << " dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1203 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1208 // Add this parameter to the dma list (somehow)
1209 str << " /*** Param: '" << curParam->param->getName() << "' ***/\n";
1210 if (curParam->param->isArray()) {
1212 << " int bufSize = sizeof(" << curParam->param->getType()->getBaseName() << ") * (" << curParam->param->getArrayLen() << ");\n"
1213 << " bufSize = ROUNDUP_128(bufSize);\n"
1214 << " cbStruct->param_buf_ptr_" << curParam->param->getName() << " = malloc_aligned(bufSize, 128);\n"
1215 << " memcpy(cbStruct->param_buf_ptr_" << curParam->param->getName() << ", " << curParam->param->getName() << ", bufSize);\n"
1216 << " dmaList[" << dmaList_curIndex << "].size = bufSize;\n"
1217 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->param_buf_ptr_" << curParam->param->getName() << ");\n"
1221 str << " *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1222 << curParam->param->getName() << ";\n"
1223 << " scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1225 curParam = curParam->next;
1229 // Read only accel params
1230 curParam = accelParam;
1231 while (curParam != NULL) {
1233 // Check to see if the scalar buffer needs slipped into the dma list here
1234 if (accel_numScalars > 0) {
1235 if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1236 ((dmaList_curIndex == accel_dmaList_numReadOnly) && (accel_dmaList_scalarNeedsWrite))
1239 str << " /*** Scalar Buffer ***/\n"
1240 << " dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1241 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1246 // Add this parameter
1247 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1248 str << " /*** Accel Param: '" << curParam->param->getName() << " ("
1249 << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1250 if (curParam->param->isArray()) {
1251 str << " dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1252 << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1253 << "(" << curParam->param->getArrayLen() << "));\n"
1254 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(" << (*(curParam->param->getAccelInstName())) << ");\n";
1257 str << " *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1258 << (*(curParam->param->getAccelInstName())) << ";\n"
1259 << " scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1264 curParam = curParam->next;
1267 // Read/write accel params
1268 curParam = accelParam;
1269 while (curParam != NULL) {
1271 // Check to see if the scalar buffer needs slipped into the dma list here
1272 if (accel_numScalars > 0) {
1273 if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1274 ((dmaList_curIndex == accel_dmaList_numReadOnly) && (accel_dmaList_scalarNeedsWrite))
1277 str << " /*** Scalar Buffer ***/\n"
1278 << " dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1279 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1284 // Add this parameter
1285 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1286 str << " /*** Accel Param: '" << curParam->param->getName() << " ("
1287 << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1288 if (curParam->param->isArray()) {
1289 str << " dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1290 << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1291 << "(" << curParam->param->getArrayLen() << "));\n"
1292 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(" << (*(curParam->param->getAccelInstName())) << ");\n";
1295 str << " *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1296 << (*(curParam->param->getAccelInstName())) << ";\n"
1297 << " scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1302 curParam = curParam->next;
1305 // Write only accel params
1306 curParam = accelParam;
1307 while (curParam != NULL) {
1309 // Add this parameter
1310 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1311 str << " /*** Accel Param: '" << curParam->param->getName() << " ("
1312 << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1313 if (curParam->param->isArray()) {
1314 str << " dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1315 << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1316 << "(" << curParam->param->getArrayLen() << "));\n"
1317 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)(" << (*(curParam->param->getAccelInstName())) << ");\n";
1320 str << " *((" << curParam->param->getType()->getBaseName() << "*)scalar_buf_offset) = "
1321 << (*(curParam->param->getAccelInstName())) << ";\n"
1322 << " scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1327 curParam = curParam->next;
1330 str << " // Issue the work request\n";
1331 str << " cbStruct->wrHandle = sendWorkRequest_list(accel_spe_func_index__" << epStr() << ",\n"
1334 << " " << accel_dmaList_numReadOnly << ",\n"
1335 << " " << accel_dmaList_numReadWrite << ",\n"
1336 << " " << accel_dmaList_numWriteOnly << ",\n"
1338 << " WORK_REQUEST_FLAGS_NONE,\n"
1339 << " _accelCall_spe_callback_" << container->baseName() << "_" << epStr() << "\n"
1345 // Some blank space for readability
1349 int Entry::genAccels_spe_c_funcBodies(XStr& str) {
1351 // Make sure this is an accelerated entry method (just return if not)
1352 if (!isAccel()) { return 0; }
1354 // Declare the spe function
1355 str << "void __speFunc__" << indexName() << "__" << epStr() << "(DMAListEntry* dmaList) {\n";
1357 ParamList* curParam = NULL;
1358 int dmaList_curIndex = 0;
1360 // Identify the scalar buffer if there is one
1361 if (accel_numScalars > 0) {
1362 if (accel_dmaList_scalarNeedsWrite) {
1363 str << " void* __scalar_buf_ptr = (void*)(dmaList[" << accel_dmaList_numReadOnly << "].ea);\n";
1365 str << " void* __scalar_buf_ptr = (void*)(dmaList[0].ea);\n";
1368 str << " char* __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1371 // Pull out all the parameters
1373 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1374 while (curParam != NULL) {
1375 if (curParam->param->isArray()) {
1376 str << " " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1379 str << " " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1380 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1382 curParam = curParam->next;
1385 // Read only accel params
1386 curParam = accelParam;
1387 while (curParam != NULL) {
1388 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1389 if (curParam->param->isArray()) {
1390 str << " " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1393 str << " " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1394 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1397 curParam = curParam->next;
1400 // Reset the dmaList_curIndex to the read-write portion of the dmaList
1401 dmaList_curIndex = accel_dmaList_numReadOnly;
1402 if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1406 // Read-write accel params
1407 curParam = accelParam;
1408 while (curParam != NULL) {
1409 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1410 if (curParam->param->isArray()) {
1411 str << " " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1414 str << " " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1415 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1418 curParam = curParam->next;
1421 // Write only accel params
1422 curParam = accelParam;
1423 while (curParam != NULL) {
1424 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1425 if (curParam->param->isArray()) {
1426 str << " " << curParam->param->getType()->getBaseName() << "* " << curParam->param->getName() << " = (" << curParam->param->getType()->getBaseName() << "*)(dmaList[" << dmaList_curIndex << "].ea);\n";
1429 str << " " << curParam->param->getType()->getBaseName() << " " << curParam->param->getName() << " = *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1430 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1433 curParam = curParam->next;
1437 // Function body from the interface file
1438 str << " {\n " << (*accelCodeBody) << "\n }\n";
1441 // Write the scalar values that are not read only back into the scalar buffer
1442 if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1444 str << " __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1448 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
1449 while (curParam != NULL) {
1450 if (!(curParam->param->isArray())) {
1451 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1453 curParam = curParam->next;
1456 // Read only accel parameters
1457 curParam = accelParam;
1458 while (curParam != NULL) {
1459 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1460 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1462 curParam = curParam->next;
1465 // Read only accel parameters
1466 curParam = accelParam;
1467 while (curParam != NULL) {
1468 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1469 str << " *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1470 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1472 curParam = curParam->next;
1475 // Read only accel parameters
1476 curParam = accelParam;
1477 while (curParam != NULL) {
1478 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1479 str << " *((" << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1480 str << " __scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName() << ");\n";
1482 curParam = curParam->next;
1492 void Entry::genAccels_spe_c_regFuncs(XStr& str) {
1494 str << " funcLookupTable[curIndex ].funcIndex = curIndex;\n"
1495 << " funcLookupTable[curIndex++].funcPtr = __speFunc__" << indexName() << "__" << epStr() << ";\n";
1499 void Entry::genAccels_ppe_c_regFuncs(XStr& str) {
1501 str << " " << indexName() << "::accel_spe_func_index__" << epStr() << " = curIndex++;\n";
1506 /******************* Shared Entry Point Code **************************/
1507 void Entry::genIndexDecls(XStr& str)
1509 str << " /* DECLS: "; print(str); str << " */";
1511 XStr templateSpecLine;
1512 templateSpecLine << "\n " << generateTemplateSpec(tspec);
1514 // Entry point index storage
1515 str << "\n // Entry point registration at startup"
1517 << "\n static int reg_" << epStr() << "();" ///< @note: Should this be generated as private?
1518 << "\n // Entry point index lookup"
1520 << "\n inline static int idx_" << epStr() << "() {"
1521 << "\n static int epidx = " << epRegFn(0) << ";"
1522 << "\n return epidx;"
1525 if (!isConstructor()) {
1526 str << templateSpecLine
1527 << "\n inline static int idx_" << name << "("
1529 << " (" << container->baseName() << "::*)(";
1533 << "\n return " << epIdx(0) << ";"
1537 // DMK - Accel Support - Also declare the function index for the Offload API call
1540 str << " static int accel_spe_func_index__" << epStr() << ";\n";
1544 // Index function, so user can find the entry point number
1545 str << templateSpecLine
1546 << "\n static int ";
1547 if (isConstructor()) str <<"ckNew";
1549 str << "("<<paramType(1,0)<<") { return "<<epIdx(0)<<"; }";
1551 // DMK - Accel Support
1553 genAccelIndexWrapperDecl_general(str);
1555 genAccelIndexWrapperDecl_spe(str);
1559 if (isReductionTarget()) {
1560 str << "\n // Entry point registration at startup"
1562 << "\n static int reg_"<< epStr(true) <<"();" ///< @note: Should this be generated as private?
1563 << "\n // Entry point index lookup"
1565 << "\n inline static int idx_" << epStr(true) << "() {"
1566 << "\n static int epidx = "<< epRegFn(0, true) <<";"
1567 << "\n return epidx;"
1570 << "\n static int " << "redn_wrapper_" << name
1571 << "(CkReductionMsg* impl_msg) { return " << epIdx(0, true) << "; }"
1573 << "\n static void _call_" << epStr(true) << "(void* impl_msg, void* impl_obj_void);";
1576 // call function declaration
1577 str << templateSpecLine
1578 << "\n static void _call_" << epStr() << "(void* impl_msg, void* impl_obj);";
1579 str << templateSpecLine
1580 << "\n static void _call_sdag_" << epStr() << "(void* impl_msg, void* impl_obj);";
1582 str << templateSpecLine
1583 << "\n static void _callthr_"<<epStr()<<"(CkThrCallArg *);";
1585 if (hasCallMarshall) {
1586 str << templateSpecLine
1587 << "\n static int _callmarshall_" << epStr()
1588 << "(char* impl_buf, void* impl_obj_void);";
1590 if (param->isMarshalled()) {
1591 str << templateSpecLine
1592 << "\n static void _marshallmessagepup_"<<epStr()<<"(PUP::er &p,void *msg);";
1597 void Entry::genDecls(XStr& str)
1602 str << "/* DECLS: "; print(str); str << " */\n";
1604 if (isMigrationConstructor())
1605 {} //User cannot call the migration constructor
1606 else if(container->isGroup()) {
1608 } else if(container->isArray()) {
1611 else if(container->isForElement())
1613 } else { // chare or mainchare
1618 void Entry::genClosureEntryDecls(XStr& str) {
1619 genClosure(str, false);
1622 void Entry::genClosureEntryDefs(XStr& str) {
1623 templateGuardBegin(tspec || container->isTemplated(), str);
1624 genClosure(str, true);
1625 templateGuardEnd(str);
1628 void Entry::genClosure(XStr& decls, bool isDef) {
1629 if (isConstructor() || (isLocal() && !sdagCon)) return;
1631 bool hasArray = false, isMessage = false;
1634 XStr structure, toPup, alloc, getter, dealloc;
1635 for(ParamList* pl = param; pl != NULL; pl = pl->next, i++) {
1636 Parameter* sv = pl->param;
1638 if (XStr(sv->type->getBaseName()) == "CkArrayOptions") continue;
1643 if ((sv->isMessage() != 1) && (sv->isVoid() != 1)) {
1644 structure << sv->type << " ";
1645 getter << sv->type << " ";
1646 if (sv->isArray() != 0) {
1651 if (sv->isArray() != 0) {
1652 hasArray = hasArray || true;
1654 toPup << " " << "__p | " << sv->name << ";\n";
1658 if (sv->name != 0) {
1659 structure << sv->name << ";\n";
1660 getter << "& " << "getP" << i << "() { return " << sv->name << ";}\n";
1664 else if (sv->isVoid() != 1){
1665 if (sv->isMessage()) {
1667 structure << sv->type << " " << sv->name << ";\n";
1668 toPup << " " << "CkPupMessage(__p, (void**)&" << sv->name << ");\n";
1669 messageType << sv->type->deref();
1676 toPup << " packClosure(__p);\n";
1679 initCode << " init();\n";
1682 structure << " " << "CkMarshallMsg* _impl_marshall;\n";
1683 structure << " " << "char* _impl_buf_in;\n";
1684 structure << " " << "int _impl_buf_size;\n";
1685 dealloc << " if (_impl_marshall) CmiFree(UsrToEnv(_impl_marshall));\n";
1687 initCode << " _impl_marshall = 0;\n";
1688 initCode << " _impl_buf_in = 0;\n";
1689 initCode << " _impl_buf_size = 0;\n";
1691 toPup << " __p | _impl_buf_size;\n";
1692 toPup << " bool hasMsg = (_impl_marshall != 0); __p | hasMsg;\n";
1693 toPup << " " << "if (hasMsg) CkPupMessage(__p, (void**)&" << "_impl_marshall" << ");\n";
1694 toPup << " " << "else PUParray(__p, _impl_buf_in, _impl_buf_size);\n";
1695 toPup << " if (__p.isUnpacking()) {\n";
1696 toPup << " char *impl_buf = _impl_marshall ? _impl_marshall->msgBuf : _impl_buf_in;\n";
1697 param->beginUnmarshallSDAG(toPup);
1701 // Generate code for ensuring we don't migrate active local closures
1704 toPup << " CkAbort(\"Can\'t migrate while a local SDAG method is active.\");\n";
1708 genClosureTypeName = new XStr();
1709 genClosureTypeNameProxy = new XStr();
1710 *genClosureTypeNameProxy << "Closure_" << container->baseName() << "::";
1711 *genClosureTypeNameProxy << name << "_" << entryCount << "_closure";
1712 *genClosureTypeName << name << "_" << entryCount << "_closure";
1714 container->sdagPUPReg << " PUPable_reg(SINGLE_ARG(" << *genClosureTypeNameProxy << "));\n";
1717 if (container->isTemplated()) {
1718 decls << container->tspec(false) << "\n";
1720 decls << generateTemplateSpec(tspec) << "\n";
1721 decls << " struct " << *genClosureTypeNameProxy <<" : public SDAG::Closure" << " {\n";
1722 decls << structure << "\n";
1723 decls << " " << *genClosureTypeName << "() {\n";
1726 decls << " " << *genClosureTypeName << "(CkMigrateMessage*) {\n";
1730 decls << " void pup(PUP::er& __p) {\n";
1733 decls << " virtual ~" << *genClosureTypeName << "() {\n";
1736 decls << " " << ((container->isTemplated() || tspec) ? "PUPable_decl_template" : "PUPable_decl") << "(SINGLE_ARG(" << *genClosureTypeName;
1739 tspec->genShort(decls);
1745 decls << generateTemplateSpec(tspec) << "\n";
1746 decls << " struct " << *genClosureTypeName << ";\n";
1749 genClosureTypeName = new XStr();
1750 genClosureTypeNameProxy = new XStr();
1751 *genClosureTypeNameProxy << messageType;
1752 *genClosureTypeName << messageType;
1755 genClosureTypeNameProxyTemp = new XStr();
1756 *genClosureTypeNameProxyTemp << (container->isTemplated() ? "typename " : "") << genClosureTypeNameProxy;
1759 //This routine is only used in Entry::genDefs.
1760 // It ends the current procedure with a call to awaken another thread,
1761 // and defines the thread function to handle that call.
1762 XStr Entry::callThread(const XStr &procName,int prependEntryName)
1765 procFull<<"_callthr_";
1766 if(prependEntryName) procFull<<name<<"_";
1769 str << " CthThread tid = CthCreate((CthVoidFn)"<<procFull
1770 <<", new CkThrCallArg(impl_msg,impl_obj), "<<getStackSize()<<");\n";
1771 str << " ((Chare *)impl_obj)->CkAddThreadListeners(tid,impl_msg);\n";
1772 // str << " CkpvAccess(_traces)->CkAddThreadListeners(tid);\n";
1773 #if CMK_BIGSIM_CHARM
1774 str << " BgAttach(tid);\n";
1776 str << " CthResume(tid);\n";
1779 str << makeDecl("void")<<"::"<<procFull<<"(CkThrCallArg *impl_arg)\n";
1781 str << " void *impl_msg = impl_arg->msg;\n";
1782 str << " "<<container->baseName()<<" *impl_obj = ("<<container->baseName()<<" *) impl_arg->obj;\n";
1783 str << " delete impl_arg;\n";
1788 Generate the code to actually unmarshall the parameters and call
1791 void Entry::genCall(XStr& str, const XStr &preCall, bool redn_wrapper, bool usesImplBuf)
1793 bool isArgcArgv=false;
1794 bool isMigMain=false;
1795 bool isSDAGGen = sdagCon || isWhenEntry;
1797 if (isConstructor() && container->isMainChare() &&
1798 (!param->isVoid()) && (!param->isCkArgMsgPtr())){
1799 if(param->isCkMigMsgPtr()) isMigMain = true;
1800 else isArgcArgv = true;
1802 //Normal case: Unmarshall variables
1803 if (redn_wrapper) param->beginRednWrapperUnmarshall(str, isSDAGGen);
1806 param->beginUnmarshallSDAGCall(str, usesImplBuf);
1808 param->beginUnmarshall(str);
1810 if (param->isVoid() && !isNoKeep())
1811 str<<" CkFreeSysMsg(impl_msg);\n";
1816 if (!isConstructor() && fortranMode) {
1817 if (!container->isArray()) { // Currently, only arrays are supported
1818 cerr << (char *)container->baseName() << ": only chare arrays are currently supported\n";
1821 str << "/* FORTRAN */\n";
1822 XStr dim; dim << ((Array*)container)->dim();
1823 if (dim==(const char*)"1D")
1824 str << " int index1 = impl_obj->thisIndex;\n";
1825 else if (dim==(const char*)"2D") {
1826 str << " int index1 = impl_obj->thisIndex.x;\n";
1827 str << " int index2 = impl_obj->thisIndex.y;\n";
1829 else if (dim==(const char*)"3D") {
1830 str << " int index1 = impl_obj->thisIndex.x;\n";
1831 str << " int index2 = impl_obj->thisIndex.y;\n";
1832 str << " int index3 = impl_obj->thisIndex.z;\n";
1834 str << " ::" << fortranify(name)
1835 << "((char **)(impl_obj->user_data), &index1";
1836 if (dim==(const char*)"2D" || dim==(const char*)"3D")
1838 if (dim==(const char*)"3D")
1840 if (!param->isVoid()) { str << ", "; param->unmarshallAddress(str); }
1842 str << "/* FORTRAN END */\n";
1845 // DMK : Accel Support
1846 else if (isAccel()) {
1849 str << " if (1) { // DMK : TODO : For now, hardcode the condition (i.e. for now, do not dynamically load-balance between host and accelerator)\n";
1850 str << " _accelCall_spe_" << epStr() << "(";
1851 genAccelFullCallList(str);
1853 str << " } else {\n ";
1856 str << " _accelCall_general_" << epStr() << "(";
1857 genAccelFullCallList(str);
1866 else { //Normal case: call regular method
1867 if (isArgcArgv) str<<" CkArgMsg *m=(CkArgMsg *)impl_msg;\n"; //Hack!
1869 if(isConstructor()) {//Constructor: call "new (obj) foo(parameters)"
1870 str << " new (impl_obj) "<<container->baseName();
1871 } else {//Regular entry method: call "obj->bar(parameters)"
1872 str << " impl_obj->" << (tspec ? "template " : "") << name;
1875 tspec->genShort(str);
1880 if (isArgcArgv) { //Extract parameters from CkArgMsg (should be parameter marshalled)
1881 str<<"(m->argc,m->argv);\n";
1882 str<<" delete m;\n";
1883 }else if(isMigMain){
1884 str<<"((CkMigrateMessage*)impl_msg);\n";
1886 else {//Normal case: unmarshall parameters (or just pass message)
1889 if (param->isMessage()) {
1890 param->unmarshall(str);
1891 //} else if (param->isVoid()) {
1893 } else if (!param->isVoid()) {
1894 str << "genClosure";
1897 if (!param->isMessage() && !param->isVoid())
1898 str << " genClosure->deref();\n";
1900 str<<"("; param->unmarshall(str); str<<");\n";
1906 void Entry::genDefs(XStr& str)
1910 XStr containerType=container->baseName();
1911 XStr preMarshall,preCall,postCall;
1913 templateGuardBegin(tspec || container->isTemplated(), str);
1914 str << "/* DEFS: "; print(str); str << " */\n";
1916 if(isMigrationConstructor())
1917 {} //User cannot call the migration constructor
1918 else if(container->isGroup()){
1920 } else if(container->isArray()) {
1925 if (container->isMainChare() || container->isChare() || container->isForElement()) {
1926 if (isReductionTarget()) {
1927 XStr retStr; retStr<<retType;
1928 str << makeDecl(retStr);
1929 //str << retType << " " << indexName(); //makeDecl(retStr, 1)
1930 str << "::_call_" << epStr(true) << "(void* impl_msg, void* impl_obj_void)"
1932 << "\n " << container->baseName() << "* impl_obj = static_cast<"
1933 << container->baseName() << "*> (impl_obj_void);\n"
1934 << " char* impl_buf = (char*)((CkReductionMsg*)impl_msg)->getData();\n";
1936 genCall(str, precall, true, false);
1937 if (!(sdagCon || isWhenEntry))
1938 str << " delete (CkReductionMsg*)impl_msg;\n}\n\n";
1945 //Prevents repeated call and __idx definitions:
1946 if (container->getForWhom()!=forAll) {
1947 templateGuardEnd(str);
1951 // Define the entry point registration functions
1952 str << "\n// Entry point registration function"
1953 << "\n" << makeDecl("int") << "::reg_" << epStr() << "() {"
1954 << "\n int epidx = " << genRegEp() << ";";
1955 if (hasCallMarshall)
1956 str << "\n CkRegisterMarshallUnpackFn(epidx, "
1957 << "_callmarshall_" << epStr(false, true) << ");";
1958 if (param->isMarshalled()) {
1959 str << "\n CkRegisterMessagePupFn(epidx, "
1960 << "_marshallmessagepup_" << epStr(false, true) << ");\n";
1962 else if (param->isMessage() && !isMigrationConstructor()) {
1963 str << "\n CkRegisterMessagePupFn(epidx, (CkMessagePupFn)";
1964 param->param->getType()->deref()->print(str);
1965 str << "::ckDebugPup);";
1967 str << "\n return epidx;"
1970 if (isReductionTarget())
1972 str << "\n// Redn wrapper registration function"
1973 << "\n" << makeDecl("int") << "::reg_"<< epStr(true) <<"() {"
1974 << "\n return " << genRegEp(true) << ";"
1978 // DMK - Accel Support
1981 str << "int " << indexName() << "::" << "accel_spe_func_index__" << epStr() << "=0;\n";
1985 // Add special pre- and post- call code
1986 if(isSync() || isIget()) {
1987 //A synchronous method can return a value, and must finish before
1988 // the caller can proceed.
1989 preMarshall<< " int impl_ref = CkGetRefNum(impl_msg), impl_src = CkGetSrcPe(impl_msg);\n";
1990 if(retType->isVoid() || retType->isMessage())
1991 preCall<< " void *impl_retMsg=";
1992 if(retType->isVoid()) {
1993 preCall << "CkAllocSysMsg();\n ";
1994 } else if(retType->isMessage()){
1995 preCall << "(void *) ";
1997 preCall<< " "<<retType<<" impl_ret_val= ";
1998 postCall<<" //Marshall: impl_ret_val\n";
1999 postCall<<" int impl_ret_size=0;\n";
2000 postCall<<" { //Find the size of the PUP'd data\n";
2001 postCall<<" PUP::sizer implPS;\n";
2002 postCall<<" implPS|impl_ret_val;\n";
2003 postCall<<" impl_ret_size+=implPS.size();\n";
2005 postCall<<" CkMarshallMsg *impl_retMsg=CkAllocateMarshallMsg(impl_ret_size, NULL);\n";
2006 postCall<<" { //Copy over the PUP'd data;\n";
2007 postCall<<" PUP::toMem implPS((void *)impl_retMsg->msgBuf);\n";
2008 postCall<<" implPS|impl_ret_val;\n";
2011 postCall << " CkSendToFutureID(impl_ref, impl_retMsg, impl_src);\n";
2012 } else if(isExclusive()) {
2013 //An exclusive method
2014 preMarshall << " if(CmiTryLock(impl_obj->__nodelock)) {\n"; /*Resend msg. if lock busy*/
2015 /******* DANGER-- RESEND CODE UNTESTED **********/
2016 if (param->isMarshalled()) {
2017 preMarshall << " impl_msg = CkCopyMsg(&impl_msg);\n";
2019 preMarshall << " CkSendMsgNodeBranch("<<epIdx()<<",impl_msg,CkMyNode(),impl_obj->CkGetNodeGroupID());\n";
2020 preMarshall << " return;\n";
2021 preMarshall << " }\n";
2023 postCall << " CmiUnlock(impl_obj->__nodelock);\n";
2026 if (!isConstructor() && fortranMode) { // Fortran90
2027 str << "/* FORTRAN SECTION */\n";
2029 XStr dim; dim << ((Array*)container)->dim();
2030 // Declare the Fortran Entry Function
2031 // This is called from C++
2032 str << "extern \"C\" void " << fortranify(name) << "(char **, " << container->indexList();
2033 if (!param->isVoid()) { str << ", "; param->printAddress(str); }
2036 // Define the Fortran interface function
2037 // This is called from Fortran to send the message to a chare.
2038 str << "extern \"C\" void "
2039 //<< container->proxyName() << "_"
2040 << fortranify("SendTo_", container->baseName(), "_", name)
2041 << "(long* aindex, " << container->indexList();
2042 if (!param->isVoid()) { str << ", "; param->printAddress(str); }
2045 str << " CkArrayID *aid = (CkArrayID *)*aindex;\n";
2047 str << " " << container->proxyName() << " h(*aid);\n";
2048 str << " if (*index1 == -1) \n";
2049 str << " h." << name << "(";
2050 if (!param->isVoid()) param->printValue(str);
2053 if (dim==(const char*)"1D")
2054 str << " h[*index1]." << name << "(";
2055 else if (dim==(const char*)"2D")
2056 str << " h[CkArrayIndex2D(*index1, *index2)]." << name << "(";
2057 else if (dim==(const char*)"3D")
2058 str << " h[CkArrayIndex3D(*index1, *index2, *index3)]." << name << "(";
2059 if (!param->isVoid()) param->printValue(str);
2062 str << "/* FORTRAN SECTION END */\n";
2065 // DMK - Accel Support
2066 // Create the wrapper function for the acceleration call
2067 // TODO : FIXME : For now, just use the standard C++ code... create OffloadAPI wrappers later
2069 genAccelIndexWrapperDef_general(str);
2071 genAccelIndexWrapperDef_spe(str);
2075 //Generate the call-method body
2076 str << makeDecl("void")<<"::_call_"<<epStr()<<"(void* impl_msg, void* impl_obj_void)\n";
2078 << " " << container->baseName() << "* impl_obj = static_cast<"
2079 << container->baseName() << " *>(impl_obj_void);\n";
2081 if(isThreaded()) str << callThread(epStr());
2083 if (param->isMarshalled()) {
2084 if (param->hasConditional()) str << " MarshallMsg_"<<epStr()<<" *impl_msg_typed=(MarshallMsg_"<<epStr()<<" *)impl_msg;\n";
2085 else str << " CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2086 str << " char *impl_buf=impl_msg_typed->msgBuf;\n";
2088 genCall(str, preCall, false, false);
2089 param->endUnmarshall(str);
2091 if(isThreaded() && param->isMarshalled()) str << " delete impl_msg_typed;\n";
2093 str << " CkAbort(\"This method should never be called as it refers to a LOCAL entry method!\");\n";
2097 if (hasCallMarshall) {
2098 str << makeDecl("int") << "::_callmarshall_" << epStr()
2099 <<"(char* impl_buf, void* impl_obj_void) {\n";
2100 str << " " << containerType << "* impl_obj = static_cast< " << containerType << " *>(impl_obj_void);\n";
2102 if (!param->hasConditional()) {
2103 genCall(str, preCall, false, true);
2104 /*FIXME: implP.size() is wrong if the parameter list contains arrays--
2105 need to add in the size of the arrays.
2107 str << " return implP.size();\n";
2109 str << " CkAbort(\"This method is not implemented for EPs using conditional packing\");\n";
2110 str << " return 0;\n";
2113 str << " CkAbort(\"This method should never be called as it refers to a LOCAL entry method!\");\n";
2114 str << " return 0;\n";
2118 if (param->isMarshalled()) {
2119 str << makeDecl("void")<<"::_marshallmessagepup_"<<epStr()<<"(PUP::er &implDestP,void *impl_msg) {\n";
2121 if (param->hasConditional()) str << " MarshallMsg_"<<epStr()<<" *impl_msg_typed=(MarshallMsg_"<<epStr()<<" *)impl_msg;\n";
2122 else str << " CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2123 str << " char *impl_buf=impl_msg_typed->msgBuf;\n";
2124 param->beginUnmarshall(str);
2125 param->pupAllValues(str);
2127 str << " /*Fake pupping since we don't really have a message */\n";
2128 str << " int n=0;\n";
2129 str << " if (implDestP.hasComments()) implDestP.comment(\"LOCAL message\");\n";
2130 str << " implDestP|n;\n";
2135 // to match the registry, generate register call even if there is no SDAG code
2136 //if ((param->isMarshalled() || param->isVoid()) /* && (sdagCon || isWhenEntry) */)
2137 if ((param->isMarshalled() || param->isVoid()) && genClosureTypeNameProxy) {
2138 if (container->isTemplated())
2139 str << container->tspec(false);
2141 str << "template <";
2142 tspec->genLong(str, false);
2146 str << ((container->isTemplated() || tspec) ? "PUPable_def_template_nonInst" : "PUPable_def") << "(SINGLE_ARG(" << *genClosureTypeNameProxy;
2149 tspec->genShort(str);
2155 templateGuardEnd(str);
2158 XStr Entry::genRegEp(bool isForRedn)
2161 str << "CkRegisterEp(\"";
2163 str << "redn_wrapper_" << name << "(CkReductionMsg *impl_msg)\",\n";
2165 str << name << "("<<paramType(0)<<")\",\n";
2166 str << " _call_" << epStr(isForRedn, true);
2169 if (param->isMarshalled()) {
2170 if (param->hasConditional()) str<<"MarshallMsg_"<<epStr()<<"::__idx";
2171 else str<<"CkMarshallMsg::__idx";
2172 } else if(!param->isVoid() && !isMigrationConstructor()) {
2173 param->genMsgProxyName(str);
2175 } else if (isForRedn) {
2176 str << "CMessage_CkReductionMsg::__idx";
2184 // reductiontarget variants should not be nokeep. The actual ep will be
2185 // parameter marshalled (and hence flagged as nokeep), but we'll delete the
2186 // CkReductionMsg in generated code, not runtime code. (so that we can cast
2187 // it to CkReductionMsg not CkMarshallMsg)
2188 if ( !isForRedn && (attribs & SNOKEEP) ) str << "+CK_EP_NOKEEP";
2189 if (attribs & SNOTRACE) str << "+CK_EP_TRACEDISABLE";
2190 if (attribs & SIMMEDIATE) str << "+CK_EP_TRACEDISABLE";
2191 if (attribs & SAPPWORK) str << "+CK_EP_APPWORK";
2194 if (attribs & SMEM) str << "+CK_EP_MEMCRITICAL";
2196 if (internalMode) str << "+CK_EP_INTRINSIC";
2201 void Entry::genReg(XStr& str)
2207 str << " CkIndex_" << label << "::idx_" << name;
2209 str << "< " << targs << " >";
2210 str << "( static_cast< "
2211 << retType << " (" << label << "::*)(" << paramType(0,0) << ") >(NULL) );\n";
2215 str << " // REG: "<<*this;
2216 str << " " << epIdx(0) << ";\n";
2217 if (isReductionTarget())
2218 str << " " << epIdx(0, true) << ";\n";
2219 if (isConstructor()) {
2220 if(container->isMainChare() && !isMigrationConstructor())
2221 str << " CkRegisterMainChare(__idx, "<<epIdx(0)<<");\n";
2223 str << " CkRegisterDefaultCtor(__idx, "<<epIdx(0)<<");\n";
2224 if(isMigrationConstructor())
2225 str << " CkRegisterMigCtor(__idx, "<<epIdx(0)<<");\n";
2229 void Entry::preprocess() {
2230 ParamList *pl = param;
2231 if (pl != NULL && pl->hasConditional()) {
2233 str << "MarshallMsg_" << epStr();
2234 NamedType *nt = new NamedType(strdup(str));
2235 MsgVar *var = new MsgVar(new BuiltinType("char"), "msgBuf", 0, 1);
2236 MsgVarList *list = new MsgVarList(var);
2238 if (pl->param->isConditional()) {
2239 var = new MsgVar(pl->param->getType(), pl->param->getName(), 1, 0);
2240 list = new MsgVarList(var, list);
2242 } while (NULL!=(pl=pl->next));
2243 Message *m = new Message(-1, nt, list);
2244 m->setModule(container->containerModule);
2245 container->containerModule->prependConstruct(m);
2248 // DMK - Accel Support
2249 // Count the total number of scalar and array parameters if this is an accelerated entry
2250 accel_numScalars = 0;
2251 accel_numArrays = 0;
2252 accel_dmaList_numReadOnly = 0;
2253 accel_dmaList_numReadWrite = 0;
2254 accel_dmaList_numWriteOnly = 0;
2255 accel_dmaList_scalarNeedsWrite = 0;
2257 ParamList* curParam = param;
2258 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) { curParam = curParam->next; }
2259 while (curParam != NULL) {
2260 if (curParam->param->isArray()) {
2262 accel_dmaList_numReadOnly++;
2266 curParam = curParam->next;
2268 curParam = accelParam;
2269 while (curParam != NULL) {
2270 if (curParam->param->isArray()) {
2272 switch (curParam->param->getAccelBufferType()) {
2273 case Parameter::ACCEL_BUFFER_TYPE_READWRITE: accel_dmaList_numReadWrite++; break;
2274 case Parameter::ACCEL_BUFFER_TYPE_READONLY: accel_dmaList_numReadOnly++; break;
2275 case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY: accel_dmaList_numWriteOnly++; break;
2276 default: XLAT_ERROR_NOCOL("unknown accel param type", first_line_); break;
2280 switch (curParam->param->getAccelBufferType()) {
2281 case Parameter::ACCEL_BUFFER_TYPE_READWRITE: accel_dmaList_scalarNeedsWrite++; break;
2282 case Parameter::ACCEL_BUFFER_TYPE_READONLY: break;
2283 case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY: accel_dmaList_scalarNeedsWrite++; break;
2284 default: XLAT_ERROR_NOCOL("unknown accel param type", first_line_); break;
2287 curParam = curParam->next;
2289 if (accel_numScalars > 0) {
2290 if (accel_dmaList_scalarNeedsWrite) {
2291 accel_dmaList_numReadWrite++;
2293 accel_dmaList_numReadOnly++;
2300 int Entry::paramIsMarshalled(void) {
2301 return param->isMarshalled();
2304 int Entry::getStackSize(void) {
2305 return (stacksize ? stacksize->getIntVal() : 0);
2308 void Entry::setAccelParam(ParamList* apl) { accelParam = apl; }
2309 void Entry::setAccelCodeBody(XStr* acb) { accelCodeBody = acb; }
2310 void Entry::setAccelCallbackName(XStr* acbn) { accelCallbackName = acbn; }
2312 int Entry::isThreaded(void) { return (attribs & STHREADED); }
2313 int Entry::isSync(void) { return (attribs & SSYNC); }
2314 int Entry::isIget(void) { return (attribs & SIGET); }
2315 int Entry::isConstructor(void) { return !strcmp(name, container->baseName(0).get_string());}
2316 bool Entry::isMigrationConstructor() { return isConstructor() && (attribs & SMIGRATE); }
2317 int Entry::isExclusive(void) { return (attribs & SLOCKED); }
2318 int Entry::isImmediate(void) { return (attribs & SIMMEDIATE); }
2319 int Entry::isSkipscheduler(void) { return (attribs & SSKIPSCHED); }
2320 int Entry::isInline(void) { return attribs & SINLINE; }
2321 int Entry::isLocal(void) { return attribs & SLOCAL; }
2322 int Entry::isCreate(void) { return (attribs & SCREATEHERE)||(attribs & SCREATEHOME); }
2323 int Entry::isCreateHome(void) { return (attribs & SCREATEHOME); }
2324 int Entry::isCreateHere(void) { return (attribs & SCREATEHERE); }
2325 int Entry::isPython(void) { return (attribs & SPYTHON); }
2326 int Entry::isNoTrace(void) { return (attribs & SNOTRACE); }
2327 int Entry::isAppWork(void) { return (attribs & SAPPWORK); }
2328 int Entry::isNoKeep(void) { return (attribs & SNOKEEP); }
2329 int Entry::isSdag(void) { return (sdagCon!=0); }
2331 // DMK - Accel support
2332 int Entry::isAccel(void) { return (attribs & SACCEL); }
2334 int Entry::isMemCritical(void) { return (attribs & SMEM); }
2335 int Entry::isReductionTarget(void) { return (attribs & SREDUCE); }
2337 char *Entry::getEntryName() { return name; }
2338 int Entry::getLine() { return line; }