Changeset 3571 for proto/Compiler


Ignore:
Timestamp:
Nov 21, 2013, 3:28:41 PM (6 years ago)
Author:
nmedfort
Message:

start of error rewriting work. some clean up done to pablo.py; a few classes in it were moved to pablo_util.py.

Location:
proto/Compiler
Files:
3 added
3 edited

Legend:

Unmodified
Added
Removed
  • proto/Compiler/config.py

    r3095 r3571  
     1#!/usr/bin/python
     2# -*- coding: utf-8 -*-
    13import optparse
    24
     5
    36def get_option_parser():
    4         """Return an C{optparse.OptionParser} instance tied to this configuration."""
    5        
    6         parser = optparse.OptionParser(usage='python %prog [options] <input file>',
    7                                         version='1.0',
    8                                         )
    9        
    10         # Option definitions
    11         parser.add_option('-t', '--template',
    12                           dest='template_filename',
    13                           type='string',
    14                           default='template.c',
    15                           help='default:template.c',
    16                           )
     7    """Return an C{optparse.OptionParser} instance tied to this configuration."""
    178
    18         parser.add_option('-o', '--output',
    19                           dest='output_filename',
    20                           type='string',
    21                           default='code.c',
    22                           help='default:code.c',
    23                           )
     9    parser = optparse.OptionParser(usage='python %prog [options] <input file>', version='1.0')
    2410
    25         parser.add_option('-l', '--label',
    26                           dest='template_label',
    27                           type='string',
    28                           default='@',
    29                           help='default:@',
    30                           )
    31        
    32         parser.add_option('-c', '--C_syntax',
    33                           dest='C_syntax',
    34                           action='store_true',
    35                           default=False,
    36                           help='use C syntax for output',
    37                           )
    38        
    39         parser.add_option('-X', '--experimental',
    40                           dest='experimental',
    41                           action='store_true',
    42                           default=False,
    43                           help='Experimental version with CCGO support',
    44                           )
    45        
    46         parser.add_option('-W', '--multicarryWhileMode',
    47                           dest='multicarryWhileMode',
    48                           action='store_true',
    49                           default=False,
    50                           help='Multicarry while loops: one carry per operation per iteration',
    51                           )
    52        
    53         parser.add_option('-i', '--IDISA',
    54                           dest='use_IDISA',
    55                           action='store_true',
    56                           default=True,
    57                           help='use new IDISA ops for output',
    58                           )
    59        
    60         parser.add_option('-e', '--error_routine',
    61                           dest='error_routine',
    62                           default='assert_0_error',
    63                           help='Name/qualified name for error routine',
    64                           )
    65        
    66         parser.add_option('-C', '--character type',
    67                           dest='pablo_char_type',
    68                           default='char',
    69                           help='The base type of character strings',
    70                           )
    71        
    72         parser.add_option('-A', '--ALWAYS_INLINE',
    73                           dest='always_inline',
    74                           action='store_true',
    75                           default=False,
    76                           help='set IDISA_ALWAYS_INLINE for do_block/do_final_block',
    77                           )
    78        
    79         # Group options
    80         # 'dump'
    81         dump = optparse.OptionGroup(parser, "Debug Options")
     11    parser.add_option(
     12        '-t',
     13        '--template',
     14        dest='template_filename',
     15        type='string',
     16        default='template.c',
     17        help='default:template.c',
     18        )
    8219
    83         dump.add_option('-d','--dump_func_data',
    84                 dest='dump_func_data',
    85                 action='store_true',
    86                 default=False,
    87                 help='Dump stream function information.')
     20    parser.add_option(
     21        '-o',
     22        '--output',
     23        dest='output_filename',
     24        type='string',
     25        default='code.c',
     26        help='default:code.c',
     27        )
    8828
    89         dump.add_option('-f','--func_defs',
    90                                 dest='func_defs',
    91                                 action='store_true',
    92                                 default=False,
    93                                 help='Display function definition transforms.')
    94        
    95         dump.add_option('-s','--struct_decs',
    96                                 dest='struct_decs',
    97                                 action='store_true',
    98                                 default=False,
    99                                 help='Display struct declartation transforms.')
     29    parser.add_option(
     30        '-l',
     31        '--label',
     32        dest='template_label',
     33        type='string',
     34        default='@',
     35        help='default:@',
     36        )
    10037
    101         dump.add_option('-a','--add_dump_stmts',
    102                                 dest='add_dump_stmts',
    103                                 action='store_true',
    104                                 default=False,
    105                                 help='Add SIMD register dump statements.')
     38    parser.add_option(
     39        '-c',
     40        '--C_syntax',
     41        dest='C_syntax',
     42        action='store_true',
     43        default=False,
     44        help='use C syntax for output',
     45        )
    10646
    107         dump.add_option('-b','--add_assert_bitblock_align',
    108                                 dest='add_assert_bitblock_align',
    109                                 action='store_true',
    110                                 default=False,
    111                                 help='Add ASSERT_BITBLOCK_ALIGN statements.')
     47    parser.add_option(
     48        '-X',
     49        '--experimental',
     50        dest='experimental',
     51        action='store_true',
     52        default=False,
     53        help='Experimental version with CCGO support',
     54        )
    11255
    113         parser.add_option_group(dump)
     56    parser.add_option(
     57        '-W',
     58        '--multicarryWhileMode',
     59        dest='multicarryWhileMode',
     60        action='store_true',
     61        default=False,
     62        help='Multicarry while loops: one carry per operation per iteration',
     63        )
    11464
    115         return parser
     65    parser.add_option(
     66        '-i',
     67        '--IDISA',
     68        dest='use_IDISA',
     69        action='store_true',
     70        default=True,
     71        help='use new IDISA ops for output',
     72        )
    11673
     74    parser.add_option('-e', '--error_routine', dest='error_routine', default='assert_0_error', help='Name/qualified name for error routine')
    11775
     76    parser.add_option('-C', '--character type', dest='pablo_char_type', default='char', help='The base type of character strings')
     77
     78    parser.add_option(
     79        '-A',
     80        '--ALWAYS_INLINE',
     81        dest='always_inline',
     82        action='store_true',
     83        default=False,
     84        help='set IDISA_ALWAYS_INLINE for do_block/do_final_block',
     85        )
     86
     87    dump = optparse.OptionGroup(parser, 'Debug Options')
     88
     89    dump.add_option(
     90        '-d',
     91        '--dump_func_data',
     92        dest='dump_func_data',
     93        action='store_true',
     94        default=False,
     95        help='Dump stream function information.',
     96        )
     97
     98    dump.add_option(
     99        '-f',
     100        '--func_defs',
     101        dest='func_defs',
     102        action='store_true',
     103        default=False,
     104        help='Display function definition transforms.',
     105        )
     106
     107    dump.add_option(
     108        '-s',
     109        '--struct_decs',
     110        dest='struct_decs',
     111        action='store_true',
     112        default=False,
     113        help='Display struct declartation transforms.',
     114        )
     115
     116    dump.add_option(
     117        '-a',
     118        '--add_dump_stmts',
     119        dest='add_dump_stmts',
     120        action='store_true',
     121        default=False,
     122        help='Add SIMD register dump statements.',
     123        )
     124
     125    dump.add_option(
     126        '-b',
     127        '--add_assert_bitblock_align',
     128        dest='add_assert_bitblock_align',
     129        action='store_true',
     130        default=False,
     131        help='Add ASSERT_BITBLOCK_ALIGN statements.',
     132        )
     133
     134    dump.add_option(
     135        '--rewrite_errors',
     136        dest='rewrite_errors',
     137        action='store_true',
     138        default=False,
     139        help='Transforms any error.* statement within each do_block to use the AnyError bitblock.\nNote: this expects AnyError to be created and initialized to 0 in the template code and that all error bitstreams are contained within \"class Error\".',
     140        )       
     141       
     142    parser.add_option_group(dump)
     143
     144    return parser
  • proto/Compiler/pablo.py

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

    r3095 r3571  
    1 # pablomain.py - compile unbounded bitstreams code into
    2 #   equivalent block-by-block code in C.
    3 #
    4 # (c) 2011 Robert D. Cameron, Ken Herdy
    5 # All rights reserved.
    6 # Licensed to International Characters, Inc. under Academic Free License 3.0
    7 #
     1#!/usr/bin/python
     2# -*- coding: utf-8 -*-
    83
    9 import config, optparse
    10 import ast, pablo, string, sys, copy, os
     4import config
     5import optparse
     6import ast
     7import pablo
     8import string
     9import sys
     10import copy
     11import os
     12
    1113
    1214class Program:
    13     def __init__(self, output_file, template_file = "template.c"):
     15
     16    def __init__(self, output_file, template_file='template.c'):
    1417        pass
    1518        self.template_file = template_file
    1619        self.output_file = output_file
    1720
    18     def output(self, tag, globaldecl, localdecl, stream_stmts, block_stmts, final_block_stmts, any_carry_expr, template_string):
    19        
     21    def output(
     22        self,
     23        tag,
     24        globaldecl,
     25        localdecl,
     26        stream_stmts,
     27        block_stmts,
     28        final_block_stmts,
     29        any_carry_expr,
     30        template_string,
     31        ):
     32
    2033        template_string = string.replace(template_string, tag + 'global', globaldecl)
    2134        template_string = string.replace(template_string, tag + 'decl', localdecl)
     
    2740
    2841    def read_template(self):
    29         f=open(self.template_file)
    30         inp = ""
     42        f = open(self.template_file)
     43        inp = ''
    3144        for line in f:
    3245            inp += line
     
    3548
    3649    def write_final_code(self, code):
    37         f=open(self.output_file, 'w')
     50        f = open(self.output_file, 'w')
    3851        f.write(code)
    3952        f.close()
    4053
    4154    def generate_code(self, input_string, options):
    42         # FRONT END
     55
    4356        s = ast.parse(input_string)
    44         # Analysis and Transformation
     57
    4558        xfrmr = pablo.MainLoopTransformer(s, options.C_syntax, options.add_dump_stmts, options.add_assert_bitblock_align, options.dump_func_data)
    4659        xfrmr.gen_globals()
    4760        xfrmr.gen_declarations()
    4861        xfrmr.gen_initializations()
    49         xfrmr.xfrm_block_stmts()     
     62        xfrmr.xfrm_block_stmts()
    5063
    51         # BACK END
    5264        template_contents = self.read_template()
    53                
     65
    5466        template_contents = self.output(
    55                             options.template_label,
    56                             xfrmr.Cglobals,
    57                             xfrmr.Cdecls,
    58                             xfrmr.Cinits,
    59                             xfrmr.Cstmts,
    60                             xfrmr.Cfinal_stmts,
    61                             xfrmr.any_carry_expr(),
    62                             template_contents)
     67            options.template_label,
     68            xfrmr.Cglobals,
     69            xfrmr.Cdecls,
     70            xfrmr.Cinits,
     71            xfrmr.Cstmts,
     72            xfrmr.Cfinal_stmts,
     73            xfrmr.any_carry_expr(),
     74            template_contents,
     75            )
    6376        self.write_final_code(template_contents)
    6477        return s
    6578
     79
    6680def readfile(filename):
    67         f = open(filename, 'r')
    68         contents = f.read()
    69         f.close()
    70         return contents
     81    f = open(filename, 'r')
     82    contents = f.read()
     83    f.close()
     84    return contents
     85
    7186
    7287if __name__ == '__main__':
    73  
    74         option_parser = config.get_option_parser()
    75         options, args = option_parser.parse_args(sys.argv[1:])
    7688
    77         # Positional arguments
    78         if len(args) != 1:
    79             option_parser.print_usage()
    80             sys.exit()
     89    option_parser = config.get_option_parser()
     90    (options, args) = option_parser.parse_args(sys.argv[1:])
    8191
    82         input_file = args[0]
    83         input_string = readfile(input_file)
     92    if len(args) != 1:
     93        option_parser.print_usage()
     94        sys.exit()
    8495
    85         pablo.error_routine = options.error_routine
     96    input_file = args[0]
     97    input_string = readfile(input_file)
    8698
    87         pablo.experimentalMode = options.experimental
    88         pablo.multicarryWhileMode = options.multicarryWhileMode
    89         pablo.pablo_char_type = options.pablo_char_type
    90        
    91         if options.use_IDISA:
    92                 pablo.name_substitution_map = {'bitblock_has_bit' : 'bitblock::any',
    93                                              'simd_const_1' : 'mvmd<1>::fill'}
    94         if options.always_inline:
    95                 pablo.do_block_inline_decorator = 'IDISA_ALWAYS_INLINE '
    96                 pablo.do_final_block_inline_decorator = 'IDISA_ALWAYS_INLINE '
     99    pablo.error_routine = options.error_routine
     100    pablo.rewrite_errors = options.rewrite_errors
     101    pablo.experimentalMode = options.experimental
     102    pablo.multicarryWhileMode = options.multicarryWhileMode
     103    pablo.pablo_char_type = options.pablo_char_type
    97104
    98         # Compiler modes
    99         if options.struct_decs:
    100                 print pablo.StreamStructGen().gen(ast.parse(input_string))
    101                
    102         elif options.func_defs:
    103                 #print pablo.FunctionXformer().xlat(ast.parse(input_string))
    104                 pass
    105                
    106         else:
    107                 s = Program(options.output_filename, options.template_filename).generate_code(input_string, options)
     105    if options.use_IDISA:
     106        pablo.name_substitution_map = {'bitblock_has_bit': 'bitblock::any', 'simd_const_1': 'mvmd<1>::fill'}
     107    if options.always_inline:
     108        pablo.do_block_inline_decorator = 'IDISA_ALWAYS_INLINE '
     109        pablo.do_final_block_inline_decorator = 'IDISA_ALWAYS_INLINE '
    108110
     111    if options.struct_decs:
     112        print pablo.StreamStructGen().gen(ast.parse(input_string))
     113    elif options.func_defs:
     114
     115        pass
     116    else:
     117
     118        s = Program(options.output_filename, options.template_filename).generate_code(input_string, options)
Note: See TracChangeset for help on using the changeset viewer.