📄 sim-cache.c
字号:
/* * sim-cache.c - sample cache simulator implementation * * This file is a part of the SimpleScalar tool suite written by * Todd M. Austin as a part of the Multiscalar Research Project. * * The tool suite is currently maintained by Doug Burger and Todd M. Austin. * * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin * * This source file is distributed "as is" in the hope that it will be * useful. The tool set comes with no warranty, and no author or * distributor accepts any responsibility for the consequences of its * use. * * Everyone is granted permission to copy, modify and redistribute * this tool set under the following conditions: * * This source code is distributed for non-commercial use only. * Please contact the maintainer for restrictions applying to * commercial use. * * Permission is granted to anyone to make or distribute copies * of this source code, either as received or modified, in any * medium, provided that all copyright notices, permission and * nonwarranty notices are preserved, and that the distributor * grants the recipient permission for further redistribution as * permitted by this document. * * Permission is granted to distribute this file in compiled * or executable form under the same conditions that apply for * source code, provided that either: * * A. it is accompanied by the corresponding machine-readable * source code, * B. it is accompanied by a written offer, with no time limit, * to give anyone a machine-readable copy of the corresponding * source code in return for reimbursement of the cost of * distribution. This written offer must permit verbatim * duplication by anyone, or * C. it is distributed by someone who received only the * executable form, and is accompanied by a copy of the * written offer of source code that they received concurrently. * * In other words, you are welcome to use, share and improve this * source file. You are forbidden to forbid anyone else to use, share * and improve what you give them. * * INTERNET: dburger@cs.wisc.edu * US Mail: 1210 W. Dayton Street, Madison, WI 53706 * * $Id: sim-cache.c,v 1.6 1997/04/16 22:09:45 taustin Exp taustin $ * * $Log: sim-cache.c,v $ * Revision 1.6 1997/04/16 22:09:45 taustin * fixed "bad l2 D-cache parms" fatal string * * Revision 1.5 1997/03/11 01:27:08 taustin * updated copyright * `-pcstat' option support added * long/int tweaks made for ALPHA target support * better defaults defined for caches/TLBs * "mstate" command supported added for DLite! * supported added for non-GNU C compilers * * Revision 1.4 1997/01/06 16:03:07 taustin * comments updated * supported added for 2-level cache memory system * instruction TLB supported added * -icompress now compresses 64-bit instruction addresses to 32-bit equiv * main loop simplified * * Revision 1.3 1996/12/30 17:14:11 taustin * updated to support options and stats packages * * Revision 1.1 1996/12/05 18:52:32 taustin * Initial revision * * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <assert.h>#include "misc.h"#include "ss.h"#include "regs.h"#include "memory.h"#include "cache.h"#include "loader.h"#include "syscall.h"#include "dlite.h"#include "sim.h"/* * This file implements a functional cache simulator. Cache statistics are * generated for a user-selected cache and TLB configuration, which may include * up to two levels of instruction and data cache (with any levels unified), * and one level of instruction and data TLBs. No timing information is * generated (hence the distinction, "functional" simulator). *//* track number of insn and refs */static SS_COUNTER_TYPE sim_num_insn = 0;static SS_COUNTER_TYPE sim_num_refs = 0;/* level 1 instruction cache, entry level instruction cache */static struct cache *cache_il1 = NULL;/* level 1 instruction cache */static struct cache *cache_il2 = NULL;/* level 1 data cache, entry level data cache */static struct cache *cache_dl1 = NULL;/* level 2 data cache */static struct cache *cache_dl2 = NULL;/* instruction TLB */static struct cache *itlb = NULL;/* data TLB */static struct cache *dtlb = NULL;/* text-based stat profiles */#define MAX_PCSTAT_VARS 8static struct stat_stat_t *pcstat_stats[MAX_PCSTAT_VARS];static SS_COUNTER_TYPE pcstat_lastvals[MAX_PCSTAT_VARS];static struct stat_stat_t *pcstat_sdists[MAX_PCSTAT_VARS];/* wedge all stat values into a SS_COUNTER_TYPE */#define STATVAL(STAT) \ ((STAT)->sc == sc_int \ ? (SS_COUNTER_TYPE)*((STAT)->variant.for_int.var) \ : ((STAT)->sc == sc_uint \ ? (SS_COUNTER_TYPE)*((STAT)->variant.for_uint.var) \ : ((STAT)->sc == sc_counter \ ? *((STAT)->variant.for_counter.var) \ : (panic("bad stat class"), 0))))/* l1 data cache l1 block miss handler function */static unsigned int /* latency of block access */dl1_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ SS_ADDR_TYPE baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk *blk, /* ptr to block in upper level */ SS_TIME_TYPE now) /* time of access */{ if (cache_dl2) { /* access next level of data cache hierarchy */ return cache_access(cache_dl2, cmd, baddr, NULL, bsize, /* now */now, /* pudata */NULL, /* repl addr */NULL); } else { /* access main memory, which is always done in the main simulator loop */ return /* access latency, ignored */1; }}/* l2 data cache block miss handler function */static unsigned int /* latency of block access */dl2_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ SS_ADDR_TYPE baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk *blk, /* ptr to block in upper level */ SS_TIME_TYPE now) /* time of access */{ /* this is a miss to the lowest level, so access main memory, which is always done in the main simulator loop */ return /* access latency, ignored */1;}/* l1 inst cache l1 block miss handler function */static unsigned int /* latency of block access */il1_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ SS_ADDR_TYPE baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk *blk, /* ptr to block in upper level */ SS_TIME_TYPE now) /* time of access */{ if (cache_il2) { /* access next level of inst cache hierarchy */ return cache_access(cache_il2, cmd, baddr, NULL, bsize, /* now */now, /* pudata */NULL, /* repl addr */NULL); } else { /* access main memory, which is always done in the main simulator loop */ return /* access latency, ignored */1; }}/* l2 inst cache block miss handler function */static unsigned int /* latency of block access */il2_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ SS_ADDR_TYPE baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk *blk, /* ptr to block in upper level */ SS_TIME_TYPE now) /* time of access */{ /* this is a miss to the lowest level, so access main memory, which is always done in the main simulator loop */ return /* access latency, ignored */1;}/* inst cache block miss handler function */static unsigned int /* latency of block access */itlb_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ SS_ADDR_TYPE baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk *blk, /* ptr to block in upper level */ SS_TIME_TYPE now) /* time of access */{ SS_ADDR_TYPE *phy_page_ptr = (SS_ADDR_TYPE *)blk->user_data; /* no real memory access, however, should have user data space attached */ assert(phy_page_ptr); /* fake translation, for now... */ *phy_page_ptr = 0; return /* access latency, ignored */1;}/* data cache block miss handler function */static unsigned int /* latency of block access */dtlb_access_fn(enum mem_cmd cmd, /* access cmd, Read or Write */ SS_ADDR_TYPE baddr, /* block address to access */ int bsize, /* size of block to access */ struct cache_blk *blk, /* ptr to block in upper level */ SS_TIME_TYPE now) /* time of access */{ SS_ADDR_TYPE *phy_page_ptr = (SS_ADDR_TYPE *)blk->user_data; /* no real memory access, however, should have user data space attached */ assert(phy_page_ptr); /* fake translation, for now... */ *phy_page_ptr = 0; return /* access latency, ignored */1;}/* cache/TLB options */static char *cache_dl1_opt /* = "none" */;static char *cache_dl2_opt /* = "none" */;static char *cache_il1_opt /* = "none" */;static char *cache_il2_opt /* = "none" */;static char *itlb_opt /* = "none" */;static char *dtlb_opt /* = "none" */;static int flush_on_syscalls /* = FALSE */;static int compress_icache_addrs /* = FALSE */;/* text-based stat profiles */static int pcstat_nelt = 0;static char *pcstat_vars[MAX_PCSTAT_VARS];/* convert 64-bit inst text addresses to 32-bit inst equivalents */#define IACOMPRESS(A) \ (compress_icache_addrs ? ((((A) - SS_TEXT_BASE) >> 1) + SS_TEXT_BASE) : (A))#define ISCOMPRESS(SZ) \ (compress_icache_addrs ? ((SZ) >> 1) : (SZ))/* register simulator-specific options */voidsim_reg_options(struct opt_odb_t *odb) /* options database */{ opt_reg_header(odb, "sim-cache: This simulator implements a functional cache simulator. Cache\n""statistics are generated for a user-selected cache and TLB configuration,\n""which may include up to two levels of instruction and data cache (with any\n""levels unified), and one level of instruction and data TLBs. No timing\n""information is generated.\n" ); opt_reg_string(odb, "-cache:dl1", "l1 data cache config, i.e., {<config>|none}", &cache_dl1_opt, "dl1:256:32:1:l", /* print */TRUE, NULL); opt_reg_note(odb," The cache config parameter <config> has the following format:\n""\n"" <name>:<nsets>:<bsize>:<assoc>:<repl>\n""\n"" <name> - name of the cache being defined\n"" <nsets> - number of sets in the cache\n"" <bsize> - block size of the cache\n"" <assoc> - associativity of the cache\n"" <repl> - block replacement strategy, 'l'-LRU, 'f'-FIFO, 'r'-random\n""\n"" Examples: -cache:dl1 dl1:4096:32:1:l\n"" -dtlb dtlb:128:4096:32:r\n" ); opt_reg_string(odb, "-cache:dl2", "l2 data cache config, i.e., {<config>|none}", &cache_dl2_opt, "ul2:1024:64:4:l", /* print */TRUE, NULL); opt_reg_string(odb, "-cache:il1", "l1 inst cache config, i.e., {<config>|dl1|dl2|none}", &cache_il1_opt, "il1:256:32:1:l", /* print */TRUE, NULL); opt_reg_note(odb," Cache levels can be unified by pointing a level of the instruction cache\n"" hierarchy at the data cache hiearchy using the \"dl1\" and \"dl2\" cache\n"" configuration arguments. Most sensible combinations are supported, e.g.,\n""\n"" A unified l2 cache (il2 is pointed at dl2):\n"" -cache:il1 il1:128:64:1:l -cache:il2 dl2\n"" -cache:dl1 dl1:256:32:1:l -cache:dl2 ul2:1024:64:2:l\n""\n"" Or, a fully unified cache hierarchy (il1 pointed at dl1):\n"" -cache:il1 dl1\n"" -cache:dl1 ul1:256:32:1:l -cache:dl2 ul2:1024:64:2:l\n" ); opt_reg_string(odb, "-cache:il2", "l2 instruction cache config, i.e., {<config>|dl2|none}", &cache_il2_opt, "dl2", /* print */TRUE, NULL); opt_reg_string(odb, "-tlb:itlb", "instruction TLB config, i.e., {<config>|none}", &itlb_opt, "itlb:16:4096:4:l", /* print */TRUE, NULL); opt_reg_string(odb, "-tlb:dtlb", "data TLB config, i.e., {<config>|none}", &dtlb_opt, "dtlb:32:4096:4:l", /* print */TRUE, NULL); opt_reg_flag(odb, "-flush", "flush caches on system calls", &flush_on_syscalls, /* default */FALSE, /* print */TRUE, NULL); opt_reg_flag(odb, "-icompress", "convert 64-bit inst addresses to 32-bit inst equivalents", &compress_icache_addrs, /* default */FALSE, /* print */TRUE, NULL); opt_reg_string_list(odb, "-pcstat", "profile stat(s) against text addr's (mult uses ok)", pcstat_vars, MAX_PCSTAT_VARS, &pcstat_nelt, NULL, /* !print */FALSE, /* format */NULL, /* accrue */TRUE);}/* check simulator-specific option values */voidsim_check_options(struct opt_odb_t *odb, /* options database */ int argc, char **argv) /* command line arguments */{ char name[128], c; int nsets, bsize, assoc; /* use a level 1 D-cache? */ if (!mystricmp(cache_dl1_opt, "none")) { cache_dl1 = NULL; /* the level 2 D-cache cannot be defined */ if (strcmp(cache_dl2_opt, "none")) fatal("the l1 data cache must defined if the l2 cache is defined"); cache_dl2 = NULL; } else /* dl1 is defined */ { if (sscanf(cache_dl1_opt, "%[^:]:%d:%d:%d:%c", name, &nsets, &bsize, &assoc, &c) != 5) fatal("bad l1 D-cache parms: <name>:<nsets>:<bsize>:<assoc>:<repl>"); cache_dl1 = cache_create(name, nsets, bsize, /* balloc */FALSE, /* usize */0, assoc, cache_char2policy(c), dl1_access_fn, /* hit latency */1); /* is the level 2 D-cache defined? */ if (!mystricmp(cache_dl2_opt, "none")) cache_dl2 = NULL; else { if (sscanf(cache_dl2_opt, "%[^:]:%d:%d:%d:%c", name, &nsets, &bsize, &assoc, &c) != 5) fatal("bad l2 D-cache parms: " "<name>:<nsets>:<bsize>:<assoc>:<repl>"); cache_dl2 = cache_create(name, nsets, bsize, /* balloc */FALSE, /* usize */0, assoc, cache_char2policy(c), dl2_access_fn, /* hit latency */1); } } /* use a level 1 I-cache? */ if (!mystricmp(cache_il1_opt, "none")) { cache_il1 = NULL; /* the level 2 I-cache cannot be defined */ if (strcmp(cache_il2_opt, "none")) fatal("the l1 inst cache must defined if the l2 cache is defined"); cache_il2 = NULL; } else if (!mystricmp(cache_il1_opt, "dl1")) { if (!cache_dl1) fatal("I-cache l1 cannot access D-cache l1 as it's undefined"); cache_il1 = cache_dl1; /* the level 2 I-cache cannot be defined */ if (strcmp(cache_il2_opt, "none")) fatal("the l1 inst cache must defined if the l2 cache is defined"); cache_il2 = NULL; } else if (!mystricmp(cache_il1_opt, "dl2")) { if (!cache_dl2) fatal("I-cache l1 cannot access D-cache l2 as it's undefined"); cache_il1 = cache_dl2; /* the level 2 I-cache cannot be defined */ if (strcmp(cache_il2_opt, "none")) fatal("the l1 inst cache must defined if the l2 cache is defined"); cache_il2 = NULL; } else /* il1 is defined */ { if (sscanf(cache_il1_opt, "%[^:]:%d:%d:%d:%c", name, &nsets, &bsize, &assoc, &c) != 5) fatal("bad l1 I-cache parms: <name>:<nsets>:<bsize>:<assoc>:<repl>"); cache_il1 = cache_create(name, nsets, bsize, /* balloc */FALSE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -