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)import subprocess 9import subprocess 10import elf_file 11import elf_correlate 12import elf_parser 13import chronos.emitter 14import re 15from dot_utils import * 16import call_graph_utils 17import sys 18import traceback 19import graph_refine.problem as problem 20import imm_utils 21from graph_refine.target_objects import functions, functions_by_tag 22import graph_refine.target_objects as target_objects 23import cplex 24import conflict 25 26chronos_executable = "../../chronos4.2/est" 27 28fast_path = [ 29'fastpath_restore', 30'fastpath_call', 31'fastpath_reply_wait', 32'slowpath' 33] 34 35dummy_funs = [ 36'idle_thread', 'halt', 37] + fast_path 38 39#funs called by boot_funs only 40boot_funs_called = [ 41'strncmp' 42] 43 44 45def makeGraph(f_name,fs): 46 p = fs[f_name].as_problem(problem.Problem) 47 toGraph(p,f_name) 48 49def runExtract(program_n_flags,cwd=None): 50 if cwd: 51 p = subprocess.Popen(program_n_flags,cwd=cwd,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 52 else: 53 p = subprocess.Popen(program_n_flags,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 54 out,err = p.communicate() 55 retval = p.returncode 56 return retval, out, err 57 58#given the imm, call chronos and cplex to return (wcet,chronos_out,chornos_err) 59def getWcetFromImm(imm_file_name, generateILPOnly= False): 60 print 'running chronos...' 61 ret,out,err = runExtract([chronos_executable, imm_file_name]) 62 print 'chronos completed, ret: %s, err: %s\n' % (ret,err) 63 if ret: 64 print 'Chronos FAILED\n out: %s\n err: %s\n' % (out,err) 65 print 'Chronos FAILED\n' 66 return None 67 else: 68 pass 69 print 'Chronos succeeded' 70 if generateILPOnly: 71 print "ILP file generated" 72 return None 73 return float(cplex.cplexSolve(imm_file_name+'.ilp')),out,err 74 75 76def toElfImmFun(f,dir_name,load_counts): 77 ef = elfFile() 78 elf_fun = ef.funcs[elfFile().gFunName(f)] 79 imm_fun = elf_correlate.immFunc(elf_fun,load_counts=load_counts) 80 return elf_fun, imm_fun, ef 81 82def toImmFun(f,dir_name,load_counts=False): 83 _, imm_fun, _ = toElfImmFun(f,dir_name,load_counts) 84 return imm_fun 85 86def analyseFunction(f,asm_fs,dir_name,gen_heads,load_counts,emit_graphs, stopAtILP=False): 87 print '========analsying from entry point: %s===========' % f 88 elf_fun,imm_fun, ef = toElfImmFun(f, dir_name,load_counts) 89 #emit graphs with graph-refine 90 if emit_graphs: 91 makeGraph(f,asm_fs) 92 93 imm_fun.process() 94 if gen_heads: 95 print 'generating loop heads' 96 imm_utils.genLoopheads(imm_fun.bin_loops_by_fs,dir_name) 97 print 'loop heads generated' 98 if gen_heads: 99 return None 100 else: 101 import elf_correlate 102 #load the dummy loop counts 103 elf_correlate.immFunc().loaded_loops_by_fs = elf_correlate.loadCounts(dir_name) 104 105 #if emit_graphs: 106 #toDot(imm_fun) 107 #toDotBB(imm_fun) 108 109 emitter = chronos.emitter.ChronosEmitter(dir_name, f, imm_fun) 110 emitter.emitTopLevelFunction() 111 112 imm_file_name = emitter.imm_file_name 113 114 ret_g = getWcetFromImm(imm_file_name, stopAtILP) 115 if not ret_g: 116 return None 117 wcet, out_chronos_gg,err_chronos_gg = ret_g 118 if wcet: 119 print 'G2G-Chronos extracted, wcet: %s\n' % wcet 120 return wcet 121 return None 122 123def init(dir_name): 124 '''setup the target and initialise the elfFile''' 125 target_objects.load_target(dir_name) 126 sys.setrecursionlimit(2000) 127 import graph_refine.stack_logic as stack_logic 128 stack_logic.add_hooks () 129 #silence graph-refine outputs that we don't care about when doing wcet 130 def silent_tracer (s,v): 131 if s.startswith('Loop') or re.search(r'\s*\(=',s) or re.search(r'\s*\(',s): 132 return 133 if s.startswith('requests') or s.startswith('Result:') or s.startswith('Now'): 134 return 135 if s.startswith('testing') or s.startswith('done') or s.startswith('rep_graph'): 136 return 137 if s.startswith('Testing') or s.startswith('Group'): 138 return 139 print s 140 141 target_objects.tracer[0] = silent_tracer 142 elf_parser.parseElf(dir_name) 143 asm_fs = elfFile().asm_fs 144 tran_call_graph = call_graph_utils.transitiveCallGraph(asm_fs,dir_name,dummy_funs) 145 146 elfFile().tcg = tran_call_graph 147 elfFile().asm_idents = None 148 elfFile().immed = None 149 return asm_fs 150 151def bench(dir_name, entry_point_function, gen_heads,load_counts, interactive, parse_only=False, conflict_file=None): 152 asm_fs = init(dir_name) 153 functions = target_objects.functions 154 if parse_only or interactive: 155 t = entry_point_function 156 i = toImmFun(t,dir_name,load_counts=load_counts) 157 i.process() 158 return 159 dn = dir_name 160 emit_graphs = False 161 wcet = analyseFunction(entry_point_function,asm_fs, dir_name, gen_heads, load_counts, emit_graphs=emit_graphs) 162 return wcet 163 164