source: proto/Compiler/CCGO.py @ 4619

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

Use carryout2carry abstraction for legacy CCGO

File size: 8.2 KB
Line 
1#
2# CCGO.py
3#
4# Copyright 2012, Robert D. Cameron
5# All rights reserved.
6#
7# Carry Code Generator Objects (CCGOs)
8#
9# CCGOs are objects which implement a particular strategy for incorporating
10# carry processing into generated Pablo code.
11#
12# A CCGO consists of methods that can be used to insert carry processing
13# code at particular locations in a Pablo program.   The CCGO is intended
14# to be a parameter to a CarryIntro tree transformer, abstracting away
15# the strategy from the tree traversal to apply the strategy to
16# a particular stream function.
17#
18import ast, mkast
19#
20# The base CCGO Class is also the null class, suitable for stream
21# functions that have no carry-generating operations.
22#
23class CCGO:
24    def __init__(self): pass
25    def allocate_all(self): pass
26    def GenerateCarryDecls(self): return ""
27    def GenerateInitializations(self): return ""
28    def GenerateStreamFunctionDecls(self):  return ""
29    def GenerateCarryInAccess(self, operation_no): return None
30    def GenerateCarryOutStore(self, operation_no, carry_out_expr): return []
31    def GenerateAdvanceInAccess(self, operation_no): return None
32    def GenerateAdvanceOutStore(self, operation_no, carry_out_expr): return []
33    def GenerateTestAll(self, instance_name): return ast.Num(0)
34    def GenerateCarryIfTest(self, block_no, ifTest): return ifTest
35    def GenerateCarryThenFinalization(self, block_no): return []
36    def GenerateCarryElseFinalization(self, block_no): return []
37    def GenerateLocalDeclare(self, block_no): return []
38    def GenerateCarryWhileTest(self, block_no, testExpr): return testExpr
39    def EnterLocalWhileBlock(self, operation_offset):  pass
40    def ExitLocalWhileBlock(self):  pass
41    def GenerateCarryWhileFinalization(self, block_no): return []
42    def GenerateStreamFunctionFinalization(self): return []
43
44
45#
46#  The testCCGO is a legacy class designed to duplicate the previous Pablo
47#  functionality of introducing a set of abstract macros into generated
48#  code (CarryArray, CarryTest, CarryDequeueEnqueue, CarryAdjust, etc.)
49#
50class testCCGO(CCGO):
51    def __init__(self, BLOCK_SIZE, carryInfoSet, carryGroupVarName='carryQ'):
52        self.BLOCK_SIZE = BLOCK_SIZE
53        self.carryInfoSet = carryInfoSet
54        self.carryGroupVar = carryGroupVarName
55
56    def allocate_all(self):
57        self.carryIndex = {}
58        self.advIndex = {}
59        self.operation_offset = 0
60        self.offset_stack = []
61        carry_counter = 0
62        adv_counter = 0
63        for op_no in range(self.carryInfoSet.operation_count):
64          self.carryIndex[op_no] = carry_counter
65          if not op_no in self.carryInfoSet.advance_amount.keys(): carry_counter += 1
66          elif self.carryInfoSet.advance_amount[op_no] == 1: carry_counter += 1
67          else: 
68            self.advIndex[op_no] = adv_counter
69            adv_counter += 1
70        # Add a dummy entry for any possible final block that is empty.
71        self.carryIndex[self.carryInfoSet.operation_count] = carry_counter
72        self.advIndex[self.carryInfoSet.operation_count] = adv_counter
73        self.carry_count = carry_counter
74
75    # Helper
76    def CarryGroupAtt(self, attname, CarryGroupVarName=""):
77        if CarryGroupVarName == '': CarryGroupVarName = self.carryGroupVar
78        return ast.Attribute(ast.Name(CarryGroupVarName, ast.Load()), attname, ast.Load())
79    def GenerateCarryDecls(self):
80        carry_counter = 0
81        adv_n_counter = 0
82        for op_no in range(self.carryInfoSet.block_op_count[0]):
83          if not op_no in self.carryInfoSet.advance_amount.keys(): carry_counter += 1
84          elif self.carryInfoSet.advance_amount[op_no] == 1: carry_counter += 1
85          else: adv_n_counter += 1
86        return "CarryArray<%i, %i> %s;" % (carry_counter, adv_n_counter, self.carryGroupVar)
87    def GenerateInitializations(self):
88        carry_counter = 0
89        adv_n_counter = 0
90        inits = ""
91        for op_no in range(self.carryInfoSet.block_op_count[0]):
92          if op_no in self.carryInfoSet.init_one_list: inits += "carryQ.cq[%s] = carryQ.carry_flip(carryQ.cq[%s]);\n" % (carry_counter, carry_counter)
93          if not op_no in self.carryInfoSet.advance_amount.keys(): carry_counter += 1
94          elif self.carryInfoSet.advance_amount[op_no] == 1: carry_counter += 1
95          else: adv_n_counter += 1
96        return inits
97    def GenerateStreamFunctionDecls(self):  return ""
98    def GenerateCarryInAccess(self, operation_no):
99        carry_index = self.carryIndex[operation_no - self.operation_offset]
100        return mkast.call(self.carryGroupVar + "." + 'get_carry_in', [ast.Num(carry_index)])
101    def GenerateCarryOutStore(self, operation_no, carry_out_expr):
102        carry_index = self.carryIndex[operation_no - self.operation_offset]
103        return [ast.Assign([ast.Subscript(self.CarryGroupAtt('cq'), ast.Index(ast.Num(carry_index)), ast.Store())], 
104                          mkast.call("carryout2carry", [carry_out_expr]))]
105    def GenerateAdvanceInAccess(self, operation_no):
106        adv_index = self.advIndex[operation_no - self.operation_offset]
107        return mkast.call(self.carryGroupVar + "." + 'get_pending64', [ast.Num(adv_index)])
108    def GenerateAdvanceOutStore(self, operation_no, adv_out_expr):
109        adv_index = self.advIndex[operation_no - self.operation_offset]
110        cq_index = adv_index + self.carry_count
111        return [ast.Assign([ast.Subscript(self.CarryGroupAtt('cq'), ast.Index(ast.Num(cq_index)), ast.Store())], 
112                           mkast.call("bitblock::srli<64>", [adv_out_expr]))]
113
114    def GenerateTestAll(self, instance_name):
115        carry_count = self.carryInfoSet.block_op_count[0]
116        if carry_count == 0: return ast.Num(0)
117        else: 
118           #return "%s.carryQ.CarryTest(0, %i)" % (instance_name, carry_count)
119           return mkast.call(ast.Attribute(ast.Attribute(ast.Name(instance_name, ast.Load()), self.carryGroupVar, ast.Load()), 'CarryTest', ast.Load()), 
120                         [ast.Num(0), ast.Num(carry_count)])
121    def GenerateCarryIfTest(self, block_no, ifTest):
122        carry_count = self.carryInfoSet.block_op_count[block_no]
123        if carry_count == 0: return ifTest
124        ifIndex = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
125        return ast.BoolOp(ast.Or(), [ifTest, mkast.call(self.CarryGroupAtt('CarryTest'), [ast.Num(ifIndex), ast.Num(carry_count)])])
126    def GenerateCarryElseFinalization(self, block_no): 
127        carry_count = self.carryInfoSet.block_op_count[block_no]
128        if carry_count == 0: return []
129        ifIndex = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
130        return [mkast.callStmt(self.CarryGroupAtt('CarryDequeueEnqueue'), [ast.Num(ifIndex), ast.Num(carry_count)])]
131    def GenerateLocalDeclare(self, block_no):
132        local_carryvar = ast.Name("sub" + self.carryGroupVar, ast.Load())
133        return [mkast.callStmt('LocalCarryDeclare', [local_carryvar, ast.Num(self.carryInfoSet.block_op_count[block_no])])]
134    def GenerateCarryWhileTest(self, block_no, testExpr):
135        carry_count = self.carryInfoSet.block_op_count[block_no]
136        if carry_count == 0: return testExpr
137        carry0 = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
138        return ast.BoolOp(ast.Or(), [testExpr, mkast.call(self.CarryGroupAtt('CarryTest'), [ast.Num(carry0), ast.Num(carry_count)])])
139    def EnterLocalWhileBlock(self, operation_offset): 
140        self.carryGroupVar = "sub" + self.carryGroupVar
141        self.offset_stack = [self.operation_offset] + self.offset_stack
142        self.operation_offset = operation_offset
143    def ExitLocalWhileBlock(self): 
144        self.operation_offset = self.offset_stack[0]
145        self.offset_stack = self.offset_stack[1:]
146        self.carryGroupVar = self.carryGroupVar[3:]
147    def GenerateCarryWhileFinalization(self, block_no): 
148        carry_count = self.carryInfoSet.block_op_count[block_no]
149        if carry_count == 0: return []
150        loopIndex = self.carryIndex[self.carryInfoSet.block_first_op[block_no]]       
151        return [mkast.callStmt(self.CarryGroupAtt('CarryCombine'), [self.CarryGroupAtt('cq', "sub" + self.carryGroupVar), ast.Num(loopIndex), ast.Num(carry_count)])]
152    def GenerateStreamFunctionFinalization(self):
153        carry_count = self.carryInfoSet.carry_count + self.carryInfoSet.adv_1_count
154        if carry_count == 0: return []
155        else: return [mkast.callStmt(self.CarryGroupAtt('CarryQ_Adjust'), [ast.Num(carry_count)])]
156
Note: See TracBrowser for help on using the repository browser.