def visit_arguments(self, node): args = map(lambda arg: self.visit(arg), node.args) defaults = map(lambda tup: self.visit(tup), node.defaults) annotations = dict() for tup in defaults: annotations[tup[0].text] = tuple([elt.text for elt in tup]) ret = [] if len(self._data_model) != len(args): raise TypeError('Expected %d arguments, received %d' % (len(args), len(self._data_model))) foo = zip(args, self._data_model) for arg, model in foo: model.name = arg.name model.should_subsample = not (model.name in annotations and 'nosubsample' in annotations[model.name]) if not model.should_subsample and type(model) is not DataModel: model = DataModel.clone(model) model.dimensions = tuple([len(model)] + model.dimensions[1:]) ret.append(cpp_ast.Pointer(cpp_ast.Value(model.ctype(), arg.name))) self.data_model[arg.name] = model self.arg_model.append(model) if self.weighted: ret.append( cpp_ast.Pointer( cpp_ast.Value("const unsigned int", cpp_ast.CName('_blb_weights')))) return ret
def gen_array_unpack(self): ret = [ cpp_ast.Assign( cpp_ast.Pointer(cpp_ast.Value("npy_double", "_my_" + x)), cpp_ast.TypeCast( cpp_ast.Pointer(cpp_ast.Value("npy_double", "")), cpp_ast.FunctionCall(cpp_ast.CName("PyArray_DATA"), params=[cpp_ast.CName(x)]))) for x in self.argdict.keys() ] return ret
def visit_StencilModel(self, node): self.argdict = dict() for i in range(len(node.input_grids)): self.var_names.append(node.input_grids[i].name) self.argdict[node.input_grids[i].name] = self.input_grids[i] self.argdict[self.output_grid_name] = self.output_grid assert node.border_kernel.body == [], 'Border kernels not yet implemented' func_name = "kernel" arg_names = [x.name for x in node.input_grids] + [self.output_grid_name] args = [ cpp_ast.Pointer(cpp_ast.Value("PyObject", x)) for x in arg_names ] body = cpp_ast.Block() # generate the code to unpack arrays into C++ pointers and macros for accessing # the arrays body.extend([self.gen_array_macro_definition(x) for x in self.argdict]) body.extend(self.gen_array_unpack()) body.append(self.visit_interior_kernel(node.interior_kernel)) return cpp_ast.FunctionBody( cpp_ast.FunctionDeclaration(cpp_ast.Value("void", func_name), args), body)
def render(self, node): declarator, args, body = self.visit(node) self.inject_registers(body) args.append( cpp_ast.Pointer( cpp_ast.Value(self.retModel.scalar_t.ctype(), '_blb_result'))) model = cpp_ast.FunctionBody( cpp_ast.FunctionDeclaration(declarator, args), body) self.desired_funcs.extend(functions.flush_requests()) return str(model)
def visit_For(self, node): _iters = self.visit(node.iter) targets = self.visit(node.target) #are we iterating over a data object? if type(_iters) is cpp_ast.CName and _iters.name in self.data_model: _iters = [_iters] targets = [targets] #co-iterating over a set of datasets! if type(_iters) is list: #set up the loop variable and weight self.loopvar.append(self.loopvar[-1] + 'i') loopvar = cpp_ast.CName(self.loopvar[-1]) body = [] weight_loop = self.weighted and reduce(lambda a, b: a or b, [ (_iter.name in self.data_model and self.data_model[_iter.name].should_subsample) for _iter in _iters ]) if weight_loop: self.aggregate_on(loopvar) # add the temporary children to the data model for target, _iter in zip(targets, _iters): if not (type(_iter) is cpp_ast.CName and _iter.name in self.data_model): raise ValueError( "Cannot iterate over unknown data object: '%s'" % _iter.name) parent_model = self.data_model[_iter.name] if type(target) is not cpp_ast.CName: raise ValueError("Not a valid iteration target: '%s'" % str(target)) if target.name in self.data_model: raise ValueError("Cannot reuse iteration target: '%s'" % target.name) target_model = self.data_model[ target.name] = parent_model.branch(name=target.name) ctype = target_model.scalar_t.ctype() decl = cpp_ast.Value( ctype, target.name) if target_model.is_scalar( ) else cpp_ast.Pointer(cpp_ast.Value(ctype, target.name)) init = parent_model.declare_child(target_model, loopvar) #init = cpp_ast.Subscript( _iter, loopvar) if target_model.is_scalar() \ # else cpp_ast.BinOp( _iter, '+', cpp_ast.BinOp( loopvar , '*', parent_model.element_size() ) ) body.append(cpp_ast.Assign(decl, init)) # visit the body of the for body += [self.visit(x) for x in node.body] # generate the C for intializer ret = cpp_ast.RawFor( cpp_ast.Assign( cpp_ast.Value( 'int', loopvar ), cpp_ast.CNumber(0) ), \ cpp_ast.Compare( loopvar, '<', cpp_ast.CNumber( self.data_model[ _iter.name ].dimensions[0] ) ), \ cpp_ast.UnaryOp( '++', loopvar ), cpp_ast.Block( body ) ) # remove temporary children from data model and otherwise clean up self.loopvar = self.loopvar[:-1] for target in targets: del self.data_model[target.name] if weight_loop: self.aggregate_off(loopvar) # return return ret #or perhaps, a known range. elif isinstance(_iters, cpp_ast.CNumber): return cpp_ast.RawFor( cpp_ast.Assign( cpp_ast.Value( 'int', targets ), cpp_ast.CNumber(0) ), \ cpp_ast.Compare( targets, '<', _iter ), cpp_ast.UnaryOp( '++', target ), \ cpp_ast.Block([ self.visit( x ) for x in node.body ] ) ) else: raise ValueError( 'Loop iterand "%s" is not a numeric expression or known data object' % str(_iters))