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<link rel="import" href="/tracing/model/counter_series.html">
10
11<script>
12'use strict';
13
14/**
15 * @fileoverview Parses power events in the Linux event trace format.
16 */
17tr.exportTo('tr.e.importer.linux_perf', function() {
18
19  var ColorScheme = tr.b.ColorScheme;
20  var Parser = tr.e.importer.linux_perf.Parser;
21
22  /**
23   * Parses linux power trace events.
24   * @constructor
25   */
26  function PowerParser(importer) {
27    Parser.call(this, importer);
28
29    // NB: old-style power events, deprecated
30    importer.registerEventHandler('power_start',
31        PowerParser.prototype.powerStartEvent.bind(this));
32    importer.registerEventHandler('power_frequency',
33        PowerParser.prototype.powerFrequencyEvent.bind(this));
34
35    importer.registerEventHandler('cpu_frequency',
36        PowerParser.prototype.cpuFrequencyEvent.bind(this));
37    importer.registerEventHandler('cpu_frequency_limits',
38        PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));
39    importer.registerEventHandler('cpu_idle',
40        PowerParser.prototype.cpuIdleEvent.bind(this));
41  }
42
43  PowerParser.prototype = {
44    __proto__: Parser.prototype,
45
46    cpuStateSlice: function(ts, targetCpuNumber, eventType, cpuState) {
47      var targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
48      var powerCounter;
49      if (eventType != '1') {
50        this.importer.model.importWarning({
51          type: 'parse_error',
52          message: 'Don\'t understand power_start events of ' +
53              'type ' + eventType
54        });
55        return;
56      }
57      powerCounter = targetCpu.getOrCreateCounter('', 'C-State');
58      if (powerCounter.numSeries === 0) {
59        powerCounter.addSeries(new tr.model.CounterSeries('state',
60            ColorScheme.getColorIdForGeneralPurposeString(
61                powerCounter.name + '.' + 'state')));
62      }
63      powerCounter.series.forEach(function(series) {
64        series.addCounterSample(ts, cpuState);
65      });
66    },
67
68    cpuIdleSlice: function(ts, targetCpuNumber, cpuState) {
69      var targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
70      var powerCounter = targetCpu.getOrCreateCounter('', 'C-State');
71      if (powerCounter.numSeries === 0) {
72        powerCounter.addSeries(new tr.model.CounterSeries('state',
73            ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name)));
74      }
75      // NB: 4294967295/-1 means an exit from the current state
76      var val = (cpuState != 4294967295 ? cpuState + 1 : 0);
77      powerCounter.series.forEach(function(series) {
78        series.addCounterSample(ts, val);
79      });
80    },
81
82    cpuFrequencySlice: function(ts, targetCpuNumber, powerState) {
83      var targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
84      var powerCounter =
85          targetCpu.getOrCreateCounter('', 'Clock Frequency');
86      if (powerCounter.numSeries === 0) {
87        powerCounter.addSeries(new tr.model.CounterSeries('state',
88            ColorScheme.getColorIdForGeneralPurposeString(
89                powerCounter.name + '.' + 'state')));
90      }
91      powerCounter.series.forEach(function(series) {
92        series.addCounterSample(ts, powerState);
93      });
94    },
95
96    cpuFrequencyLimitsSlice: function(ts, targetCpuNumber, minFreq, maxFreq) {
97      var targetCpu = this.importer.getOrCreateCpu(targetCpuNumber);
98      var powerCounter =
99          targetCpu.getOrCreateCounter('', 'Clock Frequency Limits');
100      if (powerCounter.numSeries === 0) {
101        powerCounter.addSeries(new tr.model.CounterSeries('Min Frequency',
102            ColorScheme.getColorIdForGeneralPurposeString(
103                powerCounter.name + '.' + 'Min Frequency')));
104        powerCounter.addSeries(new tr.model.CounterSeries('Max Frequency',
105            ColorScheme.getColorIdForGeneralPurposeString(
106                powerCounter.name + '.' + 'Max Frequency')));
107      }
108      powerCounter.series.forEach(function(series) {
109        if (series.name == 'Min Frequency')
110          series.addCounterSample(ts, minFreq);
111        if (series.name == 'Max Frequency')
112          series.addCounterSample(ts, maxFreq);
113      });
114    },
115
116    /**
117     * Parses power events and sets up state in the importer.
118     */
119    powerStartEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
120      var event = /type=(\d+) state=(\d) cpu_id=(\d+)/.exec(eventBase.details);
121      if (!event)
122        return false;
123
124      var targetCpuNumber = parseInt(event[3]);
125      var cpuState = parseInt(event[2]);
126      this.cpuStateSlice(ts, targetCpuNumber, event[1], cpuState);
127      return true;
128    },
129
130    powerFrequencyEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
131      var event = /type=(\d+) state=(\d+) cpu_id=(\d+)/
132          .exec(eventBase.details);
133      if (!event)
134        return false;
135
136      var targetCpuNumber = parseInt(event[3]);
137      var powerState = parseInt(event[2]);
138      this.cpuFrequencySlice(ts, targetCpuNumber, powerState);
139      return true;
140    },
141
142    cpuFrequencyEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
143      var event = /state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);
144      if (!event)
145        return false;
146
147      var targetCpuNumber = parseInt(event[2]);
148      var powerState = parseInt(event[1]);
149      this.cpuFrequencySlice(ts, targetCpuNumber, powerState);
150      return true;
151    },
152
153    cpuFrequencyLimitsEvent: function(eventName, cpu, pid, ts, eventBase) {
154      var event = /min=(\d+) max=(\d+) cpu_id=(\d+)/.exec(eventBase.details);
155      if (!event)
156        return false;
157
158      var targetCpuNumber = parseInt(event[3]);
159      var minFreq = parseInt(event[1]);
160      var maxFreq = parseInt(event[2]);
161      this.cpuFrequencyLimitsSlice(ts, targetCpuNumber, minFreq, maxFreq);
162      return true;
163    },
164
165    cpuIdleEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
166      var event = /state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);
167      if (!event)
168        return false;
169
170      var targetCpuNumber = parseInt(event[2]);
171      var cpuState = parseInt(event[1]);
172      this.cpuIdleSlice(ts, targetCpuNumber, cpuState);
173      return true;
174    }
175  };
176
177  Parser.register(PowerParser);
178
179  return {
180    PowerParser: PowerParser
181  };
182});
183</script>
184