From 23d72e47d436aa53c0676dc3898d69f300fa8d61 Mon Sep 17 00:00:00 2001 From: Metin Kaya Date: Wed, 27 Nov 2024 14:12:48 +0000 Subject: [PATCH 1/2] target_conf.yml: analysis: Fix trivial typos FIX Signed-off-by: Metin Kaya --- lisa/analysis/pixel6.py | 2 +- target_conf.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lisa/analysis/pixel6.py b/lisa/analysis/pixel6.py index 2286083a2..a265e8109 100644 --- a/lisa/analysis/pixel6.py +++ b/lisa/analysis/pixel6.py @@ -54,7 +54,7 @@ class Pixel6Analysis(TraceAnalysisBase): """ Get the power meter readings across the trace. - :retuns: A :class:`pandas.DataFrame` with: + :returns: A :class:`pandas.DataFrame` with: * A ``channel`` column (name of the power meter channel) * A ``power`` column (average power usage in mW since the last measurement) diff --git a/target_conf.yml b/target_conf.yml index 24dd76f70..a44e9ae14 100644 --- a/target_conf.yml +++ b/target_conf.yml @@ -67,10 +67,10 @@ target-conf: # Optional devlib configuration # devlib: - # Devlib modules names to enable/disbale for all the experiment + # Devlib modules names to enable/disable for all the experiment # excluded-modules: [] # - # devlib Platform sublcass to use, with the keyword arguments to use it + # devlib Platform subclass to use, with the keyword arguments to use it # platform: # Defaults to devlib.platform.Platform # class: devlib.platform.Platform -- GitLab From 9c76e710ae5c358b539e3455d8875757994d8f69 Mon Sep 17 00:00:00 2001 From: Metin Kaya Date: Fri, 6 Dec 2024 12:08:40 +0000 Subject: [PATCH 2/2] lisa/analysis: Customize power rails for Pixel-9 FIX Pixel6Analysis.EMETER_CHAN_NAMES needs to be updated for Pixel-9. So, make current version of pixel6.py class private as the first thing. And then, inherit Pixel6Analysis & Pixel9Analysis classes from the new base class PixelAnalysis. Signed-off-by: Metin Kaya --- doc/plot_conf.yml | 4 ++ lisa/analysis/_pixel.py | 93 +++++++++++++++++++++++++++++++++++++++++ lisa/analysis/pixel6.py | 73 ++------------------------------ lisa/analysis/pixel9.py | 42 +++++++++++++++++++ 4 files changed, 142 insertions(+), 70 deletions(-) create mode 100644 lisa/analysis/_pixel.py create mode 100644 lisa/analysis/pixel9.py diff --git a/doc/plot_conf.yml b/doc/plot_conf.yml index 024f50960..4e31d9298 100644 --- a/doc/plot_conf.yml +++ b/doc/plot_conf.yml @@ -165,6 +165,10 @@ doc-plot-conf: trace: !call:lisa.trace.Trace trace_path: !env:interpolate $LISA_HOME/doc/traces/trace_pixel6.dat + Pixel9Analysis.plot_power_meter: + trace: !call:lisa.trace.Trace + trace_path: !env:interpolate $LISA_HOME/doc/traces/trace_pixel6.dat + NotebookAnalysis.plot_event_field: kwargs: event: cpu_frequency diff --git a/lisa/analysis/_pixel.py b/lisa/analysis/_pixel.py new file mode 100644 index 000000000..0f70f2a21 --- /dev/null +++ b/lisa/analysis/_pixel.py @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2024, ARM Limited and contributors. +# +# 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. +# +""" +Pixel phones specific analysis. +""" + +import pandas as pd +import holoviews as hv +from holoviews import opts + +from lisa.datautils import df_add_delta +from lisa.analysis.base import TraceAnalysisBase +from lisa.trace import requires_events +from lisa.notebook import plot_signal + + +class PixelAnalysis(TraceAnalysisBase): + """ + Support for Pixel phones specific data analysis + + :param trace: input Trace object + :type trace: lisa.trace.Trace + """ + + ############################################################################### + # DataFrame Getter Methods + ############################################################################### + @TraceAnalysisBase.df_method + @requires_events('pixel6_emeter') + def df_power_meter(self): + """ + Get the power meter readings across the trace. + + :returns: A :class:`pandas.DataFrame` with: + + * A ``channel`` column (name of the power meter channel) + * A ``power`` column (average power usage in mW since the last measurement) + """ + df = self.trace.df_event('pixel6_emeter') + df = df[df['chan_name'].isin(self.EMETER_CHAN_NAMES)] + grouped = df.groupby('chan_name', observed=True, group_keys=False) + + def make_chan_df(df): + energy_diff = df_add_delta(df, col='energy_diff', src_col='value', window=self.trace.window)['energy_diff'] + ts_diff = df_add_delta(df, col='ts_diff', src_col='ts', window=self.trace.window)['ts_diff'] + power = energy_diff / ts_diff + df = pd.DataFrame(dict(power=power, channel=df['chan_name'])) + return df.dropna() + + df = grouped[df.columns].apply(make_chan_df) + df['channel'] = df['channel'].astype('category').cat.rename_categories(self.EMETER_CHAN_NAMES) + + return df + + ############################################################################### + # Plotting methods + ############################################################################### + @TraceAnalysisBase.plot_method + @df_power_meter.used_events + def plot_power_meter(self, channels=None): + """ + Plot the power meter readings from various channels. + + :param channels: List of channels to plot + :type channels: list(str) + + The channels needs to correspond to values in the ``channel`` column of df_power_meter(). + """ + df = self.df_power_meter() + + channels = list(channels or df['channel'].unique()) + if any(channel not in df['channel'].cat.categories for channel in channels): + raise ValueError('Specified channel not found') + + channel_data = dict(iter(df[df['channel'].isin(channels)].groupby('channel', group_keys=False, observed=True))) + return hv.Overlay([ + plot_signal(channel_data[channel]['power'], name=channel, vdim=hv.Dimension('power', label='Power', unit='mW')) + for channel in channels + ]).opts(title='Power usage per channel over time') diff --git a/lisa/analysis/pixel6.py b/lisa/analysis/pixel6.py index a265e8109..ce68f56df 100644 --- a/lisa/analysis/pixel6.py +++ b/lisa/analysis/pixel6.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # -# Copyright (C) 2023, ARM Limited and contributors. +# Copyright (C) 2024, ARM Limited and contributors. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. @@ -18,22 +18,12 @@ Pixel 6-specific analysis. """ -import pandas as pd -import holoviews as hv -from holoviews import opts +from lisa.analysis._pixel import PixelAnalysis -from lisa.datautils import df_add_delta -from lisa.analysis.base import TraceAnalysisBase -from lisa.trace import requires_events -from lisa.notebook import plot_signal - -class Pixel6Analysis(TraceAnalysisBase): +class Pixel6Analysis(PixelAnalysis): """ Support for Pixel 6-specific data analysis - - :param trace: input Trace object - :type trace: lisa.trace.Trace """ name = 'pixel6' @@ -44,60 +34,3 @@ class Pixel6Analysis(TraceAnalysisBase): 'S2M_VDD_CPUCL2': 'CPU-Big', 'S2S_VDD_G3D': 'GPU', } - -############################################################################### -# DataFrame Getter Methods -############################################################################### - @TraceAnalysisBase.df_method - @requires_events('pixel6_emeter') - def df_power_meter(self): - """ - Get the power meter readings across the trace. - - :returns: A :class:`pandas.DataFrame` with: - - * A ``channel`` column (name of the power meter channel) - * A ``power`` column (average power usage in mW since the last measurement) - """ - df = self.trace.df_event('pixel6_emeter') - df = df[df['chan_name'].isin(Pixel6Analysis.EMETER_CHAN_NAMES)] - grouped = df.groupby('chan_name', observed=True, group_keys=False) - - def make_chan_df(df): - energy_diff = df_add_delta(df, col='energy_diff', src_col='value', window=self.trace.window)['energy_diff'] - ts_diff = df_add_delta(df, col='ts_diff', src_col='ts', window=self.trace.window)['ts_diff'] - power = energy_diff / ts_diff - df = pd.DataFrame(dict(power=power, channel=df['chan_name'])) - return df.dropna() - - df = grouped[df.columns].apply(make_chan_df) - df['channel'] = df['channel'].astype('category').cat.rename_categories(Pixel6Analysis.EMETER_CHAN_NAMES) - - return df - -############################################################################### -# Plotting methods -############################################################################### - - @TraceAnalysisBase.plot_method - @df_power_meter.used_events - def plot_power_meter(self, channels=None): - """ - Plot the power meter readings from various channels. - - :param channels: List of channels to plot - :type channels: list(str) - - The channels needs to correspond to values in the ``channel`` column of df_power_meter(). - """ - df = self.df_power_meter() - - channels = list(channels or df['channel'].unique()) - if any(channel not in df['channel'].cat.categories for channel in channels): - raise ValueError('Specified channel not found') - - channel_data = dict(iter(df[df['channel'].isin(channels)].groupby('channel', group_keys=False, observed=True))) - return hv.Overlay([ - plot_signal(channel_data[channel]['power'], name=channel, vdim=hv.Dimension('power', label='Power', unit='mW')) - for channel in channels - ]).opts(title='Power usage per channel over time') diff --git a/lisa/analysis/pixel9.py b/lisa/analysis/pixel9.py new file mode 100644 index 000000000..fbca7ad75 --- /dev/null +++ b/lisa/analysis/pixel9.py @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2024, ARM Limited and contributors. +# +# 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. +# +""" +Pixel 9-specific analysis. +""" + +from lisa.analysis._pixel import PixelAnalysis + + +class Pixel9Analysis(PixelAnalysis): + """ + Support for Pixel 9-specific data analysis + """ + + name = 'pixel9' + + """ + Power rail vs CPU/GPU cluster mapping + + Power rail information is extracted from + https://cs.android.com/android/platform/superproject/main/+/main:device/google/caimito/thermal/thermal_info_config_tokay.json;l=628 + """ + EMETER_CHAN_NAMES = { + 'S4M_VDD_CPUCL0': 'CPU-Little', + 'S2M_VDD_CPUCL1': 'CPU-Mid', + 'S3M_VDD_CPUCL2': 'CPU-Big', + 'S2S_VDD_G3D': 'GPU', + } -- GitLab