BOAST 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/BOAST.gemspec +2 -31
  3. data/README.md +240 -0
  4. data/lib/BOAST/{OpenMP.rb → Language/OpenMP.rb} +1 -0
  5. data/lib/BOAST/{Variable.rb → Language/Variable.rb} +2 -1
  6. data/lib/BOAST/Runtime/CKernel.rb +94 -0
  7. data/lib/BOAST/Runtime/CRuntime.rb +32 -0
  8. data/lib/BOAST/Runtime/CUDARuntime.rb +158 -0
  9. data/lib/BOAST/Runtime/CompiledRuntime.rb +398 -0
  10. data/lib/BOAST/Runtime/Compilers.rb +205 -0
  11. data/lib/BOAST/Runtime/Config.rb +94 -0
  12. data/lib/BOAST/Runtime/FFIRuntime.rb +104 -0
  13. data/lib/BOAST/Runtime/FORTRANRuntime.rb +45 -0
  14. data/lib/BOAST/Runtime/MPPARuntime.rb +464 -0
  15. data/lib/BOAST/Runtime/NonRegression.rb +157 -0
  16. data/lib/BOAST/Runtime/OpenCLRuntime.rb +181 -0
  17. data/lib/BOAST/Runtime/Probe.rb +136 -0
  18. data/lib/BOAST.rb +37 -26
  19. metadata +40 -28
  20. data/lib/BOAST/CKernel.rb +0 -1236
  21. /data/lib/BOAST/{Algorithm.rb → Language/Algorithm.rb} +0 -0
  22. /data/lib/BOAST/{Arithmetic.rb → Language/Arithmetic.rb} +0 -0
  23. /data/lib/BOAST/{BOAST_OpenCL.rb → Language/BOAST_OpenCL.rb} +0 -0
  24. /data/lib/BOAST/{Case.rb → Language/Case.rb} +0 -0
  25. /data/lib/BOAST/{ControlStructure.rb → Language/ControlStructure.rb} +0 -0
  26. /data/lib/BOAST/{DataTypes.rb → Language/DataTypes.rb} +0 -0
  27. /data/lib/BOAST/{Expression.rb → Language/Expression.rb} +0 -0
  28. /data/lib/BOAST/{For.rb → Language/For.rb} +0 -0
  29. /data/lib/BOAST/{FuncCall.rb → Language/FuncCall.rb} +0 -0
  30. /data/lib/BOAST/{Functors.rb → Language/Functors.rb} +0 -0
  31. /data/lib/BOAST/{If.rb → Language/If.rb} +0 -0
  32. /data/lib/BOAST/{Index.rb → Language/Index.rb} +0 -0
  33. /data/lib/BOAST/{Inspectable.rb → Language/Inspectable.rb} +0 -0
  34. /data/lib/BOAST/{Operators.rb → Language/Operators.rb} +0 -0
  35. /data/lib/BOAST/{Optimization.rb → Language/Optimization.rb} +0 -0
  36. /data/lib/BOAST/{Parens.rb → Language/Parens.rb} +0 -0
  37. /data/lib/BOAST/{Pragma.rb → Language/Pragma.rb} +0 -0
  38. /data/lib/BOAST/{Print.rb → Language/Print.rb} +0 -0
  39. /data/lib/BOAST/{Procedure.rb → Language/Procedure.rb} +0 -0
  40. /data/lib/BOAST/{Slice.rb → Language/Slice.rb} +0 -0
  41. /data/lib/BOAST/{State.rb → Language/State.rb} +0 -0
  42. /data/lib/BOAST/{Transitions.rb → Language/Transitions.rb} +0 -0
  43. /data/lib/BOAST/{While.rb → Language/While.rb} +0 -0
@@ -0,0 +1,398 @@
1
+ require 'stringio'
2
+ require 'rake'
3
+ require 'tempfile'
4
+ require 'rbconfig'
5
+ require 'systemu'
6
+ require 'pathname'
7
+ require 'os'
8
+
9
+ class Dir
10
+ module Tmpname
11
+ module_function
12
+ def make_tmpname(prefix_suffix, n)
13
+ case prefix_suffix
14
+ when String
15
+ prefix = prefix_suffix
16
+ suffix = ""
17
+ when Array
18
+ prefix = prefix_suffix[0]
19
+ suffix = prefix_suffix[1]
20
+ else
21
+ raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
22
+ end
23
+ t = Time.now.strftime("%Y%m%d")
24
+ path = "#{prefix}#{t}_#{$$}_#{rand(0x100000000).to_s(36)}"
25
+ path << "_#{n}" if n
26
+ path << suffix
27
+ end
28
+ end
29
+ end
30
+
31
+ module BOAST
32
+
33
+ module CompiledRuntime
34
+ @@extensions = {
35
+ C => ".c",
36
+ CUDA => ".cu",
37
+ FORTRAN => ".f90"
38
+ }
39
+
40
+ def base_name
41
+ return File::split(@marker.path)[1]
42
+ end
43
+
44
+ def module_name
45
+ return "Mod_" + base_name#.gsub("-","_")
46
+ end
47
+
48
+ def directory
49
+ return File::split(@marker.path)[0]
50
+ end
51
+
52
+ def module_file_base_name
53
+ return "Mod_" + base_name
54
+ end
55
+
56
+ def module_file_base_path
57
+ return "#{directory}/#{module_file_base_name}"
58
+ end
59
+
60
+ def module_file_path
61
+ return "#{module_file_base_path}.#{RbConfig::CONFIG["DLEXT"]}"
62
+ end
63
+
64
+ def module_file_source
65
+ return module_file_base_path + ".c"
66
+ end
67
+
68
+ def module_file_object
69
+ return "#{module_file_base_path}.#{RbConfig::CONFIG["OBJEXT"]}"
70
+ end
71
+
72
+ def base_path
73
+ return "#{directory}/#{base_name}"
74
+ end
75
+
76
+ def library_source
77
+ return base_path + @@extensions[@lang]
78
+ end
79
+
80
+ def library_object
81
+ return "#{base_path}.#{RbConfig::CONFIG["OBJEXT"]}"
82
+ end
83
+
84
+ def library_path
85
+ return "#{base_path}.#{RbConfig::CONFIG["DLEXT"]}"
86
+ end
87
+
88
+ def target
89
+ return module_file_path
90
+ end
91
+
92
+ def target_depends
93
+ return [ module_file_object, library_object ]
94
+ end
95
+
96
+ def save_binary
97
+ f = File::open(library_object,"rb")
98
+ @binary = StringIO::new
99
+ @binary.write( f.read )
100
+ f.close
101
+ end
102
+
103
+ def create_targets( linker, ldshared, ldflags, kernel_files)
104
+ file target => target_depends do
105
+ #puts "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
106
+ sh "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
107
+ end
108
+ Rake::Task[target].invoke
109
+ end
110
+
111
+ def method_name
112
+ return @procedure.name
113
+ end
114
+
115
+ def get_sub_kernels
116
+ kernel_files = []
117
+ @kernels.each { |kernel|
118
+ kernel_file = Tempfile::new([kernel.procedure.name,".#{RbConfig::CONFIG["OBJEXT"]}"])
119
+ kernel.binary.rewind
120
+ kernel_file.write( kernel.binary.read )
121
+ kernel_file.close
122
+ kernel_files.push(kernel_file)
123
+ }
124
+ return kernel_files
125
+ end
126
+
127
+ def create_library_source
128
+ f = File::open(library_source,"w+")
129
+ previous_lang = get_lang
130
+ previous_output = get_output
131
+ set_output(f)
132
+ set_lang(@lang)
133
+
134
+ fill_library_source
135
+
136
+ if debug_source? then
137
+ f.rewind
138
+ puts f.read
139
+ end
140
+ set_output(previous_output)
141
+ set_lang(previous_lang)
142
+ f.close
143
+ end
144
+
145
+ def fill_module_header
146
+ get_output.print <<EOF
147
+ #include "ruby.h"
148
+ #include <inttypes.h>
149
+ #ifdef HAVE_NARRAY_H
150
+ #include "narray.h"
151
+ #endif
152
+ EOF
153
+ end
154
+
155
+ def fill_module_preamble
156
+ get_output.print <<EOF
157
+ VALUE #{module_name} = Qnil;
158
+ void Init_#{module_name}();
159
+ VALUE method_run(int _boast_argc, VALUE *_boast_argv, VALUE _boast_self);
160
+ void Init_#{module_name}() {
161
+ #{module_name} = rb_define_module("#{module_name}");
162
+ rb_define_method(#{module_name}, "run", method_run, -1);
163
+ }
164
+ EOF
165
+ end
166
+
167
+ def fill_check_args
168
+ get_output.print <<EOF
169
+ VALUE _boast_rb_opts;
170
+ if( _boast_argc < #{@procedure.parameters.length} || _boast_argc > #{@procedure.parameters.length + 1} )
171
+ rb_raise(rb_eArgError, "Wrong number of arguments for #{@procedure.name} (%d for #{@procedure.parameters.length})!", _boast_argc);
172
+ _boast_rb_opts = Qnil;
173
+ if( _boast_argc == #{@procedure.parameters.length + 1} ) {
174
+ _boast_rb_opts = _boast_argv[_boast_argc -1];
175
+ if ( _boast_rb_opts != Qnil ) {
176
+ if (TYPE(_boast_rb_opts) != T_HASH)
177
+ rb_raise(rb_eArgError, "Options should be passed as a hash");
178
+ }
179
+ }
180
+ EOF
181
+ end
182
+
183
+ def fill_decl_module_params
184
+ set_decl_module(true)
185
+ @procedure.parameters.each { |param|
186
+ param_copy = param.copy
187
+ param_copy.constant = nil
188
+ param_copy.direction = nil
189
+ param_copy.decl
190
+ }
191
+ get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
192
+ get_output.puts " VALUE _boast_stats = rb_hash_new();"
193
+ get_output.puts " VALUE _boast_rb_ptr = Qnil;"
194
+ refs = false
195
+ @procedure.parameters.each_with_index do |param,i|
196
+ refs = true if param.scalar_output?
197
+ end
198
+ if refs then
199
+ get_output.puts " VALUE _boast_refs = rb_hash_new();"
200
+ get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);"
201
+ end
202
+ set_decl_module(false)
203
+ end
204
+
205
+ def copy_scalar_param_from_ruby( param, ruby_param )
206
+ case param.type
207
+ when Int
208
+ (param === FuncCall::new("NUM2INT", ruby_param)).pr if param.type.size == 4
209
+ (param === FuncCall::new("NUM2LONG", ruby_param)).pr if param.type.size == 8
210
+ when Real
211
+ (param === FuncCall::new("NUM2DBL", ruby_param)).pr
212
+ end
213
+ end
214
+
215
+ def copy_array_param_from_ruby( param, ruby_param )
216
+ rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
217
+ (rb_ptr === ruby_param).pr
218
+ get_output.print <<EOF
219
+ if (TYPE(_boast_rb_ptr) == T_STRING) {
220
+ #{param} = (void *) RSTRING_PTR(_boast_rb_ptr);
221
+ } else if ( IsNArray(_boast_rb_ptr) ) {
222
+ struct NARRAY *_boast_n_ary;
223
+ Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
224
+ #{param} = (void *) _boast_n_ary->ptr;
225
+ } else {
226
+ rb_raise(rb_eArgError, "Wrong type of argument for %s, expecting array!", "#{param}");
227
+ }
228
+ EOF
229
+ end
230
+
231
+ def get_params_value
232
+ argc = @procedure.parameters.length
233
+ argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
234
+ rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
235
+ set_decl_module(true)
236
+ @procedure.parameters.each_index do |i|
237
+ param = @procedure.parameters[i]
238
+ if not param.dimension then
239
+ copy_scalar_param_from_ruby(param, argv[i])
240
+ else
241
+ copy_array_param_from_ruby(param, argv[i])
242
+ end
243
+ end
244
+ set_decl_module(false)
245
+ end
246
+
247
+ def create_procedure_call
248
+ get_output.print " _boast_ret = " if @procedure.properties[:return]
249
+ get_output.print " #{method_name}( "
250
+ get_output.print create_procedure_call_parameters.join(", ")
251
+ get_output.puts " );"
252
+ end
253
+
254
+ def copy_scalar_param_to_ruby(param, ruby_param)
255
+ if param.scalar_output? then
256
+ case param.type
257
+ when Int
258
+ get_output.puts " rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_int_new((long long)#{param}));" if param.type.signed?
259
+ get_output.puts " rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_int_new((unsigned long long)#{param}));" if not param.type.signed?
260
+ when Real
261
+ get_output.puts " rb_hash_aset(_boast_refs, ID2SYM(rb_intern(\"#{param}\")),rb_float_new((double)#{param}));"
262
+ end
263
+ end
264
+ end
265
+
266
+ def copy_array_param_to_ruby(param, ruby_param)
267
+ end
268
+
269
+ def get_results
270
+ argc = @procedure.parameters.length
271
+ argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
272
+ rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
273
+ set_decl_module(true)
274
+ @procedure.parameters.each_index do |i|
275
+ param = @procedure.parameters[i]
276
+ if not param.dimension then
277
+ copy_scalar_param_to_ruby(param, argv[i])
278
+ else
279
+ copy_array_param_to_ruby(param, argv[i])
280
+ end
281
+ end
282
+ set_decl_module(false)
283
+ end
284
+
285
+ def store_results
286
+ if @procedure.properties[:return] then
287
+ type_ret = @procedure.properties[:return].type
288
+ get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_int_new((long long)_boast_ret));" if type_ret.kind_of?(Int) and type_ret.signed
289
+ get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_int_new((unsigned long long)_boast_ret));" if type_ret.kind_of?(Int) and not type_ret.signed
290
+ get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"return\")),rb_float_new((double)_boast_ret));" if type_ret.kind_of?(Real)
291
+ end
292
+ end
293
+
294
+ def fill_module_file_source
295
+ fill_module_header
296
+ @probes.map(&:header)
297
+ @procedure.boast_header(@lang)
298
+
299
+ fill_module_preamble
300
+
301
+ set_transition("VALUE", "VALUE", :default, CustomType::new(:type_name => "VALUE"))
302
+ get_output.puts "VALUE method_run(int _boast_argc, VALUE *_boast_argv, VALUE _boast_self) {"
303
+ increment_indent_level
304
+
305
+ fill_check_args
306
+
307
+ fill_decl_module_params
308
+
309
+ @probes.reverse.map(&:decl)
310
+
311
+ get_params_value
312
+
313
+ @probes.map(&:configure)
314
+
315
+ @probes.reverse.map(&:start)
316
+
317
+ create_procedure_call
318
+
319
+ @probes.map(&:stop)
320
+
321
+ @probes.map(&:compute)
322
+
323
+ get_results
324
+
325
+ store_results
326
+
327
+ get_output.puts " return _boast_stats;"
328
+ decrement_indent_level
329
+ get_output.puts "}"
330
+ end
331
+
332
+ def create_module_file_source
333
+ f = File::open(module_file_source, "w+")
334
+ previous_lang = get_lang
335
+ previous_output = get_output
336
+ set_output(f)
337
+ set_lang(C)
338
+
339
+ fill_module_file_source
340
+
341
+ if debug_source? then
342
+ f.rewind
343
+ puts f.read
344
+ end
345
+ set_output(previous_output)
346
+ set_lang(previous_lang)
347
+ f.close
348
+ end
349
+
350
+ def create_sources
351
+ create_library_source
352
+ create_module_file_source
353
+ end
354
+
355
+ def load_module
356
+ require module_file_path
357
+ end
358
+
359
+ def target_sources
360
+ return [ module_file_source, library_source ]
361
+ end
362
+
363
+ def cleanup(kernel_files)
364
+ ([target] + target_depends + target_sources).each { |fn|
365
+ File::unlink(fn)
366
+ }
367
+ kernel_files.each { |f|
368
+ f.unlink
369
+ }
370
+ end
371
+
372
+ def build(options={})
373
+ compiler_options = BOAST::get_compiler_options
374
+ compiler_options.update(options)
375
+ linker, ldshared, ldflags = setup_compilers(compiler_options)
376
+
377
+ @marker = Tempfile::new([@procedure.name,""])
378
+
379
+ kernel_files = get_sub_kernels
380
+
381
+ create_sources
382
+
383
+ create_targets(linker, ldshared, ldflags, kernel_files)
384
+
385
+ save_binary
386
+
387
+ load_module
388
+
389
+ cleanup(kernel_files)
390
+
391
+ eval "self.extend(#{module_name})"
392
+
393
+ return self
394
+ end
395
+
396
+ end
397
+
398
+ end
@@ -0,0 +1,205 @@
1
+ require 'rake'
2
+ require 'rbconfig'
3
+ require 'systemu'
4
+ require 'os'
5
+
6
+ module BOAST
7
+
8
+ module Compilers
9
+ include Rake::DSL
10
+
11
+ def get_openmp_flags(compiler)
12
+ openmp_flags = BOAST::get_openmp_flags[compiler]
13
+ if not openmp_flags then
14
+ keys = BOAST::get_openmp_flags.keys
15
+ keys.each { |k|
16
+ openmp_flags = BOAST::get_openmp_flags[k] if compiler.match(k)
17
+ }
18
+ end
19
+ return openmp_flags
20
+ end
21
+
22
+ def get_includes(narray_path)
23
+ includes = "-I#{RbConfig::CONFIG["archdir"]}"
24
+ includes += " -I#{RbConfig::CONFIG["rubyhdrdir"]} -I#{RbConfig::CONFIG["rubyhdrdir"]}/#{RbConfig::CONFIG["arch"]}"
25
+ includes += " -I#{RbConfig::CONFIG["rubyarchhdrdir"]}" if RbConfig::CONFIG["rubyarchhdrdir"]
26
+ includes += " -I#{narray_path}" if narray_path
27
+ return includes
28
+ end
29
+
30
+ def get_narray_path
31
+ narray_path = nil
32
+ begin
33
+ spec = Gem::Specification::find_by_name('narray')
34
+ narray_path = spec.full_gem_path
35
+ rescue Gem::LoadError => e
36
+ rescue NoMethodError => e
37
+ spec = Gem::available?('narray')
38
+ if spec then
39
+ require 'narray'
40
+ narray_path = Gem.loaded_specs['narray'].full_gem_path
41
+ end
42
+ end
43
+ end
44
+
45
+ def setup_c_compiler(options, includes, narray_path, runner)
46
+ c_mppa_compiler = "k1-gcc"
47
+ c_compiler = options[:CC]
48
+ cflags = options[:CFLAGS]
49
+ cflags += " -fPIC #{includes}"
50
+ cflags += " -DHAVE_NARRAY_H" if narray_path
51
+ cflags += " -I/usr/local/k1tools/include" if @architecture == MPPA
52
+ objext = RbConfig::CONFIG["OBJEXT"]
53
+ if options[:openmp] and @lang == C then
54
+ openmp_cflags = get_openmp_flags(c_compiler)
55
+ raise "unkwown openmp flags for: #{c_compiler}" if not openmp_cflags
56
+ cflags += " #{openmp_cflags}"
57
+ end
58
+
59
+ rule ".#{objext}" => '.c' do |t|
60
+ c_call_string = "#{c_compiler} #{cflags} -c -o #{t.name} #{t.source}"
61
+ runner.call(t, c_call_string)
62
+ end
63
+
64
+ rule ".#{objext}io" => ".cio" do |t|
65
+ c_call_string = "#{c_mppa_compiler} -mcore=k1io -mos=rtems"
66
+ c_call_string += " -mboard=developer -x c -c -o #{t.name} #{t.source}"
67
+ runner.call(t, c_call_string)
68
+ end
69
+
70
+ rule ".#{objext}comp" => ".ccomp" do |t|
71
+ c_call_string = "#{c_mppa_compiler} -mcore=k1dp -mos=nodeos"
72
+ c_call_string += " -mboard=developer -x c -c -o #{t.name} #{t.source}"
73
+ runner.call(t, c_call_string)
74
+ end
75
+ end
76
+
77
+ def setup_cxx_compiler(options, includes, runner)
78
+ cxx_compiler = options[:CXX]
79
+ cxxflags = options[:CXXFLAGS]
80
+ cxxflags += " -fPIC #{includes}"
81
+ if options[:openmp] and @lang == C then
82
+ openmp_cxxflags = get_openmp_flags(cxx_compiler)
83
+ raise "unkwown openmp flags for: #{cxx_compiler}" if not openmp_cxxflags
84
+ cxxflags += " #{openmp_cxxflags}"
85
+ end
86
+
87
+ rule ".#{RbConfig::CONFIG["OBJEXT"]}" => '.cpp' do |t|
88
+ cxx_call_string = "#{cxx_compiler} #{cxxflags} -c -o #{t.name} #{t.source}"
89
+ runner.call(t, cxx_call_string)
90
+ end
91
+ end
92
+
93
+ def setup_fortran_compiler(options, runner)
94
+ f_compiler = options[:FC]
95
+ fcflags = options[:FCFLAGS]
96
+ fcflags += " -fPIC"
97
+ fcflags += " -fno-second-underscore" if f_compiler == 'g95'
98
+ if options[:openmp] and @lang == FORTRAN then
99
+ openmp_fcflags = get_openmp_flags(f_compiler)
100
+ raise "unkwown openmp flags for: #{f_compiler}" if not openmp_fcflags
101
+ fcflags += " #{openmp_fcflags}"
102
+ end
103
+
104
+ rule ".#{RbConfig::CONFIG["OBJEXT"]}" => '.f90' do |t|
105
+ f_call_string = "#{f_compiler} #{fcflags} -c -o #{t.name} #{t.source}"
106
+ runner.call(t, f_call_string)
107
+ end
108
+ end
109
+
110
+ def setup_cuda_compiler(options, runner)
111
+ cuda_compiler = options[:NVCC]
112
+ cudaflags = options[:NVCCFLAGS]
113
+ cudaflags += " --compiler-options '-fPIC'"
114
+
115
+ rule ".#{RbConfig::CONFIG["OBJEXT"]}" => '.cu' do |t|
116
+ cuda_call_string = "#{cuda_compiler} #{cudaflags} -c -o #{t.name} #{t.source}"
117
+ runner.call(t, cuda_call_string)
118
+ end
119
+ end
120
+
121
+ def setup_linker_mppa(options, runner)
122
+ objext = RbConfig::CONFIG["OBJEXT"]
123
+ ldflags = options[:LDFLAGS]
124
+ board = " -mboard=developer"
125
+ ldflags += " -lmppaipc"
126
+
127
+ linker = "k1-gcc"
128
+
129
+ rule ".bincomp" => ".#{objext}comp" do |t|
130
+ linker_string = "#{linker} -o #{t.name} #{t.source} -mcore=k1dp #{board} -mos=nodeos #{ldflags}"
131
+ runner.call(t, linker_string)
132
+ end
133
+
134
+ rule ".binio" => ".#{objext}io" do |t|
135
+ linker_string = "#{linker} -o #{t.name} #{t.source} -mcore=k1io #{board} -mos=rtems #{ldflags}"
136
+ runner.call(t, linker_string)
137
+ end
138
+
139
+ end
140
+
141
+ def setup_linker(options)
142
+ ldflags = options[:LDFLAGS]
143
+ ldflags += " -L#{RbConfig::CONFIG["libdir"]} #{RbConfig::CONFIG["LIBRUBYARG"]}"
144
+ ldflags += " -lrt" if not OS.mac?
145
+ ldflags += " -lcudart" if @lang == CUDA
146
+ ldflags += " -L/usr/local/k1tools/lib64 -lmppaipc -lpcie -lz -lelf -lmppa_multiloader" if @architecture == MPPA
147
+ ldflags += " -lmppamon -lmppabm -lm -lmppalock" if @architecture == MPPA
148
+ c_compiler = options[:CC]
149
+ c_compiler = "cc" if not c_compiler
150
+ linker = options[:LD]
151
+ linker = c_compiler if not linker
152
+ if options[:openmp] then
153
+ openmp_ldflags = get_openmp_flags(linker)
154
+ raise "unknown openmp flags for: #{linker}" if not openmp_ldflags
155
+ ldflags += " #{openmp_ldflags}"
156
+ end
157
+
158
+ if OS.mac? then
159
+ ldflags = "-Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress #{ldflags}"
160
+ ldshared = "-dynamic -bundle"
161
+ else
162
+ ldflags = "-Wl,-Bsymbolic-functions -Wl,-z,relro -rdynamic -Wl,-export-dynamic #{ldflags}"
163
+ ldshared = "-shared"
164
+ end
165
+
166
+ return [linker, ldshared, ldflags]
167
+ end
168
+
169
+ def setup_compilers(options = {})
170
+ Rake::Task::clear
171
+ verbose = options[:verbose]
172
+ verbose = get_verbose if not verbose
173
+ Rake::verbose(verbose)
174
+ Rake::FileUtilsExt.verbose_flag=verbose
175
+
176
+ narray_path = get_narray_path
177
+ includes = get_includes(narray_path)
178
+
179
+ runner = lambda { |t, call_string|
180
+ if verbose then
181
+ sh call_string
182
+ else
183
+ status, stdout, stderr = systemu call_string
184
+ if not status.success? then
185
+ puts stderr
186
+ fail "#{t.source}: compilation failed"
187
+ end
188
+ status.success?
189
+ end
190
+ }
191
+
192
+ setup_c_compiler(options, includes, narray_path, runner)
193
+ setup_cxx_compiler(options, includes, runner)
194
+ setup_fortran_compiler(options, runner)
195
+ setup_cuda_compiler(options, runner)
196
+
197
+ setup_linker_mppa(options, runner) if @architecture == MPPA
198
+
199
+ return setup_linker(options)
200
+
201
+ end
202
+
203
+ end
204
+
205
+ end
@@ -0,0 +1,94 @@
1
+ require 'yaml'
2
+
3
+ module BOAST
4
+
5
+ @@compiler_default_options = {
6
+ :FC => 'gfortran',
7
+ :FCFLAGS => '-O2 -Wall',
8
+ :CC => 'gcc',
9
+ :CFLAGS => '-O2 -Wall',
10
+ :CXX => 'g++',
11
+ :CXXFLAGS => '-O2 -Wall',
12
+ :NVCC => 'nvcc',
13
+ :NVCCFLAGS => '-O2',
14
+ :LDFLAGS => '',
15
+ :CLFLAGS => '',
16
+ :CLVENDOR => nil,
17
+ :CLPLATFORM => nil,
18
+ :CLDEVICE => nil,
19
+ :CLDEVICETYPE => nil,
20
+ :openmp => false
21
+ }
22
+
23
+ @@openmp_default_flags = {
24
+ "gcc" => "-fopenmp",
25
+ "icc" => "-openmp",
26
+ "gfortran" => "-fopenmp",
27
+ "ifort" => "-openmp",
28
+ "g++" => "-fopenmp",
29
+ "icpc" => "-openmp"
30
+ }
31
+
32
+ module PrivateStateAccessor
33
+ private_boolean_state_accessor :verbose
34
+ private_boolean_state_accessor :debug_source
35
+ private_boolean_state_accessor :ffi
36
+ end
37
+
38
+ boolean_state_accessor :verbose
39
+ boolean_state_accessor :debug_source
40
+ boolean_state_accessor :ffi
41
+ @@ffi = false
42
+ @@verbose = false
43
+ @@debug_source = false
44
+ FORTRAN_LINE_LENGTH = 72
45
+
46
+ module_function
47
+
48
+ def read_boast_config
49
+ home_config_dir = ENV["XDG_CONFIG_HOME"]
50
+ home_config_dir = "#{Dir.home}/.config" if not home_config_dir
51
+ Dir.mkdir( home_config_dir ) if not File::exist?( home_config_dir )
52
+ return if not File::directory?(home_config_dir)
53
+ boast_config_dir = "#{home_config_dir}/BOAST"
54
+ Dir.mkdir( boast_config_dir ) if not File::exist?( boast_config_dir )
55
+ compiler_options_file = "#{boast_config_dir}/compiler_options"
56
+ if File::exist?( compiler_options_file ) then
57
+ File::open( compiler_options_file, "r" ) { |f|
58
+ @@compiler_default_options.update( YAML::load( f.read ) )
59
+ }
60
+ else
61
+ File::open( compiler_options_file, "w" ) { |f|
62
+ f.write YAML::dump( @@compiler_default_options )
63
+ }
64
+ end
65
+ openmp_flags_file = "#{boast_config_dir}/openmp_flags"
66
+ if File::exist?( openmp_flags_file ) then
67
+ File::open( openmp_flags_file, "r" ) { |f|
68
+ @@openmp_default_flags.update( YAML::load( f.read ) )
69
+ }
70
+ else
71
+ File::open( openmp_flags_file, "w" ) { |f|
72
+ f.write YAML::dump( @@openmp_default_flags )
73
+ }
74
+ end
75
+ @@compiler_default_options.each_key { |k|
76
+ @@compiler_default_options[k] = ENV[k.to_s] if ENV[k.to_s]
77
+ }
78
+ @@compiler_default_options[:LD] = ENV["LD"] if ENV["LD"]
79
+ @@verbose = ENV["VERBOSE"] if ENV["VERBOSE"]
80
+ @@ffi = ENV["FFI"] if ENV["FFI"]
81
+ @@debug_source = ENV["DEBUG_SOURCE"] if ENV["DEBUG_SOURCE"]
82
+ end
83
+
84
+ read_boast_config
85
+
86
+ def get_openmp_flags
87
+ return @@openmp_default_flags.clone
88
+ end
89
+
90
+ def get_compiler_options
91
+ return @@compiler_default_options.clone
92
+ end
93
+
94
+ end