OpenCores
URL https://opencores.org/ocsvn/or2k/or2k/trunk

Subversion Repositories or2k

[/] [or2k/] [trunk/] [analysis-bin/] [opcodeanalysis/] [opcodeanalysis.c] - Blame information for rev 13

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 julius
/*
2
  Instruction opcode frequency analysis application
3
 
4
  Author:
5
  Julius Baxter - julius.baxter@orsoc.se
6
 
7
*/
8
 
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <string.h>
12
 
13
// Opcode space in OR1K is 32-bits, so maximum 64 opcodes
14
#define MAX_OR1K_32_OPCODES 64
15
// Array of opcode string pointers (we malloc space for actual strings)
16
char *opcode_strings[MAX_OR1K_32_OPCODES];
17
// Count for occurance of each opcode
18
int opcode_count[MAX_OR1K_32_OPCODES];
19
 
20 13 julius
// Maximum number of pairs to keep track of
21 9 julius
#define MAX_OR1K_32_PAIRS (MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES)
22
// 2-dimensional array, long enough to hold all possible pairs, and the 2
23
// indexes corresponding to their opcode in the *opcode_strings[] array
24
// Ie. Each will be: [previous_opcode][current_opcode][count]
25
int opcode_pairs[MAX_OR1K_32_PAIRS][3];
26
 
27 13 julius
// Maximum number of triplets to kep track of
28 9 julius
#define MAX_OR1K_32_TRIPLETS (MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES)
29
// 2-dimensional array, long enough to hold all possible pairs, and the 2
30
// indexes corresponding to their opcode in the *opcode_strings[] array
31 13 julius
// Ie. Each will be: 
32
//      [second_prev][first_prev][current_opcode][count]
33 9 julius
int opcode_triplets[MAX_OR1K_32_TRIPLETS][4];
34
 
35 13 julius
// Maximum number of quadruples to keep track of
36 9 julius
#define MAX_OR1K_32_QUADS (MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES)
37
// 2-dimensional array, long enough to hold all possible pairs, and the 2
38
// indexes corresponding to their opcode in the *opcode_strings[] array
39 13 julius
// Ie. Each will be: 
40
//  [third_prev][second_prev][first_prev][current_opcode][count]
41 9 julius
int opcode_quads[MAX_OR1K_32_QUADS][5];
42
 
43
// Strings shouldn't be more than 32 bytes long
44
#define OPCODE_STRING_SIZE 32
45
 
46
// Indicator for an opcode we haven't seen before
47
#define IS_UNIQUE -1
48
 
49 13 julius
// Result defines
50 9 julius
#define SORTED_DESCENDING_DISPLAY
51
 
52 13 julius
// Style of output  - String or CSV
53
// Uncomment only 1!
54
#define DISPLAY_STRING
55
//#define DISPLAY_CSV
56
 
57
// Report only the 10 most common pairs/triples/quadruples, etc
58
#define MAX_SETS_TO_REPORT 10
59
 
60 9 julius
// Little function to strip newlines
61
inline void strip_newline(char* str)
62
{
63
  int len = strlen(str);
64
  if (str[len-1] == '\n')
65
    str[len-1] = '\0';
66
 
67
}
68
 
69
// Return the position in the index this instruction is at
70
// else -1 if it isn't
71
int check_opcode(char *opcode_to_check, int num_opcodes_so_far)
72
{
73
  // Get stringlength of current instruction
74
  int opcode_strlen = strlen(opcode_to_check);
75
 
76
  int i = 0;
77
  // Loop for all opcodes we have so far
78
  while (i < num_opcodes_so_far)
79
    {
80
      // Do we have a match?
81
      // Debugging output
82
      //printf("Comparing: %s (%d) == %s (%d) ?\n", 
83
      //             opcode_to_check, opcode_strlen,
84
      //             opcode_strings[i], strlen(opcode_strings[i]));
85
      if ((strncmp(opcode_to_check, opcode_strings[i], opcode_strlen) == 0)
86
          && (strlen(opcode_strings[i]) == opcode_strlen))
87
        // Found a match - return its index
88
        return i;
89
      // No match yet, go to next opcode
90
      i++;
91
    }
92
  // No opcodes found, indicate it's one we haven't seen before
93
  return IS_UNIQUE;
94
}
95
 
96
// Record an opcode in our list of known opcodes
97
void add_opcode(char *opcode_to_add, int num_opcodes_so_far)
98
{
99
  int opcode_strlen = strlen(opcode_to_add);
100
 
101
  // Malloc space to hold the new opcode string
102
  char *new_opcode;
103
  new_opcode = (char*) calloc(OPCODE_STRING_SIZE, 1);
104
 
105
  // Copy in opcode string
106
  strncpy(new_opcode, opcode_to_add, opcode_strlen);
107
 
108
  // Now store the pointer to this new opcode string
109
  opcode_strings[num_opcodes_so_far] = new_opcode;
110
 
111
  // Initialise count
112
  opcode_count[num_opcodes_so_far] = 1;
113
 
114
  return;
115
}
116
 
117
// Increment the count for this opcode
118
void count_opcode(int opcode_index)
119
{
120
  opcode_count[opcode_index]++;
121
 
122
  return;
123
}
124
 
125
 
126
 
127 13 julius
void display_opcodes(int total_unique_opcodes, int total_opcodes_counted)
128 9 julius
{
129 13 julius
 
130
#ifdef DISPLAY_STRING  
131
  // Totals
132
  printf("Number of total opcodes: %d\n",total_opcodes_counted);
133
  printf("Number unique opcodes: %d\n", total_unique_opcodes);
134
#endif
135
#ifdef DISPLAY_CSV
136
  printf("\"Opcode\",\"Occurances\",\"%%'age of total\",\"Total opcodes counted:\",%d\n",total_opcodes_counted);
137
#endif
138
 
139 9 julius
#ifdef SIMPLE_DISPLAY  
140
  while (total_unique_opcodes)
141
    {
142
      --total_unique_opcodes;
143
      printf("Opcode:\t%s\tCount:\t%d\n",
144
             opcode_strings[total_unique_opcodes],
145
             opcode_count[total_unique_opcodes]);
146
    }
147
#endif
148
#ifdef SORTED_DESCENDING_DISPLAY
149
  int i, largest, largest_index;
150
  int initial_total = total_unique_opcodes;
151
  while (total_unique_opcodes)
152
    {
153
      --total_unique_opcodes;
154
      largest=0;
155
      // Go through the list, find the largest, print it, eliminate it
156
      for(i=0;i<initial_total;i++)
157
        if(opcode_count[i] > largest)
158
          {
159
            largest = opcode_count[i];
160
            largest_index = i;
161
          }
162 13 julius
 
163
      printf(
164
#ifdef DISPLAY_STRING      
165
             "Opcode:\t%s\tCount:\t%d\t(%f%%)\n",
166
#endif
167
#ifdef DISPLAY_CSV
168
             // CSV format - "opcode string",frequency,percentage
169
             "\"%s\",%d,%f\n",
170
#endif
171
             opcode_strings[largest_index],
172
             opcode_count[largest_index],
173
             (float)(((float)opcode_count[largest_index])/
174
                     ((float)total_opcodes_counted))*100.f);
175 9 julius
 
176
 
177
      opcode_count[largest_index] = -1; // Eliminate this one
178
 
179
    }
180
#endif
181 13 julius
 
182 9 julius
 
183
}
184
 
185
// Deal with opcode pair checking
186
int opcode_pair_check( int previous_opcode_index, int current_opcode_index,
187
                       int total_pairs )
188
{
189
  int i;
190
  // Check through for this pair's occurance before
191
  for (i=0;i<total_pairs;i++)
192
    {
193
      if ((opcode_pairs[i][0] == previous_opcode_index) &&
194
          (opcode_pairs[i][1] == current_opcode_index))
195
        // Found a match
196
        {
197
          opcode_pairs[i][2]++;
198
          return 0;
199
        }
200
    }
201
  // No match, let's create a new entry
202
  // Index for previous opcode
203
  opcode_pairs[total_pairs][0] = previous_opcode_index;
204
  // Index for current opcode
205
  opcode_pairs[total_pairs][1] = current_opcode_index;
206
  // Count for this pair
207
  opcode_pairs[total_pairs][2] = 1;
208
 
209
  return 1;
210
 
211
}
212
 
213
 
214 13 julius
void opcode_pair_report(int total_opcode_sets)
215 9 julius
{
216
 
217
  int i, largest, largest_index;
218 13 julius
  int initial_total = total_opcode_sets;
219 9 julius
 
220 13 julius
#ifdef DISPLAY_STRING 
221
  printf("Number of unique opcode pairs: %d\n", total_opcode_sets);
222
#endif
223
#ifdef DISPLAY_CSV
224
  printf("\"Opcode pair\",\"Occurances\",\"Total unique pairs:\",%d\n",
225
         total_opcode_sets);
226
#endif
227
 
228
  while (total_opcode_sets)
229 9 julius
    {
230 13 julius
      --total_opcode_sets;
231 9 julius
      largest=0;
232
      // Go through the list, find the largest, print it, eliminate it
233
      for(i=0;i<initial_total;i++)
234
        if(opcode_pairs[i][2] > largest)
235
          {
236
            largest = opcode_pairs[i][2];
237
            largest_index = i;
238
          }
239 13 julius
      printf(
240
#ifdef DISPLAY_STRING            
241
             "Opcode pair:\t%s\t%s\tCount:\t%d\n",
242
#endif
243
#ifdef DISPLAY_CSV
244
             "\"%s %s\",%d\n",
245
#endif
246
 
247 9 julius
             opcode_strings[opcode_pairs[largest_index][0]],
248
             opcode_strings[opcode_pairs[largest_index][1]],
249
             opcode_pairs[largest_index][2]);
250
 
251 13 julius
 
252 9 julius
      opcode_pairs[largest_index][2] = -1; // Eliminate this one
253 13 julius
 
254
      // If we've printed out the maximum we wanted then return
255
      if ((initial_total - total_opcode_sets) == MAX_SETS_TO_REPORT)
256
        return;
257 9 julius
 
258 13 julius
 
259 9 julius
    }
260
 
261
 
262
}
263
 
264
// Deal with opcode triplet checking
265
int opcode_triplet_check(int second_previous_opcode_index,
266
                         int previous_opcode_index,
267
                         int current_opcode_index,
268
                         int sets_so_far )
269
{
270
  int i;
271
  // Check through for this pair's occurance before
272
  for (i=0;i<sets_so_far;i++)
273
    {
274
      if ((opcode_triplets[i][0] == second_previous_opcode_index) &&
275
          (opcode_triplets[i][1] == previous_opcode_index) &&
276
          (opcode_triplets[i][2] == current_opcode_index))
277
 
278
        // Found a match
279
        {
280
          opcode_triplets[i][3]++;
281
          return 0;
282
        }
283
    }
284
  // No match, let's create a new entry
285
  opcode_triplets[sets_so_far][0] = second_previous_opcode_index;
286
  // Index for previous opcode
287
  opcode_triplets[sets_so_far][1] = previous_opcode_index;
288
  // Index for current opcode
289
  opcode_triplets[sets_so_far][2] = current_opcode_index;
290
  // Count for this pair
291
  opcode_triplets[sets_so_far][3] = 1;
292
 
293
  return 1;
294
 
295
}
296
 
297
void opcode_triplet_report(int total_opcode_sets)
298
{
299
 
300
  int i, largest, largest_index;
301
  int initial_total = total_opcode_sets;
302
 
303 13 julius
#ifdef DISPLAY_STRING 
304
  printf("Number of unique opcode triplets: %d\n", total_opcode_sets);
305
#endif
306
#ifdef DISPLAY_CSV
307
  printf("\"Opcode triplet\",\"Occurances\",\"Total unique triplets:\",%d\n",
308
         total_opcode_sets);
309
#endif
310
 
311 9 julius
  while (total_opcode_sets)
312
    {
313
      --total_opcode_sets;
314
      largest=0;
315
      // Go through the list, find the largest, print it, eliminate it
316
      for(i=0;i<initial_total;i++)
317
        if(opcode_triplets[i][3] > largest)
318
          {
319
            largest = opcode_triplets[i][3];
320
            largest_index = i;
321
          }
322
 
323 13 julius
      printf(
324
#ifdef DISPLAY_STRING
325
             "Opcode triplet:\t%s\t%s\t%s\tCount:\t%d\n",
326
#endif
327
#ifdef DISPLAY_CSV
328
             "\"%s %s %s\",%d\n",
329
#endif       
330 9 julius
             opcode_strings[opcode_triplets[largest_index][0]],
331
             opcode_strings[opcode_triplets[largest_index][1]],
332
             opcode_strings[opcode_triplets[largest_index][2]],
333
             opcode_triplets[largest_index][3]);
334
 
335
      opcode_triplets[largest_index][3] = -1; // Eliminate this one
336
 
337 13 julius
      // If we've printed out the maximum we wanted then return
338
      if ((initial_total - total_opcode_sets) == MAX_SETS_TO_REPORT)
339
        return;
340
 
341 9 julius
    }
342
}
343
 
344
// Deal with opcode triplet checking
345
int opcode_quad_check(int third_previous_opcode_index,
346
                      int second_previous_opcode_index,
347
                      int previous_opcode_index,
348
                      int current_opcode_index,
349
                      int sets_so_far )
350
{
351
  int i;
352
  // Check through for this pair's occurance before
353
  for (i=0;i<sets_so_far;i++)
354
    {
355
      if ((opcode_quads[i][0] == third_previous_opcode_index) &&
356
          (opcode_quads[i][1] == second_previous_opcode_index) &&
357
          (opcode_quads[i][2] == previous_opcode_index) &&
358
          (opcode_quads[i][3] == current_opcode_index))
359
 
360
        // Found a match
361
        {
362
          opcode_quads[i][4]++;
363
          return 0;
364
        }
365
    }
366
  // No match, let's create a new entry
367
  opcode_quads[sets_so_far][0] = third_previous_opcode_index;
368
  opcode_quads[sets_so_far][1] = second_previous_opcode_index;
369
  // Index for previous opcode
370
  opcode_quads[sets_so_far][2] = previous_opcode_index;
371
  // Index for current opcode
372
  opcode_quads[sets_so_far][3] = current_opcode_index;
373
  // Count for this pair
374
  opcode_quads[sets_so_far][4] = 1;
375
 
376
  return 1;
377
 
378
}
379
 
380
void opcode_quad_report(int total_opcode_sets)
381
{
382
 
383
  int i, largest, largest_index;
384
  int initial_total = total_opcode_sets;
385
 
386 13 julius
#ifdef DISPLAY_STRING 
387
  printf("Number of unique opcode quads: %d\n", total_opcode_sets);
388
#endif
389
#ifdef DISPLAY_CSV
390
  printf("\"Opcode quad\",\"Occurances\",\"Total unique quadruples:\",%d\n",
391
         total_opcode_sets);
392
#endif
393
 
394 9 julius
  while (total_opcode_sets)
395
    {
396
      --total_opcode_sets;
397
      largest=0;
398
      // Go through the list, find the largest, print it, eliminate it
399
      for(i=0;i<initial_total;i++)
400
        if(opcode_quads[i][4] > largest)
401
          {
402
            largest = opcode_quads[i][4];
403
            largest_index = i;
404
          }
405
 
406 13 julius
      printf(
407
#ifdef DISPLAY_STRING
408
             "Opcode triplet:\t%s\t%s\t%s\t%s\tCount:\t%d\n",
409
#endif
410
#ifdef DISPLAY_CSV
411
             "\"%s %s %s %s\",%d\n",
412
#endif       
413 9 julius
             opcode_strings[opcode_quads[largest_index][0]],
414
             opcode_strings[opcode_quads[largest_index][1]],
415
             opcode_strings[opcode_quads[largest_index][2]],
416
             opcode_strings[opcode_quads[largest_index][3]],
417
             opcode_quads[largest_index][4]);
418
 
419
      opcode_quads[largest_index][4] = -1; // Eliminate this one
420 13 julius
 
421
      // If we've printed out the maximum we wanted then return
422
      if ((initial_total - total_opcode_sets) == MAX_SETS_TO_REPORT)
423
        return;
424 9 julius
 
425
    }
426
}
427
 
428
 
429
int main(int argc, char *argv[])
430
{
431
  FILE *fp;
432
 
433
  char current_opcode[OPCODE_STRING_SIZE];
434
 
435
  int num_unique_opcodes = 0;
436
 
437
  int opcode_index;
438
 
439
  int total_seen_opcodes = 0;
440
 
441
  int previous_opcode_indexes[16]; // keep last 16 opcode indexes
442
 
443
  int i;
444
 
445
  int num_opcode_pairs = 0;
446
 
447
  int num_opcode_triplets = 0;
448
  int num_opcode_quads = 0;
449
 
450
 
451
 
452
  if((fp = fopen(argv[ 1 ], "r"))==NULL) {
453
    printf("Cannot open file.\n");
454
    exit(1);
455
  }
456
 
457
  // Do initial instruction set analysis
458
  while(!feof(fp)) {
459
    if(fgets(current_opcode, OPCODE_STRING_SIZE, fp))
460
      {
461
 
462
        strip_newline(current_opcode);
463
        //printf("Checking for: %s \n", current_opcode);
464
 
465
        // Find if we have this opcode already, if so we'll get its index in
466
        // the list, else we'll get an indication that it's unique
467
        opcode_index = check_opcode(current_opcode, num_unique_opcodes);
468
 
469
        if (opcode_index == IS_UNIQUE)
470
          {
471
            // Add this opcode to our list so we know it now
472
            add_opcode(current_opcode, num_unique_opcodes);
473
            // Increment the number of known opcodes
474
            num_unique_opcodes++;
475
          }
476
        else
477
          // Is not unique, just increment the incidences of this opcode
478
          count_opcode(opcode_index);
479
 
480
        // Track the total number of opcodes we've looked at
481
        total_seen_opcodes++;
482
 
483
        // Error check - bail out early if we're doing something wrong and
484
        // there's too many unique opcodes (ISA is only so big...)
485
        if (num_unique_opcodes == MAX_OR1K_32_OPCODES)
486
          {
487
            printf("Error: Reached maximum opcodes\n");
488
            break;
489
          }
490
 
491
        //printf("So far: unique: %d total: %d\n", 
492
        //num_unique_opcodes, total_seen_opcodes);
493
 
494
      }
495
  }
496
 
497 13 julius
  // Print some more detailed information
498
  display_opcodes(num_unique_opcodes, total_seen_opcodes);
499 9 julius
 
500 13 julius
#ifdef DISPLAY_STRING
501
  fprintf(stdout,"Beginning groups analysis\n");
502
#endif
503 9 julius
 
504
  // Now do groups analysis
505
  rewind(fp);
506
 
507
  // Reset total_seen_opcodes, we'll count through the list again
508
 
509
  total_seen_opcodes = 0;
510
 
511
  while(!feof(fp)) {
512
    if(fgets(current_opcode, OPCODE_STRING_SIZE, fp))
513
      {
514
 
515
        total_seen_opcodes++;
516
 
517
        strip_newline(current_opcode);
518
 
519
        // Find if we have this opcode already, if so we'll get its index in
520
        // the list, else we'll get an indication that it's unique
521
        opcode_index = check_opcode(current_opcode, num_unique_opcodes);
522
 
523
        if (opcode_index == IS_UNIQUE)
524
          {
525
            // Error! Should not have unique opcodes here...
526
            printf("Unique opcode detected during pair analysis.\n");
527
            break;
528
          }
529
 
530
        // Now pass this current pair to the function to check if we've seen
531
        // it before - if not we record it (and return 1) else we just increment
532
        // count of it (and return 0)
533
        if (total_seen_opcodes > 1)
534
          {
535
            if (opcode_pair_check(previous_opcode_indexes[0], opcode_index,
536
                                  num_opcode_pairs))
537
              num_opcode_pairs++;
538
          }
539
 
540
        if (total_seen_opcodes > 2)
541
          {
542
            if (opcode_triplet_check(previous_opcode_indexes[1],
543
                                     previous_opcode_indexes[0],
544
                                     opcode_index,
545
                                     num_opcode_triplets))
546
              num_opcode_triplets++;
547
          }
548
        if (total_seen_opcodes > 3)
549
          {
550
            if (opcode_quad_check(previous_opcode_indexes[2],
551
                                  previous_opcode_indexes[1],
552
                                  previous_opcode_indexes[0],
553
                                  opcode_index,
554
                                  num_opcode_quads))
555
              num_opcode_quads++;
556
          }
557
        // Shift along our list of previously seen opcodes
558
        for (i=16-1;i > 0; i--)
559
          previous_opcode_indexes[i] = previous_opcode_indexes[i-1];
560
 
561
        previous_opcode_indexes[0] = opcode_index;
562
 
563
      }
564
  }
565
 
566
  opcode_pair_report(num_opcode_pairs);
567
 
568
  opcode_triplet_report(num_opcode_pairs);
569
 
570
  opcode_quad_report(num_opcode_quads);
571
 
572 13 julius
  // Close file pointer, we're done with it
573
  fclose(fp);
574 9 julius
 
575
  // Free all the strings we declared
576
  while(num_unique_opcodes)
577
    {
578
      --num_unique_opcodes;
579
      free(opcode_strings[num_unique_opcodes]);
580
    }
581
 
582
  //printf("freeing complete: %d\n", num_unique_opcodes);
583
 
584
  return 0;
585
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.