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

📄 sim-outorder.c

📁 RISC处理器仿真分析程序。可以用于研究通用RISC处理器的指令和架构设计。在linux下编译
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* 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);  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);    }}/* 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);/* default register state accessor, used by DLite */static char *					/* err str, NULL for no err */simoo_reg_obj(enum dlite_access_t at,		/* access type */	      enum dlite_reg_t rt,		/* reg bank to probe */	      int reg,				/* register number */	      union dlite_reg_val_t *val);	/* input, output *//* default memory state accessor, used by DLite */static char *					/* err str, NULL for no err */simoo_mem_obj(enum dlite_access_t at,		/* access type */	      SS_ADDR_TYPE 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 *//* total RS links allocated at program start */#define MAX_RS_LINKS                    4096/* initialize the simulator */voidsim_init(void){  sim_num_insn = 0;  sim_num_refs = 0;  /* 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>");  /* decode all instructions */  {    SS_ADDR_TYPE addr;    SS_INST_TYPE inst;    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 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 */  SS_INST_TYPE IR;                      /* instruction bits */  enum ss_opcode op;                    /* decoded instruction opcode */  SS_ADDR_TYPE 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 dir_update;	/* bpred direction update info */  int spec_mode;                        /* non-zero if issued in spec_mode */  SS_ADDR_TYPE 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 */  /* 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;}/* 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 (header)    fprintf(stream, "idx: %2d: opcode: %s, inst: `",	    index, SS_OP_NAME(rs->op));  else    fprintf(stream, "       opcode: %s, inst: `",	    SS_OP_NAME(rs->op));  ss_print_insn(rs->IR, rs->PC, stream);  fprintf(stream, "'\n");  fprintf(stream, "         PC: 0x%08x, NPC: 0x%08x (pred_PC: 0x%08x)\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");  fprintf(stream, "         spec_mode: %s, addr: 0x%08x, 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;  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: *   1) register operands are ready * * stores are serviced by: *   1) depositing store value into the load/store queue *   2) writing store value to the store buffer (plus tag check) at commit *   3) writing store buffer entry to data cache when cache is free * * NOTE: the load/store queue can bypass a store value to a load in the same *   cycle the store executes (using a bypass network), thus stores complete *   in effective zero time after their effective address is known */static struct RUU_station *LSQ;         /* load/store queue */static int LSQ_head, LSQ_tail;          /* LSQ head and tail pointers */static int LSQ_num;                     /* num entries currently in LSQ *//* * input dependencies for stores in the LSQ: *   idep #0 - operand input (value that is store'd) *   idep #1 - effective address input (address of store operation) */#define STORE_OP_INDEX                  0#define STORE_ADDR_INDEX                1#define STORE_OP_READY(RS)              ((RS)->idep_ready[STORE_OP_INDEX])#define STORE_ADDR_READY(RS)            ((RS)->idep_ready[STORE_ADDR_INDEX])/* allocate and initialize the load/store queue (LSQ) */static voidlsq_init(void){  LSQ = calloc(LSQ_size, sizeof(struct RUU_station));  if (!LSQ)    fatal("out of virtual memory");  LSQ_num = 0;  LSQ_head = LSQ_tail = 0;}/* dump the contents of the RUU */static voidlsq_dump(FILE *stream)				/* output stream */{  int num, head;  struct RUU_station *rs;  fprintf(stream, "** LSQ state **\n");  fprintf(stream, "LSQ_head: %d, LSQ_tail: %d\n", LSQ_head, LSQ_tail);  fprintf(stream, "LSQ_num: %d\n", LSQ_num);  num = LSQ_num;  head = LSQ_head;  while (num)    {      rs = &LSQ[head];      ruu_dumpent(rs, rs - LSQ, stream, /* header */TRUE);      head = (head + 1) % LSQ_size;      num--;    }}/* * RS_LINK defs and decls *//* a reservation station link: this structure links elements of a RUU   reservation station list; used for ready instruction queue, event queue, and   output dependency lists; each RS_LINK node contains a pointer to the RUU   entry it references along with an instance tag, the RS_LINK is only valid if   the instruction instance tag matches the instruction RUU entry instance tag;   this strategy allows entries in the RUU can be squashed and reused without   updating the lists that point to it, which significantly improves the   performance of (all to frequent) squash events */struct RS_link {  struct RS_link *next;                 /* next entry in list */  struct RUU_station *rs;               /* referenced RUU resv station */  INST_TAG_TYPE tag;                    /* inst instance sequence number */  union {    SS_TIME_TYPE when;                  /* time stamp of entry (for eventq) */    INST_SEQ_TYPE seq;                  /* inst sequence */    int opnum;                          /* input/output operand number */  } x;};/* RS link free list, grab RS_LINKs from here, when needed */static struct RS_link *rslink_free_list;/* NULL value for an RS link */#define RSLINK_NULL_DATA		{ NULL, NULL, 0 }static struct RS_link RSLINK_NULL = RSLINK_NULL_DATA;/* NULL value for an RS link */#define RSLINK_INIT(RSL, RS)						\  ((RSL).next = NULL, (RSL).rs = (RS), (RSL).tag = (RS)->tag)/* non-zero if RS link is NULL */#define RSLINK_IS_NULL(LINK)            ((LINK)->rs == NULL)/* non-zero if RS link is to a valid (non-squashed) entry */#define RSLINK_VALID(LINK)              ((LINK)->tag == (LINK)->rs->tag)

⌨️ 快捷键说明

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