?? eio.cc
字號:
Addr page_addr; struct exo_term_t *blob; /* read the page */ exo = exo_read(fd); if (!exo || exo->ec != ec_list || !exo->as_list.head || exo->as_list.head->ec != ec_address || !exo->as_list.head->next || exo->as_list.head->next->ec != ec_blob || exo->as_list.head->next->next != NULL) fatal("could not read EIO memory page"); page_addr = (Addr) exo->as_list.head->as_integer.val; blob = exo->as_list.head->next; /* write data to simulator memory */ for (j = 0; j < blob->as_blob.size; j++) { uint8_t val; val = blob->as_blob.data[j]; /* unchecked access... */ memory->access(Write, page_addr, &val, 1); page_addr++; } exo_delete(exo); } return trans_icnt;}/* syscall proxy handler from an EIO trace, architect registers and memory are assumed to be precise when this function is called, register and memory are updated with the results of the system call */// Note that we pass in a memory object that may be different from the// process's memory object (mem field), since we may be executing the// syscall early in the pipeline on uncommitted memory state. It// might be reasonable to eliminate this parameter if we do syscalls// at commit time, or only after flushing the pipeline, etc.voidEioProcess::read_trace(RegFile *regs, /* registers to update */ FunctionalMemory *curmem, /* memory space */ Counter icnt) /* instruction count */{ int i; struct exo_term_t *exo = 0, *exo_icnt = 0, *exo_pc = 0; struct exo_term_t *exo_inregs = 0, *exo_inmem = 0, *exo_outregs = 0, *exo_outmem = 0; struct exo_term_t *brkrec, *regrec, *memrec; /* exit() system calls get executed for real... */ if (MD_EXIT_SYSCALL(regs)) { /* * FIXME: Not clear what to do for a multithreaded workload * where one thread may call exit before the simulation * is complete. */ panic("EIO program called exit()"); } /* else, read the external I/O (EIO) transaction */ exo = exo_read(eio_fd); /* if we started from a checkpoint, we need to add in the number of * instructions executed at the chkpt to the number simulated thus * far to get our distance from the start of the program */ icnt += chkpt_num_inst; /* pull apart the EIO transaction (EXO format) */ if (!exo || exo->ec != ec_list || !(exo_icnt = exo->as_list.head) || exo_icnt->ec != ec_integer || !(exo_pc = exo_icnt->next) || exo_pc->ec != ec_address || !(exo_inregs = exo_pc->next) || exo_inregs->ec != ec_list || !(exo_inmem = exo_inregs->next) || exo_inmem->ec != ec_list || !(exo_outregs = exo_inmem->next) || exo_outregs->ec != ec_list || !(exo_outmem = exo_outregs->next) || exo_outmem->ec != ec_list || exo_outmem->next != NULL) fatal("%s: cannot read EIO transaction", name()); /* * check the system call inputs */ /* check ICNT input */ if (icnt != (Counter) exo_icnt->as_integer.val) { ccprintf(cerr, "actual=%d, eio=%d\n", icnt, (Counter) exo_icnt->as_integer.val); fatal("%s: EIO trace inconsistency: ICNT mismatch", name()); } /* check PC input */ if (regs->pc != (Addr) exo_pc->as_integer.val) { ccprintf(cerr, "actual=%d, eio=%d\n", regs->pc, (Counter) exo_pc->as_integer.val); fatal("%s: EIO trace inconsistency: PC mismatch", name()); } /* check integer register inputs */ for (i = MD_FIRST_IN_REG, regrec = exo_inregs->as_list.head; i <= MD_LAST_IN_REG; i++, regrec = regrec->next) { if (!regrec || regrec->ec != ec_address) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: missing input reg", name()); } if (MD_EXO_CMP_IREG(regrec, regs, i)) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: R[%d] input mismatch", name(), i); }#ifdef VERBOSE ccprintf(cerr, "** R[%d] checks out...\n", i);#endif /* VERBOSE */ } if (regrec != NULL) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: too many input regs", name()); } /* check memory inputs */ for (memrec = exo_inmem->as_list.head; memrec != NULL; memrec = memrec->next) { Addr loc; struct exo_term_t *addr = 0, *blob = 0; /* check the mem transaction format */ if (!memrec || memrec->ec != ec_list || !(addr = memrec->as_list.head) || addr->ec != ec_address || !(blob = addr->next) || blob->ec != ec_blob || blob->next != NULL) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: bad memory transaction", name()); } for (loc = addr->as_integer.val, i = 0; i < blob->as_blob.size; loc++, i++) { unsigned char val; /* was: val = MEM_READ_BYTE(loc); */ curmem->access(Read, loc, &val, sizeof(unsigned char)); if (val != blob->as_blob.data[i]) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: " "addr 0x%08p input mismatch", name(), loc); }#ifdef VERBOSE ccprintf(cerr, "** %#08d checks out...\n", loc);#endif /* VERBOSE */ } /* echo stdout/stderr output */ if (MD_OUTPUT_SYSCALL(regs)) { int tgt_fd = MD_STREAM_FILENO(regs); if (tgt_fd == STDOUT_FILENO || tgt_fd == STDERR_FILENO) { int real_fd = sim_fd(tgt_fd); if (real_fd >= 0) { write(real_fd, blob->as_blob.data, blob->as_blob.size); } } } } /* * write system call outputs */ /* adjust breakpoint */ brkrec = exo_outregs->as_list.head; if (!brkrec || brkrec->ec != ec_address) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: missing memory breakpoint", name()); } brk_point = (Addr) brkrec->as_integer.val; /* write integer register outputs */ for (i = MD_FIRST_OUT_REG, regrec = exo_outregs->as_list.head->next; i <= MD_LAST_OUT_REG; i++, regrec = regrec->next) { if (!regrec || regrec->ec != ec_address) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: missing output reg", name()); } MD_EXO_TO_IREG(regrec, regs, i);#ifdef VERBOSE ccprintf(cerr, "** R[%d] written...\n", i);#endif /* VERBOSE */ } if (regrec != NULL) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace inconsistency: too many output regs", name()); } /* write memory outputs */ for (memrec = exo_outmem->as_list.head; memrec != NULL; memrec = memrec->next) { Addr loc; struct exo_term_t *addr = 0, *blob = 0; /* check the mem transaction format */ if (!memrec || memrec->ec != ec_list || !(addr = memrec->as_list.head) || addr->ec != ec_address || !(blob = addr->next) || blob->ec != ec_blob || blob->next != NULL) { ccprintf(cerr, "icount=%d, cycle=%d\n", icnt, curTick); fatal("%s: EIO trace icnonsistency: bad memory transaction", name()); } for (loc = addr->as_integer.val, i = 0; i < blob->as_blob.size; loc++, i++) { /* was: MEM_WRITE_BYTE(loc, blob->as_blob.data[i]); */ curmem->access(Write, loc, &blob->as_blob.data[i], sizeof(unsigned char));#ifdef VERBOSE ccprintf(cerr, "** %#08d written...\n", loc);#endif /* VERBOSE */ } } /* release the EIO EXO node */ exo_delete(exo);}/* fast forward EIO trace EIO_FD to the transaction just after ICNT */voideio_fast_forward(FILE * eio_fd, Counter icnt){ struct exo_term_t *exo; Counter this_icnt; do { /* read the next external I/O (EIO) transaction */ exo = exo_read(eio_fd); /* pull apart the EIO transaction (EXO format) */ if (!exo || exo->ec != ec_list || !exo->as_list.head || exo->as_list.head->ec != ec_integer) fatal("cannot read EIO transaction (during fast forward)"); this_icnt = exo->as_list.head->as_integer.val; exo_delete(exo); } while (this_icnt < icnt); /* instruction counts should match exactly */ if (this_icnt > icnt) fatal("EIO transaction icnt mismatch during fast forward");}EioProcess::EioProcess(const string &name, int stdout_fd, int stderr_fd, const string &eio_file, const string &chkpt_file) : Process(name, -1, // stdin_fd unused: all input redirecte from EIO trace stdout_fd, stderr_fd){ /* open the EIO file stream */ eio_fd = eio_open(eio_file); /* load initial state checkpoint */ if (read_chkpt(init_regs, eio_fd) != -1) fatal("bad initial checkpoint in EIO file"); /* load checkpoint? */ if (chkpt_file != "") { Counter restore_icnt; FILE *chkpt_fd; cerr << "sim: loading checkpoint file: " << chkpt_file << "\n"; if (!eio_valid(chkpt_file)) { cerr << "file `" << chkpt_file << "' does not appear to be a checkpoint file" << endl; cerr << " ==> Running without checkpoint!" << endl; } else { /* open the checkpoint file */ chkpt_fd = eio_open(chkpt_file); /* load the state image */ restore_icnt = read_chkpt(init_regs, chkpt_fd); /* fast forward the baseline EIO trace to checkpoint location */ ccprintf(cerr, "sim: fast forwarding to instruction %d\n", restore_icnt); eio_fast_forward(eio_fd, restore_icnt); eio_close(chkpt_fd); } } /* computed state... */ prog_entry = init_regs->pc;}voidEioProcess::syscall(ExecContext *xc){ num_syscalls++; read_trace(&xc->regs, xc->mem, xc->func_exe_inst);}BEGIN_DECLARE_SIM_OBJECT_PARAMS(EioProcess) Param<string> file; Param<string> chkpt; Param<string> output;END_DECLARE_SIM_OBJECT_PARAMS(EioProcess)BEGIN_INIT_SIM_OBJECT_PARAMS(EioProcess) INIT_PARAM(file, "EIO trace file name"), INIT_PARAM(chkpt, "EIO checkpoint file name (optional)"), INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)")END_INIT_SIM_OBJECT_PARAMS(EioProcess)CREATE_SIM_OBJECT(EioProcess){ // initialize file descriptors to default: same as simulator int stdout_fd, stderr_fd; string out = output; if (out == "stdout" || out == "cout") stdout_fd = STDOUT_FILENO; else if (out == "stderr" || out == "cerr") stdout_fd = STDERR_FILENO; else stdout_fd = Process::openOutputFile(out); stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO; return new EioProcess(getInstanceName(), stdout_fd, stderr_fd, file, chkpt);}REGISTER_SIM_OBJECT("EioProcess", EioProcess)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -