aboutsummaryrefslogtreecommitdiff
path: root/devlib/instrument/gem5power.py
diff options
context:
space:
mode:
Diffstat (limited to 'devlib/instrument/gem5power.py')
-rw-r--r--devlib/instrument/gem5power.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/devlib/instrument/gem5power.py b/devlib/instrument/gem5power.py
new file mode 100644
index 0000000..4b145d9
--- /dev/null
+++ b/devlib/instrument/gem5power.py
@@ -0,0 +1,81 @@
+# Copyright 2017 ARM Limited
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import division
+import csv
+import re
+
+from devlib.platform.gem5 import Gem5SimulationPlatform
+from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
+from devlib.exception import TargetError, HostError
+
+
+class Gem5PowerInstrument(Instrument):
+ '''
+ Instrument enabling power monitoring in gem5
+ '''
+
+ mode = CONTINUOUS
+ roi_label = 'power_instrument'
+ site_mapping = {'timestamp': 'sim_seconds'}
+
+ def __init__(self, target, power_sites):
+ '''
+ Parameter power_sites is a list of gem5 identifiers for power values.
+ One example of such a field:
+ system.cluster0.cores0.power_model.static_power
+ '''
+ if not isinstance(target.platform, Gem5SimulationPlatform):
+ raise TargetError('Gem5PowerInstrument requires a gem5 platform')
+ if not target.has('gem5stats'):
+ raise TargetError('Gem5StatsModule is not loaded')
+ super(Gem5PowerInstrument, self).__init__(target)
+
+ # power_sites is assumed to be a list later
+ if isinstance(power_sites, list):
+ self.power_sites = power_sites
+ else:
+ self.power_sites = [power_sites]
+ self.add_channel('timestamp', 'time')
+ for field in self.power_sites:
+ self.add_channel(field, 'power')
+ self.target.gem5stats.book_roi(self.roi_label)
+ self.sample_period_ns = 10000000
+ # Sample rate must remain unset as gem5 does not provide samples
+ # at regular intervals therefore the reported timestamp should be used.
+ self.sample_rate_hz = None
+ self.target.gem5stats.start_periodic_dump(0, self.sample_period_ns)
+ self._base_stats_dump = 0
+
+ def start(self):
+ self.target.gem5stats.roi_start(self.roi_label)
+
+ def stop(self):
+ self.target.gem5stats.roi_end(self.roi_label)
+
+ def get_data(self, outfile):
+ active_sites = [c.site for c in self.active_channels]
+ with open(outfile, 'wb') as wfh:
+ writer = csv.writer(wfh)
+ writer.writerow([c.label for c in self.active_channels]) # headers
+ sites_to_match = [self.site_mapping.get(s, s) for s in active_sites]
+ for rec, rois in self.target.gem5stats.match_iter(sites_to_match,
+ [self.roi_label], self._base_stats_dump):
+ writer.writerow([rec[s] for s in active_sites])
+ return MeasurementsCsv(outfile, self.active_channels, self.sample_rate_hz)
+
+ def reset(self, sites=None, kinds=None, channels=None):
+ super(Gem5PowerInstrument, self).reset(sites, kinds, channels)
+ self._base_stats_dump = self.target.gem5stats.next_dump_no()
+