• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <inttypes.h>
5 #include "trace_reader.h"
6 #include "armdis.h"
7 
8 struct MyStaticRec {
9     StaticRec   bb;
10     uint32_t    *insns;
11     uint32_t    *cycles;    // number of cycles for each insn
12     uint32_t    elapsed;    // number of cycles for basic block
13     int         freq;       // execution frequency
14     MyStaticRec *inner;     // pointer to an inner basic block
15     int         is_thumb;
16 };
17 
18 MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks);
19 
20 // This function is called from quicksort to compare addresses of basic
21 // blocks.
cmp_inc_addr(const void * a,const void * b)22 int cmp_inc_addr(const void *a, const void *b) {
23     MyStaticRec *bb1, *bb2;
24 
25     bb1 = *(MyStaticRec**)a;
26     bb2 = *(MyStaticRec**)b;
27     if (bb1->bb.bb_addr < bb2->bb.bb_addr)
28         return -1;
29     if (bb1->bb.bb_addr > bb2->bb.bb_addr)
30         return 1;
31     return bb1->bb.bb_num - bb2->bb.bb_num;
32 }
33 
34 // This function is called from quicksort to compare the elapsed time
35 // of basic blocks.
cmp_dec_elapsed(const void * a,const void * b)36 int cmp_dec_elapsed(const void *a, const void *b) {
37     MyStaticRec *bb1, *bb2;
38 
39     bb1 = *(MyStaticRec**)a;
40     bb2 = *(MyStaticRec**)b;
41     if (bb1->elapsed < bb2->elapsed)
42         return 1;
43     if (bb1->elapsed > bb2->elapsed)
44         return -1;
45     return bb1->bb.bb_num - bb2->bb.bb_num;
46 }
47 
48 // This function is called from quicksort to compare frequencies of
49 // basic blocks.
cmp_dec_freq(const void * a,const void * b)50 int cmp_dec_freq(const void *a, const void *b) {
51     MyStaticRec *bb1, *bb2;
52 
53     bb1 = *(MyStaticRec**)a;
54     bb2 = *(MyStaticRec**)b;
55     if (bb1->freq < bb2->freq)
56         return 1;
57     if (bb1->freq > bb2->freq)
58         return -1;
59     return bb1->bb.bb_num - bb2->bb.bb_num;
60 }
61 
main(int argc,char ** argv)62 int main(int argc, char **argv)
63 {
64     if (argc != 2) {
65         fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
66         exit(1);
67     }
68 
69     char *trace_filename = argv[1];
70     TraceReaderBase *trace = new TraceReaderBase;
71     trace->Open(trace_filename);
72     TraceHeader *header = trace->GetHeader();
73     uint32_t num_static_bb = header->num_static_bb;
74 
75     // Allocate space for all of the static blocks
76     MyStaticRec *blocks = new MyStaticRec[num_static_bb];
77 
78     // Read in all the static blocks
79     for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
80         trace->ReadStatic(&blocks[ii].bb);
81         blocks[ii].is_thumb = blocks[ii].bb.bb_addr & 1;
82         blocks[ii].bb.bb_addr &= ~1;
83         uint32_t num_insns = blocks[ii].bb.num_insns;
84         blocks[ii].insns = new uint32_t[num_insns];
85         blocks[ii].cycles = new uint32_t[num_insns];
86         memset(blocks[ii].cycles, 0, num_insns * sizeof(uint32_t));
87         trace->ReadStaticInsns(num_insns, blocks[ii].insns);
88         blocks[ii].elapsed = 0;
89         blocks[ii].freq = 0;
90         blocks[ii].inner = NULL;
91     }
92 
93     MyStaticRec **sorted = assign_inner_blocks(num_static_bb, blocks);
94 
95     uint32_t prev_time = 0;
96     uint32_t elapsed = 0;
97     uint32_t dummy;
98     uint32_t *cycle_ptr = &dummy;
99     uint32_t *bb_elapsed_ptr = &dummy;
100     while (1) {
101         BBEvent event;
102 
103         if (trace->ReadBB(&event))
104             break;
105         // Assign frequencies to each basic block
106         uint64_t bb_num = event.bb_num;
107         int num_insns = event.num_insns;
108         blocks[bb_num].freq += 1;
109         for (MyStaticRec *bptr = blocks[bb_num].inner; bptr; bptr = bptr->inner)
110             bptr->freq += 1;
111 
112         // Assign simulation time to each instruction
113         for (MyStaticRec *bptr = &blocks[bb_num]; bptr; bptr = bptr->inner) {
114             uint32_t bb_num_insns = bptr->bb.num_insns;
115             for (uint32_t ii = 0; num_insns && ii < bb_num_insns; ++ii, --num_insns) {
116                 uint32_t sim_time = trace->ReadInsnTime(event.time);
117                 elapsed = sim_time - prev_time;
118                 prev_time = sim_time;
119 
120                 // Attribute the elapsed time to the previous instruction and
121                 // basic block.
122                 *cycle_ptr += elapsed;
123                 *bb_elapsed_ptr += elapsed;
124                 cycle_ptr = &bptr->cycles[ii];
125                 bb_elapsed_ptr = &bptr->elapsed;
126             }
127         }
128     }
129     *cycle_ptr += 1;
130     *bb_elapsed_ptr += 1;
131 
132     // Sort the basic blocks into decreasing elapsed time
133     qsort(sorted, num_static_bb, sizeof(MyStaticRec*), cmp_dec_elapsed);
134 
135     char spaces[80];
136     memset(spaces, ' ', 79);
137     spaces[79] = 0;
138     for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
139         printf("bb %lld addr: 0x%x, insns: %d freq: %u elapsed: %u\n",
140                sorted[ii]->bb.bb_num, sorted[ii]->bb.bb_addr,
141                sorted[ii]->bb.num_insns, sorted[ii]->freq,
142                sorted[ii]->elapsed);
143         int num_insns = sorted[ii]->bb.num_insns;
144         uint32_t addr = sorted[ii]->bb.bb_addr;
145         for (int jj = 0; jj < num_insns; ++jj) {
146             uint32_t elapsed = sorted[ii]->cycles[jj];
147             uint32_t insn = sorted[ii]->insns[jj];
148             if (insn_is_thumb(insn)) {
149                 insn = insn_unwrap_thumb(insn);
150 
151                 // thumb_pair is true if this is the first of a pair of
152                 // thumb instructions (BL or BLX).
153                 bool thumb_pair = ((insn & 0xf800) == 0xf000);
154 
155                 // Get the next thumb instruction (if any) because we may need
156                 // it for the case where insn is BL or BLX.
157                 uint32_t insn2 = 0;
158                 if (thumb_pair && (jj + 1 < num_insns)) {
159                     insn2 = sorted[ii]->insns[jj + 1];
160                     insn2 = insn_unwrap_thumb(insn2);
161                     jj += 1;
162                 }
163                 char *disasm = disasm_insn_thumb(addr, insn, insn2, NULL);
164                 if (thumb_pair) {
165                     printf("  %4u %08x %04x %04x %s\n", elapsed, addr, insn,
166                            insn2, disasm);
167                     addr += 2;
168                 } else {
169                     printf("  %4u %08x     %04x %s\n", elapsed, addr, insn,
170                            disasm);
171                 }
172                 addr += 2;
173             } else {
174                 char *disasm = Arm::disasm(addr, insn, NULL);
175                 printf("  %4u %08x %08x %s\n", elapsed, addr, insn, disasm);
176                 addr += 4;
177             }
178         }
179     }
180 
181     delete[] sorted;
182     return 0;
183 }
184 
185 // Find the basic blocks that are subsets of other basic blocks.
assign_inner_blocks(int num_blocks,MyStaticRec * blocks)186 MyStaticRec **assign_inner_blocks(int num_blocks, MyStaticRec *blocks)
187 {
188     int ii;
189     uint32_t addr_end, addr_diff;
190 
191     // Create a list of pointers to the basic blocks that we can sort.
192     MyStaticRec **sorted = new MyStaticRec*[num_blocks];
193     for (ii = 0; ii < num_blocks; ++ii) {
194         sorted[ii] = &blocks[ii];
195     }
196 
197     // Sort the basic blocks into increasing address order
198     qsort(sorted, num_blocks, sizeof(MyStaticRec*), cmp_inc_addr);
199 
200     // Create pointers to inner blocks and break up the enclosing block
201     // so that there is no overlap.
202     for (ii = 0; ii < num_blocks - 1; ++ii) {
203         int num_bytes;
204         if (sorted[ii]->is_thumb)
205             num_bytes = sorted[ii]->bb.num_insns << 1;
206         else
207             num_bytes = sorted[ii]->bb.num_insns << 2;
208         addr_end = sorted[ii]->bb.bb_addr + num_bytes;
209         if (addr_end > sorted[ii + 1]->bb.bb_addr) {
210             sorted[ii]->inner = sorted[ii + 1];
211             addr_diff = sorted[ii + 1]->bb.bb_addr - sorted[ii]->bb.bb_addr;
212             uint32_t num_insns;
213             if (sorted[ii]->is_thumb)
214                 num_insns = addr_diff >> 1;
215             else
216                 num_insns = addr_diff >> 2;
217             sorted[ii]->bb.num_insns = num_insns;
218         }
219     }
220 
221     return sorted;
222 }
223