From 3cceef1316f75366ca0ddbbe0f86eb0342529df3 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Thu, 13 Sep 2018 14:54:34 +0100 Subject: [PATCH] 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 Reviewed-by: Andreas Sandberg Maintainer: Jason Lowe-Power --- src/python/m5/SimObject.py | 83 +++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) 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] -- 2.30.2