def loopDot(head,p): from elf_correlate import immFunc graph = pydot.Dot(graph_type='digraph') nodes = {} ns = list(p.loop_data[head][1]) print 'len: %d' % len(ns) for n in ns: phy_n = immFunc().phyAddrP(n,p) if isinstance(phy_n,int) and phy_n %4 == 0: text, _ = rawVals(phy_n) else: text = '' n_cap = '%s / %d \n %s' % (hex(phy_n),n, text) if [x for x in p.nodes[n].get_conts() if x not in ns and not x == 'Err']: print 'found exit node ! %d' % n nodes[n] = pydot.Node(n_cap,color="blue") else: nodes[n] = pydot.Node(n_cap) for n in nodes: graph.add_node(nodes[n]) for n in ns: conts = p.nodes[n].get_conts() for c in conts: if c in ns: graph.add_edge(pydot.Edge(nodes[n],nodes[c])) graph.write_svg('graphs/loop.svg' ) graph.write('graphs/loop.dot' ) return
def emit_f_conflicts(fout, line): ''' ''' bbAddr = immFunc().bbAddr match = re.search(r'\s*\[(?P<infeas>.*)\]\s*:\s*(?P<kind>.*$)', line) print 'infeas: %s' % match.group('infeas') infeasible_fs = match.group('infeas').split(',') print 'infeasible_fs: %s' % infeasible_fs #find all bb_addrs where f[-1] can be called by f[-2] bbCallStrings = callstring_bbs(infeasible_fs) print 'bbcs: %s' % str(bbCallStrings) for s in bbCallStrings: for x in s: assert bbAddr(x) == x final_callee_bb = s[-1] #print 'final_callee_bb: %s'% str(final_callee_bb) assert final_callee_bb in bb_addr_to_ids ids = bb_addr_to_ids[final_callee_bb] ids_ctx = [ x for x in ids if bbs_context_match(id_to_context[x], s[:-1]) ] print 'ids: %d, ids_ctx: %d' % (len(ids), len(ids_ctx)) #ok, now all of these are just unreachable. for tcfg_id in ids_ctx: fout.write("b{0} = 0\n".format(tcfg_id))
def loopDot(head, p): from elf_correlate import immFunc graph = pydot.Dot(graph_type='digraph') nodes = {} ns = list(p.loop_data[head][1]) print 'len: %d' % len(ns) for n in ns: phy_n = immFunc().phyAddrP(n, p) if isinstance(phy_n, int) and phy_n % 4 == 0: text, _ = rawVals(phy_n) else: text = '' n_cap = '%s / %d \n %s' % (hex(phy_n), n, text) if [ x for x in p.nodes[n].get_conts() if x not in ns and not x == 'Err' ]: print 'found exit node ! %d' % n nodes[n] = pydot.Node(n_cap, color="blue") else: nodes[n] = pydot.Node(n_cap) for n in nodes: graph.add_node(nodes[n]) for n in ns: conts = p.nodes[n].get_conts() for c in conts: if c in ns: graph.add_edge(pydot.Edge(nodes[n], nodes[c])) graph.write_svg('graphs/loop.svg') graph.write('graphs/loop.dot') return
def conflict(entry_point_function, tcfg_map, conflict_files, old_ilp, new_ilp, dir_name, sol_file, emit_conflicts=False, do_cplex=False, interactive=False, silent_cplex=False, preempt_limit=None, default_phantom_preempt=False): if preempt_limit == None: preempt_limit = 5 if default_phantom_preempt: conflict_files.append( convert_loop_bounds.phantomPreemptsAnnoFileName(dir_name)) #initialise graph_to_graph so we get immFunc #load the loop_counts print 'conflict.conflict: sol_file %s' % sol_file bench.bench(dir_name, entry_point_function, False, True, False, parse_only=True) #we need the loop data immFunc().process() global bbAddr bbAddr = immFunc().bbAddr read_tcfg_map(tcfg_map) if interactive: assert False, 'Halt' if emit_conflicts: print 'new_ilp:%s' % new_ilp print_constraints(conflict_files, old_ilp, new_ilp, sol_file, preempt_limit) if do_cplex: cplex_ret = cplex.cplexSolve(new_ilp, silent=silent_cplex, sol_file=sol_file) print 'cplex_ret: %s' % cplex_ret return cplex_ret
def process_conflict(fout, conflict_files): fake_preemption_points = [] for conflict_file in conflict_files: f = open(conflict_file,'r') global bb_addr_to_id fout.write('\ === conflict constraints from %s === \n\n' % conflict_file) last_bb_id = 0 bbAddr = immFunc().bbAddr while True: line = f.readline() if line == '': break #get rid of all white spaces line = line.replace(' ', '') line = line.rstrip() if line.startswith('#') or line=='': #comment line continue if line.rstrip() == '': continue match = re.search(r'.*:\s*(?P<kind>.*$)', line) kind = match.group('kind') #print 'kind: %s' % kind if kind == 'possible': continue elif kind == 'f_conflicts': emit_f_conflicts (fout, line) elif kind == 'phantom_preemp_point': match = re.search(r'\[(?P<addr>.*)\]:(?P<kind>.*$)', line) fake_preemption_points.append(int(match.group('addr'),16)) elif kind == 'times': match = re.search(r'\s*\[(?P<addr>.*)\]\s*:\s*\[(?P<times>.*)\]\s*:\s*(?P<kind>.*$)', line) addr = int(match.group('addr'),16) times = int(match.group('times')) print 'addr: %x' % addr print 'times: %d' % times times_limit(fout,[addr],times) else: bits = line.split(':') [stack,visits,verdict] = bits assert 'impossible' in verdict stack = trace_refute.parse_num_list(stack) visits = trace_refute.parse_num_arrow_list(visits) bb_visits = [(bbAddr(x[0]),x[1]) for x in visits] in_loops = [x for x in (stack[1:] + [x[0] for x in visits]) if inFunLoop(x)] if in_loops: print '!!! loops in inconsistent !!!' print '%r' % in_loops print 'rejected line: %s\n\n' % line continue print 'line: %s' % line emitInconsistent(fout, stack,bb_visits) fout.write("\n"); f.close() return fake_preemption_points
def bbs_context_match(context_targ, context_to_match): bbAddr = immFunc().bbAddr #print 'context: %s' % str(context) #print 's: %s' % str(s) #all of s must be in context to begin with, strip the 0 subfix bb_ctx = [bbAddr(x) for x in context_targ[:-1]] if len(bb_ctx) < len(context_to_match): return False for i in range(len(context_to_match)): if context_to_match[i] != bb_ctx[len(context_to_match) - i - 1]: return False return True
def bbs_context_match(context_targ, context_to_match): bbAddr = immFunc().bbAddr #print 'context: %s' % str(context) #print 's: %s' % str(s) #all of s must be in context to begin with, strip the 0 subfix bb_ctx = [bbAddr(x) for x in context_targ[:-1]] if len(bb_ctx) < len(context_to_match): return False for i in range(len(context_to_match)): if context_to_match[i] != bb_ctx[len(context_to_match) -i - 1]: return False return True
def conflict(entry_point_function, tcfg_map, conflict_files, old_ilp, new_ilp, dir_name, sol_file, emit_conflicts=False, do_cplex=False, interactive=False, silent_cplex=False, preempt_limit= None, default_phantom_preempt=False): if preempt_limit == None: preempt_limit = 5 if default_phantom_preempt: conflict_files.append(convert_loop_bounds.phantomPreemptsAnnoFileName(dir_name)) #initialise graph_to_graph so we get immFunc #load the loop_counts print 'conflict.conflict: sol_file %s' % sol_file bench.bench(dir_name, [entry_point_function],False,True,False,parse_only=True ) #we need the loop data immFunc().process() global bbAddr bbAddr = immFunc().bbAddr read_tcfg_map(tcfg_map) if interactive: assert False, 'Halt' if emit_conflicts: print 'new_ilp:%s' % new_ilp print_constraints(conflict_files, old_ilp, new_ilp, sol_file, preempt_limit) if do_cplex: cplex_ret = cplex.cplexSolve(new_ilp,silent=silent_cplex,sol_file=sol_file) print 'cplex_ret: %s' % cplex_ret return cplex_ret
def callstring_bbs(fs,cs_so_far = None): bbAddr= immFunc().bbAddr #print 'fs: %s' % str(fs) #print 'cs_so_far: %s' % str(cs_so_far) if not cs_so_far: cs_so_far = [ ] ret = [] top_f = fs[0] next_f = fs[1] #print 'top_f #%s# next_f #%s#' % (top_f,next_f) p = immFunc().f_problems[top_f] cns = callNodes(p,fs=[next_f]) #print 'cns:%s'% cns pA = lambda x: phyAddrP(x,p) #phy_rets =[phyAddrP(x,p) for x in cns] phy_rets =[callSitePA(x,p) for x in cns] #print ' phy_rets: %s' % str(phy_rets) if len(fs) == 2: return [(cs_so_far +[bbAddr(x)]) for x in phy_rets] assert len(fs) >2 for x in phy_rets: ret += callstring_bbs(fs[1:],cs_so_far = cs_so_far + [bbAddr(x)]) return ret
def callstring_bbs(fs, cs_so_far=None): bbAddr = immFunc().bbAddr #print 'fs: %s' % str(fs) #print 'cs_so_far: %s' % str(cs_so_far) if not cs_so_far: cs_so_far = [] ret = [] top_f = fs[0] next_f = fs[1] #print 'top_f #%s# next_f #%s#' % (top_f,next_f) p = immFunc().f_problems[top_f] cns = callNodes(p, fs=[next_f]) #print 'cns:%s'% cns pA = lambda x: phyAddrP(x, p) #phy_rets =[phyAddrP(x,p) for x in cns] phy_rets = [callSitePA(x, p) for x in cns] #print ' phy_rets: %s' % str(phy_rets) if len(fs) == 2: return [(cs_so_far + [bbAddr(x)]) for x in phy_rets] assert len(fs) > 2 for x in phy_rets: ret += callstring_bbs(fs[1:], cs_so_far=cs_so_far + [bbAddr(x)]) return ret
def analyseFunction(f, asm_fs, dir_name, gen_heads, load_counts, emit_graphs, stopAtILP=False): print '========analsying from entry point: %s===========' % f elf_fun, imm_fun, ef = toElfImmFun(f, dir_name, load_counts) #emit graphs with graph-refine if emit_graphs: makeGraph(f, asm_fs) imm_fun.process() if gen_heads: print 'generating loop heads' imm_utils.genLoopheads(imm_fun.bin_loops_by_fs, dir_name) print 'loop heads generated' if gen_heads: return None else: import elf_correlate #load the dummy loop counts elf_correlate.immFunc( ).loaded_loops_by_fs = elf_correlate.loadCounts(dir_name) #if emit_graphs: #toDot(imm_fun) #toDotBB(imm_fun) emitter = chronos.emitter.ChronosEmitter(dir_name, f, imm_fun) emitter.emitTopLevelFunction() imm_file_name = emitter.imm_file_name ret_g = getWcetFromImm(imm_file_name, stopAtILP) if not ret_g: return None wcet, out_chronos_gg, err_chronos_gg = ret_g if wcet: print 'G2G-Chronos extracted, wcet: %s\n' % wcet return wcet return None
def emit_f_conflicts (fout, line): bbAddr = immFunc().bbAddr match = re.search(r'\s*\[(?P<infeas>.*)\]\s*:\s*(?P<kind>.*$)', line) print 'infeas: %s' % match.group('infeas') infeasible_fs = match.group('infeas').split(',') print 'infeasible_fs: %s' % infeasible_fs #find all bb_addrs where f[-1] can be called by f[-2] bbCallStrings = callstring_bbs(infeasible_fs) print 'bbcs: %s' % str(bbCallStrings) for s in bbCallStrings: for x in s: assert bbAddr(x) == x final_callee_bb = s[-1] #print 'final_callee_bb: %s'% str(final_callee_bb) assert final_callee_bb in bb_addr_to_ids ids = bb_addr_to_ids[final_callee_bb] ids_ctx = [x for x in ids if bbs_context_match(id_to_context[x],s[:-1])] print 'ids: %d, ids_ctx: %d' % (len(ids),len(ids_ctx)) #ok, now all of these are just unreachable. for tcfg_id in ids_ctx: fout.write("b{0} = 0\n".format(tcfg_id))
def analyseFunction(f,asm_fs,dir_name,gen_heads,load_counts,emit_graphs, stopAtILP=False): print '========analsying from entry point: %s===========' % f elf_fun,imm_fun, ef = toElfImmFun(f, dir_name,load_counts) #emit graphs with graph-refine if emit_graphs: makeGraph(f,asm_fs) imm_fun.process() if gen_heads: print 'generating loop heads' imm_utils.genLoopheads(imm_fun.bin_loops_by_fs,dir_name) print 'loop heads generated' if gen_heads: return None else: import elf_correlate #load the dummy loop counts elf_correlate.immFunc().loaded_loops_by_fs = elf_correlate.loadCounts(dir_name) #if emit_graphs: #toDot(imm_fun) #toDotBB(imm_fun) emitter = chronos.emitter.ChronosEmitter(dir_name, f, imm_fun) emitter.emitTopLevelFunction() imm_file_name = emitter.imm_file_name ret_g = getWcetFromImm(imm_file_name, stopAtILP) if not ret_g: return None wcet, out_chronos_gg,err_chronos_gg = ret_g if wcet: print 'G2G-Chronos extracted, wcet: %s\n' % wcet return wcet return None
def toElfImmFun(f,dir_name,load_counts): ef = elfFile() elf_fun = ef.funcs[elfFile().gFunName(f)] imm_fun = elf_correlate.immFunc(elf_fun,load_counts=load_counts) return elf_fun, imm_fun, ef
def bbAddrs(l): bbAddr = immFunc().bbAddr return [bbAddr(x) for x in l if x]
def inFunLoop(addr): from addr_utils import gToPAddrP f = elfFile().addrs_to_f[addr] p = immFunc().f_problems[f] p_addr = gToPAddrP(addr,p) return p_addr in p.loop_data
def toElfImmFun(f, dir_name, load_counts): ef = elfFile() elf_fun = ef.funcs[elfFile().gFunName(f)] imm_fun = elf_correlate.immFunc(elf_fun, load_counts=load_counts) return elf_fun, imm_fun, ef
def process_conflict(fout, conflict_files): fake_preemption_points = [] for conflict_file in conflict_files: f = open(conflict_file, 'r') global bb_addr_to_id fout.write('\ === conflict constraints from %s === \n\n' % conflict_file) last_bb_id = 0 bbAddr = immFunc().bbAddr while True: line = f.readline() if line == '': break #get rid of all white spaces line = line.replace(' ', '') line = line.rstrip() if line.startswith('#') or line == '': #comment line continue if line.rstrip() == '': continue match = re.search(r'.*:\s*(?P<kind>.*$)', line) kind = match.group('kind') #print 'kind: %s' % kind if kind == 'possible': continue elif kind == 'f_conflicts': emit_f_conflicts(fout, line) elif kind == 'phantom_preemp_point': match = re.search(r'\[(?P<addr>.*)\]:(?P<kind>.*$)', line) fake_preemption_points.append(int(match.group('addr'), 16)) elif kind == 'times': match = re.search( r'\s*\[(?P<addr>.*)\]\s*:\s*\[(?P<times>.*)\]\s*:\s*(?P<kind>.*$)', line) addr = int(match.group('addr'), 16) times = int(match.group('times')) print 'addr: %x' % addr print 'times: %d' % times times_limit(fout, [addr], times) else: bits = line.split(':') [stack, visits, verdict] = bits assert 'impossible' in verdict stack = trace_refute.parse_num_list(stack) visits = trace_refute.parse_num_arrow_list(visits) bb_visits = [(bbAddr(x[0]), x[1]) for x in visits] in_loops = [ x for x in (stack[1:] + [x[0] for x in visits]) if inFunLoop(x) ] if in_loops: print '!!! loops in inconsistent !!!' print '%r' % in_loops print 'rejected line: %s\n\n' % line continue print 'line: %s' % line emitInconsistent(fout, stack, bb_visits) f.close() fout.write("\n") return fake_preemption_points
def inFunLoop(addr): from addr_utils import gToPAddrP f = elfFile().addrs_to_f[addr] p = immFunc().f_problems[f] p_addr = gToPAddrP(addr, p) return p_addr in p.loop_data