URL
https://opencores.org/ocsvn/or2k/or2k/trunk
Subversion Repositories or2k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or2k/trunk/analysis-bin/insnanalysis
- from Rev 25 to Rev 26
- ↔ Reverse comparison
Rev 25 → Rev 26
/test.S
1,7 → 1,7
/* Assembly source, with one of every instruction for the or1k |
instruction set */ |
|
l.j 0 |
l.j 0x1234 |
l.jal 0 |
l.bnf 0 |
l.bf 0 |
/or1k-32-insn.c
898,14 → 898,23
break; |
|
case 0xd: |
insn_props->insn_string="l.extws"; |
insn_props->insn_index=103; |
switch(insn_or1k_opcode_0x38_get_op_hi_4bit(insn)) |
{ |
case 0x0: |
insn_props->insn_string="l.extws"; |
insn_props->insn_index=103; |
break; |
case 0x1: |
insn_props->insn_string="l.extwz"; |
insn_props->insn_index=104; |
break; |
} |
insn_props->has_rB = 0; |
break; |
|
case 0xe: |
insn_props->insn_string="l.cmov"; |
insn_props->insn_index=104; |
insn_props->insn_index=105; |
break; |
|
case 0xf: |
912,12 → 921,12
if (insn_or1k_opcode_0x38_get_op_hi_2bit(insn) & 0x1) |
{ |
insn_props->insn_string="l.fl1"; |
insn_props->insn_index=105; |
insn_props->insn_index=106; |
} |
else |
{ |
insn_props->insn_string="l.ff1"; |
insn_props->insn_index=106; |
insn_props->insn_index=107; |
} |
insn_props->has_rB = 0; |
break; |
937,43 → 946,43
{ |
case 0x0: |
insn_props->insn_string="l.sfeq"; |
insn_props->insn_index=107; |
insn_props->insn_index=108; |
break; |
case 0x1: |
insn_props->insn_string="l.sfne"; |
insn_props->insn_index=108; |
insn_props->insn_index=109; |
break; |
case 0x2: |
insn_props->insn_string="l.sfgtu"; |
insn_props->insn_index=109; |
insn_props->insn_index=110; |
break; |
case 0x3: |
insn_props->insn_string="l.sfgeu"; |
insn_props->insn_index=110; |
insn_props->insn_index=111; |
break; |
case 0x4: |
insn_props->insn_string="l.sfltu"; |
insn_props->insn_index=111; |
insn_props->insn_index=112; |
break; |
case 0x5: |
insn_props->insn_string="l.sfleu"; |
insn_props->insn_index=112; |
insn_props->insn_index=113; |
break; |
case 0xa: |
insn_props->insn_string="l.sfgts"; |
insn_props->insn_index=113; |
insn_props->insn_index=114; |
break; |
case 0xb: |
insn_props->insn_string="l.sfges"; |
insn_props->insn_index=114; |
insn_props->insn_index=115; |
break; |
case 0xc: |
insn_props->insn_string="l.sflts"; |
insn_props->insn_index=115; |
insn_props->insn_index=116; |
break; |
case 0xd: |
insn_props->insn_string="l.sfles"; |
insn_props->insn_index=116; |
insn_props->insn_index=117; |
break; |
default: |
printf("Unknown opcode for l.sfxxx opcode (0x%x)", |
1456,7 → 1465,7
"Insn: \"%s\" statistics (%d times (%f%%))\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"Instruction:\",\"%s\",\"occurrences:\",%d,%f\n", |
"\"Instruction:\",\"%s\",\"occurrences:\",%d,%f%%\n", |
#endif |
insn_info->insn_string, |
insn_info->count, |
1473,10 → 1482,10
{ |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"Branch values:\n" |
"Branch immediates:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"branch distance\",\"occurrences\"\n" |
"\"branch imm\",\"occurrences\",\"frequency\"\n" |
#endif |
); |
i = 0; |
1491,13 → 1500,15
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"value:\t0x%x\tcount:\t%d\n", |
"value:\t0x%x\tcount:\t%d,\tfreq:\t%f%%\n", |
#endif |
#ifdef DISPLAY_CSV |
"0x%x,%d\n", |
"0x%x,%d,%f\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], |
(float)(((float)insn_info->branch_info.values[largest_i][1]) |
/((float)((insn_info)->count)))*100.0f); |
insn_info->branch_info.values[largest_i][1] = -1; // clear this one |
i++; |
} |
1509,7 → 1520,7
"Immediate values:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"immediate value\",\"count\"\n" |
"\"immediate value\",\"count\",\"frequency\"\n" |
#endif |
); |
i = 0; |
1524,13 → 1535,15
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"value:\t0x%x\tcount:\t%d\n", |
"value:\t0x%x\tcount:\t%d\tfreq:\t%f%%\n", |
#endif |
#ifdef DISPLAY_CSV |
"0x%x,%d\n", |
"0x%x,%d,%f\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], |
(float)(((float)insn_info->imm_info.values[largest_i][1]) |
/((float)((insn_info)->count)))*100.0f); |
insn_info->imm_info.values[largest_i][1] = -1; // clear this one |
i++; |
} |
1543,7 → 1556,7
"rD usage:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"rD\",\"count\"\n" |
"\"rD\",\"count\",\"frequency\"\n" |
#endif |
); |
i = 0; |
1562,13 → 1575,15
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"r%d\tcount:\t%d\n", |
"r%d\tcount:\t%d\tfreq:\t%f%%\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"r%d\",%d\n", |
"\"r%d\",%d,%f\n", |
#endif |
largest_i, |
insn_info->rD_use_freq[largest_i]); |
insn_info->rD_use_freq[largest_i], |
(float)(((float)insn_info->rD_use_freq[largest_i]) |
/((float)((insn_info)->count)))*100.0f); |
insn_info->rD_use_freq[largest_i] = -1; // clear this one |
i++; |
} |
1581,7 → 1596,7
"rA usage:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"rA\",\"count\"\n" |
"\"rA\",\"count\",\"frequency\"\n" |
#endif |
); |
i = 0; |
1601,13 → 1616,15
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"r%d\tcount:\t%d\n", |
"r%d\tcount:\t%d\tfreq:\t%f%%\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"r%d\",%d\n", |
"\"r%d\",%d,%f\n", |
#endif |
largest_i, |
insn_info->rA_use_freq[largest_i]); |
insn_info->rA_use_freq[largest_i], |
(float)(((float)insn_info->rA_use_freq[largest_i]) |
/((float)((insn_info)->count)))*100.0f); |
insn_info->rA_use_freq[largest_i] = -1; // clear this one |
i++; |
} |
1620,7 → 1637,7
"rB usage:\n" |
#endif |
#ifdef DISPLAY_CSV |
"\"rB\",\"count\"\n" |
"\"rB\",\"count\",\"frequency\"\n" |
#endif |
); |
i = 0; |
1640,13 → 1657,15
// largest_i has index of most frequent value |
fprintf(stream, |
#ifdef DISPLAY_STRING |
"r%d\tcount:\t%d\n", |
"r%d\tcount:\t%d\tfreq:\t%f%%\n", |
#endif |
#ifdef DISPLAY_CSV |
"\"r%d\",%d\n", |
"\"r%d\",%d,%f\n", |
#endif |
largest_i, |
insn_info->rB_use_freq[largest_i]); |
insn_info->rB_use_freq[largest_i], |
(float)(((float)insn_info->rB_use_freq[largest_i]) |
/((float)((insn_info)->count)))*100.0f); |
insn_info->rB_use_freq[largest_i] = -1; // clear this one |
i++; |
} |
/or1k-32-insn.h
10,8 → 10,8
#define DEBUG_PRINT 0 |
|
// Choose the output format, uncomment only one |
//#define DISPLAY_STRING |
#define DISPLAY_CSV |
#define DISPLAY_STRING |
//#define DISPLAY_CSV |
|
|
// Struct for information about the register to be confugred |
99,7 → 99,7
|
// This number should correspond to the maximum insn_index we assign in the |
// analyse function |
#define OR1K_32_MAX_INSNS 117 |
#define OR1K_32_MAX_INSNS 118 |
extern struct or1k_insn_info * or1k_32_insns[OR1K_32_MAX_INSNS]; |
|
|
/README
3,11 → 3,21
This application reads in a binary list of instructions, and analyses it with a |
set of functions looking at various parameters in each instruction. |
|
It has been designed so a different instruction set support can be added. |
|
Right now it's not so user friendly. Everything is hardcoded, and only support |
for the OR1K instruction set exists. |
|
It has been written in a way that should allow other instructinos to be added |
easily. It remains to be seen how much would be reusable between the sets but |
for now, at least it would be easy enough to take the OR1K instruction |
analysis functions and drop in a different instruction set. |
|
The types of information given for OR1K instruction analysis is instruction |
frequency, immediate frequency for each instruction, branch distance value |
frequency, and register usage frequency. For each instruction, the most common |
n-tuple sets of instructions, finishing with that instruction, are presented, |
for pairs, triples and quadruples. Additionally output is the most common |
overall n-tuples. |
|
Compile the program with: |
|
$ make all |
19,23 → 29,49
To run the program itself, just give it a binary blob of instructions (usually |
the output of objcopy -O binary). |
|
For instance the Linux kernel ELF can be prepared with the following command: |
Static analysis: |
|
For instance the Linux kernel ELF for OR1K can be prepared with the following |
command: |
|
$ or32-elf-objcopy -O binary -j .text -S vmlinux vmlinux.text.bin |
|
Run it in the program with |
It is passed to the program like so, and the output is captured by redirecting |
stdout. |
|
$ ./insnanalysis vmlinux.text.bin > vmlinux.insnanalysis |
|
Currently the program will output all appropriate information for each |
instruction (ie. only ones with rA, or immediate fields in the instructions will |
have reports on those fields.) |
Dynamic analysis with binary execution log from or1ksim: |
|
As of revision 202 of the OpenRISC repository, or1ksim is capable of generating |
an execution trace log in binary format, logging each instruction executed. |
This log file can be given to insnanalysis. |
|
In the or1ksim config file ensure the line "exe_bin_insn_log = 1" is in the |
sim section. This will enable the binary instruction logging. The resulting |
output file is then given to insnanalysis in the same manner as above. |
|
Output: |
|
Currently there are only two output formats, human readable string and CSV. |
|
The output can be switched between human readable strings and CSV format (ready |
to be imported into a spreadsheet application) by uncommenting one of the |
"#define DISPLAY_" defines in the instruction set header. The program must be |
recompiled if this is changed. |
|
|
TODO: |
o Collect and display information about l.j and l.jal instruction immediates |
o Add an easy way to switch between human readable and CSV output |
o Figure out how to tack this thing onto a simulator (or1ksim maybe) to give |
results of execution when that finishes executing, or just how to get the |
simulator to output a binary dump of executed instructions to be fed through |
this |
o Add support for a list of binary files to be specified at the command line |
o Allow statistics to be collated over different files - this would allow each |
function to be broken out of a library, or application, and in that regard |
the instruction sequence data would then be accurate for static analysis. |
|
|
July 24, 2010 - Julius Baxter |