Reorganisation of the source tree
[ghc-hetmet.git] / includes / GranSim.h
diff --git a/includes/GranSim.h b/includes/GranSim.h
new file mode 100644 (file)
index 0000000..be5aa83
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+  Headers for GranSim specific objects.
+  
+  Note that in GranSim we have one run-queue and blocking-queue for each
+  processor. Therefore, this header file redefines variables like
+  run_queue_hd to be relative to CurrentProc. The main arrays of runnable
+  and blocking queues are defined in Schedule.c.  The important STG-called
+  GranSim macros (e.g. for fetching nodes) are at the end of this
+  file. Usually they are just wrappers to proper C functions in GranSim.c.  
+*/
+
+#ifndef GRANSIM_H
+#define GRANSIM_H
+
+#if !defined(GRAN)
+
+/* Dummy definitions for basic GranSim macros called from STG land */
+#define DO_GRAN_ALLOCATE(n)                              /* nothing */
+#define DO_GRAN_UNALLOCATE(n)                            /* nothing */
+#define DO_GRAN_FETCH(node)                              /* nothing */
+#define DO_GRAN_EXEC(arith,branch,load,store,floats)      /* nothing */
+#define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)  /* nothing */
+#define GRAN_RESCHEDULE(liveness_mask,reenter)           /* nothing */
+
+#endif
+
+#if defined(GRAN)  /* whole file */
+
+extern StgTSO *CurrentTSO;
+
+/*
+ * @node Headers for GranSim specific objects, , ,
+ * @section Headers for GranSim specific objects
+ *
+ * @menu
+ * * Externs and prototypes::  
+ * * Run and blocking queues:: 
+ * * Spark queues::            
+ * * Processor related stuff:: 
+ * * GranSim costs::           
+ * * STG called GranSim functions::  
+ * * STG-called routines::     
+ * @end menu
+ *
+ * @node Externs and prototypes, Run and blocking queues, Includes, Headers for GranSim specific objects
+ * @subsection Externs and prototypes
+ */
+
+/* Global constants */
+extern char *gran_event_names[];
+extern char *proc_status_names[];
+extern char *event_names[];
+
+/* Vars checked from within STG land */
+extern rtsBool  NeedToReSchedule, IgnoreEvents, IgnoreYields; 
+; 
+extern rtsTime  TimeOfNextEvent, TimeOfLastEvent, EndOfTimeSlice;
+
+/* costs for basic operations (copied from RTS flags) */
+extern nat gran_arith_cost, gran_branch_cost, gran_load_cost, gran_store_cost, gran_float_cost;
+
+extern nat SparksAvail;     /* How many sparks are available */
+extern nat SurplusThreads;  /* How many excess threads are there */
+extern nat sparksIgnored, sparksCreated;
+
+/*
+ * @node Run and blocking queues, Spark queues, Externs and prototypes, Headers for GranSim specific objects
+ * @subsection Run and blocking queues
+ */
+
+/* declared in Schedule.c */
+extern StgTSO *run_queue_hds[], *run_queue_tls[];
+extern StgTSO *blocked_queue_hds[], *blocked_queue_tls[];
+extern StgTSO *ccalling_threadss[];
+
+#define run_queue_hd         run_queue_hds[CurrentProc]
+#define run_queue_tl         run_queue_tls[CurrentProc]
+#define blocked_queue_hd     blocked_queue_hds[CurrentProc]
+#define blocked_queue_tl     blocked_queue_tls[CurrentProc]
+#define pending_sparks_hd    pending_sparks_hds[CurrentProc]
+#define pending_sparks_tl    pending_sparks_tls[CurrentProc]
+#define ccalling_threads     ccalling_threadss[CurrentProc]
+
+/*
+ * @node Spark queues, Processor related stuff, Run and blocking queues, Headers for GranSim specific objects
+ * @subsection Spark queues
+ */
+
+/*
+  In GranSim we use a double linked list to represent spark queues.
+  
+  This is more flexible, but slower, than the array of pointers
+  representation used in GUM. We use the flexibility to define new fields in
+  the rtsSpark structure, representing e.g. granularity info (see HWL's PhD
+  thesis), or info about the parent of a spark.
+*/
+
+/* Sparks and spark queues */
+typedef struct rtsSpark_
+{
+  StgClosure    *node;
+  nat            name, global;
+  nat            gran_info;      /* for granularity improvement mechanisms */
+  PEs            creator;        /* PE that created this spark (unused) */
+  struct rtsSpark_  *prev, *next;
+} rtsSpark;
+typedef rtsSpark *rtsSparkQ;
+
+/* The spark queues, proper */
+/* In GranSim this is a globally visible array of spark queues */
+extern rtsSparkQ pending_sparks_hds[];
+extern rtsSparkQ pending_sparks_tls[];
+
+/* Prototypes of those spark routines visible to compiler generated .hc */
+/* Routines only used inside the RTS are defined in rts/parallel GranSimRts.h */
+rtsSpark    *newSpark(StgClosure *node, 
+                     nat name, nat gran_info, nat size_info, 
+                     nat par_info, nat local);
+/* void         add_to_spark_queue(rtsSpark *spark); */
+
+/*
+ * @node Processor related stuff, GranSim costs, Spark queues, Headers for GranSim specific objects
+ * @subsection Processor related stuff
+ */
+
+extern PEs CurrentProc;
+extern rtsTime CurrentTime[];  
+
+/* Maximum number of PEs that can be simulated */
+#define MAX_PROC             32 /* (BITS_IN(StgWord))  */ /* ToDo: fix this!! */
+/*
+#if MAX_PROC==16 
+#else 
+#error MAX_PROC should be 32 on this architecture 
+#endif
+*/
+
+/* #define CurrentTSO           CurrentTSOs[CurrentProc] */
+
+/* Processor numbers to bitmasks and vice-versa */
+#define MainProc            0           /* Id of main processor */
+#define NO_PRI               0           /* dummy priority */
+#define MAX_PRI              10000       /* max possible priority */
+#define MAIN_PRI             MAX_PRI     /* priority of main thread */ 
+
+/* GrAnSim uses IdleProcs as bitmask to indicate which procs are idle */
+#define PE_NUMBER(n)          (1l << (long)n)
+#define ThisPE               PE_NUMBER(CurrentProc)
+#define MainPE               PE_NUMBER(MainProc)
+#define Everywhere           (~0l)
+#define Nowhere                      (0l)
+#define Now                   CurrentTime[CurrentProc]
+
+#define IS_LOCAL_TO(ga,proc)  ((1l << (PEs) proc) & ga)
+
+#define GRAN_TIME_SLICE       1000        /* max time between 2 ReSchedules */
+
+/*
+ * @node GranSim costs, STG called GranSim functions, Processor related stuff, Headers for GranSim specific objects
+ * @subsection GranSim costs
+ */
+
+/* Default constants for communication (see RtsFlags on how to change them) */
+
+#define LATENCY                           1000 /* Latency for single packet */
+#define ADDITIONAL_LATENCY         100 /* Latency for additional packets */
+#define BASICBLOCKTIME              10
+#define FETCHTIME              (LATENCY*2+MSGUNPACKTIME)
+#define LOCALUNBLOCKTIME            10
+#define GLOBALUNBLOCKTIME      (LATENCY+MSGUNPACKTIME)
+
+#define        MSGPACKTIME                  0  /* Cost of creating a packet */
+#define        MSGUNPACKTIME                0  /* Cost of receiving a packet */
+#define MSGTIDYTIME                  0  /* Cost of cleaning up after send */
+
+/* How much to increase GrAnSims internal packet size if an overflow 
+   occurs.
+   NB: This is a GrAnSim internal variable and is independent of the
+   simulated packet buffer size.
+*/
+
+#define GRANSIM_DEFAULT_PACK_BUFFER_SIZE     400
+#define REALLOC_SZ                           200
+
+/* extern W_ gran_mpacktime, gran_mtidytime, gran_munpacktime; */
+
+/* Thread cost model */
+#define THREADCREATETIME          (25+THREADSCHEDULETIME)
+#define THREADQUEUETIME                    12  /* Cost of adding a thread to the running/runnable queue */
+#define THREADDESCHEDULETIME       75  /* Cost of descheduling a thread */
+#define THREADSCHEDULETIME         75  /* Cost of scheduling a thread */
+#define THREADCONTEXTSWITCHTIME            (THREADDESCHEDULETIME+THREADSCHEDULETIME)
+
+/* Instruction Cost model (SPARC, including cache misses) */
+#define ARITH_COST                1
+#define BRANCH_COST               2
+#define LOAD_COST                 4
+#define STORE_COST                4
+#define FLOAT_COST                1 /* ? */
+
+#define HEAPALLOC_COST             11
+
+#define PRI_SPARK_OVERHEAD    5
+#define PRI_SCHED_OVERHEAD    5
+
+/*
+ * @node STG called GranSim functions, STG-called routines, GranSim costs, Headers for GranSim specific objects
+ * @subsection STG called GranSim functions
+ */
+
+/* STG called GranSim functions */
+void GranSimAllocate(StgInt n);
+void GranSimUnallocate(StgInt n);
+void GranSimExec(StgWord ariths, StgWord branches, StgWord loads, StgWord stores, StgWord floats);
+StgInt GranSimFetch(StgClosure *node);
+void GranSimSpark(StgInt local, StgClosure *node);
+void GranSimSparkAt(rtsSpark *spark, StgClosure *where,StgInt identifier);
+void GranSimSparkAtAbs(rtsSpark *spark, PEs proc, StgInt identifier);
+void GranSimBlock(StgTSO *tso, PEs proc, StgClosure *node);
+
+
+/*
+ * @node STG-called routines,  , STG called GranSim functions, Headers for GranSim specific objects
+ * @subsection STG-called routines
+ */
+
+/* Wrapped version of calls to GranSim-specific STG routines */
+
+/*
+#define DO_PERFORM_RESCHEDULE(liveness, always_reenter_node) PerformReschedule_wrapper(liveness, always_reenter_node)
+*/
+#define DO_GRAN_ALLOCATE(n)     STGCALL1(GranSimAllocate, n)
+#define DO_GRAN_UNALLOCATE(n)   STGCALL1(GranSimUnallocate, n)
+#define DO_GRAN_FETCH(node)     STGCALL1(GranSimFetch, node)
+#define DO_GRAN_EXEC(arith,branch,load,store,floats) GranSimExec(arith,branch,load,store,floats)
+
+/* 
+   ToDo: Clean up this mess of GRAN macros!!! -- HWL
+*/
+/* DO_GRAN_FETCH((StgClosure*)R1.p); */
+#define GRAN_FETCH()           /* nothing */
+
+#define GRAN_FETCH_AND_RESCHEDULE(liveness,reenter)    \
+          DO_GRAN_FETCH((StgClosure*)R1.p);                            \
+          DO_GRAN_YIELD(liveness,ENTRY_CODE((D_)(*R1.p))); 
+/* RESTORE_EVERYTHING is done implicitly before entering threaded world again */
+
+/*
+  This is the only macro currently enabled;
+  It should check whether it is time for the current thread to yield
+  (e.g. if there is a more recent event in the queue) and it should check
+  whether node is local, via a call to GranSimFetch.
+  ToDo: split this in 2 routines:
+         - GRAN_YIELD (as it is below)
+        - GRAN_FETCH (the rest of this macro)
+        emit only these 2 macros based on node's liveness
+         node alive: emit both macros
+         node not alive: do only a GRAN_YIELD
+         
+        replace gran_yield_? with gran_block_? (they really block the current
+       thread)
+*/
+#define GRAN_RESCHEDULE(liveness,ptrs)  \
+          if (RET_STGCALL1(StgInt, GranSimFetch, (StgClosure*)R1.p)) {\
+            EXTFUN_RTS(gran_block_##ptrs); \
+            JMP_(gran_block_##ptrs);       \
+          } else {                         \
+           if (TimeOfLastEvent < CurrentTime[CurrentProc] && \
+                HEAP_ALLOCED((StgClosure *)R1.p) && \
+                LOOKS_LIKE_GHC_INFO(get_itbl((StgClosure *)R1.p))) { \
+                                  EXTFUN_RTS(gran_yield_##ptrs); \
+                                  JMP_(gran_yield_##ptrs); \
+                } \
+            /* GRAN_YIELD(ptrs)  */             \
+         }
+
+
+/*                                                   YIELD(liveness,reenter) */
+
+/* GRAN_YIELD(liveness_mask); */
+
+/* GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter) */
+
+#define THREAD_CONTEXT_SWITCH(liveness_mask,reenter)   \
+        do { \
+       if (context_switch /* OR_INTERVAL_EXPIRED */) { \
+          GRAN_RESCHEDULE(liveness_mask,reenter); \
+        } }while(0)
+
+#define GRAN_EXEC(arith,branch,load,store,floats)       \
+        { \
+          W_ cost = gran_arith_cost*arith +   \
+                    gran_branch_cost*branch + \
+                    gran_load_cost*load +   \
+                    gran_store_cost*store +   \
+                    gran_float_cost*floats;   \
+          CurrentTSO->gran.exectime += cost;                      \
+          CurrentTime[CurrentProc] += cost;                      \
+        }
+
+/* In GranSim we first check whether there is an event to handle; only if
+   this is the case (or the time slice is over in case of fair scheduling)
+   we do a yield, which is very similar to that in the concurrent world 
+   ToDo: check whether gran_yield_? can be merged with other yielding codes
+*/
+
+#define DO_GRAN_YIELD(ptrs)    if (!IgnoreYields && \
+                                    TimeOfLastEvent < CurrentTime[CurrentProc] && \
+                                   HEAP_ALLOCED((StgClosure *)R1.p) && \
+                                    LOOKS_LIKE_GHC_INFO(get_itbl((StgClosure *)R1.p))) { \
+                                  EXTFUN_RTS(gran_yield_##ptrs); \
+                                  JMP_(gran_yield_##ptrs); \
+                                }
+
+#define GRAN_YIELD(ptrs)                                   \
+        {                                                   \
+          extern int context_switch;                          \
+          if ( (CurrentTime[CurrentProc]>=EndOfTimeSlice) ||   \
+               ((CurrentTime[CurrentProc]>=TimeOfNextEvent) && \
+               (TimeOfNextEvent!=0) && !IgnoreEvents )) {     \
+           /* context_switch = 1; */                          \
+            DO_GRAN_YIELD(ptrs);   \
+         }                                                    \
+       }
+
+#define ADD_TO_SPARK_QUEUE(spark)            \
+   STGCALL1(add_to_spark_queue,spark) \
+
+#endif /* GRAN */
+
+#endif /* GRANSIM_H */