Revision 524060b3
Added by PierreLoïc Garoche over 6 years ago
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 (14)], ...] 

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@ " 
Also available in: Unified diff
Ongoin work on EMF backend. Commit to store a working version. More work to do on clocks and resets