source: proto/Compiler/pablo.py @ 2709

Last change on this file since 2709 was 2708, checked in by cameron, 7 years ago

New experimental version eliminating ubitblock and convert; much faster

File size: 45.6 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
10from carryInfo import *
11import CCGO
12import CCGO_HMCPS
13
14name_substitution_map = {}
15do_block_inline_decorator = 'IDISA_INLINE '
16do_final_block_inline_decorator = ''
17error_routine = 'raise_assert'
18experimentalMode=False
19
20
21def dump_Call(fncall):
22        if isinstance(fncall.func, ast.Name): print "fn_name = %s\n" % fncall.func.id
23        elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
24                print "fn_name = %s.%s\n" % (fncall.func.value.id, fncall.func.attr)
25        print "len(fncall.args) = %s\n" % len(fncall.args)
26
27def is_simd_not(e):
28  return isinstance(e, ast.Call) and isinstance(e.func, ast.Name) and e.func.id == 'simd_not'
29
30def mkQname(obj, field):
31  return ast.Attribute(ast.Name(obj, ast.Load()), field, ast.Load())
32
33def mkCall(fn_name, args):
34  if isinstance(fn_name, str): 
35        if name_substitution_map.has_key(fn_name): fn_name = name_substitution_map[fn_name]
36        fn_name = ast.Name(fn_name, ast.Load())
37  return ast.Call(fn_name, args, [], None, None)
38
39def mkCallStmt(fn_name, args):
40  if isinstance(fn_name, str): fn_name = ast.Name(fn_name, ast.Load())
41  return ast.Expr(ast.Call(fn_name, args, [], None, None))
42 
43 
44
45#
46# Reducing AugAssign, e.g.  x |= y becomes x = x | y
47#
48class AugAssignRemoval(ast.NodeTransformer):
49  def xfrm(self, t):
50    return self.generic_visit(t)
51  def visit_AugAssign(self, e):
52    self.generic_visit(e)
53    return ast.Assign([e.target], ast.BinOp(e.target, e.op, e.value))
54#
55# pablo.Advance(pablo.Advance(x, n)) => pablo.Advance(x, n+1)
56#
57class AdvanceCombiner(ast.NodeTransformer):
58  def xfrm(self, t):
59    return self.generic_visit(t)
60  def visit_if(self, ifNode):
61    return IfNode
62  def visit_While(self, whileNode):
63    return whileNode
64  def visit_Call(self, callnode):
65    self.generic_visit(callnode)
66    if len(callnode.args) == 0: return callnode
67    if not isinstance(callnode.args[0], ast.Call): return callnode
68    if is_BuiltIn_Call(callnode,'Advance', 1):
69        if is_BuiltIn_Call(callnode.args[0],'Advance', 1):
70          callnode.args = [callnode.args[0].args[0], ast.Num(2)]
71        elif is_BuiltIn_Call(callnode.args[0], 'Advance', 2):
72          if isinstance(callnode.args[0].args[1], ast.Num):
73            callnode.args = [callnode.args[0].args[0], ast.Num(callnode.args[0].args[1].n + 1)]
74          else:
75            callnode.args = [callnode.args[0].args[0], ast.BinOp(callnode.args[0].args[1], ast.Add(), ast.Num(1))]
76    return callnode
77
78
79#
80#  Translating pablo.match(marker, str)
81#  Incremental character match with lookahead
82#
83CharNameMap = {'[' : 'LBrak', ']' : 'RBrak', '{' : 'LBrace', '}' : 'LBrace', '(' : 'LParen', ')' : 'RParen', \
84              '!' : 'Exclam', '"' : 'DQuote', '#' : 'Hash', '$' : 'Dollar', '%' : 'PerCent', '&': 'RefStart', \
85              "'" : 'SQuote', '*': 'Star', '+' : 'Plus', ',' : 'Comma', '-' : 'Hyphen', '.' : 'Dot', '/' : 'Slash', \
86              ':' : 'Colon', ';' : 'Semicolon', '=' : 'Equals', '?' : 'QMark', '@' : 'AtSign', '\\' : 'BackSlash', \
87              '^' : 'Caret', '_' : 'Underscore', '|' : 'VBar', '~' : 'Tilde', ' ' : 'SP', '\t' : 'HT', '\m' : 'CR', '\n' : 'LF'}
88
89def GetCharName(char):
90        if char >= 'a' and char <= 'z' or char >= 'A' and char <= 'Z': return 'letter_' + char
91        elif char >= '0' and char <= '9': return 'digit_' + char
92        else: return CharNameMap[char]
93
94def MkCharStream(char):
95        return mkQname('lex', GetCharName(char))
96
97def MkLookAheadExpr(v, i):
98        return mkCall(mkQname('pablo', 'LookAhead'), [v, ast.Num(i)])
99
100def CompileMatch(match_var, string_to_match):
101        expr = mkCall('simd_and', [match_var, MkCharStream(string_to_match[0])])
102        for i in range(1, len(string_to_match)):
103                expr = mkCall('simd_and', [expr, MkLookAheadExpr(MkCharStream(string_to_match[i]), i)])
104        return expr
105
106class StringMatchCompiler(ast.NodeTransformer):
107  def xfrm(self, t):
108    return self.generic_visit(t)
109  def visit_Call(self, callnode):
110    if is_BuiltIn_Call(callnode,'match', 2):
111        ast.dump(callnode)
112        assert isinstance(callnode.args[0], ast.Str)
113        string_to_match = callnode.args[0].s
114        match_var = callnode.args[1]
115        expr = mkCall('simd_and', [match_var, MkCharStream(string_to_match[0])])
116        for i in range(1, len(string_to_match)):
117                expr = mkCall('simd_and', [expr, MkLookAheadExpr(MkCharStream(string_to_match[i]), i)])
118        return expr
119    else: return callnode
120
121
122
123#
124#  Converting expressions involving built-ins to compiled form. 
125#  Apply before carry variable insertion.
126#
127class TempifyBuiltins(ast.NodeTransformer):
128    def __init__(self, tempVarpfx = "tempvar"):
129      self.tempVarCount = 0
130      self.newTempList = []
131      self.tempVarPrefix = tempVarpfx
132    def genVar(self):
133      newTemp = self.tempVarPrefix + repr(self.tempVarCount)
134      self.newTempList.append(newTemp)
135      self.tempVarCount += 1
136      return newTemp
137    def tempVars(self):
138      return self.newTempList
139    def xfrm(self, t):
140      self.setUpStmts = []
141      self.assigNode = None
142      return self.generic_visit(t)
143    def is_Assign_value(self, node):
144      return self.assigNode != None and self.assigNode.value == node
145    def visit_If(self, ifNode):
146      self.setUpStmts = []
147      self.generic_visit(ifNode.test)
148      ifSetUpStmts = self.setUpStmts
149      self.generic_visit(ifNode)
150      if ifSetUpStmts == []: return ifNode
151      else: return ifSetUpStmts + [ifNode]
152    def visit_While(self, whileNode):
153      self.setUpStmts = []
154      self.generic_visit(whileNode.test)
155      whileSetUpStmts = self.setUpStmts
156      self.generic_visit(whileNode)
157      whileNode.body = whileNode.body + whileSetUpStmts
158      return whileSetUpStmts + [whileNode]
159    def visit_Assign(self, node):
160      self.assigNode = node
161      self.setUpStmts = []
162      self.generic_visit(node)
163      return self.setUpStmts + [node]
164    def visit_AugAssign(self, node):
165      self.setUpStmts = []
166      self.generic_visit(node)
167      return self.setUpStmts + [node]
168    def visit_Call(self, callnode):     
169        self.generic_visit(callnode)
170        if CheckForBuiltin(callnode) and not self.is_Assign_value(callnode):
171        #if not self.is_Assign_value(callnode):
172            tempVar = ast.Name(self.genVar(), ast.Load())
173            self.setUpStmts.append(ast.Assign([tempVar], callnode))
174            return tempVar
175        else: return callnode
176
177
178
179
180
181#
182# Introducing BitBlock logical operations
183#
184class Bitwise_to_SIMD(ast.NodeTransformer):
185  """
186  Make the following substitutions:
187     x & y => simd_and(x, y)
188     x & ~y => simd_andc(x, y)
189     x | y => simd_or(x, y)
190     x ^ y => simd_xor(x, y)
191     ~x    => simd_not(x)
192     0     => simd_const_1(0)
193     -1    => simd_const_1(1)
194     if x: => if bitblock::any(x):
195  while x: => while bitblock::any(x):
196  >>> ast_show(Bitwise_to_SIMD().xfrm(ast.parse("pfx = bit0 & bit1; sfx = bit0 &~ bit1")))
197 
198  pfx = simd_and(bit0, bit1)
199  sfx = simd_and(bit0, simd_not(bit1))
200  >>>
201  """
202  def xfrm(self, t):
203    return self.generic_visit(t)
204  def visit_UnaryOp(self, t):
205    self.generic_visit(t)
206    if isinstance(t.op, ast.Invert):
207      return mkCall('simd_not', [t.operand])
208    else: return t
209  def visit_BinOp(self, t):
210    self.generic_visit(t)
211    if isinstance(t.op, ast.BitOr):
212      return mkCall('simd_or', [t.left, t.right])
213    elif isinstance(t.op, ast.BitAnd):
214      if is_simd_not(t.right): return mkCall('simd_andc', [t.left, t.right.args[0]])
215      elif is_simd_not(t.left): return mkCall('simd_andc', [t.right, t.left.args[0]])
216      else: return mkCall('simd_and', [t.left, t.right])
217    elif isinstance(t.op, ast.BitXor):
218      return mkCall('simd_xor', [t.left, t.right])
219    else: return t
220  def visit_Num(self, numnode):
221    n = numnode.n
222    if n == 0: return mkCall('simd<1>::constant<0>', [])
223    elif n == -1: return mkCall('simd<1>::constant<1>', [])
224    else: return numnode
225  def visit_If(self, ifNode):
226    self.generic_visit(ifNode)
227    ifNode.test = mkCall('bitblock::any', [ifNode.test])
228    return ifNode
229  def visit_While(self, whileNode):
230    self.generic_visit(whileNode)
231    whileNode.test = mkCall('bitblock::any', [whileNode.test])
232    return whileNode
233  def visit_Subscript(self, numnode):
234    return numnode  # no recursive modifications of index expressions
235
236#
237#  Generating BitBlock declarations for Local Variables
238#
239class FunctionVars(ast.NodeVisitor):
240  def __init__(self,node):
241        self.params = []
242        self.stores = []
243        self.generic_visit(node)
244  def visit_Name(self, nm):
245    if isinstance(nm.ctx, ast.Param):
246      self.params.append(nm.id)
247    if isinstance(nm.ctx, ast.Store):
248      if nm.id not in self.stores: self.stores.append(nm.id)
249  def getLocals(self): 
250    return [v for v in self.stores if not v in self.params]
251
252MAX_LINE_LENGTH = 80
253
254def BitBlock_decls_from_vars(varlist):
255  global MAX_LINE_LENGTH
256  decls =  ""
257  if not len(varlist) == 0:
258          decls = "             BitBlock"
259          pending = ""
260          linelgth = 10
261          for v in varlist:
262            if linelgth + len(v) + 2 <= MAX_LINE_LENGTH:
263              decls += pending + " " + v
264              linelgth += len(pending + v) + 1
265            else:
266              decls += ";\n             BitBlock " + v
267              linelgth = 11 + len(v)
268            pending = ","
269          decls += ";"
270  return decls
271
272def BitBlock_decls_of_fn(fndef):
273  return BitBlock_decls_from_vars(FunctionVars(fndef).getLocals())
274
275def BitBlock_header_of_fn(fndef):
276  Ccode = "static inline void " + fndef.name + "("
277  pending = ""
278  for arg in fndef.args.args:
279    if isinstance(arg, ast.Name):
280      Ccode += pending + arg.id.upper()[0] + arg.id[1:] + " & " + arg.id
281      pending = ", "
282  if CarryCounter().count(fndef) > 0:
283    Ccode += pending + " CarryQtype & carryQ"
284  Ccode += ")"
285  return Ccode
286
287
288
289#
290#  Stream Initialization Statement Extraction
291#
292#  streamvar = 1 ==> streamvar = sisd_from_int(1) initially.
293class StreamInitializations(ast.NodeTransformer):
294  def xfrm(self, node):
295    self.stream_stmts = []
296    self.loop_post_inits = []
297    self.generic_visit(node)
298    return Cgen.py2C().gen(self.stream_stmts)
299  def visit_Assign(self, node):
300    if isinstance(node.value, ast.Num):
301      if node.value.n == 0: return node
302      elif node.value.n == -1: return node
303      else: 
304        stream_init = copy.deepcopy(node)
305        stream_init.value = mkCall('sisd_from_int', [node.value])
306        loop_init = copy.deepcopy(node)
307        loop_init.value.n = 0
308        self.stream_stmts.append(stream_init)
309        self.loop_post_inits.append(loop_init)
310        return None
311    else: return node
312  def visit_FunctionDef(self, node):
313    self.generic_visit(node)
314    node.body = node.body + self.loop_post_inits
315    return node
316
317
318
319#
320# Carry Introduction Transformation
321#
322
323def Strategic_CCGO_Factory(carryInfoSet):
324  if experimentalMode:
325    ops = carryInfoSet.operation_count
326    if ops == 0: ccgo = CCGO.CCGO()
327    elif ops <= 2: ccgo = CCGO_HMCPS.HMCPS_CCGO2(64, carryInfoSet, 'carryG', '__c')
328    elif ops <= 4: ccgo = CCGO_HMCPS.HMCPS_CCGO2(32, carryInfoSet, 'carryG', '__c')
329    #elif ops <= 8: ccgo = CCGO_HMCPS.HMCPS_CCGO(16, carryInfoSet, 'carryG', '__c')
330    #else: ccgo = CCGO_HMCPS.HMCPS_CCGO(8, carryInfoSet, 'carryG', '__c')
331    else: ccgo = CCGO_HMCPS.HMCPS_CCGO2(16, carryInfoSet, 'carryG', '__c')
332  else:
333    ccgo = CCGO.testCCGO(carryInfoSet, 'carryQ')
334  return ccgo
335
336
337class CarryIntro(ast.NodeTransformer):
338  def __init__(self, ccgo, carryvar="carryQ", carryin = "_ci", carryout = "_co"):
339    self.carryvar = ast.Name(carryvar, ast.Load())
340    self.carryin = carryin
341    self.carryout = carryout
342    self.ccgo = ccgo
343  def xfrm_fndef(self, fndef):
344    self.block_no = 0
345    self.operation_count = 0
346    self.current_carry = 0
347    self.current_adv_n = 0
348    carry_count = CarryCounter().count(fndef)
349    if carry_count == 0: return fndef
350    self.generic_visit(fndef)
351  def xfrm_fndef_final(self, fndef):
352    self.block_no = 0
353    self.operation_count = 0
354    self.carryout = ""
355    self.current_carry = 0
356    self.current_adv_n = 0
357    carry_count = CarryCounter().count(fndef)
358    if carry_count == 0: return fndef
359    self.generic_visit(fndef)
360#   
361#    fndef.body.insert(0, mkCallStmt('CarryDeclare', [self.carryvar, ast.Num(carry_count)]))
362    return fndef
363  def generic_xfrm(self, node):
364    self.block_no = 0
365    self.operation_count = 0
366    self.current_carry = 0
367    self.current_adv_n = 0
368    self.last_stmt = None
369    self.last_stmt_carries = 0
370    carry_count = CarryCounter().count(node)
371    adv_n_count = adv_nCounter().count(node)
372    if carry_count == 0 and adv_n_count == 0: return node
373    self.generic_visit(node)
374    return node
375   
376  def local_while_xfrm(self, local_carryvar, whileNode):
377    saved_state = (self.block_no, self.operation_count, self.carryvar, self.carryin, self.carryout, self.current_carry, self.current_adv_n)
378    (self.carryvar, self.carryin, self.current_carry, self.current_adv_n) = (local_carryvar, '', 0, 0)
379    #(self.carryvar, self.carryin) = (local_carryvar, '')
380    self.ccgo.EnterLocalWhileBlock(self.operation_count);
381    inner_while = self.generic_visit(whileNode)
382    self.ccgo.ExitLocalWhileBlock();
383    (self.block_no, self.operation_count, self.carryvar, self.carryin, self.carryout, self.current_carry, self.current_adv_n) = saved_state
384    return inner_while
385   
386  def visit_Call(self, callnode):
387    self.generic_visit(callnode)
388    #CARRYSET
389    #carry_args = [ast.Num(self.current_carry)]
390    #adv_n_args = [ast.Subscript(ast.Name(self.carryvar.id + '.pending64', ast.Load()), ast.Num(self.current_adv_n), ast.Load())]
391    #adv_n_pending = ast.Subscript(ast.Name(self.carryvar.id + '.pending64', ast.Load()), ast.Num(self.current_adv_n), ast.Load())
392    if self.carryin == "_ci":
393        carry_args = [mkCall(self.carryvar.id + "." + 'get_carry_in', [ast.Num(self.current_carry)]), ast.Num(self.current_carry)]
394        adv_n_args = [mkCall(self.carryvar.id + "." + 'get_pending64', [ast.Num(self.current_adv_n)]), ast.Num(self.current_adv_n)]
395    else: 
396        carry_args = [mkCall('simd<1>::constant<0>', []), ast.Num(self.current_carry)]
397        adv_n_args = [mkCall('simd<1>::constant<0>', []), ast.Num(self.current_adv_n)]
398
399    if is_BuiltIn_Call(callnode, 'Advance', 2):         
400      #CARRYSET
401      rtn = self.carryvar.id + "." + "BitBlock_advance_n_<%i>" % callnode.args[1].n
402      c = mkCall(rtn, [callnode.args[0]] + adv_n_args)
403      self.current_adv_n += 1
404      return c
405    if is_BuiltIn_Call(callnode, 'Advance', 1):         
406      #CARRYSET
407      rtn = self.carryvar.id + "." + "BitBlock_advance_ci_co"
408      c = mkCall(rtn, callnode.args + carry_args)
409      self.current_carry += 1
410      return c
411    elif is_BuiltIn_Call(callnode, 'Advance32', 1):     
412      #CARRYSET
413      rtn = self.carryvar.id + "." + "BitBlock_advance_n_<32>"
414      c = mkCall(rtn, callnode.args + adv_n_args)
415      self.current_adv_n += 1
416      return c
417    elif is_BuiltIn_Call(callnode, 'ScanThru', 2):
418      #CARRYSET
419      rtn = self.carryvar.id + "." + "BitBlock_scanthru_ci_co"
420      c = mkCall(rtn, callnode.args + carry_args)
421      self.current_carry += 1
422      return c
423    elif is_BuiltIn_Call(callnode, 'AdvanceThenScanThru', 2):
424      #CARRYSET
425      rtn = self.carryvar.id + "." + "BitBlock_advance_then_scanthru"
426      c = mkCall(rtn, callnode.args + carry_args)
427      self.current_carry += 1
428      return c
429    elif is_BuiltIn_Call(callnode, 'AdvanceThenScanTo', 2):
430      #CARRYSET
431      rtn = self.carryvar.id + "." + "BitBlock_advance_then_scanthru" 
432      if self.carryout == "":  scanclass = mkCall('simd_andc', [ast.Name('EOF_mask', ast.Load()), callnode.args[1]])
433      else: scanclass = mkCall('simd_not', [callnode.args[1]])
434      c = mkCall(rtn, [callnode.args[0], scanclass] + carry_args)
435      self.current_carry += 1
436      return c
437    elif is_BuiltIn_Call(callnode, 'SpanUpTo', 2):
438      #CARRYSET
439      rtn = self.carryvar.id + "." + "BitBlock_span_upto"
440      c = mkCall(rtn, callnode.args + carry_args)
441      self.current_carry += 1
442      return c
443    elif is_BuiltIn_Call(callnode, 'InclusiveSpan', 2):
444      #CARRYSET
445#      rtn = self.carryvar.id + "." + "BitBlock_span_upto"
446#      c = mkCall('simd_or', [mkCall(rtn, callnode.args + carry_args), callnode.args[1]])
447      rtn = self.carryvar.id + "." + "BitBlock_inclusive_span"
448      c = mkCall(rtn, callnode.args + carry_args)
449      self.current_carry += 1
450      return c
451    elif is_BuiltIn_Call(callnode, 'ExclusiveSpan', 2):
452      #CARRYSET
453#      rtn = self.carryvar.id + "." + "BitBlock_span_upto"
454#      c = mkCall('simd_andc', [mkCall(rtn, callnode.args + carry_args), callnode.args[0]])
455      rtn = self.carryvar.id + "." + "BitBlock_exclusive_span"
456      c = mkCall(rtn, callnode.args + carry_args)
457      self.current_carry += 1
458      return c
459    elif is_BuiltIn_Call(callnode, 'ScanTo', 2):
460      # Modified Oct. 9, 2011 to directly use BitBlock_scanthru, eliminating duplication
461      # in having a separate BitBlock_scanto routine.
462      #CARRYSET
463      rtn = self.carryvar.id + "." + "BitBlock_scanthru_ci_co" 
464      if self.carryout == "":  scanclass = mkCall('simd_andc', [ast.Name('EOF_mask', ast.Load()), callnode.args[1]])
465      else: scanclass = mkCall('simd_not', [callnode.args[1]])
466      c = mkCall(rtn, [callnode.args[0], scanclass] + carry_args)
467      self.current_carry += 1
468      return c
469    elif is_BuiltIn_Call(callnode, 'ScanToFirst', 1):
470      #CARRYSET
471      rtn = self.carryvar.id + "." + "BitBlock_scantofirst"
472      #if self.carryout == "":  carry_args = [ast.Name('EOF_mask', ast.Load())] + carry_args
473      c = mkCall(rtn, callnode.args + carry_args)
474      self.current_carry += 1
475      return c
476    elif is_BuiltIn_Call(callnode, 'atEOF', 1):
477      if self.carryout != "": 
478        # Non final block: atEOF(x) = 0.
479        return mkCall('simd<1>::constant<0>', [])
480      else: return mkCall('simd_andc', [callnode.args[0], ast.Name('EOF_mask', ast.Load())])
481    elif is_BuiltIn_Call(callnode, 'inFile', 1):
482      if self.carryout != "": 
483        # Non final block: inFile(x) = x.
484        return callnode.args[0]
485      else: return mkCall('simd_and', [callnode.args[0], ast.Name('EOF_mask', ast.Load())])
486    elif is_BuiltIn_Call(callnode, 'StreamScan', 2):
487      rtn = "StreamScan"           
488      c = mkCall(rtn, [ast.Name('(ScanBlock *) &' + callnode.args[0].id, ast.Load()), 
489                                           ast.Name('sizeof(BitBlock)/sizeof(ScanBlock)', ast.Load()),
490                                           ast.Name(callnode.args[1].id, ast.Load())])
491      return c
492    else:
493      #dump_Call(callnode)
494      return callnode
495  def visit_BinOp(self, exprnode):
496    self.generic_visit(exprnode)
497    carry_args = [ast.Num(self.current_carry)]
498    if self.carryin == "_ci":
499        carry_args = [mkCall(self.carryvar.id + "." + 'get_carry_in', [ast.Num(self.current_carry)]), ast.Num(self.current_carry)]
500    else: 
501        carry_args = [mkCall('simd<1>::constant<0>', []), ast.Num(self.current_carry)]
502    if isinstance(exprnode.op, ast.Sub):
503      #CARRYSET
504      rtn = self.carryvar.id + "." + "BitBlock_sub_ci_co"
505      c = mkCall(rtn, [exprnode.left, exprnode.right] + carry_args)
506      self.current_carry += 1
507      return c
508    elif isinstance(exprnode.op, ast.Add):
509      #CARRYSET
510      rtn = self.carryvar.id + "." + "BitBlock_add_ci_co"
511      c = mkCall(rtn, [exprnode.left, exprnode.right] + carry_args)
512      self.current_carry += 1
513      return c
514    else: return exprnode
515  def visit_Assign(self, assigNode):
516    self.last_stmt_carries = CarryCounter().count(assigNode)
517    f = CheckForBuiltin(assigNode.value)
518    if f == None or not experimentalMode: 
519            self.generic_visit(assigNode)
520            self.last_stmt = assigNode
521            return assigNode
522    elif isCarryGenerating(f) or (isAdvance(f) and ((len(assigNode.value.args) == 1) or (assigNode.value.args[1].n==1))):
523    # We have an assignment v = pablo.SomeCarryGeneratingFunction()
524    #elif f == 'ScanThru':
525            if self.carryin == "_ci":
526                carry_in_expr = self.ccgo.GenerateCarryInAccess(self.operation_count)
527            else: 
528                carry_in_expr = mkCall('simd<1>::constant<0>', [])
529            callnode = assigNode.value
530            if isAdvance(f):
531               pablo_routine_call = mkCall('pablo_blk_' + f, [assigNode.value.args[0], carry_in_expr, assigNode.targets[0]])
532            elif f in ['ScanTo', 'AdvanceThenScanTo']:
533               if self.carryout == "":  scanclass = mkCall('simd_andc', [ast.Name('EOF_mask', ast.Load()), callnode.args[1]])
534               else: scanclass = mkCall('simd_not', [callnode.args[1]])
535               pablo_routine_call = mkCall('pablo_blk_' +f[:-2] + 'Thru', [callnode.args[0], scanclass, carry_in_expr, assigNode.targets[0]])
536            else:
537               pablo_routine_call = mkCall('pablo_blk_' + f, assigNode.value.args + [carry_in_expr, assigNode.targets[0]])
538            self.last_stmt = pablo_routine_call
539            compiled = self.ccgo.GenerateCarryOutStore(self.operation_count, pablo_routine_call)
540            self.operation_count += 1
541            self.current_carry += 1
542            return compiled
543    elif isAdvance(f):
544            if self.carryin == "_ci":
545                carry_in_expr = self.ccgo.GenerateAdvanceInAccess(self.operation_count)
546            else: 
547                carry_in_expr = mkCall('simd<1>::constant<0>', [])
548            callnode = assigNode.value
549            pablo_routine_call = mkCall('pablo_blk_Advance_n_<%i>' %  assigNode.value.args[1].n, [assigNode.value.args[0], carry_in_expr, assigNode.targets[0]])
550            self.last_stmt = pablo_routine_call
551            compiled = self.ccgo.GenerateAdvanceOutStore(self.operation_count, pablo_routine_call)
552            self.operation_count += 1
553            self.current_adv_n += 1
554            return compiled
555
556    else:
557            self.generic_visit(assigNode)
558            self.last_stmt = assigNode
559            self.operation_count += 1
560            return assigNode
561           
562           
563  def visit_If(self, ifNode):
564    self.block_no += 1
565    this_block = self.block_no
566    carry_base = self.current_carry
567    carries = CarryCounter().count(ifNode)
568    assert adv_nCounter().count(ifNode) == 0, "Advance(x,n) within if: illegal\n"
569    self.generic_visit(ifNode)
570    if carries == 0: # or self.carryin == "":
571      self.last_stmt = ifNode
572      return ifNode
573    #CARRYSET
574    carry_arglist = [ast.Num(carry_base), ast.Num(carries)]
575    #new_test = ast.BoolOp(ast.Or(), [ifNode.test, mkCall(ast.Attribute(self.carryvar, 'CarryTest', ast.Load()), carry_arglist)])
576    #new_else_part = ifNode.orelse + [mkCallStmt(ast.Attribute(self.carryvar, 'CarryDequeueEnqueue', ast.Load()), carry_arglist)]
577    new_test = self.ccgo.GenerateCarryIfTest(this_block, ifNode.test)
578    new_else_part = ifNode.orelse + self.ccgo.GenerateCarryElseFinalization(this_block)
579    newIf = ast.If(new_test, ifNode.body, new_else_part)
580    self.last_stmt = newIf
581    self.last_stmt_carries = carries
582    return newIf
583
584
585  def is_while_special_case(self, whileNode):
586    #
587    # Special case optimization for pattern:
588    #   m=pablo.scan...()
589    #   while m:
590    #      S
591    #      m=pablo.scan...()
592    #
593    # Determine the original test expression, now encloded in bitblock::any()
594    original_test_expr = whileNode.test.args[0]
595    if not isinstance(original_test_expr, ast.Name): return False
596    test_var = original_test_expr.id
597    if not isinstance(self.last_stmt, ast.Assign): return False
598    if not isinstance(whileNode.body[-1], ast.Assign): return False
599    if len(self.last_stmt.targets) != 1: return False
600    if len(whileNode.body[-1].targets) != 1: return False
601    if not isinstance(self.last_stmt.targets[0], ast.Name): return False
602    if not isinstance(whileNode.body[-1].targets[0], ast.Name): return False
603    if self.last_stmt.targets[0].id != test_var: return False
604    if whileNode.body[-1].targets[0].id != test_var: return False
605    if self.last_stmt_carries != 1: return False
606    if CarryCounter().count(whileNode.body[-1]) != 1: return False
607    return True
608
609  def visit_While(self, whileNode):
610    # Determine the original test expression, now encloded in bitblock::any()
611    self.block_no += 1
612    this_block = self.block_no
613    original_test_expr = whileNode.test.args[0]
614    if self.carryout == '':
615      whileNode.test.args[0] = mkCall("simd_and", [original_test_expr, ast.Name('EOF_mask', ast.Load())])
616    carry_base = self.current_carry
617    assert adv_nCounter().count(whileNode) == 0, "Advance(x,n) within while: illegal\n"
618    carries = CarryCounter().count(whileNode)
619#   Special Case Recognition
620    is_special = self.is_while_special_case(whileNode)
621    #CARRYSET
622    if carries == 0: return whileNode
623    local_carryvar = ast.Name('sub' + self.carryvar.id, ast.Load())
624    inner_while = self.local_while_xfrm(local_carryvar, copy.deepcopy(whileNode))
625    self.generic_visit(whileNode)
626    local_carry_decl = self.ccgo.GenerateLocalDeclare(this_block)
627    #local_carry_decl = []
628    #local_carry_decl = mkCallStmt('LocalCarryDeclare', [local_carryvar, ast.Num(carries)])
629    inner_while.body = local_carry_decl + inner_while.body
630    #final_combine = mkCallStmt(ast.Attribute(self.carryvar, 'CarryCombine', ast.Load()), [ast.Attribute(local_carryvar, 'cq', ast.Load()),ast.Num(carry_base), ast.Num(carries)])
631    final_combine = self.ccgo.GenerateCarryWhileFinalization(this_block)
632    inner_while.body += final_combine
633    #CARRYSET
634
635#   Special Case Optimization
636    if is_special:
637      # We combine the final carry into the one preceeding the loop.
638      combine1 = mkCallStmt(ast.Attribute(self.carryvar, 'CarryCombine1', ast.Load()), [ast.Num(carry_base-1), ast.Num(carry_base+carries-1)])
639      while_body_extend = [inner_while, combine1]
640      # The carry test can skip the final case.
641      carry_test_arglist = [ast.Num(carry_base), ast.Num(carries-1)]
642    else: 
643      carry_test_arglist = [ast.Num(carry_base), ast.Num(carries)]
644      while_body_extend = [inner_while]
645
646    if self.carryin == '': new_test = whileNode.test
647    else: new_test = self.ccgo.GenerateCarryWhileTest(this_block, whileNode.test)
648    else_part = [self.ccgo.GenerateCarryElseFinalization(this_block)]   
649    newIf = ast.If(new_test, whileNode.body + while_body_extend, else_part)
650    self.last_stmt = newIf
651    self.last_stmt_carries = carries
652    return newIf
653
654class StreamStructGen(ast.NodeVisitor):
655  """
656  Given a BitStreamSet subclass, generate the equivalent C struct.
657  >>> obj = ast.parse(r'''
658  ... class S1(BitStreamSet):
659  ...   a1 = 0
660  ...   a2 = 0
661  ...   a3 = 0
662  ...
663  ... class S2(BitStreamSet):
664  ...   x1 = 0
665  ...   x2 = 0
666  ... ''')
667  >>> print StreamStructGen().gen(obj)
668  struct S1 {
669    BitBlock a1;
670    BitBlock a2;
671    BitBlock a3;
672  }    self.current_adv_n = 0
673
674 
675  struct S2 {
676    BitBlock x1;
677    BitBlock x2;
678  }
679  """
680  def __init__(self, asType=False):
681    self.asType = asType
682  def gen(self, tree):
683    self.Ccode=""
684    self.generic_visit(tree)
685    return self.Ccode
686  def gen_struct_types(self, tree):
687    self.asType = True
688    self.Ccode=""
689    self.generic_visit(tree)
690    return self.Ccode
691  def gen_struct_vars(self, tree):
692    self.asType = False
693    self.Ccode=""
694    self.generic_visit(tree)
695    return self.Ccode
696  def visit_ClassDef(self, node):
697    class_name = node.name[0].upper() + node.name[1:]
698    instance_name = node.name[0].lower() + node.name[1:]
699    self.Ccode += "  struct " + class_name
700    if self.asType:
701            self.Ccode += " {\n"
702            for stmt in node.body:
703              if isinstance(stmt, ast.Assign):
704                for v in stmt.targets:
705                  if isinstance(v, ast.Name):
706                    self.Ccode += "  BitBlock " + v.id + ";\n"
707            self.Ccode += "}" 
708    else: self.Ccode += " " + instance_name
709    self.Ccode += ";\n\n"
710 
711class StreamFunctionDecl(ast.NodeVisitor):
712  def __init__(self):
713    pass
714  def gen(self, tree):
715    self.Ccode=""
716    self.generic_visit(tree)
717    return self.Ccode
718  def visit_FunctionDef(self, node):
719    self.Ccode += "static inline void " + node.name + "("
720    pending = ""
721    for arg in node.args.args:
722      if isinstance(arg, ast.Name):
723        self.Ccode += pending + arg.id.upper()[0] + arg.id[1:] + " & " + arg.id
724        pending = ", "
725    self.Ccode += ");\n"
726
727class AssertCompiler(ast.NodeTransformer):
728  def __init__(self):
729    self.assert_routine = ast.parse(error_routine).body[0].value
730  def xfrm(self, t):
731    return self.generic_visit(t)
732  def visit_Expr(self, node):
733    if isinstance(node.value, ast.Call):
734        if is_BuiltIn_Call(node.value, "assert_0", 2):
735                err_stream = node.value.args[0]
736                err_code = node.value.args[1]
737                return ast.If(mkCall('bitblock::any', [err_stream]),
738                              [ast.Expr(mkCall(self.assert_routine, [err_code, err_stream]))],
739                              [])
740        else: return node
741    else: return node
742       
743#
744# Adding Debugging Statements
745#
746class Add_SIMD_Register_Dump(ast.NodeTransformer):
747  def xfrm(self, t):
748    return self.generic_visit(t)
749  def visit_Assign(self, t):
750    self.generic_visit(t)
751    v = t.targets[0]
752    dump_stmt = mkCallStmt(' print_register<BitBlock>', [ast.Str(Cgen.py2C().gen(v)), v])
753    return [t, dump_stmt]
754
755#
756# Adding ASSERT_BITBLOCK_ALIGN macros
757#
758class Add_Assert_BitBlock_Align(ast.NodeTransformer):
759    def xfrm(self, t):
760      return self.generic_visit(t)
761    def visit_Assign(self, t):
762      self.generic_visit(t)
763      v = t.targets[0]
764      dump_stmt = mkCallStmt(' ASSERT_BITBLOCK_ALIGN', [v])
765      return [t, dump_stmt]
766
767class StreamFunctionCarryCounter(ast.NodeVisitor):
768  def __init__(self):
769        self.carry_count = {}
770       
771  def count(self, node):
772        self.generic_visit(node)
773        return self.carry_count
774                                   
775  def visit_FunctionDef(self, node):   
776        type_name = node.name[0].upper() + node.name[1:]                       
777        self.carry_count[type_name] = CarryCounter().count(node)
778     
779class StreamFunctionCallXlator(ast.NodeTransformer):
780  def __init__(self, xlate_type="normal"):
781        self.stream_function_type_names = []
782        self.xlate_type = xlate_type
783
784  def xfrm(self, node, stream_function_type_names, C_syntax):
785        self.stream_function_type_names = stream_function_type_names
786        self.C_syntax = C_syntax
787        self.generic_visit(node)
788       
789  def visit_Call(self, node):   
790        self.generic_visit(node)
791
792        if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):# and node.func.id in self.stream_function_type_names:
793             name = lower1(node.func.id)
794             node.func.id = name + ("_" if self.C_syntax else ".") + ("do_final_block" if self.xlate_type == "final" else "do_block")
795             if self.C_syntax:
796                     node.args = [ast.Name(lower1(name), ast.Load())] + node.args
797             if self.xlate_type == "final":
798                   node.args = node.args + [ast.Name("EOF_mask", ast.Load())]
799                     
800        return node     
801               
802class StreamFunctionVisitor(ast.NodeVisitor):
803        def __init__(self,node):
804                self.stream_function_node = {}
805                self.generic_visit(node)
806                                                             
807        def visit_FunctionDef(self, node):                     
808                key = node.name[0].upper() + node.name[1:]
809                self.stream_function_node[key] = node
810
811
812               
813class StreamFunction():
814        def __init__(self):
815                self.carry_count = 0 
816                self.init_to_one_list = [] 
817                self.adv_n_count = 0 
818                self.type_name = ""
819                self.instance_name = "" 
820                self.parameters = ""
821                self.declarations = "" 
822                self.initializations = "" 
823       
824        def dump(self):
825                print "%s" % (self.type_name)
826                print "%s=%s" % ("Carry Count", str(self.carry_count))
827                print "%s=[%s]" % ("Init to One List" , ','.join(map(str,self.init_to_one_list)))
828                print "%s=%s" % ("Adv n Count", str(self.adv_n_count)) 
829        #print "Instance Name:"     #+ self.instance_name = ""
830        #print "Parameters:"        #+ self.parameters = ""
831        #print "Declarations:"           #+ self.declarations = ""
832        #print "Initializations:"   # + self.initializations = ""
833   
834#
835# TODO Consolidate *all* C code generation into the Emitter class.   Medium priority.
836# TODO Implement 'pretty print' indentation.   Low priority.
837# TODO Migrate Emiter() class to Emitter module.  Medium priority.
838
839def lower1(name):
840    return name[0].lower() + name[1:]
841def upper1(name):
842    return name[0].upper() + name[1:]
843
844def escape_newlines(str):
845  return str.replace('\n', '\\\n')
846
847class Emitter():
848        def __init__(self, use_C_syntax, ccgo):
849                self.use_C_syntax = use_C_syntax
850                self.ccgo = ccgo
851
852        def definition(self, stream_function, icount=0):
853               
854                constructor = ""
855                carry_declaration = ""
856                self.type_name = stream_function.type_name
857               
858                if stream_function.carry_count > 0 or stream_function.adv_n_count > 0:
859                        constructor = self.constructor(stream_function.type_name, stream_function.carry_count, stream_function.init_to_one_list, stream_function.adv_n_count)
860                        carry_declaration = self.carry_declare('carryQ', stream_function.carry_count, stream_function.adv_n_count)
861
862                do_block_function = self.do_block(self.do_block_parameters(stream_function.parameters), 
863                                                stream_function.declarations, 
864                                                stream_function.initializations, 
865                                                stream_function.statements)             
866
867                do_final_block_function = self.do_final_block(self.do_final_block_parameters(stream_function.parameters), 
868                                                stream_function.declarations, 
869                                                stream_function.initializations, 
870                                                stream_function.final_block_statements)                 
871
872                do_segment_function = self.do_segment(self.do_segment_parameters(stream_function.parameters), 
873                                                self.do_segment_args(stream_function.parameters))       
874
875                if self.use_C_syntax:
876                        return self.indent(icount) + "struct " + stream_function.type_name + " {" \
877                               + "\n" + self.indent(icount) + carry_declaration \
878                               + "\n" + self.indent(icount) + "};\n" \
879                               + "\n" + self.indent(icount) + do_block_function \
880                               + "\n" + self.indent(icount) + do_final_block_function \
881                               + "\n" + self.indent(icount) + do_segment_function + "\n\n"
882                               
883                return self.indent(icount) + "struct " + stream_function.type_name + " {" \
884                + "\n" + self.indent(icount) + constructor \
885                + "\n" + self.indent(icount) + do_block_function \
886                + "\n" + self.indent(icount) + do_final_block_function \
887                + "\n" + self.indent(icount) + do_segment_function \
888                + "\n" + self.indent(icount) + carry_declaration \
889                + "\n" + self.indent(icount) + "};\n\n"
890
891        def constructor(self, type_name, carry_count, init_to_one_list, adv_n_count, icount=0):
892                one_inits = self.ccgo.GenerateInitializations()
893                #one_inits = ""
894                #for v in init_to_one_list:
895                #       one_inits += "  carryQ.cq[%s] = carryQ.carry_flip(carryQ.cq[%s]);\n" % (v, v)
896                adv_n_decl = ""
897                #for i in range(adv_n_count): adv_n_decl += self.indent(icount+2) + "pending64[%s] = simd<1>::constant<0>();\n" % i     
898                return self.indent(icount) + "%s() { ""\n" % (type_name) + adv_n_decl + self.carry_init(carry_count) + one_inits + " }" 
899                       
900        def do_block(self, parameters, declarations, initializations, statements, icount=0):
901                pfx = (lower1(self.type_name) + "_" if self.use_C_syntax else "")
902                if self.use_C_syntax:
903                        return "#define " + pfx + "do_block(" + parameters + ")\\\n do {" \
904                        + "\\\n" + self.indent(icount) + escape_newlines(declarations) \
905                        + "\\\n" + self.indent(icount) + escape_newlines(initializations) \
906                        + "\\\n" + self.indent(icount) + escape_newlines(statements) \
907                        + "\\\n" + self.indent(icount + 2) + "} while (0)" 
908                return self.indent(icount) + do_block_inline_decorator + "void " + pfx + "do_block(" + parameters + ") {" \
909                + "\n" + self.indent(icount) + declarations \
910                + "\n" + self.indent(icount) + initializations \
911                + "\n" + self.indent(icount) + statements \
912                + "\n" + self.indent(icount + 2) + "}" 
913
914
915
916
917        def do_final_block(self, parameters, declarations, initializations, statements, icount=0):
918                pfx = (lower1(self.type_name) + "_" if self.use_C_syntax else "")
919                if self.use_C_syntax:
920                        return "#define " + pfx + "do_final_block(" + parameters + ")\\\n do {" \
921                        + "\\\n" + self.indent(icount) + escape_newlines(declarations) \
922                        + "\\\n" + self.indent(icount) + escape_newlines(initializations) \
923                        + "\\\n" + self.indent(icount) + escape_newlines(statements) \
924                        + "\\\n" + self.indent(icount + 2) + "} while (0)" 
925                return self.indent(icount) + do_final_block_inline_decorator + "void " + pfx + "do_final_block(" + parameters + ") {" \
926                + "\n" + self.indent(icount) + declarations \
927                + "\n" + self.indent(icount) + initializations \
928                + "\n" + self.indent(icount) + statements \
929                + "\n" + self.indent(icount + 2) + "}" 
930
931        def do_segment(self, parameters, do_block_call_args, icount=0):
932                pfx = (lower1(self.type_name) + "_" if self.use_C_syntax else "")
933                if self.use_C_syntax:
934                        return "#define " + pfx + "do_segment(" + parameters + ")\\\n do {" \
935                        + "\\\n" + self.indent(icount) + "  int i;" \
936                        + "\\\n" + self.indent(icount) + "  for (i = 0; i < segment_blocks; i++)" \
937                        + "\\\n" + self.indent(icount) + "    " + pfx + "do_block(" + do_block_call_args + ");" \
938                        + "\\\n" + self.indent(icount + 2) + "} while (0)" 
939                return self.indent(icount) + "void " + pfx + "do_segment(" + parameters + ") {" \
940                + "\n" + self.indent(icount) + "  int i;" \
941                + "\n" + self.indent(icount) + "  for (i = 0; i < segment_blocks; i++)" \
942                + "\n" + self.indent(icount) + "    " + pfx + "do_block(" + do_block_call_args + ");" \
943                + "\n" + self.indent(icount + 2) + "}" 
944
945        def declaration(self, type_name, instance_name, icount=0):
946                if self.use_C_syntax: return self.indent(icount) + "struct " + type_name + " " + instance_name + ";\n"
947                return self.indent(icount) + type_name + " " + instance_name + ";\n"
948               
949        def carry_init(self, carry_count, icount=0):   
950                #CARRY SET
951                return ""
952               
953        def carry_declare(self, carry_variable, carry_count, adv_n_count=0, icount=0):
954                adv_n_decl = ""
955                #if adv_n_count > 0:
956                #       adv_n_decl = "\n" + self.indent(icount) + "BitBlock pending64[%s];" % adv_n_count
957                #CARRY SET
958                return self.indent(icount) + self.ccgo.GenerateCarryDecls()
959
960        def carry_test(self, carry_variable, carry_count, icount=0):
961                #CARRY SET
962                return self.indent(icount) + "carryQ.CarryTest(0, %i)" % (carry_count)         
963               
964        def indent(self, icount):
965                s = ""
966                for i in range(0,icount): s += " "
967                return s       
968               
969        def do_block_parameters(self, parameters):
970                if self.use_C_syntax:
971                        #return ", ".join([self.type_name + " * " + self.instance_name] + [upper1(p) + " * " + lower1(p) for p in parameters])
972                        return ", ".join([lower1(self.type_name)] + [lower1(p) for p in parameters])
973                else: return ", ".join([upper1(p) + " & " + lower1(p) for p in parameters])
974               
975        def do_final_block_parameters(self, parameters):
976                if self.use_C_syntax:
977                        #return ", ".join([self.type_name + " * " + self.instance_name] + [upper1(p) + " * " + lower1(p) for p in parameters]+ ["BitBlock EOF_mask"])
978                        return ", ".join([lower1(self.type_name)] + [lower1(p) for p in parameters]+ ["EOF_mask"])
979                else: return ", ".join([upper1(p) + " & " + lower1(p) for p in parameters]+ ["BitBlock EOF_mask"])
980               
981        def do_segment_parameters(self, parameters):
982                if self.use_C_syntax:
983                        #return ", ".join([self.type_name + " * " + + self.instance_name] + [upper1(p) + " " + lower1(p) + "[]" for p in parameters])
984                        return ", ".join([lower1(self.type_name)] + [lower1(p) for p in parameters] + ["segment_blocks"])
985                else: return ", ".join([upper1(p) + " " + lower1(p) + "[]" for p in parameters] + ["int segment_blocks"])
986
987        def do_segment_args(self, parameters):
988                if self.use_C_syntax:
989                        return ", ".join([lower1(self.type_name)] + [lower1(p) + "[i]" for p in parameters])
990                else: return ", ".join([lower1(p) + "[i]" for p in parameters])
991
992def main(infilename, outfile = sys.stdout):
993  t = ast.parse(file(infilename).read())
994  outfile.write(StreamStructGen(True).gen(t))
995  outfile.write(FunctionXlator().xlat(t))
996
997#
998#  Routines for compatibility with the old compiler/template.
999#  Quick and dirty hacks for now - Dec. 2010.
1000#
1001
1002class MainLoopTransformer:
1003  def __init__(self, main_module, C_syntax=False, add_dump_stmts=False, add_assert_bitblock_align=False, dump_func_data=False, main_node_id='Main'):
1004       
1005    self.main_module = main_module
1006    self.main_node_id = main_node_id
1007    self.use_C_syntax = C_syntax
1008    self.add_dump_stmts = add_dump_stmts
1009    self.add_assert_bitblock_align = add_assert_bitblock_align
1010    self.dump_func_data = dump_func_data
1011   
1012        # Gather and partition function definition nodes.
1013    stream_function_visitor = StreamFunctionVisitor(self.main_module)
1014    self.stream_function_node = stream_function_visitor.stream_function_node
1015    for key, node in self.stream_function_node.iteritems():
1016                AdvanceCombiner().xfrm(node)
1017    self.main_node = self.stream_function_node[main_node_id]
1018    self.main_carry_count = CarryCounter().count(self.main_node)
1019    self.main_adv_n_count = adv_nCounter().count(self.main_node)
1020    self.main_carry_info_set = CarryInfoSetVisitor(self.main_node)
1021    self.main_ccgo = Strategic_CCGO_Factory(self.main_carry_info_set)
1022    assert self.main_adv_n_count == 0, "Advance32() in main not supported.\n"
1023    del self.stream_function_node[self.main_node_id]
1024   
1025    self.stream_functions = {}
1026    for key, node in self.stream_function_node.iteritems():
1027                stream_function = StreamFunction()
1028                stream_function.carry_count = CarryCounter().count(node)
1029                stream_function.init_to_one_list = CarryInitToOneList().count(node)
1030                stream_function.adv_n_count = adv_nCounter().count(node)
1031                carry_info_set = CarryInfoSetVisitor(node)
1032                stream_function.ccgo = Strategic_CCGO_Factory(carry_info_set)
1033                stream_function.type_name = node.name[0].upper() + node.name[1:]
1034                stream_function.instance_name = node.name[0].lower() + node.name[1:]
1035                stream_function.parameters = FunctionVars(node).params
1036                stream_function.declarations = BitBlock_decls_of_fn(node)
1037                stream_function.declarations += "\n" + stream_function.ccgo.GenerateStreamFunctionDecls()
1038                stream_function.initializations = StreamInitializations().xfrm(node) 
1039               
1040                if self.add_dump_stmts: 
1041                        Add_SIMD_Register_Dump().xfrm(node)
1042                t = TempifyBuiltins()
1043                t.xfrm(node)
1044                stream_function.declarations += "\n" + BitBlock_decls_from_vars(t.tempVars())
1045
1046                StringMatchCompiler().xfrm(node)
1047                AugAssignRemoval().xfrm(node)
1048
1049               
1050                Bitwise_to_SIMD().xfrm(node)
1051                final_block_node = copy.deepcopy(node)
1052                if self.use_C_syntax:
1053                        carryQname = stream_function.instance_name + ".carryQ"
1054                else: carryQname = "carryQ"
1055                CarryIntroVisitor = CarryIntro(stream_function.ccgo, carryQname)
1056                CarryIntroVisitor.xfrm_fndef(node)
1057                CarryIntroVisitor.xfrm_fndef_final(final_block_node)
1058                #
1059                # Compile asserts after carry intro so that generated if-statements
1060                # are ignored.
1061                AssertCompiler().xfrm(node)
1062                AssertCompiler().xfrm(final_block_node)
1063
1064                if self.add_assert_bitblock_align:
1065                        Add_Assert_BitBlock_Align().xfrm(node)
1066                        Add_Assert_BitBlock_Align().xfrm(final_block_node)
1067
1068                #if stream_function.carry_count > 0:
1069                #       node.body += [mkCallStmt('carryQ.CarryQ_Adjust', [ast.Num(stream_function.carry_count)])]
1070                node.body += stream_function.ccgo.GenerateStreamFunctionFinalization()
1071
1072               
1073                stream_function.statements = Cgen.py2C(4).gen(node.body)
1074                stream_function.final_block_statements = Cgen.py2C(4).gen(final_block_node.body)
1075                self.stream_functions[stream_function.type_name] = stream_function
1076               
1077    if self.dump_func_data:     
1078        for key, value in self.stream_functions.iteritems():
1079                        value.dump()
1080        sys.exit()
1081               
1082    self.emitter = Emitter(self.use_C_syntax, stream_function.ccgo)
1083   
1084  def any_carry_expr(self):
1085       
1086        carry_test = []
1087       
1088        if self.main_carry_count > 0:
1089                        carry_test.append(self.emitter.carry_test('carryQ', self.main_carry_count)) 
1090                        carry_test.append(" || ")
1091
1092        for key in self.stream_functions.keys():               
1093                if self.stream_functions[key].carry_count > 0:
1094                        carry_test.append(self.stream_functions[key].instance_name + "." + self.emitter.carry_test('carryQ',self.stream_functions[key].carry_count))# TODO Update self.emitter.carry_test
1095                        carry_test.append(" || ")
1096
1097        if len(carry_test) > 0:
1098                carry_test.pop()
1099                return "".join(carry_test)
1100        return "1"
1101
1102  def gen_globals(self):
1103    self.Cglobals = StreamStructGen().gen_struct_types(self.main_module)
1104    for key in self.stream_functions.keys():
1105                sf = self.stream_functions[key]
1106                self.Cglobals += Emitter(self.use_C_syntax, sf.ccgo).definition(sf, 2)     
1107                       
1108  def gen_declarations(self): 
1109    self.Cdecls = StreamStructGen().gen_struct_vars(self.main_module)
1110    self.Cdecls += BitBlock_decls_of_fn(self.main_node) + "\n" + self.main_ccgo.GenerateStreamFunctionDecls()
1111    if self.main_carry_count > 0: 
1112        self.Cdecls += self.emitter.carry_declare('carryQ', self.main_carry_count)
1113               
1114  def gen_initializations(self):
1115    self.Cinits = ""
1116    if self.main_carry_count > 0: 
1117        self.Cinits += self.emitter.carry_init(self.main_carry_count)
1118    self.Cinits += StreamInitializations().xfrm(self.main_module)
1119    if self.use_C_syntax:
1120                for key in self.stream_functions.keys():
1121                        if self.stream_functions[key].carry_count == 0: continue
1122                        self.Cinits += self.emitter.declaration(self.stream_functions[key].type_name, self.stream_functions[key].instance_name, 2)
1123                        self.Cinits += "CarryInit(" + self.stream_functions[key].instance_name + ".carryQ, %i);\n" % (self.stream_functions[key].carry_count)
1124    else:
1125                for key in self.stream_functions.keys():
1126                        self.Cinits += self.emitter.declaration(self.stream_functions[key].type_name, self.stream_functions[key].instance_name, 2)
1127
1128                       
1129  def xfrm_block_stmts(self):
1130    StringMatchCompiler().xfrm(self.main_node)
1131    AugAssignRemoval().xfrm(self.main_node)
1132    Bitwise_to_SIMD().xfrm(self.main_node)
1133    Bitwise_to_SIMD().xfrm(self.main_node)
1134    final_block_main = copy.deepcopy(self.main_node)
1135    carry_info_set = CarryInfoSetVisitor(self.main_node)
1136    #ccgo = Strategic_CCGO_Factory(carry_info_set)
1137    #CarryIntroVisitor = CarryIntro(ccgo)
1138    #CarryIntroVisitor.xfrm_fndef(self.main_node)
1139    #CarryIntroVisitor.xfrm_fndef_final(final_block_main)
1140    AssertCompiler().xfrm(self.main_node)
1141    if self.add_dump_stmts: 
1142        Add_SIMD_Register_Dump().xfrm(self.main_node)
1143        Add_SIMD_Register_Dump().xfrm(final_block_main)
1144               
1145    if self.add_assert_bitblock_align:
1146        print "add_assert_bitblock_align"
1147        Add_Assert_BitBlock_Align().xfrm(self.main_node)
1148        Add_Assert_BitBlock_Align().xfrm(final_block_main)
1149
1150    StreamFunctionCallXlator().xfrm(self.main_node, self.stream_function_node.keys(), self.use_C_syntax)
1151    StreamFunctionCallXlator('final').xfrm(final_block_main, self.stream_function_node.keys(), self.use_C_syntax)
1152   
1153    #if self.main_carry_count > 0:
1154                #self.main_node.body += [mkCallStmt('CarryQ_Adjust', [ast.Name('carryQ', ast.Load()), ast.Num(self.main_carry_count)])]
1155    #self.main_node.body += ccgo.GenerateStreamFunctionFinalization()
1156   
1157   
1158       
1159    self.Cstmts = Cgen.py2C().gen(self.main_node.body)
1160    self.Cfinal_stmts = Cgen.py2C().gen(final_block_main.body)
1161   
1162if __name__ == "__main__":
1163                import doctest
1164                doctest.testmod()
Note: See TracBrowser for help on using the repository browser.