bones-compiler 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. data/CHANGELOG +117 -0
  2. data/LICENSE +9 -0
  3. data/README.rdoc +126 -0
  4. data/Rakefile +107 -0
  5. data/VERSION +1 -0
  6. data/bin/bones +20 -0
  7. data/examples/applications/ffos.c +552 -0
  8. data/examples/benchmarks/2mm.c +70 -0
  9. data/examples/benchmarks/3mm.c +81 -0
  10. data/examples/benchmarks/adi.c +81 -0
  11. data/examples/benchmarks/atax.c +65 -0
  12. data/examples/benchmarks/bicg.c +67 -0
  13. data/examples/benchmarks/cholesky.c +64 -0
  14. data/examples/benchmarks/common.h +168 -0
  15. data/examples/benchmarks/correlation.c +97 -0
  16. data/examples/benchmarks/covariance.c +77 -0
  17. data/examples/benchmarks/doitgen.c +63 -0
  18. data/examples/benchmarks/durbin.c +76 -0
  19. data/examples/benchmarks/dynprog.c +67 -0
  20. data/examples/benchmarks/fdtd-2d-apml.c +114 -0
  21. data/examples/benchmarks/fdtd-2d.c +74 -0
  22. data/examples/benchmarks/floyd-warshall.c +50 -0
  23. data/examples/benchmarks/gemm.c +69 -0
  24. data/examples/benchmarks/gemver.c +89 -0
  25. data/examples/benchmarks/gesummv.c +64 -0
  26. data/examples/benchmarks/gramschmidt.c +84 -0
  27. data/examples/benchmarks/jacobi-1d-imper.c +55 -0
  28. data/examples/benchmarks/jacobi-2d-imper.c +61 -0
  29. data/examples/benchmarks/lu.c +57 -0
  30. data/examples/benchmarks/ludcmp.c +91 -0
  31. data/examples/benchmarks/mvt.c +65 -0
  32. data/examples/benchmarks/overview.txt +38 -0
  33. data/examples/benchmarks/reg_detect.c +82 -0
  34. data/examples/benchmarks/saxpy.c +45 -0
  35. data/examples/benchmarks/seidel-2d.c +51 -0
  36. data/examples/benchmarks/symm.c +74 -0
  37. data/examples/benchmarks/syr2k.c +65 -0
  38. data/examples/benchmarks/syrk.c +62 -0
  39. data/examples/benchmarks/trisolv.c +57 -0
  40. data/examples/benchmarks/trmm.c +57 -0
  41. data/examples/chunk/example1.c +54 -0
  42. data/examples/chunk/example2.c +44 -0
  43. data/examples/chunk/example3.c +59 -0
  44. data/examples/chunk/example4.c +55 -0
  45. data/examples/chunk/example5.c +52 -0
  46. data/examples/element/example1.c +46 -0
  47. data/examples/element/example10.c +50 -0
  48. data/examples/element/example11.c +47 -0
  49. data/examples/element/example12.c +56 -0
  50. data/examples/element/example2.c +46 -0
  51. data/examples/element/example3.c +58 -0
  52. data/examples/element/example4.c +49 -0
  53. data/examples/element/example5.c +56 -0
  54. data/examples/element/example6.c +46 -0
  55. data/examples/element/example7.c +54 -0
  56. data/examples/element/example8.c +45 -0
  57. data/examples/element/example9.c +48 -0
  58. data/examples/neighbourhood/example1.c +54 -0
  59. data/examples/neighbourhood/example2.c +55 -0
  60. data/examples/neighbourhood/example3.c +82 -0
  61. data/examples/neighbourhood/example4.c +52 -0
  62. data/examples/shared/example1.c +45 -0
  63. data/examples/shared/example2.c +51 -0
  64. data/examples/shared/example3.c +55 -0
  65. data/examples/shared/example4.c +52 -0
  66. data/examples/shared/example5.c +48 -0
  67. data/lib/bones.rb +266 -0
  68. data/lib/bones/algorithm.rb +541 -0
  69. data/lib/bones/engine.rb +386 -0
  70. data/lib/bones/preprocessor.rb +161 -0
  71. data/lib/bones/species.rb +196 -0
  72. data/lib/bones/structure.rb +94 -0
  73. data/lib/bones/variable.rb +169 -0
  74. data/lib/bones/variablelist.rb +72 -0
  75. data/lib/castaddon.rb +27 -0
  76. data/lib/castaddon/index.rb +40 -0
  77. data/lib/castaddon/node.rb +753 -0
  78. data/lib/castaddon/type.rb +37 -0
  79. data/skeletons/CPU-C/common/epilogue.c +0 -0
  80. data/skeletons/CPU-C/common/globals.c +17 -0
  81. data/skeletons/CPU-C/common/globals_kernel.c +1 -0
  82. data/skeletons/CPU-C/common/header.c +0 -0
  83. data/skeletons/CPU-C/common/mem_copy_D2H.c +0 -0
  84. data/skeletons/CPU-C/common/mem_copy_H2D.c +0 -0
  85. data/skeletons/CPU-C/common/mem_epilogue.c +0 -0
  86. data/skeletons/CPU-C/common/mem_prologue.c +3 -0
  87. data/skeletons/CPU-C/common/prologue.c +0 -0
  88. data/skeletons/CPU-C/common/timer_1_start.c +0 -0
  89. data/skeletons/CPU-C/common/timer_1_stop.c +0 -0
  90. data/skeletons/CPU-C/common/timer_2_start.c +20 -0
  91. data/skeletons/CPU-C/common/timer_2_stop.c +8 -0
  92. data/skeletons/CPU-C/kernel/default.host.c +3 -0
  93. data/skeletons/CPU-C/kernel/default.kernel.c +15 -0
  94. data/skeletons/CPU-C/skeletons.txt +24 -0
  95. data/skeletons/CPU-OPENCL-AMD/common/epilogue.c +6 -0
  96. data/skeletons/CPU-OPENCL-AMD/common/globals.c +155 -0
  97. data/skeletons/CPU-OPENCL-AMD/common/globals_kernel.c +4 -0
  98. data/skeletons/CPU-OPENCL-AMD/common/header.c +0 -0
  99. data/skeletons/CPU-OPENCL-AMD/common/mem_copy_D2H.c +8 -0
  100. data/skeletons/CPU-OPENCL-AMD/common/mem_copy_H2D.c +4 -0
  101. data/skeletons/CPU-OPENCL-AMD/common/mem_epilogue.c +3 -0
  102. data/skeletons/CPU-OPENCL-AMD/common/mem_prologue.c +6 -0
  103. data/skeletons/CPU-OPENCL-AMD/common/prologue.c +24 -0
  104. data/skeletons/CPU-OPENCL-AMD/common/timer_1_start.c +5 -0
  105. data/skeletons/CPU-OPENCL-AMD/common/timer_1_stop.c +9 -0
  106. data/skeletons/CPU-OPENCL-AMD/common/timer_2_start.c +16 -0
  107. data/skeletons/CPU-OPENCL-AMD/common/timer_2_stop.c +11 -0
  108. data/skeletons/CPU-OPENCL-AMD/kernel/D-element-to-1-shared.host.c +67 -0
  109. data/skeletons/CPU-OPENCL-AMD/kernel/D-element-to-1-shared.kernel.cl +72 -0
  110. data/skeletons/CPU-OPENCL-AMD/kernel/default.host.c +14 -0
  111. data/skeletons/CPU-OPENCL-AMD/kernel/default.kernel.cl +13 -0
  112. data/skeletons/CPU-OPENCL-AMD/skeletons.txt +26 -0
  113. data/skeletons/CPU-OPENCL-INTEL/common/epilogue.c +3 -0
  114. data/skeletons/CPU-OPENCL-INTEL/common/globals.c +154 -0
  115. data/skeletons/CPU-OPENCL-INTEL/common/globals_kernel.c +4 -0
  116. data/skeletons/CPU-OPENCL-INTEL/common/header.c +31 -0
  117. data/skeletons/CPU-OPENCL-INTEL/common/mem_copy_D2H.c +5 -0
  118. data/skeletons/CPU-OPENCL-INTEL/common/mem_copy_H2D.c +3 -0
  119. data/skeletons/CPU-OPENCL-INTEL/common/mem_epilogue.c +3 -0
  120. data/skeletons/CPU-OPENCL-INTEL/common/mem_prologue.c +4 -0
  121. data/skeletons/CPU-OPENCL-INTEL/common/prologue.c +24 -0
  122. data/skeletons/CPU-OPENCL-INTEL/common/timer_1_start.c +5 -0
  123. data/skeletons/CPU-OPENCL-INTEL/common/timer_1_stop.c +9 -0
  124. data/skeletons/CPU-OPENCL-INTEL/common/timer_2_start.c +16 -0
  125. data/skeletons/CPU-OPENCL-INTEL/common/timer_2_stop.c +11 -0
  126. data/skeletons/CPU-OPENCL-INTEL/kernel/D-element-to-1-shared.host.c +67 -0
  127. data/skeletons/CPU-OPENCL-INTEL/kernel/D-element-to-1-shared.kernel.cl +72 -0
  128. data/skeletons/CPU-OPENCL-INTEL/kernel/default.host.c +14 -0
  129. data/skeletons/CPU-OPENCL-INTEL/kernel/default.kernel.cl +13 -0
  130. data/skeletons/CPU-OPENCL-INTEL/skeletons.txt +26 -0
  131. data/skeletons/CPU-OPENMP/common/epilogue.c +0 -0
  132. data/skeletons/CPU-OPENMP/common/globals.c +37 -0
  133. data/skeletons/CPU-OPENMP/common/globals_kernel.c +6 -0
  134. data/skeletons/CPU-OPENMP/common/header.c +0 -0
  135. data/skeletons/CPU-OPENMP/common/mem_copy_D2H.c +0 -0
  136. data/skeletons/CPU-OPENMP/common/mem_copy_H2D.c +0 -0
  137. data/skeletons/CPU-OPENMP/common/mem_epilogue.c +0 -0
  138. data/skeletons/CPU-OPENMP/common/mem_prologue.c +3 -0
  139. data/skeletons/CPU-OPENMP/common/prologue.c +0 -0
  140. data/skeletons/CPU-OPENMP/common/timer_1_start.c +12 -0
  141. data/skeletons/CPU-OPENMP/common/timer_1_stop.c +0 -0
  142. data/skeletons/CPU-OPENMP/common/timer_2_start.c +18 -0
  143. data/skeletons/CPU-OPENMP/common/timer_2_stop.c +8 -0
  144. data/skeletons/CPU-OPENMP/kernel/D-element-to-1-shared.host.c +27 -0
  145. data/skeletons/CPU-OPENMP/kernel/D-element-to-1-shared.kernel.c +46 -0
  146. data/skeletons/CPU-OPENMP/kernel/default.host.c +11 -0
  147. data/skeletons/CPU-OPENMP/kernel/default.kernel.c +18 -0
  148. data/skeletons/CPU-OPENMP/skeletons.txt +26 -0
  149. data/skeletons/GPU-CUDA/common/epilogue.c +0 -0
  150. data/skeletons/GPU-CUDA/common/globals.c +31 -0
  151. data/skeletons/GPU-CUDA/common/globals_kernel.c +4 -0
  152. data/skeletons/GPU-CUDA/common/header.c +0 -0
  153. data/skeletons/GPU-CUDA/common/mem_copy_D2H.c +3 -0
  154. data/skeletons/GPU-CUDA/common/mem_copy_H2D.c +3 -0
  155. data/skeletons/GPU-CUDA/common/mem_epilogue.c +3 -0
  156. data/skeletons/GPU-CUDA/common/mem_prologue.c +5 -0
  157. data/skeletons/GPU-CUDA/common/prologue.c +6 -0
  158. data/skeletons/GPU-CUDA/common/timer_1_start.c +6 -0
  159. data/skeletons/GPU-CUDA/common/timer_1_stop.c +10 -0
  160. data/skeletons/GPU-CUDA/common/timer_2_start.c +6 -0
  161. data/skeletons/GPU-CUDA/common/timer_2_stop.c +10 -0
  162. data/skeletons/GPU-CUDA/kernel/2xN-N-chunk-1-N-to-D-element.host.c +3 -0
  163. data/skeletons/GPU-CUDA/kernel/2xN-N-chunk-1-N-to-D-element.kernel.cu +105 -0
  164. data/skeletons/GPU-CUDA/kernel/D-element-to-1-shared.host.c +3 -0
  165. data/skeletons/GPU-CUDA/kernel/D-element-to-1-shared.kernel.cu +119 -0
  166. data/skeletons/GPU-CUDA/kernel/D-element-to-N-shared.host.c +3 -0
  167. data/skeletons/GPU-CUDA/kernel/D-element-to-N-shared.kernel.cu +166 -0
  168. data/skeletons/GPU-CUDA/kernel/N-N-chunk-1-N-to-D-element.host.c +3 -0
  169. data/skeletons/GPU-CUDA/kernel/N-N-chunk-1-N-to-D-element.kernel.cu +69 -0
  170. data/skeletons/GPU-CUDA/kernel/N-neighbourhood-N-to-N-element.host.c +3 -0
  171. data/skeletons/GPU-CUDA/kernel/N-neighbourhood-N-to-N-element.kernel.cu +42 -0
  172. data/skeletons/GPU-CUDA/kernel/default.host.c +3 -0
  173. data/skeletons/GPU-CUDA/kernel/default.kernel.cu +28 -0
  174. data/skeletons/GPU-CUDA/skeletons.txt +30 -0
  175. data/skeletons/GPU-OPENCL-AMD/common/epilogue.c +3 -0
  176. data/skeletons/GPU-OPENCL-AMD/common/globals.c +155 -0
  177. data/skeletons/GPU-OPENCL-AMD/common/globals_kernel.c +4 -0
  178. data/skeletons/GPU-OPENCL-AMD/common/header.c +0 -0
  179. data/skeletons/GPU-OPENCL-AMD/common/mem_copy_D2H.c +4 -0
  180. data/skeletons/GPU-OPENCL-AMD/common/mem_copy_H2D.c +4 -0
  181. data/skeletons/GPU-OPENCL-AMD/common/mem_epilogue.c +3 -0
  182. data/skeletons/GPU-OPENCL-AMD/common/mem_prologue.c +3 -0
  183. data/skeletons/GPU-OPENCL-AMD/common/prologue.c +24 -0
  184. data/skeletons/GPU-OPENCL-AMD/common/timer_1_start.c +5 -0
  185. data/skeletons/GPU-OPENCL-AMD/common/timer_1_stop.c +9 -0
  186. data/skeletons/GPU-OPENCL-AMD/common/timer_2_start.c +4 -0
  187. data/skeletons/GPU-OPENCL-AMD/common/timer_2_stop.c +11 -0
  188. data/skeletons/GPU-OPENCL-AMD/kernel/D-element-to-1-shared.host.c +67 -0
  189. data/skeletons/GPU-OPENCL-AMD/kernel/D-element-to-1-shared.kernel.cl +72 -0
  190. data/skeletons/GPU-OPENCL-AMD/kernel/default.host.c +14 -0
  191. data/skeletons/GPU-OPENCL-AMD/kernel/default.kernel.cl +13 -0
  192. data/skeletons/GPU-OPENCL-AMD/skeletons.txt +26 -0
  193. data/skeletons/verification/header.c +2 -0
  194. data/skeletons/verification/timer_start.c +4 -0
  195. data/skeletons/verification/timer_stop.c +6 -0
  196. data/skeletons/verification/verify_results.c +23 -0
  197. data/test/bones/test_algorithm.rb +40 -0
  198. data/test/bones/test_common.rb +54 -0
  199. data/test/bones/test_preprocessor.rb +46 -0
  200. data/test/bones/test_species.rb +21 -0
  201. data/test/bones/test_variable.rb +84 -0
  202. data/test/test_helper.rb +106 -0
  203. metadata +303 -0
@@ -0,0 +1,196 @@
1
+
2
+ module Bones
3
+ # The species class contains 'algorithm classes', or 'species'.
4
+ # Individual species contain a number of input and output
5
+ # structures and possibly a prefix.
6
+ #
7
+ # Examples of species are found below:
8
+ #
9
+ # 0:9|element -> 0:0|shared
10
+ # 0:31,0:31|neighbourhood(-1:1,-1:1) -> 0:31,0:31|element
11
+ # unordered 0:99,0:9|chunk(0:0,0:9) -> 0:99|element
12
+ #
13
+ # == Naming conventions
14
+ # The species class uses several naming conventions within
15
+ # functions. They are as follows for the example species
16
+ # '0:31,0:15|neighbourhood(-1:1,-1:1) ^ 0:31,0:15|element -> 0:31,0:15|element':
17
+ #
18
+ # input:: '0:31,0:15|neighbourhood(-1:1,-1:1) ^ 0:31,0:15|element'
19
+ # output:: '0:31,0:15|element'
20
+ # structures:: \['0:31,0:15|neighbourhood(-1:1,-1:1)', '0:31,0:15|element', '0:31,0:15|element']
21
+ # structure:: '0:31,0:15|neighbourhood(-1:1,-1:1)' or '0:31,0:15|element' (twice)
22
+ # pattern:: 'neighbourhood' or 'element'
23
+ # ranges:: \['0:31', '0:15'] or ['-1:1', '-1:1']
24
+ # range:: '0:31' or '0:15' or '-1:1'
25
+ # from:: '0' or '-1'
26
+ # to:: '31' or '15' or '1'
27
+ # sum:: '32' or '16' or '3'
28
+ class Species < Common
29
+ attr_reader :name, :inputs, :outputs, :skeleton_name, :settings, :prefix
30
+
31
+ # Initializes the species with a prefix, inputs and out-
32
+ # puts. It additionally verifies the correctness of the
33
+ # provided raw data.
34
+ def initialize(prefix, input, output)
35
+ @prefix = prefix
36
+ @name = (input+' '+ARROW+' '+output)
37
+ @inputs = set_structures(input)
38
+ @outputs = set_structures(output)
39
+ @skeleton_name = nil
40
+ @settings = nil
41
+ self.verify_species
42
+ end
43
+
44
+ # This method splits the raw data (a string) into seperate
45
+ # structures. The method returns an array of structures.
46
+ def set_structures(raw_data)
47
+ raw_data.split(WEDGE).map { |structure| Structure.new(structure) }
48
+ end
49
+
50
+ # Method to return an array of structures in a given di-
51
+ # rection.
52
+ def structures(direction)
53
+ (direction == INPUT) ? @inputs : @outputs
54
+ end
55
+
56
+ # Method to return an array of structures for both direc-
57
+ # tions.
58
+ def all_structures
59
+ @inputs + @outputs
60
+ end
61
+
62
+ # Method to return an ordered array of structures in a
63
+ # given direction. The order is specified by an argument
64
+ # which contains a list of pattern names.
65
+ def ordered(direction,order)
66
+ ordered = []
67
+ order.each do |pattern_name|
68
+ self.structures(direction).each do |structure|
69
+ ordered.push(structure) if structure.pattern == pattern_name
70
+ end
71
+ end
72
+
73
+ # Remove structures with a duplicate name (for matching only - and only if names are given)
74
+ if ordered.all? { |s| s.name != "" }
75
+ names = []
76
+ ordered.each do |structure|
77
+ ordered.delete(structure) if names.include?(structure.name)
78
+ names.push(structure.name)
79
+ end
80
+ end
81
+ return ordered
82
+ end
83
+
84
+ # This method maps an algorithm species to a skeleton.
85
+ # This is done based on a mapping file provided as part
86
+ # of the skeleton library. If multiple skeletons match
87
+ # the current species, the first found match is taken.
88
+ # This method does not return any values, but instead
89
+ # sets the class variables +skeleton_name+ and +settings+.
90
+ def set_skeleton(mapping_file)
91
+ matches = []
92
+ File.read(mapping_file).each_line do |line|
93
+ next if line =~ /^#/
94
+ data = line.split(/\s:/)
95
+ matches.push(data) if match_species?(data[0].split(ARROW))
96
+ end
97
+ puts MESSAGE+'Multiple matches in skeleton file, selecting the first listed' if matches.length > 1
98
+ if matches.length != 0
99
+ @skeleton_name = matches[0][1].delete(':').strip
100
+ @settings = matches[0][2].delete(':').strip
101
+ end
102
+ end
103
+
104
+ # This method is called by the +set_skeleton+ method. It
105
+ # performs a match between the current species and the
106
+ # species found in the mapping file. The matching is based
107
+ # on a fixed order of patterns. The method returns either
108
+ # true or false.
109
+ def match_species?(file_data)
110
+ DIRECTIONS.each_with_index do |direction,num_direction|
111
+ file_structures = file_data[num_direction].split(WEDGE)
112
+ counter = 0
113
+ search_structures = ordered(direction,['chunk','neighbourhood','element','shared','void'])
114
+ search_structures.each do |search_structure|
115
+ if !match?(file_structures[counter],search_structure)
116
+ if (counter != 0) && (file_structures[counter-1] =~ /\+/) && match?(file_structures[counter-1],search_structure)
117
+ counter = counter - 1
118
+ else
119
+ return false
120
+ end
121
+ end
122
+ counter = counter + 1
123
+ end
124
+ return false if counter != file_structures.length
125
+ end
126
+ return true
127
+ end
128
+
129
+ # This method implements the match between a species'
130
+ # structure and a structure found in the mapping file.
131
+ # It is called from the +match_species+ method. It first
132
+ # checks for a pattern match, followed by a match of the
133
+ # dimensions. The method returns either true or false.
134
+ # TODO: Complete the matching (N-dimensional).
135
+ def match?(file,search)
136
+ if (file =~ /#{search.pattern}/)
137
+ condition = true
138
+
139
+ # Check for parameters
140
+ if file.split('(').length == 2
141
+ parameters = file.split('(')[1].split(')')[0]
142
+ if (parameters == 'D') ||
143
+ ((parameters == 'N') && (search.parameters.length == 1)) ||
144
+ ((parameters == 'N,N') && (search.parameters.length == 2)) ||
145
+ ((parameters == 'N,1') && (search.parameters.length == 2) && simplify(sum(search.parameters[1])) == '1') ||
146
+ ((parameters == '1,N') && (search.parameters.length == 2) && simplify(sum(search.parameters[0])) == '1') ||
147
+ ((parameters == simplify(search.parameters.map { |r| sum(r) }.join(','))))
148
+ condition = condition && true
149
+ else
150
+ condition = false
151
+ end
152
+ end
153
+
154
+ # Check for dimensions
155
+ dimensions = file.split(PIPE)[0].strip
156
+ if (dimensions == 'D') ||
157
+ ((dimensions == 'N') && (search.dimensions.length == 1)) ||
158
+ ((dimensions == 'N,N') && (search.dimensions.length == 2)) ||
159
+ ((dimensions == simplify(search.dimensions.map { |r| sum(r) }.join(','))))
160
+ condition = condition && true
161
+ else
162
+ condition = false
163
+ end
164
+
165
+ # Return
166
+ return true if condition == true
167
+ end
168
+ return false
169
+ end
170
+
171
+ # Method to verify whether this species is shared-based
172
+ # or not. The method either returns true (if 'shared' is
173
+ # included in the input or output) or false (if not).
174
+ def shared?
175
+ (@name =~ /shared/)
176
+ end
177
+
178
+ # This method verifies if the species dimensions match
179
+ # with its parameters in terms of number of dimensions.
180
+ def verify_species
181
+ DIRECTIONS.each do |direction|
182
+ structures(direction).each do |structure|
183
+ if (structure.has_parameter?) && (structure.dimensions.length != structure.parameters.length)
184
+ puts WARNING+'Parameter dimension mismatch: '+structure.parameters.inspect+' versus '+structure.dimensions.inspect
185
+ end
186
+ structure.dimensions.each do |dimension|
187
+ puts WARNING+'Negative range given: '+dimension.inspect if (simplify(sum(dimension)).to_i < 1) && !(sum(dimension) =~ /[a-zA-Z]/)
188
+ end
189
+ end
190
+ end
191
+ end
192
+
193
+ end
194
+
195
+ end
196
+
@@ -0,0 +1,94 @@
1
+
2
+ module Bones
3
+ # This class represents a single structure in a species.
4
+ # Such a structure is a single input or output 'structure'.
5
+ # Stuctures can be set as part of array variables. Examples
6
+ # of structures are given below:
7
+ # 0:9|element
8
+ # 0:0|shared
9
+ # 0:31,0:31|neighbourhood(-1:1,-1:1)
10
+ # 0:99,0:9|chunk(0:0,0:9)
11
+ #
12
+ class Structure < Common
13
+ attr_reader :dimensions, :pattern, :parameters
14
+ attr_accessor :name
15
+
16
+ # The structure is initialized by the full name given as
17
+ # a string. It is then analyzed and stored accordingly in
18
+ # a number of class variables.
19
+ def initialize(raw_data)
20
+ data = raw_data.split(PIPE)
21
+ pattern_data = data[1].split('(')
22
+ dimension_data = data[0].split('[')
23
+ @pattern = pattern_data[0].strip
24
+ @name = (dimension_data.length == 2) ? dimension_data[0].strip : ''
25
+ @dimensions = (dimension_data.length == 2) ? dimension_data[1].delete(']').split(DIM_SEP) : dimension_data[0].split(DIM_SEP)
26
+ @parameters = (pattern_data.length > 1) ? pattern_data[1].delete(')').split(DIM_SEP) : []
27
+ end
28
+
29
+ # TODO: Implement the reverse function
30
+ def reverse?
31
+ true
32
+ end
33
+
34
+ # Method to find out if the structure has a parameter.
35
+ # This is only the case if it is neighbourhood or chunk
36
+ # based.
37
+ def has_parameter?
38
+ return (@parameters != [])
39
+ end
40
+
41
+ # Method to find out if the structure has a arrayname
42
+ # defined. This is optional for a structure.
43
+ def has_arrayname?
44
+ return (@name != '')
45
+ end
46
+
47
+ # Method to get the start of a range given a dimension 'n'.
48
+ # The method returns the proper simplified result, taking
49
+ # chunk-sizes into account.
50
+ def from_at(n)
51
+ return simplify(from(@dimensions[n]))
52
+ end
53
+
54
+ # Method to get the end of a range given a dimension 'n'.
55
+ # The method returns the proper simplified result, taking
56
+ # chunk-sizes into account.
57
+ def to_at(n)
58
+ return (chunk?) ? simplify('((('+to(@dimensions[n])+'+1)/('+to(@parameters[n])+'+1))-1)') : simplify(to(@dimensions[n]))
59
+ end
60
+
61
+ # Method to verify if a structure is empty or not (e.g. if
62
+ # it is based on the 'void' pattern.
63
+ def empty?
64
+ return @pattern =~ /void/
65
+ end
66
+
67
+ # Method to check whether a structure is element-based.
68
+ def element?
69
+ return @pattern =~ /element/
70
+ end
71
+
72
+ # Method to check whether a structure is neighbourhood-based.
73
+ def neighbourhood?
74
+ return @pattern =~ /neighbourhood/
75
+ end
76
+
77
+ # Method to check whether a structure is chunk-based.
78
+ def chunk?
79
+ return @pattern =~ /chunk/
80
+ end
81
+
82
+ # Method to check whether a structure is shared-based.
83
+ def shared?
84
+ return @pattern =~ /shared/
85
+ end
86
+
87
+ # Method to check whether a structure is full-based.
88
+ def full?
89
+ return @pattern =~ /full/
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,169 @@
1
+
2
+ module Bones
3
+ # This class represents individual variables. Variables have a
4
+ # name, a type, a direction and an id. They might also have an
5
+ # algorithmic species coupled if they represent an array. The
6
+ # variable type is in AST form and holds information which can
7
+ # be extracted through methods implemented for the Type class.
8
+ #
9
+ # The provided methods are able to obtain information from the
10
+ # variables, such as the number of dimensions and the definition.
11
+ # Other methods query variables for properties, such as whether
12
+ # a variable is an array or not. Several methods should only be
13
+ # executed if the variable is an array - this is not checked
14
+ # within the methods itself.
15
+ class Variable < Common
16
+ attr_reader :name, :type, :factors, :direction
17
+ attr_accessor :species, :size, :guess
18
+
19
+ # Method to initilize the variable class with a name, type
20
+ # and a direction.
21
+ def initialize(name,type,size,direction,id,shared)
22
+ @name = name
23
+ @type = type
24
+ @size = size
25
+ @direction = direction
26
+ @id = id
27
+ @shared = shared
28
+ @guess = false
29
+ @species = nil
30
+ end
31
+
32
+ # This method returns the device name of the variable.
33
+ def device_name
34
+ DEVICE+@name
35
+ end
36
+
37
+ # This method returns the 'golden' name of a variable.
38
+ # This is used to generate verification code.
39
+ def golden_name
40
+ GOLDEN + '_' + @name + '_' + @id
41
+ end
42
+
43
+ # Method to find out whether a variable is used as an in-
44
+ # put. If the current algorithm uses the 'shared' pattern,
45
+ # then the variable must be input only, otherwise it can
46
+ # be both input or inout to be considered input. The return
47
+ # value is boolean.
48
+ def input?
49
+ return (@shared) ? (@direction == INPUT) : (@direction == INPUT || @direction == INOUT)
50
+ end
51
+
52
+ # Method to find out whether a variable is used as an out-
53
+ # put. The variable can be both output or inout to be con-
54
+ # sidered input. The return value is boolean.
55
+ def output?
56
+ return (@direction == OUTPUT || @direction == INOUT)
57
+ end
58
+
59
+ # Method to obtain the type of a variable, omitting any
60
+ # information about arrays or pointers. Examples of out-
61
+ # puts are: +int+, +float+ or +char+. This functionality
62
+ # is implemented as a recursive search in the Type class,
63
+ # since the type is in AST form.
64
+ def type_name
65
+ @type.type_name.to_s
66
+ end
67
+
68
+ # Method to obtain the number of dimensions of a variable.
69
+ # This method returns a positive integer. The functionality
70
+ # is implemented as a recursive search in the Type class.
71
+ def dimensions
72
+ @type.dimensions
73
+ end
74
+
75
+ # Method to return the device version of a variable's
76
+ # definition. This includes the variable's type, zero or
77
+ # more stars and the variable's name, all returned as a
78
+ # single string.
79
+ def device_definition
80
+ type_name + device_pointer + ' ' + @name
81
+ end
82
+
83
+ # Method to obtain the full defintion of a variable. This
84
+ # includes the variable type, the variable name, and the
85
+ # dimensions and/or pointers. Example return values are:
86
+ # int example[10]
87
+ # char **variable
88
+ # unsigned int* example[N]
89
+ # float array[][]
90
+ def definition
91
+ definition_prefix + ' ' + @name + definition_suffix
92
+ end
93
+
94
+ # This method returns a star ('*') if the variable is an
95
+ # array or an empty string if it is not. It will not be
96
+ # able to return more than a single star, as device varia-
97
+ # bles are assumed to be flattened.
98
+ def device_pointer
99
+ (@type.array_or_pointer?) ? '*' : ''
100
+ end
101
+
102
+ # Method to flatten an array into a one dimensional array.
103
+ # If an array has multiple dimensions, the method will
104
+ # return a '[0]' for each additional dimension. This method
105
+ # assumes that the variable is an array.
106
+ def flatten
107
+ ''+'[0]'*(dimensions-1)
108
+ end
109
+
110
+ # This method returns the initialization code for a varia-
111
+ # ble, formatted as a string. This is used to generate the
112
+ # verification code.
113
+ def initialization
114
+ (dynamic?) ? " = (#{definition_prefix})malloc(#{@size.join('*')}*sizeof(#{type_name}));"+NL : ';'+NL
115
+ end
116
+
117
+ # This method detects whether the variable is dynamically
118
+ # allocated or not. It returns either true or false.
119
+ def dynamic?
120
+ (definition_prefix.count('*') > 0)
121
+ end
122
+
123
+ # Method to return an array of multiplication factors for
124
+ # multi-dimensional arrays that need to be flattened. For
125
+ # every dimension, one factor is generated.
126
+ def set_factors
127
+ raise_error("Species dimensions (#{@species.dimensions.length}) and array dimensions (#{@size.length}) mismatch for array '#{@name}'") if @species.dimensions.length != @size.length
128
+ sizes, @factors = [], []
129
+ @species.dimensions.each_with_index do |dimension,num_dimension|
130
+ (sizes.empty?) ? @factors.push('') : @factors.push('*'+sizes.join('*'))
131
+ sizes.push(simplify(@size[dimensions-num_dimension-1]))
132
+ end
133
+ end
134
+
135
+ # Method to return the full flattened address.
136
+ def flatindex
137
+ indices = []
138
+ @species.dimensions.each_with_index do |dimension,num_dimension|
139
+ index_reverse = !(@species.reverse?) ? num_dimension : @species.dimensions.length-num_dimension-1 # FIXME: REVERSED
140
+ if (from(dimension) != to(dimension))
141
+ data = "#{GLOBAL_ID}_#{index_reverse}"
142
+ else
143
+ data = from(dimension)
144
+ end
145
+ indices.push(data + @factors[index_reverse])
146
+ end
147
+ return indices.join(' + ')
148
+ end
149
+
150
+ # Start of the class's private methods.
151
+ private
152
+
153
+ # Method to obtain the prefix of a variable's definition,
154
+ # formatted as a string. The string contains the variable's
155
+ # type and zero or more stars ('*').
156
+ def definition_prefix
157
+ @type.to_s.partition('[')[0].strip
158
+ end
159
+
160
+ # Method to obtain the suffix of a variable's definition,
161
+ # formatted as a string. The string is either empty or
162
+ # contains one or more brackets (e.g. [N][M] or [10]).
163
+ def definition_suffix
164
+ @type.to_s.partition('[')[1]+@type.to_s.partition('[')[2]
165
+ end
166
+
167
+ end
168
+
169
+ end