mirror of
https://github.com/ARM-software/devlib.git
synced 2025-01-31 10:10:46 +00:00
Add support for Python 3
Add support for running on Python 3 while maintaining Python 2 compatibility.
This commit is contained in:
parent
0d63386343
commit
5cafd2ec4d
@ -34,7 +34,7 @@ class DerivedEnergyMeasurements(DerivedMeasurements):
|
|||||||
if channel.site == 'timestamp':
|
if channel.site == 'timestamp':
|
||||||
use_timestamp = True
|
use_timestamp = True
|
||||||
time_measurment = channel.measurement_type
|
time_measurment = channel.measurement_type
|
||||||
for site, kinds in channel_map.iteritems():
|
for site, kinds in channel_map.items():
|
||||||
if 'power' in kinds and not 'energy' in kinds:
|
if 'power' in kinds and not 'energy' in kinds:
|
||||||
should_calculate_energy.append(site)
|
should_calculate_energy.append(site)
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
import csv
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -8,8 +7,11 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pd = None
|
pd = None
|
||||||
|
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
from devlib import DerivedMeasurements, DerivedMetric, MeasurementsCsv, InstrumentChannel
|
from devlib import DerivedMeasurements, DerivedMetric, MeasurementsCsv, InstrumentChannel
|
||||||
from devlib.exception import HostError
|
from devlib.exception import HostError
|
||||||
|
from devlib.utils.csvutil import csvwriter
|
||||||
from devlib.utils.rendering import gfxinfo_get_last_dump, VSYNC_INTERVAL
|
from devlib.utils.rendering import gfxinfo_get_last_dump, VSYNC_INTERVAL
|
||||||
from devlib.utils.types import numeric
|
from devlib.utils.types import numeric
|
||||||
|
|
||||||
@ -103,8 +105,7 @@ class DerivedGfxInfoStats(DerivedFpsStats):
|
|||||||
fps = 0
|
fps = 0
|
||||||
|
|
||||||
csv_file = self._get_csv_file_name(measurements_csv.path)
|
csv_file = self._get_csv_file_name(measurements_csv.path)
|
||||||
with open(csv_file, 'wb') as wfh:
|
with csvwriter(csv_file) as writer:
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow(['fps'])
|
writer.writerow(['fps'])
|
||||||
writer.writerows(per_frame_fps)
|
writer.writerows(per_frame_fps)
|
||||||
|
|
||||||
|
@ -15,7 +15,11 @@
|
|||||||
|
|
||||||
class DevlibError(Exception):
|
class DevlibError(Exception):
|
||||||
"""Base class for all Devlib exceptions."""
|
"""Base class for all Devlib exceptions."""
|
||||||
pass
|
@property
|
||||||
|
def message(self):
|
||||||
|
if self.args:
|
||||||
|
return self.args[0]
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
class TargetError(DevlibError):
|
class TargetError(DevlibError):
|
||||||
@ -75,13 +79,13 @@ def get_traceback(exc=None):
|
|||||||
object, or for the current exception exc is not specified.
|
object, or for the current exception exc is not specified.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import StringIO, traceback, sys
|
import io, traceback, sys
|
||||||
if exc is None:
|
if exc is None:
|
||||||
exc = sys.exc_info()
|
exc = sys.exc_info()
|
||||||
if not exc:
|
if not exc:
|
||||||
return None
|
return None
|
||||||
tb = exc[2]
|
tb = exc[2]
|
||||||
sio = StringIO.StringIO()
|
sio = io.BytesIO()
|
||||||
traceback.print_tb(tb, file=sio)
|
traceback.print_tb(tb, file=sio)
|
||||||
del tb # needs to be done explicitly see: http://docs.python.org/2/library/sys.html#sys.exc_info
|
del tb # needs to be done explicitly see: http://docs.python.org/2/library/sys.html#sys.exc_info
|
||||||
return sio.getvalue()
|
return sio.getvalue()
|
||||||
|
@ -13,10 +13,12 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import csv
|
|
||||||
import logging
|
import logging
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
|
from devlib.utils.csvutil import csvreader
|
||||||
from devlib.utils.types import numeric
|
from devlib.utils.types import numeric
|
||||||
from devlib.utils.types import identifier
|
from devlib.utils.types import identifier
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ class MeasurementType(object):
|
|||||||
self.category = category
|
self.category = category
|
||||||
self.conversions = {}
|
self.conversions = {}
|
||||||
if conversions is not None:
|
if conversions is not None:
|
||||||
for key, value in conversions.iteritems():
|
for key, value in conversions.items():
|
||||||
if not callable(value):
|
if not callable(value):
|
||||||
msg = 'Converter must be callable; got {} "{}"'
|
msg = 'Converter must be callable; got {} "{}"'
|
||||||
raise ValueError(msg.format(type(value), value))
|
raise ValueError(msg.format(type(value), value))
|
||||||
@ -189,14 +191,13 @@ class MeasurementsCsv(object):
|
|||||||
|
|
||||||
def iter_values(self):
|
def iter_values(self):
|
||||||
for row in self._iter_rows():
|
for row in self._iter_rows():
|
||||||
values = map(numeric, row)
|
values = list(map(numeric, row))
|
||||||
yield self.data_tuple(*values)
|
yield self.data_tuple(*values)
|
||||||
|
|
||||||
def _load_channels(self):
|
def _load_channels(self):
|
||||||
header = []
|
header = []
|
||||||
with open(self.path, 'rb') as fh:
|
with csvreader(self.path) as reader:
|
||||||
reader = csv.reader(fh)
|
header = next(reader)
|
||||||
header = reader.next()
|
|
||||||
|
|
||||||
self.channels = []
|
self.channels = []
|
||||||
for entry in header:
|
for entry in header:
|
||||||
@ -218,9 +219,8 @@ class MeasurementsCsv(object):
|
|||||||
self.channels.append(chan)
|
self.channels.append(chan)
|
||||||
|
|
||||||
def _iter_rows(self):
|
def _iter_rows(self):
|
||||||
with open(self.path, 'rb') as fh:
|
with csvreader(self.path) as reader:
|
||||||
reader = csv.reader(fh)
|
next(reader) # headings
|
||||||
reader.next() # headings
|
|
||||||
for row in reader:
|
for row in reader:
|
||||||
yield row
|
yield row
|
||||||
|
|
||||||
@ -252,7 +252,7 @@ class InstrumentChannel(object):
|
|||||||
self.measurement_type = MEASUREMENT_TYPES[measurement_type]
|
self.measurement_type = MEASUREMENT_TYPES[measurement_type]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError('Unknown measurement type: {}'.format(measurement_type))
|
raise ValueError('Unknown measurement type: {}'.format(measurement_type))
|
||||||
for atname, atvalue in attrs.iteritems():
|
for atname, atvalue in attrs.items():
|
||||||
setattr(self, atname, atvalue)
|
setattr(self, atname, atvalue)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -278,7 +278,7 @@ class Instrument(object):
|
|||||||
# channel management
|
# channel management
|
||||||
|
|
||||||
def list_channels(self):
|
def list_channels(self):
|
||||||
return self.channels.values()
|
return list(self.channels.values())
|
||||||
|
|
||||||
def get_channels(self, measure):
|
def get_channels(self, measure):
|
||||||
if hasattr(measure, 'name'):
|
if hasattr(measure, 'name'):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pylint: disable=attribute-defined-outside-init
|
#pylint: disable=attribute-defined-outside-init
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import csv
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
import tempfile
|
import tempfile
|
||||||
from fcntl import fcntl, F_GETFL, F_SETFL
|
from fcntl import fcntl, F_GETFL, F_SETFL
|
||||||
@ -10,6 +10,7 @@ from subprocess import Popen, PIPE, STDOUT
|
|||||||
|
|
||||||
from devlib import Instrument, CONTINUOUS, MeasurementsCsv
|
from devlib import Instrument, CONTINUOUS, MeasurementsCsv
|
||||||
from devlib.exception import HostError
|
from devlib.exception import HostError
|
||||||
|
from devlib.utils.csvutil import csvreader, csvwriter
|
||||||
from devlib.utils.misc import which
|
from devlib.utils.misc import which
|
||||||
|
|
||||||
OUTPUT_CAPTURE_FILE = 'acme-cape.csv'
|
OUTPUT_CAPTURE_FILE = 'acme-cape.csv'
|
||||||
@ -83,7 +84,7 @@ class AcmeCapeInstrument(Instrument):
|
|||||||
self.process.terminate()
|
self.process.terminate()
|
||||||
timeout_secs = 10
|
timeout_secs = 10
|
||||||
output = ''
|
output = ''
|
||||||
for _ in xrange(timeout_secs):
|
for _ in range(timeout_secs):
|
||||||
if self.process.poll() is not None:
|
if self.process.poll() is not None:
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
@ -95,7 +96,10 @@ class AcmeCapeInstrument(Instrument):
|
|||||||
msg = 'Could not terminate iio-capture:\n{}'
|
msg = 'Could not terminate iio-capture:\n{}'
|
||||||
raise HostError(msg.format(output))
|
raise HostError(msg.format(output))
|
||||||
if self.process.returncode != 15: # iio-capture exits with 15 when killed
|
if self.process.returncode != 15: # iio-capture exits with 15 when killed
|
||||||
output += self.process.stdout.read()
|
if sys.version_info[0] == 3:
|
||||||
|
output += self.process.stdout.read().decode(sys.stdout.encoding)
|
||||||
|
else:
|
||||||
|
output += self.process.stdout.read()
|
||||||
self.logger.info('ACME instrument encountered an error, '
|
self.logger.info('ACME instrument encountered an error, '
|
||||||
'you may want to try rebooting the ACME device:\n'
|
'you may want to try rebooting the ACME device:\n'
|
||||||
' ssh root@{} reboot'.format(self.host))
|
' ssh root@{} reboot'.format(self.host))
|
||||||
@ -114,13 +118,11 @@ class AcmeCapeInstrument(Instrument):
|
|||||||
active_channels = [c.label for c in self.active_channels]
|
active_channels = [c.label for c in self.active_channels]
|
||||||
active_indexes = [all_channels.index(ac) for ac in active_channels]
|
active_indexes = [all_channels.index(ac) for ac in active_channels]
|
||||||
|
|
||||||
with open(self.raw_data_file, 'rb') as fh:
|
with csvreader(self.raw_data_file, skipinitialspace=True) as reader:
|
||||||
with open(outfile, 'wb') as wfh:
|
with csvwriter(outfile) as writer:
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow(active_channels)
|
writer.writerow(active_channels)
|
||||||
|
|
||||||
reader = csv.reader(fh, skipinitialspace=True)
|
header = next(reader)
|
||||||
header = reader.next()
|
|
||||||
ts_index = header.index('timestamp ms')
|
ts_index = header.index('timestamp ms')
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
# pylint: disable=W0613,E1101,access-member-before-definition,attribute-defined-outside-init
|
# pylint: disable=W0613,E1101,access-member-before-definition,attribute-defined-outside-init
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import os
|
import os
|
||||||
import csv
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import signal
|
import signal
|
||||||
import struct
|
import struct
|
||||||
@ -28,6 +27,7 @@ import shutil
|
|||||||
|
|
||||||
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
||||||
from devlib.exception import HostError
|
from devlib.exception import HostError
|
||||||
|
from devlib.utils.csvutil import csvreader, csvwriter
|
||||||
from devlib.utils.misc import which
|
from devlib.utils.misc import which
|
||||||
|
|
||||||
from devlib.utils.parse_aep import AepParser
|
from devlib.utils.parse_aep import AepParser
|
||||||
@ -108,10 +108,8 @@ class ArmEnergyProbeInstrument(Instrument):
|
|||||||
active_channels = [c.label for c in self.active_channels]
|
active_channels = [c.label for c in self.active_channels]
|
||||||
active_indexes = [all_channels.index(ac) for ac in active_channels]
|
active_indexes = [all_channels.index(ac) for ac in active_channels]
|
||||||
|
|
||||||
with open(self.output_file, 'rb') as ifile:
|
with csvreader(self.output_file, delimiter=' ') as reader:
|
||||||
reader = csv.reader(ifile, delimiter=' ')
|
with csvwriter(outfile) as writer:
|
||||||
with open(outfile, 'wb') as wfh:
|
|
||||||
writer = csv.writer(wfh)
|
|
||||||
for row in reader:
|
for row in reader:
|
||||||
if skip_header == 1:
|
if skip_header == 1:
|
||||||
writer.writerow(active_channels)
|
writer.writerow(active_channels)
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import os
|
import os
|
||||||
import csv
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from devlib.instrument import Instrument, MeasurementsCsv, CONTINUOUS
|
from devlib.instrument import Instrument, MeasurementsCsv, CONTINUOUS
|
||||||
from devlib.exception import HostError
|
from devlib.exception import HostError
|
||||||
|
from devlib.utils.csvutil import csvwriter, create_reader
|
||||||
from devlib.utils.misc import unique
|
from devlib.utils.misc import unique
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from daqpower.client import execute_command, Status
|
from daqpower.client import execute_command, Status
|
||||||
from daqpower.config import DeviceConfiguration, ServerConfiguration
|
from daqpower.config import DeviceConfiguration, ServerConfiguration
|
||||||
except ImportError, e:
|
except ImportError as e:
|
||||||
execute_command, Status = None, None
|
execute_command, Status = None, None
|
||||||
DeviceConfiguration, ServerConfiguration, ConfigurationError = None, None, None
|
DeviceConfiguration, ServerConfiguration, ConfigurationError = None, None, None
|
||||||
import_error_mesg = e.message
|
import_error_mesg = e.args[0] if e.args else str(e)
|
||||||
|
|
||||||
|
|
||||||
class DaqInstrument(Instrument):
|
class DaqInstrument(Instrument):
|
||||||
@ -37,7 +37,7 @@ class DaqInstrument(Instrument):
|
|||||||
if execute_command is None:
|
if execute_command is None:
|
||||||
raise HostError('Could not import "daqpower": {}'.format(import_error_mesg))
|
raise HostError('Could not import "daqpower": {}'.format(import_error_mesg))
|
||||||
if labels is None:
|
if labels is None:
|
||||||
labels = ['PORT_{}'.format(i) for i in xrange(len(resistor_values))]
|
labels = ['PORT_{}'.format(i) for i in range(len(resistor_values))]
|
||||||
if len(labels) != len(resistor_values):
|
if len(labels) != len(resistor_values):
|
||||||
raise ValueError('"labels" and "resistor_values" must be of the same length')
|
raise ValueError('"labels" and "resistor_values" must be of the same length')
|
||||||
self.server_config = ServerConfiguration(host=host,
|
self.server_config = ServerConfiguration(host=host,
|
||||||
@ -97,8 +97,8 @@ class DaqInstrument(Instrument):
|
|||||||
for site in active_sites:
|
for site in active_sites:
|
||||||
try:
|
try:
|
||||||
site_file = raw_file_map[site]
|
site_file = raw_file_map[site]
|
||||||
fh = open(site_file, 'rb')
|
reader, fh = create_reader(site_file)
|
||||||
site_readers[site] = csv.reader(fh)
|
site_readers[site] = reader
|
||||||
file_handles.append(fh)
|
file_handles.append(fh)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
message = 'Could not get DAQ trace for {}; Obtained traces are in {}'
|
message = 'Could not get DAQ trace for {}; Obtained traces are in {}'
|
||||||
@ -106,22 +106,21 @@ class DaqInstrument(Instrument):
|
|||||||
|
|
||||||
# The first row is the headers
|
# The first row is the headers
|
||||||
channel_order = []
|
channel_order = []
|
||||||
for site, reader in site_readers.iteritems():
|
for site, reader in site_readers.items():
|
||||||
channel_order.extend(['{}_{}'.format(site, kind)
|
channel_order.extend(['{}_{}'.format(site, kind)
|
||||||
for kind in reader.next()])
|
for kind in next(reader)])
|
||||||
|
|
||||||
def _read_next_rows():
|
def _read_next_rows():
|
||||||
parts = []
|
parts = []
|
||||||
for reader in site_readers.itervalues():
|
for reader in site_readers.values():
|
||||||
try:
|
try:
|
||||||
parts.extend(reader.next())
|
parts.extend(next(reader))
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
parts.extend([None, None])
|
parts.extend([None, None])
|
||||||
return list(chain(parts))
|
return list(chain(parts))
|
||||||
|
|
||||||
with open(outfile, 'wb') as wfh:
|
with csvwriter(outfile) as writer:
|
||||||
field_names = [c.label for c in self.active_channels]
|
field_names = [c.label for c in self.active_channels]
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow(field_names)
|
writer.writerow(field_names)
|
||||||
raw_row = _read_next_rows()
|
raw_row = _read_next_rows()
|
||||||
while any(raw_row):
|
while any(raw_row):
|
||||||
|
@ -14,14 +14,15 @@
|
|||||||
#
|
#
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import os
|
import os
|
||||||
import csv
|
|
||||||
import signal
|
import signal
|
||||||
import tempfile
|
import tempfile
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
||||||
from devlib.exception import HostError
|
from devlib.exception import HostError
|
||||||
|
from devlib.utils.csvutil import csvwriter
|
||||||
from devlib.utils.misc import which
|
from devlib.utils.misc import which
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
self.labels = labels
|
self.labels = labels
|
||||||
else:
|
else:
|
||||||
self.labels = ['PORT_{}'.format(i)
|
self.labels = ['PORT_{}'.format(i)
|
||||||
for i in xrange(len(resistor_values))]
|
for i in range(len(resistor_values))]
|
||||||
self.device_entry = device_entry
|
self.device_entry = device_entry
|
||||||
self.caiman = which('caiman')
|
self.caiman = which('caiman')
|
||||||
if self.caiman is None:
|
if self.caiman is None:
|
||||||
@ -80,6 +81,9 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
self.process.poll()
|
self.process.poll()
|
||||||
if self.process.returncode is not None:
|
if self.process.returncode is not None:
|
||||||
stdout, stderr = self.process.communicate()
|
stdout, stderr = self.process.communicate()
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
stdout = stdout.decode(sys.stdout.encoding)
|
||||||
|
stderr = stderr.decode(sys.stdout.encoding)
|
||||||
raise HostError(
|
raise HostError(
|
||||||
'Energy Probe: Caiman exited unexpectedly with exit code {}.\n'
|
'Energy Probe: Caiman exited unexpectedly with exit code {}.\n'
|
||||||
'stdout:\n{}\nstderr:\n{}'.format(self.process.returncode,
|
'stdout:\n{}\nstderr:\n{}'.format(self.process.returncode,
|
||||||
@ -98,8 +102,7 @@ class EnergyProbeInstrument(Instrument):
|
|||||||
|
|
||||||
self.logger.debug('Parsing raw data file: {}'.format(self.raw_data_file))
|
self.logger.debug('Parsing raw data file: {}'.format(self.raw_data_file))
|
||||||
with open(self.raw_data_file, 'rb') as bfile:
|
with open(self.raw_data_file, 'rb') as bfile:
|
||||||
with open(outfile, 'wb') as wfh:
|
with csvwriter(outfile) as writer:
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow(active_channels)
|
writer.writerow(active_channels)
|
||||||
while True:
|
while True:
|
||||||
data = bfile.read(num_of_ports * self.bytes_per_sample)
|
data = bfile.read(num_of_ports * self.bytes_per_sample)
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from __future__ import division
|
from __future__ import division
|
||||||
import csv
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from devlib.platform.gem5 import Gem5SimulationPlatform
|
from devlib.platform.gem5 import Gem5SimulationPlatform
|
||||||
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
||||||
from devlib.exception import TargetError, HostError
|
from devlib.exception import TargetError, HostError
|
||||||
|
from devlib.utils.csvutil import csvwriter
|
||||||
|
|
||||||
|
|
||||||
class Gem5PowerInstrument(Instrument):
|
class Gem5PowerInstrument(Instrument):
|
||||||
@ -66,8 +66,7 @@ class Gem5PowerInstrument(Instrument):
|
|||||||
|
|
||||||
def get_data(self, outfile):
|
def get_data(self, outfile):
|
||||||
active_sites = [c.site for c in self.active_channels]
|
active_sites = [c.site for c in self.active_channels]
|
||||||
with open(outfile, 'wb') as wfh:
|
with csvwriter(outfile) as writer:
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow([c.label for c in self.active_channels]) # headers
|
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]
|
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,
|
for rec, rois in self.target.gem5stats.match_iter(sites_to_match,
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import csv
|
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
|
import sys
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
|
|
||||||
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
from devlib.instrument import Instrument, CONTINUOUS, MeasurementsCsv
|
||||||
from devlib.exception import HostError
|
from devlib.exception import HostError
|
||||||
from devlib.host import PACKAGE_BIN_DIRECTORY
|
from devlib.host import PACKAGE_BIN_DIRECTORY
|
||||||
|
from devlib.utils.csvutil import csvwriter
|
||||||
from devlib.utils.misc import which
|
from devlib.utils.misc import which
|
||||||
|
|
||||||
|
|
||||||
INSTALL_INSTRUCTIONS="""
|
INSTALL_INSTRUCTIONS="""
|
||||||
MonsoonInstrument requires the monsoon.py tool, available from AOSP:
|
MonsoonInstrument requires the monsoon.py tool, available from AOSP:
|
||||||
|
|
||||||
@ -18,6 +21,7 @@ parameter to MonsoonInstrument). `pip install python-gflags pyserial` to install
|
|||||||
the dependencies.
|
the dependencies.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class MonsoonInstrument(Instrument):
|
class MonsoonInstrument(Instrument):
|
||||||
"""Instrument for Monsoon Solutions power monitor
|
"""Instrument for Monsoon Solutions power monitor
|
||||||
|
|
||||||
@ -81,6 +85,9 @@ class MonsoonInstrument(Instrument):
|
|||||||
process.poll()
|
process.poll()
|
||||||
if process.returncode is not None:
|
if process.returncode is not None:
|
||||||
stdout, stderr = process.communicate()
|
stdout, stderr = process.communicate()
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
stdout = stdout.encode(sys.stdout.encoding)
|
||||||
|
stderr = stderr.encode(sys.stdout.encoding)
|
||||||
raise HostError(
|
raise HostError(
|
||||||
'Monsoon script exited unexpectedly with exit code {}.\n'
|
'Monsoon script exited unexpectedly with exit code {}.\n'
|
||||||
'stdout:\n{}\nstderr:\n{}'.format(process.returncode,
|
'stdout:\n{}\nstderr:\n{}'.format(process.returncode,
|
||||||
@ -104,8 +111,7 @@ class MonsoonInstrument(Instrument):
|
|||||||
|
|
||||||
stdout, stderr = self.output
|
stdout, stderr = self.output
|
||||||
|
|
||||||
with open(outfile, 'wb') as f:
|
with csvwriter(outfile) as writer:
|
||||||
writer = csv.writer(f)
|
|
||||||
active_sites = [c.site for c in self.active_channels]
|
active_sites = [c.site for c in self.active_channels]
|
||||||
|
|
||||||
# Write column headers
|
# Write column headers
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import csv
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from itertools import izip_longest
|
|
||||||
|
from future.moves.itertools import zip_longest
|
||||||
|
|
||||||
from devlib.instrument import Instrument, MeasurementsCsv, CONTINUOUS
|
from devlib.instrument import Instrument, MeasurementsCsv, CONTINUOUS
|
||||||
from devlib.exception import TargetError, HostError
|
from devlib.exception import TargetError, HostError
|
||||||
from devlib.utils.android import ApkInfo
|
from devlib.utils.android import ApkInfo
|
||||||
|
from devlib.utils.csvutil import csvwriter
|
||||||
|
|
||||||
|
|
||||||
THIS_DIR = os.path.dirname(__file__)
|
THIS_DIR = os.path.dirname(__file__)
|
||||||
@ -46,10 +47,9 @@ def netstats_to_measurements(netstats):
|
|||||||
def write_measurements_csv(measurements, filepath):
|
def write_measurements_csv(measurements, filepath):
|
||||||
headers = sorted(measurements.keys())
|
headers = sorted(measurements.keys())
|
||||||
columns = [measurements[h] for h in headers]
|
columns = [measurements[h] for h in headers]
|
||||||
with open(filepath, 'wb') as wfh:
|
with csvwriter(filepath) as writer:
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow(headers)
|
writer.writerow(headers)
|
||||||
writer.writerows(izip_longest(*columns))
|
writer.writerows(zip_longest(*columns))
|
||||||
|
|
||||||
|
|
||||||
class NetstatsInstrument(Instrument):
|
class NetstatsInstrument(Instrument):
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
import logging
|
import logging
|
||||||
from inspect import isclass
|
from inspect import isclass
|
||||||
|
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
from devlib.utils.misc import walk_modules
|
from devlib.utils.misc import walk_modules
|
||||||
from devlib.utils.types import identifier
|
from devlib.utils.types import identifier
|
||||||
|
|
||||||
@ -75,7 +77,7 @@ class BootModule(Module): # pylint: disable=R0921
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def update(self, **kwargs):
|
def update(self, **kwargs):
|
||||||
for name, value in kwargs.iteritems():
|
for name, value in kwargs.items():
|
||||||
if not hasattr(self, name):
|
if not hasattr(self, name):
|
||||||
raise ValueError('Unknown parameter "{}" for {}'.format(name, self.name))
|
raise ValueError('Unknown parameter "{}" for {}'.format(name, self.name))
|
||||||
self.logger.debug('Updating "{}" to "{}"'.format(name, value))
|
self.logger.debug('Updating "{}" to "{}"'.format(name, value))
|
||||||
@ -117,6 +119,6 @@ def register_module(mod):
|
|||||||
|
|
||||||
def __load_cache():
|
def __load_cache():
|
||||||
for module in walk_modules('devlib.module'):
|
for module in walk_modules('devlib.module'):
|
||||||
for obj in vars(module).itervalues():
|
for obj in vars(module).values():
|
||||||
if isclass(obj) and issubclass(obj, Module) and obj.name:
|
if isclass(obj) and issubclass(obj, Module) and obj.name:
|
||||||
register_module(obj)
|
register_module(obj)
|
||||||
|
@ -63,7 +63,7 @@ class FastbootFlashModule(FlashModule):
|
|||||||
image_bundle = expand_path(image_bundle)
|
image_bundle = expand_path(image_bundle)
|
||||||
to_flash = self._bundle_to_images(image_bundle)
|
to_flash = self._bundle_to_images(image_bundle)
|
||||||
to_flash = merge_dicts(to_flash, images or {}, should_normalize=False)
|
to_flash = merge_dicts(to_flash, images or {}, should_normalize=False)
|
||||||
for partition, image_path in to_flash.iteritems():
|
for partition, image_path in to_flash.items():
|
||||||
self.logger.debug('flashing {}'.format(partition))
|
self.logger.debug('flashing {}'.format(partition))
|
||||||
self._flash_image(self.target, partition, expand_path(image_path))
|
self._flash_image(self.target, partition, expand_path(image_path))
|
||||||
fastboot_command('reboot')
|
fastboot_command('reboot')
|
||||||
|
@ -325,7 +325,7 @@ class CGroup(object):
|
|||||||
def get_tasks(self):
|
def get_tasks(self):
|
||||||
task_ids = self.target.read_value(self.tasks_file).split()
|
task_ids = self.target.read_value(self.tasks_file).split()
|
||||||
logging.debug('Tasks: %s', task_ids)
|
logging.debug('Tasks: %s', task_ids)
|
||||||
return map(int, task_ids)
|
return list(map(int, task_ids))
|
||||||
|
|
||||||
def add_task(self, tid):
|
def add_task(self, tid):
|
||||||
self.target.write_value(self.tasks_file, tid, verify=False)
|
self.target.write_value(self.tasks_file, tid, verify=False)
|
||||||
|
@ -150,7 +150,7 @@ class CpufreqModule(Module):
|
|||||||
if governor is None:
|
if governor is None:
|
||||||
governor = self.get_governor(cpu)
|
governor = self.get_governor(cpu)
|
||||||
valid_tunables = self.list_governor_tunables(cpu)
|
valid_tunables = self.list_governor_tunables(cpu)
|
||||||
for tunable, value in kwargs.iteritems():
|
for tunable, value in kwargs.items():
|
||||||
if tunable in valid_tunables:
|
if tunable in valid_tunables:
|
||||||
path = '/sys/devices/system/cpu/{}/cpufreq/{}/{}'.format(cpu, governor, tunable)
|
path = '/sys/devices/system/cpu/{}/cpufreq/{}/{}'.format(cpu, governor, tunable)
|
||||||
try:
|
try:
|
||||||
@ -176,7 +176,7 @@ class CpufreqModule(Module):
|
|||||||
try:
|
try:
|
||||||
cmd = 'cat /sys/devices/system/cpu/{}/cpufreq/scaling_available_frequencies'.format(cpu)
|
cmd = 'cat /sys/devices/system/cpu/{}/cpufreq/scaling_available_frequencies'.format(cpu)
|
||||||
output = self.target.execute(cmd)
|
output = self.target.execute(cmd)
|
||||||
available_frequencies = map(int, output.strip().split()) # pylint: disable=E1103
|
available_frequencies = list(map(int, output.strip().split())) # pylint: disable=E1103
|
||||||
except TargetError:
|
except TargetError:
|
||||||
# On some devices scaling_frequencies is not generated.
|
# On some devices scaling_frequencies is not generated.
|
||||||
# http://adrynalyne-teachtofish.blogspot.co.uk/2011/11/how-to-enable-scalingavailablefrequenci.html
|
# http://adrynalyne-teachtofish.blogspot.co.uk/2011/11/how-to-enable-scalingavailablefrequenci.html
|
||||||
@ -190,7 +190,7 @@ class CpufreqModule(Module):
|
|||||||
return []
|
return []
|
||||||
raise
|
raise
|
||||||
|
|
||||||
available_frequencies = map(int, reversed([f for f, _ in zip(out_iter, out_iter)]))
|
available_frequencies = list(map(int, reversed([f for f, _ in zip(out_iter, out_iter)])))
|
||||||
return available_frequencies
|
return available_frequencies
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
@ -478,7 +478,7 @@ class CpufreqModule(Module):
|
|||||||
"""
|
"""
|
||||||
cpus = set(range(self.target.number_of_cpus))
|
cpus = set(range(self.target.number_of_cpus))
|
||||||
while cpus:
|
while cpus:
|
||||||
cpu = iter(cpus).next()
|
cpu = next(iter(cpus))
|
||||||
domain = self.target.cpufreq.get_related_cpus(cpu)
|
domain = self.target.cpufreq.get_related_cpus(cpu)
|
||||||
yield domain
|
yield domain
|
||||||
cpus = cpus.difference(domain)
|
cpus = cpus.difference(domain)
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
# pylint: disable=attribute-defined-outside-init
|
# pylint: disable=attribute-defined-outside-init
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
from devlib.module import Module
|
from devlib.module import Module
|
||||||
from devlib.utils.misc import memoized
|
from devlib.utils.misc import memoized
|
||||||
from devlib.utils.types import integer, boolean
|
from devlib.utils.types import integer, boolean
|
||||||
|
@ -75,7 +75,7 @@ class Gem5StatsModule(Module):
|
|||||||
raise KeyError('ROI label {} already used'.format(label))
|
raise KeyError('ROI label {} already used'.format(label))
|
||||||
if len(self.rois) >= GEM5STATS_ROI_NUMBER:
|
if len(self.rois) >= GEM5STATS_ROI_NUMBER:
|
||||||
raise RuntimeError('Too many ROIs reserved')
|
raise RuntimeError('Too many ROIs reserved')
|
||||||
all_rois = set(xrange(GEM5STATS_ROI_NUMBER))
|
all_rois = set(range(GEM5STATS_ROI_NUMBER))
|
||||||
used_rois = set([roi.number for roi in self.rois.values()])
|
used_rois = set([roi.number for roi in self.rois.values()])
|
||||||
avail_rois = all_rois - used_rois
|
avail_rois = all_rois - used_rois
|
||||||
self.rois[label] = Gem5ROI(list(avail_rois)[0], self.target)
|
self.rois[label] = Gem5ROI(list(avail_rois)[0], self.target)
|
||||||
@ -223,7 +223,7 @@ class Gem5StatsModule(Module):
|
|||||||
'''
|
'''
|
||||||
with open(self._stats_file_path, 'r') as stats_file:
|
with open(self._stats_file_path, 'r') as stats_file:
|
||||||
# _goto_dump reach EOF and returns the total number of dumps + 1
|
# _goto_dump reach EOF and returns the total number of dumps + 1
|
||||||
return self._goto_dump(stats_file, sys.maxint)
|
return self._goto_dump(stats_file, sys.maxsize)
|
||||||
|
|
||||||
def _goto_dump(self, stats_file, target_dump):
|
def _goto_dump(self, stats_file, target_dump):
|
||||||
if target_dump < 0:
|
if target_dump < 0:
|
||||||
@ -243,7 +243,7 @@ class Gem5StatsModule(Module):
|
|||||||
dump_iterator = iter_statistics_dump(stats_file)
|
dump_iterator = iter_statistics_dump(stats_file)
|
||||||
while curr_dump < target_dump:
|
while curr_dump < target_dump:
|
||||||
try:
|
try:
|
||||||
dump = dump_iterator.next()
|
dump = next(dump_iterator)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
break
|
break
|
||||||
# End of passed dump is beginning og next one
|
# End of passed dump is beginning og next one
|
||||||
|
@ -26,7 +26,7 @@ class GpufreqModule(Module):
|
|||||||
def __init__(self, target):
|
def __init__(self, target):
|
||||||
super(GpufreqModule, self).__init__(target)
|
super(GpufreqModule, self).__init__(target)
|
||||||
frequencies_str = self.target.read_value("/sys/kernel/gpu/gpu_freq_table")
|
frequencies_str = self.target.read_value("/sys/kernel/gpu/gpu_freq_table")
|
||||||
self.frequencies = map(int, frequencies_str.split(" "))
|
self.frequencies = list(map(int, frequencies_str.split(" ")))
|
||||||
self.frequencies.sort()
|
self.frequencies.sort()
|
||||||
self.governors = self.target.read_value("/sys/kernel/gpu/gpu_available_governor").split(" ")
|
self.governors = self.target.read_value("/sys/kernel/gpu/gpu_available_governor").split(" ")
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ class HwmonDevice(object):
|
|||||||
@property
|
@property
|
||||||
def sensors(self):
|
def sensors(self):
|
||||||
all_sensors = []
|
all_sensors = []
|
||||||
for sensors_of_kind in self._sensors.itervalues():
|
for sensors_of_kind in self._sensors.values():
|
||||||
all_sensors.extend(sensors_of_kind.values())
|
all_sensors.extend(list(sensors_of_kind.values()))
|
||||||
return all_sensors
|
return all_sensors
|
||||||
|
|
||||||
def __init__(self, target, path, name, fields):
|
def __init__(self, target, path, name, fields):
|
||||||
@ -100,7 +100,7 @@ class HwmonDevice(object):
|
|||||||
|
|
||||||
def get(self, kind, number=None):
|
def get(self, kind, number=None):
|
||||||
if number is None:
|
if number is None:
|
||||||
return [s for _, s in sorted(self._sensors[kind].iteritems(),
|
return [s for _, s in sorted(self._sensors[kind].items(),
|
||||||
key=lambda x: x[0])]
|
key=lambda x: x[0])]
|
||||||
else:
|
else:
|
||||||
return self._sensors[kind].get(number)
|
return self._sensors[kind].get(number)
|
||||||
@ -139,7 +139,7 @@ class HwmonModule(Module):
|
|||||||
|
|
||||||
def scan(self):
|
def scan(self):
|
||||||
values_tree = self.target.read_tree_values(self.root, depth=3)
|
values_tree = self.target.read_tree_values(self.root, depth=3)
|
||||||
for entry_id, fields in values_tree.iteritems():
|
for entry_id, fields in values_tree.items():
|
||||||
path = self.target.path.join(self.root, entry_id)
|
path = self.target.path.join(self.root, entry_id)
|
||||||
name = fields.pop('name', None)
|
name = fields.pop('name', None)
|
||||||
if name is None:
|
if name is None:
|
||||||
|
@ -100,5 +100,5 @@ class ThermalModule(Module):
|
|||||||
|
|
||||||
def disable_all_zones(self):
|
def disable_all_zones(self):
|
||||||
"""Disables all the thermal zones in the target"""
|
"""Disables all the thermal zones in the target"""
|
||||||
for zone in self.zones.itervalues():
|
for zone in self.zones.values():
|
||||||
zone.set_enabled(False)
|
zone.set_enabled(False)
|
||||||
|
@ -251,7 +251,7 @@ class VexpressUBoot(VexpressBootModule):
|
|||||||
menu = UbootMenu(tty)
|
menu = UbootMenu(tty)
|
||||||
self.logger.debug('Waiting for U-Boot prompt...')
|
self.logger.debug('Waiting for U-Boot prompt...')
|
||||||
menu.open(timeout=120)
|
menu.open(timeout=120)
|
||||||
for var, value in self.env.iteritems():
|
for var, value in self.env.items():
|
||||||
menu.setenv(var, value)
|
menu.setenv(var, value)
|
||||||
menu.boot()
|
menu.boot()
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ class VersatileExpressFlashModule(FlashModule):
|
|||||||
if images:
|
if images:
|
||||||
self._overlay_images(images)
|
self._overlay_images(images)
|
||||||
os.system('sync')
|
os.system('sync')
|
||||||
except (IOError, OSError), e:
|
except (IOError, OSError) as e:
|
||||||
msg = 'Could not deploy images to {}; got: {}'
|
msg = 'Could not deploy images to {}; got: {}'
|
||||||
raise TargetError(msg.format(self.vemsd_mount, e))
|
raise TargetError(msg.format(self.vemsd_mount, e))
|
||||||
self.target.boot()
|
self.target.boot()
|
||||||
@ -352,7 +352,7 @@ class VersatileExpressFlashModule(FlashModule):
|
|||||||
tar.extractall(self.vemsd_mount)
|
tar.extractall(self.vemsd_mount)
|
||||||
|
|
||||||
def _overlay_images(self, images):
|
def _overlay_images(self, images):
|
||||||
for dest, src in images.iteritems():
|
for dest, src in images.items():
|
||||||
dest = os.path.join(self.vemsd_mount, dest)
|
dest = os.path.join(self.vemsd_mount, dest)
|
||||||
self.logger.debug('Copying {} to {}'.format(src, dest))
|
self.logger.debug('Copying {} to {}'.format(src, dest))
|
||||||
shutil.copy(src, dest)
|
shutil.copy(src, dest)
|
||||||
@ -379,7 +379,7 @@ def wait_for_vemsd(vemsd_mount, tty, mcc_prompt=DEFAULT_MCC_PROMPT, short_delay=
|
|||||||
path = os.path.join(vemsd_mount, 'config.txt')
|
path = os.path.join(vemsd_mount, 'config.txt')
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return
|
return
|
||||||
for _ in xrange(attempts):
|
for _ in range(attempts):
|
||||||
tty.sendline('') # clear any garbage
|
tty.sendline('') # clear any garbage
|
||||||
tty.expect(mcc_prompt, timeout=short_delay)
|
tty.expect(mcc_prompt, timeout=short_delay)
|
||||||
tty.sendline('usb_on')
|
tty.sendline('usb_on')
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
from __future__ import division
|
from __future__ import division
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import csv
|
|
||||||
import time
|
import time
|
||||||
import pexpect
|
import pexpect
|
||||||
|
|
||||||
@ -23,6 +22,7 @@ from devlib.platform import Platform
|
|||||||
from devlib.instrument import Instrument, InstrumentChannel, MeasurementsCsv, Measurement, CONTINUOUS, INSTANTANEOUS
|
from devlib.instrument import Instrument, InstrumentChannel, MeasurementsCsv, Measurement, CONTINUOUS, INSTANTANEOUS
|
||||||
from devlib.exception import TargetError, HostError
|
from devlib.exception import TargetError, HostError
|
||||||
from devlib.host import PACKAGE_BIN_DIRECTORY
|
from devlib.host import PACKAGE_BIN_DIRECTORY
|
||||||
|
from devlib.utils.csvutil import csvreader, csvwriter
|
||||||
from devlib.utils.serial_port import open_serial_connection
|
from devlib.utils.serial_port import open_serial_connection
|
||||||
|
|
||||||
|
|
||||||
@ -267,9 +267,8 @@ class JunoEnergyInstrument(Instrument):
|
|||||||
self.target.pull(self.on_target_file, temp_file)
|
self.target.pull(self.on_target_file, temp_file)
|
||||||
self.target.remove(self.on_target_file)
|
self.target.remove(self.on_target_file)
|
||||||
|
|
||||||
with open(temp_file, 'rb') as fh:
|
with csvreader(temp_file) as reader:
|
||||||
reader = csv.reader(fh)
|
headings = next(reader)
|
||||||
headings = reader.next()
|
|
||||||
|
|
||||||
# Figure out which columns from the collected csv we actually want
|
# Figure out which columns from the collected csv we actually want
|
||||||
select_columns = []
|
select_columns = []
|
||||||
@ -279,10 +278,9 @@ class JunoEnergyInstrument(Instrument):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
raise HostError('Channel "{}" is not in {}'.format(chan.name, temp_file))
|
raise HostError('Channel "{}" is not in {}'.format(chan.name, temp_file))
|
||||||
|
|
||||||
with open(output_file, 'wb') as wfh:
|
with csvwriter(output_file) as writer:
|
||||||
write_headings = ['{}_{}'.format(c.site, c.kind)
|
write_headings = ['{}_{}'.format(c.site, c.kind)
|
||||||
for c in self.active_channels]
|
for c in self.active_channels]
|
||||||
writer = csv.writer(wfh)
|
|
||||||
writer.writerow(write_headings)
|
writer.writerow(write_headings)
|
||||||
for row in reader:
|
for row in reader:
|
||||||
write_row = [row[c] for c in select_columns]
|
write_row = [row[c] for c in select_columns]
|
||||||
@ -293,11 +291,11 @@ class JunoEnergyInstrument(Instrument):
|
|||||||
def take_measurement(self):
|
def take_measurement(self):
|
||||||
result = []
|
result = []
|
||||||
output = self.target.execute(self.command2).split()
|
output = self.target.execute(self.command2).split()
|
||||||
reader=csv.reader(output)
|
with csvreader(output) as reader:
|
||||||
headings=reader.next()
|
headings=next(reader)
|
||||||
values = reader.next()
|
values = next(reader)
|
||||||
for chan in self.active_channels:
|
for chan in self.active_channels:
|
||||||
value = values[headings.index(chan.name)]
|
value = values[headings.index(chan.name)]
|
||||||
result.append(Measurement(value, chan))
|
result.append(Measurement(value, chan))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -63,13 +63,12 @@ class Gem5SimulationPlatform(Platform):
|
|||||||
|
|
||||||
# Find the first one that does not exist. Ensures that we do not re-use
|
# Find the first one that does not exist. Ensures that we do not re-use
|
||||||
# the directory used by someone else.
|
# the directory used by someone else.
|
||||||
for i in xrange(sys.maxint):
|
i = 0
|
||||||
|
directory = os.path.join(self.gem5_interact_dir, "wa_{}".format(i))
|
||||||
|
while os.path.exists(directory):
|
||||||
|
i += 1
|
||||||
directory = os.path.join(self.gem5_interact_dir, "wa_{}".format(i))
|
directory = os.path.join(self.gem5_interact_dir, "wa_{}".format(i))
|
||||||
try:
|
|
||||||
os.stat(directory)
|
|
||||||
continue
|
|
||||||
except OSError:
|
|
||||||
break
|
|
||||||
self.gem5_interact_dir = directory
|
self.gem5_interact_dir = directory
|
||||||
self.logger.debug("Using {} as the temporary directory."
|
self.logger.debug("Using {} as the temporary directory."
|
||||||
.format(self.gem5_interact_dir))
|
.format(self.gem5_interact_dir))
|
||||||
|
@ -4,6 +4,7 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
import posixpath
|
import posixpath
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tarfile
|
import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
@ -233,7 +234,7 @@ class Target(object):
|
|||||||
self._install_module(get_module('bl'))
|
self._install_module(get_module('bl'))
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
for conn in self._connections.itervalues():
|
for conn in self._connections.values():
|
||||||
conn.close()
|
conn.close()
|
||||||
self._connections = {}
|
self._connections = {}
|
||||||
|
|
||||||
@ -514,8 +515,8 @@ class Target(object):
|
|||||||
|
|
||||||
def tempfile(self, prefix='', suffix=''):
|
def tempfile(self, prefix='', suffix=''):
|
||||||
names = tempfile._get_candidate_names() # pylint: disable=W0212
|
names = tempfile._get_candidate_names() # pylint: disable=W0212
|
||||||
for _ in xrange(tempfile.TMP_MAX):
|
for _ in range(tempfile.TMP_MAX):
|
||||||
name = names.next()
|
name = next(names)
|
||||||
path = self.get_workpath(prefix + name + suffix)
|
path = self.get_workpath(prefix + name + suffix)
|
||||||
if not self.file_exists(path):
|
if not self.file_exists(path):
|
||||||
return path
|
return path
|
||||||
@ -542,7 +543,7 @@ class Target(object):
|
|||||||
|
|
||||||
def list_offline_cpus(self):
|
def list_offline_cpus(self):
|
||||||
online = self.list_online_cpus()
|
online = self.list_online_cpus()
|
||||||
return [c for c in xrange(self.number_of_cpus)
|
return [c for c in range(self.number_of_cpus)
|
||||||
if c not in online]
|
if c not in online]
|
||||||
|
|
||||||
def getenv(self, variable):
|
def getenv(self, variable):
|
||||||
@ -716,7 +717,7 @@ class Target(object):
|
|||||||
def _update_modules(self, stage):
|
def _update_modules(self, stage):
|
||||||
for mod in self.modules:
|
for mod in self.modules:
|
||||||
if isinstance(mod, dict):
|
if isinstance(mod, dict):
|
||||||
mod, params = mod.items()[0]
|
mod, params = list(mod.items())[0]
|
||||||
else:
|
else:
|
||||||
params = {}
|
params = {}
|
||||||
mod = get_module(mod)
|
mod = get_module(mod)
|
||||||
@ -790,7 +791,7 @@ class LinuxTarget(Target):
|
|||||||
@memoized
|
@memoized
|
||||||
def abi(self):
|
def abi(self):
|
||||||
value = self.execute('uname -m').strip()
|
value = self.execute('uname -m').strip()
|
||||||
for abi, architectures in ABI_MAP.iteritems():
|
for abi, architectures in ABI_MAP.items():
|
||||||
if value in architectures:
|
if value in architectures:
|
||||||
result = abi
|
result = abi
|
||||||
break
|
break
|
||||||
@ -858,27 +859,27 @@ class LinuxTarget(Target):
|
|||||||
result = self.execute('ps -C {} -o pid'.format(process_name), # NOQA
|
result = self.execute('ps -C {} -o pid'.format(process_name), # NOQA
|
||||||
check_exit_code=False).strip().split()
|
check_exit_code=False).strip().split()
|
||||||
if len(result) >= 2: # at least one row besides the header
|
if len(result) >= 2: # at least one row besides the header
|
||||||
return map(int, result[1:])
|
return list(map(int, result[1:]))
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def ps(self, **kwargs):
|
def ps(self, **kwargs):
|
||||||
command = 'ps -eo user,pid,ppid,vsize,rss,wchan,pcpu,state,fname'
|
command = 'ps -eo user,pid,ppid,vsize,rss,wchan,pcpu,state,fname'
|
||||||
lines = iter(convert_new_lines(self.execute(command)).split('\n'))
|
lines = iter(convert_new_lines(self.execute(command)).split('\n'))
|
||||||
lines.next() # header
|
next(lines) # header
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
parts = re.split(r'\s+', line, maxsplit=8)
|
parts = re.split(r'\s+', line, maxsplit=8)
|
||||||
if parts and parts != ['']:
|
if parts and parts != ['']:
|
||||||
result.append(PsEntry(*(parts[0:1] + map(int, parts[1:5]) + parts[5:])))
|
result.append(PsEntry(*(parts[0:1] + list(map(int, parts[1:5])) + parts[5:])))
|
||||||
|
|
||||||
if not kwargs:
|
if not kwargs:
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
filtered_result = []
|
filtered_result = []
|
||||||
for entry in result:
|
for entry in result:
|
||||||
if all(getattr(entry, k) == v for k, v in kwargs.iteritems()):
|
if all(getattr(entry, k) == v for k, v in kwargs.items()):
|
||||||
filtered_result.append(entry)
|
filtered_result.append(entry)
|
||||||
return filtered_result
|
return filtered_result
|
||||||
|
|
||||||
@ -952,7 +953,7 @@ class AndroidTarget(Target):
|
|||||||
|
|
||||||
mapped_result = []
|
mapped_result = []
|
||||||
for supported_abi in result:
|
for supported_abi in result:
|
||||||
for abi, architectures in ABI_MAP.iteritems():
|
for abi, architectures in ABI_MAP.items():
|
||||||
found = False
|
found = False
|
||||||
if supported_abi in architectures and abi not in mapped_result:
|
if supported_abi in architectures and abi not in mapped_result:
|
||||||
mapped_result.append(abi)
|
mapped_result.append(abi)
|
||||||
@ -1125,7 +1126,7 @@ class AndroidTarget(Target):
|
|||||||
|
|
||||||
def ps(self, **kwargs):
|
def ps(self, **kwargs):
|
||||||
lines = iter(convert_new_lines(self.execute('ps')).split('\n'))
|
lines = iter(convert_new_lines(self.execute('ps')).split('\n'))
|
||||||
lines.next() # header
|
next(lines) # header
|
||||||
result = []
|
result = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
parts = line.split(None, 8)
|
parts = line.split(None, 8)
|
||||||
@ -1134,13 +1135,13 @@ class AndroidTarget(Target):
|
|||||||
if len(parts) == 8:
|
if len(parts) == 8:
|
||||||
# wchan was blank; insert an empty field where it should be.
|
# wchan was blank; insert an empty field where it should be.
|
||||||
parts.insert(5, '')
|
parts.insert(5, '')
|
||||||
result.append(PsEntry(*(parts[0:1] + map(int, parts[1:5]) + parts[5:])))
|
result.append(PsEntry(*(parts[0:1] + list(map(int, parts[1:5])) + parts[5:])))
|
||||||
if not kwargs:
|
if not kwargs:
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
filtered_result = []
|
filtered_result = []
|
||||||
for entry in result:
|
for entry in result:
|
||||||
if all(getattr(entry, k) == v for k, v in kwargs.iteritems()):
|
if all(getattr(entry, k) == v for k, v in kwargs.items()):
|
||||||
filtered_result.append(entry)
|
filtered_result.append(entry)
|
||||||
return filtered_result
|
return filtered_result
|
||||||
|
|
||||||
@ -1188,7 +1189,10 @@ class AndroidTarget(Target):
|
|||||||
|
|
||||||
parsed_xml = xml.dom.minidom.parse(filepath)
|
parsed_xml = xml.dom.minidom.parse(filepath)
|
||||||
with open(filepath, 'w') as f:
|
with open(filepath, 'w') as f:
|
||||||
f.write(parsed_xml.toprettyxml().encode('utf-8'))
|
if sys.version_info[0] == 3:
|
||||||
|
f.write(parsed_xml.toprettyxml())
|
||||||
|
else:
|
||||||
|
f.write(parsed_xml.toprettyxml().encode('utf-8'))
|
||||||
|
|
||||||
def is_installed(self, name):
|
def is_installed(self, name):
|
||||||
return super(AndroidTarget, self).is_installed(name) or self.package_is_installed(name)
|
return super(AndroidTarget, self).is_installed(name) or self.package_is_installed(name)
|
||||||
@ -1626,7 +1630,7 @@ class KernelConfig(object):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
def iteritems(self):
|
def iteritems(self):
|
||||||
return self._config.iteritems()
|
return iter(self._config.items())
|
||||||
|
|
||||||
def __init__(self, text):
|
def __init__(self, text):
|
||||||
self.text = text
|
self.text = text
|
||||||
@ -1647,7 +1651,7 @@ class KernelConfig(object):
|
|||||||
def like(self, name):
|
def like(self, name):
|
||||||
regex = re.compile(name, re.I)
|
regex = re.compile(name, re.I)
|
||||||
result = {}
|
result = {}
|
||||||
for k, v in self._config.iteritems():
|
for k, v in self._config.items():
|
||||||
if regex.search(k):
|
if regex.search(k):
|
||||||
result[k] = v
|
result[k] = v
|
||||||
return result
|
return result
|
||||||
@ -1707,7 +1711,7 @@ def _get_part_name(section):
|
|||||||
implementer = section.get('CPU implementer', '0x0')
|
implementer = section.get('CPU implementer', '0x0')
|
||||||
part = section['CPU part']
|
part = section['CPU part']
|
||||||
variant = section.get('CPU variant', '0x0')
|
variant = section.get('CPU variant', '0x0')
|
||||||
name = get_cpu_name(*map(integer, [implementer, part, variant]))
|
name = get_cpu_name(*list(map(integer, [implementer, part, variant])))
|
||||||
if name is None:
|
if name is None:
|
||||||
name = '{}/{}/{}'.format(implementer, part, variant)
|
name = '{}/{}/{}'.format(implementer, part, variant)
|
||||||
return name
|
return name
|
||||||
@ -1730,13 +1734,13 @@ def _build_path_tree(path_map, basepath, sep=os.path.sep, dictcls=dict):
|
|||||||
process_node(node[parts[0]], parts[1], value)
|
process_node(node[parts[0]], parts[1], value)
|
||||||
|
|
||||||
relpath_map = {os.path.relpath(p, basepath): v
|
relpath_map = {os.path.relpath(p, basepath): v
|
||||||
for p, v in path_map.iteritems()}
|
for p, v in path_map.items()}
|
||||||
|
|
||||||
if len(relpath_map) == 1 and relpath_map.keys()[0] == '.':
|
if len(relpath_map) == 1 and list(relpath_map.keys())[0] == '.':
|
||||||
result = relpath_map.values()[0]
|
result = list(relpath_map.values())[0]
|
||||||
else:
|
else:
|
||||||
result = dictcls()
|
result = dictcls()
|
||||||
for path, value in relpath_map.iteritems():
|
for path, value in relpath_map.items():
|
||||||
process_node(result, path, value)
|
process_node(result, path, value)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -19,6 +19,7 @@ import json
|
|||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
from devlib.trace import TraceCollector
|
from devlib.trace import TraceCollector
|
||||||
from devlib.host import PACKAGE_BIN_DIRECTORY
|
from devlib.host import PACKAGE_BIN_DIRECTORY
|
||||||
@ -121,7 +122,7 @@ class FtraceCollector(TraceCollector):
|
|||||||
_event = '*' + event
|
_event = '*' + event
|
||||||
event_re = re.compile(_event.replace('*', '.*'))
|
event_re = re.compile(_event.replace('*', '.*'))
|
||||||
# Select events matching the required ones
|
# Select events matching the required ones
|
||||||
if len(filter(event_re.match, available_events)) == 0:
|
if len(list(filter(event_re.match, available_events))) == 0:
|
||||||
message = 'Event [{}] not available for tracing'.format(event)
|
message = 'Event [{}] not available for tracing'.format(event)
|
||||||
if strict:
|
if strict:
|
||||||
raise TargetError(message)
|
raise TargetError(message)
|
||||||
@ -276,6 +277,8 @@ class FtraceCollector(TraceCollector):
|
|||||||
self.logger.debug(command)
|
self.logger.debug(command)
|
||||||
process = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True)
|
process = subprocess.Popen(command, stderr=subprocess.PIPE, shell=True)
|
||||||
_, error = process.communicate()
|
_, error = process.communicate()
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
error = error.decode(sys.stdout.encoding)
|
||||||
if process.returncode:
|
if process.returncode:
|
||||||
raise TargetError('trace-cmd returned non-zero exit code {}'.format(process.returncode))
|
raise TargetError('trace-cmd returned non-zero exit code {}'.format(process.returncode))
|
||||||
if error:
|
if error:
|
||||||
|
@ -27,7 +27,8 @@ import logging
|
|||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
import tempfile
|
import tempfile
|
||||||
import Queue
|
import queue
|
||||||
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from devlib.exception import TargetError, HostError, DevlibError
|
from devlib.exception import TargetError, HostError, DevlibError
|
||||||
@ -88,7 +89,7 @@ class AndroidProperties(object):
|
|||||||
self._properties = dict(re.findall(r'\[(.*?)\]:\s+\[(.*?)\]', text))
|
self._properties = dict(re.findall(r'\[(.*?)\]:\s+\[(.*?)\]', text))
|
||||||
|
|
||||||
def iteritems(self):
|
def iteritems(self):
|
||||||
return self._properties.iteritems()
|
return iter(self._properties.items())
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self._properties)
|
return iter(self._properties)
|
||||||
@ -140,6 +141,8 @@ class ApkInfo(object):
|
|||||||
logger.debug(' '.join(command))
|
logger.debug(' '.join(command))
|
||||||
try:
|
try:
|
||||||
output = subprocess.check_output(command, stderr=subprocess.STDOUT)
|
output = subprocess.check_output(command, stderr=subprocess.STDOUT)
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
output = output.decode(sys.stdout.encoding)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
raise HostError('Error parsing APK file {}. `aapt` says:\n{}'
|
raise HostError('Error parsing APK file {}. `aapt` says:\n{}'
|
||||||
.format(apk_path, e.output))
|
.format(apk_path, e.output))
|
||||||
@ -160,7 +163,7 @@ class ApkInfo(object):
|
|||||||
mapped_abis = []
|
mapped_abis = []
|
||||||
for apk_abi in apk_abis:
|
for apk_abi in apk_abis:
|
||||||
found = False
|
found = False
|
||||||
for abi, architectures in ABI_MAP.iteritems():
|
for abi, architectures in ABI_MAP.items():
|
||||||
if apk_abi in architectures:
|
if apk_abi in architectures:
|
||||||
mapped_abis.append(abi)
|
mapped_abis.append(abi)
|
||||||
found = True
|
found = True
|
||||||
|
85
devlib/utils/csvutil.py
Normal file
85
devlib/utils/csvutil.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
'''
|
||||||
|
Due to the change in the nature of "binary mode" when opening files in
|
||||||
|
Python 3, the way files need to be opened for ``csv.reader`` and ``csv.writer``
|
||||||
|
is different from Python 2.
|
||||||
|
|
||||||
|
The functions in this module are intended to hide these differences allowing
|
||||||
|
the rest of the code to create csv readers/writers without worrying about which
|
||||||
|
Python version it is running under.
|
||||||
|
|
||||||
|
First up are ``csvwriter`` and ``csvreader`` context mangers that handle the
|
||||||
|
opening and closing of the underlying file. These are intended to replace the
|
||||||
|
most common usage pattern
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with open(filepath, 'wb') as wfh: # or open(filepath, 'w', newline='') in Python 3
|
||||||
|
writer = csv.writer(wfh)
|
||||||
|
writer.writerows(data)
|
||||||
|
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with csvwriter(filepath) as writer:
|
||||||
|
writer.writerows(data)
|
||||||
|
|
||||||
|
|
||||||
|
``csvreader`` works in an analogous way. ``csvreader`` and ``writer`` can take
|
||||||
|
additional arguments which will be passed directly to the
|
||||||
|
``csv.reader``/``csv.writer`` calls.
|
||||||
|
|
||||||
|
In some cases, it is desirable not to use a context manager (e.g. if the
|
||||||
|
reader/writer is intended to be returned from the function that creates it. For
|
||||||
|
such cases, alternative functions, ``create_reader`` and ``create_writer``,
|
||||||
|
exit. These return a two-tuple, with the created reader/writer as the first
|
||||||
|
element, and the corresponding ``FileObject`` as the second. It is the
|
||||||
|
responsibility of the calling code to ensure that the file is closed properly.
|
||||||
|
|
||||||
|
'''
|
||||||
|
import csv
|
||||||
|
import sys
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def csvwriter(filepath, *args, **kwargs):
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
wfh = open(filepath, 'w', newline='')
|
||||||
|
else:
|
||||||
|
wfh = open(filepath, 'wb')
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield csv.writer(wfh, *args, **kwargs)
|
||||||
|
finally:
|
||||||
|
wfh.close()
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def csvreader(filepath, *args, **kwargs):
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
fh = open(filepath, 'r', newline='')
|
||||||
|
else:
|
||||||
|
fh = open(filepath, 'rb')
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield csv.reader(fh, *args, **kwargs)
|
||||||
|
finally:
|
||||||
|
fh.close()
|
||||||
|
|
||||||
|
|
||||||
|
def create_writer(filepath, *args, **kwargs):
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
wfh = open(filepath, 'w', newline='')
|
||||||
|
else:
|
||||||
|
wfh = open(filepath, 'wb')
|
||||||
|
return csv.writer(wfh, *args, **kwargs), wfh
|
||||||
|
|
||||||
|
|
||||||
|
def create_reader(filepath, *args, **kwargs):
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
fh = open(filepath, 'r', newline='')
|
||||||
|
else:
|
||||||
|
fh = open(filepath, 'rb')
|
||||||
|
return csv.reader(fh, *args, **kwargs), fh
|
@ -45,7 +45,7 @@ def iter_statistics_dump(stats_file):
|
|||||||
k = res.group("key")
|
k = res.group("key")
|
||||||
vtext = res.group("value")
|
vtext = res.group("value")
|
||||||
try:
|
try:
|
||||||
v = map(numeric, vtext.split())
|
v = list(map(numeric, vtext.split()))
|
||||||
cur_dump[k] = v[0] if len(v)==1 else set(v)
|
cur_dump[k] = v[0] if len(v)==1 else set(v)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
msg = 'Found non-numeric entry in gem5 stats ({}: {})'
|
msg = 'Found non-numeric entry in gem5 stats ({}: {})'
|
||||||
|
@ -36,8 +36,10 @@ from itertools import groupby
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
import wrapt
|
import wrapt
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
from devlib.exception import HostError, TimeoutError
|
from devlib.exception import HostError, TimeoutError
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
|
||||||
# ABI --> architectures list
|
# ABI --> architectures list
|
||||||
@ -176,6 +178,9 @@ def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
output, error = process.communicate(inputtext)
|
output, error = process.communicate(inputtext)
|
||||||
|
if sys.version_info[0] == 3:
|
||||||
|
output = output.decode(sys.stdout.encoding)
|
||||||
|
error = error.decode(sys.stderr.encoding)
|
||||||
finally:
|
finally:
|
||||||
if timeout:
|
if timeout:
|
||||||
timer.cancel()
|
timer.cancel()
|
||||||
@ -185,7 +190,7 @@ def check_output(command, timeout=None, ignore=None, inputtext=None, **kwargs):
|
|||||||
if retcode == -9: # killed, assume due to timeout callback
|
if retcode == -9: # killed, assume due to timeout callback
|
||||||
raise TimeoutError(command, output='\n'.join([output, error]))
|
raise TimeoutError(command, output='\n'.join([output, error]))
|
||||||
elif ignore != 'all' and retcode not in ignore:
|
elif ignore != 'all' and retcode not in ignore:
|
||||||
raise subprocess.CalledProcessError(retcode, command, output='\n'.join([output, error]))
|
raise subprocess.CalledProcessError(retcode, command, output='\n'.join([str(output), str(error)]))
|
||||||
return output, error
|
return output, error
|
||||||
|
|
||||||
|
|
||||||
@ -257,8 +262,8 @@ def _merge_two_dicts(base, other, list_duplicates='all', match_types=False, # p
|
|||||||
dict_type=dict, should_normalize=True, should_merge_lists=True):
|
dict_type=dict, should_normalize=True, should_merge_lists=True):
|
||||||
"""Merge dicts normalizing their keys."""
|
"""Merge dicts normalizing their keys."""
|
||||||
merged = dict_type()
|
merged = dict_type()
|
||||||
base_keys = base.keys()
|
base_keys = list(base.keys())
|
||||||
other_keys = other.keys()
|
other_keys = list(other.keys())
|
||||||
norm = normalize if should_normalize else lambda x, y: x
|
norm = normalize if should_normalize else lambda x, y: x
|
||||||
|
|
||||||
base_only = []
|
base_only = []
|
||||||
@ -390,7 +395,7 @@ def normalize(value, dict_type=dict):
|
|||||||
no surrounding whitespace, underscore-delimited strings."""
|
no surrounding whitespace, underscore-delimited strings."""
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
normalized = dict_type()
|
normalized = dict_type()
|
||||||
for k, v in value.iteritems():
|
for k, v in value.items():
|
||||||
key = k.strip().lower().replace(' ', '_')
|
key = k.strip().lower().replace(' ', '_')
|
||||||
normalized[key] = normalize(v, dict_type)
|
normalized[key] = normalize(v, dict_type)
|
||||||
return normalized
|
return normalized
|
||||||
@ -431,7 +436,7 @@ def getch(count=1):
|
|||||||
"""Read ``count`` characters from standard input."""
|
"""Read ``count`` characters from standard input."""
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
import msvcrt # pylint: disable=F0401
|
import msvcrt # pylint: disable=F0401
|
||||||
return ''.join([msvcrt.getch() for _ in xrange(count)])
|
return ''.join([msvcrt.getch() for _ in range(count)])
|
||||||
else: # assume Unix
|
else: # assume Unix
|
||||||
import tty # NOQA
|
import tty # NOQA
|
||||||
import termios # NOQA
|
import termios # NOQA
|
||||||
@ -509,7 +514,7 @@ def strip_bash_colors(text):
|
|||||||
|
|
||||||
def get_random_string(length):
|
def get_random_string(length):
|
||||||
"""Returns a random ASCII string of the specified length)."""
|
"""Returns a random ASCII string of the specified length)."""
|
||||||
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in xrange(length))
|
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))
|
||||||
|
|
||||||
|
|
||||||
class LoadSyntaxError(Exception):
|
class LoadSyntaxError(Exception):
|
||||||
@ -526,7 +531,10 @@ class LoadSyntaxError(Exception):
|
|||||||
|
|
||||||
RAND_MOD_NAME_LEN = 30
|
RAND_MOD_NAME_LEN = 30
|
||||||
BAD_CHARS = string.punctuation + string.whitespace
|
BAD_CHARS = string.punctuation + string.whitespace
|
||||||
TRANS_TABLE = string.maketrans(BAD_CHARS, '_' * len(BAD_CHARS))
|
if sys.version_info[0] == 3:
|
||||||
|
TRANS_TABLE = str.maketrans(BAD_CHARS, '_' * len(BAD_CHARS))
|
||||||
|
else:
|
||||||
|
TRANS_TABLE = string.maketrans(BAD_CHARS, '_' * len(BAD_CHARS))
|
||||||
|
|
||||||
|
|
||||||
def to_identifier(text):
|
def to_identifier(text):
|
||||||
@ -555,8 +563,8 @@ def ranges_to_list(ranges_string):
|
|||||||
values = []
|
values = []
|
||||||
for rg in ranges_string.split(','):
|
for rg in ranges_string.split(','):
|
||||||
if '-' in rg:
|
if '-' in rg:
|
||||||
first, last = map(int, rg.split('-'))
|
first, last = list(map(int, rg.split('-')))
|
||||||
values.extend(xrange(first, last + 1))
|
values.extend(range(first, last + 1))
|
||||||
else:
|
else:
|
||||||
values.append(int(rg))
|
values.append(int(rg))
|
||||||
return values
|
return values
|
||||||
@ -565,8 +573,8 @@ def ranges_to_list(ranges_string):
|
|||||||
def list_to_ranges(values):
|
def list_to_ranges(values):
|
||||||
"""Converts a list, e.g ``[0,2,3,4]``, into a sysfs-style ranges string, e.g. ``"0,2-4"``"""
|
"""Converts a list, e.g ``[0,2,3,4]``, into a sysfs-style ranges string, e.g. ``"0,2-4"``"""
|
||||||
range_groups = []
|
range_groups = []
|
||||||
for _, g in groupby(enumerate(values), lambda (i, x): i - x):
|
for _, g in groupby(enumerate(values), lambda i_x: i_x[0] - i_x[1]):
|
||||||
range_groups.append(map(itemgetter(1), g))
|
range_groups.append(list(map(itemgetter(1), g)))
|
||||||
range_strings = []
|
range_strings = []
|
||||||
for group in range_groups:
|
for group in range_groups:
|
||||||
if len(group) == 1:
|
if len(group) == 1:
|
||||||
@ -589,7 +597,7 @@ def mask_to_list(mask):
|
|||||||
"""Converts the specfied integer bitmask into a list of
|
"""Converts the specfied integer bitmask into a list of
|
||||||
indexes of bits that are set in the mask."""
|
indexes of bits that are set in the mask."""
|
||||||
size = len(bin(mask)) - 2 # because of "0b"
|
size = len(bin(mask)) - 2 # because of "0b"
|
||||||
return [size - i - 1 for i in xrange(size)
|
return [size - i - 1 for i in range(size)
|
||||||
if mask & (1 << size - i - 1)]
|
if mask & (1 << size - i - 1)]
|
||||||
|
|
||||||
|
|
||||||
@ -634,7 +642,7 @@ def memoized(wrapped, instance, args, kwargs):
|
|||||||
def memoize_wrapper(*args, **kwargs):
|
def memoize_wrapper(*args, **kwargs):
|
||||||
id_string = func_id + ','.join([__get_memo_id(a) for a in args])
|
id_string = func_id + ','.join([__get_memo_id(a) for a in args])
|
||||||
id_string += ','.join('{}={}'.format(k, v)
|
id_string += ','.join('{}={}'.format(k, v)
|
||||||
for k, v in kwargs.iteritems())
|
for k, v in kwargs.items())
|
||||||
if id_string not in __memo_cache:
|
if id_string not in __memo_cache:
|
||||||
__memo_cache[id_string] = wrapped(*args, **kwargs)
|
__memo_cache[id_string] = wrapped(*args, **kwargs)
|
||||||
return __memo_cache[id_string]
|
return __memo_cache[id_string]
|
||||||
|
@ -67,7 +67,7 @@ class AepParser(object):
|
|||||||
virtual = {}
|
virtual = {}
|
||||||
|
|
||||||
# Create an entry for each virtual parent
|
# Create an entry for each virtual parent
|
||||||
for supply in topo.iterkeys():
|
for supply in topo.keys():
|
||||||
index = topo[supply]['index']
|
index = topo[supply]['index']
|
||||||
# Don't care of hidden columns
|
# Don't care of hidden columns
|
||||||
if hide[index]:
|
if hide[index]:
|
||||||
@ -85,11 +85,11 @@ class AepParser(object):
|
|||||||
|
|
||||||
# Remove parent with 1 child as they don't give more information than their
|
# Remove parent with 1 child as they don't give more information than their
|
||||||
# child
|
# child
|
||||||
for supply in virtual.keys():
|
for supply in list(virtual.keys()):
|
||||||
if len(virtual[supply]) == 1:
|
if len(virtual[supply]) == 1:
|
||||||
del virtual[supply];
|
del virtual[supply];
|
||||||
|
|
||||||
for supply in virtual.keys():
|
for supply in list(virtual.keys()):
|
||||||
# Add label, hide and duplicate columns for virtual domains
|
# Add label, hide and duplicate columns for virtual domains
|
||||||
hide.append(0)
|
hide.append(0)
|
||||||
duplicate.append(1)
|
duplicate.append(1)
|
||||||
@ -166,9 +166,9 @@ class AepParser(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def add_virtual_data(data, virtual):
|
def add_virtual_data(data, virtual):
|
||||||
# write virtual domain
|
# write virtual domain
|
||||||
for parent in virtual.iterkeys():
|
for parent in virtual.keys():
|
||||||
power = 0
|
power = 0
|
||||||
for child in virtual[parent].values():
|
for child in list(virtual[parent].values()):
|
||||||
try:
|
try:
|
||||||
power += data[child]
|
power += data[child]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@ -440,7 +440,7 @@ class AepParser(object):
|
|||||||
|
|
||||||
|
|
||||||
# Create an entry for each virtual parent
|
# Create an entry for each virtual parent
|
||||||
for supply in topo.iterkeys():
|
for supply in topo.keys():
|
||||||
# Parent is in the topology
|
# Parent is in the topology
|
||||||
parent = topo[supply]['parent']
|
parent = topo[supply]['parent']
|
||||||
if parent in topo:
|
if parent in topo:
|
||||||
@ -454,15 +454,15 @@ class AepParser(object):
|
|||||||
|
|
||||||
# Remove parent with 1 child as they don't give more information than their
|
# Remove parent with 1 child as they don't give more information than their
|
||||||
# child
|
# child
|
||||||
for supply in virtual.keys():
|
for supply in list(virtual.keys()):
|
||||||
if len(virtual[supply]) == 1:
|
if len(virtual[supply]) == 1:
|
||||||
del virtual[supply];
|
del virtual[supply];
|
||||||
|
|
||||||
topo_list = ['']*(1+len(topo)+len(virtual))
|
topo_list = ['']*(1+len(topo)+len(virtual))
|
||||||
topo_list[0] = 'time'
|
topo_list[0] = 'time'
|
||||||
for chnl in topo.iterkeys():
|
for chnl in topo.keys():
|
||||||
topo_list[topo[chnl]['index']] = chnl
|
topo_list[topo[chnl]['index']] = chnl
|
||||||
for chnl in virtual.iterkeys():
|
for chnl in virtual.keys():
|
||||||
index +=1
|
index +=1
|
||||||
topo_list[index] = chnl
|
topo_list[index] = chnl
|
||||||
|
|
||||||
@ -495,7 +495,7 @@ if __name__ == '__main__':
|
|||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], "i:vo:s:l:t:")
|
opts, args = getopt.getopt(sys.argv[1:], "i:vo:s:l:t:")
|
||||||
except getopt.GetoptError as err:
|
except getopt.GetoptError as err:
|
||||||
print str(err) # will print something like "option -a not recognized"
|
print(str(err)) # will print something like "option -a not recognized"
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
@ -513,7 +513,7 @@ if __name__ == '__main__':
|
|||||||
if o == "-t":
|
if o == "-t":
|
||||||
topofile = a
|
topofile = a
|
||||||
parser = AepParser()
|
parser = AepParser()
|
||||||
print parser.topology_from_config(topofile)
|
print(parser.topology_from_config(topofile))
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
parser = AepParser()
|
parser = AepParser()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import csv
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -11,6 +10,7 @@ from collections import namedtuple, OrderedDict
|
|||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
from devlib.exception import WorkerThreadError, TargetNotRespondingError, TimeoutError
|
from devlib.exception import WorkerThreadError, TargetNotRespondingError, TimeoutError
|
||||||
|
from devlib.utils.csvutil import csvwriter
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('rendering')
|
logger = logging.getLogger('rendering')
|
||||||
@ -53,7 +53,7 @@ class FrameCollector(threading.Thread):
|
|||||||
wfh.close()
|
wfh.close()
|
||||||
except (TargetNotRespondingError, TimeoutError): # pylint: disable=W0703
|
except (TargetNotRespondingError, TimeoutError): # pylint: disable=W0703
|
||||||
raise
|
raise
|
||||||
except Exception, e: # pylint: disable=W0703
|
except Exception as e: # pylint: disable=W0703
|
||||||
logger.warning('Exception on collector thread: {}({})'.format(e.__class__.__name__, e))
|
logger.warning('Exception on collector thread: {}({})'.format(e.__class__.__name__, e))
|
||||||
self.exc = WorkerThreadError(self.name, sys.exc_info())
|
self.exc = WorkerThreadError(self.name, sys.exc_info())
|
||||||
logger.debug('Surface flinger frame data collection stopped.')
|
logger.debug('Surface flinger frame data collection stopped.')
|
||||||
@ -93,8 +93,7 @@ class FrameCollector(threading.Thread):
|
|||||||
indexes.append(self.header.index(c))
|
indexes.append(self.header.index(c))
|
||||||
frames = [[f[i] for i in indexes] for f in self.frames]
|
frames = [[f[i] for i in indexes] for f in self.frames]
|
||||||
header = columns
|
header = columns
|
||||||
with open(outfile, 'w') as wfh:
|
with csvwriter(outfile) as writer:
|
||||||
writer = csv.writer(wfh)
|
|
||||||
if header:
|
if header:
|
||||||
writer.writerow(header)
|
writer.writerow(header)
|
||||||
writer.writerows(frames)
|
writer.writerows(frames)
|
||||||
@ -142,7 +141,7 @@ class SurfaceFlingerFrameCollector(FrameCollector):
|
|||||||
def _process_trace_line(self, line):
|
def _process_trace_line(self, line):
|
||||||
parts = line.split()
|
parts = line.split()
|
||||||
if len(parts) == 3:
|
if len(parts) == 3:
|
||||||
frame = SurfaceFlingerFrame(*map(int, parts))
|
frame = SurfaceFlingerFrame(*list(map(int, parts)))
|
||||||
if not frame.frame_ready_time:
|
if not frame.frame_ready_time:
|
||||||
return # "null" frame
|
return # "null" frame
|
||||||
if frame.frame_ready_time <= self.last_ready_time:
|
if frame.frame_ready_time <= self.last_ready_time:
|
||||||
@ -167,7 +166,7 @@ def read_gfxinfo_columns(target):
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
if line.startswith('---PROFILEDATA---'):
|
if line.startswith('---PROFILEDATA---'):
|
||||||
break
|
break
|
||||||
columns_line = lines.next()
|
columns_line = next(lines)
|
||||||
return columns_line.split(',')[:-1] # has a trailing ','
|
return columns_line.split(',')[:-1] # has a trailing ','
|
||||||
|
|
||||||
|
|
||||||
@ -202,11 +201,11 @@ class GfxinfoFrameCollector(FrameCollector):
|
|||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
|
|
||||||
fh.next() # headers
|
next(fh) # headers
|
||||||
for line in fh:
|
for line in fh:
|
||||||
if line.startswith('---PROFILEDATA---'):
|
if line.startswith('---PROFILEDATA---'):
|
||||||
break
|
break
|
||||||
entries = map(int, line.strip().split(',')[:-1]) # has a trailing ','
|
entries = list(map(int, line.strip().split(',')[:-1])) # has a trailing ','
|
||||||
if entries[1] <= last_vsync:
|
if entries[1] <= last_vsync:
|
||||||
continue # repeat frame
|
continue # repeat frame
|
||||||
last_vsync = entries[1]
|
last_vsync = entries[1]
|
||||||
@ -240,14 +239,14 @@ def gfxinfo_get_last_dump(filepath):
|
|||||||
fh_iter = _file_reverse_iter(fh)
|
fh_iter = _file_reverse_iter(fh)
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
buf = fh_iter.next()
|
buf = next(fh_iter)
|
||||||
ix = buf.find('** Graphics')
|
ix = buf.find('** Graphics')
|
||||||
if ix >= 0:
|
if ix >= 0:
|
||||||
return buf[ix:] + record
|
return buf[ix:] + record
|
||||||
|
|
||||||
ix = buf.find(' **\n')
|
ix = buf.find(' **\n')
|
||||||
if ix >= 0:
|
if ix >= 0:
|
||||||
buf = fh_iter.next() + buf
|
buf = next(fh_iter) + buf
|
||||||
ix = buf.find('** Graphics')
|
ix = buf.find('** Graphics')
|
||||||
if ix < 0:
|
if ix < 0:
|
||||||
msg = '"{}" appears to be corrupted'
|
msg = '"{}" appears to be corrupted'
|
||||||
|
@ -23,6 +23,7 @@ import threading
|
|||||||
import tempfile
|
import tempfile
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pexpect
|
import pexpect
|
||||||
@ -236,7 +237,7 @@ class SshConnection(object):
|
|||||||
def cancel_running_command(self):
|
def cancel_running_command(self):
|
||||||
# simulate impatiently hitting ^C until command prompt appears
|
# simulate impatiently hitting ^C until command prompt appears
|
||||||
logger.debug('Sending ^C')
|
logger.debug('Sending ^C')
|
||||||
for _ in xrange(self.max_cancel_attempts):
|
for _ in range(self.max_cancel_attempts):
|
||||||
self.conn.sendline(chr(3))
|
self.conn.sendline(chr(3))
|
||||||
if self.conn.prompt(0.1):
|
if self.conn.prompt(0.1):
|
||||||
return True
|
return True
|
||||||
@ -263,7 +264,10 @@ class SshConnection(object):
|
|||||||
timed_out = self._wait_for_prompt(timeout)
|
timed_out = self._wait_for_prompt(timeout)
|
||||||
# the regex removes line breaks potential introduced when writing
|
# the regex removes line breaks potential introduced when writing
|
||||||
# command to shell.
|
# command to shell.
|
||||||
output = process_backspaces(self.conn.before)
|
if sys.version_info[0] == 3:
|
||||||
|
output = process_backspaces(self.conn.before.decode(sys.stdout.encoding))
|
||||||
|
else:
|
||||||
|
output = process_backspaces(self.conn.before)
|
||||||
output = re.sub(r'\r([^\n])', r'\1', output)
|
output = re.sub(r'\r([^\n])', r'\1', output)
|
||||||
if '\r\n' in output: # strip the echoed command
|
if '\r\n' in output: # strip the echoed command
|
||||||
output = output.split('\r\n', 1)[1]
|
output = output.split('\r\n', 1)[1]
|
||||||
@ -604,7 +608,7 @@ class Gem5Connection(TelnetConnection):
|
|||||||
break
|
break
|
||||||
except pxssh.ExceptionPxssh:
|
except pxssh.ExceptionPxssh:
|
||||||
pass
|
pass
|
||||||
except EOF, err:
|
except EOF as err:
|
||||||
self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
|
self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
|
||||||
else:
|
else:
|
||||||
gem5_simulation.kill()
|
gem5_simulation.kill()
|
||||||
@ -626,7 +630,7 @@ class Gem5Connection(TelnetConnection):
|
|||||||
self._login_to_device()
|
self._login_to_device()
|
||||||
except TIMEOUT:
|
except TIMEOUT:
|
||||||
pass
|
pass
|
||||||
except EOF, err:
|
except EOF as err:
|
||||||
self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
|
self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -636,7 +640,7 @@ class Gem5Connection(TelnetConnection):
|
|||||||
prompt_found = True
|
prompt_found = True
|
||||||
except TIMEOUT:
|
except TIMEOUT:
|
||||||
pass
|
pass
|
||||||
except EOF, err:
|
except EOF as err:
|
||||||
self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
|
self._gem5_EOF_handler(gem5_simulation, gem5_out_dir, err)
|
||||||
|
|
||||||
gem5_logger.info("Successfully logged in")
|
gem5_logger.info("Successfully logged in")
|
||||||
|
@ -26,6 +26,9 @@ is not the best language to use for configuration.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import math
|
import math
|
||||||
|
from functools import total_ordering
|
||||||
|
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
from devlib.utils.misc import isiterable, to_identifier, ranges_to_list, list_to_mask
|
from devlib.utils.misc import isiterable, to_identifier, ranges_to_list, list_to_mask
|
||||||
|
|
||||||
@ -88,6 +91,7 @@ def numeric(value):
|
|||||||
return fvalue
|
return fvalue
|
||||||
|
|
||||||
|
|
||||||
|
@total_ordering
|
||||||
class caseless_string(str):
|
class caseless_string(str):
|
||||||
"""
|
"""
|
||||||
Just like built-in Python string except case-insensitive on comparisons. However, the
|
Just like built-in Python string except case-insensitive on comparisons. However, the
|
||||||
@ -100,13 +104,13 @@ class caseless_string(str):
|
|||||||
other = other.lower()
|
other = other.lower()
|
||||||
return self.lower() == other
|
return self.lower() == other
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __lt__(self, other):
|
||||||
return not self.__eq__(other)
|
if isinstance(other, basestring):
|
||||||
|
|
||||||
def __cmp__(self, other):
|
|
||||||
if isinstance(basestring, other):
|
|
||||||
other = other.lower()
|
other = other.lower()
|
||||||
return cmp(self.lower(), other)
|
return self.lower() < other
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return hash(self.lower())
|
||||||
|
|
||||||
def format(self, *args, **kwargs):
|
def format(self, *args, **kwargs):
|
||||||
return caseless_string(super(caseless_string, self).format(*args, **kwargs))
|
return caseless_string(super(caseless_string, self).format(*args, **kwargs))
|
||||||
|
@ -19,6 +19,8 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
|
from past.builtins import basestring
|
||||||
|
|
||||||
from devlib.utils.serial_port import write_characters, TIMEOUT
|
from devlib.utils.serial_port import write_characters, TIMEOUT
|
||||||
from devlib.utils.types import boolean
|
from devlib.utils.types import boolean
|
||||||
|
|
||||||
@ -193,14 +195,14 @@ class UefiMenu(object):
|
|||||||
is not in the current menu, ``LookupError`` will be raised."""
|
is not in the current menu, ``LookupError`` will be raised."""
|
||||||
if not self.prompt:
|
if not self.prompt:
|
||||||
self.read_menu(timeout)
|
self.read_menu(timeout)
|
||||||
return self.options.items()
|
return list(self.options.items())
|
||||||
|
|
||||||
def get_option_index(self, text, timeout=default_timeout):
|
def get_option_index(self, text, timeout=default_timeout):
|
||||||
"""Returns the menu index of the specified option text (uses regex matching). If the option
|
"""Returns the menu index of the specified option text (uses regex matching). If the option
|
||||||
is not in the current menu, ``LookupError`` will be raised."""
|
is not in the current menu, ``LookupError`` will be raised."""
|
||||||
if not self.prompt:
|
if not self.prompt:
|
||||||
self.read_menu(timeout)
|
self.read_menu(timeout)
|
||||||
for k, v in self.options.iteritems():
|
for k, v in self.options.items():
|
||||||
if re.search(text, v):
|
if re.search(text, v):
|
||||||
return k
|
return k
|
||||||
raise LookupError(text)
|
raise LookupError(text)
|
||||||
|
3
setup.py
3
setup.py
@ -70,6 +70,7 @@ params = dict(
|
|||||||
'pexpect>=3.3', # Send/recieve to/from device
|
'pexpect>=3.3', # Send/recieve to/from device
|
||||||
'pyserial', # Serial port interface
|
'pyserial', # Serial port interface
|
||||||
'wrapt', # Basic for construction of decorator functions
|
'wrapt', # Basic for construction of decorator functions
|
||||||
|
'future', # Python 2-3 compatibility
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
'daq': ['daqpower'],
|
'daq': ['daqpower'],
|
||||||
@ -85,7 +86,7 @@ params = dict(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
all_extras = list(chain(params['extras_require'].itervalues()))
|
all_extras = list(chain(iter(params['extras_require'].values())))
|
||||||
params['extras_require']['full'] = all_extras
|
params['extras_require']['full'] = all_extras
|
||||||
|
|
||||||
setup(**params)
|
setup(**params)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user