Line 8... |
Line 8... |
|
|
#include "stdio.h"
|
#include "stdio.h"
|
#include "stdint.h"
|
#include "stdint.h"
|
#include "stdlib.h"
|
#include "stdlib.h"
|
#include "string.h"
|
#include "string.h"
|
|
#include "assert.h"
|
#include "or1k-32-insn.h"
|
#include "or1k-32-insn.h"
|
|
|
// These should also be in insnanalysis.h insnanalysis.h
|
// These should also be in insnanalysis.h 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"
|
|
|
|
#define DEBUG_PRINT 0
|
|
|
// 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;
|
|
|
Line 85... |
Line 87... |
switch(insn_or1k_opcode_0x08_get_id(insn))
|
switch(insn_or1k_opcode_0x08_get_id(insn))
|
{
|
{
|
case 0x0:
|
case 0x0:
|
insn_props->insn_string="l.sys";
|
insn_props->insn_string="l.sys";
|
insn_props->insn_index=7;
|
insn_props->insn_index=7;
|
|
insn_props->has_imm = 1;
|
break;
|
break;
|
case 0x2:
|
case 0x2:
|
insn_props->insn_string="l.trap";
|
insn_props->insn_string="l.trap";
|
insn_props->insn_index=8;
|
insn_props->insn_index=8;
|
break;
|
break;
|
Line 777... |
Line 780... |
insn_props->insn_index=81;
|
insn_props->insn_index=81;
|
break;
|
break;
|
|
|
case 0x35:
|
case 0x35:
|
insn_props->insn_string="l.sw";
|
insn_props->insn_string="l.sw";
|
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=82;
|
insn_props->insn_index=82;
|
break;
|
break;
|
|
|
case 0x36:
|
case 0x36:
|
insn_props->insn_string="l.sb";
|
insn_props->insn_string="l.sb";
|
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=83;
|
insn_props->insn_index=83;
|
break;
|
break;
|
|
|
case 0x37:
|
case 0x37:
|
insn_props->insn_string="l.sh";
|
insn_props->insn_string="l.sh";
|
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=84;
|
insn_props->insn_index=84;
|
break;
|
break;
|
|
|
case 0x38:
|
case 0x38:
|
insn_props->has_rD = 1;
|
insn_props->has_rD = 1;
|
Line 1161... |
Line 1167... |
|
|
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
|
|
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; int tuple_set_itr, tuple_set_match;
|
int set_match_index;
|
|
int tuple_set_itr, tuple_set_match;
|
|
|
|
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
|
|
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);
|
|
printf("\n");
|
|
#endif
|
for (set_match_index=0; set_match_index<sets_for_ntuple; set_match_index++)
|
for (set_match_index=0; set_match_index<sets_for_ntuple; set_match_index++)
|
{
|
{
|
// Check this set for a match with our existing trace
|
// Check this set for a match with our existing trace
|
// Example:
|
// Example:
|
// In case of a triple (n=3), 1st set, [3][1][0] corresponds to the third
|
// In case of a triple (n=3), 1st set, [3][1][0] corresponds to the third
|
// instruction in the trace (or1k_32_recent_insns[2]), [3][1][1] should
|
// instruction in the trace (or1k_32_recent_insns[2]), [3][1][1] should
|
// be the second in the trace, and [3][1][2] should be the first in the
|
// be the second in the trace, and [3][1][2] should be the first in the
|
// trace (same index as insn_props->insn_index)
|
// trace (same index as insn_props->insn_index)
|
|
|
|
#if DEBUG_PRINT
|
|
printf("Chk:\t");
|
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
|
printf("%s ",
|
|
or1k_32_insns[(insn_info->groupings[n-1][set_match_index+1][tuple_set_itr])]->insn_string);
|
|
printf("\t(%d)\n", insn_info->groupings[n-1][set_match_index+1][n]);
|
|
#endif
|
|
tuple_set_match = 1;
|
// Presuppose a match, de-assert and break out of the loop as soon as we
|
// Presuppose a match, de-assert and break out of the loop as soon as we
|
// detect a mismatch.
|
// detect a mismatch.
|
tuple_set_match = 1;
|
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
{
|
{
|
|
|
if (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr]
|
if (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr]
|
!= or1k_32_recent_insns[n-1 - tuple_set_itr])
|
!= or1k_32_recent_insns[n-1 - tuple_set_itr])
|
{
|
{
|
tuple_set_match = 0;
|
tuple_set_match = 0;
|
break; // No match, so break out of this for() loop
|
break; // No match, so break out of this for() loop
|
}
|
}
|
}
|
}
|
|
|
if (!tuple_set_match)
|
if (!tuple_set_match)
|
continue; // go again...
|
continue; // go again...
|
|
else
|
|
break; // Bail out, we've found our match
|
}
|
}
|
|
|
if (tuple_set_match)
|
if (tuple_set_match)
|
|
{
|
// Found a match - just increment the counter (set_match_index should
|
// Found a match - just increment the counter (set_match_index should
|
// be pointing at the right set)
|
// be pointing at the right set)
|
|
#if DEBUG_PRINT
|
|
printf("Match!\n");
|
|
#endif
|
|
|
(insn_info->groupings[n-1][set_match_index+1][n])++;
|
(insn_info->groupings[n-1][set_match_index+1][n])++;
|
|
}
|
else
|
else
|
{
|
{
|
// If we can record a new set
|
// If we can record a new set
|
if (sets_for_ntuple < OR1K_MAX_ENTRIES_PER_GROUP)
|
if (sets_for_ntuple < OR1K_MAX_ENTRIES_PER_GROUP)
|
{
|
{
|
|
#if DEBUG_PRINT
|
|
printf("New entry\n");
|
|
#endif
|
|
|
// Increment the number of sets we have for this n-tuple starting
|
// Increment the number of sets we have for this n-tuple starting
|
// on the current instruction
|
// on the current instruction
|
sets_for_ntuple++;
|
sets_for_ntuple++;
|
// Add new set to the end (all n instructions, copy in)
|
// Add new set to the end (all n instructions, copy in)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr]
|
insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr]
|
= or1k_32_recent_insns[n-1 - tuple_set_itr];
|
= or1k_32_recent_insns[n-1 - tuple_set_itr];
|
// Set the count for this set to 1
|
// Set the count for this set to 1
|
insn_info->groupings[n-1][sets_for_ntuple][n] = 1;
|
(insn_info->groupings[n-1][sets_for_ntuple][n]) = 1;
|
// Increment the counter of these n-tuple sets
|
// Increment the counter of these n-tuple sets
|
(insn_info->groupings[n-1][0][0])++;
|
insn_info->groupings[n-1][0][0] = sets_for_ntuple;
|
|
}
|
|
}
|
|
|
|
// Debugging :
|
|
#if DEBUG_PRINT
|
|
if (tuple_set_match)
|
|
{
|
|
printf("%s\t:\tMatch for %d-tuple - set %d - cnt: %d - ",
|
|
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++)
|
|
printf("%s ",
|
|
or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
|
|
printf("\n");
|
}
|
}
|
|
else
|
|
{
|
|
printf("%s\t:\tNew %d-tuple - set %d - cnt: %d - ",
|
|
insn_info->insn_string, n, sets_for_ntuple,
|
|
insn_info->groupings[n-1][sets_for_ntuple][n]);
|
|
for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
|
|
printf("%s ",
|
|
or1k_32_insns[(insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr])]->insn_string);
|
|
printf("\n");
|
}
|
}
|
|
#endif
|
|
|
}
|
}
|
|
|
|
|
#define DISPLAY_STRING
|
#define DISPLAY_STRING
|
//#define DISPLAY_CSV
|
//#define DISPLAY_CSV
|
Line 1263... |
Line 1326... |
|
|
// Print out top x of each kept statistic for the requested instruction
|
// 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,
|
void or1k_32_insn_top_x(struct or1k_insn_info *insn_info, FILE * stream,
|
int max_stats)
|
int max_stats)
|
{
|
{
|
int i, j, largest, largest_i;
|
int i, j, largest_i;
|
|
|
fprintf(stream,
|
fprintf(stream,
|
"Insn: \"%s\" statistics (%d times (%f%%)):\n",
|
"Insn: \"%s\" statistics (%d times (%f%%)):\n",
|
insn_info->insn_string,
|
insn_info->insn_string,
|
insn_info->count,
|
insn_info->count,
|
Line 1401... |
Line 1464... |
i++;
|
i++;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
#define MAX_NTUPLE_LISTING 5
|
|
|
|
// Print out the most common n-tuple groupings for an instruction
|
// Print out the most common n-tuple groupings for an instruction
|
void or1k_32_generate_ntuple_stats(int n, struct or1k_insn_info *insn_info,
|
void or1k_32_generate_ntuple_stats(int n, struct or1k_insn_info *insn_info,
|
FILE * stream)
|
FILE * stream)
|
{
|
{
|
|
// 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;
|
|
|
// If n=2 (pairs) then groupings[1] is where our list is
|
// 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.
|
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 ending with this instruction\n",n);
|
fprintf(stream, "%d-tuple groupings finishing with %s (%d)\n",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]);
|
|
|
|
for(set_count2=0;set_count2<n;set_count2++)
|
|
fprintf(stream, "%s\t",
|
|
or1k_32_insns[(insn_info->groupings[n-1][set_count+1][set_count2])]->insn_string);
|
|
printf("\n");
|
|
}
|
|
#endif
|
|
|
|
// 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;]
|
// [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1], so in 2-dimensional
|
int *ntuplelist = (int*)&(insn_info->groupings[n-1]);
|
// array pointer fashion, we should provide the "column" sizing.
|
int *set;
|
ntuplelist = insn_info->groupings[n-1];
|
int set_count, set_count2;
|
|
|
|
// 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];
|
|
|
|
assert(total_sets_for_ntuple <= OR1K_MAX_ENTRIES_PER_GROUP);
|
|
|
// 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++)
|
{
|
{
|
set = (int*)ntuplelist[set_count+1];
|
// 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)
|
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 1454... |
Line 1548... |
// 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, "%s\t", or1k_32_insns[(set[set_count2])]->insn_string);
|
|
|
// now print out the occurances
|
// now print out the occurances
|
fprintf(stream, "%d\ttimes\n", set_count_copy[largest_indx + 1]);
|
fprintf(stream, "\t%d\ttimes\n", set[n]);
|
|
|
// 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;
|
|
|
set_count++;
|
set_count++;
|
Line 1496... |
Line 1590... |
or1k_32_insn_top_x(or1k_32_insns[insn_index],stream,10);
|
or1k_32_insn_top_x(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);
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
// 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
|
or1k_32_most_freq_insn(stream);
|
or1k_32_most_freq_insn(stream);
|
|
|
}
|
}
|