changeset 18bb597fc40c in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=18bb597fc40c
description:
        cpu: Create record type enum for elastic traces

        This patch replaces the booleans that specified the elastic trace record
        type with an enum type. The source of change is the proto message for
        elastic trace where the enum is introduced. The struct definitions in 
the
        elastic trace probe listener as well as the Trace CPU replace the 
boleans
        with the proto message enum.

        The patch does not impact functionality, but traces are not compatible 
with
        previous version. This is preparation for adding new types of records in
        subsequent patches.

diffstat:

 src/cpu/o3/probe/elastic_trace.cc |  70 ++++++++++++++++++++------------------
 src/cpu/o3/probe/elastic_trace.hh |  22 +++++++++++-
 src/cpu/trace/trace_cpu.cc        |  44 ++++++++++++-----------
 src/cpu/trace/trace_cpu.hh        |  22 +++++++++--
 src/proto/inst_dep_record.proto   |  47 ++++++++++++++-----------
 util/decode_inst_dep_trace.py     |  36 ++++++++++++++-----
 util/encode_inst_dep_trace.py     |  51 ++++++++++++++++++---------
 7 files changed, 182 insertions(+), 110 deletions(-)

diffs (truncated from 677 to 300 lines):

diff -r a15c86af004a -r 18bb597fc40c src/cpu/o3/probe/elastic_trace.cc
--- a/src/cpu/o3/probe/elastic_trace.cc Mon Dec 07 16:42:16 2015 -0600
+++ b/src/cpu/o3/probe/elastic_trace.cc Mon Dec 07 16:42:16 2015 -0600
@@ -384,9 +384,10 @@
 
     // 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 @@
 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 @@
     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 @@
 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 @@
 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 @@
                                 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 @@
 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 @@
     // 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 @@
     // 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 @@
 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 @@
     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 @@
             // 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 @@
         ;
 }
 
+const std::string&
+ElasticTrace::TraceInfo::typeToStr() const
+{
+    return Record::RecordType_Name(type);
+}
+
 const std::string
 ElasticTrace::name() const
 {
diff -r a15c86af004a -r 18bb597fc40c src/cpu/o3/probe/elastic_trace.hh
--- a/src/cpu/o3/probe/elastic_trace.hh Mon Dec 07 16:42:16 2015 -0600
+++ b/src/cpu/o3/probe/elastic_trace.hh Mon Dec 07 16:42:16 2015 -0600
@@ -92,6 +92,10 @@
     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 @@
          */
         /* 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 @@
         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 -r a15c86af004a -r 18bb597fc40c src/cpu/trace/trace_cpu.cc
--- a/src/cpu/trace/trace_cpu.cc        Mon Dec 07 16:42:16 2015 -0600
+++ b/src/cpu/trace/trace_cpu.cc        Mon Dec 07 16:42:16 2015 -0600
@@ -453,7 +453,7 @@
                 ++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 @@
         // 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 @@
             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 @@
         // 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 @@
     // 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 @@
     req->setPC(node_ptr->pc);
     PacketPtr pkt;
     uint8_t* pkt_data = new uint8_t[req->getSize()];
-    if (node_ptr->isLoad) {
+    if (node_ptr->isLoad()) {
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to