PAPI 0.100
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/PAPI.gemspec +14 -0
- data/lib/PAPI.rb +5 -0
- data/lib/PAPI/Component.rb +155 -0
- data/lib/PAPI/Error.rb +115 -0
- data/lib/PAPI/Event.rb +147 -0
- data/lib/PAPI/EventSet.rb +195 -0
- data/lib/PAPI/Version.rb +93 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0f46591e6beaf71b1b303a90c2fd08a6f4ce8aa3
|
4
|
+
data.tar.gz: 7479c89a0aefed2e55a85da912294e5b9fea5e1c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f0a38ba8caa53bd5f57e219b09782cebef482972ec8304e4e9ed026bf6928aa5997cdccb448b4fca18fe20e5e17cd65adbf6df7ec4babfe9b8af7aa5274c682e
|
7
|
+
data.tar.gz: b2e5c9a9ac7ff1e8fe79e359ebdec68a432cd21c63e8afebafa5b5b4b1d06bb025dde85d1e1636438b7422db2aa3a220a58e2dce8402b49db91ce61c287b516e
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014, Brice Videau <brice.videau@imag.fr>
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
17
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
18
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
19
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
20
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
21
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
22
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/PAPI.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'PAPI'
|
3
|
+
s.version = "0.100"
|
4
|
+
s.author = "Brice Videau"
|
5
|
+
s.email = "brice.videau@imag.fr"
|
6
|
+
s.homepage = "https://github.com/Nanosim-LIG/papi-ruby"
|
7
|
+
s.summary = "Ruby PAPI bindings"
|
8
|
+
s.description = "Ruby PAPI bindings."
|
9
|
+
s.files = %w( PAPI.gemspec LICENSE lib/PAPI.rb lib/PAPI/ lib/PAPI/Version.rb lib/PAPI/Error.rb lib/PAPI/Event.rb lib/PAPI/Component.rb lib/PAPI/EventSet.rb )
|
10
|
+
s.has_rdoc = true
|
11
|
+
s.license = 'BSD'
|
12
|
+
s.required_ruby_version = '>= 1.9.3'
|
13
|
+
s.add_dependency 'ffi', '>=1.9.3'
|
14
|
+
end
|
data/lib/PAPI.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
module PAPI
|
2
|
+
|
3
|
+
if VERSION >= Version::new(4,0,0,0) then
|
4
|
+
attach_function :PAPI_num_components, [], :int
|
5
|
+
attach_function :PAPI_get_component_info, [:int], :pointer
|
6
|
+
attach_function :PAPI_enum_cmp_event, [:pointer, EventModifier, :int], :int
|
7
|
+
else
|
8
|
+
attach_function :PAPI_get_substrate_info, [], :pointer
|
9
|
+
end
|
10
|
+
|
11
|
+
COMPONENTS = []
|
12
|
+
COMPONENTS_HASH = {}
|
13
|
+
|
14
|
+
class Component
|
15
|
+
class Info < FFI::Struct
|
16
|
+
lay = []
|
17
|
+
lay.push(:name, [:char, MAX_STR_LEN])
|
18
|
+
lay.push(:short_name, [:char, MIN_STR_LEN],
|
19
|
+
:description, [:char, MAX_STR_LEN]) if VERSION >= Version::new(5,0,0,0)
|
20
|
+
lay.push(:version, [:char, MIN_STR_LEN],
|
21
|
+
:support_version, [:char, MIN_STR_LEN],
|
22
|
+
:kernel_version, [:char, MIN_STR_LEN])
|
23
|
+
lay.push(:disabled_reason, [:char, MAX_STR_LEN],
|
24
|
+
:disabled, :int) if VERSION >= Version::new(5,0,0,0)
|
25
|
+
lay.push(:CmpIdx, :int) if VERSION >= Version::new(4,0,0,0)
|
26
|
+
lay.push(:num_cntrs, :int,
|
27
|
+
:num_mpx_cntrs, :int,
|
28
|
+
:num_preset_events, :int,
|
29
|
+
:num_native_events, :int,
|
30
|
+
:default_domain, :int,
|
31
|
+
:available_domains, :int,
|
32
|
+
:default_granularity, :int,
|
33
|
+
:available_granularities, :int)
|
34
|
+
lay.push(:itimer_sig, :int,
|
35
|
+
:itimer_num, :int,
|
36
|
+
:itimer_ns, :int,
|
37
|
+
:itimer_res_ns, :int) if VERSION < Version::new(5,0,0,0)
|
38
|
+
lay.push(:hardware_intr_sig, :int)
|
39
|
+
lay.push(:clock_ticks, :int,
|
40
|
+
:opcode_match_width, :int) if VERSION < Version::new(5,0,0,0)
|
41
|
+
lay.push(:component_type, :int) if VERSION >= Version::new(5,0,0,0)
|
42
|
+
lay.push(:pmu_names, [:pointer, PMU_MAX]) if VERSION >= Version::new(5,4,1,0)
|
43
|
+
lay.push(:reserved, [:int, 8]) if VERSION >= Version::new(5,0,0,0)
|
44
|
+
lay.push(:os_version, :int,
|
45
|
+
:reserved, [:int, 1]) if VERSION < Version::new(5,0,0,0) and VERSION >= Version::new(4,1,1,0)
|
46
|
+
lay.push(:reserved, [:int, 2]) if VERSION < Version::new(4,1,1,0)
|
47
|
+
lay.push(:bifield, :uint)
|
48
|
+
|
49
|
+
layout( *lay )
|
50
|
+
end
|
51
|
+
|
52
|
+
attr_reader :info
|
53
|
+
attr_accessor :native
|
54
|
+
attr_accessor :preset
|
55
|
+
|
56
|
+
def initialize(info, idx = 0)
|
57
|
+
@info = info
|
58
|
+
@idx = idx
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_i
|
62
|
+
return @idx
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_s
|
66
|
+
@info[:name].to_ptr.read_string
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.get_mask_info( code, component )
|
72
|
+
m_p = FFI::MemoryPointer::new(:uint)
|
73
|
+
m_p.write_uint( code.read_uint )
|
74
|
+
if VERSION < Version::new(4,0,0,0) then
|
75
|
+
e = PAPI_enum_event( m_p, :ntv_enum_umasks )
|
76
|
+
else
|
77
|
+
e = PAPI_enum_cmp_event( m_p, :ntv_enum_umasks, component.to_i )
|
78
|
+
end
|
79
|
+
return nil if e != OK
|
80
|
+
info = Event::Info::new
|
81
|
+
e = PAPI_get_event_info( m_p.read_int, info )
|
82
|
+
if e == OK then
|
83
|
+
ev = Event::new(info)
|
84
|
+
masks = []
|
85
|
+
masks.push(ev)
|
86
|
+
end
|
87
|
+
while ( VERSION < Version::new(4,0,0,0) ? PAPI_enum_event(e_p, :ntv_enum_umasks) : PAPI_enum_cmp_event( m_p, :ntv_enum_umasks, component.to_i ) ) == OK do
|
88
|
+
info = Event::Info::new
|
89
|
+
e = PAPI_get_event_info( m_p.read_int, info )
|
90
|
+
next if e != OK
|
91
|
+
ev = Event::new(info)
|
92
|
+
masks = [] if not masks
|
93
|
+
masks.push(ev)
|
94
|
+
end
|
95
|
+
return masks
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.get_native_events( component )
|
99
|
+
e_p = FFI::MemoryPointer::new(:uint)
|
100
|
+
e_p.write_uint(0 | Event::NATIVE_MASK)
|
101
|
+
if VERSION < Version::new(4,0,0,0) then
|
102
|
+
e = PAPI_enum_event(e_p, :enum_first)
|
103
|
+
else
|
104
|
+
e = PAPI_enum_cmp_event(e_p, :enum_first, component.to_i)
|
105
|
+
end
|
106
|
+
return if e != OK
|
107
|
+
info = Event::Info::new
|
108
|
+
e = PAPI_get_event_info( e_p.read_int, info )
|
109
|
+
if e == OK then
|
110
|
+
ev = Event::new(info, get_mask_info( e_p, component ))
|
111
|
+
component.native = []
|
112
|
+
component.native.push(ev)
|
113
|
+
end
|
114
|
+
while ( VERSION < Version::new(4,0,0,0) ? PAPI_enum_event(e_p, :enum_events) : PAPI_enum_cmp_event(e_p, :enum_events, component.to_i) ) == OK do
|
115
|
+
info = Event::Info::new
|
116
|
+
e = PAPI_get_event_info( e_p.read_int, info )
|
117
|
+
next if e != OK
|
118
|
+
ev = Event::new(info, get_mask_info( e_p, component ) )
|
119
|
+
component.native = [] if not component.native
|
120
|
+
component.native.push(ev)
|
121
|
+
end
|
122
|
+
|
123
|
+
#puts "#{component}: #{component.to_i}"
|
124
|
+
#puts component.native.length
|
125
|
+
#component.native.each { |evt| puts evt.to_s(true, true) }
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.get_components_info
|
129
|
+
if VERSION < Version::new(4,0,0,0) then
|
130
|
+
info_p = PAPI_get_substrate_info()
|
131
|
+
COMPONENTS.push( Component::new(Component::Info::new(info_p)))
|
132
|
+
COMPONENTS_HASH[0] = COMPONENTS[0]
|
133
|
+
else
|
134
|
+
(0...PAPI_num_components()).each { |cid|
|
135
|
+
info_p = PAPI_get_component_info(cid)
|
136
|
+
info = Component::Info::new(info_p)
|
137
|
+
if VERSION >= Version::new(5,0,0,0) and info[:disabled] != 0 then
|
138
|
+
#puts "#{info[:name].to_ptr.read_string}: #{info[:disabled_reason].to_ptr.read_string}"
|
139
|
+
else
|
140
|
+
COMPONENTS.push( Component::new(info, cid) )
|
141
|
+
COMPONENTS_HASH[cid] = COMPONENTS.last
|
142
|
+
end
|
143
|
+
}
|
144
|
+
end
|
145
|
+
if COMPONENTS.length > 0 then
|
146
|
+
COMPONENTS[0].preset = PRESET_EVENTS
|
147
|
+
end
|
148
|
+
COMPONENTS.each { |c|
|
149
|
+
get_native_events( c )
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
get_components_info
|
154
|
+
|
155
|
+
end
|
data/lib/PAPI/Error.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
module PAPI
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
attr_reader :code
|
5
|
+
|
6
|
+
def initialize(code)
|
7
|
+
@code = code
|
8
|
+
super("#{code}")
|
9
|
+
end
|
10
|
+
|
11
|
+
#:stopdoc:
|
12
|
+
CLASSES = {}
|
13
|
+
#:startdoc:
|
14
|
+
|
15
|
+
private_constant :CLASSES
|
16
|
+
|
17
|
+
def self.error_class(errcode)
|
18
|
+
return CLASSES[errcode]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.name(code)
|
22
|
+
if CLASSES[code] then
|
23
|
+
return CLASSES[code].name
|
24
|
+
else
|
25
|
+
return "#{code}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def name
|
30
|
+
return "#{@code}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.register_error(code, symbol)
|
34
|
+
s = <<EOF
|
35
|
+
class #{symbol} < Error
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
super(#{code})
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.name
|
42
|
+
return "#{symbol}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def name
|
46
|
+
return "#{symbol}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.code
|
50
|
+
return #{code}
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
CLASSES[#{code}] = #{symbol}
|
55
|
+
EOF
|
56
|
+
end
|
57
|
+
errors = []
|
58
|
+
errors.push([-1, "EINVAL"],
|
59
|
+
[-2, "ENOMEM"],
|
60
|
+
[-3, "ESYS"])
|
61
|
+
if VERSION >= Version::new(5,0,0,0) then
|
62
|
+
errors.push [-4, "ECMP"]
|
63
|
+
else
|
64
|
+
errors.push [-4, "ESBSTR"]
|
65
|
+
end
|
66
|
+
errors.push([-5, "ECLOST"],
|
67
|
+
[-6, "EBUG"],
|
68
|
+
[-7, "ENOEVNT"],
|
69
|
+
[-8, "ECNFLCT"],
|
70
|
+
[-9, "ENOTRUN"],
|
71
|
+
[-10, "EISRUN"],
|
72
|
+
[-11, "ENOEVST"],
|
73
|
+
[-12, "ENOTPRESET"],
|
74
|
+
[-13, "ENOCNTR"],
|
75
|
+
[-14, "EMISC"],
|
76
|
+
[-15, "EPERM"],
|
77
|
+
[-16, "ENOINIT"])
|
78
|
+
if VERSION >= Version::new(4,2,0,0) then
|
79
|
+
errors.push([-17, "ENOCMP"],
|
80
|
+
[-18, "ENOSUPP"],
|
81
|
+
[-19, "ENOIMPL"],
|
82
|
+
[-20, "EBUF"],
|
83
|
+
[-21, "EINVAL_DOM"],
|
84
|
+
[-22, "EATTR"],
|
85
|
+
[-23, "ECOUNT"],
|
86
|
+
[-24, "ECOMBO"])
|
87
|
+
elsif VERSION >= Version::new(4,1,0,0) then
|
88
|
+
errors.push([-17, "ENOCMP"],
|
89
|
+
[-18, "ENOSUPP"],
|
90
|
+
[-19, "ENOIMPL"],
|
91
|
+
[-20, "EBUF"],
|
92
|
+
[-21, "EINVAL_DOM"])
|
93
|
+
elsif VERSION >= Version::new(4,0,0,0) then
|
94
|
+
errors.push([-17, "EBUF"],
|
95
|
+
[-18, "EINVAL_DOM"],
|
96
|
+
[-19, "ENOCMP"])
|
97
|
+
else
|
98
|
+
errors.push([-17, "EBUF"],
|
99
|
+
[-18, "EINVAL_DOM"])
|
100
|
+
end
|
101
|
+
errors.each { |code, symbol| eval register_error(code, symbol) }
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.error_check(errcode)
|
106
|
+
return nil if errcode >= OK
|
107
|
+
klass = Error::error_class(errcode)
|
108
|
+
if klass then
|
109
|
+
raise klass::new
|
110
|
+
else
|
111
|
+
raise Error::new("#{errcode}")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
data/lib/PAPI/Event.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
module PAPI
|
2
|
+
|
3
|
+
MIN_STR_LEN = 64
|
4
|
+
MAX_STR_LEN = 128
|
5
|
+
MAX_STR_LEN2 = 256
|
6
|
+
HUGE_STR_LEN = 1024
|
7
|
+
MAX_INFO_TERMS = 12
|
8
|
+
PMU_MAX = 40
|
9
|
+
|
10
|
+
OK = 0
|
11
|
+
|
12
|
+
PAPI_NULL = -1
|
13
|
+
|
14
|
+
class Event
|
15
|
+
class Mask < Event
|
16
|
+
def initialize(info)
|
17
|
+
super(info,nil)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
PRESET_MASK = 0x80000000
|
22
|
+
NATIVE_MASK = 0x40000000
|
23
|
+
PRESET_AND_MASK = 0x7FFFFFFF
|
24
|
+
NATIVE_AND_MASK = 0xBFFFFFFF
|
25
|
+
|
26
|
+
MAX_PRESET_EVENTS = 128
|
27
|
+
|
28
|
+
attr_reader :info
|
29
|
+
attr_reader :masks
|
30
|
+
|
31
|
+
def initialize(info, masks = nil)
|
32
|
+
@info = info
|
33
|
+
@masks = masks
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_i
|
37
|
+
@info[:event_code]
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s(description = false, masks = false)
|
41
|
+
s1 = @info[:symbol].to_ptr.read_string
|
42
|
+
s = "#{s1}"
|
43
|
+
s += "\n #{@info[:long_descr]}" if description
|
44
|
+
if masks and @masks then
|
45
|
+
s += "\n "
|
46
|
+
s += @masks.collect{ |m| m.to_s.gsub(s1.gsub(/.*::/,""),"")+"\n " + m.info[:long_descr].to_ptr.read_string.gsub(/.*masks:/,"") }.join("\n ")
|
47
|
+
end
|
48
|
+
return s
|
49
|
+
end
|
50
|
+
|
51
|
+
class Info < FFI::Struct
|
52
|
+
if VERSION >= Version::new(5,0,0,0) then
|
53
|
+
layout :event_code, :int,
|
54
|
+
:symbol, [:char, HUGE_STR_LEN],
|
55
|
+
:short_descr, [:char, MIN_STR_LEN],
|
56
|
+
:long_descr, [:char, HUGE_STR_LEN],
|
57
|
+
:component_index, :int,
|
58
|
+
:units, [:char, MIN_STR_LEN],
|
59
|
+
:location, :int,
|
60
|
+
:data_type, :int,
|
61
|
+
:value_type, :int,
|
62
|
+
:timescope, :int,
|
63
|
+
:update_type, :int,
|
64
|
+
:update_freq, :int,
|
65
|
+
:count, :uint,
|
66
|
+
:event_type, :uint,
|
67
|
+
:derived, [:char, MIN_STR_LEN],
|
68
|
+
:postfix, [:char, MAX_STR_LEN2],
|
69
|
+
:code, [:int, MAX_INFO_TERMS],
|
70
|
+
:name, [:char, MAX_INFO_TERMS*MAX_STR_LEN2],
|
71
|
+
:note, [:char, HUGE_STR_LEN]
|
72
|
+
else
|
73
|
+
layout :event_code, :uint,
|
74
|
+
:event_type, :uint,
|
75
|
+
:count, :uint,
|
76
|
+
:symbol, [:char, HUGE_STR_LEN],
|
77
|
+
:short_descr, [:char, MIN_STR_LEN],
|
78
|
+
:long_descr, [:char, HUGE_STR_LEN],
|
79
|
+
:derived, [:char, MIN_STR_LEN],
|
80
|
+
:postfix, [:char, MIN_STR_LEN],
|
81
|
+
:code, [:int, MAX_INFO_TERMS],
|
82
|
+
:name, [:char, MAX_INFO_TERMS*MAX_STR_LEN2],
|
83
|
+
:note, [:char, HUGE_STR_LEN]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
typedef :pointer, :papi_event_info_t
|
89
|
+
|
90
|
+
EventModifier = enum( :enum_events,
|
91
|
+
:enum_first,
|
92
|
+
:preset_enum_avail,
|
93
|
+
:preset_enum_msc,
|
94
|
+
:preset_enum_ins,
|
95
|
+
:preset_enum_idl,
|
96
|
+
:preset_enum_br,
|
97
|
+
:preset_enum_cnd,
|
98
|
+
:preset_enum_mem,
|
99
|
+
:preset_enum_cach,
|
100
|
+
:preset_enum_l1,
|
101
|
+
:preset_enum_l2,
|
102
|
+
:preset_enum_l3,
|
103
|
+
:preset_enum_tlb,
|
104
|
+
:preset_enum_fp,
|
105
|
+
:ntv_enum_umasks,
|
106
|
+
:ntv_enum_umasks_combos,
|
107
|
+
:ntv_enum_iarr,
|
108
|
+
:ntv_enum_darr,
|
109
|
+
:ntv_enum_opcm,
|
110
|
+
:ntv_enum_iear,
|
111
|
+
:ntv_enum_dear,
|
112
|
+
:ntv_enum_groups )
|
113
|
+
|
114
|
+
attach_function :PAPI_enum_event, [:pointer, EventModifier], :int
|
115
|
+
attach_function :PAPI_get_event_info, [:int, :papi_event_info_t], :int
|
116
|
+
|
117
|
+
PRESET_EVENTS = []
|
118
|
+
PRESET_EVENTS_HASH = {}
|
119
|
+
|
120
|
+
def self.get_events_info
|
121
|
+
e_p = FFI::MemoryPointer::new(:uint)
|
122
|
+
e_p.write_uint(0 | Event::PRESET_MASK)
|
123
|
+
PAPI_enum_event(e_p, :enum_first)
|
124
|
+
info = Event::Info::new
|
125
|
+
e = PAPI_get_event_info( e_p.read_int, info )
|
126
|
+
ev = Event::new(info)
|
127
|
+
PRESET_EVENTS.push(ev)
|
128
|
+
PRESET_EVENTS_HASH[ev.to_i] = ev
|
129
|
+
while PAPI_enum_event(e_p, :preset_enum_avail) == OK do
|
130
|
+
info = Event::Info::new
|
131
|
+
e = PAPI_get_event_info( e_p.read_int, info )
|
132
|
+
ev = Event::new(info)
|
133
|
+
PRESET_EVENTS.push(ev)
|
134
|
+
PRESET_EVENTS_HASH[ev.to_i] = ev
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
get_events_info
|
139
|
+
|
140
|
+
PRESET_EVENTS.each_index { |i|
|
141
|
+
s = <<EOF
|
142
|
+
#{PRESET_EVENTS[i].to_s.gsub("PAPI_","")} = PRESET_EVENTS[#{i}]
|
143
|
+
EOF
|
144
|
+
eval s
|
145
|
+
}
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
module PAPI
|
2
|
+
|
3
|
+
typedef :int, :event_set
|
4
|
+
attach_function :PAPI_create_eventset, [:pointer], :int
|
5
|
+
attach_function :PAPI_add_event, [:event_set, :int], :int
|
6
|
+
attach_function :PAPI_add_named_event, [:event_set, :string], :int
|
7
|
+
attach_function :PAPI_remove_event, [:event_set, :int], :int
|
8
|
+
attach_function :PAPI_remove_named_event, [:event_set, :string], :int
|
9
|
+
attach_function :PAPI_num_events, [:event_set], :int
|
10
|
+
attach_function :PAPI_list_events, [:event_set, :pointer, :pointer], :int
|
11
|
+
attach_function :PAPI_start, [:event_set], :int
|
12
|
+
attach_function :PAPI_stop, [:event_set, :pointer], :int
|
13
|
+
attach_function :PAPI_accum, [:event_set, :pointer], :int
|
14
|
+
attach_function :PAPI_read, [:event_set, :pointer], :int
|
15
|
+
attach_function :PAPI_read_ts, [:event_set, :pointer, :pointer], :int
|
16
|
+
attach_function :PAPI_assign_eventset_component, [:event_set, :int], :int
|
17
|
+
attach_function :PAPI_get_eventset_component, [:event_set], :int
|
18
|
+
|
19
|
+
class EventSet
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
number = FFI::MemoryPointer::new(:int)
|
23
|
+
number.write_int(PAPI_NULL)
|
24
|
+
error = PAPI::PAPI_create_eventset( number )
|
25
|
+
@number = number.read_int
|
26
|
+
PAPI::error_check(error)
|
27
|
+
@size = 0
|
28
|
+
end
|
29
|
+
|
30
|
+
def assign_component(component)
|
31
|
+
error = PAPI::PAPI_assign_eventset_component( @number, component.to_i )
|
32
|
+
PAPI::error_check(error)
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
def add( events )
|
37
|
+
evts = [events].flatten
|
38
|
+
evts.each { |ev|
|
39
|
+
error = PAPI::PAPI_add_event(@number, ev.to_i)
|
40
|
+
PAPI::error_check(error)
|
41
|
+
}
|
42
|
+
error = PAPI::PAPI_num_events(@number)
|
43
|
+
PAPI::error_check(error)
|
44
|
+
@size = error
|
45
|
+
return self
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_named(events)
|
49
|
+
evts = [events].flatten
|
50
|
+
evts.each { |ev|
|
51
|
+
error = PAPI::PAPI_add_named_event(@number, ev.to_s)
|
52
|
+
PAPI::error_check(error)
|
53
|
+
}
|
54
|
+
error = PAPI::PAPI_num_events(@number)
|
55
|
+
PAPI::error_check(error)
|
56
|
+
@size = error
|
57
|
+
return self
|
58
|
+
end
|
59
|
+
|
60
|
+
def remove( events )
|
61
|
+
evts = [events].flatten
|
62
|
+
evts.each { |ev|
|
63
|
+
error = PAPI::PAPI_remove_event(@number, ev.to_i)
|
64
|
+
PAPI::error_check(error)
|
65
|
+
}
|
66
|
+
error = PAPI::PAPI_num_events(@number)
|
67
|
+
PAPI::error_check(error)
|
68
|
+
@size = error
|
69
|
+
return self
|
70
|
+
end
|
71
|
+
|
72
|
+
def remove_named( events )
|
73
|
+
evts = [events].flatten
|
74
|
+
evts.each { |ev|
|
75
|
+
error = PAPI::PAPI_remove_named_event(@number, ev.to_s)
|
76
|
+
PAPI::error_check(error)
|
77
|
+
}
|
78
|
+
error = PAPI::PAPI_num_events(@number)
|
79
|
+
PAPI::error_check(error)
|
80
|
+
@size = error
|
81
|
+
return self
|
82
|
+
end
|
83
|
+
|
84
|
+
def possible(preset = true)
|
85
|
+
cid = nil
|
86
|
+
begin
|
87
|
+
e = PAPI::PAPI_get_eventset_component(@number)
|
88
|
+
PAPI::error_check(e)
|
89
|
+
cid = e
|
90
|
+
rescue
|
91
|
+
cid = 0
|
92
|
+
end
|
93
|
+
list = []
|
94
|
+
if preset and COMPONENTS[cid].preset then
|
95
|
+
events = COMPONENTS[cid].preset
|
96
|
+
else
|
97
|
+
events = COMPONENTS[cid].native
|
98
|
+
end
|
99
|
+
events.each { |event|
|
100
|
+
error = PAPI::PAPI_add_event(@number, event.to_i)
|
101
|
+
if( error >= OK ) then
|
102
|
+
error = PAPI::PAPI_remove_event(@number, event.to_i)
|
103
|
+
PAPI::error_check(error)
|
104
|
+
list.push event
|
105
|
+
elsif event.masks then
|
106
|
+
event.masks.each { |mask|
|
107
|
+
error = PAPI::PAPI_add_named_event(@number, mask.info[:symbol])
|
108
|
+
if( error >= OK ) then
|
109
|
+
error = PAPI::PAPI_remove_named_event(@number, mask.info[:symbol])
|
110
|
+
PAPI::error_check(error)
|
111
|
+
list.push event
|
112
|
+
break
|
113
|
+
end
|
114
|
+
}
|
115
|
+
event.masks.each { |mask|
|
116
|
+
error = PAPI::PAPI_add_named_event(@number, mask.info[:symbol].to_ptr.read_string+":cpu=1")
|
117
|
+
if( error >= OK ) then
|
118
|
+
error = PAPI::PAPI_remove_named_event(@number, mask.info[:symbol].to_ptr.read_string+":cpu=1")
|
119
|
+
PAPI::error_check(error)
|
120
|
+
list.push event
|
121
|
+
break
|
122
|
+
end
|
123
|
+
}
|
124
|
+
else
|
125
|
+
error = PAPI::PAPI_add_named_event(@number, (event.info[:symbol].to_ptr.read_string+":cpu=1").gsub(/.*::/,""))
|
126
|
+
if( error >= OK ) then
|
127
|
+
error = PAPI::PAPI_remove_named_event(@number, (event.info[:symbol].to_ptr.read_string+":cpu=1").gsub(/.*::/,""))
|
128
|
+
PAPI::error_check(error)
|
129
|
+
list.push event
|
130
|
+
end
|
131
|
+
end
|
132
|
+
}
|
133
|
+
return list
|
134
|
+
end
|
135
|
+
|
136
|
+
def size
|
137
|
+
return @size
|
138
|
+
end
|
139
|
+
|
140
|
+
alias length size
|
141
|
+
alias num_events size
|
142
|
+
|
143
|
+
def events
|
144
|
+
events_p = FFI::MemoryPointer::new(:int, @size)
|
145
|
+
size_p = FFI::MemoryPointer::new(:int)
|
146
|
+
size_p.write_int(@size)
|
147
|
+
error = PAPI::PAPI_list_events(@number, events_p, size_p)
|
148
|
+
PAPI::error_check(error)
|
149
|
+
evts = events_p.read_array_of_int(size_p.read_int)
|
150
|
+
return evts.collect { |code| PRESET_EVENTS_HASH[code] }
|
151
|
+
end
|
152
|
+
|
153
|
+
alias list_events events
|
154
|
+
|
155
|
+
def start
|
156
|
+
error = PAPI::PAPI_start(@number)
|
157
|
+
PAPI::error_check(error)
|
158
|
+
return self
|
159
|
+
end
|
160
|
+
|
161
|
+
def stop
|
162
|
+
values_p = FFI::MemoryPointer::new(:long_long, @size)
|
163
|
+
error = PAPI::PAPI_stop(@number, values_p)
|
164
|
+
PAPI::error_check(error)
|
165
|
+
return values_p.read_array_of_long_long(@size)
|
166
|
+
end
|
167
|
+
|
168
|
+
def accum(values)
|
169
|
+
values_p = FFI::MemoryPointer::new(:long_long, @size)
|
170
|
+
values_p.write_array_of_long_long(values)
|
171
|
+
error = PAPI::PAPI_accum(@number, values_p)
|
172
|
+
PAPI::error_check(error)
|
173
|
+
new_values = values_p.read_array_of_long_long(@size)
|
174
|
+
values.replace(new_values)
|
175
|
+
return self
|
176
|
+
end
|
177
|
+
|
178
|
+
def read
|
179
|
+
values_p = FFI::MemoryPointer::new(:long_long, @size)
|
180
|
+
error = PAPI::PAPI_read(@number, values_p)
|
181
|
+
PAPI::error_check(error)
|
182
|
+
return values_p.read_array_of_long_long(@size)
|
183
|
+
end
|
184
|
+
|
185
|
+
def read_ts
|
186
|
+
values_p = FFI::MemoryPointer::new(:long_long, @size)
|
187
|
+
ts_p = FFI::MemoryPointer::new(:long_long)
|
188
|
+
error = PAPI::PAPI_read_ts(@number, values_p, ts_p)
|
189
|
+
PAPI::error_check(error)
|
190
|
+
return [values_p.read_array_of_long_long(@size), ts_p.read_long_long]
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
data/lib/PAPI/Version.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module PAPI
|
4
|
+
|
5
|
+
extend FFI::Library
|
6
|
+
|
7
|
+
ffi_lib "libpapi.so"
|
8
|
+
attach_function :PAPI_library_init, [ :int ], :int
|
9
|
+
attach_function :PAPI_shutdown, [ ], :void
|
10
|
+
|
11
|
+
class Version
|
12
|
+
include Comparable
|
13
|
+
|
14
|
+
def initialize( *vals )
|
15
|
+
if( vals.length > 1 )
|
16
|
+
@number = 0
|
17
|
+
4.times {
|
18
|
+
v = vals.shift
|
19
|
+
v = 0 unless v
|
20
|
+
@number <<= 8
|
21
|
+
@number += v & 0xff
|
22
|
+
}
|
23
|
+
else
|
24
|
+
@number = vals[0]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def major
|
29
|
+
return ( @number >> 24 ) & 0xff
|
30
|
+
end
|
31
|
+
|
32
|
+
def minor
|
33
|
+
return ( @number >> 16 ) & 0xff
|
34
|
+
end
|
35
|
+
|
36
|
+
def revision
|
37
|
+
return ( @number >> 8 ) & 0xff
|
38
|
+
end
|
39
|
+
|
40
|
+
def increment
|
41
|
+
return @number & 0xff
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_int
|
45
|
+
return @number
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
return "#{major}.#{minor}.#{revision}.#{increment}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def <=>(v)
|
53
|
+
return self.to_int <=> v.to_int
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.init
|
58
|
+
5.downto(3) { |major|
|
59
|
+
9.downto(0) { |minor|
|
60
|
+
9.downto(0) { |revision|
|
61
|
+
9.downto(0) { |increment|
|
62
|
+
v = Version::new(major, minor, revision, increment)
|
63
|
+
res = PAPI_library_init(v)
|
64
|
+
if res == v.to_int then
|
65
|
+
return Version::new(res)
|
66
|
+
end
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.init
|
75
|
+
5.downto(3) { |major|
|
76
|
+
9.downto(0) { |minor|
|
77
|
+
9.downto(0) { |revision|
|
78
|
+
9.downto(0) { |increment|
|
79
|
+
v = Version::new(major, minor, revision, increment)
|
80
|
+
res = PAPI_library_init(v)
|
81
|
+
if res == v.to_int then
|
82
|
+
return Version::new(res)
|
83
|
+
end
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
|
91
|
+
VERSION = self.init()
|
92
|
+
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: PAPI
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.100'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brice Videau
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.9.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.9.3
|
27
|
+
description: Ruby PAPI bindings.
|
28
|
+
email: brice.videau@imag.fr
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- LICENSE
|
34
|
+
- PAPI.gemspec
|
35
|
+
- lib/PAPI.rb
|
36
|
+
- lib/PAPI/Component.rb
|
37
|
+
- lib/PAPI/Error.rb
|
38
|
+
- lib/PAPI/Event.rb
|
39
|
+
- lib/PAPI/EventSet.rb
|
40
|
+
- lib/PAPI/Version.rb
|
41
|
+
homepage: https://github.com/Nanosim-LIG/papi-ruby
|
42
|
+
licenses:
|
43
|
+
- BSD
|
44
|
+
metadata: {}
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.9.3
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 2.2.2
|
62
|
+
signing_key:
|
63
|
+
specification_version: 4
|
64
|
+
summary: Ruby PAPI bindings
|
65
|
+
test_files: []
|