C++程序  |  218行  |  5.1 KB

/**
 * @file alloc_counter_tests.c
 *
 * @remark Copyright 2003 OProfile authors
 * @remark Read the file COPYING
 *
 * @author John Levon
 * @author Philippe Elie
 */

#include <stdlib.h>
#include <stdio.h>

#include "op_parse_event.h"
#include "op_alloc_counter.h"
#include "op_events.h"
#include "op_hw_config.h"
#include "op_cpu_type.h"
#include "op_events.h"

/* FIXME: alpha description events need 20 but when running test on x86
 * OP_MAX_COUNTERS is 8, so we can't use it */
#define MAX_EVENTS 20


/* some test are setup to fail in a known way */
enum failure_type {
	no_failure,
	fail_to_find_event,
	fail_to_alloc_counter
};

struct allocated_counter {
	op_cpu cpu_type;
	char  const * const * events;
	size_t alloc_map[MAX_EVENTS];
	/* expected failure for this test */
	enum failure_type failure;
};


/* not more than MAX_EVENTS string for all these arrays */
static char const * const events_alpha_ev4_1[] = {
	"ISSUES:4096:0:1:1",
	NULL
};

static char const * const events_alpha_ev4_2[] = {
	"UNKNOWN_EVENT:4096:0:1:1",
	NULL
};

static char const * const events_ppro_1[] = {
	"CPU_CLK_UNHALTED:4096:0:1:1",
	NULL
};

static char const * const events_ppro_2[] = {
	"CPU_CLK_UNHALTED:4096:0:1:1",
	"DATA_MEM_REFS:4096:0:1:1",
	NULL
};

static char const * const events_ppro_3[] = {
	/* fail_to_alloc_counter: 2 event to counter 0 */
	"COMP_FLOP_RET:4096:0:1:1",
	"FLOPS:4096:0:1:1",
	NULL
};

static char const * const events_ppro_4[] = {
	"FLOPS:4096:0:1:1",
	"FP_ASSIST:4096:0:1:1",
	NULL
};

static char const * const events_ppro_5[] = {
	"FP_ASSIST:4096:0:1:1",
	"FLOPS:4096:0:1:1",
	NULL
};

static char const * const events_p4_1[] = {
	"BRANCH_RETIRED:4096:1:1:1",
	"MISPRED_BRANCH_RETIRED:4096:1:1:1",
	"BPU_FETCH_REQUEST:4096:1:1:1",
	"ITLB_REFERENCE:4096:1:1:1",
	"MEMORY_CANCEL:4096:4:1:1",
	"MEMORY_COMPLETE:4096:1:1:1",
	"TC_MS_XFER:4096:1:1:1",
	"UOP_QUEUE_WRITES:4096:1:1:1",
	NULL
};

static char const * const events_p4_2[] = {
	/* fail_to_alloc_counter: 3 event to counter 3, 7 */
	"BRANCH_RETIRED:4096:1:1:1",
	"MISPRED_BRANCH_RETIRED:4096:1:1:1",
	"INSTR_RETIRED:4096:1:1:1",
	"BPU_FETCH_REQUEST:4096:1:1:1",
	"ITLB_REFERENCE:4096:1:1:1",
	"MEMORY_CANCEL:4096:4:1:1",
	"MEMORY_COMPLETE:4096:1:1:1",
	"TC_MS_XFER:4096:1:1:1",
	NULL
};

static char const * const events_mips_34k[] = {
	/* fail_to_alloc_counter: w/o 2006-8-03  Jeremiah Lott patch, see
	 * ChangeLog */
	"DTLB_MISSES:500:0:1:1",
	"JR_31_INSNS:500:0:1:1",
	NULL
};

static struct allocated_counter const tests[] = {
	{ CPU_AXP_EV4, events_alpha_ev4_1, { 0 }, no_failure },
	{ CPU_AXP_EV4, events_alpha_ev4_2, { -1 }, fail_to_find_event },
	{ CPU_PPRO, events_ppro_1, { 0 }, no_failure },
	{ CPU_PPRO, events_ppro_2, { 0, 1 }, no_failure },
	{ CPU_PPRO, events_ppro_3, { -1 }, fail_to_alloc_counter },
	{ CPU_PPRO, events_ppro_4, { 0, 1 }, no_failure },
	{ CPU_PPRO, events_ppro_5, { 1, 0 }, no_failure },
	{ CPU_P4, events_p4_1, { 3, 7, 0, 4, 2, 6, 1, 5 }, no_failure },
	{ CPU_P4, events_p4_2, { -1 }, fail_to_alloc_counter },
	{ CPU_MIPS_34K, events_mips_34k, { 1, 0 }, no_failure },
	{ CPU_NO_GOOD, 0, { 0 }, 0 }
};


static void show_events(char const * const * events)
{
	for ( ; *events; ++events)
		printf("%s\n", *events);
}


static void show_counter_map(size_t const * counter_map, size_t nr_events)
{
	size_t i;
	for (i = 0; i < nr_events; ++i)
		printf("%lu ", (unsigned long)counter_map[i]);
	printf("\n");
}


static void do_test(struct allocated_counter const * it)
{
	size_t i;
	size_t * counter_map;
	size_t nr_events;
	struct parsed_event parsed[MAX_EVENTS];
	struct op_event const * event[MAX_EVENTS];

	op_events(it->cpu_type);

	nr_events = parse_events(parsed, MAX_EVENTS, it->events);

	for (i = 0; i < nr_events; ++i) {
		event[i] = find_event_by_name(parsed[i].name, parsed[i].unit_mask,
		                              parsed[i].unit_mask_valid);
		if (!event[i]) {
			if (it->failure == fail_to_find_event)
				goto free_events;
			printf("Can't find events %s for cpu %s\n",
			       parsed[i].name,
			       op_get_cpu_type_str(it->cpu_type));
			exit(EXIT_FAILURE);
		}
	}

	counter_map =  map_event_to_counter(event, nr_events, it->cpu_type);
	if (!counter_map) {
		if (it->failure == fail_to_alloc_counter)
			goto free_events;
		printf("Can't map this set of events to counter:\n");
		show_events(it->events);
		exit(EXIT_FAILURE);
	}

	for (i = 0; i < nr_events; ++i) {
		if (counter_map[i] != it->alloc_map[i]) {
			printf("Incorrect allocation map for these events:\n");
			show_events(it->events);
			printf("(expect, found):\n");
			show_counter_map(it->alloc_map, nr_events);
			show_counter_map(counter_map, nr_events);
			exit(EXIT_FAILURE);
		}
	}

	if (it->failure != no_failure) {
		/* test should fail but success! */
		printf("test should fail with a failure type %d but succeed "
		       "for events:\n", it->failure);
		for (i = 0; i < nr_events; ++i)
			printf("%s\n", it->events[i]);
		exit(EXIT_FAILURE);
	}

	free(counter_map);
free_events:
	op_free_events();
}


int main(void)
{
	struct allocated_counter const * it;

	setenv("OPROFILE_EVENTS_DIR", OPROFILE_SRCDIR "/events", 1);

	for (it = tests; it->cpu_type != CPU_NO_GOOD; ++it)
		do_test(it);

	return 0;
}