/* parse execution position *PSTR to *POS */ char * /* error string, or NULL */ range_parse_pos(char *pstr, /* execution position string */ struct range_pos_t *pos) /* position return buffer */ { char *s, *endp; struct sym_sym_t *sym; /* determine position type */ if (pstr[0] == '@') { /* address position */ pos->ptype = pt_addr; s = pstr + 1; } else if (pstr[0] == '#') { /* cycle count position */ pos->ptype = pt_cycle; s = pstr + 1; } else { /* inst count position */ pos->ptype = pt_inst; s = pstr; } /* get position value */ errno = 0; pos->pos = (counter_t)strtoul(s, &endp, /* parse base */0); if (!errno && !*endp) { /* good conversion */ return NULL; } /* else, not an integer, attempt double conversion */ errno = 0; pos->pos = (counter_t)strtod(s, &endp); if (!errno && !*endp) { /* good conversion */ /* FIXME: ignoring decimal point!! */ return NULL; } /* else, attempt symbol lookup */ sym_loadsyms(ld_prog_fname, /* !locals */FALSE); sym = sym_bind_name(s, NULL, sdb_any); if (sym != NULL) { pos->pos = (counter_t)sym->addr; return NULL; } /* else, no binding made */ return "cannot bind execution position to a value"; }
//parse execution position *PSTR to *POS, returns error string or NULL const char * range_parse_pos(char *pstr, //execution position string range_pos_t *pos, //position return buffer mem_t* my_mem) { char *s, *endp; //determine position type if (pstr[0] == '@') { //address position pos->ptype = pt_addr; s = pstr + 1; } else if (pstr[0] == '#') { //cycle count position pos->ptype = pt_cycle; s = pstr + 1; } else { //inst count position pos->ptype = pt_inst; s = pstr; } //get position value errno = 0; pos->pos = (counter_t)strtoul(s, &endp, /*parse base*/0); if(!errno && !*endp) { //good conversion return NULL; } //else, not an integer, attempt double conversion errno = 0; pos->pos = (counter_t)strtod(s, &endp); if(!errno && !*endp) { //good conversion //FIXME: ignoring decimal point!! return NULL; } //else, attempt symbol lookup sym_loadsyms(my_mem->ld_prog_fname.c_str(), /*!locals*/FALSE, my_mem); sym_sym_t *sym = sym_bind_name(s, NULL, sdb_any); if(sym != NULL) { pos->pos = (counter_t)sym->addr; return NULL; } //else, no binding made return "cannot bind execution position to a value"; }
/* register simulator-specific statistics */ void sim_reg_stats(struct stat_sdb_t *sdb) { int i; stat_reg_counter(sdb, "sim_num_insn", "total number of instructions executed", &sim_num_insn, sim_num_insn, NULL); stat_reg_counter(sdb, "sim_num_refs", "total number of loads and stores executed", &sim_num_refs, 0, NULL); stat_reg_int(sdb, "sim_elapsed_time", "total simulation time in seconds", &sim_elapsed_time, 0, NULL); stat_reg_formula(sdb, "sim_inst_rate", "simulation speed (in insts/sec)", "sim_num_insn / sim_elapsed_time", NULL); if (prof_ic) { /* instruction class profile */ ic_prof = stat_reg_dist(sdb, "sim_inst_class_prof", "instruction class profile", /* initial value */0, /* array size */ic_NUM, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */inst_class_str, /* print fn */NULL); } if (prof_inst) { int i; char buf[512]; /* conjure up appropriate instruction description strings */ for (i=0; i < /* skip NA */OP_MAX-1; i++) { sprintf(buf, "%-8s %-6s", md_op2name[i+1], md_op2format[i+1]); inst_str[i] = mystrdup(buf); } /* instruction profile */ inst_prof = stat_reg_dist(sdb, "sim_inst_prof", "instruction profile", /* initial value */0, /* array size */ /* skip NA */OP_MAX-1, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */inst_str, /* print fn */NULL); } if (prof_bc) { /* instruction branch profile */ bc_prof = stat_reg_dist(sdb, "sim_branch_prof", "branch instruction profile", /* initial value */0, /* array size */bc_NUM, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */branch_class_str, /* print fn */NULL); } if (prof_am) { /* instruction branch profile */ am_prof = stat_reg_dist(sdb, "sim_addr_mode_prof", "addressing mode profile", /* initial value */0, /* array size */md_amode_NUM, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */md_amode_str, /* print fn */NULL); } if (prof_seg) { /* instruction branch profile */ seg_prof = stat_reg_dist(sdb, "sim_addr_seg_prof", "load/store address segment profile", /* initial value */0, /* array size */seg_NUM, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */addr_seg_str, /* print fn */NULL); } if (prof_tsyms && sym_ntextsyms != 0) { int i; /* load program symbols */ sym_loadsyms(ld_prog_fname, load_locals); /* conjure up appropriate instruction description strings */ tsym_names = (char **)calloc(sym_ntextsyms, sizeof(char *)); for (i=0; i < sym_ntextsyms; i++) tsym_names[i] = sym_textsyms[i]->name; /* text symbol profile */ tsym_prof = stat_reg_dist(sdb, "sim_text_sym_prof", "text symbol profile", /* initial value */0, /* array size */sym_ntextsyms, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */tsym_names, /* print fn */NULL); } if (prof_dsyms && sym_ndatasyms != 0) { int i; /* load program symbols */ sym_loadsyms(ld_prog_fname, load_locals); /* conjure up appropriate instruction description strings */ dsym_names = (char **)calloc(sym_ndatasyms, sizeof(char *)); for (i=0; i < sym_ndatasyms; i++) dsym_names[i] = sym_datasyms[i]->name; /* data symbol profile */ dsym_prof = stat_reg_dist(sdb, "sim_data_sym_prof", "data symbol profile", /* initial value */0, /* array size */sym_ndatasyms, /* bucket size */1, /* print format */(PF_COUNT|PF_PDF), /* format */NULL, /* index map */dsym_names, /* print fn */NULL); } if (prof_taddr) { /* text address profile (sparse profile), NOTE: a dense print format is used, its more difficult to read, but the profiles are *much* smaller, I've assumed that the profiles are read by programs, at least for your sake I hope this is the case!! */ taddr_prof = stat_reg_sdist(sdb, "sim_text_addr_prof", "text address profile", /* initial value */0, /* print format */(PF_COUNT|PF_PDF), /* format */"0x%p %u %.2f", /* print fn */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%p %u %.2f", /* print fn */NULL); } ld_reg_stats(sdb); mem_reg_stats(mem, sdb); }