xref: /freebsd-src/usr.sbin/pmcstudy/pmcstudy.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
1d95b3509SRandall Stewart /*-
252467047SWarner Losh  * Copyright (c) 2014-2015 Netflix, Inc.
3d95b3509SRandall Stewart  *
4d95b3509SRandall Stewart  * Redistribution and use in source and binary forms, with or without
5d95b3509SRandall Stewart  * modification, are permitted provided that the following conditions
6d95b3509SRandall Stewart  * are met:
7d95b3509SRandall Stewart  * 1. Redistributions of source code must retain the above copyright
8d95b3509SRandall Stewart  *    notice, this list of conditions and the following disclaimer,
9d95b3509SRandall Stewart  *    in this position and unchanged.
10d95b3509SRandall Stewart  * 2. Redistributions in binary form must reproduce the above copyright
11d95b3509SRandall Stewart  *    notice, this list of conditions and the following disclaimer in the
12d95b3509SRandall Stewart  *    documentation and/or other materials provided with the distribution.
13d95b3509SRandall Stewart  * 3. The name of the author may not be used to endorse or promote products
14d95b3509SRandall Stewart  *    derived from this software without specific prior written permission
15d95b3509SRandall Stewart  *
16d95b3509SRandall Stewart  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17d95b3509SRandall Stewart  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18d95b3509SRandall Stewart  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19d95b3509SRandall Stewart  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20d95b3509SRandall Stewart  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21d95b3509SRandall Stewart  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22d95b3509SRandall Stewart  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23d95b3509SRandall Stewart  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24d95b3509SRandall Stewart  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25d95b3509SRandall Stewart  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26d95b3509SRandall Stewart  */
27d95b3509SRandall Stewart #include <sys/types.h>
28d95b3509SRandall Stewart #include <stdio.h>
29d95b3509SRandall Stewart #include <stdlib.h>
30d95b3509SRandall Stewart #include <unistd.h>
31d95b3509SRandall Stewart #include <string.h>
32d95b3509SRandall Stewart #include <strings.h>
33d95b3509SRandall Stewart #include <sys/errno.h>
34d95b3509SRandall Stewart #include <signal.h>
35d95b3509SRandall Stewart #include <sys/wait.h>
36d95b3509SRandall Stewart #include <getopt.h>
37d95b3509SRandall Stewart #include "eval_expr.h"
38eef0660aSRandall Stewart static int max_pmc_counters = 1;
39eef0660aSRandall Stewart static int run_all = 0;
40eef0660aSRandall Stewart 
41d95b3509SRandall Stewart #define MAX_COUNTER_SLOTS 1024
42d95b3509SRandall Stewart #define MAX_NLEN 64
43d95b3509SRandall Stewart #define MAX_CPU 64
44d95b3509SRandall Stewart static int verbose = 0;
45d95b3509SRandall Stewart 
46d95b3509SRandall Stewart extern char **environ;
47d95b3509SRandall Stewart extern struct expression *master_exp;
48d95b3509SRandall Stewart struct expression *master_exp=NULL;
49d95b3509SRandall Stewart 
50d95b3509SRandall Stewart #define PMC_INITIAL_ALLOC 512
51d95b3509SRandall Stewart extern char **valid_pmcs;
52d95b3509SRandall Stewart char **valid_pmcs = NULL;
53d95b3509SRandall Stewart extern int valid_pmc_cnt;
54d95b3509SRandall Stewart int valid_pmc_cnt=0;
55d95b3509SRandall Stewart extern int pmc_allocated_cnt;
56d95b3509SRandall Stewart int pmc_allocated_cnt=0;
57d95b3509SRandall Stewart 
58d95b3509SRandall Stewart /*
59d95b3509SRandall Stewart  * The following two varients on popen and pclose with
60d95b3509SRandall Stewart  * the cavet that they get you the PID so that you
61d95b3509SRandall Stewart  * can supply it to pclose so it can send a SIGTERM
62d95b3509SRandall Stewart  *  to the process.
63d95b3509SRandall Stewart  */
64d95b3509SRandall Stewart static FILE *
my_popen(const char * command,const char * dir,pid_t * p_pid)65d95b3509SRandall Stewart my_popen(const char *command, const char *dir, pid_t *p_pid)
66d95b3509SRandall Stewart {
67d95b3509SRandall Stewart 	FILE *io_out, *io_in;
68d95b3509SRandall Stewart 	int pdesin[2], pdesout[2];
69d95b3509SRandall Stewart 	char *argv[4];
70d95b3509SRandall Stewart 	pid_t pid;
71d95b3509SRandall Stewart 	char cmd[4];
72d95b3509SRandall Stewart 	char cmd2[1024];
73d95b3509SRandall Stewart 	char arg1[4];
74d95b3509SRandall Stewart 
75d95b3509SRandall Stewart 	if ((strcmp(dir, "r") != 0) &&
76d95b3509SRandall Stewart 	    (strcmp(dir, "w") != 0)) {
77d95b3509SRandall Stewart 		errno = EINVAL;
78d95b3509SRandall Stewart 		return(NULL);
79d95b3509SRandall Stewart 	}
80d95b3509SRandall Stewart 	if (pipe(pdesin) < 0)
81d95b3509SRandall Stewart 		return (NULL);
82d95b3509SRandall Stewart 
83d95b3509SRandall Stewart 	if (pipe(pdesout) < 0) {
84d95b3509SRandall Stewart 		(void)close(pdesin[0]);
85d95b3509SRandall Stewart 		(void)close(pdesin[1]);
86d95b3509SRandall Stewart 		return (NULL);
87d95b3509SRandall Stewart 	}
88d95b3509SRandall Stewart 	strcpy(cmd, "sh");
89d95b3509SRandall Stewart 	strcpy(arg1, "-c");
90d95b3509SRandall Stewart 	strcpy(cmd2, command);
91d95b3509SRandall Stewart 	argv[0] = cmd;
92d95b3509SRandall Stewart 	argv[1] = arg1;
93d95b3509SRandall Stewart 	argv[2] = cmd2;
94d95b3509SRandall Stewart 	argv[3] = NULL;
95d95b3509SRandall Stewart 
96d95b3509SRandall Stewart 	switch (pid = fork()) {
97d95b3509SRandall Stewart 	case -1:			/* Error. */
98d95b3509SRandall Stewart 		(void)close(pdesin[0]);
99d95b3509SRandall Stewart 		(void)close(pdesin[1]);
100d95b3509SRandall Stewart 		(void)close(pdesout[0]);
101d95b3509SRandall Stewart 		(void)close(pdesout[1]);
102d95b3509SRandall Stewart 		return (NULL);
103d95b3509SRandall Stewart 		/* NOTREACHED */
104d95b3509SRandall Stewart 	case 0:				/* Child. */
105d95b3509SRandall Stewart 		/* Close out un-used sides */
106d95b3509SRandall Stewart 		(void)close(pdesin[1]);
107d95b3509SRandall Stewart 		(void)close(pdesout[0]);
108d95b3509SRandall Stewart 		/* Now prepare the stdin of the process */
109d95b3509SRandall Stewart 		close(0);
110d95b3509SRandall Stewart 		(void)dup(pdesin[0]);
111d95b3509SRandall Stewart 		(void)close(pdesin[0]);
112d95b3509SRandall Stewart 		/* Now prepare the stdout of the process */
113d95b3509SRandall Stewart 		close(1);
114d95b3509SRandall Stewart 		(void)dup(pdesout[1]);
115d95b3509SRandall Stewart 		/* And lets do stderr just in case */
116d95b3509SRandall Stewart 		close(2);
117d95b3509SRandall Stewart 		(void)dup(pdesout[1]);
118d95b3509SRandall Stewart 		(void)close(pdesout[1]);
119d95b3509SRandall Stewart 		/* Now run it */
120d95b3509SRandall Stewart 		execve("/bin/sh", argv, environ);
121d95b3509SRandall Stewart 		exit(127);
122d95b3509SRandall Stewart 		/* NOTREACHED */
123d95b3509SRandall Stewart 	}
124d95b3509SRandall Stewart 	/* Parent; assume fdopen can't fail. */
125d95b3509SRandall Stewart 	/* Store the pid */
126d95b3509SRandall Stewart 	*p_pid = pid;
127d95b3509SRandall Stewart 	if (strcmp(dir, "r") != 0) {
128d95b3509SRandall Stewart 		io_out = fdopen(pdesin[1], "w");
129d95b3509SRandall Stewart 		(void)close(pdesin[0]);
130d95b3509SRandall Stewart 		(void)close(pdesout[0]);
131d95b3509SRandall Stewart 		(void)close(pdesout[1]);
132d95b3509SRandall Stewart 		return(io_out);
133d95b3509SRandall Stewart  	} else {
134d95b3509SRandall Stewart 		/* Prepare the input stream */
135d95b3509SRandall Stewart 		io_in = fdopen(pdesout[0], "r");
136d95b3509SRandall Stewart 		(void)close(pdesout[1]);
137d95b3509SRandall Stewart 		(void)close(pdesin[0]);
138d95b3509SRandall Stewart 		(void)close(pdesin[1]);
139d95b3509SRandall Stewart 		return (io_in);
140d95b3509SRandall Stewart 	}
141d95b3509SRandall Stewart }
142d95b3509SRandall Stewart 
143d95b3509SRandall Stewart /*
144d95b3509SRandall Stewart  * pclose --
145d95b3509SRandall Stewart  *	Pclose returns -1 if stream is not associated with a `popened' command,
146d95b3509SRandall Stewart  *	if already `pclosed', or waitpid returns an error.
147d95b3509SRandall Stewart  */
148d95b3509SRandall Stewart static void
my_pclose(FILE * io,pid_t the_pid)149d95b3509SRandall Stewart my_pclose(FILE *io, pid_t the_pid)
150d95b3509SRandall Stewart {
151d95b3509SRandall Stewart 	int pstat;
152d95b3509SRandall Stewart 	pid_t pid;
153d95b3509SRandall Stewart 
154d95b3509SRandall Stewart 	/*
155d95b3509SRandall Stewart 	 * Find the appropriate file pointer and remove it from the list.
156d95b3509SRandall Stewart 	 */
157d95b3509SRandall Stewart 	(void)fclose(io);
158d95b3509SRandall Stewart 	/* Die if you are not dead! */
159d95b3509SRandall Stewart 	kill(the_pid, SIGTERM);
160d95b3509SRandall Stewart 	do {
161d95b3509SRandall Stewart 		pid = wait4(the_pid, &pstat, 0, (struct rusage *)0);
162d95b3509SRandall Stewart 	} while (pid == -1 && errno == EINTR);
163d95b3509SRandall Stewart }
164d95b3509SRandall Stewart 
165d95b3509SRandall Stewart struct counters {
166d95b3509SRandall Stewart 	struct counters *next_cpu;
167d95b3509SRandall Stewart 	char counter_name[MAX_NLEN];		/* Name of counter */
168d95b3509SRandall Stewart 	int cpu;				/* CPU we are on */
169d95b3509SRandall Stewart 	int pos;				/* Index we are filling to. */
170d95b3509SRandall Stewart 	uint64_t vals[MAX_COUNTER_SLOTS];	/* Last 64 entries */
171d95b3509SRandall Stewart 	uint64_t sum;				/* Summary of entries */
172d95b3509SRandall Stewart };
173d95b3509SRandall Stewart 
174d95b3509SRandall Stewart extern struct counters *glob_cpu[MAX_CPU];
175d95b3509SRandall Stewart struct counters *glob_cpu[MAX_CPU];
176d95b3509SRandall Stewart 
177d95b3509SRandall Stewart extern struct counters *cnts;
178d95b3509SRandall Stewart struct counters *cnts=NULL;
179d95b3509SRandall Stewart 
180d95b3509SRandall Stewart extern int ncnts;
181d95b3509SRandall Stewart int ncnts=0;
182d95b3509SRandall Stewart 
183d95b3509SRandall Stewart extern int (*expression)(struct counters *, int);
184d95b3509SRandall Stewart int (*expression)(struct counters *, int);
185d95b3509SRandall Stewart 
186d95b3509SRandall Stewart static const char *threshold=NULL;
187d95b3509SRandall Stewart static const char *command;
188d95b3509SRandall Stewart 
189d95b3509SRandall Stewart struct cpu_entry {
190d95b3509SRandall Stewart 	const char *name;
191d95b3509SRandall Stewart 	const char *thresh;
192d95b3509SRandall Stewart 	const char *command;
193d95b3509SRandall Stewart 	int (*func)(struct counters *, int);
194eef0660aSRandall Stewart 	int counters_required;
195d95b3509SRandall Stewart };
196d95b3509SRandall Stewart 
197d95b3509SRandall Stewart struct cpu_type {
198d95b3509SRandall Stewart 	char cputype[32];
199d95b3509SRandall Stewart 	int number;
200d95b3509SRandall Stewart 	struct cpu_entry *ents;
201d95b3509SRandall Stewart 	void (*explain)(const char *name);
202d95b3509SRandall Stewart };
203d95b3509SRandall Stewart extern struct cpu_type the_cpu;
204d95b3509SRandall Stewart struct cpu_type the_cpu;
205d95b3509SRandall Stewart 
206d95b3509SRandall Stewart static void
explain_name_sb(const char * name)207d95b3509SRandall Stewart explain_name_sb(const char *name)
208d95b3509SRandall Stewart {
209d95b3509SRandall Stewart 	const char *mythresh;
210d95b3509SRandall Stewart 	if (strcmp(name, "allocstall1") == 0) {
211d95b3509SRandall Stewart 		printf("Examine PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW / CPU_CLK_UNHALTED.THREAD_P\n");
212d95b3509SRandall Stewart 		mythresh = "thresh > .05";
213d95b3509SRandall Stewart 	} else if (strcmp(name, "allocstall2") == 0) {
214d95b3509SRandall Stewart 		printf("Examine PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP_CYCLES/CPU_CLK_UNHALTED.THREAD_P\n");
215d95b3509SRandall Stewart 		mythresh = "thresh > .05";
216d95b3509SRandall Stewart 	} else if (strcmp(name, "br_miss") == 0) {
217d95b3509SRandall Stewart 		printf("Examine (20 * BR_MISP_RETIRED.ALL_BRANCHES)/CPU_CLK_UNHALTED.THREAD_P\n");
218d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
219d95b3509SRandall Stewart 	} else if (strcmp(name, "splitload") == 0) {
220eef0660aSRandall Stewart 		printf("Examine MEM_UOPS_RETIRED.SPLIT_LOADS * 5) / CPU_CLK_UNHALTED.THREAD_P\n");
221d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
222d95b3509SRandall Stewart 	} else if (strcmp(name, "splitstore") == 0) {
223eef0660aSRandall Stewart 		printf("Examine MEM_UOPS_RETIRED.SPLIT_STORES / MEM_UOPS_RETIRED.ALL_STORES\n");
224d95b3509SRandall Stewart 		mythresh = "thresh >= .01";
225d95b3509SRandall Stewart 	} else if (strcmp(name, "contested") == 0) {
226d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 60) / CPU_CLK_UNHALTED.THREAD_P\n");
227d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
228d95b3509SRandall Stewart 	} else if (strcmp(name, "blockstorefwd") == 0) {
229d95b3509SRandall Stewart 		printf("Examine (LD_BLOCKS_STORE_FORWARD * 13) / CPU_CLK_UNHALTED.THREAD_P\n");
230d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
231d95b3509SRandall Stewart 	} else if (strcmp(name, "cache2") == 0) {
232d95b3509SRandall Stewart 		printf("Examine ((MEM_LOAD_RETIRED.L3_HIT * 26) + \n");
233d95b3509SRandall Stewart 		printf("         (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT * 43) + \n");
234d95b3509SRandall Stewart 		printf("         (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 60)) / CPU_CLK_UNHALTED.THREAD_P\n");
235d95b3509SRandall Stewart 		printf("**Note we have it labeled MEM_LOAD_UOPS_RETIRED.LLC_HIT not MEM_LOAD_RETIRED.L3_HIT\n");
236d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
237d95b3509SRandall Stewart 	} else if (strcmp(name, "cache1") == 0) {
238d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS * 180) / CPU_CLK_UNHALTED.THREAD_P\n");
239d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
240d95b3509SRandall Stewart 	} else if (strcmp(name, "dtlbmissload") == 0) {
241d95b3509SRandall Stewart 		printf("Examine (((DTLB_LOAD_MISSES.STLB_HIT * 7) + DTLB_LOAD_MISSES.WALK_DURATION)\n");
242d95b3509SRandall Stewart 		printf("         / CPU_CLK_UNHALTED.THREAD_P)\n");
243d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
244d95b3509SRandall Stewart 	} else if (strcmp(name, "frontendstall") == 0) {
245d95b3509SRandall Stewart 		printf("Examine IDQ_UOPS_NOT_DELIVERED.CORE / (CPU_CLK_UNHALTED.THREAD_P * 4)\n");
246d95b3509SRandall Stewart 		mythresh = "thresh >= .15";
247d95b3509SRandall Stewart 	} else if (strcmp(name, "clears") == 0) {
248d95b3509SRandall Stewart 		printf("Examine ((MACHINE_CLEARS.MEMORY_ORDERING + \n");
249d95b3509SRandall Stewart 		printf("          MACHINE_CLEARS.SMC + \n");
250d95b3509SRandall Stewart 		printf("          MACHINE_CLEARS.MASKMOV ) * 100 ) / CPU_CLK_UNHALTED.THREAD_P\n");
251d95b3509SRandall Stewart 		mythresh = "thresh >= .02";
252d95b3509SRandall Stewart 	} else if (strcmp(name, "microassist") == 0) {
253d95b3509SRandall Stewart 		printf("Examine IDQ.MS_CYCLES / (CPU_CLK_UNHALTED.THREAD_P * 4)\n");
254d95b3509SRandall Stewart 		printf("***We use IDQ.MS_UOPS,cmask=1 to get cycles\n");
255d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
256d95b3509SRandall Stewart 	} else if (strcmp(name, "aliasing_4k") == 0) {
257d95b3509SRandall Stewart 		printf("Examine (LD_BLOCKS_PARTIAL.ADDRESS_ALIAS * 5) / CPU_CLK_UNHALTED.THREAD_P\n");
258d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
259d95b3509SRandall Stewart 	} else if (strcmp(name, "fpassist") == 0) {
260d95b3509SRandall Stewart 		printf("Examine FP_ASSIST.ANY/INST_RETIRED.ANY_P\n");
261d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
262d95b3509SRandall Stewart 	} else if (strcmp(name, "otherassistavx") == 0) {
263d95b3509SRandall Stewart 		printf("Examine (OTHER_ASSISTS.AVX_TO_SSE * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
264d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
265d95b3509SRandall Stewart 	} else if (strcmp(name, "otherassistsse") == 0) {
266d95b3509SRandall Stewart 		printf("Examine (OTHER_ASSISTS.SSE_TO_AVX * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
267d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
268d95b3509SRandall Stewart 	} else if (strcmp(name, "eff1") == 0) {
269d95b3509SRandall Stewart 		printf("Examine (UOPS_RETIRED.RETIRE_SLOTS)/(4 *CPU_CLK_UNHALTED.THREAD_P)\n");
270d95b3509SRandall Stewart 		mythresh = "thresh < .9";
271d95b3509SRandall Stewart 	} else if (strcmp(name, "eff2") == 0) {
272d95b3509SRandall Stewart 		printf("Examine CPU_CLK_UNHALTED.THREAD_P/INST_RETIRED.ANY_P\n");
273d95b3509SRandall Stewart 		mythresh = "thresh > 1.0";
274d95b3509SRandall Stewart 	} else if (strcmp(name, "dtlbmissstore") == 0) {
275d95b3509SRandall Stewart 		printf("Examine (((DTLB_STORE_MISSES.STLB_HIT * 7) + DTLB_STORE_MISSES.WALK_DURATION)\n");
276d95b3509SRandall Stewart 		printf("         / CPU_CLK_UNHALTED.THREAD_P)\n");
277d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
278d95b3509SRandall Stewart 	} else {
279d95b3509SRandall Stewart 		printf("Unknown name:%s\n", name);
280d95b3509SRandall Stewart 		mythresh = "unknown entry";
281d95b3509SRandall Stewart         }
282d95b3509SRandall Stewart 	printf("If the value printed is %s we may have the ability to improve performance\n", mythresh);
283d95b3509SRandall Stewart }
284d95b3509SRandall Stewart 
285d95b3509SRandall Stewart static void
explain_name_ib(const char * name)286d95b3509SRandall Stewart explain_name_ib(const char *name)
287d95b3509SRandall Stewart {
288d95b3509SRandall Stewart 	const char *mythresh;
289d95b3509SRandall Stewart 	if (strcmp(name, "br_miss") == 0) {
290d95b3509SRandall Stewart 		printf("Examine ((BR_MISP_RETIRED.ALL_BRANCHES /(BR_MISP_RETIRED.ALL_BRANCHES +\n");
291d95b3509SRandall Stewart 		printf("         MACHINE_CLEAR.COUNT) * ((UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES)\n");
292d95b3509SRandall Stewart 		printf("/ (4 * CPU_CLK_UNHALTED.THREAD))))\n");
293d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
294d95b3509SRandall Stewart 	} else if (strcmp(name, "eff1") == 0) {
295d95b3509SRandall Stewart 		printf("Examine (UOPS_RETIRED.RETIRE_SLOTS)/(4 *CPU_CLK_UNHALTED.THREAD_P)\n");
296d95b3509SRandall Stewart 		mythresh = "thresh < .9";
297d95b3509SRandall Stewart 	} else if (strcmp(name, "eff2") == 0) {
298d95b3509SRandall Stewart 		printf("Examine CPU_CLK_UNHALTED.THREAD_P/INST_RETIRED.ANY_P\n");
299d95b3509SRandall Stewart 		mythresh = "thresh > 1.0";
300d95b3509SRandall Stewart 	} else if (strcmp(name, "cache1") == 0) {
301d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM * 180) / CPU_CLK_UNHALTED.THREAD_P\n");
302d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
303d95b3509SRandall Stewart 	} else if (strcmp(name, "cache2") == 0) {
304d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_RETIRED.LLC_HIT / CPU_CLK_UNHALTED.THREAD_P\n");
305d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
306d95b3509SRandall Stewart 	} else if (strcmp(name, "itlbmiss") == 0) {
307d95b3509SRandall Stewart 		printf("Examine ITLB_MISSES.WALK_DURATION / CPU_CLK_UNHALTED.THREAD_P\n");
308d95b3509SRandall Stewart 		mythresh = "thresh > .05";
309d95b3509SRandall Stewart 	} else if (strcmp(name, "icachemiss") == 0) {
310d95b3509SRandall Stewart 		printf("Examine (ICACHE.IFETCH_STALL - ITLB_MISSES.WALK_DURATION)/ CPU_CLK_UNHALTED.THREAD_P\n");
311d95b3509SRandall Stewart 		mythresh = "thresh > .05";
312d95b3509SRandall Stewart 	} else if (strcmp(name, "lcpstall") == 0) {
313d95b3509SRandall Stewart 		printf("Examine ILD_STALL.LCP/CPU_CLK_UNHALTED.THREAD_P\n");
314d95b3509SRandall Stewart 		mythresh = "thresh > .05";
315d95b3509SRandall Stewart 	} else if (strcmp(name, "datashare") == 0) {
316d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT * 43)/CPU_CLK_UNHALTED.THREAD_P\n");
317d95b3509SRandall Stewart 		mythresh = "thresh > .05";
318d95b3509SRandall Stewart 	} else if (strcmp(name, "blockstorefwd") == 0) {
319d95b3509SRandall Stewart 		printf("Examine (LD_BLOCKS_STORE_FORWARD * 13) / CPU_CLK_UNHALTED.THREAD_P\n");
320d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
321d95b3509SRandall Stewart 	} else if (strcmp(name, "splitload") == 0) {
322d95b3509SRandall Stewart 		printf("Examine  ((L1D_PEND_MISS.PENDING / MEM_LOAD_UOPS_RETIRED.L1_MISS) *\n");
323d95b3509SRandall Stewart 		printf("         LD_BLOCKS.NO_SR)/CPU_CLK_UNHALTED.THREAD_P\n");
324d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
325d95b3509SRandall Stewart 	} else if (strcmp(name, "splitstore") == 0) {
326eef0660aSRandall Stewart 		printf("Examine MEM_UOPS_RETIRED.SPLIT_STORES / MEM_UOPS_RETIRED.ALL_STORES\n");
327d95b3509SRandall Stewart 		mythresh = "thresh >= .01";
328d95b3509SRandall Stewart 	} else if (strcmp(name, "aliasing_4k") == 0) {
329d95b3509SRandall Stewart 		printf("Examine (LD_BLOCKS_PARTIAL.ADDRESS_ALIAS * 5) / CPU_CLK_UNHALTED.THREAD_P\n");
330d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
331d95b3509SRandall Stewart 	} else if (strcmp(name, "dtlbmissload") == 0) {
332d95b3509SRandall Stewart 		printf("Examine (((DTLB_LOAD_MISSES.STLB_HIT * 7) + DTLB_LOAD_MISSES.WALK_DURATION)\n");
333d95b3509SRandall Stewart 		printf("         / CPU_CLK_UNHALTED.THREAD_P)\n");
334d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
335d95b3509SRandall Stewart 	} else if (strcmp(name, "dtlbmissstore") == 0) {
336d95b3509SRandall Stewart 		printf("Examine (((DTLB_STORE_MISSES.STLB_HIT * 7) + DTLB_STORE_MISSES.WALK_DURATION)\n");
337d95b3509SRandall Stewart 		printf("         / CPU_CLK_UNHALTED.THREAD_P)\n");
338d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
339d95b3509SRandall Stewart 	} else if (strcmp(name, "contested") == 0) {
340d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 60) / CPU_CLK_UNHALTED.THREAD_P\n");
341d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
342d95b3509SRandall Stewart 	} else if (strcmp(name, "clears") == 0) {
343d95b3509SRandall Stewart 		printf("Examine ((MACHINE_CLEARS.MEMORY_ORDERING + \n");
344d95b3509SRandall Stewart 		printf("          MACHINE_CLEARS.SMC + \n");
345d95b3509SRandall Stewart 		printf("          MACHINE_CLEARS.MASKMOV ) * 100 ) / CPU_CLK_UNHALTED.THREAD_P\n");
346d95b3509SRandall Stewart 		mythresh = "thresh >= .02";
347d95b3509SRandall Stewart 	} else if (strcmp(name, "microassist") == 0) {
348d95b3509SRandall Stewart 		printf("Examine IDQ.MS_CYCLES / (4 * CPU_CLK_UNHALTED.THREAD_P)\n");
349d95b3509SRandall Stewart 		printf("***We use IDQ.MS_UOPS,cmask=1 to get cycles\n");
350d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
351d95b3509SRandall Stewart 	} else if (strcmp(name, "fpassist") == 0) {
352d95b3509SRandall Stewart 		printf("Examine FP_ASSIST.ANY/INST_RETIRED.ANY_P\n");
353d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
354d95b3509SRandall Stewart 	} else if (strcmp(name, "otherassistavx") == 0) {
355d95b3509SRandall Stewart 		printf("Examine (OTHER_ASSISTS.AVX_TO_SSE * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
356d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
357d95b3509SRandall Stewart 	} else if (strcmp(name, "otherassistsse") == 0) {
358d95b3509SRandall Stewart 		printf("Examine (OTHER_ASSISTS.SSE_TO_AVX * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
359d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
360d95b3509SRandall Stewart 	} else {
361d95b3509SRandall Stewart 		printf("Unknown name:%s\n", name);
362d95b3509SRandall Stewart 		mythresh = "unknown entry";
363d95b3509SRandall Stewart         }
364d95b3509SRandall Stewart 	printf("If the value printed is %s we may have the ability to improve performance\n", mythresh);
365d95b3509SRandall Stewart }
366d95b3509SRandall Stewart 
367d95b3509SRandall Stewart 
368d95b3509SRandall Stewart static void
explain_name_has(const char * name)369d95b3509SRandall Stewart explain_name_has(const char *name)
370d95b3509SRandall Stewart {
371d95b3509SRandall Stewart 	const char *mythresh;
372d95b3509SRandall Stewart 	if (strcmp(name, "eff1") == 0) {
373d95b3509SRandall Stewart 		printf("Examine (UOPS_RETIRED.RETIRE_SLOTS)/(4 *CPU_CLK_UNHALTED.THREAD_P)\n");
374d95b3509SRandall Stewart 		mythresh = "thresh < .75";
375d95b3509SRandall Stewart 	} else if (strcmp(name, "eff2") == 0) {
376d95b3509SRandall Stewart 		printf("Examine CPU_CLK_UNHALTED.THREAD_P/INST_RETIRED.ANY_P\n");
377d95b3509SRandall Stewart 		mythresh = "thresh > 1.0";
378d95b3509SRandall Stewart 	} else if (strcmp(name, "itlbmiss") == 0) {
379d95b3509SRandall Stewart 		printf("Examine ITLB_MISSES.WALK_DURATION / CPU_CLK_UNHALTED.THREAD_P\n");
380d95b3509SRandall Stewart 		mythresh = "thresh > .05";
381d95b3509SRandall Stewart 	} else if (strcmp(name, "icachemiss") == 0) {
382d95b3509SRandall Stewart 		printf("Examine (36 * ICACHE.MISSES)/ CPU_CLK_UNHALTED.THREAD_P\n");
383d95b3509SRandall Stewart 		mythresh = "thresh > .05";
384d95b3509SRandall Stewart 	} else if (strcmp(name, "lcpstall") == 0) {
385d95b3509SRandall Stewart 		printf("Examine ILD_STALL.LCP/CPU_CLK_UNHALTED.THREAD_P\n");
386d95b3509SRandall Stewart 		mythresh = "thresh > .05";
387d95b3509SRandall Stewart 	} else if (strcmp(name, "cache1") == 0) {
388d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM * 180) / CPU_CLK_UNHALTED.THREAD_P\n");
389d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
390d95b3509SRandall Stewart 	} else if (strcmp(name, "cache2") == 0) {
391d95b3509SRandall Stewart 		printf("Examine ((MEM_LOAD_UOPS_RETIRED.LLC_HIT * 36) + \n");
392d95b3509SRandall Stewart 		printf("         (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT * 72) + \n");
393d95b3509SRandall Stewart 		printf("         (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 84))\n");
394d95b3509SRandall Stewart 		printf("          / CPU_CLK_UNHALTED.THREAD_P\n");
395d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
396d95b3509SRandall Stewart 	} else if (strcmp(name, "contested") == 0) {
397d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 84) / CPU_CLK_UNHALTED.THREAD_P\n");
398d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
399d95b3509SRandall Stewart 	} else if (strcmp(name, "datashare") == 0) {
400d95b3509SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT * 72)/CPU_CLK_UNHALTED.THREAD_P\n");
401d95b3509SRandall Stewart 		mythresh = "thresh > .05";
402d95b3509SRandall Stewart 	} else if (strcmp(name, "blockstorefwd") == 0) {
403d95b3509SRandall Stewart 		printf("Examine (LD_BLOCKS_STORE_FORWARD * 13) / CPU_CLK_UNHALTED.THREAD_P\n");
404d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
405d95b3509SRandall Stewart 	} else if (strcmp(name, "splitload") == 0) {
406eef0660aSRandall Stewart 		printf("Examine  (MEM_UOPS_RETIRED.SPLIT_LOADS * 5) / CPU_CLK_UNHALTED.THREAD_P\n");
407d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
408d95b3509SRandall Stewart 	} else if (strcmp(name, "splitstore") == 0) {
409eef0660aSRandall Stewart 		printf("Examine MEM_UOPS_RETIRED.SPLIT_STORES / MEM_UOPS_RETIRED.ALL_STORES\n");
410d95b3509SRandall Stewart 		mythresh = "thresh >= .01";
411d95b3509SRandall Stewart 	} else if (strcmp(name, "aliasing_4k") == 0) {
412d95b3509SRandall Stewart 		printf("Examine (LD_BLOCKS_PARTIAL.ADDRESS_ALIAS * 5) / CPU_CLK_UNHALTED.THREAD_P\n");
413d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
414d95b3509SRandall Stewart 	} else if (strcmp(name, "dtlbmissload") == 0) {
415d95b3509SRandall Stewart 		printf("Examine (((DTLB_LOAD_MISSES.STLB_HIT * 7) + DTLB_LOAD_MISSES.WALK_DURATION)\n");
416d95b3509SRandall Stewart 		printf("         / CPU_CLK_UNHALTED.THREAD_P)\n");
417d95b3509SRandall Stewart 		mythresh = "thresh >= .1";
418d95b3509SRandall Stewart 	} else if (strcmp(name, "br_miss") == 0) {
419d95b3509SRandall Stewart 		printf("Examine (20 * BR_MISP_RETIRED.ALL_BRANCHES)/CPU_CLK_UNHALTED.THREAD\n");
420d95b3509SRandall Stewart 		mythresh = "thresh >= .2";
421d95b3509SRandall Stewart 	} else if (strcmp(name, "clears") == 0) {
422d95b3509SRandall Stewart 		printf("Examine ((MACHINE_CLEARS.MEMORY_ORDERING + \n");
423d95b3509SRandall Stewart 		printf("          MACHINE_CLEARS.SMC + \n");
424d95b3509SRandall Stewart 		printf("          MACHINE_CLEARS.MASKMOV ) * 100 ) / CPU_CLK_UNHALTED.THREAD_P\n");
425d95b3509SRandall Stewart 		mythresh = "thresh >= .02";
426d95b3509SRandall Stewart 	} else if (strcmp(name, "microassist") == 0) {
427d95b3509SRandall Stewart 		printf("Examine IDQ.MS_CYCLES / (4 * CPU_CLK_UNHALTED.THREAD_P)\n");
428d95b3509SRandall Stewart 		printf("***We use IDQ.MS_UOPS,cmask=1 to get cycles\n");
429d95b3509SRandall Stewart 		mythresh = "thresh >= .05";
430d95b3509SRandall Stewart 	} else if (strcmp(name, "fpassist") == 0) {
431d95b3509SRandall Stewart 		printf("Examine FP_ASSIST.ANY/INST_RETIRED.ANY_P\n");
432d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
433d95b3509SRandall Stewart 	} else if (strcmp(name, "otherassistavx") == 0) {
434d95b3509SRandall Stewart 		printf("Examine (OTHER_ASSISTS.AVX_TO_SSE * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
435d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
436d95b3509SRandall Stewart 	} else if (strcmp(name, "otherassistsse") == 0) {
437d95b3509SRandall Stewart 		printf("Examine (OTHER_ASSISTS.SSE_TO_AVX * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
438d95b3509SRandall Stewart 		mythresh = "look for a excessive value";
439d95b3509SRandall Stewart 	} else {
440d95b3509SRandall Stewart 		printf("Unknown name:%s\n", name);
441d95b3509SRandall Stewart 		mythresh = "unknown entry";
442d95b3509SRandall Stewart         }
443d95b3509SRandall Stewart 	printf("If the value printed is %s we may have the ability to improve performance\n", mythresh);
444d95b3509SRandall Stewart }
445d95b3509SRandall Stewart 
446eef0660aSRandall Stewart 
447eef0660aSRandall Stewart 
448d95b3509SRandall Stewart static struct counters *
find_counter(struct counters * base,const char * name)449d95b3509SRandall Stewart find_counter(struct counters *base, const char *name)
450d95b3509SRandall Stewart {
451d95b3509SRandall Stewart 	struct counters *at;
452d95b3509SRandall Stewart 	int len;
453d95b3509SRandall Stewart 
454d95b3509SRandall Stewart 	at = base;
455d95b3509SRandall Stewart 	len = strlen(name);
456d95b3509SRandall Stewart 	while(at) {
457d95b3509SRandall Stewart 		if (strncmp(at->counter_name, name, len) == 0) {
458d95b3509SRandall Stewart 			return(at);
459d95b3509SRandall Stewart 		}
460d95b3509SRandall Stewart 		at = at->next_cpu;
461d95b3509SRandall Stewart 	}
462d95b3509SRandall Stewart 	printf("Can't find counter %s\n", name);
463d95b3509SRandall Stewart 	printf("We have:\n");
464d95b3509SRandall Stewart 	at = base;
465d95b3509SRandall Stewart 	while(at) {
466d95b3509SRandall Stewart 		printf("- %s\n", at->counter_name);
467d95b3509SRandall Stewart 		at = at->next_cpu;
468d95b3509SRandall Stewart 	}
469d95b3509SRandall Stewart 	exit(-1);
470d95b3509SRandall Stewart }
471d95b3509SRandall Stewart 
472d95b3509SRandall Stewart static int
allocstall1(struct counters * cpu,int pos)473d95b3509SRandall Stewart allocstall1(struct counters *cpu, int pos)
474d95b3509SRandall Stewart {
475d95b3509SRandall Stewart /*  1  - PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW/CPU_CLK_UNHALTED.THREAD_P (thresh > .05)*/
476d95b3509SRandall Stewart 	int ret;
477d95b3509SRandall Stewart 	struct counters *partial;
478d95b3509SRandall Stewart 	struct counters *unhalt;
479d95b3509SRandall Stewart 	double un, par, res;
480d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
481d95b3509SRandall Stewart 	partial = find_counter(cpu, "PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW");
482d95b3509SRandall Stewart 	if (pos != -1) {
483d95b3509SRandall Stewart 		par = partial->vals[pos] * 1.0;
484d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
485d95b3509SRandall Stewart 	} else {
486d95b3509SRandall Stewart 		par = partial->sum * 1.0;
487d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
488d95b3509SRandall Stewart 	}
489d95b3509SRandall Stewart 	res = par/un;
490d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
491d95b3509SRandall Stewart 	return(ret);
492d95b3509SRandall Stewart }
493d95b3509SRandall Stewart 
494d95b3509SRandall Stewart static int
allocstall2(struct counters * cpu,int pos)495d95b3509SRandall Stewart allocstall2(struct counters *cpu, int pos)
496d95b3509SRandall Stewart {
497d95b3509SRandall Stewart /*  2  - PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP_CYCLES/CPU_CLK_UNHALTED.THREAD_P (thresh >.05) */
498d95b3509SRandall Stewart 	int ret;
499d95b3509SRandall Stewart 	struct counters *partial;
500d95b3509SRandall Stewart 	struct counters *unhalt;
501d95b3509SRandall Stewart 	double un, par, res;
502d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
503d95b3509SRandall Stewart 	partial = find_counter(cpu, "PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP");
504d95b3509SRandall Stewart 	if (pos != -1) {
505d95b3509SRandall Stewart 		par = partial->vals[pos] * 1.0;
506d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
507d95b3509SRandall Stewart 	} else {
508d95b3509SRandall Stewart 		par = partial->sum * 1.0;
509d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
510d95b3509SRandall Stewart 	}
511d95b3509SRandall Stewart 	res = par/un;
512d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
513d95b3509SRandall Stewart 	return(ret);
514d95b3509SRandall Stewart }
515d95b3509SRandall Stewart 
516d95b3509SRandall Stewart static int
br_mispredict(struct counters * cpu,int pos)517d95b3509SRandall Stewart br_mispredict(struct counters *cpu, int pos)
518d95b3509SRandall Stewart {
519d95b3509SRandall Stewart 	struct counters *brctr;
520d95b3509SRandall Stewart 	struct counters *unhalt;
521d95b3509SRandall Stewart 	int ret;
522d95b3509SRandall Stewart /*  3  - (20 * BR_MISP_RETIRED.ALL_BRANCHES)/CPU_CLK_UNHALTED.THREAD_P (thresh >= .2) */
523d95b3509SRandall Stewart 	double br, un, con, res;
524d95b3509SRandall Stewart 	con = 20.0;
525d95b3509SRandall Stewart 
526d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
527d95b3509SRandall Stewart         brctr = find_counter(cpu, "BR_MISP_RETIRED.ALL_BRANCHES");
528d95b3509SRandall Stewart 	if (pos != -1) {
529d95b3509SRandall Stewart 		br = brctr->vals[pos] * 1.0;
530d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
531d95b3509SRandall Stewart 	} else {
532d95b3509SRandall Stewart 		br = brctr->sum * 1.0;
533d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
534d95b3509SRandall Stewart 	}
535d95b3509SRandall Stewart 	res = (con * br)/un;
536d95b3509SRandall Stewart  	ret = printf("%1.3f", res);
537d95b3509SRandall Stewart 	return(ret);
538d95b3509SRandall Stewart }
539d95b3509SRandall Stewart 
540d95b3509SRandall Stewart static int
br_mispredictib(struct counters * cpu,int pos)541d95b3509SRandall Stewart br_mispredictib(struct counters *cpu, int pos)
542d95b3509SRandall Stewart {
543d95b3509SRandall Stewart 	struct counters *brctr;
544d95b3509SRandall Stewart 	struct counters *unhalt;
545d95b3509SRandall Stewart 	struct counters *clear, *clear2, *clear3;
546d95b3509SRandall Stewart 	struct counters *uops;
547d95b3509SRandall Stewart 	struct counters *recv;
548d95b3509SRandall Stewart 	struct counters *iss;
549d95b3509SRandall Stewart /*	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s BR_MISP_RETIRED.ALL_BRANCHES -s MACHINE_CLEARS.MEMORY_ORDERING -s MACHINE_CLEARS.SMC -s MACHINE_CLEARS.MASKMOV -s UOPS_ISSUED.ANY -s UOPS_RETIRED.RETIRE_SLOTS -s INT_MISC.RECOVERY_CYCLES -w 1",*/
550d95b3509SRandall Stewart 	int ret;
551d95b3509SRandall Stewart         /*
552eef0660aSRandall Stewart 	 * (BR_MISP_RETIRED.ALL_BRANCHES /
553eef0660aSRandall Stewart 	 *         (BR_MISP_RETIRED.ALL_BRANCHES +
554eef0660aSRandall Stewart 	 *          MACHINE_CLEAR.COUNT) *
555eef0660aSRandall Stewart 	 *	   ((UOPS_ISSUED.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES) / (4 * CPU_CLK_UNHALTED.THREAD)))
556d95b3509SRandall Stewart 	 *
557d95b3509SRandall Stewart 	 */
558d95b3509SRandall Stewart 	double br, cl, cl2, cl3, uo, re, un, con, res, is;
559d95b3509SRandall Stewart 	con = 4.0;
560d95b3509SRandall Stewart 
561d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
562d95b3509SRandall Stewart         brctr = find_counter(cpu, "BR_MISP_RETIRED.ALL_BRANCHES");
563d95b3509SRandall Stewart 	clear = find_counter(cpu, "MACHINE_CLEARS.MEMORY_ORDERING");
564d95b3509SRandall Stewart 	clear2 = find_counter(cpu, "MACHINE_CLEARS.SMC");
565d95b3509SRandall Stewart 	clear3 = find_counter(cpu, "MACHINE_CLEARS.MASKMOV");
566d95b3509SRandall Stewart 	uops = find_counter(cpu, "UOPS_RETIRED.RETIRE_SLOTS");
567d95b3509SRandall Stewart 	iss = find_counter(cpu, "UOPS_ISSUED.ANY");
568d95b3509SRandall Stewart 	recv = find_counter(cpu, "INT_MISC.RECOVERY_CYCLES");
569d95b3509SRandall Stewart 	if (pos != -1) {
570d95b3509SRandall Stewart 		br = brctr->vals[pos] * 1.0;
571d95b3509SRandall Stewart 		cl = clear->vals[pos] * 1.0;
572d95b3509SRandall Stewart 		cl2 = clear2->vals[pos] * 1.0;
573d95b3509SRandall Stewart 		cl3 = clear3->vals[pos] * 1.0;
574d95b3509SRandall Stewart 		uo = uops->vals[pos] * 1.0;
575d95b3509SRandall Stewart 		re = recv->vals[pos] * 1.0;
576d95b3509SRandall Stewart 		is = iss->vals[pos] * 1.0;
577d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
578d95b3509SRandall Stewart 	} else {
579d95b3509SRandall Stewart 		br = brctr->sum * 1.0;
580d95b3509SRandall Stewart 		cl = clear->sum * 1.0;
581d95b3509SRandall Stewart 		cl2 = clear2->sum * 1.0;
582d95b3509SRandall Stewart 		cl3 = clear3->sum * 1.0;
583d95b3509SRandall Stewart 		uo = uops->sum * 1.0;
584d95b3509SRandall Stewart 		re = recv->sum * 1.0;
585d95b3509SRandall Stewart 		is = iss->sum * 1.0;
586d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
587d95b3509SRandall Stewart 	}
588d95b3509SRandall Stewart 	res = (br/(br + cl + cl2 + cl3) * ((is - uo + con * re) / (con * un)));
589d95b3509SRandall Stewart  	ret = printf("%1.3f", res);
590d95b3509SRandall Stewart 	return(ret);
591d95b3509SRandall Stewart }
592d95b3509SRandall Stewart 
593eef0660aSRandall Stewart 
594d95b3509SRandall Stewart static int
br_mispredict_broad(struct counters * cpu,int pos)595ade40db3SRandall Stewart br_mispredict_broad(struct counters *cpu, int pos)
596ade40db3SRandall Stewart {
597ade40db3SRandall Stewart 	struct counters *brctr;
598ade40db3SRandall Stewart 	struct counters *unhalt;
599ade40db3SRandall Stewart 	struct counters *clear;
600ade40db3SRandall Stewart 	struct counters *uops;
601ade40db3SRandall Stewart 	struct counters *uops_ret;
602ade40db3SRandall Stewart 	struct counters *recv;
603ade40db3SRandall Stewart 	int ret;
604ade40db3SRandall Stewart 	double br, cl, uo, uo_r, re, con, un, res;
605ade40db3SRandall Stewart 
606ade40db3SRandall Stewart 	con = 4.0;
607ade40db3SRandall Stewart 
608ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
609ade40db3SRandall Stewart         brctr = find_counter(cpu, "BR_MISP_RETIRED.ALL_BRANCHES");
610ade40db3SRandall Stewart 	clear = find_counter(cpu, "MACHINE_CLEARS.CYCLES");
611ade40db3SRandall Stewart 	uops = find_counter(cpu, "UOPS_ISSUED.ANY");
612ade40db3SRandall Stewart 	uops_ret = find_counter(cpu, "UOPS_RETIRED.RETIRE_SLOTS");
613ade40db3SRandall Stewart 	recv = find_counter(cpu, "INT_MISC.RECOVERY_CYCLES");
614ade40db3SRandall Stewart 
615ade40db3SRandall Stewart 	if (pos != -1) {
616ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
617ade40db3SRandall Stewart 		br = brctr->vals[pos] * 1.0;
618ade40db3SRandall Stewart 		cl = clear->vals[pos] * 1.0;
619ade40db3SRandall Stewart 		uo = uops->vals[pos] * 1.0;
620ade40db3SRandall Stewart 		uo_r = uops_ret->vals[pos] * 1.0;
621ade40db3SRandall Stewart 		re = recv->vals[pos] * 1.0;
622ade40db3SRandall Stewart 	} else {
623ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
624ade40db3SRandall Stewart 		br = brctr->sum * 1.0;
625ade40db3SRandall Stewart 		cl = clear->sum * 1.0;
626ade40db3SRandall Stewart 		uo = uops->sum * 1.0;
627ade40db3SRandall Stewart 		uo_r = uops_ret->sum * 1.0;
628ade40db3SRandall Stewart 		re = recv->sum * 1.0;
629ade40db3SRandall Stewart 	}
630ade40db3SRandall Stewart 	res = br / (br + cl) * (uo - uo_r + con * re) / (un * con);
631ade40db3SRandall Stewart  	ret = printf("%1.3f", res);
632ade40db3SRandall Stewart 	return(ret);
633ade40db3SRandall Stewart }
634ade40db3SRandall Stewart 
635ade40db3SRandall Stewart static int
splitloadib(struct counters * cpu,int pos)636d95b3509SRandall Stewart splitloadib(struct counters *cpu, int pos)
637d95b3509SRandall Stewart {
638d95b3509SRandall Stewart 	int ret;
639d95b3509SRandall Stewart 	struct counters *mem;
640d95b3509SRandall Stewart 	struct counters *l1d, *ldblock;
641d95b3509SRandall Stewart 	struct counters *unhalt;
642d95b3509SRandall Stewart 	double un, memd, res, l1, ldb;
643d95b3509SRandall Stewart         /*
644eef0660aSRandall Stewart 	 * ((L1D_PEND_MISS.PENDING / MEM_LOAD_UOPS_RETIRED.L1_MISS) * LD_BLOCKS.NO_SR) / CPU_CLK_UNHALTED.THREAD_P
645eef0660aSRandall Stewart 	 * "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s L1D_PEND_MISS.PENDING -s MEM_LOAD_UOPS_RETIRED.L1_MISS -s LD_BLOCKS.NO_SR -w 1",
646d95b3509SRandall Stewart 	 */
647d95b3509SRandall Stewart 
648d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
649d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_RETIRED.L1_MISS");
650d95b3509SRandall Stewart 	l1d = find_counter(cpu, "L1D_PEND_MISS.PENDING");
651d95b3509SRandall Stewart 	ldblock = find_counter(cpu, "LD_BLOCKS.NO_SR");
652d95b3509SRandall Stewart 	if (pos != -1) {
653d95b3509SRandall Stewart 		memd = mem->vals[pos] * 1.0;
654d95b3509SRandall Stewart 		l1 = l1d->vals[pos] * 1.0;
655d95b3509SRandall Stewart 		ldb = ldblock->vals[pos] * 1.0;
656d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
657d95b3509SRandall Stewart 	} else {
658d95b3509SRandall Stewart 		memd = mem->sum * 1.0;
659d95b3509SRandall Stewart 		l1 = l1d->sum * 1.0;
660d95b3509SRandall Stewart 		ldb = ldblock->sum * 1.0;
661d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
662d95b3509SRandall Stewart 	}
663d95b3509SRandall Stewart 	res = ((l1 / memd) * ldb)/un;
664d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
665d95b3509SRandall Stewart 	return(ret);
666d95b3509SRandall Stewart }
667d95b3509SRandall Stewart 
668eef0660aSRandall Stewart 
669d95b3509SRandall Stewart static int
splitload(struct counters * cpu,int pos)670d95b3509SRandall Stewart splitload(struct counters *cpu, int pos)
671d95b3509SRandall Stewart {
672d95b3509SRandall Stewart 	int ret;
673d95b3509SRandall Stewart 	struct counters *mem;
674d95b3509SRandall Stewart 	struct counters *unhalt;
675d95b3509SRandall Stewart 	double con, un, memd, res;
676eef0660aSRandall Stewart /*  4  - (MEM_UOPS_RETIRED.SPLIT_LOADS * 5) / CPU_CLK_UNHALTED.THREAD_P (thresh >= .1)*/
677058ccb75SRandall Stewart 
678eef0660aSRandall Stewart 	con = 5.0;
679eef0660aSRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
680eef0660aSRandall Stewart 	mem = find_counter(cpu, "MEM_UOPS_RETIRED.SPLIT_LOADS");
681eef0660aSRandall Stewart 	if (pos != -1) {
682eef0660aSRandall Stewart 		memd = mem->vals[pos] * 1.0;
683eef0660aSRandall Stewart 		un = unhalt->vals[pos] * 1.0;
684eef0660aSRandall Stewart 	} else {
685eef0660aSRandall Stewart 		memd = mem->sum * 1.0;
686eef0660aSRandall Stewart 		un = unhalt->sum * 1.0;
687eef0660aSRandall Stewart 	}
688eef0660aSRandall Stewart 	res = (memd * con)/un;
689eef0660aSRandall Stewart 	ret = printf("%1.3f", res);
690eef0660aSRandall Stewart 	return(ret);
691eef0660aSRandall Stewart }
692eef0660aSRandall Stewart 
693eef0660aSRandall Stewart 
694eef0660aSRandall Stewart static int
splitload_sb(struct counters * cpu,int pos)695eef0660aSRandall Stewart splitload_sb(struct counters *cpu, int pos)
696eef0660aSRandall Stewart {
697eef0660aSRandall Stewart 	int ret;
698eef0660aSRandall Stewart 	struct counters *mem;
699eef0660aSRandall Stewart 	struct counters *unhalt;
700eef0660aSRandall Stewart 	double con, un, memd, res;
701d95b3509SRandall Stewart /*  4  - (MEM_UOP_RETIRED.SPLIT_LOADS * 5) / CPU_CLK_UNHALTED.THREAD_P (thresh >= .1)*/
702d95b3509SRandall Stewart 
703d95b3509SRandall Stewart 	con = 5.0;
704d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
705d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_UOP_RETIRED.SPLIT_LOADS");
706d95b3509SRandall Stewart 	if (pos != -1) {
707d95b3509SRandall Stewart 		memd = mem->vals[pos] * 1.0;
708d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
709d95b3509SRandall Stewart 	} else {
710d95b3509SRandall Stewart 		memd = mem->sum * 1.0;
711d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
712d95b3509SRandall Stewart 	}
713d95b3509SRandall Stewart 	res = (memd * con)/un;
714d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
715d95b3509SRandall Stewart 	return(ret);
716d95b3509SRandall Stewart }
717d95b3509SRandall Stewart 
718eef0660aSRandall Stewart 
719d95b3509SRandall Stewart static int
splitstore_sb(struct counters * cpu,int pos)720eef0660aSRandall Stewart splitstore_sb(struct counters *cpu, int pos)
721d95b3509SRandall Stewart {
722eef0660aSRandall Stewart         /*  5  - MEM_UOP_RETIRED.SPLIT_STORES / MEM_UOP_RETIRED.ALL_STORES (thresh > 0.01) */
723d95b3509SRandall Stewart 	int ret;
724d95b3509SRandall Stewart 	struct counters *mem_split;
725d95b3509SRandall Stewart 	struct counters *mem_stores;
726d95b3509SRandall Stewart 	double memsplit, memstore, res;
727d95b3509SRandall Stewart 	mem_split = find_counter(cpu, "MEM_UOP_RETIRED.SPLIT_STORES");
728d95b3509SRandall Stewart 	mem_stores = find_counter(cpu, "MEM_UOP_RETIRED.ALL_STORES");
729d95b3509SRandall Stewart 	if (pos != -1) {
730d95b3509SRandall Stewart 		memsplit = mem_split->vals[pos] * 1.0;
731d95b3509SRandall Stewart 		memstore = mem_stores->vals[pos] * 1.0;
732d95b3509SRandall Stewart 	} else {
733d95b3509SRandall Stewart 		memsplit = mem_split->sum * 1.0;
734d95b3509SRandall Stewart 		memstore = mem_stores->sum * 1.0;
735d95b3509SRandall Stewart 	}
736d95b3509SRandall Stewart 	res = memsplit/memstore;
737d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
738d95b3509SRandall Stewart 	return(ret);
739d95b3509SRandall Stewart }
740d95b3509SRandall Stewart 
741d95b3509SRandall Stewart 
742eef0660aSRandall Stewart 
743eef0660aSRandall Stewart static int
splitstore(struct counters * cpu,int pos)744eef0660aSRandall Stewart splitstore(struct counters *cpu, int pos)
745eef0660aSRandall Stewart {
746eef0660aSRandall Stewart         /*  5  - MEM_UOPS_RETIRED.SPLIT_STORES / MEM_UOPS_RETIRED.ALL_STORES (thresh > 0.01) */
747eef0660aSRandall Stewart 	int ret;
748eef0660aSRandall Stewart 	struct counters *mem_split;
749eef0660aSRandall Stewart 	struct counters *mem_stores;
750eef0660aSRandall Stewart 	double memsplit, memstore, res;
751eef0660aSRandall Stewart 	mem_split = find_counter(cpu, "MEM_UOPS_RETIRED.SPLIT_STORES");
752eef0660aSRandall Stewart 	mem_stores = find_counter(cpu, "MEM_UOPS_RETIRED.ALL_STORES");
753eef0660aSRandall Stewart 	if (pos != -1) {
754eef0660aSRandall Stewart 		memsplit = mem_split->vals[pos] * 1.0;
755eef0660aSRandall Stewart 		memstore = mem_stores->vals[pos] * 1.0;
756eef0660aSRandall Stewart 	} else {
757eef0660aSRandall Stewart 		memsplit = mem_split->sum * 1.0;
758eef0660aSRandall Stewart 		memstore = mem_stores->sum * 1.0;
759eef0660aSRandall Stewart 	}
760eef0660aSRandall Stewart 	res = memsplit/memstore;
761eef0660aSRandall Stewart 	ret = printf("%1.3f", res);
762eef0660aSRandall Stewart 	return(ret);
763eef0660aSRandall Stewart }
764eef0660aSRandall Stewart 
765eef0660aSRandall Stewart 
766d95b3509SRandall Stewart static int
contested(struct counters * cpu,int pos)767d95b3509SRandall Stewart contested(struct counters *cpu, int pos)
768d95b3509SRandall Stewart {
769eef0660aSRandall Stewart         /*  6  - (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 60) / CPU_CLK_UNHALTED.THREAD_P (thresh >.05) */
770d95b3509SRandall Stewart 	int ret;
771d95b3509SRandall Stewart 	struct counters *mem;
772d95b3509SRandall Stewart 	struct counters *unhalt;
773d95b3509SRandall Stewart 	double con, un, memd, res;
774d95b3509SRandall Stewart 
775d95b3509SRandall Stewart 	con = 60.0;
776d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
777d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM");
778d95b3509SRandall Stewart 	if (pos != -1) {
779d95b3509SRandall Stewart 		memd = mem->vals[pos] * 1.0;
780d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
781d95b3509SRandall Stewart 	} else {
782d95b3509SRandall Stewart 		memd = mem->sum * 1.0;
783d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
784d95b3509SRandall Stewart 	}
785d95b3509SRandall Stewart 	res = (memd * con)/un;
786d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
787d95b3509SRandall Stewart 	return(ret);
788d95b3509SRandall Stewart }
789d95b3509SRandall Stewart 
790d95b3509SRandall Stewart static int
contested_has(struct counters * cpu,int pos)791d95b3509SRandall Stewart contested_has(struct counters *cpu, int pos)
792d95b3509SRandall Stewart {
793eef0660aSRandall Stewart         /*  6  - (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 84) / CPU_CLK_UNHALTED.THREAD_P (thresh >.05) */
794d95b3509SRandall Stewart 	int ret;
795d95b3509SRandall Stewart 	struct counters *mem;
796d95b3509SRandall Stewart 	struct counters *unhalt;
797d95b3509SRandall Stewart 	double con, un, memd, res;
798d95b3509SRandall Stewart 
799d95b3509SRandall Stewart 	con = 84.0;
800d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
801d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM");
802d95b3509SRandall Stewart 	if (pos != -1) {
803d95b3509SRandall Stewart 		memd = mem->vals[pos] * 1.0;
804d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
805d95b3509SRandall Stewart 	} else {
806d95b3509SRandall Stewart 		memd = mem->sum * 1.0;
807d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
808d95b3509SRandall Stewart 	}
809d95b3509SRandall Stewart 	res = (memd * con)/un;
810d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
811d95b3509SRandall Stewart 	return(ret);
812d95b3509SRandall Stewart }
813d95b3509SRandall Stewart 
814ade40db3SRandall Stewart static int
contestedbroad(struct counters * cpu,int pos)815ade40db3SRandall Stewart contestedbroad(struct counters *cpu, int pos)
816ade40db3SRandall Stewart {
817eef0660aSRandall Stewart         /*  6  - (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 84) / CPU_CLK_UNHALTED.THREAD_P (thresh >.05) */
818ade40db3SRandall Stewart 	int ret;
819ade40db3SRandall Stewart 	struct counters *mem;
820ade40db3SRandall Stewart 	struct counters *mem2;
821ade40db3SRandall Stewart 	struct counters *unhalt;
822ade40db3SRandall Stewart 	double con, un, memd, memtoo, res;
823ade40db3SRandall Stewart 
824ade40db3SRandall Stewart 	con = 84.0;
825ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
826ade40db3SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM");
827ade40db3SRandall Stewart 	mem2 = find_counter(cpu,"MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS");
828ade40db3SRandall Stewart 
829ade40db3SRandall Stewart 	if (pos != -1) {
830ade40db3SRandall Stewart 		memd = mem->vals[pos] * 1.0;
831ade40db3SRandall Stewart 		memtoo = mem2->vals[pos] * 1.0;
832ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
833ade40db3SRandall Stewart 	} else {
834ade40db3SRandall Stewart 		memd = mem->sum * 1.0;
835ade40db3SRandall Stewart 		memtoo = mem2->sum * 1.0;
836ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
837ade40db3SRandall Stewart 	}
838ade40db3SRandall Stewart 	res = ((memd * con) + memtoo)/un;
839ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
840ade40db3SRandall Stewart 	return(ret);
841ade40db3SRandall Stewart }
842ade40db3SRandall Stewart 
843d95b3509SRandall Stewart 
844d95b3509SRandall Stewart static int
blockstoreforward(struct counters * cpu,int pos)845d95b3509SRandall Stewart blockstoreforward(struct counters *cpu, int pos)
846d95b3509SRandall Stewart {
847eef0660aSRandall Stewart         /*  7  - (LD_BLOCKS_STORE_FORWARD * 13) / CPU_CLK_UNHALTED.THREAD_P (thresh >= .05)*/
848d95b3509SRandall Stewart 	int ret;
849d95b3509SRandall Stewart 	struct counters *ldb;
850d95b3509SRandall Stewart 	struct counters *unhalt;
851d95b3509SRandall Stewart 	double con, un, ld, res;
852d95b3509SRandall Stewart 
853d95b3509SRandall Stewart 	con = 13.0;
854d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
855d95b3509SRandall Stewart 	ldb = find_counter(cpu, "LD_BLOCKS_STORE_FORWARD");
856d95b3509SRandall Stewart 	if (pos != -1) {
857d95b3509SRandall Stewart 		ld = ldb->vals[pos] * 1.0;
858d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
859d95b3509SRandall Stewart 	} else {
860d95b3509SRandall Stewart 		ld = ldb->sum * 1.0;
861d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
862d95b3509SRandall Stewart 	}
863d95b3509SRandall Stewart 	res = (ld * con)/un;
864d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
865d95b3509SRandall Stewart 	return(ret);
866d95b3509SRandall Stewart }
867d95b3509SRandall Stewart 
868d95b3509SRandall Stewart static int
cache2(struct counters * cpu,int pos)869d95b3509SRandall Stewart cache2(struct counters *cpu, int pos)
870d95b3509SRandall Stewart {
871eef0660aSRandall Stewart 	/* ** Suspect ***
872eef0660aSRandall Stewart 	 *  8  - ((MEM_LOAD_RETIRED.L3_HIT * 26) + (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT * 43) +
873eef0660aSRandall Stewart 	 *        (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 60)) / CPU_CLK_UNHALTED.THREAD_P (thresh >.2)
874d95b3509SRandall Stewart 	 */
875d95b3509SRandall Stewart 	int ret;
876d95b3509SRandall Stewart 	struct counters *mem1, *mem2, *mem3;
877d95b3509SRandall Stewart 	struct counters *unhalt;
878d95b3509SRandall Stewart 	double con1, con2, con3, un, me_1, me_2, me_3, res;
879d95b3509SRandall Stewart 
880d95b3509SRandall Stewart 	con1 = 26.0;
881d95b3509SRandall Stewart 	con2 = 43.0;
882d95b3509SRandall Stewart 	con3 = 60.0;
883d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
884d95b3509SRandall Stewart /* Call for MEM_LOAD_RETIRED.L3_HIT possibly MEM_LOAD_UOPS_RETIRED.LLC_HIT ?*/
885d95b3509SRandall Stewart 	mem1 = find_counter(cpu, "MEM_LOAD_UOPS_RETIRED.LLC_HIT");
886d95b3509SRandall Stewart 	mem2 = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT");
887d95b3509SRandall Stewart 	mem3 = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM");
888d95b3509SRandall Stewart 	if (pos != -1) {
889d95b3509SRandall Stewart 		me_1 = mem1->vals[pos] * 1.0;
890d95b3509SRandall Stewart 		me_2 = mem2->vals[pos] * 1.0;
891d95b3509SRandall Stewart 		me_3 = mem3->vals[pos] * 1.0;
892d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
893d95b3509SRandall Stewart 	} else {
894d95b3509SRandall Stewart 		me_1 = mem1->sum * 1.0;
895d95b3509SRandall Stewart 		me_2 = mem2->sum * 1.0;
896d95b3509SRandall Stewart 		me_3 = mem3->sum * 1.0;
897d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
898d95b3509SRandall Stewart 	}
899d95b3509SRandall Stewart 	res = ((me_1 * con1) + (me_2 * con2) + (me_3 * con3))/un;
900d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
901d95b3509SRandall Stewart 	return(ret);
902d95b3509SRandall Stewart }
903d95b3509SRandall Stewart 
904d95b3509SRandall Stewart static int
datasharing(struct counters * cpu,int pos)905d95b3509SRandall Stewart datasharing(struct counters *cpu, int pos)
906d95b3509SRandall Stewart {
907d95b3509SRandall Stewart 	/*
908eef0660aSRandall Stewart 	 * (MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT * 43)/ CPU_CLK_UNHALTED.THREAD_P (thresh >.2)
909d95b3509SRandall Stewart 	 */
910d95b3509SRandall Stewart 	int ret;
911d95b3509SRandall Stewart 	struct counters *mem;
912d95b3509SRandall Stewart 	struct counters *unhalt;
913d95b3509SRandall Stewart 	double con, res, me, un;
914d95b3509SRandall Stewart 
915d95b3509SRandall Stewart 	con = 43.0;
916d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
917d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT");
918d95b3509SRandall Stewart 	if (pos != -1) {
919d95b3509SRandall Stewart 		me = mem->vals[pos] * 1.0;
920d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
921d95b3509SRandall Stewart 	} else {
922d95b3509SRandall Stewart 		me = mem->sum * 1.0;
923d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
924d95b3509SRandall Stewart 	}
925d95b3509SRandall Stewart 	res = (me * con)/un;
926d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
927d95b3509SRandall Stewart 	return(ret);
928d95b3509SRandall Stewart 
929d95b3509SRandall Stewart }
930d95b3509SRandall Stewart 
931d95b3509SRandall Stewart 
932d95b3509SRandall Stewart static int
datasharing_has(struct counters * cpu,int pos)933d95b3509SRandall Stewart datasharing_has(struct counters *cpu, int pos)
934d95b3509SRandall Stewart {
935d95b3509SRandall Stewart 	/*
936eef0660aSRandall Stewart 	 * (MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT * 43)/ CPU_CLK_UNHALTED.THREAD_P (thresh >.2)
937d95b3509SRandall Stewart 	 */
938d95b3509SRandall Stewart 	int ret;
939d95b3509SRandall Stewart 	struct counters *mem;
940d95b3509SRandall Stewart 	struct counters *unhalt;
941d95b3509SRandall Stewart 	double con, res, me, un;
942d95b3509SRandall Stewart 
943d95b3509SRandall Stewart 	con = 72.0;
944d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
945d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT");
946d95b3509SRandall Stewart 	if (pos != -1) {
947d95b3509SRandall Stewart 		me = mem->vals[pos] * 1.0;
948d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
949d95b3509SRandall Stewart 	} else {
950d95b3509SRandall Stewart 		me = mem->sum * 1.0;
951d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
952d95b3509SRandall Stewart 	}
953d95b3509SRandall Stewart 	res = (me * con)/un;
954d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
955d95b3509SRandall Stewart 	return(ret);
956d95b3509SRandall Stewart 
957d95b3509SRandall Stewart }
958d95b3509SRandall Stewart 
959d95b3509SRandall Stewart 
960d95b3509SRandall Stewart static int
cache2ib(struct counters * cpu,int pos)961d95b3509SRandall Stewart cache2ib(struct counters *cpu, int pos)
962d95b3509SRandall Stewart {
963d95b3509SRandall Stewart         /*
964eef0660aSRandall Stewart 	 *  (29 * MEM_LOAD_UOPS_RETIRED.LLC_HIT / CPU_CLK_UNHALTED.THREAD_P (thresh >.2)
965d95b3509SRandall Stewart 	 */
966d95b3509SRandall Stewart 	int ret;
967d95b3509SRandall Stewart 	struct counters *mem;
968d95b3509SRandall Stewart 	struct counters *unhalt;
969d95b3509SRandall Stewart 	double con, un, me, res;
970d95b3509SRandall Stewart 
971d95b3509SRandall Stewart 	con = 29.0;
972d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
973d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_RETIRED.LLC_HIT");
974d95b3509SRandall Stewart 	if (pos != -1) {
975d95b3509SRandall Stewart 		me = mem->vals[pos] * 1.0;
976d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
977d95b3509SRandall Stewart 	} else {
978d95b3509SRandall Stewart 		me = mem->sum * 1.0;
979d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
980d95b3509SRandall Stewart 	}
981d95b3509SRandall Stewart 	res = (con * me)/un;
982d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
983d95b3509SRandall Stewart 	return(ret);
984d95b3509SRandall Stewart }
985d95b3509SRandall Stewart 
986d95b3509SRandall Stewart static int
cache2has(struct counters * cpu,int pos)987d95b3509SRandall Stewart cache2has(struct counters *cpu, int pos)
988d95b3509SRandall Stewart {
989d95b3509SRandall Stewart 	/*
990d95b3509SRandall Stewart 	 * Examine ((MEM_LOAD_UOPS_RETIRED.LLC_HIT * 36) + \
991d95b3509SRandall Stewart 	 *          (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT * 72) +
992eef0660aSRandall Stewart 	 *          (MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 84))
993eef0660aSRandall Stewart 	 *           / CPU_CLK_UNHALTED.THREAD_P
994d95b3509SRandall Stewart 	 */
995d95b3509SRandall Stewart 	int ret;
996d95b3509SRandall Stewart 	struct counters *mem1, *mem2, *mem3;
997d95b3509SRandall Stewart 	struct counters *unhalt;
998d95b3509SRandall Stewart 	double con1, con2, con3, un, me1, me2, me3, res;
999d95b3509SRandall Stewart 
1000d95b3509SRandall Stewart 	con1 = 36.0;
1001d95b3509SRandall Stewart 	con2 = 72.0;
1002d95b3509SRandall Stewart 	con3 = 84.0;
1003d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1004d95b3509SRandall Stewart 	mem1 = find_counter(cpu, "MEM_LOAD_UOPS_RETIRED.LLC_HIT");
1005d95b3509SRandall Stewart 	mem2 = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT");
1006d95b3509SRandall Stewart 	mem3 = find_counter(cpu, "MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM");
1007d95b3509SRandall Stewart 	if (pos != -1) {
1008d95b3509SRandall Stewart 		me1 = mem1->vals[pos] * 1.0;
1009d95b3509SRandall Stewart 		me2 = mem2->vals[pos] * 1.0;
1010d95b3509SRandall Stewart 		me3 = mem3->vals[pos] * 1.0;
1011d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1012d95b3509SRandall Stewart 	} else {
1013d95b3509SRandall Stewart 		me1 = mem1->sum * 1.0;
1014d95b3509SRandall Stewart 		me2 = mem2->sum * 1.0;
1015d95b3509SRandall Stewart 		me3 = mem3->sum * 1.0;
1016d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1017d95b3509SRandall Stewart 	}
1018d95b3509SRandall Stewart 	res = ((me1 * con1) + (me2 * con2) + (me3 * con3))/un;
1019d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1020d95b3509SRandall Stewart 	return(ret);
1021d95b3509SRandall Stewart }
1022d95b3509SRandall Stewart 
1023eef0660aSRandall Stewart 
1024d95b3509SRandall Stewart static int
cache2broad(struct counters * cpu,int pos)1025ade40db3SRandall Stewart cache2broad(struct counters *cpu, int pos)
1026ade40db3SRandall Stewart {
1027ade40db3SRandall Stewart         /*
1028eef0660aSRandall Stewart 	 *  (29 * MEM_LOAD_UOPS_RETIRED.LLC_HIT / CPU_CLK_UNHALTED.THREAD_P (thresh >.2)
1029ade40db3SRandall Stewart 	 */
1030ade40db3SRandall Stewart 	int ret;
1031ade40db3SRandall Stewart 	struct counters *mem;
1032ade40db3SRandall Stewart 	struct counters *unhalt;
1033ade40db3SRandall Stewart 	double con, un, me, res;
1034ade40db3SRandall Stewart 
1035ade40db3SRandall Stewart 	con = 36.0;
1036ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1037ade40db3SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_RETIRED.L3_HIT");
1038ade40db3SRandall Stewart 	if (pos != -1) {
1039ade40db3SRandall Stewart 		me = mem->vals[pos] * 1.0;
1040ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1041ade40db3SRandall Stewart 	} else {
1042ade40db3SRandall Stewart 		me = mem->sum * 1.0;
1043ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
1044ade40db3SRandall Stewart 	}
1045ade40db3SRandall Stewart 	res = (con * me)/un;
1046ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
1047ade40db3SRandall Stewart 	return(ret);
1048ade40db3SRandall Stewart }
1049ade40db3SRandall Stewart 
1050ade40db3SRandall Stewart 
1051ade40db3SRandall Stewart static int
cache1(struct counters * cpu,int pos)1052d95b3509SRandall Stewart cache1(struct counters *cpu, int pos)
1053d95b3509SRandall Stewart {
1054eef0660aSRandall Stewart 	/*  9  - (MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS * 180) / CPU_CLK_UNHALTED.THREAD_P (thresh >= .2) */
1055d95b3509SRandall Stewart 	int ret;
1056d95b3509SRandall Stewart 	struct counters *mem;
1057d95b3509SRandall Stewart 	struct counters *unhalt;
1058d95b3509SRandall Stewart 	double con, un, me, res;
1059d95b3509SRandall Stewart 
1060d95b3509SRandall Stewart 	con = 180.0;
1061d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1062d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS");
1063d95b3509SRandall Stewart 	if (pos != -1) {
1064d95b3509SRandall Stewart 		me = mem->vals[pos] * 1.0;
1065d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1066d95b3509SRandall Stewart 	} else {
1067d95b3509SRandall Stewart 		me = mem->sum * 1.0;
1068d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1069d95b3509SRandall Stewart 	}
1070d95b3509SRandall Stewart 	res = (me * con)/un;
1071d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1072d95b3509SRandall Stewart 	return(ret);
1073d95b3509SRandall Stewart }
1074d95b3509SRandall Stewart 
1075d95b3509SRandall Stewart static int
cache1ib(struct counters * cpu,int pos)1076d95b3509SRandall Stewart cache1ib(struct counters *cpu, int pos)
1077d95b3509SRandall Stewart {
1078eef0660aSRandall Stewart 	/*  9  - (MEM_LOAD_UOPS_L3_MISS_RETIRED.LCOAL_DRAM * 180) / CPU_CLK_UNHALTED.THREAD_P (thresh >= .2) */
1079d95b3509SRandall Stewart 	int ret;
1080d95b3509SRandall Stewart 	struct counters *mem;
1081d95b3509SRandall Stewart 	struct counters *unhalt;
1082d95b3509SRandall Stewart 	double con, un, me, res;
1083d95b3509SRandall Stewart 
1084d95b3509SRandall Stewart 	con = 180.0;
1085d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1086d95b3509SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM");
1087d95b3509SRandall Stewart 	if (pos != -1) {
1088d95b3509SRandall Stewart 		me = mem->vals[pos] * 1.0;
1089d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1090d95b3509SRandall Stewart 	} else {
1091d95b3509SRandall Stewart 		me = mem->sum * 1.0;
1092d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1093d95b3509SRandall Stewart 	}
1094d95b3509SRandall Stewart 	res = (me * con)/un;
1095d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1096d95b3509SRandall Stewart 	return(ret);
1097d95b3509SRandall Stewart }
1098d95b3509SRandall Stewart 
1099d95b3509SRandall Stewart 
1100d95b3509SRandall Stewart static int
cache1broad(struct counters * cpu,int pos)1101ade40db3SRandall Stewart cache1broad(struct counters *cpu, int pos)
1102ade40db3SRandall Stewart {
1103eef0660aSRandall Stewart 	/*  9  - (MEM_LOAD_UOPS_L3_MISS_RETIRED.LCOAL_DRAM * 180) / CPU_CLK_UNHALTED.THREAD_P (thresh >= .2) */
1104ade40db3SRandall Stewart 	int ret;
1105ade40db3SRandall Stewart 	struct counters *mem;
1106ade40db3SRandall Stewart 	struct counters *unhalt;
1107ade40db3SRandall Stewart 	double con, un, me, res;
1108ade40db3SRandall Stewart 
1109ade40db3SRandall Stewart 	con = 180.0;
1110ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1111ade40db3SRandall Stewart 	mem = find_counter(cpu, "MEM_LOAD_UOPS_RETIRED.L3_MISS");
1112ade40db3SRandall Stewart 	if (pos != -1) {
1113ade40db3SRandall Stewart 		me = mem->vals[pos] * 1.0;
1114ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1115ade40db3SRandall Stewart 	} else {
1116ade40db3SRandall Stewart 		me = mem->sum * 1.0;
1117ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
1118ade40db3SRandall Stewart 	}
1119ade40db3SRandall Stewart 	res = (me * con)/un;
1120ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
1121ade40db3SRandall Stewart 	return(ret);
1122ade40db3SRandall Stewart }
1123ade40db3SRandall Stewart 
1124ade40db3SRandall Stewart 
1125ade40db3SRandall Stewart static int
dtlb_missload(struct counters * cpu,int pos)1126d95b3509SRandall Stewart dtlb_missload(struct counters *cpu, int pos)
1127d95b3509SRandall Stewart {
1128eef0660aSRandall Stewart 	/* 10  - ((DTLB_LOAD_MISSES.STLB_HIT * 7) + DTLB_LOAD_MISSES.WALK_DURATION) / CPU_CLK_UNHALTED.THREAD_P (t >=.1) */
1129d95b3509SRandall Stewart 	int ret;
1130d95b3509SRandall Stewart 	struct counters *dtlb_m, *dtlb_d;
1131d95b3509SRandall Stewart 	struct counters *unhalt;
1132d95b3509SRandall Stewart 	double con, un, d1, d2, res;
1133d95b3509SRandall Stewart 
1134d95b3509SRandall Stewart 	con = 7.0;
1135d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1136d95b3509SRandall Stewart 	dtlb_m = find_counter(cpu, "DTLB_LOAD_MISSES.STLB_HIT");
1137d95b3509SRandall Stewart 	dtlb_d = find_counter(cpu, "DTLB_LOAD_MISSES.WALK_DURATION");
1138d95b3509SRandall Stewart 	if (pos != -1) {
1139d95b3509SRandall Stewart 		d1 = dtlb_m->vals[pos] * 1.0;
1140d95b3509SRandall Stewart 		d2 = dtlb_d->vals[pos] * 1.0;
1141d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1142d95b3509SRandall Stewart 	} else {
1143d95b3509SRandall Stewart 		d1 = dtlb_m->sum * 1.0;
1144d95b3509SRandall Stewart 		d2 = dtlb_d->sum * 1.0;
1145d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1146d95b3509SRandall Stewart 	}
1147d95b3509SRandall Stewart 	res = ((d1 * con) + d2)/un;
1148d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1149d95b3509SRandall Stewart 	return(ret);
1150d95b3509SRandall Stewart }
1151d95b3509SRandall Stewart 
1152d95b3509SRandall Stewart static int
dtlb_missstore(struct counters * cpu,int pos)1153d95b3509SRandall Stewart dtlb_missstore(struct counters *cpu, int pos)
1154d95b3509SRandall Stewart {
1155d95b3509SRandall Stewart         /*
1156eef0660aSRandall Stewart 	 * ((DTLB_STORE_MISSES.STLB_HIT * 7) + DTLB_STORE_MISSES.WALK_DURATION) /
1157eef0660aSRandall Stewart 	 * CPU_CLK_UNHALTED.THREAD_P (t >= .1)
1158d95b3509SRandall Stewart 	 */
1159d95b3509SRandall Stewart         int ret;
1160d95b3509SRandall Stewart         struct counters *dtsb_m, *dtsb_d;
1161d95b3509SRandall Stewart         struct counters *unhalt;
1162d95b3509SRandall Stewart         double con, un, d1, d2, res;
1163d95b3509SRandall Stewart 
1164d95b3509SRandall Stewart         con = 7.0;
1165d95b3509SRandall Stewart         unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1166d95b3509SRandall Stewart         dtsb_m = find_counter(cpu, "DTLB_STORE_MISSES.STLB_HIT");
1167d95b3509SRandall Stewart         dtsb_d = find_counter(cpu, "DTLB_STORE_MISSES.WALK_DURATION");
1168d95b3509SRandall Stewart         if (pos != -1) {
1169d95b3509SRandall Stewart                 d1 = dtsb_m->vals[pos] * 1.0;
1170d95b3509SRandall Stewart                 d2 = dtsb_d->vals[pos] * 1.0;
1171d95b3509SRandall Stewart                 un = unhalt->vals[pos] * 1.0;
1172d95b3509SRandall Stewart         } else {
1173d95b3509SRandall Stewart                 d1 = dtsb_m->sum * 1.0;
1174d95b3509SRandall Stewart                 d2 = dtsb_d->sum * 1.0;
1175d95b3509SRandall Stewart                 un = unhalt->sum * 1.0;
1176d95b3509SRandall Stewart         }
1177d95b3509SRandall Stewart         res = ((d1 * con) + d2)/un;
1178d95b3509SRandall Stewart         ret = printf("%1.3f", res);
1179d95b3509SRandall Stewart         return(ret);
1180d95b3509SRandall Stewart }
1181d95b3509SRandall Stewart 
1182d95b3509SRandall Stewart static int
itlb_miss(struct counters * cpu,int pos)1183d95b3509SRandall Stewart itlb_miss(struct counters *cpu, int pos)
1184d95b3509SRandall Stewart {
1185d95b3509SRandall Stewart 	/* ITLB_MISSES.WALK_DURATION / CPU_CLK_UNTHREAD_P  IB */
1186d95b3509SRandall Stewart 	int ret;
1187d95b3509SRandall Stewart 	struct counters *itlb;
1188d95b3509SRandall Stewart 	struct counters *unhalt;
1189d95b3509SRandall Stewart 	double un, d1, res;
1190d95b3509SRandall Stewart 
1191d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1192d95b3509SRandall Stewart 	itlb = find_counter(cpu, "ITLB_MISSES.WALK_DURATION");
1193d95b3509SRandall Stewart 	if (pos != -1) {
1194d95b3509SRandall Stewart 		d1 = itlb->vals[pos] * 1.0;
1195d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1196d95b3509SRandall Stewart 	} else {
1197d95b3509SRandall Stewart 		d1 = itlb->sum * 1.0;
1198d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1199d95b3509SRandall Stewart 	}
1200d95b3509SRandall Stewart 	res = d1/un;
1201d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1202d95b3509SRandall Stewart 	return(ret);
1203d95b3509SRandall Stewart }
1204d95b3509SRandall Stewart 
1205ade40db3SRandall Stewart 
1206ade40db3SRandall Stewart static int
itlb_miss_broad(struct counters * cpu,int pos)1207ade40db3SRandall Stewart itlb_miss_broad(struct counters *cpu, int pos)
1208ade40db3SRandall Stewart {
1209eef0660aSRandall Stewart 	/* (7 * ITLB_MISSES.STLB_HIT_4K + ITLB_MISSES.WALK_DURATION) / CPU_CLK_UNTHREAD_P   */
1210ade40db3SRandall Stewart 	int ret;
1211ade40db3SRandall Stewart 	struct counters *itlb;
1212ade40db3SRandall Stewart 	struct counters *unhalt;
1213ade40db3SRandall Stewart 	struct counters *four_k;
1214ade40db3SRandall Stewart 	double un, d1, res, k;
1215ade40db3SRandall Stewart 
1216ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1217ade40db3SRandall Stewart 	itlb = find_counter(cpu, "ITLB_MISSES.WALK_DURATION");
1218ade40db3SRandall Stewart 	four_k = find_counter(cpu, "ITLB_MISSES.STLB_HIT_4K");
1219ade40db3SRandall Stewart 	if (pos != -1) {
1220ade40db3SRandall Stewart 		d1 = itlb->vals[pos] * 1.0;
1221ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1222ade40db3SRandall Stewart 		k = four_k->vals[pos] * 1.0;
1223ade40db3SRandall Stewart 	} else {
1224ade40db3SRandall Stewart 		d1 = itlb->sum * 1.0;
1225ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
1226ade40db3SRandall Stewart 		k = four_k->sum * 1.0;
1227ade40db3SRandall Stewart 	}
1228ade40db3SRandall Stewart 	res = (7.0 * k + d1)/un;
1229ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
1230ade40db3SRandall Stewart 	return(ret);
1231ade40db3SRandall Stewart }
1232ade40db3SRandall Stewart 
1233ade40db3SRandall Stewart 
1234d95b3509SRandall Stewart static int
icache_miss(struct counters * cpu,int pos)1235d95b3509SRandall Stewart icache_miss(struct counters *cpu, int pos)
1236d95b3509SRandall Stewart {
1237eef0660aSRandall Stewart 	/* (ICACHE.IFETCH_STALL - ITLB_MISSES.WALK_DURATION) / CPU_CLK_UNHALTED.THREAD_P IB */
1238d95b3509SRandall Stewart 
1239d95b3509SRandall Stewart 	int ret;
1240d95b3509SRandall Stewart 	struct counters *itlb, *icache;
1241d95b3509SRandall Stewart 	struct counters *unhalt;
1242d95b3509SRandall Stewart 	double un, d1, ic, res;
1243d95b3509SRandall Stewart 
1244d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1245d95b3509SRandall Stewart 	itlb = find_counter(cpu, "ITLB_MISSES.WALK_DURATION");
1246d95b3509SRandall Stewart 	icache = find_counter(cpu, "ICACHE.IFETCH_STALL");
1247d95b3509SRandall Stewart 	if (pos != -1) {
1248d95b3509SRandall Stewart 		d1 = itlb->vals[pos] * 1.0;
1249d95b3509SRandall Stewart 		ic = icache->vals[pos] * 1.0;
1250d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1251d95b3509SRandall Stewart 	} else {
1252d95b3509SRandall Stewart 		d1 = itlb->sum * 1.0;
1253d95b3509SRandall Stewart 		ic = icache->sum * 1.0;
1254d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1255d95b3509SRandall Stewart 	}
1256d95b3509SRandall Stewart 	res = (ic-d1)/un;
1257d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1258d95b3509SRandall Stewart 	return(ret);
1259d95b3509SRandall Stewart 
1260d95b3509SRandall Stewart }
1261d95b3509SRandall Stewart 
1262d95b3509SRandall Stewart static int
icache_miss_has(struct counters * cpu,int pos)1263d95b3509SRandall Stewart icache_miss_has(struct counters *cpu, int pos)
1264d95b3509SRandall Stewart {
1265d95b3509SRandall Stewart 	/* (36 * ICACHE.MISSES) / CPU_CLK_UNHALTED.THREAD_P */
1266d95b3509SRandall Stewart 
1267d95b3509SRandall Stewart 	int ret;
1268d95b3509SRandall Stewart 	struct counters *icache;
1269d95b3509SRandall Stewart 	struct counters *unhalt;
1270d95b3509SRandall Stewart 	double un, con, ic, res;
1271d95b3509SRandall Stewart 
1272d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1273d95b3509SRandall Stewart 	icache = find_counter(cpu, "ICACHE.MISSES");
1274d95b3509SRandall Stewart 	con = 36.0;
1275d95b3509SRandall Stewart 	if (pos != -1) {
1276d95b3509SRandall Stewart 		ic = icache->vals[pos] * 1.0;
1277d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1278d95b3509SRandall Stewart 	} else {
1279d95b3509SRandall Stewart 		ic = icache->sum * 1.0;
1280d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1281d95b3509SRandall Stewart 	}
1282d95b3509SRandall Stewart 	res = (con * ic)/un;
1283d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1284d95b3509SRandall Stewart 	return(ret);
1285d95b3509SRandall Stewart 
1286d95b3509SRandall Stewart }
1287d95b3509SRandall Stewart 
1288d95b3509SRandall Stewart static int
lcp_stall(struct counters * cpu,int pos)1289d95b3509SRandall Stewart lcp_stall(struct counters *cpu, int pos)
1290d95b3509SRandall Stewart {
1291d95b3509SRandall Stewart          /* ILD_STALL.LCP/CPU_CLK_UNHALTED.THREAD_P IB */
1292d95b3509SRandall Stewart 	int ret;
1293d95b3509SRandall Stewart 	struct counters *ild;
1294d95b3509SRandall Stewart 	struct counters *unhalt;
1295d95b3509SRandall Stewart 	double un, d1, res;
1296d95b3509SRandall Stewart 
1297d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1298d95b3509SRandall Stewart 	ild = find_counter(cpu, "ILD_STALL.LCP");
1299d95b3509SRandall Stewart 	if (pos != -1) {
1300d95b3509SRandall Stewart 		d1 = ild->vals[pos] * 1.0;
1301d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1302d95b3509SRandall Stewart 	} else {
1303d95b3509SRandall Stewart 		d1 = ild->sum * 1.0;
1304d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1305d95b3509SRandall Stewart 	}
1306d95b3509SRandall Stewart 	res = d1/un;
1307d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1308d95b3509SRandall Stewart 	return(ret);
1309d95b3509SRandall Stewart 
1310d95b3509SRandall Stewart }
1311d95b3509SRandall Stewart 
1312d95b3509SRandall Stewart 
1313d95b3509SRandall Stewart static int
frontendstall(struct counters * cpu,int pos)1314d95b3509SRandall Stewart frontendstall(struct counters *cpu, int pos)
1315d95b3509SRandall Stewart {
1316eef0660aSRandall Stewart       /* 12  -  IDQ_UOPS_NOT_DELIVERED.CORE / (CPU_CLK_UNHALTED.THREAD_P * 4) (thresh >= .15) */
1317d95b3509SRandall Stewart 	int ret;
1318d95b3509SRandall Stewart 	struct counters *idq;
1319d95b3509SRandall Stewart 	struct counters *unhalt;
1320d95b3509SRandall Stewart 	double con, un, id, res;
1321d95b3509SRandall Stewart 
1322d95b3509SRandall Stewart 	con = 4.0;
1323d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1324d95b3509SRandall Stewart 	idq = find_counter(cpu, "IDQ_UOPS_NOT_DELIVERED.CORE");
1325d95b3509SRandall Stewart 	if (pos != -1) {
1326d95b3509SRandall Stewart 		id = idq->vals[pos] * 1.0;
1327d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1328d95b3509SRandall Stewart 	} else {
1329d95b3509SRandall Stewart 		id = idq->sum * 1.0;
1330d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1331d95b3509SRandall Stewart 	}
1332d95b3509SRandall Stewart 	res = id/(un * con);
1333d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1334d95b3509SRandall Stewart 	return(ret);
1335d95b3509SRandall Stewart }
1336d95b3509SRandall Stewart 
1337d95b3509SRandall Stewart static int
clears(struct counters * cpu,int pos)1338d95b3509SRandall Stewart clears(struct counters *cpu, int pos)
1339d95b3509SRandall Stewart {
1340eef0660aSRandall Stewart 	/* 13  - ((MACHINE_CLEARS.MEMORY_ORDERING + MACHINE_CLEARS.SMC + MACHINE_CLEARS.MASKMOV ) * 100 )
1341eef0660aSRandall Stewart 	 *         / CPU_CLK_UNHALTED.THREAD_P (thresh  >= .02)*/
1342d95b3509SRandall Stewart 
1343d95b3509SRandall Stewart 	int ret;
1344d95b3509SRandall Stewart 	struct counters *clr1, *clr2, *clr3;
1345d95b3509SRandall Stewart 	struct counters *unhalt;
1346d95b3509SRandall Stewart 	double con, un, cl1, cl2, cl3, res;
1347d95b3509SRandall Stewart 
1348d95b3509SRandall Stewart 	con = 100.0;
1349d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1350d95b3509SRandall Stewart 	clr1 = find_counter(cpu, "MACHINE_CLEARS.MEMORY_ORDERING");
1351d95b3509SRandall Stewart 	clr2 = find_counter(cpu, "MACHINE_CLEARS.SMC");
1352d95b3509SRandall Stewart 	clr3 = find_counter(cpu, "MACHINE_CLEARS.MASKMOV");
1353d95b3509SRandall Stewart 
1354d95b3509SRandall Stewart 	if (pos != -1) {
1355d95b3509SRandall Stewart 		cl1 = clr1->vals[pos] * 1.0;
1356d95b3509SRandall Stewart 		cl2 = clr2->vals[pos] * 1.0;
1357d95b3509SRandall Stewart 		cl3 = clr3->vals[pos] * 1.0;
1358d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1359d95b3509SRandall Stewart 	} else {
1360d95b3509SRandall Stewart 		cl1 = clr1->sum * 1.0;
1361d95b3509SRandall Stewart 		cl2 = clr2->sum * 1.0;
1362d95b3509SRandall Stewart 		cl3 = clr3->sum * 1.0;
1363d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1364d95b3509SRandall Stewart 	}
1365d95b3509SRandall Stewart 	res = ((cl1 + cl2 + cl3) * con)/un;
1366d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1367d95b3509SRandall Stewart 	return(ret);
1368d95b3509SRandall Stewart }
1369d95b3509SRandall Stewart 
1370eef0660aSRandall Stewart 
1371eef0660aSRandall Stewart 
1372d95b3509SRandall Stewart static int
clears_broad(struct counters * cpu,int pos)1373ade40db3SRandall Stewart clears_broad(struct counters *cpu, int pos)
1374ade40db3SRandall Stewart {
1375ade40db3SRandall Stewart 	int ret;
1376ade40db3SRandall Stewart 	struct counters *clr1, *clr2, *clr3, *cyc;
1377ade40db3SRandall Stewart 	struct counters *unhalt;
1378ade40db3SRandall Stewart 	double con, un, cl1, cl2, cl3, cy, res;
1379ade40db3SRandall Stewart 
1380ade40db3SRandall Stewart 	con = 100.0;
1381ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1382ade40db3SRandall Stewart 	clr1 = find_counter(cpu, "MACHINE_CLEARS.MEMORY_ORDERING");
1383ade40db3SRandall Stewart 	clr2 = find_counter(cpu, "MACHINE_CLEARS.SMC");
1384ade40db3SRandall Stewart 	clr3 = find_counter(cpu, "MACHINE_CLEARS.MASKMOV");
1385ade40db3SRandall Stewart 	cyc = find_counter(cpu, "MACHINE_CLEARS.CYCLES");
1386ade40db3SRandall Stewart 	if (pos != -1) {
1387ade40db3SRandall Stewart 		cl1 = clr1->vals[pos] * 1.0;
1388ade40db3SRandall Stewart 		cl2 = clr2->vals[pos] * 1.0;
1389ade40db3SRandall Stewart 		cl3 = clr3->vals[pos] * 1.0;
1390ade40db3SRandall Stewart 		cy = cyc->vals[pos] * 1.0;
1391ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1392ade40db3SRandall Stewart 	} else {
1393ade40db3SRandall Stewart 		cl1 = clr1->sum * 1.0;
1394ade40db3SRandall Stewart 		cl2 = clr2->sum * 1.0;
1395ade40db3SRandall Stewart 		cl3 = clr3->sum * 1.0;
1396ade40db3SRandall Stewart 		cy = cyc->sum * 1.0;
1397ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
1398ade40db3SRandall Stewart 	}
1399ade40db3SRandall Stewart 	/* Formula not listed but extrapulated to add the cy ?? */
1400ade40db3SRandall Stewart 	res = ((cl1 + cl2 + cl3 + cy) * con)/un;
1401ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
1402ade40db3SRandall Stewart 	return(ret);
1403ade40db3SRandall Stewart }
1404ade40db3SRandall Stewart 
1405eef0660aSRandall Stewart 
1406eef0660aSRandall Stewart 
1407eef0660aSRandall Stewart 
1408eef0660aSRandall Stewart 
1409ade40db3SRandall Stewart static int
microassist(struct counters * cpu,int pos)1410d95b3509SRandall Stewart microassist(struct counters *cpu, int pos)
1411d95b3509SRandall Stewart {
1412d95b3509SRandall Stewart 	/* 14  - IDQ.MS_CYCLES / CPU_CLK_UNHALTED.THREAD_P (thresh > .05) */
1413d95b3509SRandall Stewart 	int ret;
1414d95b3509SRandall Stewart 	struct counters *idq;
1415d95b3509SRandall Stewart 	struct counters *unhalt;
1416d95b3509SRandall Stewart 	double un, id, res, con;
1417d95b3509SRandall Stewart 
1418d95b3509SRandall Stewart 	con = 4.0;
1419d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1420d95b3509SRandall Stewart 	idq = find_counter(cpu, "IDQ.MS_UOPS");
1421d95b3509SRandall Stewart 	if (pos != -1) {
1422d95b3509SRandall Stewart 		id = idq->vals[pos] * 1.0;
1423d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1424d95b3509SRandall Stewart 	} else {
1425d95b3509SRandall Stewart 		id = idq->sum * 1.0;
1426d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1427d95b3509SRandall Stewart 	}
1428d95b3509SRandall Stewart 	res = id/(un * con);
1429d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1430d95b3509SRandall Stewart 	return(ret);
1431d95b3509SRandall Stewart }
1432d95b3509SRandall Stewart 
1433eef0660aSRandall Stewart 
1434ade40db3SRandall Stewart static int
microassist_broad(struct counters * cpu,int pos)1435ade40db3SRandall Stewart microassist_broad(struct counters *cpu, int pos)
1436ade40db3SRandall Stewart {
1437ade40db3SRandall Stewart 	int ret;
1438ade40db3SRandall Stewart 	struct counters *idq;
1439ade40db3SRandall Stewart 	struct counters *unhalt;
1440ade40db3SRandall Stewart 	struct counters *uopiss;
1441ade40db3SRandall Stewart 	struct counters *uopret;
1442ade40db3SRandall Stewart 	double un, id, res, con, uoi, uor;
1443ade40db3SRandall Stewart 
1444ade40db3SRandall Stewart 	con = 4.0;
1445ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1446ade40db3SRandall Stewart 	idq = find_counter(cpu, "IDQ.MS_UOPS");
1447ade40db3SRandall Stewart 	uopiss = find_counter(cpu, "UOPS_ISSUED.ANY");
1448ade40db3SRandall Stewart 	uopret = find_counter(cpu, "UOPS_RETIRED.RETIRE_SLOTS");
1449ade40db3SRandall Stewart 	if (pos != -1) {
1450ade40db3SRandall Stewart 		id = idq->vals[pos] * 1.0;
1451ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1452ade40db3SRandall Stewart 		uoi = uopiss->vals[pos] * 1.0;
1453ade40db3SRandall Stewart 		uor = uopret->vals[pos] * 1.0;
1454ade40db3SRandall Stewart 	} else {
1455ade40db3SRandall Stewart 		id = idq->sum * 1.0;
1456ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
1457ade40db3SRandall Stewart 		uoi = uopiss->sum * 1.0;
1458ade40db3SRandall Stewart 		uor = uopret->sum * 1.0;
1459ade40db3SRandall Stewart 	}
1460ade40db3SRandall Stewart 	res = (uor/uoi) * (id/(un * con));
1461ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
1462ade40db3SRandall Stewart 	return(ret);
1463ade40db3SRandall Stewart }
1464d95b3509SRandall Stewart 
1465eef0660aSRandall Stewart 
1466d95b3509SRandall Stewart static int
aliasing(struct counters * cpu,int pos)1467d95b3509SRandall Stewart aliasing(struct counters *cpu, int pos)
1468d95b3509SRandall Stewart {
1469eef0660aSRandall Stewart 	/* 15  - (LD_BLOCKS_PARTIAL.ADDRESS_ALIAS * 5) / CPU_CLK_UNHALTED.THREAD_P (thresh > .1) */
1470d95b3509SRandall Stewart 	int ret;
1471d95b3509SRandall Stewart 	struct counters *ld;
1472d95b3509SRandall Stewart 	struct counters *unhalt;
1473d95b3509SRandall Stewart 	double un, lds, con, res;
1474d95b3509SRandall Stewart 
1475d95b3509SRandall Stewart 	con = 5.0;
1476d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1477d95b3509SRandall Stewart 	ld = find_counter(cpu, "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS");
1478d95b3509SRandall Stewart 	if (pos != -1) {
1479d95b3509SRandall Stewart 		lds = ld->vals[pos] * 1.0;
1480d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1481d95b3509SRandall Stewart 	} else {
1482d95b3509SRandall Stewart 		lds = ld->sum * 1.0;
1483d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1484d95b3509SRandall Stewart 	}
1485d95b3509SRandall Stewart 	res = (lds * con)/un;
1486d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1487d95b3509SRandall Stewart 	return(ret);
1488d95b3509SRandall Stewart }
1489d95b3509SRandall Stewart 
1490d95b3509SRandall Stewart static int
aliasing_broad(struct counters * cpu,int pos)1491ade40db3SRandall Stewart aliasing_broad(struct counters *cpu, int pos)
1492ade40db3SRandall Stewart {
1493eef0660aSRandall Stewart 	/* 15  - (LD_BLOCKS_PARTIAL.ADDRESS_ALIAS * 5) / CPU_CLK_UNHALTED.THREAD_P (thresh > .1) */
1494ade40db3SRandall Stewart 	int ret;
1495ade40db3SRandall Stewart 	struct counters *ld;
1496ade40db3SRandall Stewart 	struct counters *unhalt;
1497ade40db3SRandall Stewart 	double un, lds, con, res;
1498ade40db3SRandall Stewart 
1499ade40db3SRandall Stewart 	con = 7.0;
1500ade40db3SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1501ade40db3SRandall Stewart 	ld = find_counter(cpu, "LD_BLOCKS_PARTIAL.ADDRESS_ALIAS");
1502ade40db3SRandall Stewart 	if (pos != -1) {
1503ade40db3SRandall Stewart 		lds = ld->vals[pos] * 1.0;
1504ade40db3SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1505ade40db3SRandall Stewart 	} else {
1506ade40db3SRandall Stewart 		lds = ld->sum * 1.0;
1507ade40db3SRandall Stewart 		un = unhalt->sum * 1.0;
1508ade40db3SRandall Stewart 	}
1509ade40db3SRandall Stewart 	res = (lds * con)/un;
1510ade40db3SRandall Stewart 	ret = printf("%1.3f", res);
1511ade40db3SRandall Stewart 	return(ret);
1512ade40db3SRandall Stewart }
1513ade40db3SRandall Stewart 
1514ade40db3SRandall Stewart 
1515ade40db3SRandall Stewart static int
fpassists(struct counters * cpu,int pos)1516d95b3509SRandall Stewart fpassists(struct counters *cpu, int pos)
1517d95b3509SRandall Stewart {
1518d95b3509SRandall Stewart 	/* 16  - FP_ASSIST.ANY/INST_RETIRED.ANY_P */
1519d95b3509SRandall Stewart 	int ret;
1520d95b3509SRandall Stewart 	struct counters *fp;
1521d95b3509SRandall Stewart 	struct counters *inst;
1522d95b3509SRandall Stewart 	double un, fpd, res;
1523d95b3509SRandall Stewart 
1524d95b3509SRandall Stewart 	inst = find_counter(cpu, "INST_RETIRED.ANY_P");
1525d95b3509SRandall Stewart 	fp = find_counter(cpu, "FP_ASSIST.ANY");
1526d95b3509SRandall Stewart 	if (pos != -1) {
1527d95b3509SRandall Stewart 		fpd = fp->vals[pos] * 1.0;
1528d95b3509SRandall Stewart 		un = inst->vals[pos] * 1.0;
1529d95b3509SRandall Stewart 	} else {
1530d95b3509SRandall Stewart 		fpd = fp->sum * 1.0;
1531d95b3509SRandall Stewart 		un = inst->sum * 1.0;
1532d95b3509SRandall Stewart 	}
1533d95b3509SRandall Stewart 	res = fpd/un;
1534d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1535d95b3509SRandall Stewart 	return(ret);
1536d95b3509SRandall Stewart }
1537d95b3509SRandall Stewart 
1538d95b3509SRandall Stewart static int
otherassistavx(struct counters * cpu,int pos)1539d95b3509SRandall Stewart otherassistavx(struct counters *cpu, int pos)
1540d95b3509SRandall Stewart {
1541eef0660aSRandall Stewart 	/* 17  - (OTHER_ASSISTS.AVX_TO_SSE * 75)/CPU_CLK_UNHALTED.THREAD_P thresh  .1*/
1542d95b3509SRandall Stewart 	int ret;
1543d95b3509SRandall Stewart 	struct counters *oth;
1544d95b3509SRandall Stewart 	struct counters *unhalt;
1545d95b3509SRandall Stewart 	double un, ot, con, res;
1546d95b3509SRandall Stewart 
1547d95b3509SRandall Stewart 	con = 75.0;
1548d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1549d95b3509SRandall Stewart 	oth = find_counter(cpu, "OTHER_ASSISTS.AVX_TO_SSE");
1550d95b3509SRandall Stewart 	if (pos != -1) {
1551d95b3509SRandall Stewart 		ot = oth->vals[pos] * 1.0;
1552d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1553d95b3509SRandall Stewart 	} else {
1554d95b3509SRandall Stewart 		ot = oth->sum * 1.0;
1555d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1556d95b3509SRandall Stewart 	}
1557d95b3509SRandall Stewart 	res = (ot * con)/un;
1558d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1559d95b3509SRandall Stewart 	return(ret);
1560d95b3509SRandall Stewart }
1561d95b3509SRandall Stewart 
1562d95b3509SRandall Stewart static int
otherassistsse(struct counters * cpu,int pos)1563d95b3509SRandall Stewart otherassistsse(struct counters *cpu, int pos)
1564d95b3509SRandall Stewart {
1565d95b3509SRandall Stewart 
1566d95b3509SRandall Stewart 	int ret;
1567d95b3509SRandall Stewart 	struct counters *oth;
1568d95b3509SRandall Stewart 	struct counters *unhalt;
1569d95b3509SRandall Stewart 	double un, ot, con, res;
1570d95b3509SRandall Stewart 
1571eef0660aSRandall Stewart 	/* 18     (OTHER_ASSISTS.SSE_TO_AVX * 75)/CPU_CLK_UNHALTED.THREAD_P  thresh .1*/
1572d95b3509SRandall Stewart 	con = 75.0;
1573d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1574d95b3509SRandall Stewart 	oth = find_counter(cpu, "OTHER_ASSISTS.SSE_TO_AVX");
1575d95b3509SRandall Stewart 	if (pos != -1) {
1576d95b3509SRandall Stewart 		ot = oth->vals[pos] * 1.0;
1577d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1578d95b3509SRandall Stewart 	} else {
1579d95b3509SRandall Stewart 		ot = oth->sum * 1.0;
1580d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1581d95b3509SRandall Stewart 	}
1582d95b3509SRandall Stewart 	res = (ot * con)/un;
1583d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1584d95b3509SRandall Stewart 	return(ret);
1585d95b3509SRandall Stewart }
1586d95b3509SRandall Stewart 
1587d95b3509SRandall Stewart static int
efficiency1(struct counters * cpu,int pos)1588d95b3509SRandall Stewart efficiency1(struct counters *cpu, int pos)
1589d95b3509SRandall Stewart {
1590d95b3509SRandall Stewart 
1591d95b3509SRandall Stewart 	int ret;
1592d95b3509SRandall Stewart 	struct counters *uops;
1593d95b3509SRandall Stewart 	struct counters *unhalt;
1594d95b3509SRandall Stewart 	double un, ot, con, res;
1595d95b3509SRandall Stewart 
1596eef0660aSRandall Stewart         /* 19 (UOPS_RETIRED.RETIRE_SLOTS/(4*CPU_CLK_UNHALTED.THREAD_P) look if thresh < .9*/
1597d95b3509SRandall Stewart 	con = 4.0;
1598d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1599d95b3509SRandall Stewart 	uops = find_counter(cpu, "UOPS_RETIRED.RETIRE_SLOTS");
1600d95b3509SRandall Stewart 	if (pos != -1) {
1601d95b3509SRandall Stewart 		ot = uops->vals[pos] * 1.0;
1602d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1603d95b3509SRandall Stewart 	} else {
1604d95b3509SRandall Stewart 		ot = uops->sum * 1.0;
1605d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1606d95b3509SRandall Stewart 	}
1607d95b3509SRandall Stewart 	res = ot/(con * un);
1608d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1609d95b3509SRandall Stewart 	return(ret);
1610d95b3509SRandall Stewart }
1611d95b3509SRandall Stewart 
1612d95b3509SRandall Stewart static int
efficiency2(struct counters * cpu,int pos)1613d95b3509SRandall Stewart efficiency2(struct counters *cpu, int pos)
1614d95b3509SRandall Stewart {
1615d95b3509SRandall Stewart 
1616d95b3509SRandall Stewart 	int ret;
1617d95b3509SRandall Stewart 	struct counters *uops;
1618d95b3509SRandall Stewart 	struct counters *unhalt;
1619d95b3509SRandall Stewart 	double un, ot, res;
1620d95b3509SRandall Stewart 
1621eef0660aSRandall Stewart         /* 20  - CPU_CLK_UNHALTED.THREAD_P/INST_RETIRED.ANY_P good if > 1. (comp factor)*/
1622d95b3509SRandall Stewart 	unhalt = find_counter(cpu, "CPU_CLK_UNHALTED.THREAD_P");
1623d95b3509SRandall Stewart 	uops = find_counter(cpu, "INST_RETIRED.ANY_P");
1624d95b3509SRandall Stewart 	if (pos != -1) {
1625d95b3509SRandall Stewart 		ot = uops->vals[pos] * 1.0;
1626d95b3509SRandall Stewart 		un = unhalt->vals[pos] * 1.0;
1627d95b3509SRandall Stewart 	} else {
1628d95b3509SRandall Stewart 		ot = uops->sum * 1.0;
1629d95b3509SRandall Stewart 		un = unhalt->sum * 1.0;
1630d95b3509SRandall Stewart 	}
1631d95b3509SRandall Stewart 	res = un/ot;
1632d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
1633d95b3509SRandall Stewart 	return(ret);
1634d95b3509SRandall Stewart }
1635d95b3509SRandall Stewart 
1636d95b3509SRandall Stewart #define SANDY_BRIDGE_COUNT 20
1637d95b3509SRandall Stewart static struct cpu_entry sandy_bridge[SANDY_BRIDGE_COUNT] = {
1638d95b3509SRandall Stewart /*01*/	{ "allocstall1", "thresh > .05",
1639d95b3509SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s PARTIAL_RAT_STALLS.SLOW_LEA_WINDOW -w 1",
1640eef0660aSRandall Stewart 	  allocstall1, 2 },
1641eef0660aSRandall Stewart /* -- not defined for SB right (partial-rat_stalls) 02*/
1642eef0660aSRandall Stewart         { "allocstall2", "thresh > .05",
1643eef0660aSRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s PARTIAL_RAT_STALLS.FLAGS_MERGE_UOP -w 1",
1644eef0660aSRandall Stewart 	  allocstall2, 2 },
1645d95b3509SRandall Stewart /*03*/	{ "br_miss", "thresh >= .2",
1646d95b3509SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s BR_MISP_RETIRED.ALL_BRANCHES -w 1",
1647eef0660aSRandall Stewart 	  br_mispredict, 2 },
1648d95b3509SRandall Stewart /*04*/	{ "splitload", "thresh >= .1",
1649d95b3509SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s MEM_UOP_RETIRED.SPLIT_LOADS -w 1",
1650eef0660aSRandall Stewart 	  splitload_sb, 2 },
1651d95b3509SRandall Stewart /* 05*/	{ "splitstore", "thresh >= .01",
1652d95b3509SRandall Stewart 	  "pmcstat -s MEM_UOP_RETIRED.SPLIT_STORES -s MEM_UOP_RETIRED.ALL_STORES -w 1",
1653eef0660aSRandall Stewart 	  splitstore_sb, 2 },
1654d95b3509SRandall Stewart /*06*/	{ "contested", "thresh >= .05",
1655d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM  -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1656eef0660aSRandall Stewart 	  contested, 2 },
1657d95b3509SRandall Stewart /*07*/	{ "blockstorefwd", "thresh >= .05",
1658d95b3509SRandall Stewart 	  "pmcstat -s LD_BLOCKS_STORE_FORWARD -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1659eef0660aSRandall Stewart 	  blockstoreforward, 2 },
1660d95b3509SRandall Stewart /*08*/	{ "cache2", "thresh >= .2",
1661d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_RETIRED.LLC_HIT -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1662eef0660aSRandall Stewart 	  cache2, 4 },
1663d95b3509SRandall Stewart /*09*/	{ "cache1", "thresh >= .2",
1664d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1665eef0660aSRandall Stewart 	  cache1, 2 },
1666d95b3509SRandall Stewart /*10*/	{ "dtlbmissload", "thresh >= .1",
1667d95b3509SRandall Stewart 	  "pmcstat -s DTLB_LOAD_MISSES.STLB_HIT -s DTLB_LOAD_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1668eef0660aSRandall Stewart 	  dtlb_missload, 3 },
1669d95b3509SRandall Stewart /*11*/	{ "dtlbmissstore", "thresh >= .05",
1670d95b3509SRandall Stewart 	  "pmcstat -s DTLB_STORE_MISSES.STLB_HIT -s DTLB_STORE_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1671eef0660aSRandall Stewart 	  dtlb_missstore, 3 },
1672d95b3509SRandall Stewart /*12*/	{ "frontendstall", "thresh >= .15",
1673d95b3509SRandall Stewart 	  "pmcstat -s IDQ_UOPS_NOT_DELIVERED.CORE -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1674eef0660aSRandall Stewart 	  frontendstall, 2 },
1675d95b3509SRandall Stewart /*13*/	{ "clears", "thresh >= .02",
1676d95b3509SRandall Stewart 	  "pmcstat -s MACHINE_CLEARS.MEMORY_ORDERING -s MACHINE_CLEARS.SMC -s MACHINE_CLEARS.MASKMOV -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1677eef0660aSRandall Stewart 	  clears, 4 },
1678d95b3509SRandall Stewart /*14*/	{ "microassist", "thresh >= .05",
1679d95b3509SRandall Stewart 	  "pmcstat -s IDQ.MS_UOPS,cmask=1 -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1680eef0660aSRandall Stewart 	  microassist, 2 },
1681d95b3509SRandall Stewart /*15*/	{ "aliasing_4k", "thresh >= .1",
1682d95b3509SRandall Stewart 	  "pmcstat -s LD_BLOCKS_PARTIAL.ADDRESS_ALIAS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1683eef0660aSRandall Stewart 	  aliasing, 2 },
1684d95b3509SRandall Stewart /*16*/	{ "fpassist", "look for a excessive value",
1685d95b3509SRandall Stewart 	  "pmcstat -s FP_ASSIST.ANY -s INST_RETIRED.ANY_P -w 1",
1686eef0660aSRandall Stewart 	  fpassists, 2 },
1687d95b3509SRandall Stewart /*17*/	{ "otherassistavx", "look for a excessive value",
1688d95b3509SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.AVX_TO_SSE -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1689eef0660aSRandall Stewart 	  otherassistavx, 2},
1690d95b3509SRandall Stewart /*18*/	{ "otherassistsse", "look for a excessive value",
1691d95b3509SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.SSE_TO_AVX -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1692eef0660aSRandall Stewart 	  otherassistsse, 2 },
1693d95b3509SRandall Stewart /*19*/	{ "eff1", "thresh < .9",
1694d95b3509SRandall Stewart 	  "pmcstat -s UOPS_RETIRED.RETIRE_SLOTS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1695eef0660aSRandall Stewart 	  efficiency1, 2 },
1696d95b3509SRandall Stewart /*20*/	{ "eff2", "thresh > 1.0",
1697d95b3509SRandall Stewart 	  "pmcstat -s INST_RETIRED.ANY_P -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1698eef0660aSRandall Stewart 	  efficiency2, 2 },
1699d95b3509SRandall Stewart };
1700d95b3509SRandall Stewart 
1701d95b3509SRandall Stewart 
1702d95b3509SRandall Stewart #define IVY_BRIDGE_COUNT 21
1703d95b3509SRandall Stewart static struct cpu_entry ivy_bridge[IVY_BRIDGE_COUNT] = {
1704d95b3509SRandall Stewart /*1*/	{ "eff1", "thresh < .75",
1705d95b3509SRandall Stewart 	  "pmcstat -s UOPS_RETIRED.RETIRE_SLOTS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1706eef0660aSRandall Stewart 	  efficiency1, 2 },
1707d95b3509SRandall Stewart /*2*/	{ "eff2", "thresh > 1.0",
1708d95b3509SRandall Stewart 	  "pmcstat -s INST_RETIRED.ANY_P -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1709eef0660aSRandall Stewart 	  efficiency2, 2 },
1710d95b3509SRandall Stewart /*3*/	{ "itlbmiss", "thresh > .05",
1711d95b3509SRandall Stewart 	  "pmcstat -s ITLB_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1712eef0660aSRandall Stewart 	  itlb_miss, 2 },
1713d95b3509SRandall Stewart /*4*/	{ "icachemiss", "thresh > .05",
1714d95b3509SRandall Stewart 	  "pmcstat -s ICACHE.IFETCH_STALL -s ITLB_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1715eef0660aSRandall Stewart 	  icache_miss, 3 },
1716d95b3509SRandall Stewart /*5*/	{ "lcpstall", "thresh > .05",
1717d95b3509SRandall Stewart 	  "pmcstat -s ILD_STALL.LCP -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1718eef0660aSRandall Stewart 	  lcp_stall, 2 },
1719d95b3509SRandall Stewart /*6*/	{ "cache1", "thresh >= .2",
1720d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1721eef0660aSRandall Stewart 	  cache1ib, 2 },
1722d95b3509SRandall Stewart /*7*/	{ "cache2", "thresh >= .2",
1723d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_RETIRED.LLC_HIT -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1724eef0660aSRandall Stewart 	  cache2ib, 2 },
1725d95b3509SRandall Stewart /*8*/	{ "contested", "thresh >= .05",
1726d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM  -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1727eef0660aSRandall Stewart 	  contested, 2 },
1728d95b3509SRandall Stewart /*9*/	{ "datashare", "thresh >= .05",
1729d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1730eef0660aSRandall Stewart 	  datasharing, 2 },
1731d95b3509SRandall Stewart /*10*/	{ "blockstorefwd", "thresh >= .05",
1732d95b3509SRandall Stewart 	  "pmcstat -s LD_BLOCKS_STORE_FORWARD -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1733eef0660aSRandall Stewart 	  blockstoreforward, 2 },
1734d95b3509SRandall Stewart /*11*/	{ "splitload", "thresh >= .1",
1735d95b3509SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s L1D_PEND_MISS.PENDING -s MEM_LOAD_UOPS_RETIRED.L1_MISS -s LD_BLOCKS.NO_SR -w 1",
1736eef0660aSRandall Stewart 	  splitloadib, 4 },
1737d95b3509SRandall Stewart /*12*/	{ "splitstore", "thresh >= .01",
1738eef0660aSRandall Stewart 	  "pmcstat -s MEM_UOPS_RETIRED.SPLIT_STORES -s MEM_UOPS_RETIRED.ALL_STORES -w 1",
1739eef0660aSRandall Stewart 	  splitstore, 2 },
1740d95b3509SRandall Stewart /*13*/	{ "aliasing_4k", "thresh >= .1",
1741d95b3509SRandall Stewart 	  "pmcstat -s LD_BLOCKS_PARTIAL.ADDRESS_ALIAS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1742eef0660aSRandall Stewart 	  aliasing, 2 },
1743d95b3509SRandall Stewart /*14*/	{ "dtlbmissload", "thresh >= .1",
1744d95b3509SRandall Stewart 	  "pmcstat -s DTLB_LOAD_MISSES.STLB_HIT -s DTLB_LOAD_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1745eef0660aSRandall Stewart 	  dtlb_missload , 3},
1746d95b3509SRandall Stewart /*15*/	{ "dtlbmissstore", "thresh >= .05",
1747d95b3509SRandall Stewart 	  "pmcstat -s DTLB_STORE_MISSES.STLB_HIT -s DTLB_STORE_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1748eef0660aSRandall Stewart 	  dtlb_missstore, 3 },
1749d95b3509SRandall Stewart /*16*/	{ "br_miss", "thresh >= .2",
1750d95b3509SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s BR_MISP_RETIRED.ALL_BRANCHES -s MACHINE_CLEARS.MEMORY_ORDERING -s MACHINE_CLEARS.SMC -s MACHINE_CLEARS.MASKMOV -s UOPS_ISSUED.ANY -s UOPS_RETIRED.RETIRE_SLOTS -s INT_MISC.RECOVERY_CYCLES -w 1",
1751eef0660aSRandall Stewart 	  br_mispredictib, 8 },
1752d95b3509SRandall Stewart /*17*/	{ "clears", "thresh >= .02",
1753d95b3509SRandall Stewart 	  "pmcstat -s MACHINE_CLEARS.MEMORY_ORDERING -s MACHINE_CLEARS.SMC -s MACHINE_CLEARS.MASKMOV -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1754eef0660aSRandall Stewart 	  clears, 4 },
1755d95b3509SRandall Stewart /*18*/	{ "microassist", "thresh >= .05",
1756d95b3509SRandall Stewart 	  "pmcstat -s IDQ.MS_UOPS,cmask=1 -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1757eef0660aSRandall Stewart 	  microassist, 2 },
1758d95b3509SRandall Stewart /*19*/	{ "fpassist", "look for a excessive value",
1759d95b3509SRandall Stewart 	  "pmcstat -s FP_ASSIST.ANY -s INST_RETIRED.ANY_P -w 1",
1760eef0660aSRandall Stewart 	  fpassists, 2 },
1761d95b3509SRandall Stewart /*20*/	{ "otherassistavx", "look for a excessive value",
1762d95b3509SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.AVX_TO_SSE -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1763eef0660aSRandall Stewart 	  otherassistavx , 2},
1764d95b3509SRandall Stewart /*21*/	{ "otherassistsse", "look for a excessive value",
1765d95b3509SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.SSE_TO_AVX -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1766eef0660aSRandall Stewart 	  otherassistsse, 2 },
1767d95b3509SRandall Stewart };
1768d95b3509SRandall Stewart 
1769d95b3509SRandall Stewart #define HASWELL_COUNT 20
1770d95b3509SRandall Stewart static struct cpu_entry haswell[HASWELL_COUNT] = {
1771d95b3509SRandall Stewart /*1*/	{ "eff1", "thresh < .75",
1772d95b3509SRandall Stewart 	  "pmcstat -s UOPS_RETIRED.RETIRE_SLOTS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1773eef0660aSRandall Stewart 	  efficiency1, 2 },
1774d95b3509SRandall Stewart /*2*/	{ "eff2", "thresh > 1.0",
1775d95b3509SRandall Stewart 	  "pmcstat -s INST_RETIRED.ANY_P -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1776eef0660aSRandall Stewart 	  efficiency2, 2 },
1777d95b3509SRandall Stewart /*3*/	{ "itlbmiss", "thresh > .05",
1778d95b3509SRandall Stewart 	  "pmcstat -s ITLB_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1779eef0660aSRandall Stewart 	  itlb_miss, 2 },
1780d95b3509SRandall Stewart /*4*/	{ "icachemiss", "thresh > .05",
1781eef0660aSRandall Stewart 	  "pmcstat -s ICACHE.MISSES -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1782eef0660aSRandall Stewart 	  icache_miss_has, 2 },
1783d95b3509SRandall Stewart /*5*/	{ "lcpstall", "thresh > .05",
1784d95b3509SRandall Stewart 	  "pmcstat -s ILD_STALL.LCP -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1785eef0660aSRandall Stewart 	  lcp_stall, 2 },
1786d95b3509SRandall Stewart /*6*/	{ "cache1", "thresh >= .2",
1787d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1788eef0660aSRandall Stewart 	  cache1ib, 2 },
1789d95b3509SRandall Stewart /*7*/	{ "cache2", "thresh >= .2",
1790d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_RETIRED.LLC_HIT  -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1791eef0660aSRandall Stewart 	  cache2has, 4 },
1792d95b3509SRandall Stewart /*8*/	{ "contested", "thresh >= .05",
1793d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM  -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1794eef0660aSRandall Stewart 	  contested_has, 2 },
1795d95b3509SRandall Stewart /*9*/	{ "datashare", "thresh >= .05",
1796d95b3509SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1797eef0660aSRandall Stewart 	  datasharing_has, 2 },
1798d95b3509SRandall Stewart /*10*/	{ "blockstorefwd", "thresh >= .05",
1799d95b3509SRandall Stewart 	  "pmcstat -s LD_BLOCKS_STORE_FORWARD -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1800eef0660aSRandall Stewart 	  blockstoreforward, 2 },
1801d95b3509SRandall Stewart /*11*/	{ "splitload", "thresh >= .1",
1802eef0660aSRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s MEM_UOPS_RETIRED.SPLIT_LOADS -w 1",
1803eef0660aSRandall Stewart 	  splitload , 2},
1804d95b3509SRandall Stewart /*12*/	{ "splitstore", "thresh >= .01",
1805eef0660aSRandall Stewart 	  "pmcstat -s MEM_UOPS_RETIRED.SPLIT_STORES -s MEM_UOPS_RETIRED.ALL_STORES -w 1",
1806eef0660aSRandall Stewart 	  splitstore, 2 },
1807d95b3509SRandall Stewart /*13*/	{ "aliasing_4k", "thresh >= .1",
1808d95b3509SRandall Stewart 	  "pmcstat -s LD_BLOCKS_PARTIAL.ADDRESS_ALIAS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1809eef0660aSRandall Stewart 	  aliasing, 2 },
1810d95b3509SRandall Stewart /*14*/	{ "dtlbmissload", "thresh >= .1",
1811d95b3509SRandall Stewart 	  "pmcstat -s DTLB_LOAD_MISSES.STLB_HIT -s DTLB_LOAD_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1812eef0660aSRandall Stewart 	  dtlb_missload, 3 },
1813d95b3509SRandall Stewart /*15*/	{ "br_miss", "thresh >= .2",
1814d95b3509SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s BR_MISP_RETIRED.ALL_BRANCHES -w 1",
1815eef0660aSRandall Stewart 	  br_mispredict, 2 },
1816d95b3509SRandall Stewart /*16*/	{ "clears", "thresh >= .02",
1817d95b3509SRandall Stewart 	  "pmcstat -s MACHINE_CLEARS.MEMORY_ORDERING -s MACHINE_CLEARS.SMC -s MACHINE_CLEARS.MASKMOV -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1818eef0660aSRandall Stewart 	  clears, 4 },
1819d95b3509SRandall Stewart /*17*/	{ "microassist", "thresh >= .05",
1820d95b3509SRandall Stewart 	  "pmcstat -s IDQ.MS_UOPS,cmask=1 -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1821eef0660aSRandall Stewart 	  microassist, 2 },
1822d95b3509SRandall Stewart /*18*/	{ "fpassist", "look for a excessive value",
1823d95b3509SRandall Stewart 	  "pmcstat -s FP_ASSIST.ANY -s INST_RETIRED.ANY_P -w 1",
1824eef0660aSRandall Stewart 	  fpassists, 2 },
1825d95b3509SRandall Stewart /*19*/	{ "otherassistavx", "look for a excessive value",
1826d95b3509SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.AVX_TO_SSE -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1827eef0660aSRandall Stewart 	  otherassistavx, 2 },
1828d95b3509SRandall Stewart /*20*/	{ "otherassistsse", "look for a excessive value",
1829d95b3509SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.SSE_TO_AVX -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1830eef0660aSRandall Stewart 	  otherassistsse, 2 },
1831d95b3509SRandall Stewart };
1832d95b3509SRandall Stewart 
1833d95b3509SRandall Stewart 
1834d95b3509SRandall Stewart static void
explain_name_broad(const char * name)1835ade40db3SRandall Stewart explain_name_broad(const char *name)
1836ade40db3SRandall Stewart {
1837ade40db3SRandall Stewart 	const char *mythresh;
1838ade40db3SRandall Stewart 	if (strcmp(name, "eff1") == 0) {
1839ade40db3SRandall Stewart 		printf("Examine (UOPS_RETIRED.RETIRE_SLOTS)/(4 *CPU_CLK_UNHALTED.THREAD_P)\n");
1840ade40db3SRandall Stewart 		mythresh = "thresh < .75";
1841ade40db3SRandall Stewart 	} else if (strcmp(name, "eff2") == 0) {
1842ade40db3SRandall Stewart 		printf("Examine CPU_CLK_UNHALTED.THREAD_P/INST_RETIRED.ANY_P\n");
1843ade40db3SRandall Stewart 		mythresh = "thresh > 1.0";
1844ade40db3SRandall Stewart 	} else if (strcmp(name, "itlbmiss") == 0) {
1845ade40db3SRandall Stewart 		printf("Examine (7 * ITLB_MISSES_STLB_HIT_4K + ITLB_MISSES.WALK_DURATION)/ CPU_CLK_UNHALTED.THREAD_P\n");
1846ade40db3SRandall Stewart 		mythresh = "thresh > .05";
1847ade40db3SRandall Stewart 	} else if (strcmp(name, "icachemiss") == 0) {
1848eef0660aSRandall Stewart 		printf("Examine ( 36.0 * ICACHE.MISSES)/ CPU_CLK_UNHALTED.THREAD_P ??? may not be right \n");
1849ade40db3SRandall Stewart 		mythresh = "thresh > .05";
1850ade40db3SRandall Stewart 	} else if (strcmp(name, "lcpstall") == 0) {
1851ade40db3SRandall Stewart 		printf("Examine ILD_STALL.LCP/CPU_CLK_UNHALTED.THREAD_P\n");
1852ade40db3SRandall Stewart 		mythresh = "thresh > .05";
1853ade40db3SRandall Stewart 	} else if (strcmp(name, "cache1") == 0) {
1854ade40db3SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM * 180) / CPU_CLK_UNHALTED.THREAD_P\n");
1855ade40db3SRandall Stewart 		mythresh = "thresh >= .1";
1856ade40db3SRandall Stewart 	} else if (strcmp(name, "cache2") == 0) {
1857ade40db3SRandall Stewart 		printf("Examine (36.0 * MEM_LOAD_UOPS_RETIRED.L3_HIT / CPU_CLK_UNHALTED.THREAD_P)\n");
1858ade40db3SRandall Stewart 		mythresh = "thresh >= .2";
1859ade40db3SRandall Stewart 	} else if (strcmp(name, "contested") == 0) {
1860ade40db3SRandall Stewart 		printf("Examine ((MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM * 84) +  MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS)/ CPU_CLK_UNHALTED.THREAD_P\n");
1861ade40db3SRandall Stewart 		mythresh = "thresh >= .05";
1862ade40db3SRandall Stewart 	} else if (strcmp(name, "datashare") == 0) {
1863ade40db3SRandall Stewart 		printf("Examine (MEM_LOAD_UOPS_L3_HIT_RETIRED.XSNP_HIT * 72)/CPU_CLK_UNHALTED.THREAD_P\n");
1864ade40db3SRandall Stewart 		mythresh = "thresh > .05";
1865ade40db3SRandall Stewart 	} else if (strcmp(name, "blockstorefwd") == 0) {
1866ade40db3SRandall Stewart 		printf("Examine (LD_BLOCKS_STORE_FORWARD * 13) / CPU_CLK_UNHALTED.THREAD_P\n");
1867ade40db3SRandall Stewart 		mythresh = "thresh >= .05";
1868ade40db3SRandall Stewart 	} else if (strcmp(name, "aliasing_4k") == 0) {
1869ade40db3SRandall Stewart 		printf("Examine (LD_BLOCKS_PARTIAL.ADDRESS_ALIAS * 7) / CPU_CLK_UNHALTED.THREAD_P\n");
1870ade40db3SRandall Stewart 		mythresh = "thresh >= .1";
1871ade40db3SRandall Stewart 	} else if (strcmp(name, "dtlbmissload") == 0) {
1872ade40db3SRandall Stewart 		printf("Examine (((DTLB_LOAD_MISSES.STLB_HIT * 7) + DTLB_LOAD_MISSES.WALK_DURATION)\n");
1873ade40db3SRandall Stewart 		printf("         / CPU_CLK_UNHALTED.THREAD_P)\n");
1874ade40db3SRandall Stewart 		mythresh = "thresh >= .1";
1875ade40db3SRandall Stewart 
1876ade40db3SRandall Stewart 	} else if (strcmp(name, "br_miss") == 0) {
1877ade40db3SRandall Stewart 		printf("Examine BR_MISP_RETIRED.ALL_BRANCHS_PS / (BR_MISP_RETIED.ALL_BRANCHES_PS + MACHINE_CLEARS.COUNT) *\n");
1878ade40db3SRandall Stewart 		printf(" (UOPS_ISSUEDF.ANY - UOPS_RETIRED.RETIRE_SLOTS + 4 * INT_MISC.RECOVERY_CYCLES) /\n");
1879ade40db3SRandall Stewart 		printf("CPU_CLK_UNHALTED.THREAD * 4)\n");
1880ade40db3SRandall Stewart 		mythresh = "thresh >= .2";
1881ade40db3SRandall Stewart 	} else if (strcmp(name, "clears") == 0) {
1882ade40db3SRandall Stewart 		printf("Examine ((MACHINE_CLEARS.MEMORY_ORDERING + \n");
1883ade40db3SRandall Stewart 		printf("          MACHINE_CLEARS.SMC + \n");
1884ade40db3SRandall Stewart 		printf("          MACHINE_CLEARS.MASKMOV ) * 100 ) / CPU_CLK_UNHALTED.THREAD_P\n");
1885ade40db3SRandall Stewart 		mythresh = "thresh >= .02";
1886ade40db3SRandall Stewart 	} else if (strcmp(name, "fpassist") == 0) {
1887ade40db3SRandall Stewart 		printf("Examine FP_ASSIST.ANY/INST_RETIRED.ANY_P\n");
1888ade40db3SRandall Stewart 		mythresh = "look for a excessive value";
1889ade40db3SRandall Stewart 	} else if (strcmp(name, "otherassistavx") == 0) {
1890ade40db3SRandall Stewart 		printf("Examine (OTHER_ASSISTS.AVX_TO_SSE * 75)/CPU_CLK_UNHALTED.THREAD_P\n");
1891ade40db3SRandall Stewart 		mythresh = "look for a excessive value";
1892ade40db3SRandall Stewart 	} else if (strcmp(name, "microassist") == 0) {
1893ade40db3SRandall Stewart 		printf("Examine (UOPS_RETIRED.RETIRE_SLOTS/UOPS_ISSUED.ANY) * (IDQ.MS_CYCLES / (4 * CPU_CLK_UNHALTED.THREAD_P)\n");
1894ade40db3SRandall Stewart 		printf("***We use IDQ.MS_UOPS,cmask=1 to get cycles\n");
1895ade40db3SRandall Stewart 		mythresh = "thresh >= .05";
1896ade40db3SRandall Stewart 	} else {
1897ade40db3SRandall Stewart 		printf("Unknown name:%s\n", name);
1898ade40db3SRandall Stewart 		mythresh = "unknown entry";
1899ade40db3SRandall Stewart         }
1900ade40db3SRandall Stewart 	printf("If the value printed is %s we may have the ability to improve performance\n", mythresh);
1901ade40db3SRandall Stewart }
1902ade40db3SRandall Stewart 
1903ade40db3SRandall Stewart 
1904ade40db3SRandall Stewart #define BROADWELL_COUNT 17
1905ade40db3SRandall Stewart static struct cpu_entry broadwell[BROADWELL_COUNT] = {
1906ade40db3SRandall Stewart /*1*/	{ "eff1", "thresh < .75",
1907ade40db3SRandall Stewart 	  "pmcstat -s UOPS_RETIRED.RETIRE_SLOTS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1908eef0660aSRandall Stewart 	  efficiency1, 2 },
1909ade40db3SRandall Stewart /*2*/	{ "eff2", "thresh > 1.0",
1910ade40db3SRandall Stewart 	  "pmcstat -s INST_RETIRED.ANY_P -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1911eef0660aSRandall Stewart 	  efficiency2, 2 },
1912ade40db3SRandall Stewart /*3*/	{ "itlbmiss", "thresh > .05",
1913ade40db3SRandall Stewart 	  "pmcstat -s ITLB_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -s ITLB_MISSES.STLB_HIT_4K -w 1",
1914eef0660aSRandall Stewart 	  itlb_miss_broad, 3 },
1915ade40db3SRandall Stewart /*4*/	{ "icachemiss", "thresh > .05",
1916eef0660aSRandall Stewart 	  "pmcstat -s ICACHE.MISSES -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1917eef0660aSRandall Stewart 	  icache_miss_has, 2 },
1918ade40db3SRandall Stewart /*5*/	{ "lcpstall", "thresh > .05",
1919ade40db3SRandall Stewart 	  "pmcstat -s ILD_STALL.LCP -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1920eef0660aSRandall Stewart 	  lcp_stall, 2 },
1921ade40db3SRandall Stewart /*6*/	{ "cache1", "thresh >= .1",
1922ade40db3SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_RETIRED.L3_MISS  -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1923eef0660aSRandall Stewart 	  cache1broad, 2 },
1924ade40db3SRandall Stewart /*7*/	{ "cache2", "thresh >= .2",
1925ade40db3SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_RETIRED.L3_HIT  -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1926eef0660aSRandall Stewart 	  cache2broad, 2 },
1927ade40db3SRandall Stewart /*8*/	{ "contested", "thresh >= .05",
1928ade40db3SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM  -s CPU_CLK_UNHALTED.THREAD_P  -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS -w 1",
1929eef0660aSRandall Stewart 	  contestedbroad, 2 },
1930ade40db3SRandall Stewart /*9*/	{ "datashare", "thresh >= .05",
1931ade40db3SRandall Stewart 	  "pmcstat -s MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1932eef0660aSRandall Stewart 	  datasharing_has, 2 },
1933ade40db3SRandall Stewart /*10*/	{ "blockstorefwd", "thresh >= .05",
1934ade40db3SRandall Stewart 	  "pmcstat -s LD_BLOCKS_STORE_FORWARD -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1935eef0660aSRandall Stewart 	  blockstoreforward, 2 },
1936ade40db3SRandall Stewart /*11*/	{ "aliasing_4k", "thresh >= .1",
1937ade40db3SRandall Stewart 	  "pmcstat -s LD_BLOCKS_PARTIAL.ADDRESS_ALIAS -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1938eef0660aSRandall Stewart 	  aliasing_broad, 2 },
1939ade40db3SRandall Stewart /*12*/	{ "dtlbmissload", "thresh >= .1",
1940eef0660aSRandall Stewart 	  "pmcstat -s DTLB_LOAD_MISSES.STLB_HIT_4K -s DTLB_LOAD_MISSES.WALK_DURATION -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1941eef0660aSRandall Stewart 	  dtlb_missload, 3 },
1942ade40db3SRandall Stewart /*13*/	{ "br_miss", "thresh >= .2",
1943ade40db3SRandall Stewart 	  "pmcstat -s CPU_CLK_UNHALTED.THREAD_P -s BR_MISP_RETIRED.ALL_BRANCHES -s MACHINE_CLEARS.CYCLES -s UOPS_ISSUED.ANY -s UOPS_RETIRED.RETIRE_SLOTS -s INT_MISC.RECOVERY_CYCLES -w 1",
1944eef0660aSRandall Stewart 	  br_mispredict_broad, 7 },
1945ade40db3SRandall Stewart /*14*/	{ "clears", "thresh >= .02",
1946ade40db3SRandall Stewart 	  "pmcstat -s MACHINE_CLEARS.CYCLES -s MACHINE_CLEARS.MEMORY_ORDERING -s MACHINE_CLEARS.SMC -s MACHINE_CLEARS.MASKMOV -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1947eef0660aSRandall Stewart 	  clears_broad, 5 },
1948ade40db3SRandall Stewart /*15*/	{ "fpassist", "look for a excessive value",
1949ade40db3SRandall Stewart 	  "pmcstat -s FP_ASSIST.ANY -s INST_RETIRED.ANY_P -w 1",
1950eef0660aSRandall Stewart 	  fpassists, 2 },
1951ade40db3SRandall Stewart /*16*/	{ "otherassistavx", "look for a excessive value",
1952ade40db3SRandall Stewart 	  "pmcstat -s OTHER_ASSISTS.AVX_TO_SSE -s CPU_CLK_UNHALTED.THREAD_P -w 1",
1953eef0660aSRandall Stewart 	  otherassistavx, 2 },
1954ade40db3SRandall Stewart /*17*/	{ "microassist", "thresh >= .2",
1955ade40db3SRandall Stewart 	  "pmcstat -s IDQ.MS_UOPS,cmask=1 -s CPU_CLK_UNHALTED.THREAD_P -s UOPS_ISSUED.ANY -s UOPS_RETIRED.RETIRE_SLOTS  -w 1",
1956eef0660aSRandall Stewart 	  microassist_broad, 4 },
1957ade40db3SRandall Stewart };
1958ade40db3SRandall Stewart 
1959eef0660aSRandall Stewart 
1960ade40db3SRandall Stewart static void
set_sandybridge(void)1961d95b3509SRandall Stewart set_sandybridge(void)
1962d95b3509SRandall Stewart {
1963d95b3509SRandall Stewart 	strcpy(the_cpu.cputype, "SandyBridge PMC");
1964d95b3509SRandall Stewart 	the_cpu.number = SANDY_BRIDGE_COUNT;
1965d95b3509SRandall Stewart 	the_cpu.ents = sandy_bridge;
1966d95b3509SRandall Stewart 	the_cpu.explain = explain_name_sb;
1967d95b3509SRandall Stewart }
1968d95b3509SRandall Stewart 
1969d95b3509SRandall Stewart static void
set_ivybridge(void)1970d95b3509SRandall Stewart set_ivybridge(void)
1971d95b3509SRandall Stewart {
1972d95b3509SRandall Stewart 	strcpy(the_cpu.cputype, "IvyBridge PMC");
1973d95b3509SRandall Stewart 	the_cpu.number = IVY_BRIDGE_COUNT;
1974d95b3509SRandall Stewart 	the_cpu.ents = ivy_bridge;
1975d95b3509SRandall Stewart 	the_cpu.explain = explain_name_ib;
1976d95b3509SRandall Stewart }
1977d95b3509SRandall Stewart 
1978d95b3509SRandall Stewart 
1979d95b3509SRandall Stewart static void
set_haswell(void)1980d95b3509SRandall Stewart set_haswell(void)
1981d95b3509SRandall Stewart {
1982d95b3509SRandall Stewart 	strcpy(the_cpu.cputype, "HASWELL PMC");
1983d95b3509SRandall Stewart 	the_cpu.number = HASWELL_COUNT;
1984d95b3509SRandall Stewart 	the_cpu.ents = haswell;
1985d95b3509SRandall Stewart 	the_cpu.explain = explain_name_has;
1986d95b3509SRandall Stewart }
1987d95b3509SRandall Stewart 
1988eef0660aSRandall Stewart 
1989d95b3509SRandall Stewart static void
set_broadwell(void)1990ade40db3SRandall Stewart set_broadwell(void)
1991ade40db3SRandall Stewart {
1992ade40db3SRandall Stewart 	strcpy(the_cpu.cputype, "HASWELL PMC");
1993ade40db3SRandall Stewart 	the_cpu.number = BROADWELL_COUNT;
1994ade40db3SRandall Stewart 	the_cpu.ents = broadwell;
1995ade40db3SRandall Stewart 	the_cpu.explain = explain_name_broad;
1996ade40db3SRandall Stewart }
1997ade40db3SRandall Stewart 
1998eef0660aSRandall Stewart 
1999eef0660aSRandall Stewart static int
set_expression(const char * name)2000eef0660aSRandall Stewart set_expression(const char *name)
2001d95b3509SRandall Stewart {
2002d95b3509SRandall Stewart 	int found = 0, i;
2003d95b3509SRandall Stewart 	for(i=0 ; i< the_cpu.number; i++) {
2004d95b3509SRandall Stewart 		if (strcmp(name, the_cpu.ents[i].name) == 0) {
2005d95b3509SRandall Stewart 			found = 1;
2006d95b3509SRandall Stewart 			expression = the_cpu.ents[i].func;
2007d95b3509SRandall Stewart 			command = the_cpu.ents[i].command;
2008d95b3509SRandall Stewart 			threshold = the_cpu.ents[i].thresh;
2009eef0660aSRandall Stewart 			if  (the_cpu.ents[i].counters_required > max_pmc_counters) {
2010eef0660aSRandall Stewart 				printf("Test %s requires that the CPU have %d counters and this CPU has only %d\n",
2011eef0660aSRandall Stewart 				       the_cpu.ents[i].name,
2012eef0660aSRandall Stewart 				       the_cpu.ents[i].counters_required, max_pmc_counters);
2013eef0660aSRandall Stewart 				printf("Sorry this test can not be run\n");
2014eef0660aSRandall Stewart 				if (run_all == 0) {
2015eef0660aSRandall Stewart 					exit(-1);
2016eef0660aSRandall Stewart 				} else {
2017eef0660aSRandall Stewart 					return(-1);
2018eef0660aSRandall Stewart 				}
2019eef0660aSRandall Stewart 			}
2020d95b3509SRandall Stewart 			break;
2021d95b3509SRandall Stewart 		}
2022d95b3509SRandall Stewart 	}
2023d95b3509SRandall Stewart 	if (!found) {
2024d95b3509SRandall Stewart 		printf("For CPU type %s we have no expression:%s\n",
2025d95b3509SRandall Stewart 		       the_cpu.cputype, name);
2026d95b3509SRandall Stewart 		exit(-1);
2027d95b3509SRandall Stewart 	}
2028eef0660aSRandall Stewart 	return(0);
2029d95b3509SRandall Stewart }
2030d95b3509SRandall Stewart 
2031eef0660aSRandall Stewart 
2032eef0660aSRandall Stewart 
2033eef0660aSRandall Stewart 
2034eef0660aSRandall Stewart 
2035d95b3509SRandall Stewart static int
validate_expression(char * name)2036d95b3509SRandall Stewart validate_expression(char *name)
2037d95b3509SRandall Stewart {
2038d95b3509SRandall Stewart 	int i, found;
2039d95b3509SRandall Stewart 
2040d95b3509SRandall Stewart 	found = 0;
2041d95b3509SRandall Stewart 	for(i=0 ; i< the_cpu.number; i++) {
2042d95b3509SRandall Stewart 		if (strcmp(name, the_cpu.ents[i].name) == 0) {
2043d95b3509SRandall Stewart 			found = 1;
2044d95b3509SRandall Stewart 			break;
2045d95b3509SRandall Stewart 		}
2046d95b3509SRandall Stewart 	}
2047d95b3509SRandall Stewart 	if (!found) {
2048d95b3509SRandall Stewart 		return(-1);
2049d95b3509SRandall Stewart 	}
2050d95b3509SRandall Stewart 	return (0);
2051d95b3509SRandall Stewart }
2052d95b3509SRandall Stewart 
2053d95b3509SRandall Stewart static void
do_expression(struct counters * cpu,int pos)2054d95b3509SRandall Stewart do_expression(struct counters *cpu, int pos)
2055d95b3509SRandall Stewart {
2056d95b3509SRandall Stewart 	if (expression == NULL)
2057d95b3509SRandall Stewart 		return;
2058d95b3509SRandall Stewart 	(*expression)(cpu, pos);
2059d95b3509SRandall Stewart }
2060d95b3509SRandall Stewart 
2061d95b3509SRandall Stewart static void
process_header(int idx,char * p)2062d95b3509SRandall Stewart process_header(int idx, char *p)
2063d95b3509SRandall Stewart {
2064d95b3509SRandall Stewart 	struct counters *up;
2065d95b3509SRandall Stewart 	int i, len, nlen;
2066d95b3509SRandall Stewart 	/*
2067eef0660aSRandall Stewart 	 * Given header element idx, at p in
2068eef0660aSRandall Stewart 	 * form 's/NN/nameof'
2069eef0660aSRandall Stewart 	 * process the entry to pull out the name and
2070eef0660aSRandall Stewart 	 * the CPU number.
2071d95b3509SRandall Stewart 	 */
2072d95b3509SRandall Stewart 	if (strncmp(p, "s/", 2)) {
2073d95b3509SRandall Stewart 		printf("Check -- invalid header no s/ in %s\n",
2074d95b3509SRandall Stewart 		       p);
2075d95b3509SRandall Stewart 		return;
2076d95b3509SRandall Stewart 	}
2077d95b3509SRandall Stewart 	up = &cnts[idx];
2078d95b3509SRandall Stewart 	up->cpu = strtol(&p[2], NULL, 10);
2079d95b3509SRandall Stewart 	len = strlen(p);
2080d95b3509SRandall Stewart 	for (i=2; i<len; i++) {
2081d95b3509SRandall Stewart 		if (p[i] == '/') {
2082d95b3509SRandall Stewart 			nlen = strlen(&p[(i+1)]);
2083d95b3509SRandall Stewart 			if (nlen < (MAX_NLEN-1)) {
2084d95b3509SRandall Stewart 				strcpy(up->counter_name, &p[(i+1)]);
2085d95b3509SRandall Stewart 			} else {
2086d95b3509SRandall Stewart 				strncpy(up->counter_name, &p[(i+1)], (MAX_NLEN-1));
2087d95b3509SRandall Stewart 			}
2088d95b3509SRandall Stewart 		}
2089d95b3509SRandall Stewart 	}
2090d95b3509SRandall Stewart }
2091d95b3509SRandall Stewart 
2092d95b3509SRandall Stewart static void
build_counters_from_header(FILE * io)2093d95b3509SRandall Stewart build_counters_from_header(FILE *io)
2094d95b3509SRandall Stewart {
2095d95b3509SRandall Stewart 	char buffer[8192], *p;
2096d95b3509SRandall Stewart 	int i, len, cnt;
2097d95b3509SRandall Stewart 	size_t mlen;
2098d95b3509SRandall Stewart 
2099eef0660aSRandall Stewart 	/* We have a new start, lets
2100eef0660aSRandall Stewart 	 * setup our headers and cpus.
2101d95b3509SRandall Stewart 	 */
2102d95b3509SRandall Stewart 	if (fgets(buffer, sizeof(buffer), io) == NULL) {
2103d95b3509SRandall Stewart 		printf("First line can't be read from file err:%d\n", errno);
2104d95b3509SRandall Stewart 		return;
2105d95b3509SRandall Stewart 	}
2106d95b3509SRandall Stewart 	/*
2107eef0660aSRandall Stewart 	 * Ok output is an array of counters. Once
2108eef0660aSRandall Stewart 	 * we start to read the values in we must
2109eef0660aSRandall Stewart 	 * put them in there slot to match there CPU and
2110eef0660aSRandall Stewart 	 * counter being updated. We create a mass array
2111eef0660aSRandall Stewart 	 * of the counters, filling in the CPU and
2112eef0660aSRandall Stewart 	 * counter name.
2113d95b3509SRandall Stewart 	 */
2114d95b3509SRandall Stewart 	/* How many do we get? */
2115d95b3509SRandall Stewart 	len = strlen(buffer);
2116d95b3509SRandall Stewart 	for (i=0, cnt=0; i<len; i++) {
2117d95b3509SRandall Stewart 		if (strncmp(&buffer[i], "s/", 2) == 0) {
2118d95b3509SRandall Stewart 			cnt++;
2119d95b3509SRandall Stewart 			for(;i<len;i++) {
2120d95b3509SRandall Stewart 				if (buffer[i] == ' ')
2121d95b3509SRandall Stewart 					break;
2122d95b3509SRandall Stewart 			}
2123d95b3509SRandall Stewart 		}
2124d95b3509SRandall Stewart 	}
2125d95b3509SRandall Stewart 	mlen = sizeof(struct counters) * cnt;
2126d95b3509SRandall Stewart 	cnts = malloc(mlen);
2127d95b3509SRandall Stewart 	ncnts = cnt;
2128d95b3509SRandall Stewart 	if (cnts == NULL) {
2129d95b3509SRandall Stewart 		printf("No memory err:%d\n", errno);
2130d95b3509SRandall Stewart 		return;
2131d95b3509SRandall Stewart 	}
2132d95b3509SRandall Stewart 	memset(cnts, 0, mlen);
2133d95b3509SRandall Stewart 	for (i=0, cnt=0; i<len; i++) {
2134d95b3509SRandall Stewart 		if (strncmp(&buffer[i], "s/", 2) == 0) {
2135d95b3509SRandall Stewart 			p = &buffer[i];
2136d95b3509SRandall Stewart 			for(;i<len;i++) {
2137d95b3509SRandall Stewart 				if (buffer[i] == ' ') {
2138d95b3509SRandall Stewart 					buffer[i] = 0;
2139d95b3509SRandall Stewart 					break;
2140d95b3509SRandall Stewart 				}
2141d95b3509SRandall Stewart 			}
2142d95b3509SRandall Stewart 			process_header(cnt, p);
2143d95b3509SRandall Stewart 			cnt++;
2144d95b3509SRandall Stewart 		}
2145d95b3509SRandall Stewart 	}
2146d95b3509SRandall Stewart 	if (verbose)
2147d95b3509SRandall Stewart 		printf("We have %d entries\n", cnt);
2148d95b3509SRandall Stewart }
2149d95b3509SRandall Stewart extern int max_to_collect;
2150d95b3509SRandall Stewart int max_to_collect = MAX_COUNTER_SLOTS;
2151d95b3509SRandall Stewart 
2152d95b3509SRandall Stewart static int
read_a_line(FILE * io)2153d95b3509SRandall Stewart read_a_line(FILE *io)
2154d95b3509SRandall Stewart {
2155d95b3509SRandall Stewart 	char buffer[8192], *p, *stop;
2156d95b3509SRandall Stewart 	int pos, i;
2157d95b3509SRandall Stewart 
2158d95b3509SRandall Stewart 	if (fgets(buffer, sizeof(buffer), io) == NULL) {
2159d95b3509SRandall Stewart 		return(0);
2160d95b3509SRandall Stewart 	}
2161d95b3509SRandall Stewart 	p = buffer;
2162d95b3509SRandall Stewart 	for (i=0; i<ncnts; i++) {
2163d95b3509SRandall Stewart 		pos = cnts[i].pos;
2164d95b3509SRandall Stewart 		cnts[i].vals[pos] = strtol(p, &stop, 0);
2165d95b3509SRandall Stewart 		cnts[i].pos++;
2166d95b3509SRandall Stewart 		cnts[i].sum += cnts[i].vals[pos];
2167d95b3509SRandall Stewart 		p = stop;
2168d95b3509SRandall Stewart 	}
2169d95b3509SRandall Stewart 	return (1);
2170d95b3509SRandall Stewart }
2171d95b3509SRandall Stewart 
2172d95b3509SRandall Stewart extern int cpu_count_out;
2173d95b3509SRandall Stewart int cpu_count_out=0;
2174d95b3509SRandall Stewart 
2175d95b3509SRandall Stewart static void
print_header(void)2176d95b3509SRandall Stewart print_header(void)
2177d95b3509SRandall Stewart {
2178d95b3509SRandall Stewart 	int i, cnt, printed_cnt;
2179d95b3509SRandall Stewart 
2180d95b3509SRandall Stewart 	printf("*********************************\n");
2181d95b3509SRandall Stewart 	for(i=0, cnt=0; i<MAX_CPU; i++) {
2182d95b3509SRandall Stewart 		if (glob_cpu[i]) {
2183d95b3509SRandall Stewart 			cnt++;
2184d95b3509SRandall Stewart 		}
2185d95b3509SRandall Stewart 	}
2186d95b3509SRandall Stewart 	cpu_count_out = cnt;
2187d95b3509SRandall Stewart 	for(i=0, printed_cnt=0; i<MAX_CPU; i++) {
2188d95b3509SRandall Stewart 		if (glob_cpu[i]) {
2189d95b3509SRandall Stewart 			printf("CPU%d", i);
2190d95b3509SRandall Stewart 			printed_cnt++;
2191d95b3509SRandall Stewart 		}
2192d95b3509SRandall Stewart 		if (printed_cnt == cnt) {
2193d95b3509SRandall Stewart 			printf("\n");
2194d95b3509SRandall Stewart 			break;
2195d95b3509SRandall Stewart 		} else {
2196d95b3509SRandall Stewart 			printf("\t");
2197d95b3509SRandall Stewart 		}
2198d95b3509SRandall Stewart 	}
2199d95b3509SRandall Stewart }
2200d95b3509SRandall Stewart 
2201d95b3509SRandall Stewart static void
lace_cpus_together(void)2202d95b3509SRandall Stewart lace_cpus_together(void)
2203d95b3509SRandall Stewart {
2204d95b3509SRandall Stewart 	int i, j, lace_cpu;
2205d95b3509SRandall Stewart 	struct counters *cpat, *at;
2206d95b3509SRandall Stewart 
2207d95b3509SRandall Stewart 	for(i=0; i<ncnts; i++) {
2208d95b3509SRandall Stewart 		cpat = &cnts[i];
2209d95b3509SRandall Stewart 		if (cpat->next_cpu) {
2210d95b3509SRandall Stewart 			/* Already laced in */
2211d95b3509SRandall Stewart 			continue;
2212d95b3509SRandall Stewart 		}
2213d95b3509SRandall Stewart 		lace_cpu = cpat->cpu;
2214d95b3509SRandall Stewart 		if (lace_cpu >= MAX_CPU) {
2215d95b3509SRandall Stewart 			printf("CPU %d to big\n", lace_cpu);
2216d95b3509SRandall Stewart 			continue;
2217d95b3509SRandall Stewart 		}
2218d95b3509SRandall Stewart 		if (glob_cpu[lace_cpu] == NULL) {
2219d95b3509SRandall Stewart 			glob_cpu[lace_cpu] = cpat;
2220d95b3509SRandall Stewart 		} else {
2221d95b3509SRandall Stewart 			/* Already processed this cpu */
2222d95b3509SRandall Stewart 			continue;
2223d95b3509SRandall Stewart 		}
2224d95b3509SRandall Stewart 		/* Ok look forward for cpu->cpu and link in */
2225d95b3509SRandall Stewart 		for(j=(i+1); j<ncnts; j++) {
2226d95b3509SRandall Stewart 			at = &cnts[j];
2227d95b3509SRandall Stewart 			if (at->next_cpu) {
2228d95b3509SRandall Stewart 				continue;
2229d95b3509SRandall Stewart 			}
2230d95b3509SRandall Stewart 			if (at->cpu == lace_cpu) {
2231d95b3509SRandall Stewart 				/* Found one */
2232d95b3509SRandall Stewart 				cpat->next_cpu = at;
2233d95b3509SRandall Stewart 				cpat = at;
2234d95b3509SRandall Stewart 			}
2235d95b3509SRandall Stewart 		}
2236d95b3509SRandall Stewart 	}
2237d95b3509SRandall Stewart }
2238d95b3509SRandall Stewart 
2239d95b3509SRandall Stewart 
2240d95b3509SRandall Stewart static void
process_file(char * filename)2241d95b3509SRandall Stewart process_file(char *filename)
2242d95b3509SRandall Stewart {
2243d95b3509SRandall Stewart 	FILE *io;
2244d95b3509SRandall Stewart 	int i;
2245d95b3509SRandall Stewart 	int line_at, not_done;
2246d95b3509SRandall Stewart 	pid_t pid_of_command=0;
2247d95b3509SRandall Stewart 
2248d95b3509SRandall Stewart 	if (filename ==  NULL) {
2249d95b3509SRandall Stewart 		io = my_popen(command, "r", &pid_of_command);
2250bffefaf3Ssebastien.bini 		if (io == NULL) {
2251bffefaf3Ssebastien.bini 			printf("Can't popen the command %s\n", command);
2252bffefaf3Ssebastien.bini 			return;
2253bffefaf3Ssebastien.bini 		}
2254d95b3509SRandall Stewart 	} else {
2255d95b3509SRandall Stewart 		io = fopen(filename, "r");
2256d95b3509SRandall Stewart 		if (io == NULL) {
2257d95b3509SRandall Stewart 			printf("Can't process file %s err:%d\n",
2258d95b3509SRandall Stewart 			       filename, errno);
2259d95b3509SRandall Stewart 			return;
2260d95b3509SRandall Stewart 		}
2261d95b3509SRandall Stewart 	}
2262d95b3509SRandall Stewart 	build_counters_from_header(io);
2263d95b3509SRandall Stewart 	if (cnts == NULL) {
2264d95b3509SRandall Stewart 		/* Nothing we can do */
2265d95b3509SRandall Stewart 		printf("Nothing to do -- no counters built\n");
2266bffefaf3Ssebastien.bini 		if (filename) {
22678a3bbeb2SRandall Stewart 			fclose(io);
2268bffefaf3Ssebastien.bini 		} else {
2269bffefaf3Ssebastien.bini 			my_pclose(io, pid_of_command);
22708a3bbeb2SRandall Stewart 		}
2271d95b3509SRandall Stewart 		return;
2272d95b3509SRandall Stewart 	}
2273d95b3509SRandall Stewart 	lace_cpus_together();
2274d95b3509SRandall Stewart 	print_header();
2275d95b3509SRandall Stewart 	if (verbose) {
2276d95b3509SRandall Stewart 		for (i=0; i<ncnts; i++) {
2277d95b3509SRandall Stewart 			printf("Counter:%s cpu:%d index:%d\n",
2278d95b3509SRandall Stewart 			       cnts[i].counter_name,
2279d95b3509SRandall Stewart 			       cnts[i].cpu, i);
2280d95b3509SRandall Stewart 		}
2281d95b3509SRandall Stewart 	}
2282d95b3509SRandall Stewart 	line_at = 0;
2283d95b3509SRandall Stewart 	not_done = 1;
2284d95b3509SRandall Stewart 	while(not_done) {
2285d95b3509SRandall Stewart 		if (read_a_line(io)) {
2286d95b3509SRandall Stewart 			line_at++;
2287d95b3509SRandall Stewart 		} else {
2288d95b3509SRandall Stewart 			break;
2289d95b3509SRandall Stewart 		}
2290d95b3509SRandall Stewart 		if (line_at >= max_to_collect) {
2291d95b3509SRandall Stewart 			not_done = 0;
2292d95b3509SRandall Stewart 		}
2293d95b3509SRandall Stewart 		if (filename == NULL) {
2294d95b3509SRandall Stewart 			int cnt;
2295d95b3509SRandall Stewart 			/* For the ones we dynamically open we print now */
2296d95b3509SRandall Stewart 			for(i=0, cnt=0; i<MAX_CPU; i++) {
2297d95b3509SRandall Stewart 				do_expression(glob_cpu[i], (line_at-1));
2298d95b3509SRandall Stewart 				cnt++;
2299d95b3509SRandall Stewart 				if (cnt == cpu_count_out) {
2300d95b3509SRandall Stewart 					printf("\n");
2301d95b3509SRandall Stewart 					break;
2302d95b3509SRandall Stewart 				} else {
2303d95b3509SRandall Stewart 					printf("\t");
2304d95b3509SRandall Stewart 				}
2305d95b3509SRandall Stewart 			}
2306d95b3509SRandall Stewart 		}
2307d95b3509SRandall Stewart 	}
2308d95b3509SRandall Stewart 	if (filename) {
2309d95b3509SRandall Stewart 		fclose(io);
2310d95b3509SRandall Stewart 	} else {
2311d95b3509SRandall Stewart 		my_pclose(io, pid_of_command);
2312d95b3509SRandall Stewart 	}
2313d95b3509SRandall Stewart }
2314d95b3509SRandall Stewart #if defined(__amd64__)
2315d95b3509SRandall Stewart #define cpuid(in,a,b,c,d)\
2316d95b3509SRandall Stewart   asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
2317eef0660aSRandall Stewart 
2318eef0660aSRandall Stewart static __inline void
do_cpuid(u_int ax,u_int cx,u_int * p)2319eef0660aSRandall Stewart do_cpuid(u_int ax, u_int cx, u_int *p)
2320eef0660aSRandall Stewart {
2321eef0660aSRandall Stewart 	__asm __volatile("cpuid"
2322eef0660aSRandall Stewart 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
2323eef0660aSRandall Stewart 			 :  "0" (ax), "c" (cx) );
2324eef0660aSRandall Stewart }
2325eef0660aSRandall Stewart 
2326d95b3509SRandall Stewart #else
2327d95b3509SRandall Stewart #define cpuid(in, a, b, c, d)
23285dedd797SBryan Drewery #define do_cpuid(ax, cx, p)
2329d95b3509SRandall Stewart #endif
2330d95b3509SRandall Stewart 
2331d95b3509SRandall Stewart static void
get_cpuid_set(void)2332d95b3509SRandall Stewart get_cpuid_set(void)
2333d95b3509SRandall Stewart {
2334d95b3509SRandall Stewart 	unsigned long eax, ebx, ecx, edx;
2335d95b3509SRandall Stewart 	int model;
2336d95b3509SRandall Stewart 	pid_t pid_of_command=0;
2337d95b3509SRandall Stewart 	size_t sz, len;
2338d95b3509SRandall Stewart 	FILE *io;
2339d95b3509SRandall Stewart 	char linebuf[1024], *str;
2340eef0660aSRandall Stewart 	u_int reg[4];
2341d95b3509SRandall Stewart 
2342d95b3509SRandall Stewart 	eax = ebx = ecx = edx = 0;
2343d95b3509SRandall Stewart 
2344d95b3509SRandall Stewart 	cpuid(0, eax, ebx, ecx, edx);
2345d95b3509SRandall Stewart 	if (ebx == 0x68747541) {
2346d95b3509SRandall Stewart 		printf("AMD processors are not supported by this program\n");
2347d95b3509SRandall Stewart 		printf("Sorry\n");
2348d95b3509SRandall Stewart 		exit(0);
2349d95b3509SRandall Stewart 	} else if (ebx == 0x6972794) {
2350d95b3509SRandall Stewart 		printf("Cyrix processors are not supported by this program\n");
2351d95b3509SRandall Stewart 		printf("Sorry\n");
2352d95b3509SRandall Stewart 		exit(0);
2353d95b3509SRandall Stewart 	} else if (ebx == 0x756e6547) {
2354d95b3509SRandall Stewart 		printf("Genuine Intel\n");
2355d95b3509SRandall Stewart 	} else {
2356d95b3509SRandall Stewart 		printf("Unknown processor type 0x%lx Only Intel AMD64 types are supported by this routine!\n", ebx);
2357d95b3509SRandall Stewart 		exit(0);
2358d95b3509SRandall Stewart 	}
2359d95b3509SRandall Stewart 	cpuid(1, eax, ebx, ecx, edx);
2360d95b3509SRandall Stewart 	model = (((eax & 0xF0000) >> 12) | ((eax & 0xF0) >> 4));
2361d95b3509SRandall Stewart 	printf("CPU model is 0x%x id:0x%lx\n", model, eax);
2362d95b3509SRandall Stewart 	switch (eax & 0xF00) {
2363d95b3509SRandall Stewart 	case 0x500:		/* Pentium family processors */
2364d95b3509SRandall Stewart 		printf("Intel Pentium P5\n");
2365d95b3509SRandall Stewart 		goto not_supported;
2366d95b3509SRandall Stewart 		break;
2367d95b3509SRandall Stewart 	case 0x600:		/* Pentium Pro, Celeron, Pentium II & III */
2368d95b3509SRandall Stewart 		switch (model) {
2369d95b3509SRandall Stewart 		case 0x1:
2370d95b3509SRandall Stewart 			printf("Intel Pentium P6\n");
2371d95b3509SRandall Stewart 			goto not_supported;
2372d95b3509SRandall Stewart 			break;
2373d95b3509SRandall Stewart 		case 0x3:
2374d95b3509SRandall Stewart 		case 0x5:
2375d95b3509SRandall Stewart 			printf("Intel PII\n");
2376d95b3509SRandall Stewart 			goto not_supported;
2377d95b3509SRandall Stewart 			break;
2378eef0660aSRandall Stewart 		case 0x6: case 0x16:
2379d95b3509SRandall Stewart 			printf("Intel CL\n");
2380d95b3509SRandall Stewart 			goto not_supported;
2381d95b3509SRandall Stewart 			break;
2382eef0660aSRandall Stewart 		case 0x7: case 0x8: case 0xA: case 0xB:
2383d95b3509SRandall Stewart 			printf("Intel PIII\n");
2384d95b3509SRandall Stewart 			goto not_supported;
2385d95b3509SRandall Stewart 			break;
2386eef0660aSRandall Stewart 		case 0x9: case 0xD:
2387d95b3509SRandall Stewart 			printf("Intel PM\n");
2388d95b3509SRandall Stewart 			goto not_supported;
2389d95b3509SRandall Stewart 			break;
2390d95b3509SRandall Stewart 		case 0xE:
2391d95b3509SRandall Stewart 			printf("Intel CORE\n");
2392d95b3509SRandall Stewart 			goto not_supported;
2393d95b3509SRandall Stewart 			break;
2394d95b3509SRandall Stewart 		case 0xF:
2395d95b3509SRandall Stewart 			printf("Intel CORE2\n");
2396d95b3509SRandall Stewart 			goto not_supported;
2397d95b3509SRandall Stewart 			break;
2398d95b3509SRandall Stewart 		case 0x17:
2399d95b3509SRandall Stewart 			printf("Intel CORE2EXTREME\n");
2400d95b3509SRandall Stewart 			goto not_supported;
2401d95b3509SRandall Stewart 			break;
2402d95b3509SRandall Stewart 		case 0x1C:	/* Per Intel document 320047-002. */
2403d95b3509SRandall Stewart 			printf("Intel ATOM\n");
2404d95b3509SRandall Stewart 			goto not_supported;
2405d95b3509SRandall Stewart 			break;
2406d95b3509SRandall Stewart 		case 0x1A:
2407eef0660aSRandall Stewart 		case 0x1E:	/*
2408eef0660aSRandall Stewart 				 * Per Intel document 253669-032 9/2009,
2409eef0660aSRandall Stewart 				 * pages A-2 and A-57
2410eef0660aSRandall Stewart 				 */
2411eef0660aSRandall Stewart 		case 0x1F:	/*
2412eef0660aSRandall Stewart 				 * Per Intel document 253669-032 9/2009,
2413eef0660aSRandall Stewart 				 * pages A-2 and A-57
2414eef0660aSRandall Stewart 				 */
2415d95b3509SRandall Stewart 			printf("Intel COREI7\n");
2416d95b3509SRandall Stewart 			goto not_supported;
2417d95b3509SRandall Stewart 			break;
2418d95b3509SRandall Stewart 		case 0x2E:
2419d95b3509SRandall Stewart 			printf("Intel NEHALEM\n");
2420d95b3509SRandall Stewart 			goto not_supported;
2421d95b3509SRandall Stewart 			break;
2422d95b3509SRandall Stewart 		case 0x25:	/* Per Intel document 253669-033US 12/2009. */
2423d95b3509SRandall Stewart 		case 0x2C:	/* Per Intel document 253669-033US 12/2009. */
2424d95b3509SRandall Stewart 			printf("Intel WESTMERE\n");
2425d95b3509SRandall Stewart 			goto not_supported;
2426d95b3509SRandall Stewart 			break;
2427d95b3509SRandall Stewart 		case 0x2F:	/* Westmere-EX, seen in wild */
2428d95b3509SRandall Stewart 			printf("Intel WESTMERE\n");
2429d95b3509SRandall Stewart 			goto not_supported;
2430d95b3509SRandall Stewart 			break;
2431d95b3509SRandall Stewart 		case 0x2A:	/* Per Intel document 253669-039US 05/2011. */
2432d95b3509SRandall Stewart 			printf("Intel SANDYBRIDGE\n");
2433d95b3509SRandall Stewart 			set_sandybridge();
2434d95b3509SRandall Stewart 			break;
2435d95b3509SRandall Stewart 		case 0x2D:	/* Per Intel document 253669-044US 08/2012. */
2436d95b3509SRandall Stewart 			printf("Intel SANDYBRIDGE_XEON\n");
2437d95b3509SRandall Stewart 			set_sandybridge();
2438d95b3509SRandall Stewart 			break;
2439d95b3509SRandall Stewart 		case 0x3A:	/* Per Intel document 253669-043US 05/2012. */
2440d95b3509SRandall Stewart 			printf("Intel IVYBRIDGE\n");
2441d95b3509SRandall Stewart 			set_ivybridge();
2442d95b3509SRandall Stewart 			break;
2443d95b3509SRandall Stewart 		case 0x3E:	/* Per Intel document 325462-045US 01/2013. */
2444d95b3509SRandall Stewart 			printf("Intel IVYBRIDGE_XEON\n");
2445d95b3509SRandall Stewart 			set_ivybridge();
2446d95b3509SRandall Stewart 			break;
2447d95b3509SRandall Stewart 		case 0x3F:	/* Per Intel document 325462-045US 09/2014. */
2448d95b3509SRandall Stewart 			printf("Intel HASWELL (Xeon)\n");
2449d95b3509SRandall Stewart 			set_haswell();
2450d95b3509SRandall Stewart 			break;
2451d95b3509SRandall Stewart 		case 0x3C:	/* Per Intel document 325462-045US 01/2013. */
2452d95b3509SRandall Stewart 		case 0x45:
2453d95b3509SRandall Stewart 		case 0x46:
2454d95b3509SRandall Stewart 			printf("Intel HASWELL\n");
2455d95b3509SRandall Stewart 			set_haswell();
2456d95b3509SRandall Stewart 			break;
2457ade40db3SRandall Stewart 
2458ade40db3SRandall Stewart 		case 0x4e:
2459ade40db3SRandall Stewart 		case 0x5e:
2460ade40db3SRandall Stewart 			printf("Intel SKY-LAKE\n");
2461ade40db3SRandall Stewart 			goto not_supported;
2462ade40db3SRandall Stewart 			break;
2463ade40db3SRandall Stewart 		case 0x3D:
2464ade40db3SRandall Stewart 		case 0x47:
2465ade40db3SRandall Stewart 			printf("Intel BROADWELL\n");
2466ade40db3SRandall Stewart 			set_broadwell();
2467ade40db3SRandall Stewart 			break;
2468ade40db3SRandall Stewart 		case 0x4f:
2469ade40db3SRandall Stewart 		case 0x56:
2470eef0660aSRandall Stewart 			printf("Intel BROADWEL (Xeon)\n");
2471ade40db3SRandall Stewart 			set_broadwell();
2472ade40db3SRandall Stewart 			break;
2473ade40db3SRandall Stewart 
2474d95b3509SRandall Stewart 		case 0x4D:
2475d95b3509SRandall Stewart 			/* Per Intel document 330061-001 01/2014. */
2476d95b3509SRandall Stewart 			printf("Intel ATOM_SILVERMONT\n");
2477d95b3509SRandall Stewart 			goto not_supported;
2478d95b3509SRandall Stewart 			break;
2479d95b3509SRandall Stewart 		default:
2480d95b3509SRandall Stewart 			printf("Intel model 0x%x is not known -- sorry\n",
2481d95b3509SRandall Stewart 			       model);
2482d95b3509SRandall Stewart 			goto not_supported;
2483d95b3509SRandall Stewart 			break;
2484d95b3509SRandall Stewart 		}
2485d95b3509SRandall Stewart 		break;
2486d95b3509SRandall Stewart 	case 0xF00:		/* P4 */
2487d95b3509SRandall Stewart 		printf("Intel unknown model %d\n", model);
2488d95b3509SRandall Stewart 		goto not_supported;
2489d95b3509SRandall Stewart 		break;
2490d95b3509SRandall Stewart 	}
2491eef0660aSRandall Stewart 	do_cpuid(0xa, 0, reg);
2492eef0660aSRandall Stewart 	max_pmc_counters = (reg[3] & 0x0000000f) + 1;
2493eef0660aSRandall Stewart 	printf("We have %d PMC counters to work with\n", max_pmc_counters);
2494d95b3509SRandall Stewart 	/* Ok lets load the list of all known PMC's */
2495d95b3509SRandall Stewart 	io = my_popen("/usr/sbin/pmccontrol -L", "r", &pid_of_command);
2496d95b3509SRandall Stewart 	if (valid_pmcs == NULL) {
2497d95b3509SRandall Stewart 		/* Likely */
2498d95b3509SRandall Stewart 		pmc_allocated_cnt = PMC_INITIAL_ALLOC;
2499d95b3509SRandall Stewart 		sz = sizeof(char *) * pmc_allocated_cnt;
2500d95b3509SRandall Stewart 		valid_pmcs = malloc(sz);
2501d95b3509SRandall Stewart 		if (valid_pmcs == NULL) {
2502d95b3509SRandall Stewart 			printf("No memory allocation fails at startup?\n");
2503d95b3509SRandall Stewart 			exit(-1);
2504d95b3509SRandall Stewart 		}
2505d95b3509SRandall Stewart 		memset(valid_pmcs, 0, sz);
2506d95b3509SRandall Stewart 	}
2507eef0660aSRandall Stewart 
2508d95b3509SRandall Stewart 	while (fgets(linebuf, sizeof(linebuf), io) != NULL) {
2509d95b3509SRandall Stewart 		if (linebuf[0] != '\t') {
2510d95b3509SRandall Stewart 			/* sometimes headers ;-) */
2511d95b3509SRandall Stewart 			continue;
2512d95b3509SRandall Stewart 		}
2513d95b3509SRandall Stewart 		len = strlen(linebuf);
2514d95b3509SRandall Stewart 		if (linebuf[(len-1)] == '\n') {
2515d95b3509SRandall Stewart 			/* Likely */
2516d95b3509SRandall Stewart 			linebuf[(len-1)] = 0;
2517d95b3509SRandall Stewart 		}
2518d95b3509SRandall Stewart 		str = &linebuf[1];
2519d95b3509SRandall Stewart 		len = strlen(str) + 1;
2520d95b3509SRandall Stewart 		valid_pmcs[valid_pmc_cnt] = malloc(len);
2521d95b3509SRandall Stewart 		if (valid_pmcs[valid_pmc_cnt] == NULL) {
2522d95b3509SRandall Stewart 			printf("No memory2 allocation fails at startup?\n");
2523d95b3509SRandall Stewart 			exit(-1);
2524d95b3509SRandall Stewart 		}
2525d95b3509SRandall Stewart 		memset(valid_pmcs[valid_pmc_cnt], 0, len);
2526d95b3509SRandall Stewart 		strcpy(valid_pmcs[valid_pmc_cnt], str);
2527d95b3509SRandall Stewart 		valid_pmc_cnt++;
2528d95b3509SRandall Stewart 		if (valid_pmc_cnt >= pmc_allocated_cnt) {
2529d95b3509SRandall Stewart 			/* Got to expand -- unlikely */
2530d95b3509SRandall Stewart 			char **more;
2531d95b3509SRandall Stewart 
2532d95b3509SRandall Stewart 			sz = sizeof(char *) * (pmc_allocated_cnt * 2);
2533d95b3509SRandall Stewart 			more = malloc(sz);
2534d95b3509SRandall Stewart 			if (more == NULL) {
2535d95b3509SRandall Stewart 				printf("No memory3 allocation fails at startup?\n");
2536d95b3509SRandall Stewart 				exit(-1);
2537d95b3509SRandall Stewart 			}
25388a3bbeb2SRandall Stewart 			memset(more, 0, sz);
2539d95b3509SRandall Stewart 			memcpy(more, valid_pmcs, sz);
2540d95b3509SRandall Stewart 			pmc_allocated_cnt *= 2;
2541d95b3509SRandall Stewart 			free(valid_pmcs);
2542d95b3509SRandall Stewart 			valid_pmcs = more;
2543d95b3509SRandall Stewart 		}
2544d95b3509SRandall Stewart 	}
2545d95b3509SRandall Stewart 	my_pclose(io, pid_of_command);
2546d95b3509SRandall Stewart 	return;
2547d95b3509SRandall Stewart not_supported:
2548d95b3509SRandall Stewart 	printf("Not supported\n");
2549d95b3509SRandall Stewart 	exit(-1);
2550d95b3509SRandall Stewart }
2551d95b3509SRandall Stewart 
2552d95b3509SRandall Stewart static void
explain_all(void)2553d95b3509SRandall Stewart explain_all(void)
2554d95b3509SRandall Stewart {
2555d95b3509SRandall Stewart 	int i;
2556d95b3509SRandall Stewart 	printf("For CPU's of type %s the following expressions are available:\n",the_cpu.cputype);
2557d95b3509SRandall Stewart 	printf("-------------------------------------------------------------\n");
2558d95b3509SRandall Stewart 	for(i=0; i<the_cpu.number; i++){
2559d95b3509SRandall Stewart 		printf("For -e %s ", the_cpu.ents[i].name);
2560d95b3509SRandall Stewart 		(*the_cpu.explain)(the_cpu.ents[i].name);
2561d95b3509SRandall Stewart 		printf("----------------------------\n");
2562d95b3509SRandall Stewart 	}
2563d95b3509SRandall Stewart }
2564d95b3509SRandall Stewart 
2565d95b3509SRandall Stewart static void
test_for_a_pmc(const char * pmc,int out_so_far)2566d95b3509SRandall Stewart test_for_a_pmc(const char *pmc, int out_so_far)
2567d95b3509SRandall Stewart {
2568d95b3509SRandall Stewart 	FILE *io;
2569d95b3509SRandall Stewart 	pid_t pid_of_command=0;
2570d95b3509SRandall Stewart 	char my_command[1024];
2571d95b3509SRandall Stewart 	char line[1024];
2572d95b3509SRandall Stewart 	char resp[1024];
2573d95b3509SRandall Stewart 	int len, llen, i;
2574d95b3509SRandall Stewart 
2575d95b3509SRandall Stewart 	if (out_so_far < 50) {
2576d95b3509SRandall Stewart 		len = 50 - out_so_far;
2577d95b3509SRandall Stewart 		for(i=0; i<len; i++) {
2578d95b3509SRandall Stewart 			printf(" ");
2579d95b3509SRandall Stewart 		}
2580d95b3509SRandall Stewart 	}
2581d95b3509SRandall Stewart 	sprintf(my_command, "/usr/sbin/pmcstat -w .25 -c 0 -s %s", pmc);
2582d95b3509SRandall Stewart 	io = my_popen(my_command, "r", &pid_of_command);
2583d95b3509SRandall Stewart 	if (io == NULL) {
2584d95b3509SRandall Stewart 		printf("Failed -- popen fails\n");
2585d95b3509SRandall Stewart 		return;
2586d95b3509SRandall Stewart 	}
2587d95b3509SRandall Stewart 	/* Setup what we expect */
2588d95b3509SRandall Stewart 	len = sprintf(resp, "%s", pmc);
2589d95b3509SRandall Stewart 	if (fgets(line, sizeof(line), io) == NULL) {
2590d95b3509SRandall Stewart 		printf("Failed -- no output from pmstat\n");
2591d95b3509SRandall Stewart 		goto out;
2592d95b3509SRandall Stewart 	}
2593d95b3509SRandall Stewart 	llen = strlen(line);
2594d95b3509SRandall Stewart 	if (line[(llen-1)] == '\n') {
2595d95b3509SRandall Stewart 		line[(llen-1)] = 0;
2596d95b3509SRandall Stewart 		llen--;
2597d95b3509SRandall Stewart 	}
2598d95b3509SRandall Stewart 	for(i=2; i<(llen-len); i++) {
2599d95b3509SRandall Stewart 		if (strncmp(&line[i], "ERROR", 5) == 0) {
2600d95b3509SRandall Stewart 			printf("Failed %s\n", line);
2601d95b3509SRandall Stewart 			goto out;
2602d95b3509SRandall Stewart 		} else if (strncmp(&line[i], resp, len) == 0) {
2603d95b3509SRandall Stewart 			int j, k;
2604d95b3509SRandall Stewart 
2605d95b3509SRandall Stewart 			if (fgets(line, sizeof(line), io) == NULL) {
2606d95b3509SRandall Stewart 				printf("Failed -- no second output from pmstat\n");
2607d95b3509SRandall Stewart 				goto out;
2608d95b3509SRandall Stewart 			}
2609d95b3509SRandall Stewart 			len = strlen(line);
2610d95b3509SRandall Stewart 			for (j=0; j<len; j++) {
2611d95b3509SRandall Stewart 				if (line[j] == ' ') {
2612d95b3509SRandall Stewart 					j++;
2613d95b3509SRandall Stewart 				} else {
2614d95b3509SRandall Stewart 					break;
2615d95b3509SRandall Stewart 				}
2616d95b3509SRandall Stewart 			}
2617d95b3509SRandall Stewart 			printf("Pass");
2618d95b3509SRandall Stewart 			len = strlen(&line[j]);
2619d95b3509SRandall Stewart 			if (len < 20) {
2620d95b3509SRandall Stewart 				for(k=0; k<(20-len); k++) {
2621d95b3509SRandall Stewart 					printf(" ");
2622d95b3509SRandall Stewart 				}
2623d95b3509SRandall Stewart 			}
26244d9bf203SRandall Stewart 			if (len) {
2625d95b3509SRandall Stewart 				printf("%s", &line[j]);
26264d9bf203SRandall Stewart 			} else {
26274d9bf203SRandall Stewart 				printf("\n");
26284d9bf203SRandall Stewart 			}
2629d95b3509SRandall Stewart 			goto out;
2630d95b3509SRandall Stewart 		}
2631d95b3509SRandall Stewart 	}
2632d95b3509SRandall Stewart 	printf("Failed -- '%s' not '%s'\n", line, resp);
2633d95b3509SRandall Stewart out:
2634d95b3509SRandall Stewart 	my_pclose(io, pid_of_command);
2635d95b3509SRandall Stewart 
2636d95b3509SRandall Stewart }
2637d95b3509SRandall Stewart 
2638d95b3509SRandall Stewart static int
add_it_to(char ** vars,int cur_cnt,char * name)2639d95b3509SRandall Stewart add_it_to(char **vars, int cur_cnt, char *name)
2640d95b3509SRandall Stewart {
2641d95b3509SRandall Stewart 	int i;
2642d95b3509SRandall Stewart 	size_t len;
2643d95b3509SRandall Stewart 	for(i=0; i<cur_cnt; i++) {
2644d95b3509SRandall Stewart 		if (strcmp(vars[i], name) == 0) {
2645d95b3509SRandall Stewart 			/* Already have */
2646d95b3509SRandall Stewart 			return(0);
2647d95b3509SRandall Stewart 		}
2648d95b3509SRandall Stewart 	}
2649d95b3509SRandall Stewart 	if (vars[cur_cnt] != NULL) {
2650d95b3509SRandall Stewart 		printf("Cur_cnt:%d filled with %s??\n",
2651d95b3509SRandall Stewart 		       cur_cnt, vars[cur_cnt]);
2652d95b3509SRandall Stewart 		exit(-1);
2653d95b3509SRandall Stewart 	}
2654d95b3509SRandall Stewart 	/* Ok its new */
2655d95b3509SRandall Stewart 	len = strlen(name) + 1;
2656d95b3509SRandall Stewart 	vars[cur_cnt] = malloc(len);
2657d95b3509SRandall Stewart 	if (vars[cur_cnt] == NULL) {
2658d95b3509SRandall Stewart 		printf("No memory %s\n", __FUNCTION__);
2659d95b3509SRandall Stewart 		exit(-1);
2660d95b3509SRandall Stewart 	}
2661d95b3509SRandall Stewart 	memset(vars[cur_cnt], 0, len);
2662d95b3509SRandall Stewart 	strcpy(vars[cur_cnt], name);
2663d95b3509SRandall Stewart 	return(1);
2664d95b3509SRandall Stewart }
2665d95b3509SRandall Stewart 
2666d95b3509SRandall Stewart static char *
build_command_for_exp(struct expression * exp)2667d95b3509SRandall Stewart build_command_for_exp(struct expression *exp)
2668d95b3509SRandall Stewart {
2669d95b3509SRandall Stewart 	/*
2670eef0660aSRandall Stewart 	 * Build the pmcstat command to handle
2671eef0660aSRandall Stewart 	 * the passed in expression.
2672eef0660aSRandall Stewart 	 * /usr/sbin/pmcstat -w 1 -s NNN -s QQQ
2673eef0660aSRandall Stewart 	 * where NNN and QQQ represent the PMC's in the expression
2674eef0660aSRandall Stewart 	 * uniquely..
2675d95b3509SRandall Stewart 	 */
2676d95b3509SRandall Stewart 	char forming[1024];
2677d95b3509SRandall Stewart 	int cnt_pmc, alloced_pmcs, i;
2678d95b3509SRandall Stewart 	struct expression *at;
2679d95b3509SRandall Stewart 	char **vars, *cmd;
2680d95b3509SRandall Stewart 	size_t mal;
2681d95b3509SRandall Stewart 
2682d95b3509SRandall Stewart 	alloced_pmcs = cnt_pmc = 0;
2683d95b3509SRandall Stewart 	/* first how many do we have */
2684d95b3509SRandall Stewart 	at = exp;
2685d95b3509SRandall Stewart 	while (at) {
2686d95b3509SRandall Stewart 		if (at->type == TYPE_VALUE_PMC) {
2687d95b3509SRandall Stewart 			cnt_pmc++;
2688d95b3509SRandall Stewart 		}
2689d95b3509SRandall Stewart 		at = at->next;
2690d95b3509SRandall Stewart 	}
2691d95b3509SRandall Stewart 	if (cnt_pmc == 0) {
2692d95b3509SRandall Stewart 		printf("No PMC's in your expression -- nothing to do!!\n");
2693d95b3509SRandall Stewart 		exit(0);
2694d95b3509SRandall Stewart 	}
2695d95b3509SRandall Stewart 	mal = cnt_pmc * sizeof(char *);
2696d95b3509SRandall Stewart 	vars = malloc(mal);
2697d95b3509SRandall Stewart 	if (vars == NULL) {
2698d95b3509SRandall Stewart 		printf("No memory\n");
2699d95b3509SRandall Stewart 		exit(-1);
2700d95b3509SRandall Stewart 	}
2701d95b3509SRandall Stewart 	memset(vars, 0, mal);
2702d95b3509SRandall Stewart 	at = exp;
2703d95b3509SRandall Stewart 	while (at) {
2704d95b3509SRandall Stewart 		if (at->type == TYPE_VALUE_PMC) {
2705d95b3509SRandall Stewart 			if(add_it_to(vars, alloced_pmcs, at->name)) {
2706d95b3509SRandall Stewart 				alloced_pmcs++;
2707d95b3509SRandall Stewart 			}
2708d95b3509SRandall Stewart 		}
2709d95b3509SRandall Stewart 		at = at->next;
2710d95b3509SRandall Stewart 	}
2711d95b3509SRandall Stewart 	/* Now we have a unique list in vars so create our command */
2712d95b3509SRandall Stewart 	mal = 23; /*	"/usr/sbin/pmcstat -w 1"  + \0 */
2713d95b3509SRandall Stewart 	for(i=0; i<alloced_pmcs; i++) {
2714d95b3509SRandall Stewart 		mal += strlen(vars[i]) + 4;	/* var + " -s " */
2715d95b3509SRandall Stewart 	}
2716d95b3509SRandall Stewart 	cmd = malloc((mal+2));
2717d95b3509SRandall Stewart 	if (cmd == NULL) {
2718d95b3509SRandall Stewart 		printf("%s out of mem\n", __FUNCTION__);
2719d95b3509SRandall Stewart 		exit(-1);
2720d95b3509SRandall Stewart 	}
2721d95b3509SRandall Stewart 	memset(cmd, 0, (mal+2));
2722d95b3509SRandall Stewart 	strcpy(cmd, "/usr/sbin/pmcstat -w 1");
2723d95b3509SRandall Stewart 	at = exp;
2724d95b3509SRandall Stewart 	for(i=0; i<alloced_pmcs; i++) {
2725d95b3509SRandall Stewart 		sprintf(forming, " -s %s", vars[i]);
2726d95b3509SRandall Stewart 		strcat(cmd, forming);
2727d95b3509SRandall Stewart 		free(vars[i]);
2728d95b3509SRandall Stewart 		vars[i] = NULL;
2729d95b3509SRandall Stewart 	}
2730d95b3509SRandall Stewart 	free(vars);
2731d95b3509SRandall Stewart 	return(cmd);
2732d95b3509SRandall Stewart }
2733d95b3509SRandall Stewart 
2734d95b3509SRandall Stewart static int
user_expr(struct counters * cpu,int pos)2735d95b3509SRandall Stewart user_expr(struct counters *cpu, int pos)
2736d95b3509SRandall Stewart {
2737d95b3509SRandall Stewart 	int ret;
2738d95b3509SRandall Stewart 	double res;
2739d95b3509SRandall Stewart 	struct counters *var;
2740d95b3509SRandall Stewart 	struct expression *at;
2741d95b3509SRandall Stewart 
2742d95b3509SRandall Stewart 	at = master_exp;
2743d95b3509SRandall Stewart 	while (at) {
2744d95b3509SRandall Stewart 		if (at->type == TYPE_VALUE_PMC) {
2745d95b3509SRandall Stewart 			var = find_counter(cpu, at->name);
2746d95b3509SRandall Stewart 			if (var == NULL) {
2747d95b3509SRandall Stewart 				printf("%s:Can't find counter %s?\n", __FUNCTION__, at->name);
2748d95b3509SRandall Stewart 				exit(-1);
2749d95b3509SRandall Stewart 			}
2750d95b3509SRandall Stewart 			if (pos != -1) {
2751d95b3509SRandall Stewart 				at->value = var->vals[pos] * 1.0;
2752d95b3509SRandall Stewart 			} else {
2753d95b3509SRandall Stewart 				at->value = var->sum * 1.0;
2754d95b3509SRandall Stewart 			}
2755d95b3509SRandall Stewart 		}
2756d95b3509SRandall Stewart 		at = at->next;
2757d95b3509SRandall Stewart 	}
2758d95b3509SRandall Stewart 	res = run_expr(master_exp, 1, NULL);
2759d95b3509SRandall Stewart 	ret = printf("%1.3f", res);
2760d95b3509SRandall Stewart 	return(ret);
2761d95b3509SRandall Stewart }
2762d95b3509SRandall Stewart 
2763d95b3509SRandall Stewart 
2764d95b3509SRandall Stewart static void
set_manual_exp(struct expression * exp)2765d95b3509SRandall Stewart set_manual_exp(struct expression *exp)
2766d95b3509SRandall Stewart {
2767d95b3509SRandall Stewart 	expression = user_expr;
2768d95b3509SRandall Stewart 	command = build_command_for_exp(exp);
2769d95b3509SRandall Stewart 	threshold = "User defined threshold";
2770d95b3509SRandall Stewart }
2771d95b3509SRandall Stewart 
2772d95b3509SRandall Stewart static void
run_tests(void)2773d95b3509SRandall Stewart run_tests(void)
2774d95b3509SRandall Stewart {
2775d95b3509SRandall Stewart 	int i, lenout;
2776d95b3509SRandall Stewart 	printf("Running tests on %d PMC's this may take some time\n", valid_pmc_cnt);
2777d95b3509SRandall Stewart 	printf("------------------------------------------------------------------------\n");
2778d95b3509SRandall Stewart 	for(i=0; i<valid_pmc_cnt; i++) {
2779d95b3509SRandall Stewart 		lenout = printf("%s", valid_pmcs[i]);
2780d95b3509SRandall Stewart 		fflush(stdout);
2781d95b3509SRandall Stewart 		test_for_a_pmc(valid_pmcs[i], lenout);
2782d95b3509SRandall Stewart 	}
2783d95b3509SRandall Stewart }
2784d95b3509SRandall Stewart static void
list_all(void)2785d95b3509SRandall Stewart list_all(void)
2786d95b3509SRandall Stewart {
2787d95b3509SRandall Stewart 	int i, cnt, j;
2788d95b3509SRandall Stewart 	printf("PMC                                               Abbreviation\n");
2789d95b3509SRandall Stewart 	printf("--------------------------------------------------------------\n");
2790d95b3509SRandall Stewart 	for(i=0; i<valid_pmc_cnt; i++) {
2791d95b3509SRandall Stewart 		cnt = printf("%s", valid_pmcs[i]);
2792d95b3509SRandall Stewart 		for(j=cnt; j<52; j++) {
2793d95b3509SRandall Stewart 			printf(" ");
2794d95b3509SRandall Stewart 		}
2795d95b3509SRandall Stewart 		printf("%%%d\n", i);
2796d95b3509SRandall Stewart 	}
2797d95b3509SRandall Stewart }
2798d95b3509SRandall Stewart 
2799d95b3509SRandall Stewart 
2800d95b3509SRandall Stewart int
main(int argc,char ** argv)2801d95b3509SRandall Stewart main(int argc, char **argv)
2802d95b3509SRandall Stewart {
2803d95b3509SRandall Stewart 	int i, j, cnt;
2804d95b3509SRandall Stewart 	char *filename=NULL;
2805eef0660aSRandall Stewart 	const char *name=NULL;
2806d95b3509SRandall Stewart 	int help_only = 0;
2807d95b3509SRandall Stewart 	int test_mode = 0;
2808eef0660aSRandall Stewart 	int test_at = 0;
2809d95b3509SRandall Stewart 
2810d95b3509SRandall Stewart 	get_cpuid_set();
2811d95b3509SRandall Stewart 	memset(glob_cpu, 0, sizeof(glob_cpu));
2812eef0660aSRandall Stewart 	while ((i = getopt(argc, argv, "ALHhvm:i:?e:TE:")) != -1) {
2813d95b3509SRandall Stewart 		switch (i) {
2814eef0660aSRandall Stewart 		case 'A':
2815eef0660aSRandall Stewart 			run_all = 1;
2816eef0660aSRandall Stewart 			break;
2817d95b3509SRandall Stewart 		case 'L':
2818d95b3509SRandall Stewart 			list_all();
2819d95b3509SRandall Stewart 			return(0);
2820d95b3509SRandall Stewart 		case 'H':
2821d95b3509SRandall Stewart 			printf("**********************************\n");
2822d95b3509SRandall Stewart 			explain_all();
2823d95b3509SRandall Stewart 			printf("**********************************\n");
2824d95b3509SRandall Stewart 			return(0);
2825d95b3509SRandall Stewart 			break;
2826d95b3509SRandall Stewart 		case 'T':
2827d95b3509SRandall Stewart 			test_mode = 1;
2828d95b3509SRandall Stewart 			break;
2829d95b3509SRandall Stewart 		case 'E':
2830d95b3509SRandall Stewart 			master_exp = parse_expression(optarg);
2831d95b3509SRandall Stewart 			if (master_exp) {
2832d95b3509SRandall Stewart 				set_manual_exp(master_exp);
2833d95b3509SRandall Stewart 			}
2834d95b3509SRandall Stewart 			break;
2835d95b3509SRandall Stewart 		case 'e':
2836d95b3509SRandall Stewart 			if (validate_expression(optarg)) {
2837d95b3509SRandall Stewart 				printf("Unknown expression %s\n", optarg);
2838d95b3509SRandall Stewart 				return(0);
2839d95b3509SRandall Stewart 			}
2840d95b3509SRandall Stewart 			name = optarg;
2841d95b3509SRandall Stewart 			set_expression(optarg);
2842d95b3509SRandall Stewart 			break;
2843d95b3509SRandall Stewart 		case 'm':
2844d95b3509SRandall Stewart 			max_to_collect = strtol(optarg, NULL, 0);
2845d95b3509SRandall Stewart 			if (max_to_collect > MAX_COUNTER_SLOTS) {
2846d95b3509SRandall Stewart 				/* You can't collect more than max in array */
2847d95b3509SRandall Stewart 				max_to_collect = MAX_COUNTER_SLOTS;
2848d95b3509SRandall Stewart 			}
2849d95b3509SRandall Stewart 			break;
2850d95b3509SRandall Stewart 		case 'v':
2851d95b3509SRandall Stewart 			verbose++;
2852d95b3509SRandall Stewart 			break;
2853d95b3509SRandall Stewart 		case 'h':
2854d95b3509SRandall Stewart 			help_only = 1;
2855d95b3509SRandall Stewart 			break;
2856d95b3509SRandall Stewart 		case 'i':
2857d95b3509SRandall Stewart 			filename = optarg;
2858d95b3509SRandall Stewart 			break;
2859d95b3509SRandall Stewart 		case '?':
2860d95b3509SRandall Stewart 		default:
2861d95b3509SRandall Stewart 		use:
2862d95b3509SRandall Stewart 			printf("Use %s [ -i inputfile -v -m max_to_collect -e expr -E -h -? -H]\n",
2863d95b3509SRandall Stewart 			       argv[0]);
2864d95b3509SRandall Stewart 			printf("-i inputfile -- use source as inputfile not stdin (if stdin collect)\n");
2865d95b3509SRandall Stewart 			printf("-v -- verbose dump debug type things -- you don't want this\n");
2866*340e08beSGordon Bergling 			printf("-m N -- maximum to collect is N measurements\n");
2867d95b3509SRandall Stewart 			printf("-e expr-name -- Do expression expr-name\n");
2868d95b3509SRandall Stewart 			printf("-E 'your expression' -- Do your expression\n");
2869d95b3509SRandall Stewart 			printf("-h -- Don't do the expression I put in -e xxx just explain what it does and exit\n");
2870d95b3509SRandall Stewart 			printf("-H -- Don't run anything, just explain all canned expressions\n");
2871d95b3509SRandall Stewart 			printf("-T -- Test all PMC's defined by this processor\n");
2872eef0660aSRandall Stewart 			printf("-A -- Run all canned tests\n");
2873d95b3509SRandall Stewart 			return(0);
2874d95b3509SRandall Stewart 			break;
287580c7cc1cSPedro F. Giffuni 		}
2876d95b3509SRandall Stewart 	}
2877eef0660aSRandall Stewart 	if ((run_all == 0) && (name == NULL) && (filename == NULL) &&
2878eef0660aSRandall Stewart 	    (test_mode == 0) && (master_exp == NULL)) {
2879d95b3509SRandall Stewart 		printf("Without setting an expression we cannot dynamically gather information\n");
2880d95b3509SRandall Stewart 		printf("you must supply a filename (and you probably want verbosity)\n");
2881d95b3509SRandall Stewart 		goto use;
2882d95b3509SRandall Stewart 	}
2883eef0660aSRandall Stewart 	if (run_all && max_to_collect > 10) {
2884eef0660aSRandall Stewart 		max_to_collect = 3;
2885eef0660aSRandall Stewart 	}
2886d95b3509SRandall Stewart 	if (test_mode) {
2887d95b3509SRandall Stewart 		run_tests();
2888d95b3509SRandall Stewart 		return(0);
2889d95b3509SRandall Stewart 	}
2890d95b3509SRandall Stewart 	printf("*********************************\n");
2891eef0660aSRandall Stewart 	if ((master_exp == NULL) && name) {
2892d95b3509SRandall Stewart 		(*the_cpu.explain)(name);
2893eef0660aSRandall Stewart 	} else if (master_exp) {
2894d95b3509SRandall Stewart 		printf("Examine your expression ");
2895d95b3509SRandall Stewart 		print_exp(master_exp);
2896d95b3509SRandall Stewart 		printf("User defined threshold\n");
2897d95b3509SRandall Stewart 	}
2898d95b3509SRandall Stewart 	if (help_only) {
2899d95b3509SRandall Stewart 		return(0);
2900d95b3509SRandall Stewart 	}
2901eef0660aSRandall Stewart 	if (run_all) {
2902eef0660aSRandall Stewart 	more:
2903eef0660aSRandall Stewart 		name = the_cpu.ents[test_at].name;
2904eef0660aSRandall Stewart 		printf("***Test %s (threshold %s)****\n", name, the_cpu.ents[test_at].thresh);
2905eef0660aSRandall Stewart 		test_at++;
2906eef0660aSRandall Stewart 		if (set_expression(name) == -1) {
2907eef0660aSRandall Stewart 			if (test_at >= the_cpu.number) {
2908eef0660aSRandall Stewart 				goto done;
2909eef0660aSRandall Stewart 			} else
2910eef0660aSRandall Stewart 				goto more;
2911eef0660aSRandall Stewart 		}
2912eef0660aSRandall Stewart 
2913eef0660aSRandall Stewart 	}
2914d95b3509SRandall Stewart 	process_file(filename);
2915d95b3509SRandall Stewart 	if (verbose >= 2) {
2916d95b3509SRandall Stewart 		for (i=0; i<ncnts; i++) {
2917d95b3509SRandall Stewart 			printf("Counter:%s cpu:%d index:%d\n",
2918d95b3509SRandall Stewart 			       cnts[i].counter_name,
2919d95b3509SRandall Stewart 			       cnts[i].cpu, i);
2920d95b3509SRandall Stewart 			for(j=0; j<cnts[i].pos; j++) {
2921d95b3509SRandall Stewart 				printf(" val - %ld\n", (long int)cnts[i].vals[j]);
2922d95b3509SRandall Stewart 			}
2923d95b3509SRandall Stewart 			printf(" sum - %ld\n", (long int)cnts[i].sum);
2924d95b3509SRandall Stewart 		}
2925d95b3509SRandall Stewart 	}
2926d95b3509SRandall Stewart 	if (expression == NULL) {
2927d95b3509SRandall Stewart 		return(0);
2928d95b3509SRandall Stewart 	}
2929eef0660aSRandall Stewart 	if (max_to_collect > 1) {
2930d95b3509SRandall Stewart 		for(i=0, cnt=0; i<MAX_CPU; i++) {
2931d95b3509SRandall Stewart 			if (glob_cpu[i]) {
2932d95b3509SRandall Stewart 				do_expression(glob_cpu[i], -1);
2933d95b3509SRandall Stewart 				cnt++;
2934d95b3509SRandall Stewart 				if (cnt == cpu_count_out) {
2935d95b3509SRandall Stewart 					printf("\n");
2936d95b3509SRandall Stewart 					break;
2937d95b3509SRandall Stewart 				} else {
2938d95b3509SRandall Stewart 					printf("\t");
2939d95b3509SRandall Stewart 				}
2940d95b3509SRandall Stewart 			}
2941d95b3509SRandall Stewart 		}
2942eef0660aSRandall Stewart 	}
2943eef0660aSRandall Stewart 	if (run_all && (test_at < the_cpu.number)) {
2944eef0660aSRandall Stewart 		memset(glob_cpu, 0, sizeof(glob_cpu));
2945eef0660aSRandall Stewart 		ncnts = 0;
2946eef0660aSRandall Stewart 		printf("*********************************\n");
2947eef0660aSRandall Stewart 		goto more;
2948eef0660aSRandall Stewart 	} else if (run_all) {
2949eef0660aSRandall Stewart 	done:
2950eef0660aSRandall Stewart 		printf("*********************************\n");
2951eef0660aSRandall Stewart 	}
2952d95b3509SRandall Stewart 	return(0);
2953d95b3509SRandall Stewart }
2954