cpu: Support virtual addr in elastic traces
authorRadhika Jagtap <radhika.jagtap@ARM.com>
Mon, 7 Dec 2015 22:42:16 +0000 (16:42 -0600)
committerRadhika Jagtap <radhika.jagtap@ARM.com>
Mon, 7 Dec 2015 22:42:16 +0000 (16:42 -0600)
This patch adds support to optionally capture the virtual address and asid
for load/store instructions in the elastic traces. If they are present in
the traces, Trace CPU will set those fields of the request during replay.

src/cpu/o3/probe/ElasticTrace.py
src/cpu/o3/probe/elastic_trace.cc
src/cpu/o3/probe/elastic_trace.hh
src/cpu/trace/trace_cpu.cc
src/cpu/trace/trace_cpu.hh
src/mem/request.hh
src/proto/inst_dep_record.proto
util/decode_inst_dep_trace.py
util/encode_inst_dep_trace.py

index fb3093a2c63cf876ae3b1e0ba433562754ae033f..20057ab97504144388c1107c5d4aa189826e3283 100644 (file)
@@ -59,4 +59,6 @@ class ElasticTrace(ProbeListenerObject):
                                     "after which to start tracing. Default " \
                                     "zero means start tracing from first " \
                                     "committed instruction.")
-
+    # Whether to trace virtual addresses for memory accesses
+    traceVirtAddr = Param.Bool(False, "Set to true if virtual addresses are " \
+                                "to be traced.")
index e1a41b69645b13dc9bbea6a226a58f6220eb5988..3332816cad1238f0fee248d94342ab6e9132210f 100644 (file)
@@ -57,7 +57,8 @@ ElasticTrace::ElasticTrace(const ElasticTraceParams* params)
        dataTraceStream(nullptr),
        instTraceStream(nullptr),
        startTraceInst(params->startTraceInst),
-       allProbesReg(false)
+       allProbesReg(false),
+       traceVirtAddr(params->traceVirtAddr)
 {
     cpu = dynamic_cast<FullO3CPU<O3CPUImpl>*>(params->manager);
     fatal_if(!cpu, "Manager of %s is not of type O3CPU and thus does not "\
@@ -391,7 +392,9 @@ ElasticTrace::addDepTraceRecord(const DynInstPtr &head_inst,
 
     // Assign fields for creating a request in case of a load/store
     new_record->reqFlags = head_inst->memReqFlags;
-    new_record->addr = head_inst->physEffAddrLow;
+    new_record->virtAddr = head_inst->effAddr;
+    new_record->asid = head_inst->asid;
+    new_record->physAddr = head_inst->physEffAddrLow;
     // Currently the tracing does not support split requests.
     new_record->size = head_inst->effSize;
     new_record->pc = head_inst->instAddr();
@@ -787,9 +790,9 @@ ElasticTrace::writeDepTrace(uint32_t num_to_write)
                      "is as follows:\n", temp_ptr->instNum);
             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);
+                DPRINTFR(ElasticTrace, "\thas a request with phys addr %i, "
+                         "size %i, flags %i\n", temp_ptr->physAddr,
+                         temp_ptr->size, temp_ptr->reqFlags);
             } else {
                  DPRINTFR(ElasticTrace, "\tis a %s\n", temp_ptr->typeToStr());
             }
@@ -813,7 +816,13 @@ ElasticTrace::writeDepTrace(uint32_t num_to_write)
             dep_pkt.set_pc(temp_ptr->pc);
             if (temp_ptr->isLoad() || temp_ptr->isStore()) {
                 dep_pkt.set_flags(temp_ptr->reqFlags);
-                dep_pkt.set_addr(temp_ptr->addr);
+                dep_pkt.set_p_addr(temp_ptr->physAddr);
+                // If tracing of virtual addresses is enabled, set the optional
+                // field for it
+                if (traceVirtAddr) {
+                    dep_pkt.set_v_addr(temp_ptr->virtAddr);
+                    dep_pkt.set_asid(temp_ptr->asid);
+                }
                 dep_pkt.set_size(temp_ptr->size);
             }
             dep_pkt.set_comp_delay(temp_ptr->compDelay);
index 001dc0e13c2a91b18f5131eb4af2614236cb83b9..584cdf18264939c853639aee2b3bf7569365d085 100644 (file)
@@ -289,8 +289,12 @@ class ElasticTrace : public ProbeListenerObject
         Addr pc;
         /* Request flags in case of a load/store instruction */
         Request::FlagsType reqFlags;
-        /* Request address in case of a load/store instruction */
-        Addr addr;
+        /* Request physical address in case of a load/store instruction */
+        Addr physAddr;
+        /* Request virtual address in case of a load/store instruction */
+        Addr virtAddr;
+        /* Address space id in case of a load/store instruction */
+        uint32_t asid;
         /* Request size in case of a load/store instruction */
         unsigned size;
         /** Default Constructor */
@@ -366,6 +370,9 @@ class ElasticTrace : public ProbeListenerObject
      */
     bool allProbesReg;
 
+    /** Whether to trace virtual addresses for memory requests. */
+    const bool traceVirtAddr;
+
     /** Pointer to the O3CPU that is this listener's parent a.k.a. manager */
     FullO3CPU<O3CPUImpl>* cpu;
 
index ffa64014af203a8ef3fe235e405c621ef204935c..f940be2f9d8124b2afdb76d777039271ad2c33ca 100644 (file)
@@ -597,8 +597,9 @@ PacketPtr
 TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr)
 {
 
-    DPRINTF(TraceCPUData, "Executing memory request %lli (addr %d, pc %#x, "
-            "size %d, flags %d).\n", node_ptr->seqNum, node_ptr->addr,
+    DPRINTF(TraceCPUData, "Executing memory request %lli (phys addr %d, "
+            "virt addr %d, pc %#x, size %d, flags %d).\n",
+            node_ptr->seqNum, node_ptr->physAddr, node_ptr->virtAddr,
             node_ptr->pc, node_ptr->size, node_ptr->flags);
 
     // If the request is strictly ordered, do not send it. Just return nullptr
@@ -617,17 +618,26 @@ TraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr)
     // happens. If required the code could be revised to mimick splitting such
     // a request into two.
     unsigned blk_size = owner.cacheLineSize();
-    Addr blk_offset = (node_ptr->addr & (Addr)(blk_size - 1));
+    Addr blk_offset = (node_ptr->physAddr & (Addr)(blk_size - 1));
     if (!(blk_offset + node_ptr->size <= blk_size)) {
         node_ptr->size = blk_size - blk_offset;
         ++numSplitReqs;
     }
 
     // Create a request and the packet containing request
-    Request* req = new Request(node_ptr->addr, node_ptr->size, node_ptr->flags,
-                               masterID, node_ptr->seqNum,
+    Request* req = new Request(node_ptr->physAddr, node_ptr->size,
+                               node_ptr->flags, masterID, node_ptr->seqNum,
                                ContextID(0), ThreadID(0));
     req->setPC(node_ptr->pc);
+    // If virtual address is valid, set the asid and virtual address fields
+    // of the request.
+    if (node_ptr->virtAddr != 0) {
+        req->setVirt(node_ptr->asid, node_ptr->virtAddr, node_ptr->size,
+                        node_ptr->flags, masterID, node_ptr->pc);
+        req->setPaddr(node_ptr->physAddr);
+        req->setReqInstSeqNum(node_ptr->seqNum);
+    }
+
     PacketPtr pkt;
     uint8_t* pkt_data = new uint8_t[req->getSize()];
     if (node_ptr->isLoad()) {
@@ -1277,10 +1287,20 @@ TraceCPU::ElasticDataGen::InputStream::read(GraphNode* element)
         }
 
         // Optional fields
-        if (pkt_msg.has_addr())
-            element->addr = pkt_msg.addr();
+        if (pkt_msg.has_p_addr())
+            element->physAddr = pkt_msg.p_addr();
+        else
+            element->physAddr = 0;
+
+        if (pkt_msg.has_v_addr())
+            element->virtAddr = pkt_msg.v_addr();
+        else
+            element->virtAddr = 0;
+
+        if (pkt_msg.has_asid())
+            element->asid = pkt_msg.asid();
         else
-            element->addr = 0;
+            element->asid = 0;
 
         if (pkt_msg.has_size())
             element->size = pkt_msg.size();
@@ -1383,7 +1403,7 @@ TraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const
     DPRINTFR(TraceCPUData, "%lli", seqNum);
     DPRINTFR(TraceCPUData, ",%s", typeToStr());
     if (isLoad() || isStore()) {
-        DPRINTFR(TraceCPUData, ",%i", addr);
+        DPRINTFR(TraceCPUData, ",%i", physAddr);
         DPRINTFR(TraceCPUData, ",%i", size);
         DPRINTFR(TraceCPUData, ",%i", flags);
     }
index 75132149120f12f5cc153a2589ee60faf11c6e4f..bb59c3fabfee98ebc813a1fc8e742607110dabf8 100644 (file)
@@ -596,7 +596,13 @@ class TraceCPU : public BaseCPU
             RecordType type;
 
             /** The address for the request if any */
-            Addr addr;
+            Addr physAddr;
+
+            /** The virtual address for the request if any */
+            Addr virtAddr;
+
+            /** The address space id which is set if the virtual address is set */
+            uint32_t asid;
 
             /** Size of request if any */
             uint32_t size;
index 177f17de2ef70aef20b8510b270ad1db823a1f3b..287a823ad1967924d2086ddaa5ff3725f6237700 100644 (file)
@@ -300,7 +300,7 @@ class Request
     Addr _pc;
 
     /** Sequence number of the instruction that creates the request */
-    const InstSeqNum _reqInstSeqNum;
+    InstSeqNum _reqInstSeqNum;
 
   public:
 
@@ -675,6 +675,13 @@ class Request
         return _reqInstSeqNum;
     }
 
+    void
+    setReqInstSeqNum(const InstSeqNum seq_num)
+    {
+        privateFlags.set(VALID_INST_SEQ_NUM);
+        _reqInstSeqNum = seq_num;
+    }
+
     /** Accessor functions for flags.  Note that these are for testing
         only; setting flags should be done via setFlags(). */
     bool isUncacheable() const { return _flags.isSet(UNCACHEABLE); }
index 98c070efc6390895f420cafac16ec2ce60af5201..f89e51d819c6638f3eea6d0730e1960b8a88296c 100644 (file)
@@ -69,7 +69,7 @@ message InstDepRecord {
   }
   required uint64 seq_num = 1;
   required RecordType type = 2 [default = INVALID];
-  optional uint64 addr = 3;
+  optional uint64 p_addr = 3;
   optional uint32 size = 4;
   optional uint32 flags = 5;
   repeated uint64 rob_dep = 6;
@@ -77,4 +77,6 @@ message InstDepRecord {
   repeated uint64 reg_dep = 8;
   optional uint32 weight = 9;
   optional uint64 pc = 10;
+  optional uint64 v_addr = 11;
+  optional uint32 asid = 12;
 }
\ No newline at end of file
index 2e7e6381c33169787d77cb1853d05bfb39a6babc..6e4030146f5b0145b7a8070e6d2074fd9df48b24 100755 (executable)
 #
 # The ASCII trace format uses one line per instruction with the format
 # instruction sequence number, (optional) pc, (optional) weight, type
-# (optional) flags, (optional) addr, (optional) size, comp delay,
+# (optional) flags, (optional) phys addr, (optional) size, comp delay,
 # (repeated) order dependencies comma-separated, and (repeated) register
 # dependencies comma-separated.
 #
 # examples:
-# seq_num,[pc],[weight,]type,[address,size,flags,]comp_delay:[rob_dep]:
+# seq_num,[pc],[weight,]type,[p_addr,size,flags,]comp_delay:[rob_dep]:
 # [reg_dep]
 # 1,35652,1,COMP,8500::
 # 2,35656,1,COMP,0:,1:
@@ -178,9 +178,10 @@ def main():
             exit(-1)
 
 
-        # Write to file if it has the optional fields addr, size, flags
-        if packet.HasField('addr'):
-            ascii_out.write(',%s' % (packet.addr))
+        # Write to file if it has the optional fields physical addr, size,
+        # flags
+        if packet.HasField('p_addr'):
+            ascii_out.write(',%s' % (packet.p_addr))
         if packet.HasField('size'):
             ascii_out.write(',%s' % (packet.size))
         if packet.HasField('flags'):
index 6293fb0ab5611674a463cad23cc469be00ff522e..e54e82d7010f1cc2310612cf9aa995d1946506f6 100755 (executable)
 #
 # The ASCII trace format uses one line per instruction with the format
 # instruction sequence number, (optional) pc, (optional) weight, type,
-# (optional) flags, (optional) addr, (optional) size, comp delay,
+# (optional) flags, (optional) physical addr, (optional) size, comp delay,
 # (repeated) order dependencies comma-separated, and (repeated) register
 # dependencies comma-separated.
 #
 # examples:
-# seq_num,[pc],[weight,]type,[address,size,flags,]comp_delay:[rob_dep]:
+# seq_num,[pc],[weight,]type,[p_addr,size,flags,]comp_delay:[rob_dep]:
 # [reg_dep]
 # 1,35652,1,COMP,8500::
 # 2,35656,1,COMP,0:,1:
@@ -167,11 +167,11 @@ def main():
             print "Seq. num", dep_record.seq_num, "is of INVALID type"
             exit(-1)
 
-        # If the instruction is a load or store record the addr, size flags
-        # in addition to recording the computation delay
+        # If the instruction is a load or store record the physical addr,
+        # size flags in addition to recording the computation delay
         if dep_record.type in [DepRecord.LOAD, DepRecord.STORE]:
-            addr, size, flags, comp_delay = inst_info_list[4:8]
-            dep_record.addr = long(addr)
+            p_addr, size, flags, comp_delay = inst_info_list[4:8]
+            dep_record.p_addr = long(p_addr)
             dep_record.size = int(size)
             dep_record.flags = int(flags)
             dep_record.comp_delay = long(comp_delay)