diff options
Diffstat (limited to 'devlib/instrument/gem5power.py')
-rw-r--r-- | devlib/instrument/gem5power.py | 81 |
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() + |