Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
simul.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
(**********************************************************************) (* *) (* This file is part of the FSML library *) (* github.com/jserot/fsml *) (* *) (* Copyright (c) 2020-present, Jocelyn SEROT. All rights reserved. *) (* *) (* This source code is licensed under the license found in the *) (* LICENSE file in the root directory of this source tree. *) (* *) (**********************************************************************) open Fsm type ctx = { state: State.t; env: Expr.env } [@@deriving show] let check_fsm m = Typing.type_check_fsm m let check_stimuli m st = Typing.type_check_stimuli m st let output_state_events m state = assert (List.mem_assoc state m.states); List.assoc state m.states |> List.map (fun (o,e) -> Action.Assign (o,e)) let step ctx m = match List.find_opt (Transition.is_fireable ctx.state (Builtins.eval_env @ ctx.env)) m.trans with | Some (src, _, acts, dst) -> let acts' = acts @ output_state_events m dst in let evs = List.concat @@ List.map (Action.perform (Builtins.eval_env @ ctx.env)) acts' in (if src <> dst then ("state",Expr.Enum dst)::evs else evs), { state = dst; env = List.fold_left Expr.update_env ctx.env evs } | None -> [], ctx let run ?ctx ?(stop_when=[]) ?(stop_after=0) ?(trace=false) ~stim m = let open Clock in let m = check_fsm m in let stim = check_stimuli m stim in let stop_conds = let open Expr in if stop_after > 0 then [mk_bool_expr (EBinop(">=", (mk_int_expr (EVar "clk")), (mk_int_expr (EInt stop_after))))] else List.map (Typing.type_check_fsm_guard ~with_clk:true m) stop_when in let eval_stop_conds clk ctx = let env' = Builtins.eval_env @ ctx.env @ ["clk", Expr.Int clk] in List.for_all (Guard.eval env') stop_conds in let trace_log = ref ([] : ctx clocked list) in let rec eval (clk, ctx, evs) stim = if eval_stop_conds clk ctx then List.rev evs, List.rev !trace_log (* Done ! *) else match stim with | (t,evs')::rest when t=clk -> let ctx' = { ctx with env = List.fold_left Expr.update_env ctx.env evs' } in let evs'', ctx'' = step ctx' m in if trace then trace_log := (t,ctx'')::!trace_log; let evs''' = begin match evs with | (t',es)::rest when t'=t -> (t',es@evs'')::rest | _ -> (t,evs'')::evs end in eval (clk+1, ctx'', evs''') rest | _ -> (* No applicable stimuli *) let evs', ctx' = step ctx m in if trace then trace_log := (clk,ctx')::!trace_log; eval (clk+1, ctx', (clk, evs')::evs) [] in let ctx, evs = match ctx, m.Fsm.itrans with | Some c, _ -> c, [] | None, (s0,acts0) -> let env0 = List.map (fun (id,_) -> id, Expr.Unknown) (m.inps @ m.outps @ m.vars) in let acts0' = acts0 @ output_state_events m s0 in let evs0 = List.concat @@ List.map (Action.perform (Builtins.eval_env @ env0)) acts0' in { state = s0; env = List.fold_left Expr.update_env env0 evs0 }, [0, ("state",Expr.Enum s0)::evs0] in if trace then trace_log := [0,ctx]; eval (0, ctx, evs) stim