1<!DOCTYPE html>
2<!--
3Copyright (c) 2012 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
9
10<script>
11'use strict';
12
13/**
14 * @fileoverview Parses i915 driver events in the Linux event trace format.
15 */
16tr.exportTo('tr.e.importer.linux_perf', function() {
17  var ColorScheme = tr.b.ColorScheme;
18  var Parser = tr.e.importer.linux_perf.Parser;
19
20  /**
21   * Parses linux i915 trace events.
22   * @constructor
23   */
24  function I915Parser(importer) {
25    Parser.call(this, importer);
26
27    importer.registerEventHandler('i915_gem_object_create',
28        I915Parser.prototype.gemObjectCreateEvent.bind(this));
29    importer.registerEventHandler('i915_gem_object_bind',
30        I915Parser.prototype.gemObjectBindEvent.bind(this));
31    importer.registerEventHandler('i915_gem_object_unbind',
32        I915Parser.prototype.gemObjectBindEvent.bind(this));
33    importer.registerEventHandler('i915_gem_object_change_domain',
34        I915Parser.prototype.gemObjectChangeDomainEvent.bind(this));
35    importer.registerEventHandler('i915_gem_object_pread',
36        I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));
37    importer.registerEventHandler('i915_gem_object_pwrite',
38        I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));
39    importer.registerEventHandler('i915_gem_object_fault',
40        I915Parser.prototype.gemObjectFaultEvent.bind(this));
41    importer.registerEventHandler('i915_gem_object_clflush',
42        // NB: reuse destroy handler
43        I915Parser.prototype.gemObjectDestroyEvent.bind(this));
44    importer.registerEventHandler('i915_gem_object_destroy',
45        I915Parser.prototype.gemObjectDestroyEvent.bind(this));
46    importer.registerEventHandler('i915_gem_ring_dispatch',
47        I915Parser.prototype.gemRingDispatchEvent.bind(this));
48    importer.registerEventHandler('i915_gem_ring_flush',
49        I915Parser.prototype.gemRingFlushEvent.bind(this));
50    importer.registerEventHandler('i915_gem_request',
51        I915Parser.prototype.gemRequestEvent.bind(this));
52    importer.registerEventHandler('i915_gem_request_add',
53        I915Parser.prototype.gemRequestEvent.bind(this));
54    importer.registerEventHandler('i915_gem_request_complete',
55        I915Parser.prototype.gemRequestEvent.bind(this));
56    importer.registerEventHandler('i915_gem_request_retire',
57        I915Parser.prototype.gemRequestEvent.bind(this));
58    importer.registerEventHandler('i915_gem_request_wait_begin',
59        I915Parser.prototype.gemRequestEvent.bind(this));
60    importer.registerEventHandler('i915_gem_request_wait_end',
61        I915Parser.prototype.gemRequestEvent.bind(this));
62    importer.registerEventHandler('i915_gem_ring_wait_begin',
63        I915Parser.prototype.gemRingWaitEvent.bind(this));
64    importer.registerEventHandler('i915_gem_ring_wait_end',
65        I915Parser.prototype.gemRingWaitEvent.bind(this));
66    importer.registerEventHandler('i915_reg_rw',
67        I915Parser.prototype.regRWEvent.bind(this));
68    importer.registerEventHandler('i915_flip_request',
69        I915Parser.prototype.flipEvent.bind(this));
70    importer.registerEventHandler('i915_flip_complete',
71        I915Parser.prototype.flipEvent.bind(this));
72    importer.registerEventHandler('intel_gpu_freq_change',
73        I915Parser.prototype.gpuFrequency.bind(this));
74  }
75
76  I915Parser.prototype = {
77    __proto__: Parser.prototype,
78
79    i915FlipOpenSlice: function(ts, obj, plane) {
80      // use i915_flip_obj_plane?
81      var kthread = this.importer.getOrCreatePseudoThread('i915_flip');
82      kthread.openSliceTS = ts;
83      kthread.openSlice = 'flip:' + obj + '/' + plane;
84    },
85
86    i915FlipCloseSlice: function(ts, args) {
87      var kthread = this.importer.getOrCreatePseudoThread('i915_flip');
88      if (kthread.openSlice) {
89        var slice = new tr.model.Slice('', kthread.openSlice,
90            ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
91            kthread.openSliceTS,
92            args,
93            ts - kthread.openSliceTS);
94
95        kthread.thread.sliceGroup.pushSlice(slice);
96      }
97      kthread.openSlice = undefined;
98    },
99
100    i915GemObjectSlice: function(ts, eventName, obj, args) {
101      var kthread = this.importer.getOrCreatePseudoThread('i915_gem');
102      kthread.openSlice = eventName + ':' + obj;
103      var slice = new tr.model.Slice('', kthread.openSlice,
104          ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
105          ts, args, 0);
106
107      kthread.thread.sliceGroup.pushSlice(slice);
108    },
109
110    i915GemRingSlice: function(ts, eventName, dev, ring, args) {
111      var kthread = this.importer.getOrCreatePseudoThread('i915_gem_ring');
112      kthread.openSlice = eventName + ':' + dev + '.' + ring;
113      var slice = new tr.model.Slice('', kthread.openSlice,
114          ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
115          ts, args, 0);
116
117      kthread.thread.sliceGroup.pushSlice(slice);
118    },
119
120    i915RegSlice: function(ts, eventName, reg, args) {
121      var kthread = this.importer.getOrCreatePseudoThread('i915_reg');
122      kthread.openSlice = eventName + ':' + reg;
123      var slice = new tr.model.Slice('', kthread.openSlice,
124          ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
125          ts, args, 0);
126
127      kthread.thread.sliceGroup.pushSlice(slice);
128    },
129
130    i915FreqChangeSlice: function(ts, eventName, args) {
131      var kthread = this.importer.getOrCreatePseudoThread('i915_gpu_freq');
132      kthread.openSlice = eventName;
133      var slice = new tr.model.Slice('', kthread.openSlice,
134          ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),
135          ts, args, 0);
136
137      kthread.thread.sliceGroup.pushSlice(slice);
138    },
139
140    /**
141     * Parses i915 driver events and sets up state in the importer.
142     */
143    gemObjectCreateEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
144      var event = /obj=(\w+), size=(\d+)/.exec(eventBase.details);
145      if (!event)
146        return false;
147
148      var obj = event[1];
149      var size = parseInt(event[2]);
150      this.i915GemObjectSlice(ts, eventName, obj,
151          {
152            obj: obj,
153            size: size
154          });
155      return true;
156    },
157
158    gemObjectBindEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
159      // TODO(sleffler) mappable
160      var event = /obj=(\w+), offset=(\w+), size=(\d+)/.exec(eventBase.details);
161      if (!event)
162        return false;
163
164      var obj = event[1];
165      var offset = event[2];
166      var size = parseInt(event[3]);
167      this.i915ObjectGemSlice(ts, eventName + ':' + obj,
168          {
169            obj: obj,
170            offset: offset,
171            size: size
172          });
173      return true;
174    },
175
176    gemObjectChangeDomainEvent: function(eventName, cpuNumber, pid, ts,
177                                         eventBase) {
178      var event = /obj=(\w+), read=(\w+=>\w+), write=(\w+=>\w+)/
179          .exec(eventBase.details);
180      if (!event)
181        return false;
182
183      var obj = event[1];
184      var read = event[2];
185      var write = event[3];
186      this.i915GemObjectSlice(ts, eventName, obj,
187          {
188            obj: obj,
189            read: read,
190            write: write
191          });
192      return true;
193    },
194
195    gemObjectPreadWriteEvent: function(eventName, cpuNumber, pid, ts,
196                                       eventBase) {
197      var event = /obj=(\w+), offset=(\d+), len=(\d+)/.exec(eventBase.details);
198      if (!event)
199        return false;
200
201      var obj = event[1];
202      var offset = parseInt(event[2]);
203      var len = parseInt(event[3]);
204      this.i915GemObjectSlice(ts, eventName, obj,
205          {
206            obj: obj,
207            offset: offset,
208            len: len
209          });
210      return true;
211    },
212
213    gemObjectFaultEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
214      // TODO(sleffler) writable
215      var event = /obj=(\w+), (\w+) index=(\d+)/.exec(eventBase.details);
216      if (!event)
217        return false;
218
219      var obj = event[1];
220      var type = event[2];
221      var index = parseInt(event[3]);
222      this.i915GemObjectSlice(ts, eventName, obj,
223          {
224            obj: obj,
225            type: type,
226            index: index
227          });
228      return true;
229    },
230
231    gemObjectDestroyEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
232      var event = /obj=(\w+)/.exec(eventBase.details);
233      if (!event)
234        return false;
235
236      var obj = event[1];
237      this.i915GemObjectSlice(ts, eventName, obj,
238          {
239            obj: obj
240          });
241      return true;
242    },
243
244    gemRingDispatchEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
245      var event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase.details);
246      if (!event)
247        return false;
248
249      var dev = parseInt(event[1]);
250      var ring = parseInt(event[2]);
251      var seqno = parseInt(event[3]);
252      this.i915GemRingSlice(ts, eventName, dev, ring,
253          {
254            dev: dev,
255            ring: ring,
256            seqno: seqno
257          });
258      return true;
259    },
260
261    gemRingFlushEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
262      var event = /dev=(\d+), ring=(\w+), invalidate=(\w+), flush=(\w+)/
263          .exec(eventBase.details);
264      if (!event)
265        return false;
266
267      var dev = parseInt(event[1]);
268      var ring = parseInt(event[2]);
269      var invalidate = event[3];
270      var flush = event[4];
271      this.i915GemRingSlice(ts, eventName, dev, ring,
272          {
273            dev: dev,
274            ring: ring,
275            invalidate: invalidate,
276            flush: flush
277          });
278      return true;
279    },
280
281    gemRequestEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
282      var event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase.details);
283      if (!event)
284        return false;
285
286      var dev = parseInt(event[1]);
287      var ring = parseInt(event[2]);
288      var seqno = parseInt(event[3]);
289      this.i915GemRingSlice(ts, eventName, dev, ring,
290          {
291            dev: dev,
292            ring: ring,
293            seqno: seqno
294          });
295      return true;
296    },
297
298    gemRingWaitEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
299      var event = /dev=(\d+), ring=(\d+)/.exec(eventBase.details);
300      if (!event)
301        return false;
302
303      var dev = parseInt(event[1]);
304      var ring = parseInt(event[2]);
305      this.i915GemRingSlice(ts, eventName, dev, ring,
306          {
307            dev: dev,
308            ring: ring
309          });
310      return true;
311    },
312
313    regRWEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
314      var event = /(\w+) reg=(\w+), len=(\d+), val=(\(\w+, \w+\))/
315          .exec(eventBase.details);
316      if (!event)
317        return false;
318
319      var rw = event[1];
320      var reg = event[2];
321      var len = event[3];
322      var data = event[3];
323      this.i915RegSlice(ts, rw, reg,
324          {
325            rw: rw,
326            reg: reg,
327            len: len,
328            data: data
329          });
330      return true;
331    },
332
333    flipEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
334      var event = /plane=(\d+), obj=(\w+)/.exec(eventBase.details);
335      if (!event)
336        return false;
337
338      var plane = parseInt(event[1]);
339      var obj = event[2];
340      if (eventName == 'i915_flip_request')
341        this.i915FlipOpenSlice(ts, obj, plane);
342      else
343        this.i915FlipCloseSlice(ts,
344            {
345              obj: obj,
346              plane: plane
347            });
348      return true;
349    },
350
351    gpuFrequency: function(eventName, cpuNumver, pid, ts, eventBase) {
352      var event = /new_freq=(\d+)/.exec(eventBase.details);
353      if (!event)
354        return false;
355      var freq = parseInt(event[1]);
356
357      this.i915FreqChangeSlice(ts, eventName, {
358            freq: freq
359          });
360      return true;
361    }
362  };
363
364  Parser.register(I915Parser);
365
366  return {
367    I915Parser: I915Parser
368  };
369});
370</script>
371
372