Home | History | Annotate | Download | only in qtools
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <inttypes.h>
      5 #include "trace_reader.h"
      6 
      7 typedef struct MyStaticRec {
      8   StaticRec bb;
      9   uint32_t  *insns;
     10 } MyStaticRec;
     11 
     12 const int kNumPids = 32768;
     13 char usedPids[kNumPids];
     14 
     15 int main(int argc, char **argv) {
     16   uint32_t insns[kMaxInsnPerBB];
     17 
     18   if (argc != 2) {
     19     fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
     20     exit(1);
     21   }
     22 
     23   char *trace_filename = argv[1];
     24   TraceReaderBase *trace = new TraceReaderBase;
     25   trace->SetPostProcessing(true);
     26   trace->Open(trace_filename);
     27 
     28   // Count the number of static basic blocks and instructions.
     29   uint64_t num_static_bb = 0;
     30   uint64_t num_static_insn = 0;
     31   while (1) {
     32     StaticRec static_rec;
     33 
     34     if (trace->ReadStatic(&static_rec))
     35       break;
     36     if (static_rec.bb_num != num_static_bb) {
     37       fprintf(stderr,
     38               "Error: basic block numbers out of order; expected %lld, got %lld\n",
     39               num_static_bb, static_rec.bb_num);
     40       exit(1);
     41     }
     42     num_static_bb += 1;
     43     num_static_insn += static_rec.num_insns;
     44     trace->ReadStaticInsns(static_rec.num_insns, insns);
     45   }
     46   trace->Close();
     47 
     48   // Allocate space for all of the static blocks
     49   MyStaticRec *blocks = new MyStaticRec[num_static_bb];
     50 
     51   // Read the static blocks again and save pointers to them
     52   trace->Open(trace_filename);
     53   for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
     54     trace->ReadStatic(&blocks[ii].bb);
     55     uint32_t num_insns = blocks[ii].bb.num_insns;
     56     if (num_insns > 0) {
     57       blocks[ii].insns = new uint32_t[num_insns];
     58       trace->ReadStaticInsns(num_insns, blocks[ii].insns);
     59     }
     60   }
     61 
     62   // Check the last basic block.  If it contains a special undefined
     63   // instruction, then truncate the basic block at that point.
     64   uint32_t num_insns = blocks[num_static_bb - 1].bb.num_insns;
     65   uint32_t *insn_ptr = blocks[num_static_bb - 1].insns;
     66   for (uint32_t ii = 0; ii < num_insns; ++ii, ++insn_ptr) {
     67     if (*insn_ptr == 0xe6c00110) {
     68       uint32_t actual_num_insns = ii + 1;
     69       blocks[num_static_bb - 1].bb.num_insns = actual_num_insns;
     70       num_static_insn -= (num_insns - actual_num_insns);
     71 
     72       // Write the changes back to the trace file
     73       trace->TruncateLastBlock(actual_num_insns);
     74       break;
     75     }
     76   }
     77   TraceHeader *header = trace->GetHeader();
     78   strcpy(header->ident, TRACE_IDENT);
     79   header->num_static_bb = num_static_bb;
     80   header->num_dynamic_bb = 0;
     81   header->num_static_insn = num_static_insn;
     82   header->num_dynamic_insn = 0;
     83   trace->WriteHeader(header);
     84 
     85   // Reopen the trace file in order to force the trace manager to reread
     86   // the static blocks now that we have written that information to the
     87   // header.
     88   trace->Close();
     89   trace->Open(trace_filename);
     90 
     91   // Count the number of dynamic executions of basic blocks and instructions.
     92   // Also keep track of which process ids are used.
     93   uint64_t num_dynamic_bb = 0;
     94   uint64_t num_dynamic_insn = 0;
     95   while (1) {
     96     BBEvent event;
     97 
     98     if (trace->ReadBB(&event))
     99       break;
    100     if (event.bb_num >= num_static_bb) {
    101       fprintf(stderr,
    102               "Error: basic block number (%lld) too large (num blocks: %lld)\n",
    103               event.bb_num, num_static_bb);
    104       exit(1);
    105     }
    106     usedPids[event.pid] = 1;
    107     num_dynamic_bb += 1;
    108     num_dynamic_insn += event.num_insns;
    109   }
    110 
    111   // Count the number of process ids that are used and remember the first
    112   // unused pid.
    113   int numUsedPids = 0;
    114   int unusedPid = -1;
    115   for (int pid = 0; pid < kNumPids; pid++) {
    116       if (usedPids[pid] == 1) {
    117           numUsedPids += 1;
    118       } else if (unusedPid == -1) {
    119           unusedPid = pid;
    120       }
    121   }
    122 
    123   // Rewrite the header with the dynamic counts
    124   header->num_dynamic_bb = num_dynamic_bb;
    125   header->num_dynamic_insn = num_dynamic_insn;
    126   header->num_used_pids = numUsedPids;
    127   header->first_unused_pid = unusedPid;
    128   trace->WriteHeader(header);
    129   trace->Close();
    130 
    131   printf("Static basic blocks: %llu, Dynamic basic blocks: %llu\n",
    132          num_static_bb, num_dynamic_bb);
    133   printf("Static instructions: %llu, Dynamic instructions: %llu\n",
    134          num_static_insn, num_dynamic_insn);
    135 
    136   double elapsed_secs = header->elapsed_usecs / 1000000.0;
    137   double insn_per_sec = 0;
    138   if (elapsed_secs != 0)
    139     insn_per_sec = num_dynamic_insn / elapsed_secs;
    140   const char *suffix = "";
    141   if (insn_per_sec >= 1000000) {
    142     insn_per_sec /= 1000000.0;
    143     suffix = "M";
    144   } else if (insn_per_sec > 1000) {
    145     insn_per_sec /= 1000.0;
    146     suffix = "K";
    147   }
    148   printf("Elapsed seconds: %.2f, simulated instructions/sec: %.1f%s\n",
    149          elapsed_secs, insn_per_sec, suffix);
    150   return 0;
    151 }
    152