PAPI 0.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'PAPI/Version.rb'
2
+ require 'PAPI/Error.rb'
3
+ require 'PAPI/Event.rb'
4
+ require 'PAPI/Component.rb'
5
+ require 'PAPI/EventSet.rb'
@@ -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
@@ -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
@@ -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
@@ -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: []