bool simulator_t::run() { if (!ipc_iter.init()) { ERROR("failed to read from pipe %s", op_ipc_name.get_value().c_str()); return false; } memref_tid_t last_thread = 0; int last_core = 0; // XXX i#1703: add options to select either ipc_reader_t or // a recorded trace file reader, and use a base class reader_t // here. for (; ipc_iter != ipc_end; ++ipc_iter) { memref_t memref = *ipc_iter; // We use a static scheduling of threads to cores, as it is // not practical to measure which core each thread actually // ran on for each memref. int core; if (memref.tid == last_thread) core = last_core; else { core = core_for_thread(memref.tid); last_thread = memref.tid; last_core = core; } if (memref.type == TRACE_TYPE_INSTR || memref.type == TRACE_TYPE_PREFETCH_INSTR) icaches[core].request(memref); else if (memref.type == TRACE_TYPE_READ || memref.type == TRACE_TYPE_WRITE || // We may potentially handle prefetches differently. // TRACE_TYPE_PREFETCH_INSTR is handled above. type_is_prefetch(memref.type)) dcaches[core].request(memref); else if (memref.type == TRACE_TYPE_INSTR_FLUSH) icaches[core].flush(memref); else if (memref.type == TRACE_TYPE_DATA_FLUSH) dcaches[core].flush(memref); else if (memref.type == TRACE_TYPE_THREAD_EXIT) { handle_thread_exit(memref.tid); last_thread = 0; } else { ERROR("unhandled memref type"); return false; } if (op_verbose.get_value() >= 3) { std::cerr << "::" << memref.pid << "." << memref.tid << ":: " << " @" << (void *)memref.pc << " " << trace_type_names[memref.type] << " " << (void *)memref.addr << " x" << memref.size << std::endl; } } return true; }
bool cache_simulator_t::process_memref(const memref_t &memref) { if (knobs.skip_refs > 0) { knobs.skip_refs--; return true; } // The references after warmup and simulated ones are dropped. if (check_warmed_up() && knobs.sim_refs == 0) return true;; // Both warmup and simulated references are simulated. simulator_t::process_memref(memref); if (memref.marker.type == TRACE_TYPE_MARKER) { // We ignore markers before we ask core_for_thread, to avoid asking // too early on a timestamp marker. if (knobs.verbose >= 3) { std::cerr << "::" << memref.data.pid << "." << memref.data.tid << ":: " << "marker type " << memref.marker.marker_type << " value " << memref.marker.marker_value << "\n"; } return true; } // We use a static scheduling of threads to cores, as it is // not practical to measure which core each thread actually // ran on for each memref. int core; if (memref.data.tid == last_thread) core = last_core; else { core = core_for_thread(memref.data.tid); last_thread = memref.data.tid; last_core = core; } if (type_is_instr(memref.instr.type) || memref.instr.type == TRACE_TYPE_PREFETCH_INSTR) { if (knobs.verbose >= 3) { std::cerr << "::" << memref.data.pid << "." << memref.data.tid << ":: " << " @" << (void *)memref.instr.addr << " instr x" << memref.instr.size << "\n"; } icaches[core]->request(memref); } else if (memref.data.type == TRACE_TYPE_READ || memref.data.type == TRACE_TYPE_WRITE || // We may potentially handle prefetches differently. // TRACE_TYPE_PREFETCH_INSTR is handled above. type_is_prefetch(memref.data.type)) { if (knobs.verbose >= 3) { std::cerr << "::" << memref.data.pid << "." << memref.data.tid << ":: " << " @" << (void *)memref.data.pc << " " << trace_type_names[memref.data.type] << " " << (void *)memref.data.addr << " x" << memref.data.size << "\n"; } dcaches[core]->request(memref); } else if (memref.flush.type == TRACE_TYPE_INSTR_FLUSH) { if (knobs.verbose >= 3) { std::cerr << "::" << memref.data.pid << "." << memref.data.tid << ":: " << " @" << (void *)memref.data.pc << " iflush " << (void *)memref.data.addr << " x" << memref.data.size << "\n"; } icaches[core]->flush(memref); } else if (memref.flush.type == TRACE_TYPE_DATA_FLUSH) { if (knobs.verbose >= 3) { std::cerr << "::" << memref.data.pid << "." << memref.data.tid << ":: " << " @" << (void *)memref.data.pc << " dflush " << (void *)memref.data.addr << " x" << memref.data.size << "\n"; } dcaches[core]->flush(memref); } else if (memref.exit.type == TRACE_TYPE_THREAD_EXIT) { handle_thread_exit(memref.exit.tid); last_thread = 0; } else if (memref.marker.type == TRACE_TYPE_INSTR_NO_FETCH) { // Just ignore. if (knobs.verbose >= 3) { std::cerr << "::" << memref.data.pid << "." << memref.data.tid << ":: " << " @" << (void *)memref.instr.addr << " non-fetched instr x" << memref.instr.size << "\n"; } } else { ERRMSG("unhandled memref type"); return false; } // reset cache stats when warming up is completed if (!is_warmed_up && check_warmed_up()) { for (unsigned int i = 0; i < knobs.num_cores; i++) { icaches[i]->get_stats()->reset(); dcaches[i]->get_stats()->reset(); } llcache->get_stats()->reset(); if (knobs.verbose >= 1) { std::cerr << "Cache simulation warmed up\n"; } } else { knobs.sim_refs--; } return true; }