| Line 17... | Line 17... | 
      
        | typedef struct or1k_32_instruction_properties instruction_properties ;
 | typedef struct or1k_32_instruction_properties instruction_properties ;
 | 
      
        |  
 |  
 | 
      
        | #include "insn-lists.h"
 | #include "insn-lists.h"
 | 
      
        |  
 |  
 | 
      
        |  
 |  
 | 
      
        |   | // Variable to keep track of unique instructions we have
 | 
      
        |   | int num_setup_insns;
 | 
      
        |   | int num_seen_insns;
 | 
      
        |   |  
 | 
      
        |   | struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
 | 
      
        |   |  
 | 
      
        |   | // Keep enough instructions required to do the maximum n-tuple set
 | 
      
        |   | // analysis.
 | 
      
        |   | int or1k_32_recent_insns[OR1K_MAX_GROUPINGS_ANALYSIS];
 | 
      
        |   |  
 | 
      
        | 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 978... | Line 988... | 
      
        |                          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);
 | 
      
        |  
 |  
 | 
      
        |   |   // n-tuple groupings stats recording here!  
 | 
      
        |   |   // only if we've seen enough to do all the sequence analysis
 | 
      
        |   |   if (num_seen_insns > OR1K_MAX_GROUPINGS_ANALYSIS+1)
 | 
      
        |   |     {
 | 
      
        |   |       int n;
 | 
      
        |   |       for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
 | 
      
        |   |         insn_lists_group_add(n, insn_props);
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        |   |   // Finished adding to stats for this instruction
 | 
      
        |  
 |  
 | 
      
        |  
 |  
 | 
      
        | struct or1k_value_list
 | }
 | 
      
        | {
 |   | 
      
        |  
 |   | 
      
        | #define OR1K_VALUE_MAX_ENTRIES 64
 |   | 
      
        |   int count;
 |   | 
      
        |   // [value][occurances_of_value]
 |   | 
      
        |   int32_t values[OR1K_VALUE_MAX_ENTRIES][2];
 |   | 
      
        |  
 |   | 
      
        | };
 |   | 
      
        |  
 |   | 
      
        |  
 |  
 | 
      
        | // Function to add entry to, or increment incidences of, value in the value list
 | // Function to add entry to, or increment incidences of, value in the value list
 | 
      
        | void or1k_add_in_list(struct or1k_value_list * list, int32_t value)
 | void or1k_add_in_list(struct or1k_value_list * list, int32_t value)
 | 
      
        | {
 | {
 | 
      
        |   int i;
 |   int i;
 | 
      
        | Line 1017... | Line 1026... | 
      
        |       // Not found, add it to the list
 |       // Not found, add it to the list
 | 
      
        |       list->values[(list->count)][0] = value;
 |       list->values[(list->count)][0] = value;
 | 
      
        |       list->values[(list->count)][1] = 1;
 |       list->values[(list->count)][1] = 1;
 | 
      
        |       list->count++;
 |       list->count++;
 | 
      
        |     }
 |     }
 | 
      
        |  
 |   | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        | struct or1k_insn_info
 |   | 
      
        | {
 |   | 
      
        |   char* insn_string;
 |   | 
      
        |  
 |   | 
      
        |   int count;
 |   | 
      
        |  
 |   | 
      
        |   int has_branchtarg;
 |   | 
      
        |   struct or1k_value_list branch_info;
 |   | 
      
        |  
 |   | 
      
        |   int has_imm;
 |   | 
      
        |   struct or1k_value_list imm_info;
 |   | 
      
        |  
 |   | 
      
        |   int has_rD;
 |   | 
      
        |   int rD_use_freq[32];
 |   | 
      
        |   int has_rA;
 |   | 
      
        |   int rA_use_freq[32];
 |   | 
      
        |   int has_rB;
 |   | 
      
        |   int rB_use_freq[32];
 |   | 
      
        |  
 |   | 
      
        |   // 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 1000
 |   | 
      
        |   // Format of grouping data:
 |   | 
      
        |   //
 |   | 
      
        |   // 1st dimension: A list for each n-tuple group we're keeping track of 
 |   | 
      
        |   // (starting at pairs of instructions)
 |   | 
      
        |   //
 |   | 
      
        |   // 2nd dimension: Stores the list entries for the 1st dimension-tuple 
 |   | 
      
        |   // grouping. The number in [x][0][0] is the number of entries in the list so 
 |   | 
      
        |   // far, beginning at 0. The actual entries with data for grouping x start at 
 |   | 
      
        |   // [x][1][], where that entry holds the 1st x+2-tuple grouping information 
 |   | 
      
        |   // (eg. at x=0, [0][1][] is the first entry for/ pair instruction 
 |   | 
      
        |   // information, x=1, is for triples, x=2 quadruples, etc)
 |   | 
      
        |   //
 |   | 
      
        |   // 3rd dimension: Store up to x+2 instruction indexes (where x is the first 
 |   | 
      
        |   // dimension index, meaning this particular data is for a (x+2)-tuple set) 
 |   | 
      
        |   // and then a frequency count for this set (in index (x+2) of the third 
 |   | 
      
        |   // dimension array). Note we will have the index for the instruction this 
 |   | 
      
        |   // struct corresponds to in [x][n][(x+2)-1], which seems redundant, but can 
 |   | 
      
        |   // help processing later on.  
 |   | 
      
        |   // 
 |   | 
      
        |   // Note that we will have empty entries in the third dimension arrays for all
 |   | 
      
        |   // but the last in the list of n-tuples. This is to save doing tricky naming
 |   | 
      
        |   // defines and, in the future, if we would like to analyse sets that are 
 |   | 
      
        |   // bigger or smaller, hopefully all we need to do is change a single define.
 |   | 
      
        |   //
 |   | 
      
        |   int groupings[OR1K_MAX_GROUPINGS_ANALYSIS][OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1];
 |   | 
      
        |  
 |   | 
      
        | };
 |   | 
      
        |  
 |   | 
      
        | // This number should correspond to the maximum insn_index we assign in the 
 |   | 
      
        | // analyse function
 |   | 
      
        | #define OR1K_32_MAX_INSNS 117
 |   | 
      
        | struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS];
 |   | 
      
        |  
 |   | 
      
        |  
 |   | 
      
        | // List management/analysis functions - accessed through insn_lists() set of
 | // List management/analysis functions - accessed through insn_lists() set of
 | 
      
        | // functions
 | // functions
 | 
      
        |  
 |  
 | 
      
        | // Variable to keep track of unique instructions we have
 |   | 
      
        | int num_setup_insns;
 |   | 
      
        | int num_seen_insns;
 |   | 
      
        |  
 |   | 
      
        |  
 |   | 
      
        | 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 1109... | Line 1056... | 
      
        |  
 |  
 | 
      
        |   // Install the pointer for this newly allocated struct in its corresponding
 |   // Install the pointer for this newly allocated struct in its corresponding
 | 
      
        |   // index, as set when we decode the instruction
 |   // index, as set when we decode the instruction
 | 
      
        |   or1k_32_insns[insn_props->insn_index] = new_insn;
 |   or1k_32_insns[insn_props->insn_index] = new_insn;
 | 
      
        |  
 |  
 | 
      
        |   |   // Clear the set statistics counters
 | 
      
        |   |   int set_itr;
 | 
      
        |   |   for(set_itr=0;set_itr<OR1K_MAX_GROUPINGS_ANALYSIS;set_itr++)
 | 
      
        |   |     or1k_32_insns[insn_props->insn_index]->groupings[set_itr][0][0] = 0;
 | 
      
        |   |  
 | 
      
        |   // Increment number of instructions we have set up
 |   // Increment number of instructions we have set up
 | 
      
        |   num_setup_insns++;
 |   num_setup_insns++;
 | 
      
        |  
 |  
 | 
      
        |   // Debugging:
 |   // Debugging:
 | 
      
        |   //printf("Adding %dth instruction - %s\n",
 |   //printf("Adding %dth instruction - %s\n",
 | 
      
        | Line 1180... | Line 1132... | 
      
        |     {
 |     {
 | 
      
        |       (or1k_32_insns[insn_props->insn_index])->has_rB = 1;
 |       (or1k_32_insns[insn_props->insn_index])->has_rB = 1;
 | 
      
        |       ((or1k_32_insns[insn_props->insn_index])->rB_use_freq[insn_or1k_32_rB(insn)])++;
 |       ((or1k_32_insns[insn_props->insn_index])->rB_use_freq[insn_or1k_32_rB(insn)])++;
 | 
      
        |     }
 |     }
 | 
      
        |  
 |  
 | 
      
        |   |   // Increment overall instructions "seen" counter
 | 
      
        |   |   num_seen_insns++;
 | 
      
        |  
 |  
 | 
      
        |   // TODO: n-tuple groupings stats recording here!
 |   // Shift along the recently seen instructions
 | 
      
        |   |   int i;
 | 
      
        |   |   for(i=OR1K_MAX_GROUPINGS_ANALYSIS-1;i>0;i--)
 | 
      
        |   |     or1k_32_recent_insns[i] = or1k_32_recent_insns[i-1];
 | 
      
        |   |   or1k_32_recent_insns[0] = insn_props->insn_index;
 | 
      
        |  
 |  
 | 
      
        |   // Finished adding to stats for this instruction
 | }
 | 
      
        |  
 |  
 | 
      
        |   // Increment overall instructions "seen" counter
 |   | 
      
        |   num_seen_insns++;
 |   | 
      
        |  
 |  
 | 
      
        |   |  
 | 
      
        |   |  
 | 
      
        |   | // Do the n-tuple set analysis for the most recently added instruction
 | 
      
        |   | void or1k_32_ntuple_add(int n,
 | 
      
        |   |                         struct or1k_32_instruction_properties *insn_props)
 | 
      
        |   | {
 | 
      
        |   |  
 | 
      
        |   |   if (n<2)
 | 
      
        |   |     {
 | 
      
        |   |       fprintf(stderr,"or1k_32_ntuple_add: tuple number < 2 (%d)",n);
 | 
      
        |   |       return;
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        |   |   struct or1k_insn_info * insn_info = or1k_32_insns[insn_props->insn_index];
 | 
      
        |  
 |  
 | 
      
        | // Free up all added instruction statistic tracking structs
 |   // Get the number of sets for these n-tuple groups we've seen so far.
 | 
      
        | void or1k_32_insn_lists_free(void)
 |   int sets_for_ntuple = insn_info->groupings[n-1][0][0];
 | 
      
        |   |  
 | 
      
        |   |   int set_match_index; int tuple_set_itr, tuple_set_match;
 | 
      
        |   |  
 | 
      
        |   |  
 | 
      
        |   |   // 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[][][].
 | 
      
        |   |   for (set_match_index=0; set_match_index<sets_for_ntuple; set_match_index++)
 | 
      
        | {
 | {
 | 
      
        |   // Free all entries we m/calloc()'d
 |       // Check this set for a match with our existing trace
 | 
      
        |   int insn_index;
 |       // Example:
 | 
      
        |   for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
 |       // 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 
 | 
      
        |   |       // be the second in the trace, and [3][1][2] should be the first in the 
 | 
      
        |   |       // trace (same index as insn_props->insn_index)
 | 
      
        |   |  
 | 
      
        |   |       // Presuppose a match, de-assert and break out of the loop as soon as we
 | 
      
        |   |       // detect a mismatch.
 | 
      
        |   |       tuple_set_match = 1;
 | 
      
        |   |       for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
 | 
      
        |     {
 |     {
 | 
      
        |       if (or1k_32_insns[insn_index] != NULL)
 |           if (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr]
 | 
      
        |         free(or1k_32_insns[insn_index]);
 |               != or1k_32_recent_insns[n-1 - tuple_set_itr])
 | 
      
        |   |             {
 | 
      
        |   |               tuple_set_match = 0;
 | 
      
        |   |               break; // No match, so break out of this for() loop
 | 
      
        |   |             }
 | 
      
        |   |         }
 | 
      
        |   |  
 | 
      
        |   |       if (!tuple_set_match)
 | 
      
        |   |         continue; // go again...
 | 
      
        |   |     }
 | 
      
        |   |  
 | 
      
        |   |   if (tuple_set_match)
 | 
      
        |   |     // Found a match - just increment the counter (set_match_index should
 | 
      
        |   |     // be pointing at the right set)
 | 
      
        |   |     (insn_info->groupings[n-1][set_match_index+1][n])++;
 | 
      
        |   |   else
 | 
      
        |   |     {
 | 
      
        |   |       // If we can record a new set
 | 
      
        |   |       if (sets_for_ntuple < OR1K_MAX_ENTRIES_PER_GROUP)
 | 
      
        |   |         {
 | 
      
        |   |           // Increment the number of sets we have for this n-tuple starting
 | 
      
        |   |           // on the current instruction  
 | 
      
        |   |           sets_for_ntuple++;
 | 
      
        |   |           // Add new set to the end (all n instructions, copy in)
 | 
      
        |   |           for(tuple_set_itr=0;tuple_set_itr<n;tuple_set_itr++)
 | 
      
        |   |             insn_info->groupings[n-1][sets_for_ntuple][tuple_set_itr]
 | 
      
        |   |               = or1k_32_recent_insns[n-1 - tuple_set_itr];
 | 
      
        |   |           // Set the count for this set to 1
 | 
      
        |   |           insn_info->groupings[n-1][sets_for_ntuple][n] = 1;
 | 
      
        |   |           // Increment the counter of these n-tuple sets
 | 
      
        |   |           (insn_info->groupings[n-1][0][0])++;
 | 
      
        |   |         }
 | 
      
        |     }
 |     }
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        |  
 |  
 | 
      
        | #define DISPLAY_STRING
 | #define DISPLAY_STRING
 | 
      
        | Line 1387... | Line 1401... | 
      
        |           i++;
 |           i++;
 | 
      
        |         }
 |         }
 | 
      
        |     }
 |     }
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        |   | #define MAX_NTUPLE_LISTING 5
 | 
      
        |   | // 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,
 | 
      
        |   |                                    FILE * stream)
 | 
      
        |   | {
 | 
      
        |   |  
 | 
      
        |   |   // If n=2 (pairs) then groupings[1] is where our list is
 | 
      
        |   |   int total_sets_for_ntuple =  insn_info->groupings[n-1][0][0];
 | 
      
        |   |  
 | 
      
        |   |   if (total_sets_for_ntuple == 0)
 | 
      
        |   |     return;
 | 
      
        |   |  
 | 
      
        |   |   fprintf(stream, "%d-tuple groupings ending with this instruction\n",n);
 | 
      
        |   |  
 | 
      
        |   |   // This is actually a pointer to a 2-dimensional integer array, looking like:
 | 
      
        |   |   // [OR1K_MAX_ENTRIES_PER_GROUP+1][OR1K_MAX_GROUPINGS_ANALYSIS+1;]
 | 
      
        |   |   int *ntuplelist = (int*)&(insn_info->groupings[n-1]);
 | 
      
        |   |   int *set;
 | 
      
        |   |   int set_count, set_count2;
 | 
      
        |   |  
 | 
      
        |   |   // 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];
 | 
      
        |   |  
 | 
      
        |   |   // Go through the list, copy the counts for each
 | 
      
        |   |   for (set_count = 0;set_count <total_sets_for_ntuple;set_count++)
 | 
      
        |   |     {
 | 
      
        |   |       set = (int*)ntuplelist[set_count+1];
 | 
      
        |   |       set_count_copy[set_count+1]=set[n];
 | 
      
        |   |     }
 | 
      
        |   |  
 | 
      
        |   |   // Now go through, finding the most frequent n-tuple of instructions and
 | 
      
        |   |   // print it out
 | 
      
        |   |   int largest_indx = 0;
 | 
      
        |   |   set_count=0;
 | 
      
        |   |   while(set_count < total_sets_for_ntuple && set_count < MAX_NTUPLE_LISTING)
 | 
      
        |   |     {
 | 
      
        |   |       largest_indx = 0;
 | 
      
        |   |       for(set_count2=0;set_count2<total_sets_for_ntuple;set_count2++)
 | 
      
        |   |         largest_indx = (set_count_copy[set_count2 + 1] >
 | 
      
        |   |                         set_count_copy[largest_indx + 1]) ?
 | 
      
        |   |           set_count2 : largest_indx;
 | 
      
        |   |       // 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
 | 
      
        |   |       set = (int*)ntuplelist[largest_indx+1];
 | 
      
        |   |  
 | 
      
        |   |       // Print out the sequence of prior isntructions
 | 
      
        |   |       fprintf(stream,"Seq:\t");
 | 
      
        |   |       // 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);
 | 
      
        |   |  
 | 
      
        |   |       // now print out the occurances
 | 
      
        |   |       fprintf(stream, "%d\ttimes\n", set_count_copy[largest_indx + 1]);
 | 
      
        |   |  
 | 
      
        |   |       // done printing this one out.. let's clear its count
 | 
      
        |   |       set_count_copy[largest_indx + 1] = -1;
 | 
      
        |   |  
 | 
      
        |   |       set_count++;
 | 
      
        |   |     }
 | 
      
        |   |  
 | 
      
        |   |   return;
 | 
      
        |   |  
 | 
      
        |   | }
 | 
      
        |   |  
 | 
      
        |   |  
 | 
      
        |   | // Print out the stats relating to the sequences of instructions most
 | 
      
        |   | // common before seeing this instruction
 | 
      
        |   | void or1k_32_generate_groupings_stats(struct or1k_insn_info *insn_info,
 | 
      
        |   |                                       FILE * stream)
 | 
      
        |   | {
 | 
      
        |   |   int n;
 | 
      
        |   |   for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
 | 
      
        |   |     or1k_32_generate_ntuple_stats(n, insn_info, stream);
 | 
      
        |   |  
 | 
      
        |   | }
 | 
      
        |   |  
 | 
      
        | void or1k_32_generate_stats(FILE * stream)
 | void or1k_32_generate_stats(FILE * stream)
 | 
      
        | {
 | {
 | 
      
        |   // Generate some useful things
 |   // Generate some useful things
 | 
      
        |   fprintf(stream, "Analysis output:\n");
 |   fprintf(stream, "Analysis output:\n");
 | 
      
        |  
 |  
 | 
      
        | Line 1399... | Line 1490... | 
      
        |   // 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_x(or1k_32_insns[insn_index],stream,10);
 | 
      
        |   |           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);
 | 
      
        |  
 |  
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        |  No newline at end of file
 |  No newline at end of file
 | 
      
        |   |  
 | 
      
        |   |  
 | 
      
        |   |  
 | 
      
        |   | // Free up all added instruction statistic tracking structs
 | 
      
        |   | void or1k_32_insn_lists_free(void)
 | 
      
        |   | {
 | 
      
        |   |   // Free all entries we m/calloc()'d
 | 
      
        |   |   int insn_index;
 | 
      
        |   |   for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
 | 
      
        |   |     {
 | 
      
        |   |       if (or1k_32_insns[insn_index] != NULL)
 | 
      
        |   |         free(or1k_32_insns[insn_index]);
 | 
      
        |   |     }
 | 
      
        |   | }
 | 
      
        |   |  
 | 
      
        |  No newline at end of file
 |  No newline at end of file
 |