blob: 7994a15862c16d22bfc4cc062a852b5ef47c7814 [file] [log] [blame]
Moritz Pflanzera4f711b2017-07-05 11:02:23 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "PMUCounter.h"
25
26#define _GNU_SOURCE 1
27#include <asm/unistd.h>
28#include <csignal>
29#include <cstdio>
30#include <cstdlib>
31#include <cstring>
32#include <fcntl.h>
33#include <linux/hw_breakpoint.h>
34#include <linux/perf_event.h>
35#include <sys/ioctl.h>
36#include <unistd.h>
37#undef _GNU_SOURCE
38
39#include <stdexcept>
40
41namespace arm_compute
42{
43namespace test
44{
45namespace framework
46{
47CycleCounter::CycleCounter()
48{
49 const pid_t pid = getpid();
50
51 struct perf_event_attr perf_config; //NOLINT
52 memset(&perf_config, 0, sizeof(struct perf_event_attr));
53
54 perf_config.config = PERF_COUNT_HW_CPU_CYCLES;
55 perf_config.size = sizeof(struct perf_event_attr);
56 perf_config.type = PERF_TYPE_HARDWARE;
57 // The inherit bit specifies that this counter should count events of child
58 // tasks as well as the task specified
59 perf_config.inherit = 1;
60 // Enables saving of event counts on context switch for inherited tasks
61 perf_config.inherit_stat = 1;
62
63 _fd = syscall(__NR_perf_event_open, &perf_config, pid, -1, -1, 0);
64
65 if(_fd < 0)
66 {
67 throw std::runtime_error("perf_event_open for cycles failed");
68 }
69}
70
71std::string CycleCounter::id() const
72{
73 return "Cycle Counter";
74}
75
76void CycleCounter::start()
77{
78 ioctl(_fd, PERF_EVENT_IOC_RESET, 0);
79 ioctl(_fd, PERF_EVENT_IOC_ENABLE, 0);
80}
81
82void CycleCounter::stop()
83{
84 ioctl(_fd, PERF_EVENT_IOC_DISABLE, 0);
85 read(_fd, &_cycles, sizeof(_cycles));
86}
87
88Instrument::Measurement CycleCounter::measurement() const
89{
90 return Measurement(_cycles, "cycles");
91}
92
93InstructionCounter::InstructionCounter()
94{
95 const pid_t pid = getpid();
96
97 struct perf_event_attr perf_config; //NOLINT
98 memset(&perf_config, 0, sizeof(struct perf_event_attr));
99
100 perf_config.config = PERF_COUNT_HW_INSTRUCTIONS;
101 perf_config.size = sizeof(struct perf_event_attr);
102 perf_config.type = PERF_TYPE_HARDWARE;
103 // The inherit bit specifies that this counter should count events of child
104 // tasks as well as the task specified
105 perf_config.inherit = 1;
106 // Enables saving of event counts on context switch for inherited tasks
107 perf_config.inherit_stat = 1;
108
109 _fd = syscall(__NR_perf_event_open, &perf_config, pid, -1, -1, 0);
110
111 if(_fd < 0)
112 {
113 throw std::runtime_error("perf_event_open for instructions failed");
114 }
115}
116
117std::string InstructionCounter::id() const
118{
119 return "Instruction Counter";
120}
121
122void InstructionCounter::start()
123{
124 ioctl(_fd, PERF_EVENT_IOC_RESET, 0);
125 ioctl(_fd, PERF_EVENT_IOC_ENABLE, 0);
126}
127
128void InstructionCounter::stop()
129{
130 ioctl(_fd, PERF_EVENT_IOC_DISABLE, 0);
131 read(_fd, &_instructions, sizeof(_instructions));
132}
133
134Instrument::Measurement InstructionCounter::measurement() const
135{
136 return Measurement(_instructions, "instructions");
137}
138} // namespace framework
139} // namespace test
140} // namespace arm_compute