/*********************************************************************** ** ** Note: compile with -lm ** Adapted for PARSEC on 11-97 by Mineo Takai ** ** Simulation of a Closed Queueing Network with FCFS servers ** ** This is a simulation of a closed network with N fully connected ** switches. Each switch is a tandem queue of Q fifo servers. ** A job that arrives at a queue is served sequentially (FCFS) ** by the Q servers and is thereafter routed to one of the ** N neighboring switches (including itself) with equal ** probability. ** ** Entities defined in the program: ** (1) driver: initiate the simulation ** (2) router: distributing jobs to N neighbors ** (3) queue: model the tandem queue ** ***********************************************************************/ #include #include #include #define MAXN 16 #define MAXNSRVR 20 #define N 16 #define NSRVR 5 #define NJOB 96 #define MAXCLOK 3000 #define MEAN 10 #define MAXTRIP 20 #define MAX(A, B) (A > B ? A : B) int expon(); int iurand(); message top_complete{}; message job { int id; int count; int t_wait; int t_serv; int dep; }; message add_to_your_sorc { ename id; }; message your_dests { ename ids[MAXN]; }; message your_dest { ename id; }; message start{}; message sorcs_over{}; entity router(ename, int, int, int); entity queue(ename, int, int, int); entity driver(int argc, char **argv) { ename q[MAXNSRVR + 1][MAXN]; int i, j; printf("CQNF Configuration simulated:\n"); printf(" Number of routers = %d\n", N); printf(" Number of servers/queue = %d\n", NSRVR); printf(" Initial no. of jobs/router = %d\n", NJOB); printf(" MAXCLOCK = %d\n", MAXCLOK); setmaxclock(MAXCLOK); if (NSRVR < 1 || N < 1){ printf("can't simulate less than 1 servers or switches\n"); return; } for (i = 0; i < N; i++) { for (j = 0; j < NSRVR; j++){ q[j][i]= new queue(self, MEAN, i * NSRVR + j, N) at i; add_source(q[j][i]); } q[NSRVR][i] = new router(self, i, NJOB, N) at i; add_source(q[NSRVR][i]); } for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { send add_to_your_sorc{q[NSRVR][j]} to q[0][i]; } send sorcs_over{} to q[0][i]; for (j = 0; j < NSRVR - 1; j++){ send add_to_your_sorc{q[j][i]} to q[j+1][i]; send sorcs_over{} to q[j+1][i]; } send add_to_your_sorc{q[NSRVR-1][i]} to q[NSRVR][i]; send your_dests{q[0]} to q[NSRVR][i]; for (j = 0; j < NSRVR; j++) send your_dest{q[j+1][i]} to q[j][i]; } for (i = 0; i < N; i++) { for (j = 0; j < NSRVR + 1; j++){ setlookahead(1, CLOCKTYPE_MAX); receive (top_complete top); } } hold(1); for (i = 0; i < N; i++) { for (j = 0; j < NSRVR + 1; j++) { send start{} to q[j][i]; } } } entity router(ename creator, int r_id, int njobs, int nswitches) { message job j1; int i; ename sourc; unsigned short seed[3]; ename qids[MAXN]; add_dest(creator); receive (add_to_your_sorc sorc) { sourc = sorc.id; } receive (your_dests dests) { for (i = 0; i < nswitches; i++) { qids[i] = dests.ids[i]; add_dest(qids[i]); } } add_source(sourc); send top_complete{} to creator; receive (start s); del_dest(creator); del_source(creator); seed[0] = r_id; seed[1] = r_id; seed[2] = r_id; for (i = 0; i < njobs; i++) { send job{r_id * njobs + i, 0, 0, 0, simclock()} to qids[i % nswitches]; } while (1) { receive (job j) { j1 = j; j1.count++; j1.dep = simclock(); send j1 to qids[iurand(r_id, nswitches, seed)]; } } } entity queue(ename creator, int mtime, int sseed, int nswitches) { ename rid; message job j1; unsigned short seed[3], over; int ntime, i, j; ename sourc[MAXN]; add_dest(creator); seed[0] = sseed; seed[1] = sseed; seed[2] = sseed; over = 0; i = 0; while (!over){ receive (add_to_your_sorc sorc) { sourc[i++] = sorc.id; } or receive (sorcs_over o){ over = 1; } } receive (your_dest dest) { rid = dest.id; } add_dest(rid); for (j = 0; j < i; j++) { add_source(sourc[j]); } send top_complete{} to creator; ntime = expon(mtime, seed); setlookahead(ntime, CLOCKTYPE_MAX); receive (start s); del_dest(creator); del_source(creator); setlookahead(ntime, CLOCKTYPE_MAX); for (;;) { receive (job j) { j1 = j; j1.t_wait += simclock() - j1.dep; j1.t_serv++; setlookahead(ntime, simclock() + ntime); hold(ntime); ntime = expon(mtime, seed); setlookahead(ntime, CLOCKTYPE_MAX); j1.dep = simclock(); send j1 to rid; } } } int iurand(int b, int t, unsigned short seed[3]) { long v = pc_nrand(seed); int ret; if (t > 0) { ret = (v % t + b) % t; return ret; } else { fprintf(stderr,"iurand: wrong range (%d -- %d)\n", b, t); return -1; } } int expon(int mean, unsigned short seed[3]) { return (int)(-log((double)(1.0 - pc_erand(seed))) * ((double) mean)) + 1; }