source: proto/Compiler/CCGO_HMCPS.py @ 2790

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

Initial Advance_n support with HMCPS

File size: 21.5 KB
RevLine 
[2700]1#
2# CCGO_HMCPS.py
3#
4# Carry Code Generator Object using Hierarchical Merging Carry Pack Strategy
5#
6# Robert D. Cameron
7# November 26, 2012
8# Licensed under Open Software License 3.0
9#
10import ast
11import CCGO
12
13# Copyright 2012, Robert D. Cameron
14# All rights reserved.
15#
16# Helper functions
17#
18def TestHelper_Bitblock_Or(testExpr, bitBlockExpr):
[2786]19    if isinstance(testExpr, ast.Call):
20      assert isinstance(testExpr.func, ast.Name)
21      assert testExpr.func.id == 'bitblock::any'
22      testExpr.args[0] = make_call('simd_or', [bitBlockExpr, testExpr.args[0]])
23      return testExpr
24    else:
25      return ast.BinOp(testExpr, ast.BitOr(), make_call('bitblock::any', [bitBlockExpr]))
[2700]26
27def TestHelper_Integer_Or(testExpr, intExpr):
28    return ast.BinOp(testExpr, ast.BitOr(), intExpr)
29
30def mk_var(var, mode=ast.Load()):
31  if isinstance(var, str): 
32        var = ast.Name(var, mode)
33  return var
34 
35def make_assign(var, expr):
[2707]36   if isinstance(var, str): 
[2700]37        var = ast.Name(var, ast.Store())
[2707]38   return ast.Assign([var], expr)
[2700]39
[2707]40def make_index(var, num, mode=ast.Load()):
[2700]41  if isinstance(var, str): 
42        var = ast.Name(var, ast.Load())
[2707]43  return ast.Subscript(var, ast.Index(ast.Num(num)), mode)
[2700]44
45def make_index_store(var, num):
46  if isinstance(var, str): 
47        var = ast.Name(var, ast.Load())
48  return ast.Subscript(var, ast.Index(ast.Num(num)), ast.Store())
49
[2707]50def make_att(var, att, mode=ast.Load()):
[2700]51  if isinstance(var, str): 
52        var = ast.Name(var, ast.Load())
[2707]53  return ast.Attribute(var, att, mode)
[2700]54
55def make_att_store(var, att):
56  if isinstance(var, str): 
57        var = ast.Name(var, ast.Load())
58  return ast.Attribute(var, att, ast.Store())
59
60def make_call(fn_name, args):
61  if isinstance(fn_name, str): 
62        fn_name = ast.Name(fn_name, ast.Load())
63  return ast.Call(fn_name, args, [], None, None)
64
65def make_callStmt(fn_name, args):
66  if isinstance(fn_name, str): fn_name = ast.Name(fn_name, ast.Load())
67  return ast.Expr(ast.Call(fn_name, args, [], None, None))
[2707]68
69def make_mergeh(fw, x, y):
70  return make_call("esimd<%i>::mergeh" % fw, [mk_var(x), mk_var(y)])
71
72def make_zero(fw):
73  return make_call("simd<%i>::constant<0>" % fw, [])
74
[2700]75 
76#
77#
78# Carry Pack Assignment Strategy
79#
80# The hierarchical merging carry pack strategy packs carries
81# into groups of 2, 4, 8 and 16.   For example, to pack
82# 4 carries c0, c1, c2, and c3 into the 32-bit fields of
83# a 128-bit register, the following operations are used.
84#
85# c0 = pablo.SomeCarryGeneratingFn(...)
86# c1 = pablo.SomeCarryGeneratingFn(...)
87# c1_0 = esimd::mergeh<32>(c1, c0)
88# c2 = pablo.SomeCarryGeneratingFn(...)
89# c3 = pablo.SomeCarryGeneratingFn(...)
90# c3_2 = esimd::mergeh<32>(c3, c2)
91# c3_0 = esimd::mergeh<64>(c3_2, c1_0)
92#
93#
94# Packing operations are generated sequentially when
95# the appropriate individual carries or subpacks become
96# available.   
97#
98# Generate the packing operations assuming that the
99# carry_num carry has just been generated.
100#
101
102def pow2ceil(n):
103   c = 1
104   while c < n: c *= 2 
105   return c
106
107def pow2floor(n):
108   c = 1
109   while c <= n: c *= 2 
110   return c/2
[2703]111
112def low_bit(n):
113   return n - (n & (n-1))
[2700]114   
115def align(n, align_base):
116  return ((n + align_base - 1) / align_base) * align_base
117
118def determine_aligned_block_sizes(pack_size, cis):
119  aligned_size = {}
120  for i in range(cis.block_count): aligned_size[i] = 0
121  seen = []
122  for i in range(cis.block_count):
123    # Work backwards to process all child blocks before the parent
124    # so that the parent incorporates the updated child counts.
125    b = cis.block_count - i - 1
126    b_carries = 0
127    op = cis.block_first_op[b]
128    while op < cis.block_first_op[b] + cis.block_op_count[b]:
129      sb = cis.containing_block[op]
130      if sb == b:
131        if op not in cis.advance_amount.keys(): b_carries += 1
132        elif cis.advance_amount[op] == 1: b_carries += 1
133        op += 1
134      else: 
135        align_base = aligned_size[sb]
136        if align_base > pack_size: align_base = pack_size
137        b_carries = align(b_carries, align_base)
138        b_carries += aligned_size[sb]
139        op += cis.block_op_count[sb]
[2707]140    # Force whiles to use full blocks; this possibly can be relaxed.
[2705]141    if cis.whileblock[b] or b_carries > pack_size:
[2700]142      aligned_size[b] = align(b_carries, pack_size)
143    else:
144      aligned_size[b] = pow2ceil(b_carries)
145  return aligned_size
146 
147MAX_LINE_LENGTH = 80
148
149def BitBlock_decls_from_vars(varlist):
150  global MAX_LINE_LENGTH
151  decls =  ""
152  if not len(varlist) == 0:
153          decls = "             BitBlock"
154          pending = ""
155          linelgth = 10
156          for v in varlist:
157            if linelgth + len(v) + 2 <= MAX_LINE_LENGTH:
158              decls += pending + " " + v
159              linelgth += len(pending + v) + 1
160            else:
161              decls += ";\n             BitBlock " + v
162              linelgth = 11 + len(v)
163            pending = ","
164          decls += ";"
165  return decls
166 
[2701]167def block_contains(b0, b1, parent_block_map):
168  if b0 == b1: return True
169  elif b1 == 0: return False
170  else: return block_contains(b0, parent_block_map[b1], parent_block_map)
171 
[2700]172class HMCPS_CCGO(CCGO.CCGO):
173    def __init__(self, fw, carryInfoSet, carryGroupVarName='carryG', temp_prefix='__c'):
174        self.fw = fw
175        self.field_count = 128/fw
176        self.carryInfoSet = carryInfoSet
177        self.carryGroupVar = carryGroupVarName
178        self.temp_prefix = temp_prefix
179        self.aligned_size = determine_aligned_block_sizes(self.field_count, carryInfoSet)
[2790]180        carry_bitblocks = (self.aligned_size[0] + self.field_count - 1) / self.field_count
181        self.ubitblock_count = carry_bitblocks + carryInfoSet.adv_n_count
[2700]182        self.alloc_map = {}
183        self.alloc_map[0] = 0
[2790]184        self.adv_n_map = {}
[2700]185        self.block_base = {}
186        self.allocate_ops()
[2701]187        # carry_offset is used within the inner body of while loops to access local carries.
188        # The calculated (ub, rp) value is reduced by this amount for the local carry group(s).
189        self.carry_offset = 0
[2707]190#
191# Carry Storage/Access
192#
193# Carries are stored in one or more ubitblocks as byte values.
194# For each block, the carry count is rounded up to the nearest power of 2 ceiling P,
195# so that the carry test for that block is accessible as a single value of P bytes.
196# Packs of 1, 2, 4 or 8 carries are respectively represented
197# as one or more _8, _16, _32 or _64 values.  (Members of ubitblock union.)
198#
199#
200# Allocation phase determines the ubitblock_no and count for each block.
201
202#  carry-in access is a byte load  carryG[packno]._8[offset]
203#  carryout store is to a local pack var until we get to the final byte of a pack
204#
205#  if-test: let P be pack_size in {1,2,4,8,...}
206#    if P <= 8, use an integer test expression cG[packno]._%i % (P * 8)[block_offset]
207#     
208#  while test similar
209#    local while decl: use a copy of carryGroup
210#    while finalize  carry combine:   round up and |= into structure
211#
[2787]212    def carry_pack_full(self, ub, v = None, mode = ast.Load()):
213       if v == None: v = self.carryGroupVar
214       return make_att(make_index(v, ub), '_128', mode)
[2707]215
216    def carry_pack_index(self, fw, ub, rp, mode = ast.Load()):
217       return make_index(make_att(make_index(self.carryGroupVar, ub), '_%i' % fw), rp, mode)
218
219    def local_pack_full(self, ub, mode = ast.Load()):
[2787]220       return self.carry_pack_full(ub, "sub" + self.carryGroupVar, mode)
[2707]221
222
223
[2703]224    def cg_temp(self, hi_carry, lo_carry = None):
225      if lo_carry == None or hi_carry == lo_carry: return "%s%i" % (self.temp_prefix, hi_carry)
226      else: return "%s%i_%i" % (self.temp_prefix, hi_carry, lo_carry)
227   
228    def local_temp(self, hi_carry, lo_carry = None):
229      if lo_carry == None or hi_carry == lo_carry: return "sub%s%i" % (self.temp_prefix, hi_carry)
[2705]230      else: return "sub%s%i_%i" % (self.temp_prefix, hi_carry, lo_carry)
[2703]231   
232    def gen_merges(self, carry_last, carry_base):
233      size = carry_last - carry_base + 1
234      if carry_last & size: 
235        v1 = mk_var(self.cg_temp(carry_last, carry_base))
236        v0 = mk_var(self.cg_temp(carry_last - size, carry_base - size))
237        v2 = mk_var(self.cg_temp(carry_last, carry_base - size), ast.Store())
238        return [make_assign(v2, make_mergeh(self.fw * size, v1, v0))] + self.gen_merges(carry_last, carry_base - size)
239      else: return []
240
241    #
242    #  Given that carry_num carries have been generated and packed,
243    #  add zero_count additional carry zero values and pack.
244    #  Use shifts to introduce multiple zeroes, where possible.
245    #
246    def gen_multiple_carry_zero_then_pack(self, carry_num, zero_count):
247      if zero_count == 0: return []
248      pending_carry_pack_size = low_bit(carry_num)
249      pending_carry_base = carry_num - pending_carry_pack_size
250      # We may be able to fill zeroes by shifting.
251      # But the shift is limited by any further pending carry pack and
252      # the constraint that the result must produce a well-formed pack
253      # having a power-of-2 entries.
254      #
255      final_num = carry_num + zero_count
256      pack_size2 = low_bit(pending_carry_base)
257      if pending_carry_base == 0:
258        shift = pow2floor(final_num) - pending_carry_pack_size
259      else:
260        shift = min(low_bit(pending_carry_base), low_bit(final_num)) - pending_carry_pack_size
261      if pending_carry_pack_size == 0 or shift == 0:
262        # There is either no pending pack or we are not generating enough
263        # carry zeroes to combine into the pending pack, so we can only add new
264        # packs.
265        #
266        if zero_count == 1:  return [make_assign(self.cg_temp(carry_num), make_zero(self.fw))]
267        else: 
268          zero_count_floor = pow2floor(zero_count)
269          hi_num = carry_num + zero_count_floor
270          a1 = make_assign(self.cg_temp(hi_num - 1, carry_num), make_zero(self.fw))
271          remaining_zeroes = zero_count - zero_count_floor
272          return [a1] + self.gen_multiple_carry_zero_then_pack(hi_num, remaining_zeroes) 
273      #
274      shift_result = self.cg_temp(carry_num + shift - 1, pending_carry_base)
275      pending = self.cg_temp(carry_num - 1, pending_carry_base)
276      #print shift_result, " by shift ", pending, shift
[2707]277      a1 = make_assign(shift_result, make_call('bitblock::srli<%i>' % (self.fw * shift), [mk_var(pending)]))
[2703]278      # Do any necessary merges
279      m = self.gen_merges(carry_num + shift - 1,  pending_carry_base)
280      return [a1] + m + self.gen_multiple_carry_zero_then_pack(carry_num + shift, zero_count - shift)
281
282
[2700]283    def allocate_ops(self):
284      carry_count = 0
[2790]285      adv_n_count = 0
[2700]286      for op in range(self.carryInfoSet.operation_count):
[2701]287        b = self.carryInfoSet.containing_block[op]
288        if op != 0: 
289          # If we've just left a block, ensure that we are aligned.
290          b_last = self.carryInfoSet.containing_block[op-1]
291          if not block_contains(b_last, b, self.carryInfoSet.parent_block):
292            # find the max-sized block just exited.
293            while not block_contains(self.carryInfoSet.parent_block[b_last], b, self.carryInfoSet.parent_block):
294              b_last = self.carryInfoSet.parent_block[b_last]
295            align_base = self.aligned_size[b_last]
[2700]296            if align_base > self.field_count: align_base = self.field_count
[2701]297            carry_count = align(carry_count, align_base)         
298        if self.carryInfoSet.block_first_op[b] == op:
299          # If we're just entering a block, ensure that we are aligned.
300          align_base = self.aligned_size[b]
301          if align_base > self.field_count: align_base = self.field_count
302          carry_count = align(carry_count, align_base)
[2700]303        if op not in self.carryInfoSet.advance_amount.keys():
304          self.alloc_map[op] = carry_count
305          carry_count += 1
306        elif self.carryInfoSet.advance_amount[op] == 1: 
307          self.alloc_map[op] = carry_count
308          carry_count += 1
[2790]309        else:
310          # Advance_n op, carry_count does not change.
311          self.alloc_map[op] = carry_count
312          self.adv_n_map[op] = adv_n_count
313          adv_n_count += 1
[2701]314      # When processing the last operation, make sure that the "next" operation
315      # appears to start a new pack.
316      self.alloc_map[self.carryInfoSet.operation_count] = align(carry_count, self.field_count)
[2718]317      for b in range(self.carryInfoSet.block_count): 
318         self.block_base[b] = self.alloc_map[self.carryInfoSet.block_first_op[b]]
[2700]319     
320    def GenerateCarryDecls(self):
321        return "  ubitblock %s [%i];\n" % (self.carryGroupVar, self.ubitblock_count)
322    def GenerateInitializations(self):
323        v = self.carryGroupVar       
324        inits = ""
325        for i in range(0, self.ubitblock_count):
326          inits += "%s[%i]._128 = simd<%i>::constant<0>();\n" % (v, i, self.fw)
327        for op_no in range(self.carryInfoSet.block_op_count[0]):
328          if op_no in self.carryInfoSet.init_one_list: 
329            posn = self.alloc_map[op_no]
330            ub = posn/self.field_count
331            rp = posn%self.field_count
332            inits += "%s[%i]._%i[%i] = 1;\n" % (self.carryGroupVar, ub, self.fw, rp)
333        return inits
334    def GenerateStreamFunctionDecls(self):
335        f = self.field_count
[2703]336        s = 1
337        decls = []
338        while f > 0:
339          decls += [self.cg_temp(s*(i+1)-1, s*i) for i in range(f)]
[2700]340          f = f/2
[2703]341          s = s * 2
[2700]342        return BitBlock_decls_from_vars(decls)
343
344    def GenerateCarryInAccess(self, operation_no):
345        block_no = self.carryInfoSet.containing_block[operation_no]
[2701]346        posn = self.alloc_map[operation_no] - self.carry_offset
[2700]347        ub = posn/self.field_count
348        rp = posn%self.field_count
[2707]349        return make_call("convert", [self.carry_pack_index(self.fw, ub, rp)])
[2700]350    def GenerateCarryOutStore(self, operation_no, carry_out_expr):
351        block_no = self.carryInfoSet.containing_block[operation_no]
[2701]352        posn = self.alloc_map[operation_no] - self.carry_offset
[2700]353        ub = posn/self.field_count
354        rp = posn%self.field_count
355        # Only generate an actual store for the last carryout
356        assigs = [make_assign(self.temp_prefix + repr(rp), carry_out_expr)] 
[2703]357        assigs += self.gen_merges(rp, rp)
[2701]358        next_posn = self.alloc_map[operation_no + 1] - self.carry_offset
359        skip = next_posn - posn - 1
[2700]360        if skip > 0: 
[2703]361          assigs += self.gen_multiple_carry_zero_then_pack(rp+1, skip)
[2701]362        #print (posn, skip)
363        if next_posn % self.field_count == 0:
[2700]364          shift_op = "simd<%i>::srli<%i>" % (self.fw, self.fw-1)
[2705]365          storable_carry_in_form = make_call(shift_op, [mk_var(self.cg_temp(self.field_count - 1, 0))])
[2787]366          assigs.append(make_assign(self.carry_pack_full(ub, mode = ast.Store()), storable_carry_in_form))
[2700]367        return assigs
[2790]368    def GenerateAdvanceInAccess(self, operation_no):
369        return self.carry_pack_full(self.ubitblock_count + self.adv_n_map[operation_no])
370    def GenerateAdvanceOutStore(self, operation_no, adv_out_expr):
371        return [ast.Assign([self.carry_pack_full(self.ubitblock_count + self.adv_n_map[operation_no], mode=ast.Store())], 
372                           make_call("bitblock::srli<64>", [adv_out_expr]))]
[2786]373    def GenerateTestAll(self, instance_name):
374        if self.ubitblock_count == 0: return ast.Num(0)
375        else:
[2787]376            v = make_att(instance_name, self.carryGroupVar)
377            t = self.carry_pack_full(0, v)
[2786]378            for i in range(1, self.ubitblock_count): 
[2787]379              t2 = self.carry_pack_full(i, v)
[2786]380              t = make_call('simd_or', [t, t2])
381            return make_call('bitblock::any', [t])
[2700]382    def GenerateTest(self, block_no, testExpr):
[2701]383        posn = self.block_base[block_no] - self.carry_offset
[2700]384        ub = posn/self.field_count
385        rp = posn%self.field_count
386        count = self.aligned_size[block_no] 
387        width = count * self.fw
[2708]388        if count < self.field_count:
[2707]389            t = self.carry_pack_index(width, ub, rp/count)
[2700]390            return TestHelper_Integer_Or(testExpr, t)
391        else:
[2707]392            t = self.carry_pack_full(ub)
[2700]393            for i in range(1, count/self.field_count): 
[2707]394              v2 = self.carry_pack_full(ub + i)
[2700]395              t = make_call('simd_or', [t, v2])
396            return TestHelper_Bitblock_Or(testExpr, t)
397    def GenerateCarryIfTest(self, block_no, ifTest):
398        return self.GenerateTest(block_no, ifTest)
399
400    def GenerateCarryElseFinalization(self, block_no):
401        # if the block consists of full carry packs, then
402        # no action need be taken: the corresponding carry-in packs
403        # must already be zero, or the then branch would have been taken.
404        count = self.aligned_size[block_no]
405        if count % self.field_count == 0: return []
[2701]406        # The block has half a carry-pack or less.
[2700]407        assigs = []
[2701]408        posn = self.block_base[block_no] - self.carry_offset
409        ub = posn / self.field_count
410        rp = posn % self.field_count
411        next_op = self.carryInfoSet.block_first_op[block_no] + self.carryInfoSet.block_op_count[block_no]
[2703]412        end_pos = (self.alloc_map[next_op]  - self.carry_offset - 1) % self.field_count
413        #print rp, next_op,self.alloc_map[next_op]
414        #assigs = [make_assign(self.cg_temp(end_pos, rp), make_zero(self.fw))]
415        assigs = self.gen_multiple_carry_zero_then_pack(rp, end_pos - rp + 1)
416        if (end_pos + 1) % self.field_count == 0:
417          shift_op = "simd<%i>::srli<%i>" % (self.fw, self.fw-1)
[2705]418          storable_carry_in_form = make_call(shift_op, [mk_var(self.cg_temp(self.field_count - 1, 0))])
[2787]419          assigs.append(make_assign(self.carry_pack_full(ub, mode = ast.Store()), storable_carry_in_form))
[2700]420        return assigs
421
422    def GenerateLocalDeclare(self, block_no):
423        if self.carryInfoSet.block_op_count[block_no] == 0: return []
[2701]424        count = self.aligned_size[block_no] 
425        if count >= self.field_count:
426          ub_count = count / self.field_count
427          decls = [make_callStmt('ubitblock_declare', [mk_var('sub' + self.carryGroupVar), ast.Num(ub_count)])]
428          count = self.field_count
429        else: decls = []
430        # Generate carry pack temps.
[2703]431        f = count
432        s = 1
433        temps = []
434        while f > 0:
435          temps += [self.local_temp(s*(i+1)-1, s*i) for i in range(f)]
[2700]436          f = f/2
[2703]437          s = s * 2
[2700]438        #return BitBlock_decls_from_vars(decls)
439        return decls + [make_callStmt('BitBlock_declare', [mk_var(t)]) for t in temps]
440   
441    def GenerateCarryWhileTest(self, block_no, testExpr):
442        return self.GenerateTest(block_no, testExpr)
443
444    def EnterLocalWhileBlock(self, operation_offset): 
445        self.carryGroupVar = "sub" + self.carryGroupVar
[2701]446        self.temp_prefix = "sub" + self.temp_prefix
447        self.carry_offset = self.alloc_map[operation_offset]
[2703]448        #print "self.carry_offset = %i" % self.carry_offset
[2700]449    def ExitLocalWhileBlock(self): 
450        self.carryGroupVar = self.carryGroupVar[3:]
[2701]451        self.temp_prefix = self.temp_prefix[3:]
452        self.carry_offset = 0
[2700]453       
454    def GenerateCarryWhileFinalization(self, block_no):
[2701]455        posn = self.block_base[block_no]
[2700]456        ub = posn/self.field_count
[2701]457        rp = posn%self.field_count
[2700]458        count = self.aligned_size[block_no] 
[2701]459        if count < self.field_count:
[2703]460          v0 = self.cg_temp(rp + count - 1, rp)
461          lv0 = self.local_temp(count - 1, 0)
[2701]462          return [make_assign(v0, make_call('simd_or', [mk_var(v0), mk_var(lv0)]))]
[2700]463        n = (count+self.field_count-1)/self.field_count
464        assigs = []
465        for i in range(n):
[2787]466          assigs.append(make_assign(self.carry_pack_full(ub + i, mode = ast.Store()), make_call('simd_or', [self.carry_pack_full(ub + i), self.local_pack_full(i)])))
[2700]467        return assigs
468    def GenerateStreamFunctionFinalization(self):
[2701]469        return []
[2700]470
[2708]471#
472#  A version of HMCPS_CCGO eliminating ubitblocks
473#
474class HMCPS_CCGO2(HMCPS_CCGO):
475
[2787]476    def carry_pack_full(self, ub, v = None, mode = ast.Load()):
477       if v == None: v = self.carryGroupVar
478       return make_index(v, ub, mode)
[2708]479
480    def carry_pack_index(self, fw, ub, rp, mode = ast.Load()):
481       return make_call("mvmd<%i>::extract<%i>" % (fw, rp), [self.carry_pack_full(ub)])
482
483    def GenerateCarryDecls(self):
484        return "  BitBlock simd_const_1\n;    BitBlock %s [%i];\n" % (self.carryGroupVar, self.ubitblock_count)
485
486    def GenerateInitializations(self):
487        v = self.carryGroupVar       
488        inits = "simd_const_1 = mvmd<16>::srli<7>(simd<16>::constant<1>());\n"
489        for i in range(0, self.ubitblock_count):
490          inits += "%s[%i] = simd<%i>::constant<0>();\n" % (v, i, self.fw)
491        for op_no in range(self.carryInfoSet.block_op_count[0]):
492          if op_no in self.carryInfoSet.init_one_list: 
493            posn = self.alloc_map[op_no]
494            ub = posn/self.field_count
495            rp = posn%self.field_count
496            v = "%s[%i]" % (self.carryGroupVar, ub)
497            inits += "%s = simd_or(%s, mvmd<%i>::slli<%i>(simd_const_1)) ;\n" % (v, v, self.fw, rp)
498        return inits
499
500    def GenerateCarryInAccess(self, operation_no):
501        block_no = self.carryInfoSet.containing_block[operation_no]
502        posn = self.alloc_map[operation_no] - self.carry_offset
503        ub = posn/self.field_count
504        rp = posn%self.field_count
505        #return make_call("convert", [self.carry_pack_index(self.fw, ub, rp)])
[2709]506        if rp == 0: e = self.carry_pack_full(ub)
507        else: e = make_call("mvmd<%i>::srli<%i>" %(self.fw, rp), [self.carry_pack_full(ub)])
508        if rp == self.field_count - 1:
509          return e
510        else: return make_call('simd_and', [e, mk_var("simd_const_1")])
[2708]511
512    def GenerateLocalDeclare(self, block_no):
513        if self.carryInfoSet.block_op_count[block_no] == 0: return []
514        count = self.aligned_size[block_no] 
515        if count >= self.field_count:
516          ub_count = count / self.field_count
517          decls = [make_callStmt('BitBlock_declare', [self.local_pack_full(ub_count)])]
518          decls += [make_assign(self.local_pack_full(i, ast.Store()), make_zero(self.fw)) for i in range(ub_count)]
519          count = self.field_count
520        else: decls = []
521        # Generate carry pack temps.
522        f = count
523        s = 1
524        temps = []
525        while f > 0:
526          temps += [self.local_temp(s*(i+1)-1, s*i) for i in range(f)]
527          f = f/2
528          s = s * 2
529        #return BitBlock_decls_from_vars(decls)
530        return decls + [make_callStmt('BitBlock_declare', [mk_var(t)]) for t in temps]
531   
532
Note: See TracBrowser for help on using the repository browser.