48 #include "debug/ElasticTrace.hh" 64 fatal_if(!
cpu,
"Manager of %s is not of type O3CPU and thus does not "\
65 "support dependency tracing.\n",
name());
68 "Recommended size is 3x ROB size in the O3CPU.\n");
73 fatal_if(
params->instFetchTraceFile ==
"",
"Assign instruction fetch "\
74 "trace file path to instFetchTraceFile");
75 fatal_if(
params->dataDepTraceFile ==
"",
"Assign data dependency "\
76 "trace file path to dataDepTraceFile");
78 params->instFetchTraceFile);
83 ProtoMessage::PacketHeader inst_pkt_header;
84 inst_pkt_header.set_obj_id(
name());
89 ProtoMessage::InstDepRecordHeader data_rec_header;
90 data_rec_header.set_obj_id(
name());
103 inform(
"@%llu: regProbeListeners() called, startTraceInst = %llu",
121 inform(
"@%llu: No. of instructions committed = %llu, registering elastic" 153 req->getPC(), req->getVaddr(), req->getPaddr(),
154 req->getFlags(), req->getSize(),
curTick());
159 inst_fetch_pkt.set_tick(
curTick());
161 inst_fetch_pkt.set_pc(req->getPC());
162 inst_fetch_pkt.set_flags(req->getFlags());
163 inst_fetch_pkt.set_addr(req->getPaddr());
164 inst_fetch_pkt.set_size(req->getSize());
180 has already retired (mostly squashed)", dyn_inst->seqNum);
193 auto itr_exec_info =
tempStore.find(dyn_inst->seqNum);
195 exec_info_ptr = itr_exec_info->second;
198 tempStore[dyn_inst->seqNum] = exec_info_ptr;
213 auto itr_exec_info =
tempStore.find(dyn_inst->seqNum);
216 " skipping.\n", dyn_inst->seqNum);
244 int8_t max_regs = dyn_inst->numSrcRegs();
245 for (
int src_idx = 0; src_idx < max_regs; src_idx++) {
247 const RegId& src_reg = dyn_inst->srcRegIdx(src_idx);
251 PhysRegIdPtr phys_src_reg = dyn_inst->renamedSrcRegIdx(src_idx);
253 " %i (%s)\n", seq_num,
275 max_regs = dyn_inst->numDestRegs();
276 for (
int dest_idx = 0; dest_idx < max_regs; dest_idx++) {
279 const RegId& dest_reg = dyn_inst->destRegIdx(dest_idx);
284 PhysRegIdPtr phys_dest_reg = dyn_inst->renamedDestRegIdx(dest_idx);
286 " %i (%s)\n", seq_num, phys_dest_reg->
flatIndex(),
299 inst_reg_pair.second);
300 auto itr_regdep_map =
physRegDepMap.find(inst_reg_pair.second);
311 auto itr_exec_info =
tempStore.find(head_inst->seqNum);
323 head_inst->hasRequest() &&
324 head_inst->getFault() ==
NoFault) {
340 if (!head_inst->isNop()) {
346 auto itr_temp_store =
tempStore.find(head_inst->seqNum);
349 "store, skipping.\n", head_inst->seqNum);
369 if (head_inst->getFault() !=
NoFault) {
371 "skip adding it to the trace\n",
372 (head_inst->isMemRef() ?
"Load/store" :
"Comp inst."),
374 }
else if (head_inst->isMemRef() && !head_inst->hasRequest()) {
376 "skip adding it to the trace\n", head_inst->seqNum);
377 }
else if (!head_inst->readPredicate()) {
379 "skip adding it to the trace\n",
380 (head_inst->isMemRef() ?
"Load/store" :
"Comp inst."),
402 new_record->
instNum = head_inst->seqNum;
403 new_record->
commit = commit;
404 new_record->
type = head_inst->isLoad() ? Record::LOAD :
405 (head_inst->isStore() ? Record::STORE :
409 new_record->
reqFlags = head_inst->memReqFlags;
410 new_record->
virtAddr = head_inst->effAddr;
411 new_record->
asid = head_inst->asid;
412 new_record->
physAddr = head_inst->physEffAddr;
414 new_record->
size = head_inst->effSize;
415 new_record->
pc = head_inst->instAddr();
441 if (head_inst->isLoad() && !commit) {
446 std::set<InstSeqNum>::const_iterator dep_set_it;
456 "%lli\n", new_record->
instNum, *dep_set_it);
457 TraceInfo* reg_dep = trace_info_itr->second;
473 "%lli is skipped\n",new_record->
instNum, *dep_set_it);
481 if (head_inst->isStore()) {
502 (commit ?
"committed" :
"squashed"), new_record->
instNum);
523 bool find_load_not_store)
531 uint32_t num_go_back = 0;
536 while (num_go_back <
depWindowSize && from_itr != until_itr) {
537 if (find_load_not_store) {
557 past_record = *from_itr;
571 uint32_t num_go_back = 0;
572 Tick execute_tick = 0;
574 if (new_record->
isLoad()) {
578 }
else if (new_record->
isStore()) {
591 while (num_go_back <
depWindowSize && from_itr != until_itr) {
603 past_record = *from_itr;
626 Tick execute_tick)
const 633 Tick execute_tick)
const 641 Tick execute_tick)
const 650 Tick execute_tick)
const 663 auto itr_exec_info =
tempStore.find(temp_sn);
667 delete exec_info_ptr;
683 int64_t comp_delay = -1;
684 Tick execution_tick = 0, completion_tick = 0;
693 if (past_record->
isLoad()) {
699 }
else if (past_record->
isStore()) {
701 }
else if (past_record->
isComp()){
704 assert(execution_tick >= completion_tick);
705 comp_delay = execution_tick - completion_tick;
708 execution_tick, completion_tick, comp_delay);
727 int64_t comp_delay = -1;
728 Tick execution_tick = 0, completion_tick = 0;
746 assert(execution_tick >= completion_tick);
747 comp_delay = execution_tick - completion_tick;
749 execution_tick, completion_tick, comp_delay);
768 }
else if (isStore()) {
793 uint16_t num_filtered_nodes = 0;
796 while (num_to_write > 0) {
798 assert(temp_ptr->
type != Record::INVALID);
805 "is as follows:\n", temp_ptr->
instNum);
809 "size %i, flags %i\n", temp_ptr->
physAddr,
817 }
else if (temp_ptr->
isStore()) {
828 ProtoMessage::InstDepRecord dep_pkt;
829 dep_pkt.set_seq_num(temp_ptr->
instNum);
830 dep_pkt.set_type(temp_ptr->
type);
831 dep_pkt.set_pc(temp_ptr->
pc);
833 dep_pkt.set_flags(temp_ptr->
reqFlags);
834 dep_pkt.set_p_addr(temp_ptr->
physAddr);
838 dep_pkt.set_v_addr(temp_ptr->
virtAddr);
839 dep_pkt.set_asid(temp_ptr->
asid);
841 dep_pkt.set_size(temp_ptr->
size);
843 dep_pkt.set_comp_delay(temp_ptr->
compDelay);
850 dep_pkt.add_rob_dep(temp_ptr->
robDepList.front());
862 if (num_filtered_nodes != 0) {
867 dep_pkt.set_weight(num_filtered_nodes);
868 num_filtered_nodes = 0;
876 ++num_filtered_nodes;
883 depTrace.erase(dep_trace_itr_start, dep_trace_itr);
890 using namespace Stats;
893 .
desc(
"Number of register dependencies recorded during tracing")
897 .
name(
name() +
".numOrderDepStores")
898 .
desc(
"Number of commit order (rob) dependencies for a store recorded" 899 " on a past load/store during tracing")
903 .
name(
name() +
".numIssueOrderDepLoads")
904 .
desc(
"Number of loads that got assigned issue order dependency" 905 " because they were dependency-free")
909 .
name(
name() +
".numIssueOrderDepStores")
910 .
desc(
"Number of stores that got assigned issue order dependency" 911 " because they were dependency-free")
915 .
name(
name() +
".numIssueOrderDepOther")
916 .
desc(
"Number of non load/store insts that got assigned issue order" 917 " dependency because they were dependency-free")
922 .
desc(
"No. of nodes filtered out before writing the output trace")
927 .
desc(
"Maximum number or dependents on any instruction")
932 .
desc(
"Maximum size of the temporary store during the run")
936 .
name(
name() +
".maxPhysRegDepMapSize")
937 .
desc(
"Maximum size of register dependency map")
944 return Record::RecordType_Name(
type);
964 ElasticTraceParams::create()
int64_t compDelay
Computational delay after the last dependent inst.
Stats::Scalar numIssueOrderDepOther
Number of non load/store insts that got assigned an issue order dependency because they were dependen...
void compDelayPhysRegDep(TraceInfo *past_record, TraceInfo *new_record)
Calculate the computational delay between an instruction and a subsequent instruction that has a Phys...
void flushTraces()
Process any outstanding trace records, flush them out to the protobuf output streams and delete the s...
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
void regProbeListeners()
Register the probe listeners that is the methods called on a probe point notify() call...
ElasticTrace(const ElasticTraceParams *params)
Constructor.
bool hasLoadBeenSent(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a load sent earlier than the execute tick.
A ProtoOutputStream wraps a coded stream, potentially with compression, based on looking at the file ...
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...
FullO3CPU< O3CPUImpl > * cpu
Pointer to the O3CPU that is this listener's parent a.k.a.
void regEtraceListeners()
Register all listeners.
decltype(nullptr) constexpr NoFault
void write(const google::protobuf::Message &msg)
Write a message to the stream, preprending it with the message size.
bool isMiscReg() const
true if it is a condition-code physical register.
The elastic trace is a type of probe listener and listens to probe points in multiple stages of the O...
bool isStore() const
Is the record a store.
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
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 ...
bool isComp() const
Is the record a fetch triggering an Icache request.
std::unordered_map< InstSeqNum, InstExecInfo * > tempStore
Temporary store of InstExecInfo objects.
std::shared_ptr< Request > RequestPtr
bool isLoad() const
Is the record a load.
const std::string & typeToStr() const
Return string specifying the type of the node.
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.
bool allProbesReg
Whther the elastic trace listener has been registered for all probes.
virtual void regStats()
Callback to set stat parameters.
uint32_t depWindowSize
The maximum distance for a dependency and is set by a top level level parameter.
std::vector< TraceInfo * >::iterator depTraceItr
Typedef of iterator to the instruction dependency trace.
void recordExecTick(const DynInstConstPtr &dyn_inst)
Populate the execute timestamp field in an InstExecInfo object for an instruction in flight...
EventFunctionWrapper regEtraceListenersEvent
Event to trigger registering this listener for all probe points.
std::vector< TraceInfo * > depTrace
The instruction dependency trace containing TraceInfo objects.
void recordToCommTick(const DynInstConstPtr &dyn_inst)
Populate the timestamp field in an InstExecInfo object for an instruction in flight when it is execut...
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
If you want a reference counting pointer to a mutable object, create it like this: ...
Tick getExecuteTick() const
Get the execute tick of the instruction.
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 numIssueOrderDepStores
Number of store insts that got assigned an issue order dependency because they were dependency-free...
bool hasLoadCompleted(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a load that completed earlier than the execute tick.
bool hasStoreCommitted(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a store sent earlier than the execute tick.
Stats::Scalar numOrderDepStores
Number of stores that got assigned a commit order dependency on a past load/store.
Tick curTick()
The current simulated 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...
Stats::Scalar numIssueOrderDepLoads
Number of load insts that got assigned an issue order dependency because they were dependency-free...
Stats::Scalar maxPhysRegDepMapSize
Maximum size of the map that holds the last writer to a physical register.
uint64_t Tick
Tick count type.
const Params * params() const
virtual void scheduleInstCountEvent(Event *event, Tick count)=0
ProtoOutputStream * dataTraceStream
Protobuf output stream for data dependency trace.
This class is a minimal wrapper around SimObject.
std::unordered_map< InstSeqNum, TraceInfo * > traceInfoMap
Map where the instruction sequence number is mapped to the pointer to the TraceInfo object...
void registerExitCallback(Callback *callback)
Register an exit callback.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
std::list< InstSeqNum > physRegDepList
Tick toCommitTick
Timestamp when instruction execution is completed in execute stage and instruction is marked as ready...
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 ...
void regStats()
Register statistics for the elastic trace.
void updateIssueOrderDep(TraceInfo *new_record)
Reverse iterate through the graph, search for an issue order dependency for a new node and update the...
Request::FlagsType reqFlags
virtual const std::string name() const
bool hasCompCompleted(TraceInfo *past_record, Tick execute_tick) const
Check if past record is a comp node that completed earlier than the execute tick. ...
void clearTempStoreUntil(const DynInstConstPtr &head_inst)
Clear entries in the temporary store of execution info objects to free allocated memory until the pre...
std::vector< ProbeListener * > listeners
ProtoOutputStream * instTraceStream
Protobuf output stream for instruction fetch trace.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
void fetchReqTrace(const RequestPtr &req)
Take the fields of the request class object that are relevant to create an instruction fetch request...
const PhysRegIndex & flatIndex() const
Flat index accessor.
Stats::Scalar maxTempStoreSize
Maximum size of the temporary store mostly useful as a check that it is not growing.
Declaration of the Packet class.
std::set< InstSeqNum > physRegDepSet
Set of instruction sequence numbers that this instruction depends on due to Read After Write data dep...
std::list< InstSeqNum > robDepList
Stats::Scalar maxNumDependents
Maximum number of dependents on any instruction.
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
bool firstWin
Used for checking the first window for processing and writing of dependency trace.
const bool traceVirtAddr
Whether to trace virtual addresses for memory requests.
Tick executeTick
Timestamp when instruction was first processed by execute stage.
void addCommittedInst(const DynInstConstPtr &head_inst)
Add an instruction that is at the head of the ROB and is committed.
void updateRegDep(const DynInstConstPtr &dyn_inst)
Record a Read After Write physical register dependency if there has been a write to the source regist...
std::reverse_iterator< depTraceItr > depTraceRevItr
Typedef of the reverse iterator to the instruction dependency trace.
Register ID: describe an architectural register with its class and index.
std::unordered_map< PhysRegIndex, InstSeqNum > physRegDepMap
Map for recording the producer of a physical register to check Read After Write dependencies.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
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...
Helper template class to turn a simple class member function into a callback.
Stats::Scalar numRegDep
Number of register dependencies recorded during tracing.
RecordType type
The type of trace record for the instruction node.
ProbeListenerArg generates a listener for the class of Arg and the class type T which is the class co...
const std::string name() const
Returns the name of the trace probe listener.
bool isZeroReg() const
Check if this is the zero register.
Counter value() const
Return the current value of this stat as its base type.
Stats::Scalar numFilteredNodes
Number of filtered nodes.
const char * className() const
Return a const char* with the register class name.
void compDelayRob(TraceInfo *past_record, TraceInfo *new_record)
Calculate the computational delay between an instruction and a subsequent instruction that has an ROB...
ProbePointArg< PacketInfo > Packet
Packet probe point.
static int numSimulatedInsts()