1-- 2-- Copyright 2024 The Android Open Source Project 3-- 4-- Licensed under the Apache License, Version 2.0 (the "License"); 5-- you may not use this file except in compliance with the License. 6-- You may obtain a copy of the License at 7-- 8-- https://www.apache.org/licenses/LICENSE-2.0 9-- 10-- Unless required by applicable law or agreed to in writing, software 11-- distributed under the License is distributed on an "AS IS" BASIS, 12-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13-- See the License for the specific language governing permissions and 14-- limitations under the License. 15 16INCLUDE PERFETTO MODULE android.suspend; 17 18INCLUDE PERFETTO MODULE intervals.intersect; 19 20INCLUDE PERFETTO MODULE time.conversion; 21 22INCLUDE PERFETTO MODULE wattson.arm_dsu; 23 24INCLUDE PERFETTO MODULE wattson.cpu_freq_idle; 25 26INCLUDE PERFETTO MODULE wattson.curves.utils; 27 28INCLUDE PERFETTO MODULE wattson.device_infos; 29 30-- Helper macro to do pivot function without policy information 31CREATE PERFETTO MACRO _stats_wo_policy_subquery( 32 cpu Expr, 33 curve_col ColumnName, 34 freq_col ColumnName, 35 idle_col ColumnName 36) 37RETURNS TableOrSubquery AS 38( 39 SELECT 40 ts, 41 dur, 42 curve_value AS $curve_col, 43 freq AS $freq_col, 44 idle AS $idle_col 45 FROM _idle_freq_materialized 46 WHERE 47 cpu = $cpu 48); 49 50-- Helper macro to do pivot function with policy information 51CREATE PERFETTO MACRO _stats_w_policy_subquery( 52 cpu Expr, 53 policy_col ColumnName, 54 curve_col ColumnName, 55 freq_col ColumnName, 56 idle_col ColumnName 57) 58RETURNS TableOrSubquery AS 59( 60 SELECT 61 ts, 62 dur, 63 policy AS $policy_col, 64 curve_value AS $curve_col, 65 freq AS $freq_col, 66 idle AS $idle_col 67 FROM _idle_freq_materialized 68 WHERE 69 cpu = $cpu 70); 71 72CREATE PERFETTO TABLE _stats_cpu0 AS 73SELECT 74 * 75FROM _stats_wo_policy_subquery!(0, cpu0_curve, freq_0, idle_0); 76 77CREATE PERFETTO TABLE _stats_cpu1 AS 78SELECT 79 * 80FROM _stats_wo_policy_subquery!(1, cpu1_curve, freq_1, idle_1); 81 82CREATE PERFETTO TABLE _stats_cpu2 AS 83SELECT 84 * 85FROM _stats_wo_policy_subquery!(2, cpu2_curve, freq_2, idle_2); 86 87CREATE PERFETTO TABLE _stats_cpu3 AS 88SELECT 89 * 90FROM _stats_wo_policy_subquery!(3, cpu3_curve, freq_3, idle_3); 91 92CREATE PERFETTO TABLE _stats_cpu4 AS 93SELECT 94 * 95FROM _stats_w_policy_subquery!(4, policy_4, cpu4_curve, freq_4, idle_4); 96 97CREATE PERFETTO TABLE _stats_cpu5 AS 98SELECT 99 * 100FROM _stats_w_policy_subquery!(5, policy_5, cpu5_curve, freq_5, idle_5); 101 102CREATE PERFETTO TABLE _stats_cpu6 AS 103SELECT 104 * 105FROM _stats_w_policy_subquery!(6, policy_6, cpu6_curve, freq_6, idle_6); 106 107CREATE PERFETTO TABLE _stats_cpu7 AS 108SELECT 109 * 110FROM _stats_w_policy_subquery!(7, policy_7, cpu7_curve, freq_7, idle_7); 111 112CREATE PERFETTO TABLE _stats_cpu0123_suspend AS 113SELECT 114 ii.ts, 115 ii.dur, 116 id_0 AS cpu0_id, 117 id_1 AS cpu1_id, 118 id_2 AS cpu2_id, 119 id_3 AS cpu3_id, 120 ss.power_state = 'suspended' AS suspended 121FROM _interval_intersect!( 122 ( 123 _ii_subquery!(_stats_cpu0), 124 _ii_subquery!(_stats_cpu1), 125 _ii_subquery!(_stats_cpu2), 126 _ii_subquery!(_stats_cpu3), 127 -- Includes suspend AND awake portions, which will cover entire trace and 128 -- allows us to use _interval_intersect instead of SPAN_OUTER_JOIN() 129 _ii_subquery!(android_suspend_state) 130 ), 131 () 132) AS ii 133JOIN android_suspend_state AS ss 134 ON ss._auto_id = id_4; 135 136CREATE PERFETTO TABLE _stats_cpu4567 AS 137SELECT 138 ii.ts, 139 ii.dur, 140 id_0 AS cpu4_id, 141 id_1 AS cpu5_id, 142 id_2 AS cpu6_id, 143 id_3 AS cpu7_id 144FROM _interval_intersect!( 145 ( 146 _ii_subquery!(_stats_cpu4), 147 _ii_subquery!(_stats_cpu5), 148 _ii_subquery!(_stats_cpu6), 149 _ii_subquery!(_stats_cpu7) 150 ), 151 () 152) AS ii; 153 154-- SPAN OUTER JOIN because sometimes CPU4/5/6/7 are empty tables 155CREATE VIRTUAL TABLE _stats_cpu01234567_suspend USING SPAN_OUTER_JOIN (_stats_cpu0123_suspend, _stats_cpu4567); 156 157-- Combine system state so that it has idle, freq, and L3 hit info. 158CREATE VIRTUAL TABLE _idle_freq_l3_hit_slice USING SPAN_OUTER_JOIN (_stats_cpu01234567_suspend, _arm_l3_hit_rate); 159 160-- Combine system state so that it has idle, freq, L3 hit, and L3 miss info. 161CREATE VIRTUAL TABLE _idle_freq_l3_hit_l3_miss_slice USING SPAN_OUTER_JOIN (_idle_freq_l3_hit_slice, _arm_l3_miss_rate); 162 163-- Does calculations for CPUs that are independent of other CPUs or frequencies 164-- This is the last generic table before going to device specific table calcs 165CREATE PERFETTO TABLE _w_independent_cpus_calc AS 166SELECT 167 base.ts, 168 base.dur, 169 cast_int!(l3_hit_rate * base.dur) AS l3_hit_count, 170 cast_int!(l3_miss_rate * base.dur) AS l3_miss_count, 171 freq_0, 172 idle_0, 173 freq_1, 174 idle_1, 175 freq_2, 176 idle_2, 177 freq_3, 178 idle_3, 179 freq_4, 180 idle_4, 181 freq_5, 182 idle_5, 183 freq_6, 184 idle_6, 185 freq_7, 186 idle_7, 187 policy_4, 188 policy_5, 189 policy_6, 190 policy_7, 191 iif( 192 suspended, 193 1, 194 min(coalesce(idle_0, 1), coalesce(idle_1, 1), coalesce(idle_2, 1), coalesce(idle_3, 1)) 195 ) AS no_static, 196 suspended, 197 cpu0_curve, 198 cpu1_curve, 199 cpu2_curve, 200 cpu3_curve, 201 cpu4_curve, 202 cpu5_curve, 203 cpu6_curve, 204 cpu7_curve, 205 -- If dependency CPUs are active, then that CPU could contribute static power 206 iif(idle_4 = -1, lut4.curve_value, -1) AS static_4, 207 iif(idle_5 = -1, lut5.curve_value, -1) AS static_5, 208 iif(idle_6 = -1, lut6.curve_value, -1) AS static_6, 209 iif(idle_7 = -1, lut7.curve_value, -1) AS static_7 210FROM _idle_freq_l3_hit_l3_miss_slice AS base 211JOIN _stats_cpu0 212 ON _stats_cpu0._auto_id = base.cpu0_id 213JOIN _stats_cpu1 214 ON _stats_cpu1._auto_id = base.cpu1_id 215JOIN _stats_cpu2 216 ON _stats_cpu2._auto_id = base.cpu2_id 217JOIN _stats_cpu3 218 ON _stats_cpu3._auto_id = base.cpu3_id 219-- Get CPU power curves for CPUs that aren't always present 220LEFT JOIN _stats_cpu4 221 ON _stats_cpu4._auto_id = base.cpu4_id 222LEFT JOIN _stats_cpu5 223 ON _stats_cpu5._auto_id = base.cpu5_id 224LEFT JOIN _stats_cpu6 225 ON _stats_cpu6._auto_id = base.cpu6_id 226LEFT JOIN _stats_cpu7 227 ON _stats_cpu7._auto_id = base.cpu7_id 228-- Match power curves if possible on CPUs that decide 2D dependence 229LEFT JOIN _filtered_curves_2d AS lut4 230 ON _stats_cpu0.freq_0 = lut4.freq_khz 231 AND _stats_cpu4.policy_4 = lut4.other_policy 232 AND _stats_cpu4.freq_4 = lut4.other_freq_khz 233 AND lut4.idle = 255 234LEFT JOIN _filtered_curves_2d AS lut5 235 ON _stats_cpu0.freq_0 = lut5.freq_khz 236 AND _stats_cpu5.policy_5 = lut5.other_policy 237 AND _stats_cpu5.freq_5 = lut5.other_freq_khz 238 AND lut5.idle = 255 239LEFT JOIN _filtered_curves_2d AS lut6 240 ON _stats_cpu0.freq_0 = lut6.freq_khz 241 AND _stats_cpu6.policy_6 = lut6.other_policy 242 AND _stats_cpu6.freq_6 = lut6.other_freq_khz 243 AND lut6.idle = 255 244LEFT JOIN _filtered_curves_2d AS lut7 245 ON _stats_cpu0.freq_0 = lut7.freq_khz 246 AND _stats_cpu7.policy_7 = lut7.other_policy 247 AND _stats_cpu7.freq_7 = lut7.other_freq_khz 248 AND lut7.idle = 255 249-- Needs to be at least 1us to reduce inconsequential rows. 250WHERE 251 base.dur > time_from_us(1); 252