diff --git a/clients/drcachesim/common/memref.h b/clients/drcachesim/common/memref.h index a7eeed1d315..87ceb0c86b8 100644 --- a/clients/drcachesim/common/memref.h +++ b/clients/drcachesim/common/memref.h @@ -44,27 +44,56 @@ typedef int_least64_t memref_pid_t; typedef int_least64_t memref_tid_t; -typedef struct _memref_t { +// Each trace entry is one of the following. +// Although the pc of each data reference is provided, the trace also guarantees that +// an instruction entry immediately precedes the data references that it is +// responsible for, with no intervening trace entries. + +struct _memref_data_t { + // TRACE_TYPE_READ, TRACE_TYPE_WRITE, and TRACE_TYPE_PREFETCH*: + // data references. + trace_type_t type; memref_pid_t pid; memref_tid_t tid; + addr_t addr; + size_t size; + addr_t pc; +}; - // The types are shared with trace_entry_t, but the types - // TRACE_TYPE_INSTR_BUNDLE, TRACE_TYPE_*_FLUSH_END, TRACE_TYPE_THREAD, and - // TRACE_TYPE_PID never show up here and are only found in trace_entry_t. - // The reader_t class places their data into other parts of memref_t. - unsigned short type; // trace_type_t - - // Fields below here are not valid for TRACE_TYPE_THREAD_EXIT. - +struct _memref_instr_t { + // TRACE_TYPE_INSTR: instruction fetch. + trace_type_t type; + memref_pid_t pid; + memref_tid_t tid; + addr_t addr; size_t size; - addr_t addr; // Data or instruction address. +}; - // The pc field is only used for read, write, and prefetch entries. - // XXX: should we remove it from here and have the simulator compute it - // from instr entries? Though if the user turns off icache simulation - // it may be better to keep it as a field here and have the reader - // fill it in for us. +struct _memref_flush_t { + // TRACE_TYPE_INSTR_FLUSH, TRACE_TYPE_DATA_FLUSH: explicit cache flush. + trace_type_t type; + memref_pid_t pid; + memref_tid_t tid; + addr_t addr; + size_t size; addr_t pc; +}; + +struct _memref_thread_exit_t { + // TRACE_TYPE_THREAD_EXIT. + trace_type_t type; + memref_pid_t pid; + memref_tid_t tid; +}; + +typedef union _memref_t { + // The C standard allows us to reference the type field of any of these, and the + // addr and size fields of data, instr, or flush generically if known to be one + // of those types, due to the shared fields in our union of structs. + struct _memref_data_t data; + struct _memref_instr_t instr; + struct _memref_flush_t flush; + struct _memref_thread_exit_t exit; } memref_t; #endif /* _MEMREF_H_ */ diff --git a/clients/drcachesim/reader/reader.cpp b/clients/drcachesim/reader/reader.cpp index 3e75fa32ce6..adfad1853a4 100644 --- a/clients/drcachesim/reader/reader.cpp +++ b/clients/drcachesim/reader/reader.cpp @@ -85,35 +85,33 @@ reader_t::operator++() case TRACE_TYPE_PREFETCH_WRITE: case TRACE_TYPE_PREFETCH_INSTR: have_memref = true; - cur_ref.pid = cur_pid; - cur_ref.tid = cur_tid; - cur_ref.type = input_entry->type; - cur_ref.size = input_entry->size; - cur_ref.addr = input_entry->addr; + cur_ref.data.pid = cur_pid; + cur_ref.data.tid = cur_tid; + cur_ref.data.type = (trace_type_t) input_entry->type; + cur_ref.data.size = input_entry->size; + cur_ref.data.addr = input_entry->addr; // The trace stream always has the instr fetch first, which we // use to obtain the PC for subsequent data references. - cur_ref.pc = cur_pc; + cur_ref.data.pc = cur_pc; break; case TRACE_TYPE_INSTR: have_memref = true; - cur_ref.pid = cur_pid; - cur_ref.tid = cur_tid; - cur_ref.type = input_entry->type; - cur_ref.size = input_entry->size; + cur_ref.instr.pid = cur_pid; + cur_ref.instr.tid = cur_tid; + cur_ref.instr.type = (trace_type_t) input_entry->type; + cur_ref.instr.size = input_entry->size; cur_pc = input_entry->addr; - cur_ref.addr = cur_pc; - cur_ref.pc = cur_pc; - next_pc = cur_pc + cur_ref.size; + cur_ref.instr.addr = cur_pc; + next_pc = cur_pc + cur_ref.instr.size; break; case TRACE_TYPE_INSTR_BUNDLE: have_memref = true; // The trace stream always has the instr fetch first, which we // use to compute the starting PC for the subsequent instructions. - cur_ref.size = input_entry->length[bundle_idx++]; + cur_ref.instr.size = input_entry->length[bundle_idx++]; cur_pc = next_pc; - cur_ref.pc = cur_pc; - cur_ref.addr = cur_pc; - next_pc = cur_pc + cur_ref.size; + cur_ref.instr.addr = cur_pc; + next_pc = cur_pc + cur_ref.instr.size; // input_entry->size stores the number of instrs in this bundle assert(input_entry->size <= sizeof(input_entry->length)); if (bundle_idx == input_entry->size) @@ -121,17 +119,17 @@ reader_t::operator++() break; case TRACE_TYPE_INSTR_FLUSH: case TRACE_TYPE_DATA_FLUSH: - cur_ref.pid = cur_pid; - cur_ref.tid = cur_tid; - cur_ref.type = input_entry->type; - cur_ref.size = input_entry->size; - cur_ref.addr = input_entry->addr; - if (cur_ref.size != 0) + cur_ref.flush.pid = cur_pid; + cur_ref.flush.tid = cur_tid; + cur_ref.flush.type = (trace_type_t) input_entry->type; + cur_ref.flush.size = input_entry->size; + cur_ref.flush.addr = input_entry->addr; + if (cur_ref.flush.size != 0) have_memref = true; break; case TRACE_TYPE_INSTR_FLUSH_END: case TRACE_TYPE_DATA_FLUSH_END: - cur_ref.size = input_entry->addr - cur_ref.addr; + cur_ref.flush.size = input_entry->addr - cur_ref.flush.addr; have_memref = true; break; case TRACE_TYPE_THREAD: @@ -142,9 +140,9 @@ reader_t::operator++() cur_tid = (memref_tid_t) input_entry->addr; cur_pid = tid2pid[cur_tid]; // We do pass this to the caller but only some fields are valid: - cur_ref.pid = cur_pid; - cur_ref.tid = cur_tid; - cur_ref.type = input_entry->type; + cur_ref.exit.pid = cur_pid; + cur_ref.exit.tid = cur_tid; + cur_ref.exit.type = (trace_type_t) input_entry->type; have_memref = true; break; case TRACE_TYPE_PID: diff --git a/clients/drcachesim/simulator/cache.cpp b/clients/drcachesim/simulator/cache.cpp index 7eab6e42df4..8b5c945fa33 100644 --- a/clients/drcachesim/simulator/cache.cpp +++ b/clients/drcachesim/simulator/cache.cpp @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2015 Google, Inc. All rights reserved. + * Copyright (c) 2015-2016 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -64,8 +64,9 @@ cache_t::request(const memref_t &memref_in) void cache_t::flush(const memref_t &memref) { - addr_t tag = compute_tag(memref.addr); - addr_t final_tag = compute_tag(memref.addr + memref.size - 1/*no overflow*/); + addr_t tag = compute_tag(memref.flush.addr); + addr_t final_tag = compute_tag(memref.flush.addr + + memref.flush.size - 1/*no overflow*/); last_tag = TAG_INVALID; for (; tag <= final_tag; ++tag) { int block_idx = compute_block_idx(tag); diff --git a/clients/drcachesim/simulator/cache_simulator.cpp b/clients/drcachesim/simulator/cache_simulator.cpp index 081dabc04b6..cc29abd17e4 100644 --- a/clients/drcachesim/simulator/cache_simulator.cpp +++ b/clients/drcachesim/simulator/cache_simulator.cpp @@ -142,29 +142,29 @@ cache_simulator_t::process_memref(const memref_t &memref) // not practical to measure which core each thread actually // ran on for each memref. int core; - if (memref.tid == last_thread) + if (memref.data.tid == last_thread) core = last_core; else { - core = core_for_thread(memref.tid); - last_thread = memref.tid; + core = core_for_thread(memref.data.tid); + last_thread = memref.data.tid; last_core = core; } - if (memref.type == TRACE_TYPE_INSTR || - memref.type == TRACE_TYPE_PREFETCH_INSTR) + if (memref.instr.type == TRACE_TYPE_INSTR || + memref.instr.type == TRACE_TYPE_PREFETCH_INSTR) icaches[core]->request(memref); - else if (memref.type == TRACE_TYPE_READ || - memref.type == TRACE_TYPE_WRITE || + 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.type)) + type_is_prefetch(memref.data.type)) dcaches[core]->request(memref); - else if (memref.type == TRACE_TYPE_INSTR_FLUSH) + else if (memref.flush.type == TRACE_TYPE_INSTR_FLUSH) icaches[core]->flush(memref); - else if (memref.type == TRACE_TYPE_DATA_FLUSH) + else if (memref.flush.type == TRACE_TYPE_DATA_FLUSH) dcaches[core]->flush(memref); - else if (memref.type == TRACE_TYPE_THREAD_EXIT) { - handle_thread_exit(memref.tid); + else if (memref.exit.type == TRACE_TYPE_THREAD_EXIT) { + handle_thread_exit(memref.exit.tid); last_thread = 0; } else { ERRMSG("unhandled memref type"); @@ -172,10 +172,10 @@ cache_simulator_t::process_memref(const memref_t &memref) } 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; + 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 << std::endl; } // process counters for warmup and simulated references diff --git a/clients/drcachesim/simulator/cache_stats.cpp b/clients/drcachesim/simulator/cache_stats.cpp index 8823effc9be..2ae7e9f9216 100644 --- a/clients/drcachesim/simulator/cache_stats.cpp +++ b/clients/drcachesim/simulator/cache_stats.cpp @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2015 Google, Inc. All rights reserved. + * Copyright (c) 2015-2016 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -43,7 +43,7 @@ void cache_stats_t::access(const memref_t &memref, bool hit) { // handle prefetching requests - if (type_is_prefetch(memref.type)) { + if (type_is_prefetch(memref.data.type)) { if (hit) num_prefetch_hits++; else diff --git a/clients/drcachesim/simulator/caching_device.cpp b/clients/drcachesim/simulator/caching_device.cpp index c3ab7bda925..36bde147922 100644 --- a/clients/drcachesim/simulator/caching_device.cpp +++ b/clients/drcachesim/simulator/caching_device.cpp @@ -89,9 +89,9 @@ caching_device_t::request(const memref_t &memref_in) // We support larger sizes to improve the IPC perf. // This means that one memref could touch multiple blocks. // We treat each block separately for statistics purposes. - addr_t final_addr = memref_in.addr + memref_in.size - 1/*avoid overflow*/; + addr_t final_addr = memref_in.data.addr + memref_in.data.size - 1/*avoid overflow*/; addr_t final_tag = compute_tag(final_addr); - addr_t tag = compute_tag(memref_in.addr); + addr_t tag = compute_tag(memref_in.data.addr); // Optimization: check last tag if single-block if (tag == final_tag && tag == last_tag) { @@ -111,7 +111,7 @@ caching_device_t::request(const memref_t &memref_in) int block_idx = compute_block_idx(tag); if (tag + 1 <= final_tag) - memref.size = ((tag + 1) << block_size_bits) - memref.addr; + memref.data.size = ((tag + 1) << block_size_bits) - memref.data.addr; for (way = 0; way < associativity; ++way) { if (get_caching_device_block(block_idx, way).tag == tag) { @@ -140,8 +140,8 @@ caching_device_t::request(const memref_t &memref_in) if (tag + 1 <= final_tag) { addr_t next_addr = (tag + 1) << block_size_bits; - memref.addr = next_addr; - memref.size = final_addr - next_addr + 1/*undo the -1*/; + memref.data.addr = next_addr; + memref.data.size = final_addr - next_addr + 1/*undo the -1*/; } // Optimization: remember last tag last_tag = tag; diff --git a/clients/drcachesim/simulator/tlb.cpp b/clients/drcachesim/simulator/tlb.cpp index 2c73f141cb5..b65381a2ecd 100644 --- a/clients/drcachesim/simulator/tlb.cpp +++ b/clients/drcachesim/simulator/tlb.cpp @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2015 Google, Inc. All rights reserved. + * Copyright (c) 2015-2016 Google, Inc. All rights reserved. * **********************************************************/ /* @@ -56,10 +56,10 @@ tlb_t::request(const memref_t &memref_in) // We support larger sizes to improve the IPC perf. // This means that one memref could touch multiple blocks. // We treat each block separately for statistics purposes. - addr_t final_addr = memref_in.addr + memref_in.size - 1/*avoid overflow*/; + addr_t final_addr = memref_in.data.addr + memref_in.data.size - 1/*avoid overflow*/; addr_t final_tag = compute_tag(final_addr); - addr_t tag = compute_tag(memref_in.addr); - memref_pid_t pid = memref_in.pid; + addr_t tag = compute_tag(memref_in.data.addr); + memref_pid_t pid = memref_in.data.pid; // Optimization: check last tag and pid if single-block if (tag == final_tag && tag == last_tag && pid == last_pid) { @@ -81,7 +81,7 @@ tlb_t::request(const memref_t &memref_in) int block_idx = compute_block_idx(tag); if (tag + 1 <= final_tag) - memref.size = ((tag + 1) << block_size_bits) - memref.addr; + memref.data.size = ((tag + 1) << block_size_bits) - memref.data.addr; for (way = 0; way < associativity; ++way) { if (get_caching_device_block(block_idx, way).tag == tag && @@ -112,8 +112,8 @@ tlb_t::request(const memref_t &memref_in) if (tag + 1 <= final_tag) { addr_t next_addr = (tag + 1) << block_size_bits; - memref.addr = next_addr; - memref.size = final_addr - next_addr + 1/*undo the -1*/; + memref.data.addr = next_addr; + memref.data.size = final_addr - next_addr + 1/*undo the -1*/; } // Optimization: remember last tag and pid last_tag = tag; diff --git a/clients/drcachesim/simulator/tlb_simulator.cpp b/clients/drcachesim/simulator/tlb_simulator.cpp index cdd1b8a9896..0f96acc4e5d 100644 --- a/clients/drcachesim/simulator/tlb_simulator.cpp +++ b/clients/drcachesim/simulator/tlb_simulator.cpp @@ -129,26 +129,26 @@ tlb_simulator_t::process_memref(const memref_t &memref) // not practical to measure which core each thread actually // ran on for each memref. int core; - if (memref.tid == last_thread) + if (memref.data.tid == last_thread) core = last_core; else { - core = core_for_thread(memref.tid); - last_thread = memref.tid; + core = core_for_thread(memref.data.tid); + last_thread = memref.data.tid; last_core = core; } - if (memref.type == TRACE_TYPE_INSTR) + if (memref.instr.type == TRACE_TYPE_INSTR) itlbs[core]->request(memref); - else if (memref.type == TRACE_TYPE_READ || - memref.type == TRACE_TYPE_WRITE) + else if (memref.data.type == TRACE_TYPE_READ || + memref.data.type == TRACE_TYPE_WRITE) dtlbs[core]->request(memref); - else if (memref.type == TRACE_TYPE_THREAD_EXIT) { - handle_thread_exit(memref.tid); + else if (memref.exit.type == TRACE_TYPE_THREAD_EXIT) { + handle_thread_exit(memref.exit.tid); last_thread = 0; } - else if (type_is_prefetch(memref.type) || - memref.type == TRACE_TYPE_INSTR_FLUSH || - memref.type == TRACE_TYPE_DATA_FLUSH) { + else if (type_is_prefetch(memref.data.type) || + memref.flush.type == TRACE_TYPE_INSTR_FLUSH || + memref.flush.type == TRACE_TYPE_DATA_FLUSH) { // TLB simulator ignores prefetching and cache flushing } else { ERRMSG("unhandled memref type"); @@ -156,10 +156,10 @@ tlb_simulator_t::process_memref(const memref_t &memref) } 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; + 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 << std::endl; } // process counters for warmup and simulated references diff --git a/clients/drcachesim/tools/histogram.cpp b/clients/drcachesim/tools/histogram.cpp index cfb17fa3e01..8fce552580f 100644 --- a/clients/drcachesim/tools/histogram.cpp +++ b/clients/drcachesim/tools/histogram.cpp @@ -53,15 +53,15 @@ histogram_t::~histogram_t() bool histogram_t::process_memref(const memref_t &memref) { - if (memref.type == TRACE_TYPE_INSTR || - memref.type == TRACE_TYPE_PREFETCH_INSTR) - ++icache_map[memref.addr >> line_size_bits]; - else if (memref.type == TRACE_TYPE_READ || - memref.type == TRACE_TYPE_WRITE || + if (memref.instr.type == TRACE_TYPE_INSTR || + memref.instr.type == TRACE_TYPE_PREFETCH_INSTR) + ++icache_map[memref.instr.addr >> line_size_bits]; + 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.type)) - ++dcache_map[memref.addr >> line_size_bits]; + type_is_prefetch(memref.data.type)) + ++dcache_map[memref.data.addr >> line_size_bits]; return true; }