Package hedge :: Package cuda :: Module cgen
[frames] | no frames]

Source Code for Module hedge.cuda.cgen

  1  """Interface with Nvidia CUDA.""" 
  2   
  3  from __future__ import division 
  4   
  5  __copyright__ = "Copyright (C) 2008 Andreas Kloeckner" 
  6   
  7  __license__ = """ 
  8  This program is free software: you can redistribute it and/or modify 
  9  it under the terms of the GNU General Public License as published by 
 10  the Free Software Foundation, either version 3 of the License, or 
 11  (at your option) any later version. 
 12   
 13  This program is distributed in the hope that it will be useful, 
 14  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  GNU General Public License for more details. 
 17   
 18  You should have received a copy of the GNU General Public License 
 19  along with this program.  If not, see U{http://www.gnu.org/licenses/}. 
 20  """ 
 21   
 22   
 23   
 24   
 25  import numpy 
 26  import numpy.linalg as la 
 27  from pytools import memoize_method 
 28   
 29   
 30   
 31   
32 -def dtype_to_ctype(dtype):
33 dtype = numpy.dtype(dtype) 34 if dtype == numpy.int32: 35 return "int" 36 elif dtype == numpy.uint32: 37 return "unsigned int" 38 elif dtype == numpy.int16: 39 return "short int" 40 elif dtype == numpy.uint16: 41 return "short unsigned int" 42 elif dtype == numpy.int8: 43 return "signed char" 44 elif dtype == numpy.uint8: 45 return "unsigned char" 46 elif dtype == numpy.intp or dtype == numpy.uintp: 47 return "void *" 48 elif dtype == numpy.float32: 49 return "float" 50 elif dtype == numpy.float64: 51 return "double" 52 else: 53 raise ValueError, "unable to map dtype '%s'" % dtype
54 55 56 57
58 -class Generable(object):
59 - def __str__(self):
60 return "\n".join(self.generate())
61
62 -class Declarator(Generable):
63 - def generate(self, with_semicolon=True):
64 tp_lines, tp_decl = self.get_decl_pair() 65 tp_lines = list(tp_lines) 66 for line in tp_lines[:-1]: 67 yield line 68 sc = ";" 69 if not with_semicolon: 70 sc = "" 71 if tp_decl is None: 72 yield "%s%s" % (tp_lines[-1], sc) 73 else: 74 yield "%s %s%s" % (tp_lines[-1], tp_decl, sc)
75
76 - def inline(self, with_semicolon=True):
77 tp_lines, tp_decl = self.get_decl_pair() 78 tp_lines = " ".join(tp_lines) 79 if tp_decl is None: 80 return tp_lines 81 else: 82 return "%s %s" % (tp_lines, tp_decl)
83
84 -class POD(Declarator):
85 - def __init__(self, dtype, name):
86 self.dtype = numpy.dtype(dtype) 87 self.name = name
88
89 - def get_decl_pair(self):
90 return [dtype_to_ctype(self.dtype)], self.name
91
92 - def struct_args(self, data):
93 return [data]
94
95 - def struct_format(self):
96 return self.dtype.char
97
98 -class Value(Declarator):
99 - def __init__(self, typename, name):
100 self.typename = typename 101 self.name = name
102
103 - def get_decl_pair(self):
104 return [self.typename], self.name
105
106 - def struct_args(self, data):
107 raise RuntimeError, "named-type values can't be put into structs"
108
109 - def struct_format(self):
110 raise RuntimeError, "named-type values have no struct format"
111 112 113 114
115 -class NestedDeclarator(Declarator):
116 - def __init__(self, subdecl):
117 self.subdecl = subdecl
118 119 @property
120 - def name(self):
121 return self.subdecl.name
122
123 - def struct_format(self):
124 return self.subdecl.struct_format()
125
126 - def struct_args(self, data):
127 return self.subdecl.struct_args(data)
128
129 - def get_decl_pair(self):
130 return self.subdecl.get_decl_pair()
131
132 -class DeclSpecifier(NestedDeclarator):
133 - def __init__(self, subdecl, spec):
134 NestedDeclarator.__init__(self, subdecl) 135 self.spec = spec
136
137 - def get_decl_pair(self):
138 def add_spec(sub_it): 139 it = iter(sub_it) 140 try: 141 yield "%s %s" % (self.spec, it.next()) 142 except StopIteration: 143 pass 144 145 for line in it: 146 yield line
147 148 sub_tp, sub_decl = self.subdecl.get_decl_pair() 149 return add_spec(sub_tp), sub_decl
150
151 -class Typedef(DeclSpecifier):
152 - def __init__(self, subdecl):
153 DeclSpecifier.__init__(self, subdecl, "typedef")
154
155 -class Static(DeclSpecifier):
156 - def __init__(self, subdecl):
157 DeclSpecifier.__init__(self, subdecl, "static")
158
159 -class CudaGlobal(DeclSpecifier):
160 - def __init__(self, subdecl):
161 DeclSpecifier.__init__(self, subdecl, "__global__")
162
163 -class CudaDevice(DeclSpecifier):
164 - def __init__(self, subdecl):
165 DeclSpecifier.__init__(self, subdecl, "__device__")
166
167 -class CudaShared(DeclSpecifier):
168 - def __init__(self, subdecl):
169 DeclSpecifier.__init__(self, subdecl, "__shared__")
170
171 -class CudaConstant(DeclSpecifier):
172 - def __init__(self, subdecl):
173 DeclSpecifier.__init__(self, subdecl, "__constant__")
174 175 176
177 -class Const(NestedDeclarator):
178 - def get_decl_pair(self):
179 sub_tp, sub_decl = self.subdecl.get_decl_pair() 180 return sub_tp, ("const %s" % sub_decl)
181
182 -class Pointer(NestedDeclarator):
183 - def __init__(self, subdecl, count=None):
184 NestedDeclarator.__init__(self, subdecl) 185 self.count = count
186
187 - def get_decl_pair(self):
188 sub_tp, sub_decl = self.subdecl.get_decl_pair() 189 return sub_tp, ("*%s" % sub_decl)
190
191 - def struct_args(self, data):
192 return data
193
194 - def struct_format(self):
195 return "P"
196
197 -class ArrayOf(NestedDeclarator):
198 - def __init__(self, subdecl, count=None):
199 NestedDeclarator.__init__(self, subdecl) 200 self.count = count
201
202 - def get_decl_pair(self):
203 sub_tp, sub_decl = self.subdecl.get_decl_pair() 204 if self.count is None: 205 count_str = "" 206 else: 207 count_str = str(self.count) 208 return sub_tp, ("%s[%s]" % (sub_decl, count_str))
209
210 - def struct_args(self, data):
211 return data
212
213 - def struct_format(self):
214 if self.count is None: 215 return "P" 216 else: 217 return "%d%s" % (self.count, self.subdecl.struct_format())
218 219 220 221
222 -class FunctionDeclaration(NestedDeclarator):
223 - def __init__(self, subdecl, arg_decls):
224 NestedDeclarator.__init__(self, subdecl) 225 self.arg_decls = arg_decls
226
227 - def get_decl_pair(self):
228 sub_tp, sub_decl = self.subdecl.get_decl_pair() 229 230 return sub_tp, ("%s(%s)" % ( 231 sub_decl, 232 ", ".join(ad.inline() for ad in self.arg_decls)))
233
234 - def struct_args(self, data):
235 raise RuntimeError, "function pointers can't be put into structs"
236
237 - def struct_format(self):
238 raise RuntimeError, "function pointers have no struct format"
239 240 241 242
243 -class Struct(Declarator):
244 - def __init__(self, tpname, fields, declname=None, debug=False):
245 self.tpname = tpname 246 self.fields = fields 247 self.declname = declname 248 self.debug = debug
249
250 - def get_decl_pair(self):
251 def get_tp(): 252 if self.tpname is not None: 253 yield "struct %s" % self.tpname 254 else: 255 yield "struct" 256 yield "{" 257 for f in self.fields: 258 for f_line in f.generate(): 259 yield " " + f_line 260 yield "}"
261 return get_tp(), self.declname
262
263 - def make(self, **kwargs):
264 import struct 265 data = [] 266 for f in self.fields: 267 data.extend(f.struct_args(kwargs[f.name])) 268 if self.debug: 269 print self 270 print data 271 print self.struct_format() 272 print kwargs 273 print [ord(i) for i in struct.pack(self.struct_format(), *data)] 274 raw_input() 275 return struct.pack(self.struct_format(), *data)
276 277 @memoize_method
278 - def struct_format(self):
279 return "".join(decl.struct_format() for decl in self.fields)
280 281 @memoize_method
282 - def __len__(self):
283 from struct import calcsize 284 return calcsize(self.struct_format())
285 286 287 288 289 # control flow/statement stuff ------------------------------------------------
290 -class If(Generable):
291 - def __init__(self, condition, then_, else_=None):
292 self.condition = condition 293 self.then_ = then_ 294 self.else_ = else_
295
296 - def generate(self):
297 yield "if (%s)" % self.condition 298 299 if isinstance(self.then_, Block): 300 for line in self.then_.generate(): 301 yield line 302 else: 303 for line in self.then_.generate(): 304 yield " "+line 305 306 if self.else_ is not None: 307 yield "else" 308 if isinstance(self.else_, Block): 309 for line in self.else_.generate(): 310 yield line 311 else: 312 for line in self.else_.generate(): 313 yield " "+line
314
315 -class While(Generable):
316 - def __init__(self, condition, body):
317 self.condition = condition 318 self.body = body
319
320 - def generate(self):
321 yield "while (%s)" % self.condition 322 323 if isinstance(self.body, Block): 324 for line in self.body.generate(): 325 yield line 326 else: 327 for line in self.body.generate(): 328 yield " "+line
329
330 -class For(Generable):
331 - def __init__(self, start, condition, end, body):
332 self.start = start 333 self.condition = condition 334 self.end = end 335 self.body = body
336
337 - def generate(self):
338 yield "for (%s; %s; %s)" % (self.start, self.condition, self.end) 339 340 if isinstance(self.body, Block): 341 for line in self.body.generate(): 342 yield line 343 else: 344 for line in self.body.generate(): 345 yield " "+line
346
347 -class DoWhile(Generable):
348 - def __init__(self, condition, body):
349 self.condition = condition 350 self.body = body
351
352 - def generate(self):
353 yield "do" 354 if isinstance(self.body, Block): 355 for line in self.body.generate(): 356 yield line 357 else: 358 for line in self.body.generate(): 359 yield " "+line 360 yield "while (%s)" % self.condition
361
362 -def make_multiple_ifs(conditions_and_blocks, base=None):
363 for cond, block in conditions_and_blocks[::-1]: 364 base = If(cond, block, base) 365 return base
366 367 368 369 370 # simple statements -----------------------------------------------------------
371 -class Define(Generable):
372 - def __init__(self, symbol, value):
373 self.symbol = symbol 374 self.value = value
375
376 - def generate(self):
377 yield "#define %s %s" % (self.symbol, self.value)
378
379 -class Pragma(Generable):
380 - def __init__(self, value):
381 self.value = value
382
383 - def generate(self):
384 yield "#pragma %s" % (self.value)
385
386 -class Statement(Generable):
387 - def __init__(self, text):
388 self.text = text
389
390 - def generate(self):
391 yield self.text+";"
392
393 -class Assign(Generable):
394 - def __init__(self, lvalue, rvalue):
395 self.lvalue = lvalue 396 self.rvalue = rvalue
397
398 - def generate(self):
399 yield "%s = %s;" % (self.lvalue, self.rvalue)
400
401 -class Line(Generable):
402 - def __init__(self, text=""):
403 self.text = text
404
405 - def generate(self):
406 yield self.text
407
408 -class Comment(Generable):
409 - def __init__(self, text):
410 self.text = text
411
412 - def generate(self):
413 yield "/* %s */" % self.text
414 415 416 417 # initializers ----------------------------------------------------------------
418 -class Initializer(Generable):
419 - def __init__(self, vdecl, data):
420 self.vdecl = vdecl 421 self.data = data
422
423 - def generate(self):
424 tp_lines, tp_decl = self.vdecl.get_decl_pair() 425 tp_lines = list(tp_lines) 426 for line in tp_lines[:-1]: 427 yield line 428 yield "%s %s = %s;" % (tp_lines[-1], tp_decl, self.data)
429
430 -def Constant(vdecl, data):
431 return Initializer(Const(vdecl), data)
432
433 -class ArrayInitializer(Generable):
434 - def __init__(self, vdecl, data):
435 self.vdecl = vdecl 436 self.data = data
437
438 - def generate(self):
439 for v_line in self.vdecl.generate(with_semicolon=False): 440 yield v_line 441 yield " = { %s };" % (", ".join(str(item) for item in self.data))
442
443 -class FunctionBody(Generable):
444 - def __init__(self, fdecl, body):
445 self.fdecl = fdecl 446 self.body = body
447
448 - def generate(self):
449 for f_line in self.fdecl.generate(with_semicolon=False): 450 yield f_line 451 for b_line in self.body.generate(): 452 yield b_line
453 454 455 456 457 458 # block -----------------------------------------------------------------------
459 -class Block(Generable):
460 - def __init__(self, contents=[]):
461 self.contents = contents[:]
462
463 - def generate(self):
464 yield "{" 465 for item in self.contents: 466 for item_line in item.generate(): 467 yield " " + item_line 468 yield "}"
469
470 - def append(self, data):
471 self.contents.append(data)
472
473 - def extend(self, data):
474 self.contents.extend(data)
475
476 - def extend_log_block(self, descr, data):
477 self.contents.append(Comment(descr)) 478 self.contents.extend(data) 479 self.contents.append(Line())
480
481 -class Module(Block):
482 - def generate(self):
483 for c in self.contents: 484 for line in c.generate(): 485 yield line
486 487 488 489 490
491 -def _test():
492 s = Struct("yuck", [ 493 POD(numpy.float32, "h", ), 494 POD(numpy.float32, "order"), 495 POD(numpy.float32, "face_jacobian"), 496 ArrayOf(POD(numpy.float32, "normal"), 17), 497 POD(numpy.uint16, "a_base"), 498 POD(numpy.uint16, "b_base"), 499 CudaGlobal(POD(numpy.uint8, "a_ilist_number")), 500 POD(numpy.uint8, "b_ilist_number"), 501 POD(numpy.uint8, "bdry_flux_number"), # 0 if not on boundary 502 POD(numpy.uint8, "reserved"), 503 POD(numpy.uint32, "b_global_base"), 504 ]) 505 f_decl = FunctionDeclaration(POD(numpy.uint16, "get_num"), [ 506 POD(numpy.uint8, "reserved"), 507 POD(numpy.uint32, "b_global_base"), 508 ]) 509 f_body = FunctionBody(f_decl, Block([ 510 POD(numpy.uint32, "i"), 511 For("i = 0", "i < 17", "++i", 512 If("a > b", 513 Assign("a", "b"), 514 Block([ 515 Assign("a", "b-1", "+="), 516 Break(), 517 ]) 518 ), 519 ), 520 BlankLine(), 521 Comment("all done"), 522 ])) 523 print s 524 print f_body
525 526 527 528 529 if __name__ == "__main__": 530 _test() 531