Revision c518d082
Added by Xavier Thirioux about 11 years ago
src/clock_calculus.ml | ||
---|---|---|
251 | 251 |
cr1.carrier_desc <- Carry_link cr2; |
252 | 252 |
update_scope_carrier cr1.carrier_scoped cr2 |
253 | 253 |
end |
254 |
| _,_ -> (assert false) |
|
254 |
| _,_ -> assert false |
|
255 |
|
|
256 |
(* Semi-unifies two clock carriers *) |
|
257 |
let semi_unify_carrier cr1 cr2 = |
|
258 |
let cr1 = carrier_repr cr1 in |
|
259 |
let cr2 = carrier_repr cr2 in |
|
260 |
if cr1=cr2 then () |
|
261 |
else |
|
262 |
match cr1.carrier_desc, cr2.carrier_desc with |
|
263 |
| Carry_const id1, Carry_const id2 -> |
|
264 |
if id1 <> id2 then raise (Mismatch (cr1, cr2)) |
|
265 |
| Carry_const _, Carry_name -> |
|
266 |
begin |
|
267 |
cr2.carrier_desc <- Carry_link cr1; |
|
268 |
update_scope_carrier cr2.carrier_scoped cr1 |
|
269 |
end |
|
270 |
| Carry_name, Carry_const _ -> raise (Mismatch (cr1, cr2)) |
|
271 |
| Carry_name, Carry_name -> |
|
272 |
if cr1.carrier_id < cr2.carrier_id then |
|
273 |
begin |
|
274 |
cr2.carrier_desc <- Carry_link cr1; |
|
275 |
update_scope_carrier cr2.carrier_scoped cr1 |
|
276 |
end |
|
277 |
else |
|
278 |
begin |
|
279 |
cr1.carrier_desc <- Carry_link cr2; |
|
280 |
update_scope_carrier cr1.carrier_scoped cr2 |
|
281 |
end |
|
282 |
| _,_ -> assert false |
|
255 | 283 |
|
256 | 284 |
(** [unify ck1 ck2] unifies clocks [ck1] and [ck2]. Raises [Unify |
257 | 285 |
(ck1,ck2)] if the clocks are not unifiable.*) |
... | ... | |
355 | 383 |
subsume ck2 (CSet_pck (b,(a,b))); |
356 | 384 |
let ck2' = simplify (new_ck (Pck_phase (ck2,(-a,b))) true) in |
357 | 385 |
unify pck1' ck2' |
358 |
(* Corner case for some functions like ite, need to unify guard clock |
|
359 |
with output clocks *) |
|
360 |
(* |
|
361 |
| Ctuple ckl, (Cvar _) -> List.iter (unify ck2) ckl |
|
362 |
| (Cvar _), Ctuple ckl -> List.iter (unify ck1) ckl |
|
363 |
*) |
|
386 |
| Cunivar _, _ | _, Cunivar _ -> () |
|
387 |
| _,_ -> raise (Unify (ck1,ck2)) |
|
388 |
|
|
389 |
(** [unify ck1 ck2] semi-unifies clocks [ck1] and [ck2]. Raises [Unify |
|
390 |
(ck1,ck2)] if the clocks are not semi-unifiable.*) |
|
391 |
let rec semi_unify ck1 ck2 = |
|
392 |
let ck1 = repr ck1 in |
|
393 |
let ck2 = repr ck2 in |
|
394 |
if ck1=ck2 then |
|
395 |
() |
|
396 |
else |
|
397 |
match ck1.cdesc,ck2.cdesc with |
|
398 |
| Cvar cset1,Cvar cset2-> |
|
399 |
if ck1.cid < ck2.cid then |
|
400 |
begin |
|
401 |
ck2.cdesc <- Clink (simplify ck1); |
|
402 |
update_scope ck2.cscoped ck1 |
|
403 |
end |
|
404 |
else |
|
405 |
begin |
|
406 |
ck1.cdesc <- Clink (simplify ck2); |
|
407 |
update_scope ck1.cscoped ck2 |
|
408 |
end |
|
409 |
| (Cvar cset,_) -> raise (Unify (ck1,ck2)) |
|
410 |
| (_, (Cvar cset)) when (not (occurs ck2 ck1)) -> |
|
411 |
update_scope ck2.cscoped ck1; |
|
412 |
ck2.cdesc <- Clink (simplify ck1) |
|
413 |
| Ccarrying (cr1,ck1'),Ccarrying (cr2,ck2') -> |
|
414 |
semi_unify_carrier cr1 cr2; |
|
415 |
semi_unify ck1' ck2' |
|
416 |
| Ccarrying (_,_),_ | _,Ccarrying (_,_) -> |
|
417 |
raise (Unify (ck1,ck2)) |
|
418 |
| Carrow (c1,c2), Carrow (c1',c2') -> |
|
419 |
begin |
|
420 |
semi_unify c1 c1'; |
|
421 |
semi_unify c2 c2' |
|
422 |
end |
|
423 |
| Ctuple ckl1, Ctuple ckl2 -> |
|
424 |
if (List.length ckl1) <> (List.length ckl2) then |
|
425 |
raise (Unify (ck1,ck2)); |
|
426 |
List.iter2 semi_unify ckl1 ckl2 |
|
427 |
| Con (ck',c1,l1), Con (ck'',c2,l2) when l1=l2 -> |
|
428 |
semi_unify_carrier c1 c2; |
|
429 |
semi_unify ck' ck'' |
|
364 | 430 |
| Cunivar _, _ | _, Cunivar _ -> () |
365 | 431 |
| _,_ -> raise (Unify (ck1,ck2)) |
366 | 432 |
|
... | ... | |
442 | 508 |
| Mismatch (cr1,cr2) -> |
443 | 509 |
raise (Error (loc, Carrier_mismatch (cr1,cr2))) |
444 | 510 |
|
511 |
let try_semi_unify ck1 ck2 loc = |
|
512 |
try |
|
513 |
semi_unify ck1 ck2 |
|
514 |
with |
|
515 |
| Unify (ck1',ck2') -> |
|
516 |
raise (Error (loc, Clock_clash (ck1',ck2'))) |
|
517 |
| Subsume (ck,cset) -> |
|
518 |
raise (Error (loc, Clock_set_mismatch (ck,cset))) |
|
519 |
| Mismatch (cr1,cr2) -> |
|
520 |
raise (Error (loc, Carrier_mismatch (cr1,cr2))) |
|
521 |
|
|
445 | 522 |
(* Checks whether ck1 is a subtype of ck2 *) |
446 | 523 |
let rec clock_subtyping ck1 ck2 = |
447 | 524 |
match (repr ck1).cdesc, (repr ck2).cdesc with |
... | ... | |
775 | 852 |
let clock_prog env decls = |
776 | 853 |
List.fold_left (fun e decl -> clock_top_decl e decl) env decls |
777 | 854 |
|
855 |
(* Once the Lustre program is fully clocked, |
|
856 |
we must get back to the original description of clocks, |
|
857 |
with constant parameters, instead of unifiable internal variables. *) |
|
858 |
|
|
859 |
(* The following functions aims at 'unevaluating' carriers occuring in clock expressions, |
|
860 |
i.e. replacing unifiable second_order variables with the original carrier names. |
|
861 |
Once restored in this formulation, clocks may be meaningfully printed. |
|
862 |
*) |
|
863 |
let uneval_vdecl_generics vdecl = |
|
864 |
if Types.is_clock_type vdecl.var_type |
|
865 |
then |
|
866 |
match get_carrier_name vdecl.var_clock with |
|
867 |
| None -> (Format.eprintf "internal error: %a@." print_ck vdecl.var_clock; assert false) |
|
868 |
| Some cr -> Clocks.uneval vdecl.var_id cr |
|
869 |
|
|
870 |
let uneval_node_generics vdecls = |
|
871 |
List.iter uneval_vdecl_generics vdecls |
|
872 |
|
|
873 |
let uneval_top_generics decl = |
|
874 |
match decl.top_decl_desc with |
|
875 |
| Node nd -> |
|
876 |
uneval_node_generics (nd.node_inputs @ nd.node_outputs) |
|
877 |
| ImportedNode nd -> |
|
878 |
uneval_node_generics (nd.nodei_inputs @ nd.nodei_outputs) |
|
879 |
| ImportedFun nd -> |
|
880 |
() |
|
881 |
| Consts clist -> () |
|
882 |
| Open _ -> () |
|
883 |
|
|
884 |
let uneval_prog_generics prog = |
|
885 |
List.iter uneval_top_generics prog |
|
886 |
|
|
778 | 887 |
let check_env_compat header declared computed = |
888 |
uneval_prog_generics header; |
|
779 | 889 |
Env.iter declared (fun k decl_clock_k -> |
780 | 890 |
let computed_c = instantiate (ref []) (ref []) (Env.lookup_value computed k) in |
781 |
try_unify decl_clock_k computed_c Location.dummy_loc |
|
891 |
try_semi_unify decl_clock_k computed_c Location.dummy_loc
|
|
782 | 892 |
) |
783 | 893 |
(* Local Variables: *) |
784 | 894 |
(* compile-command:"make -C .." *) |
src/clocks.ml | ||
---|---|---|
121 | 121 |
needs to be considered here *) |
122 | 122 |
| _ -> failwith "Internal error: not an arrow clock" |
123 | 123 |
|
124 |
let get_carrier_name ck = |
|
125 |
match (repr ck).cdesc with |
|
126 |
| Ccarrying (cr, _) -> Some cr |
|
127 |
| _ -> None |
|
128 |
|
|
124 | 129 |
let uncarrier ck = |
125 | 130 |
match ck.cdesc with |
126 |
| Ccarrying (cr, ck') -> ck'
|
|
127 |
| _ -> ck
|
|
131 |
| Ccarrying (_, ck') -> ck'
|
|
132 |
| _ -> ck |
|
128 | 133 |
|
129 | 134 |
(* Removes all links in a clock. Only used for clocks |
130 | 135 |
simplification though. *) |
... | ... | |
268 | 273 |
let rec print_carrier fmt cr = |
269 | 274 |
(* (if cr.carrier_scoped then fprintf fmt "[%t]" else fprintf fmt "%t") (fun fmt -> *) |
270 | 275 |
match cr.carrier_desc with |
271 |
| Carry_const id -> fprintf fmt "'%s'" id
|
|
276 |
| Carry_const id -> fprintf fmt "%s" id
|
|
272 | 277 |
| Carry_name -> |
273 |
fprintf fmt "?%s" (name_of_carrier cr.carrier_id)
|
|
278 |
fprintf fmt "_%s" (name_of_carrier cr.carrier_id)
|
|
274 | 279 |
| Carry_var -> |
275 |
fprintf fmt "_%s" (name_of_carrier cr.carrier_id)
|
|
280 |
fprintf fmt "'%s" (name_of_carrier cr.carrier_id)
|
|
276 | 281 |
| Carry_link cr' -> |
277 | 282 |
print_carrier fmt cr' |
278 | 283 |
|
... | ... | |
512 | 517 |
fprintf fmt " (where %a)" |
513 | 518 |
(fprintf_list ~sep:", " print_cvar) cvars |
514 | 519 |
|
520 |
(* prints only the Con components of a clock, useful for printing nodes *) |
|
521 |
let rec print_ck_suffix fmt ck = |
|
522 |
let ck = simplify ck in |
|
523 |
match ck.cdesc with |
|
524 |
| Carrow _ |
|
525 |
| Ctuple _ |
|
526 |
| Cvar _ |
|
527 |
| Cunivar _ -> () |
|
528 |
| Con (ck,c,l) -> |
|
529 |
fprintf fmt "%a when %s(%a)" print_ck_suffix ck l print_carrier c |
|
530 |
| Clink ck' -> |
|
531 |
print_ck_suffix fmt ck' |
|
532 |
| Ccarrying (cr,ck') -> |
|
533 |
fprintf fmt "%a" print_ck_suffix ck' |
|
534 |
| _ -> assert false |
|
535 |
|
|
515 | 536 |
let pp_error fmt = function |
516 | 537 |
| Clock_clash (ck1,ck2) -> |
517 | 538 |
reset_names (); |
... | ... | |
552 | 573 |
print_ck ck_node |
553 | 574 |
print_ck ck |
554 | 575 |
|
576 |
let uneval const cr = |
|
577 |
(*Format.printf "uneval %s %a@." const print_carrier cr;*) |
|
578 |
let cr = carrier_repr cr in |
|
579 |
match cr.carrier_desc with |
|
580 |
| Carry_var -> cr.carrier_desc <- Carry_const const |
|
581 |
| _ -> assert false |
|
555 | 582 |
|
556 | 583 |
(* Local Variables: *) |
557 | 584 |
(* compile-command:"make -C .." *) |
src/dimension.ml | ||
---|---|---|
347 | 347 |
| Dident id1, Dident id2 when id1 = id2 -> () |
348 | 348 |
| _ -> raise (Unify (dim1, dim2)) |
349 | 349 |
|
350 |
(* unification with the constraint that dim1 is an instance of dim2 *) |
|
350 | 351 |
let rec semi_unify dim1 dim2 = |
351 | 352 |
let dim1 = repr dim1 in |
352 | 353 |
let dim2 = repr dim2 in |
src/main_lustre_compiler.ml | ||
---|---|---|
28 | 28 |
|
29 | 29 |
let usage = "Usage: lustrec [options] <source-file>" |
30 | 30 |
|
31 |
let extensions = [".ec";".lus"]
|
|
31 |
let extensions = [".ec"; ".lus"; ".lusi"]
|
|
32 | 32 |
|
33 | 33 |
let type_decls env decls = |
34 | 34 |
report ~level:1 (fun fmt -> fprintf fmt ".. typing@,@?"); |
... | ... | |
79 | 79 |
|
80 | 80 |
let check_lusi header = |
81 | 81 |
let new_tenv = type_decls Basic_library.type_env header in (* Typing *) |
82 |
let new_cenv: Clocks.clock_expr Utils.IMap.t = clock_decls Basic_library.clock_env header in (* Clock calculus *)
|
|
82 |
let new_cenv = clock_decls Basic_library.clock_env header in (* Clock calculus *) |
|
83 | 83 |
header, new_tenv, new_cenv |
84 | 84 |
|
85 | 85 |
let rec compile basename extension = |
... | ... | |
192 | 192 |
let lusi_out = open_out lusi_name in |
193 | 193 |
let lusi_fmt = formatter_of_out_channel lusi_out in |
194 | 194 |
Typing.uneval_prog_generics prog; |
195 |
Clock_calculus.uneval_prog_generics prog; |
|
195 | 196 |
Printers.pp_lusi_header lusi_fmt source_name prog |
196 | 197 |
) |
197 | 198 |
| (Types.Error (loc,err)) as exc -> |
198 | 199 |
Format.eprintf "Type mismatch between computed type and declared type in lustre interface file: %a@]@." |
199 | 200 |
Types.pp_error err; |
200 | 201 |
raise exc |
202 |
| Clocks.Error (loc, err) as exc -> |
|
203 |
Format.eprintf "Clock mismatch between computed clock and declared clock in lustre interface file: %a@]@." |
|
204 |
Clocks.pp_error err; |
|
205 |
raise exc |
|
201 | 206 |
in |
202 | 207 |
|
203 | 208 |
(* Computes and stores generic calls for each node, |
... | ... | |
226 | 231 |
|
227 | 232 |
(* Printing code *) |
228 | 233 |
let basename = Filename.basename basename in |
234 |
let destname = !Options.dest_dir ^ "/" ^ basename in |
|
229 | 235 |
let _ = match !Options.output with |
230 | 236 |
"C" -> |
231 | 237 |
begin |
232 |
let destname = !Options.dest_dir ^ "/" ^ basename in |
|
233 | 238 |
let header_file = destname ^ ".h" in (* Could be changed *) |
234 | 239 |
let source_file = destname ^ ".c" in (* Could be changed *) |
235 | 240 |
let makefile_file = destname ^ ".makefile" in (* Could be changed *) |
... | ... | |
268 | 273 |
end |
269 | 274 |
| "horn" -> |
270 | 275 |
begin |
271 |
let destname = !Options.dest_dir ^ "/" ^ basename in |
|
272 | 276 |
let source_file = destname ^ ".smt2" in (* Could be changed *) |
273 | 277 |
let source_out = open_out source_file in |
274 | 278 |
let fmt = formatter_of_out_channel source_out in |
... | ... | |
286 | 290 |
let basename = Filename.chop_suffix filename ext in |
287 | 291 |
compile basename ext |
288 | 292 |
else |
289 |
raise (Arg.Bad ("Can only compile *.lus or *.ec files")) |
|
293 |
raise (Arg.Bad ("Can only compile *.lusi, *.lus or *.ec files"))
|
|
290 | 294 |
|
291 | 295 |
let _ = |
292 | 296 |
Corelang.add_internal_funs (); |
src/printers.ml | ||
---|---|---|
50 | 50 |
|
51 | 51 |
and pp_var fmt id = fprintf fmt "%s%s: %a" (if id.var_dec_const then "const " else "") id.var_id Types.print_ty id.var_type |
52 | 52 |
|
53 |
and pp_node_var fmt id = fprintf fmt "%s%s: %a" (if id.var_dec_const then "const " else "") id.var_id Types.print_node_ty id.var_type
|
|
53 |
and pp_node_var fmt id = fprintf fmt "%s%s: %a%a" (if id.var_dec_const then "const " else "") id.var_id Types.print_node_ty id.var_type Clocks.print_ck_suffix id.var_clock
|
|
54 | 54 |
|
55 | 55 |
and pp_expr fmt expr = |
56 | 56 |
match expr.expr_desc with |
src/types.ml | ||
---|---|---|
176 | 176 |
| Tstatic (d, _) -> Some d |
177 | 177 |
| _ -> None |
178 | 178 |
|
179 |
let is_clock_type ty = |
|
180 |
match (repr ty).tdesc with |
|
181 |
| Tclock _ -> true |
|
182 |
| _ -> false |
|
183 |
|
|
179 | 184 |
let rec is_dimension_type ty = |
180 | 185 |
match (repr ty).tdesc with |
181 | 186 |
| Tint |
src/typing.ml | ||
---|---|---|
678 | 678 |
i.e. replacing unifiable second_order variables with the original static parameters. |
679 | 679 |
Once restored in this formulation, dimensions may be meaningfully printed. |
680 | 680 |
*) |
681 |
(* |
|
682 |
let uneval_vdecl_generics vdecl ty = |
|
683 |
if vdecl.var_dec_const |
|
684 |
then |
|
685 |
match get_static_value ty with |
|
686 |
| None -> (Format.eprintf "internal error: %a@." Types.print_ty vdecl.var_type; assert false) |
|
687 |
| Some d -> Dimension.unify d (Dimension.mkdim_ident vdecl.var_loc vdecl.var_id) |
|
688 |
|
|
689 |
let uneval_node_generics vdecls = |
|
690 |
let inst_typ_vars = ref [] in |
|
691 |
let inst_dim_vars = ref [] in |
|
692 |
let inst_ty_list = List.map (fun v -> instantiate inst_typ_vars inst_dim_vars v.var_type) vdecls in |
|
693 |
List.iter2 (fun v ty -> uneval_vdecl_generics v ty) vdecls inst_ty_list; |
|
694 |
List.iter2 (fun v ty -> generalize ty; v.var_type <- ty) vdecls inst_ty_list |
|
695 |
*) |
|
696 | 681 |
let uneval_vdecl_generics vdecl = |
697 | 682 |
if vdecl.var_dec_const |
698 | 683 |
then |
... | ... | |
717 | 702 |
let uneval_prog_generics prog = |
718 | 703 |
List.iter uneval_top_generics prog |
719 | 704 |
|
720 |
let check_env_compat header declared computed = |
|
721 |
(try |
|
722 |
uneval_prog_generics header |
|
723 |
with e -> raise e); |
|
705 |
let check_env_compat header declared computed = |
|
706 |
uneval_prog_generics header; |
|
724 | 707 |
Env.iter declared (fun k decl_type_k -> |
725 | 708 |
let computed_t = instantiate (ref []) (ref []) (Env.lookup_value computed k) in |
726 | 709 |
(*Types.print_ty Format.std_formatter decl_type_k; |
test/src/arrays_arnaud/dummy_lib.lusi | ||
---|---|---|
1 |
node test(x:int) returns (t:int^2); |
|
2 |
|
|
3 |
function _MatMul_real ( |
|
4 |
const n, m, p : int ; |
|
5 |
in1 : real^n^m ; |
|
6 |
in2 : real^m^p) |
|
7 |
returns ( |
|
8 |
out : real^n^p) ; |
|
9 |
|
|
10 |
function _Vect_Leqt_real ( |
|
11 |
const n : int ; |
|
12 |
in : real^n ; |
|
13 |
in2 : real^n) |
|
14 |
returns ( |
|
15 |
out : bool^n) ; |
|
16 |
|
|
17 |
node imp1(const m:int; a:int^(3*m)) returns (c:int^m); |
|
18 |
|
|
19 |
node imp2(const n:int; a:int^n) returns (d:int^n); |
test/src/clocks/oversampling0.lus | ||
---|---|---|
18 | 18 |
var toto:int; |
19 | 19 |
let |
20 | 20 |
toto = 1 ; |
21 |
c = true fby false fby c;
|
|
21 |
c = toto = 0 (*true fby false fby c*);
|
|
22 | 22 |
out = g(x,toto=0); |
23 | 23 |
tel |
24 | 24 |
*) |
test/test-compile.sh | ||
---|---|---|
51 | 51 |
fi |
52 | 52 |
fi |
53 | 53 |
popd > /dev/null |
54 |
echo "lustrec ($rlustrec1), gcc($rgcc1), `dirname $file`,`basename $file`,node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
54 |
echo "lustrec ($rlustrec1), gcc($rgcc1), $dir, ${name}.lus, node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
55 | 55 |
done < $file_list |
56 | 56 |
} |
57 | 57 |
|
... | ... | |
78 | 78 |
else |
79 | 79 |
rgcc2="VALID" |
80 | 80 |
fi |
81 |
echo "lustrec inlined ($rlustrec2), gcc ($rgcc2),`dirname $file`,`basename $file`,node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
81 |
echo "lustrec inlined ($rlustrec2), gcc ($rgcc2), $dir, ${name}.lus, node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
82 | 82 |
popd > /dev/null |
83 | 83 |
done < $file_list |
84 | 84 |
} |
... | ... | |
106 | 106 |
fi |
107 | 107 |
# Cheching witness |
108 | 108 |
pushd $build > /dev/null |
109 |
lustrec -horn -d $build/${name}_witnesses -node check $build/${name}_witnesses/inliner_witness.lus 2>/dev/null
|
|
109 |
$LUSTREC -horn -d $build/${name}_witnesses -node check $build/${name}_witnesses/inliner_witness.lus 2>/dev/null
|
|
110 | 110 |
popd > /dev/null |
111 | 111 |
z3="`z3 -T:10 $build/${name}_witnesses/inliner_witness.smt2 | xargs`" |
112 | 112 |
if [ "x`echo $z3 | grep unsat`" == "xunsat" ]; then |
... | ... | |
119 | 119 |
rinlining="INVALID" |
120 | 120 |
exit 1 |
121 | 121 |
fi |
122 |
echo "lustrec inlined ($rlustrec2), gcc ($rgcc2), inlining valid ($rinlining),`dirname $file`,`basename $file`,node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
122 |
echo "lustrec inlined ($rlustrec2), gcc ($rgcc2), inlining valid ($rinlining), $dir, ${name}.lus, node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
123 | 123 |
popd > /dev/null |
124 | 124 |
done < $file_list |
125 | 125 |
|
... | ... | |
146 | 146 |
else |
147 | 147 |
rhorn="VALID" |
148 | 148 |
fi |
149 |
echo "horn-pdr ($rhorn), `dirname $file`,`basename $file`,node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
149 |
echo "horn-pdr ($rhorn), $dir, ${name}.lus, node $main" | column -t -s',' | tee -a $report | grep "INVALID\|ERROR\|UNKNOWN"
|
|
150 | 150 |
popd > /dev/null |
151 | 151 |
done < $file_list |
152 | 152 |
} |
Also available in: Unified diff
- added generation of clock information in interface (.lusi) files
- added clock checking between interface and implementation files