diff options
author | Ciro Santilli <ciro.santilli@arm.com> | 2018-09-13 14:54:34 +0100 |
---|---|---|
committer | Ciro Santilli <ciro.santilli@arm.com> | 2018-10-19 17:12:35 +0000 |
commit | 3cceef1316f75366ca0ddbbe0f86eb0342529df3 (patch) | |
tree | 48fbbc22921bbf384317f2c287fbc0c359df6d0f | |
parent | fcc379674201ea8eb23b2cfc9bf22d7d0925f65c (diff) | |
download | gem5-3cceef1316f75366ca0ddbbe0f86eb0342529df3.tar.xz |
python: Add utility function to override config parameters
Add a utility method, SimObject.apply_config that can be used to
implement SimObject param overrides from the command line. This
function provides safe and convenient semantics for CLI assignment:
* The override expression is evaluated in a restricted environment. The
only global variables are the child objects and params from the root
object.
* Only params can be overridden. For example, calling methods or setting
attributes on SimObjects isn't possible.
* Vectors use non-standard list semantics which enable something similar
to glob expansion on the shell. For example, setting:
root.system.cpu[0:2].numThreads = 2
will override numThreads for cpu 0 and 1 and:
root.system.cpus[0,2].numThreads = 2
sets it for cpus 0 and 2.
The intention is that the helper method is called to override default
values before calling m5.instantiate.
Change-Id: I73f99da21d6d8ce1ff2ec8db2bb34338456f6799
Reviewed-on: https://gem5-review.googlesource.com/c/12984
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
-rw-r--r-- | src/python/m5/SimObject.py | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 0a5436f5b..44f26ea9b 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 ARM Limited +# Copyright (c) 2017-2018 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -934,6 +934,63 @@ class ParamInfo(object): if not "created" in self.__dict__: self.__dict__[name] = value +class SimObjectCliWrapperException(Exception): + def __init__(self, message): + super(Exception, self).__init__(message) + +class SimObjectCliWrapper(object): + """ + Wrapper class to restrict operations that may be done + from the command line on SimObjects. + + Only parameters may be set, and only children may be accessed. + + Slicing allows for multiple simultaneous assignment of items in + one statement. + """ + + def __init__(self, sim_objects): + self.__dict__['_sim_objects'] = list(sim_objects) + + def __getattr__(self, key): + return SimObjectCliWrapper(sim_object._children[key] + for sim_object in self._sim_objects) + + def __setattr__(self, key, val): + for sim_object in self._sim_objects: + if key in sim_object._params: + if sim_object._params[key].isCmdLineSettable(): + setattr(sim_object, key, val) + else: + raise SimObjectCliWrapperException( + 'tried to set or unsettable' \ + 'object parameter: ' + key) + else: + raise SimObjectCliWrapperException( + 'tried to set or access non-existent' \ + 'object parameter: ' + key) + + def __getitem__(self, idx): + """ + Extends the list() semantics to also allow tuples, + for example object[1, 3] selects items 1 and 3. + """ + out = [] + if isinstance(idx, tuple): + for t in idx: + out.extend(self[t]._sim_objects) + else: + if isinstance(idx, int): + _range = range(idx, idx + 1) + elif not isinstance(idx, slice): + raise SimObjectCliWrapperException( \ + 'invalid index type: ' + repr(idx)) + for sim_object in self._sim_objects: + if isinstance(idx, slice): + _range = range(*idx.indices(len(sim_object))) + out.extend(sim_object[i] for i in _range) + return SimObjectCliWrapper(out) + # The SimObject class is the root of the special hierarchy. Most of # the code in this class deals with the configuration hierarchy itself # (parent/child node relationships). @@ -1525,6 +1582,30 @@ class SimObject(object): for dt in item.generateDeviceTree(state): yield dt + # On a separate method otherwise certain buggy Python versions + # would fail with: SyntaxError: unqualified exec is not allowed + # in function 'apply_config' + def _apply_config_get_dict(self): + return { + child_name: SimObjectCliWrapper( + iter(self._children[child_name])) + for child_name in self._children + } + + def apply_config(self, params): + """ + exec a list of Python code strings contained in params. + + The only exposed globals to those strings are the child + SimObjects of this node. + + This function is intended to allow users to modify SimObject + parameters from the command line with Python statements. + """ + d = self._apply_config_get_dict() + for param in params: + exec(param, d) + # Function to provide to C++ so it can look up instances based on paths def resolveSimObject(name): obj = instanceDict[name] |