1
|
(* TODO
|
2
|
|
3
|
- build the output function: for the moment we slice the node with
|
4
|
its memories, building the function updating the memory. We will
|
5
|
need later the output function, using inputs and memories to
|
6
|
compute the output. A way to do this would be to declared memories
|
7
|
as input, remove their definitions, and slice the node with its
|
8
|
outputs. This should clean up unnecessary internal variables and
|
9
|
give us the output function.
|
10
|
|
11
|
- compute the dimension of the node (nb of memories)
|
12
|
|
13
|
- if the updates are all linear or affine, provide the update as a
|
14
|
matrix rather then a polynomial. Check if this is simpler to do
|
15
|
here or in matlab.
|
16
|
|
17
|
- analyzes require bounds on inputs or sometimes target property
|
18
|
over states. These could be specified as node annotations: eg
|
19
|
- /seal/bounds/inputs/semialg/: (in1^4 + in2^3, 1)
|
20
|
to specify that the inputs are constrained by a semialgebraic
|
21
|
set (p,b) such as p(inputs) <= b
|
22
|
- /seal/bounds/inputs/LMI/: (todo_describe_a_matrix) .... and so on.
|
23
|
To be defined depending on needs.
|
24
|
- /seal/prop/semialg/: (x3 - x5, 2) -- if x3 - x5 <= 2 is
|
25
|
the property to prove
|
26
|
|
27
|
*)
|
28
|
|
29
|
|
30
|
open Seal_slice
|
31
|
open Seal_extract
|
32
|
open Seal_utils
|
33
|
|
34
|
let active = ref false
|
35
|
let seal_export = ref None
|
36
|
|
37
|
let set_export s = match s with
|
38
|
| "lustre" | "lus" | "m" | "matlab" -> seal_export := Some s
|
39
|
| _ -> (Format.eprintf "Unrecognized seal export: %s@.@?" s; exit 1)
|
40
|
|
41
|
(* Select the appropriate node, should have been inlined already and
|
42
|
extract update/output functions. *)
|
43
|
let seal_run ~basename prog machines =
|
44
|
let node_name =
|
45
|
match !Options.main_node with
|
46
|
| "" -> (
|
47
|
Format.eprintf "SEAL verifier requires a main node.@.";
|
48
|
Format.eprintf "@[<v 2>Available ones are:@ %a@]@.@?"
|
49
|
(Utils.fprintf_list ~sep:"@ "
|
50
|
(fun fmt m ->
|
51
|
Format.fprintf fmt "%s" m.Machine_code_types.mname.node_id
|
52
|
)
|
53
|
)
|
54
|
machines;
|
55
|
exit 1
|
56
|
)
|
57
|
| s -> ( (* should have been addessed before *)
|
58
|
match Machine_code_common.get_machine_opt machines s with
|
59
|
| None -> begin
|
60
|
Global.main_node := s;
|
61
|
Format.eprintf "Code generation error: %a@." Error.pp_error_msg Error.Main_not_found;
|
62
|
raise (Error.Error (Location.dummy_loc, Error.Main_not_found))
|
63
|
end
|
64
|
| Some _ -> s
|
65
|
)
|
66
|
in
|
67
|
let m = Machine_code_common.get_machine machines node_name in
|
68
|
let nd = m.mname in
|
69
|
let mems = m.mmemory in
|
70
|
|
71
|
report ~level:1 (fun fmt -> Format.fprintf fmt "Node %s compiled: %i memories@." nd.node_id (List.length mems));
|
72
|
|
73
|
(* Slicing node *)
|
74
|
let msch = Utils.desome m.msch in
|
75
|
let sliced_nd = slice_node (mems@nd.node_outputs) msch nd in
|
76
|
report ~level:3 (fun fmt -> Format.fprintf fmt "Node sliced@.");
|
77
|
report ~level:10 (fun fmt -> Format.fprintf fmt "Sliced Node %a@." Printers.pp_node sliced_nd);
|
78
|
|
79
|
let consts = Corelang.(List.map const_of_top (get_consts prog)) in
|
80
|
|
81
|
let pp_sys = pp_sys Printers.pp_expr in
|
82
|
if List.length mems = 0 then
|
83
|
begin (* A stateless node = a function ! *)
|
84
|
|
85
|
let update_out = fun_as_switched_sys consts sliced_nd in
|
86
|
|
87
|
report ~level:1 (fun fmt ->
|
88
|
Format.fprintf fmt
|
89
|
"Output (%i step switch cases):@ @[<v 0>%a@]@."
|
90
|
(List.length update_out)
|
91
|
pp_sys update_out
|
92
|
);
|
93
|
|
94
|
let _ = match !seal_export with
|
95
|
| Some "lustre" | Some "lus" ->
|
96
|
Seal_export.fun_to_lustre basename prog m update_out
|
97
|
| Some "matlab" | Some "m" -> assert false (* TODO *)
|
98
|
| Some _ -> assert false
|
99
|
| None -> ()
|
100
|
in
|
101
|
()
|
102
|
end
|
103
|
else
|
104
|
begin (* A stateful node *)
|
105
|
|
106
|
let sw_init, sw_sys, init_out, update_out = node_as_switched_sys consts mems sliced_nd in
|
107
|
|
108
|
report ~level:1 (fun fmt ->
|
109
|
Format.fprintf fmt
|
110
|
"DynSys: (%i memories, %i init, %i step switch cases)@ @[<v 0>@[<v 3>Init:@ %a@]@ @[<v 3>Step:@ %a@]@]@."
|
111
|
(List.length mems)
|
112
|
(List.length sw_init)
|
113
|
(List.length sw_sys)
|
114
|
pp_sys sw_init
|
115
|
pp_sys sw_sys
|
116
|
);
|
117
|
|
118
|
report ~level:1 (fun fmt ->
|
119
|
Format.fprintf fmt
|
120
|
"Output (%i init, %i step switch cases):@ @[<v 0>@[<v 3>Init:@ %a@]@ @[<v 3>Step:@ %a@]@]@."
|
121
|
(List.length init_out)
|
122
|
(List.length update_out)
|
123
|
pp_sys init_out
|
124
|
pp_sys update_out
|
125
|
);
|
126
|
|
127
|
let _ = match !seal_export with
|
128
|
| Some "lustre" | Some "lus" ->
|
129
|
Seal_export.node_to_lustre basename prog m sw_init sw_sys init_out update_out
|
130
|
| Some "matlab" | Some "m" -> assert false (* TODO *)
|
131
|
| Some _ -> assert false
|
132
|
| None -> ()
|
133
|
in
|
134
|
()
|
135
|
end
|
136
|
|
137
|
module Verifier =
|
138
|
(struct
|
139
|
include VerifierType.Default
|
140
|
let name = "seal"
|
141
|
let options =
|
142
|
[
|
143
|
"-export", Arg.String set_export, "seal export option (lustre, matlab)";
|
144
|
"-debug", Arg.Set seal_debug, "seal debug"
|
145
|
|
146
|
]
|
147
|
let activate () =
|
148
|
active := true;
|
149
|
Options.global_inline := true;
|
150
|
Options.optimization := 0;
|
151
|
Options.const_unfold := true;
|
152
|
()
|
153
|
|
154
|
let is_active () = !active
|
155
|
let run = seal_run
|
156
|
|
157
|
|
158
|
end: VerifierType.S)
|
159
|
|