added a variable higherLevel and a method deliverer to be used to uniform the
[charm.git] / src / conv-com / treerouter.C
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**************************************
9  * File: treerouter.C
10  *
11  * Author: Krishnan V
12  *
13  * Tree based router
14  *********************************************/
15 #include "treerouter.h"
16 #define DEGREE 4
17 #define gmap(pe) (gpes ? gpes[pe] : pe)
18
19
20 /**The only communication op used. Modify this to use
21  ** vector send */
22 #define TREESENDFN(kid, u, knewmsg, klen, khndl, knextpe)  \
23         {if (knewmsg) {\
24           CmiSetHandler(knewmsg, khndl);\
25           CmiSyncSendAndFree(knextpe, klen, knewmsg);\
26         }\
27         else {\
28           SendDummyMsg(kid, knextpe, u);\
29         }\
30 }
31
32 /************************************************
33  ************************************************/
34 TreeRouter :: TreeRouter(int n, int me)
35 {
36   int i;
37   MyPe=me;
38   NumPes=n;
39   gpes=NULL;
40
41   numChildren=0;
42   for (i=0;i<DEGREE;i++) {
43         if ((MyPe*DEGREE+i+1) < NumPes) numChildren++;
44   }
45
46   PeTree = new PeTable(NumPes);
47
48   recvExpected=1+numChildren;
49   InitVars();
50   //CmiPrintf("Tree with n=%d, me=%d\n", n, me);
51 }
52
53 TreeRouter :: ~TreeRouter()
54 {
55   delete PeTree;
56 }
57
58 void TreeRouter :: InitVars()
59 {
60   recvCount=0;
61 }
62
63
64 void TreeRouter::NumDeposits(comID , int num)
65 {
66 }
67
68 void TreeRouter::EachToAllMulticast(comID id, int size, void *msg, int more)
69 {
70   int npe=NumPes;
71   int * destpes=(int *)CmiAlloc(sizeof(int)*npe);
72   for (int i=0;i<npe;i++) destpes[i]=i;
73   EachToManyMulticast(id, size, msg, npe, destpes, more);
74 }
75
76 void TreeRouter::EachToManyMulticast(comID id, int size, void *msg, int numpes, int *destpes, int more)
77 {
78  //Create the message
79   if (size) {
80         PeTree->InsertMsgs(numpes, destpes, size, msg);
81   }
82
83   if (more >0) return;
84
85   //Hand it over to Recv. 
86   RecvManyMsg(id, NULL);
87 }
88
89 void TreeRouter :: RecvManyMsg(comID id, char *msg)
90 {
91   if (msg)
92         PeTree->UnpackAndInsert(msg);
93   recvCount++;
94   //CmiPrintf("%d Tree: recvCount=%d, recvExpected=%d\n",MyPe, recvCount, recvExpected);
95   if (recvCount == recvExpected) {
96         if (MyPe) {
97                 int len;
98                 int parent=(MyPe-1)/DEGREE;
99                 parent=gmap(parent);
100                 char *newmsg=SortBufferUp(id, 0, &len);
101                 TREESENDFN(id, 0, newmsg, len, CkpvAccess(RecvHandle), parent);
102
103         }
104         else {
105                 DownStreamMsg(id);
106         }
107   }
108   if (recvCount > recvExpected) DownStreamMsg(id);
109 }
110
111 char * TreeRouter :: SortBufferUp(comID id, int ufield, int *len)
112 {
113   int np=0, i;
114   int * pelst=(int *)CmiAlloc(sizeof(int)*NumPes);
115
116   for (i=0;i<NumPes;i++) {
117
118         //if (i==MyPe) continue;
119         int pe=i;
120         while (pe!=MyPe && pe>0) pe =(pe-1)/DEGREE;
121         if (pe == MyPe) continue;
122
123         pelst[np++]=i;
124   }
125   char *newmsg=PeTree->ExtractAndPack(id, ufield, np, pelst, len); 
126   CmiFree(pelst);
127   return(newmsg);
128 }
129   
130 char * TreeRouter :: SortBufferDown(comID id, int ufield, int *len, int s)
131 {
132   int np=0, i;
133   int * plist=(int *)CmiAlloc(sizeof(int)*NumPes);
134
135   for (i=0;i<NumPes;i++) {
136         if (i==MyPe) continue;
137         int pe=i;
138         int rep=MyPe*DEGREE+s;
139         while (pe!=rep && pe>0) pe =(pe-1)/DEGREE;
140         if (pe == rep) plist[np++]=i;
141   }
142
143   char * newmsg=PeTree->ExtractAndPack(id, ufield, np, plist, len); 
144   CmiFree(plist);
145   return(newmsg);
146 }
147
148 void TreeRouter :: DownStreamMsg(comID id)
149 {
150   int deg=DEGREE;
151   if (NumPes < deg) deg=NumPes;
152
153   for (int i=0;i<deg;i++) {
154     int len;
155     char *newmsg=SortBufferDown(id, 0, &len, i+1);
156     int child=MyPe*DEGREE+i+1;
157     if (child >=NumPes || child==MyPe) break;
158     child=gmap(child);
159     TREESENDFN(id, 0, newmsg, len, CkpvAccess(RecvHandle), child);
160   }
161
162   LocalProcMsg(id);
163 }
164
165 void TreeRouter :: ProcManyMsg(comID id, char *m)
166 {
167   PeTree->UnpackAndInsert(m);
168   LocalProcMsg(id);
169 }
170
171 void TreeRouter:: LocalProcMsg(comID id)
172 {
173   PeTree->ExtractAndDeliverLocalMsgs(MyPe);
174   PeTree->Purge();
175   InitVars();
176   Done(id);
177 }
178
179 void TreeRouter :: DummyEP(comID id, int)
180 {
181   RecvManyMsg(id, NULL);
182 }
183
184 Router * newtreeobject(int n, int me)
185 {
186   Router * obj=new TreeRouter(n, me);
187   return(obj);
188 }
189
190 void TreeRouter :: SetMap(int *pes)
191 {
192   gpes=pes;
193 }