-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtracereader.c
182 lines (158 loc) · 4.66 KB
/
tracereader.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include <stdio.h>
#include "tracereader.h"
/*
* If you are using this program on a big-endian machine (something
* other than an Intel PC or equivalent) the unsigned longs will need
* to be converted from little-endian to big-endian.
*/
uint32_t swap_endian(uint32_t num)
{
return(((num << 24) & 0xff000000) | ((num << 8) & 0x00ff0000) |
((num >> 8) & 0x0000ff00) | ((num >> 24) & 0x000000ff));
}
/* determine if system is big- or little- endian */
ENDIAN endian()
{
/* Allocate a 32 bit character array and pointer which will be used
* to manipulate it.
*/
uint32_t* a;
unsigned char p[4];
a = (uint32_t*)p; /* Let a point to the character array */
*a = 0x12345678; /* Store a known bit pattern to the array */
/* Check the first byte. If it contains the high order bits,
* it is big-endian, otherwise little-endian.
*/
if (*p == 0x12)
return BIG;
else
return LITTLE;
}
/* int NextAddress(FILE *trace_file, p2AddrTr *Addr)
* Fetch the next address from the trace.
*
* trace_file must be a file handle to an trace file opened
* with fopen. User provides a pointer to an address structure.
*
* Populates the Addr structure and returns non-zero if successful.
*/
int NextAddress(FILE* trace_file, p2AddrTr* addr_ptr) {
int readN; /* number of records stored */
static ENDIAN byte_order = UNKNOWN; /* don't know machine format */
if (byte_order == UNKNOWN) {
/* First invocation. Determine if this is a litte- or
* big- endian machine so that we can convert bit patterns
* if needed that are stored in little-endian format
*/
byte_order = endian();
}
/* Read the next address record. */
readN = fread(addr_ptr, sizeof(p2AddrTr), 1, trace_file);
if (readN) {
if (byte_order == BIG) {
/* records stored in little endian format, convert */
addr_ptr->addr = swap_endian(addr_ptr->addr);
addr_ptr->time = swap_endian(addr_ptr->time);
}
}
return readN;
}
/* void AddressDecoder(p2AddrTr *addr_ptr, FILE *out)
* Decode a Pentium II BYU address and print to the specified
* file handle (opened by fopen in write mode)
*/
void AddressDecoder(p2AddrTr* addr_ptr, FILE* out) {
fprintf(out, "%08x ", addr_ptr->addr); /* address */
/* what type of address request */
switch (addr_ptr->reqtype) {
case FETCH:
fprintf(out, "FETCH\t\t");
break;
case MEMREAD:
fprintf(out, "MEMREAD\t");
break;
case MEMREADINV:
fprintf(out, "MEMREADINV\t");
break;
case MEMWRITE:
fprintf(out, "MEMWRITE\t");
break;
case IOREAD:
fprintf(out, "IOREAD\t\t");
break;
case IOWRITE:
fprintf(out, "IOWRITE\t");
break;
case DEFERREPLY:
fprintf(out, "DEFERREPLY\t");
break;
case INTA:
fprintf(out, "INTA\t\t");
break;
case CNTRLAGNTRES:
fprintf(out, "CNTRLAGNTRES\t");
break;
case BRTRACEREC:
fprintf(out, "BRTRACEREC\t");
break;
case SHUTDOWN:
fprintf(out, "SHUTDOWN\t");
break;
case FLUSH:
fprintf(out, "FLUSH\t\t");
break;
case HALT:
fprintf(out, "HALT\t\t");
break;
case SYNC:
fprintf(out, "SYNC\t\t");
break;
case FLUSHACK:
fprintf(out, "FLUSHACK\t");
break;
case STOPCLKACK:
fprintf(out, "STOPCLKAK\t");
break;
case SMIACK:
fprintf(out, "SMIACK\t\t");
break;
}
/* print remaining attributes:
bytes accessed
other tattributes
process
timestamp
*/
fprintf(out, "%2d\t%02x\t%1d\t%08x\n", addr_ptr->size, addr_ptr->attr,
addr_ptr->proc, addr_ptr->time);
}
#ifdef STANDALONE /* #define to use this as a program */
int main(int argc, char** argv)
{
FILE* ifp; /* trace file */
unsigned long i = 0; /* instructions processed */
p2AddrTr trace; /* traced address */
/* check usage */
if (argc != 2) {
fprintf(stderr, "usage: %s input_byutr_file\n", argv[0]);
exit(1);
}
/* attempt to open trace file */
if ((ifp = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "cannot open %s for reading\n", argv[1]);
exit(1);
}
while (!feof(ifp)) {
/* get next address and process */
if (NextAddress(ifp, &trace)) {
AddressDecoder(&trace, stdout);
i++;
if ((i % 100000) == 0)
fprintf(stderr, "%dK samples processed\r", i / 100000);
}
}
/* clean up and return success */
fclose(ifp);
return (0);
}
#endif