source: proto/Compiler/pablo.py @ 1074

Last change on this file since 1074 was 1074, checked in by cameron, 8 years ago

Add ScanToFirst? support

File size: 23.0 KB
Line 
1#
2# Pablo.py - parallel bitstream to bitblock
3#  2nd generation compiler
4#
5# Copyright 2010, 2011, Robert D. Cameron, Kenneth S. Herdy
6# All rights reserved.
7#
8import ast, copy, sys
9import Cgen
10
11def is_BuiltIn_Call(fncall, builtin_fnname, builtin_arg_cnt, builtin_fnmod_noprefix='bitutil'):
12        if isinstance(fncall.func, ast.Name): iscall = fncall.func.id == builtin_fnname
13        elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
14                 iscall = fncall.func.value.id == builtin_fnmod_noprefix and fncall.func.attr == builtin_fnname
15        return iscall and len(fncall.args) == builtin_arg_cnt and fncall.kwargs == None and fncall.starargs == None
16
17def is_simd_not(e):
18  return isinstance(e, ast.Call) and isinstance(e.func, ast.Name) and e.func.id == 'simd_not'
19
20def mkQname(obj, field):
21  return ast.Attribute(ast.Name(obj, ast.Load()), field, ast.Load())
22
23def mkCall(fn_name, args):
24  if isinstance(fn_name, str): fn_name = ast.Name(fn_name, ast.Load())
25  return ast.Call(fn_name, args, [], None, None)
26
27def mkCallStmt(fn_name, args):
28  if isinstance(fn_name, str): fn_name = ast.Name(fn_name, ast.Load())
29  return ast.Expr(ast.Call(fn_name, args, [], None, None))
30
31#
32# Reducing AugAssign, e.g.  x |= y becomes x = x | y
33#
34class AugAssignRemoval(ast.NodeTransformer):
35  def xfrm(self, t):
36    return self.generic_visit(t)
37  def visit_AugAssign(self, e):
38    self.generic_visit(e)
39    return ast.Assign([e.target], ast.BinOp(e.target, e.op, e.value))
40
41#
42# Introducing BitBlock logical operations
43#
44class Bitwise_to_SIMD(ast.NodeTransformer):
45  """
46  Make the following substitutions:
47     x & y => simd_and(x, y)
48     x & ~y => simd_andc(x, y)
49     x | y => simd_or(x, y)
50     x ^ y => simd_xor(x, y)
51     ~x    => simd_not(x)
52     0     => simd_const_1(0)
53     -1    => simd_const_1(1)
54     if x: => if bitblock_has_bit(x):
55  while x: => while bitblock_has_bit(x):
56  >>> ast_show(Bitwise_to_SIMD().xfrm(ast.parse("pfx = bit0 & bit1; sfx = bit0 &~ bit1")))
57 
58  pfx = simd_and(bit0, bit1)
59  sfx = simd_and(bit0, simd_not(bit1))
60  >>>
61  """
62  def xfrm(self, t):
63    return self.generic_visit(t)
64  def visit_UnaryOp(self, t):
65    self.generic_visit(t)
66    if isinstance(t.op, ast.Invert):
67      return mkCall('simd_not', [t.operand])
68    else: return t
69  def visit_BinOp(self, t):
70    self.generic_visit(t)
71    if isinstance(t.op, ast.BitOr):
72      return mkCall('simd_or', [t.left, t.right])
73    elif isinstance(t.op, ast.BitAnd):
74      if is_simd_not(t.right): return mkCall('simd_andc', [t.left, t.right.args[0]])
75      elif is_simd_not(t.left): return mkCall('simd_andc', [t.right, t.left.args[0]])
76      else: return mkCall('simd_and', [t.left, t.right])
77    elif isinstance(t.op, ast.BitXor):
78      return mkCall('simd_xor', [t.left, t.right])
79    else: return t
80  def visit_Num(self, numnode):
81    n = numnode.n
82    if n == 0: return mkCall('simd_const_1', [numnode])
83    elif n == -1: return mkCall('simd_const_1', [ast.Num(1)])
84    else: return numnode
85  def visit_If(self, ifNode):
86    self.generic_visit(ifNode)
87    ifNode.test = mkCall('bitblock_has_bit', [ifNode.test])
88    return ifNode
89  def visit_While(self, whileNode):
90    self.generic_visit(whileNode)
91    whileNode.test = mkCall('bitblock_has_bit', [whileNode.test])
92    return whileNode
93  def visit_Subscript(self, numnode):
94    return numnode  # no recursive modifications of index expressions
95
96#
97#  Generating BitBlock declarations for Local Variables
98#
99class FunctionVars(ast.NodeVisitor):
100  def __init__(self,node):
101        self.params = []
102        self.stores = []
103        self.generic_visit(node)
104  def visit_Name(self, nm):
105    if isinstance(nm.ctx, ast.Param):
106      self.params.append(nm.id)
107    if isinstance(nm.ctx, ast.Store):
108      if nm.id not in self.stores: self.stores.append(nm.id)
109  def getLocals(self): 
110    return [v for v in self.stores if not v in self.params]
111
112MAX_LINE_LENGTH = 80
113
114def BitBlock_decls_from_vars(varlist):
115  global MAX_LINE_LENGTH
116  decls =  ""
117  if not len(varlist) == 0:
118          decls = "             BitBlock"
119          pending = ""
120          linelgth = 10
121          for v in varlist:
122            if linelgth + len(v) + 2 <= MAX_LINE_LENGTH:
123              decls += pending + " " + v
124              linelgth += len(pending + v) + 1
125            else:
126              decls += ";\n             BitBlock " + v
127              linelgth = 11 + len(v)
128            pending = ","
129          decls += ";"
130  return decls
131
132def BitBlock_decls_of_fn(fndef):
133  return BitBlock_decls_from_vars(FunctionVars(fndef).getLocals())
134
135def BitBlock_header_of_fn(fndef):
136  Ccode = "static inline void " + fndef.name + "("
137  pending = ""
138  for arg in fndef.args.args:
139    if isinstance(arg, ast.Name):
140      Ccode += pending + arg.id.upper()[0] + arg.id[1:] + " & " + arg.id
141      pending = ", "
142  if CarryCounter().count(fndef) > 0:
143    Ccode += pending + " CarryQtype & carryQ"
144  Ccode += ")"
145  return Ccode
146
147
148
149#
150#  Stream Initialization Statement Extraction
151#
152#  streamvar = 1 ==> streamvar = sisd_from_int(1) initially.
153class StreamInitializations(ast.NodeTransformer):
154  def xfrm(self, node):
155    self.stream_stmts = []
156    self.loop_post_inits = []
157    self.generic_visit(node)
158    return Cgen.py2C().gen(self.stream_stmts)
159  def visit_Assign(self, node):
160    if isinstance(node.value, ast.Num):
161      if node.value.n == 0: return node
162      elif node.value.n == -1: return node
163      else: 
164        stream_init = copy.deepcopy(node)
165        stream_init.value = mkCall('sisd_from_int', [node.value])
166        loop_init = copy.deepcopy(node)
167        loop_init.value.n = 0
168        self.stream_stmts.append(stream_init)
169        self.loop_post_inits.append(loop_init)
170        return None
171    else: return node
172  def visit_FunctionDef(self, node):
173    self.generic_visit(node)
174    node.body = node.body + self.loop_post_inits
175    return node
176
177#
178# Carry Introduction Transformation
179#
180class CarryCounter(ast.NodeVisitor):
181  def visit_Call(self, callnode):
182    self.generic_visit(callnode)
183    if is_BuiltIn_Call(callnode,'Advance', 1) or is_BuiltIn_Call(callnode,'ScanThru', 2) or is_BuiltIn_Call(callnode,'ScanTo', 2) or is_BuiltIn_Call(callnode,'ScanToFirst', 1):       
184      self.carry_count += 1
185  def visit_BinOp(self, exprnode):
186    self.generic_visit(exprnode)
187    if isinstance(exprnode.op, ast.Sub):
188      self.carry_count += 1
189    if isinstance(exprnode.op, ast.Add):
190      self.carry_count += 1
191  def count(self, nodeToVisit):
192    self.carry_count = 0
193    self.generic_visit(nodeToVisit)
194    return self.carry_count
195
196class CarryIntro(ast.NodeTransformer):
197  def __init__(self, carryvar="carryQ", carryin = "_ci", carryout = "_co"):
198    self.carryvar = ast.Name(carryvar, ast.Load())
199    self.carryin = carryin
200    self.carryout = carryout
201  def xfrm_fndef(self, fndef):
202    self.current_carry = 0
203    carry_count = CarryCounter().count(fndef)
204    if carry_count == 0: return fndef
205    self.generic_visit(fndef)
206#   
207#    fndef.body.insert(0, mkCallStmt('CarryDeclare', [self.carryvar, ast.Num(carry_count)]))
208    return fndef
209  def generic_xfrm(self, node):
210    self.current_carry = 0
211    carry_count = CarryCounter().count(node)
212    if carry_count == 0: return node
213    self.generic_visit(node)
214    return node
215  def visit_Call(self, callnode):
216    self.generic_visit(callnode)
217    if self.carryin == '' and self.carryout == '': carry_args = []
218    else: carry_args = [self.carryvar, ast.Num(self.current_carry)]
219    if is_BuiltIn_Call(callnode, 'Advance', 1):         
220      rtn = "BitBlock_advance%s%s" % (self.carryin, self.carryout)
221      c = mkCall(rtn, callnode.args + carry_args)
222      self.current_carry += 1
223      return c
224    elif is_BuiltIn_Call(callnode, 'ScanThru', 2):
225      rtn = "BitBlock_scanthru%s%s" % (self.carryin, self.carryout)
226      c = mkCall(rtn, callnode.args + carry_args)
227      self.current_carry += 1
228      return c
229    elif is_BuiltIn_Call(callnode, 'ScanTo', 2):
230      rtn = "BitBlock_scanto%s%s" % (self.carryin, self.carryout)
231      if self.carryout == "":  carry_args = [ast.Name('EOF_mask', ast.Load())] + carry_args
232      c = mkCall(rtn, callnode.args + carry_args)
233      self.current_carry += 1
234      return c
235    elif is_BuiltIn_Call(callnode, 'ScanToFirst', 1):
236      rtn = "BitBlock_scantofirst"
237      #if self.carryout == "":  carry_args = [ast.Name('EOF_mask', ast.Load())] + carry_args
238      c = mkCall(rtn, callnode.args + carry_args)
239      self.current_carry += 1
240      return c
241    elif is_BuiltIn_Call(callnode, 'StreamScan', 2):
242      rtn = "StreamScan"           
243      c = mkCall(rtn, [ast.Name('(ScanBlock *) &' + callnode.args[0].id, ast.Load()), 
244                                           ast.Name('sizeof(BitBlock)/sizeof(ScanBlock)', ast.Load()),
245                                           ast.Name(callnode.args[1].id, ast.Load())])
246      return c
247    else: return callnode
248  def visit_BinOp(self, exprnode):
249    self.generic_visit(exprnode)
250    if self.carryin == '' and self.carryout == '': carry_args = []
251    else: carry_args = [self.carryvar, ast.Num(self.current_carry)]
252    if isinstance(exprnode.op, ast.Sub):
253      rtn = "BitBlock_sub%s%s" % (self.carryin, self.carryout)
254      c = mkCall(rtn, [exprnode.left, exprnode.right] + carry_args)
255      self.current_carry += 1
256      return c
257    elif isinstance(exprnode.op, ast.Add):
258      rtn = "BitBlock_add%s%s" % (self.carryin, self.carryout)
259      c = mkCall(rtn, [exprnode.left, exprnode.right] + carry_args)
260      self.current_carry += 1
261      return c
262    else: return exprnode
263  def visit_If(self, ifNode):
264    carry_base = self.current_carry
265    carries = CarryCounter().count(ifNode)
266    self.generic_visit(ifNode)
267    if carries == 0 or self.carryin == "": return ifNode
268    carry_arglist = [self.carryvar, ast.Num(carry_base), ast.Num(carries)]
269    new_test = ast.BoolOp(ast.Or(), [ifNode.test, mkCall('CarryTest', carry_arglist)])
270    new_else_part = ifNode.orelse + [mkCallStmt('CarryDequeueEnqueue', carry_arglist)]
271    return ast.If(new_test, ifNode.body, new_else_part)
272  def visit_While(self, whileNode):
273    if self.carryout == '':
274      whileNode.test.args[0] = mkCall("simd_and", [whileNode.test.args[0], ast.Name('EOF_mask', ast.Load())])
275    carry_base = self.current_carry
276    carries = CarryCounter().count(whileNode)
277    if carries == 0: return whileNode
278    carry_arglist = [self.carryvar, ast.Num(carry_base), ast.Num(carries)]
279    local_carryvar = 'sub'+self.carryvar.id
280    inner_while = CarryIntro(local_carryvar, '', self.carryout).generic_xfrm(copy.deepcopy(whileNode))
281    self.generic_visit(whileNode)
282    if self.carryout == '_co':
283      local_decl = mkCallStmt('CarryDeclare', [ast.Name(local_carryvar, ast.Load()), ast.Num(carries)])
284      local_init = mkCallStmt('CarryInit', [ast.Name(local_carryvar, ast.Load()), ast.Num(carries)])
285      inner_while.body.insert(0, local_decl)
286      inner_while.body.insert(1, local_init)
287      final_combine = mkCallStmt('CarryCombine', [self.carryvar, ast.Name(local_carryvar, ast.Load()), ast.Num(carry_base), ast.Num(carries)])
288      inner_while.body.append(final_combine)
289    if self.carryin == '': new_test = whileNode.test
290    else: new_test = ast.BoolOp(ast.Or(), [whileNode.test, mkCall('CarryTest', carry_arglist)])
291    else_part = [mkCallStmt('CarryDequeueEnqueue', carry_arglist)]
292    return ast.If(new_test, whileNode.body + [inner_while], else_part)
293
294class StreamStructGen(ast.NodeVisitor):
295  """
296  Given a BitStreamSet subclass, generate the equivalent C struct.
297  >>> obj = ast.parse(r'''
298  ... class S1(BitStreamSet):
299  ...   a1 = 0
300  ...   a2 = 0
301  ...   a3 = 0
302  ...
303  ... class S2(BitStreamSet):
304  ...   x1 = 0
305  ...   x2 = 0
306  ... ''')
307  >>> print StreamStructGen().gen(obj)
308  struct S1 {
309    BitBlock a1;
310    BitBlock a2;
311    BitBlock a3;
312  }
313 
314  struct S2 {
315    BitBlock x1;
316    BitBlock x2;
317  }
318  """
319  def __init__(self, asType=False):
320    self.asType = asType
321  def gen(self, tree):
322    self.Ccode=""
323    self.generic_visit(tree)
324    return self.Ccode
325  def gen_struct_types(self, tree):
326    self.asType = True
327    self.Ccode=""
328    self.generic_visit(tree)
329    return self.Ccode
330  def gen_struct_vars(self, tree):
331    self.asType = False
332    self.Ccode=""
333    self.generic_visit(tree)
334    return self.Ccode
335  def visit_ClassDef(self, node):
336    class_name = node.name[0].upper() + node.name[1:]
337    instance_name = node.name[0].lower() + node.name[1:]
338    self.Ccode += "  struct " + class_name
339    if self.asType:
340            self.Ccode += " {\n"
341            for stmt in node.body:
342              if isinstance(stmt, ast.Assign):
343                for v in stmt.targets:
344                  if isinstance(v, ast.Name):
345                    self.Ccode += "  BitBlock " + v.id + ";\n"
346            self.Ccode += "}" 
347    else: self.Ccode += " " + instance_name
348    self.Ccode += ";\n\n"
349 
350class StreamFunctionDecl(ast.NodeVisitor):
351  def __init__(self):
352    pass
353  def gen(self, tree):
354    self.Ccode=""
355    self.generic_visit(tree)
356    return self.Ccode
357  def visit_FunctionDef(self, node):
358    self.Ccode += "static inline void " + node.name + "("
359    pending = ""
360    for arg in node.args.args:
361      if isinstance(arg, ast.Name):
362        self.Ccode += pending + arg.id.upper()[0] + arg.id[1:] + " & " + arg.id
363        pending = ", "
364    self.Ccode += ");\n"
365
366#
367# Adding Debugging Statements
368#
369class Add_SIMD_Register_Dump(ast.NodeTransformer):
370  def xfrm(self, t):
371    return self.generic_visit(t)
372  def visit_Assign(self, t):
373    self.generic_visit(t)
374    v = t.targets[0]
375    dump_stmt = mkCallStmt('print_simd_register', [ast.Str(Cgen.py2C().gen(v)), v])
376    return [t, dump_stmt]
377
378class StreamFunctionCarryCounter(ast.NodeVisitor):
379  def __init__(self):
380        self.carry_count = {}
381       
382  def count(self, node):
383        self.generic_visit(node)
384        return self.carry_count
385                                   
386  def visit_FunctionDef(self, node):   
387        type_name = node.name[0].upper() + node.name[1:]                       
388        self.carry_count[type_name] = CarryCounter().count(node)
389     
390class StreamFunctionCallXlator(ast.NodeTransformer):
391  def __init__(self, xlate_type="normal"):
392        self.stream_function_type_names = []
393        self.xlate_type = xlate_type
394
395  def xfrm(self, node, stream_function_type_names):
396        self.stream_function_type_names = stream_function_type_names
397        self.generic_visit(node)
398       
399  def visit_Call(self, node):   
400        self.generic_visit(node)
401
402        if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id in self.stream_function_type_names:
403             struct_name = node.func.id[0].lower() + node.func.id[1:]
404             if self.xlate_type == "final":
405                   node.func.id = struct_name + ".do_final_block"
406                   node.args = node.args + [ast.Name("EOF_mask", ast.Load())]
407             else:
408                   node.func.id = struct_name + ".do_block"
409        return node     
410               
411class StreamFunctionVisitor(ast.NodeVisitor):
412        def __init__(self,node):
413                self.stream_function_node = {}
414                self.generic_visit(node)
415                                                             
416        def visit_FunctionDef(self, node):                     
417                key = node.name[0].upper() + node.name[1:]
418                self.stream_function_node[key] = node
419               
420class StreamFunction():
421        def __init__(self):
422                self.carry_count = 0 
423                self.type_name = ""
424                self.instance_name = "" 
425                self.parameters = ""
426                self.declarations = "" 
427                self.initializations = "" 
428#
429# TODO Consolidate *all* C code generation into the Emitter class.   Medium priority.
430# TODO Implement 'pretty print' indentation.   Low priority.
431# TODO Migrate Emiter() class to Emitter module.  Medium priority.
432
433def lower1(name):
434    return name[0].lower() + name[1:]
435def upper1(name):
436    return name[0].upper() + name[1:]
437
438class Emitter():
439
440        def definition(self, stream_function, icount=0):
441               
442                constructor = ""
443                carry_declaration = ""
444               
445                if stream_function.carry_count > 0:
446                        constructor = self.constructor(stream_function.type_name, stream_function.carry_count)
447                        carry_declaration = self.carry_declare(stream_function.carry_count)
448
449                do_block_function = self.do_block(self.do_block_parameters(stream_function.parameters), 
450                                                stream_function.declarations, 
451                                                stream_function.initializations, 
452                                                stream_function.statements)             
453
454                do_final_block_function = self.do_final_block(self.do_final_block_parameters(stream_function.parameters), 
455                                                stream_function.declarations, 
456                                                stream_function.initializations, 
457                                                stream_function.final_block_statements)                 
458
459                do_segment_function = self.do_segment(self.do_segment_parameters(stream_function.parameters), 
460                                                self.do_segment_args(stream_function.parameters))       
461
462                return self.indent(icount) + "struct " + stream_function.type_name + " {" \
463                + "\n" + self.indent(icount) + constructor \
464                + "\n" + self.indent(icount) + do_block_function \
465                + "\n" + self.indent(icount) + do_final_block_function \
466                + "\n" + self.indent(icount) + do_segment_function \
467                + "\n" + self.indent(icount) + carry_declaration \
468                + "\n" + self.indent(icount) + "};\n\n"
469
470        def constructor(self, type_name, carry_count, icount=0):
471                return self.indent(icount) + "%s() { """ % (type_name) + self.carry_init(carry_count) + " }" 
472                       
473        def do_block(self, parameters, declarations, initializations, statements, icount=0):
474                return self.indent(icount) + "void do_block(" + parameters + ") {" \
475            + "\n" + self.indent(icount) + declarations \
476                + "\n" + self.indent(icount) + initializations \
477                + "\n" + self.indent(icount) + statements \
478                + "\n" + self.indent(icount + 2) + "}" 
479
480        def do_final_block(self, parameters, declarations, initializations, statements, icount=0):
481                return self.indent(icount) + "void do_final_block(" + parameters + ") {" \
482            + "\n" + self.indent(icount) + declarations \
483                + "\n" + self.indent(icount) + initializations \
484                + "\n" + self.indent(icount) + statements \
485                + "\n" + self.indent(icount + 2) + "}" 
486
487        def do_segment(self, parameters, do_block_call_args, icount=0):
488                return self.indent(icount) + "void do_segment(" + parameters + ") {" \
489            + "\n" + self.indent(icount) + "  for (int i = 0; i < SEGMENT_BLOCKS; i++)" \
490                + "\n" + self.indent(icount) + "    do_block(" + do_block_call_args + ");" \
491                + "\n" + self.indent(icount + 2) + "}" 
492
493        def declaration(self, type_name, instance_name, icount=0):     
494                return self.indent(icount) + type_name + " " + instance_name + ";\n"
495               
496        def carry_init(self, carry_count, icount=0):   
497                return self.indent(icount) + "CarryInit(carryQ, %i);" % (carry_count)
498       
499        def carry_declare(self, carry_count, icount=0):
500                return self.indent(icount) + "CarryDeclare(carryQ, %i);" % (carry_count)
501
502        def carry_test(self, carry_variable, carry_count, icount=0):
503                return self.indent(icount) + "CarryTest(%s, 0, %i)" % (carry_variable, carry_count)             
504               
505        def indent(self, icount):
506                s = ""
507                for i in range(0,icount): s += " "
508                return s       
509               
510        def do_block_parameters(self, parameters):
511                return ", ".join([upper1(p) + " & " + lower1(p) for p in parameters])
512               
513        def do_final_block_parameters(self, parameters):
514                return ", ".join([upper1(p) + " & " + lower1(p) for p in parameters]+ ["BitBlock EOF_mask"])
515               
516        def do_segment_parameters(self, parameters):
517                return ", ".join([upper1(p) + " " + lower1(p) + "[]" for p in parameters])
518
519        def do_segment_args(self, parameters):
520                return ", ".join([lower1(p) + "[i]" for p in parameters])
521
522def main(infilename, outfile = sys.stdout):
523  t = ast.parse(file(infilename).read())
524  outfile.write(StreamStructGen(True).gen(t))
525  outfile.write(FunctionXlator().xlat(t))
526
527#
528#  Routines for compatibility with the old compiler/template.
529#  Quick and dirty hacks for now - Dec. 2010.
530#
531
532class MainLoopTransformer:
533  def __init__(self, main_module, add_dump_stmts=False, main_node_id='Main'):
534       
535    self.main_module = main_module
536    self.main_node_id = main_node_id
537    self.add_dump_stmts = add_dump_stmts
538   
539        # Gather and partition function definition nodes.
540    stream_function_visitor = StreamFunctionVisitor(self.main_module)
541    self.stream_function_node = stream_function_visitor.stream_function_node
542    self.main_node = self.stream_function_node[main_node_id]
543    self.main_carry_count = CarryCounter().count(self.main_node)
544    del self.stream_function_node[self.main_node_id]
545   
546    self.stream_functions = {}
547    for key, node in self.stream_function_node.iteritems():
548                stream_function = StreamFunction()
549                stream_function.carry_count = CarryCounter().count(node)
550                stream_function.type_name = node.name[0].upper() + node.name[1:]
551                stream_function.instance_name = node.name[0].lower() + node.name[1:]
552                stream_function.parameters = FunctionVars(node).params
553                stream_function.declarations = BitBlock_decls_of_fn(node)
554                stream_function.initializations = StreamInitializations().xfrm(node) 
555               
556                AugAssignRemoval().xfrm(node)
557                Bitwise_to_SIMD().xfrm(node)
558                final_block_node = copy.deepcopy(node)
559                CarryIntro().xfrm_fndef(node)
560                CarryIntro("carryQ", "_ci", "").xfrm_fndef(final_block_node)
561
562                if self.add_dump_stmts: 
563                        Add_SIMD_Register_Dump().xfrm(node)
564               
565                if stream_function.carry_count > 0:
566                        node.body += [mkCallStmt('CarryQ_Adjust', [ast.Name('carryQ', ast.Load()), ast.Num(stream_function.carry_count)])]
567               
568                stream_function.statements = Cgen.py2C(4).gen(node.body)
569                stream_function.final_block_statements = Cgen.py2C(4).gen(final_block_node.body)
570                self.stream_functions[stream_function.type_name] = stream_function
571       
572    self.emitter = Emitter()
573   
574  def any_carry_expr(self):
575       
576        carry_test = []
577       
578        if self.main_carry_count > 0:
579                        carry_test.append(self.emitter.carry_test('carryQ', self.main_carry_count))
580                        carry_test.append(" || ")
581
582        for key in self.stream_functions.keys():               
583                if self.stream_functions[key].carry_count > 0:
584                        carry_test.append(self.emitter.carry_test(self.stream_functions[key].instance_name + ".carryQ", self.stream_functions[key].carry_count))
585                        carry_test.append(" || ")
586
587        if len(carry_test) > 0:
588                carry_test.pop()
589        return "".join(carry_test)
590   
591        return "1"
592
593  def gen_globals(self):
594    self.Cglobals = StreamStructGen().gen_struct_types(self.main_module)
595    for key in self.stream_functions.keys():
596                self.Cglobals += Emitter().definition(self.stream_functions[key],2)       
597                       
598  def gen_declarations(self): 
599    self.Cdecls = StreamStructGen().gen_struct_vars(self.main_module)
600    self.Cdecls += BitBlock_decls_of_fn(self.main_node)
601    if self.main_carry_count > 0: 
602        self.Cdecls += self.emitter.carry_declare(self.main_carry_count)
603               
604  def gen_initializations(self):
605    self.Cinits = ""
606    if self.main_carry_count > 0: 
607        self.Cinits += self.emitter.carry_init(self.main_carry_count)
608    self.Cinits += StreamInitializations().xfrm(self.main_module)
609   
610    for key in self.stream_functions.keys():
611                self.Cinits += self.emitter.declaration(self.stream_functions[key].type_name, self.stream_functions[key].instance_name, 2)
612                       
613  def xfrm_block_stmts(self):
614    AugAssignRemoval().xfrm(self.main_node)
615    Bitwise_to_SIMD().xfrm(self.main_node)
616    final_block_main = copy.deepcopy(self.main_node)
617    CarryIntro().xfrm_fndef(self.main_node)
618    CarryIntro('carryQ', '_ci', '').xfrm_fndef(final_block_main)
619    if self.add_dump_stmts: 
620        Add_SIMD_Register_Dump().xfrm(self.main_node)
621        Add_SIMD_Register_Dump().xfrm(final_block_main)
622               
623    StreamFunctionCallXlator().xfrm(self.main_node, self.stream_function_node.keys())
624    StreamFunctionCallXlator('final').xfrm(final_block_main, self.stream_function_node.keys())
625   
626    if self.main_carry_count > 0:
627                self.main_node.body += [mkCallStmt('CarryQ_Adjust', [ast.Name('carryQ', ast.Load()), ast.Num(self.main_carry_count)])]
628   
629   
630       
631    self.Cstmts = Cgen.py2C().gen(self.main_node.body)
632    self.Cfinal_stmts = Cgen.py2C().gen(final_block_main.body)
633   
634if __name__ == "__main__":
635                import doctest
636                doctest.testmod()
Note: See TracBrowser for help on using the repository browser.