|  |  |  | @ -57,7 +57,17 @@ module TransferFunctionsNodesBasicCost = struct | 
			
		
	
		
			
				
					|  |  |  |  |     { inferbo_invariant_map: BufferOverrunAnalysis.invariant_map | 
			
		
	
		
			
				
					|  |  |  |  |     ; integer_type_widths: Typ.IntegerWidths.t } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let cost_atomic_instruction = BasicCost.one | 
			
		
	
		
			
				
					|  |  |  |  |   let callee_OperationCost callee_cost_record integer_type_widths inferbo_mem callee_pname params = | 
			
		
	
		
			
				
					|  |  |  |  |     let callee_cost = CostDomain.get_operation_cost callee_cost_record in | 
			
		
	
		
			
				
					|  |  |  |  |     if BasicCost.is_symbolic callee_cost then | 
			
		
	
		
			
				
					|  |  |  |  |       instantiate_cost integer_type_widths ~inferbo_caller_mem:inferbo_mem ~callee_pname ~params | 
			
		
	
		
			
				
					|  |  |  |  |         ~callee_cost | 
			
		
	
		
			
				
					|  |  |  |  |     else callee_cost | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let callee_AllocationCost cost_record = CostDomain.get_allocation_cost cost_record | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let callee_IOCost cost_record = CostDomain.get_IO_cost cost_record | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let exec_instr_cost integer_type_widths inferbo_mem | 
			
		
	
		
			
				
					|  |  |  |  |       (astate : CostDomain.NodeInstructionToCostMap.t) {ProcData.pdesc} (node : CFG.Node.t) instr : | 
			
		
	
	
		
			
				
					|  |  |  | @ -69,24 +79,29 @@ module TransferFunctionsNodesBasicCost = struct | 
			
		
	
		
			
				
					|  |  |  |  |           let callee_cost = | 
			
		
	
		
			
				
					|  |  |  |  |             match CostModels.Call.dispatch () callee_pname params with | 
			
		
	
		
			
				
					|  |  |  |  |             | Some model -> | 
			
		
	
		
			
				
					|  |  |  |  |                 model inferbo_mem | 
			
		
	
		
			
				
					|  |  |  |  |                 CostDomain.set_operation_cost (model inferbo_mem) CostDomain.zero_record | 
			
		
	
		
			
				
					|  |  |  |  |             | None -> ( | 
			
		
	
		
			
				
					|  |  |  |  |               match Payload.read pdesc callee_pname with | 
			
		
	
		
			
				
					|  |  |  |  |               | Some {post= {CostDomain.basic_operation_cost= callee_cost}} -> | 
			
		
	
		
			
				
					|  |  |  |  |                   if BasicCost.is_symbolic callee_cost then | 
			
		
	
		
			
				
					|  |  |  |  |                     instantiate_cost integer_type_widths ~inferbo_caller_mem:inferbo_mem | 
			
		
	
		
			
				
					|  |  |  |  |                       ~callee_pname ~params ~callee_cost | 
			
		
	
		
			
				
					|  |  |  |  |                   else callee_cost | 
			
		
	
		
			
				
					|  |  |  |  |               | Some {post= callee_cost_record} -> | 
			
		
	
		
			
				
					|  |  |  |  |                   let callee_operation_cost = | 
			
		
	
		
			
				
					|  |  |  |  |                     callee_OperationCost callee_cost_record integer_type_widths inferbo_mem | 
			
		
	
		
			
				
					|  |  |  |  |                       callee_pname params | 
			
		
	
		
			
				
					|  |  |  |  |                   in | 
			
		
	
		
			
				
					|  |  |  |  |                   let callee_allocation_cost = callee_AllocationCost callee_cost_record in | 
			
		
	
		
			
				
					|  |  |  |  |                   let callee_IO_cost = callee_IOCost callee_cost_record in | 
			
		
	
		
			
				
					|  |  |  |  |                   CostDomain.mk_cost_record ~operation_cost:callee_operation_cost | 
			
		
	
		
			
				
					|  |  |  |  |                     ~allocation_cost:callee_allocation_cost ~io_cost:callee_IO_cost | 
			
		
	
		
			
				
					|  |  |  |  |               | None -> | 
			
		
	
		
			
				
					|  |  |  |  |                   cost_atomic_instruction ) | 
			
		
	
		
			
				
					|  |  |  |  |                   CostDomain.unit_cost_atomic_operation ) | 
			
		
	
		
			
				
					|  |  |  |  |           in | 
			
		
	
		
			
				
					|  |  |  |  |           CostDomain.NodeInstructionToCostMap.add key callee_cost astate | 
			
		
	
		
			
				
					|  |  |  |  |       | Sil.Load _ | Sil.Store _ | Sil.Call _ | Sil.Prune _ -> | 
			
		
	
		
			
				
					|  |  |  |  |           CostDomain.NodeInstructionToCostMap.add key cost_atomic_instruction astate | 
			
		
	
		
			
				
					|  |  |  |  |           CostDomain.NodeInstructionToCostMap.add key CostDomain.unit_cost_atomic_operation astate | 
			
		
	
		
			
				
					|  |  |  |  |       | Sil.ExitScope _ -> ( | 
			
		
	
		
			
				
					|  |  |  |  |         match CFG.Node.kind node with | 
			
		
	
		
			
				
					|  |  |  |  |         | Procdesc.Node.Start_node -> | 
			
		
	
		
			
				
					|  |  |  |  |             CostDomain.NodeInstructionToCostMap.add key cost_atomic_instruction astate | 
			
		
	
		
			
				
					|  |  |  |  |             CostDomain.NodeInstructionToCostMap.add key CostDomain.unit_cost_atomic_operation | 
			
		
	
		
			
				
					|  |  |  |  |               astate | 
			
		
	
		
			
				
					|  |  |  |  |         | _ -> | 
			
		
	
		
			
				
					|  |  |  |  |             astate ) | 
			
		
	
		
			
				
					|  |  |  |  |       | _ -> | 
			
		
	
	
		
			
				
					|  |  |  | @ -611,13 +626,10 @@ let compute_errlog_extras cost = | 
			
		
	
		
			
				
					|  |  |  |  |   ; cost_degree= BasicCost.degree cost |> Option.map ~f:Polynomials.Degree.encode_to_int } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | (* Calculate the final Worst Case Execution Time predicted for each node. | 
			
		
	
		
			
				
					|  |  |  |  |    It uses the basic cost of the nodes (computed previously by AnalyzerNodesBasicCost) | 
			
		
	
		
			
				
					|  |  |  |  |    and MinTrees which give an upperbound on the number of times a node can be executed | 
			
		
	
		
			
				
					|  |  |  |  | *) | 
			
		
	
		
			
				
					|  |  |  |  | (* Calculate the final Worst Case Execution Time predicted for each node. *) | 
			
		
	
		
			
				
					|  |  |  |  | module TransferFunctionsWCET = struct | 
			
		
	
		
			
				
					|  |  |  |  |   module CFG = InstrCFG | 
			
		
	
		
			
				
					|  |  |  |  |   module Domain = AbstractDomain.Pair (BasicCost) (ReportedOnNodes) | 
			
		
	
		
			
				
					|  |  |  |  |   module Domain = AbstractDomain.Pair (CostDomain.VariantCostMap) (ReportedOnNodes) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   type extras = extras_TransferFunctionsWCET | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -668,9 +680,10 @@ module TransferFunctionsWCET = struct | 
			
		
	
		
			
				
					|  |  |  |  |       preds | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   let map_cost get_node_nb_exec m : BasicCost.t = | 
			
		
	
		
			
				
					|  |  |  |  |   let map_operation_cost get_node_nb_exec m : BasicCost.t = | 
			
		
	
		
			
				
					|  |  |  |  |     CostDomain.NodeInstructionToCostMap.fold | 
			
		
	
		
			
				
					|  |  |  |  |       (fun ((node_id, _) as instr_node_id) c acc -> | 
			
		
	
		
			
				
					|  |  |  |  |       (fun ((node_id, _) as instr_node_id) c_record acc -> | 
			
		
	
		
			
				
					|  |  |  |  |         let c = CostDomain.get_operation_cost c_record in | 
			
		
	
		
			
				
					|  |  |  |  |         let t = get_node_nb_exec node_id in | 
			
		
	
		
			
				
					|  |  |  |  |         let c_node = BasicCost.mult c t in | 
			
		
	
		
			
				
					|  |  |  |  |         let c_node' = BasicCost.plus acc c_node in | 
			
		
	
	
		
			
				
					|  |  |  | @ -693,7 +706,7 @@ module TransferFunctionsWCET = struct | 
			
		
	
		
			
				
					|  |  |  |  |       | Some node_map -> | 
			
		
	
		
			
				
					|  |  |  |  |           L.(debug Analysis Medium) | 
			
		
	
		
			
				
					|  |  |  |  |             "@\n [AnalyzerWCET] Final map for node: %a @\n" CFG.Node.pp_id instr_node_id ; | 
			
		
	
		
			
				
					|  |  |  |  |           map_cost get_node_nb_exec node_map | 
			
		
	
		
			
				
					|  |  |  |  |           map_operation_cost get_node_nb_exec node_map | 
			
		
	
		
			
				
					|  |  |  |  |       | _ -> | 
			
		
	
		
			
				
					|  |  |  |  |           assert false | 
			
		
	
		
			
				
					|  |  |  |  |     in | 
			
		
	
	
		
			
				
					|  |  |  | @ -715,7 +728,11 @@ module TransferFunctionsWCET = struct | 
			
		
	
		
			
				
					|  |  |  |  |           ReportedOnNodes.add nid reported_so_far ) | 
			
		
	
		
			
				
					|  |  |  |  |         else reported_so_far | 
			
		
	
		
			
				
					|  |  |  |  |       in | 
			
		
	
		
			
				
					|  |  |  |  |       (cost_node, reported_so_far) | 
			
		
	
		
			
				
					|  |  |  |  |       let cost_map = | 
			
		
	
		
			
				
					|  |  |  |  |         CostDomain.mk_cost_record ~operation_cost:cost_node ~allocation_cost:BasicCost.zero | 
			
		
	
		
			
				
					|  |  |  |  |           ~io_cost:BasicCost.zero | 
			
		
	
		
			
				
					|  |  |  |  |       in | 
			
		
	
		
			
				
					|  |  |  |  |       (cost_map, reported_so_far) | 
			
		
	
		
			
				
					|  |  |  |  |     in | 
			
		
	
		
			
				
					|  |  |  |  |     astate' | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -725,7 +742,8 @@ end | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | module AnalyzerWCET = AbstractInterpreter.MakeRPO (TransferFunctionsWCET) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | let check_and_report_top_and_bottom cost proc_desc summary = | 
			
		
	
		
			
				
					|  |  |  |  | let check_and_report_top_and_bottom cost_record proc_desc summary = | 
			
		
	
		
			
				
					|  |  |  |  |   let cost = CostDomain.get_operation_cost cost_record in | 
			
		
	
		
			
				
					|  |  |  |  |   let report issue suffix = | 
			
		
	
		
			
				
					|  |  |  |  |     let message = | 
			
		
	
		
			
				
					|  |  |  |  |       F.asprintf "The execution time of the function %a %s" Typ.Procname.pp | 
			
		
	
	
		
			
				
					|  |  |  | @ -793,20 +811,20 @@ let checker {Callbacks.tenv; proc_desc; integer_type_widths; summary} : Summary. | 
			
		
	
		
			
				
					|  |  |  |  |     if Config.write_html then NodePrinter.finish_session start_node ; | 
			
		
	
		
			
				
					|  |  |  |  |     ConstraintSolver.get_node_nb_exec equalities | 
			
		
	
		
			
				
					|  |  |  |  |   in | 
			
		
	
		
			
				
					|  |  |  |  |   let initWCET = (BasicCost.zero, ReportedOnNodes.empty) in | 
			
		
	
		
			
				
					|  |  |  |  |   let initWCET = (CostDomain.zero_record, ReportedOnNodes.empty) in | 
			
		
	
		
			
				
					|  |  |  |  |   match | 
			
		
	
		
			
				
					|  |  |  |  |     AnalyzerWCET.compute_post ~initial:initWCET | 
			
		
	
		
			
				
					|  |  |  |  |       (ProcData.make proc_desc tenv | 
			
		
	
		
			
				
					|  |  |  |  |          {basic_cost_map= invariant_map_NodesBasicCost; get_node_nb_exec; summary}) | 
			
		
	
		
			
				
					|  |  |  |  |   with | 
			
		
	
		
			
				
					|  |  |  |  |   | Some (exit_cost, _) -> | 
			
		
	
		
			
				
					|  |  |  |  |   | Some (exit_cost_record, _) -> | 
			
		
	
		
			
				
					|  |  |  |  |       L.(debug Analysis Verbose) | 
			
		
	
		
			
				
					|  |  |  |  |         "@\n[COST ANALYSIS] PROCEDURE '%a' |CFG| = %i FINAL COST = %a @\n" Typ.Procname.pp | 
			
		
	
		
			
				
					|  |  |  |  |         (Procdesc.get_proc_name proc_desc) | 
			
		
	
		
			
				
					|  |  |  |  |         (Container.length ~fold:NodeCFG.fold_nodes node_cfg) | 
			
		
	
		
			
				
					|  |  |  |  |         BasicCost.pp exit_cost ; | 
			
		
	
		
			
				
					|  |  |  |  |       check_and_report_top_and_bottom exit_cost proc_desc summary ; | 
			
		
	
		
			
				
					|  |  |  |  |       Payload.update_summary {post= {CostDomain.basic_operation_cost= exit_cost}} summary | 
			
		
	
		
			
				
					|  |  |  |  |         CostDomain.VariantCostMap.pp exit_cost_record ; | 
			
		
	
		
			
				
					|  |  |  |  |       check_and_report_top_and_bottom exit_cost_record proc_desc summary ; | 
			
		
	
		
			
				
					|  |  |  |  |       Payload.update_summary {post= exit_cost_record} summary | 
			
		
	
		
			
				
					|  |  |  |  |   | None -> | 
			
		
	
		
			
				
					|  |  |  |  |       if Procdesc.Node.get_succs (Procdesc.get_start_node proc_desc) <> [] then ( | 
			
		
	
		
			
				
					|  |  |  |  |         L.internal_error "Failed to compute final cost for function %a" Typ.Procname.pp | 
			
		
	
	
		
			
				
					|  |  |  | 
 |