aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/cpu.h
blob: ec9dbfc64fe2f9304e87cbba328881811469589e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
 * Copyright 2010, Intel Corporation
 *
 * This file is part of PowerTOP
 *
 * This program file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program in a file named COPYING; if not, write to the
 * Free Software Foundation, Inc,
 * 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 * or just google for it.
 *
 * Authors:
 *	Arjan van de Ven <arjan@linux.intel.com>
 */

#ifndef __INCLUDE_GUARD_CPUDEV_H
#define __INCLUDE_GUARD_CPUDEV_H

#include <iostream>
#include <vector>
#include <string>
#include <stdint.h>
#include <sys/time.h>

using namespace std;

class abstract_cpu;

#define LEVEL_C0 -1
#define LEVEL_HEADER -2

#define PSTATE 1
#define CSTATE 2

struct idle_state {
	char linux_name[16]; /* state0 etc.. cpuidle name */
	char human_name[32];

	uint64_t usage_before;
	uint64_t usage_after;
	uint64_t usage_delta;

	uint64_t duration_before;
	uint64_t duration_after;
	uint64_t duration_delta;

	int before_count;
	int after_count;

	int line_level;
};

struct frequency {
	char human_name[32];
	int line_level;

	uint64_t freq;

	uint64_t time_after;
	uint64_t time_before;

	int before_count;
	int after_count;

	double   display_value;
};

class abstract_cpu
{
protected:
	int	first_cpu;
	struct timeval	stamp_before, stamp_after;
	double  time_factor;
	uint64_t max_frequency;
	uint64_t max_minus_one_frequency;
public:
	uint64_t	last_stamp;
	uint64_t	total_stamp;
	int	number;
	int	childcount;
	bool	idle, old_idle;
	uint64_t	current_frequency;
	uint64_t	effective_frequency;

	vector<class abstract_cpu *> children;
	vector<struct idle_state *> cstates;
	vector<struct frequency *> pstates;

	virtual ~abstract_cpu() {};

	class abstract_cpu *parent;


	void		set_number(int _number, int cpu) {this->number = _number; this->first_cpu = cpu;};

	virtual void	measurement_start(void);
	virtual void	measurement_end(void);

	virtual int     can_collapse(void) { return 0;};


	/* C state related methods */

	void		insert_cstate(const char *linux_name, const char *human_name, uint64_t usage, uint64_t duration, int count, int level = -1);
	void		update_cstate(const char *linux_name, const char *human_name, uint64_t usage, uint64_t duration, int count, int level = -1);
	void		finalize_cstate(const char *linux_name, uint64_t usage, uint64_t duration, int count);

	virtual int	has_cstate_level(int level);

	virtual char *  fill_cstate_line(int line_nr, char *buffer, const char *separator="") { return buffer;};
	virtual char *  fill_cstate_name(int line_nr, char *buffer) { return buffer;};


	/* P state related methods */
	void		insert_pstate(uint64_t freq, const char *human_name, uint64_t duration, int count);
	void		update_pstate(uint64_t freq, const char *human_name, uint64_t duration, int count);
	void		finalize_pstate(uint64_t freq, uint64_t duration, int count);


	virtual char *  fill_pstate_line(int line_nr, char *buffer) { return buffer;};
	virtual char *  fill_pstate_name(int line_nr, char *buffer) { return buffer;};
	virtual int	has_pstate_level(int level);
	virtual int	has_pstates(void) { return 1; };

	/* Frequency micro accounting methods */
	virtual void    calculate_freq(uint64_t time);
	virtual void    go_idle(uint64_t time) { idle = true; if (parent) parent->calculate_freq(time);};
	virtual void    go_unidle(uint64_t time) { idle = false; if (parent) parent->calculate_freq(time);};;
	virtual void    change_freq(uint64_t time, int freq) { current_frequency = freq; if (parent) parent->calculate_freq(time);};

	virtual void	change_effective_frequency(uint64_t time, uint64_t freq);

	virtual void    wiggle(void);

	virtual uint64_t total_pstate_time(void);

	virtual void validate(void);
	virtual void reset_pstate_data(void);
};

extern vector<class abstract_cpu *> all_cpus;

class cpu_linux: public abstract_cpu
{

	void		account_freq(uint64_t frequency, uint64_t duration);
public:
	virtual void	measurement_start(void);
	virtual void	measurement_end(void);

	virtual char *  fill_cstate_line(int line_nr, char *buffer, const char *separator="");
	virtual char *  fill_cstate_name(int line_nr, char *buffer);

	virtual char *  fill_pstate_line(int line_nr, char *buffer);
	virtual char *  fill_pstate_name(int line_nr, char *buffer);

	virtual void    change_freq(uint64_t time, int freq);
	virtual void	change_effective_frequency(uint64_t time, uint64_t freq);
	virtual void    go_idle(uint64_t time);
	virtual void    go_unidle(uint64_t time);

};

class cpu_core: public abstract_cpu
{
	void		account_freq(uint64_t frequency, uint64_t duration);
public:
	virtual char *  fill_cstate_line(int line_nr, char *buffer, const char *separator="");
	virtual char *  fill_cstate_name(int line_nr, char *buffer);

	virtual char *  fill_pstate_line(int line_nr, char *buffer);
	virtual char *  fill_pstate_name(int line_nr, char *buffer);

	virtual int     can_collapse(void) { return childcount == 1;};
	virtual void    calculate_freq(uint64_t time);
	virtual void	change_effective_frequency(uint64_t time, uint64_t freq);
};

class cpu_package: public abstract_cpu
{
	void		account_freq(uint64_t frequency, uint64_t duration);
public:
	virtual char *  fill_cstate_line(int line_nr, char *buffer, const char *separator="");
	virtual char *  fill_cstate_name(int line_nr, char *buffer);

	virtual char *  fill_pstate_line(int line_nr, char *buffer);
	virtual char *  fill_pstate_name(int line_nr, char *buffer);
	virtual int     can_collapse(void) { return childcount == 1;};

	virtual void    calculate_freq(uint64_t time);
	virtual void	change_effective_frequency(uint64_t time, uint64_t freq);

};

#include "intel_cpus.h"

extern void enumerate_cpus(void);

extern void report_display_cpu_pstates(void);
extern void report_display_cpu_cstates(void);



extern void display_cpu_cstates(const char *start= "",
				const char *end = "",
				const char *linestart = "",
				const char *separator = "| ",
				const char *lineend = "\n");

extern void w_display_cpu_cstates(void);
extern void w_display_cpu_pstates(void);


extern void start_cpu_measurement(void);
extern void end_cpu_measurement(void);
extern void process_cpu_data(void);
extern void end_cpu_data(void);
extern void clear_cpu_data(void);
extern void clear_all_cpus(void);

#endif