URL
https://opencores.org/ocsvn/or2k/or2k/trunk
Subversion Repositories or2k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or2k/trunk
- from Rev 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/analysis-bin/opcodeanalysis/Makefile
0,0 → 1,8
|
all: opcodeanalysis |
|
%: %.c |
gcc -O2 $< -o $@ |
|
clean: |
rm -f opcodeanalysis |
/analysis-bin/opcodeanalysis/README
0,0 → 1,44
Opcode analysis program |
|
This program is designed to help look at the frequency of opcodes, and the |
occurance of groups of opcodes together. |
|
This can also be done on the command line, but it was felt, at the time a C |
program might be a quicker way. 3 hours later, it's not the author's intention |
to now try doing this with sed, awk and sort. |
|
The list of instructions/opcodes should be one per line, with a newline at the |
end. There is no capability to look at register numbers. An example of |
generating suitable input to the program is given below. |
|
At the moment this program only analyses up to quadruples, and is not codeded |
in such a way that makes an arbitrary number of instruction groups easily |
testable. Fix this if you like. |
|
There are no options when running the program. It will simply spit out a list |
of individual opcodes, then list of pairs, triples and quadruples. |
|
Compile the program with |
$ make all |
|
Generate a list of opcodes from a large set of code, with the following: |
|
Disassemble an application with: |
$ or32-elf-objdump -d app.elf > app.dis |
|
The generate a list of opcodes with |
$ grep "l\." app.dis | cut -d '.' -f 2 | cut -d ' ' -f 1 > opcodes |
|
Call the program and pass the file with the list of opcodes as the first |
argument. It's best to pipe the output it generates to a file: |
$ opcodeanalysis opcodes > opcodes.analsys |
|
Things that might be good: |
* Actually verifying the pair/triple/quadruple results are correct/true |
* Limiting the output of set results to the first 5/10/20 |
* Provide an option to perform register analysis, also. |
* Generate CSV formatted output |
|
|
Julius Baxter |
14 July, 2010 |
/analysis-bin/opcodeanalysis/opcodeanalysis.c
0,0 → 1,513
/* |
Instruction opcode frequency analysis application |
|
Author: |
Julius Baxter - julius.baxter@orsoc.se |
|
*/ |
|
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
|
// Opcode space in OR1K is 32-bits, so maximum 64 opcodes |
#define MAX_OR1K_32_OPCODES 64 |
// Array of opcode string pointers (we malloc space for actual strings) |
char *opcode_strings[MAX_OR1K_32_OPCODES]; |
// Count for occurance of each opcode |
int opcode_count[MAX_OR1K_32_OPCODES]; |
|
// Maximum number of pairs |
#define MAX_OR1K_32_PAIRS (MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES) |
// 2-dimensional array, long enough to hold all possible pairs, and the 2 |
// indexes corresponding to their opcode in the *opcode_strings[] array |
// Ie. Each will be: [previous_opcode][current_opcode][count] |
int opcode_pairs[MAX_OR1K_32_PAIRS][3]; |
|
// Maximum number of pairs |
#define MAX_OR1K_32_TRIPLETS (MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES) |
// 2-dimensional array, long enough to hold all possible pairs, and the 2 |
// indexes corresponding to their opcode in the *opcode_strings[] array |
// Ie. Each will be: [second_previous_opcode][first_previous_opcode][current_opcode][count] |
int opcode_triplets[MAX_OR1K_32_TRIPLETS][4]; |
|
// Maximum number of pairs |
#define MAX_OR1K_32_QUADS (MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES*MAX_OR1K_32_OPCODES) |
// 2-dimensional array, long enough to hold all possible pairs, and the 2 |
// indexes corresponding to their opcode in the *opcode_strings[] array |
// Ie. Each will be: [second_previous_opcode][first_previous_opcode][current_opcode][count] |
int opcode_quads[MAX_OR1K_32_QUADS][5]; |
|
// Strings shouldn't be more than 32 bytes long |
#define OPCODE_STRING_SIZE 32 |
|
// Indicator for an opcode we haven't seen before |
#define IS_UNIQUE -1 |
|
// Result type |
#define SORTED_DESCENDING_DISPLAY |
|
// Little function to strip newlines |
inline void strip_newline(char* str) |
{ |
int len = strlen(str); |
if (str[len-1] == '\n') |
str[len-1] = '\0'; |
|
} |
|
// Return the position in the index this instruction is at |
// else -1 if it isn't |
int check_opcode(char *opcode_to_check, int num_opcodes_so_far) |
{ |
// Get stringlength of current instruction |
int opcode_strlen = strlen(opcode_to_check); |
|
int i = 0; |
// Loop for all opcodes we have so far |
while (i < num_opcodes_so_far) |
{ |
// Do we have a match? |
// Debugging output |
//printf("Comparing: %s (%d) == %s (%d) ?\n", |
// opcode_to_check, opcode_strlen, |
// opcode_strings[i], strlen(opcode_strings[i])); |
if ((strncmp(opcode_to_check, opcode_strings[i], opcode_strlen) == 0) |
&& (strlen(opcode_strings[i]) == opcode_strlen)) |
// Found a match - return its index |
return i; |
// No match yet, go to next opcode |
i++; |
} |
// No opcodes found, indicate it's one we haven't seen before |
return IS_UNIQUE; |
} |
|
// Record an opcode in our list of known opcodes |
void add_opcode(char *opcode_to_add, int num_opcodes_so_far) |
{ |
int opcode_strlen = strlen(opcode_to_add); |
|
// Malloc space to hold the new opcode string |
char *new_opcode; |
new_opcode = (char*) calloc(OPCODE_STRING_SIZE, 1); |
|
// Copy in opcode string |
strncpy(new_opcode, opcode_to_add, opcode_strlen); |
|
// Now store the pointer to this new opcode string |
opcode_strings[num_opcodes_so_far] = new_opcode; |
|
// Initialise count |
opcode_count[num_opcodes_so_far] = 1; |
|
return; |
} |
|
// Increment the count for this opcode |
void count_opcode(int opcode_index) |
{ |
opcode_count[opcode_index]++; |
|
return; |
} |
|
|
|
void display_opcodes(int total_unique_opcodes) |
{ |
#ifdef SIMPLE_DISPLAY |
while (total_unique_opcodes) |
{ |
--total_unique_opcodes; |
printf("Opcode:\t%s\tCount:\t%d\n", |
opcode_strings[total_unique_opcodes], |
opcode_count[total_unique_opcodes]); |
} |
#endif |
#ifdef SORTED_DESCENDING_DISPLAY |
int i, largest, largest_index; |
int initial_total = total_unique_opcodes; |
while (total_unique_opcodes) |
{ |
--total_unique_opcodes; |
largest=0; |
// Go through the list, find the largest, print it, eliminate it |
for(i=0;i<initial_total;i++) |
if(opcode_count[i] > largest) |
{ |
largest = opcode_count[i]; |
largest_index = i; |
} |
|
printf("Opcode:\t%s\tCount:\t%d\n", |
opcode_strings[largest_index], |
opcode_count[largest_index]); |
|
opcode_count[largest_index] = -1; // Eliminate this one |
|
} |
#endif |
|
} |
|
// Deal with opcode pair checking |
int opcode_pair_check( int previous_opcode_index, int current_opcode_index, |
int total_pairs ) |
{ |
int i; |
// Check through for this pair's occurance before |
for (i=0;i<total_pairs;i++) |
{ |
if ((opcode_pairs[i][0] == previous_opcode_index) && |
(opcode_pairs[i][1] == current_opcode_index)) |
// Found a match |
{ |
opcode_pairs[i][2]++; |
return 0; |
} |
} |
// No match, let's create a new entry |
// Index for previous opcode |
opcode_pairs[total_pairs][0] = previous_opcode_index; |
// Index for current opcode |
opcode_pairs[total_pairs][1] = current_opcode_index; |
// Count for this pair |
opcode_pairs[total_pairs][2] = 1; |
|
return 1; |
|
} |
|
|
void opcode_pair_report(int total_opcode_pairs) |
{ |
|
int i, largest, largest_index; |
int initial_total = total_opcode_pairs; |
|
while (total_opcode_pairs) |
{ |
--total_opcode_pairs; |
largest=0; |
// Go through the list, find the largest, print it, eliminate it |
for(i=0;i<initial_total;i++) |
if(opcode_pairs[i][2] > largest) |
{ |
largest = opcode_pairs[i][2]; |
largest_index = i; |
} |
|
printf("Opcode pair:\t%s\t%s\tCount:\t%d\n", |
opcode_strings[opcode_pairs[largest_index][0]], |
opcode_strings[opcode_pairs[largest_index][1]], |
opcode_pairs[largest_index][2]); |
|
opcode_pairs[largest_index][2] = -1; // Eliminate this one |
|
} |
|
|
} |
|
// Deal with opcode triplet checking |
int opcode_triplet_check(int second_previous_opcode_index, |
int previous_opcode_index, |
int current_opcode_index, |
int sets_so_far ) |
{ |
int i; |
// Check through for this pair's occurance before |
for (i=0;i<sets_so_far;i++) |
{ |
if ((opcode_triplets[i][0] == second_previous_opcode_index) && |
(opcode_triplets[i][1] == previous_opcode_index) && |
(opcode_triplets[i][2] == current_opcode_index)) |
|
// Found a match |
{ |
opcode_triplets[i][3]++; |
return 0; |
} |
} |
// No match, let's create a new entry |
opcode_triplets[sets_so_far][0] = second_previous_opcode_index; |
// Index for previous opcode |
opcode_triplets[sets_so_far][1] = previous_opcode_index; |
// Index for current opcode |
opcode_triplets[sets_so_far][2] = current_opcode_index; |
// Count for this pair |
opcode_triplets[sets_so_far][3] = 1; |
|
return 1; |
|
} |
|
void opcode_triplet_report(int total_opcode_sets) |
{ |
|
int i, largest, largest_index; |
int initial_total = total_opcode_sets; |
|
while (total_opcode_sets) |
{ |
--total_opcode_sets; |
largest=0; |
// Go through the list, find the largest, print it, eliminate it |
for(i=0;i<initial_total;i++) |
if(opcode_triplets[i][3] > largest) |
{ |
largest = opcode_triplets[i][3]; |
largest_index = i; |
} |
|
printf("Opcode triplet:\t%s\t%s\t%s\tCount:\t%d\n", |
opcode_strings[opcode_triplets[largest_index][0]], |
opcode_strings[opcode_triplets[largest_index][1]], |
opcode_strings[opcode_triplets[largest_index][2]], |
opcode_triplets[largest_index][3]); |
|
opcode_triplets[largest_index][3] = -1; // Eliminate this one |
|
} |
} |
|
// Deal with opcode triplet checking |
int opcode_quad_check(int third_previous_opcode_index, |
int second_previous_opcode_index, |
int previous_opcode_index, |
int current_opcode_index, |
int sets_so_far ) |
{ |
int i; |
// Check through for this pair's occurance before |
for (i=0;i<sets_so_far;i++) |
{ |
if ((opcode_quads[i][0] == third_previous_opcode_index) && |
(opcode_quads[i][1] == second_previous_opcode_index) && |
(opcode_quads[i][2] == previous_opcode_index) && |
(opcode_quads[i][3] == current_opcode_index)) |
|
// Found a match |
{ |
opcode_quads[i][4]++; |
return 0; |
} |
} |
// No match, let's create a new entry |
opcode_quads[sets_so_far][0] = third_previous_opcode_index; |
opcode_quads[sets_so_far][1] = second_previous_opcode_index; |
// Index for previous opcode |
opcode_quads[sets_so_far][2] = previous_opcode_index; |
// Index for current opcode |
opcode_quads[sets_so_far][3] = current_opcode_index; |
// Count for this pair |
opcode_quads[sets_so_far][4] = 1; |
|
return 1; |
|
} |
|
void opcode_quad_report(int total_opcode_sets) |
{ |
|
int i, largest, largest_index; |
int initial_total = total_opcode_sets; |
|
while (total_opcode_sets) |
{ |
--total_opcode_sets; |
largest=0; |
// Go through the list, find the largest, print it, eliminate it |
for(i=0;i<initial_total;i++) |
if(opcode_quads[i][4] > largest) |
{ |
largest = opcode_quads[i][4]; |
largest_index = i; |
} |
|
printf("Opcode triplet:\t%s\t%s\t%s\t%s\tCount:\t%d\n", |
opcode_strings[opcode_quads[largest_index][0]], |
opcode_strings[opcode_quads[largest_index][1]], |
opcode_strings[opcode_quads[largest_index][2]], |
opcode_strings[opcode_quads[largest_index][3]], |
opcode_quads[largest_index][4]); |
|
opcode_quads[largest_index][4] = -1; // Eliminate this one |
|
} |
} |
|
|
int main(int argc, char *argv[]) |
{ |
FILE *fp; |
|
char current_opcode[OPCODE_STRING_SIZE]; |
|
int num_unique_opcodes = 0; |
|
int opcode_index; |
|
int total_seen_opcodes = 0; |
|
int previous_opcode_indexes[16]; // keep last 16 opcode indexes |
|
int i; |
|
int num_opcode_pairs = 0; |
|
int num_opcode_triplets = 0; |
int num_opcode_quads = 0; |
|
|
|
if((fp = fopen(argv[ 1 ], "r"))==NULL) { |
printf("Cannot open file.\n"); |
exit(1); |
} |
|
// Do initial instruction set analysis |
while(!feof(fp)) { |
if(fgets(current_opcode, OPCODE_STRING_SIZE, fp)) |
{ |
|
strip_newline(current_opcode); |
//printf("Checking for: %s \n", current_opcode); |
|
// Find if we have this opcode already, if so we'll get its index in |
// the list, else we'll get an indication that it's unique |
opcode_index = check_opcode(current_opcode, num_unique_opcodes); |
|
if (opcode_index == IS_UNIQUE) |
{ |
// Add this opcode to our list so we know it now |
add_opcode(current_opcode, num_unique_opcodes); |
// Increment the number of known opcodes |
num_unique_opcodes++; |
} |
else |
// Is not unique, just increment the incidences of this opcode |
count_opcode(opcode_index); |
|
// Track the total number of opcodes we've looked at |
total_seen_opcodes++; |
|
// Error check - bail out early if we're doing something wrong and |
// there's too many unique opcodes (ISA is only so big...) |
if (num_unique_opcodes == MAX_OR1K_32_OPCODES) |
{ |
printf("Error: Reached maximum opcodes\n"); |
break; |
} |
|
//printf("So far: unique: %d total: %d\n", |
//num_unique_opcodes, total_seen_opcodes); |
|
} |
} |
|
|
// Totals |
printf("Number of total opcodes: %d\n",total_seen_opcodes); |
printf("Number unique opcodes: %d\n", num_unique_opcodes); |
|
// Print some more detailed information |
display_opcodes(num_unique_opcodes); |
|
printf("Beginning groups analysis\n"); |
|
// Now do groups analysis |
rewind(fp); |
|
// Reset total_seen_opcodes, we'll count through the list again |
|
total_seen_opcodes = 0; |
|
while(!feof(fp)) { |
if(fgets(current_opcode, OPCODE_STRING_SIZE, fp)) |
{ |
|
total_seen_opcodes++; |
|
strip_newline(current_opcode); |
|
// Find if we have this opcode already, if so we'll get its index in |
// the list, else we'll get an indication that it's unique |
opcode_index = check_opcode(current_opcode, num_unique_opcodes); |
|
if (opcode_index == IS_UNIQUE) |
{ |
// Error! Should not have unique opcodes here... |
printf("Unique opcode detected during pair analysis.\n"); |
break; |
} |
|
// Now pass this current pair to the function to check if we've seen |
// it before - if not we record it (and return 1) else we just increment |
// count of it (and return 0) |
if (total_seen_opcodes > 1) |
{ |
if (opcode_pair_check(previous_opcode_indexes[0], opcode_index, |
num_opcode_pairs)) |
num_opcode_pairs++; |
} |
|
if (total_seen_opcodes > 2) |
{ |
if (opcode_triplet_check(previous_opcode_indexes[1], |
previous_opcode_indexes[0], |
opcode_index, |
num_opcode_triplets)) |
num_opcode_triplets++; |
} |
if (total_seen_opcodes > 3) |
{ |
if (opcode_quad_check(previous_opcode_indexes[2], |
previous_opcode_indexes[1], |
previous_opcode_indexes[0], |
opcode_index, |
num_opcode_quads)) |
num_opcode_quads++; |
} |
// Shift along our list of previously seen opcodes |
for (i=16-1;i > 0; i--) |
previous_opcode_indexes[i] = previous_opcode_indexes[i-1]; |
|
previous_opcode_indexes[0] = opcode_index; |
|
} |
} |
|
|
printf("Number of unique opcode pairs: %d\n", num_opcode_pairs); |
|
// Report opcode pairs (will be a lot, > 1000) |
opcode_pair_report(num_opcode_pairs); |
|
|
printf("Number of unique opcode triplets: %d\n", num_opcode_triplets); |
|
// Report opcode pairs (will be a lot, > 1000) |
opcode_triplet_report(num_opcode_pairs); |
|
printf("Number of opcode quads: %d\n", num_opcode_quads); |
|
// Report opcode pairs (will be a lot, > 1000) |
opcode_quad_report(num_opcode_quads); |
|
// Close file pointer, we're done with it |
fclose(fp); |
|
|
// Free all the strings we declared |
while(num_unique_opcodes) |
{ |
--num_unique_opcodes; |
free(opcode_strings[num_unique_opcodes]); |
} |
|
//printf("freeing complete: %d\n", num_unique_opcodes); |
|
return 0; |
} |