mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-31 15:12:25 +00:00 
			
		
		
		
	Merge pull request #52 from ep1cman/freqsweep
Added freqsweep instrument
This commit is contained in:
		
							
								
								
									
										141
									
								
								wlauto/instrumentation/freqsweep/__init__.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										141
									
								
								wlauto/instrumentation/freqsweep/__init__.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| #    Copyright 2015 ARM Limited | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| # pylint: disable=access-member-before-definition,attribute-defined-outside-init | ||||
|  | ||||
| import os | ||||
| from wlauto import Instrument, Parameter | ||||
| from wlauto.exceptions import ConfigError, InstrumentError | ||||
| from wlauto.utils.types import caseless_string | ||||
|  | ||||
|  | ||||
| class FreqSweep(Instrument): | ||||
|     name = 'freq_sweep' | ||||
|     description = """ | ||||
|     Sweeps workloads through all available frequencies on a device. | ||||
|  | ||||
|     When enabled this instrument will take all workloads specified in an agenda | ||||
|     and run them at all available frequencies for all clusters. | ||||
|  | ||||
|     Recommendations: | ||||
|         - Setting the runner to 'by_spec' increases the chance of successfully | ||||
|           completing an agenda without encountering hotplug issues | ||||
|         - If possible disable dynamic hotplug on the target device | ||||
|     """ | ||||
|  | ||||
|     parameters = [ | ||||
|         Parameter('sweeps', kind=list, | ||||
|                   description=""" | ||||
|                   By default this instrument will sweep across all available | ||||
|                   frequencies for all available clusters. If you wish to only | ||||
|                   sweep across certain frequencies on particular clusters you | ||||
|                   can do so by specifying this parameter. | ||||
|  | ||||
|                   Sweeps should be a lists of dictionaries that can contain: | ||||
|                     - Cluster (mandatory): The name of the cluster this sweep will be | ||||
|                                            performed on. E.g A7 | ||||
|                     - Frequencies: A list of frequencies (in KHz) to use. If this is | ||||
|                                    not provided all frequencies available for this | ||||
|                                    cluster will be used. | ||||
|                                    E.g: [800000, 900000, 100000] | ||||
|                     - label: Workload specs will be named '{spec id}_{label}_{frequency}'. | ||||
|                              If a label is not provided it will be named 'sweep{sweep No.}' | ||||
|  | ||||
|                  Example sweep specification: | ||||
|  | ||||
|                      freq_sweep: | ||||
|                          sweeps: | ||||
|                              - cluster: A53 | ||||
|                                label: littles | ||||
|                                frequencies: [800000, 900000, 100000] | ||||
|                              - cluster: A57 | ||||
|                                label: bigs | ||||
|                   """), | ||||
|     ] | ||||
|  | ||||
|     def validate(self): | ||||
|         if not self.device.core_names: | ||||
|             raise ConfigError('The Device does not appear to have core_names configured.') | ||||
|  | ||||
|     def initialize(self, context):  # pylint: disable=r0912 | ||||
|         if not self.device.is_rooted: | ||||
|             raise InstrumentError('The device must be rooted to sweep frequencies') | ||||
|  | ||||
|         if 'userspace' not in self.device.list_available_cluster_governors(0): | ||||
|             raise InstrumentError("'userspace' cpufreq governor must be enabled") | ||||
|  | ||||
|         # Create sweeps for each core type using num_cpus cores | ||||
|         if not self.sweeps: | ||||
|             self.sweeps = [] | ||||
|             for core in set(self.device.core_names): | ||||
|                 sweep_spec = {} | ||||
|                 sweep_spec['cluster'] = core | ||||
|                 sweep_spec['label'] = core | ||||
|                 self.sweeps.append(sweep_spec) | ||||
|  | ||||
|         new_specs = [] | ||||
|         old_specs = [] | ||||
|         for job in context.runner.job_queue: | ||||
|             if job.spec not in old_specs: | ||||
|                 old_specs.append(job.spec) | ||||
|  | ||||
|         # Validate sweeps, add missing sections and create workload specs | ||||
|         for i, sweep_spec in enumerate(self.sweeps): | ||||
|             if 'cluster' not in sweep_spec: | ||||
|                 raise ConfigError('cluster must be define for all sweeps') | ||||
|             # Check if cluster exists on device | ||||
|             if caseless_string(sweep_spec['cluster']) not in self.device.core_names: | ||||
|                 raise ConfigError('Only {} cores are present on this device, you specified {}' | ||||
|                                   .format(", ".join(set(self.device.core_names)), sweep_spec['cluster'])) | ||||
|  | ||||
|             # Default to all available frequencies | ||||
|             if 'frequencies' not in sweep_spec: | ||||
|                 self.device.enable_cpu(self.device.core_names.index(sweep_spec['cluster'])) | ||||
|                 sweep_spec['frequencies'] = self.device.list_available_core_frequencies(sweep_spec['cluster']) | ||||
|  | ||||
|             # Check that given frequencies are valid of the core cluster | ||||
|             else: | ||||
|                 self.device.enable_cpu(self.device.core_names.index(sweep_spec['cluster'])) | ||||
|                 available_freqs = self.device.list_available_core_frequencies(sweep_spec['cluster']) | ||||
|                 for freq in sweep_spec['frequencies']: | ||||
|                     if freq not in available_freqs: | ||||
|                         raise ConfigError('Frequency {} is not supported by {} cores'.format(freq, sweep_spec['cluster'])) | ||||
|  | ||||
|             # Add default labels | ||||
|             if 'label' not in sweep_spec: | ||||
|                 sweep_spec['label'] = "sweep{}".format(i + 1) | ||||
|  | ||||
|             new_specs.extend(self.get_sweep_workload_specs(old_specs, sweep_spec, context)) | ||||
|  | ||||
|         # Update config to refect jobs that will actually run. | ||||
|         context.config.workload_specs = new_specs | ||||
|         config_file = os.path.join(context.host_working_directory, 'run_config.json') | ||||
|         with open(config_file, 'wb') as wfh: | ||||
|             context.config.serialize(wfh) | ||||
|         context.runner.init_queue(new_specs) | ||||
|  | ||||
|     def get_sweep_workload_specs(self, old_specs, sweep_spec, context): | ||||
|         new_specs = [] | ||||
|         for old_spec in old_specs: | ||||
|             for freq in sweep_spec['frequencies']: | ||||
|                 spec = old_spec.copy() | ||||
|                 spec.runtime_parameters['{}_governor'.format(sweep_spec['cluster'])] = "userspace" | ||||
|                 spec.runtime_parameters['{}_frequency'.format(sweep_spec['cluster'])] = freq | ||||
|                 spec.id = '{}_{}_{}'.format(spec.id, sweep_spec['label'], freq) | ||||
|                 spec.classifiers['core'] = sweep_spec['cluster'] | ||||
|                 spec.classifiers['freq'] = freq | ||||
|                 spec.load(self.device, context.config.ext_loader) | ||||
|                 spec.workload.init_resources(context) | ||||
|                 spec.workload.validate() | ||||
|                 new_specs.append(spec) | ||||
|         return new_specs | ||||
		Reference in New Issue
	
	Block a user