summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cpu/o3/probe/elastic_trace.cc70
-rw-r--r--src/cpu/o3/probe/elastic_trace.hh22
-rw-r--r--src/cpu/trace/trace_cpu.cc44
-rw-r--r--src/cpu/trace/trace_cpu.hh22
-rw-r--r--src/proto/inst_dep_record.proto47
5 files changed, 122 insertions, 83 deletions
diff --git a/src/cpu/o3/probe/elastic_trace.cc b/src/cpu/o3/probe/elastic_trace.cc
index a7a0403f9..e1a41b696 100644
--- a/src/cpu/o3/probe/elastic_trace.cc
+++ b/src/cpu/o3/probe/elastic_trace.cc
@@ -384,9 +384,10 @@ ElasticTrace::addDepTraceRecord(const DynInstPtr &head_inst,
// Assign fields from the instruction
new_record->instNum = head_inst->seqNum;
- new_record->load = head_inst->isLoad();
- new_record->store = head_inst->isStore();
new_record->commit = commit;
+ new_record->type = head_inst->isLoad() ? Record::LOAD :
+ (head_inst->isStore() ? Record::STORE :
+ Record::COMP);
// Assign fields for creating a request in case of a load/store
new_record->reqFlags = head_inst->memReqFlags;
@@ -503,7 +504,7 @@ void
ElasticTrace::updateCommitOrderDep(TraceInfo* new_record,
bool find_load_not_store)
{
- assert(new_record->store);
+ assert(new_record->isStore());
// Iterate in reverse direction to search for the last committed
// load/store that completed earlier than the new record
depTraceRevItr from_itr(depTrace.end());
@@ -552,11 +553,11 @@ ElasticTrace::updateIssueOrderDep(TraceInfo* new_record)
uint32_t num_go_back = 0;
Tick execute_tick = 0;
- if (new_record->load) {
+ if (new_record->isLoad()) {
// The execution time of a load is when a request is sent
execute_tick = new_record->executeTick;
++numIssueOrderDepLoads;
- } else if (new_record->store) {
+ } else if (new_record->isStore()) {
// The execution time of a store is when it is sent, i.e. committed
execute_tick = curTick();
++numIssueOrderDepStores;
@@ -589,10 +590,8 @@ ElasticTrace::updateIssueOrderDep(TraceInfo* new_record)
void
ElasticTrace::assignRobDep(TraceInfo* past_record, TraceInfo* new_record) {
DPRINTF(ElasticTrace, "%s %lli has ROB dependency on %lli\n",
- new_record->load ? "Load" : (new_record->store ? "Store" :
- "Non load/store"),
- new_record->instNum, past_record->instNum);
-
+ new_record->typeToStr(), new_record->instNum,
+ past_record->instNum);
// Add dependency on past record
new_record->robDepList.push_back(past_record->instNum);
// Update new_record's compute delay with respect to the past record
@@ -608,14 +607,14 @@ bool
ElasticTrace::hasStoreCommitted(TraceInfo* past_record,
Tick execute_tick) const
{
- return (past_record->store && past_record->commitTick <= execute_tick);
+ return (past_record->isStore() && past_record->commitTick <= execute_tick);
}
bool
ElasticTrace::hasLoadCompleted(TraceInfo* past_record,
Tick execute_tick) const
{
- return(past_record->load && past_record->commit &&
+ return(past_record->isLoad() && past_record->commit &&
past_record->toCommitTick <= execute_tick);
}
@@ -624,7 +623,7 @@ ElasticTrace::hasLoadBeenSent(TraceInfo* past_record,
Tick execute_tick) const
{
// Check if previous inst is a load sent earlier than this
- return (past_record->load && past_record->commit &&
+ return (past_record->isLoad() && past_record->commit &&
past_record->executeTick <= execute_tick);
}
@@ -632,8 +631,7 @@ bool
ElasticTrace::hasCompCompleted(TraceInfo* past_record,
Tick execute_tick) const
{
- return(!past_record->store && !past_record->load &&
- past_record->toCommitTick <= execute_tick);
+ return(past_record->isComp() && past_record->toCommitTick <= execute_tick);
}
void
@@ -674,15 +672,15 @@ ElasticTrace::compDelayRob(TraceInfo* past_record, TraceInfo* new_record)
// computation delay
execution_tick = new_record->getExecuteTick();
- if (past_record->load) {
- if (new_record->store) {
+ if (past_record->isLoad()) {
+ if (new_record->isStore()) {
completion_tick = past_record->toCommitTick;
} else {
completion_tick = past_record->executeTick;
}
- } else if (past_record->store) {
+ } else if (past_record->isStore()) {
completion_tick = past_record->commitTick;
- } else {
+ } else if (past_record->isComp()){
completion_tick = past_record->toCommitTick;
}
assert(execution_tick >= completion_tick);
@@ -722,7 +720,7 @@ ElasticTrace::compDelayPhysRegDep(TraceInfo* past_record,
// completion tick of that instruction is when it wrote to the register,
// that is toCommitTick. In case, of a store updating a destination
// register, this is approximated to commitTick instead
- if (past_record->store) {
+ if (past_record->isStore()) {
completion_tick = past_record->commitTick;
} else {
completion_tick = past_record->toCommitTick;
@@ -745,11 +743,11 @@ ElasticTrace::compDelayPhysRegDep(TraceInfo* past_record,
Tick
ElasticTrace::TraceInfo::getExecuteTick() const
{
- if (load) {
+ if (isLoad()) {
// Execution tick for a load instruction is when the request was sent,
// that is executeTick.
return executeTick;
- } else if (store) {
+ } else if (isStore()) {
// Execution tick for a store instruction is when the request was sent,
// that is commitTick.
return commitTick;
@@ -779,27 +777,26 @@ ElasticTrace::writeDepTrace(uint32_t num_to_write)
depTraceItr dep_trace_itr_start = dep_trace_itr;
while (num_to_write > 0) {
TraceInfo* temp_ptr = *dep_trace_itr;
- // If no node dependends on a non load/store node then there is
- // no reason to track it in the dependency graph. We filter out such
+ assert(temp_ptr->type != Record::INVALID);
+ // If no node dependends on a comp node then there is no reason to
+ // track the comp node in the dependency graph. We filter out such
// nodes but count them and add a weight field to the subsequent node
// that we do include in the trace.
- if (temp_ptr->numDepts != 0 || temp_ptr->load || temp_ptr->store) {
-
+ if (!temp_ptr->isComp() || temp_ptr->numDepts != 0) {
DPRINTFR(ElasticTrace, "Instruction with seq. num %lli "
"is as follows:\n", temp_ptr->instNum);
- if (temp_ptr->load || temp_ptr->store) {
- DPRINTFR(ElasticTrace, "\tis a %s\n",
- (temp_ptr->load ? "Load" : "Store"));
+ if (temp_ptr->isLoad() || temp_ptr->isStore()) {
+ DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
DPRINTFR(ElasticTrace, "\thas a request with addr %i, size %i,"
" flags %i\n", temp_ptr->addr, temp_ptr->size,
temp_ptr->reqFlags);
} else {
- DPRINTFR(ElasticTrace, "\tis not a load or store\n");
+ DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
}
if (firstWin && temp_ptr->compDelay == -1) {
- if (temp_ptr->load) {
+ if (temp_ptr->isLoad()) {
temp_ptr->compDelay = temp_ptr->executeTick;
- } else if (temp_ptr->store) {
+ } else if (temp_ptr->isStore()) {
temp_ptr->compDelay = temp_ptr->commitTick;
} else {
temp_ptr->compDelay = temp_ptr->toCommitTick;
@@ -812,10 +809,9 @@ ElasticTrace::writeDepTrace(uint32_t num_to_write)
// Create a protobuf message for the dependency record
ProtoMessage::InstDepRecord dep_pkt;
dep_pkt.set_seq_num(temp_ptr->instNum);
- dep_pkt.set_load(temp_ptr->load);
- dep_pkt.set_store(temp_ptr->store);
+ dep_pkt.set_type(temp_ptr->type);
dep_pkt.set_pc(temp_ptr->pc);
- if (temp_ptr->load || temp_ptr->store) {
+ if (temp_ptr->isLoad() || temp_ptr->isStore()) {
dep_pkt.set_flags(temp_ptr->reqFlags);
dep_pkt.set_addr(temp_ptr->addr);
dep_pkt.set_size(temp_ptr->size);
@@ -916,6 +912,12 @@ ElasticTrace::regStats() {
;
}
+const std::string&
+ElasticTrace::TraceInfo::typeToStr() const
+{
+ return Record::RecordType_Name(type);
+}
+
const std::string
ElasticTrace::name() const
{
diff --git a/src/cpu/o3/probe/elastic_trace.hh b/src/cpu/o3/probe/elastic_trace.hh
index 5dd2949e8..001dc0e13 100644
--- a/src/cpu/o3/probe/elastic_trace.hh
+++ b/src/cpu/o3/probe/elastic_trace.hh
@@ -92,6 +92,10 @@ class ElasticTrace : public ProbeListenerObject
typedef typename O3CPUImpl::DynInstPtr DynInstPtr;
typedef typename std::pair<InstSeqNum, PhysRegIndex> SeqNumRegPair;
+ /** Trace record types corresponding to instruction node types */
+ typedef ProtoMessage::InstDepRecord::RecordType RecordType;
+ typedef ProtoMessage::InstDepRecord Record;
+
/** Constructor */
ElasticTrace(const ElasticTraceParams *params);
@@ -260,14 +264,16 @@ class ElasticTrace : public ProbeListenerObject
*/
/* Instruction sequence number. */
InstSeqNum instNum;
+ /** The type of trace record for the instruction node */
+ RecordType type;
/* Tick when instruction was in execute stage. */
Tick executeTick;
/* Tick when instruction was marked ready and sent to commit stage. */
Tick toCommitTick;
/* Tick when instruction was committed. */
Tick commitTick;
- /* If instruction was a load, a store, committed. */
- bool load, store, commit;
+ /* If instruction was committed, as against squashed. */
+ bool commit;
/* List of order dependencies. */
std::list<InstSeqNum> robDepList;
/* List of physical register RAW dependencies. */
@@ -287,6 +293,18 @@ class ElasticTrace : public ProbeListenerObject
Addr addr;
/* Request size in case of a load/store instruction */
unsigned size;
+ /** Default Constructor */
+ TraceInfo()
+ : type(Record::INVALID)
+ { }
+ /** Is the record a load */
+ bool isLoad() const { return (type == Record::LOAD); }
+ /** Is the record a store */
+ bool isStore() const { return (type == Record::STORE); }
+ /** Is the record a fetch triggering an Icache request */
+ bool isComp() const { return (type == Record::COMP); }
+ /** Return string specifying the type of the node */
+ const std::string& typeToStr() const;
/** @} */
/**
diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc
index 2e989f6ff..ffa64014a 100644
--- a/src/cpu/trace/trace_cpu.cc
+++ b/src/cpu/trace/trace_cpu.cc
@@ -453,7 +453,7 @@ TraceCPU::ElasticDataGen::execute()
++numRetrySucceeded;
retryPkt = nullptr;
}
- } else if (node_ptr->isLoad || node_ptr->isStore) {
+ } else if (node_ptr->isLoad() || node_ptr->isStore()) {
// If there is no retryPkt, attempt to send a memory request in
// case of a load or store node. If the send fails, executeMemReq()
// returns a packet pointer, which we save in retryPkt. In case of
@@ -474,7 +474,7 @@ TraceCPU::ElasticDataGen::execute()
// dependencies complete. But as per dependency modelling we need
// to mark ROB dependencies of load and non load/store nodes which
// are based on successful sending of the load as complete.
- if (node_ptr->isLoad && !node_ptr->isStrictlyOrdered()) {
+ if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) {
// If execute succeeded mark its dependents as complete
DPRINTF(TraceCPUData, "Node seq. num %lli sent. Waking up "
"dependents..\n", node_ptr->seqNum);
@@ -483,7 +483,7 @@ TraceCPU::ElasticDataGen::execute()
while (child_itr != (node_ptr->dependents).end()) {
// ROB dependency of a store on a load must not be removed
// after load is sent but after response is received
- if (!(*child_itr)->isStore &&
+ if (!(*child_itr)->isStore() &&
(*child_itr)->removeRobDep(node_ptr->seqNum)) {
// Check if the child node has become dependency free
@@ -530,7 +530,7 @@ TraceCPU::ElasticDataGen::execute()
// marked complete. Thus it is safe to delete it. For
// stores and non load/store nodes all dependencies were
// marked complete so it is safe to delete it.
- if (!node_ptr->isLoad || node_ptr->isStrictlyOrdered()) {
+ if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) {
// Release all resources occupied by the completed node
hwResource.release(node_ptr);
// clear the dynamically allocated set of dependents
@@ -604,7 +604,7 @@ TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr)
// If the request is strictly ordered, do not send it. Just return nullptr
// as if it was succesfully sent.
if (node_ptr->isStrictlyOrdered()) {
- node_ptr->isLoad ? ++numSOLoads : ++numSOStores;
+ node_ptr->isLoad() ? ++numSOLoads : ++numSOStores;
DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n",
node_ptr->seqNum);
return nullptr;
@@ -630,7 +630,7 @@ TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr)
req->setPC(node_ptr->pc);
PacketPtr pkt;
uint8_t* pkt_data = new uint8_t[req->getSize()];
- if (node_ptr->isLoad) {
+ if (node_ptr->isLoad()) {
pkt = Packet::createRead(req);
} else {
pkt = Packet::createWrite(req);
@@ -664,8 +664,7 @@ TraceCPU::ElasticDataGen::checkAndIssue(const GraphNode* node_ptr, bool first)
// If this is the first attempt, print a debug message to indicate this.
if (first) {
DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now"
- " dependency free.\n", node_ptr->seqNum,
- node_ptr->isLoad ? "L" : (node_ptr->isStore ? "S" : "C"),
+ " dependency free.\n", node_ptr->seqNum, node_ptr->typeToStr(),
node_ptr->robNum);
}
@@ -831,8 +830,7 @@ TraceCPU::ElasticDataGen::printReadyList() {
auto graph_itr = depGraph.find(itr->seqNum);
GraphNode* node_ptr M5_VAR_USED = graph_itr->second;
DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum,
- node_ptr->isLoad ? "L" : (node_ptr->isStore ? "S" : "C"),
- itr->execTick);
+ node_ptr->typeToStr(), itr->execTick);
itr++;
}
}
@@ -857,9 +855,9 @@ TraceCPU::ElasticDataGen::HardwareResource::occupy(const GraphNode* new_node)
oldestInFlightRobNum = inFlightNodes.begin()->second;
// Occupy Load/Store Buffer entry for the issued node if applicable
- if (new_node->isLoad) {
+ if (new_node->isLoad()) {
++numInFlightLoads;
- } else if (new_node->isStore) {
+ } else if (new_node->isStore()) {
++numInFlightStores;
} // else if it is a non load/store node, no buffer entry is occupied
@@ -894,7 +892,7 @@ TraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node)
// freed. But it occupies an entry in the Store Buffer until its response
// is received. A load is considered complete when a response is received,
// thus both ROB and Load Buffer entries can be released.
- if (done_node->isLoad) {
+ if (done_node->isLoad()) {
assert(numInFlightLoads != 0);
--numInFlightLoads;
}
@@ -902,7 +900,7 @@ TraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node)
// entry on response. For writes which are strictly ordered, for e.g.
// writes to device registers, we do that within release() which is called
// when node is executed and taken off from readyList.
- if (done_node->isStore && done_node->isStrictlyOrdered()) {
+ if (done_node->isStore() && done_node->isStrictlyOrdered()) {
releaseStoreBuffer();
}
}
@@ -949,10 +947,10 @@ TraceCPU::ElasticDataGen::HardwareResource::isAvailable(
if (num_in_flight_nodes >= sizeROB) {
return false;
}
- if (new_node->isLoad && numInFlightLoads >= sizeLoadBuffer) {
+ if (new_node->isLoad() && numInFlightLoads >= sizeLoadBuffer) {
return false;
}
- if (new_node->isStore && numInFlightStores >= sizeStoreBuffer) {
+ if (new_node->isStore() && numInFlightStores >= sizeStoreBuffer) {
return false;
}
return true;
@@ -1250,8 +1248,7 @@ TraceCPU::ElasticDataGen::InputStream::read(GraphNode* element)
if (trace.read(pkt_msg)) {
// Required fields
element->seqNum = pkt_msg.seq_num();
- element->isLoad = pkt_msg.load();
- element->isStore = pkt_msg.store();
+ element->type = pkt_msg.type();
element->compDelay = pkt_msg.comp_delay();
// Repeated field robDepList
@@ -1384,9 +1381,8 @@ void
TraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const
{
DPRINTFR(TraceCPUData, "%lli", seqNum);
- DPRINTFR(TraceCPUData, ",%s", (isLoad ? "True" : "False"));
- DPRINTFR(TraceCPUData, ",%s", (isStore ? "True" : "False"));
- if (isLoad || isStore) {
+ DPRINTFR(TraceCPUData, ",%s", typeToStr());
+ if (isLoad() || isStore()) {
DPRINTFR(TraceCPUData, ",%i", addr);
DPRINTFR(TraceCPUData, ",%i", size);
DPRINTFR(TraceCPUData, ",%i", flags);
@@ -1414,6 +1410,12 @@ TraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const
DPRINTFR(TraceCPUData, "\n");
}
+std::string
+TraceCPU::ElasticDataGen::GraphNode::typeToStr() const
+{
+ return Record::RecordType_Name(type);
+}
+
TraceCPU::FixedRetryGen::InputStream::InputStream(const std::string& filename)
: trace(filename)
{
diff --git a/src/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh
index 3a869ebe0..751321491 100644
--- a/src/cpu/trace/trace_cpu.hh
+++ b/src/cpu/trace/trace_cpu.hh
@@ -561,6 +561,9 @@ class TraceCPU : public BaseCPU
/** Node ROB number type. */
typedef uint64_t NodeRobNum;
+ typedef ProtoMessage::InstDepRecord::RecordType RecordType;
+ typedef ProtoMessage::InstDepRecord Record;
+
/**
* The struct GraphNode stores an instruction in the trace file. The
* format of the trace file favours constructing a dependency graph of
@@ -589,11 +592,8 @@ class TraceCPU : public BaseCPU
/** ROB occupancy number */
NodeRobNum robNum;
- /** If instruction is a load */
- bool isLoad;
-
- /** If instruction is a store */
- bool isStore;
+ /** Type of the node corresponding to the instruction modelled by it */
+ RecordType type;
/** The address for the request if any */
Addr addr;
@@ -632,6 +632,15 @@ class TraceCPU : public BaseCPU
*/
std::vector<GraphNode *> dependents;
+ /** Is the node a load */
+ bool isLoad() const { return (type == Record::LOAD); }
+
+ /** Is the node a store */
+ bool isStore() const { return (type == Record::STORE); }
+
+ /** Is the node a compute (non load/store) node */
+ bool isComp() const { return (type == Record::COMP); }
+
/** Initialize register dependency array to all zeroes */
void clearRegDep();
@@ -656,6 +665,9 @@ class TraceCPU : public BaseCPU
* TraceCPUData.
*/
void writeElementAsTrace() const;
+
+ /** Return string specifying the type of the node */
+ std::string typeToStr() const;
};
/** Struct to store a ready-to-execute node and its execution tick. */
diff --git a/src/proto/inst_dep_record.proto b/src/proto/inst_dep_record.proto
index 7035bfc74..98c070efc 100644
--- a/src/proto/inst_dep_record.proto
+++ b/src/proto/inst_dep_record.proto
@@ -50,26 +50,31 @@ message InstDepRecordHeader {
}
// Packet to encapsulate an instruction in the o3cpu data dependency trace.
-// The required fields include the instruction sequence number, whether it
-// is a load, and whether it is a store. The request related fields are
-// optional, namely address, size and flags. These exist only if the
-// instruction is a load or store. The dependency related information includes
-// a repeated field for order dependencies, a repeated field for register
-// dependencies and the computational delay with respect to the dependency
-// that completed last. A weight field is used to account for committed
-// instructions that were filtered out before writing the trace and is used
-// to estimate ROB occupancy during replay. An optional field is provided for
-// the instruction PC.
+// The required fields include the instruction sequence number and the type
+// of the record associated with the instruction e.g. load. The request related
+// fields are optional, namely address, size and flags. The dependency related
+// information includes a repeated field for order dependencies and register
+// dependencies for loads, stores and comp records. There is a field for the
+// computational delay with respect to the dependency that completed last. A
+// weight field is used to account for committed instruction that were
+// filtered out before writing the trace and is used to estimate ROB
+// occupancy during replay. An optional field is provided for the instruction
+// PC.
message InstDepRecord {
+ enum RecordType {
+ INVALID = 0;
+ LOAD = 1;
+ STORE = 2;
+ COMP = 3;
+ }
required uint64 seq_num = 1;
- required bool load = 2;
- required bool store = 3;
- optional uint64 addr = 4;
- optional uint32 size = 5;
- optional uint32 flags = 6;
- repeated uint64 rob_dep = 7;
- required uint64 comp_delay = 8;
- repeated uint64 reg_dep = 9;
- optional uint32 weight = 10;
- optional uint64 pc = 11;
-}
+ required RecordType type = 2 [default = INVALID];
+ optional uint64 addr = 3;
+ optional uint32 size = 4;
+ optional uint32 flags = 5;
+ repeated uint64 rob_dep = 6;
+ required uint64 comp_delay = 7;
+ repeated uint64 reg_dep = 8;
+ optional uint32 weight = 9;
+ optional uint64 pc = 10;
+} \ No newline at end of file