/* print all simulator stats */ void sim_print_stats(FILE *fd) /* output stream */ { #if 0 /* not portable... :-( */ extern char etext, *sbrk(int); #endif if (!running) return; /* get stats time */ sim_end_time = time((time_t *)NULL); sim_elapsed_time = MAX(sim_end_time - sim_start_time, 1); #if 0 /* not portable... :-( */ /* compute simulator memory usage */ sim_mem_usage = (sbrk(0) - &etext) / 1024; #endif /* print simulation stats */ fprintf(fd, "\nsim: ** simulation statistics **\n"); stat_print_stats(sim_sdb, fd); sim_aux_stats(fd); fprintf(fd, "\n"); //Yuanwen Added here struct stat_stat_t * stat_max_power = stat_find_stat(sim_sdb, "max_cycle_power_cc3"); FILE *f=fopen("MaxPower.txt", "w"); fprintf(f, "%g", *stat_max_power->variant.for_double.var); //Yuanwen Added /* instantiate a new evaluator to avoid recursion problems */ struct eval_state_t *es = eval_new(stat_eval_ident, sim_sdb); //stat_eval_ident() is a function char *endp; struct stat_stat_t * stat_avg_total_power = stat_find_stat(sim_sdb, "avg_total_power_cycle_cc3"); struct eval_value_t val = eval_expr(es, stat_avg_total_power->variant.for_formula.formula, &endp); // if (eval_error != ERR_NOERR || *endp != '\0') // fprintf(fd, "<error: %s>", eval_err_str[eval_error]); // else // myfprintf(fd, stat->format, eval_as_double(val)); // fprintf(fd, " # %s", stat->desc); fprintf(f, ",%g", eval_as_double(val)); struct stat_stat_t * stat_1 = stat_find_stat(sim_sdb, "avg_alu_power_cc3"); struct eval_value_t val_1 = eval_expr(es, stat_1->variant.for_formula.formula, &endp); fprintf(f, ",%g", eval_as_double(val_1)); struct stat_stat_t * stat_2 = stat_find_stat(sim_sdb, "avg_lsq_power_cc3"); struct eval_value_t val_2 = eval_expr(es, stat_2->variant.for_formula.formula, &endp); fprintf(f, ",%g", eval_as_double(val_2)); /* done with the evaluator */ eval_delete(es); fclose(f); }
/* compute <val1> / <val2> */ static struct eval_value_t f_div(struct eval_value_t val1, struct eval_value_t val2) { enum eval_type_t et; struct eval_value_t val; /* symbols are not allowed in arithmetic expressions */ if (val1.type == et_symbol || val2.type == et_symbol) { eval_error = ERR_BADEXPR; return err_value; } /* get result type, and perform operation in that type */ et = result_type(val1.type, val2.type); switch (et) { case et_double: val.type = et_double; val.value.as_double = eval_as_double(val1) / eval_as_double(val2); break; case et_float: val.type = et_float; val.value.as_float = eval_as_float(val1) / eval_as_float(val2); break; #ifdef HOST_HAS_QWORD case et_qword: val.type = et_qword; val.value.as_qword = eval_as_qword(val1) / eval_as_qword(val2); break; case et_sqword: val.type = et_sqword; val.value.as_sqword = eval_as_sqword(val1) / eval_as_sqword(val2); break; #endif /* HOST_HAS_QWORD */ case et_addr: val.type = et_addr; val.value.as_addr = eval_as_addr(val1) / eval_as_addr(val2); break; case et_uint: val.type = et_uint; val.value.as_uint = eval_as_uint(val1) / eval_as_uint(val2); break; case et_int: val.type = et_int; val.value.as_int = eval_as_int(val1) / eval_as_int(val2); break; default: panic("bogus expression type"); } return val; }
char * /* err str, NULL for no err */ md_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 */ { switch (rt) { case rt_gpr: if (reg < 0 || reg >= MD_NUM_IREGS) return "register number out of range"; if (!is_write) { val->type = et_quad; val->value.as_quad = regs->regs_R[reg]; } else regs->regs_R[reg] = eval_as_quad(*val); break; case rt_lpr: if (reg < 0 || reg >= MD_NUM_FREGS) return "register number out of range"; if (!is_write) { val->type = et_quad; val->value.as_quad = regs->regs_F.q[reg]; } else regs->regs_F.q[reg] = eval_as_quad(*val); break; case rt_fpr: if (reg < 0 || reg >= MD_NUM_FREGS) return "register number out of range"; if (!is_write) { val->type = et_double; val->value.as_double = regs->regs_F.d[reg]; } else regs->regs_F.d[reg] = eval_as_double(*val); break; case rt_ctrl: switch (reg) { case /* FPCR */0: if (!is_write) { val->type = et_quad; val->value.as_quad = regs->regs_C.fpcr; } else regs->regs_C.fpcr = eval_as_quad(*val); break; case /* UNIQ */1: if (!is_write) { val->type = et_quad; val->value.as_quad = regs->regs_C.uniq; } else regs->regs_C.uniq = eval_as_quad(*val); break; default: return "register number out of range"; } break; case rt_PC: if (!is_write) { val->type = et_addr; val->value.as_addr = regs->regs_PC; } else regs->regs_PC = eval_as_addr(*val); break; case rt_NPC: if (!is_write) { val->type = et_addr; val->value.as_addr = regs->regs_NPC; } else regs->regs_NPC = eval_as_addr(*val); break; default: panic("bogus register bank"); } /* no error */ return NULL; }
char * /* err str, NULL for no err */ md_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 */ { switch (rt) { case rt_gpr: if (reg < 0 || reg >= MD_NUM_IREGS) return "register number out of range"; if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_R[reg]; } else regs->regs_R[reg] = eval_as_uint(*val); break; case rt_lpr: if (reg < 0 || reg >= MD_NUM_FREGS) return "register number out of range"; if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_F.l[reg]; } else regs->regs_F.l[reg] = eval_as_uint(*val); break; case rt_fpr: if (reg < 0 || reg >= MD_NUM_FREGS) return "register number out of range"; if (!is_write) { val->type = et_float; val->value.as_float = regs->regs_F.f[reg]; } else regs->regs_F.f[reg] = eval_as_float(*val); break; case rt_dpr: if (reg < 0 || reg >= MD_NUM_FREGS/2) return "register number out of range"; if (!is_write) { val->type = et_double; val->value.as_double = regs->regs_F.d[reg]; } else regs->regs_F.d[reg] = eval_as_double(*val); break; case rt_ctrl: switch (reg) { case /* HI */0: if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_C.hi; } else regs->regs_C.hi = eval_as_uint(*val); break; case /* LO */1: if (!is_write) { val->type = et_uint; val->value.as_uint = regs->regs_C.lo; } else regs->regs_C.lo = eval_as_uint(*val); break; case /* FCC */2: if (!is_write) { val->type = et_int; val->value.as_int = regs->regs_C.fcc; } else regs->regs_C.fcc = eval_as_uint(*val); break; default: return "register number out of range"; } break; case rt_PC: if (!is_write) { val->type = et_addr; val->value.as_addr = regs->regs_PC; } else regs->regs_PC = eval_as_addr(*val); break; case rt_NPC: if (!is_write) { val->type = et_addr; val->value.as_addr = regs->regs_NPC; } else regs->regs_NPC = eval_as_addr(*val); break; default: panic("bogus register bank"); } /* no error */ return NULL; }
/* print the value of stat variable STAT */ void stat_print_stat(struct stat_sdb_t *sdb, /* stat database */ struct stat_stat_t *stat,/* stat variable */ FILE *fd) /* output stream */ { struct eval_value_t val; switch (stat->sc) { case sc_int: fprintf(fd, "%-22s ", stat->name); myfprintf(fd, stat->format, *stat->variant.for_int.var); fprintf(fd, " # %s", stat->desc); break; case sc_uint: fprintf(fd, "%-22s ", stat->name); myfprintf(fd, stat->format, *stat->variant.for_uint.var); fprintf(fd, " # %s", stat->desc); break; #ifdef HOST_HAS_QWORD case sc_qword: { char buf[128]; fprintf(fd, "%-22s ", stat->name); mysprintf(buf, stat->format, *stat->variant.for_qword.var); fprintf(fd, "%s # %s", buf, stat->desc); } break; case sc_sqword: { char buf[128]; fprintf(fd, "%-22s ", stat->name); mysprintf(buf, stat->format, *stat->variant.for_sqword.var); fprintf(fd, "%s # %s", buf, stat->desc); } break; #endif /* HOST_HAS_QWORD */ case sc_float: fprintf(fd, "%-22s ", stat->name); myfprintf(fd, stat->format, (double)*stat->variant.for_float.var); fprintf(fd, " # %s", stat->desc); break; case sc_double: fprintf(fd, "%-22s ", stat->name); myfprintf(fd, stat->format, *stat->variant.for_double.var); fprintf(fd, " # %s", stat->desc); break; case sc_dist: print_dist(stat, fd); break; case sc_sdist: print_sdist(stat, fd); break; case sc_formula: { /* instantiate a new evaluator to avoid recursion problems */ struct eval_state_t *es = eval_new(stat_eval_ident, sdb); char *endp; fprintf(fd, "%-22s ", stat->name); val = eval_expr(es, stat->variant.for_formula.formula, &endp); if (eval_error != ERR_NOERR || *endp != '\0') fprintf(fd, "<error: %s>", eval_err_str[eval_error]); else myfprintf(fd, stat->format, eval_as_double(val)); fprintf(fd, " # %s", stat->desc); /* done with the evaluator */ eval_delete(es); } break; default: panic("bogus stat class"); } fprintf(fd, "\n"); }
double __math_xflow(uint32_t sign, double y) { return eval_as_double(fp_barrier(sign ? -y : y) * y); }