|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.carbide.cpp.pi.internal.ipc; |
|
19 |
|
20 import java.io.DataInputStream; |
|
21 import java.io.File; |
|
22 import java.io.FileInputStream; |
|
23 import java.io.FileNotFoundException; |
|
24 import java.io.IOException; |
|
25 import java.util.ArrayList; |
|
26 import java.util.HashMap; |
|
27 import java.util.List; |
|
28 import java.util.Map; |
|
29 |
|
30 import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData; |
|
31 import com.nokia.carbide.cpp.internal.pi.model.Parser; |
|
32 |
|
33 |
|
34 /** |
|
35 * Parser for performance counter event traces in binary format. |
|
36 * Converts parsed content into IpcSamples. |
|
37 */ |
|
38 public class IpcTraceParser extends Parser { |
|
39 private static final String IPC_EVENT_NOT_RECOGNISED = Messages.IpcTraceParser_0; |
|
40 private static final int MAX_IPC_EVENTS_TRACED = 14; //2 IPC events * 5 possible values + 4 optional L2 counter values |
|
41 private static final int MAX_IPC_NO_L2_EVENTS_TRACED = 10; //2 IPC events * 5 possible values |
|
42 |
|
43 |
|
44 //private static int CPU_CLOCK_TICK_DIV64 = 0xFFFF; |
|
45 private boolean debug = false; //CH: this could be replaced with Eclipse-style logging |
|
46 private boolean l2Enabled = false; |
|
47 |
|
48 long time = 0; |
|
49 |
|
50 private static final Map<Integer, String> eventTypeTable = new HashMap<Integer, String>(); |
|
51 static { |
|
52 eventTypeTable.put(0x0,Messages.IpcTraceParser_1); |
|
53 eventTypeTable.put(0x1,Messages.IpcTraceParser_2); |
|
54 eventTypeTable.put(0x2,Messages.IpcTraceParser_3); |
|
55 eventTypeTable.put(0x3,Messages.IpcTraceParser_4); |
|
56 eventTypeTable.put(0x4,Messages.IpcTraceParser_5); |
|
57 } |
|
58 private static final Map<Integer, String> counterTypeTable = new HashMap<Integer, String>(); |
|
59 static { |
|
60 counterTypeTable.put(0x0,Messages.IpcTraceParser_6); |
|
61 counterTypeTable.put(0x1,Messages.IpcTraceParser_7); |
|
62 counterTypeTable.put(0x2,Messages.IpcTraceParser_8); |
|
63 counterTypeTable.put(0x3,Messages.IpcTraceParser_9); |
|
64 counterTypeTable.put(0x4,Messages.IpcTraceParser_10); |
|
65 counterTypeTable.put(0x5,Messages.IpcTraceParser_11); |
|
66 } |
|
67 private static final Map<Integer, String> l2EventTypeTable = new HashMap<Integer, String>(); |
|
68 static { |
|
69 l2EventTypeTable.put(0x3,Messages.IpcTraceParser_12); |
|
70 l2EventTypeTable.put(0x4,Messages.IpcTraceParser_13); |
|
71 l2EventTypeTable.put(0x5,Messages.IpcTraceParser_14); |
|
72 l2EventTypeTable.put(0x6,Messages.IpcTraceParser_15); |
|
73 l2EventTypeTable.put(0x7,Messages.IpcTraceParser_16); |
|
74 l2EventTypeTable.put(0xC,Messages.IpcTraceParser_17); |
|
75 l2EventTypeTable.put(0xD,Messages.IpcTraceParser_18); |
|
76 } |
|
77 |
|
78 /* (non-Javadoc) |
|
79 * @see com.nokia.carbide.cpp.internal.pi.model.Parser#parse(java.io.File) |
|
80 */ |
|
81 @Override |
|
82 public ParsedTraceData parse(File file) throws Exception |
|
83 { |
|
84 ParsedTraceData ptd = new ParsedTraceData(); |
|
85 ptd.functionResolvers = null; |
|
86 ptd.staticData = null; |
|
87 ptd.traceData = new IpcTrace(); |
|
88 doParsing(file,(IpcTrace)ptd.traceData); |
|
89 time = 0; |
|
90 |
|
91 return ptd; |
|
92 } |
|
93 |
|
94 private void doParsing(File f, IpcTrace trace) throws FileNotFoundException |
|
95 { |
|
96 DataInputStream dis = new DataInputStream(new FileInputStream(f)); |
|
97 try { |
|
98 int len = dis.readByte(); |
|
99 byte[] versionString = new byte[len]; |
|
100 dis.read(versionString); |
|
101 this.traceVersion = new String(versionString); |
|
102 if (debug){ |
|
103 System.out.println("IPC trace version:" + this.traceVersion); //$NON-NLS-1$ |
|
104 } |
|
105 |
|
106 List<Integer> counterTypes = new ArrayList<Integer>(); |
|
107 List<Integer> counterL2Types = new ArrayList<Integer>(); |
|
108 |
|
109 // IPC counters |
|
110 int firstCounter = dis.readUnsignedByte(); |
|
111 counterTypes.add(firstCounter); |
|
112 int secondCounter = dis.readUnsignedByte(); |
|
113 counterTypes.add(secondCounter); |
|
114 |
|
115 // this type is always the cpu clock tick div 64 |
|
116 // int thirdData = CPU_CLOCK_TICK_DIV64; |
|
117 // valueTypeVector.add(new Integer(thirdData)); |
|
118 |
|
119 if (dis.readUnsignedByte() != 0) { |
|
120 // L2 counters, add if available |
|
121 int thirdCounter = dis.readUnsignedByte(); |
|
122 counterL2Types.add(thirdCounter); |
|
123 int fourthCounter = dis.readUnsignedByte(); |
|
124 counterL2Types.add(fourthCounter); |
|
125 int fifthCounter = dis.readUnsignedByte(); |
|
126 counterL2Types.add(fifthCounter); |
|
127 int sixthCounter = dis.readUnsignedByte(); |
|
128 counterL2Types.add(sixthCounter); |
|
129 |
|
130 trace.setValueTypes(this.parseValueTypes(counterTypes, counterL2Types)); |
|
131 } else { |
|
132 trace.setValueTypes(this.parseValueTypes(counterTypes, null)); |
|
133 } |
|
134 |
|
135 // System.out.println("IPC first "+firstCounter+" second "+secondCounter); |
|
136 |
|
137 IpcSample s = null; |
|
138 while (true) { |
|
139 s = readSample(dis, s); |
|
140 // System.out.println(this.time+" "+Long.toHexString(s.values[0])+" "+Long.toHexString(s.values[1])+" "+Long.toHexString(s.values[2])); |
|
141 trace.addSample(s); |
|
142 } |
|
143 } catch (IOException ioe) { |
|
144 // CH: is this just caught for end-of-file condition? |
|
145 } |
|
146 } |
|
147 |
|
148 private IpcSample readSample(DataInputStream dis, IpcSample prevSample) |
|
149 throws IOException { |
|
150 // int headerByte = (dis.readInt()); // << 24) >>> 24; |
|
151 int headerByte1 = (dis.readByte() << 24) >>> 24; |
|
152 int headerByte2 = (dis.readByte() << 24) >>> 24; |
|
153 int headerByte3 = (dis.readByte() << 24) >>> 24; |
|
154 int headerByte4 = (dis.readByte() << 24) >>> 24; |
|
155 int headerByte = ((((headerByte1) | (headerByte2) << 8) | (headerByte3) << 16) | headerByte4 << 24); |
|
156 |
|
157 int headerByte11 = 0; |
|
158 int headerByte12 = 0; |
|
159 int headerByteL2 = 0; |
|
160 // int j = ((headerByte >>> 30)&1); |
|
161 if (((headerByte >>> 30) & 1) != 0 || l2Enabled) // flag bit in trace => |
|
162 // L2 trace included |
|
163 { |
|
164 l2Enabled = true; |
|
165 headerByte11 = (dis.readByte() << 24) >>> 24; |
|
166 headerByte12 = (dis.readByte() << 24) >>> 24; // overflow bits |
|
167 headerByteL2 = ((headerByte11) | ((headerByte12) << 8)); |
|
168 } |
|
169 |
|
170 int eventNumber = l2Enabled ? MAX_IPC_EVENTS_TRACED |
|
171 : MAX_IPC_NO_L2_EVENTS_TRACED; |
|
172 |
|
173 int[] neg = new int[eventNumber]; |
|
174 int[] prev = new int[eventNumber]; |
|
175 |
|
176 if (prevSample != null) { |
|
177 prev[0] = prevSample.values[0]; |
|
178 prev[1] = prevSample.values[1]; |
|
179 prev[2] = prevSample.values[2]; |
|
180 prev[3] = prevSample.values[3]; |
|
181 prev[4] = prevSample.values[4]; |
|
182 prev[5] = prevSample.values[5]; |
|
183 prev[6] = prevSample.values[6]; |
|
184 prev[7] = prevSample.values[7]; |
|
185 prev[8] = prevSample.values[8]; |
|
186 prev[9] = prevSample.values[9]; |
|
187 if (l2Enabled) { |
|
188 prev[10] = prevSample.values[10]; |
|
189 prev[11] = prevSample.values[11]; |
|
190 prev[12] = prevSample.values[12]; |
|
191 prev[13] = prevSample.values[13]; |
|
192 } |
|
193 } |
|
194 // /*if(debug) if(this.time > 7820 && this.time < 7830)*/ |
|
195 // System.out.println("header: "+Long.toHexString(headerByte)+" = "+Integer.toBinaryString(headerByte)); |
|
196 |
|
197 if (((headerByte >>> 29) & 1) != 0) { |
|
198 neg[0] = 1; |
|
199 } |
|
200 |
|
201 if (((headerByte >>> 28) & 1) != 0) { |
|
202 neg[1] = 1; |
|
203 } |
|
204 |
|
205 if (((headerByte >>> 27) & 1) != 0) { |
|
206 neg[2] = 1; |
|
207 } |
|
208 if (((headerByte >>> 26) & 1) != 0) { |
|
209 neg[3] = 1; |
|
210 } |
|
211 |
|
212 if (((headerByte >>> 25) & 1) != 0) { |
|
213 neg[4] = 1; |
|
214 } |
|
215 |
|
216 if (((headerByte >>> 24) & 1) != 0) { |
|
217 neg[5] = 1; |
|
218 } |
|
219 if (((headerByte >>> 23) & 1) != 0) { |
|
220 neg[6] = 1; |
|
221 } |
|
222 |
|
223 if (((headerByte >>> 22) & 1) != 0) { |
|
224 neg[7] = 1; |
|
225 } |
|
226 |
|
227 if (((headerByte >>> 21) & 1) != 0) { |
|
228 neg[8] = 1; |
|
229 } |
|
230 if (((headerByte >>> 20) & 1) != 0) { |
|
231 neg[9] = 1; |
|
232 } |
|
233 |
|
234 // check overflows of L2 counters |
|
235 if (l2Enabled) { |
|
236 if (((headerByteL2 >>> 11) & 1) != 0) { |
|
237 neg[10] = 1; |
|
238 } |
|
239 |
|
240 if (((headerByteL2 >>> 10) & 1) != 0) { |
|
241 neg[11] = 1; |
|
242 } |
|
243 |
|
244 if (((headerByteL2 >>> 9) & 1) != 0) { |
|
245 neg[12] = 1; |
|
246 } |
|
247 if (((headerByteL2 >>> 8) & 1) != 0) { |
|
248 neg[13] = 1; |
|
249 } |
|
250 |
|
251 } |
|
252 |
|
253 int[] len = new int[eventNumber]; |
|
254 len[0] = (((headerByte >> 18) << 30) >>> 30) + 1; |
|
255 len[1] = (((headerByte >> 16) << 30) >>> 30) + 1; |
|
256 len[2] = (((headerByte >> 14) << 30) >>> 30) + 1; |
|
257 len[3] = (((headerByte >> 12) << 30) >>> 30) + 1; |
|
258 len[4] = (((headerByte >> 10) << 30) >>> 30) + 1; |
|
259 len[5] = (((headerByte >> 8) << 30) >>> 30) + 1; |
|
260 len[6] = (((headerByte >> 6) << 30) >>> 30) + 1; |
|
261 len[7] = (((headerByte >> 4) << 30) >>> 30) + 1; |
|
262 len[8] = (((headerByte >> 2) << 30) >>> 30) + 1; |
|
263 len[9] = (((headerByte) << 30) >>> 30) + 1; |
|
264 |
|
265 if (l2Enabled) { |
|
266 len[10] = (((headerByteL2 >> 6) << 30) >>> 30) + 1; |
|
267 len[11] = (((headerByteL2 >> 4) << 30) >>> 30) + 1; |
|
268 len[12] = (((headerByteL2 >> 2) << 30) >>> 30) + 1; |
|
269 len[13] = ((headerByteL2 << 30) >>> 30) + 1; |
|
270 } |
|
271 if (debug) |
|
272 if (this.time > 7820 && this.time < 7830) |
|
273 System.out.println("T:" + this.time + " len0:" + len[0] + " len1:" + len[1] + " len2:" + len[2]); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
|
274 if (debug) |
|
275 if (this.time > 7900 && this.time < 7900) |
|
276 System.out.println("H: " + Integer.toBinaryString(headerByte) + " N0:" + neg[0] + " N1:" + neg[1] + " N2:" + neg[2]); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ |
|
277 |
|
278 int[] val = new int[eventNumber]; |
|
279 val[0] = readVal(neg[0], len[0], dis); |
|
280 val[1] = readVal(neg[1], len[1], dis); |
|
281 val[2] = readVal(neg[2], len[2], dis); |
|
282 val[3] = readVal(neg[3], len[3], dis); |
|
283 val[4] = readVal(neg[4], len[4], dis); |
|
284 val[5] = readVal(neg[5], len[5], dis); |
|
285 val[6] = readVal(neg[6], len[6], dis); |
|
286 val[7] = readVal(neg[7], len[7], dis); |
|
287 val[8] = readVal(neg[8], len[8], dis); |
|
288 val[9] = readVal(neg[9], len[9], dis); |
|
289 |
|
290 if (l2Enabled) { |
|
291 val[10] = readVal(neg[10], len[10], dis); |
|
292 val[11] = readVal(neg[11], len[11], dis); |
|
293 val[12] = readVal(neg[12], len[12], dis); |
|
294 val[13] = readVal(neg[13], len[13], dis); |
|
295 } |
|
296 |
|
297 if (debug) |
|
298 if (this.time > 7820 && this.time < 7900) |
|
299 System.out.println("READ T:" + this.time + " V0:" + Integer.toHexString(val[0]) + " V1:" + Long.toHexString(val[1]) + " V2:" + Long.toHexString(val[2])); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
|
300 for (int i = 0; i < eventNumber; i++) { |
|
301 val[i] = prev[i] - val[i]; |
|
302 } |
|
303 |
|
304 IpcSample ps = new IpcSample(val, this.time); |
|
305 |
|
306 if (debug) |
|
307 if (this.time > 7820 && this.time < 7900) |
|
308 System.out.println("T:" + this.time + " V0:" + Long.toHexString(val[0]) + " V1:" + Long.toHexString(val[1]) + " V2:" + Long.toHexString(val[2])); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ |
|
309 if (debug) |
|
310 if (this.time > 7820 && this.time < 7900) |
|
311 System.out.println("T:" + this.time + " " + val[0] + " " + val[1] + " " + val[2]); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ |
|
312 this.time++; |
|
313 /* |
|
314 * dis.readByte(); dis.readByte(); dis.readByte(); dis.readByte(); |
|
315 */ |
|
316 return ps; |
|
317 } |
|
318 |
|
319 private int readVal(int neg,int len,DataInputStream dis) throws IOException |
|
320 { |
|
321 byte[] array = new byte[len]; |
|
322 dis.read(array); |
|
323 |
|
324 //System.out.println("array: "+array); |
|
325 |
|
326 if(debug) |
|
327 for(int k=0;k<array.length;k++) |
|
328 { |
|
329 if(this.time > 7820 && this.time < 7900) System.out.println(" "+Integer.toHexString(array[k])); //$NON-NLS-1$ |
|
330 } |
|
331 |
|
332 long total = 0; |
|
333 for(int i=0;i<len;i++) |
|
334 { |
|
335 int value = ((array[i] << 24) >>> 24) << (i*8); |
|
336 total |= value; |
|
337 } |
|
338 |
|
339 if(debug) if(this.time > 7820 && this.time < 7900) System.out.println("\n"+Long.toHexString(total)); //$NON-NLS-1$ |
|
340 |
|
341 if(debug) if(this.time > 7820 && this.time < 7900) System.out.println("T:"+this.time+" "+Long.toHexString(total)); //$NON-NLS-1$//$NON-NLS-2$ |
|
342 |
|
343 if(neg != 0) total = ~total; |
|
344 |
|
345 return (int)total; |
|
346 } |
|
347 |
|
348 private String[] parseValueTypes(List<Integer> counterTypes, List<Integer> counterL2Types){ |
|
349 String[] s = new String[counterTypes.size() * eventTypeTable.size() + (counterL2Types == null ? 0 : counterL2Types.size())]; |
|
350 int k = 0; |
|
351 for (int i = 0; i < eventTypeTable.size(); i++) { |
|
352 String eventType = eventTypeTable.get(i); |
|
353 for (Integer counterType : counterTypes) { |
|
354 s[k] = String.format(Messages.IpcTraceParser_20, eventType, convertCounterType(counterType)); |
|
355 k++; |
|
356 } |
|
357 } |
|
358 |
|
359 if (counterL2Types != null){ |
|
360 for (Integer l2Type : counterL2Types) { |
|
361 s[k] = convertL2EventType(l2Type); |
|
362 k++; |
|
363 } |
|
364 } |
|
365 return s; |
|
366 } |
|
367 |
|
368 private String convertL2EventType(Integer value) { |
|
369 String s = IpcTraceParser.l2EventTypeTable.get(value); |
|
370 if (s == null) { |
|
371 s = String.format(IPC_EVENT_NOT_RECOGNISED, value); |
|
372 } |
|
373 return s; |
|
374 } |
|
375 |
|
376 private String convertCounterType(Integer value) { |
|
377 String s = IpcTraceParser.counterTypeTable.get(value); |
|
378 if (s == null) { |
|
379 s = String.format(IPC_EVENT_NOT_RECOGNISED, value); |
|
380 } |
|
381 return s; |
|
382 } |
|
383 } |