Example #1
0
def fitness_function(chromosome):
    try:
        if fitness_function.vectorProperties.base_type == TestVectorProperties.BaseType[2]:
            # Sometimes this conversion fails and I don't see why?
            # Just catch it and move on
            chromosome.genomeList = [chr(val) for val in chromosome.genomeList]
    except TypeError:
        pass
        
    fitness_function.run += 1
    traceFile  = "%s.%s.%d" % (os.path.basename(fitness_function.binary), "trace", fitness_function.run)
    cmd        = '%s --debug-flags=Fetch --trace-file=%s %s --cpu-type=timing -c %s -o "%s"' % \
     (config.Arguments.gem5_simulator, traceFile, config.Arguments.gem5_config, fitness_function.binary, ' '.join(map(str, chromosome.genomeList)))
    debug.debug_message("Running '%s' on gem5" % cmd, 1)
    proc       = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)    
    returncode = proc.wait()
    if returncode:
        debug.exit_message("Running '%s' failed" % cmd)
    gem5_trace = os.path.abspath(os.getcwd()) + os.sep + config.Arguments.m5_trace_directory + os.sep + traceFile
    assert os.path.exists(gem5_trace), "Expected to find gem5 trace in '%s' but it is not there" % gem5_trace
    firstLines = os.popen("head -1 %s" % gem5_trace).readlines()
    lastLines  = os.popen("tail -1 %s" % gem5_trace).readlines()
    assert len(firstLines) == 1
    assert len(lastLines) == 1
    firstLine = firstLines[0]
    lastLine  = lastLines[0]
    time1 = shlex.split(firstLine)[0]
    time2 = shlex.split(lastLine)[0]
    time1 = time1[:-1]
    time2 = time2[:-1]
    score = int(time2) - int(time1)
    debug.debug_message("Score = %d" % score, 1)
    fitness_function.gem5traces.append(compress_trace(gem5_trace))
    return score
Example #2
0
 def solve(self):
     with open(self._filename, 'w') as clpFile:
         for line in self._lines:
             clpFile.write(line)
     debug.debug_message("Solving CLP in %s" % self._filename, 10)
     command = 'jeclipse -b %s -e "%s."' % (self._filename, self.__goal)
     debug.verbose_message("Running command '%s'" % command, __name__)
     start = timeit.default_timer()
     proc = subprocess.Popen(command, shell=True, executable="/bin/bash")
     returnCode = proc.wait()
     self._solvingTime = (timeit.default_timer() - start)
     if returnCode != 0:
         debug.warning_message("Running '%s' failed" % command)
         return self._wcet, self._solvingTime
     else:
         with open(self._filename + '.res') as f:
             for line in f:
                 if re.match(r'%s' % CLP.WCET, line):
                     values = re.findall(r'[0-9]+', line)
                     assert len(
                         values
                     ) == 1, "Unable to find WCET value in CLP output file"
                     self._wcet = int(values[0])
     assert self._wcet
     assert self._solvingTime
     return self._wcet, self._solvingTime
Example #3
0
 def generate_a_trace(self):
     if config.Arguments.add_timestamps:
         current_time = random.randint(1, 100)  
     root_callv    = self.program.callg.getVertex(self.program.callg.rootID)
     current_callv = root_callv 
     current_CFG   = self.program.cfgs[root_callv.name]
     currentv      = current_CFG.getVertex(current_CFG.get_entryID())
     call_stack    = []
     while True:
         if not config.Arguments.add_timestamps:
             self.the_file.write("(%d) " % currentv.vertexID)
         else:
             self.the_file.write("(%d, %d) " % (currentv.vertexID, current_time))
             current_time += random.randint(1, 100)
         if currentv.vertexID == current_CFG.get_exitID():
             if current_callv == root_callv:
                 # End of the program reached
                 break
             else:
                 # End of function call
                 debug.debug_message("Returning from %s" % current_callv.name, __name__, 10)
                 current_callv, current_CFG, currentv = call_stack.pop()
                 # Go past the call site
                 currentv = self.choose_intra_procedural_successor(current_CFG, currentv)
         elif current_CFG.is_call_site(currentv.vertexID):
             call_stack.append((current_callv, current_CFG, currentv))
             succID        = current_callv.get_successor_with_call_site(currentv.vertexID)
             current_callv = self.program.callg.getVertex(succID)
             debug.debug_message("Calling %s" % current_callv.name, __name__, 10)
             current_CFG   = self.program.cfgs[current_callv.name]
             currentv      = current_CFG.getVertex(current_CFG.get_entryID())
         else:
             currentv = self.choose_intra_procedural_successor(current_CFG, currentv)
Example #4
0
 def __parseAddress (self, time, address, runID):
     if address == self.__lastAddr:
         self.__analyseWCETOfBasicBlock(time - self.__time1)
     if not self.__currentBB.hasAddress(address):
         # Instructions in the current basic block have finished. Analyse its execution time
         self.__analyseWCETOfBasicBlock(time - self.__time1)
         # Move the time marker forward to the current time to reflect that we are transitioning
         # to a new basic block
         self.__time1 = time
         # Make the switch to the next basic block
         if self.__currentCFG.isCallSite(self.__currentBB.vertexID):
             self.__handleCall(address)
         elif self.__currentCFG.getExitID() == self.__currentBB.vertexID:
             self.__handleReturn()
             # Since we have switched basic blocks in the current CFG, analyse the super blocks
             self._analyseCFGEdge(self.__currentPathg, self.__currentLNT, self.__predBB.vertexID, self.__currentBB.vertexID) 
         else:
             for succID in self.__currentBB.getSuccessorIDs():
                 succv = self.__currentCFG.getVertex(succID)
                 if succv.hasAddress(address):
                     self.__predBB    = self.__currentBB
                     self.__currentBB = succv
                     break
             # Since we have switched basic blocks in the current CFG, analyse the super blocks
             self._analyseCFGEdge(self.__currentPathg, self.__currentLNT, self.__predBB.vertexID, self.__currentBB.vertexID)     
         debug.debug_message("Now in CFG '%s' at basic block %d" % (self.__currentCFG.getName(), self.__currentBB.vertexID), 10)   
         self._analyseCFGVertex(self.__currentPathg, self.__currentLNT, self.__currentBB.vertexID)     
Example #5
0
    def construct_loop_info(self, enhanced_icfg, lnt, ipg):
        for v in ipg:
            for succID in v.successors.keys():
                succe = v.get_successor_edge(succID)
                for program_point in succe.edge_label:
                    if isinstance(program_point, vertices.CFGEdge):
                        the_edge = program_point.edge
                        if lnt.is_loop_back_edge(the_edge[0], the_edge[1]):
                            self.loop_back_edges[the_edge[1]].add(
                                (v.vertexID, succID))

        for treev in self.enhanced_lnt:
            if isinstance(treev, vertices.HeaderVertex):
                debug.debug_message("Analysing header %d" % treev.headerID,
                                    __name__, 1)
                enhanced_icfg_of_loop = self.enhanced_lnt.induce_subgraph(
                    treev)
                self.enhanced_icfgs_per_loop[
                    treev.headerID] = enhanced_icfg_of_loop
                self.loop_exit_regions[
                    treev.
                    headerID] = self.compute_reachable_program_points_from_loop_exits(
                        treev)
                udraw.make_file(
                    enhanced_icfg_of_loop, "%s.header_%d.%s" %
                    (enhanced_icfg.name, treev.headerID, "icfg"))
                self.ipgs_per_loop[treev.headerID] = ipgs.IPGLoopInformation(
                    self, treev.headerID, enhanced_icfg_of_loop, self.lnt,
                    self.enhanced_lnt, ipg)
Example #6
0
 def __initialise(self):
     self.__currentContextv = None
     self.__currentCFG = None
     self.__currentLNT = None
     self.__predBB = None
     self.__currentBB = None
     self.__currentHeaderID = None
     self.__currentPathg = None
     self.__time1 = None
     self.__stack = []
     self.__contextg = self._program.getContextGraph()
     rootv = self.__contextg.getVertex(self.__contextg.getRootID())
     self.__rootCFG = self._program.getCFG(rootv.getName())
     self.__firstAddr = self.__rootCFG.getFirstInstruction().getAddress()
     lastbb = self.__rootCFG.getVertex(self.__rootCFG.getExitID())
     for instruction in reversed(lastbb.getInstructions()):
         if instruction.getOp() not in arm.armInstructionSet.Nops:
             self.__lastAddr = instruction.getAddress()
             break
     assert self.__lastAddr, "Unable to find last address"
     debug.debug_message(
         "Start address of root function '%s' is %s" %
         (rootv.getName(), hex(self.__firstAddr)), 1)
     debug.debug_message(
         "End address of root function '%s' is %s" %
         (rootv.getName(), hex(self.__lastAddr)), 1)
Example #7
0
 def solve(self):
     assert self._filename, "ILP filename has not been set"
     debug.debug_message("Solving ILP for %s" % self._filename, 10)
     command = "lp_solve %s -S1 -time" % self._filename
     start = timeit.default_timer()
     proc = subprocess.Popen(command,
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             executable="/bin/bash")
     returnCode = proc.wait()
     self._solvingTime = (timeit.default_timer() - start)
     if returnCode != 0:
         debug.warning_message("Running '%s' failed" % command)
         return self._wcet, self._solvingTime
     for line in proc.stdout.readlines():
         if line.startswith("Value of objective function"):
             lexemes = shlex.split(line)
             self._wcet = long(decimal.Decimal(lexemes[-1]))
     assert self._wcet
     assert self._solvingTime
     for line in proc.stderr.readlines():
         if line.startswith("CPU Time for Parsing"):
             lexemes = shlex.split(line)
             time = lexemes[5][:-1]
             #self.solvingTime -= float(time)
     return self._wcet, self._solvingTime
Example #8
0
 def __parseAddress(self, time, address, runID):
     if address == self.__lastAddr:
         self.__analyseWCETOfBasicBlock(time - self.__time1)
     if not self.__currentBB.hasAddress(address):
         # Instructions in the current basic block have finished. Analyse its execution time
         self.__analyseWCETOfBasicBlock(time - self.__time1)
         # Move the time marker forward to the current time to reflect that we are transitioning
         # to a new basic block
         self.__time1 = time
         # Make the switch to the next basic block
         if self.__currentCFG.isCallSite(self.__currentBB.vertexID):
             self.__handleCall(address)
         elif self.__currentCFG.getExitID() == self.__currentBB.vertexID:
             self.__handleReturn()
             # Since we have switched basic blocks in the current CFG, analyse the super blocks
             self._analyseCFGEdge(self.__currentPathg, self.__currentLNT,
                                  self.__predBB.vertexID,
                                  self.__currentBB.vertexID)
         else:
             for succID in self.__currentBB.getSuccessorIDs():
                 succv = self.__currentCFG.getVertex(succID)
                 if succv.hasAddress(address):
                     self.__predBB = self.__currentBB
                     self.__currentBB = succv
                     break
             # Since we have switched basic blocks in the current CFG, analyse the super blocks
             self._analyseCFGEdge(self.__currentPathg, self.__currentLNT,
                                  self.__predBB.vertexID,
                                  self.__currentBB.vertexID)
         debug.debug_message(
             "Now in CFG '%s' at basic block %d" %
             (self.__currentCFG.getName(), self.__currentBB.vertexID), 10)
         self._analyseCFGVertex(self.__currentPathg, self.__currentLNT,
                                self.__currentBB.vertexID)
Example #9
0
 def do_it(self):
     filename = config.Arguments.basepath + os.sep + config.Arguments.basename + ".traces.gz"
     with gzip.open(filename, 'wb') as self.the_file:
         for trace in xrange(1, config.Arguments.generate_traces+1):
             debug.debug_message("Generating trace #%d" % trace, __name__, 10)
             self.generate_a_trace() 
             self.the_file.write("\n\n")
Example #10
0
 def identify_leaders(self):
     functionToBranchTargets = {}
     for function_name in self.functions:
         debug.debug_message("Identifying leaders in '%s'" % function_name, __name__, 10)
         self.function_to_leaders[function_name] = set()
         functionToBranchTargets[function_name]  = set()
         newLeader                               = True
         noopAfterJumpTableBranch                = False
         index                                   = 0
         for instruction, nextInstruction in utils.peekahead_iterator(self.function_to_instructions[function_name]):
             if newLeader:
                 self.function_to_leaders[function_name].add(instruction)
                 newLeader = False
             elif noopAfterJumpTableBranch:
                 assert instruction.the_instruction[1] in InstructionSet.Nops, "Did not find an no-op after jump table branch. Instead found %s" % instruction
                 noopAfterJumpTableBranch = False
                 newLeader                = True
             
             op = instruction.the_instruction[1]
             if op in InstructionSet.Branches:
                 newLeader     = True
                 addressTarget = int(instruction.the_instruction[2], 16) 
                 functionToBranchTargets[function_name].add(addressTarget)
             elif self.is_jump_table_branch(instruction):
                 # Look for instructions with an explicit load into the PC
                 debug.debug_message("Instruction '%s' is loading a value into the PC" % instruction, __name__, 10)
                 if nextInstruction and nextInstruction.the_instruction[0] in InstructionSet.Nops:
                     noopAfterJumpTableBranch = True
                 else:
                     newLeader = True
             index += 1
         for instruction in self.function_to_instructions[function_name]:
             if instruction.address in functionToBranchTargets[function_name]:
                 self.function_to_leaders[function_name].add(instruction)
Example #11
0
 def add_jump_table_edges(self):
     for function_name in self.functions:
         debug.debug_message("Adding jump table edges in '%s'" % function_name, __name__, 10)
         cfg = self.program.cfgs[function_name]
         i    = 0
         hasJumpTablePredecessor = set()
         for instr in self.function_to_instructions[function_name]:
             # If the instruction loads into the PC...
             if self.is_jump_table_branch(instr):
                 # Get the number of directives associated with this instruction to work out
                 # how many arms it has
                 assert instr in self.jump_table_to_directives
                 numberOfBranchArms = len(self.jump_table_to_directives[instr])
                 if instr.the_instruction[0] == InstructionSet.LoadInstructions[3] \
                 or instr.the_instruction[0] == InstructionSet.LoadInstructions[4]:
                     numberOfBranchArms = 3
                 predv = cfg.get_basic_block_with_address(instr.address)
                 # Now go through each successive address, get the vertex associated with
                 # that address, and add an edge if the address belongs to a newly discovered
                 # basic block
                 for j in range(i, len(self.function_to_instructions[function_name])):
                     nextInstr = self.function_to_instructions[function_name][j]
                     address   = nextInstr.address
                     if not predv.hasAddress(address):
                         succv = cfg.get_basic_block_with_address(address)
                         if not predv.hasSuccessor(succv.vertexID) and succv not in hasJumpTablePredecessor:
                             cfg.addEdge(predv.vertexID, succv.vertexID)
                             hasJumpTablePredecessor.add(succv)
                             numberOfBranchArms -= 1
                         # We know how many arms to expect. As soon as the supply has been
                         # exhausted, stop adding edges
                         if not numberOfBranchArms or self.is_jump_table_branch(nextInstr):
                             break
             i += 1 
Example #12
0
 def identify_call_graph(self, root_function):
     assert root_function in self.function_to_instructions, "Unable to locate root function '%s' in disassembly" % root_function
     self.functions = set()
     stack = [root_function]
     while stack:
         function_name = stack.pop()
         self.functions.add(function_name)
         debug.debug_message("Analysing function '%s'" % function_name,
                             __name__, 10)
         assert function_name in self.function_to_instructions, "No instructions for '%s' discovered" % function_name
         for instruction in self.function_to_instructions[function_name]:
             if InstructionSet.Call in instruction.the_instruction:
                 assert len(
                     instruction.the_instruction
                 ) == 4, "Unable to handle call instruction '%s' since it does not have 3 fields exactly" % instruction.the_instruction
                 startAddress = int(instruction.the_instruction[2], 16)
                 assert startAddress in self.start_address_to_function, "Unable to find function with start address %s (it should be %s)" % (
                     hex(startAddress), instruction.the_instruction[3])
                 callee_name = self.start_address_to_function[startAddress]
                 if callee_name not in self.functions:
                     stack.append(callee_name)
             elif instruction.the_instruction[1] in InstructionSet.Branches:
                 assert len(
                     instruction.the_instruction
                 ) == 4, "Unable to handle branch instruction '%s' since it does not have 3 fields exactly" % instruction.the_instruction
                 startAddress = int(instruction.the_instruction[2], 16)
                 if startAddress < self.function_to_start_address[
                         function_name] or startAddress > self.function_to_last_address[
                             function_name]:
                     callee_name = self.get_callee_name(
                         instruction.the_instruction)
                     if callee_name not in self.functions:
                         stack.append(callee_name)
Example #13
0
 def __generateTrace(self):
     # To keep track of loop tail iteration count
     self.__functionToTailCount = {}
     # To keep trace of the number of function calls
     self.__numberOfCalls = 0
     callg = self.__program.getCallGraph()
     rootv = callg.getVertex(callg.getRootID())
     self.__currentCallv = rootv
     self.__currentCFG = self.__program.getCFG(rootv.getName())
     self.__currentLNT = self.__program.getLNT(rootv.getName())
     self.__currentv = self.__currentCFG.getVertex(
         self.__currentCFG.getEntryID())
     self.__vertexID = self.__currentv.vertexID
     self.__callStack = []
     while True:
         self.__outfile.write("%d " % self.__vertexID)
         if self.__vertexID == self.__currentCFG.getExitID():
             if callg.getVertexWithName(
                     self.__currentCFG.getName()) == rootv:
                 # End of the program reached
                 break
             else:
                 # End of function call
                 debug.debug_message(
                     "Returning from %s" % self.__currentCallv.getName(), 5)
                 self.__currentCallv, self.__currentCFG, self.__currentLNT, self.__currentv = self.__callStack.pop(
                 )
                 self.__vertexID = self.__currentv.vertexID
                 # Go past the call site
                 self.__chooseSuccessorInICFG()
         elif self.__currentLNT.isLoopTail(self.__vertexID):
             tupleIndex = self.__currentCFG.getName(), self.__vertexID
             if tupleIndex not in self.__functionToTailCount:
                 self.__functionToTailCount[tupleIndex] = 1
                 self.__chooseSuccessorInICFG()
             elif self.__functionToTailCount[
                     tupleIndex] < Generatetraces.maxLoopIterations:
                 self.__functionToTailCount[tupleIndex] += 1
                 self.__chooseSuccessorInICFG()
             else:
                 self.__chooseNonLoopBackEdgeSuccessorInICFG()
         elif self.__currentCFG.isCallSite(self.__vertexID):
             # Make the call. First save state then move to the callee ICFG
             self.__callStack.append(
                 (self.__currentCallv, self.__currentCFG, self.__currentLNT,
                  self.__currentv))
             succID = self.__currentCallv.getSuccessorWithCallSite(
                 self.__vertexID)
             self.__currentCallv = callg.getVertex(succID)
             calleeName = self.__currentCallv.getName()
             debug.debug_message(
                 "Calling %s" % self.__currentCallv.getName(), 5)
             self.__currentCFG = self.__program.getICFG(calleeName)
             self.__currentLNT = self.__program.getLNT(calleeName)
             self.__currentv = self.__currentCFG.getVertex(
                 self.__currentCFG.getEntryID())
             self.__vertexID = self.__currentv.vertexID
         else:
             self.__chooseSuccessorInICFG()
Example #14
0
 def do_it(self):
     filename = config.Arguments.basepath + os.sep + config.Arguments.basename + ".traces.gz"
     with gzip.open(filename, 'wb') as self.the_file:
         for trace in xrange(1, config.Arguments.generate_traces + 1):
             debug.debug_message("Generating trace #%d" % trace, __name__,
                                 10)
             self.generate_a_trace()
             self.the_file.write("\n\n")
Example #15
0
 def assign_wcets_to_ipg_egdes_using_random_values(self, ipg):
     for v in ipg:
         for succID in v.successors.keys():
             succ_edge = v.getSuccessorEdge(succID)
             if not succ_edge.isDummyEdge():
                 key                      = (v.vertexID, succID)
                 self.ipg_edge_WCETs[key] = random.randint(1, 10)
                 debug.debug_message("WCET(%s) = %d" % (key, self.ipg_edge_WCETs[key]), __name__, 1)
Example #16
0
 def assign_wcets_to_basic_blocks(self, icfg):
     for v in icfg:
         if isinstance(v, vertices.CFGVertex) and not v.is_ipoint:
             self.basic_block_WCETs[v.vertexID] = random.randint(1, 20)
             debug.debug_message(
                 "WCET(%d) = %d" %
                 (v.vertexID, self.basic_block_WCETs[v.vertexID]), __name__,
                 1)
Example #17
0
 def __init__(self, program, numberOftraces=1):
     self.__program = program
     filename = config.Arguments.basepath + os.sep + config.Arguments.basename + ".traces"
     with open(filename, 'w') as self.__outfile:
         for trace in xrange(1, numberOftraces + 1):
             debug.debug_message("Generating trace #%d" % trace, 1)
             self.__outfile.write("%s\n" % newTrace)
             self.__generateTrace()
             self.__outfile.write("\n%s\n" % endTrace)
Example #18
0
 def __init__ (self, program, numberOftraces=1):
     self.__program = program
     filename       = config.Arguments.basepath + os.sep + config.Arguments.basename + ".traces"
     with open(filename, 'w') as self.__outfile:
         for trace in xrange(1, numberOftraces+1):
             debug.debug_message("Generating trace #%d" % trace, 1)
             self.__outfile.write("%s\n" % newTrace)
             self.__generateTrace() 
             self.__outfile.write("\n%s\n" % endTrace)
Example #19
0
 def add_edges(self):
     for function_name in self.functions:
         debug.debug_message("Adding edges in '%s'" % function_name,
                             __name__, 10)
         cfg = self.program.cfgs[function_name]
         predID = vertices.dummyID
         for instruction in self.function_to_instructions[function_name]:
             v = self.instruction_to_basic_block[instruction]
             if predID != vertices.dummyID:
                 cfg.addEdge(predID, v.vertexID)
                 predID = vertices.dummyID
             if v.instructions[-1] == instruction:
                 if instruction.the_instruction[1] == InstructionSet.Call:
                     callee_name = self.get_callee_name(
                         instruction.the_instruction)
                     cfg.add_call_site(v.vertexID, callee_name)
                     self.program.callg.addEdge(function_name, callee_name,
                                                v.vertexID)
                     predID = v.vertexID
                 elif instruction.the_instruction[
                         1] in InstructionSet.UnconditionalJumps:
                     jump_address = int(instruction.the_instruction[2], 16)
                     if jump_address >= self.function_to_start_address[
                             function_name] and jump_address <= self.function_to_last_address[
                                 function_name]:
                         succv = cfg.get_basic_block_with_address(
                             jump_address)
                         cfg.addEdge(v.vertexID, succv.vertexID)
                     else:
                         callee_name = self.start_address_to_function[
                             jump_address]
                         cfg.add_call_site(v.vertexID, callee_name)
                         self.program.callg.addEdge(function_name,
                                                    callee_name, v.vertexID)
                         predID = v.vertexID
                 elif instruction.the_instruction[
                         1] in InstructionSet.Branches:
                     branch_address = int(instruction.the_instruction[2],
                                          16)
                     if branch_address >= self.function_to_start_address[
                             function_name] and branch_address <= self.function_to_last_address[
                                 function_name]:
                         succv = cfg.get_basic_block_with_address(
                             branch_address)
                         cfg.addEdge(v.vertexID, succv.vertexID)
                     else:
                         callee_name = self.get_callee_name(
                             instruction.the_instruction)
                         cfg.add_call_site(v.vertexID, callee_name)
                         self.program.callg.addEdge(function_name,
                                                    callee_name, v.vertexID)
                     predID = v.vertexID
                 elif v in self.function_to_jump_table_basic_blocks[
                         function_name]:
                     pass
                 else:
                     predID = v.vertexID
Example #20
0
 def __handleReturn(self):
     debug.debug_message(
         "Returning because of basic block %d" % self.__currentBB.vertexID,
         1)
     self._endOfFunction(self.__currentCFG, self.__currentLNT,
                         self.__currentPathg)
     if self.__stack:
         (self.__currentContextv, self.__currentCFG, self.__currentLNT,
          self.__predBB, self.__currentBB,
          self.__currentPathg) = self.__stack.pop()
Example #21
0
 def assign_wcets_to_ipg_egdes_using_random_values(self, ipg):
     for v in ipg:
         for succID in v.successors.keys():
             succ_edge = v.getSuccessorEdge(succID)
             if not succ_edge.isDummyEdge():
                 key = (v.vertexID, succID)
                 self.ipg_edge_WCETs[key] = random.randint(1, 10)
                 debug.debug_message(
                     "WCET(%s) = %d" % (key, self.ipg_edge_WCETs[key]),
                     __name__, 1)
Example #22
0
 def assign_wcets_to_ipg_egdes_using_basic_block_wcets(self, ipg, icfg):
     for v in ipg:
         for succID in v.successors.keys():
             key  = (v.vertexID, succID)
             wcet = 0
             for program_point in v.get_successor_edge(succID).edge_label:
                 if isinstance(program_point, vertices.CFGVertex) and not program_point.is_ipoint:
                     wcet += self.basic_block_WCETs[program_point.vertexID]
             self.ipg_edge_WCETs[key] = wcet
             debug.debug_message("WCET(%s) = %d" % (key, self.ipg_edge_WCETs[key]), __name__, 1)
Example #23
0
 def __parse(self, traceFiles):
     runID = 0
     for filename in traceFiles:
         parsing = False
         with gzip.open(filename, 'r') as f:
             runID += 1
             self._allruns.add(runID)
             debug.debug_message(
                 "Analysing gem5 trace file '%s'" % filename, 1)
             for line in f:
                 lexemes = shlex.split(line)
                 PCLexeme = lexemes[-1]
                 assert len(
                     PCLexeme
                 ) == 11, "Unable to parse program counter %s" % PCLexeme
                 try:
                     time = int(lexemes[0][:-1])
                     PCLexeme = PCLexeme[5:]
                     PC = int(PCLexeme, 16)
                     if PC == self.__firstAddr:
                         self.__time1 = time
                         startTime = time
                         parsing = True
                         self.__currentContextv = self.__contextg.getVertex(
                             self.__contextg.getRootID())
                         self.__currentCFG = self._program.getCFG(
                             self.__currentContextv.getName())
                         self.__currentLNT = self._program.getLNT(
                             self.__currentContextv.getName())
                         self.__currentPathg = self._program.getPathInfoGraph(
                             self.__currentContextv.getName())
                         self.__predBB = None
                         self.__currentBB = self.__currentCFG.getVertex(
                             self.__currentCFG.getEntryID())
                         self._analyseCFGVertex(self.__currentPathg,
                                                self.__currentLNT,
                                                self.__currentBB.vertexID)
                     if parsing:
                         self.__parseAddress(time, PC, runID)
                     if PC == self.__lastAddr:
                         # Stop parsing
                         parsing = False
                         # Compute the HWMT
                         totalTime = time - startTime
                         self._longestTime = max(self._longestTime,
                                                 totalTime)
                         # Falsify conjectures
                         self._endOfFunction(self.__currentCFG,
                                             self.__currentLNT,
                                             self.__currentPathg)
                 except ValueError:
                     debug.exit_message(
                         "Cannot cast %s into an integer: it is not a hexadecimal string"
                         % PCLexeme)
Example #24
0
 def __parse(self, tracefile):
     runID = 0
     with open(tracefile, 'r') as f:
         for line in f:
             if line.startswith(newTrace):
                 runID += 1
                 debug.debug_message("=====> Run %d" % runID, 1)
                 self._allruns.add(runID)
                 self.__reset()
             elif line.startswith(endTrace):
                 self.__handleReturn()
             else:
                 lexemes = shlex.split(line)
                 for lex in lexemes:
                     nextID = int(lex)
                     if nextID == self.__rootCFG.getEntryID():
                         self.__currentBB = self.__currentCFG.getVertex(
                             nextID)
                     else:
                         found = False
                         for succID in self.__currentBB.getSuccessorIDs():
                             if succID == nextID:
                                 self.__predBB = self.__currentBB
                                 self.__currentBB = self.__currentCFG.getVertex(
                                     succID)
                                 # We have switched basic blocks in the current CFG
                                 self._analyseCFGEdge(
                                     self.__currentPathg, self.__currentLNT,
                                     self.__predBB.vertexID,
                                     self.__currentBB.vertexID)
                                 found = True
                                 break
                         if not found:
                             if self.__currentBB.vertexID == self.__currentCFG.getExitID(
                             ):
                                 succIDs = self.__currentBB.getSuccessorIDs(
                                 )
                                 assert len(succIDs) == 1
                                 succv = self.__currentCFG.getVertex(
                                     succIDs[0])
                                 self.__predBB = self.__currentBB
                                 self.__currentBB = succv
                                 # Since we have switched basic blocks in the current CFG, analyse the super blocks
                                 self._analyseCFGEdge(
                                     self.__currentPathg, self.__currentLNT,
                                     self.__predBB.vertexID,
                                     self.__currentBB.vertexID)
                             else:
                                 self.__handleCall(nextID)
                     # We have switched basic blocks in the current CFG
                     self._analyseCFGVertex(self.__currentPathg,
                                            self.__currentLNT,
                                            self.__currentBB.vertexID)
Example #25
0
def parse_file():
    program = programs.Program()
    icfg    = None
    bb      = None
    with open(config.Arguments.program_file) as f:
        for line in f:
            line = line.lower()
            if line.startswith('cfg:'):
                lexemes = shlex.split(line)
                assert len(lexemes) == 2, "Unable to parse CFG line %s" % line
                icfg          = cfgs.ICFG()
                function_name = lexemes[-1]
                icfg.name     = function_name
                debug.debug_message("Found new ICFG '%s'" % function_name, __name__, 1)
            elif line.startswith('bb:'):
                assert icfg, "Found basic block but current ICFG is null"
                lexemes = shlex.split(line) 
                assert len(lexemes) == 2, "Unable to parse basic block line %s" % line
                vertexID = lexemes[-1]
                assert vertexID.isdigit(), "Vertex identifier '%s' is not an integer" % vertexID
                bb = vertices.CFGVertex(int(vertexID), False)
                icfg.addVertex(bb)
            elif line.startswith('ipoint'):
                assert bb, "Trying to add an Ipoint to a basic block but current basic block is null"
                index    = line.index(':')
                position = line[index+1:].replace(' ', '').strip().lower()
                icfg.ipoint_positions[bb.vertexID] = position
            elif line.startswith('succ:'):
                assert bb, "Found edge but current basic block is null"
                index = line.index(':')
                line = line[index+1:]
                splitter = shlex.shlex(line)
                splitter.whitespace += ')'
                splitter.whitespace += '('
                splitter.whitespace_split = False
                lexemes = list(splitter)
                assert len(lexemes) % 3 == 0, "Unable to parse edge information '%s'" % line
                if len(lexemes) > 1:
                    index = 0
                    for lex in lexemes:
                        if index % 3 == 0:
                            function_name = lexemes[index]
                            assert function_name == icfg.name, "Call edge found which is currently not handled"
                        elif index % 3 == 2:
                            succID = lexemes[index]
                            assert succID.isdigit(), "Successor identifier '%s' is not an integer" % succID
                            bb.add_successor(int(succID))
                        index += 1                        
        assert icfg, "Attempting to analyse ICFG but current ICFG is null"
        icfg.add_predecessor_edges()
        icfg.set_entry_and_exit()
        program.add_ICFG(icfg)
    return program     
Example #26
0
 def extract_instructions(self, filename):
     with open(filename, 'r') as f:
         parse = False
         last_instruction = None
         last_jump_table_instruction = None
         current_function = None
         for line in f:
             if parse:
                 if re.match(r'[0-9a-fA-F]+\s<.*>.*', line):
                     if last_instruction:
                         assert current_function, "No function detected yet"
                         self.function_to_last_address[
                             current_function] = last_instruction.address
                         self.last_address_to_function[
                             last_instruction.address] = current_function
                     lexemes = shlex.split(line)
                     assert len(
                         lexemes
                     ) == 2, "Unable to handle disassembly line %s" % line
                     address = int(lexemes[0], 16)
                     function_name = lexemes[1][1:-2]
                     debug.debug_message(
                         "Detected function '%s' @ start address %d" %
                         (function_name, address), __name__, 10)
                     self.start_address_to_function[address] = function_name
                     current_function = function_name
                     self.function_to_instructions[current_function] = []
                     self.function_to_directives[current_function] = []
                     self.function_to_start_address[
                         current_function] = address
                     self.function_to_jump_table_basic_blocks[
                         current_function] = []
                     last_jump_table_instruction = None
                 elif re.match(r'\s*[0-9a-fA-F]+:.*', line):
                     # Ignore directives reserving space for data
                     if '.word' not in line and '.short' not in line and '.byte' not in line:
                         instruction = vertices.BasicBlock.Instruction.get_instruction(
                             line)
                         self.function_to_instructions[
                             current_function].append(instruction)
                         last_instruction = instruction
                         if self.is_jump_table_branch(instruction):
                             last_jump_table_instruction = instruction
                             self.jump_table_to_directives[instruction] = []
                     else:
                         self.function_to_directives[
                             current_function].append(line)
                         if last_jump_table_instruction:
                             self.jump_table_to_directives[
                                 last_jump_table_instruction].append(line)
             elif line.startswith('Disassembly of section'):
                 parse = '.text' in line
Example #27
0
 def assign_wcets_to_ipg_egdes_using_basic_block_wcets(self, ipg, icfg):
     for v in ipg:
         for succID in v.successors.keys():
             key = (v.vertexID, succID)
             wcet = 0
             for program_point in v.get_successor_edge(succID).edge_label:
                 if isinstance(program_point, vertices.CFGVertex
                               ) and not program_point.is_ipoint:
                     wcet += self.basic_block_WCETs[program_point.vertexID]
             self.ipg_edge_WCETs[key] = wcet
             debug.debug_message(
                 "WCET(%s) = %d" % (key, self.ipg_edge_WCETs[key]),
                 __name__, 1)
Example #28
0
 def find_loop_exits(self):
     for headerID in self.__headerVertices.keys():
         self.__loop_exit_edges[headerID] = set()
         for vertexID in self.__loopBodies[headerID]:
             v = self.__directedg.getVertex(vertexID)
             for succID in v.successors.keys():
                 if succID not in self.__loopBodies[headerID]:
                     if headerID != vertexID and self.is_loop_header(vertexID):
                         if succID not in self.__loopBodies[vertexID]:
                             self.__loop_exit_edges[headerID].add((vertexID, succID))
                     else:
                         self.__loop_exit_edges[headerID].add((vertexID, succID))
         debug.debug_message("Exits of %s = %s" % (headerID, self.__loop_exit_edges[headerID]), __name__, 4)
Example #29
0
 def add_loop_back_edges(self, headerID):
     for predID in self.iteration_edge_sources:
         for succID in self.iteration_edge_destinations:
             predv = self.__ipg.getVertex(predID)
             succv = self.__ipg.getVertex(succID)
             succe = predv.get_successor_edge(succID)
             prede = succv.get_predecessor_edge(predID)
             succe.iteration_edge = True
             prede.iteration_edge = True
             self.edges_added.add((predID, succID))
             debug.debug_message(
                 "(%d, %d) is a loop-back edge for loop with header %d" % (predID, succID, headerID), __name__, 1
             )
Example #30
0
 def __computeInnerRelativeBounds (self, pathg, lnt, pathv, headerv):
     for succID in headerv.getSuccessorIDs():
         succv = lnt.getVertex(succID)
         if isinstance(succv, vertices.HeaderVertex):
             innerHeaderID     = succv.getHeaderID()
             innerProgramPoint = list(pathg.getLoopMonitoredProgramPoints(innerHeaderID))[0]
             innerPathv        = pathg.getProgramPointVertex(innerProgramPoint)
             succe             = innerPathv.getSuccessoredges(edges.PathInformationEdgeType.LOOP_BOUNDS)[0]
             executionCount    = self._relativeExecutionCountsThisRun[pathg][innerHeaderID]
             if executionCount > succe.relative:
                 debug.debug_message("Falsifying conjecture that %d executes at most %d times relative to its innermost enclosing loop. Found %d instead"  % (innerHeaderID, succe.relative, executionCount), 1)
                 succe.relative = executionCount
             self._relativeExecutionCountsThisRun[pathg][innerHeaderID] = 0
Example #31
0
 def add_loop_back_edges(self, headerID):
     for predID in self.iteration_edge_sources:
         for succID in self.iteration_edge_destinations:
             predv = self.__ipg.getVertex(predID)
             succv = self.__ipg.getVertex(succID)
             succe = predv.get_successor_edge(succID)
             prede = succv.get_predecessor_edge(predID)
             succe.iteration_edge = True
             prede.iteration_edge = True
             self.edges_added.add((predID, succID))
             debug.debug_message(
                 "(%d, %d) is a loop-back edge for loop with header %d" %
                 (predID, succID, headerID), __name__, 1)
Example #32
0
def first_pass(filename):
    # Partially build call graph
    program = programs.Program()
    with open(filename) as the_file:
        for line in the_file:
            line = line.lower()
            if line.startswith(cfg_lexeme):
                names = name_regex.findall(line)
                assert len(names) == 2, "Too many names found '%s'" % ' '.join(names)
                cfg      = directed_graphs.CFG()
                cfg.name = names[1]
                debug.debug_message("Found new CFG '%s'" % cfg.name, __name__, 1)
                program.add_CFG(cfg)
    return program
 def tenant(tenant):
     PrintingService.default_start("TENANT")
     debug.debug_message("name: " + tenant["name"])
     debug.debug_message("description: " + tenant["description"])
     debug.debug_message("id: " + tenant["id"])
     debug.debug_message("enabled: " + str(tenant["enabled"]))
     PrintingService.default_end()
Example #34
0
 def __generateTrace (self):
     # To keep track of loop tail iteration count
     self.__functionToTailCount = {}
     # To keep trace of the number of function calls
     self.__numberOfCalls = 0
     callg = self.__program.getCallGraph()
     rootv = callg.getVertex(callg.getRootID())
     self.__currentCallv = rootv
     self.__currentCFG  = self.__program.getCFG(rootv.getName())
     self.__currentLNT   = self.__program.getLNT(rootv.getName())
     self.__currentv     = self.__currentCFG.getVertex(self.__currentCFG.getEntryID())
     self.__vertexID     = self.__currentv.vertexID
     self.__callStack    = []
     while True: 
         self.__outfile.write("%d " % self.__vertexID)
         if self.__vertexID == self.__currentCFG.getExitID():
             if callg.getVertexWithName(self.__currentCFG.getName()) == rootv:
                 # End of the program reached
                 break
             else:
                 # End of function call
                 debug.debug_message("Returning from %s" % self.__currentCallv.getName(), 5)
                 self.__currentCallv, self.__currentCFG, self.__currentLNT, self.__currentv = self.__callStack.pop()
                 self.__vertexID  = self.__currentv.vertexID
                 # Go past the call site
                 self.__chooseSuccessorInICFG()
         elif self.__currentLNT.isLoopTail(self.__vertexID):
             tupleIndex = self.__currentCFG.getName(), self.__vertexID
             if tupleIndex not in self.__functionToTailCount:
                 self.__functionToTailCount[tupleIndex] = 1
                 self.__chooseSuccessorInICFG()
             elif self.__functionToTailCount[tupleIndex] < Generatetraces.maxLoopIterations:
                 self.__functionToTailCount[tupleIndex] += 1
                 self.__chooseSuccessorInICFG()
             else:
                 self.__chooseNonLoopBackEdgeSuccessorInICFG()
         elif self.__currentCFG.isCallSite(self.__vertexID):
             # Make the call. First save state then move to the callee ICFG
             self.__callStack.append((self.__currentCallv, self.__currentCFG, self.__currentLNT, self.__currentv))
             succID              = self.__currentCallv.getSuccessorWithCallSite(self.__vertexID)
             self.__currentCallv = callg.getVertex(succID)
             calleeName          = self.__currentCallv.getName()
             debug.debug_message("Calling %s" % self.__currentCallv.getName(), 5)
             self.__currentCFG  = self.__program.getICFG(calleeName)
             self.__currentLNT   = self.__program.getLNT(calleeName)
             self.__currentv     = self.__currentCFG.getVertex(self.__currentCFG.getEntryID())
             self.__vertexID     = self.__currentv.vertexID
         else:
             self.__chooseSuccessorInICFG()
Example #35
0
 def find_loops_of_states(self, rootID):
     for v in self.__transition_graph:
         self.current_parent[v.vertexID] = v.vertexID
     predom_tree = Dominators(self.__transition_graph)
     for vertexID in reversed(self.__dfs.pre_order):
         v = self.__transition_graph.get_vertex(vertexID)
         for predID in v.predecessors.keys():
             if self.__dfs.isDFSBackedge(predID, vertexID):
                 assert predom_tree.is_ancestor(vertexID, predID), "Non-reducible loop found with DFS backedge %d => %d" % (predID, vertexID)
                 debug.debug_message("%s => %s is a loop-back edge of non-trivial loop" % (predID, vertexID), __name__, 15)
                 self.loop_bodies_per_backedge[(predID, vertexID)]     = set()
                 self.loop_exit_edges_per_backedge[(predID, vertexID)] = set()
                 self.create_header_information(vertexID)
                 self.find_loop_body(predID, vertexID)
                 self.loop_tails.add(predID)
Example #36
0
 def find_loops(self, rootID):
     self.__dfs = DepthFirstSearch (self.__directedg, rootID)
     for vertexID in reversed(self.__dfs.getPreorder()):
         v = self.__directedg.getVertex(vertexID)
         worklist = []
         for predID in v.predecessors.keys():
             if self.__dfs.isDFSBackedge(predID, vertexID):
                 if predID == vertexID:
                     debug.debug_message("%s => %s is a loop-back edge of trivial loop" % (predID, vertexID), __name__, 3)
                     self.add_self_loop(vertexID)
                 else:
                     debug.debug_message("%s => %s is a loop-back edge of non-trivial loop" % (predID, vertexID), __name__, 3)
                     worklist.append(self.__parent[predID])
         
         if worklist:
             self.build_loop_body(worklist, vertexID)
Example #37
0
def first_pass(filename):
    # Partially build call graph
    program = programs.Program()
    with open(filename) as the_file:
        for line in the_file:
            line = line.lower()
            if line.startswith(cfg_lexeme):
                names = name_regex.findall(line)
                assert len(
                    names) == 2, "Too many names found '%s'" % ' '.join(names)
                cfg = directed_graphs.CFG()
                cfg.name = names[1]
                debug.debug_message("Found new CFG '%s'" % cfg.name, __name__,
                                    1)
                program.add_CFG(cfg)
    return program
Example #38
0
 def add_acyclic_edges(self, headerID):
     # Compute a topological sort on the ICFG
     dfs = trees.DepthFirstSearch(self.__icfg, self.__icfg.get_entryID())
     if self.__ipg.hasVertex(self.__icfg.get_entryID()):
         # If the header of the loop is an ipoint then it is the only
         # destination of an iteration edge
         self.iteration_edge_destinations.add(self.__icfg.get_entryID())
     # Perform data-flow analysis
     changed = True
     while changed:
         changed = False
         for vertexID in reversed(dfs.getPostorder()):
             debug.debug_message("At vertex %d" % vertexID, __name__, 1)
             v = self.__icfg.getVertex(vertexID)
             if self.__enhanced_lnt.is_loop_header(
                     vertexID) and vertexID != self.__icfg.get_entryID():
                 # Inner header detected
                 self.add_loop_entry_edges(v)
                 self.add_ipoints_to_abstract_vertex(v)
             else:
                 for predID in v.predecessors.keys():
                     if self.__ipg.hasVertex(predID):
                         if self.__ipg.hasVertex(vertexID):
                             self.add_edge(predID, vertexID)
                         else:
                             self.vertex_to_reachable[vertexID].add(predID)
                     else:
                         for keyID in self.vertex_to_reachable[predID]:
                             if self.__ipg.hasVertex(
                                     keyID) and self.__ipg.hasVertex(
                                         vertexID):
                                 self.add_edge(keyID, vertexID)
                             elif not self.__ipg.hasVertex(
                                     keyID) and self.__ipg.hasVertex(
                                         vertexID):
                                 self.iteration_edge_destinations.add(
                                     vertexID)
                             else:
                                 self.vertex_to_reachable[vertexID].add(
                                     keyID)
         if vertexID in self.__enhanced_lnt.get_loop_tails(headerID):
             if self.__ipg.hasVertex(vertexID):
                 self.iteration_edge_sources.add(vertexID)
             else:
                 for keyID in self.vertex_to_reachable[vertexID]:
                     if self.__ipg.hasVertex(keyID):
                         self.iteration_edge_sources.add(keyID)
def read_file(filename):
    program = programs.Program()
    cfg = None
    bb = None
    with open(filename) as the_file:
        for line in the_file:
            line = line.lower()
            if line.startswith(cfg_lexeme):
                names = name_regex.findall(line)
                assert len(
                    names) == 2, "Too many names found '%s'" % ' '.join(names)
                cfg = directed_graphs.CFG()
                cfg.name = names[1]
                program.add_CFG(cfg)
                debug.debug_message("Found new CFG '%s'" % cfg.name, __name__,
                                    1)
            elif line.startswith(basic_block_lexeme):
                assert cfg, "Found basic block but current CFG is null"
                ids = int_regex.findall(line)
                assert len(
                    ids
                ) == 1, "Too many identifiers found '%s'" % ' '.join(ids)
                assert ids[0].isdigit(
                ), "Vertex identifier '%s' is not an integer" % ids[0]
                bb = vertices.Vertex(int(ids[0]))
                cfg.add_vertex(bb)
            elif line.startswith(successors_lexeme):
                assert bb, "Found edge but current basic block is null"
                edges = edges_regex.findall(line)
                for edge in edges:
                    a_tuple = edge_tuple_regex.findall(edge)
                    assert len(
                        a_tuple
                    ) == 2, "Too many components in edge tuple: %s" % edge
                    assert a_tuple[
                        0] == cfg.name, "Call edge found which is currently not handled"
                    assert a_tuple[1].isdigit(
                    ), "Successor identifier '%s' is not an integer" % a_tuple[
                        1]
                    bb.add_successor(int(a_tuple[1]))
    for cfg in program.cfgs.values():
        cfg.add_predecessor_edges()
        cfg.set_entry_and_exit()
        cfg.add_dummy_loop_between_exit_and_entry()
        udraw.make_file(cfg, "%s.cfg" % (cfg.name))
    return program
Example #40
0
def compile_program(program):
    debug.verbose_message("Compiling program", __name__)
    optimisation = ""
    extraFlags = ""
    if config.Arguments.flags:
        for flag in config.Arguments.flags:
            extraFlags += "-%s " % flag
            if re.match(r"O[0-3]+", flag):
                optimisation = flag
    binary = program[:-2] + optimisation
    cmd = "%s -fno-stack-protector -static %s %s -o %s" % (config.Arguments.GCC, extraFlags, program, binary)
    debug.debug_message("Compiling with command '%s'" % cmd, 1)
    proc = subprocess.Popen(cmd, shell=True, stdout=sys.stdout, stderr=sys.stderr)
    returncode = proc.wait()
    if returncode:
        debug.exit_message("Compiling '%s' with '%s' failed" % (program, cmd))
    return binary
Example #41
0
 def create_basic_blocks(self):
     for function_name in self.functions:
         debug.debug_message("Identifying basic blocks in '%s'" % function_name, __name__, 10)
         cfg      = directed_graphs.CFG()
         cfg.name = function_name
         self.program.addCFG(cfg)
         bb = None
         for instruction in self.function_to_instructions[function_name]:
             if instruction in self.function_to_leaders[function_name]:
                 debug.debug_message("Instruction @ %s is a leader" % hex(instruction.address), __name__, 10)
                 bb       = vertices.BasicBlock(self.next_vertexID, function_name)
                 cfg.addVertex(bb)
                 self.next_vertexID += 1
             assert bb, "Basic block is currently null"
             bb.instructions.append(instruction)
             self.instruction_to_basic_block[instruction] = bb
             if self.is_jump_table_branch(instruction):
                 self.function_to_jump_table_basic_blocks[function_name].append(bb)
Example #42
0
 def __computeInnerRelativeBounds(self, pathg, lnt, pathv, headerv):
     for succID in headerv.getSuccessorIDs():
         succv = lnt.getVertex(succID)
         if isinstance(succv, vertices.HeaderVertex):
             innerHeaderID = succv.getHeaderID()
             innerProgramPoint = list(
                 pathg.getLoopMonitoredProgramPoints(innerHeaderID))[0]
             innerPathv = pathg.getProgramPointVertex(innerProgramPoint)
             succe = innerPathv.getSuccessoredges(
                 edges.PathInformationEdgeType.LOOP_BOUNDS)[0]
             executionCount = self._relativeExecutionCountsThisRun[pathg][
                 innerHeaderID]
             if executionCount > succe.relative:
                 debug.debug_message(
                     "Falsifying conjecture that %d executes at most %d times relative to its innermost enclosing loop. Found %d instead"
                     % (innerHeaderID, succe.relative, executionCount), 1)
                 succe.relative = executionCount
             self._relativeExecutionCountsThisRun[pathg][innerHeaderID] = 0
Example #43
0
 def add_loop_entry_edges(self, v):
     debug.debug_message("Inner header %d detected" % v.vertexID, __name__, 1)
     inner_loop_info = self.loop_by_loop_info.ipgs_per_loop[v.vertexID]
     for predID in v.predecessors.keys():
         if self.__ipg.hasVertex(predID):
             for succID in inner_loop_info.iteration_edge_destinations:
                 self.add_edge(predID, succID)
         else:
             for keyID in self.vertex_to_reachable[predID]:
                 if self.__ipg.hasVertex(keyID):
                     for succID in inner_loop_info.iteration_edge_destinations:
                         self.add_edge(keyID, succID)
                 else:
                     # The key is a header vertex.
                     # This means that all the destinations of iteration edges of
                     # the inner loop are also destinations of iterations edges of
                     # the outer loop
                     self.iteration_edge_destinations.update(inner_loop_info.iteration_edge_destinations)
Example #44
0
def run_gem5(binary):
    test_vector_properties = TestVectorProperties()
    run = get_next_trace_file_number(binary) + 1
    # Now run the program n times
    random_test_vectors = RandomGeneration(test_vector_properties)
    gem5traces          = []
    for i in xrange(run, config.Arguments.tests + run):
        traceFile  = "%s.%s.%d.gz" % (os.path.basename(binary), "trace", i)
        cmd        = '%s --debug-flags=Fetch --trace-file=%s %s --cpu-type=timing -c %s -o "%s"' % \
        (config.Arguments.gem5_simulator, traceFile, config.Arguments.gem5_config, binary, random_test_vectors.next_test_vector())
        debug.debug_message("Running '%s' on gem5" % cmd, 1)
        proc       = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)    
        returncode = proc.wait()
        if returncode:
            debug.exit_message("Running '%s' failed" % cmd)
        gem5_trace = os.path.abspath(os.getcwd()) + os.sep + config.Arguments.m5_trace_directory + os.sep + traceFile
        assert os.path.exists(gem5_trace), "Expected to find gem5 trace in '%s' but it is not there" % gem5_trace
        gem5traces.append(gem5_trace)
    return gem5traces
Example #45
0
 def add_jump_table_edges(self):
     for function_name in self.functions:
         debug.debug_message(
             "Adding jump table edges in '%s'" % function_name, __name__,
             10)
         cfg = self.program.cfgs[function_name]
         i = 0
         hasJumpTablePredecessor = set()
         for instr in self.function_to_instructions[function_name]:
             # If the instruction loads into the PC...
             if self.is_jump_table_branch(instr):
                 # Get the number of directives associated with this instruction to work out
                 # how many arms it has
                 assert instr in self.jump_table_to_directives
                 numberOfBranchArms = len(
                     self.jump_table_to_directives[instr])
                 if instr.the_instruction[0] == InstructionSet.LoadInstructions[3] \
                 or instr.the_instruction[0] == InstructionSet.LoadInstructions[4]:
                     numberOfBranchArms = 3
                 predv = cfg.get_basic_block_with_address(instr.address)
                 # Now go through each successive address, get the vertex associated with
                 # that address, and add an edge if the address belongs to a newly discovered
                 # basic block
                 for j in range(
                         i,
                         len(self.function_to_instructions[function_name])):
                     nextInstr = self.function_to_instructions[
                         function_name][j]
                     address = nextInstr.address
                     if not predv.hasAddress(address):
                         succv = cfg.get_basic_block_with_address(address)
                         if not predv.hasSuccessor(
                                 succv.vertexID
                         ) and succv not in hasJumpTablePredecessor:
                             cfg.addEdge(predv.vertexID, succv.vertexID)
                             hasJumpTablePredecessor.add(succv)
                             numberOfBranchArms -= 1
                         # We know how many arms to expect. As soon as the supply has been
                         # exhausted, stop adding edges
                         if not numberOfBranchArms or self.is_jump_table_branch(
                                 nextInstr):
                             break
             i += 1
Example #46
0
 def query(self, the_pair):    
     debug.debug_message("Computing lca(%s)" % (the_pair,), __name__, 1) 
     if isinstance(self.tree, LoopNests):
         the_pair = (self.tree.program_point_to_lnt_vertexID[the_pair[0]], 
                     self.tree.program_point_to_lnt_vertexID[the_pair[1]])
     lowest_level = self.dummy_level
     level_index  = 2 * self.tree.number_of_vertices()
     if self.representative[the_pair[0]] < self.representative[the_pair[1]]:
         startIndex = self.representative[the_pair[0]]
         endIndex   = self.representative[the_pair[1]]
     else:
         startIndex = self.representative[the_pair[1]]
         endIndex   = self.representative[the_pair[0]]
     for i in range(startIndex, endIndex+1):
         if self.level[i] < lowest_level:
             lowest_level = self.level[i]
             level_index  = i
     debug.debug_message("lca(%s) = %d" % (the_pair, self.euler_tour[level_index]), __name__, 15)
     return self.euler_tour[level_index]
Example #47
0
 def inline_calls(self):
     debug.verbose_message("Inlining to create single CFG", __name__)
     rootv = self.callg.getVertex(self.callg.rootID)
     dfs   = directed_graphs.DepthFirstSearch(self.callg, rootv.vertexID)
     for vertexID in dfs.post_order:
         succv = self.callg.getVertex(vertexID)
         for calle in succv.predecessors.values():
             predv = self.callg.getVertex(calle.vertexID)
             for call_siteID in calle.getCallSites():
                 debug.debug_message("Inlining '%s' into '%s' at call site %d" % (succv.name, predv.name, call_siteID), 1)
                 self.__doInline(self.cfgs[predv.name], self.cfgs[succv.name], call_siteID)
                 self.cfgs[succv.name].remove_call_site(call_siteID)
     for vertexID in dfs.post_order:
         callv = self.callg.getVertex(vertexID)
         if callv != rootv:
             self.remove_function(callv.name)
         else:
             cfg = self.cfgs[rootv.name]
             cfg.addEdge(cfg.get_exitID(), cfg.get_entryID())
Example #48
0
 def add_loop_entry_edges(self, v):
     debug.debug_message("Inner header %d detected" % v.vertexID, __name__,
                         1)
     inner_loop_info = self.loop_by_loop_info.ipgs_per_loop[v.vertexID]
     for predID in v.predecessors.keys():
         if self.__ipg.hasVertex(predID):
             for succID in inner_loop_info.iteration_edge_destinations:
                 self.add_edge(predID, succID)
         else:
             for keyID in self.vertex_to_reachable[predID]:
                 if self.__ipg.hasVertex(keyID):
                     for succID in inner_loop_info.iteration_edge_destinations:
                         self.add_edge(keyID, succID)
                 else:
                     # The key is a header vertex.
                     # This means that all the destinations of iteration edges of
                     # the inner loop are also destinations of iterations edges of
                     # the outer loop
                     self.iteration_edge_destinations.update(
                         inner_loop_info.iteration_edge_destinations)
Example #49
0
    def identify_leaders(self):
        functionToBranchTargets = {}
        for function_name in self.functions:
            debug.debug_message("Identifying leaders in '%s'" % function_name,
                                __name__, 10)
            self.function_to_leaders[function_name] = set()
            functionToBranchTargets[function_name] = set()
            newLeader = True
            noopAfterJumpTableBranch = False
            index = 0
            for instruction, nextInstruction in utils.peekahead_iterator(
                    self.function_to_instructions[function_name]):
                if newLeader:
                    self.function_to_leaders[function_name].add(instruction)
                    newLeader = False
                elif noopAfterJumpTableBranch:
                    assert instruction.the_instruction[
                        1] in InstructionSet.Nops, "Did not find an no-op after jump table branch. Instead found %s" % instruction
                    noopAfterJumpTableBranch = False
                    newLeader = True

                op = instruction.the_instruction[1]
                if op in InstructionSet.Branches:
                    newLeader = True
                    addressTarget = int(instruction.the_instruction[2], 16)
                    functionToBranchTargets[function_name].add(addressTarget)
                elif self.is_jump_table_branch(instruction):
                    # Look for instructions with an explicit load into the PC
                    debug.debug_message(
                        "Instruction '%s' is loading a value into the PC" %
                        instruction, __name__, 10)
                    if nextInstruction and nextInstruction.the_instruction[
                            0] in InstructionSet.Nops:
                        noopAfterJumpTableBranch = True
                    else:
                        newLeader = True
                index += 1
            for instruction in self.function_to_instructions[function_name]:
                if instruction.address in functionToBranchTargets[
                        function_name]:
                    self.function_to_leaders[function_name].add(instruction)
Example #50
0
def compile_program(program):
    debug.verbose_message("Compiling program", __name__)
    optimisation = ""
    extraFlags = ""
    if config.Arguments.flags:
        for flag in config.Arguments.flags:
            extraFlags += "-%s " % flag
            if re.match(r'O[0-3]+', flag):
                optimisation = flag
    binary = program[:-2] + optimisation
    cmd = "%s -fno-stack-protector -static %s %s -o %s" % (
        config.Arguments.GCC, extraFlags, program, binary)
    debug.debug_message("Compiling with command '%s'" % cmd, 1)
    proc = subprocess.Popen(cmd,
                            shell=True,
                            stdout=sys.stdout,
                            stderr=sys.stderr)
    returncode = proc.wait()
    if returncode:
        debug.exit_message("Compiling '%s' with '%s' failed" % (program, cmd))
    return binary
Example #51
0
 def __parse (self, tracefile):
     runID = 0
     with open(tracefile, 'r') as f:
         for line in f:
             if line.startswith(newTrace):
                 runID += 1
                 debug.debug_message("=====> Run %d" % runID, 1)
                 self._allruns.add(runID)
                 self.__reset()
             elif line.startswith(endTrace):
                 self.__handleReturn()
             else:
                 lexemes = shlex.split(line)
                 for lex in lexemes:
                     nextID = int(lex)
                     if nextID == self.__rootCFG.getEntryID():
                         self.__currentBB = self.__currentCFG.getVertex(nextID)
                     else:
                         found = False
                         for succID in self.__currentBB.getSuccessorIDs():
                             if succID == nextID:
                                 self.__predBB    = self.__currentBB
                                 self.__currentBB = self.__currentCFG.getVertex(succID)
                                 # We have switched basic blocks in the current CFG
                                 self._analyseCFGEdge(self.__currentPathg, self.__currentLNT, self.__predBB.vertexID, self.__currentBB.vertexID)
                                 found = True
                                 break
                         if not found:
                             if self.__currentBB.vertexID == self.__currentCFG.getExitID():
                                 succIDs = self.__currentBB.getSuccessorIDs()
                                 assert len(succIDs) == 1
                                 succv            = self.__currentCFG.getVertex(succIDs[0])
                                 self.__predBB    = self.__currentBB
                                 self.__currentBB = succv
                                 # Since we have switched basic blocks in the current CFG, analyse the super blocks
                                 self._analyseCFGEdge(self.__currentPathg, self.__currentLNT, self.__predBB.vertexID, self.__currentBB.vertexID)             
                             else:
                                 self.__handleCall(nextID)    
                     # We have switched basic blocks in the current CFG
                     self._analyseCFGVertex(self.__currentPathg, self.__currentLNT, self.__currentBB.vertexID)
Example #52
0
 def add_acyclic_edges(self, headerID):
     # Compute a topological sort on the ICFG
     dfs = trees.DepthFirstSearch(self.__icfg, self.__icfg.get_entryID())
     if self.__ipg.hasVertex(self.__icfg.get_entryID()):
         # If the header of the loop is an ipoint then it is the only
         # destination of an iteration edge
         self.iteration_edge_destinations.add(self.__icfg.get_entryID())
     # Perform data-flow analysis
     changed = True
     while changed:
         changed = False
         for vertexID in reversed(dfs.getPostorder()):
             debug.debug_message("At vertex %d" % vertexID, __name__, 1)
             v = self.__icfg.getVertex(vertexID)
             if self.__enhanced_lnt.is_loop_header(vertexID) and vertexID != self.__icfg.get_entryID():
                 # Inner header detected
                 self.add_loop_entry_edges(v)
                 self.add_ipoints_to_abstract_vertex(v)
             else:
                 for predID in v.predecessors.keys():
                     if self.__ipg.hasVertex(predID):
                         if self.__ipg.hasVertex(vertexID):
                             self.add_edge(predID, vertexID)
                         else:
                             self.vertex_to_reachable[vertexID].add(predID)
                     else:
                         for keyID in self.vertex_to_reachable[predID]:
                             if self.__ipg.hasVertex(keyID) and self.__ipg.hasVertex(vertexID):
                                 self.add_edge(keyID, vertexID)
                             elif not self.__ipg.hasVertex(keyID) and self.__ipg.hasVertex(vertexID):
                                 self.iteration_edge_destinations.add(vertexID)
                             else:
                                 self.vertex_to_reachable[vertexID].add(keyID)
         if vertexID in self.__enhanced_lnt.get_loop_tails(headerID):
             if self.__ipg.hasVertex(vertexID):
                 self.iteration_edge_sources.add(vertexID)
             else:
                 for keyID in self.vertex_to_reachable[vertexID]:
                     if self.__ipg.hasVertex(keyID):
                         self.iteration_edge_sources.add(keyID)
Example #53
0
 def extract_instructions(self, filename):
     with open(filename, 'r') as f:
         parse                       = False
         last_instruction            = None
         last_jump_table_instruction = None
         current_function            = None
         for line in f:
             if parse:
                 if re.match(r'[0-9a-fA-F]+\s<.*>.*', line):
                     if last_instruction:
                         assert current_function, "No function detected yet"
                         self.function_to_last_address[current_function]         = last_instruction.address
                         self.last_address_to_function[last_instruction.address] = current_function 
                     lexemes = shlex.split(line)
                     assert len(lexemes) == 2, "Unable to handle disassembly line %s" % line
                     address       = int(lexemes[0], 16)
                     function_name = lexemes[1][1:-2]
                     debug.debug_message("Detected function '%s' @ start address %d" % (function_name, address), __name__, 10)
                     self.start_address_to_function[address]                    = function_name
                     current_function                                           = function_name
                     self.function_to_instructions[current_function]            = []
                     self.function_to_directives[current_function]              = []
                     self.function_to_start_address[current_function]           = address
                     self.function_to_jump_table_basic_blocks[current_function] = []
                     last_jump_table_instruction                                = None
                 elif re.match(r'\s*[0-9a-fA-F]+:.*', line):
                     # Ignore directives reserving space for data
                     if '.word' not in line and '.short' not in line and '.byte' not in line:                  
                         instruction = vertices.BasicBlock.Instruction.get_instruction(line)
                         self.function_to_instructions[current_function].append(instruction)
                         last_instruction = instruction
                         if self.is_jump_table_branch(instruction):
                             last_jump_table_instruction = instruction
                             self.jump_table_to_directives[instruction] = []
                     else:
                         self.function_to_directives[current_function].append(line)
                         if last_jump_table_instruction:
                             self.jump_table_to_directives[last_jump_table_instruction].append(line)   
             elif line.startswith('Disassembly of section'):
                 parse = '.text' in line
Example #54
0
 def add_edges(self):
     for function_name in self.functions:
         debug.debug_message("Adding edges in '%s'" % function_name, __name__, 10)
         cfg   = self.program.cfgs[function_name]
         predID = vertices.dummyID
         for instruction in self.function_to_instructions[function_name]:
             v = self.instruction_to_basic_block[instruction]
             if predID != vertices.dummyID:
                 cfg.addEdge(predID, v.vertexID)
                 predID = vertices.dummyID
             if v.instructions[-1] == instruction:
                 if instruction.the_instruction[1] == InstructionSet.Call:
                     callee_name = self.get_callee_name(instruction.the_instruction)
                     cfg.add_call_site(v.vertexID, callee_name)
                     self.program.callg.addEdge(function_name, callee_name, v.vertexID)
                     predID = v.vertexID
                 elif instruction.the_instruction[1] in InstructionSet.UnconditionalJumps:
                     jump_address = int(instruction.the_instruction[2], 16)
                     if jump_address >= self.function_to_start_address[function_name] and jump_address <= self.function_to_last_address[function_name]:
                         succv = cfg.get_basic_block_with_address(jump_address)
                         cfg.addEdge(v.vertexID, succv.vertexID)
                     else:
                         callee_name = self.start_address_to_function[jump_address]
                         cfg.add_call_site(v.vertexID, callee_name)
                         self.program.callg.addEdge(function_name, callee_name, v.vertexID)
                         predID = v.vertexID
                 elif instruction.the_instruction[1] in InstructionSet.Branches:
                     branch_address = int(instruction.the_instruction[2], 16)
                     if branch_address >= self.function_to_start_address[function_name] and branch_address <= self.function_to_last_address[function_name]:
                         succv = cfg.get_basic_block_with_address(branch_address)
                         cfg.addEdge(v.vertexID, succv.vertexID)
                     else:
                         callee_name = self.get_callee_name(instruction.the_instruction)
                         cfg.add_call_site(v.vertexID, callee_name)
                         self.program.callg.addEdge(function_name, callee_name, v.vertexID)
                     predID = v.vertexID
                 elif v in self.function_to_jump_table_basic_blocks[function_name]:
                     pass
                 else:
                     predID = v.vertexID
Example #55
0
 def __initialise (self):
     self.__currentContextv = None
     self.__currentCFG      = None
     self.__currentLNT      = None
     self.__predBB          = None
     self.__currentBB       = None
     self.__currentHeaderID = None
     self.__currentPathg    = None
     self.__time1           = None
     self.__stack           = []
     self.__contextg        = self._program.getContextGraph()
     rootv                  = self.__contextg.getVertex(self.__contextg.getRootID())
     self.__rootCFG         = self._program.getCFG(rootv.getName())
     self.__firstAddr       = self.__rootCFG.getFirstInstruction().getAddress()
     lastbb                 = self.__rootCFG.getVertex(self.__rootCFG.getExitID())
     for instruction in reversed(lastbb.getInstructions()):
         if instruction.getOp() not in arm.armInstructionSet.Nops:
             self.__lastAddr = instruction.getAddress()
             break
     assert self.__lastAddr, "Unable to find last address"
     debug.debug_message("Start address of root function '%s' is %s" % (rootv.getName(), hex(self.__firstAddr)), 1)    
     debug.debug_message("End address of root function '%s' is %s" % (rootv.getName(), hex(self.__lastAddr)), 1)
Example #56
0
 def __parse (self, traceFiles):
     runID = 0
     for filename in traceFiles:
         parsing = False 
         with gzip.open(filename, 'r') as f:
             runID += 1
             self._allruns.add(runID)
             debug.debug_message("Analysing gem5 trace file '%s'" % filename, 1)
             for line in f:
                 lexemes  = shlex.split(line)
                 PCLexeme = lexemes[-1]
                 assert len(PCLexeme) == 11, "Unable to parse program counter %s" % PCLexeme
                 try:
                     time     = int(lexemes[0][:-1])
                     PCLexeme = PCLexeme[5:]
                     PC       = int(PCLexeme, 16)
                     if PC == self.__firstAddr:
                         self.__time1           = time
                         startTime              = time
                         parsing                = True
                         self.__currentContextv = self.__contextg.getVertex(self.__contextg.getRootID())
                         self.__currentCFG      = self._program.getCFG(self.__currentContextv.getName())
                         self.__currentLNT      = self._program.getLNT(self.__currentContextv.getName())
                         self.__currentPathg    = self._program.getPathInfoGraph(self.__currentContextv.getName())
                         self.__predBB          = None
                         self.__currentBB       = self.__currentCFG.getVertex(self.__currentCFG.getEntryID())
                         self._analyseCFGVertex(self.__currentPathg, self.__currentLNT, self.__currentBB.vertexID)     
                     if parsing:
                         self.__parseAddress (time, PC, runID)
                     if PC == self.__lastAddr:
                         # Stop parsing
                         parsing = False
                         # Compute the HWMT
                         totalTime = time - startTime
                         self._longestTime = max(self._longestTime, totalTime)
                         # Falsify conjectures
                         self._endOfFunction(self.__currentCFG, self.__currentLNT, self.__currentPathg)
                 except ValueError:
                     debug.exit_message("Cannot cast %s into an integer: it is not a hexadecimal string" % PCLexeme)