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 reuse_time_t::process_memref(const memref_t &memref) { if (DEBUG_VERBOSE(3)) { std::cerr << " ::" << memref.data.pid << "." << memref.data.tid << ":: " << trace_type_names[memref.data.type]; if (memref.data.type != TRACE_TYPE_THREAD_EXIT) { std::cerr << " @ "; if (!type_is_instr(memref.data.type)) std::cerr << (void *)memref.data.pc << " "; std::cerr << (void *)memref.data.addr << " x" << memref.data.size; } std::cerr << std::endl; } // Only care about data for now. if (type_is_instr(memref.instr.type)) { total_instructions++; return true; } // Ignore thread events and other tracing metadata. if (memref.data.type != TRACE_TYPE_READ && memref.data.type != TRACE_TYPE_WRITE && !type_is_prefetch(memref.data.type)) { return true; } time_stamp++; addr_t line = memref.data.addr >> line_size_bits; if (time_map.count(line) > 0) { int_least64_t reuse_time = time_stamp - time_map[line]; if (DEBUG_VERBOSE(3)) { std::cerr << "Reuse " << reuse_time << std::endl; } reuse_time_histogram[reuse_time]++; } time_map[line] = time_stamp; return true; }
bool basic_counts_t::process_memref(const memref_t &memref) { if (type_is_instr(memref.instr.type)) { ++thread_instrs[memref.instr.tid]; ++total_instrs; } else if (memref.data.type == TRACE_TYPE_INSTR_NO_FETCH) { ++thread_instrs_nofetch[memref.instr.tid]; ++total_instrs_nofetch; } else if (type_is_prefetch(memref.data.type)) { ++thread_prefetches[memref.data.tid]; ++total_prefetches; } else if (memref.data.type == TRACE_TYPE_READ) { ++thread_loads[memref.data.tid]; ++total_loads; } else if (memref.data.type == TRACE_TYPE_WRITE) { ++thread_stores[memref.data.tid]; ++total_stores; } else if (memref.marker.type == TRACE_TYPE_MARKER) { if (memref.marker.marker_type == TRACE_MARKER_TYPE_TIMESTAMP || memref.marker.marker_type == TRACE_MARKER_TYPE_CPU_ID) { ++thread_sched_markers[memref.data.tid]; ++total_sched_markers; } else if (memref.marker.marker_type == TRACE_MARKER_TYPE_KERNEL_EVENT || memref.marker.marker_type == TRACE_MARKER_TYPE_KERNEL_XFER) { ++thread_xfer_markers[memref.data.tid]; ++total_xfer_markers; } else { ++thread_other_markers[memref.data.tid]; ++total_other_markers; } } else if (memref.exit.type == TRACE_TYPE_THREAD_EXIT) { ++total_threads; } 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; }