BOAST 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/BOAST.gemspec +2 -31
- data/README.md +240 -0
- data/lib/BOAST/{OpenMP.rb → Language/OpenMP.rb} +1 -0
- data/lib/BOAST/{Variable.rb → Language/Variable.rb} +2 -1
- data/lib/BOAST/Runtime/CKernel.rb +94 -0
- data/lib/BOAST/Runtime/CRuntime.rb +32 -0
- data/lib/BOAST/Runtime/CUDARuntime.rb +158 -0
- data/lib/BOAST/Runtime/CompiledRuntime.rb +398 -0
- data/lib/BOAST/Runtime/Compilers.rb +205 -0
- data/lib/BOAST/Runtime/Config.rb +94 -0
- data/lib/BOAST/Runtime/FFIRuntime.rb +104 -0
- data/lib/BOAST/Runtime/FORTRANRuntime.rb +45 -0
- data/lib/BOAST/Runtime/MPPARuntime.rb +464 -0
- data/lib/BOAST/Runtime/NonRegression.rb +157 -0
- data/lib/BOAST/Runtime/OpenCLRuntime.rb +181 -0
- data/lib/BOAST/Runtime/Probe.rb +136 -0
- data/lib/BOAST.rb +37 -26
- metadata +40 -28
- data/lib/BOAST/CKernel.rb +0 -1236
- /data/lib/BOAST/{Algorithm.rb → Language/Algorithm.rb} +0 -0
- /data/lib/BOAST/{Arithmetic.rb → Language/Arithmetic.rb} +0 -0
- /data/lib/BOAST/{BOAST_OpenCL.rb → Language/BOAST_OpenCL.rb} +0 -0
- /data/lib/BOAST/{Case.rb → Language/Case.rb} +0 -0
- /data/lib/BOAST/{ControlStructure.rb → Language/ControlStructure.rb} +0 -0
- /data/lib/BOAST/{DataTypes.rb → Language/DataTypes.rb} +0 -0
- /data/lib/BOAST/{Expression.rb → Language/Expression.rb} +0 -0
- /data/lib/BOAST/{For.rb → Language/For.rb} +0 -0
- /data/lib/BOAST/{FuncCall.rb → Language/FuncCall.rb} +0 -0
- /data/lib/BOAST/{Functors.rb → Language/Functors.rb} +0 -0
- /data/lib/BOAST/{If.rb → Language/If.rb} +0 -0
- /data/lib/BOAST/{Index.rb → Language/Index.rb} +0 -0
- /data/lib/BOAST/{Inspectable.rb → Language/Inspectable.rb} +0 -0
- /data/lib/BOAST/{Operators.rb → Language/Operators.rb} +0 -0
- /data/lib/BOAST/{Optimization.rb → Language/Optimization.rb} +0 -0
- /data/lib/BOAST/{Parens.rb → Language/Parens.rb} +0 -0
- /data/lib/BOAST/{Pragma.rb → Language/Pragma.rb} +0 -0
- /data/lib/BOAST/{Print.rb → Language/Print.rb} +0 -0
- /data/lib/BOAST/{Procedure.rb → Language/Procedure.rb} +0 -0
- /data/lib/BOAST/{Slice.rb → Language/Slice.rb} +0 -0
- /data/lib/BOAST/{State.rb → Language/State.rb} +0 -0
- /data/lib/BOAST/{Transitions.rb → Language/Transitions.rb} +0 -0
- /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
|