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