BOAST 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
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