BOAST 0.6 → 0.7

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.
data/BOAST.gemspec CHANGED
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'BOAST'
3
- s.version = "0.6"
3
+ s.version = "0.7"
4
4
  s.author = "Brice Videau"
5
5
  s.email = "brice.videau@imag.fr"
6
6
  s.homepage = "https://forge.imag.fr/projects/boast/"
7
7
  s.summary = "BOAST is a computing kernel metaprogramming tool."
8
8
  s.description = "BOAST aims at providing a framework to metaprogram, benchmark and validate computing kernels"
9
- s.files = %w( BOAST.gemspec LICENSE lib/BOAST.rb lib/BOAST/Algorithm.rb lib/BOAST/CKernel.rb lib/BOAST/BOAST_OpenCL.rb lib/BOAST/Transitions.rb lib/BOAST/Parens.rb)
9
+ s.files = %w( BOAST.gemspec LICENSE lib/BOAST.rb lib/BOAST/Algorithm.rb lib/BOAST/CKernel.rb lib/BOAST/BOAST_OpenCL.rb lib/BOAST/Transitions.rb lib/BOAST/Parens.rb lib/BOAST/Operators.rb lib/BOAST/DataTypes.rb )
10
10
  s.has_rdoc = true
11
11
  s.license = 'BSD'
12
12
  s.required_ruby_version = '>= 1.9.3'
data/lib/BOAST.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'BOAST/Transitions.rb'
2
+ require 'BOAST/Operators.rb'
3
+ require 'BOAST/DataTypes.rb'
2
4
  require 'BOAST/Algorithm.rb'
3
5
  require 'BOAST/CKernel.rb'
4
6
  require 'BOAST/Parens.rb'
@@ -6,6 +6,8 @@ module BOAST
6
6
  C = 2
7
7
  CL = 3
8
8
  CUDA = 4
9
+ X86 = 1
10
+ ARM = 2
9
11
  @@output = STDOUT
10
12
  @@lang = FORTRAN
11
13
  @@replace_constants = true
@@ -16,6 +18,7 @@ module BOAST
16
18
  @@indent_increment = 2
17
19
  @@array_start = 1
18
20
  @@chain_code = false
21
+ @@architecture = X86
19
22
 
20
23
  @@env = Hash.new{|h, k| h[k] = []}
21
24
 
@@ -55,6 +58,14 @@ module BOAST
55
58
  a.close
56
59
  end
57
60
 
61
+ def BOAST::set_architecture(arch)
62
+ @@architecture = arch
63
+ end
64
+
65
+ def BOAST::get_architecture
66
+ return @@architecture
67
+ end
68
+
58
69
  def BOAST::set_indent_level(level)
59
70
  @@indent_level = level
60
71
  end
@@ -199,7 +210,7 @@ module BOAST
199
210
  end
200
211
 
201
212
  def ===(x)
202
- return Expression::new("=",self,x)
213
+ return Expression::new(BOAST::Affectation,self,x)
203
214
  end
204
215
 
205
216
  def ==(x)
@@ -207,7 +218,7 @@ module BOAST
207
218
  end
208
219
 
209
220
  def +(x)
210
- return Expression::new("+",self,x)
221
+ return Expression::new(BOAST::Addition,self,x)
211
222
  end
212
223
 
213
224
  def >(x)
@@ -223,11 +234,11 @@ module BOAST
223
234
  end
224
235
 
225
236
  def *(x)
226
- return Expression::new("*",self,x)
237
+ return Expression::new(BOAST::Multiplication,self,x)
227
238
  end
228
239
 
229
240
  def /(x)
230
- return Expression::new("/",self,x)
241
+ return Expression::new(BOAST::Division,self,x)
231
242
  end
232
243
 
233
244
  def dereference
@@ -239,18 +250,19 @@ module BOAST
239
250
  end
240
251
 
241
252
  def -(x)
242
- return Expression::new("-",self,x)
253
+ return Expression::new(BOAST::Substraction,self,x)
243
254
  end
244
255
 
245
256
  def !
246
- return Expression::new("!",nil,self)
257
+ return Expression::new(BOAST::Not,nil,self)
247
258
  end
248
259
 
249
260
  def -@
250
- return Expression::new("-",nil,self)
261
+ return Expression::new(BOAST::Minus,nil,self)
251
262
  end
252
263
 
253
- def Expression.to_str_base(op1, op2, oper)
264
+ def Expression.to_str_base(op1, op2, oper, return_type = nil)
265
+ return oper.to_s(op1,op2, return_type) if not oper.kind_of?(String)
254
266
  s = ""
255
267
  if op1 then
256
268
  s += "(" if (oper == "*" or oper == "/")
@@ -275,7 +287,7 @@ module BOAST
275
287
  op2 = @operand2.to_var if @operand2.respond_to?(:to_var)
276
288
  if op1 and op2 then
277
289
  r_t, oper = BOAST::transition(op1, op2, @operator)
278
- res_exp = BOAST::Expression::to_str_base(op1, op2, oper)
290
+ res_exp = BOAST::Expression::to_str_base(op1, op2, oper, r_t)
279
291
  return r_t.copy(res_exp, :const => nil, :constant => nil)
280
292
  elsif op2
281
293
  res_exp = BOAST::Expression::to_str_base(@operand1, op2, @operator)
@@ -294,16 +306,17 @@ module BOAST
294
306
  op1 = @operand1.to_var if @operand1.respond_to?(:to_var)
295
307
  op2 = nil
296
308
  op2 = @operand2.to_var if @operand2.respond_to?(:to_var)
309
+ r_t = nil
297
310
  if op1 and op2 then
298
311
  r_t, oper = BOAST::transition(op1, op2, @operator)
299
312
  else
300
313
  oper = @operator
301
314
  end
302
315
 
303
- op1 = @operand1 if not op1
304
- op2 = @operand2 if not op2
316
+ op1 = @operand1 if op1.nil?
317
+ op2 = @operand2 if op2.nil?
305
318
 
306
- return BOAST::Expression::to_str_base(op1, op2, oper)
319
+ return BOAST::Expression::to_str_base(op1, op2, oper, r_t)
307
320
  end
308
321
 
309
322
  def print(final=true)
@@ -316,24 +329,6 @@ module BOAST
316
329
  end
317
330
  end
318
331
 
319
- class Mult < Expression
320
- def initialize(operand1, operand2)
321
- super("*", operand1, operand2)
322
- end
323
- end
324
-
325
- class Add < Expression
326
- def initialize(operand1, operand2)
327
- super("+", operand1, operand2)
328
- end
329
- end
330
-
331
- class Affect < Expression
332
- def initialize(operand1, operand2)
333
- super("=", operand1, operand2)
334
- end
335
- end
336
-
337
332
  class Index < Expression
338
333
  attr_reader :source
339
334
  attr_reader :indexes
@@ -454,94 +449,14 @@ module BOAST
454
449
  end
455
450
  end
456
451
 
457
- class CStruct
458
- attr_reader :name, :members, :members_array
459
- def self.parens(*args,&block)
460
- return Variable::new(args[0], self, *args[1..-1], &block)
461
- end
462
-
463
- def initialize(hash={})
464
- @name = hash[:type_name]
465
- @members = {}
466
- @members_array = []
467
- hash[:members].each { |m|
468
- mc = m.copy
469
- @members_array.push(mc)
470
- @members[mc.name] = mc
471
- }
472
- end
473
-
474
- def decl
475
- return "struct #{@name}" if [C, CL, CUDA].include?( BOAST::get_lang )
476
- return "TYPE(#{@name})" if BOAST::get_lang == FORTRAN
477
- end
478
-
479
- def finalize
480
- s = ""
481
- s += ";" if [C, CL, CUDA].include?( BOAST::get_lang )
482
- s+="\n"
483
- return s
484
- end
485
-
486
- def indent
487
- return " "*BOAST::get_indent_level
488
- end
489
-
490
- def header
491
- return header_c if [C, CL, CUDA].include?( BOAST::get_lang )
492
- return header_fortran if BOAST::get_lang == FORTRAN
493
- raise "Unsupported language!"
494
- end
495
-
496
- def header_c(final = true)
497
- s = ""
498
- s += self.indent if final
499
- s += self.decl + " {\n"
500
- @members_array.each { |value|
501
- s+= self.indent if final
502
- s+= " "*BOAST::get_indent_increment + value.decl(false)+";\n"
503
- }
504
- s += self.indent if final
505
- s += "}"
506
- s += self.finalize if final
507
- BOAST::get_output.print s if final
508
- return s
509
- end
510
-
511
- def header_fortran(final = true)
512
- s = ""
513
- s += self.indent if final
514
- s += "TYPE :: #{@name}\n"
515
- members_array.each { |value|
516
- s+= self.indent if final
517
- s+= " "*BOAST::get_indent_increment + value.decl(false)+"\n"
518
- }
519
- s += self.indent if final
520
- s += "END TYPE #{@name}"
521
- s += self.finalize if final
522
- BOAST::get_output.print s if final
523
- return s
524
- end
525
-
526
- end
527
- class CustomType
528
- attr_reader :size, :name, :vector_length
529
- def initialize(hash={})
530
- @name = hash[:type_name]
531
- @size = hash[:size]
532
- @vector_length = hash[:vector_length]
533
- end
534
- def decl
535
- return "#{@name}" if [C, CL, CUDA].include?( BOAST::get_lang )
536
- end
537
- end
538
-
539
452
 
540
453
  class Variable
541
454
  alias_method :orig_method_missing, :method_missing
542
455
 
543
456
  def method_missing(m, *a, &b)
544
457
  return self.struct_reference(type.members[m.to_s]) if type.members[m.to_s]
458
+ # return self.get_element(m.to_s) if type.getters[m.to_s]
459
+ # return self.set_element(m.to_s) if type.setters[m.to_s]
545
460
  return self.orig_method_missing(m, *a, &b)
546
461
  end
547
462
 
@@ -558,6 +473,7 @@ module BOAST
558
473
  attr_reader :local
559
474
  attr_reader :texture
560
475
  attr_reader :sampler
476
+ attr_reader :restrict
561
477
  attr_accessor :replace_constant
562
478
  attr_accessor :force_replace_constant
563
479
 
@@ -569,6 +485,7 @@ module BOAST
569
485
  @local = hash[:local] ? hash[:local] : hash[:shared]
570
486
  @texture = hash[:texture]
571
487
  @allocate = hash[:allocate]
488
+ @restrict = hash[:restrict]
572
489
  @force_replace_constant = false
573
490
  if not hash[:replace_constant].nil? then
574
491
  @replace_constant = hash[:replace_constant]
@@ -591,6 +508,14 @@ module BOAST
591
508
  }
592
509
  return Variable::new(name, @type.class, hash)
593
510
  end
511
+
512
+ def Variable.from_type(name, type, options={})
513
+ hash = type.to_hash
514
+ options.each { |k,v|
515
+ hash[k] = v
516
+ }
517
+ return Variable::new(name, type.class, hash)
518
+ end
594
519
 
595
520
  def to_s
596
521
  self.to_str
@@ -609,8 +534,12 @@ module BOAST
609
534
  return self
610
535
  end
611
536
 
537
+ def set(x)
538
+ return Expression::new(BOAST::Set, self, x)
539
+ end
540
+
612
541
  def ===(x)
613
- return Expression::new("=",self,x)
542
+ return Expression::new(BOAST::Affectation,self,x)
614
543
  end
615
544
 
616
545
  def ==(x)
@@ -630,27 +559,27 @@ module BOAST
630
559
  end
631
560
 
632
561
  def +(x)
633
- return Expression::new("+",self,x)
562
+ return Expression::new(BOAST::Addition,self,x)
634
563
  end
635
564
 
636
565
  def *(x)
637
- return Expression::new("*",self,x)
566
+ return Expression::new(BOAST::Multiplication,self,x)
638
567
  end
639
568
 
640
569
  def /(x)
641
- return Expression::new("/",self,x)
570
+ return Expression::new(BOAST::Division,self,x)
642
571
  end
643
572
 
644
573
  def -(x)
645
- return Expression::new("-",self,x)
574
+ return Expression::new(BOAST::Substraction,self,x)
646
575
  end
647
576
 
648
577
  def !
649
- return Expression::new("!",nil,self)
578
+ return Expression::new(BOAST::Not,nil,self)
650
579
  end
651
580
 
652
581
  def -@
653
- return Expression::new("-",nil,self)
582
+ return Expression::new(BOAST::Minus,nil,self)
654
583
  end
655
584
 
656
585
  def address
@@ -658,7 +587,9 @@ module BOAST
658
587
  end
659
588
 
660
589
  def dereference
661
- return Expression::new("*",nil,self)
590
+ return self.copy("*(#{self.name})", :dimension => false, :dim => false) if [C, CL, CUDA].include?( BOAST::get_lang )
591
+ return self if BOAST::get_lang == FORTRAN
592
+ #return Expression::new("*",nil,self)
662
593
  end
663
594
 
664
595
  def struct_reference(x)
@@ -696,6 +627,13 @@ module BOAST
696
627
  s += @type.decl
697
628
  if(@dimension and not @constant and not @allocate and (not @local or (@local and device))) then
698
629
  s += " *"
630
+ if @restrict then
631
+ if BOAST::get_lang == CL
632
+ s += " restrict"
633
+ else
634
+ s += " __restrict__"
635
+ end
636
+ end
699
637
  end
700
638
  s += " #{@name}"
701
639
  if @dimension and @constant then
@@ -806,38 +744,6 @@ module BOAST
806
744
 
807
745
  end
808
746
 
809
-
810
-
811
- class Real
812
- def self.parens(*args,&block)
813
- return Variable::new(args[0], self, *args[1..-1], &block)
814
- end
815
-
816
- attr_reader :size
817
- def initialize(hash={})
818
- if hash[:size] then
819
- @size = hash[:size]
820
- else
821
- @size = BOAST::get_default_real_size
822
- end
823
- if hash[:vector_length] and hash[:vector_length] > 1 then
824
- @vector_length = hash[:vector_length]
825
- else
826
- @vector_length = 1
827
- end
828
- end
829
- def decl
830
- return "real(kind=#{@size})" if BOAST::get_lang == FORTRAN
831
- if [C, CL, CUDA].include?( BOAST::get_lang ) and @vector_length == 1 then
832
- return "float" if @size == 4
833
- return "double" if @size == 8
834
- elsif [CL, CUDA].include?(BOAST::get_lang) and @vector_length > 1 then
835
- return "float#{@vector_length}" if @size == 4
836
- return "double#{@vector_length}" if @size == 8
837
- end
838
- end
839
- end
840
-
841
747
  class CodeBlock
842
748
  def initialize(&block)
843
749
  @block = block
@@ -968,18 +874,25 @@ module BOAST
968
874
  if BOAST::get_lang == CL then
969
875
  if not @properties[:local] then
970
876
  s += "__kernel "
971
- end
972
- wgs = @properties[:reqd_work_group_size]
973
- if wgs then
974
- s += "__attribute__((reqd_work_group_size(#{wgs[0]},#{wgs[1]},#{wgs[2]}))) "
877
+ wgs = @properties[:reqd_work_group_size]
878
+ if wgs then
879
+ s += "__attribute__((reqd_work_group_size(#{wgs[0]},#{wgs[1]},#{wgs[2]}))) "
880
+ end
975
881
  end
976
882
  elsif BOAST::get_lang == CUDA then
977
883
  if @properties[:local] then
978
- s += "__device__ "
884
+ s += "static __device__ "
979
885
  else
980
886
  s += "__global__ "
887
+ wgs = @properties[:reqd_work_group_size]
888
+ if wgs then
889
+ s += "__launch_bounds__(#{wgs[0]}*#{wgs[1]}*#{wgs[2]}) "
890
+ end
981
891
  end
982
892
  end
893
+ if @properties[:qualifiers] then
894
+ s += "#{@properties[:qualifiers]} "
895
+ end
983
896
  if @properties[:return] then
984
897
  s += "#{@properties[:return].type.decl} "
985
898
  else
@@ -1077,67 +990,6 @@ module BOAST
1077
990
  end
1078
991
  end
1079
992
 
1080
- class Sizet
1081
- def self.parens(*args,&block)
1082
- return Variable::new(args[0], self, *args[1..-1], &block)
1083
- end
1084
-
1085
- attr_reader :signed
1086
- def initialize(hash={})
1087
- if hash[:signed] != nil then
1088
- @signed = hash[:signed]
1089
- end
1090
- end
1091
- def decl
1092
- return "integer(kind=#{BOAST::get_default_int_size})" if BOAST::get_lang == FORTRAN
1093
- if not @signed then
1094
- return "size_t" if [C, CL, CUDA].include?( BOAST::get_lang )
1095
- else
1096
- return "ptrdiff_t" if [C, CL, CUDA].include?( BOAST::get_lang )
1097
- end
1098
- end
1099
- end
1100
-
1101
- class Int
1102
- def self.parens(*args,&block)
1103
- return Variable::new(args[0], self, *args[1..-1], &block)
1104
- end
1105
-
1106
- attr_reader :size
1107
- attr_reader :signed
1108
- def initialize(hash={})
1109
- if hash[:size] then
1110
- @size = hash[:size]
1111
- else
1112
- @size = BOAST::get_default_int_size
1113
- end
1114
- if hash[:signed] != nil then
1115
- @signed = hash[:signed]
1116
- else
1117
- @signed = BOAST::get_default_int_signed
1118
- end
1119
- end
1120
- def decl
1121
- return "integer(kind=#{@size})" if BOAST::get_lang == FORTRAN
1122
- return "int#{8*@size}_t" if BOAST::get_lang == C
1123
- if BOAST::get_lang == CL then
1124
- #char="cl_"
1125
- char=""
1126
- char += "u" if not @signed
1127
- return char += "char" if @size==1
1128
- return char += "short" if @size==2
1129
- return char += "int" if @size==4
1130
- return char += "long" if @size==8
1131
- elsif BOAST::get_lang == CUDA then
1132
- char = ""
1133
- char += "unsigned " if not @signed
1134
- return char += "char" if @size==1
1135
- return char += "short" if @size==2
1136
- return char += "int" if @size==4
1137
- return char += "long long" if @size==8
1138
- end
1139
- end
1140
- end
1141
993
 
1142
994
  class ConstArray < Array
1143
995
  def initialize(array,type = nil)
@@ -0,0 +1,318 @@
1
+ module BOAST
2
+
3
+ class Sizet
4
+ def self.parens(*args,&block)
5
+ return Variable::new(args[0], self, *args[1..-1], &block)
6
+ end
7
+
8
+ attr_reader :signed
9
+ attr_reader :size
10
+ attr_reader :vector_length
11
+ def initialize(hash={})
12
+ if hash[:signed] != nil then
13
+ @signed = hash[:signed]
14
+ end
15
+ @size = nil
16
+ @vector_length = 1
17
+ end
18
+
19
+ def to_hash
20
+ return { :signed => @signed }
21
+ end
22
+
23
+ def copy(options={})
24
+ hash = self.to_hash
25
+ options.each { |k,v|
26
+ hash[k] = v
27
+ }
28
+ return Sizet::new(hash)
29
+ end
30
+
31
+ def decl
32
+ return "integer(kind=#{BOAST::get_default_int_size})" if BOAST::get_lang == FORTRAN
33
+ if not @signed then
34
+ return "size_t" if [C, CL, CUDA].include?( BOAST::get_lang )
35
+ else
36
+ return "ptrdiff_t" if [C, CL, CUDA].include?( BOAST::get_lang )
37
+ end
38
+ end
39
+ end
40
+
41
+ class Real
42
+ def self.parens(*args,&block)
43
+ return Variable::new(args[0], self, *args[1..-1], &block)
44
+ end
45
+
46
+ attr_reader :size
47
+ attr_reader :signed
48
+ attr_reader :vector_length
49
+ attr_reader :total_size
50
+ attr_reader :getters
51
+ attr_reader :setters
52
+
53
+ def ==(t)
54
+ return true if t.class == self.class and t.size == self.size and t.vector_length == self.vector_length
55
+ return false
56
+ end
57
+
58
+ def initialize(hash={})
59
+ if hash[:size] then
60
+ @size = hash[:size]
61
+ else
62
+ @size = BOAST::get_default_real_size
63
+ end
64
+ # @getters = {}
65
+ # @setters = {}
66
+ if hash[:vector_length] and hash[:vector_length] > 1 then
67
+ @vector_length = hash[:vector_length]
68
+ # @vector_length.times{ |indx|
69
+ # @getters["s#{indx}"] = indx
70
+ # @setters["s#{indx}="] = indx
71
+ # }
72
+ else
73
+ @vector_length = 1
74
+ end
75
+ @total_size = @vector_length*@size
76
+ @signed = true
77
+ end
78
+
79
+ def to_hash
80
+ return { :size => @size, :vector_length => @vector_length }
81
+ end
82
+
83
+ def copy(options={})
84
+ hash = to_hash
85
+ options.each { |k,v|
86
+ hash[k] = v
87
+ }
88
+ return Real::new(hash)
89
+ end
90
+
91
+ def decl
92
+ return "real(kind=#{@size})" if BOAST::get_lang == FORTRAN
93
+ if [C, CL, CUDA].include?( BOAST::get_lang ) and @vector_length == 1 then
94
+ return "float" if @size == 4
95
+ return "double" if @size == 8
96
+ elsif BOAST::get_lang == C and @vector_length > 1 then
97
+ if BOAST::get_architecture == BOAST::X86 then
98
+ return "__m#{@total_size*8}" if @size == 4
99
+ return "__m#{@total_size*8}d" if @size == 8
100
+ elsif BOAST::get_architecture == BOAST::ARM then
101
+ raise "Unsupported data type in NEON: double!" if @size == 8
102
+ raise "Unsupported vector length in NEON: #{@total_size} (#{@size} x 8 x #{@vector_length})!" if @total_size * 8 != 64 or @total_size * 8 != 128
103
+ return "float#{@size*8}x#{@vector_length}_t"
104
+ else
105
+ raise "Unsupported architecture!"
106
+ end
107
+ elsif [CL, CUDA].include?( BOAST::get_lang ) and @vector_length > 1 then
108
+ return "float#{@vector_length}" if @size == 4
109
+ return "double#{@vector_length}" if @size == 8
110
+ end
111
+ end
112
+ end
113
+
114
+ class Int
115
+ def self.parens(*args,&block)
116
+ return Variable::new(args[0], self, *args[1..-1], &block)
117
+ end
118
+
119
+ attr_reader :size
120
+ attr_reader :signed
121
+ attr_reader :vector_length
122
+ attr_reader :total_size
123
+
124
+ def ==(t)
125
+ return true if t.class == self.class and t.signed == self.signed and t.size == self.size and t.vector_length == self.vector_length
126
+ return false
127
+ end
128
+
129
+ def initialize(hash={})
130
+ if hash[:size] then
131
+ @size = hash[:size]
132
+ else
133
+ @size = BOAST::get_default_int_size
134
+ end
135
+ if hash[:signed] != nil then
136
+ @signed = hash[:signed]
137
+ else
138
+ @signed = BOAST::get_default_int_signed
139
+ end
140
+ # @getters = {}
141
+ # @setters = {}
142
+ if hash[:vector_length] and hash[:vector_length] > 1 then
143
+ @vector_length = hash[:vector_length]
144
+ # @vector_length.times{ |indx|
145
+ # @getters["s#{indx}"] = indx
146
+ # @setters["s#{indx}="] = indx
147
+ # }
148
+ else
149
+ @vector_length = 1
150
+ end
151
+ @total_size = @vector_length*@size
152
+ end
153
+
154
+ def to_hash
155
+ return { :size => @size, :vector_length => @vector_length, :signed => @signed }
156
+ end
157
+
158
+ def copy(options={})
159
+ hash = self.to_hash
160
+ options.each { |k,v|
161
+ hash[k] = v
162
+ }
163
+ return Int::new(hash)
164
+ end
165
+
166
+ def decl
167
+ return "integer(kind=#{@size})" if BOAST::get_lang == FORTRAN
168
+ if BOAST::get_lang == C then
169
+ if @vector_length == 1 then
170
+ s = ""
171
+ s += "u" if not @signed
172
+ return s+"int#{8*@size}_t"
173
+ elsif @vector_length > 1 then
174
+ if BOAST::get_architecture == BOAST::X86 then
175
+ return "__m#{@total_size*8}#{@total_size*8>64 ? "i" : ""}"
176
+ elsif BOAST::get_architecture == BOAST::ARM then
177
+ raise "Unsupported vector length in NEON: #{@total_size*8} (#{@size} x 8 x #{@vector_length})!" if @total_size * 8 != 64 and @total_size * 8 != 128
178
+ return "#{ @signed ? "" : "u"}int#{@size*8}x#{@vector_length}_t"
179
+ else
180
+ raise "Unsupported architecture!"
181
+ end
182
+ end
183
+ elsif BOAST::get_lang == CL then
184
+ #char="cl_"
185
+ char=""
186
+ char += "u" if not @signed
187
+ case @size
188
+ when 1
189
+ char += "char"
190
+ when 2
191
+ char += "short"
192
+ when 4
193
+ char += "int"
194
+ when 8
195
+ char += "long"
196
+ else
197
+ raise "Unsupported integer size!"
198
+ end
199
+ if @vector_length > 1 then
200
+ char += "#{@vector_length}"
201
+ end
202
+ return char
203
+ elsif BOAST::get_lang == CUDA then
204
+ if @vector_length > 1 then
205
+ char=""
206
+ char += "u" if not @signed
207
+ case @size
208
+ when 1
209
+ char += "char"
210
+ when 2
211
+ char += "short"
212
+ when 4
213
+ char += "int"
214
+ when 8
215
+ char += "longlong"
216
+ else
217
+ raise "Unsupported integer size!"
218
+ end
219
+ return char + "#{@vector_length}"
220
+ else
221
+ char = ""
222
+ char += "unsigned " if not @signed
223
+ return char += "char" if @size==1
224
+ return char += "short" if @size==2
225
+ return char += "int" if @size==4
226
+ return char += "long long" if @size==8
227
+ end
228
+ end
229
+ end
230
+ end
231
+
232
+ class CStruct
233
+ attr_reader :name, :members, :members_array
234
+ def self.parens(*args,&block)
235
+ return Variable::new(args[0], self, *args[1..-1], &block)
236
+ end
237
+
238
+ def initialize(hash={})
239
+ @name = hash[:type_name]
240
+ @members = {}
241
+ @members_array = []
242
+ hash[:members].each { |m|
243
+ mc = m.copy
244
+ @members_array.push(mc)
245
+ @members[mc.name] = mc
246
+ }
247
+ end
248
+
249
+ def decl
250
+ return "struct #{@name}" if [C, CL, CUDA].include?( BOAST::get_lang )
251
+ return "TYPE(#{@name})" if BOAST::get_lang == FORTRAN
252
+ end
253
+
254
+ def finalize
255
+ s = ""
256
+ s += ";" if [C, CL, CUDA].include?( BOAST::get_lang )
257
+ s+="\n"
258
+ return s
259
+ end
260
+
261
+ def indent
262
+ return " "*BOAST::get_indent_level
263
+ end
264
+
265
+ def header
266
+ return header_c if [C, CL, CUDA].include?( BOAST::get_lang )
267
+ return header_fortran if BOAST::get_lang == FORTRAN
268
+ raise "Unsupported language!"
269
+ end
270
+
271
+ def header_c(final = true)
272
+ s = ""
273
+ s += self.indent if final
274
+ s += self.decl + " {\n"
275
+ @members_array.each { |value|
276
+ s+= self.indent if final
277
+ s+= " "*BOAST::get_indent_increment + value.decl(false)+";\n"
278
+ }
279
+ s += self.indent if final
280
+ s += "}"
281
+ s += self.finalize if final
282
+ BOAST::get_output.print s if final
283
+ return s
284
+ end
285
+
286
+ def header_fortran(final = true)
287
+ s = ""
288
+ s += self.indent if final
289
+ s += "TYPE :: #{@name}\n"
290
+ members_array.each { |value|
291
+ s+= self.indent if final
292
+ s+= " "*BOAST::get_indent_increment + value.decl(false)+"\n"
293
+ }
294
+ s += self.indent if final
295
+ s += "END TYPE #{@name}"
296
+ s += self.finalize if final
297
+ BOAST::get_output.print s if final
298
+ return s
299
+ end
300
+
301
+ end
302
+
303
+ class CustomType
304
+ attr_reader :size, :name, :vector_length
305
+ def initialize(hash={})
306
+ @name = hash[:type_name]
307
+ @size = hash[:size]
308
+ @size = 0 if @size.nil?
309
+ @vector_length = hash[:vector_length]
310
+ @vector_length = 1 if @vector_length.nil?
311
+ @total_size = @vector_length*@size
312
+ end
313
+ def decl
314
+ return "#{@name}" if [C, CL, CUDA].include?( BOAST::get_lang )
315
+ end
316
+ end
317
+
318
+ end
@@ -0,0 +1,391 @@
1
+ module BOAST
2
+
3
+ class Operator
4
+ def Operator.get_vector_name(type)
5
+ case BOAST::get_architecture
6
+ when X86
7
+ case type
8
+ when Int
9
+ size = "#{type.size*8}"
10
+ name = ""
11
+ if type.total_size*8 > 64
12
+ name += "e"
13
+ end
14
+ if type.vector_length > 1 then
15
+ name += "p"
16
+ else
17
+ name = "s"
18
+ end
19
+ if type.signed then
20
+ name += "i"
21
+ else
22
+ name += "u"
23
+ end
24
+ return name += size
25
+ when Real
26
+ case type.size
27
+ when 4
28
+ return "ps" if type.vector_length > 1
29
+ return "ss"
30
+ when 8
31
+ return "pd" if type.vector_length > 1
32
+ return "sd"
33
+ end
34
+ else
35
+ raise "Undefined vector type!"
36
+ end
37
+ when ARM
38
+ case type
39
+ when Int
40
+ name = "#{ type.signed ? "s" : "u" }"
41
+ name += "#{ type.size * 8}"
42
+ return name
43
+ when Real
44
+ return "f#{type.size*8}"
45
+ else
46
+ raise "Undefined vector type!"
47
+ end
48
+ else
49
+ raise "Unsupported architecture!"
50
+ end
51
+ end
52
+
53
+ def Operator.convert(arg, type)
54
+ case BOAST::get_architecture
55
+ when X86
56
+ s1 = arg.type.total_size*8
57
+ s2 = type.total_size*8
58
+ n1 = get_vector_name(arg.type)
59
+ n2 = get_vector_name(type)
60
+ if s1 <= 128 and s2 <= 128 then
61
+ return "_mm_cvt#{n1}_#{n2}( #{arg} )"
62
+ elsif [s1, s2].max <= 256 then
63
+ return "_mm256_cvt#{n1}_#{n2}( #{arg} )"
64
+ elsif [s1, s2].max <= 512 then
65
+ return "_mm512_cvt#{n1}_#{n2}( #{arg} )"
66
+ end
67
+ when ARM
68
+ if type.class != arg.type.class then
69
+ if type.size == arg.type.size then
70
+ s = type.total_size*8
71
+ n1 = get_vector_name(arg.type)
72
+ n2 = get_vector_name(type)
73
+ return "vcvt#{ s == 128 ? "q" : "" }_#{n2}_#{n1}( #{arg} )"
74
+ elsif type.class == Real then
75
+ intr = convert(arg, arg.type.copy(:size=>type.size))
76
+ return convert(arg.copy(intr, :size => type.size ), type)
77
+ else
78
+ n1 = get_vector_name(arg.type)
79
+ s = type.total_size*8
80
+ t2 = type.copy(:size => arg.type.size)
81
+ n2 = get_vector_name( t2 )
82
+ intr = "vcvt#{ s == 128 ? "q" : "" }_#{n2}_#{n1}( #{arg} )"
83
+ return convert(Variable::from_type(intr, t2), type)
84
+ end
85
+ elsif type.class != Real then
86
+ n = get_vector_name(arg.type)
87
+ if type.size == arg.type.size then
88
+ if type.signed == arg.type.signed then
89
+ return "#{arg}"
90
+ else
91
+ n2 = get_vector_name(type)
92
+ return "vreinterpret_#{n2}_#{n}( #{arg} )"
93
+ end
94
+ elsif type.size < arg.type.size then
95
+ intr = "vmovn_#{n}( #{arg} )"
96
+ s = arg.type.size/2
97
+ else
98
+ intr = "vmovl_#{n}( #{arg} )"
99
+ s = arg.type.size*2
100
+ end
101
+ return convert(arg.copy(intr, :size => s), type)
102
+ end
103
+ else
104
+ raise "Unsupported architecture!"
105
+ end
106
+ end
107
+ end
108
+
109
+ class BasicBinaryOperator < Operator
110
+
111
+ def BasicBinaryOperator.to_s(arg1, arg2, return_type)
112
+ #puts "#{arg1.class} * #{arg2.class} : #{arg1} * #{arg2}"
113
+ if BOAST::get_lang == C and (arg1.class == Variable and arg2.class == Variable) and (arg1.type.vector_length > 1 or arg2.type.vector_length > 1) then
114
+ raise "Vectors have different length: #{arg1} #{arg1.type.vector_length}, #{arg2} #{arg2.type.vector_length}" if arg1.type.vector_length != arg2.type.vector_length
115
+ #puts "#{arg1.type.signed} #{arg2.type.signed} #{return_type.type.signed}"
116
+ return_name = get_vector_name(return_type.type)
117
+ size = return_type.type.total_size * 8
118
+ case BOAST::get_architecture
119
+ when X86
120
+ if arg1.type != return_type.type
121
+ a1 = convert(arg1, return_type.type)
122
+ else
123
+ a1 = "#{arg1}"
124
+ end
125
+ if arg2.type != return_type.type
126
+ a2 = convert(arg2, return_type.type)
127
+ else
128
+ a2 = "#{arg2}"
129
+ end
130
+ intr_name = "_mm"
131
+ if size > 128 then
132
+ intr_name += "#{size}"
133
+ end
134
+ intr_name += "_#{intr_name_X86}_#{return_name}"
135
+ return "#{intr_name}( #{a1}, #{a2} )"
136
+ when ARM
137
+ if arg1.type.class != return_type.type.class then
138
+ a1 = convert(arg1, return_type.type)
139
+ else
140
+ a1 = "#{arg1}"
141
+ end
142
+ if arg2.type.class != return_type.type.class then
143
+ a2 = convert(arg2, return_type.type)
144
+ else
145
+ a2 = "#{arg2}"
146
+ end
147
+ intr_name = "#{intr_name_ARM}"
148
+ intr_name += "q" if size == 128
149
+ intr_name += "_" + return_name + "( #{a1}, #{a2} )"
150
+ return intr_name
151
+ else
152
+ raise "Unsupported architecture!"
153
+ end
154
+ else
155
+ return basic_usage( arg1, arg2 )
156
+ end
157
+ end
158
+ end
159
+
160
+ class Set < Operator
161
+
162
+ def Set.to_s(arg1, arg2, return_type)
163
+ if BOAST::get_lang == C then
164
+ if arg1.class == Variable and arg1.type.vector_length > 1 then
165
+ if arg1.type == arg2.type then
166
+ return basic_usage(arg1, arg2)
167
+ elsif arg1.type.vector_length == arg2.type.vector_length then
168
+ return "(#{arg1} = #{convert(arg2, arg1.type)})"
169
+ elsif arg2.type.vector_length == 1 then
170
+ size = arg1.type.total_size*8
171
+ case BOAST::get_architecture
172
+ when ARM
173
+ intr_name = "vmov"
174
+ intr_name += "q" if size == 128
175
+ intr_name += "_n_#{get_vector_name(arg1.type)}"
176
+ when X86
177
+ return "(#{arg1} = _m_from_int64( #{a2} ))" if arg1.type.class == Int and arg1.type.size == 8 and size == 64
178
+ intr_name = "_mm"
179
+ if size > 128 then
180
+ intr_name += "#{size}"
181
+ end
182
+ intr_name += "_set1_#{get_vector_name(arg1.type).gsub("u","")}"
183
+ intr_name += "x" if arg1.type.class == Int and arg1.type.size == 8
184
+ else
185
+ raise "Unsupported architecture!"
186
+ end
187
+ return "(#{arg1} = #{intr_name}( #{arg2} ))"
188
+ else
189
+ raise "Unknown convertion between vector of different length!"
190
+ end
191
+ else
192
+ return basic_usage(arg1, arg2)
193
+ end
194
+ else
195
+ return basic_usage(arg1, arg2)
196
+ end
197
+ end
198
+
199
+ def Set.basic_usage(arg1, arg2)
200
+ return "(#{arg1} = #{arg2})"
201
+ end
202
+ end
203
+
204
+ class Affectation < Operator
205
+ def Affectation.to_s(arg1, arg2, return_type)
206
+ if BOAST::get_lang == C then
207
+ if arg1.class == Variable and arg1.type.vector_length > 1 then
208
+ #puts "#{arg1.type.vector_length} #{arg2.type.vector_length}"
209
+ if arg1.type == arg2.type then
210
+ return basic_usage(arg1, arg2)
211
+ elsif arg1.type.vector_length == arg2.type.vector_length then
212
+ return "#{arg1} = #{convert(arg2, arg1.type)}"
213
+ elsif arg2.type.vector_length == 1 then
214
+ size = arg1.type.total_size*8
215
+ a2 = "#{arg2}"
216
+ if a2[0] != "*" then
217
+ a2 = "&" + a2
218
+ else
219
+ a2 = a2[1..-1]
220
+ end
221
+ case BOAST::get_architecture
222
+ when ARM
223
+ intr_name = "vldl"
224
+ intr_name += "q" if size == 128
225
+ intr_name += "_#{get_vector_name(arg1.type)}"
226
+ when X86
227
+ if arg1.type.class == Int and size == 64 then
228
+ return "#{arg1} = _m_from_int64( *((int64_t * ) #{a2} ) )"
229
+ end
230
+ intr_name = "_mm"
231
+ if size > 128 then
232
+ intr_name += "#{size}"
233
+ end
234
+ intr_name += "_load_"
235
+ if arg1.type.class == Int then
236
+ intr_name += "si#{size}"
237
+ else
238
+ intr_name += "#{get_vector_name(arg1.type)}"
239
+ end
240
+ else
241
+ raise "Unsupported architecture!"
242
+ end
243
+ return "#{arg1} = #{intr_name}( (#{arg1.type.decl} * ) #{a2} )"
244
+ else
245
+ raise "Unknown convertion between vectors of different length!"
246
+ end
247
+ elsif arg2.class == Variable and arg2.type.vector_length > 1 then
248
+ size = arg2.type.total_size*8
249
+ a1 = "#{arg1}"
250
+ if a1[0] != "*" then
251
+ a1 = "&" + a1
252
+ else
253
+ a1 = a1[1..-1]
254
+ end
255
+ case BOAST::get_architecture
256
+ when ARM
257
+ intr_name = "vstl"
258
+ intr_name += "q" if size == 128
259
+ intr_name += "_#{get_vector_name(arg2.type)}"
260
+ when X86
261
+ if arg2.type.class == Int and size == 64 then
262
+ return " *((int64_t * ) #{a1}) = _m_to_int64( #{arg2} )"
263
+ end
264
+ intr_name = "_mm"
265
+ if size > 128 then
266
+ intr_name += "#{size}"
267
+ end
268
+ intr_name += "_store_"
269
+ if arg2.type.class == Int then
270
+ intr_name += "si#{size}"
271
+ else
272
+ intr_name += "#{get_vector_name(arg2.type)}"
273
+ end
274
+ else
275
+ raise "Unsupported architecture!"
276
+ end
277
+ return "#{intr_name}((#{arg2.type.decl} * ) #{a1}, #{arg2} )"
278
+ else
279
+ return basic_usage(arg1, arg2)
280
+ end
281
+ else
282
+ return basic_usage(arg1, arg2)
283
+ end
284
+ end
285
+
286
+ def Affectation.basic_usage(arg1, arg2)
287
+ return "#{arg1} = #{arg2}"
288
+ end
289
+ end
290
+
291
+ class Multiplication < BasicBinaryOperator
292
+ class << self
293
+
294
+ def symbol
295
+ return "*"
296
+ end
297
+
298
+ def intr_name_X86
299
+ return "mul"
300
+ end
301
+
302
+ def intr_name_ARM
303
+ return "vmul"
304
+ end
305
+
306
+ def basic_usage(arg1, arg2)
307
+ return "(#{arg1}) * (#{arg2})"
308
+ end
309
+
310
+ end
311
+ end
312
+
313
+ class Addition < BasicBinaryOperator
314
+ class << self
315
+
316
+ def symbol
317
+ return "+"
318
+ end
319
+
320
+ def intr_name_X86
321
+ return "add"
322
+ end
323
+
324
+ def intr_name_ARM
325
+ return "vadd"
326
+ end
327
+
328
+ def basic_usage(arg1, arg2)
329
+ return "#{arg1} + #{arg2}"
330
+ end
331
+
332
+ end
333
+ end
334
+
335
+ class Substraction < BasicBinaryOperator
336
+ class << self
337
+
338
+ def symbol
339
+ return "-"
340
+ end
341
+
342
+ def intr_name_X86
343
+ return "sub"
344
+ end
345
+
346
+ def intr_name_ARM
347
+ return "vsub"
348
+ end
349
+
350
+ def basic_usage(arg1, arg2)
351
+ return "#{arg1} - (#{arg2})"
352
+ end
353
+
354
+ end
355
+ end
356
+
357
+ class Division < BasicBinaryOperator
358
+ class << self
359
+
360
+ def symbol
361
+ return "/"
362
+ end
363
+
364
+ def intr_name_X86
365
+ return "div"
366
+ end
367
+
368
+ def intr_name_ARM
369
+ raise "Neon doesn't support division!"
370
+ end
371
+
372
+ def basic_usage(arg1, arg2)
373
+ return "(#{arg1}) / (#{arg2})"
374
+ end
375
+
376
+ end
377
+ end
378
+
379
+ class Minus < Operator
380
+ def Minus.to_s(arg1, arg2, return_type)
381
+ return " -(#{arg2})"
382
+ end
383
+ end
384
+
385
+ class Not < Operator
386
+ def Not.to_s(arg1, arg2, return_type)
387
+ return " ! #{arg2}"
388
+ end
389
+ end
390
+
391
+ end
@@ -20,15 +20,15 @@ module BOAST
20
20
  def transition(var1, var2, operator)
21
21
  signed = false
22
22
  size = nil
23
+ vector_length = 1
23
24
  return_type, operator = get_transition(var1.type.class, var2.type.class, operator)
24
25
  #STDERR.puts "#{return_type} : #{var1.type.class} #{operator} #{var2.type.class}"
25
26
  if var1.type.class == return_type and var2.type.class == return_type then
26
- signed = signed or var1.type.signed if var1.type.respond_to?(:signed)
27
- signed = signed or var2.type.signed if var2.type.respond_to?(:signed)
28
- if var1.type.respond_to?(:size) and var2.type.respond_to?(:size) then
29
- size = [var1.type.size, var2.type.size].max
30
- end
31
- [BOAST::Variable::new("dummy", return_type, :size => size, :signed => signed), operator]
27
+ signed = (signed or var1.type.signed)
28
+ signed = (signed or var2.type.signed)
29
+ size = [var1.type.size, var2.type.size].max
30
+ vector_length = [var1.type.vector_length, var2.type.vector_length].max
31
+ [BOAST::Variable::new("dummy", return_type, :size => size, :signed => signed, :vector_length => vector_length), operator]
32
32
  elsif var1.type.class == return_type then
33
33
  return [var1, operator]
34
34
  elsif var2.type.class == return_type then
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: BOAST
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.6'
4
+ version: '0.7'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-14 00:00:00.000000000 Z
12
+ date: 2014-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: narray
@@ -74,6 +74,8 @@ files:
74
74
  - lib/BOAST/BOAST_OpenCL.rb
75
75
  - lib/BOAST/Transitions.rb
76
76
  - lib/BOAST/Parens.rb
77
+ - lib/BOAST/Operators.rb
78
+ - lib/BOAST/DataTypes.rb
77
79
  homepage: https://forge.imag.fr/projects/boast/
78
80
  licenses:
79
81
  - BSD