From e1b6f9bd0bd7f94d0ed0ca333de8b81a46d4ba6c Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 25 Apr 2017 13:21:34 +0100 Subject: [PATCH 1/3] energy/hwmon: Use 'site' instead of 'label' The current code string-manipulates the 'label' attribute of channel objects to extract the site name. Instead just use the 'site' field. Also rename the 'label' variables to 'site' for accuracy. --- libs/utils/energy.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/libs/utils/energy.py b/libs/utils/energy.py index 37d5d29e2..561e5ab89 100644 --- a/libs/utils/energy.py +++ b/libs/utils/energy.py @@ -162,22 +162,20 @@ class HWMon(EnergyMeter): return None samples = self._hwmon.take_measurement() for s in samples: - label = s.channel.label\ - .replace('_energy', '')\ - .replace(" ", "_") + site = s.channel.site value = s.value - if label not in self.readings: - self.readings[label] = { + if site not in self.readings: + self.readings[site] = { 'last' : value, 'delta' : 0, 'total' : 0 } continue - self.readings[label]['delta'] = value - self.readings[label]['last'] - self.readings[label]['last'] = value - self.readings[label]['total'] += self.readings[label]['delta'] + self.readings[site]['delta'] = value - self.readings[site]['last'] + self.readings[site]['last'] = value + self.readings[site]['total'] += self.readings[site]['delta'] self._log.debug('SAMPLE: %s', self.readings) return self.readings @@ -186,9 +184,9 @@ class HWMon(EnergyMeter): if self._hwmon is None: return self.sample() - for label in self.readings: - self.readings[label]['delta'] = 0 - self.readings[label]['total'] = 0 + for site in self.readings: + self.readings[site]['delta'] = 0 + self.readings[site]['total'] = 0 self._log.debug('RESET: %s', self.readings) def report(self, out_dir, out_file='energy.json'): @@ -198,14 +196,13 @@ class HWMon(EnergyMeter): nrg = self.sample() # Reformat data for output generation clusters_nrg = {} - for channel in self._channels: - label = self._channels[channel] - if label not in nrg: + for channel, site in self._channels.iteritems(): + if site not in nrg: raise RuntimeError('hwmon channel "{}" not available. ' 'Selected channels: {}'.format( channel, nrg.keys())) - nrg_total = nrg[label]['total'] - self._log.debug('Energy [%16s]: %.6f', label, nrg_total) + nrg_total = nrg[site]['total'] + self._log.debug('Energy [%16s]: %.6f', site, nrg_total) clusters_nrg[channel] = nrg_total # Dump data as JSON file -- GitLab From 9c4950d634fd5680b7980ba8b4b7a5d3565ade4b Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Wed, 26 Apr 2017 12:13:26 +0100 Subject: [PATCH 2/3] energy/hwmon: Simplify channel/site/kind configuration - The only kind of measurement we support is energy, so hard-code that and remove the 'kinds' field from the conf['conf'] entry. - Remove the 'sites' field from the conf['conf'] entry, instead just use the values of the channel_map. The channel_map values are already required to be subset of conf['conf']['sites'], and sites not listed in the channel_map are not returned in output. --- libs/utils/energy.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/libs/utils/energy.py b/libs/utils/energy.py index 561e5ab89..8c289c0db 100644 --- a/libs/utils/energy.py +++ b/libs/utils/energy.py @@ -37,10 +37,6 @@ DEFAULT_ENERGY_METER = { # ARM TC2: by default use HWMON 'tc2' : { 'instrument' : 'hwmon', - 'conf' : { - 'sites' : [ 'A7 Jcore', 'A15 Jcore' ], - 'kinds' : [ 'energy'] - }, 'channel_map' : { 'LITTLE' : 'A7 Jcore', 'big' : 'A15 Jcore', @@ -50,10 +46,6 @@ DEFAULT_ENERGY_METER = { # ARM Juno: by default use HWMON 'juno' : { 'instrument' : 'hwmon', - 'conf' : { - 'sites' : [ 'BOARDLITTLE', 'BOARDBIG' ], - 'kinds' : [ 'energy' ] - }, # if the channels do not contain a core name we can match to the # little/big cores on the board, use a channel_map section to # indicate which channel is which @@ -142,20 +134,21 @@ class HWMon(EnergyMeter): self._log.info('Scanning for HWMON channels, may take some time...') self._hwmon = devlib.HwmonInstrument(self._target) + # record the HWMon channels + self._channels = conf.get('channel_map', { + 'LITTLE': self._target.little_core.upper(), + 'big': self._target.big_core.upper() + }) + # Configure channels for energy measurements - self._log.debug('Enabling channels %s', conf['conf']) - self._hwmon.reset(**conf['conf']) + self._log.debug('Enabling channels %s', self._channels.values()) + self._hwmon.reset(kinds=['energy'], sites=self._channels.values()) # Logging enabled channels self._log.info('Channels selected for energy sampling:') for channel in self._hwmon.active_channels: self._log.info(' %s', channel.label) - # record the HWMon channels - self._channels = conf.get('channel_map', { - 'LITTLE': self._target.little_core.upper(), - 'big': self._target.big_core.upper() - }) def sample(self): if self._hwmon is None: -- GitLab From 4c12acc36ac64f4fb91e6553c6951d56ebb533a5 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Wed, 26 Apr 2017 12:29:11 +0100 Subject: [PATCH 3/3] energy/hwmon: Improve default channel_map This changes the selection of hwmon channels so that: - If a channel_map is provided explicitly, all the named hwmon sites are required to exist, or an error is raised. - Otherwise, if we have big.LITTLE information about the platform, and hwmon reports the presence of channels with names matching the names we have for the big.LITTLE cores, then we use those hwmon sites for the "big" and "LITTLE" channels. - If neither of the above criteria are met, we enable all available hwmon energy channels. We can probably factor this into a common base class with the AEP, but I'll leave that for later when I can test it. --- libs/utils/energy.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/libs/utils/energy.py b/libs/utils/energy.py index 8c289c0db..5aaf10cd4 100644 --- a/libs/utils/energy.py +++ b/libs/utils/energy.py @@ -134,11 +134,31 @@ class HWMon(EnergyMeter): self._log.info('Scanning for HWMON channels, may take some time...') self._hwmon = devlib.HwmonInstrument(self._target) - # record the HWMon channels - self._channels = conf.get('channel_map', { - 'LITTLE': self._target.little_core.upper(), - 'big': self._target.big_core.upper() - }) + # Decide which channels we'll collect data from. + # If the caller provided a channel_map, require that all the named + # channels exist. + # Otherwise, try using the big.LITTLE core names as channel names. + # If they don't match, just collect all available channels. + + available_sites = [c.site for c in self._hwmon.get_channels('energy')] + + self._channels = conf.get('channel_map') + if self._channels: + # If the user provides a channel_map then require it to be correct. + if not all (s in available_sites for s in self._channels.values()): + raise RuntimeError( + "Found sites {} but channel_map contains {}".format( + sorted(available_sites), sorted(channels.values()))) + elif self._target.big_core: + bl_sites = [self._target.big_core.upper(), + self._target.little_core.upper()] + if all(s in available_sites for s in bl_sites): + self._log.info('Using default big.LITTLE hwmon channels') + self._channels = dict(zip(['big', 'LITTLE'], bl_sites)) + + if not self._channels: + self._log.info('Using all hwmon energy channels') + self._channels = {site: site for site in available_sites} # Configure channels for energy measurements self._log.debug('Enabling channels %s', self._channels.values()) -- GitLab