%* *
%************************************************************************
+Dummy definitions if we are not compiling for GrAnSim.
+
+\begin{code}
+#ifndef GRAN
+#define GRAN_ALLOC_HEAP(n,liveness) /* nothing */
+#define GRAN_UNALLOC_HEAP(n,liveness) /* nothing */
+#define GRAN_FETCH() /* nothing */
+#define GRAN_FETCH_AND_RESCHEDULE(liveness) /* nothing */
+#define GRAN_RESCHEDULE(liveness, reenter) /* nothing */
+#define GRAN_EXEC(arith,branch,loads,stores,floats) /* nothing */
+#define GRAN_SPARK() /* nothing */
+#endif
+\end{code}
+
+First the basic types specific to GrAnSim.
+
\begin{code}
-#ifdef GRAN
-
-# define IS_IDLE(proc) ((IdleProcs & PE_NUMBER((long)proc)) != 0l)
-# define ANY_IDLE (Idlers > 0)
-# define MAKE_IDLE(proc) do { if(!IS_IDLE(proc)) { ++Idlers; IdleProcs |= PE_NUMBER(proc); } } while(0)
-# define MAKE_BUSY(proc) do { if(IS_IDLE(proc)) { --Idlers; IdleProcs &= ~PE_NUMBER(proc); } } while(0)
-
-/* Event Types */
-# define STARTTHREAD 0 /* Start a newly created thread */
-# define CONTINUETHREAD 1 /* Continue running the first thread in the queue */
-# define RESUMETHREAD 2 /* Resume a previously running thread */
-# define MOVESPARK 3 /* Move a spark from one PE to another */
-# define MOVETHREAD 4 /* Move a thread from one PE to another */
-# define FINDWORK 5 /* Search for work */
-# define FETCHNODE 6 /* Fetch a node */
-# define FETCHREPLY 7 /* Receive a node */
-
-# define EVENT_PROC(evt) (evt->proc)
-# define EVENT_CREATOR(evt) (evt->creator)
-# define EVENT_TIME(evt) (evt->time)
-# define EVENT_TYPE(evt) (evt->evttype)
-# define EVENT_TSO(evt) (evt->tso)
-# define EVENT_NODE(evt) (evt->node)
-# define EVENT_SPARK(evt) (evt->spark)
-# define EVENT_NEXT(evt) (eventq)(evt->next)
-
-#endif /* GRAN */
+#if defined(GRAN)
+#define GRANSIMSTATS_BINARY RTSflags.GranFlags.granSimStats_Binary
+#elif defined(PAR)
+#define GRANSIMSTATS_BINARY RTSflags.ParFlags.granSimStats_Binary
+#endif
+
+#ifdef PAR
+ullong msTime(STG_NO_ARGS);
+# define CURRENT_TIME msTime()
+# define TIME_ON_PROC(p) msTime()
+
+# define CURRENT_PROC thisPE
+#endif
+
+#if defined(GRAN)
+
+#if !defined(COMPILING_GHC)
+#include "RtsFlags.h"
+#endif
+
+# define CURRENT_TIME CurrentTime[CurrentProc]
+# define TIME_ON_PROC(p) CurrentTime[p]
+# define CURRENT_PROC CurrentProc
+#endif
#if defined(GRAN) || defined(PAR)
+
+/* Granularity event types for output (see DumpGranEvent) */
+enum gran_event_types {
+ GR_START = 0, GR_STARTQ,
+ GR_STEALING, GR_STOLEN, GR_STOLENQ,
+ GR_FETCH, GR_REPLY, GR_BLOCK, GR_RESUME, GR_RESUMEQ,
+ GR_SCHEDULE, GR_DESCHEDULE,
+ GR_END,
+ SP_SPARK, SP_SPARKAT, SP_USED, SP_PRUNED, SP_EXPORTED, SP_ACQUIRED,
+ GR_ALLOC,
+ GR_TERMINATE,
+ GR_SYSTEM_START, GR_SYSTEM_END, /* only for debugging */
+ GR_EVENT_MAX
+};
+
+/* Prototypes of functions needed both in GRAN and PAR setup */
void DumpGranEvent PROTO((enum gran_event_types name, P_ tso));
-void DumpSparkGranEvent PROTO((enum gran_event_types name, W_ id));
-void DumpGranEventAndNode PROTO((enum gran_event_types name, P_ tso, P_ node, PROC proc));
-void DumpRawGranEvent PROTO((PROC pe, enum gran_event_types name, W_ id));
-void DumpGranInfo PROTO((PROC pe, P_ tso, rtsBool mandatory_thread));
+void DumpRawGranEvent PROTO((PROC proc, PROC p, enum gran_event_types name, P_ tso, P_ node, I_ len));
+void DumpStartEventAt PROTO((TIME time, PROC proc, PROC p, enum gran_event_types name,
+ P_ tso, P_ node, I_ len));
+void DumpGranInfo PROTO((PROC proc, P_ tso, rtsBool mandatory_thread));
+void DumpTSO PROTO((P_ tso));
+
void grterminate PROTO((TIME v));
+void grputw PROTO((TIME v));
+
+extern unsigned CurrentProc;
+ /* I have no idea what this is supposed to be in the PAR case WDP 96/03 */
+
+#endif /* GRAN || PAR */
+
+/* ---------- The rest of this file is GRAN only ---------- */
+
+#if defined(GRAN)
+rtsBool any_idle PROTO((STG_NO_ARGS));
+int idlers PROTO((STG_NO_ARGS));
+
+enum proc_status {
+ Idle = 0, /* empty threadq */
+ Sparking, /* non-empty sparkq; FINDWORK has been issued */
+ Starting, /* STARTTHREAD has been issue */
+ Fetching, /* waiting for remote data (only if block-on-fetch) */
+ Fishing, /* waiting for remote spark/thread */
+ Busy /* non-empty threadq, with head of queue active */
+};
+
+typedef struct event {
+ PROC proc; /* Processor id */
+ PROC creator; /* Processor id of PE that created the event */
+ EVTTYPE evttype; /* Event type */
+ TIME time; /* Time at which event happened */
+ P_ tso; /* Associated TSO, if relevant, Nil_closure otherwise*/
+ P_ node; /* Associated node, if relevant, Nil_closure otherwise*/
+ sparkq spark; /* Associated SPARK, if relevant, NULL otherwise */
+ I_ gc_info; /* Counter of heap objects to mark (used in GC only)*/
+ struct event *next;
+ } *eventq;
+
+#if (defined(GCap) || defined(GCgn))
+typedef struct clos /* a queue of ex-RBHs (needed for gen GC only) */
+{
+ struct clos *prev, *next;
+ P_ closure;
+} *closq;
+
+#define CLOS_CLOSURE(clos) (clos->closure)
+#define CLOS_PREV(clos) (clos->prev)
+#define CLOS_NEXT(clos) (clos->next)
+#endif
+
+/* Macros for accessing components of the event structure */
+#define EVENT_PROC(evt) (evt->proc)
+#define EVENT_CREATOR(evt) (evt->creator)
+#define EVENT_TIME(evt) (evt->time)
+#define EVENT_TYPE(evt) (evt->evttype)
+#define EVENT_TSO(evt) (evt->tso)
+#define EVENT_NODE(evt) (evt->node)
+#define EVENT_SPARK(evt) (evt->spark)
+#define EVENT_GC_INFO(evt) (evt->gc_info)
+#define EVENT_NEXT(evt) (eventq)(evt->next)
+
+/* Maximum number of PEs that can be simulated */
+#define MAX_PROC (BITS_IN(W_))
+
+/* Processor numbers to bitmasks and vice-versa */
+#define MainProc 0 /* Id of main processor */
+#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 IS_LOCAL_TO(ga,proc) ((1l << (long) proc) & ga)
+
+#define GRAN_TIME_SLICE 1000 /* max time between 2 ReSchedules */
+
+#if 1
+
+#define IS_IDLE(proc) (procStatus[proc] == Idle)
+#define IS_SPARKING(proc) (procStatus[proc] == Sparking)
+#define IS_STARTING(proc) (procStatus[proc] == Starting)
+#define IS_FETCHING(proc) (procStatus[proc] == Fetching)
+#define IS_FISHING(proc) (procStatus[proc] == Fishing)
+#define IS_BUSY(proc) (procStatus[proc] == Busy)
+#define ANY_IDLE (any_idle())
+#define MAKE_IDLE(proc) do { procStatus[proc] = Idle; } while(0)
+#define MAKE_SPARKING(proc) do { procStatus[proc] = Sparking; } while(0)
+#define MAKE_STARTING(proc) do { procStatus[proc] = Starting; } while(0)
+#define MAKE_FETCHING(proc) do { procStatus[proc] = Fetching; } while(0)
+#define MAKE_FISHING(proc) do { procStatus[proc] = Fishing; } while(0)
+#define MAKE_BUSY(proc) do { procStatus[proc] = Busy; } while(0)
+
+#else
+
+#define IS_IDLE(proc) ((IdleProcs & PE_NUMBER((long)proc)) != 0l)
+#define ANY_IDLE (Idlers > 0)
+#define MAKE_IDLE(proc) do { \
+ if (!IS_IDLE(proc)) { \
+ ++Idlers; \
+ IdleProcs |= PE_NUMBER(proc); \
+ procStatus[proc] = Idle; \
+ } \
+ } while(0)
+#define MAKE_BUSY(proc) do { \
+ if (IS_IDLE(proc)) { \
+ --Idlers; \
+ IdleProcs &= ~PE_NUMBER(proc); \
+ procStatus[proc] = Busy; \
+ } \
+ } while(0)
+#endif
+
+/* Number of last event type */
+#define MAX_EVENT 9
+
+/* Event Types (internal use only) */
+#define STARTTHREAD 0 /* Start a newly created thread */
+#define CONTINUETHREAD 1 /* Continue running the first thread in the queue */
+#define RESUMETHREAD 2 /* Resume a previously running thread */
+#define MOVESPARK 3 /* Move a spark from one PE to another */
+#define MOVETHREAD 4 /* Move a thread from one PE to another */
+#define FINDWORK 5 /* Search for work */
+#define FETCHNODE 6 /* Fetch a node */
+#define FETCHREPLY 7 /* Receive a node */
+#define GLOBALBLOCK 8 /* Block a TSO on a remote node */
+#define UNBLOCKTHREAD 9 /* Make a TSO runnable */
+
+#if defined(GRAN_CHECK)
+/* Prototypes of GrAnSim debugging functions */
+void G_PRINT_NODE(P_);
+void G_TREE(P_);
+void G_INFO_TABLE(P_);
+void G_CURR_THREADQ(I_);
+void G_THREADQ(P_, I_);
+void G_TSO(P_, I_);
+void G_EVENT(eventq, I_);
+void G_EVENTQ(I_);
+void G_PE_EQ(PROC, I_);
+void G_SPARK(sparkq, I_);
+void G_SPARKQ(sparkq, I_);
+void G_CURR_SPARKQ(I_);
+void G_PROC(I_, I_);
+void GP(I_);
+void GCP();
+void GT(P_);
+void GCT();
+void GEQ();
+void GTQ(PROC);
+void GCTQ();
+void GSQ(PROC);
+void GCSQ();
+void GN(P_);
+void GIT(P_);
+void pC(P_);
+void DN(P_);
+void DIT(P_);
+void DT(P_);
+/* void DS(P_); */
+#endif
+
+/* Interface to event queues */
+extern eventq EventHd; /* global event queue */
+extern char *event_names[];
+eventq get_next_event PROTO(());
+TIME get_time_of_next_event PROTO(());
+void newevent PROTO((PROC proc, PROC creator, TIME time, EVTTYPE
+ evttype, P_ tso, P_ node, sparkq spark));
+void prepend_event PROTO((eventq event));
+eventq grab_event PROTO((STG_NO_ARGS));
+void traverse_eventq_for_gc PROTO((STG_NO_ARGS));
+
+void print_event PROTO((eventq event));
+void print_eventq PROTO((eventq hd));
+void print_spark PROTO((sparkq spark));
+void print_sparkq PROTO((sparkq hd));
+
+/* void DumpPruneEvent PROTO((PROC proc, sparkq spark)); */
-# ifdef GRAN
I_ SaveSparkRoots PROTO((I_));
I_ SaveEventRoots PROTO((I_));
IF_RTS(int init_gr_simulation PROTO((int, char **, int, char **));)
IF_RTS(void end_gr_simulation(STG_NO_ARGS);)
-# endif
-# ifdef PAR
-ullong msTime(STG_NO_ARGS);
-# define CURRENT_TIME msTime()
+/* These constants are defaults for the RTS flags of GranSim */
-# define CURRENT_PROC thisPE
+/* Communication Cost Model (EDS-like), max_proc > 2. */
-# else /* GRAN */
+#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 CURRENT_TIME CurrentTime[CurrentProc]
-# define CURRENT_PROC CurrentProc
-# endif
+#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 */
+
+#define MAX_FISHES 1 /* max no. of outstanding spark steals */
+/* 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
+
+/* Miscellaneous Parameters */
+extern rtsBool DoFairSchedule;
+extern rtsBool DoReScheduleOnFetch;
+extern rtsBool SimplifiedFetch;
+extern rtsBool DoStealThreadsFirst;
+extern rtsBool DoAlwaysCreateThreads;
+extern rtsBool DoThreadMigration;
+extern rtsBool DoGUMMFetching;
+extern I_ FetchStrategy;
+extern rtsBool PreferSparksOfLocalNodes;
+extern rtsBool DoPrioritySparking, DoPriorityScheduling;
+extern I_ SparkPriority, SparkPriority2, ThunksToPack;
+/* These come from debug options -bD? */
+extern rtsBool NoForward;
+extern rtsBool PrintFetchMisses;
+
+extern TIME TimeOfNextEvent, EndOfTimeSlice; /* checked from the threaded world! */
+extern I_ avoidedCS; /* Unused!! ToDo: Remake libraries and nuke this var */
+extern rtsBool IgnoreEvents; /* HACK only for testing */
+
+#if defined(GRAN_CHECK)
+/* Variables for gathering misc statistics */
+extern I_ tot_low_pri_sparks;
+extern I_ rs_sp_count, rs_t_count, ntimes_total, fl_total, no_of_steals;
+extern I_ tot_packets, tot_packet_size, tot_cuts, tot_thunks,
+ tot_sq_len, tot_sq_probes, tot_sparks, withered_sparks,
+ tot_add_threads, tot_tq_len, non_end_add_threads;
+#endif
+
+extern I_ fetch_misses;
+#if defined(GRAN_COUNT)
+extern I_ nUPDs, nUPDs_old, nUPDs_new, nUPDs_BQ, nPAPs, BQ_lens;
+#endif
+
+extern FILE *gr_file;
+/* extern rtsBool no_gr_profile; */
+/* extern rtsBool do_sp_profile; */
+
+extern rtsBool NeedToReSchedule;
+
+void GranSimAllocate PROTO((I_ n, P_ node, W_ liveness));
+void GranSimUnAllocate PROTO((I_ n, P_ node, W_ liveness));
+I_ GranSimFetch PROTO((P_ node));
+void GranSimExec PROTO((W_ ariths, W_ branches, W_ loads, W_ stores, W_ floats));
+void GranSimSpark PROTO((W_ local, P_ node));
+void GranSimSparkAt PROTO((sparkq spark, P_ where, I_ identifier));
+void GranSimSparkAtAbs PROTO((sparkq spark, PROC proc, I_ identifier));
+void GranSimBlock PROTO((P_ tso, PROC proc, P_ node));
+void PerformReschedule PROTO((W_, rtsBool));
+
+#define GRAN_ALLOC_HEAP(n,liveness) \
+ GranSimAllocate_wrapper(n,0,0);
+
+#define GRAN_UNALLOC_HEAP(n,liveness) \
+ GranSimUnallocate_wrapper(n,0,0);
+
+#if 0
+
+#define GRAN_FETCH() \
+ GranSimFetch_wrapper(Node);
+
+#define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter) \
+ do { if(liveness_mask&LIVENESS_R1) \
+ SaveAllStgRegs(); \
+ GranSimFetch(Node); \
+ PerformReschedule(liveness_mask,reenter); \
+ RestoreAllStgRegs(); \
+ } while(0)
+
+#define GRAN_RESCHEDULE(liveness_mask,reenter) \
+ PerformReschedule_wrapper(liveness_mask,reenter)
+
+#else
+
+#define GRAN_FETCH() /*nothing */
+
+#define GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter) \
+ do { if(liveness_mask&LIVENESS_R1) \
+ SaveAllStgRegs(); \
+ GranSimFetch(Node); \
+ PerformReschedule(liveness_mask,reenter); \
+ RestoreAllStgRegs(); \
+ } while(0)
+
+#define GRAN_RESCHEDULE(liveness_mask,reenter) GRAN_FETCH_AND_RESCHEDULE(liveness_mask,reenter)
#endif
+
+#define THREAD_CONTEXT_SWITCH(liveness_mask,reenter) \
+ do { \
+ if (context_switch /* OR_INTERVAL_EXPIRED */) { \
+ GRAN_RESCHEDULE(liveness_mask,reenter); \
+ } }while(0)
+
+#if 0
+
+#define GRAN_EXEC(arith,branch,load,store,floats) \
+ GranSimExec_wrapper(arith,branch,load,store,floats);
+
+#else
+
+#define GRAN_EXEC(arith,branch,load,store,floats) \
+ { \
+ W_ cost = RTSflags.GranFlags.gran_arith_cost*arith + \
+ RTSflags.GranFlags.gran_branch_cost*branch + \
+ RTSflags.GranFlags.gran_load_cost*load + \
+ RTSflags.GranFlags.gran_store_cost*store + \
+ RTSflags.GranFlags.gran_float_cost*floats; \
+ TSO_EXECTIME(CurrentTSO) += cost; \
+ CurrentTime[CurrentProc] += cost; \
+ }
+
+#endif
+
+#define GRAN_YIELD(liveness) \
+ do { \
+ if ( (CurrentTime[CurrentProc]>=EndOfTimeSlice) || \
+ ((CurrentTime[CurrentProc]>=TimeOfNextEvent) && \
+ (TimeOfNextEvent!=0) && !IgnoreEvents )) { \
+ DO_GRAN_YIELD(liveness); \
+ } \
+ } while (0);
+
+#define ADD_TO_SPARK_QUEUE(spark) \
+ STGCALL1(void,(),add_to_spark_queue,spark) \
+
+#endif /* GRAN */
+
\end{code}