OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / sdk / emulator / qtools / post_trace.cpp
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 }