• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import logging
2
3
4BIG_CPUS = ['A15', 'A57', 'A72']
5
6
7class Platform(object):
8
9    @property
10    def number_of_clusters(self):
11        return len(set(self.core_clusters))
12
13    def __init__(self,
14                 name=None,
15                 core_names=None,
16                 core_clusters=None,
17                 big_core=None,
18                 model=None,
19                 modules=None,
20                 ):
21        self.name = name
22        self.core_names = core_names or []
23        self.core_clusters = core_clusters or []
24        self.big_core = big_core
25        self.little_core = None
26        self.model = model
27        self.modules = modules or []
28        self.logger = logging.getLogger(self.name)
29        if not self.core_clusters and self.core_names:
30            self._set_core_clusters_from_core_names()
31
32    def init_target_connection(self, target):
33        # May be ovewritten by subclasses to provide target-specific
34        # connection initialisation.
35        pass
36
37    def update_from_target(self, target):
38        if not self.core_names:
39            self.core_names = target.cpuinfo.cpu_names
40            self._set_core_clusters_from_core_names()
41        if not self.big_core and self.number_of_clusters == 2:
42            self.big_core = self._identify_big_core()
43        if not self.core_clusters and self.core_names:
44            self._set_core_clusters_from_core_names()
45        if not self.model:
46            self._set_model_from_target(target)
47        if not self.name:
48            self.name = self.model
49        self._validate()
50
51    def setup(self, target):
52        # May be overwritten by subclasses to provide platform-specific
53        # setup procedures.
54        pass
55
56    def _set_core_clusters_from_core_names(self):
57        self.core_clusters = []
58        clusters = []
59        for cn in self.core_names:
60            if cn not in clusters:
61                clusters.append(cn)
62            self.core_clusters.append(clusters.index(cn))
63
64    def _set_model_from_target(self, target):
65        if target.os == 'android':
66            self.model = target.getprop('ro.product.model')
67        elif target.is_rooted:
68            try:
69                self.model = target.execute('dmidecode -s system-version',
70                                            as_root=True).strip()
71            except Exception:  # pylint: disable=broad-except
72                pass  # this is best-effort
73
74    def _identify_big_core(self):
75        for core in self.core_names:
76            if core.upper() in BIG_CPUS:
77                return core
78        big_idx = self.core_clusters.index(max(self.core_clusters))
79        return self.core_names[big_idx]
80
81    def _validate(self):
82        if len(self.core_names) != len(self.core_clusters):
83            raise ValueError('core_names and core_clusters are of different lengths.')
84        if self.big_core and self.number_of_clusters != 2:
85            raise ValueError('attempting to set big_core on non-big.LITTLE device. '
86                             '(number of clusters  is not 2)')
87        if self.big_core and self.big_core not in self.core_names:
88            message = 'Invalid big_core value "{}"; must be in [{}]'
89            raise ValueError(message.format(self.big_core,
90                                            ', '.join(set(self.core_names))))
91        if self.big_core:
92            for core in self.core_names:
93                if core != self.big_core:
94                    self.little_core = core
95                    break
96