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 Mali DDK/kernel events in the Linux event trace format.
15 */
16tr.exportTo('tr.e.importer.linux_perf', function() {
17
18  var ColorScheme = tr.b.ColorScheme;
19  var Parser = tr.e.importer.linux_perf.Parser;
20
21  /**
22   * Parses Mali DDK/kernel trace events.
23   * @constructor
24   */
25  function MaliParser(importer) {
26    Parser.call(this, importer);
27
28    // kernel DVFS events
29    importer.registerEventHandler('mali_dvfs_event',
30        MaliParser.prototype.dvfsEventEvent.bind(this));
31    importer.registerEventHandler('mali_dvfs_set_clock',
32        MaliParser.prototype.dvfsSetClockEvent.bind(this));
33    importer.registerEventHandler('mali_dvfs_set_voltage',
34        MaliParser.prototype.dvfsSetVoltageEvent.bind(this));
35
36    // kernel Mali hw counter events
37    this.addJMCounter('mali_hwc_MESSAGES_SENT', 'Messages Sent');
38    this.addJMCounter('mali_hwc_MESSAGES_RECEIVED', 'Messages Received');
39    this.addJMCycles('mali_hwc_GPU_ACTIVE', 'GPU Active');
40    this.addJMCycles('mali_hwc_IRQ_ACTIVE', 'IRQ Active');
41
42    for (var i = 0; i < 7; i++) {
43      var jobStr = 'JS' + i;
44      var jobHWCStr = 'mali_hwc_' + jobStr;
45      this.addJMCounter(jobHWCStr + '_JOBS', jobStr + ' Jobs');
46      this.addJMCounter(jobHWCStr + '_TASKS', jobStr + ' Tasks');
47      this.addJMCycles(jobHWCStr + '_ACTIVE', jobStr + ' Active');
48      this.addJMCycles(jobHWCStr + '_WAIT_READ', jobStr + ' Wait Read');
49      this.addJMCycles(jobHWCStr + '_WAIT_ISSUE', jobStr + ' Wait Issue');
50      this.addJMCycles(jobHWCStr + '_WAIT_DEPEND', jobStr + ' Wait Depend');
51      this.addJMCycles(jobHWCStr + '_WAIT_FINISH', jobStr + ' Wait Finish');
52    }
53
54    this.addTilerCounter('mali_hwc_TRIANGLES', 'Triangles');
55    this.addTilerCounter('mali_hwc_QUADS', 'Quads');
56    this.addTilerCounter('mali_hwc_POLYGONS', 'Polygons');
57    this.addTilerCounter('mali_hwc_POINTS', 'Points');
58    this.addTilerCounter('mali_hwc_LINES', 'Lines');
59    this.addTilerCounter('mali_hwc_VCACHE_HIT', 'VCache Hit');
60    this.addTilerCounter('mali_hwc_VCACHE_MISS', 'VCache Miss');
61    this.addTilerCounter('mali_hwc_FRONT_FACING', 'Front Facing');
62    this.addTilerCounter('mali_hwc_BACK_FACING', 'Back Facing');
63    this.addTilerCounter('mali_hwc_PRIM_VISIBLE', 'Prim Visible');
64    this.addTilerCounter('mali_hwc_PRIM_CULLED', 'Prim Culled');
65    this.addTilerCounter('mali_hwc_PRIM_CLIPPED', 'Prim Clipped');
66
67    this.addTilerCounter('mali_hwc_WRBUF_HIT', 'Wrbuf Hit');
68    this.addTilerCounter('mali_hwc_WRBUF_MISS', 'Wrbuf Miss');
69    this.addTilerCounter('mali_hwc_WRBUF_LINE', 'Wrbuf Line');
70    this.addTilerCounter('mali_hwc_WRBUF_PARTIAL', 'Wrbuf Partial');
71    this.addTilerCounter('mali_hwc_WRBUF_STALL', 'Wrbuf Stall');
72
73    this.addTilerCycles('mali_hwc_ACTIVE', 'Tiler Active');
74    this.addTilerCycles('mali_hwc_INDEX_WAIT', 'Index Wait');
75    this.addTilerCycles('mali_hwc_INDEX_RANGE_WAIT', 'Index Range Wait');
76    this.addTilerCycles('mali_hwc_VERTEX_WAIT', 'Vertex Wait');
77    this.addTilerCycles('mali_hwc_PCACHE_WAIT', 'Pcache Wait');
78    this.addTilerCycles('mali_hwc_WRBUF_WAIT', 'Wrbuf Wait');
79    this.addTilerCycles('mali_hwc_BUS_READ', 'Bus Read');
80    this.addTilerCycles('mali_hwc_BUS_WRITE', 'Bus Write');
81
82    this.addTilerCycles('mali_hwc_TILER_UTLB_STALL', 'Tiler UTLB Stall');
83    this.addTilerCycles('mali_hwc_TILER_UTLB_HIT', 'Tiler UTLB Hit');
84
85    this.addFragCycles('mali_hwc_FRAG_ACTIVE', 'Active');
86    /* NB: don't propagate spelling mistakes to labels */
87    this.addFragCounter('mali_hwc_FRAG_PRIMATIVES', 'Primitives');
88    this.addFragCounter('mali_hwc_FRAG_PRIMATIVES_DROPPED',
89        'Primitives Dropped');
90    this.addFragCycles('mali_hwc_FRAG_CYCLE_DESC', 'Descriptor Processing');
91    this.addFragCycles('mali_hwc_FRAG_CYCLES_PLR', 'PLR Processing??');
92    this.addFragCycles('mali_hwc_FRAG_CYCLES_VERT', 'Vertex Processing');
93    this.addFragCycles('mali_hwc_FRAG_CYCLES_TRISETUP', 'Triangle Setup');
94    this.addFragCycles('mali_hwc_FRAG_CYCLES_RAST', 'Rasterization???');
95    this.addFragCounter('mali_hwc_FRAG_THREADS', 'Threads');
96    this.addFragCounter('mali_hwc_FRAG_DUMMY_THREADS', 'Dummy Threads');
97    this.addFragCounter('mali_hwc_FRAG_QUADS_RAST', 'Quads Rast');
98    this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_TEST', 'Quads EZS Test');
99    this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_KILLED', 'Quads EZS Killed');
100    this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_TEST', 'Quads LZS Test');
101    this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_KILLED', 'Quads LZS Killed');
102    this.addFragCycles('mali_hwc_FRAG_CYCLE_NO_TILE', 'No Tiles');
103    this.addFragCounter('mali_hwc_FRAG_NUM_TILES', 'Tiles');
104    this.addFragCounter('mali_hwc_FRAG_TRANS_ELIM', 'Transactions Eliminated');
105
106    this.addComputeCycles('mali_hwc_COMPUTE_ACTIVE', 'Active');
107    this.addComputeCounter('mali_hwc_COMPUTE_TASKS', 'Tasks');
108    this.addComputeCounter('mali_hwc_COMPUTE_THREADS', 'Threads Started');
109    this.addComputeCycles('mali_hwc_COMPUTE_CYCLES_DESC',
110        'Waiting for Descriptors');
111
112    this.addTripipeCycles('mali_hwc_TRIPIPE_ACTIVE', 'Active');
113
114    this.addArithCounter('mali_hwc_ARITH_WORDS', 'Instructions (/Pipes)');
115    this.addArithCycles('mali_hwc_ARITH_CYCLES_REG',
116        'Reg scheduling stalls (/Pipes)');
117    this.addArithCycles('mali_hwc_ARITH_CYCLES_L0',
118        'L0 cache miss stalls (/Pipes)');
119    this.addArithCounter('mali_hwc_ARITH_FRAG_DEPEND',
120        'Frag dep check failures (/Pipes)');
121
122    this.addLSCounter('mali_hwc_LS_WORDS', 'Instruction Words Completed');
123    this.addLSCounter('mali_hwc_LS_ISSUES', 'Full Pipeline Issues');
124    this.addLSCounter('mali_hwc_LS_RESTARTS', 'Restarts (unpairable insts)');
125    this.addLSCounter('mali_hwc_LS_REISSUES_MISS',
126        'Pipeline reissue (cache miss/uTLB)');
127    this.addLSCounter('mali_hwc_LS_REISSUES_VD',
128        'Pipeline reissue (varying data)');
129    /* TODO(sleffler) fix kernel event typo */
130    this.addLSCounter('mali_hwc_LS_REISSUE_ATTRIB_MISS',
131        'Pipeline reissue (attribute cache miss)');
132    this.addLSCounter('mali_hwc_LS_REISSUE_NO_WB', 'Writeback not used');
133
134    this.addTexCounter('mali_hwc_TEX_WORDS', 'Words');
135    this.addTexCounter('mali_hwc_TEX_BUBBLES', 'Bubbles');
136    this.addTexCounter('mali_hwc_TEX_WORDS_L0', 'Words L0');
137    this.addTexCounter('mali_hwc_TEX_WORDS_DESC', 'Words Desc');
138    this.addTexCounter('mali_hwc_TEX_THREADS', 'Threads');
139    this.addTexCounter('mali_hwc_TEX_RECIRC_FMISS', 'Recirc due to Full Miss');
140    this.addTexCounter('mali_hwc_TEX_RECIRC_DESC', 'Recirc due to Desc Miss');
141    this.addTexCounter('mali_hwc_TEX_RECIRC_MULTI', 'Recirc due to Multipass');
142    this.addTexCounter('mali_hwc_TEX_RECIRC_PMISS',
143        'Recirc due to Partial Cache Miss');
144    this.addTexCounter('mali_hwc_TEX_RECIRC_CONF',
145        'Recirc due to Cache Conflict');
146
147    this.addLSCCounter('mali_hwc_LSC_READ_HITS', 'Read Hits');
148    this.addLSCCounter('mali_hwc_LSC_READ_MISSES', 'Read Misses');
149    this.addLSCCounter('mali_hwc_LSC_WRITE_HITS', 'Write Hits');
150    this.addLSCCounter('mali_hwc_LSC_WRITE_MISSES', 'Write Misses');
151    this.addLSCCounter('mali_hwc_LSC_ATOMIC_HITS', 'Atomic Hits');
152    this.addLSCCounter('mali_hwc_LSC_ATOMIC_MISSES', 'Atomic Misses');
153    this.addLSCCounter('mali_hwc_LSC_LINE_FETCHES', 'Line Fetches');
154    this.addLSCCounter('mali_hwc_LSC_DIRTY_LINE', 'Dirty Lines');
155    this.addLSCCounter('mali_hwc_LSC_SNOOPS', 'Snoops');
156
157    this.addAXICounter('mali_hwc_AXI_TLB_STALL', 'Address channel stall');
158    this.addAXICounter('mali_hwc_AXI_TLB_MISS', 'Cache Miss');
159    this.addAXICounter('mali_hwc_AXI_TLB_TRANSACTION', 'Transactions');
160    this.addAXICounter('mali_hwc_LS_TLB_MISS', 'LS Cache Miss');
161    this.addAXICounter('mali_hwc_LS_TLB_HIT', 'LS Cache Hit');
162    this.addAXICounter('mali_hwc_AXI_BEATS_READ', 'Read Beats');
163    this.addAXICounter('mali_hwc_AXI_BEATS_WRITE', 'Write Beats');
164
165    this.addMMUCounter('mali_hwc_MMU_TABLE_WALK', 'Page Table Walks');
166    this.addMMUCounter('mali_hwc_MMU_REPLAY_MISS',
167        'Cache Miss from Replay Buffer');
168    this.addMMUCounter('mali_hwc_MMU_REPLAY_FULL', 'Replay Buffer Full');
169    this.addMMUCounter('mali_hwc_MMU_NEW_MISS', 'Cache Miss on New Request');
170    this.addMMUCounter('mali_hwc_MMU_HIT', 'Cache Hit');
171
172    this.addMMUCycles('mali_hwc_UTLB_STALL', 'UTLB Stalled');
173    this.addMMUCycles('mali_hwc_UTLB_REPLAY_MISS', 'UTLB Replay Miss');
174    this.addMMUCycles('mali_hwc_UTLB_REPLAY_FULL', 'UTLB Replay Full');
175    this.addMMUCycles('mali_hwc_UTLB_NEW_MISS', 'UTLB New Miss');
176    this.addMMUCycles('mali_hwc_UTLB_HIT', 'UTLB Hit');
177
178    this.addL2Counter('mali_hwc_L2_READ_BEATS', 'Read Beats');
179    this.addL2Counter('mali_hwc_L2_WRITE_BEATS', 'Write Beats');
180    this.addL2Counter('mali_hwc_L2_ANY_LOOKUP', 'Any Lookup');
181    this.addL2Counter('mali_hwc_L2_READ_LOOKUP', 'Read Lookup');
182    this.addL2Counter('mali_hwc_L2_SREAD_LOOKUP', 'Shareable Read Lookup');
183    this.addL2Counter('mali_hwc_L2_READ_REPLAY', 'Read Replayed');
184    this.addL2Counter('mali_hwc_L2_READ_SNOOP', 'Read Snoop');
185    this.addL2Counter('mali_hwc_L2_READ_HIT', 'Read Cache Hit');
186    this.addL2Counter('mali_hwc_L2_CLEAN_MISS', 'CleanUnique Miss');
187    this.addL2Counter('mali_hwc_L2_WRITE_LOOKUP', 'Write Lookup');
188    this.addL2Counter('mali_hwc_L2_SWRITE_LOOKUP', 'Shareable Write Lookup');
189    this.addL2Counter('mali_hwc_L2_WRITE_REPLAY', 'Write Replayed');
190    this.addL2Counter('mali_hwc_L2_WRITE_SNOOP', 'Write Snoop');
191    this.addL2Counter('mali_hwc_L2_WRITE_HIT', 'Write Cache Hit');
192    this.addL2Counter('mali_hwc_L2_EXT_READ_FULL', 'ExtRD with BIU Full');
193    this.addL2Counter('mali_hwc_L2_EXT_READ_HALF', 'ExtRD with BIU >1/2 Full');
194    this.addL2Counter('mali_hwc_L2_EXT_WRITE_FULL', 'ExtWR with BIU Full');
195    this.addL2Counter('mali_hwc_L2_EXT_WRITE_HALF', 'ExtWR with BIU >1/2 Full');
196
197    this.addL2Counter('mali_hwc_L2_EXT_READ', 'External Read (ExtRD)');
198    this.addL2Counter('mali_hwc_L2_EXT_READ_LINE', 'ExtRD (linefill)');
199    this.addL2Counter('mali_hwc_L2_EXT_WRITE', 'External Write (ExtWR)');
200    this.addL2Counter('mali_hwc_L2_EXT_WRITE_LINE', 'ExtWR (linefill)');
201    this.addL2Counter('mali_hwc_L2_EXT_WRITE_SMALL', 'ExtWR (burst size <64B)');
202    this.addL2Counter('mali_hwc_L2_EXT_BARRIER', 'External Barrier');
203    this.addL2Counter('mali_hwc_L2_EXT_AR_STALL', 'Address Read stalls');
204    this.addL2Counter('mali_hwc_L2_EXT_R_BUF_FULL',
205        'Response Buffer full stalls');
206    this.addL2Counter('mali_hwc_L2_EXT_RD_BUF_FULL',
207        'Read Data Buffer full stalls');
208    this.addL2Counter('mali_hwc_L2_EXT_R_RAW', 'RAW hazard stalls');
209    this.addL2Counter('mali_hwc_L2_EXT_W_STALL', 'Write Data stalls');
210    this.addL2Counter('mali_hwc_L2_EXT_W_BUF_FULL', 'Write Data Buffer full');
211    this.addL2Counter('mali_hwc_L2_EXT_R_W_HAZARD', 'WAW or WAR hazard stalls');
212    this.addL2Counter('mali_hwc_L2_TAG_HAZARD', 'Tag hazard replays');
213    this.addL2Cycles('mali_hwc_L2_SNOOP_FULL', 'Snoop buffer full');
214    this.addL2Cycles('mali_hwc_L2_REPLAY_FULL', 'Replay buffer full');
215
216    // DDK events (from X server)
217    importer.registerEventHandler('tracing_mark_write:mali_driver',
218        MaliParser.prototype.maliDDKEvent.bind(this));
219
220    this.model_ = importer.model_;
221  }
222
223  MaliParser.prototype = {
224    __proto__: Parser.prototype,
225
226    maliDDKOpenSlice: function(pid, tid, ts, func, blockinfo) {
227      var thread = this.importer.model_.getOrCreateProcess(pid)
228        .getOrCreateThread(tid);
229      var funcArgs = /^([\w\d_]*)(?:\(\))?:?\s*(.*)$/.exec(func);
230      thread.sliceGroup.beginSlice('gpu-driver', funcArgs[1], ts,
231          { 'args': funcArgs[2],
232            'blockinfo': blockinfo });
233    },
234
235    maliDDKCloseSlice: function(pid, tid, ts, args, blockinfo) {
236      var thread = this.importer.model_.getOrCreateProcess(pid)
237        .getOrCreateThread(tid);
238      if (!thread.sliceGroup.openSliceCount) {
239        // Discard unmatched ends.
240        return;
241      }
242      thread.sliceGroup.endSlice(ts);
243    },
244
245    /**
246     * Deduce the format of Mali perf events.
247     *
248     * @return {RegExp} the regular expression for parsing data when the format
249     * is recognized; otherwise null.
250     */
251    autoDetectLineRE: function(line) {
252      // Matches Mali perf events with thread info
253      var lineREWithThread =
254          /^\s*\(([\w\-]*)\)\s*(\w+):\s*([\w\\\/\.\-]*@\d*):?\s*(.*)$/;
255      if (lineREWithThread.test(line))
256        return lineREWithThread;
257
258      // Matches old-style Mali perf events
259      var lineRENoThread = /^s*()(\w+):\s*([\w\\\/.\-]*):?\s*(.*)$/;
260      if (lineRENoThread.test(line))
261        return lineRENoThread;
262      return null;
263    },
264
265    lineRE: null,
266
267    /**
268     * Parses maliDDK events and sets up state in the importer.
269     * events will come in pairs with a cros_trace_print_enter
270     * like this (line broken here for formatting):
271     *
272     * tracing_mark_write: mali_driver: (mali-012345) cros_trace_print_enter: \
273     *   gles/src/texture/mali_gles_texture_slave.c@1505: gles2_texturep_upload
274     *
275     * and a cros_trace_print_exit like this:
276     *
277     * tracing_mark_write: mali_driver: (mali-012345) cros_trace_print_exit: \
278     *   gles/src/texture/mali_gles_texture_slave.c@1505:
279     */
280    maliDDKEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
281      if (this.lineRE == null) {
282        this.lineRE = this.autoDetectLineRE(eventBase.details);
283        if (this.lineRE == null)
284          return false;
285      }
286      var maliEvent = this.lineRE.exec(eventBase.details);
287      // Old-style Mali perf events have no thread id, so make one.
288      var tid = (maliEvent[1] === '' ? 'mali' : maliEvent[1]);
289      switch (maliEvent[2]) {
290        case 'cros_trace_print_enter':
291          this.maliDDKOpenSlice(pid, tid, ts, maliEvent[4],
292              maliEvent[3]);
293          break;
294        case 'cros_trace_print_exit':
295          this.maliDDKCloseSlice(pid, tid, ts, [], maliEvent[3]);
296      }
297      return true;
298    },
299
300    /*
301     * Kernel event support.
302     */
303
304    dvfsSample: function(counterName, seriesName, ts, s) {
305      var value = parseInt(s);
306      var counter = this.model_.kernel.
307          getOrCreateCounter('DVFS', counterName);
308      if (counter.numSeries === 0) {
309        counter.addSeries(new tr.model.CounterSeries(seriesName,
310            ColorScheme.getColorIdForGeneralPurposeString(counter.name)));
311      }
312      counter.series.forEach(function(series) {
313        series.addCounterSample(ts, value);
314      });
315    },
316
317    dvfsEventEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
318      var event = /utilization=(\d+)/.exec(eventBase.details);
319      if (!event)
320        return false;
321
322      this.dvfsSample('DVFS Utilization', 'utilization', ts, event[1]);
323      return true;
324    },
325
326    dvfsSetClockEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
327      var event = /frequency=(\d+)/.exec(eventBase.details);
328      if (!event)
329        return false;
330
331      this.dvfsSample('DVFS Frequency', 'frequency', ts, event[1]);
332      return true;
333    },
334
335    dvfsSetVoltageEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
336      var event = /voltage=(\d+)/.exec(eventBase.details);
337      if (!event)
338        return false;
339
340      this.dvfsSample('DVFS Voltage', 'voltage', ts, event[1]);
341      return true;
342    },
343
344    hwcSample: function(cat, counterName, seriesName, ts, eventBase) {
345      var event = /val=(\d+)/.exec(eventBase.details);
346      if (!event)
347        return false;
348      var value = parseInt(event[1]);
349
350      var counter = this.model_.kernel.
351          getOrCreateCounter(cat, counterName);
352      if (counter.numSeries === 0) {
353        counter.addSeries(new tr.model.CounterSeries(seriesName,
354            ColorScheme.getColorIdForGeneralPurposeString(counter.name)));
355      }
356      counter.series.forEach(function(series) {
357        series.addCounterSample(ts, value);
358      });
359      return true;
360    },
361
362    /*
363     * Job Manager block counters.
364     */
365    jmSample: function(ctrName, seriesName, ts, eventBase) {
366      return this.hwcSample('mali:jm', 'JM: ' + ctrName, seriesName, ts,
367          eventBase);
368    },
369    addJMCounter: function(hwcEventName, hwcTitle) {
370      function handler(eventName, cpuNumber, pid, ts, eventBase) {
371        return this.jmSample(hwcTitle, 'count', ts, eventBase);
372      }
373      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
374    },
375    addJMCycles: function(hwcEventName, hwcTitle) {
376      function handler(eventName, cpuNumber, pid, ts, eventBase) {
377        return this.jmSample(hwcTitle, 'cycles', ts, eventBase);
378      }
379      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
380    },
381
382    /*
383     * Tiler block counters.
384     */
385    tilerSample: function(ctrName, seriesName, ts, eventBase) {
386      return this.hwcSample('mali:tiler', 'Tiler: ' + ctrName, seriesName,
387          ts, eventBase);
388    },
389    addTilerCounter: function(hwcEventName, hwcTitle) {
390      function handler(eventName, cpuNumber, pid, ts, eventBase) {
391        return this.tilerSample(hwcTitle, 'count', ts, eventBase);
392      }
393      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
394    },
395    addTilerCycles: function(hwcEventName, hwcTitle) {
396      function handler(eventName, cpuNumber, pid, ts, eventBase) {
397        return this.tilerSample(hwcTitle, 'cycles', ts, eventBase);
398      }
399      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
400    },
401
402    /*
403     * Fragment counters.
404     */
405    fragSample: function(ctrName, seriesName, ts, eventBase) {
406      return this.hwcSample('mali:fragment', 'Fragment: ' + ctrName,
407          seriesName, ts, eventBase);
408    },
409    addFragCounter: function(hwcEventName, hwcTitle) {
410      function handler(eventName, cpuNumber, pid, ts, eventBase) {
411        return this.fragSample(hwcTitle, 'count', ts, eventBase);
412      }
413      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
414    },
415    addFragCycles: function(hwcEventName, hwcTitle) {
416      function handler(eventName, cpuNumber, pid, ts, eventBase) {
417        return this.fragSample(hwcTitle, 'cycles', ts, eventBase);
418      }
419      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
420    },
421
422    /*
423     * Compute counters.
424     */
425    computeSample: function(ctrName, seriesName, ts, eventBase) {
426      return this.hwcSample('mali:compute', 'Compute: ' + ctrName,
427          seriesName, ts, eventBase);
428    },
429    addComputeCounter: function(hwcEventName, hwcTitle) {
430      function handler(eventName, cpuNumber, pid, ts, eventBase) {
431        return this.computeSample(hwcTitle, 'count', ts, eventBase);
432      }
433      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
434    },
435    addComputeCycles: function(hwcEventName, hwcTitle) {
436      function handler(eventName, cpuNumber, pid, ts, eventBase) {
437        return this.computeSample(hwcTitle, 'cycles', ts, eventBase);
438      }
439      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
440    },
441
442    /*
443     * Tripipe counters.
444     */
445    addTripipeCycles: function(hwcEventName, hwcTitle) {
446      function handler(eventName, cpuNumber, pid, ts, eventBase) {
447        return this.hwcSample('mali:shader', 'Tripipe: ' + hwcTitle, 'cycles',
448            ts, eventBase);
449      }
450      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
451    },
452
453    /*
454     * Arith counters.
455     */
456    arithSample: function(ctrName, seriesName, ts, eventBase) {
457      return this.hwcSample('mali:arith', 'Arith: ' + ctrName, seriesName, ts,
458          eventBase);
459    },
460    addArithCounter: function(hwcEventName, hwcTitle) {
461      function handler(eventName, cpuNumber, pid, ts, eventBase) {
462        return this.arithSample(hwcTitle, 'count', ts, eventBase);
463      }
464      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
465    },
466    addArithCycles: function(hwcEventName, hwcTitle) {
467      function handler(eventName, cpuNumber, pid, ts, eventBase) {
468        return this.arithSample(hwcTitle, 'cycles', ts, eventBase);
469      }
470      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
471    },
472
473    /*
474     * Load/Store counters.
475     */
476    addLSCounter: function(hwcEventName, hwcTitle) {
477      function handler(eventName, cpuNumber, pid, ts, eventBase) {
478        return this.hwcSample('mali:ls', 'LS: ' + hwcTitle, 'count', ts,
479            eventBase);
480      }
481      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
482    },
483
484    /*
485     * Texture counters.
486     */
487    textureSample: function(ctrName, seriesName, ts, eventBase) {
488      return this.hwcSample('mali:texture', 'Texture: ' + ctrName,
489          seriesName, ts, eventBase);
490    },
491    addTexCounter: function(hwcEventName, hwcTitle) {
492      function handler(eventName, cpuNumber, pid, ts, eventBase) {
493        return this.textureSample(hwcTitle, 'count', ts, eventBase);
494      }
495      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
496    },
497
498    /*
499     * LSC counters.
500     */
501    addLSCCounter: function(hwcEventName, hwcTitle) {
502      function handler(eventName, cpuNumber, pid, ts, eventBase) {
503        return this.hwcSample('mali:lsc', 'LSC: ' + hwcTitle, 'count', ts,
504            eventBase);
505      }
506      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
507    },
508
509    /*
510     * TLB counters.
511     */
512    addAXICounter: function(hwcEventName, hwcTitle) {
513      function handler(eventName, cpuNumber, pid, ts, eventBase) {
514        return this.hwcSample('mali:axi', 'AXI: ' + hwcTitle, 'count', ts,
515            eventBase);
516      }
517      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
518    },
519
520    /*
521     * MMU counters.
522     */
523    mmuSample: function(ctrName, seriesName, ts, eventBase) {
524      return this.hwcSample('mali:mmu', 'MMU: ' + ctrName, seriesName, ts,
525          eventBase);
526    },
527    addMMUCounter: function(hwcEventName, hwcTitle) {
528      function handler(eventName, cpuNumber, pid, ts, eventBase) {
529        return this.mmuSample(hwcTitle, 'count', ts, eventBase);
530      }
531      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
532    },
533    addMMUCycles: function(hwcEventName, hwcTitle) {
534      function handler(eventName, cpuNumber, pid, ts, eventBase) {
535        return this.mmuSample(hwcTitle, 'cycles', ts, eventBase);
536      }
537      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
538    },
539
540    /*
541     * L2 counters.
542     */
543    l2Sample: function(ctrName, seriesName, ts, eventBase) {
544      return this.hwcSample('mali:l2', 'L2: ' + ctrName, seriesName, ts,
545          eventBase);
546    },
547    addL2Counter: function(hwcEventName, hwcTitle) {
548      function handler(eventName, cpuNumber, pid, ts, eventBase) {
549        return this.l2Sample(hwcTitle, 'count', ts, eventBase);
550      }
551      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
552    },
553    addL2Cycles: function(hwcEventName, hwcTitle) {
554      function handler(eventName, cpuNumber, pid, ts, eventBase) {
555        return this.l2Sample(hwcTitle, 'cycles', ts, eventBase);
556      }
557      this.importer.registerEventHandler(hwcEventName, handler.bind(this));
558    }
559  };
560
561  Parser.register(MaliParser);
562
563  return {
564    MaliParser: MaliParser
565  };
566});
567</script>
568
569