source: proto/Compiler/pablo.py @ 2699

Last change on this file since 2699 was 2698, checked in by cameron, 7 years ago

Fixes for advance_n support in experimental mode

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