BOAST 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,7 +11,7 @@ module BOAST
11
11
  elsif lang == C then
12
12
  s += "#pragma omp"
13
13
  else
14
- raise "Language does not support OpenMP!"
14
+ raise LanguageError, "Language does not support OpenMP!"
15
15
  end
16
16
  return s
17
17
  end
@@ -1,5 +1,8 @@
1
1
  module BOAST
2
2
 
3
+ class OperatorError < Error
4
+ end
5
+
3
6
  class Operator
4
7
  extend PrivateStateAccessor
5
8
  extend Intrinsics
@@ -11,10 +14,10 @@ module BOAST
11
14
  end
12
15
 
13
16
  def Operator.convert(arg, type)
17
+ return "#{arg}" if get_vector_name(arg.type) == get_vector_name(type) or lang == CUDA
14
18
  return "convert_#{type.decl}( #{arg} )" if lang == CL
15
19
 
16
20
  path = get_conversion_path(type, arg.type)
17
- raise "Unavailable conversion from #{get_vector_name(arg.type)} to #{get_vector_name(type)}!" if not path
18
21
  s = "#{arg}"
19
22
  if path.length > 1 then
20
23
  path.each_cons(2) { |slice|
@@ -29,10 +32,9 @@ module BOAST
29
32
 
30
33
  class BasicBinaryOperator < Operator
31
34
 
32
- def BasicBinaryOperator.to_s(arg1, arg2, return_type)
35
+ def BasicBinaryOperator.string(arg1, arg2, return_type)
33
36
  if lang == C and (arg1.class == Variable and arg2.class == Variable) and (arg1.type.vector_length > 1 or arg2.type.vector_length > 1) then
34
37
  instruction = intrinsics(intr_symbol, return_type.type)
35
- raise "Unavailable operator #{symbol} for #{get_vector_name(return_type.type)}!" unless instruction
36
38
  a1 = convert(arg1, return_type.type)
37
39
  a2 = convert(arg2, return_type.type)
38
40
  return "#{instruction}( #{a1}, #{a2} )"
@@ -43,9 +45,63 @@ module BOAST
43
45
 
44
46
  end
45
47
 
48
+ class Minus < Operator
49
+
50
+ def Minus.string(arg1, arg2, return_type)
51
+ return " -(#{arg2})"
52
+ end
53
+
54
+ end
55
+
56
+ class Plus < Operator
57
+
58
+ def Plus.string(arg1, arg2, return_type)
59
+ return " +#{arg2}"
60
+ end
61
+
62
+ end
63
+
64
+ class Not < Operator
65
+
66
+ def Not.string(arg1, arg2, return_type)
67
+ return " (.not. (#{arg2}))" if lang == FORTRAN
68
+ return " !(#{arg2})"
69
+ end
70
+
71
+ end
72
+
73
+ class Reference < Operator
74
+
75
+ def Reference.string(arg1, arg2, return_type)
76
+ return " #{arg2}" if lang == FORTRAN
77
+ return " &#{arg2}"
78
+ end
79
+
80
+ end
81
+
82
+ class Dereference < Operator
83
+
84
+ def Dereference.string(arg1, arg2, return_type)
85
+ return " *(#{arg2})"
86
+ end
87
+
88
+ end
89
+
90
+ class Equal < Operator
91
+
92
+ def Equal.string(arg1, arg2, return_type)
93
+ return basic_usage(arg1, arg2)
94
+ end
95
+
96
+ def Equal.basic_usage(arg1, arg2)
97
+ return "#{arg1} == #{arg2}"
98
+ end
99
+
100
+ end
101
+
46
102
  class Different < Operator
47
103
 
48
- def Different.to_s(arg1, arg2, return_type)
104
+ def Different.string(arg1, arg2, return_type)
49
105
  return basic_usage(arg1, arg2)
50
106
  end
51
107
 
@@ -56,9 +112,83 @@ module BOAST
56
112
 
57
113
  end
58
114
 
115
+ class Greater < Operator
116
+
117
+ def Greater.string(arg1, arg2, return_type)
118
+ return basic_usage(arg1, arg2)
119
+ end
120
+
121
+ def Greater.basic_usage(arg1, arg2)
122
+ return "#{arg1} > #{arg2}"
123
+ end
124
+
125
+ end
126
+
127
+ class Less < Operator
128
+
129
+ def Less.string(arg1, arg2, return_type)
130
+ return basic_usage(arg1, arg2)
131
+ end
132
+
133
+ def Less.basic_usage(arg1, arg2)
134
+ return "#{arg1} < #{arg2}"
135
+ end
136
+
137
+ end
138
+
139
+ class GreaterOrEqual < Operator
140
+
141
+ def GreaterOrEqual.string(arg1, arg2, return_type)
142
+ return basic_usage(arg1, arg2)
143
+ end
144
+
145
+ def GreaterOrEqual.basic_usage(arg1, arg2)
146
+ return "#{arg1} >= #{arg2}"
147
+ end
148
+
149
+ end
150
+
151
+ class LessOrEqual < Operator
152
+
153
+ def LessOrEqual.string(arg1, arg2, return_type)
154
+ return basic_usage(arg1, arg2)
155
+ end
156
+
157
+ def LessOrEqual.basic_usage(arg1, arg2)
158
+ return "#{arg1} <= #{arg2}"
159
+ end
160
+
161
+ end
162
+
163
+ class And < Operator
164
+
165
+ def And.string(arg1, arg2, return_type)
166
+ return basic_usage(arg1, arg2)
167
+ end
168
+
169
+ def And.basic_usage(arg1, arg2)
170
+ return "#{arg1} .and. #{arg2}" if lang == FORTRAN
171
+ return "#{arg1} && #{arg2}"
172
+ end
173
+
174
+ end
175
+
176
+ class Or < Operator
177
+
178
+ def Or.string(arg1, arg2, return_type)
179
+ return basic_usage(arg1, arg2)
180
+ end
181
+
182
+ def Or.basic_usage(arg1, arg2)
183
+ return "#{arg1} .or. #{arg2}" if lang == FORTRAN
184
+ return "#{arg1} || #{arg2}"
185
+ end
186
+
187
+ end
188
+
59
189
  class Affectation < Operator
60
190
 
61
- def Affectation.to_s(arg1, arg2, return_type)
191
+ def Affectation.string(arg1, arg2, return_type)
62
192
  if arg1.class == Variable and arg1.type.vector_length > 1 then
63
193
  return "#{arg1} = #{Load(arg2, arg1)}"
64
194
  elsif arg2.class == Variable and arg2.type.vector_length > 1 then
@@ -73,6 +203,27 @@ module BOAST
73
203
 
74
204
  end
75
205
 
206
+ class Exponentiation < BasicBinaryOperator
207
+
208
+ class << self
209
+
210
+ def symbol
211
+ return "**"
212
+ end
213
+
214
+ def intr_symbol
215
+ return :POW
216
+ end
217
+
218
+ def basic_usage(arg1, arg2)
219
+ return "(#{arg1})**(#{arg2})" if lang == FORTRAN
220
+ return "pow(#{arg1}, #{arg2})"
221
+ end
222
+
223
+ end
224
+
225
+ end
226
+
76
227
  class Multiplication < BasicBinaryOperator
77
228
 
78
229
  class << self
@@ -153,22 +304,6 @@ module BOAST
153
304
 
154
305
  end
155
306
 
156
- class Minus < Operator
157
-
158
- def Minus.to_s(arg1, arg2, return_type)
159
- return " -(#{arg2})"
160
- end
161
-
162
- end
163
-
164
- class Not < Operator
165
-
166
- def Not.to_s(arg1, arg2, return_type)
167
- return " ! #{arg2}"
168
- end
169
-
170
- end
171
-
172
307
  class Set < Operator
173
308
  extend Functor
174
309
  include Intrinsics
@@ -191,24 +326,24 @@ module BOAST
191
326
  def to_var
192
327
  if lang == C or lang == CL and @return_type.type.vector_length > 1 then
193
328
  if @source.kind_of?( Array ) then
194
- raise "Invalid array length!" unless @source.length == @return_type.type.vector_length
329
+ raise OperatorError, "Invalid array length!" unless @source.length == @return_type.type.vector_length
195
330
  return @return_type.copy("(#{@return_type.type.decl})( #{@source.join(", ")} )", DISCARD_OPTIONS) if lang == CL
196
331
 
197
- instruction = intrinsics(:SET, @return_type.type)
198
- return @return_type.copy("#{instruction}( #{@source.join(", ")} )", DISCARD_OPTIONS) if instruction
199
-
200
- instruction = intrinsics(:SET_LANE, @return_type.type)
201
- raise "Unavailable operator set for #{get_vector_name(@return_type.type)}!" unless instruction
202
- s = Set(0, @return_type).to_s
203
- @source.each_with_index { |v,i|
204
- s = "#{instruction}(#{v}, #{s}, #{i})"
205
- }
206
- return @return_type.copy(s, DISCARD_OPTIONS)
332
+ begin
333
+ instruction = intrinsics(:SET, @return_type.type)
334
+ return @return_type.copy("#{instruction}( #{@source.join(", ")} )", DISCARD_OPTIONS)
335
+ rescue IntrinsicsError
336
+ instruction = intrinsics(:SET_LANE, @return_type.type)
337
+ s = Set(0, @return_type).to_s
338
+ @source.each_with_index { |v,i|
339
+ s = "#{instruction}(#{v}, #{s}, #{i})"
340
+ }
341
+ return @return_type.copy(s, DISCARD_OPTIONS)
342
+ end
207
343
  elsif @source.class != Variable or @source.type.vector_length == 1 then
208
344
  return @return_type.copy("(#{@return_type.type.decl})( #{@source} )", DISCARD_OPTIONS) if lang == CL
209
345
 
210
346
  instruction = intrinsics(:SET1, @return_type.type)
211
- raise "Unavailable operator set1 for #{get_vector_name(@return_type.type)}!" unless instruction
212
347
  return @return_type.copy("#{instruction}( #{@source} )", DISCARD_OPTIONS)
213
348
  elsif @return_type.type != @source.type
214
349
  return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
@@ -267,12 +402,11 @@ module BOAST
267
402
  end
268
403
  return @return_type.copy("vload#{@return_type.type.vector_length}(0, #{a2})", DISCARD_OPTIONS) if lang == CL
269
404
  return @return_type.copy("_m_from_int64( *((int64_t * ) #{a2} ) )", DISCARD_OPTIONS) if get_architecture == X86 and @return_type.type.total_size*8 == 64
270
- if @source.align == @return_type.type.total_size then
405
+ if @source.alignment == @return_type.type.total_size then
271
406
  instruction = intrinsics(:LOADA, @return_type.type)
272
407
  else
273
408
  instruction = intrinsics(:LOAD, @return_type.type)
274
409
  end
275
- raise "Unavailable operator load for #{get_vector_name(@return_type.type)}!" unless instruction
276
410
  return @return_type.copy("#{instruction}( #{a2} )", DISCARD_OPTIONS)
277
411
  else
278
412
  return @return_type.copy("#{Operator.convert(@source, @return_type.type)}", DISCARD_OPTIONS)
@@ -315,7 +449,7 @@ module BOAST
315
449
  end
316
450
 
317
451
  def get_mask
318
- raise "Mask size is wrong: #{@mask.length} for #{@return_type.type.vector_length}!" if @mask.length != @return_type.type.vector_length
452
+ raise OperatorError, "Mask size is wrong: #{@mask.length} for #{@return_type.type.vector_length}!" if @mask.length != @return_type.type.vector_length
319
453
  return Load(@mask.collect { |m| ( m and m != 0 ) ? -1 : 0 }, Int("mask", :size => @return_type.type.size, :vector_length => @return_type.type.vector_length ) )
320
454
  end
321
455
 
@@ -326,9 +460,9 @@ module BOAST
326
460
  end
327
461
 
328
462
  def to_var
329
- raise "Cannot load unknown type!" unless @return_type
330
- raise "Unsupported language!" unless lang == C
331
- raise "MaskLoad not supported!"unless supported(:MASKLOAD, @return_type.type)
463
+ raise OperatorError, "Cannot load unknown type!" unless @return_type
464
+ raise LanguageError, "Unsupported language!" unless lang == C
465
+ instruction = intrinsics(:MASKLOAD, @return_type.type)
332
466
  s = ""
333
467
  src = "#{@source}"
334
468
  if src[0] != "*" then
@@ -337,7 +471,7 @@ module BOAST
337
471
  src = src[1..-1]
338
472
  end
339
473
  p_type = @return_type.type.copy(:vector_length => 1)
340
- s += "#{intrinsics(:MASKLOAD, @return_type.type)}((#{p_type.decl} * )#{src}, #{get_mask})"
474
+ s += "#{instruction}((#{p_type.decl} * )#{src}, #{get_mask})"
341
475
  return @return_type.copy( s, DISCARD_OPTIONS)
342
476
  end
343
477
 
@@ -386,12 +520,11 @@ module BOAST
386
520
  return "vstore#{@source.type.vector_length}(#{@source}, 0, #{dst})" if lang == CL
387
521
  return "*((int64_t * ) #{dst}) = _m_to_int64( #{@source} )" if get_architecture == X86 and @source.type.total_size*8 == 64
388
522
 
389
- if @dest.align == @source.type.total_size then
523
+ if @dest.alignment == @source.type.total_size then
390
524
  instruction = intrinsics(:STOREA, @source.type)
391
525
  else
392
526
  instruction = intrinsics(:STORE, @source.type)
393
527
  end
394
- raise "Unavailable operator store for #{get_vector_name(@source.type)}!" unless instruction
395
528
  p_type = @source.type.copy(:vector_length => 1)
396
529
  p_type = @source.type if get_architecture == X86 and @source.type.kind_of?(Int)
397
530
  return "#{instruction}( (#{p_type.decl} * ) #{dst}, #{@source} )"
@@ -431,16 +564,16 @@ module BOAST
431
564
  end
432
565
 
433
566
  def get_mask
434
- raise "Mask size is wrong: #{@mask.length} for #{@store_type.type.vector_length}!" if @mask.length != @store_type.type.vector_length
567
+ raise OperatorError, "Mask size is wrong: #{@mask.length} for #{@store_type.type.vector_length}!" if @mask.length != @store_type.type.vector_length
435
568
  return Load.to_s(@mask.collect { |m| ( m and m != 0 ) ? -1 : 0 }, Int("mask", :size => @store_type.type.size, :vector_length => @store_type.type.vector_length ) )
436
569
  end
437
570
 
438
571
  private :get_mask
439
572
 
440
573
  def to_s
441
- raise "Cannot store unknown type!" unless @store_type
442
- raise "Unsupported language!" unless lang == C
443
- raise "MaskStore not supported!"unless supported(:MASKSTORE, @store_type.type)
574
+ raise OperatorError, "Cannot store unknown type!" unless @store_type
575
+ raise LanguageError, "Unsupported language!" unless lang == C
576
+ instruction = intrinsics(:MASKSTORE, @store_type.type)
444
577
  s = ""
445
578
  dst = "#{@dest}"
446
579
  if dst[0] != "*" then
@@ -449,7 +582,7 @@ module BOAST
449
582
  dst = dst[1..-1]
450
583
  end
451
584
  p_type = @store_type.type.copy(:vector_length => 1)
452
- return s += "#{intrinsics(:MASKSTORE, @store_type.type)}((#{p_type.decl} * )#{dst}, #{get_mask}, #{Operator.convert(@source, @store_type.type)})"
585
+ return s += "#{instruction}((#{p_type.decl} * )#{dst}, #{get_mask}, #{Operator.convert(@source, @store_type.type)})"
453
586
  end
454
587
 
455
588
  def pr
@@ -494,7 +627,12 @@ module BOAST
494
627
  end
495
628
 
496
629
  def to_var
497
- return (@operand3 + @operand1 * @operand2).to_var unless lang != FORTRAN and @return_type and ( supported(:FMADD, @return_type.type) or ( [CL, CUDA].include?(lang) ) )
630
+ instruction = nil
631
+ begin
632
+ instruction = intrinsics(:FMADD,@return_type.type)
633
+ rescue
634
+ end
635
+ return (@operand3 + @operand1 * @operand2).to_var unless lang != FORTRAN and @return_type and ( instruction or ( [CL, CUDA].include?(lang) ) )
498
636
  op1 = convert_operand(@operand1)
499
637
  op2 = convert_operand(@operand2)
500
638
  op3 = convert_operand(@operand3)
@@ -503,9 +641,9 @@ module BOAST
503
641
  else
504
642
  case architecture
505
643
  when X86
506
- ret_name = "#{intrinsics(:FMADD,@return_type.type)}(#{op1},#{op2},#{op3})"
644
+ ret_name = "#{instruction}(#{op1},#{op2},#{op3})"
507
645
  when ARM
508
- ret_name = "#{intrinsics(:FMADD,@return_type.type)}(#{op2},#{op3},#{op1})"
646
+ ret_name = "#{instruction}(#{op2},#{op3},#{op1})"
509
647
  else
510
648
  return (@operand1 * @operand2 + @operand3).to_var
511
649
  end
@@ -544,14 +682,31 @@ module BOAST
544
682
  @operand3 = z
545
683
  end
546
684
 
685
+ def op_to_var
686
+ op1 = @operand1.respond_to?(:to_var) ? @operand1.to_var : @operand1
687
+ op1 = @operand1 unless op1
688
+ op2 = @operand2.respond_to?(:to_var) ? @operand2.to_var : @operand2
689
+ op2 = @operand2 unless op2
690
+ op3 = @operand3.respond_to?(:to_var) ? @operand3.to_var : @operand3
691
+ op3 = @operand3 unless op3
692
+ return [op1, op2, op3]
693
+ end
694
+
695
+ private :op_to_var
696
+
547
697
  def to_s
548
- raise "Ternary operator unsupported in FORTRAN!" if lang == FORTRAN
698
+ return to_s_fortran if lang == FORTRAN
549
699
  return to_s_c if [C, CL, CUDA].include?( lang )
550
700
  end
551
701
 
702
+ def to_s_fortran
703
+ op1, op2, op3 = op_to_var
704
+ "merge(#{op2}, #{op3}, #{op1})"
705
+ end
706
+
552
707
  def to_s_c
553
- s = ""
554
- s += "(#{@operand1} ? #{@operand2} : #{@operand3})"
708
+ op1, op2, op3 = op_to_var
709
+ "(#{op1} ? #{op2} : #{op3})"
555
710
  end
556
711
 
557
712
  def pr
@@ -8,7 +8,7 @@ module BOAST
8
8
  attr_reader :name
9
9
  attr_reader :options
10
10
 
11
- def initialize(name, options)
11
+ def initialize(name, *options)
12
12
  @name = name
13
13
  @options = options
14
14
  end
@@ -16,9 +16,9 @@ module BOAST
16
16
  def to_s
17
17
  s = ""
18
18
  if lang == FORTRAN then
19
- s += "$!"
19
+ s += "!#{@name}$"
20
20
  else
21
- s += "#pragma"
21
+ s += "#pragma #{name}"
22
22
  end
23
23
  @options.each{ |opt|
24
24
  s += " #{opt}"
@@ -1,11 +1,11 @@
1
1
  module BOAST
2
2
 
3
- def self.print(a)
4
- a.pr
3
+ def self.print(a, *args)
4
+ pr(a, *args)
5
5
  end
6
6
 
7
7
  def self.open(a)
8
- a.open
8
+ opn(a)
9
9
  end
10
10
 
11
11
  end