1# * Copyright 2016, NICTA 2# * 3# * This software may be distributed and modified according to the terms 4# of 5# * the BSD 2-Clause license. Note that NO WARRANTY is provided. 6# * See "LICENSE_BSD2.txt" for details. 7# * 8# * @TAG(NICTA_BSD) 9import graph_refine.loop_bounds as loop_bounds 10import graph_refine.trace_refute as trace_refute 11import graph_refine.target_objects as target_objects 12from graph_refine.target_objects import functions 13import graph_refine.problem as problem 14import imm_utils 15import sys 16 17#extract all loop heads from loops_by_fs 18def loopHeadsToWorkOn(lbfs, funs_with_phantom_preempt, worker_ids): 19 ret = [] 20 n_ignored = 0 21 for f in lbfs: 22 for head in lbfs[f]: 23 if (f not in funs_with_phantom_preempt) and ("ignore" in lbfs[f][head][1]): 24 n_ignored +=1 25 elif (-1 in worker_ids) or (lbfs[f][head][2] in worker_ids): 26 ret += lbfs[f].keys() 27 print 'ignored %d loops' % n_ignored 28 print 'working on %s' % str(map(hex,ret)) 29 return ret 30 31def phantomPreemptsAnnoFileName(target_dir_name): 32 return '%s/preempt_refutes.txt' % target_dir_name 33 34def convert_loop_bounds(target_dir_name, worker_ids=None, cached_only=False): 35 if worker_ids == None: 36 worker_ids = set([-1]) 37 print 'target_dir_name: %s' % target_dir_name 38 args = target_objects.load_target(target_dir_name) 39 target_dir = target_objects.target_dir 40 context = {} 41 execfile('%s/loop_counts.py' % target_dir,context) 42 assert 'loops_by_fs' in context 43 lbfs = context['loops_by_fs'] 44 context = {} 45 execfile('%s/phantom_preempt.py' % target_dir,context) 46 funs_with_phantom_preempt = context['functions'] 47 if funs_with_phantom_preempt: 48 preempt_annotations_file = open(phantomPreemptsAnnoFileName(target_dir), 'w') 49 #print 'funs_with_phantom_preempt: %s' % str(funs_with_phantom_preempt) 50 bin_heads = loopHeadsToWorkOn(lbfs, funs_with_phantom_preempt, worker_ids) 51 funs_with_unbounded_loop = set() 52 #all_loop_heads = loop_bounds.get_all_loop_heads() 53 print 'bin_heads: ' + str(bin_heads) 54 for head in bin_heads: 55 f = trace_refute.get_body_addrs_fun(head) 56 if f not in lbfs: 57 lbfs[f] = {} 58 ret= None 59 if f in funs_with_phantom_preempt: 60 ret = (64, 'phantom_preempt') 61 preempt_annotations_file.write("#" + f + "\n") 62 preempt_annotations_file.write("[%s]:phantom_preemp_point\n\n" % hex(head)) 63 64 print '%s injected with phantom preemption point' % f 65 else: 66 try: 67 ret = loop_bounds.get_bound_super_ctxt(head,[], 68 known_bound_only = cached_only) 69 except problem.Abort, e: 70 print 'failed to analyse %s, problem aborted' % f 71 except: 72 print "Unexpected error:", sys.exc_info() 73 raise 74 old_worker = lbfs[f][head][2] 75 if ret == None or ret[1]== 'None': 76 if cached_only: 77 comment = 'did not find cached result' 78 else: 79 comment = 'ignore: failed' 80 lbfs[f][head] = (2**30, comment, old_worker) 81 funs_with_unbounded_loop.add(f) 82 else: 83 lbfs[f][head] = (ret[0],ret[1], old_worker) 84 imm_utils.genLoopheads(lbfs, target_objects.target_dir, incremental_head=(f,head)) 85 preempt_annotations_file.close() 86 unex_unbounded_funcs = set([x for x in funs_with_unbounded_loop if x not in funs_with_phantom_preempt]) 87 if unex_unbounded_funcs: 88 print 'functions with unbounded loop and not bounded by preemption: %s' % str(unex_unbounded_funcs) 89 return None 90 return lbfs 91 92if __name__== '__main__': 93 import argparse 94 parser = argparse.ArgumentParser() 95 parser.add_argument("target_dir_name") 96 parser.add_argument('--worker_id', type=int, help="what bound marker is this instance responsible for, -1 means everything", default= -1) 97 parser.add_argument('--worker_ids', type=str, help="multiple worker IDs, e.g. 1,2,3", default= None) 98 parser.add_argument('--cached_only', type=bool, default=False, help="Only read what's cached in LoopBounds.txt") 99 args = parser.parse_args() 100 worker_ids = set ([args.worker_id]) 101 if args.worker_ids != None: 102 ids = args.worker_ids.split(",") 103 try: 104 worker_ids = set(map(int,ids)) 105 except ValueError, e: 106 print "Worker IDs not numeric: %s" % ids 107 sys.exit(-1) 108 target_dir_name = args.target_dir_name 109 print "I am workers %s" % sorted(worker_ids) 110 lbfs = convert_loop_bounds(target_dir_name, worker_ids, cached_only = args.cached_only) 111 if lbfs is None: 112 sys.exit(-1) 113 114