155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdio.h>
255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <stdlib.h>
355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <string.h>
455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include <inttypes.h>
555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project#include "trace_reader.h"
655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projecttypedef struct MyStaticRec {
855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  StaticRec bb;
955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint32_t  *insns;
1055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project} MyStaticRec;
1155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectconst int kNumPids = 32768;
1355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectchar usedPids[kNumPids];
1455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Projectint main(int argc, char **argv) {
1655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint32_t insns[kMaxInsnPerBB];
1755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
1855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (argc != 2) {
1955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    fprintf(stderr, "Usage: %s trace_file\n", argv[0]);
2055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    exit(1);
2155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
2255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
2355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  char *trace_filename = argv[1];
2455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  TraceReaderBase *trace = new TraceReaderBase;
2555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->SetPostProcessing(true);
2655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Open(trace_filename);
2755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
2855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Count the number of static basic blocks and instructions.
2955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint64_t num_static_bb = 0;
3055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint64_t num_static_insn = 0;
3155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  while (1) {
3255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    StaticRec static_rec;
3355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
3455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (trace->ReadStatic(&static_rec))
3555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      break;
3655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (static_rec.bb_num != num_static_bb) {
3755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      fprintf(stderr,
3855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project              "Error: basic block numbers out of order; expected %lld, got %lld\n",
3955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project              num_static_bb, static_rec.bb_num);
4055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      exit(1);
4155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
4255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    num_static_bb += 1;
4355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    num_static_insn += static_rec.num_insns;
4455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    trace->ReadStaticInsns(static_rec.num_insns, insns);
4555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
4655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Close();
4755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
4855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Allocate space for all of the static blocks
4955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  MyStaticRec *blocks = new MyStaticRec[num_static_bb];
5055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
5155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Read the static blocks again and save pointers to them
5255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Open(trace_filename);
5355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  for (uint32_t ii = 0; ii < num_static_bb; ++ii) {
5455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    trace->ReadStatic(&blocks[ii].bb);
5555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    uint32_t num_insns = blocks[ii].bb.num_insns;
5655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (num_insns > 0) {
5755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      blocks[ii].insns = new uint32_t[num_insns];
5855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      trace->ReadStaticInsns(num_insns, blocks[ii].insns);
5955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
6055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
6155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
6255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Check the last basic block.  If it contains a special undefined
6355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // instruction, then truncate the basic block at that point.
6455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint32_t num_insns = blocks[num_static_bb - 1].bb.num_insns;
6555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint32_t *insn_ptr = blocks[num_static_bb - 1].insns;
6655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  for (uint32_t ii = 0; ii < num_insns; ++ii, ++insn_ptr) {
6755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (*insn_ptr == 0xe6c00110) {
6855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      uint32_t actual_num_insns = ii + 1;
6955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      blocks[num_static_bb - 1].bb.num_insns = actual_num_insns;
7055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      num_static_insn -= (num_insns - actual_num_insns);
7155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
7255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      // Write the changes back to the trace file
7355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      trace->TruncateLastBlock(actual_num_insns);
7455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      break;
7555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
7655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
7755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  TraceHeader *header = trace->GetHeader();
7855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  strcpy(header->ident, TRACE_IDENT);
7955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_static_bb = num_static_bb;
8055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_dynamic_bb = 0;
8155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_static_insn = num_static_insn;
8255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_dynamic_insn = 0;
8355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->WriteHeader(header);
8455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
8555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Reopen the trace file in order to force the trace manager to reread
8655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // the static blocks now that we have written that information to the
8755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // header.
8855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Close();
8955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Open(trace_filename);
9055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
9155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Count the number of dynamic executions of basic blocks and instructions.
9255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Also keep track of which process ids are used.
9355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint64_t num_dynamic_bb = 0;
9455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  uint64_t num_dynamic_insn = 0;
9555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  while (1) {
9655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    BBEvent event;
9755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
9855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (trace->ReadBB(&event))
9955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      break;
10055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    if (event.bb_num >= num_static_bb) {
10155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      fprintf(stderr,
10255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project              "Error: basic block number (%lld) too large (num blocks: %lld)\n",
10355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project              event.bb_num, num_static_bb);
10455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      exit(1);
10555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    }
10655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    usedPids[event.pid] = 1;
10755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    num_dynamic_bb += 1;
10855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    num_dynamic_insn += event.num_insns;
10955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
11055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
11155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Count the number of process ids that are used and remember the first
11255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // unused pid.
11355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  int numUsedPids = 0;
11455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  int unusedPid = -1;
11555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  for (int pid = 0; pid < kNumPids; pid++) {
11655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      if (usedPids[pid] == 1) {
11755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project          numUsedPids += 1;
11855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      } else if (unusedPid == -1) {
11955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project          unusedPid = pid;
12055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project      }
12155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
12255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
12355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  // Rewrite the header with the dynamic counts
12455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_dynamic_bb = num_dynamic_bb;
12555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_dynamic_insn = num_dynamic_insn;
12655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->num_used_pids = numUsedPids;
12755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  header->first_unused_pid = unusedPid;
12855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->WriteHeader(header);
12955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  trace->Close();
13055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
13155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  printf("Static basic blocks: %llu, Dynamic basic blocks: %llu\n",
13255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project         num_static_bb, num_dynamic_bb);
13355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  printf("Static instructions: %llu, Dynamic instructions: %llu\n",
13455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project         num_static_insn, num_dynamic_insn);
13555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project
13655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  double elapsed_secs = header->elapsed_usecs / 1000000.0;
13755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  double insn_per_sec = 0;
13855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (elapsed_secs != 0)
13955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    insn_per_sec = num_dynamic_insn / elapsed_secs;
140d4d5b4f63a5760b2212166f539f906edda0bc4deJack Veenstra  const char *suffix = "";
14155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  if (insn_per_sec >= 1000000) {
14255a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    insn_per_sec /= 1000000.0;
14355a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    suffix = "M";
14455a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  } else if (insn_per_sec > 1000) {
14555a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    insn_per_sec /= 1000.0;
14655a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project    suffix = "K";
14755a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  }
14855a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  printf("Elapsed seconds: %.2f, simulated instructions/sec: %.1f%s\n",
14955a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project         elapsed_secs, insn_per_sec, suffix);
15055a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project  return 0;
15155a2c71f27d3e0b8344597c7f281e687cb7aeb1bThe Android Open Source Project}
152