📄 misc.c
字号:
/* * Invalidate cache contents. The operation affects the whole cache * or just 1 block, depending on m: * if m == NULL or m->size == 0, it affects the whole cache. * If prop is true, the same invalidate operation will be propagated * to other caches towards memory. * This function can be invoked directly by the subroutine-calling user, * or indirectly by passing a D4XINVAL access type to d4ref * (in which case d4ref passes prop == 1). * * NOTE: this does not copy back dirty stuff! * you have to call d4copyback first for that. */voidd4invalidate (d4cache *c, const d4memref *m, int prop){ int stacknum; d4stacknode *ptr; d4pendstack *newm; if (m != NULL) assert (m->accesstype == D4XINVAL); if (prop) { newm = d4get_mref(); if (m != NULL) newm->m = *m; else { newm->m.accesstype = D4XINVAL; newm->m.address = 0; newm->m.size = 0; /* affect the whole cache */ } newm->next = c->pending; c->pending = newm; } if (m != NULL && m->size > 0) { /* invalidate just one block */ d4addr blockaddr = D4ADDR2BLOCK (c, m->address); stacknum = D4ADDR2SET (c, m->address); ptr = d4_find (c, stacknum, blockaddr); if (ptr != NULL) d4_invblock (c, stacknum, ptr); if ((c->flags & D4F_CCC) != 0 && /* fully assoc cache */ (ptr = d4_find (c, c->numsets, blockaddr)) != NULL) d4_invblock (c, c->numsets, ptr); } else for (stacknum=0; stacknum < c->numsets + ((c->flags & D4F_CCC) != 0); stacknum++) { d4stacknode *top = c->stack[stacknum].top; assert (top->up->valid == 0); /* all invalid nodes are at bottom; at least 1 */ for (ptr = top; ptr->down != top; ptr = ptr->down) { if (ptr->valid == 0) break; d4_invblock (c, stacknum, ptr); } } if ((c->flags & D4F_CCC) != 0) d4_invinfcache (c, m); if ((newm = c->pending) != NULL) d4_dopending (c, newm);}/* * Handle invalidation for infinite cache */voidd4_invinfcache (d4cache *c, const d4memref *m){ int i; if (m == NULL || m->size == 0) { /* invalidate whole cache */ for (i = 0; i < c->nranges; i++) { assert (c->ranges[i].bitmap != NULL); free (c->ranges[i].bitmap); c->ranges[i].bitmap = NULL; } c->nranges = 0; c->maxranges = 0; } else { /* invalidate just one block */ const unsigned int sbsize = 1 << D4VAL (c, lg2subblocksize); const unsigned int baddr = D4ADDR2BLOCK (c, m->address); unsigned int bitoff; /* offset of bit in bitmap */ int hi, lo, nsb; bitoff = (baddr & (D4_BITMAP_RSIZE-1)) / sbsize; /* binary search for range containing our address */ hi = c->nranges-1; lo = 0; while (lo <= hi) { i = lo + (hi-lo)/2; if (c->ranges[i].addr + D4_BITMAP_RSIZE <= baddr) lo = i + 1; /* need to look higher */ else if (c->ranges[i].addr > baddr) hi = i - 1; /* need to look lower */ else { /* found the right range */ for (nsb = c->lg2blocksize - c->lg2subblocksize; nsb-- > 0; bitoff++) c->ranges[i].bitmap[bitoff/CHAR_BIT] &= ~(1<<(bitoff%CHAR_BIT)); break; } } }}/* * Create custom code for d4ref and some routines it calls. * For each cache, we output macro definitions to establish constant * alternatives for key fields within d4cache, rename customizable * functions, and output an #include "ref.c". * The expectation is that the user will compile this output file * and link it with the simulator. */voidd4customize (FILE *f){ d4cache *c; int i, n; fprintf (f, "#if !D4CUSTOM\n" "#error \"D4CUSTOM not set\"\n" "#endif\n" "#include \"ref.c\"\n\n"); /* get one-time stuff */ /* * define d4_custom[] and d4_ncustom, * which can be used to find the proper customized d4ref function * when the customized program is started up. */ if (d4_allcaches == NULL) { fprintf (stderr, "Dinero IV: d4customize called before d4new\n"); exit (9); } n = d4_allcaches->cacheid; for (i = 1; i <= n; i++) fprintf (f, "extern void d4_%dref (d4cache *, d4memref);\n", i); fprintf (f, "void (*d4_custom[])(d4cache *, d4memref) = {\n\t"); for (i = 1; i <= n; i++) fprintf (f, "d4_%dref%s", i, (i<n) ? ", " : ""); fprintf (f, "\n};\n"); fprintf (f, "int d4_ncustom = %d;\n", n); /* * Now Generate the customized stuff for each cache. * Only the policy functions provided with Dinero IV are * customized; user-supplied policy functions are unaltered. * If you add new policy functions to ref.c, you need to * add code here too! */ for (c = d4_allcaches; c != NULL; c = c->link) { int cid = c->cacheid; fprintf (f, "\n"); /* Define helper used by D4VAL macro */ fprintf (f, "#undef D4_CACHEID\n" "#define D4_CACHEID %d\n", cid); /* * Define a cache-specific macro * for the value of each field to be constantized, * and a "trigger" macro to allow its use in D4VAL. * In a few cases, we may #undef the trigger later * if we find we can't use it. */ fprintf (f, "#define D4_CACHE_%d_flags 0x%x\n" "#define D4_TRIGGER_%d_flags 1\n", cid, c->flags, cid); fprintf (f, "#define D4_CACHE_%d_lg2blocksize %d\n" "#define D4_TRIGGER_%d_lg2blocksize 1\n", cid, c->lg2blocksize, cid); fprintf (f, "#define D4_CACHE_%d_lg2subblocksize %d\n" "#define D4_TRIGGER_%d_lg2subblocksize 1\n", cid, c->lg2subblocksize, cid); fprintf (f, "#define D4_CACHE_%d_lg2size %d\n" "#define D4_TRIGGER_%d_lg2size 1\n", cid, c->lg2size, cid); fprintf (f, "#define D4_CACHE_%d_assoc %d\n" "#define D4_TRIGGER_%d_assoc 1\n", cid, c->assoc, cid); fprintf (f, "#define D4_CACHE_%d_numsets %d\n" "#define D4_TRIGGER_%d_numsets 1\n", cid, c->numsets, cid); fprintf (f, "#define D4_CACHE_%d_prefetch_abortpercent %d\n" "#define D4_TRIGGER_%d_prefetch_abortpercent 1\n", cid, c->prefetch_abortpercent, cid); fprintf (f, "#define D4_CACHE_%d_replacementf d4_%dreplacement\n" "#define D4_TRIGGER_%d_replacementf 1\n", cid, cid, cid); fprintf (f, "#define D4_CACHE_%d_prefetchf d4_%dprefetch\n" "#define D4_TRIGGER_%d_prefetchf 1\n", cid, cid, cid); fprintf (f, "#define D4_CACHE_%d_wallocf d4_%dwalloc\n" "#define D4_TRIGGER_%d_wallocf 1\n", cid, cid, cid); fprintf (f, "#define D4_CACHE_%d_wbackf d4_%dwback\n" "#define D4_TRIGGER_%d_wbackf 1\n", cid, cid, cid); /* define macro to activate CCC computations */ fprintf (f, "#define D4_OPTS_%d_ccc %d\n", cid, (c->flags & D4F_CCC) != 0); /* * For each policy function we recognize, * define a macro to activate it and * define the cache-specific policy name for it. * For policy functions we don't recognize, * turn off the trigger macro, so the call will * be treated in a non-customized manner, using the pointer * in the d4cache structure. */ if (c->replacementf == d4rep_lru) fprintf (f, "#define D4_OPTS_%d_rep_lru 1\n" "#define D4_POLICY_%d_rep 'l'\n" "#undef d4rep_lru\n" "#define d4rep_lru d4_%dreplacement\n", cid, cid, cid); else if (c->replacementf == d4rep_fifo) fprintf (f, "#define D4_OPTS_%d_rep_fifo 1\n" "#define D4_POLICY_%d_rep 'f'\n" "#undef d4rep_fifo\n" "#define d4rep_fifo d4_%dreplacement\n", cid, cid, cid); else if (c->replacementf == d4rep_random) fprintf (f, "#define D4_OPTS_%d_rep_random 1\n" "#define D4_POLICY_%d_rep 'r'\n" "#undef d4rep_random\n" "#define d4rep_random d4_%dreplacement\n", cid, cid, cid); else fprintf (f, "#undef D4_TRIGGER_%d_replacementf\n" "#define D4_TRIGGER_%d_replacementf 0\n" "#define D4_POLICY_%d_rep 0\n" "#define d4_%dreplacement D4_CACHE_bogus_replacementf\n", cid, cid, cid, cid); if (c->prefetchf != d4prefetch_none) fprintf (f, "#define D4_OPTS_%d_prefetch_none 0\n", cid); if (c->prefetchf == d4prefetch_none) fprintf (f, "#define D4_OPTS_%d_prefetch_none 1\n" "#define D4_POLICY_%d_pref 'n'\n" "#undef d4prefetch_none\n" "#define d4prefetch_none d4_%dprefetch\n", cid, cid, cid); else if (c->prefetchf == d4prefetch_always) fprintf (f, "#define D4_OPTS_%d_prefetch_always 1\n" "#define D4_POLICY_%d_pref 'a'\n" "#undef d4prefetch_always\n" "#define d4prefetch_always d4_%dprefetch\n", cid, cid, cid); else if (c->prefetchf == d4prefetch_loadforw) fprintf (f, "#define D4_OPTS_%d_prefetch_loadforw 1\n" "#define D4_POLICY_%d_pref 'l'\n" "#undef d4prefetch_loadforw\n" "#define d4prefetch_loadforw d4_%dprefetch\n", cid, cid, cid); else if (c->prefetchf == d4prefetch_subblock) fprintf (f, "#define D4_OPTS_%d_prefetch_subblock 1\n" "#define D4_POLICY_%d_pref 's'\n" "#undef d4prefetch_subblock\n" "#define d4prefetch_subblock d4_%dprefetch\n", cid, cid, cid); else if (c->prefetchf == d4prefetch_miss) fprintf (f, "#define D4_OPTS_%d_prefetch_miss 1\n" "#define D4_POLICY_%d_pref 'm'\n" "#undef d4prefetch_miss\n" "#define d4prefetch_miss d4_%dprefetch\n", cid, cid, cid); else if (c->prefetchf == d4prefetch_tagged) fprintf (f, "#define D4_OPTS_%d_prefetch_tagged 1\n" "#define D4_POLICY_%d_pref 't'\n" "#undef d4prefetch_tagged\n" "#define d4prefetch_tagged d4_%dprefetch\n", cid, cid, cid); else fprintf (f, "#undef D4_TRIGGER_%d_prefetchf\n" "#define D4_TRIGGER_%d_prefetchf 0\n" "#define D4_POLICY_%d_pref 0\n" "#define d4_%dprefetch D4_CACHE_bogus_prefetchf\n", cid, cid, cid, cid); if (c->wallocf == d4walloc_always) fprintf (f, "#define D4_OPTS_%d_walloc_always 1\n" "#define D4_POLICY_%d_walloc 'a'\n" "#undef d4walloc_always\n" "#define d4walloc_always d4_%dwalloc\n", cid, cid, cid); else if (c->wallocf == d4walloc_never) fprintf (f, "#define D4_OPTS_%d_walloc_never 1\n" "#define D4_POLICY_%d_walloc 'n'\n" "#undef d4walloc_never\n" "#define d4walloc_never d4_%dwalloc\n", cid, cid, cid); else if (c->wallocf == d4walloc_nofetch) fprintf (f, "#define D4_OPTS_%d_walloc_nofetch 1\n" "#define D4_POLICY_%d_walloc 'f'\n" "#undef d4walloc_nofetch\n" "#define d4walloc_nofetch d4_%dwalloc\n", cid, cid, cid); else fprintf (f, "#undef D4_TRIGGER_%d_wallocf\n" "#define D4_TRIGGER_%d_wallocf 0\n" "#define D4_POLICY_%d_walloc 0\n" "#define d4_%dwalloc D4_CACHE_bogus_wallocf\n", cid, cid, cid, cid); if (c->wbackf == d4wback_always) fprintf (f, "#define D4_OPTS_%d_wback_always 1\n" "#define D4_POLICY_%d_wback 'a'\n" "#undef d4wback_always\n" "#define d4wback_always d4_%dwback\n", cid, cid, cid); else if (c->wbackf == d4wback_never) fprintf (f, "#define D4_OPTS_%d_wback_never 1\n" "#define D4_POLICY_%d_wback 'n'\n" "#undef d4wback_never\n" "#define d4wback_never d4_%dwback\n", cid, cid, cid); else if (c->wbackf == d4wback_nofetch) fprintf (f, "#define D4_OPTS_%d_wback_nofetch 1\n" "#define D4_POLICY_%d_wback 'f'\n" "#undef d4wback_nofetch\n" "#define d4wback_nofetch d4_%dwback\n", cid, cid, cid); else fprintf (f, "#undef D4_TRIGGER_%d_wbackf\n" "#define D4_TRIGGER_%d_wbackf 0\n" "#define D4_POLICY_%d_wback 0\n" "#define d4_%dwback D4_CACHE_bogus_wbackf\n", cid, cid, cid, cid); /* * Other customized functions require special renaming */ fprintf (f, "#undef d4infcache\n"); if ((c->flags & D4F_CCC) != 0) fprintf (f, "#define d4infcache d4_%dinfcache\n", cid); else fprintf (f, "#define d4infcache(c,m) 0\n"); fprintf (f, "#undef d4_splitm\n"); fprintf (f, "#define d4_splitm d4_%dsplitm\n", cid); /* * Record the various customized values * for checking in d4setup. The order here is significant, * and must match the order in which things are checked * in d4setup. */ fprintf (f, "long d4_cust_%d_vals[] = {\n", cid); fprintf (f, " D4_CACHE_%d_flags,\n", cid); fprintf (f, " D4_CACHE_%d_lg2blocksize,\n", cid); fprintf (f, " D4_CACHE_%d_lg2subblocksize,\n", cid); fprintf (f, " D4_CACHE_%d_lg2size,\n", cid); fprintf (f, " D4_CACHE_%d_assoc,\n", cid); fprintf (f, " D4_CACHE_%d_prefetch_abortpercent,\n", cid); fprintf (f, " D4_POLICY_%d_rep,\n", cid); fprintf (f, " D4_POLICY_%d_pref,\n", cid); fprintf (f, " D4_POLICY_%d_walloc,\n", cid); fprintf (f, " D4_POLICY_%d_wback\n", cid); fprintf (f, "};\n"); /* * Now define the cache-specific name for d4ref * and include the real code */ fprintf (f, "#undef d4ref\n"); fprintf (f, "#define d4ref d4_%dref\n", cid); fprintf (f, "#include \"ref.c\"\n"); } /* * Now tie all the customized values up for checking in d4setup */ n = d4_allcaches->cacheid; fprintf (f, "\nlong *d4_cust_vals[%d+1] = {\n\tNULL,\n", n); for (i = 1; i <= n; i++) fprintf (f, " &d4_cust_%d_vals[0]%s\n", i, (i<n) ? "," : ""); fprintf (f, "};\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -