stdlib: Add function to query for devfreq counters

Add a Perfetto function that returns device frequency slices for any
arbitrary device. This is analagous to existing tables such as
cpu_frequency_counters.

Bug: 370829192
Change-Id: I925b8ca25bae4bb885aa84f925faa6df574492a5
Signed-off-by: Samuel Wu <wusamuel@google.com>
diff --git a/Android.bp b/Android.bp
index 8e9dace..bab4148 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13611,6 +13611,7 @@
         "src/trace_processor/perfetto_sql/stdlib/linux/cpu/utilization/slice.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/cpu/utilization/system.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/cpu/utilization/thread.sql",
+        "src/trace_processor/perfetto_sql/stdlib/linux/devfreq.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/memory/general.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/memory/high_watermark.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/memory/process.sql",
diff --git a/BUILD b/BUILD
index 84cd949..05da2c1 100644
--- a/BUILD
+++ b/BUILD
@@ -2960,6 +2960,7 @@
 perfetto_filegroup(
     name = "src_trace_processor_perfetto_sql_stdlib_linux_linux",
     srcs = [
+        "src/trace_processor/perfetto_sql/stdlib/linux/devfreq.sql",
         "src/trace_processor/perfetto_sql/stdlib/linux/threads.sql",
     ],
 )
diff --git a/src/trace_processor/perfetto_sql/stdlib/linux/BUILD.gn b/src/trace_processor/perfetto_sql/stdlib/linux/BUILD.gn
index 23371df..95f49d8 100644
--- a/src/trace_processor/perfetto_sql/stdlib/linux/BUILD.gn
+++ b/src/trace_processor/perfetto_sql/stdlib/linux/BUILD.gn
@@ -15,7 +15,10 @@
 import("../../../../../gn/perfetto_sql.gni")
 
 perfetto_sql_source_set("linux") {
-  sources = [ "threads.sql" ]
+  sources = [
+    "devfreq.sql",
+    "threads.sql",
+  ]
   deps = [
     "cpu",
     "memory",
diff --git a/src/trace_processor/perfetto_sql/stdlib/linux/devfreq.sql b/src/trace_processor/perfetto_sql/stdlib/linux/devfreq.sql
new file mode 100644
index 0000000..a8e1e3c
--- /dev/null
+++ b/src/trace_processor/perfetto_sql/stdlib/linux/devfreq.sql
@@ -0,0 +1,62 @@
+--
+-- Copyright 2024 The Android Open Source Project
+--
+-- 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
+--
+--     https://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.
+
+INCLUDE PERFETTO MODULE counters.intervals;
+
+-- Gets devfreq frequency counter based on device queried. These counters will
+-- only be available if the "devfreq/devfreq_frequency" ftrace event is enabled.
+CREATE PERFETTO FUNCTION linux_get_devfreq_counters(
+  -- Devfreq name to query for.
+  device_name STRING
+)
+RETURNS TABLE(
+  -- Unique identifier for this counter.
+  id INT,
+  -- Starting timestamp of the counter.
+  ts LONG,
+  -- Duration in which counter is constant and frequency doesn't chamge.
+  dur INT,
+  -- Frequency in kHz of the device that corresponds to the counter.
+  freq INT
+) AS
+SELECT
+  count_w_dur.id,
+  count_w_dur.ts,
+  count_w_dur.dur,
+  cast_int!(count_w_dur.value) as freq
+FROM counter_leading_intervals!((
+  SELECT c.*
+  FROM counter c
+  JOIN counter_track ct ON ct.id = c.track_id AND ct.name = $device_name
+)) AS count_w_dur
+JOIN counter_track AS ct ON track_id = ct.id;
+
+-- ARM DSU device frequency counters. This table will only be populated on
+-- traces collected with "devfreq/devfreq_frequency" ftrace event enabled,
+-- and from ARM devices with the DSU (DynamIQ Shared Unit) hardware.
+CREATE PERFETTO TABLE linux_devfreq_dsu_counter(
+  -- Unique identifier for this counter.
+  id INT,
+  -- Starting timestamp of the counter.
+  ts LONG,
+  -- Duration in which counter is constant and frequency doesn't chamge.
+  dur INT,
+  -- Frequency in kHz of the device that corresponds to the counter.
+  dsu_freq INT
+) AS
+SELECT
+  id, ts, dur, freq as dsu_freq
+FROM linux_get_devfreq_counters("dsufreq");
+
diff --git a/test/data/wattson_tk4_pcmark.pb.sha256 b/test/data/wattson_tk4_pcmark.pb.sha256
new file mode 100644
index 0000000..c39092d
--- /dev/null
+++ b/test/data/wattson_tk4_pcmark.pb.sha256
@@ -0,0 +1 @@
+9f807b520842034eda96b81ef6e6be6d2b395e83d08a3162ad0df2956ca9f947
\ No newline at end of file
diff --git a/test/trace_processor/diff_tests/stdlib/linux/tests.py b/test/trace_processor/diff_tests/stdlib/linux/tests.py
index 5be22eb..20fc769 100644
--- a/test/trace_processor/diff_tests/stdlib/linux/tests.py
+++ b/test/trace_processor/diff_tests/stdlib/linux/tests.py
@@ -44,4 +44,37 @@
         18,45,2379,2379,"csf_kcpu_0","csf_kcpu_0"
         12,47,247,247,"decon0_kthread","decon0_kthread"
         65,48,159,159,"spi0","spi0"
-            """))
\ No newline at end of file
+            """))
+
+  # Tests that DSU devfreq counters are working properly
+  def test_dsu_devfreq(self):
+    return DiffTestBlueprint(
+        trace=DataPath('wattson_tk4_pcmark.pb'),
+        query=("""
+            INCLUDE PERFETTO MODULE linux.devfreq;
+            SELECT id, ts, dur, dsu_freq FROM linux_devfreq_dsu_counter
+            LIMIT 20
+            """),
+        out=Csv("""
+            "id","ts","dur","dsu_freq"
+            61,4106584783742,11482788,610000
+            166,4106596266530,8108602,1197000
+            212,4106604375132,21453410,610000
+            487,4106625828542,39427368,820000
+            1130,4106665255910,3264242,610000
+            1173,4106668520152,16966105,820000
+            1391,4106685486257,10596883,970000
+            1584,4106696083140,10051636,610000
+            1868,4106706134776,14058960,820000
+            2136,4106720193736,116719238,610000
+            4388,4106836912974,8285848,1197000
+            4583,4106845198822,16518433,820000
+            5006,4106861717255,9357503,1328000
+            5238,4106871074758,27228760,1197000
+            5963,4106898303518,16581706,820000
+            6498,4106914885224,9954142,1197000
+            6763,4106924839366,9024780,970000
+            7061,4106933864146,26264160,820000
+            7637,4106960128306,11008505,970000
+            7880,4106971136811,9282511,1197000
+            """))