From 8230355e5e6b2693b0d792e0116f9a18b9fcc853 Mon Sep 17 00:00:00 2001 From: Erwan Jahier <jahier@imag.fr> Date: Mon, 9 Feb 2015 15:48:26 +0100 Subject: [PATCH] Add a --2c-stack option that uses the stack instead of the heap to transfer I/O when calling soc. Do not work all the times (eg, with arrays it generates C code that does not compile). cf next changes. --- _oasis | 2 +- src/filenameExtras.ml | 3 +- src/lic2soc.ml | 15 +- src/lv6MainArgs.ml | 31 +++- src/lv6MainArgs.mli | 10 +- src/soc.ml | 2 +- src/soc2c.ml | 197 +++++++++++++------------ src/soc2cDep.ml | 59 ++++++-- src/soc2cDep.mli | 17 ++- src/soc2cExtern.ml | 7 +- src/soc2cHeap.ml | 41 +++++- src/soc2cHeap.mli | 6 +- src/soc2cIdent.ml | 2 +- src/soc2cStack.ml | 194 +++++++++++++++++++++++++ src/soc2cStack.mli | 41 ++++++ src/soc2cUtil.ml | 9 +- src/soc2cUtil.mli | 4 +- src/socPredef2cHeap.ml | 3 +- src/socPredef2cStack.ml | 300 +++++++++++++++++++++++++++++++++++++++ src/socPredef2cStack.mli | 15 ++ src/socUtils.ml | 28 +++- src/socUtils.mli | 18 ++- test/Makefile | 8 +- test/lus2lic.sum | 26 ++-- test/lus2lic.time | 16 +-- test/should_work/ex.lus | 4 +- 26 files changed, 883 insertions(+), 175 deletions(-) create mode 100644 src/soc2cStack.ml create mode 100644 src/soc2cStack.mli create mode 100644 src/socPredef2cStack.ml create mode 100644 src/socPredef2cStack.mli diff --git a/_oasis b/_oasis index 7b440b47..b00cf5db 100644 --- a/_oasis +++ b/_oasis @@ -37,5 +37,5 @@ Library "lustre-v6" Install:true XMETAEnable: true XMETADescription: an API to call the Lustre v6 interpreter from ocaml - InternalModules: SocExecValue,SocUtils,Lv6util,Lv6version,Lv6errors,Lxm,Lv6MainArgs,Verbose,Soc,SocPredef,Ident,SocExec,SocExecEvalPredef,Compile,AstTab,AstTabSymbol,AstInstanciateModel,Lv6parserUtils,AstV6,FilenameExtras,LicTab,LicDump,AstPredef,Lic,AstCore,LicName,IdSolver,EvalConst,LicEvalConst,LicEvalType,UnifyType,Ast2lic,AstV6Dump,EvalClock,UnifyClock,LicEvalClock,EvalType,LicPrg,LicMetaOp,L2lCheckOutputs,Misc,L2lRmPoly,L2lExpandMetaOp,L2lSplit,L2lExpandNodes,L2lExpandArrays,L2lCheckLoops,Lv6lexer,Lv6parser,AstRecognizePredef,Lic2soc,ActionsDeps,SocVar,Lus2licRun,SortActions + InternalModules: SocExecValue,SocUtils,Lv6util,Lv6version,Lv6errors,Lxm,Lv6MainArgs,Verbose,Soc,SocPredef,Ident,SocExec,SocExecEvalPredef,Compile,AstTab,AstTabSymbol,AstInstanciateModel,Lv6parserUtils,AstV6,FilenameExtras,LicTab,LicDump,AstPredef,Lic,AstCore,LicName,IdSolver,EvalConst,LicEvalConst,LicEvalType,UnifyType,Ast2lic,AstV6Dump,EvalClock,UnifyClock,LicEvalClock,EvalType,LicPrg,LicMetaOp,L2lCheckOutputs,Misc,L2lRmPoly,L2lExpandMetaOp,L2lSplit,L2lExpandNodes,L2lExpandArrays,L2lCheckLoops,L2lCheckMemSafe,L2lOptimIte,Lv6lexer,Lv6parser,AstRecognizePredef,Lic2soc,Action,ActionsDeps,SocVar,Lus2licRun,SortActions # Comment se passer de cette liste à la Prevert ? diff --git a/src/filenameExtras.ml b/src/filenameExtras.ml index 3efdb568..d0f8fcbc 100644 --- a/src/filenameExtras.ml +++ b/src/filenameExtras.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 11/12/2012 (at 15:29) by Erwan Jahier> *) +(* Time-stamp: <modified the 05/02/2015 (at 17:31) by Erwan Jahier> *) let (to_list : string -> string list) = @@ -62,3 +62,4 @@ let _ = assert(simplify "/home/./name/././././dir/.././../file" = "/home/file"); assert(simplify "" = "./."); (* hum, that one is not simpler... *) assert(simplify "./a/b/../../../x" = "./../x") + diff --git a/src/lic2soc.ml b/src/lic2soc.ml index 6051eddf..814b81cd 100644 --- a/src/lic2soc.ml +++ b/src/lic2soc.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 19/01/2015 (at 14:13) by Erwan Jahier> *) +(** Time-stamp: <modified the 06/02/2015 (at 14:28) by Erwan Jahier> *) (* XXX ce module est mal écrit. A reprendre. (R1) *) @@ -424,17 +424,8 @@ let soc_step_to_operation: let (action_of_step : Lxm.t -> Soc.t -> Lic.clock -> Soc.var_expr list -> Soc.var_expr list -> Soc.instance option -> Soc.step_method -> action) = fun lxm c clk il ol mem step -> - let local_nth i l = - try List.nth l i - with _ -> - print_string ( - "\n*** Cannot get the " ^ (string_of_int (i+1)) ^ - "th element of a list of size " ^ (string_of_int (List.length l))^"\n"); - flush stdout; - assert false - in - let inputs = List.map (fun i -> local_nth i il) step.Soc.idx_ins in - let outputs = List.map (fun i -> local_nth i ol) step.Soc.idx_outs in + let inputs = SocUtils.filter_step_params step.Soc.idx_ins il in + let outputs = SocUtils.filter_step_params step.Soc.idx_outs ol in let call_action = soc_step_to_operation step.Soc.name c mem in (clk, inputs, outputs, call_action, step.Soc.lxm) diff --git a/src/lv6MainArgs.ml b/src/lv6MainArgs.ml index 545b55e4..89badcc6 100644 --- a/src/lv6MainArgs.ml +++ b/src/lv6MainArgs.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 22/01/2015 (at 11:10) by Erwan Jahier> *) +(* Time-stamp: <modified the 09/02/2015 (at 16:10) by Erwan Jahier> *) (* Le manager d'argument adapté de celui de lutin, plus joli N.B. solution un peu batarde : les options sont stockées, comme avant, dans Global, @@ -11,8 +11,9 @@ open Arg let tool_name = Lv6version.tool let usage_msg = "usage: "^tool_name^" [options] <file> | "^tool_name^" -help" -type c_code_gen_kind = Heap type enum_mode = AsInt | AsConst | AsEnum +type io_transmit_mode = Stack | Heap | HeapStack + type t = { mutable opts : (string * Arg.spec * string) list; (* classical Arg option tab used by Arg.parse *) mutable user_man : (string * string list) list; (* ad hoc tab for pretty prtting usage *) @@ -54,8 +55,8 @@ type global_opt = { mutable current_file : string; mutable line_num : int; mutable line_start_pos : int; - mutable c_code_gen : c_code_gen_kind; mutable soc2c_no_switch : bool; + mutable io_transmit_mode : io_transmit_mode; } let (global_opt:global_opt) = { @@ -69,8 +70,8 @@ let (global_opt:global_opt) = line_start_pos = 0; current_file = ""; expand_enums = AsInt; - c_code_gen = Heap; - soc2c_no_switch = false + soc2c_no_switch = false; + io_transmit_mode = Heap; } let (make_opt : unit -> t) = fun () -> @@ -358,9 +359,25 @@ let mkoptab (opt:t) : unit = ( *) mkopt opt ~hide:true ["-cc"] - (Arg.Unit (fun i -> opt.launch_cc <- true)) - ["Try to compile the generated C files (requires -2c)"] + (Arg.Unit (fun i -> opt.gen_c <- true; opt.launch_cc <- true)) + ["Try to compile the generated C files (forces -2c)"] + ; + mkopt opt ~hide:true + ["-2cs";"--2c-stack"] + (Arg.Unit (fun i -> opt.gen_c <- true; global_opt.io_transmit_mode <- Stack)) + ["Soc I/O are transmitted as params of the step functions (forces -2c)"] + ; + mkopt opt ~hide:true + ["--2c-heap"] + (Arg.Unit (fun i -> opt.gen_c <- true; global_opt.io_transmit_mode <- Heap)) + ["Soc I/O are transmitted via a ctx structure in the heap (forces -2c)"] + ; + mkopt opt ~hide:true + ["-2chs";"--2c-heap-and-stack"] + (Arg.Unit (fun i -> opt.gen_c <- true; global_opt.io_transmit_mode <- HeapStack)) + ["I/O of memoryless soc are transmitted via the stack, and the heap otherwise (forces -2c)"] ; + mkopt opt ~hide:true ["--2c-no-switch"] (Arg.Unit (fun () -> global_opt.soc2c_no_switch <-true)) diff --git a/src/lv6MainArgs.mli b/src/lv6MainArgs.mli index 3da308ad..c9911ca7 100644 --- a/src/lv6MainArgs.mli +++ b/src/lv6MainArgs.mli @@ -9,8 +9,12 @@ type enum_mode = les options dans des var. globales ! (cf Global *) -type c_code_gen_kind = Heap - +type io_transmit_mode = + | Stack (* All I/O are are passed as arguments of the step functions *) + | Heap (* All I/O are in a ctx structure; ctx of memoryless soc are global *) + | HeapStack (* I/O of memoryful soc are in a ctx structure; memoryless soc uses step arg *) +(* *) + type t = { mutable opts : (string * Arg.spec * string) list; (* classical Arg option tab used by Arg.parse *) mutable user_man : (string * string list) list; (* ad hoc tab for pretty prtting usage *) @@ -51,8 +55,8 @@ type global_opt = { mutable current_file : string; mutable line_num : int; mutable line_start_pos : int; - mutable c_code_gen : c_code_gen_kind; mutable soc2c_no_switch : bool; + mutable io_transmit_mode : io_transmit_mode; } val paranoid : Verbose.flag diff --git a/src/soc.ml b/src/soc.ml index 641d2b5a..ade7eea1 100644 --- a/src/soc.ml +++ b/src/soc.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 06/01/2015 (at 11:35) by Erwan Jahier> *) +(* Time-stamp: <modified the 28/01/2015 (at 15:22) by Erwan Jahier> *) (** Synchronous Object Component *) diff --git a/src/soc2c.ml b/src/soc2c.ml index f79d653f..973fe52c 100644 --- a/src/soc2c.ml +++ b/src/soc2c.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 21/01/2015 (at 17:50) by Erwan Jahier> *) +(* Time-stamp: <modified the 09/02/2015 (at 15:08) by Erwan Jahier> *) (* let put (os: out_channel) (fmt:('a, unit, string, unit) format4) : 'a = *) @@ -41,11 +41,6 @@ type 'a soc_pp = { let (string_of_soc_key : Soc.key -> string) = fun (name,_,_) -> (id2s name) -let string_of_flow_decl (id, t) = - Printf.sprintf " %s;\n" (Soc2cUtil.type_to_string t (id2s id)) - - -let (is_memory_less : Soc.t -> bool) = SocUtils.is_memory_less let string_of_var_expr = Soc2cDep.string_of_var_expr open Soc @@ -69,7 +64,8 @@ let (gao2c : Soc.tbl -> 'a soc_pp -> Soc.gao -> unit) = let ctx_opt = let il,ol = sp.soc.profile in if List.mem_assoc id il || List.mem_assoc id ol then - (if SocUtils.is_memory_less sp.soc then Soc2cUtil.ML_IO sp.soc.key + (if SocUtils.ctx_is_global sp.soc + then Soc2cUtil.ML_IO sp.soc.key else Soc2cUtil.M_IO) else Soc2cUtil.Local in @@ -109,20 +105,15 @@ let (step2c : Soc.tbl -> 'a soc_pp -> Soc.step_method -> unit) = if inlined_soc sp.soc then () (* don't generate code if inlined *) else (* let sname = Soc2cDep.step_name sp.soc.key sm.name in *) let sname = Soc2cDep.step_name sp.soc.key sm.name in - let ctx = if is_memory_less sp.soc then "" else - Printf.sprintf "%s_type* ctx" (get_ctx_name sp.soc.key) - in - let ctx_decl = if is_memory_less sp.soc then "" else - Printf.sprintf "%s_type*" (get_ctx_name sp.soc.key) - in if sm.impl<>Extern then ( - sp.hput (Printf.sprintf "void %s(%s);\n" sname ctx_decl); - sp.cput (Printf.sprintf "void %s(%s){\n" sname ctx); + let decl, def = Soc2cDep.get_step_prototype sm sp.soc in + sp.hput (Printf.sprintf "%s\n" decl); + sp.cput (Printf.sprintf "%s\n" def); (match sm.impl with | Extern -> () | Predef -> sp.cput (Soc2cDep.get_predef_op sp.soc.key) | Gaol(vl, gaol) -> ( - List.iter (fun v -> sp.cput (string_of_flow_decl v)) vl ; + List.iter (fun v -> sp.cput (Soc2cUtil.string_of_flow_decl v)) vl ; sp.cput "\n"; List.iter (gao2c stbl sp) gaol ) @@ -153,9 +144,9 @@ let (soc2c: int -> out_channel -> out_channel -> Soc.tbl -> Soc.t -> unit) = let ctx_name_type = ctx_name^"_type" in if pass=1 then ( (* Only for ctx of memoryless nodes + main node *) - if is_memory_less soc then cfmt "%s %s;\n" ctx_name_type ctx_name; + if SocUtils.ctx_is_global soc then cfmt "%s %s;\n" ctx_name_type ctx_name; ) else ( - if is_memory_less soc then () else ( + if SocUtils.is_memory_less soc then () else ( cfmt "// Memory initialisation for %s\n" ctx_name; hfmt "void %s_reset(%s_type* ctx);\n" ctx_name ctx_name; cfmt "void %s_reset(%s_type* ctx){" ctx_name ctx_name; @@ -171,16 +162,20 @@ let (soc2c: int -> out_channel -> out_channel -> Soc.tbl -> Soc.t -> unit) = cfmt " } "; - cfmt "// Memory allocation for %s\n" ctx_name; - hfmt "%s_type* %s_new_ctx();\n" ctx_name ctx_name; - cfmt "%s_type* %s_new_ctx(){" ctx_name ctx_name; - cfmt " + if + SocUtils.is_memory_less soc + then () (*no ctx at all in this case ! *) else ( + cfmt "// Memory allocation for %s\n" ctx_name; + hfmt "%s_type* %s_new_ctx();\n" ctx_name ctx_name; + cfmt "%s_type* %s_new_ctx(){" ctx_name ctx_name; + cfmt " %s_type* ctx = (%s_type*)calloc(1, sizeof(%s_type)); // ctx->client_data = cdata; %s_reset(ctx); return ctx; } -" ctx_name ctx_name ctx_name ctx_name) ; +" ctx_name ctx_name ctx_name ctx_name) + ); cfmt "// Step function(s) for %s\n" ctx_name; List.iter (step2c stbl sp) soc.step; () @@ -202,31 +197,6 @@ let (type_to_format_string : Data.t -> string) = (****************************************************************************) -let (typedef_of_soc : Soc.t -> string) = - fun soc -> - if inlined_soc soc then "" (* don't generate code if inlined *) else - let ctx_name = get_ctx_name soc.key in - let ctx_name_type = ctx_name^"_type" in - let il,ol = soc.profile in - let str = Printf.sprintf "/* %s */\ntypedef struct {\n /*INPUTS*/\n" ctx_name in - let str = List.fold_left (fun acc v -> acc^ (string_of_flow_decl v)) str il in - let str = str ^ " /*OUTPUTS*/\n" in - let str = List.fold_left (fun acc v -> acc^ (string_of_flow_decl v)) str ol in - let str = str ^ - (match soc.memory with - | No_mem -> "" - | Mem t -> - Printf.sprintf " /*Memory cell*/\n %s ;\n" (id2s (Soc2cUtil.type_to_string t "_memory")) - | Mem_hidden -> "" - ) - in - let str = str ^ (if soc.instances <> [] then " /*INSTANCES*/\n" else "") in - let string_of_instance (id,sk) = - Printf.sprintf " %s_type %s;\n" (get_ctx_name sk) (id2s id) - in - let str = List.fold_left (fun acc inst -> acc^(string_of_instance inst)) str soc.instances in - let str = Printf.sprintf "%s} %s;\n\n" str ctx_name_type in - str module KeySet = Set.Make(struct type t = Soc.key let compare = compare end) module ItemKeySet = Set.Make(struct type t = Lic.item_key let compare = compare end) @@ -273,11 +243,11 @@ let (typedef : LicPrg.t -> Soc.tbl -> Soc.t -> string) = ) (acc,visited) soc.instances in - let acc = acc ^ (typedef_of_soc soc) in + let acc = acc ^ (Soc2cDep.typedef_of_soc soc) in acc,visited in let soc_ctx_typedef_with = - if is_memory_less main_soc then "" else fst (soc_with_mem ("",visited) main_soc) + if SocUtils.ctx_is_global main_soc then "" else fst (soc_with_mem ("",visited) main_soc) in (* Then we still have to print memoryless soc that can not appear as a soc instance *) @@ -285,7 +255,7 @@ let (typedef : LicPrg.t -> Soc.tbl -> Soc.t -> string) = let socs = Soc.SocMap.bindings soc_tbl in let socs = snd (List.split socs) in let memless_soc_to_string acc soc = - if is_memory_less soc then acc^(typedef_of_soc soc) else acc + if SocUtils.is_memory_less soc then acc^(Soc2cDep.typedef_of_soc soc) else acc in List.fold_left memless_soc_to_string "" socs in @@ -354,22 +324,29 @@ let (constdef : LicPrg.t -> string) = (long2s k) (const_to_c c) in - LicPrg.fold_consts (fun k t acc -> acc ^ (to_c k t)) licprg "\n// Constant definitions \n" + let str = LicPrg.fold_consts (fun k t acc -> acc ^ (to_c k t)) licprg "" in + if str = "" then "" else + "\n// Constant definitions \n" ^ str (****************************************************************************) let (gen_memoryless_ctx : Soc.tbl -> string) = fun stbl -> - let acc = Printf.sprintf "\n// Allocation of memoryless ctx\n" in let do_soc sk soc acc = - if is_memory_less soc && not (inlined_soc soc) then + if (SocUtils.ctx_is_global soc) && not (inlined_soc soc) then let ctx_name = get_ctx_name soc.key in let ctx_name_type = ctx_name^"_type" in Printf.sprintf "%sextern %s %s;\n" acc ctx_name_type ctx_name - else acc + else + acc in - Soc.SocMap.fold do_soc stbl acc + let acc = Soc.SocMap.fold do_soc stbl "" in + if acc = "" then "" else + Printf.sprintf "\n// Allocation of memoryless ctx\n%s" acc + +(* a shortcut *) +let io_transmit_mode () = Lv6MainArgs.global_opt.Lv6MainArgs.io_transmit_mode (****************************************************************************) let (gen_loop_file : Soc.t -> out_channel -> Soc.tbl -> unit) = @@ -491,13 +468,29 @@ void "^n^"_O_n(void* cdata, _integer _V) { }"^ (gen_memoryless_ctx stbl) ^ "/* Main procedure *************************/ int main(){ - - int s = 0; - /* Context allocation */ - "^ctx^"_type* ctx = "^(if is_memory_less soc then ( - "&"^ ctx^ ";" - ) else (ctx^"_new_ctx(NULL);"))); - + int s = 0;" ^ ( + match io_transmit_mode () with + | Lv6MainArgs.Stack -> + let to_c_decl (n,t) = ((Soc2cUtil.type_to_string t "")^ " " ^n^";\n ") in + let inputs_t = List.map to_c_decl inputs_io in + let outputs_t = List.map to_c_decl outputs_io in + let inputs_decl = Printf.sprintf "\n %s" (String.concat "" inputs_t) in + let outputs_decl = Printf.sprintf "%s" (String.concat "" outputs_t) in + let ctx_decl = if SocUtils.is_memory_less soc then "" else + ctx^"_type* ctx ;\n "^ ctx^"_reset(ctx);" + in + inputs_decl ^ outputs_decl ^ ctx_decl + | Lv6MainArgs.Heap -> (" + /* Context allocation */ + " ^ (if SocUtils.is_memory_less soc then ctx^"_type* ctx = &"^ctx^";\n" + else ctx^"_type* ctx = "^ ctx^"_new_ctx(NULL);") + ) + | Lv6MainArgs.HeapStack -> (" + /* Context allocation */ + " ^ (if SocUtils.is_memory_less soc then ctx^"" + else ctx^"_type* ctx ;\n"^ ctx^"_reset(ctx);") + ) + )); let to_rif_decl (n,t) = ("\\\""^n^"\\\":" ^(type_to_string t)) in let inputs_t = List.map to_rif_decl inputs_io in let outputs_t = List.map to_rif_decl outputs_io in @@ -505,43 +498,65 @@ int main(){ let outputs_decl = Printf.sprintf "#outputs %s" (String.concat " " outputs_t) in putc (" - printf(\""^inputs_decl^"\\n\"); - printf(\""^outputs_decl^"\\n\"); - - /* Main loop */ - ISATTY = isatty(0); - while(1){ - if (ISATTY) printf(\"#step %d \\n\", s+1); - else if(s) printf(\"\\n\"); - fflush(stdout); - ++s; + printf(\""^inputs_decl^"\\n\"); + printf(\""^outputs_decl^"\\n\"); + + /* Main loop */ + ISATTY = isatty(0); + while(1){ + if (ISATTY) printf(\"#step %d \\n\", s+1); + else if(s) printf(\"\\n\"); + fflush(stdout); + ++s; "); List.iter (fun (id,t) -> let t = type_to_string2 t in - let str = Printf.sprintf " ctx->%s = _get_%s(\"%s\");\n" id t id in + let str = + if io_transmit_mode () = Lv6MainArgs.Stack + then Printf.sprintf " %s = _get_%s(\"%s\");\n" id t id + else Printf.sprintf " ctx->%s = _get_%s(\"%s\");\n" id t id + in putc str ) inputs; let inputs_fmt = List.map (fun (_,t) -> type_to_format_string t) inputs in let outputs_fmt = List.map (fun (_,t) -> type_to_format_string t) outputs in - putc (" " ^ step^"(ctx); - // printf(\"" ^ (String.concat " " inputs_fmt)^ " #outs " ^ - (String.concat " " outputs_fmt)^ "\\n\"," ^ - (String.concat "," (List.map (fun (id,_) -> "ctx->"^id ) (inputs@outputs)))^ - "); - printf(\"" ^ - (String.concat " " outputs_fmt)^ "\\n\"," ^ + if io_transmit_mode () = Lv6MainArgs.Stack + then + let i = fst (List.split inputs_io) in + let o = fst (List.split outputs_io) in + let o = List.map (fun s -> "&"^s) o in + let io = String.concat "," (i@o) in + let io = if SocUtils.is_memory_less soc then io else if io = "" then "ctx" else io^",ctx" in + putc (" " ^ step^"("^io^"); + // printf(\"" ^ (String.concat " " inputs_fmt)^ " #outs " ^ + (String.concat " " outputs_fmt)^ "\\n\"," ^ + (String.concat "," (List.map (fun (id,_) -> ""^id ) (inputs@outputs)))^ + "); + printf(\"" ^ + (String.concat " " outputs_fmt)^ "\\n\"," ^ + (String.concat "," (List.map (fun (id,_) -> ""^id ) (outputs)))^ + "); + }" + ) else ( + putc (" " ^ step^"(ctx); + // printf(\"" ^ (String.concat " " inputs_fmt)^ " #outs " ^ + (String.concat " " outputs_fmt)^ "\\n\"," ^ + (String.concat "," (List.map (fun (id,_) -> "ctx->"^id ) (inputs@outputs)))^ + "); + printf(\"" ^ + (String.concat " " outputs_fmt)^ "\\n\"," ^ (String.concat "," (List.map (fun (id,_) -> "ctx->"^id ) (outputs)))^ - "); - } - return 1; + "); + }")); + putc "\n return 1; } -") +" (****************************************************************************) (* The entry point for lus2lic --to-c *) -let (f : Lv6MainArgs.t -> Soc.key -> Soc.tbl -> LicPrg.t -> unit) = + let (f : Lv6MainArgs.t -> Soc.key -> Soc.tbl -> LicPrg.t -> unit) = fun args msoc stbl licprg -> let socs = Soc.SocMap.bindings stbl in let socs = snd (List.split socs) in @@ -597,10 +612,12 @@ typedef float _float; putc (constdef licprg); (* putc (Soc2cExtern.cpy_declaration licprg); *) putc (Soc2cExtern.const_declaration licprg); - puth "/////////////////////////////////////////////////\n"; - puth "//// Static allocation of memoryless soc ctx\n"; - List.iter (soc2c 1 och occ stbl) socs; - puth "/////////////////////////////////////////////////\n"; + if io_transmit_mode () = Lv6MainArgs.Heap then ( + puth "/////////////////////////////////////////////////\n"; + puth "//// Static allocation of memoryless soc ctx\n"; + List.iter (soc2c 1 och occ stbl) socs; + puth "/////////////////////////////////////////////////\n" + ); putc "//// Defining step functions\n"; List.iter (soc2c 2 och occ stbl) socs; diff --git a/src/soc2cDep.ml b/src/soc2cDep.ml index c07de43d..54862e01 100644 --- a/src/soc2cDep.ml +++ b/src/soc2cDep.ml @@ -1,48 +1,77 @@ -(* Time-stamp: <modified the 21/01/2015 (at 17:52) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/02/2015 (at 10:52) by Erwan Jahier> *) open Lv6MainArgs -let gen_assign x = - match global_opt.c_code_gen with - | Heap -> Soc2cHeap.gen_assign x - let gen_assign_var_expr x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> Soc2cHeap.gen_assign_var_expr x + | HeapStack -> Soc2cHeap.gen_assign_var_expr x + | Stack -> Soc2cStack.gen_assign_var_expr x let step_name x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> Soc2cHeap.step_name x + | HeapStack -> Soc2cHeap.step_name x + | Stack -> Soc2cStack.step_name x + +let get_step_prototype x y = + match global_opt.io_transmit_mode with + | Heap -> Soc2cHeap.get_step_prototype x y + | HeapStack -> Soc2cHeap.get_step_prototype x y + | Stack -> Soc2cStack.get_step_prototype x y let string_of_var_expr x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> Soc2cHeap.string_of_var_expr x + | HeapStack -> Soc2cHeap.string_of_var_expr x + | Stack -> Soc2cStack.string_of_var_expr x let ctx_var x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> Soc2cHeap.ctx_var x + | HeapStack -> Soc2cHeap.ctx_var x + | Stack -> Soc2cStack.ctx_var x let gen_step_call x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> Soc2cHeap.gen_step_call x + | HeapStack -> Soc2cHeap.gen_step_call x + | Stack -> Soc2cStack.gen_step_call x let inlined_soc x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> Soc2cHeap.inlined_soc x + | HeapStack -> Soc2cHeap.inlined_soc x + | Stack -> Soc2cStack.inlined_soc x +let typedef_of_soc x = + match global_opt.io_transmit_mode with + | Heap -> Soc2cHeap.typedef_of_soc x + | HeapStack -> Soc2cHeap.typedef_of_soc x + | Stack -> Soc2cStack.typedef_of_soc x let get_predef_op x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> SocPredef2cHeap.get_predef_op x + | HeapStack -> SocPredef2cHeap.get_predef_op x + | Stack -> SocPredef2cStack.get_predef_op x let get_iterator x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> SocPredef2cHeap.get_iterator x + | HeapStack -> SocPredef2cHeap.get_iterator x + | Stack -> SocPredef2cStack.get_iterator x let get_condact x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> SocPredef2cHeap.get_condact x + | HeapStack -> SocPredef2cHeap.get_condact x + | Stack -> SocPredef2cStack.get_condact x let get_boolred x = - match global_opt.c_code_gen with + match global_opt.io_transmit_mode with | Heap -> SocPredef2cHeap.get_boolred x + | HeapStack -> SocPredef2cHeap.get_boolred x + | Stack -> SocPredef2cStack.get_boolred x + + diff --git a/src/soc2cDep.mli b/src/soc2cDep.mli index c46d6325..d1350f6e 100644 --- a/src/soc2cDep.mli +++ b/src/soc2cDep.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 03/10/2014 (at 11:17) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/02/2015 (at 11:07) by Erwan Jahier> *) (** Choose between the various C code generators (heap-based, Stack @@ -8,16 +8,21 @@ with this name... *) -(* [gen_assign t vi vo size] generated the C code that assign vo to vi, - using memcpy or = depending on the type t *) -val gen_assign : Data.t -> string -> string -> string -> string - (* ditto *) val gen_assign_var_expr : Soc.t -> Soc.var_expr -> Soc.var_expr -> string (* Generates the C step name from the soc key and the soc step name *) val step_name : Soc.key -> string -> string +(* returns the step declaration (to put in the .h) and step header + (to put in the .c) + For instance , something like: + "void step(ctx_type, int, int, int* );", + "void step(ctx_type ctx, int x, int y,int* z){", +*) +val get_step_prototype : Soc.step_method -> Soc.t -> string * string + + val string_of_var_expr: Soc.t -> Soc.var_expr -> string @@ -51,4 +56,6 @@ val get_condact : Soc.t -> Soc.t -> Soc.var_expr list -> string (** Returns the C code implementing a boolred *) val get_boolred : Soc.t -> int -> int -> int -> string +val typedef_of_soc : Soc.t -> string + diff --git a/src/soc2cExtern.ml b/src/soc2cExtern.ml index b8babd3b..832c0057 100644 --- a/src/soc2cExtern.ml +++ b/src/soc2cExtern.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 03/10/2014 (at 17:41) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/02/2015 (at 16:07) by Erwan Jahier> *) open Soc2cIdent @@ -25,6 +25,7 @@ let (type_decl : LicPrg.t -> string) = let str = LicPrg.fold_types type_to_string prg "" in if str = "" then "" else (preambule^""^str^"\n") + (* Now done in soc2cGenAssign.ml let (cpy_def : LicPrg.t -> string) = fun prg -> @@ -121,7 +122,7 @@ let (gen_files : Soc.t -> Soc.tbl -> LicPrg.t -> string -> string-> string -> bo (* output_string ext_och (cpy_decl licprg); *) List.iter (fun (sm,soc) -> let sname = Soc2cDep.step_name soc.key sm.name in - if SocUtils.is_memory_less soc then + if SocUtils.ctx_is_global soc then output_string ext_och (Printf.sprintf "void %s();\n" sname) else let ctx = get_ctx_name soc.key in @@ -139,7 +140,7 @@ let (gen_files : Soc.t -> Soc.tbl -> LicPrg.t -> string -> string-> string -> bo output_string ext_occ (const_def licprg); List.iter (fun (sm,soc) -> let sname = Soc2cDep.step_name soc.key sm.name in - if SocUtils.is_memory_less soc then + if SocUtils.ctx_is_global soc then output_string ext_occ (Printf.sprintf "void %s(){\n /* finish me! */\n}\n" sname) else let ctx = get_ctx_name soc.key in diff --git a/src/soc2cHeap.ml b/src/soc2cHeap.ml index 14ca58a5..6c9d2224 100644 --- a/src/soc2cHeap.ml +++ b/src/soc2cHeap.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 03/10/2014 (at 18:03) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/02/2015 (at 16:08) by Erwan Jahier> *) open Soc2cUtil open Soc2cIdent @@ -153,3 +153,42 @@ let (gen_step_call : Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list -> in let str = Printf.sprintf " %s(%s); \n" (step_name called_soc.key sname) step_arg in (si_str ^ str ^ so_str) + +(* exported *) +let (typedef_of_soc : Soc.t -> string) = + fun soc -> + if inlined_soc soc then "" (* don't generate code if inlined *) else + let ctx_name = get_ctx_name soc.key in + let ctx_name_type = ctx_name^"_type" in + let il,ol = soc.profile in + let str = Printf.sprintf "/* %s */\ntypedef struct {\n /*INPUTS*/\n" ctx_name in + let str = List.fold_left (fun acc v -> acc^ (string_of_flow_decl v)) str il in + let str = str ^ " /*OUTPUTS*/\n" in + let str = List.fold_left (fun acc v -> acc^ (string_of_flow_decl v)) str ol in + let str = str ^ + (match soc.memory with + | No_mem -> "" + | Mem t -> + Printf.sprintf " /*Memory cell*/\n %s ;\n" (id2s (Soc2cUtil.type_to_string t "_memory")) + | Mem_hidden -> "" + ) + in + let str = str ^ (if soc.instances <> [] then " /*INSTANCES*/\n" else "") in + let string_of_instance (id,sk) = + Printf.sprintf " %s_type %s;\n" (get_ctx_name sk) (id2s id) + in + let str = List.fold_left (fun acc inst -> acc^(string_of_instance inst)) str soc.instances in + let str = Printf.sprintf "%s} %s;\n\n" str ctx_name_type in + str + +let (get_step_prototype : Soc.step_method -> Soc.t -> string * string) = + fun sm soc -> + let sname = step_name soc.key sm.name in + let ctx = if SocUtils.is_memory_less soc then "" else + Printf.sprintf "%s_type* ctx" (get_ctx_name soc.key) + in + let ctx_decl = if SocUtils.is_memory_less soc then "" else + Printf.sprintf "%s_type*" (get_ctx_name soc.key) + in + Printf.sprintf "void %s(%s);\n" sname ctx_decl, + Printf.sprintf "void %s(%s){\n" sname ctx diff --git a/src/soc2cHeap.mli b/src/soc2cHeap.mli index 4e382cc1..bffcc930 100644 --- a/src/soc2cHeap.mli +++ b/src/soc2cHeap.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 03/10/2014 (at 10:17) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/02/2015 (at 11:07) by Erwan Jahier> *) (** Gathers all entities (functions, types) that implement the heap-based C generator. *) @@ -13,6 +13,8 @@ val gen_assign_var_expr : Soc.t -> Soc.var_expr -> Soc.var_expr -> string (* Generates the C step name from the soc key and the soc step name *) val step_name : Soc.key -> string -> string +val get_step_prototype : Soc.step_method -> Soc.t -> string * string + val string_of_var_expr: Soc.t -> Soc.var_expr -> string @@ -32,3 +34,5 @@ val gen_step_call : Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list -> string -> string -> string -> string (* should this soc be inlined? (depends on Lv6MainArgs.global_opt) *) val inlined_soc : Soc.t -> bool + +val typedef_of_soc : Soc.t -> string diff --git a/src/soc2cIdent.ml b/src/soc2cIdent.ml index fcd2826b..13eaf6b1 100644 --- a/src/soc2cIdent.ml +++ b/src/soc2cIdent.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 27/01/2015 (at 10:31) by Erwan Jahier> *) +(* Time-stamp: <modified the 28/01/2015 (at 15:18) by Erwan Jahier> *) open Soc let colcol = Str.regexp "::" diff --git a/src/soc2cStack.ml b/src/soc2cStack.ml new file mode 100644 index 00000000..ebb2a2de --- /dev/null +++ b/src/soc2cStack.ml @@ -0,0 +1,194 @@ +(* Time-stamp: <modified the 06/02/2015 (at 15:15) by Erwan Jahier> *) + +open Soc2cUtil +open Soc2cIdent +open Soc + + +let (mem_interface : Soc.t -> string -> bool) = + fun soc id -> + let ins,outs = soc.profile in + List.mem_assoc id ins || List.mem_assoc id outs + +let rec (string_of_var_expr: Soc.t -> Soc.var_expr -> string) = + fun soc -> function + | Const("true", _) -> "_true" + | Const("false", _) -> "_false" + | Const(id, _) -> id2s id + | Var ("_memory",_) -> (* Clutch! it's not an interface var... *) "ctx->_memory" + | Var (id,_) -> id2s id + | Field(f, id,_) -> Printf.sprintf "%s.%s" (string_of_var_expr soc f) (id2s id) + | Index(f, index,_) -> Printf.sprintf "%s[%i]" (string_of_var_expr soc f) index + | Slice(f,fi,la,st,wi,vt) -> assert false (* should not occur *) + + +(* exported *) +let rec (gen_assign : Data.t -> string -> string -> string -> string) = + fun t vi vo size -> + match t with + | Data.Alias(_,t) -> gen_assign t vi vo size + | Data.Enum _ + | Data.Struct(_) (* should I rather use memcpy for struct? *) + | Data.Bool | Data.Int | Data.Real -> Printf.sprintf " %s = %s;\n" vi vo + | Data.Alpha(_) (* dead code ? *) + | Data.Array(_) -> + let t_str = Soc2cIdent.type_to_short_string t in + Printf.sprintf " _assign_%s(%s, %s, sizeof(%s));\n" t_str vi vo vi + + | Data.Extern (id) -> + Printf.sprintf " _assign_%s(&%s, &%s, sizeof(%s));\n" (id2s id) vi vo vo + +let (is_soc_output : Soc.var_expr -> Soc.t -> bool) = + fun v soc -> + match v with + | Var(v) -> List.mem v (snd soc.profile) + | _ -> false + +let (gen_assign_var_expr : Soc.t -> Soc.var_expr -> Soc.var_expr -> string) = +fun soc vi vo -> + match vi,vo with + | Slice _, _ | _, Slice _ -> assert false + | _,_ -> + let left = string_of_var_expr soc vi in + let left = if is_soc_output vi soc then "*"^left else left in + gen_assign (Soc.data_type_of_var_expr vi) left (string_of_var_expr soc vo) + (Printf.sprintf "sizeof(%s)" (string_of_var_expr soc vo)) + + +let (step_name : Soc.key -> string -> string) = + fun sk sm -> + let str = Printf.sprintf "%s_%s" (Soc2cIdent.get_soc_name sk) sm in + id2s str + +let (ctx_var : var_kind -> Ident.t -> string) = + fun opt id -> + Printf.sprintf "%s" (id2s id) + +let (list_split : 'a list -> int -> 'a list * 'a list) = + fun l s -> + let rec aux s l acc = + match s,l with + | 0, _ -> List.rev acc,l + | _, x::l -> aux (s-1) l (x::acc) + | _, [] -> assert false + in + aux s l [] + +let _ = assert (list_split [1;2;3;4;5;6] 3 = ([1;2;3],[4;5;6])) + +let (inline_soc : Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list -> string option) = + fun soc called_soc vel_out vel_in -> + let called_soc_name,_,_ = called_soc.key in + match called_soc_name with + (* those soc are inlined. Currently we only inline ite because + of its polymorphism. Simple arith operators (+,-,*,/,etc.) + should be inlined too. *) + | "Lustre::if" -> + let c,vel_in= match vel_in with [] -> assert false | c::l -> c,l in + let s = (List.length vel_out) in + let vel_in_t, vel_in_e = list_split vel_in s in + let lt = List.map2 (gen_assign_var_expr soc) vel_out vel_in_t in + let le = List.map2 (gen_assign_var_expr soc) vel_out vel_in_e in + let str = " if ("^(string_of_var_expr soc c) ^ " == _true) {\n "^ + (String.concat " " lt)^ " } else {\n "^ + (String.concat " " le)^ " }\n" + in + Some str + | _ -> + try + if + Lv6MainArgs.global_opt.Lv6MainArgs.gen_c_inline_predef + && Soc2cPredef.is_call_supported called_soc_name soc + then + let vel_in = List.map (string_of_var_expr soc) vel_in in + let vel_out_str = List.map (string_of_var_expr soc) vel_out in + let vel_out = List.map2 + (fun v s -> if is_soc_output v soc then "*"^s else s) vel_out vel_out_str + in + Some (Soc2cPredef.gen_call called_soc_name soc vel_out vel_in) + else + None + with Not_found -> +(* Printf.eprintf "won't inline %s\n" called_soc_name; *) + None +(* exported *) +let (inlined_soc : Soc.t -> bool) = + fun soc -> + let soc_name,_,_ = soc.key in + soc_name = "Lustre::if" || Soc2cPredef.is_call_supported soc_name soc + + +(* exported *) +let (gen_step_call : Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list -> + string -> string -> string -> string) = + fun soc called_soc vel_out vel_in ctx sname step_arg -> + match inline_soc soc called_soc vel_out vel_in with + | Some str -> str + | None -> + let vel_in = List.map (string_of_var_expr soc) vel_in in + let vel_out_str = List.map (string_of_var_expr soc) vel_out in + let vel_out = + List.map2 (fun v s -> if is_soc_output v soc then s else "&"^s) vel_out vel_out_str + in + let step_arg = if step_arg = "" then [] else [step_arg] in + let step_arg = String.concat "," (vel_in@vel_out@step_arg) in + let str = Printf.sprintf " %s(%s); \n" (step_name called_soc.key sname) step_arg in + str + +(* exported *) +let (typedef_of_soc : Soc.t -> string) = + fun soc -> + if inlined_soc soc then "" (* don't generate code if inlined *) else + if SocUtils.is_memory_less soc then "" else + let ctx_name = get_ctx_name soc.key in + let ctx_name_type = ctx_name^"_type" in + let str = Printf.sprintf "/* %s */\ntypedef struct {\n" ctx_name in + let str = str ^ + (match soc.memory with + | No_mem -> "" + | Mem t -> Printf.sprintf " /*Memory cell*/\n %s ;\n" + (id2s (Soc2cUtil.type_to_string t "_memory")) + | Mem_hidden -> "" + ) + in + let str = str ^ (if soc.instances <> [] then " /*INSTANCES*/\n" else "") in + let string_of_instance (id,sk) = + Printf.sprintf " %s_type %s;\n" (get_ctx_name sk) (id2s id) + in + let str = List.fold_left (fun acc inst -> acc^(string_of_instance inst)) str soc.instances in + let str = Printf.sprintf "%s} %s;\n\n" str ctx_name_type in + str + +(* exported *) +(* for soc of type (int * int -> int), it generates something like + +"void step(int, int, int*, soc_ctx_type* );", +"void step(int x, int y, int* res, soc_ctx_type* ctx){" + +*) +let (get_step_prototype : Soc.step_method -> Soc.t -> string * string) = + fun sm soc -> + let sname = step_name soc.key sm.name in + let inputs, outputs = soc.Soc.profile in + let inputs = SocUtils.filter_step_params sm.Soc.idx_ins inputs in + let outputs = SocUtils.filter_step_params sm.Soc.idx_outs outputs in + let to_param (id,dt) = Soc2cUtil.type_to_string dt "",id in + let in_params = List.map to_param inputs in + let out_params = List.map to_param outputs in + let out_params = List.map (fun (t,id) -> t^"*",id) out_params in + + let in_params_decl = List.map fst in_params in + let out_params_decl = List.map fst out_params in + let in_params = List.map (fun (t,id) -> t^" "^id) in_params in + let out_params = List.map (fun (t,id) -> t^" "^id) out_params in + + let params = String.concat "," (in_params@out_params) in + let params_decl = String.concat "," (in_params_decl@out_params_decl) in + if SocUtils.is_memory_less soc then + Printf.sprintf "void %s(%s);\n" sname params_decl, + Printf.sprintf "void %s(%s){\n" sname params + else + let ctx = Printf.sprintf "%s_type* ctx" (get_ctx_name soc.key) in + let ctx_decl = Printf.sprintf "%s_type*" (get_ctx_name soc.key) in + Printf.sprintf "void %s(%s,%s);\n" sname params_decl ctx_decl, + Printf.sprintf "void %s(%s,%s){\n" sname params ctx diff --git a/src/soc2cStack.mli b/src/soc2cStack.mli new file mode 100644 index 00000000..32896afa --- /dev/null +++ b/src/soc2cStack.mli @@ -0,0 +1,41 @@ +(* Time-stamp: <modified the 06/02/2015 (at 11:06) by Erwan Jahier> *) + +(** Gathers all entities (functions, types) that implement the + heap-based C generator. *) + +(** [gen_assign t vi vo size] generated the C code that assign vo to vi, + using memcpy or = depending on the type t *) +val gen_assign : Data.t -> string -> string -> string -> string + +(** ditto *) +val gen_assign_var_expr : Soc.t -> Soc.var_expr -> Soc.var_expr -> string + +(** Generates the C step name from the soc key and the soc step name *) +val step_name : Soc.key -> string -> string + +(** Returns the prototype (.c) and the decl (.h) of the step function. + For the stack based approach, we need to arg I/O params. + *) +val get_step_prototype : Soc.step_method -> Soc.t -> string * string + +val string_of_var_expr: Soc.t -> Soc.var_expr -> string + + +(* [ctx_var vk id] *) +val ctx_var : Soc2cUtil.var_kind -> Ident.t -> string + +(** [gen_step_call soc called_soc vel_out vel_in ctx sname step_arg] + Generates the C code that performs the call to a step method of + [called_soc] from [soc]. + - [vel_out] and [vel_in] are the called_soc O/I arguments + - [ctx] is the C name of the context of the called_soc + - [sname] is the C name of the step to call + - [step_arg] is a string holding the arg of the step (empty for proc call) +*) + +val gen_step_call : Soc.t -> Soc.t -> Soc.var_expr list -> Soc.var_expr list -> + string -> string -> string -> string +(* should this soc be inlined? (depends on Lv6MainArgs.global_opt) *) +val inlined_soc : Soc.t -> bool + +val typedef_of_soc : Soc.t -> string diff --git a/src/soc2cUtil.ml b/src/soc2cUtil.ml index 38b15d0a..3ea2b5bd 100644 --- a/src/soc2cUtil.ml +++ b/src/soc2cUtil.ml @@ -1,12 +1,12 @@ -(* Time-stamp: <modified the 21/01/2015 (at 17:48) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/02/2015 (at 16:07) by Erwan Jahier> *) open Soc2cIdent open Data type var_kind = (* XXX poor names: fixme! *) - | ML_IO of Soc.key (* for idents that are part of a MemoryLess soc interface *) - | M_IO (* for idents that are part of a soc interface with Memories*) + | ML_IO of Soc.key (* For memoryless soc in Heap mode *) + | M_IO (* *) | Local (* for soc local variables *) let rec (type_to_string : Data.t -> string -> string) = @@ -34,6 +34,9 @@ let rec (type_to_string : Data.t -> string -> string) = in aux [] v n +let string_of_flow_decl (id, t) = + Printf.sprintf " %s;\n" (type_to_string t (id2s id)) + let rec (lic_type_to_c: Lic.type_ -> string -> string) = fun t n -> diff --git a/src/soc2cUtil.mli b/src/soc2cUtil.mli index 7cf0e1fc..0e9283f6 100644 --- a/src/soc2cUtil.mli +++ b/src/soc2cUtil.mli @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 09/10/2014 (at 15:37) by Erwan Jahier> *) +(* Time-stamp: <modified the 04/02/2015 (at 14:23) by Erwan Jahier> *) (** *) @@ -6,6 +6,8 @@ val type_to_string : Data.t -> string -> string val lic_type_to_c: Lic.type_ -> string -> string +val string_of_flow_decl : string * Data.t -> string + type var_kind = (* XXX poor names: fixme! *) | ML_IO of Soc.key (* for idents that are part of a MemoryLess soc interface *) | M_IO (* for idents that are part of a soc interface with Memories*) diff --git a/src/socPredef2cHeap.ml b/src/socPredef2cHeap.ml index 51499c16..0e379e6c 100644 --- a/src/socPredef2cHeap.ml +++ b/src/socPredef2cHeap.ml @@ -1,4 +1,5 @@ -(* Time-stamp: <modified the 14/01/2015 (at 14:55) by Erwan Jahier> *) + +(* Time-stamp: <modified the 06/02/2015 (at 16:09) by Erwan Jahier> *) open Data open Soc diff --git a/src/socPredef2cStack.ml b/src/socPredef2cStack.ml new file mode 100644 index 00000000..b352e047 --- /dev/null +++ b/src/socPredef2cStack.ml @@ -0,0 +1,300 @@ + +(* Time-stamp: <modified the 05/02/2015 (at 11:26) by Erwan Jahier> *) + +open Data +open Soc +open Soc2cIdent + +(* A boring but simple module... *) + +(* XXX should i use gen_assign here? for the time being, its useless as + there is no binop (nor unop) over arrays. +*) +let (lustre_binop : Soc.key -> string -> string) = + fun sk op -> + Printf.sprintf " *z = (x %s y);\n" op + +let (lustre_unop : Soc.key -> string -> string) = + fun sk op -> + (* use gen_assign? *) + Printf.sprintf" *z = %s x;\n" op + +let (lustre_ite : Soc.key -> string) = + fun sk -> + let t = match sk with (_,_::t::_,_) -> t | _ -> assert false in +(* Printf.sprintf" %s.z = (%s.c)? %s.xt : %s.xe;\n" ctx ctx ctx ctx *) + Soc2cHeap.gen_assign t (Printf.sprintf "*z") + (Printf.sprintf "(c)? xt : xe") + (Printf.sprintf "sizeof(*z)") + +let (lustre_impl : Soc.key -> string) = + fun sk -> + (* use gen_assign? *) + Printf.sprintf" *z = (!x || y);\n" + + +let (lustre_arrow : Soc.key -> string) = + fun sk -> + let x,y,z = "x", "y", "*z" in + let t = match sk with (_,_::t::_,_) -> t | _ -> assert false in + let vo = Printf.sprintf"((ctx->_memory)? %s : %s)" x y in + let size = Printf.sprintf "sizeof(%s)" x in + (Soc2cHeap.gen_assign t z vo size) ^ + (" ctx->_memory = _false;\n") + +let (lustre_hat : Soc.key -> string) = + fun (n,tl,si_opt) -> + let i,t = match tl with + | [_;Data.Array(t,i)] -> i,t + | _ -> assert false + in + let buff = ref "" in + for j=0 to i-1 do + buff := !buff^(Soc2cHeap.gen_assign t (Printf.sprintf "z[%d]" j) + (Printf.sprintf "x") (Printf.sprintf "sizeof(x)")); + done; + !buff + +let (lustre_array: Soc.key -> string) = + fun (n,tl,si_opt) -> + let t,i = match List.hd (List.rev tl) with + | Data.Array(t,i) -> t,i + | _ -> assert false + in + let buff = ref "" in + for j=0 to i-1 do + buff := !buff^(Soc2cHeap.gen_assign t (Printf.sprintf "z[%d]" j) + (Printf.sprintf "x%d" (j+1)) + (Printf.sprintf "sizeof(x%d)" (j+1))); + done; + !buff + +let (lustre_concat: Soc.key -> string) = + fun (n,tl,si_opt) -> + let t,s1,s2 = match tl with + | [Data.Array(t,s1); Data.Array(_,s2); _] -> t,s1,s2 + | _ -> assert false + in + let t1 = Printf.sprintf "x" + and t2 = Printf.sprintf "y" + and t12 = Printf.sprintf "z" in + (Printf.sprintf " memcpy(%s, &%s, sizeof(%s));\n" t12 t1 t1)^ + (Printf.sprintf " memcpy(%s[%d], &%s, sizeof(%s));\n" t12 s1 t2 t2) +(* Both seems to work *) +(* let buff = ref "" in *) +(* for j=0 to s1-1 do *) +(* buff := !buff^(Soc2cHeap.gen_assign t (Printf.sprintf "%s.z[%d]" ctx j) *) +(* (Printf.sprintf "%s.x[%d]" ctx j)); *) +(* done; *) +(* for j=s1 to s1+s2-1 do *) +(* buff := !buff^(Soc2cHeap.gen_assign t (Printf.sprintf "%s.z[%d]" ctx j) *) +(* (Printf.sprintf "%s.y[%d]" ctx (j-s1))); *) +(* done; *) +(* !buff *) + +let (lustre_slice: Soc.key -> string) = + fun (n,tl,si_opt) -> + let t,size = match List.hd (List.rev tl) with + | Data.Array(t,i) -> t,i + | _ -> assert false + in + match si_opt with + | Slic(b,e,step) -> + let buff = ref "" in + let j=ref 0 in + for i = b to e do + if (i-b) mod step = 0 then ( + buff := !buff^(Soc2cHeap.gen_assign t (Printf.sprintf "z[%d]" !j) + (Printf.sprintf "x[%d]" i) + (Printf.sprintf "sizeof(x[%d])" i) + ); + incr j); + done; + !buff + | _ -> assert false + + + +(* exported *) +let (get_predef_op: Soc.key -> string) = + fun sk -> + let (n,tl,si_opt) = sk in + match n with + | "Lustre::rplus" + | "Lustre::plus" + | "Lustre::iplus" -> lustre_binop sk "+" + | "Lustre::itimes" + | "Lustre::times" + | "Lustre::rtimes" -> lustre_binop sk "*" + | "Lustre::idiv" + | "Lustre::div" + | "Lustre::rdiv" -> lustre_binop sk "/" + | "Lustre::islash" + | "Lustre::slash" + | "Lustre::rslash" -> lustre_binop sk "/" + | "Lustre::iminus" + | "Lustre::minus" + | "Lustre::rminus" -> lustre_binop sk "-" + + | "Lustre::mod" -> lustre_binop sk "%" + | "Lustre::iuminus" + | "Lustre::uminus" + | "Lustre::ruminus"-> lustre_unop sk "-" + + | "Lustre::eq" -> lustre_binop sk "==" + + | "Lustre::and" -> lustre_binop sk "&&" + | "Lustre::neq" -> lustre_binop sk "!=" + | "Lustre::or" -> lustre_binop sk "||" + + | "Lustre::xor" -> lustre_binop sk "!=" + | "Lustre::not" -> lustre_unop sk "!" + | "Lustre::real2int" -> lustre_unop sk "(_integer)" + | "Lustre::int2real" -> lustre_unop sk "(_real)" + + | "Lustre::lt" + | "Lustre::rlt" + | "Lustre::ilt" -> lustre_binop sk "<" + | "Lustre::gt" + | "Lustre::rgt" + | "Lustre::igt" -> lustre_binop sk ">" + | "Lustre::lte" + | "Lustre::rlte" + | "Lustre::ilte" -> lustre_binop sk "<=" + | "Lustre::gte" + | "Lustre::rgte" + | "Lustre::igte" -> lustre_binop sk ">=" + | "Lustre::impl" -> lustre_impl sk + + | "Lustre::if" + | "Lustre::rif" + | "Lustre::iif" -> lustre_ite sk + + | "Lustre::current" -> assert false + | "Lustre::arrow" -> lustre_arrow sk + + | "Lustre::hat" -> lustre_hat sk + | "Lustre::array" -> lustre_array sk + | "Lustre::concat" -> lustre_concat sk + | "Lustre::array_slice" -> lustre_slice sk + + + | "Lustre::nor" -> assert false (* ougth to be translated into boolred *) + | "Lustre::diese" -> assert false (* ditto *) + + | _ -> assert false + + +let rec type_elt_of_array = function + | Data.Array(t,_) -> t + | Data.Alias(_,t) -> type_elt_of_array t + | _ -> assert false + + +(* exported *) +let (get_iterator : Soc.t -> string -> Soc.t -> int -> string) = + fun soc iterator it_soc n -> + let iter_inputs,iter_outputs = soc.profile in + let node_step = match soc.step with [step] -> step.name | _ -> assert false in + let step_args, ctx, array_index = + match soc.instances with + | [] -> ( + let (array_index : int -> var -> Soc.var_expr) = + fun i (vn,vt) -> Var(Printf.sprintf "%s[%d]" vn i, type_elt_of_array vt) + in + Array.make n "", + Array.make n (get_ctx_name it_soc.key), + array_index + ) + | _ -> + let inst_names = List.map fst soc.instances in + let inst_names = List.rev inst_names in + let step_args = List.map (fun sn -> ("&ctx->"^(id2s sn))) inst_names in + let ctx = List.map (fun sn -> ("ctx->"^(id2s sn))) inst_names in + let (array_index : int -> var -> Soc.var_expr) = + fun i (vn,vt) -> Var(Printf.sprintf "ctx->%s[%d]" vn i,vt) + in + Array.of_list step_args, + Array.of_list ctx, + array_index + in + let buff = ref "" in + for i=0 to n-1 do + let vel_in, vel_out = + match iterator with + | "map" -> + (List.map (array_index i) iter_inputs, + List.map (array_index i) iter_outputs) + | "fold" | "red" | "fill" | "fillred" -> + let name, telt = List.hd iter_inputs in + let a_in = name in + let a_in = Var(a_in, telt) in + ( a_in::(List.map (array_index i) (List.tl iter_inputs)), + a_in::(List.map (array_index i) (List.tl iter_outputs))) + | _ -> assert false (* should not occur *) + in + buff := !buff^( + Soc2cHeap.gen_step_call + soc it_soc vel_out vel_in ctx.(i) node_step step_args.(i)) + done; + + if iterator <> "map" then ( + let type_in = (snd (List.hd iter_inputs)) in + let a_in = (fst (List.hd iter_inputs)) in + let a_out = "*" ^ (fst (List.hd iter_outputs)) in + buff := !buff^(Soc2cHeap.gen_assign type_in a_out a_in + (Printf.sprintf "sizeof(%s)" a_in)) (* a_out=a_n *) + ); + !buff + + +(* exported *) +let (get_condact : Soc.t -> Soc.t -> var_expr list -> string ) = + fun soc condact_soc el -> + let buff = ref "" in + let add str = buff:=!buff^(str^"\n") in + + let clk = Printf.sprintf "i0" in + let vel_in,vel_out = soc.profile in + let vel_in = List.tl vel_in in + let vel_in = List.map (fun var -> Var var) vel_in in + let vel_out = List.map (fun var -> Var var) vel_out in + add (Printf.sprintf " if (%s == _true) { " clk); + (if SocUtils.is_memory_less condact_soc then + let condact_ctx = get_ctx_name condact_soc.key in + add (Soc2cStack.gen_step_call soc condact_soc vel_out vel_in condact_ctx "step" "") + else + let condact_ctx = + let inst_name = + match soc.instances with + | [inst] -> (id2s (fst inst)) + | _ -> assert false + in + Printf.sprintf "ctx->%s" inst_name + in + add (Soc2cStack.gen_step_call soc condact_soc vel_out vel_in + condact_ctx "step" ("&"^condact_ctx)) + ); + add " ctx->_memory = _false;"; + add " } else if (ctx->_memory == _true) {"; + List.iter2 (fun var ve -> + add (Printf.sprintf " %s = %s;" (Soc2cHeap.string_of_var_expr soc var) + (Soc2cHeap.string_of_var_expr soc ve) ) + ) vel_out el ; + add " ctx->_memory = _false;"; + add " }"; + !buff + + +(* exported *) +let (get_boolred : Soc.t -> int -> int -> int -> string )= + fun soc i j k -> + let ctx = get_ctx_name soc.key in + let buff = ref "" in + let add str = buff:=!buff^(str^"\n") in + add " int cpt,i;"; + add " cpt=0;"; + add (Printf.sprintf + " for (i = 0 ; i < %d ; i += 1) if (%s.i0[i] == _true) cpt++;" k ctx); + add (Printf.sprintf " %s.o0 = (%d <= cpt && cpt <= %d) ? _true : _false;" ctx i j ); + !buff diff --git a/src/socPredef2cStack.mli b/src/socPredef2cStack.mli new file mode 100644 index 00000000..fb1706b6 --- /dev/null +++ b/src/socPredef2cStack.mli @@ -0,0 +1,15 @@ +(* Time-stamp: <modified the 04/02/2015 (at 14:38) by Erwan Jahier> *) + + +(** Returns the C code corresponding a soc key *) +val get_predef_op: Soc.key -> string + +(** Returns the C code implementing an iterator (map, fill, red) *) +val get_iterator : Soc.t -> string -> Soc.t -> int -> string + + +(** Returns the C code implementing a condact *) +val get_condact : Soc.t -> Soc.t -> Soc.var_expr list -> string + +(** Returns the C code implementing a boolred *) +val get_boolred : Soc.t -> int -> int -> int -> string diff --git a/src/socUtils.ml b/src/socUtils.ml index 2424303e..a0d166de 100644 --- a/src/socUtils.ml +++ b/src/socUtils.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 14/08/2014 (at 16:30) by Erwan Jahier> *) +(** Time-stamp: <modified the 06/02/2015 (at 15:59) by Erwan Jahier> *) open Soc @@ -353,3 +353,29 @@ let (my_string_of_float_precision : int option -> float -> string) = let (is_memory_less : Soc.t -> bool) = fun soc -> soc.memory = No_mem && soc.instances = [] + +(* exported *) +let (ctx_is_global : Soc.t -> bool) = + fun soc -> + match Lv6MainArgs.global_opt.Lv6MainArgs.io_transmit_mode with + | Lv6MainArgs.Heap -> is_memory_less soc + | Lv6MainArgs.Stack | Lv6MainArgs.HeapStack -> false + + + +let (filter_step_params : int list -> 'a list -> 'a list) = + fun il vl -> (* we suppose that the index list is in increasing order *) + let rec aux il vl idx acc = + match il,vl with + | [],_ -> acc + | _::_, [] -> assert false + | i::til,v::tvl -> + if i = idx then aux til tvl (idx+1) (v::acc) + else if i > idx then aux il tvl (idx+1) acc + else assert false + in + List.rev (aux il vl 0 []) + + +let _ = ( + assert (filter_step_params [0;1;4] ["v1";"v2";"v3";"v4";"v5"] = ["v1";"v2";"v5"])) diff --git a/src/socUtils.mli b/src/socUtils.mli index 89008942..243fb70a 100644 --- a/src/socUtils.mli +++ b/src/socUtils.mli @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 20/06/2014 (at 10:32) by Erwan Jahier> *) +(** Time-stamp: <modified the 06/02/2015 (at 16:00) by Erwan Jahier> *) (** Donne toute les méthodes d'un composant. *) @@ -50,3 +50,19 @@ val gen_index_list : int -> int list val my_string_of_float_precision : int option -> float -> string val is_memory_less : Soc.t -> bool + +(** should we omit the ctx in arg of the step function? + yes in Heap mode when the soc is memory less. + *) +val ctx_is_global : Soc.t -> bool + +(** [filter_step_params index_list var_list] + +only keeps the var present in the index list. + +For instance, +filter_step_params [0;1;4] [v1;v2;v3;v4;v5] = [v1;v2;v5] + +nb : we suppose that the index list is in increasing order. +*) +val filter_step_params : int list -> 'a list -> 'a list diff --git a/test/Makefile b/test/Makefile index 9a386577..7ce7db11 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,11 +1,11 @@ # to run the test, one needs to (apt-get) install: # dejagnu tcl tcllib -all: clean qtest reftest lus2lic.time -test: clean qtest +all: clean ltop qtest rest +test: clean ltop qtest rest: reftest lus2lic.time -TEST_MACHINE=ssh granier +TEST_MACHINE=ssh ovaz #TEST_MACHINE=eval # This fixes sporadic memory errors I get when running tests OCAMLRUNPARAM=s=1M,i=32M,o=150 @@ -68,7 +68,7 @@ reftest: time -o lus2lic.ref_time make $(LOG) make lus2lic.time -qtest:ltop +qtest: rm -f $(LOG) $(TEST_MACHINE) "cd $(testdir); make tmpdirs" time -o lus2lic.quick_time make -j 8 $(LOG) diff --git a/test/lus2lic.sum b/test/lus2lic.sum index 7b5d6072..c6548949 100644 --- a/test/lus2lic.sum +++ b/test/lus2lic.sum @@ -1,5 +1,5 @@ ==> lus2lic0.sum <== -Test Run By jahier on Tue Jan 27 10:37:57 +Test Run By jahier on Mon Feb 9 15:44:03 Native configuration is x86_64-unknown-linux-gnu === lus2lic0 tests === @@ -63,7 +63,7 @@ XFAIL: Test bad programs (assert): test_lus2lic_no_node should_fail/assert/lecte XFAIL: Test bad programs (assert): test_lus2lic_no_node should_fail/assert/s.lus ==> lus2lic1.sum <== -Test Run By jahier on Tue Jan 27 10:38:01 +Test Run By jahier on Mon Feb 9 15:44:08 Native configuration is x86_64-unknown-linux-gnu === lus2lic1 tests === @@ -397,7 +397,7 @@ PASS: gcc -o multipar.exec multipar_multipar.c multipar_multipar_loop.c PASS: /home/jahier/lus2lic/test/../utils/compare_exec_and_2c multipar.lus {} ==> lus2lic2.sum <== -Test Run By jahier on Tue Jan 27 10:38:37 +Test Run By jahier on Mon Feb 9 15:44:45 Native configuration is x86_64-unknown-linux-gnu === lus2lic2 tests === @@ -727,7 +727,7 @@ PASS: gcc -o zzz2.exec zzz2_zzz2.c zzz2_zzz2_loop.c PASS: /home/jahier/lus2lic/test/../utils/compare_exec_and_2c zzz2.lus {} ==> lus2lic3.sum <== -Test Run By jahier on Tue Jan 27 10:39:48 +Test Run By jahier on Mon Feb 9 15:45:48 Native configuration is x86_64-unknown-linux-gnu === lus2lic3 tests === @@ -1230,7 +1230,7 @@ PASS: ./myec2c {-o multipar.c multipar.ec} PASS: /home/jahier/lus2lic/test/../utils/test_lus2lic_no_node multipar.lus {} ==> lus2lic4.sum <== -Test Run By jahier on Tue Jan 27 10:40:27 +Test Run By jahier on Mon Feb 9 15:46:24 Native configuration is x86_64-unknown-linux-gnu === lus2lic4 tests === @@ -1727,13 +1727,13 @@ PASS: /home/jahier/lus2lic/test/../utils/test_lus2lic_no_node zzz2.lus {} =============================== # Total number of failures: 14 lus2lic0.log:testcase ./lus2lic.tests/test0.exp completed in 4 seconds -lus2lic1.log:testcase ./lus2lic.tests/test1.exp completed in 35 seconds -lus2lic2.log:testcase ./lus2lic.tests/test2.exp completed in 71 seconds -lus2lic3.log:testcase ./lus2lic.tests/test3.exp completed in 39 seconds -lus2lic4.log:testcase ./lus2lic.tests/test4.exp completed in 71 seconds +lus2lic1.log:testcase ./lus2lic.tests/test1.exp completed in 36 seconds +lus2lic2.log:testcase ./lus2lic.tests/test2.exp completed in 62 seconds +lus2lic3.log:testcase ./lus2lic.tests/test3.exp completed in 36 seconds +lus2lic4.log:testcase ./lus2lic.tests/test4.exp completed in 75 seconds * Ref time: -0.05user 0.09system 3:41.58elapsed 0%CPU (0avgtext+0avgdata 3016maxresident)k -0inputs+0outputs (0major+14901minor)pagefaults 0swaps +0.04user 0.05system 3:36.73elapsed 0%CPU (0avgtext+0avgdata 5080maxresident)k +160inputs+0outputs (0major+5488minor)pagefaults 0swaps * Quick time (-j 4): -0.05user 0.05system 1:20.56elapsed 0%CPU (0avgtext+0avgdata 3016maxresident)k -0inputs+0outputs (0major+14920minor)pagefaults 0swaps +0.04user 0.02system 1:26.50elapsed 0%CPU (0avgtext+0avgdata 5072maxresident)k +160inputs+0outputs (0major+5567minor)pagefaults 0swaps diff --git a/test/lus2lic.time b/test/lus2lic.time index 60639462..df8db41a 100644 --- a/test/lus2lic.time +++ b/test/lus2lic.time @@ -1,11 +1,11 @@ lus2lic0.log:testcase ./lus2lic.tests/test0.exp completed in 4 seconds -lus2lic1.log:testcase ./lus2lic.tests/test1.exp completed in 35 seconds -lus2lic2.log:testcase ./lus2lic.tests/test2.exp completed in 71 seconds -lus2lic3.log:testcase ./lus2lic.tests/test3.exp completed in 39 seconds -lus2lic4.log:testcase ./lus2lic.tests/test4.exp completed in 71 seconds +lus2lic1.log:testcase ./lus2lic.tests/test1.exp completed in 36 seconds +lus2lic2.log:testcase ./lus2lic.tests/test2.exp completed in 62 seconds +lus2lic3.log:testcase ./lus2lic.tests/test3.exp completed in 36 seconds +lus2lic4.log:testcase ./lus2lic.tests/test4.exp completed in 75 seconds * Ref time: -0.05user 0.09system 3:41.58elapsed 0%CPU (0avgtext+0avgdata 3016maxresident)k -0inputs+0outputs (0major+14901minor)pagefaults 0swaps +0.04user 0.05system 3:36.73elapsed 0%CPU (0avgtext+0avgdata 5080maxresident)k +160inputs+0outputs (0major+5488minor)pagefaults 0swaps * Quick time (-j 4): -0.05user 0.05system 1:20.56elapsed 0%CPU (0avgtext+0avgdata 3016maxresident)k -0inputs+0outputs (0major+14920minor)pagefaults 0swaps +0.04user 0.02system 1:26.50elapsed 0%CPU (0avgtext+0avgdata 5072maxresident)k +160inputs+0outputs (0major+5567minor)pagefaults 0swaps diff --git a/test/should_work/ex.lus b/test/should_work/ex.lus index 6b289811..448c40e9 100644 --- a/test/should_work/ex.lus +++ b/test/should_work/ex.lus @@ -4,12 +4,12 @@ let o = true -> pre(i) and trueNode(i); tel -node trueNode(x : bool) returns (y : bool); +function trueNode(x : bool) returns (y : bool); let y = x or id(true,false); tel -node id(f,a:bool) returns (g:bool); +function id(f,a:bool) returns (g:bool); let g = f or a; tel -- GitLab