c6d562a7c8ac5635c3516a626d811330f79b52a5
[IRC.git] / Robust / src / Runtime / bamboo / multicoreruntime.h
1 #ifndef MULTICORE_RUNTIME
2 #define MULTICORE_RUNTIME
3 #include "structdefs.h"
4
5 #ifndef INLINE
6 #define INLINE    inline __attribute__((always_inline))
7 #endif
8
9 #ifndef bool
10 #define bool int
11 #define true 1
12 #define false 0
13 #endif
14
15 ////////////////////////////////////////////////////////////////
16 // global variables                                          //
17 ///////////////////////////////////////////////////////////////
18
19 // record the starting time
20 unsigned long long bamboo_start_time;
21 bool stall;
22 int totalexetime;
23 #ifndef INTERRUPT
24 bool reside;
25 #endif
26
27 #ifdef MULTICORE
28 #ifdef GC_SMALLPAGESIZE
29 #define BAMBOO_GLOBAL_DEFS_SIZE (1024 * 1024)
30 #define BAMBOO_GLOBAL_DEFS_PRIM_SIZE (1024 * 512)
31 #else
32 #define BAMBOO_GLOBAL_DEFS_SIZE (BAMBOO_SMEM_SIZE)
33 #define BAMBOO_GLOBAL_DEFS_PRIM_SIZE (BAMBOO_SMEM_SIZE/2)
34 #endif // GC_SMALLPAGESIZE
35 #endif // MULTICORE
36
37 #ifdef MGC
38 // shared memory pointer for global thread queue
39 // In MGC version, this block of memory is located at the very bottom of the 
40 // shared memory with the base address as BAMBOO_BASE_VA.
41 // The bottom of the shared memory = global thread queue + sbstart tbl 
42 //                                  + smemtbl + NUMCORES4GC bamboo_rmsp
43 // This queue is always reside at the bottom of the shared memory.  It is 
44 // considered as runtime structure, during gc, it is scanned for mark and flush 
45 // phase but never been compacted.
46 //
47 // This is a loop array and the first 4 int fields of the queue are:
48 //     mutex + thread counter + start pointer + end pointer
49 #ifdef GC_SMALLPAGESIZE
50 #define BAMBOO_THREAD_QUEUE_SIZE (1024 * 1024)
51 #else
52 #define BAMBOO_THREAD_QUEUE_SIZE (BAMBOO_SMEM_SIZE) // (45 * 16 * 1024)
53 #endif
54 // data structures for threads
55 unsigned int * bamboo_thread_queue;
56 unsigned int bamboo_max_thread_num_mask;
57 unsigned int bamboo_current_thread;
58
59 extern int corenum;
60 #endif // MGC
61
62 // data structures for msgs
63 #define BAMBOO_OUT_BUF_LENGTH 2048
64 #define BAMBOO_OUT_BUF_MASK (0x7FF)
65 #define BAMBOO_MSG_BUF_LENGTH 2048
66 #define BAMBOO_MSG_BUF_MASK (0x7FF)
67 int msgdata[BAMBOO_MSG_BUF_LENGTH];
68 volatile int msgdataindex;
69 volatile int msgdatalast;
70 int msglength;
71 volatile bool msgdatafull;
72 int outmsgdata[BAMBOO_OUT_BUF_LENGTH];
73 int outmsgindex;
74 int outmsglast;
75 int outmsgleft;
76 volatile bool isMsgHanging;
77
78 #define MSG_INDEXINC_I() \
79   msgdataindex = (msgdataindex + 1) & (BAMBOO_MSG_BUF_MASK) 
80
81 #define MSG_LASTINDEXINC_I() \
82   msgdatalast = (msgdatalast + 1) & (BAMBOO_MSG_BUF_MASK)
83
84 #define MSG_CACHE_I(n) \
85   msgdata[msgdatalast] = (n); \
86   MSG_LASTINDEXINC_I()
87
88 // NOTE: if msgdataindex == msgdatalast, it always means that the buffer if
89 //       full. In the case that the buffer is empty, should never call this
90 //       MACRO
91 #define MSG_REMAINSIZE_I(s) \
92   if(msgdataindex < msgdatalast) { \
93     (*(int*)s) = msgdatalast - msgdataindex; \
94   } else if((msgdataindex == msgdatalast) && (!msgdatafull)) { \
95     (*(int*)s) = 0; \
96   } else { \
97     (*(int*)s) = (BAMBOO_MSG_BUF_LENGTH) - msgdataindex + msgdatalast; \
98   }
99
100 #define OUTMSG_INDEXINC() \
101   outmsgindex = (outmsgindex + 1) & (BAMBOO_OUT_BUF_MASK)
102
103 #define OUTMSG_LASTINDEXINC() \
104   outmsglast = (outmsglast + 1) & (BAMBOO_OUT_BUF_MASK); \
105   if(outmsglast == outmsgindex) { \
106     BAMBOO_EXIT(0xd101); \
107   }
108
109 #define OUTMSG_CACHE(n) \
110   outmsgdata[outmsglast] = (n); \
111   OUTMSG_LASTINDEXINC();
112
113 #define MAX_PACKET_WORDS 5
114
115 /* Message format:
116  *      type + Msgbody
117  * type: 1 -- transfer object
118  *       2 -- transfer stall msg
119  *       3 -- lock request
120  *       4 -- lock grount
121  *       5 -- lock deny
122  *       6 -- lock release
123  *       // add for profile info
124  *       7 -- transfer profile output msg
125  *       8 -- transfer profile output finish msg
126  *       // add for alias lock strategy
127  *       9 -- redirect lock request
128  *       a -- lock grant with redirect info
129  *       b -- lock deny with redirect info
130  *       c -- lock release with redirect info
131  *       d -- status confirm request
132  *       e -- status report msg
133  *       f -- terminate
134  *      10 -- requiring for new memory
135  *      11 -- response for new memory request
136  *      12 -- GC init phase start
137  *      13 -- GC start
138  *      14 -- compact phase start
139  *      15 -- flush phase start
140  *      16 -- init phase finish
141  *      17 -- mark phase finish
142  *      18 -- compact phase finish
143  *      19 -- flush phase finish
144  *      1a -- GC finish
145  *      1b -- marked phase finish confirm request
146  *      1c -- marked phase finish confirm response
147  *      1d -- markedObj msg
148  *      1e -- start moving objs msg
149  *      1f -- ask for mapping info of a markedObj
150  *      20 -- mapping info of a markedObj
151  *      21 -- large objs info request
152  *      22 -- large objs info response
153  *      23 -- large objs mapping info
154  *
155  * ObjMsg: 1 + size of msg + obj's address + (task index + param index)+
156  * StallMsg: 2 + corenum + sendobjs + receiveobjs
157  *             (size is always 4 * sizeof(int))
158  * LockMsg: 3 + lock type + obj pointer + lock + request core
159  *            (size is always 5 * sizeof(int))
160  *          4/5/6 + lock type + obj pointer + lock
161  *            (size is always 4 * sizeof(int))
162  *          9 + lock type + obj pointer +  redirect lock + root request core
163  *            + request core
164  *            (size is always 6 * sizeof(int))
165  *          a/b + lock type + obj pointer + redirect lock
166  *              (size is always 4 * sizeof(int))
167  *          c + lock type + lock + redirect lock
168  *            (size is always 4 * sizeof(int))
169  *          lock type: 0 -- read; 1 -- write
170  * ProfileMsg: 7 + totalexetime
171  *               (size is always 2 * sizeof(int))
172  *             8 + corenum
173  *               (size is always 2 * sizeof(int))
174  * StatusMsg: d (size is always 1 * sizeof(int))
175  *            e + status + corenum + sendobjs + receiveobjs
176  *              (size is always 5 * sizeof(int))
177  *            status: 0 -- stall; 1 -- busy
178  * TerminateMsg: f (size is always 1 * sizeof(int)
179  * MemoryMsg: 10 + size + corenum
180  *              (size is always 3 * sizeof(int))
181  *           11 + base_va + size
182  *              (size is always 3 * sizeof(int))
183  * GCMsg: 12/13 (size is always 1 * sizeof(int))
184  *        14 + size of msg + (num of objs to move + (start address
185  *           + end address + dst core + start dst)+)?
186  *           + (num of incoming objs + (start dst + orig core)+)?
187  *           + (num of large obj lists + (start address + lenght
188  *           + start dst)+)?
189  *        15 (size is always 1 * sizeof(int))
190  *        16 + corenum
191  *           (size is always 2 * sizeof(int))
192  *        17 + corenum + gcsendobjs + gcreceiveobjs
193  *           (size if always 4 * sizeof(int))
194  *        18 + corenum + fulfilled blocks num + (finish compact(1) + current
195  *           heap top)/(need mem(0) + mem need)
196  *           size is always 5 * sizeof(int))
197  *        19 + corenum
198  *              (size is always 2 * sizeof(int))
199  *        1a (size is always 1 * sizeof(int))
200  *        1b (size if always 1 * sizeof(int))
201  *        1c + size of msg + corenum + gcsendobjs + gcreceiveobjs
202  *           (size is always 5 * sizeof(int))
203  *        1d + obj's address + request core
204  *           (size is always 3 * sizeof(int))
205  *        1e + corenum + start addr + end addr
206  *           (size if always 4 * sizeof(int))
207  *        1f + obj's address + corenum
208  *           (size is always 3 * sizeof(int))
209  *        20 + obj's address + dst address
210  *           (size if always 3 * sizeof(int))
211  *        21 (size is always 1 * sizeof(int))
212  *        22 + size of msg + corenum + current heap size
213  *           + (num of large obj lists + (start address + length)+)?
214  *        23 + orig large obj ptr + new large obj ptr
215  *            (size is always 3 * sizeof(int))
216  */
217 typedef enum {
218   MSGSTART = 0xD0,       // 0xD0
219   TRANSOBJ,              // 0xD1
220   TRANSTALL,             // 0xD2
221   LOCKREQUEST,           // 0xD3
222   LOCKGROUNT,            // 0xD4
223   LOCKDENY,              // 0xD5
224   LOCKRELEASE,           // 0xD6
225   PROFILEOUTPUT,         // 0xD7
226   PROFILEFINISH,         // 0xD8
227   REDIRECTLOCK,          // 0xD9
228   REDIRECTGROUNT,        // 0xDa
229   REDIRECTDENY,          // 0xDb
230   REDIRECTRELEASE,       // 0xDc
231   STATUSCONFIRM,         // 0xDd
232   STATUSREPORT,          // 0xDe
233   TERMINATE,             // 0xDf
234   MEMREQUEST,            // 0xE0
235   MEMRESPONSE,           // 0xE1
236 #ifdef MULTICORE_GC
237   GCSTARTPRE,            // 0xE2
238   GCSTARTINIT,           // 0xE3
239   GCSTART,               // 0xE4
240   GCSTARTCOMPACT,        // 0xE5
241   GCSTARTFLUSH,          // 0xE6
242   GCFINISHPRE,           // 0xE7
243   GCFINISHINIT,          // 0xE8
244   GCFINISHMARK,          // 0xE9
245   GCFINISHCOMPACT,       // 0xEa
246   GCFINISHFLUSH,         // 0xEb
247   GCFINISH,              // 0xEc
248   GCMARKCONFIRM,         // 0xEd
249   GCMARKREPORT,          // 0xEe
250   GCMARKEDOBJ,           // 0xEf
251   GCMOVESTART,           // 0xF0
252   GCLOBJREQUEST,         // 0xF1   
253   GCLOBJINFO,            // 0xF2
254 #ifdef GC_PROFILE
255   GCPROFILES,            // 0xF3
256 #endif // GC_PROFILE
257 #ifdef GC_CACHE_ADAPT
258   GCSTARTPOSTINIT,       // 0xF4
259   GCSTARTPREF,           // 0xF5
260   GCFINISHPOSTINIT,      // 0xF6
261   GCFINISHPREF,          // 0xF7
262 #endif // GC_CACHE_ADAPT
263 #endif // MULTICORE_GC
264   MSGEND
265 } MSGTYPE;
266
267 /////////////////////////////////////////////////////////////////////////////////
268 // NOTE: BAMBOO_TOTALCORE -- number of the available cores in the processor.
269 //                           No greater than the number of all the cores in
270 //                           the processor
271 //       NUMCORES -- number of cores chosen to deploy the application. It can
272 //                   be greater than that required to fully parallelize the
273 //                   application. The same as NUMCORES.
274 //       NUMCORESACTIVE -- number of cores that really execute the
275 //                         application. No greater than NUMCORES
276 //       NUMCORES4GC -- number of cores for gc. No greater than NUMCORES.
277 //                      NOTE: currently only support ontinuous cores as gc
278 //                            cores, i.e. 0~NUMCORES4GC-1
279 ////////////////////////////////////////////////////////////////////////////////
280 // data structures of status for termination
281 // only check working cores
282 volatile int corestatus[NUMCORESACTIVE]; // records status of each core
283                                          // 1: running tasks
284                                          // 0: stall
285 volatile int numsendobjs[NUMCORESACTIVE]; // records how many objects a core
286                                           // has sent out
287 volatile int numreceiveobjs[NUMCORESACTIVE]; // records how many objects a
288                                              // core has received
289 volatile int numconfirm;
290 volatile bool waitconfirm;
291 bool busystatus;
292 int self_numsendobjs;
293 int self_numreceiveobjs;
294
295 // TASK specific data structures
296 #ifdef TASK
297 // get rid of lock msgs for GC version
298 #ifndef MULTICORE_GC
299 // data structures for locking
300 struct RuntimeHash locktable;
301 static struct RuntimeHash* locktbl = &locktable;
302 struct RuntimeHash * lockRedirectTbl;
303 struct RuntimeHash * objRedirectLockTbl;
304 #endif // ifndef MULTICORE_GC
305 struct LockValue {
306   int redirectlock;
307   int value;
308 };
309 int lockobj;
310 int lock2require;
311 int lockresult;
312 bool lockflag;
313
314 // data structures for waiting objs
315 struct Queue objqueue;
316 struct Queue * totransobjqueue; // queue to hold objs to be transferred
317                                 // should be cleared whenever enter a task
318                                         
319 // for test TODO
320 int total_num_t6;
321
322 // data structures for profile mode
323 #ifdef PROFILE
324 #define TASKINFOLENGTH 3000 // 0
325 #ifdef PROFILE_INTERRUPT
326 #define INTERRUPTINFOLENGTH 50 //0
327 #endif // PROFILE_INTERRUPT
328
329 typedef struct task_info {
330   char* taskName;
331   unsigned long long startTime;
332   unsigned long long endTime;
333   unsigned long long exitIndex;
334   struct Queue * newObjs;
335 } TaskInfo;
336
337 TaskInfo * taskInfoArray[TASKINFOLENGTH];
338 int taskInfoIndex;
339 bool taskInfoOverflow;
340 #ifdef PROFILE_INTERRUPT
341 typedef struct interrupt_info {
342   unsigned long long startTime;
343   unsigned long long endTime;
344 } InterruptInfo;
345
346 InterruptInfo * interruptInfoArray[INTERRUPTINFOLENGTH];
347 int interruptInfoIndex;
348 bool interruptInfoOverflow;
349 #endif // PROFILE_INTERUPT
350 volatile int profilestatus[NUMCORESACTIVE]; // records status of each core
351                                             // 1: running tasks
352                                             // 0: stall
353 #endif // #ifdef PROFILE
354 #endif // TASK
355
356 #include "multicoremem.h"
357
358 /////////////////////////////////////////////////////////////
359
360 ////////////////////////////////////////////////////////////
361 // these are functions should be implemented in           //
362 // multicore runtime for any multicore processors         //
363 ////////////////////////////////////////////////////////////
364 #ifdef MULTICORE
365 INLINE void initialization(void);
366 INLINE void initCommunication(void);
367 INLINE void fakeExecution(void);
368 INLINE void terminate(void);
369 INLINE void initlock(struct ___Object___ * v);
370 #ifdef BAMBOO_MEMPROF
371 INLINE void terminatememprof(void);
372 #endif // BAMBOO_MEMPROF
373
374 // msg related functions
375 INLINE void send_hanging_msg(bool isInterrupt);
376 INLINE void send_msg_1(int targetcore,
377                        unsigned long n0,
378                                            bool isInterrupt);
379 INLINE void send_msg_2(int targetcore,
380                        unsigned long n0,
381                        unsigned long n1,
382                                            bool isInterrupt);
383 INLINE void send_msg_3(int targetcore,
384                        unsigned long n0,
385                        unsigned long n1,
386                        unsigned long n2,
387                                            bool isInterrupt);
388 INLINE void send_msg_4(int targetcore,
389                        unsigned long n0,
390                        unsigned long n1,
391                        unsigned long n2,
392                        unsigned long n3,
393                                            bool isInterrupt);
394 INLINE void send_msg_5(int targetcore,
395                        unsigned long n0,
396                        unsigned long n1,
397                        unsigned long n2,
398                        unsigned long n3,
399                        unsigned long n4,
400                                            bool isInterrupt);
401 INLINE void send_msg_6(int targetcore,
402                        unsigned long n0,
403                        unsigned long n1,
404                        unsigned long n2,
405                        unsigned long n3,
406                        unsigned long n4,
407                        unsigned long n5,
408                                            bool isInterrupt);
409 INLINE void cache_msg_1(int targetcore,
410                         unsigned long n0);
411 INLINE void cache_msg_2(int targetcore,
412                         unsigned long n0,
413                         unsigned long n1);
414 INLINE void cache_msg_3(int targetcore,
415                         unsigned long n0,
416                         unsigned long n1,
417                         unsigned long n2);
418 INLINE void cache_msg_4(int targetcore,
419                         unsigned long n0,
420                         unsigned long n1,
421                         unsigned long n2,
422                         unsigned long n3);
423 INLINE void cache_msg_5(int targetcore,
424                         unsigned long n0,
425                         unsigned long n1,
426                         unsigned long n2,
427                         unsigned long n3,
428                         unsigned long n4);
429 INLINE void cache_msg_6(int targetcore,
430                         unsigned long n0,
431                         unsigned long n1,
432                         unsigned long n2,
433                         unsigned long n3,
434                         unsigned long n4,
435                         unsigned long n5);
436 INLINE int receiveMsg(unsigned int send_port_pending);
437
438 #ifdef MULTICORE_GC
439 INLINE void transferMarkResults();
440 #endif // MULTICORE_GC
441
442 #ifdef TASK
443 // lock related functions
444 bool getreadlock(void* ptr);
445 void releasereadlock(void* ptr);
446 bool getwritelock(void* ptr);
447 void releasewritelock(void* ptr);
448 bool getwritelock_I(void* ptr);
449 void releasewritelock_I(void * ptr);
450 #ifndef MULTICORE_GC
451 void releasewritelock_r(void * lock, void * redirectlock);
452 #endif // ifndef MULTICORE_GC
453 /* this function is to process lock requests.
454  * can only be invoked in receiveObject() */
455 // if return -1: the lock request is redirected
456 //            0: the lock request is approved
457 //            1: the lock request is denied
458 INLINE int processlockrequest(int locktype,
459                               int lock,
460                               int obj,
461                               int requestcore,
462                               int rootrequestcore,
463                               bool cache);
464 INLINE void processlockrelease(int locktype,
465                                int lock,
466                                int redirectlock,
467                                bool redirect);
468
469 // msg related functions
470 INLINE void transferObject(struct transObjInfo * transObj);
471
472 #ifdef PROFILE
473 INLINE void profileTaskStart(char * taskname);
474 INLINE void profileTaskEnd(void);
475 void outputProfileData();
476 #endif  // #ifdef PROFILE
477 ///////////////////////////////////////////////////////////
478
479 /////////////////////////////////////////////////////////////////////////////
480 // For each version of BAMBOO runtime, there should be a header file named //
481 // runtim_arch.h defining following MARCOS:                                //
482 // BAMBOO_NUM_OF_CORE: the # of current residing core                      //
483 // BAMBOO_GET_NUM_OF_CORE(): compute the # of current residing core        //
484 // BAMBOO_COORDS(c, x, y): convert the cpu # to coords (*x, *y)            //
485 // BAMBOO_DEBUGPRINT(x): print out integer x                               //
486 // BAMBOO_DEBUGPRINT_REG(x): print out value of variable x                 //
487 // BAMBOO_EXIT_APP(x): exit the whole application                          //
488 // BAMBOO_EXIT(x): error exit routine with error #                         //
489 // BAMBOO_DIE(x): error exit routine with error msg                        //
490 // BAMBOO_GET_EXE_TIME(): rountine to get current clock cycle number       //
491 // BAMBOO_MSG_AVAIL(): checking if there are msgs coming in                //
492 // BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT(): change to runtime mode from    //
493 //                                          client mode                    //
494 // BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME(): change to client mode from     //
495 //                                          runtime mode                   //
496 // BAMBOO_ENTER_SEND_MODE_FROM_CLIENT(): change to send mode from          //
497 //                                       client mode                       //
498 // BAMBOO_ENTER_CLIENT_MODE_FROM_SEND(): change to client mode from        //
499 //                                       send mode                         //
500 // BAMBOO_ENTER_RUNTIME_MODE_FROM_SEND(): change to runtime mode from      //
501 //                                        send mode                        //
502 // BAMBOO_ENTER_SEND_MODE_FROM_RUNTIME(): change to send mode from         //
503 //                                        runtime mode                     //
504 // BAMBOO_WAITING_FOR_LOCK(): routine executed while waiting for lock      //
505 //                            request response                             //
506 // BAMBOO_LOCAL_MEM_CALLOC(x, y): allocate an array of x elements each of  //
507 //                                whose size in bytes is y on local memory //
508 //                                which is given by the hypervisor         //
509 // BAMBOO_LOCAL_MEM_FREE(x): free space with ptr x on local memory         //
510 // BAMBOO_LOCAL_MEM_CLOSE(): close the local heap                          //
511 // BAMBOO_LOCAL_MEM_CALLOC_S(x, y): allocate an array of x elements each of//
512 //                                  whose size in bytes is y on local      //
513 //                                  memory which is not from the hypervisor//
514 //                                  but is allocated from the free memory  //
515 // BAMBOO_LOCAL_MEM_FREE_S(x): free space with ptr x on self-allocated     //
516 //                             local memory                                //
517 // BAMBOO_LOCAL_MEM_CLOSE_S(): close the self-allocated local heap        //
518 // BAMBOO_SHARE_MEM_CALLOC_I(x, y): allocate an array of x elements each of//
519 //                                whose size in bytes is y on shared memory//
520 // BAMBOO_SHARE_MEM_CLOSE(): close the shared heap                         //
521 // BAMBOO_CACHE_LINE_SIZE: the cache line size                             //
522 // BAMBOO_CACHE_LINE_MASK: mask for a cache line                           //
523 // BAMBOO_CACHE_FLUSH_RANGE(x, y): flush cache lines started at x with     //
524 //                                 length y                                //
525 // BAMBOO_CACHE_FLUSH_ALL(): flush the whole cache of a core if necessary  //
526 // BAMBOO_MEMSET_WH(x, y, z): memset the specified region of memory (start //
527 //                            address x, size z) to value y with write     //
528 //                            hint, the processor will not fetch the       //
529 //                            current content of the memory and directly   //
530 //                            write                                        //
531 // BAMBOO_CLEAN_DTLB(): zero-out all the dtlb entries                      //
532 // BAMBOO_CACHE_FLUSH_L2(): Flush the contents of this tile's L2 back to   //
533 //                          main memory                                    //
534 // BAMBOO_CACHE_FLUSH_RANGE_NO_FENCE(x, y): flush a range of mem without   //
535 //                                          mem fence                      //
536 // BAMBOO_CACHE_MEM_FENCE_INCOHERENT(): fence to guarantee visibility of   //
537 //                                      stores to incoherent memory        //
538 /////////////////////////////////////////////////////////////////////////////
539
540 #endif  // #ifdef TASK
541 #endif  // #ifdef MULTICORE
542 #endif  // #ifndef MULTICORE_RUNTIME