aca7571bdafb43ec33fee284d48fcce4a27d919e
[charm.git] / src / ck-core / charisma.h
1 #ifndef CHARISMA_H
2 #define CHARISMA_H
3
4 #include "charisma.decl.h"
5
6 class Name
7 {
8   private:
9     char *curname;
10     int curbuflen;
11     int curlen;
12   public:
13     Name(void)
14     {
15       curbuflen = 100;
16       curname = new char[curbuflen];
17       curname[0] = '\0';
18       curlen = 0;
19     }
20     void add(const char *n)
21     {
22       int len = strlen(n);
23       if((curlen+len+2) > curbuflen) {
24         char *t = new char[curlen+len+2];
25         strcpy(t, curname);
26         delete[] curname;
27         curname = t;
28         curbuflen = curlen+len+2;
29       }
30       if(curlen!=0) {
31         strcat(curname, ".");
32         curlen++;
33       }
34       strcat(curname, n);
35       curlen += len;
36     }
37     void remove(const char *n)
38     {
39       int len = strlen(n);
40       curlen = curlen-len;
41       curname[curlen] = '\0';
42       if(curlen!=0) {
43         curname[--curlen] = '\0';
44       }
45     }
46     inline operator char *() const { return curname; }
47     ~Name()
48     {
49       delete[] curname;
50     }
51 };
52
53 class Component
54 {
55   private:
56     char *name;
57     char *type;
58     int idx; // unique index for every component given for partitioning
59     int pe; // mapping resulting from partitioning
60     int nout; // number of output ports
61     int nin; // number of input ports
62     int ncout; // number of connected output ports
63     int ncin; // number of connected input ports
64   public:
65     Component(const char *n, const char *t)
66     {
67       name = new char[strlen(n)+1];
68       strcpy(name,n);
69       type = new char[strlen(t)+1];
70       strcpy(type,t);
71       ncout = ncin = nout = nin = 0;
72       idx = pe = (-1); // something invalid
73     }
74     ~Component()
75     {
76       delete[] type;
77     }
78     char *getName(void) { return name; }
79     char *getType(void) { return type; }
80     void setIdx(int _idx) { idx = _idx; }
81     int getIdx(void) { return idx; }
82     void setPe(int _pe) { pe = _pe; }
83     int getPe(void) { return pe; }
84     void addOutPort(void) { nout++; }
85     void addInPort(void) { nin++; }
86     void connectOutPort(void) { ncout++; }
87     void connectInPort(void) { ncin++; }
88     int getNumPorts(void) { return nout + nin; }
89     int getNumConnectedPorts(void) { return ncout + ncin; }
90 };
91
92 #define CHARISMA_IN 1
93 #define CHARISMA_OUT 2
94
95 class Port
96 {
97   private:
98     int inout; // IN/OUT
99     char *name;
100     Component *comp;
101     char *type;
102     Port *peer;
103   public:
104     Port(const char *n, Component *c, const char *t, int io)
105     {
106       name = new char[strlen(n)+1];
107       strcpy(name,n);
108       comp = c;
109       type = new char[strlen(t)+1];
110       strcpy(type,t);
111       inout = io;
112       peer = 0;
113     }
114     void setPeer(Port *p)
115     {
116       peer = p;
117     }
118     ~Port()
119     {
120       delete[] name;
121       delete[] type;
122     }
123     char *getName(void) { return name; }
124     char *getType(void) { return type; }
125     Port *getPeer(void) { return peer; }
126     Component *getComp(void) { return comp; }
127 };
128
129 extern "C"
130 void METIS_PartGraphRecursive(int* n, int* xadj, int* adjncy, int* vwght,
131     int* adjwgt, int* wgtflag, int* numflag, int* nparts, int* options,
132     int* edgecut, int* part);
133
134 class CharismaGraph
135 {
136   private:
137     CkHashtableTslow<const char *, Port *> ports;
138     CkHashtableTslow<const char *, Component *> comps;
139     Name *curname;
140   public:
141     CharismaGraph(void)
142     {
143       curname = new Name;
144     }
145     // indicate that all the following registrations belong to component
146     // named name.
147     void start(const char *name, const char *type)
148     {
149       curname->add(name);
150       CkPrintf("starting registration for %s\n", (char *) curname);
151       Component *curcomp = new Component((const char *)curname, type);
152       comps.put((const char *)curname) = curcomp;
153     }
154     // end registrations for component called name
155     void end(const char *name)
156     {
157       CkPrintf("ending registration for %s\n", (char *) curname);
158       curname->remove(name);
159     }
160     // register an output port
161     void registerOutPort(const char *name, const char *type)
162     {
163       Component *curcomp = comps.get((const char *) curname);
164       curcomp->addOutPort();
165       curname->add(name);
166       CkPrintf("registering outport %s\n", (char *) curname);
167       ports.put((const char *)curname) = new Port((const char *)curname,
168           curcomp, type, CHARISMA_OUT);
169       curname->remove(name);
170     }
171     // register an input port
172     void registerInPort(const char *name, const char *type)
173     {
174       Component *curcomp = comps.get((const char *) curname);
175       curcomp->addInPort();
176       curname->add(name);
177       CkPrintf("registering outport %s\n", (char *) curname);
178       ports.put((const char *)curname) = new Port((const char *) curname,
179           curcomp, type, CHARISMA_IN);
180       curname->remove(name);
181     }
182     // connect an output port name1 to input port name2
183     void connect(const char *name1, const char *name2)
184     {
185       curname->add(name1);
186       char *oname = new char[strlen((char*)curname)+1];
187       strcpy(oname, (char*) curname);
188       curname->remove(name1);
189       curname->add(name2);
190       char *iname = new char[strlen((char*)curname)+1];
191       strcpy(iname, (char*) curname);
192       curname->remove(name2);
193       Port *oport = ports.get(oname);
194       Port *iport = ports.get(iname);
195       if(strcmp(oport->getType(), iport->getType())!=0)
196         CkAbort("Types of connected ports do not match !!!\n");
197       oport->setPeer(iport);
198       iport->setPeer(oport);
199       oport->getComp()->connectOutPort();
200       iport->getComp()->connectInPort();
201       delete[] oname;
202       delete[] iname;
203     }
204     void Partition(void)
205     {
206       int i;
207       int n = 0; // number of objects
208       CkHashtableIterator *ht = comps.iterator();
209       CkHashtableIterator *pt = ports.iterator();
210       // count the number of components, assigning unique index to each
211       // component, this index will be used for partitioning
212       ht->seekStart();
213       while(ht->hasNext()) {
214         Component *c = (Component *) ht->next();
215         c->setIdx(n);
216         n++;
217       }
218       int *nconnect = new int[n];
219       int tadj = 0;
220       ht->seekStart();
221       while(ht->hasNext()) {
222         Component *c = (Component *) ht->next();
223         nconnect[c->getIdx()] = c->getNumConnectedPorts();
224         tadj += nconnect[c->getIdx()];
225       }
226       // now the nconnect array contains the number of edges for each vertex
227       // and tadj contains total number of connections
228       int *xadj = new int[n];
229       int *adjncy = new int[tadj];
230       // construct the adjcency in CSR format as required by Metis
231       xadj[0] = 0;
232       for(i=1;i<n;i++)
233         xadj[i] = xadj[i-1] + nconnect[i-1];
234       for(i=0;i<tadj;i++)
235         adjncy[i] = (-1); // set to something invalid
236       pt->seekStart();
237       while(pt->hasNext()) {
238         Port *p = (Port *) pt->next();
239         Port *peer = p->getPeer();
240         if(peer==0) // an unconnected port
241           continue;
242         Component *comp1 = p->getComp();
243         Component *comp2 = peer->getComp();
244         int idx1 = comp1->getIdx();
245         int idx2 = comp2->getIdx();
246         int i;
247         for(i=xadj[idx1];adjncy[i]!=(-1);i++);
248         adjncy[i] = idx2;
249       }
250       int *vwgt = new int[n];
251       int *adjwgt = new int[tadj];
252       // currently all vertices are assumed to be of same wgt
253       // this will change after embellishing the connection code
254       for(i=0;i<n; i++)
255         vwgt[i] = 1;
256       // currently all vertices are assumed to be of same wgt
257       // this will change after embellishing the connection code
258       for(i=0;i<tadj; i++)
259         adjwgt[i] = 1;
260       int wgtflag = 3; // weights on both vertices and edges
261       int numflag = 0; // we use C-style numbering (starting with 0)
262       int nparts = CkNumPes(); // number of partitions desired
263       int options[5];
264       options[0] = 0; // use default options
265       int edgecut; // contains edgecut after partitioning
266       int *part = new int[n]; // contains mapping output to processor number
267       METIS_PartGraphRecursive(&n, xadj, adjncy, vwgt, adjwgt, &wgtflag,
268           &numflag, &nparts, options, &edgecut, part);
269       ht->seekStart();
270       while(ht->hasNext()) {
271         Component* c = (Component *) ht->next();
272         c->setPe(part[c->getIdx()]);
273       }
274     }
275 };
276
277 class CkArrayIndexCharisma: public CkArrayIndex
278 {
279   int i, j, k;
280   public:
281     CkArrayIndexCharisma(int _i) {
282       i = _i; j = 0; k = 0;
283       nInts = 1;
284     }
285     CkArrayIndexCharisma(int _i, int _j) {
286       i = _i; j= _j; k= 0;
287       nInts = 2;
288     }
289     CkArrayIndexCharisma(int _i, int _j, int _k) {
290       i = _i; j = _j; k= _k;
291       nInts = 3;
292     }
293 };
294
295 class CharismaInPort
296 {
297   public:
298     virtual void send(void *msg, int len) = 0;
299     void _create(const char *name)
300     {
301       // todo: tell Charisma that the inport is created
302     }
303 };
304
305 class CharismaOutPort
306 {
307   protected:
308     CharismaInPort *inport;
309   public:
310     virtual void emitData(void *data, int len)
311     {
312       inport->send(data, len);
313     }
314     void _create(const char *name)
315     {
316       // todo: tell charisma that the outport is created
317     }
318 };
319
320 template <class d>
321 class CkOutPort: public CharismaOutPort
322 {
323   public:
324     CkOutPort(const char *name) { _create(name); }
325     void emit(d &_d)
326     {
327       CharismaOutPort::emitData((void *) &_d, sizeof(d));
328     }
329 };
330
331 template <class d>
332 class CkInPort : public CharismaInPort
333 {
334   private:
335     CkCallback cb;
336     CkInPort() {} // prevent illegal inports
337   public:
338     CkInPort(const char *name, int ep,const CkChareID &id)
339     {
340       _create(name);
341       CkCallback _cb(ep,id);
342       cb = _cb;
343     }
344     CkInPort(const char *name, int ep,int onPE,const CkGroupID &id)
345     {
346       _create(name);
347       CkCallback _cb(ep,onPE,id);
348       cb = _cb;
349     }
350     CkInPort(const char *name, int ep,const CkArrayIndex &idx,
351              const CkArrayID &id)
352     {
353       _create(name);
354       CkCallback _cb(ep,idx,id);
355       cb = _cb;
356     }
357     void send(void *data, int len)
358     {
359       send((d&) (*((d*)data)));
360     }
361     void send(d &_d)
362     {
363       int impl_off=0,impl_arrstart=0;
364       { //Find the size of the PUP'd data
365         PUP::sizer implP;
366         implP|_d;
367         impl_arrstart=CK_ALIGN(implP.size(),16);
368         impl_off+=impl_arrstart;
369       }
370       CkMarshallMsg *impl_msg=new (impl_off,0)CkMarshallMsg;
371       { //Copy over the PUP'd data
372         PUP::toMem implP((void *)impl_msg->msgBuf);
373         implP|_d;
374       }
375       CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;
376       impl_amsg->array_setIfNotThere(CkArray_IfNotThere_buffer);
377       cb.send(impl_msg);
378     }
379 };
380
381 class CkOutPortString : public CharismaOutPort
382 {
383   public:
384     CkOutPortString(const char *name) { _create(name); }
385     void emit(char *str)
386     {
387       CharismaOutPort::emitData((void *) str, (int) strlen(str)+1);
388     }
389 };
390
391 class CkInPortString : public CharismaInPort
392 {
393   private:
394     CkCallback cb;
395     CkInPortString() {} // prevent illegal inports
396   public:
397     CkInPortString(const char *name, int ep,const CkChareID &id)
398     {
399       _create(name);
400       CkCallback _cb(ep,id);
401       cb = _cb;
402     }
403     CkInPortString(const char *name, int ep,int onPE,const CkGroupID &id)
404     {
405       _create(name);
406       CkCallback _cb(ep,onPE,id);
407       cb = _cb;
408     }
409     CkInPortString(const char *name, int ep,const CkArrayIndex &idx,
410                    const CkArrayID &id)
411     {
412       _create(name);
413       CkCallback _cb(ep,idx,id);
414       cb = _cb;
415     }
416     void send(void *data, int len)
417     {
418       send((char *) data);
419     }
420     void send(char *str)
421     {
422       CkMarshallMsg *impl_msg=new (strlen(str)+1,0)CkMarshallMsg;
423       strcpy((char *)(impl_msg->msgBuf),str);
424       CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;
425       impl_amsg->array_setIfNotThere(CkArray_IfNotThere_buffer);
426       cb.send(impl_msg);
427     }
428 };
429
430 template <class d>
431 class CkOutPortArray : public CharismaOutPort
432 {
433   public:
434     CkOutPortArray(const char *name) { _create(name); }
435     void emit(int n, const d *a)
436     {
437       CharismaOutPort::emitData((void *)a, n*sizeof(d));
438     }
439 };
440
441 template <class d>
442 class CkInPortArray : public CharismaInPort
443 {
444   private:
445     CkCallback cb;
446     CkInPortArray() {} // prevent illegal inports
447   public:
448     CkInPortArray(const char *name, int ep,const CkChareID &id)
449     {
450       _create(name);
451       CkCallback _cb(ep,id);
452       cb = _cb;
453     }
454     CkInPortArray(const char *name, int ep,int onPE,const CkGroupID &id)
455     {
456       _create(name);
457       CkCallback _cb(ep,onPE,id);
458       cb = _cb;
459     }
460     CkInPortArray(const char *name, int ep,const CkArrayIndex &idx,
461                   const CkArrayID &id)
462     {
463       _create(name);
464       CkCallback _cb(ep,idx,id);
465       cb = _cb;
466     }
467     void send(void *data, int len)
468     {
469       send(len/sizeof(d), (const d*) data);
470     }
471     void send(int n, const d *a)
472     {
473       //Marshall: int n, const int *a
474       int impl_off=0,impl_arrstart=0;
475       int impl_off_a, impl_cnt_a;
476       impl_off_a=impl_off=CK_ALIGN(impl_off,sizeof(int));
477       impl_off+=(impl_cnt_a=sizeof(int)*(n));
478       { //Find the size of the PUP'd data
479         PUP::sizer implP;
480         implP|n;
481         implP|impl_off_a;
482         impl_arrstart=CK_ALIGN(implP.size(),16);
483         impl_off+=impl_arrstart;
484       }
485       CkMarshallMsg *impl_msg=new (impl_off,0)CkMarshallMsg;
486       { //Copy over the PUP'd data
487         PUP::toMem implP((void *)impl_msg->msgBuf);
488         implP|n;
489         implP|impl_off_a;
490       }
491       char *impl_buf=impl_msg->msgBuf+impl_arrstart;
492       memcpy(impl_buf+impl_off_a,a,impl_cnt_a);
493     }
494 };
495
496 class CkOutPortVoid : public CharismaOutPort
497 {
498   public:
499     CkOutPortVoid(const char *name) { _create(name); }
500     void emit(void)
501     {
502       CharismaOutPort::emitData((void*) 0, 0);
503     }
504 };
505
506 class CkInPortVoid : public CharismaInPort
507 {
508   private:
509     CkCallback cb;
510     CkInPortVoid() {} // prevent illegal inports
511   public:
512     CkInPortVoid(const char *name, int ep,const CkChareID &id)
513     {
514       _create(name);
515       CkCallback _cb(ep,id);
516       cb = _cb;
517     }
518     CkInPortVoid(const char *name, int ep,int onPE,const CkGroupID &id)
519     {
520       _create(name);
521       CkCallback _cb(ep,onPE,id);
522       cb = _cb;
523     }
524     CkInPortVoid(const char *name, int ep,const CkArrayIndex &idx,
525                  const CkArrayID &id)
526     {
527       _create(name);
528       CkCallback _cb(ep,idx,id);
529       cb = _cb;
530     }
531     void send(void *data, int len)
532     {
533       send();
534     }
535     void send(void)
536     {
537       void *impl_msg = CkAllocSysMsg();
538       cb.send(impl_msg);
539     }
540 };
541
542 template <class d>
543 class CkOutPortMsg : public CharismaOutPort
544 {
545   public:
546     CkOutPortMsg(const char *name) { _create(name); }
547     void emit(d *data)
548     {
549       // TODO: do message packing, and get the actual buffer size
550       CharismaOutPort::emitData((void*) data, sizeof(d));
551     }
552 };
553
554 template <class d>
555 class CkInPortMsg : public CharismaInPort
556 {
557   private:
558     CkCallback cb;
559     CkInPortMsg() {} // prevent illegal inports
560   public:
561     CkInPortMsg(const char *name, int ep,const CkChareID &id)
562     {
563       _create(name);
564       CkCallback _cb(ep,id);
565       cb = _cb;
566     }
567     CkInPortMsg(const char *name, int ep,int onPE,const CkGroupID &id)
568     {
569       _create(name);
570       CkCallback _cb(ep,onPE,id);
571       cb = _cb;
572     }
573     CkInPortMsg(const char *name, int ep,const CkArrayIndex &idx,
574                 const CkArrayID &id)
575     {
576       _create(name);
577       CkCallback _cb(ep,idx,id);
578       cb = _cb;
579     }
580     void send(void *data, int len)
581     {
582       send((d*) data);
583     }
584     void send(d *_d)
585     {
586       cb.send(_d);
587     }
588 };
589
590 class Charisma : public IrrGroup
591 {
592   public:
593     Charisma(void) { }
594     Charisma(CkMigrateMessage *m) : IrrGroup(m) { }
595 };
596
597 #endif