Changeset 2693 for proto


Ignore:
Timestamp:
Nov 26, 2012, 10:38:35 AM (7 years ago)
Author:
cameron
Message:

Create separate CCGO module

Location:
proto/Compiler
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • proto/Compiler/pablo.py

    r2691 r2693  
    88import ast, copy, sys
    99import Cgen
     10from carryInfo import *
     11import CCGO
    1012
    1113name_substitution_map = {}
     
    1517experimentalMode=False
    1618
    17 def isCarryGenerating(builtin_fn):
    18    return builtin_fn in ['ScanThru', 'ScanTo', 'AdvanceThenScanThru', 'AdvanceThenScanTo', 'SpanUpTo', 'InclusiveSpan', 'ExclusiveSpan', 'ScanToFirst']
    19 def usesCarryInit1(builtin_fn):
    20    return builtin_fn in ['ScanToFirst']
    21 def isAdvance(builtin_fn):
    22    return builtin_fn in ['Advance']
    23 
    24 
    25 def CheckForBuiltin(fncall, builtin_fnmod_noprefix='pablo'):
    26   if not isinstance(fncall, ast.Call): return None
    27   if isinstance(fncall.func, ast.Name): fn_name = fncall.func.id
    28   elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
    29     if fncall.func.value.id == builtin_fnmod_noprefix: fn_name = fncall.func.attr
    30     else: return None
    31   else: return None
    32   if isCarryGenerating(fn_name) or isAdvance(fn_name): return fn_name
    33   else: return None
    34 
    35 def CarryCountOfFn(fncall, builtin_fnmod_noprefix='pablo'):
    36   if not isinstance(fncall, ast.Call): return 0
    37   if isinstance(fncall.func, ast.Name): fn_name = fncall.func.id
    38   elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
    39     if fncall.func.value.id == builtin_fnmod_noprefix: fn_name = fncall.func.attr
    40     else: return 0
    41   else: return 0
    42   if isAdvance(fn_name):
    43     if len(fncall.args) == 1: return 1
    44     else: return 0 #  return fncall.args[1].n  # Possibly count Advance(m, n) as generating n carries.
    45   elif isCarryGenerating(fn_name): return 1
    46   else: return 0
    47    
    48 def is_BuiltIn_Call(fncall, builtin_fnname, builtin_arg_cnt, builtin_fnmod_noprefix='pablo'):
    49         if isinstance(fncall.func, ast.Name): iscall = fncall.func.id == builtin_fnname
    50         elif isinstance(fncall.func, ast.Attribute) and isinstance(fncall.func.value, ast.Name):
    51                  iscall = fncall.func.value.id == builtin_fnmod_noprefix and fncall.func.attr == builtin_fnname
    52         return iscall and len(fncall.args) == builtin_arg_cnt
    5319
    5420def dump_Call(fncall):
     
    6430  return ast.Attribute(ast.Name(obj, ast.Load()), field, ast.Load())
    6531
     32#
     33# Helpers
    6634def mkCall(fn_name, args):
    6735  if isinstance(fn_name, str):
    68         if name_substitution_map.has_key(fn_name): fn_name = name_substitution_map[fn_name]
    6936        fn_name = ast.Name(fn_name, ast.Load())
    7037  return ast.Call(fn_name, args, [], None, None)
     
    7441  return ast.Expr(ast.Call(fn_name, args, [], None, None))
    7542 
    76  
    77 #
    78 # Carry Info Set
    79 #
    80 class CarryInfoSetVisitor(ast.NodeVisitor):
    81   def __init__(self, streamFunctionNode):
    82     (self.operation_count, self.block_count) = (0, 0)
    83     (self.block_first_op, self.block_op_count, self.advance_amount) = ({}, {}, {})
    84     self.init_one_list = []
    85     (self.parent_block, self.children, self.whileblock) = ({}, {}, {})
    86     (self.carry_count, self.adv_n_count, self.adv_1_count) = (0, 0, 0)
    87     (self.total_advance, self.max_advance) = (0, 0)
    88 
    89     # Initialize for the main block
    90     self.block_no = 0
    91     self.block_count += 1
    92     self.children[0] = []
    93     self.block_first_op[0] = 0
    94     # Recursively process all blocks
    95     self.generic_visit(streamFunctionNode)
    96     self.block_op_count[0] = self.operation_count
    97 
    98   def visit_Call(self, callnode):
    99     self.generic_visit(callnode)
    100     builtin = CheckForBuiltin(callnode)
    101     if builtin == None: return
    102     if isCarryGenerating(builtin):
    103       if usesCarryInit1(builtin): self.init_one_list.append(self.operation_count)
    104       self.operation_count += 1
    105       self.carry_count += 1
    106     elif isAdvance(builtin):
    107       if len(callnode.args) > 1:
    108         adv_amount = callnode.args[1].n
    109         self.adv_n_count += 1
    110       else:
    111         adv_amount = 1
    112         self.adv_1_count += 1
    113       self.advance_amount[self.operation_count] = adv_amount
    114       self.total_advance += adv_amount
    115       if adv_amount > self.max_advance: self.max_advance = adv_amount
    116       self.operation_count += 1
    117     else: return
    118 
    119   def block_visit(self, blkNode):
    120     prnt = self.block_no
    121     this_block_no = self.block_count
    122     self.block_count += 1
    123     self.parent_block[this_block_no] = prnt
    124     self.children[prnt].append(this_block_no)
    125     self.whileblock = isinstance(blkNode, ast.While)
    126     self.block_no = this_block_no
    127     self.block_first_op[this_block_no] = self.operation_count
    128     self.children[this_block_no] = []
    129     self.generic_visit(blkNode)
    130     self.block_op_count[this_block_no] = self.operation_count - self.block_first_op[this_block_no]
    131     # reset for processing remainder of parent
    132     self.block_no = self.parent_block[this_block_no]
    133 
    134 
    135   def visit_If(self, ifNode): 
    136     self.block_visit(ifNode)
    137  
    138   def visit_While(self, whileNode):   
    139     self.block_visit(whileNode)
    140 
    141   def countBlockCarrysWithAdv1(self, blk):
    142     op_count = self.block_op_count[blk]
    143     if op_count == 0: return 0
    144     carries = 0
    145     for op in range(self.block_first_op[blk], self.block_first_op[blk] + op_count):
    146       if op not in self.advance_amount.keys(): carries += 1
    147       elif self.advance_amount[op] == 1: carries += 1
    148     return carries
     43
    14944
    15045#
     
    425320# Carry Introduction Transformation
    426321#
    427 class CarryCounter(ast.NodeVisitor):
    428   def visit_Call(self, callnode):
    429     self.generic_visit(callnode)
    430     self.carry_count += CarryCountOfFn(callnode)
    431   def visit_BinOp(self, exprnode):
    432     self.generic_visit(exprnode)
    433     if isinstance(exprnode.op, ast.Sub):
    434       self.carry_count += 1
    435     if isinstance(exprnode.op, ast.Add):
    436       self.carry_count += 1
    437   def count(self, nodeToVisit):
    438     self.carry_count = 0
    439     self.generic_visit(nodeToVisit)
    440     return self.carry_count
    441 
    442 #
    443 # Carry Initialization:  Aug. 4, 2012
    444 # - Carry variables are initialized to 0 by default
    445 # - However, the scan_to_first routine should ideally use
    446 #   initialization with 1.
    447 
    448 #
    449 class CarryInitToOneList(ast.NodeVisitor):
    450   def visit_Call(self, callnode):
    451     self.generic_visit(callnode)
    452     if is_BuiltIn_Call(callnode,'Advance', 1) or is_BuiltIn_Call(callnode,'ScanThru', 2) or is_BuiltIn_Call(callnode,'ScanTo', 2) or is_BuiltIn_Call(callnode,'AdvanceThenScanThru', 2) or is_BuiltIn_Call(callnode,'AdvanceThenScanTo', 2) or is_BuiltIn_Call(callnode,'SpanUpTo', 2) or  is_BuiltIn_Call(callnode,'InclusiveSpan', 2) or is_BuiltIn_Call(callnode,'ExclusiveSpan', 2):       
    453       self.carry_count += 1
    454     elif is_BuiltIn_Call(callnode,'ScanToFirst', 1):
    455       self.init_to_one_list.append(self.carry_count)
    456       self.carry_count += 1
    457   def visit_BinOp(self, exprnode):
    458     self.generic_visit(exprnode)
    459     if isinstance(exprnode.op, ast.Sub):
    460       self.carry_count += 1
    461     if isinstance(exprnode.op, ast.Add):
    462       self.carry_count += 1
    463   def count(self, nodeToVisit):
    464     self.carry_count = 0
    465     self.init_to_one_list = []
    466     self.generic_visit(nodeToVisit)
    467     return self.init_to_one_list
    468 
    469 class adv_nCounter(ast.NodeVisitor):
    470   def visit_Call(self, callnode):
    471     self.generic_visit(callnode)
    472     if is_BuiltIn_Call(callnode,'Advance32', 1):       
    473       self.adv_n_count += 1
    474     if is_BuiltIn_Call(callnode,'Advance', 2):         
    475       self.adv_n_count += 1
    476   def count(self, nodeToVisit):
    477     self.adv_n_count = 0
    478     self.generic_visit(nodeToVisit)
    479     return self.adv_n_count
    480 
    481 #
    482 # Base CCGO Class is also the null class, suitable for stream
    483 # functions that have no carry-generating operations.
    484 #
    485 class CCGO:
    486     def __init__(self): pass
    487     def GenerateCarryDecls(self): return ""
    488     def GenerateInitializations(self): return ""
    489     def GenerateStreamFunctionDecls(self):  return ""
    490     def GenerateCarryInAccess(self, operation_no): return None
    491     def GenerateCarryOutStore(self, operation_no, carry_out_expr): return []
    492     def GenerateCarryIfTest(self, block_no, ifTest): return ifTest
    493     def GenerateCarryElseFinalization(self, block_no): return []
    494     def GenerateLocalDeclare(self, block_no): return []
    495     def GenerateCarryWhileTest(self, block_no, testExpr): return testExpr
    496     def EnterLocalWhileBlock(self, operation_offset):  pass
    497     def ExitLocalWhileBlock(self):  pass
    498     def GenerateCarryWhileFinalization(self, block_no): return []
    499     def GenerateStreamFunctionFinalization(self): return []
    500 
    501 class testCCGO(CCGO):
    502     def __init__(self, carryInfoSet, carryGroupVarName='carryQ'):
    503         self.carryInfoSet = carryInfoSet
    504         self.carryGroupVar = carryGroupVarName
    505         self.carryIndex = {}
    506         self.operation_offset = 0
    507         carry_counter = 0
    508         for op_no in range(carryInfoSet.operation_count):
    509           self.carryIndex[op_no] = carry_counter
    510           if not op_no in carryInfoSet.advance_amount.keys(): carry_counter += 1
    511           elif carryInfoSet.advance_amount[op_no] == 1: carry_counter += 1
    512         # Add a dummy entry for any possible final block that is empty.
    513         self.carryIndex[carryInfoSet.operation_count] = carry_counter
    514     # Helper
    515     def CarryGroupAtt(self, attname, CarryGroupVarName=""):
    516         if CarryGroupVarName == '': CarryGroupVarName = self.carryGroupVar
    517         return ast.Attribute(ast.Name(CarryGroupVarName, ast.Load()), attname, ast.Load())
    518     def GenerateCarryDecls(self):
    519         carry_counter = 0
    520         adv_n_counter = 0
    521         for op_no in range(self.carryInfoSet.block_op_count[0]):
    522           if not op_no in self.carryInfoSet.advance_amount.keys(): carry_counter += 1
    523           elif self.carryInfoSet.advance_amount[op_no] == 1: carry_counter += 1
    524           else: adv_n_counter += 1
    525         return "CarryArray<%i, %i> %s;" % (carry_counter, adv_n_counter, self.carryGroupVar)
    526     def GenerateInitializations(self):
    527         carry_counter = 0
    528         adv_n_counter = 0
    529         inits = ""
    530         for op_no in range(self.carryInfoSet.block_op_count[0]):
    531           if op_no in self.carryInfoSet.init_one_list: inits += "carryQ.cq[%s] = carryQ.carry_flip(carryQ.cq[%s]);\n" % (carry_counter, carry_counter)
    532           if not op_no in self.carryInfoSet.advance_amount.keys(): carry_counter += 1
    533           elif self.carryInfoSet.advance_amount[op_no] == 1: carry_counter += 1
    534           else: adv_n_counter += 1
    535         return inits
    536     def GenerateStreamFunctionDecls(self):  return ""
    537     def GenerateCarryInAccess(self, operation_no):
    538         carry_index = self.carryIndex[operation_no - self.operation_offset]
    539         return mkCall(self.carryGroupVar + "." + 'get_carry_in', [ast.Num(carry_index)])
    540     def GenerateCarryOutStore(self, operation_no, carry_out_expr):
    541         carry_index = self.carryIndex[operation_no - self.operation_offset]
    542         return [ast.Assign([ast.Subscript(self.CarryGroupAtt('cq'), ast.Index(ast.Num(carry_index)), ast.Store())],
    543                           mkCall("bitblock::srli<127>", [carry_out_expr]))]
    544     def GenerateCarryIfTest(self, block_no, ifTest):
    545         carry_count = self.carryInfoSet.block_op_count[block_no]
    546         if carry_count == 0: return ifTest
    547         ifIndex = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
    548         return ast.BoolOp(ast.Or(), [ifTest, mkCall(self.CarryGroupAtt('CarryTest'), [ast.Num(ifIndex), ast.Num(carry_count)])])
    549     def GenerateCarryElseFinalization(self, block_no):
    550         carry_count = self.carryInfoSet.block_op_count[block_no]
    551         if carry_count == 0: return []
    552         ifIndex = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
    553         return [mkCallStmt(self.CarryGroupAtt('CarryDequeueEnqueue'), [ast.Num(ifIndex), ast.Num(carry_count)])]
    554     def GenerateLocalDeclare(self, block_no):
    555         local_carryvar = ast.Name("sub" + self.carryGroupVar, ast.Load())
    556         return [mkCallStmt('LocalCarryDeclare', [local_carryvar, ast.Num(self.carryInfoSet.block_op_count[block_no])])]
    557     def GenerateCarryWhileTest(self, block_no, testExpr):
    558         carry_count = self.carryInfoSet.block_op_count[block_no]
    559         if carry_count == 0: return testExpr
    560         carry0 = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
    561         return ast.BoolOp(ast.Or(), [testExpr, mkCall(self.CarryGroupAtt('CarryTest'), [ast.Num(carry0), ast.Num(carry_count)])])
    562     def EnterLocalWhileBlock(self, operation_offset): 
    563         self.carryGroupVar = "sub" + self.carryGroupVar
    564         self.operation_offset = operation_offset
    565     def ExitLocalWhileBlock(self): 
    566         self.operation_offset = 0
    567         self.carryGroupVar = self.carryGroupVar[3:]
    568     def GenerateCarryWhileFinalization(self, block_no):
    569         carry_count = self.carryInfoSet.block_op_count[block_no]
    570         if carry_count == 0: return []
    571         loopIndex = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
    572         return [mkCallStmt(self.CarryGroupAtt('CarryCombine'), [self.CarryGroupAtt('cq', "sub" + self.carryGroupVar), ast.Num(loopIndex), ast.Num(carry_count)])]
    573     def GenerateStreamFunctionFinalization(self):
    574         carry_count = self.carryInfoSet.countBlockCarrysWithAdv1(0)
    575         if carry_count == 0: return []
    576         else: return [mkCallStmt(self.CarryGroupAtt('CarryQ_Adjust'), [ast.Num(carry_count)])]
    577 
    578322
    579323def Strategic_CCGO_Factory(carryInfoSet):
    580     ccgo = testCCGO(carryInfoSet, 'carryQ')
     324    ccgo = CCGO.testCCGO(carryInfoSet, 'carryQ')
    581325    return ccgo
    582326
     
    858602    self.generic_visit(whileNode)
    859603    local_carry_decl = self.ccgo.GenerateLocalDeclare(this_block)
     604    #local_carry_decl = []
    860605    #local_carry_decl = mkCallStmt('LocalCarryDeclare', [local_carryvar, ast.Num(carries)])
    861606    inner_while.body = local_carry_decl + inner_while.body
     
    12671012                stream_function.parameters = FunctionVars(node).params
    12681013                stream_function.declarations = BitBlock_decls_of_fn(node)
    1269                 stream_function.declarations += stream_function.ccgo.GenerateStreamFunctionDecls()
     1014                stream_function.declarations += "\n" + stream_function.ccgo.GenerateStreamFunctionDecls()
    12701015                stream_function.initializations = StreamInitializations().xfrm(node)
    12711016               
     
    13411086  def gen_declarations(self): 
    13421087    self.Cdecls = StreamStructGen().gen_struct_vars(self.main_module)
    1343     self.Cdecls += BitBlock_decls_of_fn(self.main_node)
     1088    self.Cdecls += BitBlock_decls_of_fn(self.main_node) + "\n" + self.main_ccgo.GenerateStreamFunctionDecls()
    13441089    if self.main_carry_count > 0:
    13451090        self.Cdecls += self.emitter.carry_declare('carryQ', self.main_carry_count)
     
    13671112    final_block_main = copy.deepcopy(self.main_node)
    13681113    carry_info_set = CarryInfoSetVisitor(self.main_node)
    1369     ccgo = Strategic_CCGO_Factory(carry_info_set)
    1370     CarryIntroVisitor = CarryIntro(ccgo)
    1371     CarryIntroVisitor.xfrm_fndef(self.main_node)
    1372     CarryIntroVisitor.xfrm_fndef_final(final_block_main)
     1114    #ccgo = Strategic_CCGO_Factory(carry_info_set)
     1115    #CarryIntroVisitor = CarryIntro(ccgo)
     1116    #CarryIntroVisitor.xfrm_fndef(self.main_node)
     1117    #CarryIntroVisitor.xfrm_fndef_final(final_block_main)
    13731118    AssertCompiler().xfrm(self.main_node)
    13741119    if self.add_dump_stmts:
     
    13861131    #if self.main_carry_count > 0:
    13871132                #self.main_node.body += [mkCallStmt('CarryQ_Adjust', [ast.Name('carryQ', ast.Load()), ast.Num(self.main_carry_count)])]
    1388     self.main_node.body += ccgo.GenerateStreamFunctionFinalization()
     1133    #self.main_node.body += ccgo.GenerateStreamFunctionFinalization()
    13891134   
    13901135   
Note: See TracChangeset for help on using the changeset viewer.