URL
https://opencores.org/ocsvn/or2k/or2k/trunk
Subversion Repositories or2k
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 18 to Rev 19
- ↔ Reverse comparison
Rev 18 → Rev 19
/or2k/trunk/analysis-bin/insnanalysis/insn-lists.c
21,6 → 21,12
or1k_32_insn_lists_add(insn, insn_props); |
} |
|
void insn_lists_group_add(int n, |
instruction_properties *insn_props) |
{ |
or1k_32_ntuple_add(n, insn_props); |
} |
|
void insn_lists_free(void) |
{ |
or1k_32_insn_lists_free(); |
/or2k/trunk/analysis-bin/insnanalysis/or1k-32-insn.c
19,6 → 19,16
#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, |
struct or1k_32_instruction_properties * insn_props) |
{ |
980,21 → 990,20
// Add this instruction's occurance to our data |
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 |
void or1k_add_in_list(struct or1k_value_list * list, int32_t value) |
{ |
1018,74 → 1027,12
list->values[(list->count)][0] = value; |
list->values[(list->count)][1] = 1; |
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 |
// 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) |
{ |
num_setup_insns = 0; |
1111,6 → 1058,11
// index, as set when we decode the instruction |
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 |
num_setup_insns++; |
|
1181,28 → 1133,90
(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)])++; |
} |
|
|
// TODO: n-tuple groupings stats recording here! |
|
// Finished adding to stats for this instruction |
|
// Increment overall instructions "seen" counter |
num_seen_insns++; |
|
// 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; |
|
} |
|
|
// Free up all added instruction statistic tracking structs |
void or1k_32_insn_lists_free(void) |
|
|
// 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) |
{ |
// Free all entries we m/calloc()'d |
int insn_index; |
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++) |
|
if (n<2) |
{ |
if (or1k_32_insns[insn_index] != NULL) |
free(or1k_32_insns[insn_index]); |
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]; |
|
// 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 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++) |
{ |
// Check this set for a match with our existing trace |
// Example: |
// 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 (insn_info->groupings[n-1][set_match_index+1][tuple_set_itr] |
!= 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])++; |
} |
} |
} |
|
|
1388,6 → 1402,83
} |
} |
} |
|
#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) |
{ |
1401,9 → 1492,13
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++) |
{ |
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 |
// frequency count - should be fixed |
1410,3 → 1505,18
or1k_32_most_freq_insn(stream); |
|
} |
|
|
|
|
// 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]); |
} |
} |
/or2k/trunk/analysis-bin/insnanalysis/insn-lists.h
17,5 → 17,9
void insn_lists_add(instruction insn, |
instruction_properties *insn_props); |
|
// Record occurance of last n instructions |
void insn_lists_group_add(int n, |
instruction_properties *insn_props); |
|
// Free, clean up, anything we need to |
void insn_lists_free(void); |
/or2k/trunk/analysis-bin/insnanalysis/or1k-32-insn.h
26,6 → 26,76
|
}; |
|
|
// Structs for internal statistics keeping |
|
struct or1k_value_list |
{ |
|
#define OR1K_VALUE_MAX_ENTRIES 64 |
int count; |
// [value][occurances_of_value] |
int32_t values[OR1K_VALUE_MAX_ENTRIES][2]; |
|
}; |
|
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. The final entry after the instruction indexes |
// is the occurance count for this particular set (at [x][n][x+2]) |
// |
// 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 |
extern struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS]; |
|
|
// OpenRISC 1000 32-bit instruction defines, helping us |
// extract fields of the instructions |
|
47,6 → 117,10
void or1k_32_insn_lists_add(uint32_t insn, |
struct or1k_32_instruction_properties *insn_props); |
|
// Record the occurance of a group of instructions |
void or1k_32_ntuple_add(int n, |
struct or1k_32_instruction_properties *insn_props); |
|
// Print out some useful information |
void or1k_32_generate_stats(FILE * stream); |
|
/or2k/trunk/analysis-bin/insnanalysis/insnanalysis.c
90,7 → 90,11
} |
else |
{ |
printf("\n"); |
// Non-zero return from analyse_insn(): problem analysing instruction. |
|
// Is a NOP for now, but do something here if needed |
|
do{ } while(0); |
} |
|
} |
/or2k/trunk/analysis-bin/insnanalysis/Makefile
1,6 → 1,8
|
APP=insnanalysis |
|
CFLAGS ?= -O2 |
|
all: $(APP) |
|
SRC=insnanalysis.c or1k-32-insn.c insn-lists.c |
8,7 → 10,7
|
|
insnanalysis: $(SRC) $(HDRS) |
gcc -O2 $(SRC) -o $@ |
gcc $(CFLAGS) $(SRC) -o $@ |
|
|
test: test.bin $(APP) |