Line 11... |
Line 11... |
#include "stdlib.h"
|
#include "stdlib.h"
|
#include "string.h"
|
#include "string.h"
|
#include "assert.h"
|
#include "assert.h"
|
#include "or1k-32-insn.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 uint32_t instruction;
|
typedef struct or1k_32_instruction_properties instruction_properties ;
|
typedef struct or1k_32_instruction_properties instruction_properties ;
|
|
|
#include "insn-lists.h"
|
#include "insn-lists.h"
|
|
|
|
// Enable debug printf'ing straight to stdout -- will be a LOT of output
|
#define DEBUG_PRINT 0
|
#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
|
// Variable to keep track of unique instructions we have
|
int num_setup_insns;
|
int num_setup_insns;
|
int num_seen_insns;
|
int num_seen_insns;
|
|
|
struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
|
struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
|
|
|
// Keep enough instructions required to do the maximum n-tuple set
|
// Keep enough instructions required to do the maximum n-tuple set
|
// analysis.
|
// analysis.
|
int or1k_32_recent_insns[OR1K_MAX_GROUPINGS_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,
|
int or1k_32_analyse_insn(uint32_t insn,
|
struct or1k_32_instruction_properties * insn_props)
|
struct or1k_32_instruction_properties * insn_props)
|
{
|
{
|
|
|
switch(insn_or1k_opcode(insn))
|
switch(insn_or1k_opcode(insn))
|
Line 987... |
Line 999... |
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
|
// 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,
|
void or1k_32_collect_stats(uint32_t insn,
|
struct or1k_32_instruction_properties * insn_props)
|
struct or1k_32_instruction_properties * insn_props)
|
{
|
{
|
// Add this instruction's occurance to our data
|
// Add this instruction's occurance to our data
|
insn_lists_add(insn, insn_props);
|
insn_lists_add(insn, insn_props);
|
Line 1037... |
Line 1051... |
}
|
}
|
|
|
// List management/analysis functions - accessed through insn_lists() set of
|
// List management/analysis functions - accessed through insn_lists() set of
|
// functions
|
// functions
|
|
|
|
// Clear the list structs
|
void or1k_32_insn_lists_init(void)
|
void or1k_32_insn_lists_init(void)
|
{
|
{
|
num_setup_insns = 0;
|
num_setup_insns = 0;
|
num_seen_insns = 0;
|
num_seen_insns = 0;
|
// Clear the pointer array so we can tell if things are used or not
|
// Clear the pointer array so we can tell if things are used or not
|
Line 1152... |
Line 1167... |
}
|
}
|
|
|
|
|
|
|
|
|
// 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,
|
void or1k_32_ntuple_add(int n,
|
struct or1k_32_instruction_properties *insn_props)
|
struct or1k_32_instruction_properties *insn_props)
|
{
|
{
|
|
|
if (n<2)
|
if (n<2)
|
Line 1168... |
Line 1183... |
struct or1k_insn_info * insn_info = or1k_32_insns[insn_props->insn_index];
|
struct or1k_insn_info * insn_info = or1k_32_insns[insn_props->insn_index];
|
|
|
// Get the number of sets for these n-tuple groups we've seen so far.
|
// 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];
|
int sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
#if DEBUG_PRINT
|
#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
|
#endif
|
|
|
int set_match_index;
|
int set_match_index;
|
int tuple_set_itr, tuple_set_match;
|
int tuple_set_itr, tuple_set_match;
|
|
|
tuple_set_match = 0;
|
tuple_set_match = 0;
|
|
|
// now find if the current n instructions in or1k_32_recent_insns[] matches
|
// 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[][][].
|
// any set of n instructions we're keeping track of in groupings[][][].
|
#if DEBUG_PRINT
|
#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++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
printf("%s ",
|
printf("%s ",
|
or1k_32_insns[(or1k_32_recent_insns[n - 1 - tuple_set_itr])]->insn_string);
|
or1k_32_insns[(or1k_32_recent_insns[n - 1 - tuple_set_itr])]->insn_string);
|
printf("\n");
|
printf("\n");
|
#endif
|
#endif
|
Line 1254... |
Line 1271... |
// Increment the counter of these n-tuple sets
|
// Increment the counter of these n-tuple sets
|
insn_info->groupings[n-1][0][0] = sets_for_ntuple;
|
insn_info->groupings[n-1][0][0] = sets_for_ntuple;
|
}
|
}
|
}
|
}
|
|
|
// Debugging :
|
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
|
// Verbose announcement of found instruction
|
if (tuple_set_match)
|
if (tuple_set_match)
|
{
|
{
|
printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ",
|
printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ",
|
insn_info->insn_string, n, set_match_index,
|
insn_info->insn_string, n, set_match_index,
|
insn_info->groupings[n-1][set_match_index+1][n]);
|
insn_info->groupings[n-1][set_match_index+1][n]);
|
Line 1280... |
Line 1297... |
}
|
}
|
#endif
|
#endif
|
|
|
}
|
}
|
|
|
|
// Generate a list for the most-frequently seen instructions
|
#define DISPLAY_STRING
|
|
//#define DISPLAY_CSV
|
|
|
|
void or1k_32_most_freq_insn(FILE * stream)
|
void or1k_32_most_freq_insn(FILE * stream)
|
{
|
{
|
// Print out most frequent instruction
|
// Print out most frequent instruction
|
int i, largest, largest_index;
|
int i, largest, largest_index;
|
int instructions_to_print = num_setup_insns;
|
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)
|
while (instructions_to_print)
|
{
|
{
|
--instructions_to_print;
|
--instructions_to_print;
|
largest=0;
|
largest=0;
|
// Go through the list, find the largest, print it, eliminate it
|
// Go through the list, find the largest, print it, eliminate it
|
Line 1322... |
Line 1342... |
|
|
}
|
}
|
}
|
}
|
|
|
|
|
// Print out top x of each kept statistic for the requested instruction
|
// Generate a list for the most-frequently seen n-tuple set
|
void or1k_32_insn_top_x(struct or1k_insn_info *insn_info, FILE * stream,
|
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 max_stats)
|
{
|
{
|
int i, j, largest_i;
|
int i, j, largest_i;
|
|
|
fprintf(stream,
|
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->insn_string,
|
insn_info->count,
|
insn_info->count,
|
(float)(((float)((insn_info)->count))/
|
(float)(((float)((insn_info)->count))/
|
((float)num_seen_insns))*100.f
|
((float)num_seen_insns))*100.f
|
);
|
);
|
Line 1343... |
Line 1477... |
// Start dumping applicable stats
|
// Start dumping applicable stats
|
|
|
// Print out top max_stats branch targets
|
// Print out top max_stats branch targets
|
if (insn_info->has_branchtarg)
|
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;
|
i = 0;
|
while(i<insn_info->branch_info.count && i < max_stats)
|
while(i<insn_info->branch_info.count && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<insn_info->branch_info.count;j++)
|
for(j=0;j<insn_info->branch_info.count;j++)
|
Line 1355... |
Line 1496... |
insn_info->branch_info.values[largest_i][1]) ?
|
insn_info->branch_info.values[largest_i][1]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"value:\t0x%x\tcount:\t%d\n",
|
"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][0],
|
insn_info->branch_info.values[largest_i][1]);
|
insn_info->branch_info.values[largest_i][1]);
|
insn_info->branch_info.values[largest_i][1] = -1; // clear this one
|
insn_info->branch_info.values[largest_i][1] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
if (insn_info->has_imm)
|
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;
|
i = 0;
|
while(i<insn_info->imm_info.count && i < max_stats)
|
while(i<insn_info->imm_info.count && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<insn_info->imm_info.count;j++)
|
for(j=0;j<insn_info->imm_info.count;j++)
|
Line 1376... |
Line 1529... |
insn_info->imm_info.values[largest_i][1]) ?
|
insn_info->imm_info.values[largest_i][1]) ?
|
j : largest_i;
|
j : largest_i;
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"value:\t0x%x\tcount:\t%d\n",
|
"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][0],
|
insn_info->imm_info.values[largest_i][1]);
|
insn_info->imm_info.values[largest_i][1]);
|
insn_info->imm_info.values[largest_i][1] = -1; // clear this one
|
insn_info->imm_info.values[largest_i][1] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if (insn_info->has_rD)
|
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;
|
i = 0;
|
while(i<32 && i < max_stats)
|
while(i<32 && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
Line 1401... |
Line 1567... |
if (insn_info->rD_use_freq[largest_i] == 0)
|
if (insn_info->rD_use_freq[largest_i] == 0)
|
break;
|
break;
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"r%d\tcount:\t%d\n",
|
"r%d\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"r%d\",%d\n",
|
|
#endif
|
largest_i,
|
largest_i,
|
insn_info->rD_use_freq[largest_i]);
|
insn_info->rD_use_freq[largest_i]);
|
insn_info->rD_use_freq[largest_i] = -1; // clear this one
|
insn_info->rD_use_freq[largest_i] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if (insn_info->has_rA)
|
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;
|
i = 0;
|
while(i<32 && i < max_stats)
|
while(i<32 && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
Line 1428... |
Line 1606... |
break;
|
break;
|
|
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"r%d\tcount:\t%d\n",
|
"r%d\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"r%d\",%d\n",
|
|
#endif
|
largest_i,
|
largest_i,
|
insn_info->rA_use_freq[largest_i]);
|
insn_info->rA_use_freq[largest_i]);
|
insn_info->rA_use_freq[largest_i] = -1; // clear this one
|
insn_info->rA_use_freq[largest_i] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
if (insn_info->has_rB)
|
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;
|
i = 0;
|
while(i<32 && i < max_stats)
|
while(i<32 && i < max_stats)
|
{
|
{
|
largest_i=0;
|
largest_i=0;
|
for(j=0;j<32;j++)
|
for(j=0;j<32;j++)
|
Line 1455... |
Line 1645... |
break;
|
break;
|
|
|
|
|
// largest_i has index of most frequent value
|
// largest_i has index of most frequent value
|
fprintf(stream,
|
fprintf(stream,
|
|
#ifdef DISPLAY_STRING
|
"r%d\tcount:\t%d\n",
|
"r%d\tcount:\t%d\n",
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
"\"r%d\",%d\n",
|
|
#endif
|
largest_i,
|
largest_i,
|
insn_info->rB_use_freq[largest_i]);
|
insn_info->rB_use_freq[largest_i]);
|
insn_info->rB_use_freq[largest_i] = -1; // clear this one
|
insn_info->rB_use_freq[largest_i] = -1; // clear this one
|
i++;
|
i++;
|
}
|
}
|
Line 1473... |
Line 1668... |
FILE * stream)
|
FILE * stream)
|
{
|
{
|
// Maximum number we'll print out
|
// Maximum number we'll print out
|
#define MAX_NTUPLE_LISTING 5
|
#define MAX_NTUPLE_LISTING 5
|
|
|
|
|
int (*ntuplelist)[OR1K_MAX_GROUPINGS_ANALYSIS+1];
|
int (*ntuplelist)[OR1K_MAX_GROUPINGS_ANALYSIS+1];
|
int *set;
|
int *set;
|
int set_count, set_count2;
|
int set_count, set_count2;
|
|
|
// Get total number of sets for this n-tuple, eg:
|
// 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
|
// if n=2 (pairs) then groupings[1] is where our list is, and we store the
|
// of sets in [0][0] of that n-tuple data.
|
// number of sets in [0][0] of that n-tuple data.
|
int total_sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
int total_sets_for_ntuple = insn_info->groupings[n-1][0][0];
|
|
|
if (total_sets_for_ntuple == 0)
|
if (total_sets_for_ntuple == 0)
|
return;
|
return;
|
|
|
fprintf(stream, "%d-tuple groupings finishing with %s (%d)\n",n, insn_info->insn_string,
|
fprintf(stream,
|
total_sets_for_ntuple);
|
#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
|
// Debug - dump out all of the info for the sets
|
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
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++)
|
for(set_count2=0;set_count2<n;set_count2++)
|
fprintf(stream, "%s\t",
|
fprintf(stream, "%s\t",
|
or1k_32_insns[(insn_info->groupings[n-1][set_count+1][set_count2])]->insn_string);
|
or1k_32_insns[(insn_info->groupings[n-1][set_count+1][set_count2])]->insn_string);
|
printf("\n");
|
printf("\n");
|
}
|
}
|
#endif
|
#endif
|
|
|
// A pointer to the n-tuple sets
|
// A pointer to the n-tuple sets
|
// This is actually a pointer to a 2-dimensional integer array, looking like:
|
// 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
|
// [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in
|
// array pointer fashion, we should provide the "column" sizing.
|
// 2-dimensional array pointer fashion, we should provide the "column" sizing.
|
ntuplelist = insn_info->groupings[n-1];
|
ntuplelist = insn_info->groupings[n-1];
|
|
|
// Let's make a copy of the counts for each... so we don't trash them
|
// Let's make a copy of the counts for each... so we don't trash them
|
int set_count_copy[OR1K_MAX_ENTRIES_PER_GROUP+1];
|
int set_count_copy[OR1K_MAX_ENTRIES_PER_GROUP+1];
|
|
|
Line 1519... |
Line 1721... |
// Go through the list, copy the counts for each
|
// Go through the list, copy the counts for each
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
|
{
|
{
|
// Pointer to a set's data
|
// Pointer to a set's data
|
set = ntuplelist[set_count+1];
|
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];
|
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
|
// Now go through, finding the most frequent n-tuple of instructions and
|
// print it out
|
// print it out
|
int largest_indx = 0;
|
int largest_indx = 0;
|
Line 1541... |
Line 1742... |
// largest_indx is the index of the set with the highest occurance, so
|
// largest_indx is the index of the set with the highest occurance, so
|
// let's print it out, but first get a pointer to the set's data
|
// let's print it out, but first get a pointer to the set's data
|
set = (int*)ntuplelist[largest_indx+1];
|
set = (int*)ntuplelist[largest_indx+1];
|
|
|
// Print out the sequence of prior isntructions
|
// Print out the sequence of prior isntructions
|
|
#ifdef DISPLAY_STRING
|
fprintf(stream,"Seq:\t");
|
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
|
// Go through the indexes of the previous instructions, get their
|
// strings, and print them out
|
// strings, and print them out
|
for(set_count2=0;set_count2<n;set_count2++)
|
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
|
// 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);
|
(float)((float)set[n]/(float)insn_info->count)*100.0f);
|
|
|
// done printing this one out.. let's clear its count
|
// done printing this one out.. let's clear its count
|
set_count_copy[largest_indx + 1] = -1;
|
set_count_copy[largest_indx + 1] = -1;
|
|
|
Line 1573... |
Line 1795... |
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
or1k_32_generate_ntuple_stats(n, insn_info, stream);
|
or1k_32_generate_ntuple_stats(n, insn_info, stream);
|
|
|
}
|
}
|
|
|
|
// Entry point for statistics generation.
|
void or1k_32_generate_stats(FILE * stream)
|
void or1k_32_generate_stats(FILE * stream)
|
{
|
{
|
|
#ifdef DISPLAY_STRING
|
// Generate some useful things
|
// Generate some useful things
|
fprintf(stream, "Analysis output:\n");
|
fprintf(stream, "Analysis output:\n");
|
|
#endif
|
//
|
//
|
|
|
// Print out all stats for every instruction we saw!
|
// Print out all stats for every instruction we saw!
|
int insn_index;
|
int insn_index;
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
{
|
{
|
if (or1k_32_insns[insn_index] != NULL)
|
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);
|
or1k_32_generate_groupings_stats(or1k_32_insns[insn_index],stream);
|
|
#ifdef DISPLAY_STRING
|
fprintf(stream, "\t---\t---\t---\t---\n");
|
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
|
// Do most frequent instruction analysis -- note this trashes instruction
|
// frequency count - should be fixed
|
// frequency count - should be fixed
|
|
#ifdef DISPLAY_STRING
|
fprintf(stream, "Individual instruction frequency:\n");
|
fprintf(stream, "Individual instruction frequency:\n");
|
|
#endif
|
or1k_32_most_freq_insn(stream);
|
or1k_32_most_freq_insn(stream);
|
|
|
}
|
}
|
|
|
|
|