^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <perf/cpumap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <perf/evlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "metricgroup.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "tests.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "pmu-events/pmu-events.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "rblist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "expr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "stat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static struct pmu_event pme_test[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) .metric_expr = "inst_retired.any / cpu_clk_unhalted.thread",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) .metric_name = "IPC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) .metric_group = "group1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) .metric_expr = "idq_uops_not_delivered.core / (4 * (( ( cpu_clk_unhalted.thread / 2 ) * "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) "( 1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk ) )))",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) .metric_name = "Frontend_Bound_SMT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .metric_expr = "l1d\\-loads\\-misses / inst_retired.any",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .metric_name = "dcache_miss_cpi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .metric_expr = "l1i\\-loads\\-misses / inst_retired.any",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .metric_name = "icache_miss_cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .metric_expr = "(dcache_miss_cpi + icache_miss_cycles)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .metric_name = "cache_miss_cycles",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .metric_group = "group1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .metric_expr = "l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .metric_name = "DCache_L2_All_Hits",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .metric_expr = "max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) "l2_rqsts.pf_miss + l2_rqsts.rfo_miss",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .metric_name = "DCache_L2_All_Miss",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .metric_expr = "dcache_l2_all_hits + dcache_l2_all_miss",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .metric_name = "DCache_L2_All",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .metric_expr = "d_ratio(dcache_l2_all_hits, dcache_l2_all)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .metric_name = "DCache_L2_Hits",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .metric_expr = "d_ratio(dcache_l2_all_miss, dcache_l2_all)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .metric_name = "DCache_L2_Misses",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .metric_expr = "ipc + m2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .metric_name = "M1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .metric_expr = "ipc + m1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .metric_name = "M2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .metric_expr = "1/m3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .metric_name = "M3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .name = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static struct pmu_events_map map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .cpuid = "test",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .version = "1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .type = "core",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .table = pme_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) const char *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u64 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static u64 find_value(const char *name, struct value *values)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct value *v = values;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) while (v->event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!strcmp(name, v->event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return v->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) v++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct value *vals)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u64 count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) count = find_value(evsel->name, vals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) perf_stat__update_shadow_stats(evsel, count, 0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static double compute_single(struct rblist *metric_events, struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct runtime_stat *st, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct metric_expr *mexp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct metric_event *me;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct evsel *evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) evlist__for_each_entry(evlist, evsel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) me = metricgroup__lookup(metric_events, evsel, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (me != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) list_for_each_entry (mexp, &me->head, nd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (strcmp(mexp->metric_name, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return test_generic_metric(mexp, 0, st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return 0.;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int __compute_metric(const char *name, struct value *vals,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) const char *name1, double *ratio1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) const char *name2, double *ratio2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct rblist metric_events = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .nr_entries = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct perf_cpu_map *cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct runtime_stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct evlist *evlist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * We need to prepare evlist for stat mode running on CPU 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * because that's where all the stats are going to be created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) evlist = evlist__new();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!evlist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) cpus = perf_cpu_map__new("0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) evlist__delete(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) perf_evlist__set_maps(&evlist->core, cpus, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) runtime_stat__init(&st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Parse the metric into metric_events list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) err = metricgroup__parse_groups_test(evlist, &map, name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) false, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) &metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) err = perf_evlist__alloc_stats(evlist, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Load the runtime stats with given numbers for events. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) load_runtime_stat(&st, evlist, vals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* And execute the metric */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (name1 && ratio1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *ratio1 = compute_single(&metric_events, evlist, &st, name1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (name2 && ratio2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *ratio2 = compute_single(&metric_events, evlist, &st, name2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* ... clenup. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) metricgroup__rblist_exit(&metric_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) runtime_stat__exit(&st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) perf_evlist__free_stats(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) perf_cpu_map__put(cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) evlist__delete(evlist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int compute_metric(const char *name, struct value *vals, double *ratio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return __compute_metric(name, vals, name, ratio, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int compute_metric_group(const char *name, struct value *vals,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) const char *name1, double *ratio1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) const char *name2, double *ratio2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return __compute_metric(name, vals, name1, ratio1, name2, ratio2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int test_ipc(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) double ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct value vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { .event = "inst_retired.any", .val = 300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { .event = "cpu_clk_unhalted.thread", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) { .event = NULL, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) TEST_ASSERT_VAL("failed to compute metric",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) compute_metric("IPC", vals, &ratio) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) TEST_ASSERT_VAL("IPC failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ratio == 1.5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int test_frontend(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) double ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct value vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { .event = "idq_uops_not_delivered.core", .val = 300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { .event = "cpu_clk_unhalted.thread", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { .event = "cpu_clk_unhalted.one_thread_active", .val = 400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { .event = "cpu_clk_unhalted.ref_xclk", .val = 600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { .event = NULL, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) TEST_ASSERT_VAL("failed to compute metric",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) compute_metric("Frontend_Bound_SMT", vals, &ratio) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) TEST_ASSERT_VAL("Frontend_Bound_SMT failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ratio == 0.45);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int test_cache_miss_cycles(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) double ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct value vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) { .event = "l1d-loads-misses", .val = 300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { .event = "l1i-loads-misses", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) { .event = "inst_retired.any", .val = 400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) { .event = NULL, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) TEST_ASSERT_VAL("failed to compute metric",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) compute_metric("cache_miss_cycles", vals, &ratio) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) TEST_ASSERT_VAL("cache_miss_cycles failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ratio == 1.25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * DCache_L2_All_Hits = l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * DCache_L2_All_Miss = max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * l2_rqsts.pf_miss + l2_rqsts.rfo_miss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * DCache_L2_All = dcache_l2_all_hits + dcache_l2_all_miss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * DCache_L2_Hits = d_ratio(dcache_l2_all_hits, dcache_l2_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * DCache_L2_Misses = d_ratio(dcache_l2_all_miss, dcache_l2_all)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * l2_rqsts.demand_data_rd_hit = 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * l2_rqsts.pf_hit = 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * l2_rqsts.rfo_hi = 300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * l2_rqsts.all_demand_data_rd = 400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * l2_rqsts.pf_miss = 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * l2_rqsts.rfo_miss = 600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * DCache_L2_All_Hits = 600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * DCache_L2_All_Miss = MAX(400 - 100, 0) + 500 + 600 = 1400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * DCache_L2_All = 600 + 1400 = 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * DCache_L2_Hits = 600 / 2000 = 0.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * DCache_L2_Misses = 1400 / 2000 = 0.7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int test_dcache_l2(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) double ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct value vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) { .event = "l2_rqsts.demand_data_rd_hit", .val = 100 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) { .event = "l2_rqsts.pf_hit", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) { .event = "l2_rqsts.rfo_hit", .val = 300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) { .event = "l2_rqsts.all_demand_data_rd", .val = 400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) { .event = "l2_rqsts.pf_miss", .val = 500 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) { .event = "l2_rqsts.rfo_miss", .val = 600 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) { .event = NULL, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) TEST_ASSERT_VAL("failed to compute metric",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) compute_metric("DCache_L2_Hits", vals, &ratio) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) TEST_ASSERT_VAL("DCache_L2_Hits failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ratio == 0.3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) TEST_ASSERT_VAL("failed to compute metric",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) compute_metric("DCache_L2_Misses", vals, &ratio) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) TEST_ASSERT_VAL("DCache_L2_Misses failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ratio == 0.7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static int test_recursion_fail(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) double ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct value vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) { .event = "inst_retired.any", .val = 300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) { .event = "cpu_clk_unhalted.thread", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) { .event = NULL, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) TEST_ASSERT_VAL("failed to find recursion",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) compute_metric("M1", vals, &ratio) == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) TEST_ASSERT_VAL("failed to find recursion",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) compute_metric("M3", vals, &ratio) == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static int test_metric_group(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) double ratio1, ratio2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct value vals[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) { .event = "cpu_clk_unhalted.thread", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { .event = "l1d-loads-misses", .val = 300 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { .event = "l1i-loads-misses", .val = 200 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) { .event = "inst_retired.any", .val = 400 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) { .event = NULL, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) TEST_ASSERT_VAL("failed to find recursion",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) compute_metric_group("group1", vals,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) "IPC", &ratio1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) "cache_miss_cycles", &ratio2) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) TEST_ASSERT_VAL("group IPC failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ratio1 == 2.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) TEST_ASSERT_VAL("group cache_miss_cycles failed, wrong ratio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ratio2 == 1.25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) TEST_ASSERT_VAL("IPC failed", test_ipc() == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) TEST_ASSERT_VAL("frontend failed", test_frontend() == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) TEST_ASSERT_VAL("cache_miss_cycles failed", test_cache_miss_cycles() == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) TEST_ASSERT_VAL("DCache_L2 failed", test_dcache_l2() == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) TEST_ASSERT_VAL("recursion fail failed", test_recursion_fail() == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) TEST_ASSERT_VAL("test metric group", test_metric_group() == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }