"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

faclru.c

Go to the documentation of this file.
00001 /************************************************************************
00002 * Copyright (C) 1989, 1990, 1991, 1992, 1993                            *
00003 *                   Rabin A. Sugumar and Santosh G. Abraham             *
00004 *                                                                       *
00005 * This software is distributed absolutely without warranty. You are     *
00006 * free to use and modify the software as you wish.  You are also free   *
00007 * to distribute the software as long as it is not for commercial gain,  *
00008 * you retain the above copyright notice, and you make clear what your   *
00009 * modifications were.                                                   *
00010 *                                                                       *
00011 * Send comments and bug reports to rabin@eecs.umich.edu                 *
00012 *                                                                       *
00013 ************************************************************************/
00014 
00015 /* Algorithm for simulating fully associative caches of a fixed line    *
00016 *  size, and a range of sizes with LRU replacement.                     */
00017 
00018 
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 
00022 #include "../host.h"
00023 #include "../misc.h"
00024 #include "../machine.h"
00025 #include "util.h"
00026 #include "libcheetah.h"
00027 
00028 /* Macros */
00029 #define toggle(i) if(i==1)i=0;else{i=1;}
00030 #define min(a,b) ((a<b) ? a : b)
00031 
00032 #define ONE 1
00033 #define HASHNO 7211    /* number of slots in hash table */
00034 #define INPUT_BUFFER_SIZE 1000
00035 #define MAX_PHYSICAL_MEM 2097152  /* Physical mem available on machine */
00036 #define BYTES_PER_LINE 35  /* Storage requirement per line */
00037 
00038 static struct hash_table slot[HASHNO];  /* Hash table */
00039 static struct tree_node *root;          /* Root of splay tree */
00040 static struct tree_node **p_stack;      /* Stack used for tree operations */
00041 
00042 static unsigned *out_stack;             /* Stack depth hits array */
00043 
00044 #ifdef PERF
00045 double comp=0.0, no_splay_steps=0.0;
00046 #endif
00047 static unsigned tot_addrs,      /* Count of distinct line */
00048                 t_entries;      /* Count of addresses processed */
00049 static short size_exceeded=0;   /* Flag */
00050 
00051 
00052 extern int L,           /* Line size */
00053            T;           /* Max addresses processed */
00054 extern unsigned MAX_CACHE_SIZE; /* Maximum cache size of interest */
00055 extern unsigned MAX_LINES;      /* Calculated from max cache and line size */
00056 extern int MISS_RATIO_INTERVAL, /* Output interval */
00057            SAVE_INTERVAL, /* Intervals at which output should be saved */
00058            P_INTERVAL;  /* Intervals at which progress output is done */
00059 
00060 extern FILE *reportfile;
00061 
00062 static unsigned long next_save_time;
00063 
00064 
00065 /*
00066  * Output routine.
00067  *
00068  * Input: None
00069  * Output: None
00070  * Side effects: None
00071  */
00072 void
00073 outpr_faclru(FILE *fd)
00074 {
00075   int i;
00076   int stack_end;
00077   unsigned sum = 0;
00078 
00079   fprintf(fd, "Addresses processed : %d\n", t_entries);
00080   fprintf(fd, "Line size : %d bytes \n", (ONE << L));
00081   fprintf(fd, "Number of distinct lines  %d\n", tot_addrs); 
00082 #ifdef PERF
00083   fprintf(fd, "Number of Comparisons %lf\n", comp);
00084   fprintf(fd, "Number of balance steps %lf\n", no_splay_steps);
00085 #endif
00086   fprintf(fd, "Cache size (bytes)\tMiss Ratio\n");
00087   stack_end = min (tot_addrs, MAX_LINES);
00088    
00089   for (i = 1; i <= stack_end; i++)
00090     {
00091       sum += out_stack[i];
00092       if ((i % MISS_RATIO_INTERVAL) == 0)
00093         fprintf(fd, "%d\t\t\t%1.6f\n", (i * (ONE << L)),
00094                 (1.0 - ((double)sum/(double)t_entries)));
00095     }
00096   if ((unsigned)stack_end == tot_addrs)
00097     fprintf(fd, "Miss ratio is %f for all bigger caches\n",
00098             (1.0 - ((double)sum/(double)t_entries)));
00099   fprintf(fd, "\n");
00100 }
00101 
00102 
00103 /*
00104  * Deletes the last node in the stack from the tree.
00105  *
00106  * Input: None
00107  * Output: Deleted node
00108  * Side effects: Deletes last node from tree.
00109  */
00110 struct tree_node *
00111 delete_node(void)
00112 {
00113   struct tree_node *ptr, *free_ptr;
00114   static struct tree_node **delete_stack;
00115   static int top;
00116   static short first_time=1;
00117   static unsigned last_inum;
00118  
00119   if (first_time
00120       || top < 5
00121       || delete_stack[top]->inum != last_inum
00122       || delete_stack[top-1]->lft != delete_stack[top])
00123     {
00124       if (first_time)
00125         {
00126           first_time = 0;
00127           delete_stack = calloc(MAX_LINES, sizeof (struct tree_node *));
00128           if (!delete_stack)
00129             fatal("out of virtual memory");
00130         }
00131       top = -1;
00132       ptr = root;
00133       while (ptr->lft != NULL)
00134         {
00135           ++top;
00136           delete_stack [top] = ptr;
00137           ptr = ptr->lft;
00138         }
00139       delete_stack[top]->lft = ptr->rt;
00140       free_ptr = ptr;
00141 
00142       ptr = delete_stack[top]->lft;
00143       while (ptr)
00144         {
00145           ++top;
00146           delete_stack [top] = ptr;
00147           ptr = ptr->lft;
00148         }
00149       last_inum = delete_stack[top]->inum;
00150     }
00151   else
00152     {
00153       if (delete_stack[top]->lft != NULL)
00154         fprintf(stderr, "libcheetah: lft ptr of last entry not NULL\n");
00155 
00156       free_ptr = delete_stack[top];
00157       delete_stack[top-1]->lft = delete_stack[top]->rt;
00158       --top;
00159       ptr = delete_stack[top]->lft;
00160       while (ptr)
00161         {
00162           ++top;
00163           delete_stack [top] = ptr;
00164           ptr = ptr->lft;
00165         }
00166       last_inum = delete_stack[top]->inum;
00167     }
00168 
00169   return free_ptr;
00170 }
00171 
00172 
00173 /*
00174  * Lookup 'addr' in the hash table. Adds 'addr' to the hash table if it is
00175  * found. The hashing scheme is 'modulo a prime'. Collision resolution is
00176  * by chaining.
00177  *
00178  * Input: Address to be looked up
00179  * Output: Previous arrival time of address if found, zero if not.
00180  * Side effects: Adds the address to the hash table if it is not found.
00181  * Updates the previous time of arrival of address.
00182  */
00183 unsigned
00184 hash_lookup_add(md_addr_t addr)
00185 {
00186   int old_inum;         /* Scratch variables */
00187   int loc;
00188   struct hash_table *ptr, *oldptr;
00189 
00190   loc = addr % HASHNO;
00191   if (slot[loc].inum == 0)
00192     {
00193       ++tot_addrs;
00194       slot[loc].addr = addr;
00195       slot[loc].inum = t_entries;
00196       slot[loc].nxt = NULL;
00197       return 0;
00198     }
00199   else
00200     {
00201       ptr = &slot[loc];
00202       while (ptr)
00203         {
00204           oldptr = ptr;
00205           if (ptr->addr == addr)
00206             break;
00207           ptr = ptr->nxt;
00208         }
00209       if (ptr)
00210         {
00211           old_inum = ptr->inum;
00212           ptr->inum = t_entries;
00213           return old_inum;
00214         }
00215       else
00216         {
00217           ++tot_addrs;
00218           oldptr->nxt = calloc(1, sizeof(struct hash_table));
00219           if (!oldptr->nxt)
00220             fatal("out of virtual memory");
00221 
00222           oldptr->nxt->addr = addr;
00223           oldptr->nxt->nxt = NULL;
00224           oldptr->nxt->inum = t_entries;
00225           return 0;
00226         }
00227     }
00228 }
00229 
00230 
00231 /*
00232  * Deletes the input address from the hash table. The entry is freed
00233  * if possible.
00234  *
00235  * Input: Address to be deleted
00236  * Output : None
00237  * Side effects: Deletes address from the hash table
00238  */
00239 void
00240 hash_del(md_addr_t addr)
00241 {
00242   int loc;              /* Scratch variables */
00243   struct hash_table *ptr, *oldptr;
00244 
00245   loc = addr % HASHNO;
00246   if (slot[loc].inum == 0)
00247     {
00248       fprintf(stderr, "libcheetah: addr not found in hash_table\n");
00249     }
00250   else if (slot[loc].addr == addr)
00251     {
00252       if (slot[loc].nxt == NULL)
00253         slot[loc].inum = 0;
00254       else
00255         {
00256           slot[loc].addr = slot[loc].nxt->addr;
00257           slot[loc].inum = slot[loc].nxt->inum;
00258           ptr = slot[loc].nxt;
00259           slot[loc].nxt = slot[loc].nxt->nxt;
00260           free(ptr);
00261         }
00262     }
00263   else
00264     {
00265       ptr = &slot[loc];
00266       while (ptr)
00267         {
00268           if (ptr->addr == addr)
00269             break;
00270           oldptr = ptr;
00271           ptr = ptr->nxt;
00272         }
00273       if (ptr)
00274         {
00275           oldptr->nxt = ptr->nxt;
00276           free (ptr);
00277         }
00278       else
00279         fprintf (stderr, "libcheetah: addr not found in hash_table\n");
00280     }
00281 }
00282 
00283 
00284 /*
00285  * Looks up the key i_inum in the splay tree, deletes the node
00286  * and reinserts it at the top. Also splays the previous entry in the
00287  * stack to the root.
00288  *
00289  * Input: Key to be looked up (i_inum) and current address.
00290  * Output: None
00291  * Side effects: Updates tree as described above.
00292  */
00293 void
00294 ref_tree(unsigned i_inum, md_addr_t addr)
00295 {
00296   struct tree_node *ptr;
00297   int top, addr_above, pos, lstlft, at;
00298 
00299 #ifdef PERF
00300   comp += 1.0;
00301 #endif
00302 
00303   if (root->inum == i_inum)
00304     {
00305       ++out_stack[1];
00306       root->inum = t_entries;
00307     }
00308   else
00309     {
00310       top = addr_above = lstlft = 0;
00311       ptr = root;
00312       while (ptr)
00313         {
00314 #ifdef PERF
00315           comp += 1.0;
00316 #endif
00317           ++top;
00318           p_stack[top] = ptr;
00319           if (ptr->inum > i_inum)
00320             {
00321               addr_above += ptr->rtwt + 1;
00322               lstlft = top;
00323               ptr = ptr->lft;
00324             }
00325           else
00326             {
00327               if (ptr->inum == i_inum)
00328                 {
00329                   addr_above += ptr->rtwt;
00330                   ++out_stack[addr_above + 1];
00331                   pos = top;
00332                   if (ptr->addr != addr)
00333                     fprintf(stderr,
00334                             "libcheetah: inconsistency w/ inum & addr'\n");
00335                   ptr->rtwt -= 1;
00336                   ptr = ptr->rt;
00337                   while (ptr)
00338                     {
00339                       ++top;
00340                       p_stack[top] = ptr;
00341                       ptr = ptr->lft;
00342                     }
00343                   break;
00344                 }
00345               ptr->rtwt -= 1;
00346               ptr = ptr->rt;
00347             }
00348         }
00349 
00350       if (pos == top)
00351         {
00352           if (p_stack[top-1]->lft == p_stack[top])
00353             p_stack[top-1]->lft = p_stack[top]->lft;
00354           else
00355             p_stack[top-1]->rt = p_stack[top]->lft;
00356           at = lstlft;
00357         }
00358       else
00359         {
00360           if (p_stack[top-1]->lft == p_stack[top])
00361             p_stack[top-1]->lft = p_stack[top]->rt;
00362           else
00363             p_stack[top-1]->rt = p_stack[top]->rt;
00364 
00365           p_stack[pos]->addr = p_stack[top]->addr;
00366           p_stack[pos]->inum = p_stack[top]->inum;
00367           at = top-1;
00368         }
00369       while (at > 1)
00370         {
00371 #ifdef PERF
00372           no_splay_steps += 1.0;   /* Counts the number of basic operations */
00373 #endif
00374           splay(at, p_stack);
00375           at = at - 2;
00376         }
00377       root = p_stack[1];
00378 
00379       p_stack[top]->lft = root;
00380       p_stack[top]->rt = NULL;
00381       p_stack[top]->inum = t_entries;
00382       p_stack[top]->addr = addr;
00383       p_stack[top]->rtwt = 0;
00384       root = p_stack[top];
00385       /* traverse(root); */
00386     }
00387 }
00388 
00389 
00390 /*
00391  * Initialization routine. Creates a root for the splay tree
00392  * and allocates space for the arrays.
00393  *
00394  * Input: None
00395  * Output: None
00396  * Side effects: Creates a root for the tree. Adds address to the splay tree.
00397  */
00398 void
00399 init_faclru(void)
00400 {
00401   unsigned addr;
00402 
00403   next_save_time = SAVE_INTERVAL;
00404 
00405   /* Stack is not cut off precisely at MAX_LINES */
00406   out_stack = calloc((MAX_LINES+INPUT_BUFFER_SIZE), sizeof (unsigned));
00407   if (!out_stack)
00408     fatal("out of virtual memory");
00409 
00410   p_stack = calloc(MAX_LINES, sizeof (struct tree_node *));
00411   if (!p_stack)
00412     fatal("out of virtual memory");
00413 
00414   addr = 1;     /* Assumes that the first address is 1. */
00415   ++t_entries;  /* Kludge to avoid a warning in hash_del */
00416   hash_lookup_add(addr);
00417   t_entries = 0;
00418   tot_addrs = 0;/* Resets tot_addrs which is incremented in hash_lookup_add */
00419 
00420   root = calloc(1, sizeof(struct tree_node));
00421   if (!root)
00422     fatal("out of virtual memory");
00423 
00424   root->inum = t_entries;
00425   root->addr = addr;
00426   root->rtwt = 0;
00427   root->lft = root->rt = NULL;
00428 }
00429 
00430 
00431 /*
00432  * Main simulation routine. Reads in addresses from trace, does hash and
00433  * tree lookups as required.
00434  *
00435  * Input: None
00436  * Output: None
00437  * Side effects: Updates the tree and hash table and other globals as the
00438  * simulation progresses.
00439  */
00440 void
00441 ptc(md_addr_t addr)
00442 { 
00443   unsigned i_inum;              /* Key lookup */
00444   struct tree_node *nnode;      /* New tree node */
00445   
00446   if (tot_addrs > MAX_LINES)
00447     {
00448       if (size_exceeded == 0)
00449         {
00450           toggle (size_exceeded);
00451           fprintf(stderr, "libcheetah: distinct entries limit exceeded\n");
00452           fprintf(stderr, "libcheetah: addresses processed %d\n", t_entries);
00453         }
00454     }
00455 
00456   if (t_entries > next_save_time)
00457     {
00458       outpr_faclru(stderr);
00459       next_save_time += SAVE_INTERVAL;
00460     }
00461     
00462   ++t_entries;
00463   if ((t_entries % P_INTERVAL) == 0)
00464     fprintf(stderr, "libcheetah: addresses processed %d\n", t_entries);
00465     
00466   addr >>= L;
00467   if (size_exceeded == 0)
00468     {
00469       if ((i_inum = hash_lookup_add(addr)) != 0)
00470         ref_tree(i_inum, addr); 
00471       else
00472         {
00473           nnode = calloc(1, sizeof(struct tree_node));
00474           if (!nnode)
00475             fatal("out of virtual memory");
00476 
00477           nnode->inum = t_entries;
00478           nnode->addr = addr;
00479           nnode->lft = root;
00480           nnode->rt = NULL;
00481           nnode->rtwt = 0;
00482           root = nnode;
00483         }
00484     }
00485   else
00486     {
00487       if ((i_inum = hash_lookup_add(addr)) != 0)
00488         ref_tree(i_inum, addr);
00489       else
00490         {
00491           nnode = delete_node();
00492           hash_del(nnode->addr);
00493           nnode->inum = t_entries;
00494           nnode->addr = addr;
00495           nnode->lft = root;
00496           nnode->rt = NULL;
00497           nnode->rtwt = 0;
00498           root = nnode;
00499         }
00500     }
00501 }


UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214