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

📄 sim-outorder.c

📁 一个很有名的硬件模拟器。可以模拟CPU
💻 C
📖 第 1 页 / 共 5 页
字号:
		   "total number of loads executed",		   &sim_total_loads, 0, NULL);  stat_reg_formula(sdb, "sim_total_stores",		   "total number of stores executed",		   "sim_total_refs - sim_total_loads", NULL);  stat_reg_counter(sdb, "sim_total_branches",		   "total number of branches executed",		   &sim_total_branches, /* initial value */0, /* format */NULL);  /* register performance stats */  stat_reg_counter(sdb, "sim_cycle",		   "total simulation time in cycles",		   &sim_cycle, /* initial value */0, /* format */NULL);  stat_reg_formula(sdb, "sim_IPC",		   "instructions per cycle",		   "sim_num_insn / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "sim_CPI",		   "cycles per instruction",		   "sim_cycle / sim_num_insn", /* format */NULL);  stat_reg_formula(sdb, "sim_exec_BW",		   "total instructions (mis-spec + committed) per cycle",		   "sim_total_insn / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "sim_IPB",		   "instruction per branch",		   "sim_num_insn / sim_num_branches", /* format */NULL);  /* occupancy stats */  stat_reg_counter(sdb, "IFQ_count", "cumulative IFQ occupancy",                   &IFQ_count, /* initial value */0, /* format */NULL);  stat_reg_counter(sdb, "IFQ_fcount", "cumulative IFQ full count",                   &IFQ_fcount, /* initial value */0, /* format */NULL);  stat_reg_formula(sdb, "ifq_occupancy", "avg IFQ occupancy (insn's)",                   "IFQ_count / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "ifq_rate", "avg IFQ dispatch rate (insn/cycle)",                   "sim_total_insn / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "ifq_latency", "avg IFQ occupant latency (cycle's)",                   "ifq_occupancy / ifq_rate", /* format */NULL);  stat_reg_formula(sdb, "ifq_full", "fraction of time (cycle's) IFQ was full",                   "IFQ_fcount / sim_cycle", /* format */NULL);  stat_reg_counter(sdb, "RUU_count", "cumulative RUU occupancy",                   &RUU_count, /* initial value */0, /* format */NULL);  stat_reg_counter(sdb, "RUU_fcount", "cumulative RUU full count",                   &RUU_fcount, /* initial value */0, /* format */NULL);  stat_reg_formula(sdb, "ruu_occupancy", "avg RUU occupancy (insn's)",                   "RUU_count / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "ruu_rate", "avg RUU dispatch rate (insn/cycle)",                   "sim_total_insn / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "ruu_latency", "avg RUU occupant latency (cycle's)",                   "ruu_occupancy / ruu_rate", /* format */NULL);  stat_reg_formula(sdb, "ruu_full", "fraction of time (cycle's) RUU was full",                   "RUU_fcount / sim_cycle", /* format */NULL);  stat_reg_counter(sdb, "LSQ_count", "cumulative LSQ occupancy",                   &LSQ_count, /* initial value */0, /* format */NULL);  stat_reg_counter(sdb, "LSQ_fcount", "cumulative LSQ full count",                   &LSQ_fcount, /* initial value */0, /* format */NULL);  stat_reg_formula(sdb, "lsq_occupancy", "avg LSQ occupancy (insn's)",                   "LSQ_count / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "lsq_rate", "avg LSQ dispatch rate (insn/cycle)",                   "sim_total_insn / sim_cycle", /* format */NULL);  stat_reg_formula(sdb, "lsq_latency", "avg LSQ occupant latency (cycle's)",                   "lsq_occupancy / lsq_rate", /* format */NULL);  stat_reg_formula(sdb, "lsq_full", "fraction of time (cycle's) LSQ was full",                   "LSQ_fcount / sim_cycle", /* format */NULL);  stat_reg_counter(sdb, "sim_slip",                   "total number of slip cycles",                   &sim_slip, 0, NULL);  /* register baseline stats */  stat_reg_formula(sdb, "avg_sim_slip",                   "the average slip between issue and retirement",                   "sim_slip / sim_num_insn", NULL);  /* register predictor stats */  if (pred)    bpred_reg_stats(pred, sdb);  /* register cache stats */  if (cache_il1      && (cache_il1 != cache_dl1 && cache_il1 != cache_dl2))    cache_reg_stats(cache_il1, sdb);  if (cache_il2      && (cache_il2 != cache_dl1 && cache_il2 != cache_dl2))    cache_reg_stats(cache_il2, sdb);  if (cache_dl1)    cache_reg_stats(cache_dl1, sdb);  if (cache_dl2)    cache_reg_stats(cache_dl2, sdb);  if (itlb)    cache_reg_stats(itlb, sdb);  if (dtlb)    cache_reg_stats(dtlb, sdb);  /* debug variable(s) */  stat_reg_counter(sdb, "sim_invalid_addrs",		   "total non-speculative bogus addresses seen (debug var)",                   &sim_invalid_addrs, /* initial value */0, /* format */NULL);  for (i=0; i<pcstat_nelt; i++)    {      char buf[512], buf1[512];      struct stat_stat_t *stat;      /* track the named statistical variable by text address */      /* find it... */      stat = stat_find_stat(sdb, pcstat_vars[i]);      if (!stat)	fatal("cannot locate any statistic named `%s'", pcstat_vars[i]);      /* stat must be an integral type */      if (stat->sc != sc_int && stat->sc != sc_uint && stat->sc != sc_counter)	fatal("`-pcstat' statistical variable `%s' is not an integral type",	      stat->name);      /* register this stat */      pcstat_stats[i] = stat;      pcstat_lastvals[i] = STATVAL(stat);      /* declare the sparce text distribution */      sprintf(buf, "%s_by_pc", stat->name);      sprintf(buf1, "%s (by text address)", stat->desc);      pcstat_sdists[i] = stat_reg_sdist(sdb, buf, buf1,					/* initial value */0,					/* print format */(PF_COUNT|PF_PDF),					/* format */"0x%lx %lu %.2f",					/* print fn */NULL);    }  ld_reg_stats(sdb);  mem_reg_stats(mem, sdb);}/* forward declarations */static void ruu_init(void);static void lsq_init(void);static void rslink_init(int nlinks);static void eventq_init(void);static void readyq_init(void);static void cv_init(void);static void tracer_init(void);static void fetch_init(void);/* initialize the simulator */voidsim_init(void){  sim_num_refs = 0;  /* allocate and initialize register file */  regs_init(&regs);  /* allocate and initialize memory space */  mem = mem_create("mem");  mem_init(mem);}/* default register state accessor, used by DLite */static char *					/* err str, NULL for no err */simoo_reg_obj(struct regs_t *regs,		/* registers to access */	      int is_write,			/* access type */	      enum md_reg_type rt,		/* reg bank to probe */	      int reg,				/* register number */	      struct eval_value_t *val);	/* input, output *//* default memory state accessor, used by DLite */static char *					/* err str, NULL for no err */simoo_mem_obj(struct mem_t *mem,		/* memory space to access */	      int is_write,			/* access type */	      md_addr_t addr,			/* address to access */	      char *p,				/* input/output buffer */	      int nbytes);			/* size of access *//* default machine state accessor, used by DLite */static char *					/* err str, NULL for no err */simoo_mstate_obj(FILE *stream,			/* output stream */		 char *cmd,			/* optional command string */		 struct regs_t *regs,		/* registers to access */		 struct mem_t *mem);		/* memory space to access *//* total RS links allocated at program start */#define MAX_RS_LINKS                    4096/* load program into simulated state */voidsim_load_prog(char *fname,		/* program to load */	      int argc, char **argv,	/* program arguments */	      char **envp)		/* program environment */{  /* load program text and data, set up environment, memory, and regs */  ld_load_prog(fname, argc, argv, envp, &regs, mem, TRUE);  /* initialize here, so symbols can be loaded */  if (ptrace_nelt == 2)    {      /* generate a pipeline trace */      ptrace_open(/* fname */ptrace_opts[0], /* range */ptrace_opts[1]);    }  else if (ptrace_nelt == 0)    {      /* no pipetracing */;    }  else    fatal("bad pipetrace args, use: <fname|stdout|stderr> <range>");  /* finish initialization of the simulation engine */  fu_pool = res_create_pool("fu-pool", fu_config, N_ELT(fu_config));  rslink_init(MAX_RS_LINKS);  tracer_init();  fetch_init();  cv_init();  eventq_init();  readyq_init();  ruu_init();  lsq_init();  /* initialize the DLite debugger */  dlite_init(simoo_reg_obj, simoo_mem_obj, simoo_mstate_obj);}/* dump simulator-specific auxiliary simulator statistics */voidsim_aux_stats(FILE *stream)             /* output stream */{  /* nada */}/* un-initialize the simulator */voidsim_uninit(void){  if (ptrace_nelt > 0)    ptrace_close();}/* * processor core definitions and declarations *//* inst tag type, used to tag an operation instance in the RUU */typedef unsigned int INST_TAG_TYPE;/* inst sequence type, used to order instructions in the ready list, if   this rolls over the ready list order temporarily will get messed up,   but execution will continue and complete correctly */typedef unsigned int INST_SEQ_TYPE;/* total input dependencies possible */#define MAX_IDEPS               3/* total output dependencies possible */#define MAX_ODEPS               2/* a register update unit (RUU) station, this record is contained in the   processors RUU, which serves as a collection of ordered reservations   stations.  The reservation stations capture register results and await   the time when all operands are ready, at which time the instruction is   issued to the functional units; the RUU is an order circular queue, in which   instructions are inserted in fetch (program) order, results are stored in   the RUU buffers, and later when an RUU entry is the oldest entry in the   machines, it and its instruction's value is retired to the architectural   register file in program order, NOTE: the RUU and LSQ share the same   structure, this is useful because loads and stores are split into two   operations: an effective address add and a load/store, the add is inserted   into the RUU and the load/store inserted into the LSQ, allowing the add   to wake up the load/store when effective address computation has finished */struct RUU_station {  /* inst info */  md_inst_t IR;			/* instruction bits */  enum md_opcode op;			/* decoded instruction opcode */  md_addr_t PC, next_PC, pred_PC;	/* inst PC, next PC, predicted PC */  int in_LSQ;				/* non-zero if op is in LSQ */  int ea_comp;				/* non-zero if op is an addr comp */  int recover_inst;			/* start of mis-speculation? */  int stack_recover_idx;		/* non-speculative TOS for RSB pred */  struct bpred_update_t dir_update;	/* bpred direction update info */  int spec_mode;			/* non-zero if issued in spec_mode */  md_addr_t addr;			/* effective address for ld/st's */  INST_TAG_TYPE tag;			/* RUU slot tag, increment to					   squash operation */  INST_SEQ_TYPE seq;			/* instruction sequence, used to					   sort the ready list and tag inst */  unsigned int ptrace_seq;		/* pipetrace sequence number */  int slip;  /* instruction status */  int queued;				/* operands ready and queued */  int issued;				/* operation is/was executing */  int completed;			/* operation has completed execution */  /* output operand dependency list, these lists are used to     limit the number of associative searches into the RUU when     instructions complete and need to wake up dependent insts */  int onames[MAX_ODEPS];		/* output logical names (NA=unused) */  struct RS_link *odep_list[MAX_ODEPS];	/* chains to consuming operations */  /* input dependent links, the output chains rooted above use these     fields to mark input operands as ready, when all these fields have     been set non-zero, the RUU operation has all of its register     operands, it may commence execution as soon as all of its memory     operands are known to be read (see lsq_refresh() for details on     enforcing memory dependencies) */  int idep_ready[MAX_IDEPS];		/* input operand ready? */};/* non-zero if all register operands are ready, update with MAX_IDEPS */#define OPERANDS_READY(RS)                                              \  ((RS)->idep_ready[0] && (RS)->idep_ready[1] && (RS)->idep_ready[2])/* register update unit, combination of reservation stations and reorder   buffer device, organized as a circular queue */static struct RUU_station *RUU;		/* register update unit */static int RUU_head, RUU_tail;		/* RUU head and tail pointers */static int RUU_num;			/* num entries currently in RUU *//* allocate and initialize register update unit (RUU) */static voidruu_init(void){  RUU = calloc(RUU_size, sizeof(struct RUU_station));  if (!RUU)    fatal("out of virtual memory");  RUU_num = 0;  RUU_head = RUU_tail = 0;  RUU_count = 0;  RUU_fcount = 0;}/* dump the contents of the RUU */static voidruu_dumpent(struct RUU_station *rs,		/* ptr to RUU station */	    int index,				/* entry index */	    FILE *stream,			/* output stream */	    int header)				/* print header? */{  if (!stream)    stream = stderr;  if (header)    fprintf(stream, "idx: %2d: opcode: %s, inst: `",	    index, MD_OP_NAME(rs->op));  else    fprintf(stream, "       opcode: %s, inst: `",	    MD_OP_NAME(rs->op));  md_print_insn(rs->IR, rs->PC, stream);  fprintf(stream, "'\n");  myfprintf(stream, "         PC: 0x%08p, NPC: 0x%08p (pred_PC: 0x%08p)\n",	    rs->PC, rs->next_PC, rs->pred_PC);  fprintf(stream, "         in_LSQ: %s, ea_comp: %s, recover_inst: %s\n",	  rs->in_LSQ ? "t" : "f",	  rs->ea_comp ? "t" : "f",	  rs->recover_inst ? "t" : "f");  myfprintf(stream, "         spec_mode: %s, addr: 0x%08p, tag: 0x%08x\n",	    rs->spec_mode ? "t" : "f", rs->addr, rs->tag);  fprintf(stream, "         seq: 0x%08x, ptrace_seq: 0x%08x\n",	  rs->seq, rs->ptrace_seq);  fprintf(stream, "         queued: %s, issued: %s, completed: %s\n",	  rs->queued ? "t" : "f",	  rs->issued ? "t" : "f",	  rs->completed ? "t" : "f");  fprintf(stream, "         operands ready: %s\n",	  OPERANDS_READY(rs) ? "t" : "f");}/* dump the contents of the RUU */static voidruu_dump(FILE *stream)				/* output stream */{  int num, head;  struct RUU_station *rs;  if (!stream)    stream = stderr;  fprintf(stream, "** RUU state **\n");  fprintf(stream, "RUU_head: %d, RUU_tail: %d\n", RUU_head, RUU_tail);  fprintf(stream, "RUU_num: %d\n", RUU_num);  num = RUU_num;  head = RUU_head;  while (num)    {      rs = &RUU[head];      ruu_dumpent(rs, rs - RUU, stream, /* header */TRUE);      head = (head + 1) % RUU_size;      num--;    }}/* * load/store queue (LSQ): holds loads and stores in program order, indicating * status of load/store access: * *   - issued: address computation complete, memory access in progress *   - completed: memory access has completed, stored value available *   - squashed: memory access was squashed, ignore this entry * * loads may execute when: *   1) register operands are ready, and *   2) memory operands are ready (no earlier unresolved store) * * loads are serviced by: *   1) previous store at same address in LSQ (hit latency), or *   2) data cache (hit latency + miss latency) * * stores may execute when:

⌨️ 快捷键说明

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