BOAST 1.3.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/BOAST.gemspec +1 -1
- data/LICENSE +13 -1
- data/README.md +62 -13
- data/lib/BOAST.rb +3 -1
- data/lib/BOAST/Language/ARMCPUID_by_name.rb +3752 -0
- data/lib/BOAST/Language/Algorithm.rb +4 -24
- data/lib/BOAST/Language/Architectures.rb +5 -0
- data/lib/BOAST/Language/Arithmetic.rb +38 -5
- data/lib/BOAST/Language/BOAST_OpenCL.rb +7 -8
- data/lib/BOAST/Language/Case.rb +10 -3
- data/lib/BOAST/Language/Config.rb +36 -12
- data/lib/BOAST/Language/ControlStructure.rb +7 -3
- data/lib/BOAST/Language/DataTypes.rb +6 -0
- data/lib/BOAST/Language/Expression.rb +26 -2
- data/lib/BOAST/Language/For.rb +59 -30
- data/lib/BOAST/Language/FuncCall.rb +9 -5
- data/lib/BOAST/Language/Functors.rb +1 -1
- data/lib/BOAST/Language/HighLevelOperators.rb +172 -0
- data/lib/BOAST/Language/If.rb +25 -9
- data/lib/BOAST/Language/Index.rb +5 -5
- data/lib/BOAST/Language/Intrinsics.rb +40 -27
- data/lib/BOAST/Language/OpenMP.rb +1 -0
- data/lib/BOAST/Language/Operators.rb +221 -34
- data/lib/BOAST/Language/Parens.rb +3 -2
- data/lib/BOAST/Language/Procedure.rb +18 -5
- data/lib/BOAST/Language/Slice.rb +176 -44
- data/lib/BOAST/Language/Variable.rb +99 -56
- data/lib/BOAST/Language/While.rb +18 -3
- data/lib/BOAST/Language/{CPUID_by_name.rb → X86CPUID_by_name.rb} +0 -0
- data/lib/BOAST/Optimization/Optimization.rb +2 -0
- data/lib/BOAST/Runtime/AffinityProbe.rb +7 -3
- data/lib/BOAST/Runtime/CKernel.rb +3 -0
- data/lib/BOAST/Runtime/CRuntime.rb +4 -0
- data/lib/BOAST/Runtime/CompiledRuntime.rb +404 -77
- data/lib/BOAST/Runtime/Compilers.rb +44 -18
- data/lib/BOAST/Runtime/Config.rb +9 -0
- data/lib/BOAST/Runtime/EnergyProbe.rb +19 -3
- data/lib/BOAST/Runtime/FFIRuntime.rb +23 -0
- data/lib/BOAST/Runtime/FORTRANRuntime.rb +1 -1
- data/lib/BOAST/Runtime/MAQAO.rb +29 -0
- data/lib/BOAST/Runtime/NonRegression.rb +64 -3
- data/lib/BOAST/Runtime/OpenCLRuntime.rb +16 -6
- data/lib/BOAST/Runtime/Probe.rb +21 -1
- metadata +5 -3
@@ -6,12 +6,13 @@ module BOAST
|
|
6
6
|
|
7
7
|
def register_funccall(name, options = {})
|
8
8
|
sym = name.to_sym
|
9
|
+
ret = options[:return] ? options[:return] : options[:returns]
|
9
10
|
FUNCCALLS[sym] = {}
|
10
11
|
FUNCCALLS[sym][:parameters] = options[:parameters]
|
11
|
-
FUNCCALLS[sym][:
|
12
|
+
FUNCCALLS[sym][:return] = ret
|
12
13
|
s =<<EOF
|
13
14
|
def self.#{name}(*args)
|
14
|
-
return FuncCall(#{sym.inspect}, *args#{
|
15
|
+
return FuncCall(#{sym.inspect}, *args#{ ret ? ", return: FUNCCALLS[#{sym.inspect}][:return]" : ""})
|
15
16
|
end
|
16
17
|
EOF
|
17
18
|
eval s
|
@@ -20,7 +20,8 @@ module BOAST
|
|
20
20
|
# @param [Hash] properties set of named properties for the Procedure.
|
21
21
|
# @option properties [Array<Variables>] :constants list of constant variables that are used in the Procedure. (see parameter in Fortran).
|
22
22
|
# @option properties [Array<#to_s>] :headers list of headers that need to be included in order to compile the Procedure
|
23
|
-
# @option
|
23
|
+
# @option properties [Variable] :return a Variable that will be returned. Procedure becomes a function, return type is the same as the returned variable. The variable will be declared at the start of the procedure.
|
24
|
+
# @option properties [Procedure] :functions sub functions used by this Procedure (FORTRAN return type of functions are problematic)
|
24
25
|
def initialize(name, parameters=[], properties={}, &block)
|
25
26
|
@name = name
|
26
27
|
@parameters = parameters
|
@@ -42,8 +43,8 @@ module BOAST
|
|
42
43
|
|
43
44
|
def call(*parameters)
|
44
45
|
prefix = ""
|
45
|
-
prefix += "call " if lang==FORTRAN
|
46
|
-
f = FuncCall::new(@name, *parameters)
|
46
|
+
prefix += "call " if lang==FORTRAN and @properties[:return].nil?
|
47
|
+
f = FuncCall::new(@name, *parameters, :return => @properties[:return] )
|
47
48
|
f.prefix = prefix
|
48
49
|
return f
|
49
50
|
end
|
@@ -54,9 +55,9 @@ module BOAST
|
|
54
55
|
end
|
55
56
|
|
56
57
|
# Returns a {CKernel} with the Procedure as entry point.
|
57
|
-
def ckernel
|
58
|
+
def ckernel(* args)
|
58
59
|
old_output = output
|
59
|
-
k = CKernel::new
|
60
|
+
k = CKernel::new(* args)
|
60
61
|
k.procedure = self
|
61
62
|
self.pr
|
62
63
|
set_output( old_output )
|
@@ -87,6 +88,13 @@ module BOAST
|
|
87
88
|
return to_s_fortran if lang==FORTRAN
|
88
89
|
end
|
89
90
|
|
91
|
+
protected
|
92
|
+
|
93
|
+
def fortran_type
|
94
|
+
raise "No return type for procedure!" unless @properties[:return]
|
95
|
+
output.puts indent + "#{@properties[:return].type.decl} :: #{@name}"
|
96
|
+
end
|
97
|
+
|
90
98
|
private
|
91
99
|
|
92
100
|
def decl_fortran
|
@@ -209,6 +217,11 @@ module BOAST
|
|
209
217
|
align = p.align
|
210
218
|
BOAST::pr align if align
|
211
219
|
}
|
220
|
+
if @properties[:functions] then
|
221
|
+
@properties[:functions].each { |f|
|
222
|
+
f.fortran_type
|
223
|
+
}
|
224
|
+
end
|
212
225
|
if @properties[:return] then
|
213
226
|
BOAST::decl @properties[:return]
|
214
227
|
end
|
data/lib/BOAST/Language/Slice.rb
CHANGED
@@ -1,16 +1,123 @@
|
|
1
1
|
module BOAST
|
2
2
|
|
3
|
-
class Slice
|
4
|
-
|
5
|
-
|
3
|
+
class Slice < Expression
|
4
|
+
class SliceItem
|
5
|
+
include PrivateStateAccessor
|
6
|
+
include Inspectable
|
7
|
+
|
8
|
+
attr_reader :first
|
9
|
+
attr_reader :last
|
10
|
+
attr_reader :step
|
11
|
+
attr_reader :length
|
12
|
+
|
13
|
+
def all?
|
14
|
+
@first.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def scalar?
|
18
|
+
not all? and @last.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(slice)
|
22
|
+
@first = nil
|
23
|
+
@last = nil
|
24
|
+
@step = nil
|
25
|
+
if slice.kind_of?(SliceItem) then
|
26
|
+
copy_slice!(slice)
|
27
|
+
elsif slice.kind_of?(Range) then
|
28
|
+
@first = slice.first
|
29
|
+
@last = slice.last
|
30
|
+
@last = Expression::new(Subtraction, @last, 1) if slice.exclude_end?
|
31
|
+
@length = Expression::new(Subtraction, @last, @first)
|
32
|
+
@length = @length + 1
|
33
|
+
elsif slice.kind_of?(Array) then
|
34
|
+
@first = slice [0] if slice.length > 0
|
35
|
+
@last = slice [1] if slice.length > 1
|
36
|
+
@step = slice [2] if slice.length > 2
|
37
|
+
@length = Expression::new(Subtraction, @last, @first)
|
38
|
+
@length = @length / @step if @step
|
39
|
+
@length = @length + 1
|
40
|
+
elsif slice.kind_of?(Symbol) then
|
41
|
+
raise "Invalid Slice item: #{slice.inspect}!" if slice != :all
|
42
|
+
else
|
43
|
+
@first = slice
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def copy_slice!(slice)
|
48
|
+
@first = slice.first
|
49
|
+
@last = slice.last
|
50
|
+
@step = slice.step
|
51
|
+
@length = slice.length
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def recurse!(s, d)
|
56
|
+
if all? then
|
57
|
+
copy_slice!(s)
|
58
|
+
else
|
59
|
+
@first = Expression::new(Subtraction, @first, get_array_start)
|
60
|
+
@first = @first * s.step if s.step
|
61
|
+
if s.all? then
|
62
|
+
@first = Expression::new(Addition, d.start, @first )
|
63
|
+
else
|
64
|
+
@first = Expression::new(Addition, s.first, @first )
|
65
|
+
end
|
66
|
+
if not scalar? then
|
67
|
+
if s.step then
|
68
|
+
if @step then
|
69
|
+
@step = Expression::new(Multiplication, @step, s.step)
|
70
|
+
else
|
71
|
+
@step = s.step
|
72
|
+
end
|
73
|
+
end
|
74
|
+
@last = @first + (@length-1)*@step
|
75
|
+
end
|
76
|
+
end
|
77
|
+
return self
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_a
|
81
|
+
a = []
|
82
|
+
a.push @first if @first
|
83
|
+
a.push @last if @last
|
84
|
+
a.push @step if @step
|
85
|
+
return a
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
6
90
|
attr_reader :source
|
7
91
|
attr_reader :slices
|
92
|
+
attr_accessor :alignment
|
8
93
|
|
9
94
|
def initialize(source, *slices)
|
10
95
|
raise "Cannot slice a non array Variable!" if not source.dimension?
|
11
96
|
raise "Invalid slice!" if slices.length != source.dimension.length
|
12
97
|
@source = source
|
13
|
-
@slices = slices
|
98
|
+
@slices = slices.collect{ |s| SliceItem::new(s) }
|
99
|
+
end
|
100
|
+
|
101
|
+
def dimension?
|
102
|
+
true
|
103
|
+
end
|
104
|
+
|
105
|
+
def dimension
|
106
|
+
dims = []
|
107
|
+
slices.each_with_index { |slice, i|
|
108
|
+
if not slice.scalar? then
|
109
|
+
if slice.all? then
|
110
|
+
if source.dimension[i].size then
|
111
|
+
dims.push Dimension::new( source.dimension[i].size )
|
112
|
+
else
|
113
|
+
dims.push Dimension::new
|
114
|
+
end
|
115
|
+
else
|
116
|
+
dims.push Dimension::new( slice.length )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
}
|
120
|
+
return dims
|
14
121
|
end
|
15
122
|
|
16
123
|
def to_s
|
@@ -27,60 +134,85 @@ module BOAST
|
|
27
134
|
return self
|
28
135
|
end
|
29
136
|
|
137
|
+
def align?
|
138
|
+
return !!@alignment
|
139
|
+
end
|
140
|
+
|
141
|
+
def set_align(align)
|
142
|
+
@alignment = align
|
143
|
+
return self
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_var
|
147
|
+
var = @source.copy("#{self}", :const => nil, :constant => nil, :dim => nil, :dimension => nil, :direction => nil, :dir => nil, :align => alignment)
|
148
|
+
return var
|
149
|
+
end
|
150
|
+
|
151
|
+
# Indexes a {Slice}
|
152
|
+
# @param [Array{#to_s, Range, [first, last, step], :all, nil}] args one entry for each {SliceItem} of the {Slice}.
|
153
|
+
# * Range: if an index is a Range, the result will be a {Slice}. The Range can be exclusive. The first and last item of the Range will be considered first and last index in the corresponding {SliceItem}.
|
154
|
+
# * [first, last, step]: if an index is an Array, the result will be a {Slice}. The first and last item of the array will be considered first and last index in the corresponding {SliceItem}. If a step is given the range will be iterated by step.
|
155
|
+
# * :all, nil: The whole corresponding {SliceItem} will be used for the slice.
|
156
|
+
# * #to_s: If an index is none of the above it will be considered a scalar index. If all indexes are scalar an {Index} will be returned.
|
157
|
+
# @return [Slice, Index]
|
158
|
+
def [](*args)
|
159
|
+
slice = false
|
160
|
+
args.each { |a|
|
161
|
+
slice = true if a.kind_of?(Range) or a.kind_of?(Array) or a.kind_of?(Symbol) or a.nil?
|
162
|
+
}
|
163
|
+
new_args = []
|
164
|
+
slices.each_with_index { |s, i|
|
165
|
+
if not s.scalar?
|
166
|
+
raise "Invalid slice!" if args.length == 0
|
167
|
+
new_arg = SliceItem::new(args.shift)
|
168
|
+
new_arg.recurse!(s, @source.dimension[i])
|
169
|
+
new_args.push new_arg
|
170
|
+
else
|
171
|
+
new_args.push s
|
172
|
+
end
|
173
|
+
}
|
174
|
+
if slice then
|
175
|
+
return Slice::new(@source, *new_args)
|
176
|
+
else
|
177
|
+
return Index::new(@source, *(new_args.collect(&:first)))
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
30
181
|
private
|
31
182
|
|
32
183
|
def to_s_c
|
33
|
-
s = "#{@source}["
|
34
184
|
dims = @source.dimension.reverse
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
slice = slices[indx]
|
39
|
-
if slice.kind_of?(Array) then
|
40
|
-
if slice.length == 0 then
|
41
|
-
slices_to_c.push(":")
|
42
|
-
elsif slice.length == 1 then
|
43
|
-
slices_to_c.push("#{Expression::new(Substraction, slice[0], dims[indx].start)}")
|
44
|
-
else
|
45
|
-
start, finish, step = slice
|
46
|
-
start_c = Expression::new(Substraction, start, dims[indx].start)
|
47
|
-
length = Expression::new(Substraction, finish, start) + 1
|
48
|
-
slices_to_c.push("#{start_c}:#{length}")
|
49
|
-
end
|
50
|
-
elsif slice.kind_of?(Range) then
|
51
|
-
start = slice.first
|
52
|
-
finish = slice.last
|
53
|
-
start_c = Expression::new(Substraction, start, dims[indx].start)
|
54
|
-
length = Expression::new(Substraction, finish, start)
|
55
|
-
length = length + 1 unless slice.exclude_end?
|
56
|
-
slices_to_c.push("#{start_c}:#{length}")
|
57
|
-
elsif slice then
|
58
|
-
slices_to_c.push("#{Expression::new(Substraction, slice, dims[indx].start)}")
|
185
|
+
slices_to_c = @slices.reverse.each_with_index.collect { |slice, indx|
|
186
|
+
if slice.all? then
|
187
|
+
":"
|
59
188
|
else
|
60
|
-
|
189
|
+
start = Expression::new(Subtraction, slice.first, dims[indx].start)
|
190
|
+
s = "#{start}"
|
191
|
+
if not slice.scalar? then
|
192
|
+
s += ":#{slice.length}"
|
193
|
+
# s += ":#{slice.step}" if slice.step
|
194
|
+
raise "Slice don't support step in C!" if slice.step
|
195
|
+
end
|
196
|
+
s
|
61
197
|
end
|
62
198
|
}
|
63
|
-
return
|
199
|
+
return "#{@source}[#{slices_to_c.join("][")}]"
|
64
200
|
end
|
65
201
|
|
66
202
|
def to_s_fortran
|
67
203
|
slices_to_fortran = @slices.collect { |slice|
|
68
|
-
if slice then
|
69
|
-
if slice.kind_of?(Range) then
|
70
|
-
"#{slice.first}:#{slice.last}#{slice.exclude_end? ? " - 1" : "" }"
|
71
|
-
else
|
72
|
-
sl = [slice].flatten
|
73
|
-
if sl.length > 0 then
|
74
|
-
sl.join(":")
|
75
|
-
else
|
76
|
-
":"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
else
|
204
|
+
if slice.all? then
|
80
205
|
":"
|
206
|
+
else
|
207
|
+
s = "#{slice.first}"
|
208
|
+
if not slice.scalar? then
|
209
|
+
s += ":#{slice.last}"
|
210
|
+
s += ":#{slice.step}" if slice.step
|
211
|
+
end
|
212
|
+
s
|
81
213
|
end
|
82
214
|
}
|
83
|
-
return "#{source}(#{slices_to_fortran.join(",")})"
|
215
|
+
return "#{@source}(#{slices_to_fortran.join(", ")})"
|
84
216
|
end
|
85
217
|
|
86
218
|
end
|
@@ -26,7 +26,7 @@ module BOAST
|
|
26
26
|
begin
|
27
27
|
@size = v2-v1+1
|
28
28
|
rescue
|
29
|
-
@size = Expression::new(
|
29
|
+
@size = Expression::new(Subtraction, v2, v1) + 1
|
30
30
|
end
|
31
31
|
else
|
32
32
|
@size = v1
|
@@ -149,21 +149,22 @@ module BOAST
|
|
149
149
|
include Annotation
|
150
150
|
ANNOTATIONS = [ :name, :type, :dimension ]
|
151
151
|
|
152
|
-
alias_method :orig_method_missing, :method_missing
|
153
|
-
|
154
152
|
def method_missing(m, *a, &b)
|
155
153
|
if @type.methods.include?(:members) and @type.members[m.to_s] then
|
156
154
|
return struct_reference(type.members[m.to_s])
|
157
|
-
elsif
|
155
|
+
elsif __vector? and m.to_s[0] == 's' and lang != CUDA then
|
158
156
|
required_set = m.to_s[1..-1].chars.to_a
|
159
157
|
existing_set = [*('0'..'9'),*('a'..'z')].first(@type.vector_length)
|
160
158
|
if required_set.length == required_set.uniq.length and (required_set - existing_set).empty? then
|
161
|
-
return copy(name+"."+m.to_s, :vector_length => m.to_s[1..-1].length)
|
159
|
+
return copy(name+"."+m.to_s, :vector_length => m.to_s[1..-1].length) if lang == CL
|
160
|
+
return copy("#{name}(#{existing_set.index(required_set[0])+1})", :vector_length => 1) if lang == FORTRAN
|
161
|
+
return copy("#{name}[#{existing_set.index(required_set[0])}]", :vector_length => 1) if lang == C
|
162
|
+
super
|
162
163
|
else
|
163
|
-
|
164
|
+
super
|
164
165
|
end
|
165
166
|
else
|
166
|
-
|
167
|
+
super
|
167
168
|
end
|
168
169
|
end
|
169
170
|
|
@@ -180,60 +181,69 @@ module BOAST
|
|
180
181
|
attr_reader :deferred_shape
|
181
182
|
attr_reader :optional
|
182
183
|
attr_accessor :reference
|
183
|
-
|
184
|
+
attr_writer :alignment
|
184
185
|
attr_accessor :replace_constant
|
185
186
|
attr_accessor :force_replace_constant
|
186
187
|
|
188
|
+
def alignment
|
189
|
+
return @type.total_size if __vector? and lang == FORTRAN and not @alignment
|
190
|
+
return @alignment
|
191
|
+
end
|
192
|
+
|
187
193
|
def constant?
|
188
|
-
|
194
|
+
@constant
|
189
195
|
end
|
190
196
|
|
191
197
|
def allocate?
|
192
|
-
|
198
|
+
@allocate
|
193
199
|
end
|
194
200
|
|
195
201
|
def texture?
|
196
|
-
|
202
|
+
@texture
|
197
203
|
end
|
198
204
|
|
199
205
|
def local?
|
200
|
-
|
206
|
+
@local
|
201
207
|
end
|
202
208
|
|
203
209
|
def restrict?
|
204
|
-
|
210
|
+
@restrict
|
205
211
|
end
|
206
212
|
|
207
213
|
def replace_constant?
|
208
|
-
|
214
|
+
@replace_constant
|
209
215
|
end
|
210
216
|
|
211
217
|
def force_replace_constant?
|
212
|
-
|
218
|
+
@force_replace_constant
|
213
219
|
end
|
214
220
|
|
215
221
|
def dimension?
|
216
|
-
|
222
|
+
@dimension
|
217
223
|
end
|
218
224
|
|
219
225
|
def scalar_output?
|
220
|
-
|
226
|
+
@scalar_output
|
221
227
|
end
|
222
228
|
|
223
229
|
def optional?
|
224
|
-
|
230
|
+
@optional
|
225
231
|
end
|
226
232
|
|
227
233
|
def align?
|
228
|
-
|
234
|
+
alignment
|
229
235
|
end
|
230
236
|
|
231
237
|
def deferred_shape?
|
232
|
-
|
238
|
+
@deferred_shape
|
233
239
|
end
|
234
240
|
|
235
241
|
def reference?
|
236
|
-
|
242
|
+
@reference
|
243
|
+
end
|
244
|
+
|
245
|
+
def vector?
|
246
|
+
__vector?
|
237
247
|
end
|
238
248
|
|
239
249
|
# Creates a new {Variable}
|
@@ -248,16 +258,24 @@ module BOAST
|
|
248
258
|
# @option properties [Symbol] :allocate specify that the variable is to be allocated and where. Can only be *:heap* or *:stack* for now.
|
249
259
|
# @option properties [Boolean] :local indicates that the variable is to be allocated on the __local space of OpenCL devices or __shared__ space of CUDA devices. In C or FORTRAN this has the same effect as *:allocate* => *:stack*.
|
250
260
|
# @option properties [Boolean] :texture for OpenCL and CUDA. In OpenCL also specifies that a sampler has to be generated to access the array variable.
|
251
|
-
# @option properties [Integer] :align specifies the alignment the variable will be declared/allocated with if allocated or is supposed to have if it is coming from another context.
|
261
|
+
# @option properties [Integer] :align specifies the alignment the variable will be declared/allocated with if allocated or is supposed to have if it is coming from another context (in bytes).
|
252
262
|
# @option properties [Boolean] :replace_constant specifies that for scalar constants this variable should be replaced by its constant value. For constant arrays, the value of the array will be replaced if the index can be determined at evaluation.
|
253
263
|
# @option properties [Boolean] :deferred_shape for Fortran interface generation mainly see Fortran documentation
|
254
264
|
# @option properties [Boolean] :optional for Fortran interface generation mainly see Fortran documentation
|
255
265
|
def initialize(name, type, properties={})
|
256
266
|
@name = name.to_s
|
257
|
-
@direction = properties[:direction]
|
258
|
-
@
|
259
|
-
|
260
|
-
@
|
267
|
+
@direction = properties[:direction]
|
268
|
+
@direction = properties[:dir] unless @direction
|
269
|
+
|
270
|
+
@constant = properties[:constant]
|
271
|
+
@constant = properties[:const] unless @constant
|
272
|
+
|
273
|
+
@dimension = properties[:dimension]
|
274
|
+
@dimension = properties[:dim] unless @dimension
|
275
|
+
|
276
|
+
@local = properties[:local]
|
277
|
+
@local = properties[:shared] unless @local
|
278
|
+
|
261
279
|
@texture = properties[:texture]
|
262
280
|
@allocate = properties[:allocate]
|
263
281
|
@restrict = properties[:restrict]
|
@@ -266,24 +284,23 @@ module BOAST
|
|
266
284
|
@optional = properties[:optional]
|
267
285
|
@reference = properties[:reference]
|
268
286
|
@force_replace_constant = false
|
269
|
-
|
270
|
-
|
271
|
-
else
|
272
|
-
@replace_constant = true
|
273
|
-
end
|
287
|
+
@replace_constant = properties[:replace_constant]
|
288
|
+
|
274
289
|
if @texture and lang == CL then
|
275
290
|
@sampler = Variable::new("sampler_#{name}", CustomType,:type_name => "sampler_t" ,:replace_constant => false, :constant => "CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST")
|
276
291
|
else
|
277
292
|
@sampler = nil
|
278
293
|
end
|
279
|
-
|
280
|
-
@
|
281
|
-
if
|
282
|
-
@
|
294
|
+
|
295
|
+
@scalar_output = false
|
296
|
+
if @dimension then
|
297
|
+
@dimension = [@dimension].flatten
|
283
298
|
else
|
284
|
-
@scalar_output =
|
299
|
+
@scalar_output = true if @direction == :out or @direction == :inout
|
285
300
|
end
|
286
|
-
|
301
|
+
|
302
|
+
@type = type::new(properties)
|
303
|
+
@properties = properties
|
287
304
|
end
|
288
305
|
|
289
306
|
def copy(name=nil,properties={})
|
@@ -343,8 +360,23 @@ module BOAST
|
|
343
360
|
return Expression::new("++",self,nil)
|
344
361
|
end
|
345
362
|
|
363
|
+
# Indexes a {Variable} with the :dimension (or :dim) property set
|
364
|
+
# @param [Array{#to_s, Range, [first, last, step], :all, nil}] args one entry for each {Dimension} of the {Variable}.
|
365
|
+
# * Range: if an index is a Range, the result will be a {Slice}. The Range can be exclusive. The first and last item of the Range will be considered first and last index in the corresponding {Dimension}.
|
366
|
+
# * [first, last, step]: if an index is an Array, the result will be a {Slice}. The first and last item of the array will be considered first and last index in the corresponding {Dimension}. If a step is given the range will be iterated by step.
|
367
|
+
# * :all, nil: The whole dimension will be used for the slice. But indexing will start at #get_array_start instead of the original index.
|
368
|
+
# * #to_s: If an index is none of the above it will be considered a scalar index. If all indexes are scalar an {Index} will be returned.
|
369
|
+
# @return [Slice, Index]
|
346
370
|
def [](*args)
|
347
|
-
|
371
|
+
slice = false
|
372
|
+
args.each { |a|
|
373
|
+
slice = true if a.kind_of?(Range) or a.kind_of?(Array) or a.kind_of?(Symbol) or a.nil?
|
374
|
+
}
|
375
|
+
if slice then
|
376
|
+
return Slice::new(self, *args)
|
377
|
+
else
|
378
|
+
return Index::new(self, *args)
|
379
|
+
end
|
348
380
|
end
|
349
381
|
|
350
382
|
def boast_header(lang=C)
|
@@ -389,6 +421,8 @@ module BOAST
|
|
389
421
|
return align_c(a) if lang == C
|
390
422
|
return align_fortran(a) if lang == FORTRAN
|
391
423
|
end
|
424
|
+
elsif vector? then
|
425
|
+
return align_fortran(alignment) if lang == FORTRAN
|
392
426
|
end
|
393
427
|
return nil
|
394
428
|
end
|
@@ -409,43 +443,47 @@ module BOAST
|
|
409
443
|
private
|
410
444
|
|
411
445
|
def __const?
|
412
|
-
return
|
446
|
+
return ( constant? or @direction == :in )
|
413
447
|
end
|
414
448
|
|
415
449
|
def __global?
|
416
|
-
return
|
450
|
+
return ( lang == CL and @direction and dimension? and not (@properties[:register] or @properties[:private] or local?) )
|
417
451
|
end
|
418
452
|
|
419
453
|
def __local?
|
420
|
-
return
|
454
|
+
return ( lang == CL and local? )
|
421
455
|
end
|
422
456
|
|
423
457
|
def __shared?(device = false)
|
424
|
-
return
|
458
|
+
return ( lang == CUDA and local? and not device )
|
425
459
|
end
|
426
460
|
|
427
461
|
def __vla_array?
|
428
|
-
return
|
462
|
+
return ( use_vla? and dimension? and not decl_module? )
|
429
463
|
end
|
430
464
|
|
431
465
|
def __pointer_array?(device = false)
|
432
|
-
return
|
466
|
+
return ( dimension? and not constant? and not ( allocate? and @allocate != :heap ) and (not local? or (local? and device)) )
|
433
467
|
end
|
434
468
|
|
435
469
|
def __pointer?(device = false)
|
436
|
-
return
|
470
|
+
return ( ( not dimension? and ( @direction == :out or @direction == :inout or @reference ) ) or __pointer_array?(device) )
|
437
471
|
end
|
438
472
|
|
439
473
|
def __restrict?
|
440
|
-
return
|
474
|
+
return ( restrict? and not decl_module? )
|
441
475
|
end
|
442
476
|
|
443
477
|
def __dimension?(device = false)
|
444
|
-
return
|
478
|
+
return ( dimension? and ((local? and not device) or ( ( allocate? and @allocate != :heap ) and not constant?)) )
|
445
479
|
end
|
446
480
|
|
447
481
|
def __align?
|
448
|
-
return
|
482
|
+
return ( dimension? and (align? or default_align > 1) and (constant? or (allocate? and @allocate != :heap ) ) )
|
483
|
+
end
|
484
|
+
|
485
|
+
def __vector?
|
486
|
+
return ( @type.vector? and @type.vector_length > 1 )
|
449
487
|
end
|
450
488
|
|
451
489
|
def decl_c_s(device = false)
|
@@ -531,18 +569,19 @@ module BOAST
|
|
531
569
|
return Pragma::new("DIR", "ASSUME_ALIGNED", "#{@name}: #{a}")
|
532
570
|
end
|
533
571
|
|
534
|
-
def alloc_fortran( dims
|
572
|
+
def alloc_fortran( dims )
|
573
|
+
dims.unshift( @type.vector_length ) if __vector?
|
535
574
|
return FuncCall::new(:allocate, FuncCall(name, * dims ) )
|
536
575
|
end
|
537
576
|
|
538
|
-
def alloc_c( dims
|
539
|
-
|
577
|
+
def alloc_c( dims, align = get_address_size)
|
578
|
+
ds = dims.collect { |d| d.to_s }.reverse.join(")*(")
|
540
579
|
if align > (OS.bits/8) then
|
541
580
|
# check alignment is a power of 2
|
542
581
|
raise "Invalid alignment #{align}!" if align & (align - 1) != 0
|
543
|
-
return FuncCall::new(:posix_memalign, address, align, FuncCall::new(:sizeof, @type.decl) *
|
582
|
+
return FuncCall::new(:posix_memalign, address, align, FuncCall::new(:sizeof, @type.decl) * ds)
|
544
583
|
else
|
545
|
-
return self === FuncCall::new(:malloc, FuncCall::new(:sizeof, @type.decl) *
|
584
|
+
return self === FuncCall::new(:malloc, FuncCall::new(:sizeof, @type.decl) * ds).cast(self)
|
546
585
|
end
|
547
586
|
end
|
548
587
|
|
@@ -562,15 +601,19 @@ module BOAST
|
|
562
601
|
s += ", optional" if optional?
|
563
602
|
s += ", allocatable" if allocate? and @allocate == :heap
|
564
603
|
s += ", parameter" if constant?
|
565
|
-
if dimension? then
|
604
|
+
if dimension? or __vector? then
|
566
605
|
s += ", dimension("
|
606
|
+
if __vector? then
|
607
|
+
s += "#{@type.vector_length}"
|
608
|
+
s += ", " if dimension?
|
609
|
+
end
|
567
610
|
s += @dimension.collect { |d|
|
568
611
|
if deferred_shape? or ( allocate? and @allocate == :heap )
|
569
612
|
":"
|
570
613
|
else
|
571
614
|
d.to_s
|
572
615
|
end
|
573
|
-
}.join(", ")
|
616
|
+
}.join(", ") if dimension?
|
574
617
|
s += ")"
|
575
618
|
end
|
576
619
|
s += " :: #{@name}"
|
@@ -581,7 +624,7 @@ module BOAST
|
|
581
624
|
end
|
582
625
|
s += finalize
|
583
626
|
output.print s
|
584
|
-
if dimension? and (align? or default_align > 1) and (constant? or ( allocate? and @allocate != :heap ) ) then
|
627
|
+
if ( dimension? and (align? or default_align > 1) and (constant? or ( allocate? and @allocate != :heap ) ) ) or ( vector? and not @direction ) then
|
585
628
|
a = ( align? ? alignment : 1 )
|
586
629
|
a = ( a >= default_align ? a : default_align )
|
587
630
|
s = ""
|