URL
https://opencores.org/ocsvn/or2k/or2k/trunk
Subversion Repositories or2k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 21 to Rev 22
- ↔ Reverse comparison
Rev 21 → Rev 22
/or2k/trunk/analysis-bin/insnanalysis/insnanalysis.h
1,11 → 1,16
/* |
Header for instruction analysis program. |
|
Define instruction sets here |
Have appropriate defines/typedefs for desired instruction set. |
|
Todo: #ifdefs for other instruction sets |
|
*/ |
|
// Settings for or1k 32-bit instruction analysis |
|
|
// OpenRISC 1000 32-bit compiler output analysis settings: |
|
#include "stdint.h" |
#include "or1k-32-insn.h" |
|
/or2k/trunk/analysis-bin/insnanalysis/or1k-32-insn.c
13,14 → 13,21
#include "assert.h" |
#include "or1k-32-insn.h" |
|
// These should also be in insnanalysis.h insnanalysis.h |
// Define the appropriate instruction type, and instruction_properties type |
// These should also be defined in insnanalysis.h |
typedef uint32_t instruction; |
typedef struct or1k_32_instruction_properties instruction_properties ; |
|
#include "insn-lists.h" |
|
// Enable debug printf'ing straight to stdout -- will be a LOT of output |
#define DEBUG_PRINT 0 |
|
// Choose the output format, uncomment only one |
//#define DISPLAY_STRING |
#define DISPLAY_CSV |
|
|
// Variable to keep track of unique instructions we have |
int num_setup_insns; |
int num_seen_insns; |
31,6 → 38,11
// analysis. |
int or1k_32_recent_insns[OR1K_MAX_GROUPINGS_ANALYSIS]; |
|
// Function to take the raw binary instruction, and configure the insn_props |
// struct with the appropriate settings for that instruction (string, attributes |
// etc.) |
// TODO: vector instructions aren't picked up - but compiler never generates |
// them, so not a big issue. |
int or1k_32_analyse_insn(uint32_t insn, |
struct or1k_32_instruction_properties * insn_props) |
{ |
989,7 → 1001,9
} |
|
|
|
// Entry point for statistics collection. |
// Passed binary copy of instruction, and pointer to properties struct |
// Each function that can collect staistics is called. |
void or1k_32_collect_stats(uint32_t insn, |
struct or1k_32_instruction_properties * insn_props) |
{ |
1039,6 → 1053,7
// List management/analysis functions - accessed through insn_lists() set of |
// functions |
|
// Clear the list structs |
void or1k_32_insn_lists_init(void) |
{ |
num_setup_insns = 0; |
1154,7 → 1169,7
|
|
|
// Do the n-tuple set analysis for the most recently added instruction |
// Do the n-tuple set checking for the current instruction |
void or1k_32_ntuple_add(int n, |
struct or1k_32_instruction_properties *insn_props) |
{ |
1170,7 → 1185,8
// Get the number of sets for these n-tuple groups we've seen so far. |
int sets_for_ntuple = insn_info->groupings[n-1][0][0]; |
#if DEBUG_PRINT |
printf("%s\t:\t%d-tuple add - sets so far : %d\n",insn_info->insn_string, n, sets_for_ntuple); |
printf("%s\t:\t%d-tuple add - sets so far : %d\n", |
insn_info->insn_string, n, sets_for_ntuple); |
#endif |
|
int set_match_index; |
1181,7 → 1197,8
// now find if the current n instructions in or1k_32_recent_insns[] matches |
// any set of n instructions we're keeping track of in groupings[][][]. |
#if DEBUG_PRINT |
printf("%s\tChecking\t%d\tsets for ntuple:\t",insn_info->insn_string,sets_for_ntuple); |
printf("%s\tChecking\t%d\tsets for ntuple:\t", |
insn_info->insn_string,sets_for_ntuple); |
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++) |
printf("%s ", |
or1k_32_insns[(or1k_32_recent_insns[n - 1 - tuple_set_itr])]->insn_string); |
1256,8 → 1273,8
} |
} |
|
// Debugging : |
#if DEBUG_PRINT |
// Verbose announcement of found instruction |
if (tuple_set_match) |
{ |
printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ", |
1282,15 → 1299,18
|
} |
|
|
#define DISPLAY_STRING |
//#define DISPLAY_CSV |
|
// Generate a list for the most-frequently seen instructions |
void or1k_32_most_freq_insn(FILE * stream) |
{ |
// Print out most frequent instruction |
int i, largest, largest_index; |
int instructions_to_print = num_setup_insns; |
|
#ifdef DISPLAY_CSV |
fprintf(stream,"\"Most frequent instructions, descending\",\n"); |
fprintf(stream,"\"Instruction\",\"Occurances\",\"Frequency\",\n"); |
#endif |
|
while (instructions_to_print) |
{ |
--instructions_to_print; |
1324,14 → 1344,128
} |
|
|
// Print out top x of each kept statistic for the requested instruction |
void or1k_32_insn_top_x(struct or1k_insn_info *insn_info, FILE * stream, |
// Generate a list for the most-frequently seen n-tuple set |
void or1k_32_most_freq_ntuple(int n, FILE * stream, int max_stats) |
{ |
|
fprintf(stream, |
#ifdef DISPLAY_STRING |
"Top %d %d-tuple groupings of instructions\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"Top %d %d-tuple groupings of instructions\",\n", |
#endif |
max_stats, n); |
|
// First get a copy of all the n-tuple values for each applicable |
// instruction. |
int set_counts[OR1K_32_MAX_INSNS][OR1K_MAX_ENTRIES_PER_GROUP]; |
int insn_index; |
int set_index; |
int num_sets; |
struct or1k_insn_info *insn_info; |
|
// Copy each instruction's set totals into our local array |
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++) |
{ |
if (or1k_32_insns[insn_index] != NULL) |
{ |
insn_info = or1k_32_insns[insn_index]; |
num_sets = insn_info->groupings[n-1][0][0]; |
for(set_index=0;set_index<num_sets;set_index++) |
set_counts[insn_index][set_index] = |
insn_info->groupings[n-1][set_index+1][n]; |
} |
} |
|
// Go through the set numbers, look at the most frequent one, print it out |
// clear its count and continue |
|
|
int largest_insn_index, largest_set_index, largest_count; |
int tuple_set_itr; |
|
|
#ifdef DISPLAY_CSV |
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++) |
fprintf(stream, "\"insn%d\",",n-1-tuple_set_itr); |
fprintf(stream, "\"count\",\n"); |
#endif |
|
while(max_stats--) |
{ |
largest_count = 0; |
// Go through each instruction we have |
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++) |
{ |
if (or1k_32_insns[insn_index] != NULL) |
{ |
insn_info = or1k_32_insns[insn_index]; |
// Get the total number of sets for the n-tup. of this instruction |
num_sets = insn_info->groupings[n-1][0][0]; |
for(set_index=0;set_index<num_sets;set_index++) |
{ |
// Go through each set, check if it's largest |
if (set_counts[insn_index][set_index] > |
largest_count) |
{ |
largest_insn_index = insn_index; |
largest_set_index = set_index; |
largest_count = set_counts[insn_index][set_index]; |
} |
} |
} |
} |
// Have indexes of the next largest n-tuple, print it out. |
|
insn_info = or1k_32_insns[largest_insn_index]; |
#ifdef DISPLAY_STRING |
fprintf(stream,"set :"); |
#endif |
|
// insn_info->insn_string, n, set_match_index, |
// insn_info->groupings[n-1][set_match_index+1][n]); |
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++) |
fprintf(stream, |
#ifdef DISPLAY_STRING |
" %s", |
#endif |
#ifdef DISPLAY_CSV |
"\"%s\",", |
#endif |
or1k_32_insns[(insn_info->groupings[n-1][largest_set_index][tuple_set_itr])]->insn_string); |
|
fprintf(stream, |
#ifdef DISPLAY_STRING |
"\tcount: %d\n", |
#endif |
#ifdef DISPLAY_CSV |
"%d,\n", |
#endif |
set_counts[largest_insn_index][largest_set_index]); |
|
// Remove this value from getting selected from largest again |
set_counts[largest_insn_index][largest_set_index] = -1; |
} |
|
} |
|
|
|
|
// Print out top n of each kept statistic for the requested instruction |
void or1k_32_insn_top_n(struct or1k_insn_info *insn_info, FILE * stream, |
int max_stats) |
{ |
int i, j, largest_i; |
|
fprintf(stream, |
"Insn: \"%s\" statistics (%d times (%f%%)):\n", |
#ifdef DISPLAY_STRING |
"Insn: \"%s\" statistics (%d times (%f%%))\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"Insn:\",\"%s\",\"occurances:\",%d,%f\n", |
#endif |
insn_info->insn_string, |
insn_info->count, |
(float)(((float)((insn_info)->count))/ |
1345,7 → 1479,14
// Print out top max_stats branch targets |
if (insn_info->has_branchtarg) |
{ |
fprintf(stream,"Branch values:\n"); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"Branch values:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"branch distance\",\"occurances\"\n" |
#endif |
); |
i = 0; |
while(i<insn_info->branch_info.count && i < max_stats) |
{ |
1357,7 → 1498,12
|
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"value:\t0x%x\tcount:\t%d\n", |
#endif |
#ifdef DISPLAY_CSV |
"0x%x,%d\n", |
#endif |
insn_info->branch_info.values[largest_i][0], |
insn_info->branch_info.values[largest_i][1]); |
insn_info->branch_info.values[largest_i][1] = -1; // clear this one |
1366,7 → 1512,14
} |
if (insn_info->has_imm) |
{ |
fprintf(stream,"Immediate values:\n"); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"Immediate values:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"immediate value\",\"count\"\n" |
#endif |
); |
i = 0; |
while(i<insn_info->imm_info.count && i < max_stats) |
{ |
1378,7 → 1531,12
|
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"value:\t0x%x\tcount:\t%d\n", |
#endif |
#ifdef DISPLAY_CSV |
"0x%x,%d\n", |
#endif |
insn_info->imm_info.values[largest_i][0], |
insn_info->imm_info.values[largest_i][1]); |
insn_info->imm_info.values[largest_i][1] = -1; // clear this one |
1385,9 → 1543,17
i++; |
} |
} |
|
if (insn_info->has_rD) |
{ |
fprintf(stream,"rD usage:\n"); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"rD usage:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"rD\",\"count\"\n" |
#endif |
); |
i = 0; |
while(i<32 && i < max_stats) |
{ |
1403,7 → 1569,12
|
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"r%d\tcount:\t%d\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"r%d\",%d\n", |
#endif |
largest_i, |
insn_info->rD_use_freq[largest_i]); |
insn_info->rD_use_freq[largest_i] = -1; // clear this one |
1413,7 → 1584,14
|
if (insn_info->has_rA) |
{ |
fprintf(stream,"rA usage:\n"); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"rA usage:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"rA\",\"count\"\n" |
#endif |
); |
i = 0; |
while(i<32 && i < max_stats) |
{ |
1430,7 → 1608,12
|
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"r%d\tcount:\t%d\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"r%d\",%d\n", |
#endif |
largest_i, |
insn_info->rA_use_freq[largest_i]); |
insn_info->rA_use_freq[largest_i] = -1; // clear this one |
1440,7 → 1623,14
|
if (insn_info->has_rB) |
{ |
fprintf(stream,"rB usage:\n"); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"rB usage:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"rB\",\"count\"\n" |
#endif |
); |
i = 0; |
while(i<32 && i < max_stats) |
{ |
1457,7 → 1647,12
|
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"r%d\tcount:\t%d\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"r%d\",%d\n", |
#endif |
largest_i, |
insn_info->rB_use_freq[largest_i]); |
insn_info->rB_use_freq[largest_i] = -1; // clear this one |
1475,28 → 1670,35
// Maximum number we'll print out |
#define MAX_NTUPLE_LISTING 5 |
|
|
int (*ntuplelist)[OR1K_MAX_GROUPINGS_ANALYSIS+1]; |
int *set; |
int set_count, set_count2; |
|
// Get total number of sets for this n-tuple, eg: |
// if n=2 (pairs) then groupings[1] is where our list is, and we store the number |
// of sets in [0][0] of that n-tuple data. |
// if n=2 (pairs) then groupings[1] is where our list is, and we store the |
// number of sets in [0][0] of that n-tuple data. |
int total_sets_for_ntuple = insn_info->groupings[n-1][0][0]; |
|
if (total_sets_for_ntuple == 0) |
return; |
|
fprintf(stream, "%d-tuple groupings finishing with %s (%d)\n",n, insn_info->insn_string, |
total_sets_for_ntuple); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"%d-tuple groupings finishing with %s (%d)\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"%d-tuple groupings\",\n", |
#endif |
n, insn_info->insn_string, total_sets_for_ntuple); |
|
|
// Debug - dump out all of the info for the sets |
#if DEBUG_PRINT |
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++) |
{ |
|
printf("set: %d - count %d - set: ", set_count, insn_info->groupings[n-1][set_count+1][n]); |
printf("set: %d - count %d - set: ", set_count, |
insn_info->groupings[n-1][set_count+1][n]); |
|
for(set_count2=0;set_count2<n;set_count2++) |
fprintf(stream, "%s\t", |
1507,8 → 1709,8
|
// A pointer to the n-tuple sets |
// This is actually a pointer to a 2-dimensional integer array, looking like: |
// [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in 2-dimensional |
// array pointer fashion, we should provide the "column" sizing. |
// [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in |
// 2-dimensional array pointer fashion, we should provide the "column" sizing. |
ntuplelist = insn_info->groupings[n-1]; |
|
// Let's make a copy of the counts for each... so we don't trash them |
1521,10 → 1723,9
{ |
// Pointer to a set's data |
set = ntuplelist[set_count+1]; |
// Fish out the copy (0 to n-1 will be the instruction index, n will be the count) |
// Fish out the copy (0 to n-1 will be the instruction index, n will be |
// the count) |
set_count_copy[set_count+1] = set[n]; |
//printf("Set %d, count %d (%d) (%d)\n", set_count+1, set_count_copy[set_count+1], |
//set[n], insn_info->groupings[n-1][set_count+1][n] ); |
} |
|
// Now go through, finding the most frequent n-tuple of instructions and |
1543,14 → 1744,35
set = (int*)ntuplelist[largest_indx+1]; |
|
// Print out the sequence of prior isntructions |
#ifdef DISPLAY_STRING |
fprintf(stream,"Seq:\t"); |
#endif |
#ifdef DISPLAY_CSV |
for(set_count2=0;set_count2<n;set_count2++) |
fprintf(stream, "\"insn%d\",",n-1-set_count2); |
fprintf(stream, "\"count\",\n"); |
#endif |
// Go through the indexes of the previous instructions, get their |
// strings, and print them out |
for(set_count2=0;set_count2<n;set_count2++) |
fprintf(stream, "%s\t", or1k_32_insns[(set[set_count2])]->insn_string); |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"%s\t", |
#endif |
#ifdef DISPLAY_CSV |
"\"%s\",", |
#endif |
or1k_32_insns[(set[set_count2])]->insn_string); |
|
// now print out the occurances |
fprintf(stream, "\t%d\ttimes (%f%%)\n", set[n], |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"\t%d\ttimes (%f%%)\n", |
#endif |
#ifdef DISPLAY_CSV |
"%d,\n", |
#endif |
set[n], |
(float)((float)set[n]/(float)insn_info->count)*100.0f); |
|
// done printing this one out.. let's clear its count |
1574,12 → 1796,14
or1k_32_generate_ntuple_stats(n, insn_info, stream); |
|
} |
|
|
// Entry point for statistics generation. |
void or1k_32_generate_stats(FILE * stream) |
{ |
#ifdef DISPLAY_STRING |
// Generate some useful things |
fprintf(stream, "Analysis output:\n"); |
|
#endif |
// |
|
// Print out all stats for every instruction we saw! |
1588,15 → 1812,24
{ |
if (or1k_32_insns[insn_index] != NULL) |
{ |
or1k_32_insn_top_x(or1k_32_insns[insn_index],stream,10); |
or1k_32_insn_top_n(or1k_32_insns[insn_index],stream,10); |
or1k_32_generate_groupings_stats(or1k_32_insns[insn_index],stream); |
#ifdef DISPLAY_STRING |
fprintf(stream, "\t---\t---\t---\t---\n"); |
#endif |
} |
} |
|
// print out most frequent n-tuple |
int ntuple; |
for(ntuple=2;ntuple<5;ntuple++) |
or1k_32_most_freq_ntuple(ntuple, stream, 10); |
|
// Do most frequent instruction analysis -- note this trashes instruction |
// frequency count - should be fixed |
#ifdef DISPLAY_STRING |
fprintf(stream, "Individual instruction frequency:\n"); |
#endif |
or1k_32_most_freq_insn(stream); |
|
} |
/or2k/trunk/analysis-bin/insnanalysis/or1k-32-insn.h
60,7 → 60,7
|
// Set maximum instructions in a row we'll keep track of, starting at pairs |
#define OR1K_MAX_GROUPINGS_ANALYSIS 4 |
#define OR1K_MAX_ENTRIES_PER_GROUP 300 |
#define OR1K_MAX_ENTRIES_PER_GROUP 500 |
// Format of grouping data: |
// |
// 1st dimension: A list for each n-tuple group we're keeping track of |
/or2k/trunk/analysis-bin/insnanalysis/insnanalysis.c
67,12 → 67,15
|
filesize_bytes = ftell(fp); |
filesize_insns = filesize_bytes / INSN_SIZE_BYTES; |
|
|
#ifdef DISPLAY_STRING |
printf("\nAnalysing file:\t%s\tSize: %d MB\n", |
argv[1],((filesize_bytes/1024)/1024)); |
#endif |
|
// Reset pointer |
rewind(fp); |
|
|
|
instruction * insn = (instruction *)insn_buff; |
|
instruction_properties insn_props; |
81,7 → 84,7
|
// What is one-percent of instructions |
float file_one_percent = ((float)filesize_insns / 100.0f ); |
float percent_of_percent=0; int percent; |
float percent_of_percent=0; int percent=0; |
|
insn_lists_init(); |
|
129,8 → 132,10
|
fclose(fp); |
|
fprintf(stderr, "\rDone\n", percent); |
#ifdef DISPLAY_STRING |
printf("\rSaw %d instructions\n", insns_seen_total); |
|
#endif |
generate_stats(stdout); |
|
insn_lists_free(); |