source: proto/Compiler/pablo.py @ 3389

Last change on this file since 3389 was 3389, checked in by cameron, 6 years ago

clear() method for stream struct carries

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