diff --git a/src/python/m5/ext/pystats/abstract_stat.py b/src/python/m5/ext/pystats/abstract_stat.py index 511ee363e0..f2a75fca1e 100644 --- a/src/python/m5/ext/pystats/abstract_stat.py +++ b/src/python/m5/ext/pystats/abstract_stat.py @@ -26,6 +26,15 @@ from .serializable_stat import SerializableStat +import re +from typing import ( + Callable, + List, + Optional, + Pattern, + Union, +) + class AbstractStat(SerializableStat): """ @@ -34,4 +43,55 @@ class AbstractStat(SerializableStat): All PyStats are JsonSerializable. """ - pass + def children( + self, + predicate: Optional[Callable[[str], bool]] = None, + recursive: bool = False, + ) -> List["AbstractStat"]: + """Iterate through all of the children, optionally with a predicate + + ``` + >>> system.children(lambda _name: 'cpu' in name) + [cpu0, cpu1, cpu2] + ``` + + :param: predicate(str) -> bool: Optional. Each child's name is passed + to this function. If it returns true, then the child is + yielded. Otherwise, the child is skipped. + If not provided then all children are returned. + """ + + to_return = [] + for attr in self.__dict__: + obj = getattr(self, attr) + if isinstance(obj, AbstractStat): + if (predicate and predicate(attr)) or not predicate: + to_return.append(obj) + if recursive: + to_return = to_return + obj.children( + predicate=predicate, recursive=True + ) + + return to_return + + def find(self, regex: Union[str, Pattern]) -> List["AbstractStat"]: + """Find all stats that match the name, recursively through all the + SimStats. + + + ``` + >>> system.find('cpu[0-9]') + [cpu0, cpu1, cpu2] + ``` + Note: The above will not match `cpu_other`. + + :param: regex: The regular expression used to search. Can be a + precompiled regex or a string in regex format + """ + if isinstance(regex, str): + pattern = re.compile(regex) + else: + pattern = regex + return self.children( + lambda _name: re.match(pattern, _name), recursive=True + ) diff --git a/src/python/m5/ext/pystats/group.py b/src/python/m5/ext/pystats/group.py index 7fcd665ffe..0b71663565 100644 --- a/src/python/m5/ext/pystats/group.py +++ b/src/python/m5/ext/pystats/group.py @@ -24,15 +24,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import re from typing import ( - Callable, Dict, - Iterator, List, Mapping, Optional, - Pattern, Union, ) @@ -68,87 +64,6 @@ class Group(AbstractStat): for key, value in kwargs.items(): setattr(self, key, value) - def children( - self, predicate: Optional[Callable[[str], bool]] = None - ) -> Iterator[Union["Group", Statistic]]: - """Iterate through all of the children, optionally with a predicate - - ``` - >>> system.children(lambda _name: 'cpu' in name) - [cpu0, cpu1, cpu2] - ``` - - :param: predicate(str) -> bool: Optional. Each child's name is passed - to this function. If it returns true, then the child is - yielded. Otherwise, the child is skipped. - If not provided then all children are returned. - """ - for attr in self.__dict__: - # Check the provided predicate. If not a match, skip this child - if predicate and not predicate(attr): - continue - obj = getattr(self, attr) - if isinstance(obj, Group) or isinstance(obj, Statistic): - yield obj - - def find(self, name: str) -> Iterator[Union["Group", Statistic]]: - """Find all stats that match the name - - This function searches all of the "children" in this group. It yields - the set of attributes (children) that have the `name` as a substring. - The order of the objects returned by the generator is arbitrary. - - ``` - >>> system.find('cpu') - [cpu0, cpu1, cpu2, cpu3, other_cpu, ...] - ``` - - This is useful for performing aggregates over substats. For instance: - - ``` - >>> total_instructions = sum([cpu.exec_context.thread_0.numInsts.value - for cpu in simstat.system.find('cpu')]) - 100000 - ``` - - :param: name: The name to search for - """ - yield from self.children(lambda _name: _name in name) - - def find_re( - self, regex: Union[str, Pattern] - ) -> Iterator[Union["Group", Statistic]]: - """Find all stats that match the name - - This function searches all of the "children" in this group. It yields - the set of attributes (children) that have the `name` mathing the - regex provided. The order of the objects returned by the generator is - arbitrary. - - ``` - >>> system.find_re('cpu[0-9]') - [cpu0, cpu1, cpu2] - ``` - Note: The above will not match `cpu_other`. - - :param: regex: The regular expression used to search. Can be a - precompiled regex or a string in regex format - """ - if isinstance(regex, str): - pattern = re.compile(regex) - else: - pattern = regex - yield from self.children(lambda _name: bool(pattern.search(_name))) - - def _repr_name(self) -> str: - return "Group" - - def __repr__(self) -> str: - stats_list = [] - for key in self.__dict__: - stats_list.append(key) - return f"{self._repr_name()}: {stats_list}" - class Vector(Group): """