Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 1 | /** |
| 2 | * @file alloc_counter_tests.c |
| 3 | * |
| 4 | * @remark Copyright 2003 OProfile authors |
| 5 | * @remark Read the file COPYING |
| 6 | * |
| 7 | * @author John Levon |
| 8 | * @author Philippe Elie |
| 9 | */ |
| 10 | |
| 11 | #include <stdlib.h> |
| 12 | #include <stdio.h> |
| 13 | |
| 14 | #include "op_parse_event.h" |
| 15 | #include "op_alloc_counter.h" |
| 16 | #include "op_events.h" |
| 17 | #include "op_hw_config.h" |
| 18 | #include "op_cpu_type.h" |
| 19 | #include "op_events.h" |
| 20 | |
| 21 | /* FIXME: alpha description events need 20 but when running test on x86 |
| 22 | * OP_MAX_COUNTERS is 8, so we can't use it */ |
| 23 | #define MAX_EVENTS 20 |
| 24 | |
| 25 | |
| 26 | /* some test are setup to fail in a known way */ |
| 27 | enum failure_type { |
| 28 | no_failure, |
| 29 | fail_to_find_event, |
| 30 | fail_to_alloc_counter |
| 31 | }; |
| 32 | |
| 33 | struct allocated_counter { |
| 34 | op_cpu cpu_type; |
| 35 | char const * const * events; |
| 36 | size_t alloc_map[MAX_EVENTS]; |
| 37 | /* expected failure for this test */ |
| 38 | enum failure_type failure; |
| 39 | }; |
| 40 | |
| 41 | |
| 42 | /* not more than MAX_EVENTS string for all these arrays */ |
| 43 | static char const * const events_alpha_ev4_1[] = { |
| 44 | "ISSUES:4096:0:1:1", |
| 45 | NULL |
| 46 | }; |
| 47 | |
| 48 | static char const * const events_alpha_ev4_2[] = { |
| 49 | "UNKNOWN_EVENT:4096:0:1:1", |
| 50 | NULL |
| 51 | }; |
| 52 | |
| 53 | static char const * const events_ppro_1[] = { |
| 54 | "CPU_CLK_UNHALTED:4096:0:1:1", |
| 55 | NULL |
| 56 | }; |
| 57 | |
| 58 | static char const * const events_ppro_2[] = { |
| 59 | "CPU_CLK_UNHALTED:4096:0:1:1", |
| 60 | "DATA_MEM_REFS:4096:0:1:1", |
| 61 | NULL |
| 62 | }; |
| 63 | |
| 64 | static char const * const events_ppro_3[] = { |
| 65 | /* fail_to_alloc_counter: 2 event to counter 0 */ |
| 66 | "COMP_FLOP_RET:4096:0:1:1", |
| 67 | "FLOPS:4096:0:1:1", |
| 68 | NULL |
| 69 | }; |
| 70 | |
| 71 | static char const * const events_ppro_4[] = { |
| 72 | "FLOPS:4096:0:1:1", |
| 73 | "FP_ASSIST:4096:0:1:1", |
| 74 | NULL |
| 75 | }; |
| 76 | |
| 77 | static char const * const events_ppro_5[] = { |
| 78 | "FP_ASSIST:4096:0:1:1", |
| 79 | "FLOPS:4096:0:1:1", |
| 80 | NULL |
| 81 | }; |
| 82 | |
| 83 | static char const * const events_p4_1[] = { |
| 84 | "BRANCH_RETIRED:4096:1:1:1", |
| 85 | "MISPRED_BRANCH_RETIRED:4096:1:1:1", |
| 86 | "BPU_FETCH_REQUEST:4096:1:1:1", |
| 87 | "ITLB_REFERENCE:4096:1:1:1", |
| 88 | "MEMORY_CANCEL:4096:4:1:1", |
| 89 | "MEMORY_COMPLETE:4096:1:1:1", |
| 90 | "TC_MS_XFER:4096:1:1:1", |
| 91 | "UOP_QUEUE_WRITES:4096:1:1:1", |
| 92 | NULL |
| 93 | }; |
| 94 | |
| 95 | static char const * const events_p4_2[] = { |
| 96 | /* fail_to_alloc_counter: 3 event to counter 3, 7 */ |
| 97 | "BRANCH_RETIRED:4096:1:1:1", |
| 98 | "MISPRED_BRANCH_RETIRED:4096:1:1:1", |
| 99 | "INSTR_RETIRED:4096:1:1:1", |
| 100 | "BPU_FETCH_REQUEST:4096:1:1:1", |
| 101 | "ITLB_REFERENCE:4096:1:1:1", |
| 102 | "MEMORY_CANCEL:4096:4:1:1", |
| 103 | "MEMORY_COMPLETE:4096:1:1:1", |
| 104 | "TC_MS_XFER:4096:1:1:1", |
| 105 | NULL |
| 106 | }; |
| 107 | |
| 108 | static char const * const events_mips_34k[] = { |
| 109 | /* fail_to_alloc_counter: w/o 2006-8-03 Jeremiah Lott patch, see |
| 110 | * ChangeLog */ |
Jeff Brown | 7a33c86 | 2011-02-02 14:00:44 -0800 | [diff] [blame^] | 111 | "DTLB_MISSES:500:0:1:1", |
| 112 | "JR_31_INSNS:500:0:1:1", |
Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 113 | NULL |
| 114 | }; |
| 115 | |
| 116 | static struct allocated_counter const tests[] = { |
| 117 | { CPU_AXP_EV4, events_alpha_ev4_1, { 0 }, no_failure }, |
| 118 | { CPU_AXP_EV4, events_alpha_ev4_2, { -1 }, fail_to_find_event }, |
| 119 | { CPU_PPRO, events_ppro_1, { 0 }, no_failure }, |
| 120 | { CPU_PPRO, events_ppro_2, { 0, 1 }, no_failure }, |
| 121 | { CPU_PPRO, events_ppro_3, { -1 }, fail_to_alloc_counter }, |
| 122 | { CPU_PPRO, events_ppro_4, { 0, 1 }, no_failure }, |
| 123 | { CPU_PPRO, events_ppro_5, { 1, 0 }, no_failure }, |
| 124 | { CPU_P4, events_p4_1, { 3, 7, 0, 4, 2, 6, 1, 5 }, no_failure }, |
| 125 | { CPU_P4, events_p4_2, { -1 }, fail_to_alloc_counter }, |
Jeff Brown | 7a33c86 | 2011-02-02 14:00:44 -0800 | [diff] [blame^] | 126 | { CPU_MIPS_34K, events_mips_34k, { 1, 0 }, no_failure }, |
Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 127 | { CPU_NO_GOOD, 0, { 0 }, 0 } |
| 128 | }; |
| 129 | |
| 130 | |
| 131 | static void show_events(char const * const * events) |
| 132 | { |
| 133 | for ( ; *events; ++events) |
| 134 | printf("%s\n", *events); |
| 135 | } |
| 136 | |
| 137 | |
| 138 | static void show_counter_map(size_t const * counter_map, size_t nr_events) |
| 139 | { |
| 140 | size_t i; |
| 141 | for (i = 0; i < nr_events; ++i) |
| 142 | printf("%lu ", (unsigned long)counter_map[i]); |
| 143 | printf("\n"); |
| 144 | } |
| 145 | |
| 146 | |
| 147 | static void do_test(struct allocated_counter const * it) |
| 148 | { |
| 149 | size_t i; |
| 150 | size_t * counter_map; |
| 151 | size_t nr_events; |
| 152 | struct parsed_event parsed[MAX_EVENTS]; |
| 153 | struct op_event const * event[MAX_EVENTS]; |
| 154 | |
| 155 | op_events(it->cpu_type); |
| 156 | |
| 157 | nr_events = parse_events(parsed, MAX_EVENTS, it->events); |
| 158 | |
| 159 | for (i = 0; i < nr_events; ++i) { |
| 160 | event[i] = find_event_by_name(parsed[i].name, parsed[i].unit_mask, |
| 161 | parsed[i].unit_mask_valid); |
| 162 | if (!event[i]) { |
| 163 | if (it->failure == fail_to_find_event) |
| 164 | goto free_events; |
| 165 | printf("Can't find events %s for cpu %s\n", |
| 166 | parsed[i].name, |
| 167 | op_get_cpu_type_str(it->cpu_type)); |
| 168 | exit(EXIT_FAILURE); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | counter_map = map_event_to_counter(event, nr_events, it->cpu_type); |
| 173 | if (!counter_map) { |
| 174 | if (it->failure == fail_to_alloc_counter) |
| 175 | goto free_events; |
| 176 | printf("Can't map this set of events to counter:\n"); |
| 177 | show_events(it->events); |
| 178 | exit(EXIT_FAILURE); |
| 179 | } |
| 180 | |
| 181 | for (i = 0; i < nr_events; ++i) { |
| 182 | if (counter_map[i] != it->alloc_map[i]) { |
| 183 | printf("Incorrect allocation map for these events:\n"); |
| 184 | show_events(it->events); |
| 185 | printf("(expect, found):\n"); |
| 186 | show_counter_map(it->alloc_map, nr_events); |
| 187 | show_counter_map(counter_map, nr_events); |
| 188 | exit(EXIT_FAILURE); |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | if (it->failure != no_failure) { |
| 193 | /* test should fail but success! */ |
| 194 | printf("test should fail with a failure type %d but succeed " |
| 195 | "for events:\n", it->failure); |
| 196 | for (i = 0; i < nr_events; ++i) |
| 197 | printf("%s\n", it->events[i]); |
| 198 | exit(EXIT_FAILURE); |
| 199 | } |
| 200 | |
| 201 | free(counter_map); |
| 202 | free_events: |
| 203 | op_free_events(); |
| 204 | } |
| 205 | |
| 206 | |
| 207 | int main(void) |
| 208 | { |
| 209 | struct allocated_counter const * it; |
| 210 | |
| 211 | setenv("OPROFILE_EVENTS_DIR", OPROFILE_SRCDIR "/events", 1); |
| 212 | |
| 213 | for (it = tests; it->cpu_type != CPU_NO_GOOD; ++it) |
| 214 | do_test(it); |
| 215 | |
| 216 | return 0; |
| 217 | } |