BOAST 1.0.9 → 1.1.0
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.
- checksums.yaml +4 -4
- data/BOAST.gemspec +1 -1
- data/lib/BOAST.rb +5 -1
- data/lib/BOAST/Language/Algorithm.rb +104 -22
- data/lib/BOAST/Language/Annotation.rb +55 -0
- data/lib/BOAST/Language/Arithmetic.rb +44 -10
- data/lib/BOAST/Language/Case.rb +89 -52
- data/lib/BOAST/Language/CodeBlock.rb +17 -0
- data/lib/BOAST/Language/Comment.rb +38 -0
- data/lib/BOAST/Language/ControlStructure.rb +7 -0
- data/lib/BOAST/Language/Error.rb +7 -0
- data/lib/BOAST/Language/Expression.rb +4 -5
- data/lib/BOAST/Language/For.rb +59 -27
- data/lib/BOAST/Language/If.rb +12 -17
- data/lib/BOAST/Language/Index.rb +5 -5
- data/lib/BOAST/Language/Intrinsics.rb +38 -32
- data/lib/BOAST/Language/OpenMP.rb +1 -1
- data/lib/BOAST/Language/Operators.rb +208 -53
- data/lib/BOAST/Language/Pragma.rb +3 -3
- data/lib/BOAST/Language/Print.rb +3 -3
- data/lib/BOAST/Language/Procedure.rb +15 -8
- data/lib/BOAST/Language/Variable.rb +45 -87
- data/lib/BOAST/Language/While.rb +3 -0
- data/lib/BOAST/Optimization/Optimization.rb +241 -0
- metadata +7 -4
- data/lib/BOAST/Language/Optimization.rb +0 -74
- data/lib/BOAST/Language/Vector.rb +0 -6
@@ -0,0 +1,38 @@
|
|
1
|
+
module BOAST
|
2
|
+
|
3
|
+
class Comment
|
4
|
+
extend Functor
|
5
|
+
include PrivateStateAccessor
|
6
|
+
include Inspectable
|
7
|
+
attr_reader :comment
|
8
|
+
|
9
|
+
def initialize(string)
|
10
|
+
@comment = string
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s_fortran
|
14
|
+
s = ""
|
15
|
+
@comment.each_line { |l| s += "! #{l}" }
|
16
|
+
return s
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s_c
|
20
|
+
s = ""
|
21
|
+
@comment.each_line { |l| s += "/* #{l.delete("\n")} */\n" }
|
22
|
+
return s
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
return to_s_fortran if get_lang == FORTRAN
|
27
|
+
return to_s_c if [C,CL,CUDA].include?(get_lang)
|
28
|
+
end
|
29
|
+
|
30
|
+
def pr
|
31
|
+
s = to_s
|
32
|
+
output.puts s
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -4,6 +4,8 @@ module BOAST
|
|
4
4
|
include PrivateStateAccessor
|
5
5
|
include Inspectable
|
6
6
|
|
7
|
+
attr_accessor :args
|
8
|
+
|
7
9
|
def self.inherited(child)
|
8
10
|
child.extend Functor
|
9
11
|
end
|
@@ -23,6 +25,11 @@ module BOAST
|
|
23
25
|
EOF
|
24
26
|
end
|
25
27
|
|
28
|
+
def [](*args)
|
29
|
+
@args = args
|
30
|
+
return self
|
31
|
+
end
|
32
|
+
|
26
33
|
end
|
27
34
|
|
28
35
|
end
|
@@ -2,16 +2,15 @@ module BOAST
|
|
2
2
|
|
3
3
|
module_function
|
4
4
|
|
5
|
-
def Return(value)
|
6
|
-
return Expression("return",nil, value)
|
7
|
-
end
|
8
|
-
|
9
5
|
class Expression
|
10
6
|
include PrivateStateAccessor
|
11
7
|
include Arithmetic
|
12
8
|
include Inspectable
|
13
9
|
extend Functor
|
14
10
|
include TypeTransition
|
11
|
+
include Annotation
|
12
|
+
|
13
|
+
ANNOTATIONS = [:operator, :operand1, :operand2]
|
15
14
|
|
16
15
|
attr_reader :operator
|
17
16
|
attr_reader :operand1
|
@@ -23,7 +22,7 @@ module BOAST
|
|
23
22
|
end
|
24
23
|
|
25
24
|
def to_s_base(op1, op2, oper, return_type = nil)
|
26
|
-
return oper.
|
25
|
+
return oper.string(op1, op2, return_type) unless oper.kind_of?(String)
|
27
26
|
s = ""
|
28
27
|
if op1 then
|
29
28
|
s += "(" if (oper == "*" or oper == "/")
|
data/lib/BOAST/Language/For.rb
CHANGED
@@ -1,15 +1,27 @@
|
|
1
1
|
module BOAST
|
2
2
|
|
3
3
|
class For < ControlStructure
|
4
|
+
include Annotation
|
5
|
+
ANNOTATIONS = [ :iterator, :begin, :end, :step, :operator ]
|
4
6
|
|
5
7
|
attr_reader :iterator
|
6
8
|
attr_reader :begin
|
7
9
|
attr_reader :end
|
8
10
|
attr_reader :step
|
11
|
+
attr_accessor :block
|
12
|
+
|
13
|
+
def unroll?
|
14
|
+
return !!@unroll
|
15
|
+
end
|
16
|
+
|
17
|
+
def unroll=(val)
|
18
|
+
@unroll = val
|
19
|
+
end
|
9
20
|
|
10
21
|
def initialize(i, b, e, options={}, &block)
|
11
22
|
default_options = {:step => 1}
|
12
23
|
default_options.update( options )
|
24
|
+
@options = options
|
13
25
|
@iterator = i
|
14
26
|
@begin = b
|
15
27
|
@end = e
|
@@ -17,6 +29,8 @@ module BOAST
|
|
17
29
|
@operator = "<="
|
18
30
|
@block = block
|
19
31
|
@openmp = default_options[:openmp]
|
32
|
+
@unroll = default_options[:unroll]
|
33
|
+
@args = default_options[:args]
|
20
34
|
if @openmp then
|
21
35
|
if @openmp.kind_of?(Hash) then
|
22
36
|
@openmp = OpenMP::For(@openmp)
|
@@ -62,39 +76,55 @@ module BOAST
|
|
62
76
|
return s
|
63
77
|
end
|
64
78
|
|
65
|
-
def
|
79
|
+
# def u(s = 2)
|
80
|
+
# return [For::new(@iterator, @begin, @end - (@step*s - 1), @options.dup.update( { :step => (@step*s) } ), &@block),
|
81
|
+
# For::new(@iterator, @begin.to_var + ((@end - @begin + 1)/(@step*s))*(@step*s), @end, @options, &@block) ]
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
def unroll
|
85
|
+
opts = @options.clone
|
86
|
+
opts[:unroll] = true
|
87
|
+
return For::new(@iterator, @begin, @end, opts, &block)
|
88
|
+
end
|
89
|
+
|
90
|
+
def pr_unroll(*args)
|
66
91
|
raise "Block not given!" if not @block
|
67
|
-
push_env( :replace_constants => true )
|
68
92
|
begin
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
93
|
+
begin
|
94
|
+
push_env( :replace_constants => true )
|
95
|
+
if @begin.kind_of?(Variable) then
|
96
|
+
start = @begin.constant
|
97
|
+
elsif @begin.kind_of?(Expression) then
|
98
|
+
start = eval "#{@begin}"
|
99
|
+
else
|
100
|
+
start = @begin.to_i
|
101
|
+
end
|
102
|
+
if @end.kind_of?(Variable) then
|
103
|
+
e = @end.constant
|
104
|
+
elsif @end.kind_of?(Expression) then
|
105
|
+
e = eval "#{@end}"
|
106
|
+
else
|
107
|
+
e = @end.to_i
|
108
|
+
end
|
109
|
+
if @step.kind_of?(Variable) then
|
110
|
+
step = @step.constant
|
111
|
+
elsif @step.kind_of?(Expression) then
|
112
|
+
step = eval "#{@step}"
|
113
|
+
else
|
114
|
+
step = @step.to_i
|
115
|
+
end
|
116
|
+
raise "Invalid bounds (not constants)!" if not ( start and e and step )
|
117
|
+
ensure
|
118
|
+
pop_env( :replace_constants )
|
89
119
|
end
|
90
|
-
raise "Invalid bounds (not constants)!" if not ( start and e and step )
|
91
120
|
rescue Exception => ex
|
92
|
-
|
93
|
-
|
94
|
-
|
121
|
+
open
|
122
|
+
if @block then
|
123
|
+
@block.call(*args)
|
124
|
+
close
|
95
125
|
end
|
126
|
+
return self
|
96
127
|
end
|
97
|
-
pop_env( :replace_constants )
|
98
128
|
range = start..e
|
99
129
|
@iterator.force_replace_constant = true
|
100
130
|
range.step(step) { |i|
|
@@ -116,6 +146,8 @@ module BOAST
|
|
116
146
|
end
|
117
147
|
|
118
148
|
def pr(*args)
|
149
|
+
args = @args if args.length == 0 and @args
|
150
|
+
return pr_unroll(*args) if unroll?
|
119
151
|
open
|
120
152
|
if @block then
|
121
153
|
@block.call(*args)
|
data/lib/BOAST/Language/If.rb
CHANGED
@@ -5,24 +5,18 @@ module BOAST
|
|
5
5
|
attr_reader :conditions
|
6
6
|
|
7
7
|
def initialize(*conditions, &block)
|
8
|
+
raise "Illegal if construct!" if conditions.size == 0
|
9
|
+
conditions.push(block) if block
|
8
10
|
@conditions = []
|
9
11
|
@blocks = []
|
10
|
-
if conditions.size ==
|
11
|
-
|
12
|
-
elsif conditions.size == 1 then
|
13
|
-
@conditions.push(conditions[0])
|
14
|
-
@blocks.push(block)
|
15
|
-
elsif conditions.size.even? then
|
16
|
-
(0..conditions.size-1).step(2) { |i|
|
17
|
-
@conditions[i/2] = conditions[i]
|
18
|
-
@blocks[i/2] = conditions[i+1]
|
19
|
-
}
|
12
|
+
if conditions.size == 1 then
|
13
|
+
@conditions.push conditions.shift
|
20
14
|
else
|
21
|
-
|
22
|
-
@conditions
|
23
|
-
@blocks
|
24
|
-
|
25
|
-
@blocks.push
|
15
|
+
while conditions.size >= 2 do
|
16
|
+
@conditions.push conditions.shift
|
17
|
+
@blocks.push conditions.shift
|
18
|
+
end
|
19
|
+
@blocks.push conditions.shift if conditions.size > 0
|
26
20
|
end
|
27
21
|
end
|
28
22
|
|
@@ -63,7 +57,7 @@ module BOAST
|
|
63
57
|
end
|
64
58
|
|
65
59
|
def open
|
66
|
-
s=""
|
60
|
+
s = ""
|
67
61
|
s += indent
|
68
62
|
s += to_s
|
69
63
|
output.puts s
|
@@ -72,11 +66,12 @@ module BOAST
|
|
72
66
|
end
|
73
67
|
|
74
68
|
def pr(*args)
|
69
|
+
args = @args if args.length == 0 and @args
|
75
70
|
if @blocks.size > 0 then
|
76
71
|
increment_indent_level
|
77
72
|
@blocks.each_index { |indx|
|
78
73
|
decrement_indent_level
|
79
|
-
s=""
|
74
|
+
s = ""
|
80
75
|
s += indent
|
81
76
|
s += to_s(indx)
|
82
77
|
output.puts s
|
data/lib/BOAST/Language/Index.rb
CHANGED
@@ -3,19 +3,19 @@ module BOAST
|
|
3
3
|
class Index < Expression
|
4
4
|
attr_reader :source
|
5
5
|
attr_reader :indexes
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :alignment
|
7
7
|
|
8
|
-
def initialize(source, indexes)
|
8
|
+
def initialize(source, *indexes)
|
9
9
|
@source = source
|
10
10
|
@indexes = indexes
|
11
11
|
end
|
12
12
|
|
13
13
|
def align?
|
14
|
-
return !!@
|
14
|
+
return !!@alignment
|
15
15
|
end
|
16
16
|
|
17
17
|
def to_var
|
18
|
-
var = @source.copy("#{self}", :const => nil, :constant => nil, :dim => nil, :dimension => nil, :direction => nil, :dir => nil, :align =>
|
18
|
+
var = @source.copy("#{self}", :const => nil, :constant => nil, :dim => nil, :dimension => nil, :direction => nil, :dir => nil, :align => alignment)
|
19
19
|
return var
|
20
20
|
end
|
21
21
|
|
@@ -60,7 +60,7 @@ module BOAST
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def to_s_texture
|
63
|
-
raise "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
|
63
|
+
raise LanguageError, "Unsupported language #{lang} for texture!" if not [CL, CUDA].include?( lang )
|
64
64
|
raise "Write is unsupported for textures!" if not ( @source.constant or @source.direction == :in )
|
65
65
|
dim_number = 1
|
66
66
|
if @source.dimension then
|
@@ -21,71 +21,77 @@ module BOAST
|
|
21
21
|
INSTRUCTIONS = {}
|
22
22
|
INSTRUCTIONS.update(X86CPUID_by_name)
|
23
23
|
|
24
|
+
class IntrinsicsError < Error
|
25
|
+
end
|
26
|
+
|
27
|
+
class InternalIntrinsicsError < Error
|
28
|
+
end
|
29
|
+
|
24
30
|
module Intrinsics
|
25
31
|
extend PrivateStateAccessor
|
26
32
|
INTRINSICS = Hash::new { |h, k| h[k] = Hash::new { |h2, k2| h2[k2] = {} } }
|
27
33
|
CONVERSIONS = Hash::new { |h, k| h[k] = Hash::new { |h2, k2| h2[k2] = {} } }
|
28
34
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
35
|
+
def intrinsics_by_vector_name(intr_symbol, type, type2=nil)
|
36
|
+
if type2 then
|
37
|
+
instruction = INTRINSICS[get_architecture][intr_symbol][type][type2]
|
38
|
+
else
|
39
|
+
instruction = INTRINSICS[get_architecture][intr_symbol][type]
|
40
|
+
end
|
41
|
+
raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? "and #{type2}" : ""} on #{get_architecture_name}!" unless instruction
|
42
|
+
supported = false
|
32
43
|
INSTRUCTIONS[instruction.to_s].each { |flag|
|
33
|
-
|
44
|
+
supported = true if MODELS[get_model].include?(flag)
|
34
45
|
}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
module_function :supported
|
39
|
-
|
40
|
-
def intrinsics_by_vector_name(intr_symbol, type, type2=nil)
|
41
|
-
return INTRINSICS[get_architecture][intr_symbol][type][type2] if type2
|
42
|
-
return INTRINSICS[get_architecture][intr_symbol][type]
|
46
|
+
raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? "and #{type2}" : ""} on #{get_model}! (requires #{INSTRUCTIONS[instruction.to_s].join(" or ")})" unless supported
|
47
|
+
return instruction
|
43
48
|
end
|
44
49
|
|
45
50
|
module_function :intrinsics_by_vector_name
|
46
51
|
|
47
52
|
def intrinsics(intr_symbol, type, type2=nil)
|
48
|
-
return
|
49
|
-
return INTRINSICS[get_architecture][intr_symbol][get_vector_name(type)]
|
53
|
+
return intrinsics_by_vector_name(intr_symbol, get_vector_name(type), type2 ? get_vector_name(type2) : nil)
|
50
54
|
end
|
51
55
|
|
52
56
|
module_function :intrinsics
|
53
57
|
|
54
58
|
def get_conversion_path(type_dest, type_orig)
|
55
|
-
|
59
|
+
conversion_path = CONVERSIONS[get_architecture][get_vector_name(type_dest)][get_vector_name(type_orig)]
|
60
|
+
raise IntrinsicsError, "Unavailable conversion from #{get_vector_name(type_orig)} to #{get_vector_name(type_dest)} on #{get_architecture_name}!" unless conversion_path
|
61
|
+
return conversion_path
|
56
62
|
end
|
57
63
|
|
58
64
|
module_function :get_conversion_path
|
59
65
|
|
60
66
|
def get_vector_decl_X86( data_type )
|
61
|
-
raise "Unsupported vector size on X86: #{data_type.total_size*8}!" unless [64,128,256].include?( data_type.total_size*8 )
|
67
|
+
raise IntrinsicsError, "Unsupported vector size on X86: #{data_type.total_size*8}!" unless [64,128,256].include?( data_type.total_size*8 )
|
62
68
|
s = "__m#{data_type.total_size*8}"
|
63
69
|
case data_type
|
64
70
|
when Int
|
65
|
-
raise "Unsupported data size for int vector on X86: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
|
71
|
+
raise IntrinsicsError, "Unsupported data size for int vector on X86: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
|
66
72
|
return s+= "#{data_type.total_size*8>64 ? "i" : ""}"
|
67
73
|
when Real
|
68
74
|
return s if data_type.size == 4
|
69
75
|
return s += "d" if data_type.size == 8
|
70
|
-
raise "Unsupported data size for real vector on X86: #{data_type.size*8}!"
|
76
|
+
raise IntrinsicsError, "Unsupported data size for real vector on X86: #{data_type.size*8}!"
|
71
77
|
else
|
72
|
-
raise "Unsupported data type #{data_type} for vector!"
|
78
|
+
raise IntrinsicsError, "Unsupported data type #{data_type} for vector on X86!"
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
76
82
|
module_function :get_vector_decl_X86
|
77
83
|
|
78
84
|
def get_vector_decl_ARM( data_type )
|
79
|
-
raise "Unsupported vector size on ARM: #{data_type.total_size*8}!" unless [64,128].include?( data_type.total_size*8 )
|
85
|
+
raise IntrinsicsError, "Unsupported vector size on ARM: #{data_type.total_size*8}!" unless [64,128].include?( data_type.total_size*8 )
|
80
86
|
case data_type
|
81
87
|
when Int
|
82
|
-
raise "Unsupported data size for int vector on ARM: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
|
88
|
+
raise IntrinsicsError, "Unsupported data size for int vector on ARM: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
|
83
89
|
return get_vector_name( data_type ).to_s
|
84
90
|
when Real
|
85
|
-
raise "Unsupported data size for real vector on ARM: #{data_type.size*8}!" if data_type.size != 4
|
91
|
+
raise IntrinsicsError, "Unsupported data size for real vector on ARM: #{data_type.size*8}!" if data_type.size != 4
|
86
92
|
return get_vector_name( data_type ).to_s
|
87
93
|
else
|
88
|
-
raise "Unsupported data type #{data_type} for vector on ARM!"
|
94
|
+
raise IntrinsicsError, "Unsupported data type #{data_type} for vector on ARM!"
|
89
95
|
end
|
90
96
|
end
|
91
97
|
|
@@ -113,7 +119,7 @@ module BOAST
|
|
113
119
|
when Real
|
114
120
|
s += "float"
|
115
121
|
else
|
116
|
-
raise "Undefined vector type!"
|
122
|
+
raise InternalIntrinsicsError, "Undefined vector type!"
|
117
123
|
end
|
118
124
|
s += "#{type.size*8}"
|
119
125
|
s += "x#{type.vector_length}_t"
|
@@ -132,12 +138,12 @@ module BOAST
|
|
132
138
|
when :unsigned
|
133
139
|
s += "uint"
|
134
140
|
else
|
135
|
-
raise "Invalid sign!"
|
141
|
+
raise InternalIntrinsicsError, "Invalid sign!"
|
136
142
|
end
|
137
143
|
when :float
|
138
144
|
s += "float"
|
139
145
|
else
|
140
|
-
raise "Invalid type!"
|
146
|
+
raise InternalIntrinsicsError, "Invalid type!"
|
141
147
|
end
|
142
148
|
s += "#{size}"
|
143
149
|
s += "x#{vector_size/size}_t"
|
@@ -156,12 +162,12 @@ module BOAST
|
|
156
162
|
when :unsigned
|
157
163
|
s += "u"
|
158
164
|
else
|
159
|
-
raise "Invalid sign!"
|
165
|
+
raise InternalIntrinsicsError, "Invalid sign!"
|
160
166
|
end
|
161
167
|
when :float
|
162
168
|
s += "f"
|
163
169
|
else
|
164
|
-
raise "Invalid type!"
|
170
|
+
raise InternalIntrinsicsError, "Invalid type!"
|
165
171
|
end
|
166
172
|
s += "#{size}"
|
167
173
|
return s
|
@@ -181,7 +187,7 @@ module BOAST
|
|
181
187
|
when :unsigned
|
182
188
|
s += "u"
|
183
189
|
else
|
184
|
-
raise "Invalid sign!"
|
190
|
+
raise InternalIntrinsicsError, "Invalid sign!"
|
185
191
|
end
|
186
192
|
s += "#{size}"
|
187
193
|
when :float
|
@@ -192,10 +198,10 @@ module BOAST
|
|
192
198
|
when 64
|
193
199
|
s += "d"
|
194
200
|
else
|
195
|
-
raise "Invalid size!"
|
201
|
+
raise InternalIntrinsicsError, "Invalid size!"
|
196
202
|
end
|
197
203
|
else
|
198
|
-
raise "Invalid type!"
|
204
|
+
raise InternalIntrinsicsError, "Invalid type!"
|
199
205
|
end
|
200
206
|
return s
|
201
207
|
end
|
@@ -234,7 +240,7 @@ module BOAST
|
|
234
240
|
sizes = []
|
235
241
|
sizes.push( 32, 64 ) if vector_size > 64
|
236
242
|
sizes.each { |size|
|
237
|
-
[[:ADD, "add"], [:SUB, "sub"], [:MUL, "mul"], [:DIV, "div"],
|
243
|
+
[[:ADD, "add"], [:SUB, "sub"], [:MUL, "mul"], [:DIV, "div"], [:POW, "pow"],
|
238
244
|
[:FMADD, "fmadd"], [:FMSUB, "fmsub"], [:FNMADD, "fnmadd"], [:FNMSUB, "fnmsub"],
|
239
245
|
[:ADDSUB, "addsub"], [:FMADDSUB, "fmaddsub"], [:FMSUBADD, "fmsubadd"],
|
240
246
|
[:LOAD, "loadu"], [:LOADA, "load"], [:MASKLOAD, "maskload"],
|