3 #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) {
22 if (isThreaded()) str << "threaded ";
23 if (isSync()) str << "sync ";
29 if (param) param->print(str);
32 str << " stacksize = ";
33 stacksize->print(str);
40 if (isConstructor() && retType && !retType->isVoid())
41 XLAT_ERROR_NOCOL("constructors cannot return a value", first_line_);
43 if (!isConstructor() && !retType)
45 "non-constructor entry methods must specify a return type (probably void)",
48 if (isConstructor() && (isSync() || isIget())) {
49 XLAT_ERROR_NOCOL("constructors cannot have the 'sync' attribute", first_line_);
53 if (param->isCkArgMsgPtr() && (!isConstructor() || !container->isMainChare()))
54 XLAT_ERROR_NOCOL("CkArgMsg can only be used in mainchare's constructor",
57 if (isExclusive() && isConstructor())
58 XLAT_ERROR_NOCOL("constructors cannot be 'exclusive'", first_line_);
60 if (isImmediate() && !container->isNodeGroup())
61 XLAT_ERROR_NOCOL("[immediate] entry methods are only allowed on 'nodegroup' types",
64 if (isLocal() && (container->isChare() || container->isNodeGroup()))
66 "[local] entry methods are only allowed on 'array' and 'group' types",
70 if (!isThreaded() && stacksize)
72 "the 'stacksize' attribute is only applicable to methods declared 'threaded'",
75 if (retType && !isSync() && !isIget() && !isLocal() && !retType->isVoid())
77 "non-void return type in a non-sync/non-local entry method\n"
78 "To return non-void, you need to declare the method as [sync], which means it "
79 "has blocking semantics,"
83 if (!isLocal() && param) param->checkParamList();
85 if (isPython() && !container->isPython())
86 XLAT_ERROR_NOCOL("python entry method declared in non-python chare", first_line_);
88 // check the parameter passed to the function, it must be only an integer
89 if (isPython() && (!param || param->next || !param->param->getType()->isBuiltin() ||
90 !((BuiltinType*)param->param->getType())->isInt()))
92 "python entry methods take only one parameter, which is of type 'int'",
95 if (isExclusive() && !container->isNodeGroup())
96 XLAT_ERROR_NOCOL("only nodegroup methods can be 'exclusive'", first_line_);
98 // (?) Check that every when statement has a corresponding entry method
99 // declaration. Otherwise, print all candidates tested (as in clang, gcc.)
101 list<CEntry*> whenEntryList;
102 sdagCon->generateEntryList(whenEntryList, NULL);
103 // containsWhenConstruct is used to prepend sdag entry method names with "_sdag_fnc_" when it contains one or more when clauses
104 containsWhenConstruct = !whenEntryList.empty();
106 for (list<CEntry*>::iterator en = whenEntryList.begin(); en != whenEntryList.end();
108 container->lookforCEntry(*en);
113 if (isTramTarget()) {
114 if (param && (!param->isMarshalled() || param->isVoid() || param->next != NULL))
116 "'aggregate' entry methods must be parameter-marshalled "
117 "and take a single argument",
120 if (!external && !((container->isGroup() && !container->isNodeGroup()) || container->isArray()))
122 "'aggregate' entry methods can only be used in regular groups and chare arrays",
127 void Entry::lookforCEntry(CEntry* centry) {
129 if (strcmp(name, *centry->entry) != 0) return;
131 centry->addCandidate(this);
134 if (param && !centry->paramlist) return;
135 if (!param && centry->paramlist) return;
136 if (param && !(*param == *centry->paramlist)) return;
139 centry->decl_entry = this;
142 Entry::Entry(int l, int a, Type* r, const char* n, ParamList* p, Value* sz,
143 SdagConstruct* sc, const char* e, int fl, int ll)
152 genClosureTypeName(0),
153 genClosureTypeNameProxy(0),
154 genClosureTypeNameProxyTemp(0),
162 containsWhenConstruct = false;
163 if (param && param->isMarshalled() && !isThreaded()) attribs |= SNOKEEP;
165 if (isPython()) pythonDoc = python_doc;
166 ParamList* plist = p;
167 while (plist != NULL) {
169 if (plist->param) plist->param->entry = this;
174 void Entry::setChare(Chare* c) {
176 // mainchare constructor parameter is not allowed
177 /* ****************** REMOVED 10/8/2002 ************************
178 if (isConstructor()&&container->isMainChare() && param != NULL)
179 if (!param->isCkArgMsgPtr())
180 die("MainChare Constructor doesn't allow parameter!", line);
181 Removed old treatment for CkArgMsg to allow argc, argv or void
182 constructors for mainchares.
183 * **************************************************************/
184 if (isConstructor() && param->isVoid()) {
185 if (container->isMainChare()) {
186 // Main chare always magically takes CkArgMsg
187 Type* t = new PtrType(new NamedType("CkArgMsg"));
188 param = new ParamList(new Parameter(line, t));
189 std::cerr << "Charmxi> " << line
190 << ": Deprecation warning: mainchare constructors should explicitly take "
191 "CkArgMsg* if that's how they're implemented.\n";
193 if (container->isArray()) {
194 Array* a = dynamic_cast<Array*>(c);
195 a->hasVoidConstructor = true;
199 entryCount = c->nextEntry();
201 // Make a special "callmarshall" method, for communication optimizations to use:
202 hasCallMarshall = param->isMarshalled() && !isThreaded() && !isSync() &&
203 !isExclusive() && !fortranMode;
205 container->setSdag(1);
207 list<CEntry*> whenEntryList;
208 sdagCon->generateEntryList(whenEntryList, NULL);
210 for (list<CEntry*>::iterator i = whenEntryList.begin(); i != whenEntryList.end();
212 container->lookforCEntry(*i);
217 void Entry::preprocessSDAG() {
218 if (isSdag() || isWhenEntry) {
219 if (container->isNodeGroup()) {
220 attribs |= SLOCKED; // Make the method [exclusive] to preclude races on SDAG
221 // control structures
226 // "parameterType *msg" or "void".
227 // Suitable for use as the only parameter
228 XStr Entry::paramType(int withDefaultVals, int withEO, int useConst, int rValue) {
230 param->print(str, withDefaultVals, useConst, rValue);
231 if (withEO) str << eo(withDefaultVals, !param->isVoid());
235 // "parameterType *msg," if there is a non-void parameter,
236 // else empty. Suitable for use with another parameter following.
237 XStr Entry::paramComma(int withDefaultVals, int withEO) {
239 if (!param->isVoid()) {
240 str << paramType(withDefaultVals, withEO);
245 XStr Entry::eo(int withDefaultVals, int priorComma) {
247 // Add CkEntryOptions for all non message params
248 // for param->isMarshalled() and param->isVoid()
249 if (!param->isMessage()) {
250 if (priorComma) str << ", ";
251 str << "const CkEntryOptions *impl_e_opts";
252 if (withDefaultVals) str << "=NULL";
257 void Entry::collectSdagCode(SdagCollection* sc) {
263 XStr Entry::marshallMsg(void) {
265 XStr epName = epStr();
266 param->marshall(ret, epName);
270 XStr Entry::epStr(bool isForRedn, bool templateCall) {
272 if (isForRedn) str << "redn_wrapper_";
275 if (param->isMessage()) {
276 str << param->getBaseName();
277 str.replace(':', '_');
278 } else if (param->isVoid())
281 str << "marshall" << entryCount;
283 if (tspec && templateCall) {
285 tspec->genShort(str);
292 XStr Entry::epIdx(int fromProxy, bool isForRedn) {
295 str << indexName() << "::";
296 // If the chare is also templated, then we must avoid a parsing ambiguity
297 if (tspec) str << "template ";
299 str << "idx_" << epStr(isForRedn, true) << "()";
303 XStr Entry::epRegFn(int fromProxy, bool isForRedn) {
305 if (fromProxy) str << indexName() << "::";
306 str << "reg_" << epStr(isForRedn, true) << "()";
310 XStr Entry::chareIdx(int fromProxy) {
312 if (fromProxy) str << indexName() << "::";
317 XStr Entry::syncPreCall(void) {
319 if (retType->isVoid())
320 str << " void *impl_msg_typed_ret = ";
321 else if (retType->isMessage())
322 str << " " << retType << " impl_msg_typed_ret = (" << retType << ")";
324 str << " CkMarshallMsg *impl_msg_typed_ret = (CkMarshallMsg *)";
328 XStr Entry::syncPostCall(void) {
330 if (retType->isVoid())
331 str << " CkFreeSysMsg(impl_msg_typed_ret); \n";
332 else if (!retType->isMessage()) {
333 str << " char *impl_buf_ret=impl_msg_typed_ret->msgBuf; \n";
334 str << " PUP::fromMem implPS(impl_buf_ret); \n";
335 str << " " << retType << " retval; implPS|retval; \n";
336 str << " CkFreeMsg(impl_msg_typed_ret); \n";
337 str << " return retval; \n";
339 str << " return impl_msg_typed_ret;\n";
344 /*************************** Chare Entry Points ******************************/
346 void Entry::genChareDecl(XStr& str) {
347 if (isConstructor()) {
348 genChareStaticConstructorDecl(str);
350 // entry method declaration
351 str << " " << generateTemplateSpec(tspec) << "\n"
352 << " " << retType << " " << name << "(" << paramType(1, 1) << ");\n";
356 void Entry::genChareDefs(XStr& str) {
357 if (isConstructor()) {
358 genChareStaticConstructorDefs(str);
361 params << epIdx() << ", impl_msg, &ckGetChareID()";
362 // entry method definition
365 str << makeDecl(retStr, 1) << "::" << name << "(" << paramType(0, 1) << ")\n";
366 str << "{\n ckCheck();\n";
367 str << marshallMsg();
369 str << syncPreCall() << "CkRemoteCall(" << params << ");\n";
370 str << syncPostCall();
371 } else { // Regular, non-sync message
372 str << " if (ckIsDelegated()) {\n";
373 if (param->hasRdma()) {
374 str << " CkAbort(\"Entry methods with nocopy parameters not supported when "
375 "called with delegation managers\");\n";
377 str << " int destPE=CkChareMsgPrep(" << params << ");\n";
378 str << " if (destPE!=-1) ckDelegatedTo()->ChareSend(ckDelegatedPtr(),"
379 << params << ",destPE);\n";
381 str << " } else {\n";
384 if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
385 if (isInline()) opts << "+CK_MSG_INLINE";
386 str << " CkSendMsg(" << params << opts << ");\n";
393 void Entry::genChareStaticConstructorDecl(XStr& str) {
394 str << " static CkChareID ckNew(" << paramComma(1) << "int onPE=CK_PE_ANY" << eo(1)
396 str << " static void ckNew(" << paramComma(1)
397 << "CkChareID* pcid, int onPE=CK_PE_ANY" << eo(1) << ");\n";
398 if (!param->isVoid())
399 str << " " << container->proxyName(0) << "(" << paramComma(1)
400 << "int onPE=CK_PE_ANY" << eo(1) << ");\n";
403 void Entry::genChareStaticConstructorDefs(XStr& str) {
404 str << makeDecl("CkChareID", 1) << "::ckNew(" << paramComma(0) << "int impl_onPE"
407 str << marshallMsg();
408 str << " CkChareID impl_ret;\n";
409 str << " CkCreateChare(" << chareIdx() << ", " << epIdx()
410 << ", impl_msg, &impl_ret, impl_onPE);\n";
411 str << " return impl_ret;\n";
414 str << makeDecl("void", 1) << "::ckNew(" << paramComma(0)
415 << "CkChareID* pcid, int impl_onPE" << eo(0) << ")\n";
417 str << marshallMsg();
418 str << " CkCreateChare(" << chareIdx() << ", " << epIdx()
419 << ", impl_msg, pcid, impl_onPE);\n";
422 if (!param->isVoid()) {
423 str << makeDecl(" ", 1) << "::" << container->proxyName(0) << "(" << paramComma(0)
424 << "int impl_onPE" << eo(0) << ")\n";
426 str << marshallMsg();
427 str << " CkChareID impl_ret;\n";
428 str << " CkCreateChare(" << chareIdx() << ", " << epIdx()
429 << ", impl_msg, &impl_ret, impl_onPE);\n";
430 str << " ckSetChareID(impl_ret);\n";
435 /***************************** Array Entry Points **************************/
437 void Entry::genArrayDecl(XStr& str) {
438 if (isConstructor()) {
439 str << " " << generateTemplateSpec(tspec) << "\n";
440 genArrayStaticConstructorDecl(str);
442 if ((isSync() || isLocal()) && !container->isForElement())
443 return; // No sync broadcast
445 str << " " << generateTemplateSpec(tspec) << "\n";
448 << " " << name << "(" << paramType(1, 1) << ") ;\n"; // no const
449 } else if ((isLocal() || isInline()) && container->isForElement()) {
452 ParamList *pl = param;
454 Parameter *p = pl->param;
455 if (!p->isRdma() && p->arrLen == NULL && !p->conditional && p->byReference) {
458 fwdStr << "typename Fwd" << fwdNum++ << " = " << p->type;
462 const bool doFwd = fwdNum > 1;
463 if (tspec || doFwd) {
464 str << " template <";
474 str << " " << retType << " " << name << "(" << paramType(1, 1, 0, 1) << ") ;\n";
475 } else if (isLocal()) {
476 str << " " << generateTemplateSpec(tspec) << "\n";
477 str << " " << retType << " " << name << "(" << paramType(1, 1, 0) << ") ;\n";
478 } else if (isTramTarget() && container->isForElement()) {
479 str << " " << generateTemplateSpec(tspec) << "\n";
480 str << " " << retType << " " << name << "(" << paramType(0, 1) << ") = delete;\n";
481 str << " " << retType << " " << name << "(" << paramType(1, 0) << ") ;\n";
483 str << " " << generateTemplateSpec(tspec) << "\n";
484 str << " " << retType << " " << name << "(" << paramType(1, 1)
485 << ") ;\n"; // no const
490 void Entry::genArrayDefs(XStr& str) {
491 if (isIget() && !container->isForElement()) return;
494 genArrayStaticConstructorDefs(str);
495 else { // Define array entry method
496 const char* ifNot = "CkArray_IfNotThere_buffer";
497 if (isCreateHere()) ifNot = "CkArray_IfNotThere_createhere";
498 if (isCreateHome()) ifNot = "CkArray_IfNotThere_createhome";
500 if ((isSync() || isLocal()) && !container->isForElement())
501 return; // No sync broadcast
506 str << makeDecl("CkFutureID ", 1) << "::" << name << "(" << paramType(0, 1)
507 << ") \n"; // no const
508 else if ((isLocal() || isInline()) && container->isForElement()) {
511 ParamList *pl = param;
513 Parameter *p = pl->param;
514 if (!p->isRdma() && p->arrLen == NULL && !p->conditional && p->byReference) {
517 fwdStr << "typename Fwd" << fwdNum++; // << " = " << p->type;
521 str << makeDecl(retStr, 1, false, fwdStr) << "::" << name << "(" << paramType(0, 1, 0, 1) << ") \n";
522 } else if (isLocal())
523 str << makeDecl(retStr, 1) << "::" << name << "(" << paramType(0, 1, 0) << ") \n";
525 str << makeDecl(retStr, 1) << "::" << name << "(" << paramType(0, 1)
526 << ") \n"; // no const
528 // regular broadcast and section broadcast for an entry method with rdma
529 if (param->hasRdma() && !container->isForElement()) {
530 str << " CkAbort(\"Broadcast not supported for entry methods with nocopy "
533 str << " ckCheck();\n";
536 // Create a dummy envelope to represent the "message send" to the local/inline method
537 // so that Projections can trace the method back to its caller
539 << " envelope env;\n"
540 << " env.setMsgtype(ForArrayEltMsg);\n"
541 << " env.setTotalsize(0);\n"
542 // NOTE: extra parentheses around the second argument to _TRACE_CREATION_DETAILED here
543 // are needed for templated entry methods
544 << " _TRACE_CREATION_DETAILED(&env, (" << epIdx() << "));\n"
545 << " _TRACE_CREATION_DONE(1);\n"
546 << " _TRACE_BEGIN_EXECUTE_DETAILED(CpvAccess(curPeEvent),ForArrayEltMsg,(" << epIdx()
547 << "),CkMyPe(), 0, ((CkArrayIndex&)ckGetIndex()).getProjectionID(), obj);\n";
548 if (isAppWork()) inlineCall << " _TRACE_BEGIN_APPWORK();\n";
549 inlineCall << "#if CMK_LBDB_ON\n"
550 << " LDObjHandle objHandle;\n"
551 << " int objstopped=0;\n"
552 << " objHandle = obj->timingBeforeCall(&objstopped);\n"
554 inlineCall << "#if CMK_CHARMDEBUG\n"
560 if (!retType->isVoid()) inlineCall << retType << " retValue = ";
561 inlineCall << "obj->" << (tspec ? "template " : "") << name;
564 tspec->genShort(inlineCall);
568 param->unmarshallForward(inlineCall, true);
569 inlineCall << ");\n";
570 inlineCall << "#if CMK_CHARMDEBUG\n"
575 inlineCall << "#if CMK_LBDB_ON\n "
576 "obj->timingAfterCall(objHandle,&objstopped);\n#endif\n";
577 if (isAppWork()) inlineCall << " _TRACE_END_APPWORK();\n";
578 if (!isNoTrace()) inlineCall << " _TRACE_END_EXECUTE();\n";
579 if (!retType->isVoid()) {
580 inlineCall << " return retValue;\n";
582 inlineCall << " return;\n";
586 prepareMsg << marshallMsg();
587 prepareMsg << " UsrToEnv(impl_msg)->setMsgtype(ForArrayEltMsg);\n";
588 prepareMsg << " CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;\n";
589 prepareMsg << " impl_amsg->array_setIfNotThere(" << ifNot << ");\n";
592 if (isInline() && container->isForElement()) {
593 str << " " << container->baseName() << " *obj = ckLocal();\n";
594 str << " if (obj) {\n" << inlineCall << " }\n";
598 str << " " << container->baseName() << " *obj = ckLocal();\n";
599 str << "#if CMK_ERROR_CHECKING\n";
600 str << " if (obj==NULL) CkAbort(\"Trying to call a LOCAL entry method on a "
601 "non-local element\");\n";
606 str << " CkFutureID f=CkCreateAttachedFutureSend(impl_amsg," << epIdx()
607 << ",ckGetArrayID(),ckGetIndex(),&CProxyElement_ArrayBase::ckSendWrapper);"
612 str << syncPreCall() << "ckSendSync(impl_amsg, " << epIdx() << ");\n";
613 str << syncPostCall();
614 } else if (!isLocal()) {
617 if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
618 if (isInline()) opts << "+CK_MSG_INLINE";
620 if (container->isForElement() || container->isForSection()) {
621 str << " ckSend(impl_amsg, " << epIdx() << opts << ");\n";
623 str << " ckBroadcast(impl_amsg, " << epIdx() << opts << ");\n";
627 str << " return f;\n";
632 if (!tspec && !container->isTemplated() && !isIget() && (isLocal() || isInline()) && container->isForElement()) {
635 ParamList *pl = param;
637 Parameter *p = pl->param;
638 if (!p->isRdma() && p->arrLen == NULL && !p->conditional && p->byReference) {
642 if (p->byConst) fwdStr << "const ";
643 fwdStr << p->type << " &";
647 const bool doFwd = fwdNum > 1;
649 str << "// explicit instantiation for compatibility\n";
650 str << "template " << makeDecl(retStr, 1) << "::" << name << "<" << fwdStr << ">(" << paramType(0, 1, 0) << ");\n";
656 void Entry::genArrayStaticConstructorDecl(XStr& str) {
657 if (!container->isArray())
658 die("Internal error - array declarations called for on non-array Chare type");
660 if (container->getForWhom() == forIndividual)
661 str << // Element insertion routine
662 " void insert(" << paramComma(1, 0) << "int onPE=-1" << eo(1) << ");";
663 else if (container->getForWhom() == forAll) {
664 // With options to specify size (including potentially empty, covering the
665 // param->isVoid() case)
666 str << " static CkArrayID ckNew(" << paramComma(1, 0)
667 << "const CkArrayOptions &opts = CkArrayOptions()" << eo(1) << ");\n";
668 str << " static void ckNew(" << paramComma(1, 0)
669 << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb" << eo(1)
672 XStr dim = ((Array*)container)->dim();
673 if (dim == (const char*)"1D") {
674 str << " static CkArrayID ckNew(" << paramComma(1, 0) << "const int s1" << eo(1)
676 str << " static void ckNew(" << paramComma(1, 0)
677 << "const int s1, CkCallback _ck_array_creation_cb" << eo(1) << ");\n";
678 } else if (dim == (const char*)"2D") {
679 str << " static CkArrayID ckNew(" << paramComma(1, 0)
680 << "const int s1, const int s2" << eo(1) << ");\n";
681 str << " static void ckNew(" << paramComma(1, 0)
682 << "const int s1, const int s2, CkCallback _ck_array_creation_cb" << eo(1)
684 } else if (dim == (const char*)"3D") {
685 str << " static CkArrayID ckNew(" << paramComma(1, 0)
686 << "const int s1, const int s2, const int s3" << eo(1) << ");\n";
687 str << " static void ckNew(" << paramComma(1, 0)
688 << "const int s1, const int s2, const int s3, CkCallback _ck_array_creation_cb"
690 /*} else if (dim==(const char*)"4D") {
691 str<<" static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short
692 s2, const short s3, const short s4"<<eo(1)<<");\n"; } else if (dim==(const
693 char*)"5D") { str<<" static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1,
694 const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n"; }
695 else if (dim==(const char*)"6D") { str<<" static CkArrayID
696 ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const
697 short s4, const short s5, const short s6"<<eo(1)<<");\n"; */
699 } else if (container->getForWhom() == forSection) {
703 void Entry::genArrayStaticConstructorDefs(XStr& str) {
704 if (!container->isArray())
705 die("Internal error - array definitions called for on non-array Chare type");
707 if (container->getForWhom() == forIndividual)
708 str << makeDecl("void", 1) << "::insert(" << paramComma(0, 0) << "int onPE" << eo(0)
712 << " UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
713 " ckInsert((CkArrayMessage *)impl_msg,"
714 << epIdx() << ",onPE);\n}\n";
715 else if (container->getForWhom() == forAll) {
716 XStr syncPrototype, asyncPrototype, head, syncTail, asyncTail;
717 syncPrototype << makeDecl("CkArrayID", 1) << "::ckNew";
718 asyncPrototype << makeDecl("void", 1) << "::ckNew";
720 head << "{\n" << marshallMsg();
722 syncTail << " UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
723 << " CkArrayID gId = ckCreateArray((CkArrayMessage *)impl_msg, " << epIdx()
726 genTramInstantiation(syncTail);
727 syncTail << " return gId;\n}\n";
729 asyncTail << " UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
730 << " CkSendAsyncCreateArray(" << epIdx()
731 << ", _ck_array_creation_cb, opts, impl_msg);\n"
734 str << syncPrototype << "(" << paramComma(0) << "const CkArrayOptions &opts" << eo(0)
737 str << asyncPrototype << "(" << paramComma(0)
738 << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb" << eo(0)
740 << head << asyncTail;
742 XStr dim = ((Array*)container)->dim();
743 XStr sizeParams, sizeArgs;
746 if (dim == (const char*)"1D") {
747 sizeParams << "const int s1";
749 } else if (dim == (const char*)"2D") {
750 sizeParams << "const int s1, const int s2";
751 sizeArgs << "s1, s2";
752 } else if (dim == (const char*)"3D") {
753 sizeParams << "const int s1, const int s2, const int s3";
754 sizeArgs << "s1, s2, s3";
757 else if (dim==(const char*)"4D") {
758 sizeParams << "const short s1, const short s2, const short s3, const short s4";
759 sizeArgs << "s1, s2, s3, s4";
760 } else if (dim==(const char*)"5D") {
761 sizeParams << "const short s1, const short s2, const short s3, const short s4, "
763 sizeArgs << "s1, s2, s3, s4, s5";
764 } else if (dim==(const char*)"6D") {
765 sizeParams << "const short s1, const short s2, const short s3, const short s4, "
766 << "const short s5, const short s6";
767 sizeArgs << "s1, s2, s3, s4, s5, s6";
775 str << syncPrototype << "(" << paramComma(0) << sizeParams << eo(0) << ")\n"
776 << head << " CkArrayOptions opts(" << sizeArgs << ");\n"
778 str << asyncPrototype << "(" << paramComma(0) << sizeParams
779 << ", CkCallback _ck_array_creation_cb" << eo(0) << ")\n"
780 << head << " CkArrayOptions opts(" << sizeArgs << ");\n"
786 /******************************** Group Entry Points *********************************/
788 void Entry::genGroupDecl(XStr& str) {
789 if (isConstructor()) {
790 str << " " << generateTemplateSpec(tspec) << "\n";
791 genGroupStaticConstructorDecl(str);
793 if ((isSync() || isLocal()) && !container->isForElement())
794 return; // No sync broadcast
795 str << " " << generateTemplateSpec(tspec) << "\n";
797 str << " " << retType << " " << name << "(" << paramType(1, 1, 0) << ");\n";
798 } else if (isTramTarget() && container->isForElement()) {
799 str << " " << retType << " " << name << "(" << paramType(0, 1) << ") = delete;\n";
800 str << " " << retType << " " << name << "(" << paramType(1, 0) << ");\n";
802 str << " " << retType << " " << name << "(" << paramType(1, 1) << ");\n";
804 // entry method on multiple PEs declaration
805 if (!container->isForElement() && !container->isForSection() && !isSync() &&
806 !isLocal() && !container->isNodeGroup()) {
807 str << " " << generateTemplateSpec(tspec) << "\n";
808 str << " " << retType << " " << name << "(" << paramComma(0, 0)
809 << "int npes, int *pes" << eo(1) << ");\n";
810 str << " " << generateTemplateSpec(tspec) << "\n";
811 str << " " << retType << " " << name << "(" << paramComma(0, 0)
812 << "CmiGroup &grp" << eo(1) << ");\n";
817 void Entry::genGroupDefs(XStr& str) {
818 if(isConstructor()) {
819 genGroupStaticConstructorDefs(str);
823 // Selects between NodeGroup and Group
824 char* node = (char*)(container->isNodeGroup() ? "Node" : "");
826 int forElement = container->isForElement();
828 params << epIdx() << ", impl_msg";
830 paramg << epIdx() << ", impl_msg, ckGetGroupID()";
832 parampg << epIdx() << ", impl_msg, ckGetGroupPe(), ckGetGroupID()";
833 // append options parameter
836 if (isImmediate()) opts << "+CK_MSG_IMMEDIATE";
837 if (isInline()) opts << "+CK_MSG_INLINE";
838 if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
840 if ((isSync() || isLocal()) && !container->isForElement())
841 return; // No sync broadcast
847 msgTypeStr << paramType(0, 1, 0);
849 msgTypeStr << paramType(0, 1);
850 str << makeDecl(retStr, 1) << "::" << name << "(" << msgTypeStr << ")\n";
852 // regular broadcast and section broadcast for an entry method with rdma
853 if (param->hasRdma() && !container->isForElement()) {
854 str << " CkAbort(\"Broadcast not supported for entry methods with nocopy "
857 str << " ckCheck();\n";
858 if (!isLocal()) str << marshallMsg();
862 param->unmarshall(unmarshallStr, true);
863 str << " " << container->baseName() << " *obj = ckLocalBranch();\n";
864 str << " CkAssert(obj);\n";
866 // Create a dummy envelope to represent the "message send" to the local/inline method
867 // so that Projections can trace the method back to its caller
868 str << " envelope env;\n"
869 << " env.setMsgtype(ForBocMsg);\n"
870 << " env.setTotalsize(0);\n"
871 << " _TRACE_CREATION_DETAILED(&env, " << epIdx() << ");\n"
872 << " _TRACE_CREATION_DONE(1);\n"
873 << " _TRACE_BEGIN_EXECUTE_DETAILED(CpvAccess(curPeEvent),ForBocMsg,(" << epIdx()
874 << "),CkMyPe(),0,NULL, NULL);\n";
875 if (isAppWork()) str << " _TRACE_BEGIN_APPWORK();\n";
876 str << "#if CMK_LBDB_ON\n"
877 " // if there is a running obj being measured, stop it temporarily\n"
878 " LDObjHandle objHandle;\n"
879 " int objstopped = 0;\n"
880 " LBDatabase *the_lbdb = (LBDatabase *)CkLocalBranch(_lbdb);\n"
881 " if (the_lbdb->RunningObject(&objHandle)) {\n"
883 " the_lbdb->ObjectStop(objHandle);\n"
886 str << "#if CMK_CHARMDEBUG\n"
891 if (!retType->isVoid()) str << retType << " retValue = ";
892 str << "obj->" << name << "(" << unmarshallStr << ");\n";
893 str << "#if CMK_CHARMDEBUG\n"
898 str << "#if CMK_LBDB_ON\n"
899 " if (objstopped) the_lbdb->ObjectStart(objHandle);\n"
901 if (isAppWork()) str << " _TRACE_END_APPWORK();\n";
902 if (!isNoTrace()) str << " _TRACE_END_EXECUTE();\n";
903 if (!retType->isVoid()) str << " return retValue;\n";
904 } else if (isSync()) {
905 str << syncPreCall() << "CkRemote" << node << "BranchCall(" << paramg
906 << ", ckGetGroupPe());\n";
907 str << syncPostCall();
908 } else { // Non-sync, non-local entry method
909 if (forElement) { // Send
910 str << " if (ckIsDelegated()) {\n";
911 if (param->hasRdma()) {
912 str << " CkAbort(\"Entry methods with nocopy parameters not supported "
913 "when called with delegation managers\");\n";
915 str << " Ck" << node << "GroupMsgPrep(" << paramg << ");\n";
916 str << " ckDelegatedTo()->" << node << "GroupSend(ckDelegatedPtr(),"
917 << parampg << ");\n";
919 str << " } else {\n";
920 str << " CkSendMsg" << node << "Branch"
921 << "(" << parampg << opts << ");\n";
923 } else if (container->isForSection()) { // Multicast
924 str << " if (ckIsDelegated()) {\n";
925 str << " ckDelegatedTo()->" << node << "GroupSectionSend(ckDelegatedPtr(),"
926 << params << ", ckGetNumSections(), ckGetSectionIDs());\n";
927 str << " } else {\n";
928 str << " void *impl_msg_tmp;\n";
929 str << " for (int i=0; i<ckGetNumSections(); ++i) {\n";
930 str << " impl_msg_tmp= (i<ckGetNumSections()-1) ? CkCopyMsg((void **) "
931 "&impl_msg):impl_msg;\n";
932 str << " CkSendMsg" << node << "BranchMulti(" << epIdx()
933 << ", impl_msg_tmp, ckGetGroupIDn(i), ckGetNumElements(i), ckGetElements(i)"
937 } else { // Broadcast
938 str << " if (ckIsDelegated()) {\n";
939 str << " Ck" << node << "GroupMsgPrep(" << paramg << ");\n";
940 str << " ckDelegatedTo()->" << node << "GroupBroadcast(ckDelegatedPtr(),"
942 str << " } else CkBroadcastMsg" << node << "Branch(" << paramg << opts
949 // entry method on multiple PEs declaration
950 if (!forElement && !container->isForSection() && !isSync() && !isLocal() &&
951 !container->isNodeGroup()) {
952 str << "" << makeDecl(retStr, 1) << "::" << name << "(" << paramComma(0, 0)
953 << "int npes, int *pes" << eo(0) << ") {\n";
954 if (param->hasRdma()) {
955 str << " CkAbort(\"Broadcast not supported for entry methods with nocopy "
958 str << marshallMsg();
959 str << " CkSendMsg" << node << "BranchMulti(" << paramg << ", npes, pes" << opts
963 str << "" << makeDecl(retStr, 1) << "::" << name << "(" << paramComma(0, 0)
964 << "CmiGroup &grp" << eo(0) << ") {\n";
965 if (param->hasRdma()) {
966 str << " CkAbort(\"Broadcast not supported for entry methods with nocopy "
969 str << marshallMsg();
970 str << " CkSendMsg" << node << "BranchGroup(" << paramg << ", grp" << opts
977 XStr Entry::aggregatorIndexType() {
979 if (container->isGroup()) {
981 } else if (container->isArray()) {
982 XStr dim, arrayIndexType;
983 dim << ((Array*)container)->dim();
987 indexType << "CkArrayIndex";
993 XStr Entry::dataItemType() {
995 if (container->isGroup()) {
996 itemType << param->param->type;
997 } else if (container->isArray()) {
998 itemType << "ArrayDataItem<" << param->param->type << ", " << aggregatorIndexType()
1004 XStr Entry::aggregatorType() {
1006 if (container->isGroup()) {
1007 groupType << "GroupMeshStreamer<" << param->param->type << ", "
1008 << container->baseName() << ", SimpleMeshRouter"
1009 << ", " << container->indexName() << "::_callmarshall_" << epStr() << ">";
1010 } else if (container->isArray()) {
1011 groupType << "ArrayMeshStreamer<" << param->param->type << ", "
1012 << aggregatorIndexType() << ", " << container->baseName() << ", "
1013 << "SimpleMeshRouter, " << container->indexName() << "::_callmarshall_"
1019 XStr Entry::aggregatorGlobalType(XStr& scope) {
1021 if (container->isGroup()) {
1022 groupType << "GroupMeshStreamer<" << param->param->type << ", " << scope
1023 << container->baseName() << ", SimpleMeshRouter"
1024 << ", " << scope << container->indexName() << "::_callmarshall_" << epStr()
1026 } else if (container->isArray()) {
1027 groupType << "ArrayMeshStreamer<" << param->param->type << ", "
1028 << aggregatorIndexType() << ", " << scope << container->baseName() << ", "
1029 << "SimpleMeshRouter, " << scope << container->indexName()
1030 << "::_callmarshall_" << epStr() << ">";
1035 XStr Entry::aggregatorName() {
1036 XStr aggregatorName;
1037 aggregatorName << epStr() << "TramAggregator";
1038 return aggregatorName;
1041 void Entry::genTramTypes() {
1042 if (isTramTarget()) {
1043 XStr typeString, nameString, itemTypeString;
1044 typeString << aggregatorType();
1045 nameString << aggregatorName();
1046 itemTypeString << dataItemType();
1047 #if __cplusplus >= 201103L
1048 container->tramInstances.emplace_back(
1049 typeString.get_string(), nameString.get_string(), itemTypeString.get_string());
1051 container->tramInstances.push_back(TramInfo(
1052 typeString.get_string(), nameString.get_string(), itemTypeString.get_string()));
1054 tramInstanceIndex = container->tramInstances.size();
1058 void Entry::genTramDefs(XStr& str) {
1064 msgTypeStr << paramType(0, 0, 0);
1066 msgTypeStr << paramType(0, 0);
1067 str << makeDecl(retStr, 1) << "::" << name << "(" << msgTypeStr << ") {\n"
1068 << " if (" << aggregatorName() << " == NULL) {\n";
1070 if (container->isGroup()) {
1071 str << " CkGroupID gId = ckGetGroupID();\n";
1072 } else if (container->isArray()) {
1073 str << " CkArray *aMgr = ckLocalBranch();\n"
1074 << " CkGroupID gId = aMgr->getGroupID();\n";
1077 str << " CkGroupID tramGid;\n"
1078 << " tramGid.idx = gId.idx + " << tramInstanceIndex << ";\n"
1079 << " " << aggregatorName() << " = (" << aggregatorType() << "*)"
1080 << " CkLocalBranch(tramGid);\n }\n";
1082 if (container->isGroup()) {
1083 str << " " << aggregatorName() << "->insertData(" << param->param->name << ", "
1084 << "ckGetGroupPe());\n}\n";
1085 } else if (container->isArray()) {
1087 dim << ((Array*)container)->dim();
1088 str << " const CkArrayIndex &myIndex = ckGetIndex();\n"
1089 << " " << aggregatorName() << "->insertData<" << (isInline() ? "true" : "false")
1090 << ">(" << param->param->name;
1091 if (dim == (const char*)"1D") {
1093 << "myIndex.data()[0]);\n}\n";
1096 << "myIndex);\n}\n";
1101 // size of TRAM buffers in bytes
1102 const static int tramBufferSize = 16384;
1104 void Entry::genTramInstantiation(XStr& str) {
1105 if (!container->tramInstances.empty()) {
1106 str << " int pesPerNode = CkMyNodeSize();\n"
1107 << " if (pesPerNode == 1) {\n"
1108 << " pesPerNode = CmiNumCores();\n"
1110 << " const int nDims = 2;\n"
1111 << " int dims[nDims];\n"
1112 << " dims[0] = CkNumPes() / pesPerNode;\n"
1113 << " dims[1] = pesPerNode;\n"
1114 << " if (dims[0] * dims[1] != CkNumPes()) {\n"
1115 << " dims[0] = CkNumPes();\n"
1116 << " dims[1] = 1;\n"
1118 << " int tramBufferSize = " << tramBufferSize << ";\n";
1119 for (int i = 0; i < container->tramInstances.size(); i++) {
1121 << " int itemsPerBuffer = tramBufferSize / sizeof("
1122 << container->tramInstances[i].itemType.c_str() << ");\n"
1123 << " if (itemsPerBuffer == 0) {\n"
1124 << " itemsPerBuffer = 1;\n"
1126 << " CProxy_" << container->tramInstances[i].type.c_str() << " tramProxy =\n"
1127 << " CProxy_" << container->tramInstances[i].type.c_str()
1128 << "::ckNew(2, dims, gId, itemsPerBuffer, false, 10.0);\n"
1129 << " tramProxy.enablePeriodicFlushing();\n"
1135 XStr Entry::tramBaseType() {
1136 XStr baseTypeString;
1137 baseTypeString << "MeshStreamer<" << dataItemType() << ", SimpleMeshRouter>";
1139 return baseTypeString;
1142 void Entry::genTramRegs(XStr& str) {
1143 if (isTramTarget()) {
1144 XStr messageTypeString;
1145 messageTypeString << "MeshStreamerMessage<" << dataItemType() << ">";
1147 XStr baseTypeString = tramBaseType();
1149 NamedType messageType(messageTypeString.get_string());
1150 Message helper(-1, &messageType);
1153 str << "\n /* REG: group " << aggregatorType() << ": IrrGroup;\n */\n"
1154 << " CkIndex_" << aggregatorType() << "::__register(\"" << aggregatorType()
1155 << "\", sizeof(" << aggregatorType() << "));\n"
1156 << " /* REG: group " << baseTypeString << ": IrrGroup;\n */\n"
1157 << " CkIndex_" << baseTypeString << "::__register(\"" << baseTypeString
1158 << "\", sizeof(" << baseTypeString << "));\n";
1162 void Entry::genTramPups(XStr& scope, XStr& decls, XStr& defs) {
1163 if (isTramTarget()) {
1164 XStr aggregatorTypeString = aggregatorGlobalType(scope);
1165 container->genRecursivePup(aggregatorTypeString, "template <>\n", decls, defs);
1169 void Entry::genGroupStaticConstructorDecl(XStr& str) {
1170 if (container->isForElement()) return;
1171 if (container->isForSection()) return;
1173 str << " static CkGroupID ckNew(" << paramType(1, 1) << ");\n";
1174 if (!param->isVoid()) {
1175 str << " " << container->proxyName(0) << "(" << paramType(1, 1) << ");\n";
1179 void Entry::genGroupStaticConstructorDefs(XStr& str) {
1180 if (container->isForElement()) return;
1181 if (container->isForSection()) return;
1183 // Selects between NodeGroup and Group
1184 char* node = (char*)(container->isNodeGroup() ? "Node" : "");
1185 str << makeDecl("CkGroupID", 1) << "::ckNew(" << paramType(0, 1) << ")\n";
1187 str << marshallMsg();
1188 str << " UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
1189 str << " CkGroupID gId = CkCreate" << node << "Group(" << chareIdx() << ", " << epIdx()
1190 << ", impl_msg);\n";
1192 genTramInstantiation(str);
1194 str << " return gId;\n";
1197 if (!param->isVoid()) {
1198 str << makeDecl(" ", 1) << "::" << container->proxyName(0) << "(" << paramType(0, 1)
1201 str << marshallMsg();
1202 str << " UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
1203 str << " ckSetGroupID(CkCreate" << node << "Group(" << chareIdx() << ", " << epIdx()
1204 << ", impl_msg));\n";
1209 /******************* Python Entry Point Code **************************/
1210 void Entry::genPythonDecls(XStr& str) {
1211 str << "/* STATIC DECLS: ";
1215 str << "PyObject *_Python_" << container->baseName() << "_" << name
1216 << "(PyObject *self, PyObject *arg);\n";
1220 void Entry::genPythonDefs(XStr& str) {
1225 str << "PyObject *_Python_" << container->baseName() << "_" << name
1226 << "(PyObject *self, PyObject *arg) {\n";
1227 str << " PyObject *dict = PyModule_GetDict(PyImport_AddModule(\"__main__\"));\n";
1228 str << " int pyNumber = "
1229 "PyInt_AsLong(PyDict_GetItemString(dict,\"__charmNumber__\"));\n";
1230 str << " PythonObject *pythonObj = (PythonObject "
1231 "*)PyLong_AsVoidPtr(PyDict_GetItemString(dict,\"__charmObject__\"));\n";
1232 str << " " << container->baseName() << " *object = static_cast<"
1233 << container->baseName() << "*>(pythonObj);\n";
1234 str << " object->pyWorkers[pyNumber].arg=arg;\n";
1235 str << " object->pyWorkers[pyNumber].result=&CtvAccess(pythonReturnValue);\n";
1236 str << " object->pyWorkers[pyNumber].pythread=PyThreadState_Get();\n";
1237 str << " CtvAccess(pythonReturnValue) = 0;\n";
1239 str << " //pyWorker->thisProxy." << name << "(pyNumber);\n";
1240 str << " object->" << name << "(pyNumber);\n";
1242 str << " //CthSuspend();\n";
1244 str << " if (CtvAccess(pythonReturnValue)) {\n";
1245 str << " return CtvAccess(pythonReturnValue);\n";
1246 str << " } else {\n";
1247 str << " Py_INCREF(Py_None); return Py_None;\n";
1253 void Entry::genPythonStaticDefs(XStr& str) {
1255 str << " {\"" << name << "\",_Python_" << container->baseName() << "_" << name
1256 << ",METH_VARARGS},\n";
1260 void Entry::genPythonStaticDocs(XStr& str) {
1262 str << "\n \"" << name << " -- \"";
1263 if (pythonDoc) str << (char*)pythonDoc;
1268 /******************* Accelerator (Accel) Entry Point Code ********************/
1270 void Entry::genAccelFullParamList(XStr& str, int makeRefs) {
1271 if (!isAccel()) return;
1273 ParamList* curParam = NULL;
1276 // Parameters (which are read only by default)
1278 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1279 curParam = curParam->next;
1281 while (curParam != NULL) {
1286 Parameter* param = curParam->param;
1288 if (param->isArray()) {
1289 str << param->getType()->getBaseName() << "* " << param->getName();
1291 str << param->getType()->getBaseName() << " " << param->getName();
1295 curParam = curParam->next;
1299 curParam = accelParam;
1300 while (curParam != NULL) {
1305 Parameter* param = curParam->param;
1306 int bufType = param->getAccelBufferType();
1307 int needWrite = makeRefs && ((bufType == Parameter::ACCEL_BUFFER_TYPE_READWRITE) ||
1308 (bufType == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY));
1309 if (param->isArray()) {
1310 str << param->getType()->getBaseName() << "* " << param->getName();
1312 str << param->getType()->getBaseName() << ((needWrite) ? (" &") : (" "))
1313 << param->getName();
1317 curParam = curParam->next;
1320 // Implied object pointer
1324 str << container->baseName() << "* impl_obj";
1327 void Entry::genAccelFullCallList(XStr& str) {
1328 if (!isAccel()) return;
1330 int isFirstFlag = 1;
1332 // Marshalled parameters to entry method
1333 ParamList* curParam = param;
1334 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1335 curParam = curParam->next;
1337 while (curParam != NULL) {
1338 if (!isFirstFlag) str << ", ";
1340 str << curParam->param->getName();
1341 curParam = curParam->next;
1344 // General variables (prefix with "impl_obj->" for member variables of the current
1346 curParam = accelParam;
1347 while (curParam != NULL) {
1348 if (!isFirstFlag) str << ", ";
1350 str << (*(curParam->param->getAccelInstName()));
1351 curParam = curParam->next;
1355 if (!isFirstFlag) str << ", ";
1360 void Entry::genAccelIndexWrapperDecl_general(XStr& str) {
1361 str << " static void _accelCall_general_" << epStr() << "(";
1362 genAccelFullParamList(str, 1);
1366 void Entry::genAccelIndexWrapperDef_general(XStr& str) {
1367 str << makeDecl("void") << "::_accelCall_general_" << epStr() << "(";
1368 genAccelFullParamList(str, 1);
1372 // str << " // DMK - DEBUG\n";
1373 // str << " CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
1374 // << makeDecl("void") << "::_accelCall_general_" << epStr()
1375 // << "(...) - Called...\\n\");\n\n";
1377 str << (*accelCodeBody);
1380 str << " impl_obj->" << (*accelCallbackName) << "();\n";
1384 void Entry::genAccelIndexWrapperDecl_spe(XStr& str) {
1385 // Function to issue work request
1386 str << " static void _accelCall_spe_" << epStr() << "(";
1387 genAccelFullParamList(str, 0);
1390 // Callback function that is a member of CkIndex_xxx
1391 str << " static void _accelCall_spe_callback_" << epStr() << "(void* userPtr);\n";
1394 // DMK - Accel Support
1399 void Entry::genAccelIndexWrapperDef_spe(XStr& str) {
1400 XStr containerType = container->baseName();
1402 // Some blank space for readability
1405 ///// Generate struct that will be passed to callback function /////
1407 str << "typedef struct __spe_callback_struct_" << epStr() << " {\n"
1408 << " " << containerType << "* impl_obj;\n"
1409 << " WRHandle wrHandle;\n"
1410 << " void* scalar_buf_ptr;\n";
1412 // Pointers for marshalled parameter buffers
1413 ParamList* curParam = param;
1414 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1415 curParam = curParam->next;
1417 while (curParam != NULL) {
1418 if (curParam->param->isArray()) {
1419 str << " void* param_buf_ptr_" << curParam->param->getName() << ";\n";
1421 curParam = curParam->next;
1423 curParam = accelParam;
1424 while (curParam != NULL) {
1425 if (curParam->param->isArray()) {
1426 str << " void* accelParam_buf_ptr_" << curParam->param->getName() << ";\n";
1428 curParam = curParam->next;
1431 str << "} SpeCallbackStruct_" << epStr() << ";\n\n";
1433 ///// Generate callback function /////
1435 str << "void _accelCall_spe_callback_" << container->baseName() << "_" << epStr()
1436 << "(void* userPtr) {\n"
1437 << " " << container->indexName() << "::_accelCall_spe_callback_" << epStr()
1441 str << makeDecl("void") << "::_accelCall_spe_callback_" << epStr()
1442 << "(void* userPtr) {\n";
1443 str << " SpeCallbackStruct_" << epStr() << "* cbStruct = (SpeCallbackStruct_"
1444 << epStr() << "*)userPtr;\n";
1445 str << " " << containerType << "* impl_obj = cbStruct->impl_obj;\n";
1447 // Write scalars that are 'out' or 'inout' from the scalar buffer back into memory
1449 if (accel_numScalars > 0) {
1450 // Get the pointer to the scalar buffer
1451 int dmaList_scalarBufIndex = 0;
1452 if (accel_dmaList_scalarNeedsWrite) {
1453 dmaList_scalarBufIndex += accel_dmaList_numReadOnly;
1455 str << " char* __scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n";
1459 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1460 curParam = curParam->next;
1462 while (curParam != NULL) {
1463 if (!(curParam->param->isArray())) {
1464 str << " __scalar_buf_offset += sizeof("
1465 << curParam->param->getType()->getBaseName() << ");\n";
1467 curParam = curParam->next;
1470 // Read only accel parameters
1471 curParam = accelParam;
1472 while (curParam != NULL) {
1473 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1474 Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1475 str << " __scalar_buf_offset += sizeof("
1476 << curParam->param->getType()->getBaseName() << ");\n";
1478 curParam = curParam->next;
1481 // Read write accel parameters
1482 curParam = accelParam;
1483 while (curParam != NULL) {
1484 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1485 Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1486 str << " " << (*(curParam->param->getAccelInstName())) << " = *(("
1487 << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1488 str << " __scalar_buf_offset += sizeof("
1489 << curParam->param->getType()->getBaseName() << ");\n";
1491 curParam = curParam->next;
1494 // Write only accel parameters
1495 curParam = accelParam;
1496 while (curParam != NULL) {
1497 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1498 Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1499 str << " " << (*(curParam->param->getAccelInstName())) << " = *(("
1500 << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1501 str << " __scalar_buf_offset += sizeof("
1502 << curParam->param->getType()->getBaseName() << ");\n";
1504 curParam = curParam->next;
1508 // Call the callback function
1509 str << " (cbStruct->impl_obj)->" << (*accelCallbackName) << "();\n";
1512 str << " if (cbStruct->scalar_buf_ptr != NULL) { "
1513 "free_aligned(cbStruct->scalar_buf_ptr); }\n";
1515 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1516 curParam = curParam->next;
1518 while (curParam != NULL) {
1519 if (curParam->param->isArray()) {
1520 str << " if (cbStruct->param_buf_ptr_" << curParam->param->getName()
1522 << "free_aligned(cbStruct->param_buf_ptr_" << curParam->param->getName()
1526 curParam = curParam->next;
1528 str << " delete cbStruct;\n";
1532 ///// Generate function to issue work request /////
1534 str << makeDecl("void") << "::_accelCall_spe_" << epStr() << "(";
1535 genAccelFullParamList(str, 0);
1539 // str << " // DMK - DEBUG\n"
1540 // << " CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
1541 // << makeDecl("void") << "::_accelCall_spe_" << epStr()
1542 // << "(...) - Called... (funcIndex:%d)\\n\", accel_spe_func_index__" << epStr() <<
1545 str << " // Allocate a user structure to be passed to the callback function\n"
1546 << " SpeCallbackStruct_" << epStr() << "* cbStruct = new SpeCallbackStruct_"
1548 << " cbStruct->impl_obj = impl_obj;\n"
1549 << " cbStruct->wrHandle = INVALID_WRHandle; // NOTE: Set actual value later...\n"
1550 << " cbStruct->scalar_buf_ptr = NULL;\n";
1551 // Set all parameter buffer pointers in the callback structure to NULL
1553 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1554 curParam = curParam->next;
1556 while (curParam != NULL) {
1557 if (curParam->param->isArray()) {
1558 str << " cbStruct->param_buf_ptr_" << curParam->param->getName() << " = NULL;\n";
1560 curParam = curParam->next;
1562 curParam = accelParam;
1563 while (curParam != NULL) {
1564 if (curParam->param->isArray()) {
1565 str << " cbStruct->accelParam_buf_ptr_" << curParam->param->getName()
1568 curParam = curParam->next;
1572 // Create the DMA list
1573 int dmaList_curIndex = 0;
1574 int numDMAListEntries = accel_numArrays;
1575 if (accel_numScalars > 0) {
1576 numDMAListEntries++;
1578 if (numDMAListEntries <= 0) {
1579 XLAT_ERROR_NOCOL("accel entry with no parameters", first_line_);
1582 // DMK - NOTE : TODO : FIXME - For now, force DMA lists to only be the static length or
1584 // Fix this in the future to handle any length supported by hardware. Also, for now,
1585 // #if this check since non-Cell architectures do not have SPE_DMA_LIST_LENGTH defined
1586 // and this code should not be called unless this is a Cell architecture.
1588 if (numDMAListEntries > SPE_DMA_LIST_LENGTH) {
1589 die("Accel entries do not support parameter lists of length > SPE_DMA_LIST_LENGTH "
1590 "yet... fix me...");
1594 // Do a pass of all the parameters, determine the size of all scalars (to pack them)
1595 if (accel_numScalars > 0) {
1596 str << " // Create a single buffer to hold all the scalar values\n";
1597 str << " int scalar_buf_len = 0;\n";
1599 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1600 curParam = curParam->next;
1602 while (curParam != NULL) {
1603 if (!(curParam->param->isArray())) {
1604 str << " scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName()
1607 curParam = curParam->next;
1609 curParam = accelParam;
1610 while (curParam != NULL) {
1611 if (!(curParam->param->isArray())) {
1612 str << " scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName()
1615 curParam = curParam->next;
1617 str << " scalar_buf_len = ROUNDUP_128(scalar_buf_len);\n"
1618 << " cbStruct->scalar_buf_ptr = malloc_aligned(scalar_buf_len, 128);\n"
1619 << " char* scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n\n";
1622 // Declare the DMA list
1623 str << " // Declare and populate the DMA list for the work request\n";
1624 str << " DMAListEntry dmaList[" << numDMAListEntries << "];\n\n";
1626 // Parameters: read only by default & arrays need to be copied since message will be
1629 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1630 curParam = curParam->next;
1632 while (curParam != NULL) {
1633 // Check to see if the scalar buffer needs slipped into the dma list here
1634 if (accel_numScalars > 0) {
1635 if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1636 ((dmaList_curIndex == accel_dmaList_numReadOnly) &&
1637 (accel_dmaList_scalarNeedsWrite))) {
1638 str << " /*** Scalar Buffer ***/\n"
1639 << " dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1640 << " dmaList[" << dmaList_curIndex
1641 << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1646 // Add this parameter to the dma list (somehow)
1647 str << " /*** Param: '" << curParam->param->getName() << "' ***/\n";
1648 if (curParam->param->isArray()) {
1650 << " int bufSize = sizeof(" << curParam->param->getType()->getBaseName()
1651 << ") * (" << curParam->param->getArrayLen() << ");\n"
1652 << " bufSize = ROUNDUP_128(bufSize);\n"
1653 << " cbStruct->param_buf_ptr_" << curParam->param->getName()
1654 << " = malloc_aligned(bufSize, 128);\n"
1655 << " memcpy(cbStruct->param_buf_ptr_" << curParam->param->getName() << ", "
1656 << curParam->param->getName() << ", bufSize);\n"
1657 << " dmaList[" << dmaList_curIndex << "].size = bufSize;\n"
1658 << " dmaList[" << dmaList_curIndex
1659 << "].ea = (unsigned int)(cbStruct->param_buf_ptr_"
1660 << curParam->param->getName() << ");\n"
1664 str << " *((" << curParam->param->getType()->getBaseName()
1665 << "*)scalar_buf_offset) = " << curParam->param->getName() << ";\n"
1666 << " scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName()
1669 curParam = curParam->next;
1673 // Read only accel params
1674 curParam = accelParam;
1675 while (curParam != NULL) {
1676 // Check to see if the scalar buffer needs slipped into the dma list here
1677 if (accel_numScalars > 0) {
1678 if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1679 ((dmaList_curIndex == accel_dmaList_numReadOnly) &&
1680 (accel_dmaList_scalarNeedsWrite))) {
1681 str << " /*** Scalar Buffer ***/\n"
1682 << " dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1683 << " dmaList[" << dmaList_curIndex
1684 << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1689 // Add this parameter
1690 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1691 str << " /*** Accel Param: '" << curParam->param->getName() << " ("
1692 << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1693 if (curParam->param->isArray()) {
1694 str << " dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1695 << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1696 << "(" << curParam->param->getArrayLen() << "));\n"
1697 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)("
1698 << (*(curParam->param->getAccelInstName())) << ");\n";
1701 str << " *((" << curParam->param->getType()->getBaseName()
1702 << "*)scalar_buf_offset) = " << (*(curParam->param->getAccelInstName()))
1704 << " scalar_buf_offset += sizeof("
1705 << curParam->param->getType()->getBaseName() << ");\n";
1710 curParam = curParam->next;
1713 // Read/write accel params
1714 curParam = accelParam;
1715 while (curParam != NULL) {
1716 // Check to see if the scalar buffer needs slipped into the dma list here
1717 if (accel_numScalars > 0) {
1718 if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1719 ((dmaList_curIndex == accel_dmaList_numReadOnly) &&
1720 (accel_dmaList_scalarNeedsWrite))) {
1721 str << " /*** Scalar Buffer ***/\n"
1722 << " dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1723 << " dmaList[" << dmaList_curIndex
1724 << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1729 // Add this parameter
1730 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1731 str << " /*** Accel Param: '" << curParam->param->getName() << " ("
1732 << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1733 if (curParam->param->isArray()) {
1734 str << " dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1735 << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1736 << "(" << curParam->param->getArrayLen() << "));\n"
1737 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)("
1738 << (*(curParam->param->getAccelInstName())) << ");\n";
1741 str << " *((" << curParam->param->getType()->getBaseName()
1742 << "*)scalar_buf_offset) = " << (*(curParam->param->getAccelInstName()))
1744 << " scalar_buf_offset += sizeof("
1745 << curParam->param->getType()->getBaseName() << ");\n";
1750 curParam = curParam->next;
1753 // Write only accel params
1754 curParam = accelParam;
1755 while (curParam != NULL) {
1756 // Add this parameter
1757 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1758 str << " /*** Accel Param: '" << curParam->param->getName() << " ("
1759 << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1760 if (curParam->param->isArray()) {
1761 str << " dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1762 << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1763 << "(" << curParam->param->getArrayLen() << "));\n"
1764 << " dmaList[" << dmaList_curIndex << "].ea = (unsigned int)("
1765 << (*(curParam->param->getAccelInstName())) << ");\n";
1768 str << " *((" << curParam->param->getType()->getBaseName()
1769 << "*)scalar_buf_offset) = " << (*(curParam->param->getAccelInstName()))
1771 << " scalar_buf_offset += sizeof("
1772 << curParam->param->getType()->getBaseName() << ");\n";
1777 curParam = curParam->next;
1780 str << " // Issue the work request\n";
1781 str << " cbStruct->wrHandle = sendWorkRequest_list(accel_spe_func_index__" << epStr()
1785 << " " << accel_dmaList_numReadOnly
1787 << " " << accel_dmaList_numReadWrite
1789 << " " << accel_dmaList_numWriteOnly
1792 << " WORK_REQUEST_FLAGS_NONE,\n"
1793 << " _accelCall_spe_callback_"
1794 << container->baseName() << "_" << epStr() << "\n"
1799 // Some blank space for readability
1803 int Entry::genAccels_spe_c_funcBodies(XStr& str) {
1804 // Make sure this is an accelerated entry method (just return if not)
1809 // Declare the spe function
1810 str << "void __speFunc__" << indexName() << "__" << epStr()
1811 << "(DMAListEntry* dmaList) {\n";
1813 ParamList* curParam = NULL;
1814 int dmaList_curIndex = 0;
1816 // Identify the scalar buffer if there is one
1817 if (accel_numScalars > 0) {
1818 if (accel_dmaList_scalarNeedsWrite) {
1819 str << " void* __scalar_buf_ptr = (void*)(dmaList[" << accel_dmaList_numReadOnly
1822 str << " void* __scalar_buf_ptr = (void*)(dmaList[0].ea);\n";
1825 str << " char* __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1828 // Pull out all the parameters
1830 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1831 curParam = curParam->next;
1833 while (curParam != NULL) {
1834 if (curParam->param->isArray()) {
1835 str << " " << curParam->param->getType()->getBaseName() << "* "
1836 << curParam->param->getName() << " = ("
1837 << curParam->param->getType()->getBaseName() << "*)(dmaList["
1838 << dmaList_curIndex << "].ea);\n";
1841 str << " " << curParam->param->getType()->getBaseName() << " "
1842 << curParam->param->getName() << " = *(("
1843 << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1844 str << " __scalar_buf_offset += sizeof("
1845 << curParam->param->getType()->getBaseName() << ");\n";
1847 curParam = curParam->next;
1850 // Read only accel params
1851 curParam = accelParam;
1852 while (curParam != NULL) {
1853 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1854 if (curParam->param->isArray()) {
1855 str << " " << curParam->param->getType()->getBaseName() << "* "
1856 << curParam->param->getName() << " = ("
1857 << curParam->param->getType()->getBaseName() << "*)(dmaList["
1858 << dmaList_curIndex << "].ea);\n";
1861 str << " " << curParam->param->getType()->getBaseName() << " "
1862 << curParam->param->getName() << " = *(("
1863 << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1864 str << " __scalar_buf_offset += sizeof("
1865 << curParam->param->getType()->getBaseName() << ");\n";
1868 curParam = curParam->next;
1871 // Reset the dmaList_curIndex to the read-write portion of the dmaList
1872 dmaList_curIndex = accel_dmaList_numReadOnly;
1873 if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1877 // Read-write accel params
1878 curParam = accelParam;
1879 while (curParam != NULL) {
1880 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1881 if (curParam->param->isArray()) {
1882 str << " " << curParam->param->getType()->getBaseName() << "* "
1883 << curParam->param->getName() << " = ("
1884 << curParam->param->getType()->getBaseName() << "*)(dmaList["
1885 << dmaList_curIndex << "].ea);\n";
1888 str << " " << curParam->param->getType()->getBaseName() << " "
1889 << curParam->param->getName() << " = *(("
1890 << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1891 str << " __scalar_buf_offset += sizeof("
1892 << curParam->param->getType()->getBaseName() << ");\n";
1895 curParam = curParam->next;
1898 // Write only accel params
1899 curParam = accelParam;
1900 while (curParam != NULL) {
1901 if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1902 if (curParam->param->isArray()) {
1903 str << " " << curParam->param->getType()->getBaseName() << "* "
1904 << curParam->param->getName() << " = ("
1905 << curParam->param->getType()->getBaseName() << "*)(dmaList["
1906 << dmaList_curIndex << "].ea);\n";
1909 str << " " << curParam->param->getType()->getBaseName() << " "
1910 << curParam->param->getName() << " = *(("
1911 << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1912 str << " __scalar_buf_offset += sizeof("
1913 << curParam->param->getType()->getBaseName() << ");\n";
1916 curParam = curParam->next;
1919 // Function body from the interface file
1920 str << " {\n " << (*accelCodeBody) << "\n }\n";
1922 // Write the scalar values that are not read only back into the scalar buffer
1923 if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1924 str << " __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1928 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1929 curParam = curParam->next;
1931 while (curParam != NULL) {
1932 if (!(curParam->param->isArray())) {
1933 str << " __scalar_buf_offset += sizeof("
1934 << curParam->param->getType()->getBaseName() << ");\n";
1936 curParam = curParam->next;
1939 // Read only accel parameters
1940 curParam = accelParam;
1941 while (curParam != NULL) {
1942 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1943 Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1944 str << " __scalar_buf_offset += sizeof("
1945 << curParam->param->getType()->getBaseName() << ");\n";
1947 curParam = curParam->next;
1950 // Read only accel parameters
1951 curParam = accelParam;
1952 while (curParam != NULL) {
1953 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1954 Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1955 str << " *((" << curParam->param->getType()->getBaseName()
1956 << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1957 str << " __scalar_buf_offset += sizeof("
1958 << curParam->param->getType()->getBaseName() << ");\n";
1960 curParam = curParam->next;
1963 // Read only accel parameters
1964 curParam = accelParam;
1965 while (curParam != NULL) {
1966 if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1967 Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1968 str << " *((" << curParam->param->getType()->getBaseName()
1969 << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1970 str << " __scalar_buf_offset += sizeof("
1971 << curParam->param->getType()->getBaseName() << ");\n";
1973 curParam = curParam->next;
1982 void Entry::genAccels_spe_c_regFuncs(XStr& str) {
1984 str << " funcLookupTable[curIndex ].funcIndex = curIndex;\n"
1985 << " funcLookupTable[curIndex++].funcPtr = __speFunc__" << indexName() << "__"
1986 << epStr() << ";\n";
1990 void Entry::genAccels_ppe_c_regFuncs(XStr& str) {
1992 str << " " << indexName() << "::accel_spe_func_index__" << epStr()
1993 << " = curIndex++;\n";
1997 /******************* Shared Entry Point Code **************************/
1998 void Entry::genIndexDecls(XStr& str) {
1999 str << " /* DECLS: ";
2003 XStr templateSpecLine;
2004 templateSpecLine << "\n " << generateTemplateSpec(tspec);
2006 // Entry point index storage
2007 str << "\n // Entry point registration at startup" << templateSpecLine
2008 << "\n static int reg_" << epStr()
2009 << "();" ///< @note: Should this be generated as private?
2010 << "\n // Entry point index lookup" << templateSpecLine
2011 << "\n inline static int idx_" << epStr() << "() {"
2012 << "\n static int epidx = " << epRegFn(0) << ";"
2013 << "\n return epidx;"
2016 if (!isConstructor()) {
2017 str << templateSpecLine << "\n inline static int idx_" << name << "(" << retType
2018 << " (" << container->baseName() << "::*)(";
2019 if (param) param->print(str);
2021 << "\n return " << epIdx(0) << ";"
2025 // DMK - Accel Support - Also declare the function index for the Offload API call
2028 str << " static int accel_spe_func_index__" << epStr() << ";\n";
2032 // Index function, so user can find the entry point number
2033 str << templateSpecLine << "\n static int ";
2034 if (isConstructor())
2038 str << "(" << paramType(1, 0) << ") { return " << epIdx(0) << "; }";
2040 // DMK - Accel Support
2042 genAccelIndexWrapperDecl_general(str);
2044 genAccelIndexWrapperDecl_spe(str);
2048 if (isReductionTarget()) {
2049 str << "\n // Entry point registration at startup" << templateSpecLine
2050 << "\n static int reg_" << epStr(true)
2051 << "();" ///< @note: Should this be generated as private?
2052 << "\n // Entry point index lookup" << templateSpecLine
2053 << "\n inline static int idx_" << epStr(true) << "() {"
2054 << "\n static int epidx = " << epRegFn(0, true) << ";"
2055 << "\n return epidx;"
2056 << "\n }" << templateSpecLine << "\n static int "
2057 << "redn_wrapper_" << name << "(CkReductionMsg* impl_msg) { return "
2058 << epIdx(0, true) << "; }" << templateSpecLine << "\n static void _call_"
2059 << epStr(true) << "(void* impl_msg, void* impl_obj_void);";
2062 // call function declaration
2063 str << templateSpecLine << "\n static void _call_" << epStr()
2064 << "(void* impl_msg, void* impl_obj);";
2065 str << templateSpecLine << "\n static void _call_sdag_" << epStr()
2066 << "(void* impl_msg, void* impl_obj);";
2068 str << templateSpecLine << "\n static void _callthr_" << epStr()
2069 << "(CkThrCallArg *);";
2071 if (hasCallMarshall) {
2072 str << templateSpecLine << "\n static int _callmarshall_" << epStr()
2073 << "(char* impl_buf, void* impl_obj_void);";
2075 if (param->isMarshalled()) {
2076 str << templateSpecLine << "\n static void _marshallmessagepup_" << epStr()
2077 << "(PUP::er &p,void *msg);";
2082 void Entry::genDecls(XStr& str) {
2083 if (external) return;
2085 str << "/* DECLS: ";
2089 if (isMigrationConstructor()) {
2090 } // User cannot call the migration constructor
2091 else if (container->isGroup()) {
2093 } else if (container->isArray()) {
2096 else if (container->isForElement())
2098 } else { // chare or mainchare
2103 void Entry::genClosureEntryDecls(XStr& str) { genClosure(str, false); }
2105 void Entry::genClosureEntryDefs(XStr& str) {
2106 templateGuardBegin(tspec || container->isTemplated(), str);
2107 genClosure(str, true);
2108 templateGuardEnd(str);
2111 void Entry::genClosure(XStr& decls, bool isDef) {
2112 if (isConstructor() || (isLocal() && !sdagCon)) return;
2114 bool hasArray = false, isMessage = false, hasRdma = false;
2116 int i = 0, addNumRdmaFields = 1;
2117 XStr structure, toPup, alloc, getter, dealloc;
2118 for (ParamList *pl = param; pl != NULL; pl = pl->next, i++) {
2119 Parameter* sv = pl->param;
2121 if (XStr(sv->type->getBaseName()) == "CkArrayOptions") continue;
2126 if ((sv->isMessage() != 1) && (sv->isVoid() != 1)) {
2128 hasRdma = hasRdma || true;
2129 structure << "\n#if CMK_ONESIDED_IMPL\n";
2130 if (sv->isFirstRdma())
2132 << "int num_rdma_fields;\n";
2135 << "ncpyBuffer_" << sv->name << ";\n";
2136 structure << "#else\n";
2137 structure << " " << sv->type << " "
2138 << "*" << sv->name << ";\n";
2139 structure << "#endif\n";
2140 getter << "#if CMK_ONESIDED_IMPL\n";
2141 if (sv->isFirstRdma()) {
2145 << "getP" << i++ << "() { return "
2146 << " num_rdma_fields;}\n";
2151 << "getP" << i << "() { return "
2152 << "ncpyBuffer_" << sv->name << ";}\n";
2153 getter << "#else\n";
2154 getter << sv->type << " "
2157 << "getP" << i << "() { return " << sv->name << ";}\n";
2158 getter << "#endif\n";
2159 toPup << "#if CMK_ONESIDED_IMPL\n";
2160 if (sv->isFirstRdma()) {
2161 toPup << " char *impl_buf = _impl_marshall ? _impl_marshall->msgBuf : "
2165 << "num_rdma_fields;\n";
2167 /* The Rdmawrapper's pointer stores the offset to the actual buffer
2168 * from the beginning of the msgBuf while packing (as the pointer itself is
2169 * invalid upon migration). During unpacking (after migration), the offset is used
2170 * to adjust the pointer back to the actual buffer that exists within the message.
2172 toPup << " if (__p.isPacking()) {\n";
2173 toPup << " ncpyBuffer_" << sv->name << ".ptr = ";
2174 toPup << "(void *)((char *)(ncpyBuffer_" << sv->name << ".ptr) - impl_buf);\n";
2178 << "ncpyBuffer_" << sv->name << ";\n";
2179 toPup << "#endif\n";
2183 structure << sv->type << " ";
2184 getter << sv->type << " ";
2187 if (sv->isArray() != 0) {
2191 if (sv->isArray() != 0) {
2192 hasArray = hasArray || true;
2193 } else if (!sv->isRdma()) {
2195 << "__p | " << sv->name << ";\n";
2199 if (sv->name != 0) {
2200 if (!sv->isRdma()) {
2201 structure << sv->name << ";\n";
2203 << "getP" << i << "() { return " << sv->name << ";}\n";
2207 } else if (sv->isVoid() != 1) {
2208 if (sv->isMessage()) {
2211 structure << "CkNcpyBuffer"
2213 << "ncpyBuffer_" << sv->name << ";\n";
2215 structure << sv->type << " " << sv->name << ";\n";
2218 << "CkPupMessage(__p, (void**)&" << sv->name << ");\n";
2219 messageType << sv->type->deref();
2226 toPup << " packClosure(__p);\n";
2229 initCode << " init();\n";
2231 if (hasArray || hasRdma) {
2233 << "CkMarshallMsg* _impl_marshall;\n";
2235 << "char* _impl_buf_in;\n";
2237 << "int _impl_buf_size;\n";
2238 dealloc << " if (_impl_marshall) CmiFree(UsrToEnv(_impl_marshall));\n";
2239 initCode << " _impl_marshall = 0;\n";
2240 initCode << " _impl_buf_in = 0;\n";
2241 initCode << " _impl_buf_size = 0;\n";
2243 toPup << " __p | _impl_buf_size;\n";
2244 toPup << " bool hasMsg = (_impl_marshall != 0); __p | hasMsg;\n";
2246 << "if (hasMsg) CkPupMessage(__p, (void**)&"
2250 << "else PUParray(__p, _impl_buf_in, _impl_buf_size);\n";
2251 toPup << " if (__p.isUnpacking()) {\n";
2252 toPup << " char *impl_buf = _impl_marshall ? _impl_marshall->msgBuf : "
2254 param->beginUnmarshallSDAG(toPup);
2258 // Generate code for ensuring we don't migrate active local closures
2262 << " CkAbort(\"Can\'t migrate while a local SDAG method is active.\");\n";
2266 genClosureTypeName = new XStr();
2267 genClosureTypeNameProxy = new XStr();
2268 *genClosureTypeNameProxy << "Closure_" << container->baseName() << "::";
2269 *genClosureTypeNameProxy << name << "_" << entryCount << "_closure";
2270 *genClosureTypeName << name << "_" << entryCount << "_closure";
2272 container->sdagPUPReg << " PUPable_reg(SINGLE_ARG(" << *genClosureTypeNameProxy
2276 if (container->isTemplated()) {
2277 decls << container->tspec(false) << "\n";
2279 decls << generateTemplateSpec(tspec) << "\n";
2280 decls << " struct " << *genClosureTypeNameProxy << " : public SDAG::Closure"
2282 decls << structure << "\n";
2283 decls << " " << *genClosureTypeName << "() {\n";
2286 decls << " " << *genClosureTypeName << "(CkMigrateMessage*) {\n";
2290 decls << " void pup(PUP::er& __p) {\n";
2293 decls << " virtual ~" << *genClosureTypeName << "() {\n";
2297 << ((container->isTemplated() || tspec) ? "PUPable_decl_template"
2299 << "(SINGLE_ARG(" << *genClosureTypeName;
2302 tspec->genShort(decls);
2308 decls << generateTemplateSpec(tspec) << "\n";
2309 decls << " struct " << *genClosureTypeName << ";\n";
2312 genClosureTypeName = new XStr();
2313 genClosureTypeNameProxy = new XStr();
2314 *genClosureTypeNameProxy << messageType;
2315 *genClosureTypeName << messageType;
2318 genClosureTypeNameProxyTemp = new XStr();
2319 *genClosureTypeNameProxyTemp << (container->isTemplated() ? "typename " : "")
2320 << genClosureTypeNameProxy;
2323 // This routine is only used in Entry::genDefs.
2324 // It ends the current procedure with a call to awaken another thread,
2325 // and defines the thread function to handle that call.
2326 XStr Entry::callThread(const XStr& procName, int prependEntryName) {
2327 if (isConstructor() || isMigrationConstructor())
2328 die("Constructors may not be 'threaded'", first_line_);
2331 procFull << "_callthr_";
2332 if (prependEntryName) procFull << name << "_";
2333 procFull << procName;
2335 str << " CthThread tid = CthCreate((CthVoidFn)" << procFull
2336 << ", new CkThrCallArg(impl_msg,impl_obj), " << getStackSize() << ");\n";
2337 str << " ((Chare *)impl_obj)->CkAddThreadListeners(tid,impl_msg);\n";
2338 // str << " CkpvAccess(_traces)->CkAddThreadListeners(tid);\n";
2339 #if CMK_BIGSIM_CHARM
2340 str << " BgAttach(tid);\n";
2342 str << " CthResume(tid);\n";
2345 str << makeDecl("void") << "::" << procFull << "(CkThrCallArg *impl_arg)\n";
2347 str << " void *impl_msg = impl_arg->msg;\n";
2348 str << " void *impl_obj_void = impl_arg->obj;\n";
2349 str << " " << container->baseName() << " *impl_obj = static_cast<"
2350 << container->baseName() << " *>(impl_obj_void);\n";
2351 str << " delete impl_arg;\n";
2356 Generate the code to actually unmarshall the parameters and call
2359 void Entry::genCall(XStr& str, const XStr& preCall, bool redn_wrapper, bool usesImplBuf) {
2360 bool isArgcArgv = false;
2361 bool isMigMain = false;
2362 bool isSDAGGen = sdagCon || isWhenEntry;
2363 bool needsClosure = isSDAGGen && (param->isMarshalled() ||
2364 (param->isVoid() && isWhenEntry && redn_wrapper));
2366 if (isConstructor() && container->isMainChare() && (!param->isVoid()) &&
2367 (!param->isCkArgMsgPtr())) {
2368 if (param->isCkMigMsgPtr())
2373 // Normal case: Unmarshall variables
2375 param->beginRednWrapperUnmarshall(str, needsClosure);
2378 param->beginUnmarshallSDAGCall(str, usesImplBuf);
2380 param->beginUnmarshall(str);
2385 if (!isConstructor() && fortranMode && !isWhenEntry && !sdagCon) {
2386 if (!container->isArray()) { // Currently, only arrays are supported
2387 cerr << (char*)container->baseName()
2388 << ": only chare arrays are currently supported\n";
2391 str << "/* FORTRAN */\n";
2393 dim << ((Array*)container)->dim();
2394 if (dim == (const char*)"1D")
2395 str << " int index1 = impl_obj->thisIndex;\n";
2396 else if (dim == (const char*)"2D") {
2397 str << " int index1 = impl_obj->thisIndex.x;\n";
2398 str << " int index2 = impl_obj->thisIndex.y;\n";
2399 } else if (dim == (const char*)"3D") {
2400 str << " int index1 = impl_obj->thisIndex.x;\n";
2401 str << " int index2 = impl_obj->thisIndex.y;\n";
2402 str << " int index3 = impl_obj->thisIndex.z;\n";
2405 str << fortranify(container->baseName(), "_Entry_", name);
2406 str << "((char **)(impl_obj->user_data)";
2408 if (dim == (const char*)"2D" || dim == (const char*)"3D") str << ", &index2";
2409 if (dim == (const char*)"3D") str << ", &index3";
2410 if (!param->isVoid()) {
2412 param->unmarshallAddress(str);
2415 str << "/* FORTRAN END */\n";
2418 // DMK : Accel Support
2419 else if (isAccel()) {
2421 str << " if (1) { // DMK : TODO : For now, hardcode the condition (i.e. for now, "
2422 "do not dynamically load-balance between host and accelerator)\n";
2423 str << " _accelCall_spe_" << epStr() << "(";
2424 genAccelFullCallList(str);
2426 str << " } else {\n ";
2429 str << " _accelCall_general_" << epStr() << "(";
2430 genAccelFullCallList(str);
2439 else { // Normal case: call regular method
2440 if (isArgcArgv) str << " CkArgMsg *m=(CkArgMsg *)impl_msg;\n"; // Hack!
2442 if (isMigrationConstructor() && container->isArray()) {
2443 // Make definition of CkMigrateMessage constructor optional for chare
2444 // array elements, but not for chare/group/nodegroup types that are
2445 // explicitly marked [migratable]
2446 str << " call_migration_constructor<" << container->baseName()
2447 << "> c = impl_obj_void;\n"
2449 } else if (isConstructor()) { // Constructor: call "new (obj) foo(parameters)"
2450 str << " new (impl_obj_void) " << container->baseName();
2451 } else { // Regular entry method: call "obj->bar(parameters)"
2452 str << " impl_obj->" << (tspec ? "template " : "") << (containsWhenConstruct ? "_sdag_fnc_" : "" ) << name;
2455 tspec->genShort(str);
2460 if (isArgcArgv) { // Extract parameters from CkArgMsg (should be parameter
2462 str << "(m->argc,m->argv);\n";
2463 str << " delete m;\n";
2464 } else if (isMigMain) {
2465 str << "((CkMigrateMessage*)impl_msg);\n";
2466 } else { // Normal case: unmarshall parameters (or just pass message)
2469 if (param->isMessage()) {
2470 param->unmarshall(str);
2471 } else if (needsClosure) {
2472 str << "genClosure";
2476 str << " genClosure->deref();\n";
2480 param->unmarshall(str);
2487 void Entry::genDefs(XStr& str) {
2488 if (external) return;
2489 XStr containerType = container->baseName();
2490 XStr preMarshall, preCall, postCall;
2492 templateGuardBegin(tspec || container->isTemplated(), str);
2497 if (isMigrationConstructor()) {
2498 } // User cannot call the migration constructor
2499 else if (isTramTarget() && container->isForElement()) {
2501 } else if (container->isGroup()) {
2503 } else if (container->isArray()) {
2508 if (!isConstructor() && fortranMode) {
2509 str << "/* FORTRAN SECTION */\n";
2511 // Declare the Fortran Entry Function
2512 // This is called from C++
2513 str << "extern \"C\" ";
2515 str << fortranify(container->baseName(), "_Entry_", name);
2517 str << ", " << container->indexList();
2518 if (!param->isVoid()) {
2520 param->printAddress(str);
2524 str << "/* FORTRAN SECTION END */\n";
2527 if (container->isMainChare() || container->isChare() || container->isForElement()) {
2528 if (isReductionTarget()) {
2531 str << makeDecl(retStr);
2532 // str << retType << " " << indexName(); //makeDecl(retStr, 1)
2533 str << "::_call_" << epStr(true) << "(void* impl_msg, void* impl_obj_void)"
2535 << "\n " << container->baseName() << "* impl_obj = static_cast<"
2536 << container->baseName() << "*> (impl_obj_void);\n"
2537 << " char* impl_buf = (char*)((CkReductionMsg*)impl_msg)->getData();\n";
2539 genCall(str, precall, true, false);
2540 if (!(sdagCon || isWhenEntry))
2541 str << " delete (CkReductionMsg*)impl_msg;\n}\n\n";
2547 // Prevents repeated call and __idx definitions:
2548 if (container->getForWhom() != forAll) {
2549 templateGuardEnd(str);
2553 // Define the entry point registration functions
2554 str << "\n// Entry point registration function"
2556 << makeDecl("int") << "::reg_" << epStr() << "() {"
2557 << "\n int epidx = " << genRegEp() << ";";
2558 if (hasCallMarshall)
2559 str << "\n CkRegisterMarshallUnpackFn(epidx, "
2560 << "_callmarshall_" << epStr(false, true) << ");";
2561 if (param->isMarshalled()) {
2562 str << "\n CkRegisterMessagePupFn(epidx, "
2563 << "_marshallmessagepup_" << epStr(false, true) << ");\n";
2564 } else if (param->isMessage() && !isMigrationConstructor()) {
2565 str << "\n CkRegisterMessagePupFn(epidx, (CkMessagePupFn)";
2566 param->param->getType()->deref()->print(str);
2567 str << "::ckDebugPup);";
2569 str << "\n return epidx;"
2572 if (isReductionTarget()) {
2573 str << "\n// Redn wrapper registration function"
2575 << makeDecl("int") << "::reg_" << epStr(true) << "() {"
2576 << "\n return " << genRegEp(true) << ";"
2580 // DMK - Accel Support
2583 str << "int " << indexName() << "::"
2584 << "accel_spe_func_index__" << epStr() << "=0;\n";
2588 // Add special pre- and post- call code
2589 if (isSync() || isIget()) {
2590 // A synchronous method can return a value, and must finish before
2591 // the caller can proceed.
2593 << " int impl_ref = CkGetRefNum(impl_msg), impl_src = CkGetSrcPe(impl_msg);\n";
2594 if (retType->isVoid() || retType->isMessage()) preCall << " void *impl_retMsg=";
2595 if (retType->isVoid()) {
2596 preCall << "CkAllocSysMsg();\n ";
2597 } else if (retType->isMessage()) {
2598 preCall << "(void *) ";
2600 preCall << " " << retType << " impl_ret_val= ";
2601 postCall << " //Marshall: impl_ret_val\n";
2602 postCall << " int impl_ret_size=0;\n";
2603 postCall << " { //Find the size of the PUP'd data\n";
2604 postCall << " PUP::sizer implPS;\n";
2605 postCall << " implPS|impl_ret_val;\n";
2606 postCall << " impl_ret_size+=implPS.size();\n";
2607 postCall << " };\n";
2609 << " CkMarshallMsg *impl_retMsg=CkAllocateMarshallMsg(impl_ret_size, NULL);\n";
2610 postCall << " { //Copy over the PUP'd data;\n";
2611 postCall << " PUP::toMem implPS((void *)impl_retMsg->msgBuf);\n";
2612 postCall << " implPS|impl_ret_val;\n";
2613 postCall << " };\n";
2615 postCall << " CkSendToFutureID(impl_ref, impl_retMsg, impl_src);\n";
2616 } else if (isExclusive()) {
2617 // An exclusive method
2619 << " if(CmiTryLock(impl_obj->__nodelock)) {\n"; /*Resend msg. if lock busy*/
2620 /******* DANGER-- RESEND CODE UNTESTED **********/
2621 if (param->isMarshalled()) {
2622 preMarshall << " impl_msg = CkCopyMsg(&impl_msg);\n";
2624 preMarshall << " CkSendMsgNodeBranch(" << epIdx()
2625 << ",impl_msg,CkMyNode(),impl_obj->CkGetNodeGroupID());\n";
2626 preMarshall << " return;\n";
2627 preMarshall << " }\n";
2629 postCall << " CmiUnlock(impl_obj->__nodelock);\n";
2632 if (param->isVoid() && !isNoKeep()) {
2633 /* Reuse the message using CkFreeSysMsg by putting it in the msgpool if it is a fixed
2634 * sized message. The message is a fixed sized message if it has no priority bytes. A
2635 * message with priority bytes will not be reused and will be deallocated similar to
2636 * other marshalled messages.
2638 postCall << " if(UsrToEnv(impl_msg)->isVarSysMsg() == 0)\n";
2639 postCall << " CkFreeSysMsg(impl_msg);\n";
2642 if (!isConstructor() && fortranMode) { // Fortran90
2643 str << "/* FORTRAN SECTION */\n";
2646 dim << ((Array*)container)->dim();
2648 // Define the Fortran interface function
2649 // This is called from Fortran to send the message to a chare.
2650 str << "extern \"C\" ";
2652 str << fortranify(container->baseName(), "_Invoke_", name);
2653 str << "(void** aindex";
2654 str << ", " << container->indexList();
2655 if (!param->isVoid()) {
2657 param->printAddress(str);
2661 str << " CkArrayID *aid = (CkArrayID *)*aindex;\n";
2663 str << " " << container->proxyName() << " h(*aid);\n";
2664 if (dim == (const char*)"1D")
2665 str << " h[*index1]." << name << "(";
2666 else if (dim == (const char*)"2D")
2667 str << " h[CkArrayIndex2D(*index1, *index2)]." << name << "(";
2668 else if (dim == (const char*)"3D")
2669 str << " h[CkArrayIndex3D(*index1, *index2, *index3)]." << name << "(";
2670 if (!param->isVoid()) param->printValue(str);
2674 if (container->isArray()) {
2675 str << "extern \"C\" ";
2677 str << fortranify(container->baseName(), "_Broadcast_", name);
2678 str << "(void** aindex";
2679 if (!param->isVoid()) {
2681 param->printAddress(str);
2685 str << " CkArrayID *aid = (CkArrayID *)*aindex;\n";
2687 str << " " << container->proxyName() << " h(*aid);\n";
2688 str << " h." << name << "(";
2689 if (!param->isVoid()) param->printValue(str);
2694 if (isReductionTarget()) {
2695 str << "extern \"C\" ";
2697 str << fortranify(container->baseName(), "_ReductionTarget_", name);
2700 str << " return CkReductionTarget(" << container->baseName() << ", " << name << ");\n";
2704 str << "/* FORTRAN SECTION END */\n";
2707 // DMK - Accel Support
2708 // Create the wrapper function for the acceleration call
2709 // TODO : FIXME : For now, just use the standard C++ code... create OffloadAPI
2712 genAccelIndexWrapperDef_general(str);
2714 genAccelIndexWrapperDef_spe(str);
2718 // Generate the call-method body
2719 str << makeDecl("void") << "::_call_" << epStr()
2720 << "(void* impl_msg, void* impl_obj_void)\n";
2722 // Do not create impl_obj for migration constructor as compiler throws an unused
2723 // variable warning otherwise
2724 if (!isMigrationConstructor()) {
2725 str << " " << container->baseName() << "* impl_obj = static_cast<"
2726 << container->baseName() << "*>(impl_obj_void);\n";
2729 if (isThreaded()) str << callThread(epStr());
2731 if (param->isMarshalled()) {
2732 if (param->hasConditional())
2733 str << " MarshallMsg_" << epStr() << " *impl_msg_typed=(MarshallMsg_" << epStr()
2734 << " *)impl_msg;\n";
2736 str << " CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2737 str << " char *impl_buf=impl_msg_typed->msgBuf;\n";
2739 genCall(str, preCall, false, false);
2740 param->endUnmarshall(str);
2742 if (isThreaded() && param->isMarshalled()) str << " delete impl_msg_typed;\n";
2744 str << " CkAbort(\"This method should never be called as it refers to a LOCAL entry "
2749 if (hasCallMarshall) {
2750 str << makeDecl("int") << "::_callmarshall_" << epStr()
2751 << "(char* impl_buf, void* impl_obj_void) {\n";
2752 str << " " << containerType << "* impl_obj = static_cast<" << containerType
2753 << "*>(impl_obj_void);\n";
2755 if (!param->hasConditional()) {
2756 genCall(str, preCall, false, true);
2757 /*FIXME: implP.size() is wrong if the parameter list contains arrays--
2758 need to add in the size of the arrays.
2760 str << " return implP.size();\n";
2762 str << " CkAbort(\"This method is not implemented for EPs using conditional "
2764 str << " return 0;\n";
2767 str << " CkAbort(\"This method should never be called as it refers to a LOCAL "
2768 "entry method!\");\n";
2769 str << " return 0;\n";
2773 if (param->isMarshalled()) {
2774 str << makeDecl("void") << "::_marshallmessagepup_" << epStr()
2775 << "(PUP::er &implDestP,void *impl_msg) {\n";
2777 if (param->hasConditional())
2778 str << " MarshallMsg_" << epStr() << " *impl_msg_typed=(MarshallMsg_" << epStr()
2779 << " *)impl_msg;\n";
2781 str << " CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2782 str << " char *impl_buf=impl_msg_typed->msgBuf;\n";
2783 param->beginUnmarshall(str);
2784 param->pupAllValues(str);
2786 str << " /*Fake pupping since we don't really have a message */\n";
2787 str << " int n=0;\n";
2788 str << " if (implDestP.hasComments()) implDestP.comment(\"LOCAL message\");\n";
2789 str << " implDestP|n;\n";
2794 // to match the registry, generate register call even if there is no SDAG code
2795 // if ((param->isMarshalled() || param->isVoid()) /* && (sdagCon || isWhenEntry) */)
2796 if ((param->isMarshalled() || param->isVoid()) && genClosureTypeNameProxy) {
2797 if (container->isTemplated()) str << container->tspec(false);
2799 str << "template <";
2800 tspec->genLong(str, false);
2804 str << ((container->isTemplated() || tspec) ? "PUPable_def_template_nonInst"
2806 << "(SINGLE_ARG(" << *genClosureTypeNameProxy;
2809 tspec->genShort(str);
2815 templateGuardEnd(str);
2818 XStr Entry::genRegEp(bool isForRedn) {
2820 str << "CkRegisterEp";
2823 tspec->genShort(str);
2828 str << "redn_wrapper_" << name << "(CkReductionMsg *impl_msg)\",\n";
2830 str << name << "(" << paramType(0) << ")\",\n";
2831 str << " _call_" << epStr(isForRedn, true);
2834 if (param->isMarshalled()) {
2835 if (param->hasConditional())
2836 str << "MarshallMsg_" << epStr() << "::__idx";
2838 str << "CkMarshallMsg::__idx";
2839 } else if (!param->isVoid() && !isMigrationConstructor()) {
2840 param->genMsgProxyName(str);
2842 } else if (isForRedn) {
2843 str << "CMessage_CkReductionMsg::__idx";
2851 // reductiontarget variants should not be nokeep. The actual ep will be
2852 // parameter marshalled (and hence flagged as nokeep), but we'll delete the
2853 // CkReductionMsg in generated code, not runtime code. (so that we can cast
2854 // it to CkReductionMsg not CkMarshallMsg)
2855 if (!isForRedn && (attribs & SNOKEEP)) str << "+CK_EP_NOKEEP";
2856 if (attribs & SNOTRACE) str << "+CK_EP_TRACEDISABLE";
2857 if (attribs & SIMMEDIATE) {
2858 str << "+CK_EP_TRACEDISABLE";
2859 str << "+CK_EP_IMMEDIATE";
2861 if (attribs & SAPPWORK) str << "+CK_EP_APPWORK";
2864 if (attribs & SMEM) str << "+CK_EP_MEMCRITICAL";
2866 if (internalMode) str << "+CK_EP_INTRINSIC";
2871 void Entry::genReg(XStr& str) {
2875 str << " CkIndex_" << label << "::idx_" << name;
2876 if (targs) str << "<" << targs << ">";
2877 str << "( static_cast<" << retType << " (" << label << "::*)(" << paramType(0, 0)
2882 str << " // REG: " << *this;
2883 str << " " << epIdx(0) << ";\n";
2884 if (isReductionTarget()) str << " " << epIdx(0, true) << ";\n";
2885 if (isConstructor()) {
2886 if (container->isMainChare() && !isMigrationConstructor())
2887 str << " CkRegisterMainChare(__idx, " << epIdx(0) << ");\n";
2888 if (param->isVoid()) str << " CkRegisterDefaultCtor(__idx, " << epIdx(0) << ");\n";
2889 if (isMigrationConstructor())
2890 str << " CkRegisterMigCtor(__idx, " << epIdx(0) << ");\n";
2894 void Entry::preprocess() {
2895 ParamList* pl = param;
2896 if (pl != NULL && pl->hasConditional()) {
2898 str << "MarshallMsg_" << epStr();
2899 NamedType* nt = new NamedType(strdup(str));
2900 MsgVar* var = new MsgVar(new BuiltinType("char"), "msgBuf", 0, 1);
2901 MsgVarList* list = new MsgVarList(var);
2903 if (pl->param->isConditional()) {
2904 var = new MsgVar(pl->param->getType(), pl->param->getName(), 1, 0);
2905 list = new MsgVarList(var, list);
2907 } while (NULL != (pl = pl->next));
2908 Message* m = new Message(-1, nt, list);
2909 m->setModule(container->containerModule);
2910 container->containerModule->prependConstruct(m);
2913 // DMK - Accel Support
2914 // Count the total number of scalar and array parameters if this is an accelerated entry
2915 accel_numScalars = 0;
2916 accel_numArrays = 0;
2917 accel_dmaList_numReadOnly = 0;
2918 accel_dmaList_numReadWrite = 0;
2919 accel_dmaList_numWriteOnly = 0;
2920 accel_dmaList_scalarNeedsWrite = 0;
2922 ParamList* curParam = param;
2923 if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
2924 curParam = curParam->next;
2926 while (curParam != NULL) {
2927 if (curParam->param->isArray()) {
2929 accel_dmaList_numReadOnly++;
2933 curParam = curParam->next;
2935 curParam = accelParam;
2936 while (curParam != NULL) {
2937 if (curParam->param->isArray()) {
2939 switch (curParam->param->getAccelBufferType()) {
2940 case Parameter::ACCEL_BUFFER_TYPE_READWRITE:
2941 accel_dmaList_numReadWrite++;
2943 case Parameter::ACCEL_BUFFER_TYPE_READONLY:
2944 accel_dmaList_numReadOnly++;
2946 case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY:
2947 accel_dmaList_numWriteOnly++;
2950 XLAT_ERROR_NOCOL("unknown accel param type", first_line_);
2955 switch (curParam->param->getAccelBufferType()) {
2956 case Parameter::ACCEL_BUFFER_TYPE_READWRITE:
2957 accel_dmaList_scalarNeedsWrite++;
2959 case Parameter::ACCEL_BUFFER_TYPE_READONLY:
2961 case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY:
2962 accel_dmaList_scalarNeedsWrite++;
2965 XLAT_ERROR_NOCOL("unknown accel param type", first_line_);
2969 curParam = curParam->next;
2971 if (accel_numScalars > 0) {
2972 if (accel_dmaList_scalarNeedsWrite) {
2973 accel_dmaList_numReadWrite++;
2975 accel_dmaList_numReadOnly++;
2981 int Entry::paramIsMarshalled(void) { return param->isMarshalled(); }
2983 int Entry::getStackSize(void) { return (stacksize ? stacksize->getIntVal() : 0); }
2985 void Entry::setAccelParam(ParamList* apl) { accelParam = apl; }
2986 void Entry::setAccelCodeBody(XStr* acb) { accelCodeBody = acb; }
2987 void Entry::setAccelCallbackName(XStr* acbn) { accelCallbackName = acbn; }
2989 int Entry::isThreaded(void) { return (attribs & STHREADED); }
2990 int Entry::isSync(void) { return (attribs & SSYNC); }
2991 int Entry::isIget(void) { return (attribs & SIGET); }
2992 int Entry::isConstructor(void) {
2993 return !strcmp(name, container->baseName(0).get_string());
2995 bool Entry::isMigrationConstructor() { return isConstructor() && (attribs & SMIGRATE); }
2996 int Entry::isExclusive(void) { return (attribs & SLOCKED); }
2997 int Entry::isImmediate(void) { return (attribs & SIMMEDIATE); }
2998 int Entry::isSkipscheduler(void) { return (attribs & SSKIPSCHED); }
2999 int Entry::isInline(void) { return attribs & SINLINE; }
3000 int Entry::isLocal(void) { return attribs & SLOCAL; }
3001 int Entry::isCreate(void) { return (attribs & SCREATEHERE) || (attribs & SCREATEHOME); }
3002 int Entry::isCreateHome(void) { return (attribs & SCREATEHOME); }
3003 int Entry::isCreateHere(void) { return (attribs & SCREATEHERE); }
3004 int Entry::isPython(void) { return (attribs & SPYTHON); }
3005 int Entry::isNoTrace(void) { return (attribs & SNOTRACE); }
3006 int Entry::isAppWork(void) { return (attribs & SAPPWORK); }
3007 int Entry::isNoKeep(void) { return (attribs & SNOKEEP); }
3008 int Entry::isSdag(void) { return (sdagCon != 0); }
3009 bool Entry::isTramTarget(void) { return (attribs & SAGGREGATE) != 0; }
3011 // DMK - Accel support
3012 int Entry::isAccel(void) { return (attribs & SACCEL); }
3014 int Entry::isMemCritical(void) { return (attribs & SMEM); }
3015 int Entry::isReductionTarget(void) { return (attribs & SREDUCE); }
3017 char* Entry::getEntryName() { return name; }
3018 int Entry::getLine() { return line; }