BOAST 1.3.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/BOAST.gemspec +1 -1
  3. data/LICENSE +13 -1
  4. data/README.md +62 -13
  5. data/lib/BOAST.rb +3 -1
  6. data/lib/BOAST/Language/ARMCPUID_by_name.rb +3752 -0
  7. data/lib/BOAST/Language/Algorithm.rb +4 -24
  8. data/lib/BOAST/Language/Architectures.rb +5 -0
  9. data/lib/BOAST/Language/Arithmetic.rb +38 -5
  10. data/lib/BOAST/Language/BOAST_OpenCL.rb +7 -8
  11. data/lib/BOAST/Language/Case.rb +10 -3
  12. data/lib/BOAST/Language/Config.rb +36 -12
  13. data/lib/BOAST/Language/ControlStructure.rb +7 -3
  14. data/lib/BOAST/Language/DataTypes.rb +6 -0
  15. data/lib/BOAST/Language/Expression.rb +26 -2
  16. data/lib/BOAST/Language/For.rb +59 -30
  17. data/lib/BOAST/Language/FuncCall.rb +9 -5
  18. data/lib/BOAST/Language/Functors.rb +1 -1
  19. data/lib/BOAST/Language/HighLevelOperators.rb +172 -0
  20. data/lib/BOAST/Language/If.rb +25 -9
  21. data/lib/BOAST/Language/Index.rb +5 -5
  22. data/lib/BOAST/Language/Intrinsics.rb +40 -27
  23. data/lib/BOAST/Language/OpenMP.rb +1 -0
  24. data/lib/BOAST/Language/Operators.rb +221 -34
  25. data/lib/BOAST/Language/Parens.rb +3 -2
  26. data/lib/BOAST/Language/Procedure.rb +18 -5
  27. data/lib/BOAST/Language/Slice.rb +176 -44
  28. data/lib/BOAST/Language/Variable.rb +99 -56
  29. data/lib/BOAST/Language/While.rb +18 -3
  30. data/lib/BOAST/Language/{CPUID_by_name.rb → X86CPUID_by_name.rb} +0 -0
  31. data/lib/BOAST/Optimization/Optimization.rb +2 -0
  32. data/lib/BOAST/Runtime/AffinityProbe.rb +7 -3
  33. data/lib/BOAST/Runtime/CKernel.rb +3 -0
  34. data/lib/BOAST/Runtime/CRuntime.rb +4 -0
  35. data/lib/BOAST/Runtime/CompiledRuntime.rb +404 -77
  36. data/lib/BOAST/Runtime/Compilers.rb +44 -18
  37. data/lib/BOAST/Runtime/Config.rb +9 -0
  38. data/lib/BOAST/Runtime/EnergyProbe.rb +19 -3
  39. data/lib/BOAST/Runtime/FFIRuntime.rb +23 -0
  40. data/lib/BOAST/Runtime/FORTRANRuntime.rb +1 -1
  41. data/lib/BOAST/Runtime/MAQAO.rb +29 -0
  42. data/lib/BOAST/Runtime/NonRegression.rb +64 -3
  43. data/lib/BOAST/Runtime/OpenCLRuntime.rb +16 -6
  44. data/lib/BOAST/Runtime/Probe.rb +21 -1
  45. metadata +5 -3
@@ -7,7 +7,11 @@ module BOAST
7
7
 
8
8
  attr_reader :condition
9
9
 
10
+ # Creates a new instance of the While construct.
11
+ # @param [Expression] condition
12
+ # @param [Proc,nil] block if given, will be evaluated when {pr} is called
10
13
  def initialize(condition, &block)
14
+ super()
11
15
  @condition = condition
12
16
  @block = block
13
17
  end
@@ -30,10 +34,13 @@ module BOAST
30
34
  eval token_string_generator( * %w{while cond} )
31
35
  eval token_string_generator( * %w{end} )
32
36
 
37
+ # Returns a string representation of the While construct.
33
38
  def to_s
34
39
  return while_string(@condition)
35
40
  end
36
41
 
42
+ # Opens the While construct (keyword, condition, opening bracket in C like languages). The result is printed to the BOAST output.
43
+ # @return [self]
37
44
  def open
38
45
  s=""
39
46
  s += indent
@@ -43,16 +50,24 @@ module BOAST
43
50
  return self
44
51
  end
45
52
 
46
- def pr(*args)
53
+ # Prints the While construct to the BOAST output (see {open}).
54
+ # If a block is provided during initialization, it will be printed and the construct will be closed (see {close}).
55
+ # @param [Array<Object>] args any number of arguments to pass to the block
56
+ # @param [Proc] block an optional block to be evaluated. Supersede the one given at initialization
57
+ # @return [self]
58
+ def pr(*args, &block)
47
59
  args = @args if args.length == 0 and @args
60
+ block = @block unless block
48
61
  open
49
- if @block then
50
- @block.call(*args)
62
+ if block then
63
+ block.call(*args)
51
64
  close
52
65
  end
53
66
  return self
54
67
  end
55
68
 
69
+ # Closes the While construct (keyword, closing bracket in C like languages). The result is printed to the BOAST output.
70
+ # @return [self]
56
71
  def close
57
72
  decrement_indent_level
58
73
  s = ""
@@ -25,6 +25,8 @@ module BOAST
25
25
  HASH_NAME = "options"
26
26
 
27
27
  def initialize( *parameters )
28
+ @rules = nil
29
+ @checkers = nil
28
30
  if parameters.length == 1 and parameters[0].is_a?(Hash) then
29
31
  @parameters = []
30
32
  parameters[0].each { |key, value|
@@ -6,10 +6,11 @@ module BOAST
6
6
 
7
7
  module_function
8
8
 
9
+ def cflags
10
+ return "-D_GNU_SOURCE"
11
+ end
12
+
9
13
  def header
10
- get_output.puts "#ifndef _GNU_SOURCE"
11
- get_output.puts "#define _GNU_SOURCE"
12
- get_output.puts "#endif"
13
14
  get_output.puts "#include <sched.h>"
14
15
  end
15
16
 
@@ -60,6 +61,9 @@ EOF
60
61
  EOF
61
62
  end
62
63
 
64
+ def store
65
+ end
66
+
63
67
  end
64
68
 
65
69
  end
@@ -23,6 +23,7 @@ module BOAST
23
23
  attr_accessor :architecture
24
24
  attr_accessor :kernels
25
25
  attr_accessor :cost_function
26
+ attr_accessor :includes
26
27
 
27
28
  # Creates a new CKernel object. BOAST output is redirected to the CKernel. If the chain_code state is set the current BOAST output, as returned by {BOAST.get_output}, is used.
28
29
  # @param [Hash] options contains named options
@@ -55,6 +56,8 @@ module BOAST
55
56
  else
56
57
  @architecture = get_architecture
57
58
  end
59
+ @includes = []
60
+ @includes = [options[:includes]].flatten if options[:includes]
58
61
 
59
62
  case @lang
60
63
  when CL
@@ -9,6 +9,10 @@ module BOAST
9
9
  def fill_library_header
10
10
  get_output.puts "#include <stdlib.h>"
11
11
  get_output.puts "#include <inttypes.h>"
12
+ get_output.puts "#include <math.h>"
13
+ @includes.each { |inc|
14
+ get_output.puts "#include \"#{inc}\""
15
+ }
12
16
  get_output.puts "#define __assume_aligned(lvalueptr, align) lvalueptr = __builtin_assume_aligned (lvalueptr, align)" if @compiler_options[:CC].match("gcc")
13
17
  end
14
18
 
@@ -8,7 +8,12 @@ require 'os'
8
8
 
9
9
  class Dir
10
10
  module Tmpname
11
- module_function
11
+ class << self
12
+ undef_method :make_tmpname
13
+ end
14
+
15
+ undef_method :make_tmpname
16
+
12
17
  def make_tmpname(prefix_suffix, n)
13
18
  case prefix_suffix
14
19
  when String
@@ -25,6 +30,9 @@ class Dir
25
30
  path << "_#{n}" if n
26
31
  path << suffix
27
32
  end
33
+
34
+ module_function :make_tmpname
35
+
28
36
  end
29
37
  end
30
38
 
@@ -86,6 +94,10 @@ module BOAST
86
94
  return "#{base_path}.#{RbConfig::CONFIG["OBJEXT"]}"
87
95
  end
88
96
 
97
+ def library_nofpic_object
98
+ return "#{base_path}.nofpic#{RbConfig::CONFIG["OBJEXT"]}"
99
+ end
100
+
89
101
  def library_path
90
102
  return "#{base_path}.#{RbConfig::CONFIG["DLEXT"]}"
91
103
  end
@@ -94,10 +106,26 @@ module BOAST
94
106
  return module_file_path
95
107
  end
96
108
 
109
+ def executable_source
110
+ return "#{base_path}_executable.c"
111
+ end
112
+
113
+ def executable_object
114
+ return "#{base_path}_executable.nofpic#{RbConfig::CONFIG["OBJEXT"]}"
115
+ end
116
+
117
+ def target_executable
118
+ return "#{base_path}_executable"
119
+ end
120
+
97
121
  def target_depends
98
122
  return [ module_file_object, library_object ]
99
123
  end
100
124
 
125
+ def target_executable_depends
126
+ return [ library_nofpic_object, executable_object ]
127
+ end
128
+
101
129
  def save_binary
102
130
  f = File::open(library_object,"rb")
103
131
  @binary = StringIO::new
@@ -112,14 +140,35 @@ module BOAST
112
140
  f.close
113
141
  end
114
142
 
115
- def create_targets( linker, ldshared, ldflags, kernel_files)
143
+ def save_module
144
+ f = File::open(module_file_path, "rb")
145
+ @module_binary = StringIO::new
146
+ @module_binary.write( f.read )
147
+ f.close
148
+ end
149
+
150
+ def save_executable
151
+ f = File::open(target_executable, "rb")
152
+ @executable = StringIO::new
153
+ @executable.write( f.read )
154
+ f.close
155
+ end
156
+
157
+ def create_targets( linker, ldshared, ldshared_flags, ldflags, kernel_files)
116
158
  file target => target_depends do
117
- #puts "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
118
- sh "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
159
+ #puts "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldshared_flags} #{ldflags}"
160
+ sh "#{linker} #{ldshared} -o #{target} #{target_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldshared_flags} #{ldflags}"
119
161
  end
120
162
  Rake::Task[target].invoke
121
163
  end
122
164
 
165
+ def create_executable_target( linker, ldflags, kernel_files)
166
+ file target_executable => target_executable_depends do
167
+ sh "#{linker} -o #{target_executable} #{target_executable_depends.join(" ")} #{(kernel_files.collect {|f| f.path}).join(" ")} #{ldflags}"
168
+ end
169
+ Rake::Task[target_executable].invoke
170
+ end
171
+
123
172
  def method_name
124
173
  return @procedure.name
125
174
  end
@@ -138,19 +187,14 @@ module BOAST
138
187
 
139
188
  def create_library_source
140
189
  f = File::open(library_source,"w+")
141
- previous_lang = get_lang
142
- previous_output = get_output
143
- set_output(f)
144
- set_lang(@lang)
145
-
146
- fill_library_source
190
+ push_env( :output => f, :lang => @lang ) {
191
+ fill_library_source
147
192
 
148
- if debug_source? then
149
- f.rewind
150
- puts f.read
151
- end
152
- set_output(previous_output)
153
- set_lang(previous_lang)
193
+ if debug_source? or debug_kernel_source? then
194
+ f.rewind
195
+ puts f.read
196
+ end
197
+ }
154
198
  f.close
155
199
  end
156
200
 
@@ -162,6 +206,9 @@ module BOAST
162
206
  #include "narray.h"
163
207
  #endif
164
208
  EOF
209
+ @includes.each { |inc|
210
+ get_output.puts "#include \"#{inc}\""
211
+ }
165
212
  end
166
213
 
167
214
  def fill_module_preamble
@@ -215,26 +262,26 @@ EOF
215
262
  end
216
263
 
217
264
  def fill_decl_module_params
218
- push_env(:decl_module => true)
219
- @procedure.parameters.each { |param|
220
- param_copy = param.copy
221
- param_copy.constant = nil
222
- param_copy.direction = nil
223
- param_copy.reference = nil
224
- param_copy.decl
265
+ push_env(:decl_module => true) {
266
+ @procedure.parameters.each { |param|
267
+ param_copy = param.copy
268
+ param_copy.constant = nil
269
+ param_copy.direction = nil
270
+ param_copy.reference = nil
271
+ param_copy.decl
272
+ }
273
+ get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
274
+ get_output.puts " VALUE _boast_stats = rb_hash_new();"
275
+ get_output.puts " VALUE _boast_rb_ptr = Qnil;"
276
+ refs = false
277
+ @procedure.parameters.each_with_index do |param,i|
278
+ refs = true if param.scalar_output?
279
+ end
280
+ if refs then
281
+ get_output.puts " VALUE _boast_refs = rb_hash_new();"
282
+ get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);"
283
+ end
225
284
  }
226
- get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
227
- get_output.puts " VALUE _boast_stats = rb_hash_new();"
228
- get_output.puts " VALUE _boast_rb_ptr = Qnil;"
229
- refs = false
230
- @procedure.parameters.each_with_index do |param,i|
231
- refs = true if param.scalar_output?
232
- end
233
- if refs then
234
- get_output.puts " VALUE _boast_refs = rb_hash_new();"
235
- get_output.puts " rb_hash_aset(_boast_stats,ID2SYM(rb_intern(\"reference_return\")),_boast_refs);"
236
- end
237
- pop_env(:decl_module)
238
285
  end
239
286
 
240
287
  def copy_scalar_param_from_ruby( param, ruby_param )
@@ -252,11 +299,23 @@ EOF
252
299
  (rb_ptr === ruby_param).pr
253
300
  get_output.print <<EOF
254
301
  if (TYPE(_boast_rb_ptr) == T_STRING) {
255
- #{param} = (void *) RSTRING_PTR(_boast_rb_ptr);
302
+ #{
303
+ if param.dimension then
304
+ "#{param} = (void *)RSTRING_PTR(_boast_rb_ptr)"
305
+ else
306
+ (param === param.copy("*(void *)RSTRING_PTR(_boast_rb_ptr)", :dimension => Dim(), :vector_length => 1)).to_s
307
+ end
308
+ };
256
309
  } else if ( IsNArray(_boast_rb_ptr) ) {
257
310
  struct NARRAY *_boast_n_ary;
258
311
  Data_Get_Struct(_boast_rb_ptr, struct NARRAY, _boast_n_ary);
259
- #{param} = (void *) _boast_n_ary->ptr;
312
+ #{
313
+ if param.dimension then
314
+ "#{param} = (void *) _boast_n_ary->ptr"
315
+ else
316
+ (param === param.copy("*(void *) _boast_n_ary->ptr", :dimension => Dim(), :vector_length => 1)).to_s
317
+ end
318
+ };
260
319
  } else {
261
320
  rb_raise(rb_eArgError, "Wrong type of argument for %s, expecting array!", "#{param}");
262
321
  }
@@ -266,17 +325,16 @@ EOF
266
325
  def get_params_value
267
326
  argc = @procedure.parameters.length
268
327
  argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
269
- rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
270
- push_env(:decl_module => true)
271
- @procedure.parameters.each_index do |i|
272
- param = @procedure.parameters[i]
273
- if not param.dimension then
274
- copy_scalar_param_from_ruby(param, argv[i])
275
- else
276
- copy_array_param_from_ruby(param, argv[i])
328
+ push_env(:decl_module => true) {
329
+ @procedure.parameters.each_index do |i|
330
+ param = @procedure.parameters[i]
331
+ if not param.dimension? and not param.vector? then
332
+ copy_scalar_param_from_ruby(param, argv[i])
333
+ else
334
+ copy_array_param_from_ruby(param, argv[i])
335
+ end
277
336
  end
278
- end
279
- pop_env(:decl_module)
337
+ }
280
338
  end
281
339
 
282
340
  def create_procedure_call
@@ -301,23 +359,67 @@ EOF
301
359
  end
302
360
  end
303
361
 
362
+ def copy_scalar_param_to_file(param, base_path)
363
+ if param.scalar_output? then
364
+ get_output.puts <<EOF
365
+ __boast_f = fopen("#{base_path}/#{param}.out", "wb");
366
+ fwrite(&#{param}, sizeof(#{param}), 1, __boast_f);
367
+ fclose(__boast_f);
368
+ EOF
369
+ end
370
+ end
371
+
372
+ def copy_scalar_param_from_file(param, base_path)
373
+ get_output.puts <<EOF
374
+ __boast_f = fopen("#{base_path}/#{param}.in", "rb");
375
+ fread(&#{param}, sizeof(#{param}), 1, __boast_f);
376
+ fclose(__boast_f);
377
+ EOF
378
+ end
379
+
304
380
  def copy_array_param_to_ruby(param, ruby_param)
305
381
  end
306
382
 
383
+ def copy_array_param_to_file(param, base_path)
384
+ if param.direction == :out or param.direction == :inout then
385
+ get_output.puts <<EOF
386
+ __boast_f = fopen("#{base_path}/#{param}.out", "wb");
387
+ fwrite(#{param}, 1, __boast_sizeof_#{param}, __boast_f);
388
+ fclose(__boast_f);
389
+ free(#{param});
390
+ EOF
391
+ else
392
+ get_output.puts <<EOF
393
+ free(#{param});
394
+ EOF
395
+ end
396
+ end
397
+
398
+ def copy_array_param_from_file(param, base_path)
399
+ get_output.puts <<EOF
400
+ __boast_f = fopen("#{base_path}/#{param}.in", "rb");
401
+ fseek(__boast_f, 0L, SEEK_END);
402
+ __boast_sizeof_#{param} = ftell(__boast_f);
403
+ rewind(__boast_f);
404
+ #{param} = malloc(__boast_sizeof_#{param});
405
+ fread(#{param}, 1, __boast_sizeof_#{param}, __boast_f);
406
+ fclose(__boast_f);
407
+ EOF
408
+ end
409
+
307
410
  def get_results
308
411
  argc = @procedure.parameters.length
309
412
  argv = Variable::new("_boast_argv", CustomType, :type_name => "VALUE", :dimension => [ Dimension::new(0,argc-1) ] )
310
- rb_ptr = Variable::new("_boast_rb_ptr", CustomType, :type_name => "VALUE")
311
- push_env(:decl_module => true)
312
- @procedure.parameters.each_index do |i|
313
- param = @procedure.parameters[i]
314
- if not param.dimension then
315
- copy_scalar_param_to_ruby(param, argv[i])
316
- else
317
- copy_array_param_to_ruby(param, argv[i])
413
+ push_env(:decl_module => true) {
414
+ @procedure.parameters.each_index do |i|
415
+ param = @procedure.parameters[i]
416
+ if not param.dimension then
417
+ copy_scalar_param_to_ruby(param, argv[i])
418
+ else
419
+ copy_array_param_to_ruby(param, argv[i])
420
+ end
318
421
  end
319
- end
320
- pop_env(:decl_module)
422
+ }
321
423
  end
322
424
 
323
425
  def store_results
@@ -329,6 +431,118 @@ EOF
329
431
  end
330
432
  end
331
433
 
434
+ def get_executable_params_value( base_path )
435
+ push_env(:decl_module => true) {
436
+ @procedure.parameters.each do |param|
437
+ if not param.dimension? then
438
+ copy_scalar_param_from_file(param, base_path)
439
+ else
440
+ copy_array_param_from_file(param, base_path)
441
+ end
442
+ end
443
+ }
444
+ end
445
+
446
+ def get_executable_params_return_value( base_path )
447
+ push_env(:decl_module => true) {
448
+ @procedure.parameters.each do |param|
449
+ if not param.dimension then
450
+ copy_scalar_param_to_file(param, base_path)
451
+ else
452
+ copy_array_param_to_file(param, base_path)
453
+ end
454
+ end
455
+ }
456
+ end
457
+
458
+ def fill_executable_source
459
+ get_output.puts "#include <inttypes.h>"
460
+ get_output.puts "#include <stdlib.h>"
461
+ get_output.puts "#include <stdio.h>"
462
+ @includes.each { |inc|
463
+ get_output.puts "#include \"#{inc}\""
464
+ }
465
+ @probes.map(&:header)
466
+ @procedure.boast_header(@lang)
467
+
468
+ get_output.print <<EOF
469
+ void Init_#{base_name}( void );
470
+ int _boast_repeat;
471
+ void Init_#{base_name}( void ) {
472
+ EOF
473
+ increment_indent_level
474
+ output.puts " FILE * __boast_f;"
475
+ push_env(:decl_module => true) {
476
+ @procedure.parameters.each { |param|
477
+ if param.dimension? then
478
+ output.puts " size_t __boast_sizeof_#{param};"
479
+ end
480
+ param_copy = param.copy
481
+ param_copy.constant = nil
482
+ param_copy.direction = nil
483
+ param_copy.reference = nil
484
+ param_copy.decl
485
+ }
486
+ get_output.puts " #{@procedure.properties[:return].type.decl} _boast_ret;" if @procedure.properties[:return]
487
+ }
488
+ @probes.reverse.map(&:decl)
489
+ @probes.map(&:configure)
490
+
491
+ get_executable_params_value( "#{@tmp_dir}/#{@procedure.name}/#{base_name}" )
492
+
493
+ @probes.reverse.map(&:start)
494
+
495
+ get_output.puts " int _boast_i;"
496
+ get_output.puts " for(_boast_i = 0; _boast_i < _boast_repeat; ++_boast_i){"
497
+ get_output.print " "
498
+ get_output.print "_boast_ret = " if @procedure.properties[:return]
499
+ get_output.print "#{method_name}( "
500
+ get_output.print create_procedure_call_parameters.join(", ")
501
+ get_output.puts " );"
502
+ get_output.puts " }"
503
+
504
+ @probes.map(&:stop)
505
+
506
+ get_output.puts ' printf("---\n");'
507
+ if @procedure.properties[:return] then
508
+ type_ret = @procedure.properties[:return].type
509
+ get_output.puts ' printf(":return: %lld\n", (long long)_boast_ret);' if type_ret.kind_of?(Int) and type_ret.signed
510
+ get_output.puts ' printf(":return: %ulld\n", (unsigned long long)_boast_ret);' if type_ret.kind_of?(Int) and not type_ret.signed
511
+ get_output.puts ' printf(":return: %lf\n", (double)_boast_ret);' if type_ret.kind_of?(Real)
512
+
513
+ end
514
+
515
+ get_executable_params_return_value( "#{@tmp_dir}/#{@procedure.name}/#{base_name}" )
516
+
517
+ @probes.map(&:compute)
518
+
519
+ @probes.map(&:to_yaml)
520
+
521
+ decrement_indent_level
522
+ get_output.print <<EOF
523
+ }
524
+ int main(int argc, char * argv[]) {
525
+ _boast_repeat=atoi(argv[1]);
526
+ Init_#{base_name}();
527
+ return 0;
528
+ }
529
+ EOF
530
+
531
+ end
532
+
533
+ def create_executable_source
534
+ f = File::open(executable_source, "w+")
535
+ push_env(:output => f, :lang => C) {
536
+ fill_executable_source
537
+
538
+ if debug_source? then
539
+ f.rewind
540
+ puts f.read
541
+ end
542
+ }
543
+ f.close
544
+ end
545
+
332
546
  def fill_module_file_source
333
547
  fill_module_header
334
548
  @probes.map(&:header)
@@ -360,7 +574,10 @@ EOF
360
574
 
361
575
  get_results
362
576
 
363
- @probes.map(&:compute)
577
+ @probes.each { |p|
578
+ p.compute
579
+ p.store
580
+ }
364
581
 
365
582
  store_results
366
583
 
@@ -371,16 +588,14 @@ EOF
371
588
 
372
589
  def create_module_file_source
373
590
  f = File::open(module_file_source, "w+")
374
- push_env(:lang => C)
375
- push_env(:output => f)
376
-
377
- fill_module_file_source
591
+ push_env(:output => f, :lang => C) {
592
+ fill_module_file_source
378
593
 
379
- if debug_source? then
380
- f.rewind
381
- puts f.read
382
- end
383
- pop_env(:lang, :output)
594
+ if debug_source? then
595
+ f.rewind
596
+ puts f.read
597
+ end
598
+ }
384
599
  f.close
385
600
  end
386
601
 
@@ -397,6 +612,10 @@ EOF
397
612
  return [ module_file_source, library_source ]
398
613
  end
399
614
 
615
+ def target_executable_sources
616
+ return [ executable_source, library_source ]
617
+ end
618
+
400
619
  def cleanup(kernel_files)
401
620
  ([target] + target_depends + target_sources).each { |fn|
402
621
  File::unlink(fn)
@@ -406,35 +625,123 @@ EOF
406
625
  }
407
626
  end
408
627
 
628
+ def cleanup_executable(kernel_files)
629
+ ( [target_executable] + target_executable_depends + target_executable_sources ).each { |fn|
630
+ File::unlink(fn)
631
+ }
632
+ kernel_files.each { |f|
633
+ f.unlink
634
+ }
635
+ end
636
+
637
+ def run_executable(*params)
638
+ options = {:repeat => 1}
639
+ if params.last.kind_of?(Hash) then
640
+ options.update(params.last)
641
+ ps = params[0..-2]
642
+ else
643
+ ps = params[0..-1]
644
+ end
645
+
646
+ Dir::mkdir(@tmp_dir, 0700) unless Dir::exist?(@tmp_dir)
647
+
648
+ dump_executable
649
+ dump_ref_inputs( { base_name => ps }, @tmp_dir )
650
+ boast_ret = YAML::load `#{target_executable} #{options[:repeat]}`
651
+ File::unlink(target_executable) unless keep_temp
652
+
653
+ res = load_ref_outputs(@tmp_dir)["#{@tmp_dir}/#{@procedure.name}/#{base_name}"]
654
+ @procedure.parameters.each_with_index { |param, indx|
655
+ if param.direction == :in or param.constant then
656
+ next
657
+ end
658
+ if param.dimension then
659
+ ps[indx][0..-1] = res[indx][0..-1]
660
+ else
661
+ boast_ret[:reference_return] = {} unless boast_ret[:reference_return]
662
+ boast_ret[:reference_return][param.name.to_sym] = res[indx]
663
+ end
664
+ }
665
+ p = Pathname::new("#{@tmp_dir}/#{@procedure.name}/#{base_name}")
666
+ p.children.each { |f| File::unlink f }
667
+ unless keep_temp then
668
+ Dir::rmdir("#{@tmp_dir}/#{@procedure.name}/#{base_name}")
669
+ Dir::rmdir("#{@tmp_dir}/#{@procedure.name}")
670
+ Dir::rmdir("#{@tmp_dir}")
671
+ end
672
+ return boast_ret
673
+ end
674
+
675
+ def build_executable(options={})
676
+ compiler_options = BOAST::get_compiler_options
677
+ compiler_options.update(options)
678
+ @probes = [TimerProbe]
679
+ linker, _, _, ldflags = setup_compilers(@probes, compiler_options)
680
+ @compiler_options = compiler_options
681
+
682
+ @marker = Tempfile::new([@procedure.name,""])
683
+ Dir::mktmpdir { |dir|
684
+ @tmp_dir = "#{dir}"
685
+ }
686
+
687
+ kernel_files = get_sub_kernels
688
+
689
+ create_library_source
690
+
691
+ create_executable_source
692
+
693
+ save_source
694
+
695
+ create_executable_target(linker, ldflags, kernel_files)
696
+
697
+ save_executable
698
+
699
+ instance_eval <<EOF
700
+ def run(*args, &block)
701
+ run_executable(*args, &block)
702
+ end
703
+ EOF
704
+
705
+ cleanup_executable(kernel_files) unless keep_temp
706
+
707
+ return self
708
+
709
+ end
710
+
409
711
  public
410
712
 
411
713
  def build(options={})
714
+ return build_executable(options) if executable? and (@lang == C or @lang == FORTRAN)
412
715
  compiler_options = BOAST::get_compiler_options
413
716
  compiler_options.update(options)
414
- linker, ldshared, ldflags = setup_compilers(compiler_options)
415
- @compiler_options = compiler_options
416
717
  @probes = []
417
- if @compiler_options[:probes] then
418
- @probes = @compiler_options[:probes]
419
- elsif get_lang != CUDA
718
+ if compiler_options[:probes] then
719
+ @probes = compiler_options[:probes]
720
+ elsif get_lang != CUDA then
420
721
  @probes = [TimerProbe, PAPIProbe]
421
722
  @probes.push EnergyProbe if EnergyProbe
422
723
  @probes.push AffinityProbe unless OS.mac?
423
724
  end
424
725
  @probes = [MPPAProbe] if @architecture == MPPA
726
+ linker, ldshared, ldshared_flags, ldflags = setup_compilers(@probes, compiler_options)
727
+ @compiler_options = compiler_options
425
728
 
426
729
  @marker = Tempfile::new([@procedure.name,""])
427
730
 
731
+ extend MAQAO if @compiler_options[:MAQAO_PASS]
732
+
428
733
  kernel_files = get_sub_kernels
429
734
 
430
735
  create_sources
431
736
 
432
737
  save_source
433
738
 
434
- create_targets(linker, ldshared, ldflags, kernel_files)
739
+ create_targets(linker, ldshared, ldshared_flags, ldflags, kernel_files)
435
740
 
436
741
  save_binary
437
742
 
743
+ save_module
744
+
438
745
  load_module
439
746
 
440
747
  cleanup(kernel_files) unless keep_temp
@@ -444,20 +751,40 @@ EOF
444
751
  return self
445
752
  end
446
753
 
447
- def dump_binary
448
- f = File::open(library_object,"wb")
754
+ def dump_binary(path = nil)
755
+ f = path ? File::open(path,"wb") : File::open(library_object,"wb")
449
756
  @binary.rewind
450
757
  f.write( @binary.read )
451
758
  f.close
452
759
  end
453
760
 
454
- def dump_source
455
- f = File::open(library_source,"wb")
761
+ def dump_source(path = nil)
762
+ f = path ? File::open(path,"wb") : File::open(library_source,"wb")
456
763
  @source.rewind
457
764
  f.write( @source.read )
458
765
  f.close
459
766
  end
460
767
 
768
+ def dump_module(path = nil)
769
+ f = path ? File::open(path,"wb") : File::open(module_file_path,"wb")
770
+ @module_binary.rewind
771
+ f.write( @module_binary.read )
772
+ f.close
773
+ end
774
+
775
+ def dump_executable(path = nil)
776
+ f = path ? File::open(path,"wb",0700) : File::open(target_executable,"wb",0700)
777
+ @executable.rewind
778
+ f.write( @executable.read )
779
+ f.close
780
+ end
781
+
782
+ def reload_module
783
+ raise "Missing binary library data!" unless @module_binary
784
+ $LOADED_FEATURES.delete(module_file_path)
785
+ require module_file_path
786
+ end
787
+
461
788
  end
462
789
 
463
790
  end