Go to the documentation of this file.
44 #include "debug/ElasticTrace.hh"
52 depWindowSize(params->depWindowSize),
53 dataTraceStream(
nullptr),
54 instTraceStream(
nullptr),
55 startTraceInst(params->startTraceInst),
57 traceVirtAddr(params->traceVirtAddr),
61 fatal_if(!cpu,
"Manager of %s is not of type O3CPU and thus does not "\
62 "support dependency tracing.\n",
name());
64 fatal_if(depWindowSize == 0,
"depWindowSize parameter must be non-zero. "\
65 "Recommended size is 3x ROB size in the O3CPU.\n");
67 fatal_if(cpu->numThreads > 1,
"numThreads = %i, %s supports tracing for"\
68 "single-threaded workload only", cpu->numThreads,
name());
70 fatal_if(params->instFetchTraceFile ==
"",
"Assign instruction fetch "\
71 "trace file path to instFetchTraceFile");
72 fatal_if(params->dataDepTraceFile ==
"",
"Assign data dependency "\
73 "trace file path to dataDepTraceFile");
75 params->instFetchTraceFile);
80 ProtoMessage::PacketHeader inst_pkt_header;
81 inst_pkt_header.set_obj_id(
name());
83 instTraceStream->write(inst_pkt_header);
86 ProtoMessage::InstDepRecordHeader data_rec_header;
87 data_rec_header.set_obj_id(
name());
89 data_rec_header.set_window_size(depWindowSize);
90 dataTraceStream->write(data_rec_header);
98 inform(
"@%llu: regProbeListeners() called, startTraceInst = %llu",
116 inform(
"@%llu: No. of instructions committed = %llu, registering elastic"
148 req->getPC(), req->getVaddr(), req->getPaddr(),
149 req->getFlags(), req->getSize(),
curTick());
154 inst_fetch_pkt.set_tick(
curTick());
156 inst_fetch_pkt.set_pc(req->getPC());
157 inst_fetch_pkt.set_flags(req->getFlags());
158 inst_fetch_pkt.set_addr(req->getPaddr());
159 inst_fetch_pkt.set_size(req->getSize());
175 has already retired (mostly squashed)", dyn_inst->seqNum);
188 auto itr_exec_info =
tempStore.find(dyn_inst->seqNum);
190 exec_info_ptr = itr_exec_info->second;
193 tempStore[dyn_inst->seqNum] = exec_info_ptr;
208 auto itr_exec_info =
tempStore.find(dyn_inst->seqNum);
211 " skipping.\n", dyn_inst->seqNum);
239 int8_t max_regs = dyn_inst->numSrcRegs();
240 for (
int src_idx = 0; src_idx < max_regs; src_idx++) {
242 const RegId& src_reg = dyn_inst->srcRegIdx(src_idx);
246 PhysRegIdPtr phys_src_reg = dyn_inst->renamedSrcRegIdx(src_idx);
248 " %i (%s)\n", seq_num,
270 max_regs = dyn_inst->numDestRegs();
271 for (
int dest_idx = 0; dest_idx < max_regs; dest_idx++) {
274 const RegId& dest_reg = dyn_inst->destRegIdx(dest_idx);
279 PhysRegIdPtr phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx);
281 " %i (%s)\n", seq_num, phys_dest_reg->
flatIndex(),
294 inst_reg_pair.second);
295 auto itr_regdep_map =
physRegDepMap.find(inst_reg_pair.second);
306 auto itr_exec_info =
tempStore.find(head_inst->seqNum);
318 head_inst->hasRequest() &&
319 head_inst->getFault() ==
NoFault) {
335 if (!head_inst->isNop()) {
341 auto itr_temp_store =
tempStore.find(head_inst->seqNum);
344 "store, skipping.\n", head_inst->seqNum);
364 if (head_inst->getFault() !=
NoFault) {
366 "skip adding it to the trace\n",
367 (head_inst->isMemRef() ?
"Load/store" :
"Comp inst."),
369 }
else if (head_inst->isMemRef() && !head_inst->hasRequest()) {
371 "skip adding it to the trace\n", head_inst->seqNum);
372 }
else if (!head_inst->readPredicate()) {
374 "skip adding it to the trace\n",
375 (head_inst->isMemRef() ?
"Load/store" :
"Comp inst."),
397 new_record->
instNum = head_inst->seqNum;
398 new_record->
commit = commit;
399 new_record->
type = head_inst->isLoad() ? Record::LOAD :
400 (head_inst->isStore() ? Record::STORE :
404 new_record->
reqFlags = head_inst->memReqFlags;
405 new_record->
virtAddr = head_inst->effAddr;
406 new_record->
physAddr = head_inst->physEffAddr;
408 new_record->
size = head_inst->effSize;
409 new_record->
pc = head_inst->instAddr();
435 if (head_inst->isLoad() && !commit) {
440 std::set<InstSeqNum>::const_iterator dep_set_it;
450 "%lli\n", new_record->
instNum, *dep_set_it);
451 TraceInfo* reg_dep = trace_info_itr->second;
467 "%lli is skipped\n",new_record->
instNum, *dep_set_it);
475 if (head_inst->isStore()) {
496 (commit ?
"committed" :
"squashed"), new_record->
instNum);
517 bool find_load_not_store)
525 uint32_t num_go_back = 0;
530 while (num_go_back <
depWindowSize && from_itr != until_itr) {
531 if (find_load_not_store) {
551 past_record = *from_itr;
565 uint32_t num_go_back = 0;
566 Tick execute_tick = 0;
568 if (new_record->
isLoad()) {
572 }
else if (new_record->
isStore()) {
585 while (num_go_back <
depWindowSize && from_itr != until_itr) {
597 past_record = *from_itr;
620 Tick execute_tick)
const
627 Tick execute_tick)
const
635 Tick execute_tick)
const
644 Tick execute_tick)
const
657 auto itr_exec_info =
tempStore.find(temp_sn);
661 delete exec_info_ptr;
677 int64_t comp_delay = -1;
678 Tick execution_tick = 0, completion_tick = 0;
687 if (past_record->
isLoad()) {
693 }
else if (past_record->
isStore()) {
695 }
else if (past_record->
isComp()){
698 assert(execution_tick >= completion_tick);
699 comp_delay = execution_tick - completion_tick;
702 execution_tick, completion_tick, comp_delay);
721 int64_t comp_delay = -1;
722 Tick execution_tick = 0, completion_tick = 0;
740 assert(execution_tick >= completion_tick);
741 comp_delay = execution_tick - completion_tick;
743 execution_tick, completion_tick, comp_delay);
787 uint16_t num_filtered_nodes = 0;
790 while (num_to_write > 0) {
792 assert(temp_ptr->
type != Record::INVALID);
799 "is as follows:\n", temp_ptr->
instNum);
803 "size %i, flags %i\n", temp_ptr->
physAddr,
811 }
else if (temp_ptr->
isStore()) {
822 ProtoMessage::InstDepRecord dep_pkt;
823 dep_pkt.set_seq_num(temp_ptr->
instNum);
824 dep_pkt.set_type(temp_ptr->
type);
825 dep_pkt.set_pc(temp_ptr->
pc);
827 dep_pkt.set_flags(temp_ptr->
reqFlags);
828 dep_pkt.set_p_addr(temp_ptr->
physAddr);
832 dep_pkt.set_v_addr(temp_ptr->
virtAddr);
833 dep_pkt.set_size(temp_ptr->
size);
835 dep_pkt.set_comp_delay(temp_ptr->
compDelay);
842 dep_pkt.add_rob_dep(temp_ptr->
robDepList.front());
854 if (num_filtered_nodes != 0) {
859 dep_pkt.set_weight(num_filtered_nodes);
860 num_filtered_nodes = 0;
868 ++num_filtered_nodes;
875 depTrace.erase(dep_trace_itr_start, dep_trace_itr);
880 ADD_STAT(numRegDep,
"Number of register dependencies recorded during"
882 ADD_STAT(numOrderDepStores,
"Number of commit order (rob) dependencies"
883 " for a store recorded on a past load/store during tracing"),
884 ADD_STAT(numIssueOrderDepLoads,
"Number of loads that got assigned"
885 " issue order dependency because they were dependency-free"),
886 ADD_STAT(numIssueOrderDepStores,
"Number of stores that got assigned"
887 " issue order dependency because they were dependency-free"),
888 ADD_STAT(numIssueOrderDepOther,
"Number of non load/store insts that"
889 " got assigned issue order dependency because they were"
891 ADD_STAT(numFilteredNodes,
"No. of nodes filtered out before writing"
892 " the output trace"),
893 ADD_STAT(maxNumDependents,
"Maximum number or dependents on any"
895 ADD_STAT(maxTempStoreSize,
"Maximum size of the temporary store during"
897 ADD_STAT(maxPhysRegDepMapSize,
"Maximum size of register dependency map")
904 return Record::RecordType_Name(
type);
924 ElasticTraceParams::create()
The elastic trace is a type of probe listener and listens to probe points in multiple stages of the O...
void write(const google::protobuf::Message &msg)
Write a message to the stream, preprending it with the message size.
bool isMiscReg() const
@Return true if it is a condition-code physical register.
std::unordered_map< PhysRegIndex, InstSeqNum > physRegDepMap
Map for recording the producer of a physical register to check Read After Write dependencies.
std::unordered_map< InstSeqNum, TraceInfo * > traceInfoMap
Map where the instruction sequence number is mapped to the pointer to the TraceInfo object.
void recordToCommTick(const DynInstConstPtr &dyn_inst)
Populate the timestamp field in an InstExecInfo object for an instruction in flight when it is execut...
bool isZeroReg() const
Check if this is the zero register.
bool isStore() const
Is the record a store.
bool hasCompCompleted(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a comp node that completed earlier than the execute tick.
const char * className() const
Return a const char* with the register class name.
void clearTempStoreUntil(const DynInstConstPtr &head_inst)
Clear entries in the temporary store of execution info objects to free allocated memory until the pre...
static int numSimulatedInsts()
const InstSeqNum startTraceInst
Number of instructions after which to enable tracing.
InstSeqNum lastClearedSeqNum
The last cleared instruction sequence number used to free up the memory allocated in the temporary st...
Stats::Scalar numIssueOrderDepOther
Number of non load/store insts that got assigned an issue order dependency because they were dependen...
void updateIssueOrderDep(TraceInfo *new_record)
Reverse iterate through the graph, search for an issue order dependency for a new node and update the...
int64_t compDelay
Computational delay after the last dependent inst.
bool hasLoadCompleted(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a load that completed earlier than the execute tick.
void regEtraceListeners()
Register all listeners.
void flushTraces()
Process any outstanding trace records, flush them out to the protobuf output streams and delete the s...
void regProbeListeners()
Register the probe listeners that is the methods called on a probe point notify() call.
const bool traceVirtAddr
Whether to trace virtual addresses for memory requests.
void fetchReqTrace(const RequestPtr &req)
Take the fields of the request class object that are relevant to create an instruction fetch request.
Stats::Scalar numIssueOrderDepStores
Number of store insts that got assigned an issue order dependency because they were dependency-free.
uint64_t Tick
Tick count type.
const PhysRegIndex & flatIndex() const
Flat index accessor.
void compDelayPhysRegDep(TraceInfo *past_record, TraceInfo *new_record)
Calculate the computational delay between an instruction and a subsequent instruction that has a Phys...
bool isLoad() const
Is the record a load.
std::shared_ptr< Request > RequestPtr
Stats::Scalar maxTempStoreSize
Maximum size of the temporary store mostly useful as a check that it is not growing.
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
const std::string & typeToStr() const
Return string specifying the type of the node.
Stats::Scalar maxPhysRegDepMapSize
Maximum size of the map that holds the last writer to a physical register.
void updateRegDep(const DynInstConstPtr &dyn_inst)
Record a Read After Write physical register dependency if there has been a write to the source regist...
bool firstWin
Used for checking the first window for processing and writing of dependency trace.
std::vector< ProbeListener * > listeners
Register ID: describe an architectural register with its class and index.
ProbeListenerArg generates a listener for the class of Arg and the class type T which is the class co...
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
EventFunctionWrapper regEtraceListenersEvent
Event to trigger registering this listener for all probe points.
ProtoOutputStream * dataTraceStream
Protobuf output stream for data dependency trace.
Stats::Scalar maxNumDependents
Maximum number of dependents on any instruction.
std::list< InstSeqNum > physRegDepList
std::vector< TraceInfo * > depTrace
The instruction dependency trace containing TraceInfo objects.
void registerExitCallback(const std::function< void()> &callback)
Register an exit callback.
Counter value() const
Return the current value of this stat as its base type.
FullO3CPU< O3CPUImpl > * cpu
Pointer to the O3CPU that is this listener's parent a.k.a.
const std::string name() const
Returns the name of the trace probe listener.
void compDelayRob(TraceInfo *past_record, TraceInfo *new_record)
Calculate the computational delay between an instruction and a subsequent instruction that has an ROB...
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
std::set< InstSeqNum > physRegDepSet
Set of instruction sequence numbers that this instruction depends on due to Read After Write data dep...
ElasticTraceStats(Stats::Group *parent)
bool hasLoadBeenSent(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a load sent earlier than the execute tick.
std::vector< TraceInfo * >::iterator depTraceItr
Typedef of iterator to the instruction dependency trace.
void assignRobDep(TraceInfo *past_record, TraceInfo *new_record)
The new_record has an order dependency on a past_record, thus update the new record's Rob dependency ...
void recordExecTick(const DynInstConstPtr &dyn_inst)
Populate the execute timestamp field in an InstExecInfo object for an instruction in flight.
void removeRegDepMapEntry(const SeqNumRegPair &inst_reg_pair)
When an instruction gets squashed the destination register mapped to it is freed up in the rename sta...
std::list< InstSeqNum > robDepList
constexpr decltype(nullptr) NoFault
This class is a minimal wrapper around SimObject.
ElasticTrace::ElasticTraceStats stats
ProbePointArg< PacketInfo > Packet
Packet probe point.
std::unordered_map< InstSeqNum, InstExecInfo * > tempStore
Temporary store of InstExecInfo objects.
Stats::Scalar numIssueOrderDepLoads
Number of load insts that got assigned an issue order dependency because they were dependency-free.
const std::string & name()
Tick getExecuteTick() const
Get the execute tick of the instruction.
bool allProbesReg
Whther the elastic trace listener has been registered for all probes.
Stats::Scalar numRegDep
Number of register dependencies recorded during tracing.
virtual const std::string name() const
std::reverse_iterator< depTraceItr > depTraceRevItr
Typedef of the reverse iterator to the instruction dependency trace.
Tick executeTick
Timestamp when instruction was first processed by execute stage.
uint32_t depWindowSize
The maximum distance for a dependency and is set by a top level level parameter.
virtual void scheduleInstCountEvent(Event *event, Tick count)=0
void addCommittedInst(const DynInstConstPtr &head_inst)
Add an instruction that is at the head of the ROB and is committed.
const char * className() const
Return a const char* with the register class name.
void addDepTraceRecord(const DynInstConstPtr &head_inst, InstExecInfo *exec_info_ptr, bool commit)
Add a record to the dependency trace depTrace which is a sequential container.
If you want a reference counting pointer to a mutable object, create it like this:
void updateCommitOrderDep(TraceInfo *new_record, bool find_load_not_store)
Reverse iterate through the graph, search for a store-after-store or store-after-load dependency and ...
Stats::Scalar numFilteredNodes
Number of filtered nodes.
Request::FlagsType reqFlags
ProtoOutputStream * instTraceStream
Protobuf output stream for instruction fetch trace.
RecordType type
The type of trace record for the instruction node.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
A ProtoOutputStream wraps a coded stream, potentially with compression, based on looking at the file ...
ElasticTrace(const ElasticTraceParams *params)
Constructor.
Tick toCommitTick
Timestamp when instruction execution is completed in execute stage and instruction is marked as ready...
bool isComp() const
Is the record a fetch triggering an Icache request.
bool hasStoreCommitted(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a store sent earlier than the execute tick.
void writeDepTrace(uint32_t num_to_write)
Write out given number of records to the trace starting with the first record in depTrace and iterati...
void addSquashedInst(const DynInstConstPtr &head_inst)
Add an instruction that is at the head of the ROB and is squashed only if it is a load and a request ...
Tick curTick()
The current simulated tick.
Generated on Wed Sep 30 2020 14:02:09 for gem5 by doxygen 1.8.17