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 wattson.cpu_split; 17 18INCLUDE PERFETTO MODULE wattson.curves.utils; 19 20INCLUDE PERFETTO MODULE wattson.curves.w_cpu_dependence; 21 22INCLUDE PERFETTO MODULE wattson.curves.w_dsu_dependence; 23 24INCLUDE PERFETTO MODULE wattson.device_infos; 25 26-- One of the two tables will be empty, depending on whether the device is 27-- dependent on devfreq or a different CPU's frequency 28CREATE PERFETTO VIEW _curves_w_dependencies ( 29 ts TIMESTAMP, 30 dur DURATION, 31 freq_0 LONG, 32 idle_0 LONG, 33 freq_1 LONG, 34 idle_1 LONG, 35 freq_2 LONG, 36 idle_2 LONG, 37 freq_3 LONG, 38 idle_3 LONG, 39 cpu0_curve DOUBLE, 40 cpu1_curve DOUBLE, 41 cpu2_curve DOUBLE, 42 cpu3_curve DOUBLE, 43 cpu4_curve DOUBLE, 44 cpu5_curve DOUBLE, 45 cpu6_curve DOUBLE, 46 cpu7_curve DOUBLE, 47 l3_hit_count LONG, 48 l3_miss_count LONG, 49 suspended BOOL, 50 no_static LONG, 51 all_cpu_deep_idle LONG, 52 dependent_freq LONG, 53 dependent_policy LONG 54) AS 55-- Table that is dependent on differet CPU's frequency 56SELECT 57 * 58FROM _w_cpu_dependence 59UNION ALL 60-- Table that is dependent of devfreq frequency 61SELECT 62 * 63FROM _w_dsu_dependence; 64 65-- Final table showing the curves per CPU per slice 66CREATE PERFETTO TABLE _system_state_curves AS 67SELECT 68 base.ts, 69 base.dur, 70 -- base.cpu[0-3]_curve will be non-zero if CPU has 1D dependency 71 -- base.cpu[0-3]_curve will be zero if device is suspended or deep idle 72 -- base.cpu[0-3]_curve will be NULL if 2D dependency required 73 iif(suspended, 0.0, coalesce(base.cpu0_curve, lut0.curve_value)) AS cpu0_curve, 74 iif(suspended, 0.0, coalesce(base.cpu1_curve, lut1.curve_value)) AS cpu1_curve, 75 iif(suspended, 0.0, coalesce(base.cpu2_curve, lut2.curve_value)) AS cpu2_curve, 76 iif(suspended, 0.0, coalesce(base.cpu3_curve, lut3.curve_value)) AS cpu3_curve, 77 -- base.cpu[4-7]_curve will be non-zero if CPU has 1D dependency 78 -- base.cpu[4-7]_curve will be zero if device is suspended or deep idle 79 -- base.cpu[4-7]_curve will be NULL if CPU doesn't exist on device 80 iif(suspended, 0.0, coalesce(base.cpu4_curve, 0.0)) AS cpu4_curve, 81 iif(suspended, 0.0, coalesce(base.cpu5_curve, 0.0)) AS cpu5_curve, 82 iif(suspended, 0.0, coalesce(base.cpu6_curve, 0.0)) AS cpu6_curve, 83 iif(suspended, 0.0, coalesce(base.cpu7_curve, 0.0)) AS cpu7_curve, 84 iif(no_static = 1, 0.0, coalesce(static_1d.curve_value, static_2d.curve_value)) AS static_curve, 85 iif(all_cpu_deep_idle = 1, 0, base.l3_hit_count * l3_hit_lut.curve_value) AS l3_hit_value, 86 iif(all_cpu_deep_idle = 1, 0, base.l3_miss_count * l3_miss_lut.curve_value) AS l3_miss_value 87FROM _curves_w_dependencies AS base 88-- LUT for 2D dependencies 89LEFT JOIN _filtered_curves_2d AS lut0 90 ON lut0.freq_khz = base.freq_0 91 AND lut0.other_policy = base.dependent_policy 92 AND lut0.other_freq_khz = base.dependent_freq 93 AND lut0.idle = base.idle_0 94LEFT JOIN _filtered_curves_2d AS lut1 95 ON lut1.freq_khz = base.freq_1 96 AND lut1.other_policy = base.dependent_policy 97 AND lut1.other_freq_khz = base.dependent_freq 98 AND lut1.idle = base.idle_1 99LEFT JOIN _filtered_curves_2d AS lut2 100 ON lut2.freq_khz = base.freq_2 101 AND lut2.other_policy = base.dependent_policy 102 AND lut2.other_freq_khz = base.dependent_freq 103 AND lut2.idle = base.idle_2 104LEFT JOIN _filtered_curves_2d AS lut3 105 ON lut3.freq_khz = base.freq_3 106 AND lut3.other_policy = base.dependent_policy 107 AND lut3.other_freq_khz = base.dependent_freq 108 AND lut3.idle = base.idle_3 109-- LUT for static curve lookup 110LEFT JOIN _filtered_curves_2d AS static_2d 111 ON static_2d.freq_khz = base.freq_0 112 AND static_2d.other_policy = base.dependent_policy 113 AND static_2d.other_freq_khz = base.dependent_freq 114 AND static_2d.idle = 255 115LEFT JOIN _filtered_curves_1d AS static_1d 116 ON static_1d.policy = 0 AND static_1d.freq_khz = base.freq_0 AND static_1d.idle = 255 117-- LUT joins for L3 cache 118LEFT JOIN _filtered_curves_l3 AS l3_hit_lut 119 ON l3_hit_lut.freq_khz = base.freq_0 120 AND l3_hit_lut.other_policy = base.dependent_policy 121 AND l3_hit_lut.other_freq_khz = base.dependent_freq 122 AND l3_hit_lut.action = 'hit' 123LEFT JOIN _filtered_curves_l3 AS l3_miss_lut 124 ON l3_miss_lut.freq_khz = base.freq_0 125 AND l3_miss_lut.other_policy = base.dependent_policy 126 AND l3_miss_lut.other_freq_khz = base.dependent_freq 127 AND l3_miss_lut.action = 'miss'; 128 129-- The most basic components of Wattson, all normalized to be in mW on a per 130-- system state basis 131CREATE PERFETTO TABLE _system_state_mw AS 132SELECT 133 ts, 134 dur, 135 cpu0_curve AS cpu0_mw, 136 cpu1_curve AS cpu1_mw, 137 cpu2_curve AS cpu2_mw, 138 cpu3_curve AS cpu3_mw, 139 cpu4_curve AS cpu4_mw, 140 cpu5_curve AS cpu5_mw, 141 cpu6_curve AS cpu6_mw, 142 cpu7_curve AS cpu7_mw, 143 -- LUT for l3 is scaled by 10^6 to save resolution and in units of kWs. Scale 144 -- this by 10^3 so when divided by ns, result is in units of mW 145 ( 146 ( 147 coalesce(l3_hit_value, 0) + coalesce(l3_miss_value, 0) 148 ) * 1000 / dur 149 ) + static_curve AS dsu_scu_mw 150FROM _system_state_curves; 151 152-- API to get power from each system state in an arbitrary time window 153CREATE PERFETTO FUNCTION _windowed_system_state_mw( 154 ts TIMESTAMP, 155 dur LONG 156) 157RETURNS TABLE ( 158 cpu0_mw DOUBLE, 159 cpu1_mw DOUBLE, 160 cpu2_mw DOUBLE, 161 cpu3_mw DOUBLE, 162 cpu4_mw DOUBLE, 163 cpu5_mw DOUBLE, 164 cpu6_mw DOUBLE, 165 cpu7_mw DOUBLE, 166 dsu_scu_mw DOUBLE 167) AS 168SELECT 169 sum(ss.cpu0_mw * ss.dur) / sum(ss.dur) AS cpu0_mw, 170 sum(ss.cpu1_mw * ss.dur) / sum(ss.dur) AS cpu1_mw, 171 sum(ss.cpu2_mw * ss.dur) / sum(ss.dur) AS cpu2_mw, 172 sum(ss.cpu3_mw * ss.dur) / sum(ss.dur) AS cpu3_mw, 173 sum(ss.cpu4_mw * ss.dur) / sum(ss.dur) AS cpu4_mw, 174 sum(ss.cpu5_mw * ss.dur) / sum(ss.dur) AS cpu5_mw, 175 sum(ss.cpu6_mw * ss.dur) / sum(ss.dur) AS cpu6_mw, 176 sum(ss.cpu7_mw * ss.dur) / sum(ss.dur) AS cpu7_mw, 177 sum(ss.dsu_scu_mw * ss.dur) / sum(ss.dur) AS dsu_scu_mw 178FROM _interval_intersect_single!($ts, $dur, _ii_subquery!(_system_state_mw)) AS ii 179JOIN _system_state_mw AS ss 180 ON ss._auto_id = id; 181