/
gem5power.py
78 lines (67 loc) · 3.19 KB
/
gem5power.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# Copyright 2017-2018 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
from devlib.platform.gem5 import Gem5SimulationPlatform
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
from devlib.exception import TargetStableError
from devlib.utils.csvutil import csvwriter
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 TargetStableError('Gem5PowerInstrument requires a gem5 platform')
if not target.has('gem5stats'):
raise TargetStableError('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 csvwriter(outfile) as writer:
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, _ in self.target.gem5stats.match_iter(sites_to_match,
[self.roi_label], self._base_stats_dump):
writer.writerow([rec[s] for s in sites_to_match])
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()