3 let error_prefix = "Main"
4 let error = Error.global_error error_prefix
7 let log_file = Filename.temp_file "log" ""
10 let print_verbose i s =
11 if Options.get_verbose_level () >= i then Printf.printf "%s%!" s
12 let print_verbose1 = print_verbose 1
13 let print_verbose2 = print_verbose 2
16 let exec cmd error_callback error_msg success_callback success_msg =
17 print_verbose2 (" -> executing command \"" ^ cmd ^ "\"...\n") ;
18 let res = Sys.command cmd in
19 if res <> 0 then (error_callback () ; error error_msg)
21 (print_verbose1 (success_msg ^ "\n") ;
25 let has_extension filename =
26 try ignore (Filename.chop_extension filename) ; true
27 with Invalid_argument ("Filename.chop_extension") -> false
29 let lustre_compilation filename node =
31 ("Compiling node " ^ node ^ " of Lustre file " ^ filename ^ "...\n") ;
32 let filename_quote = Filename.quote filename in
34 if has_extension filename then Filename.chop_extension filename
38 [".c" ; "-annotated.c" ; ".s" ; ".hex" ; ".cerco" ; ".cost_results" ;
39 ".jessie_results" ; "-annotated_test.c" ; "-annotated_test.s" ;
40 "-annotated_test.hex" ; "-annotated_test.results"] in
41 let res_file = base ^ ".c" in
42 let res_file_quote = Filename.quote res_file in
44 "lus2c " ^ filename_quote ^ " " ^ node ^ " -o " ^ res_file_quote ^ " >> " ^
46 let error_callback () = () in
48 "Failed to compile node " ^ node ^ " of Lustre file " ^ filename ^ "." in
49 let success_callback () = res_file in
50 let success_msg = "Done. Result is in file " ^ res_file ^ "." in
51 exec cmd error_callback error_msg success_callback success_msg
54 let extract_inputs_booleans filename =
56 ("Extracting boolean inputs from file " ^ filename ^ "...\n") ;
58 let ic = open_in filename in
59 let rec inputs_booleans b =
61 let str_inputs = Str.regexp " *//INPUTS *" in
62 (* let str_registers = Str.regexp " *//REGISTERS *" in *)
63 let is_input_start s =
64 Str.string_match str_inputs s 0
65 (* || Str.string_match str_registers s 0 *) in
66 let str_outputs = Str.regexp " *//OUTPUTS *" in
67 let str_acc = Str.regexp ".*}.*" in
69 Str.string_match str_outputs s 0 ||
70 Str.string_match str_acc s 0 in
71 let str_boolean = Str.regexp " _boolean .*;" in
72 let str_input = Str.regexp " [^ ]* .*;" in
74 let i = String.index_from s 3 ' ' in
75 String.sub s (i+1) (String.length s - (i+2)) in
76 let s = input_line ic in
77 let (added_input, added_boolean) =
78 let extract cond = if b && cond then [extract_input s] else [] in
79 (extract (Str.string_match str_input s 0),
80 extract (Str.string_match str_boolean s 0)) in
81 let next_b = (b || (is_input_start s)) && (not (is_input_end s)) in
82 let (inputs, booleans) = inputs_booleans next_b in
83 (added_input @ inputs, added_boolean @ booleans)
84 with End_of_file -> close_in ic ; ([], []) in
85 let res = inputs_booleans false in
86 print_verbose1 "Done.\n" ;
89 error ("Could not extract boolean inputs from file " ^ filename ^ ".")
92 let framac_option () =
94 (if Options.test_requested () then "-cost-lustre-test " else "") ^
95 (if Options.verify_requested () then "-cost-lustre-verify " else "")
97 let cost_plugin filename =
98 print_verbose1 ("Running Cost plug-in on file " ^ filename ^ "...\n") ;
99 let filename_quote = Filename.quote filename in
101 if has_extension filename then Filename.chop_extension filename
103 let annotated_file = base ^ "-annotated.c" in
104 let results_file = base ^ ".cost_results" in
105 let hex_file = base ^ ".hex" in
106 let cerco_file = base ^ ".cerco" in
107 let option = framac_option () in
108 let cmd = "frama-c -cost " ^ option ^ filename_quote ^ " >> " ^
110 let error_callback () = () in
111 let error_msg = "Failed to run Cost plug-in on file " ^ filename ^ "." in
112 let success_callback () = (annotated_file, results_file, cerco_file) in
114 "Done. Annotations are in file " ^ annotated_file ^
115 ", object code is in file " ^ hex_file ^
116 ", cost results are in file " ^ results_file ^
117 (if Options.test_requested () then
118 ", CerCo information is in file " ^ cerco_file
121 exec cmd error_callback error_msg success_callback success_msg
124 let print_step_result filename =
125 print_verbose1 ("Reading the cost results in file " ^ filename ^ "...\n") ;
126 let ic = open_in filename in
129 let s = input_line ic in
130 if String.contains s ' ' then
131 let i = String.index s ' ' in
132 let fun_name = String.sub s 0 i in
133 let cost = String.sub s (i+1) ((String.length s) - (i+1)) in
134 let suffix = "_step" in
135 let l = String.length fun_name in
136 let l' = String.length suffix in
137 if l > l' && String.sub s (l - l') l' = suffix then
138 (print_verbose1 "Done.\n" ;
140 "WCET of %s: %s (not verified).\n%!"
144 else error ("Bad format of result file " ^ filename ^ ".")
146 error "No step function found or its cost could not be computed." in
151 if Options.gui_requested () then ""
152 else "-jessie-atp " ^ (Options.get_prover ()) ^ " "
154 let jessie filename =
155 print_verbose1 ("Running Frama-C/Jessie on file " ^ filename ^ "...\n") ;
156 let filename_quote = Filename.quote filename in
158 if has_extension filename then Filename.chop_extension filename
160 let res_file = base ^ ".jessie_results" in
161 let timeout = string_of_int (Options.get_timeout ()) in
163 "TIMEOUT=" ^ timeout ^ " frama-c -jessie -jessie-behavior default " ^
164 "-jessie-why-opt=\"-fast-wp\" " ^ (prover ()) ^
165 filename_quote ^ " >> " ^ res_file in
166 let error_callback () = () in
167 let error_msg = "Failed to run Frama-C/Jessie on file " ^ filename ^ "." in
168 let success_callback () = res_file in
169 let success_msg = "Done. Results are in file " ^ res_file ^ "." in
170 exec cmd error_callback error_msg success_callback success_msg
172 let string_starts_with prefix s =
173 let l = String.length prefix in
174 (l <= String.length s) && (String.sub s 0 l = prefix)
176 let read_jessie_results filename =
177 if not (Options.gui_requested ()) then
180 ("Reading Frama-C/Jessie results in file " ^ filename ^ "...\n" ) ;
181 let print_failed () = Printf.printf "Failed to prove the result.\n%!" in
183 let ic = open_in filename in
185 let s = input_line ic in
186 if string_starts_with "valid" s then
187 let regexp = Str.regexp (".*100%.*") in
188 if Str.string_match regexp s 0 then
189 (print_verbose1 "Done.\n" ;
190 Printf.printf "WCET is proven correct.\n%!")
194 with Sys_error _ | End_of_file -> print_failed ()
197 let verification filename =
198 Printf.printf "Verifying the result (this may take some time)...\n%!" ;
199 let res_file = jessie filename in
200 read_jessie_results res_file
203 let cerco_test_info (inputs, booleans) step_fun step_cost cerco_file =
205 ("Adding step function information to CerCo file " ^ cerco_file ^ "...\n") ;
207 let ic = open_in cerco_file in
208 let rec contents () =
209 try let s = input_line ic in s ^ "\n" ^ (contents ())
210 with End_of_file -> close_in ic ; "" in
211 let contents = step_fun ^ "\n" ^ step_cost ^ "\n" ^ contents () ^ "\n" in
212 let f contents s = contents ^ s ^ "\n" in
213 let contents = (List.fold_left f contents inputs) ^ "\n" in
214 let contents = List.fold_left f contents booleans in
215 let oc = open_out cerco_file in
216 output_string oc contents ;
218 print_verbose1 "Done.\n" ;
221 error ("Could not add step function information to CerCo file " ^
224 let cerco_test_file filename cerco_test_info =
225 print_verbose1 ("Adding a main to file " ^ filename ^ "...\n") ;
226 let filename_quote = Filename.quote filename in
228 if has_extension filename then Filename.chop_extension filename
230 let res_base = base ^ "_test" in
231 let res_c = res_base ^ ".c" in
233 "acc -o " ^ res_base ^ " -lustre-test " ^ cerco_test_info ^
234 " -lustre-test-cases " ^ (string_of_int (Options.get_test_cases ())) ^
235 " -lustre-test-cycles " ^ (string_of_int (Options.get_test_cycles ())) ^
236 " -lustre-test-min-int " ^ (string_of_int (Options.get_test_min_int ())) ^
237 " -lustre-test-max-int " ^ (string_of_int (Options.get_test_max_int ())) ^
238 " " ^ filename_quote ^ " >> " ^ log_file in
239 let error_callback () = () in
240 let error_msg = "Failed to add a main to file " ^ filename ^ "." in
241 let success_callback () = res_c in
242 let success_msg = "Done. Result is in files " ^ res_c ^ "." in
243 exec cmd error_callback error_msg success_callback success_msg
245 let test_exec filename =
246 print_verbose1 ("Simulating the generated code in file " ^ filename ^
248 let filename_quote = Filename.quote filename in
250 if has_extension filename then Filename.chop_extension filename
252 let res_file = base ^ ".results" in
253 let cmd = "acc -l Clight -i " ^ filename_quote ^ " > " ^ res_file in
254 let error_callback () = () in
255 let error_msg = "Failed to run acc on file " ^ filename ^ "." in
256 let success_callback () = res_file in
257 let success_msg = "Done. Results are in file " ^ res_file ^ "." in
258 exec cmd error_callback error_msg success_callback success_msg
260 let read_test_results filename =
262 ("Reading simulation results in file " ^ filename ^ "...\n" ) ;
264 let ic = open_in filename in
265 Misc.repeat 2 (fun () -> ignore (input_line ic)) () ;
266 let wcet = int_of_string (input_line ic) in
267 let min = int_of_string (input_line ic) in
268 let max = int_of_string (input_line ic) in
269 let average = int_of_string (input_line ic) in
270 let wcet_correct = max <= wcet in
271 print_verbose1 "Done.\n" ;
272 Printf.printf "Estimated WCET: %d\nMinimum: %d\nMaximum: %d\nAverage: %d\nEstimated WCET is %scorrect for these executions.\n%!"
273 wcet min max average (if wcet_correct then "" else "in")
274 with Sys_error _ | End_of_file | Failure "int_of_string" ->
275 error "Failed to test the result."
277 let test filename inputs_booleans step_fun step_cost cerco_file =
278 Printf.printf "Testing the result (this may take some time)...\n%!" ;
279 let cerco_test_info =
280 cerco_test_info inputs_booleans step_fun step_cost cerco_file in
281 let cerco_test_file = cerco_test_file filename cerco_test_info in
282 let test_results = test_exec cerco_test_file in
283 read_test_results test_results
287 let args = OptionsParsing.results () in
288 if List.length args < 2 then error OptionsParsing.usage_msg
291 let lustre_file = List.nth args 0 in
292 let node = List.nth args 1 in
294 ("*** Processing node " ^ node ^ " of Lustre file " ^ lustre_file ^
296 let c_file = lustre_compilation lustre_file node in
297 let inputs_booleans = extract_inputs_booleans c_file in
298 let (c_annotated_file, cost_results_file, cerco_file) =
299 cost_plugin c_file in
300 let (step_fun, step_cost) = print_step_result cost_results_file in
301 if Options.verify_requested () then verification c_annotated_file ;
302 if Options.test_requested () then
303 test c_annotated_file inputs_booleans step_fun step_cost cerco_file ;