Commit 2202eabc authored by Erwan Jahier's avatar Erwan Jahier
Browse files

Split luc2c into 2 files: one for the functions that performs the real work (luc2c), and one

for the toplevel stuff (dealing with args, etc.)

The rationale is that we plan to call that code directly from lutin.
parent dd37a749
include $(LURETTE_PATH)/Makefile.common.source
LUTINSRC=../../source/Lutin
......@@ -76,3 +77,6 @@ objs:
clean:
rm -f ./objs/*
www:
cp lutin-man.pdf $(SYNCHRONE_DIR)/lurette/
......@@ -2,8 +2,8 @@
-- Simulate perfect sensors that never get worn
inputs {
Heat_on : bool ;
T : float;
-- Heat_on : bool
}
outputs {
T1 : real;
......@@ -20,7 +20,8 @@ start_node { 1 }
transitions {
1 -> 1 ~ cond T1 = T + eps1 and
T2 = T + eps2
T2 = T +eps2
and T3 = T + eps3
}
include
-include Makefile.foo
export LURETTE_PATH=../../..
......
......@@ -6,13 +6,13 @@ LURETTETOP=$(LTOP) --precision 2 --sut heater_control.lus \
--oracle-compiler verimag --test-length 100 --thick-draw 1 \
--draw-inside 0 --draw-edges 0 --draw-vertices 0 --draw-all-vertices \
--step-mode Inside --local-var --no-sim2chro --seed 3 \
--do-not-show-step
--do-not-show-step
#
test:
rm -f test.rif0 .lurette_rc
$(LURETTETOP) -go --output test.rif0 env.lut && \
$(LURETTETOP) -go --output test.rif0 env.lut && \
grep -v "lurette chronogram" test.rif0 | \
grep -v "The execution lasted"| sed -e "s/^M//" > test.rif &&\
rm -f test.res && diff -u -i test.rif.exp test.rif > test.res
......
......@@ -108,7 +108,9 @@ SOURCES_OCAML = \
\
$(OBJDIR)/luciole.ml \
$(OBJDIR)/luc2alice.ml \
$(OBJDIR)/luc2c.ml
$(OBJDIR)/luc2c.mli \
$(OBJDIR)/luc2c.ml \
$(OBJDIR)/luc2c_top.ml
ifdef MLONLY
SOURCES_OCAML =$(filter %.ml, $(SOURCES_OCAML))
......
......@@ -13,11 +13,9 @@
*)
open LucProg
open Exp
open Prog
open Type
type gen_mode = C | Lustre | Scade | Alice
type gen_mode = C | Lustre | Scade | Alice | Luciole
type step_mode = Inside | Edges | Vertices
let step_mode_to_str = function
......@@ -25,26 +23,24 @@ let step_mode_to_str = function
| Edges -> "step_edges"
| Vertices -> "step_vertices"
type flagT = {
type optionT = {
mutable pp : string option;
mutable output : string option;
mutable gen_mode : gen_mode;
mutable calling_module_name : string;
mutable gen_mode : gen_mode;
mutable step_mode : step_mode;
mutable seed : int option;
mutable luciole : bool;
mutable env : string list
}
let (flag : flagT) = {
let (option : optionT) = {
pp = None;
output = None;
gen_mode = C;
calling_module_name = "XXX_SCADE_MODULE_NAME";
step_mode = Inside;
seed = None;
luciole = false;
env = []
}
......@@ -53,16 +49,16 @@ let (flag : flagT) = {
let (gen_lustre_ext_h : string -> unit) =
fun fn ->
let oc = open_out (flag.calling_module_name ^ "_ext.h") in
let oc = open_out (option.calling_module_name ^ "_ext.h") in
let putln s = output_string oc (s^"\n") in
putln (Util.entete "// ");
putln ("#include \"" ^ flag.calling_module_name ^ "_ext_func.h\"");
putln ("#include \"" ^ option.calling_module_name ^ "_ext_func.h\"");
flush oc;
close_out oc
let (gen_lustre_ext_func_h : string -> Exp.var list -> Exp.var list -> unit) =
fun fn in_vars out_vars ->
let oc = open_out (flag.calling_module_name ^ "_ext_func.h") in
let oc = open_out (option.calling_module_name ^ "_ext_func.h") in
let put s = output_string oc s in
let putln s = output_string oc (s^"\n") in
let rec putlist = function
......@@ -71,7 +67,7 @@ let (gen_lustre_ext_func_h : string -> Exp.var list -> Exp.var list -> unit) =
| x::l' -> put x; put ", "; putlist l'
in
putln (Util.entete "// ");
putln ("#include \"" ^ flag.calling_module_name ^ ".h\"");
putln ("#include \"" ^ option.calling_module_name ^ ".h\"");
putln ("#include \"" ^ fn ^ ".h\"");
putln "#define bool int";
putln "";
......@@ -98,7 +94,7 @@ let (gen_lustre_ext_func_h : string -> Exp.var list -> Exp.var list -> unit) =
let (gen_lustre_ext_func_c : string -> Exp.var list -> Exp.var list -> unit) =
fun fn in_vars out_vars ->
let oc = open_out (flag.calling_module_name ^ "_ext_func.c") in
let oc = open_out (option.calling_module_name ^ "_ext_func.c") in
let put s = output_string oc s in
let putln s = output_string oc (s^"\n") in
let rec putlist = function
......@@ -107,7 +103,7 @@ let (gen_lustre_ext_func_c : string -> Exp.var list -> Exp.var list -> unit) =
| x::l' -> put x; put ", "; putlist l'
in
putln (Util.entete "// ");
putln ("#include \"" ^ flag.calling_module_name ^ "_ext_func.h\"");
putln ("#include \"" ^ option.calling_module_name ^ "_ext_func.h\"");
putln "";
putln "// Output procedures";
......@@ -146,7 +142,7 @@ let (gen_lustre_ext_func_c : string -> Exp.var list -> Exp.var list -> unit) =
putln (" if (not_init) {
lucky_ctx = "^fn^"_new_ctx(NULL);
not_init = false;");
(match flag.seed with
(match option.seed with
None -> ()
| Some i -> putln (" lucky_set_seed(" ^ (string_of_int i) ^ ");");
);
......@@ -158,7 +154,7 @@ let (gen_lustre_ext_func_c : string -> Exp.var list -> Exp.var list -> unit) =
)
in_vars;
putln (" "^fn^ "_step(lucky_ctx, "^ (step_mode_to_str flag.step_mode)^ ");");
putln (" "^fn^ "_step(lucky_ctx, "^ (step_mode_to_str option.step_mode)^ ");");
List.iter
(fun var ->
putln (" *" ^ (Var.name var) ^ "=lucky_ctx->_" ^(Var.name var) ^ ";");
......@@ -231,7 +227,7 @@ typedef float _float;
putln "";
if flag.gen_mode = Scade then
if option.gen_mode = Scade then
(
putln ("/* \n// Put the following in the scade generated file " ^ fn ^
......@@ -254,9 +250,9 @@ typedef float _float;
putln " ";
putln " // lucky process number";
putln " int lp;";
if flag.gen_mode = Scade then (
if option.gen_mode = Scade then (
putln " // Scade node context";
putln (" struct C_" ^ flag.calling_module_name ^ " * client_data;");
putln (" struct C_" ^ option.calling_module_name ^ " * client_data;");
putln "};\n";
putln ("typedef struct _" ^ fn ^ "_ctx " ^ fn ^ "_ctx;\n");
putln "*/\n";
......@@ -313,7 +309,7 @@ typedef float _float;
let (gen_c_file : string -> Exp.var list -> Exp.var list -> Exp.var list -> unit) =
fun fn in_vars out_vars loc_vars ->
let oc =
if flag.gen_mode = Scade then
if option.gen_mode = Scade then
open_out (fn ^ "_fctext.c")
else
open_out (fn ^ ".c")
......@@ -326,15 +322,15 @@ let (gen_c_file : string -> Exp.var list -> Exp.var list -> Exp.var list -> unit
put ("#include <stdlib.h>\n" ^
"#include <stdio.h> \n" ^
"#include <string.h> \n" ^
( if flag.gen_mode = Scade then
"#include \"" ^ flag.calling_module_name ^ ".h\" \n"
( if option.gen_mode = Scade then
"#include \"" ^ option.calling_module_name ^ ".h\" \n"
else
"#include \"" ^ fn ^ ".h\" \n"
) ^
"");
putln "";
if flag.gen_mode = Scade then
if option.gen_mode = Scade then
begin
(* putln ("static " ^ fn ^ "_ctx* ctx;\n"); *)
putln "
......@@ -397,11 +393,11 @@ Dynamic allocation of an internal structure
putln (" ctx = malloc(sizeof("^ fn ^ "_ctx));");
putln " ctx->client_data = cdata;";
put (" ctx->lp = make(" );
put (match flag.pp with | None -> "\"\"" | Some pp -> ("\""^pp^"\""));
put (match option.pp with | None -> "\"\"" | Some pp -> ("\""^pp^"\""));
put (", \"");
assert (flag.env <> []);
put (List.hd flag.env);
List.iter (fun x -> put (" " ^ x)) (List.tl flag.env);
assert (option.env <> []);
put (List.hd option.env);
List.iter (fun x -> put (" " ^ x)) (List.tl option.env);
putln "\");";
putln " return ctx;";
......@@ -441,16 +437,16 @@ Reset procedure
--------*/";
put ("void " ^ fn ^ "_reset(" ^ fn ^ "_ctx* ctx, step_mode sm){\n");
put (" ctx->lp = make(" );
put (match flag.pp with | None -> "\"\"" | Some pp -> ("\""^pp^"\""));
put (match option.pp with | None -> "\"\"" | Some pp -> ("\""^pp^"\""));
put (", \"");
assert (flag.env <> []);
put (List.hd flag.env);
List.iter (fun x -> put (" " ^ x)) (List.tl flag.env);
assert (option.env <> []);
put (List.hd option.env);
List.iter (fun x -> put (" " ^ x)) (List.tl option.env);
putln "\");";
putln "}";
if flag.gen_mode = Scade then (
if option.gen_mode = Scade then (
(* let dump_in_var var = *)
(* put (Type.to_cstring (Var.typ var)); *)
(* put " "; *)
......@@ -467,14 +463,14 @@ Reset procedure
This is the main function to be called by Scade
--------*/";
putln ("void " ^ flag.calling_module_name ^ "_init(_C_" ^
flag.calling_module_name ^ " * _C_)");
putln ("void " ^ option.calling_module_name ^ "_init(_C_" ^
option.calling_module_name ^ " * _C_)");
putln "{";
putln (" _C_->lucky_ctx = " ^ fn ^ "_new_ctx(_C_);");
putln "}";
put ("void " ^ flag.calling_module_name ^ "(_C_" ^
flag.calling_module_name ^ " *_C_){");
put ("void " ^ option.calling_module_name ^ "(_C_" ^
option.calling_module_name ^ " *_C_){");
(* if in_out_vars = [] then () else *)
......@@ -515,107 +511,6 @@ This is the main function to be called by Scade
flush oc;
close_out oc
(****************************************************************************)
let usage_begin = "usage: luc2c [<options>]* <.luc files or .lut file>+
"
let usage_end = "The available <options> are:"
let usage = (usage_begin ^ usage_end)
let more_usage = (usage_begin ^ "
luc2c generates C stub code in a way that is very similar to ec2c.
For example, \"luc2c f.luc\" generates \"f.c\" and \"f.h\" that defines
the type foo_ctx as well as the following functions:
foo_ctx* foo_new_ctx(void* client_data) // a function to create a lucky process
void foo_I_ivn1(foo_ctx*, <c type of ivn1>) // functions to set the inputs
void foo_I_ivn2(foo_ctx*, <c type of ivn2>)
...
void foo_step(struct foo_ctx*, step_mode sm) // a function to perform a step
and that requires the user to define the functions to get the output:
void foo_O_ovn1(foo_ctx*, <c type of ovn1>) // functions to get the outputs
void foo_O_ovn2(foo_ctx*, <c type of ovn2>)
...
The final executable needs to be linked in with the following C libs:
-lluc4c_nc -llucky_nc // distributed with luc2c
-lgmp // the Gnu Multi-precision Library
-lm -ldl -lstdc++ // ...
The lib path should (of course) contains a path to those libs. Moreover,
the include path should contain a path to the \"luc4c_stubs.h\" header file,
which is also distributed with luc2c.
" ^ usage_end)
let rec speclist =
[
"--output", Arg.String (fun s -> flag.output <- Some s),
"\tTo set a string used to name the output files.";
"-o", Arg.String (fun s -> flag.output <- Some s), "\n";
"--pre-processor", Arg.String (fun s -> flag.pp <- Some s),
"To set a Pre-processor to be used before parsing Lucky files";
"-pp", Arg.String (fun s -> flag.pp <- Some s), "\t\t(e.g., cpp).\n";
"--scade", Arg.String
(fun str ->
flag.gen_mode <- Scade;
flag.calling_module_name <- str;
),
"<name of the Scade module>\tTo generate C code to be called from Scade ";
"-scade", Arg.String
(fun str ->
flag.gen_mode <- Scade;
flag.calling_module_name <- str;
),
"";
"--lustre", Arg.String
(fun str -> flag.gen_mode <- Lustre;flag.calling_module_name <- str),
"<calling lustre node name>\tTo generate C code to be called from Lustre V4 ";
"-lustre", Arg.String
(fun str -> flag.gen_mode <- Lustre;flag.calling_module_name <- str),
"";
"--alice", Arg.String
(fun str -> flag.gen_mode <- Alice;flag.calling_module_name <- str),
"Generate C++ code to be called from Alice";
"--seed", Arg.String (fun str -> flag.seed <- Some (int_of_string str)),
"\tTo set a seed to the lucky random generator (with --lustre option))";
"--luciole", Arg.Unit (fun _ -> flag.luciole <- true),
"\tGenerate a C file containing the necessary stuff to call the lucky file with luciole";
"--step-mode", Arg.String
(fun str -> flag.step_mode <-
match str with
"edges" -> Edges
| "vertices" -> Vertices
| _ -> Inside),
"<inside(default)|edges|vertices>\tTo set the lucky step mode (with --lustre option))";
"--help", Arg.Unit (fun _ -> (Arg.usage speclist more_usage ; exit 0)),
"\tTo display this list of options." ;
"-help", Arg.Unit (fun _ -> (Arg.usage speclist more_usage ; exit 0)),
"";
"-h", Arg.Unit (fun _ -> (Arg.usage speclist more_usage ; exit 0)),
""
]
(****************************************************************************)
(*
Invent a file name from the list of file names, unless one was provided
......@@ -635,7 +530,7 @@ let (build_file_name : string list -> string) =
let f2 = Str.global_replace (Str.regexp "-") "_" f1 in
f2
in
match flag.output with
match option.output with
None ->
let fn =
assert (el <> []);
......@@ -644,89 +539,55 @@ let (build_file_name : string list -> string) =
(change_file_name (List.hd el))
(List.tl el)
in
flag.output <- Some fn;
option.output <- Some fn;
fn
| Some fn -> fn
(****************************************************************************)
open LucProg
open Prog
let rec (main : unit -> 'a) =
let (main : unit -> unit) =
fun _ ->
if
(Array.length Sys.argv) = 1
then
(
Arg.usage speclist usage;
exit 2
let env_list = option.env in
let state = LucProg.make_state option.pp env_list in
let from_lutin = Util.get_extension (List.hd env_list) = ".lut" in
let fn = build_file_name env_list in
let _ =
gen_c_file fn state.s.in_vars state.s.out_vars state.s.loc_vars;
gen_h_file fn state.s.in_vars state.s.out_vars state.s.loc_vars
in
let gen_files_for_lustre () =
gen_lustre_ext_func_c fn state.s.in_vars state.s.out_vars ;
gen_lustre_ext_func_h fn state.s.in_vars state.s.out_vars ;
gen_lustre_ext_h fn
in
(match option.gen_mode with
| Lustre -> gen_files_for_lustre ()
| Luciole ->
let var_to_vn_ct v =
(Var.name v,
Type.to_cstring (Var.typ v)
)
in
Luciole.gen_stubs false from_lutin fn
(List.map var_to_vn_ct state.s.in_vars)
(List.map var_to_vn_ct state.s.out_vars)
| C -> ()
| Scade -> ()
| Alice ->
let alice_args = {
Luc2alice.env_name = fn;
Luc2alice.alice_module_name = option.calling_module_name ;
Luc2alice.seed = option.seed;
Luc2alice.env_in_vars = state.s.in_vars ;
Luc2alice.env_out_vars = state.s.out_vars ;
}
in
Luc2alice.gen_alice_stub_c alice_args;
Luc2alice.gen_alice_stub_h alice_args;
)
else
( try
Arg.parse speclist
(fun s -> flag.env <- (List.append flag.env [s]))
usage
with
Failure(e) ->
print_string e;
flush stdout ;
flush stderr ;
exit 2
| _ ->
exit 2
);
try
if flag.env = [] then (
print_string "*** Bad usage: you ougth to specify a lucky file in input.\n";
Arg.usage speclist usage;
flush stdout ;
flush stderr ;
exit 2
)
else
let env_list = flag.env in
let state = LucProg.make_state flag.pp env_list in
let from_lutin = Util.get_extension (List.hd env_list) = ".lut" in
let fn = build_file_name env_list in
gen_c_file fn state.s.in_vars state.s.out_vars state.s.loc_vars;
gen_h_file fn state.s.in_vars state.s.out_vars state.s.loc_vars;
(match flag.gen_mode with
| Lustre ->
gen_lustre_ext_func_c fn state.s.in_vars state.s.out_vars ;
gen_lustre_ext_func_h fn state.s.in_vars state.s.out_vars ;
gen_lustre_ext_h fn
| C -> ()
| Scade -> ()
| Alice ->
let alice_args = {
Luc2alice.env_name = fn;
Luc2alice.alice_module_name = flag.calling_module_name ;
Luc2alice.seed = flag.seed;
Luc2alice.env_in_vars = state.s.in_vars ;
Luc2alice.env_out_vars = state.s.out_vars ;
}
in
Luc2alice.gen_alice_stub_c alice_args;
Luc2alice.gen_alice_stub_h alice_args;
);
if flag.luciole then
(
let var_to_vn_ct v =
(Var.name v,
Type.to_cstring (Var.typ v)
)
in
Luciole.gen_stubs false from_lutin fn
(List.map var_to_vn_ct state.s.in_vars)
(List.map var_to_vn_ct state.s.out_vars)
)
with e ->
Arg.usage speclist usage;
flush stdout;
raise e
;;
main ();;
(*-----------------------------------------------------------------------
** Copyright (C) - Verimag.
** This file may only be copied under the terms of the GNU Library General
** Public License
**-----------------------------------------------------------------------
**
** File: luc2c.mli
** Author: jahier@imag.fr
**
** functions to generate C files to call Lucky or Lutin from C.
**
*)
(* To specify the different C backends (not all the tools have the
same convention for interfacing via C). *)
type gen_mode = C | Lustre | Scade | Alice | Luciole
type step_mode = Inside | Edges | Vertices
type optionT = {
mutable pp : string option; (* Pre-processor *)
mutable output : string option; (* A string used in generated files name *)
mutable calling_module_name : string; (* also used in generated files name *)
mutable gen_mode : gen_mode;
mutable step_mode : step_mode;
mutable seed : int option;
mutable env : string list (* lutin/lucky files *)
}
val option : optionT
val main : unit -> unit
(* *)
open LucProg
open Exp
open Prog
open Type
open Luc2c
let usage_begin = "usage: luc2c [<options>]* <.luc files or .lut file>+
"
let usage_end = "The available <options> are:"
let usage = (usage_begin ^ usage_end)
let more_usage = (usage_begin ^ "
luc2c generates C stub code in a way that is very similar to ec2c.
For example, \"luc2c f.luc\" generates \"f.c\" and \"f.h\" that defines
the type foo_ctx as well as the following functions:
foo_ctx* foo_new_ctx(void* client_data) // a function to create a lucky process
void foo_I_ivn1(foo_ctx*, <c type of ivn1>) // functions to set the inputs
void foo_I_ivn2(foo_ctx*, <c type of ivn2>)
...
void foo_step(struct foo_ctx*, step_mode sm) // a function to perform a step
and that requires the user to define the functions to get the output:
void foo_O_ovn1(foo_ctx*, <c type of ovn1>) // functions to get the outputs
void foo_O_ovn2(foo_ctx*, <c type of ovn2>)
...
The final executable needs to be linked in with the following C libs:
-lluc4c_nc -llucky_nc // distributed with luc2c
-lgmp // the Gnu Multi-precision Library
-lm -ldl -lstdc++ // ...
The lib path should (of course) contains a path to those libs. Moreover,
the include path should contain a path to the \"luc4c_stubs.h\" header file,
which is also distributed with luc2c.
" ^ usage_end)
let rec speclist =
[
"--output", Arg.String (fun s -> option.output <- Some s),
"\tTo set a string used to name the output files.";
"-o", Arg.String (fun s -> option.output <- Some s), "\n";