⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sim-mpcache.c

📁 体系机构仿真
💻 C
字号:
/* * sim-mpcache.c - front end for multiprocessor cache simulator * * This file is an adaptation of the software in the SimpleScalar tool suite * originally written by Todd M. Austin for the Multiscalar Research Project * at the University of Wisconsin-Madison. * * The modifications were made by Naraig Manjikian at Queen's University, * Kingston, Ontario, Canada. * * The remainder of this header comment is unchanged from the original text. * *.......................................................................... * * 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-fast.c,v 1.4 1997/03/11 01:28:36 taustin Exp taustin $ * * $Log: sim-fast.c,v $ * Revision 1.4  1997/03/11  01:28:36  taustin * updated copyright * simulation now fails when DLite! support requested * long/int tweaks made for ALPHA target support * supported added for non-GNU C compilers * * Revision 1.3  1997/01/06  16:04:21  taustin * comments updated * SPARC-specific compilation supported deleted (most opts now generalized) * new stats and options package support added * NO_INSN_COUNT added for conditional instruction count support * USE_JUMP_TABLE added to support simple and complex main loops * * Revision 1.1  1996/12/05  18:52:32  taustin * Initial revision * * */#include <stdio.h>#include <stdlib.h>#include <math.h>#include <sys/time.h>#include <sys/resource.h>#include "misc.h"#include "ss.h"#include "regs.h"/* the following is some macro magic needed to register allocate the   pointer to the level one memory page map table *//* the level 1 page table map */#define mem_table local_mem_table#define HIDE_MEM_TABLE_DEF#include "memory.h"#undef HIDE_MEM_TABLE_DEF#undef mem_tableextern char *mem_table[MEM_TABLE_SIZE];#define mem_table local_mem_table#include "loader.h"#include "syscall.h"#include "sim.h"#include "mpcache.h"/* we count instructions executed by each process, and also the   number of cycles from beginning to end (note that processes may   not be in existence or active during part of the total number of   cycles) */unsigned int	sim_num_instructions[MAX_PROCS];unsigned int	sim_num_cycles = 0;extern	int	active[MAX_PROCS];/* the following is made volatile because it may be changed externally   during execution, and it is the upper bound of a 'for' loop (see below) */extern	volatile int	num_created_processes;/* cache parameters with default values   (cache size is in kilobytes, line size is in bytes) */static	int	L1_size =8,   L1_line_size = 16;static	int	L2_size =256, L2_line_size = 16;#ifdef GRAPHICSstatic	int	graphics_flag;	/* flag to select graphics */static	int	graphics_speed;	/* animation speed (1 to 10) */#endif /* GRAPHICS *//* macro for computing log base 2; the 'log_base2' function that   is already defined in misc.c expects exact powers of 2;   this macro works for any number */#define log2(x) ((int)(log(x)/log(2)))/* register simulator-specific options */voidsim_reg_options(struct opt_odb_t *odb){  opt_reg_header(odb,"sim-mpcache: This program implements a fast multiprocessor cache simulator\n""by cycling through one or more active processes and maintaining the states\n""of cache lines in L1 and L2 caches for each processor. Direct-mapped caches\n""are modelled using a writeback policy. Statistics are maintained for hits,\n""misses, invalidations, and bus activity. Note that no timing simulation is\n""performed; the bus activity is simply a count of the types of requests that\n""would result from misses in the processor caches. By default, the simulator\n""performs no instruction error checking. As a result, instruction errors are\n""likely to cause simulator execution errors, possibly even a core dump.\n""\n""Multiprocessor enhancements made by Naraig Manjikian, Queen's University\n"		 );  opt_reg_int (odb, "-L1", "Level 1 cache size (kbytes)",	       &L1_size, /* default */8, /* print */TRUE, NULL);    opt_reg_int (odb, "-L1line", "Level 1 line size (bytes)",	       &L1_line_size, /* default */16, /* print */TRUE, NULL);    opt_reg_int (odb, "-L2", "Level 2 cache size (kbytes)",	       &L2_size, /* default */256, /* print */TRUE, NULL);    opt_reg_int (odb, "-L2line", "Level 2 line size (bytes)",	       &L2_line_size, /* default */16, /* print */TRUE, NULL);#ifdef GRAPHICS    opt_reg_flag(odb, "-graphics", "graphical display of coherence",	       &graphics_flag, /* default */FALSE, /* print */TRUE, NULL);  opt_reg_int (odb, "-speed", "animation speed (1 to 10)",	       &graphics_speed, /* default */10, /* print */TRUE, NULL);#endif /* GRAPHICS */}/* check simulator-specific option values */voidsim_check_options(struct opt_odb_t *odb, int argc, char **argv){    /* verify that L1 and L2 cache capacities are powers of 2 */    if ((1 << log2(L1_size)) != L1_size)	fatal("The L1 cache size of %d kbytes is not a power of 2.", L1_size);    if ((1 << log2(L2_size)) != L2_size)	fatal("The L2 cache size of %d kbytes is not a power of 2.", L2_size);    /* verify that L1 cache capacity is no larger than L2 cache capacity */    if (L1_size > L2_size)	fatal ("The L1 cache size of %d kbytes is larger than"	       "\n\tthe L2 cache size of %d kbytes.", L1_size, L2_size);    /* verify that L1 and L2 line sizes are powers of 2 */    if ((1 << log2(L1_line_size)) != L1_line_size)	fatal("The L1 line size of %d bytes is not a power of 2.",	      L1_line_size);    if ((1 << log2(L2_line_size)) != L2_line_size)	fatal("The L2 line size of %d bytes is not a power of 2.",	      L2_line_size);    /* verify that L2 line size is greater than or equal to L1 line size */    if (L2_line_size < L1_line_size)	fatal ("The L2 line size of %d bytes is smaller than"	       "\n\tthe L1 line size of %d bytes.", L2_line_size,L1_line_size);#ifdef GRAPHICS    /* check validity of animation speed parameter */    if (graphics_speed < 1 || graphics_speed > 10)	fatal("The animation speed must be 1 (slowest) to 10 (fastest).");#endif /* GRAPHICS */    }/* register simulator-specific statistics */voidsim_reg_stats(struct stat_sdb_t *sdb){  stat_reg_uint(sdb, "sim_num_cycles",		"total number of execution cycles",		&sim_num_cycles, 0, NULL);  stat_reg_uintarray(sdb, "sim_num_instructions",		     "instructions executed per process",		     sim_num_instructions,	/* pointer to array */		     MAX_PROCS,			/* max size of array */		     (int *) &num_created_processes, /* ptr to actual used */		     0,				/* init value for all items */		     NULL);  stat_reg_int(sdb, "sim_elapsed_time",	       "total simulation time in seconds",	       (int *)&sim_elapsed_time, 0, NULL);}#undef mem_tablechar **local_mem_table = mem_table;#define mem_table local_mem_table/* initialize the simulator */voidsim_init(void){  SS_INST_TYPE inst;  /* decode all instructions */  {    SS_ADDR_TYPE addr;    if (OP_MAX > 255)      fatal("cannot do fast decoding, too many opcodes");    debug("sim: decoding text segment...");    for (addr=ld_text_base;	 addr < (ld_text_base+ld_text_size);	 addr += SS_INST_SIZE)      {	inst = __UNCHK_MEM_ACCESS(SS_INST_TYPE, addr);	inst.a = (inst.a & ~0xff) | (unsigned int)SS_OP_ENUM(SS_OPCODE(inst));	__UNCHK_MEM_ACCESS(SS_INST_TYPE, addr) = inst;      }  }  /* initialize multiprocessor cache simulator */#ifdef GRAPHICS    MPCacheInit (L1_line_size, L1_size * 1024,	       L2_line_size, L2_size * 1024,	       graphics_flag, graphics_speed);#else  MPCacheInit (L1_line_size, L1_size * 1024,	       L2_line_size, L2_size * 1024,	       0, 0);#endif /* GRAPHICS */  }/* print simulator-specific configuration information */voidsim_aux_config(FILE *stream){  /* nothing currently */}/* dump simulator-specific auxiliary simulator statistics */voidsim_aux_stats(FILE *stream){    unsigned int total_of_all_instructions = 0;    int	i;    for (i = 0; i < num_created_processes; i++)	total_of_all_instructions += sim_num_instructions[i];    fprintf (stream, "%-22s ", "sim_total_instructions");    fprintf (stream, "%12u", total_of_all_instructions);    fprintf (stream, " # total of all instructions executed\n");    fprintf (stream, "%-22s ", "sim_inst_rate");    fprintf (stream, "%12u",	     (unsigned int) ((double) total_of_all_instructions / sim_elapsed_time));    fprintf (stream, " # simulation speed (in insts/sec)\n");    MPCacheReport ();}/* un-initialize simulator-specific state */voidsim_uninit(void){    /* nothing */}/* * configure the execution engine *//* next program counter */#define SET_NPC(EXPR)		(local_next_PC = (EXPR))/* current program counter */#define CPC			(local_regs_PC)/* general purpose registers */#define GPR(N)			(regs_R[pid][N])#define SET_GPR(N,EXPR)		(regs_R[pid][N] = (EXPR))/* floating point registers, L->word, F->single-prec, D->double-prec */#define FPR_L(N)		(regs_F[pid].l[(N)])#define SET_FPR_L(N,EXPR)	(regs_F[pid].l[(N)] = (EXPR))#define FPR_F(N)		(regs_F[pid].f[(N)])#define SET_FPR_F(N,EXPR)	(regs_F[pid].f[(N)] = (EXPR))#define FPR_D(N)		(regs_F[pid].d[(N) >> 1])#define SET_FPR_D(N,EXPR)	(regs_F[pid].d[(N) >> 1] = (EXPR))/* miscellaneous register accessors */#define SET_HI(EXPR)		(regs_HI[pid] = (EXPR))#define HI			(regs_HI[pid])#define SET_LO(EXPR)		(regs_LO[pid] = (EXPR))#define LO			(regs_LO[pid])#define FCC			(regs_FCC[pid])#define SET_FCC(EXPR)		(regs_FCC[pid] = (EXPR))/* precise architected memory state accessor macros, all unsafe for speed  */#define READ_WORD(SRC)							\  (__MEM_READ_WORD(SRC))#define READ_UNSIGNED_HALF(SRC)						\  ((unsigned int)((unsigned short)__MEM_READ_HALF(SRC)))#define READ_SIGNED_HALF(SRC)						\  ((signed int)((signed short)__MEM_READ_HALF(SRC)))#define READ_UNSIGNED_BYTE(SRC)						\  ((unsigned int)((unsigned char)__MEM_READ_BYTE(SRC)))#define READ_SIGNED_BYTE(SRC)						\  ((unsigned int)((signed int)((signed char)__MEM_READ_BYTE(SRC))))#define WRITE_WORD(SRC, DST)						\  (__MEM_WRITE_WORD((DST), (unsigned int)(SRC)))#define WRITE_HALF(SRC, DST)						\  (__MEM_WRITE_HALF((DST), (unsigned short)((unsigned int)(SRC))))#define WRITE_BYTE(SRC, DST)						\  (__MEM_WRITE_BYTE((DST), (unsigned char)((unsigned int)(SRC))))/* system call handler macro */#define SYSCALL(INST)		(ss_syscall(mem_access, INST, pid))/* instantiate the helper functions in the '.def' file *//* access global register */#define DEFINST(OP,MSK,NAME,OPFORM,RES,CLASS,O1,O2,I1,I2,I3,EXPR)#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)#define CONNECT(OP)#define IMPL#include "ss.def"#undef DEFINST#undef DEFLINK#undef CONNECT#undef IMPL/* start simulation, program loaded */voidsim_main(void){  /* register allocate PC and next PC */  register SS_ADDR_TYPE local_regs_PC, local_next_PC;  /* register allocate level one memory page map */#undef mem_table  register char **local_mem_table = mem_table;#define mem_table local_mem_table  /* register allocate instruction buffer */  register SS_INST_TYPE inst;  /* register allocate pid */  register int	pid;    fprintf(stderr,	  "sim: ** starting multiprocessor cache simulation **\n");  num_created_processes = 1;	/* pid 0 exists at beginning */  active[0] = 1;		/* mark pid 0 as active */  /* must have natural byte/word ordering */  if (sim_swap_bytes || sim_swap_words)    fatal("sim: multiprocessor cache simulation cannot swap bytes or words");  while (TRUE)  {    /* increment number of cycles */    ++sim_num_cycles;    for (pid = 0; pid < num_created_processes; pid++)    {      if (! active[pid])	/* skip inactive processes */	continue;      /* maintain $r0 semantics */      regs_R[pid][0] = 0;      /* set current/next PC value */      local_regs_PC = regs_PC[pid];      local_next_PC = local_regs_PC + SS_INST_SIZE;      /* keep an instruction count for each processor */      ++sim_num_instructions[pid];      inst = __UNCHK_MEM_ACCESS(SS_INST_TYPE, local_regs_PC);      /* pass memory events only to multiprocr cache simulator	 and send base+offset address _before_ executing instruction	 because simulating "lw $reg,0($reg)" modifies base register */      if (SS_OP_FLAGS(SS_OPCODE(inst)) & F_MEM)	  MPCacheMemRef (			 pid,				/* processor id */			 GPR(BS)+OFS,			/* data mem address */			 ((SS_OP_FLAGS(SS_OPCODE(inst))) & F_STORE) /* rd/wr */			 );      switch (SS_OPCODE(inst)) {#define DEFINST(OP,MSK,NAME,OPFORM,RES,FLAGS,O1,O2,I1,I2,I3,EXPR)	\      case OP:								\        EXPR;								\        break;#define DEFLINK(OP,MSK,NAME,MASK,SHIFT)					\      case OP:								\        panic("attempted to execute a linking opcode");#define CONNECT(OP)#include "ss.def"#undef DEFINST#undef DEFLINK#undef CONNECT      }            /* save next PC value for this processor */      regs_PC[pid] = local_next_PC;      /* inner loop will now move on to next active process */    }    /* outer loop is infinite */  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -