BOAST 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ module BOAST
2
+
3
+ class CodeBlock < Proc
4
+ include PrivateStateAccessor
5
+ include Inspectable
6
+ extend Functor
7
+
8
+ attr_accessor :options
9
+
10
+ def initialize(options = {},&block)
11
+ @options = options
12
+ super(&block)
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ module BOAST
2
+ class Error < StandardError
3
+ end
4
+
5
+ class LanguageError < Error
6
+ end
7
+ 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.to_s(op1, op2, return_type) if not oper.kind_of?(String)
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 == "/")
@@ -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 unroll(*args)
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
- if @begin.kind_of?(Variable) then
70
- start = @begin.constant
71
- elsif @begin.kind_of?(Expression) then
72
- start = eval "#{@begin}"
73
- else
74
- start = @begin.to_i
75
- end
76
- if @end.kind_of?(Variable) then
77
- e = @end.constant
78
- elsif @end.kind_of?(Expression) then
79
- e = eval "#{@end}"
80
- else
81
- e = @end.to_i
82
- end
83
- if @step.kind_of?(Variable) then
84
- step = @step.constant
85
- elsif @step.kind_of?(Expression) then
86
- step = eval "#{@step}"
87
- else
88
- step = @step.to_i
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
- if not ( start and e and step ) then
93
- pop_env( :replace_constants )
94
- return pr(*args) if not ( start and e and step )
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)
@@ -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 == 0 then
11
- raise "Illegal if construct!"
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
- (0..conditions.size-2).step(2) { |i|
22
- @conditions[i/2] = conditions[i]
23
- @blocks[i/2] = conditions[i+1]
24
- }
25
- @blocks.push(conditions.last)
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
@@ -3,19 +3,19 @@ module BOAST
3
3
  class Index < Expression
4
4
  attr_reader :source
5
5
  attr_reader :indexes
6
- attr_accessor :align
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 !!@align
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 => 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 supported(intr_symbol, type, type2=nil)
30
- instruction = intrinsics(intr_symbol, type, type2)
31
- return false unless instruction
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
- return true if MODELS[get_model].include?(flag)
44
+ supported = true if MODELS[get_model].include?(flag)
34
45
  }
35
- return false
36
- end
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 INTRINSICS[get_architecture][intr_symbol][get_vector_name(type)][get_vector_name(type2)] if type2
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
- return CONVERSIONS[get_architecture][get_vector_name(type_dest)][get_vector_name(type_orig)]
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"],