Project

General

Profile

« Previous | Next » 

Revision 524060b3

Added by Pierre-Loïc Garoche over 4 years ago

Ongoin work on EMF backend. Commit to store a working version. More work to do on clocks and resets

View differences:

src/backends/EMF/EMF_backend.ml
139 139
(*   Printing machine code as EMF             *)
140 140
(**********************************************)
141 141

  
142
(* detect whether the instruction i represents an ARROW, ie an arrow with true
143
   -> false *)
144
let is_arrow_fun m i =
145
  match Corelang.get_instr_desc i with
146
  | MStep ([var], i, vl)  -> (
147
    let name = try (Machine_code.get_node_def i m).node_id with Not_found -> Format.eprintf "Impossible to find node %s@.@?" i; raise Not_found in
148
    match name, vl with
149
    | "_arrow", [v1; v2] -> (
150
	match v1.value_desc, v2.value_desc with
151
	| Cst c1, Cst c2 ->
152
	   if c1 = Corelang.const_of_bool true && c2 = Corelang.const_of_bool false then
153
	     true
154
	   else
155
	     assert false (* only handle true -> false *)
156
	| _ -> assert false
157
    )
158
    | _ -> false
159
  )
160
  | _ -> false
161

  
162
let pp_original_lustre_expression m fmt i =
163
  match Corelang.get_instr_desc i with
164
  | MLocalAssign _ | MStateAssign _ 
165
  | MBranch _
166
    -> ( match i.lustre_eq with None -> () | Some e -> Printers.pp_node_eq fmt e) 
167
  | MStep _ when is_arrow_fun m i -> () (* we print nothing, this is a STEP *)
168
  | MStep _ -> (match i.lustre_eq with None -> () | Some eq -> Printers.pp_node_eq fmt eq)
169
  | _ -> ()
170

  
171

  
142 172
(* Print machine code values as matlab expressions. Variable identifiers are
143 173
   replaced by uX where X is the index of the variables in the list vars of input
144 174
   variables. *)
145
let rec pp_val vars fmt v =
175
let rec pp_matlab_val vars fmt v =
146 176
  match v.value_desc with
147 177
  | Cst c -> Printers.pp_const fmt c
148 178
  | LocalVar v
......
151 181
     if List.mem id vars then
152 182
       Format.fprintf fmt "u%i" (get_idx id vars)
153 183
     else
154
       assert false (* impossible to find element id in var list *)
184
       let _ = Format.eprintf "Error: looking for var %s in %a@.@?" id (Utils.fprintf_list ~sep:"," Format.pp_print_string) vars in assert false (* impossible to find element id in var list *)
155 185
  | Fun (n, vl) -> pp_fun vars n fmt vl
156 186
  | _ -> assert false (* not available in EMF backend *)
157 187
and pp_fun vars id fmt vl =
158 188
  (* eprintf "print %s with %i args@.@?" id (List.length vl);*)
159 189
  match id, vl with
160
    | "+", [v1;v2] -> fprintf fmt "(%a + %a)" (pp_val vars) v1 (pp_val vars) v2
161
    | "uminus", [v] -> fprintf fmt "(- %a)" (pp_val vars) v
162
    | "-", [v1;v2] -> fprintf fmt "(%a - %a)" (pp_val vars) v1 (pp_val vars) v2
163
    | "*",[v1;v2] -> fprintf fmt "(%a * %a)" (pp_val vars) v1 (pp_val vars) v2
164
    | "/", [v1;v2] -> fprintf fmt "(%a / %a)" (pp_val vars) v1 (pp_val vars) v2
165
    | "mod", [v1;v2] -> fprintf fmt "mod (%a, %a)" (pp_val vars) v1 (pp_val vars) v2
166
    | "&&", [v1;v2] -> fprintf fmt "(%a & %a)" (pp_val vars) v1 (pp_val vars) v2
167
    | "||", [v1; v2] -> fprintf fmt "(%a | %a)" (pp_val vars) v1 (pp_val vars) v2
168
    | "xor", [v1; v2] -> fprintf fmt "xor (%a, %a)" (pp_val vars) v1 (pp_val vars) v2
169
    | "impl", [v1; v2] -> fprintf fmt "((~%a) | %a)" (pp_val vars) v1 (pp_val vars) v2
170
    | "<", [v1; v2] -> fprintf fmt "(%a < %a)" (pp_val vars) v1 (pp_val vars) v2
171
    | "<=", [v1; v2] -> fprintf fmt "(%a <= %a)" (pp_val vars) v1 (pp_val vars) v2
172
    | ">", [v1; v2] -> fprintf fmt "(%a > %a)" (pp_val vars) v1 (pp_val vars) v2
173
    | ">=", [v1; v2] -> fprintf fmt "(%a >= %a)" (pp_val vars) v1 (pp_val vars) v2
174
    | "!=", [v1; v2] -> fprintf fmt "(%a != %a)" (pp_val vars) v1 (pp_val vars) v2
175
    | "=", [v1; v2] -> fprintf fmt "(%a = %a)" (pp_val vars) v1 (pp_val vars) v2
176
    | "not", [v] -> fprintf fmt "(~%a)" (pp_val vars) v
177
    | _ -> fprintf fmt "%s (%a)" id  (Utils.fprintf_list ~sep:", " (pp_val vars)) vl 
190
    | "+", [v1;v2] -> fprintf fmt "(%a + %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
191
    | "uminus", [v] -> fprintf fmt "(- %a)" (pp_matlab_val vars) v
192
    | "-", [v1;v2] -> fprintf fmt "(%a - %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
193
    | "*",[v1;v2] -> fprintf fmt "(%a * %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
194
    | "/", [v1;v2] -> fprintf fmt "(%a / %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
195
    | "mod", [v1;v2] -> fprintf fmt "mod (%a, %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
196
    | "&&", [v1;v2] -> fprintf fmt "(%a & %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
197
    | "||", [v1; v2] -> fprintf fmt "(%a | %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
198
    | "xor", [v1; v2] -> fprintf fmt "xor (%a, %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
199
    | "impl", [v1; v2] -> fprintf fmt "((~%a) | %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
200
    | "<", [v1; v2] -> fprintf fmt "(%a < %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
201
    | "<=", [v1; v2] -> fprintf fmt "(%a <= %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
202
    | ">", [v1; v2] -> fprintf fmt "(%a > %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
203
    | ">=", [v1; v2] -> fprintf fmt "(%a >= %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
204
    | "!=", [v1; v2] -> fprintf fmt "(%a != %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
205
    | "=", [v1; v2] -> fprintf fmt "(%a = %a)" (pp_matlab_val vars) v1 (pp_matlab_val vars) v2
206
    | "not", [v] -> fprintf fmt "(~%a)" (pp_matlab_val vars) v
207
    | _ -> fprintf fmt "%s (%a)" id  (Utils.fprintf_list ~sep:", " (pp_matlab_val vars)) vl 
178 208

  
179 209
     
180
(* detect whether the instruction i represents an ARROW, ie an arrow with true -> false *)
181
let is_arrow_fun m i =
182
  match Corelang.get_instr_desc i with
183
  | MStep ([var], i, vl)  -> (
184
    let name = try (Machine_code.get_node_def i m).node_id with Not_found -> Format.eprintf "Impossible to find node %s@.@?" i; raise Not_found in
185
    match name, vl with
186
    | "_arrow", [v1; v2] -> (
187
	match v1.value_desc, v2.value_desc with
188
	| Cst c1, Cst c2 ->
189
	   if c1 = Corelang.const_of_bool true && c2 = Corelang.const_of_bool false then
190
	     true
191
	   else
192
	     assert false (* only handle true -> false *)
193
	| _ -> assert false
194
    )
195
    | _ -> false
196
  )
197
  | _ -> false
198 210

  
199 211
(* pp_basic_instr prints regular instruction. These do not contain MStep which
200 212
   should have been already filtered out. Another restriction which is supposed
201 213
   to be enforced is that branching statement contain a single instruction (in
202 214
   practice it has to be an assign) *)
203
let rec pp_basic_instr m vars fmt i =
215
let pp_matlab_basic_instr m vars fmt i =
204 216
  match Corelang.get_instr_desc i with
205 217
  | MLocalAssign (var,v) 
206
  | MStateAssign (var,v) -> fprintf fmt "y = %a" (pp_val vars) v
207
  | MBranch (g,[(tag1,[case1]);(tag2,[case2])])     ->
208
     (* Thanks to normalization with join_guards = false, branches shall contain
209
	a single expression *)
210
     let then_case, else_case =
211
       if tag1 = Corelang.tag_true then
212
	 case1, case2
213
       else
214
	 case2, case1
215
     in
216
     fprintf fmt "if %a; %a; else %a; end"
217
       (pp_val vars) g
218
       (pp_basic_instr m vars) then_case
219
       (pp_basic_instr m vars) else_case
220
  | MBranch _ (* EMF backend only accept true/false ite *)
221
    -> Format.eprintf "unhandled branch in EMF@.@?"; assert false
218
  | MStateAssign (var,v) -> fprintf fmt "y = %a" (pp_matlab_val vars) v
222 219
  | MReset _           
223 220
    -> Format.eprintf "unhandled reset in EMF@.@?"; assert false
224 221
  | MNoReset _
225 222
    -> Format.eprintf "unhandled noreset in EMF@.@?"; assert false
223
  | MBranch _ (* branching instructions already handled *)
224
    -> Format.eprintf "unhandled branch statement in EMF (should have been filtered out before)@.@?";
225
      assert false
226 226
  | MStep _ (* function calls already handled, including STEP *)
227 227
    -> Format.eprintf "unhandled function call in EMF (should have been filtered out before)@.@?";
228 228
      assert false
......
232 232

  
233 233

  
234 234

  
235
let rec get_instr_var i =
235
let rec get_instr_lhs_var i =
236 236
  match Corelang.get_instr_desc i with
237 237
  | MLocalAssign (var,_) 
238 238
  | MStateAssign (var,_) 
239
  | MStep ([var], _, _)  -> var 
240
  | MBranch (_,[(tag1,case1);(tag2,case2)])     ->
241
     get_instrs_var case1 (* assuming case1 and case2 define the same variable *)
242
  | MStep _ (* only single output for function call *)
243
  | MBranch _ (* EMF backend only accept true/false ite *)
239
  | MStep ([var], _, _)  ->
240
     (* The only MStep instructions that filtered here
241
	should be arrows, ie. single var *)
242
     var
243
  | MBranch (_,(_,case1)::_)     ->
244
     get_instrs_var case1 (* assuming all cases define the same variables *)
245
  | MStep (f,name,a) -> Format.eprintf "step %s@.@?" name; assert false (* no other MStep here *)
246
  | MBranch _ -> assert false (* branch instruction should admit at least one case *)
244 247
  | MReset _           
245 248
  | MNoReset _
246 249
  | MComment _ -> assert false (* not  available for EMF output *)
247 250
and get_instrs_var il =
248 251
  match il with
249
  | i::_ -> get_instr_var i (* looking for the first instr *)
252
  | i::_ -> get_instr_lhs_var i (* looking for the first instr *)
250 253
  | _ -> assert false
251 254

  
252 255
  
......
258 261
  | Fun (n, vl) -> List.fold_left (fun res v -> Utils.ISet.union (get_val_vars v) res) Utils.ISet.empty vl
259 262
  | _ -> assert false (* not available in EMF backend *)
260 263

  
261
let rec get_instr_vars i =
264
let rec get_instr_rhs_vars i =
262 265
  match Corelang.get_instr_desc i with
263 266
  | MLocalAssign (_,v)  
264 267
  | MStateAssign (_,v) -> get_val_vars v
......
268 271
       (get_val_vars c)
269 272
       (
270 273
	 Utils.ISet.union
271
	   (get_instr_vars case1)
272
	   (get_instr_vars case2)
274
	   (get_instr_rhs_vars case1)
275
	   (get_instr_rhs_vars case2)
273 276
       )
274
  | MBranch _ (* EMF backend only accept true/false ite *)
275
  | MReset _           
276
  | MNoReset _
277
  | MComment _ -> failwith "Error in compiling some constructs into EMF. Have you considered -node foo -inline options ?" (* not  available for EMF output *)
278
(* and get_instrs_vars il = *)
279
(*   List.fold_left (fun res i -> Utils.ISet.union res (get_instr_vars i)) *)
280
(*     Utils.ISet.empty *)
281
(*     il *)
277
  | MBranch (g, branches) ->
278
     List.fold_left
279
       (fun accu (_, il) -> Utils.ISet.union accu (get_instrs_vars il))
280
       (get_val_vars g)
281
       branches
282
  | MReset id           
283
  | MNoReset id -> Utils.ISet.singleton id
284
  | MComment _ -> Utils.ISet.empty
285
and get_instrs_vars il =
286
  List.fold_left (fun res i -> Utils.ISet.union res (get_instr_rhs_vars i))
287
    Utils.ISet.empty
288
    il
282 289

  
283 290

  
284
let pp_original_lustre_expression m fmt i =
285
  match Corelang.get_instr_desc i with
286
  | MLocalAssign _ | MStateAssign _ 
287
  | MBranch _
288
    -> ( match i.lustre_eq with None -> () | Some e -> Printers.pp_node_eq fmt e) 
289
  | MStep _ when is_arrow_fun m i -> () (* we print nothing, this is a STEP *)
290
  | MStep _ -> (match i.lustre_eq with None -> () | Some eq -> Printers.pp_node_eq fmt eq)
291
  | _ -> ()
292
    
293
let pp_emf_instrs m fmt i =
291
     
292
let rec pp_emf_instr m fmt i =
294 293
  (* Either it is a Step function non arrow, then we have a dedicated treatment,
295 294
     or it has to be a single variable assigment *)
296
  let arguments_vars = Utils.ISet.elements (get_instr_vars i) in	
295
  let arguments_vars = Utils.ISet.elements (get_instr_rhs_vars i) in	
297 296
  
298 297
  match Corelang.get_instr_desc i with
299
    (* Regular node call either a statuful node or a functional one *)
300
    MStep (outputs, f, inputs) when not (is_arrow_fun m i) -> (
301
      fprintf fmt "\"__functioncall\": @[<v 2>{ \"node\": \"%s\",@ \"inputs\": [%a],@ \"vars\": [%a]@ \"outputs\": [%a],@ \"original_lustre_expr\": [%a]@]}"
302
	((Machine_code.get_node_def f m).node_id) (* Node name *)
303
        (Utils.fprintf_list ~sep:", " (fun fmt _val -> fprintf fmt "\"%a\"" (pp_val arguments_vars) _val)) inputs                  (* inputs *)
304
	(fprintf_list ~sep:", " pp_var_string) arguments_vars
305
	(fprintf_list ~sep:", " (fun fmt v -> pp_var_string fmt v.var_id)) outputs  (* outputs *)
306
	(pp_original_lustre_expression m) i         (* original lustre expr *)
307
    )
308
  | _ ->
309
     (* Other expressions, including "pre" *)
310
     ( 
311
    (* first, we extract the expression and associated variables *)
312
    let var = get_instr_var i in
313
    fprintf fmt "\"%s\": @[<v 2>{ \"expr\": \"%a\",@ \"vars\": [%a] @ \"original_lustre_expr\": [%a]@]}"
298
  (* Regular node call either a statuful node or a functional one *)
299
  | MStep (outputs, f, inputs) when not (is_arrow_fun m i) -> (
300
    fprintf fmt "\"CALL\": @[<v 2>{ \"node\": \"%s\",@ \"inputs\": [%a],@ \"vars\": [%a]@ \"lhs\": [%a],@ \"original_lustre_expr\": [%a]@]}"
301
      ((Machine_code.get_node_def f m).node_id) (* Node name *)
302
      (Utils.fprintf_list ~sep:", " (fun fmt _val -> fprintf fmt "\"%a\"" (pp_matlab_val arguments_vars) _val)) inputs                  (* inputs *)
303
      (fprintf_list ~sep:", " pp_var_string) arguments_vars
304
      (fprintf_list ~sep:", " (fun fmt v -> pp_var_string fmt v.var_id)) outputs  (* outputs *)
305
      (pp_original_lustre_expression m) i         (* original lustre expr *)
306
  )
307
  | MStep _ -> (* Arrow case *) (
308
    let var = get_instr_lhs_var i in
309
    fprintf fmt "\"STEP\": @[<v 2>{ \"lhs\": \"%s\",@ \"vars\": [%a] @ \"original_lustre_expr\": [%a]@]}"
314 310
      var.var_id
315
      (fun fmt i -> match Corelang.get_instr_desc i with
316
      | MStep _ -> fprintf fmt "STEP"
317
      | _ -> pp_basic_instr m arguments_vars fmt i) i
318 311
      (fprintf_list ~sep:", " pp_var_string) arguments_vars
319 312
      (pp_original_lustre_expression m) i
320 313
  )
314
  | MBranch (g,[(tag1,[case1]);(tag2,[case2])]) when tag1 = Corelang.tag_true || tag2 = Corelang.tag_true  ->
315
     (* Thanks to normalization with join_guards = false, branches shall contain
316
	a single expression *)
317
     let var = get_instr_lhs_var i in
318
     let then_case, else_case =
319
       if tag1 = Corelang.tag_true then
320
	 case1, case2
321
       else
322
	 case2, case1
323
     in
324
     fprintf fmt "\"ITE\": @[<v 2>{ \"lhs\": \"%s\",@ \"guard\": \"%a\",@ \"then_expr\": \"%a\",@ \"else_expr\": \"%a\",@ \"vars\": [%a],@ \"original_lustre_expr\": [%a]@]}"
325
       var.var_id
326
       (pp_matlab_val arguments_vars) g
327
       (pp_matlab_basic_instr m arguments_vars) then_case
328
       (pp_matlab_basic_instr m arguments_vars) else_case
329
       (fprintf_list ~sep:", " pp_var_string) arguments_vars
330
       (pp_original_lustre_expression m) i
331

  
332
  | MBranch (g, [single_tag, single_branch]) ->
333
     (* First case: it corresponds to a clocked expression: a MBranch with a
334
	single case. It shall become a subsystem with an enable port that depends on g = single_tag *)
335
     (* Thanks to normalization with join_guards = false, branches shall contain
336
	a single expression TODO REMOVE COMMENT THIS IS NOT TRUE *)
337
     let var = get_instr_lhs_var i in
338
     fprintf fmt "\"ENABLEDSUB\": @[<v 2>{ \"lhs\": \"%s\",@ \"enable_cond\": \"%a = %s\",@ \"subsystem\": {%a },@ \"vars\": [%a],@ \"original_lustre_expr\": [%a]@]}"
339
       var.var_id
340
       (pp_matlab_val arguments_vars) g
341
       single_tag
342
       (fprintf_list ~sep:",@ " (pp_emf_instr m)) single_branch
343
       (fprintf_list ~sep:", " pp_var_string) arguments_vars
344
       (pp_original_lustre_expression m) i
345
       
346
  | MBranch (g, hl) ->
347
     (* Thanks to normalization with join_guards = false, branches shall contain
348
	a single expression *)
349
     fprintf fmt "\"BRANCH\": @[<v 2>{ \"guard\": \"%a\",@ \"branches\": [@[<v 0>%a@]],@ \"vars\": [%a],@ \"original_lustre_expr\": [%a]@]}"
350
       (pp_matlab_val arguments_vars) g
351
       (fprintf_list ~sep:",@ "
352
	  (fun fmt (tag, (is_tag: instr_t list)) ->
353
	    fprintf fmt "\"%s\": [%a]"
354
	      tag
355
	      (fprintf_list ~sep:",@ " (fun fmt i_tag -> match Corelang.get_instr_desc i_tag with
356
		  | MLocalAssign (var,v) 
357
		  | MStateAssign (var,v) ->
358
		     fprintf fmt "{lhs= \"%s\", rhs= \"%a\"]" var.var_id (pp_matlab_val arguments_vars) v
359
		  | _ -> Format.eprintf "unhandled instr: %a@." Machine_code.pp_instr i_tag; assert false
360
	      )) is_tag
361
	  )) hl 
362
       (fprintf_list ~sep:", " pp_var_string) arguments_vars
363
       (pp_original_lustre_expression m) i
364
       
365
       
366
       
367
  | _ ->
368
     (* Other expressions, including "pre" *)
369
     ( 
370
       (* first, we extract the expression and associated variables *)
371
       let var = get_instr_lhs_var i in
372
       fprintf fmt "\"EXPR\": @[<v 2>{ \"lhs\": \"%s\",@ \"expr\": \"%a\",@ \"vars\": [%a] @ \"original_lustre_expr\": [%a]@]}"
373
	 var.var_id
374
	 (fun fmt i -> match Corelang.get_instr_desc i with
375
	 | MStep _ -> fprintf fmt "STEP"
376
	 | _ -> pp_matlab_basic_instr m arguments_vars fmt i) i
377
	 (fprintf_list ~sep:", " pp_var_string) arguments_vars
378
	 (pp_original_lustre_expression m) i
379
     )
321 380
    
322
     
381
(* A (normalized) node becomes a JSON struct
382
   node foo (in1, in2: int) returns (out1, out2: int);
383
   var x : int;
384
   let
385
     x = bar(in1, in2); -- a stateful node
386
     out1 = x;
387
     out2 = in2;
388
   tel
389

  
390
   Since foo contains a stateful node, it is stateful itself. Its prototype is 
391
   extended with a reset input. When the node is reset, each of its "pre" expression
392
   is reset as well as all calls to stateful node it contains. 
393

  
394
   will produce the following JSON struct:
395
   "foo": {inputs:  [{name: "in1", type: "int"}, 
396
                     {name: "in2", type: "int"}, 
397
                     {name: "__reset", type: "reset"}
398
                    ],
399
           outputs: [{name: "out1", type: "int"}, {name: "out2", type: "int"}],
400
           locals:  [{name: "x", type: "int"}],
401
           instrs:  [
402
                    { def_x: { lhs: ["x"], 
403
                               rhs: {type: "statefulcall", name: "bar", 
404
                                     args: [in1, in2], reset: [ni4_reset] } 
405
                             }
406
                    }
407
                    { def_out1: { lhs: "out1", rhs: "x" } },
408
                    { def_out2: { lhs: "out2", rhs: "in2" }}
409
                    ]
410
           }
411

  
412
Basically we have three different definitions
413
1. classical assign of a variable to another one:
414
   { def_out1: { lhs: "out1", rhs: "x" } },
415
2. call to a stateless function, typically an operator
416
   { def_x: { lhs: ["x"], 
417
     rhs: {type: "statelesscall", name: "bar", args: [in1, in2]} 
418
   }
419
  or in the operator version 
420
   { def_x: { lhs: ["x"], 
421
     rhs: {type: "operator", name: "+", args: [in1, in2]} 
422
   }
423

  
424
  In Simulink this should introduce a subsystem in the first case or a 
425
  regular block in the second with card(lhs) outputs and card{args} inputs.
426

  
427
3. call to a stateful node. It is similar to the stateless above, 
428
   with the addition of the reset argument
429
    { def_x: { lhs: ["x"], 
430
               rhs: {type: "statefulcall", name: "bar", 
431
                     args: [in1, in2], reset: [ni4_reset] } 
432
             }
433
    }
434
  
435
  In lustrec compilation phases, a unique id is associated to this specific
436
  instance of stateful node "bar", here ni4. 
437
  Instruction such as reset(ni4) or noreset(ni4) may -- or not -- reset this 
438
  specific node. This corresponds to "every c" suffix of a node call in lustre.
439

  
440
  In Simulink this should introduce a subsystem that has this extra reset input.  
441
  The reset should be defined as an "OR" over (1) the input reset of the parent 
442
  node, __reset in the present example and (2) any occurence of reset(ni4) in 
443
  the instructions.
444

  
445
4. branching construct: (guard expr, (tag, instr list) list)
446
   { "merge_XX": { type: "branch", guard: "var_guard", 
447
                   inputs:   ["varx", "vary"],
448
                   outputs:  ["vark", "varz"],
449
                   branches: ["tag1": [liste_of_definitions (1-4)], ...] 
450
                 }
451
   }
452

  
453
  In Simulink, this should become one IF block to produce enable ports "var_guard == tag1", "var_guard == tag2", .... as well as one action block per branch: each of these action block shall  
454
*)     
323 455
let pp_machine fmt m =
324 456
  try
325 457
    fprintf fmt "@[<v 2>\"%s\": {@ \"inputs\": [%a],@ \"outputs\": [%a],@ "
......
327 459
      pp_node_args m.mstep.step_inputs
328 460
      pp_node_args m.mstep.step_outputs;
329 461
    fprintf fmt "\"exprs\": {@[<v 1> %a@]@ }"
330
      (fprintf_list ~sep:",@ " (pp_emf_instrs m)) m.mstep.step_instrs;
462
      (fprintf_list ~sep:",@ " (pp_emf_instr m)) m.mstep.step_instrs;
331 463
    fprintf fmt "@]@ }"
332 464
  with Unhandled msg -> (
333 465
    eprintf "[Error] @[<v 0>EMF backend@ Issues while translating node %s@ "
src/backends/backends.ml
4 4
let setup s =
5 5
  match s with
6 6
  | "emf" ->
7
     join_guards := false; (* guards should not be joined, in order to have only
7
     join_guards := true; (* guards should not be joined, in order to have only
8 8
			      if c then x = e1 else x = e2 to ease
9 9
			      reconstruction of flows. *)
10 10
    Options.optimization := 0; (* Optimization=0 prevents expression

Also available in: Unified diff