[project @ 1996-07-25 20:43:49 by partain]
[ghc-hetmet.git] / ghc / includes / GranSim.lh
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section{Macros and global declarations for GranSim}
7 %*                                                                      *
8 %************************************************************************
9
10 Dummy definitions if we are not compiling for GrAnSim.
11
12 \begin{code}
13 #ifndef GRAN 
14 #define GRAN_ALLOC_HEAP(n,liveness)                     /* nothing */
15 #define GRAN_UNALLOC_HEAP(n,liveness)                   /* nothing */
16 #define GRAN_FETCH()                                    /* nothing */
17 #define GRAN_FETCH_AND_RESCHEDULE(liveness)             /* nothing */
18 #define GRAN_RESCHEDULE(liveness, reenter)              /* nothing */
19 #define GRAN_EXEC(arith,branch,loads,stores,floats)     /* nothing */
20 #define GRAN_SPARK()                                    /* nothing */
21 #endif
22 \end{code}
23
24 First the basic types specific to GrAnSim.
25
26 \begin{code}
27 #if defined(GRAN)
28 #define GRANSIMSTATS_BINARY   RTSflags.GranFlags.granSimStats_Binary
29 #elif defined(PAR)
30 #define GRANSIMSTATS_BINARY   RTSflags.ParFlags.granSimStats_Binary
31 #endif
32
33 #ifdef PAR
34 ullong msTime(STG_NO_ARGS);
35 #  define CURRENT_TIME msTime()
36 #  define TIME_ON_PROC(p) msTime()
37
38 #  define CURRENT_PROC thisPE
39 #endif
40
41 #if defined(GRAN)
42
43 #if !defined(COMPILING_GHC)
44 #include "RtsFlags.h"
45 #endif
46
47 #  define CURRENT_TIME CurrentTime[CurrentProc]
48 #  define TIME_ON_PROC(p) CurrentTime[p]
49 #  define CURRENT_PROC CurrentProc
50 #endif
51
52 #if defined(GRAN) || defined(PAR)
53
54 /* Granularity event types for output (see DumpGranEvent) */
55 enum gran_event_types {
56     GR_START = 0, GR_STARTQ, 
57     GR_STEALING, GR_STOLEN, GR_STOLENQ, 
58     GR_FETCH, GR_REPLY, GR_BLOCK, GR_RESUME, GR_RESUMEQ,
59     GR_SCHEDULE, GR_DESCHEDULE,
60     GR_END,
61     SP_SPARK, SP_SPARKAT, SP_USED, SP_PRUNED, SP_EXPORTED, SP_ACQUIRED,
62     GR_ALLOC,
63     GR_TERMINATE,
64     GR_SYSTEM_START, GR_SYSTEM_END,            /* only for debugging */
65     GR_EVENT_MAX
66 };
67
68 /* Prototypes of functions needed both in GRAN and PAR setup */
69 void DumpGranEvent PROTO((enum gran_event_types name, P_ tso));
70 void DumpRawGranEvent PROTO((PROC proc, PROC p, enum gran_event_types name, P_ tso, P_ node, I_ len));
71 void DumpStartEventAt PROTO((TIME time, PROC proc, PROC p, enum gran_event_types name,
72                              P_ tso, P_ node, I_ len));
73 void DumpGranInfo PROTO((PROC proc, P_ tso, rtsBool mandatory_thread));
74 void DumpTSO PROTO((P_ tso));
75
76 void grterminate PROTO((TIME v));
77 void grputw PROTO((TIME v));
78
79 extern unsigned CurrentProc;
80     /* I have no idea what this is supposed to be in the PAR case WDP 96/03 */
81
82 #endif  /* GRAN || PAR */
83
84 /* ----------  The rest of this file is GRAN only  ---------- */
85
86 #if defined(GRAN)
87 rtsBool any_idle PROTO((STG_NO_ARGS));
88 int     idlers   PROTO((STG_NO_ARGS));
89
90 enum proc_status {
91   Idle = 0,             /* empty threadq */
92   Sparking,             /* non-empty sparkq; FINDWORK has been issued */
93   Starting,             /* STARTTHREAD has been issue */
94   Fetching,             /* waiting for remote data (only if block-on-fetch) */
95   Fishing,              /* waiting for remote spark/thread */
96   Busy                  /* non-empty threadq, with head of queue active */
97 };
98
99 typedef struct event {
100   PROC proc;            /* Processor id */
101   PROC creator;         /* Processor id of PE that created the event */
102   EVTTYPE evttype;      /* Event type */
103   TIME time;            /* Time at which event happened */
104   P_ tso;               /* Associated TSO, if relevant, Nil_closure otherwise*/
105   P_ node;              /* Associated node, if relevant, Nil_closure otherwise*/
106   sparkq spark;         /* Associated SPARK, if relevant, NULL otherwise */
107   I_  gc_info;          /* Counter of heap objects to mark (used in GC only)*/
108   struct event *next;
109   } *eventq;
110
111 #if (defined(GCap) || defined(GCgn))
112 typedef struct clos      /* a queue of ex-RBHs (needed for gen GC only) */
113 {
114   struct clos *prev, *next;
115   P_ closure;
116 } *closq;
117
118 #define CLOS_CLOSURE(clos)  (clos->closure)
119 #define CLOS_PREV(clos)     (clos->prev)
120 #define CLOS_NEXT(clos)     (clos->next)
121 #endif
122
123 /* Macros for accessing components of the event structure */ 
124 #define EVENT_PROC(evt) (evt->proc)
125 #define EVENT_CREATOR(evt)      (evt->creator)
126 #define EVENT_TIME(evt) (evt->time)
127 #define EVENT_TYPE(evt) (evt->evttype)
128 #define EVENT_TSO(evt)  (evt->tso)
129 #define EVENT_NODE(evt) (evt->node)
130 #define EVENT_SPARK(evt)        (evt->spark)
131 #define EVENT_GC_INFO(evt) (evt->gc_info)
132 #define EVENT_NEXT(evt) (eventq)(evt->next)
133
134 /* Maximum number of PEs that can be simulated */
135 #define MAX_PROC (BITS_IN(W_))
136
137 /* Processor numbers to bitmasks and vice-versa */
138 #define MainProc             0           /* Id of main processor */
139 #define MAX_PRI              10000       /* max possible priority */
140 #define MAIN_PRI             MAX_PRI     /* priority of main thread */ 
141
142 /* GrAnSim uses IdleProcs as bitmask to indicate which procs are idle */
143 #define PE_NUMBER(n)          (1l << (long)n)
144 #define ThisPE                PE_NUMBER(CurrentProc)
145 #define MainPE                PE_NUMBER(MainProc)
146 #define Everywhere            (~0l)
147 #define Nowhere               (0l)
148
149 #define IS_LOCAL_TO(ga,proc)  ((1l << (long) proc) & ga)
150
151 #define GRAN_TIME_SLICE       1000        /* max time between 2 ReSchedules */
152
153 #if 1
154
155 #define IS_IDLE(proc)        (procStatus[proc] == Idle)
156 #define IS_SPARKING(proc)    (procStatus[proc] == Sparking)
157 #define IS_STARTING(proc)    (procStatus[proc] == Starting)
158 #define IS_FETCHING(proc)    (procStatus[proc] == Fetching)
159 #define IS_FISHING(proc)     (procStatus[proc] == Fishing)
160 #define IS_BUSY(proc)        (procStatus[proc] == Busy)    
161 #define ANY_IDLE             (any_idle())
162 #define MAKE_IDLE(proc)      do { procStatus[proc] = Idle; } while(0)
163 #define MAKE_SPARKING(proc)  do { procStatus[proc] = Sparking; } while(0)
164 #define MAKE_STARTING(proc)  do { procStatus[proc] = Starting; } while(0)
165 #define MAKE_FETCHING(proc)  do { procStatus[proc] = Fetching; } while(0)
166 #define MAKE_FISHING(proc)   do { procStatus[proc] = Fishing; } while(0)
167 #define MAKE_BUSY(proc)      do { procStatus[proc] = Busy; } while(0)
168
169 #else 
170
171 #define IS_IDLE(proc)   ((IdleProcs & PE_NUMBER((long)proc)) != 0l)
172 #define ANY_IDLE        (Idlers > 0)
173 #define MAKE_IDLE(proc) do { \
174                           if (!IS_IDLE(proc)) { \
175                             ++Idlers; \
176                             IdleProcs |= PE_NUMBER(proc); \
177                             procStatus[proc] = Idle; \
178                           } \
179                         } while(0)
180 #define MAKE_BUSY(proc) do { \
181                           if (IS_IDLE(proc)) { \
182                             --Idlers; \
183                             IdleProcs &= ~PE_NUMBER(proc); \
184                             procStatus[proc] = Busy; \
185                           } \
186                         } while(0)
187 #endif
188
189 /* Number of last event type */
190 #define MAX_EVENT       9
191  
192 /* Event Types (internal use only) */
193 #define STARTTHREAD     0     /* Start a newly created thread */
194 #define CONTINUETHREAD  1     /* Continue running the first thread in the queue */
195 #define RESUMETHREAD    2     /* Resume a previously running thread */
196 #define MOVESPARK       3     /* Move a spark from one PE to another */
197 #define MOVETHREAD      4     /* Move a thread from one PE to another */
198 #define FINDWORK        5     /* Search for work */
199 #define FETCHNODE       6     /* Fetch a node */
200 #define FETCHREPLY      7     /* Receive a node */
201 #define GLOBALBLOCK     8     /* Block a TSO on a remote node */
202 #define UNBLOCKTHREAD   9     /* Make a TSO runnable */
203
204 #if defined(GRAN_CHECK)
205 /* Prototypes of GrAnSim debugging functions */
206 void G_PRINT_NODE(P_);
207 void G_TREE(P_); 
208 void G_INFO_TABLE(P_);
209 void G_CURR_THREADQ(I_);
210 void G_THREADQ(P_, I_);
211 void G_TSO(P_, I_);
212 void G_EVENT(eventq, I_);
213 void G_EVENTQ(I_);
214 void G_PE_EQ(PROC, I_);
215 void G_SPARK(sparkq, I_);
216 void G_SPARKQ(sparkq, I_);
217 void G_CURR_SPARKQ(I_);
218 void G_PROC(I_, I_);
219 void GP(I_);
220 void GCP();
221 void GT(P_);
222 void GCT();
223 void GEQ();
224 void GTQ(PROC);
225 void GCTQ();
226 void GSQ(PROC);
227 void GCSQ();
228 void GN(P_);
229 void GIT(P_);
230 void pC(P_);
231 void DN(P_);
232 void DIT(P_);
233 void DT(P_);
234 /* void DS(P_); */
235 #endif
236
237 /* Interface to event queues */
238 extern eventq EventHd;             /* global event queue */
239 extern char *event_names[];
240 eventq get_next_event PROTO(());
241 TIME get_time_of_next_event PROTO(());
242 void newevent PROTO((PROC proc, PROC creator, TIME time, EVTTYPE
243                             evttype, P_ tso, P_ node, sparkq spark));
244 void prepend_event PROTO((eventq event));
245 eventq grab_event PROTO((STG_NO_ARGS));
246 void traverse_eventq_for_gc PROTO((STG_NO_ARGS));
247
248 void print_event PROTO((eventq event));
249 void print_eventq PROTO((eventq hd));
250 void print_spark PROTO((sparkq spark));
251 void print_sparkq PROTO((sparkq hd));
252
253 /* void DumpPruneEvent PROTO((PROC proc, sparkq spark)); */
254
255 I_ SaveSparkRoots PROTO((I_));
256 I_ SaveEventRoots PROTO((I_));
257
258 I_ RestoreSparkRoots PROTO((I_));
259 I_ RestoreEventRoots PROTO((I_));
260
261 IF_RTS(int init_gr_simulation PROTO((int, char **, int, char **));)
262 IF_RTS(void end_gr_simulation(STG_NO_ARGS);)
263
264 /* These constants are defaults for the RTS flags of GranSim */
265
266 /* Communication Cost Model (EDS-like), max_proc > 2. */
267
268 #define LATENCY                    1000 /* Latency for single packet */
269 #define ADDITIONAL_LATENCY          100 /* Latency for additional packets */
270 #define BASICBLOCKTIME               10
271 #define FETCHTIME               (LATENCY*2+MSGUNPACKTIME)
272 #define LOCALUNBLOCKTIME             10
273 #define GLOBALUNBLOCKTIME       (LATENCY+MSGUNPACKTIME)
274
275 #define MSGPACKTIME                  0  /* Cost of creating a packet */
276 #define MSGUNPACKTIME                0  /* Cost of receiving a packet */
277 #define MSGTIDYTIME                  0  /* Cost of cleaning up after send */
278
279 #define MAX_FISHES                   1  /* max no. of outstanding spark steals */
280 /* How much to increase GrAnSims internal packet size if an overflow 
281    occurs.
282    NB: This is a GrAnSim internal variable and is independent of the
283    simulated packet buffer size.
284 */
285
286 #define GRANSIM_DEFAULT_PACK_BUFFER_SIZE     400
287 #define REALLOC_SZ                           200
288
289 /* extern W_ gran_mpacktime, gran_mtidytime, gran_munpacktime; */
290
291 /* Thread cost model */
292 #define THREADCREATETIME           (25+THREADSCHEDULETIME)
293 #define THREADQUEUETIME             12  /* Cost of adding a thread to the running/runnable queue */
294 #define THREADDESCHEDULETIME        75  /* Cost of descheduling a thread */
295 #define THREADSCHEDULETIME          75  /* Cost of scheduling a thread */
296 #define THREADCONTEXTSWITCHTIME     (THREADDESCHEDULETIME+THREADSCHEDULETIME)
297
298 /* Instruction Cost model (SPARC, including cache misses) */
299 #define ARITH_COST                 1
300 #define BRANCH_COST                2
301 #define LOAD_COST                  4
302 #define STORE_COST                 4
303 #define FLOAT_COST                 1 /* ? */
304
305 #define HEAPALLOC_COST             11
306
307 #define PRI_SPARK_OVERHEAD    5
308 #define PRI_SCHED_OVERHEAD    5
309
310 /* Miscellaneous Parameters */
311 extern rtsBool DoFairSchedule;
312 extern rtsBool DoReScheduleOnFetch;
313 extern rtsBool SimplifiedFetch;
314 extern rtsBool DoStealThreadsFirst;
315 extern rtsBool DoAlwaysCreateThreads;
316 extern rtsBool DoThreadMigration;
317 extern rtsBool DoGUMMFetching;
318 extern I_ FetchStrategy;
319 extern rtsBool PreferSparksOfLocalNodes;
320 extern rtsBool DoPrioritySparking, DoPriorityScheduling;
321 extern I_ SparkPriority, SparkPriority2, ThunksToPack;
322 /* These come from debug options -bD? */
323 extern rtsBool NoForward;
324 extern rtsBool PrintFetchMisses;
325
326 extern TIME TimeOfNextEvent, EndOfTimeSlice; /* checked from the threaded world! */
327 extern I_ avoidedCS; /* Unused!! ToDo: Remake libraries and nuke this var */
328 extern rtsBool IgnoreEvents; /* HACK only for testing */
329
330 #if defined(GRAN_CHECK)
331 /* Variables for gathering misc statistics */
332 extern I_ tot_low_pri_sparks;
333 extern I_ rs_sp_count, rs_t_count, ntimes_total, fl_total, no_of_steals;
334 extern I_ tot_packets, tot_packet_size, tot_cuts, tot_thunks,
335           tot_sq_len, tot_sq_probes,  tot_sparks, withered_sparks,
336           tot_add_threads, tot_tq_len, non_end_add_threads;
337 #endif 
338
339 extern I_ fetch_misses;
340 #if defined(GRAN_COUNT)
341 extern I_ nUPDs, nUPDs_old, nUPDs_new, nUPDs_BQ, nPAPs, BQ_lens;
342 #endif
343
344 extern FILE *gr_file;
345 /* extern rtsBool no_gr_profile; */
346 /* extern rtsBool do_sp_profile; */ 
347
348 extern rtsBool NeedToReSchedule;
349
350 void GranSimAllocate                PROTO((I_ n, P_ node, W_ liveness));
351 void GranSimUnAllocate              PROTO((I_ n, P_ node, W_ liveness));
352 I_   GranSimFetch                   PROTO((P_ node));
353 void GranSimExec                    PROTO((W_ ariths, W_ branches, W_ loads, W_ stores, W_ floats));
354 void GranSimSpark                   PROTO((W_ local, P_ node));
355 void GranSimSparkAt                 PROTO((sparkq spark, P_ where, I_ identifier));
356 void GranSimSparkAtAbs              PROTO((sparkq spark, PROC proc, I_ identifier));
357 void GranSimBlock                   PROTO((P_ tso, PROC proc, P_ node));
358 void PerformReschedule              PROTO((W_, rtsBool));
359
360 #define GRAN_ALLOC_HEAP(n,liveness)        \
361         GranSimAllocate_wrapper(n,0,0);
362
363 #define GRAN_UNALLOC_HEAP(n,liveness)      \
364         GranSimUnallocate_wrapper(n,0,0);
365
366 #if 0 
367
368 #define GRAN_FETCH()                       \
369         GranSimFetch_wrapper(Node);
370
371 #define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)        \
372         do { if(liveness_mask&LIVENESS_R1)                      \
373              SaveAllStgRegs();                                  \
374              GranSimFetch(Node);                                \
375              PerformReschedule(liveness_mask,reenter);          \
376              RestoreAllStgRegs();                               \
377            } while(0)
378
379 #define GRAN_RESCHEDULE(liveness_mask,reenter)  \
380         PerformReschedule_wrapper(liveness_mask,reenter)
381
382 #else
383
384 #define GRAN_FETCH()                       /*nothing */
385
386 #define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)        \
387         do { if(liveness_mask&LIVENESS_R1)                      \
388              SaveAllStgRegs();                                  \
389              GranSimFetch(Node);                                \
390              PerformReschedule(liveness_mask,reenter);          \
391              RestoreAllStgRegs();                               \
392            } while(0)
393
394 #define GRAN_RESCHEDULE(liveness_mask,reenter)   GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)
395
396 #endif
397
398 #define THREAD_CONTEXT_SWITCH(liveness_mask,reenter)    \
399         do { \
400         if (context_switch /* OR_INTERVAL_EXPIRED */) { \
401           GRAN_RESCHEDULE(liveness_mask,reenter); \
402         } }while(0)
403
404 #if 0
405
406 #define GRAN_EXEC(arith,branch,load,store,floats)       \
407         GranSimExec_wrapper(arith,branch,load,store,floats);
408
409 #else
410
411 #define GRAN_EXEC(arith,branch,load,store,floats)       \
412         { \
413           W_ cost = RTSflags.GranFlags.gran_arith_cost*arith +   \
414                     RTSflags.GranFlags.gran_branch_cost*branch + \
415                     RTSflags.GranFlags.gran_load_cost*load +   \
416                     RTSflags.GranFlags.gran_store_cost*store +   \
417                     RTSflags.GranFlags.gran_float_cost*floats;   \
418           TSO_EXECTIME(CurrentTSO) += cost;                      \
419           CurrentTime[CurrentProc] += cost;                      \
420         }
421
422 #endif
423                
424 #define GRAN_YIELD(liveness)                                   \
425         do {                                                   \
426           if ( (CurrentTime[CurrentProc]>=EndOfTimeSlice) ||   \
427                ((CurrentTime[CurrentProc]>=TimeOfNextEvent) && \
428                 (TimeOfNextEvent!=0) && !IgnoreEvents )) {     \
429             DO_GRAN_YIELD(liveness);                           \
430           }                                                    \
431         } while (0);
432
433 #define ADD_TO_SPARK_QUEUE(spark)             \
434    STGCALL1(void,(),add_to_spark_queue,spark) \
435
436 #endif  /* GRAN */
437         
438 \end{code}