~ubuntu-branches/ubuntu/wily/marionnet/wily

« back to all changes in this revision

Viewing changes to chip/chip_parser_p4.old_version.ml

  • Committer: Package Import Robot
  • Author(s): Lucas Nussbaum
  • Date: 2013-03-29 15:57:12 UTC
  • Revision ID: package-import@ubuntu.com-20130329155712-o0b9b96w8av68ktq
Tags: upstream-0.90.6+bzr407
ImportĀ upstreamĀ versionĀ 0.90.6+bzr407

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(* This file is part of Marionnet, a virtual network laboratory
 
2
   Copyright (C) 2009  Jean-Vincent Loddo
 
3
   Copyright (C) 2009  UniversitĆ© Paris 13
 
4
 
 
5
   This program is free software: you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation, either version 2 of the License, or
 
8
   (at your option) any later version.
 
9
 
 
10
   This program is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
   GNU General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License
 
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
 
17
 
 
18
 
 
19
open Camlp4 (* -*- camlp4o -*- *)
 
20
 
 
21
(* ocamlc -I +camlp4 -pp camlp4of.opt camlp4lib.cma chip_parser.p4.ml *)
 
22
 
 
23
(* For a strange bug, Camlp4of goes in a loop (StackOverflow) when a chip
 
24
   with more than 1 port is declared virtual. Thus, in practice, if the chip
 
25
   is virtual, we are limited to 1 port! *)
 
26
 
 
27
module Id = struct
 
28
  let name = "Chip_pa"
 
29
  let version = "$Id: chip_pa.ml,v 0.1 2009/02/16 16:16:16 $"
 
30
end
 
31
 
 
32
module Make (Syntax : Sig.Camlp4Syntax) = struct
 
33
  open Sig
 
34
  include Syntax
 
35
 
 
36
  (* Make a multiple application. *)
 
37
  let apply _loc f xs = List.fold_left (fun f x -> <:expr< $f$ $x$>>) f xs
 
38
 
 
39
  (* Make a string list ast from... a string list. *)
 
40
  let rec string_list_of_string_list _loc = function
 
41
   | []    -> <:expr< [] >>
 
42
   | x::xs -> let xs' = string_list_of_string_list _loc xs in <:expr< $str:x$ :: $xs'$>>
 
43
 
 
44
  let rec expr_of_expr_list _loc = function
 
45
   | []    -> <:expr< [] >>
 
46
   | x::xs -> let xs' = expr_of_expr_list _loc xs in <:expr< $x$ :: $xs'$>>
 
47
 
 
48
  (* Make a multiple abstraction to a class_expr. *)
 
49
  let lambda_class_expr _loc xs body = List.fold_right (fun x b -> <:class_expr< fun $x$ -> $b$>>) xs body
 
50
 
 
51
  (* Make a multiple abstraction to a type. *)
 
52
  let lambda_ctyp _loc xs body = List.fold_right (fun x b -> <:ctyp< $x$ -> $b$>>) xs body
 
53
 
 
54
  (* Make a fresh identifier (string). *)
 
55
  let fresh_var_name ~blacklist ~prefix =
 
56
   let rec loop n =
 
57
    let candidate = (prefix^(string_of_int n)) in
 
58
    if not (List.mem candidate blacklist) then candidate else loop (n+1)
 
59
   in
 
60
   if (List.mem prefix blacklist) then (loop 0) else prefix
 
61
 
 
62
  let fresh_var_names ~blacklist ~prefixes =
 
63
   let r = List.fold_left (fun l p -> (fresh_var_name ~blacklist:(l@blacklist) ~prefix:p) :: l) [] prefixes in
 
64
   List.rev r
 
65
 
 
66
  (* List.combine for 3 lists *)
 
67
  let rec combine3 l1 l2 l3 = match (l1,l2,l3) with
 
68
  | []    , []    , []     -> []
 
69
  | x1::r1, x2::r2, x3::r3 -> (x1,x2,x3)::(combine3 r1 r2 r3)
 
70
  | _ -> raise (Invalid_argument "combine3")
 
71
 
 
72
  let rec combine4 l1 l2 l3 l4 = match (l1,l2,l3,l4) with
 
73
  | []    , []    , []   , []  -> []
 
74
  | x1::r1, x2::r2, x3::r3, x4::r4 -> (x1,x2,x3,x4)::(combine4 r1 r2 r3 r4)
 
75
  | _ -> raise (Invalid_argument "combine4")
 
76
 
 
77
  (* Check unicity in a string list. Raises a failure with the duplicated string. *)
 
78
  let rec check_unicity = function
 
79
  | []   -> ()
 
80
  | x::r -> if (List.mem x r) then failwith ("Duplicated port name '"^x^"'")
 
81
                              else (check_unicity r)
 
82
 
 
83
 
 
84
  EXTEND Gram
 
85
    GLOBAL: str_item;
 
86
 
 
87
    where:
 
88
      [ [  "complement"; w = LIST0 class_str_item ; "end" -> w ] ] ;
 
89
 
 
90
    port_ident:
 
91
      [ [  "("; x = LIDENT ; ":"; t = ctyp; ")" -> (x, Some t)
 
92
        |       x = LIDENT ; ":"; t = ctyp      -> (x, Some t)
 
93
        |       x = LIDENT                      -> (x, None  )  ] ] ;
 
94
 
 
95
    str_item: FIRST
 
96
      [ [ "chip"; virt = OPT "virtual"; class_name = LIDENT; user_parameters = LIST0 [ x=patt -> x];  ":" ;
 
97
 
 
98
          input_ports  = [ "(" ; l = LIST0 [ x = port_ident -> x] SEP ","; ")" -> l ];
 
99
 
 
100
          output_ports = [ "->"; "("; l = LIST0 [ x = port_ident -> x] SEP "," ; ")"; "=" -> l
 
101
                         | "->"; "unit"; "=" -> []
 
102
                         | "="               -> [] ];
 
103
 
 
104
          e = expr ; w = OPT where ->
 
105
 
 
106
          (* Class type *)
 
107
          let is_virtual = (virt <> None) in
 
108
 
 
109
          (* Are there where clauses: *)
 
110
          let user_complement_section = match w with None -> [] | Some w -> w in
 
111
 
 
112
          (* Port names (inputs + outputs) *)
 
113
          let is_source = (input_ports = []) in
 
114
          let inputs  = List.map fst input_ports  in
 
115
          let outputs = List.map fst output_ports in
 
116
          let port_names = List.append inputs outputs in
 
117
          let () = check_unicity port_names in
 
118
 
 
119
          let ancestor = match input_ports, output_ports with
 
120
            | [],[] ->  failwith "Autistic chips not allowed!"
 
121
            | [], _ -> "source"
 
122
            | _ ,[] -> "sink"
 
123
            | _ ,_  -> "relay"
 
124
          in
 
125
 
 
126
          (* Support functions and values *)
 
127
 
 
128
          let set_alone_application  a = <:expr< self#$lid:"set_alone_" ^a$ $lid:a$ >>  in
 
129
          let connect_application    a = <:expr< self#$lid:"connect_"   ^a$ $lid:a$ >>  in
 
130
          let disconnect_application a = <:expr< self#$lid:"disconnect_"^a$ >>          in
 
131
 
 
132
          let (pat_w, exp_w) =
 
133
            let str = (fresh_var_name ~blacklist:port_names ~prefix:"w") in
 
134
            (<:patt< $lid:str$ >> , <:expr< $lid:str$ >>)
 
135
          in
 
136
 
 
137
          let (pat_v, exp_v) =
 
138
            let str = (fresh_var_name ~blacklist:port_names ~prefix:"v") in
 
139
            (<:patt< $lid:str$ >> , <:expr< $lid:str$ >>)
 
140
          in
 
141
 
 
142
          let (pat_s, exp_s) =
 
143
            let str = (fresh_var_name ~blacklist:port_names ~prefix:"s") in
 
144
            (<:patt< $lid:str$ >> , <:expr< $lid:str$ >>)
 
145
          in
 
146
 
 
147
          (* Class type variables *)
 
148
          let ctv =
 
149
            let type_variables = List.map (fun i -> <:ctyp< '$lid:i$ >>) port_names in
 
150
            Ast.tyCom_of_list type_variables
 
151
          in
 
152
 
 
153
          (* Inherit section *)
 
154
          let inherit_section =  [ <:class_str_item< inherit $lid:ancestor$ ?name system >> ] in
 
155
 
 
156
          (* Tool for creating a pattern depending on the length of a list of identifiers
 
157
             encoded by strings. If the list is empty, the pattern () is built. If the list is
 
158
             a singleton, the pattern is simply itself. If the list has almost two elements,
 
159
             a tuple pattern is created. *)
 
160
          let pattern_of_string_list = function
 
161
           | []  -> <:patt< () >>
 
162
           | [x] -> <:patt< $lid:x$>>
 
163
           |  l  -> Ast.PaTup (_loc, Ast.paCom_of_list (List.map (fun x-> <:patt< $lid:x$>>) l))
 
164
          in
 
165
 
 
166
          (* Similar to pattern_of_string_list, but for making an expression from a list of
 
167
             sub-expressions. *)
 
168
          let expression_of_expr_list = function
 
169
           | []  -> <:expr< () >>
 
170
           | [e] -> e
 
171
           |  l  -> Ast.ExTup (_loc, Ast.exCom_of_list l)
 
172
          in
 
173
 
 
174
          let type_of_ctyp_list = function
 
175
           | []  -> <:ctyp< unit >>
 
176
           | [t] -> t
 
177
           |  l  -> Ast.TyTup (_loc, Ast.tySta_of_list l)
 
178
          in
 
179
 
 
180
          (* Firmware section *)
 
181
 
 
182
          let domains =
 
183
            let mill =
 
184
             fun (x,ot) -> match ot with None -> Ast.TyLab(_loc,x,<:ctyp< _ >>) | Some t -> Ast.TyLab(_loc,x,t) in
 
185
            List.map mill input_ports
 
186
          in
 
187
 
 
188
          let codomain =
 
189
            let mill = fun (_,ot) -> match ot with None -> <:ctyp< _ >> | Some t -> t in
 
190
            type_of_ctyp_list (List.map mill output_ports)
 
191
          in
 
192
 
 
193
          let signature = lambda_ctyp _loc domains codomain in
 
194
 
 
195
          let firmware =
 
196
            let pl = List.map (fun i -> Ast.PaLab (_loc, i, <:patt< >>)) inputs             in
 
197
            let firmware_expr   = List.fold_right (fun p e -> <:expr< fun $p$ -> $e$ >>) pl e in
 
198
            let firmware_method =
 
199
              match is_source with
 
200
              | false -> <:class_str_item< method firmware : $signature$ = $firmware_expr$ >>
 
201
              | true  -> <:class_str_item< method firmware = $firmware_expr$ >>
 
202
            in
 
203
            [firmware_method]
 
204
          in
 
205
 
 
206
          (* in_port fields section *)
 
207
          let in_port_fields =
 
208
            let mill a = <:class_str_item< val mutable $lid:a$ = in_port_of_wire_option $lid:a$ >> in
 
209
            List.map mill inputs
 
210
          in
 
211
 
 
212
          (* out_port fields section *)
 
213
          let out_port_fields =
 
214
            let mill x = <:class_str_item< val mutable $lid:x$ = out_port_of_wire_option $lid:x$ >> in
 
215
            List.map mill outputs
 
216
          in
 
217
 
 
218
          let port_names_fields =
 
219
            let  in_port_names = string_list_of_string_list _loc inputs  in
 
220
            let out_port_names = string_list_of_string_list _loc outputs in
 
221
            [ <:class_str_item< val  in_port_names =  $in_port_names$ >> ;
 
222
              <:class_str_item< val out_port_names = $out_port_names$ >> ]
 
223
          in
 
224
 
 
225
          (* connect_? methods for input ports *)
 
226
          let connect_i =
 
227
            let mill a =
 
228
             let b  = fresh_var_name ~blacklist:port_names ~prefix:a in
 
229
             let tv = <:ctyp< '$lid:a$ >> in
 
230
             let tv'= <:ctyp< '$lid:b$ >> in
 
231
             let t  = <:ctyp< ($tv'$,$tv$) wire -> unit >> in
 
232
             let method_type = Ast.TyPol (_loc, Ast.TyQuo(_loc,b), t) in
 
233
             <:class_str_item< method $lid:"connect_"^a$ : $method_type$ = function $pat_w$ -> ($lid:a$ <- in_port_of_wire $exp_w$) >> in
 
234
            List.map mill inputs
 
235
          in
 
236
 
 
237
          (* connect_? methods for output ports *)
 
238
          let connect_o =
 
239
            let mill a =
 
240
             let b  = fresh_var_name ~blacklist:port_names ~prefix:a in
 
241
             let tv = <:ctyp< '$lid:a$ >> in
 
242
             let tv'= <:ctyp< '$lid:b$ >> in
 
243
             let t   = <:ctyp< ($tv$,$tv'$) wire -> unit >> in
 
244
             let method_type = Ast.TyPol (_loc, Ast.TyQuo(_loc,b), t) in
 
245
             <:class_str_item< method $lid:"connect_"^a$ : $method_type$ = function $pat_w$ -> ($lid:a$ <- out_port_of_wire $exp_w$) >> in
 
246
            List.map mill outputs
 
247
          in
 
248
 
 
249
          (* connect method *)
 
250
          let connect =
 
251
           let ivl = fresh_var_names ~blacklist:port_names       ~prefixes:inputs  in
 
252
           let ovl = fresh_var_names ~blacklist:(port_names@ivl) ~prefixes:outputs in
 
253
           let wire_type a b =
 
254
             let va = <:ctyp< '$lid:a$ >> in
 
255
             let vb = <:ctyp< '$lid:b$ >> in
 
256
             <:ctyp< ($va$,$vb$) wire >>
 
257
           in
 
258
           let it = type_of_ctyp_list (List.map2 wire_type ivl inputs) in
 
259
           let ot = type_of_ctyp_list (List.map2 wire_type outputs ovl) in
 
260
           let qivl = List.map (fun x -> Ast.TyQuo(_loc,x)) ivl in
 
261
           let qovl = List.map (fun x -> Ast.TyQuo(_loc,x)) ovl in
 
262
           let pi = pattern_of_string_list inputs  in
 
263
           let po = pattern_of_string_list outputs in
 
264
           let connect_actions = Ast.exSem_of_list (List.map connect_application port_names) in
 
265
           match inputs, outputs with
 
266
           | [] , [] -> assert false
 
267
           |  _ , [] ->
 
268
              let i_forall_vars = List.fold_left (fun x y -> Ast.TyApp (_loc,x,y)) (List.hd qivl) (List.tl qivl) in
 
269
              let method_type = Ast.TyPol (_loc, i_forall_vars, <:ctyp< $it$ -> unit>>) in
 
270
              [ <:class_str_item< method connect : $method_type$ = function $pi$ -> begin $connect_actions$ end >> ]
 
271
 
 
272
           | [] , _  ->
 
273
              let o_forall_vars = List.fold_left (fun x y -> Ast.TyApp (_loc,x,y)) (List.hd qovl) (List.tl qovl) in
 
274
              let method_type = Ast.TyPol (_loc, o_forall_vars, <:ctyp< $ot$ -> unit>>) in
 
275
              [ <:class_str_item< method connect : $method_type$ = function $po$ -> begin $connect_actions$ end >> ]
 
276
 
 
277
           |  _ , _  ->
 
278
              let qvl = List.append qivl qovl in
 
279
              let forall_vars = List.fold_left (fun x y -> Ast.TyApp (_loc,x,y)) (List.hd qvl) (List.tl qvl) in
 
280
              let method_type = Ast.TyPol (_loc, forall_vars, <:ctyp< $it$ -> $ot$ -> unit>>) in
 
281
              [ <:class_str_item< method connect : $method_type$ = function $pi$ -> function $po$ -> begin $connect_actions$ end >> ]
 
282
          in
 
283
 
 
284
          (* disconnect_? methods for all ports *)
 
285
          let disconnect_x =
 
286
            let mill a = <:class_str_item< method $lid:"disconnect_"^a$ = $lid:a$ <- None >> in
 
287
            List.map mill port_names
 
288
          in
 
289
 
 
290
          (* disconnect method *)
 
291
          let disconnect =
 
292
           let disconnect_actions = Ast.exSem_of_list (List.map disconnect_application port_names)
 
293
            in
 
294
            [ <:class_str_item<
 
295
             method disconnect =
 
296
              begin $disconnect_actions$ end
 
297
            >> ]
 
298
 
 
299
          in
 
300
 
 
301
          (* get_wire_? methods for input ports *)
 
302
          let get_wire_i =
 
303
            let mill a =
 
304
             let str = <:expr< $str:class_name^"#get_wire_"^a$ >> in
 
305
             <:class_str_item< method $lid:"get_wire_"^a$ = fst_of_triple (extract ~caller:$str$ $lid:a$) >> in
 
306
            List.map mill inputs
 
307
          in
 
308
 
 
309
          (* get_wire_? methods for output ports *)
 
310
          let get_wire_o =
 
311
            let mill a =
 
312
             let str = <:expr< $str:class_name^"#get_wire_"^a$ >> in
 
313
             <:class_str_item< method $lid:"get_wire_"^a$ = extract ~caller:$str$ $lid:a$ >> in
 
314
            List.map mill outputs
 
315
          in
 
316
 
 
317
          let get_wire_connections =
 
318
            let connections_i =
 
319
             let mill a =
 
320
              <:expr< ($str:a$, wire_as_common_option_of_in_port $lid:a$) >> in
 
321
             List.map mill inputs
 
322
            in
 
323
            let connections_o =
 
324
             let mill a =
 
325
              <:expr< ($str:a$, wire_as_common_option_of_out_port $lid:a$) >> in
 
326
             List.map mill outputs
 
327
            in
 
328
            let il = expr_of_expr_list _loc connections_i in
 
329
            let ol = expr_of_expr_list _loc connections_o in
 
330
            [ <:class_str_item< method $lid:"input_wire_connections"$  = $il$ >> ;
 
331
              <:class_str_item< method $lid:"output_wire_connections"$ = $ol$ >> ]
 
332
          in
 
333
 
 
334
          (* set_in_port_? methods *)
 
335
          let set_in_port_i =
 
336
            let mill a =
 
337
             <:class_str_item< method $lid:"set_in_port_"^a$  $pat_w$ $pat_v$ $pat_s$ = $lid:a$ <- Some ($exp_w$,(Some $exp_v$),$exp_s$) >> in
 
338
            List.map mill inputs
 
339
          in
 
340
 
 
341
          (* set_alone_? methods for input ports *)
 
342
          let set_alone_i =
 
343
            let mill a =
 
344
             let str = <:expr< $str:class_name^"#set_alone_"^a$ >> in
 
345
             <:class_str_item< method $lid:"set_alone_"^a$ $pat_v$ = (fst (extract ~caller:$str$ $lid:a$))#set_alone $exp_v$ >> in
 
346
            List.map mill inputs
 
347
          in
 
348
 
 
349
          (* set_alone_? methods for output ports *)
 
350
          let set_alone_o =
 
351
            let mill a =
 
352
             let str = <:expr< $str:class_name^"#set_alone_"^a$ >> in
 
353
             <:class_str_item< method $lid:"set_alone_"^a$ v = (extract ~caller:$str$ $lid:a$)#set_alone v >> in
 
354
            List.map mill outputs
 
355
          in
 
356
 
 
357
          (* stabilize method section *)
 
358
          let stabilize =
 
359
            let str = <:expr< $str:class_name^"#stabilize"$ >> in
 
360
 
 
361
            let winputs          = List.map (fun a -> fresh_var_name ~blacklist:port_names ~prefix:("w"^a)) inputs in
 
362
            let unchanged_inputs = List.map (fun a -> fresh_var_name ~blacklist:port_names ~prefix:("unchanged_"^a)) inputs in
 
363
            let sensitiveness_inputs = List.map (fun a -> fresh_var_name ~blacklist:port_names ~prefix:("sens_"^a)) inputs in
 
364
 
 
365
            let input_bindings =
 
366
              let mill (wa,a,sa,unchanged_a) =
 
367
                let p = <:patt< ($lid:wa$, $lid:a$ , $lid:sa$ , $lid:unchanged_a$) >> in
 
368
                <:binding< $p$ = (extract_and_compare $str$ $lid:"equality"$ $lid:a$) >>
 
369
              in Ast.biAnd_of_list (List.map mill (combine4 winputs inputs sensitiveness_inputs unchanged_inputs))
 
370
            in
 
371
 
 
372
            let unchanged_test =
 
373
              let l = (List.map (fun unchanged_a -> <:expr< $lid:unchanged_a$ >>) unchanged_inputs) in
 
374
              List.fold_right (fun e1 e2 -> <:expr< $e1$ && $e2$ >>) l <:expr< true >>
 
375
            in
 
376
 
 
377
            let output_bindings =
 
378
             let inputs_as_lid_expressions = List.map (fun x -> <:expr< $lid:x$>>) inputs            in
 
379
             let firmware_application = apply _loc <:expr< self#firmware>> inputs_as_lid_expressions in
 
380
             let output_pattern = pattern_of_string_list outputs in
 
381
             <:binding< $output_pattern$ = $firmware_application$ >>
 
382
            in
 
383
 
 
384
            let set_actions =
 
385
             let set_in_port_application (wa,a,sa) = <:expr< self#$lid:"set_in_port_"^a$ $lid:wa$ $lid:a$ $lid:sa$ >> in
 
386
             Ast.exSem_of_list ((List.map set_in_port_application (combine3 winputs inputs sensitiveness_inputs))
 
387
                               @(List.map set_alone_application outputs))
 
388
            in
 
389
 
 
390
            [ <:class_str_item<
 
391
             method stabilize : performed =
 
392
               let $binding:input_bindings$ in
 
393
                if ($unchanged_test$)
 
394
                then
 
395
                 (Performed false)
 
396
                else
 
397
                 let $binding:output_bindings$ in
 
398
                  $set_actions$ ;
 
399
                 (Performed true)
 
400
            >>]
 
401
 
 
402
          in
 
403
 
 
404
          (* emit method section (for sources) *)
 
405
          let emit =
 
406
 
 
407
            let arg = fresh_var_name ~blacklist:port_names ~prefix:"arg" in
 
408
 
 
409
            let output_bindings =
 
410
             let inputs_as_lid_expressions = List.map (fun x -> <:expr< $lid:x$>>) inputs            in
 
411
             let firmware_application = apply _loc <:expr< self#firmware $lid:arg$ >> inputs_as_lid_expressions in
 
412
             let output_pattern = pattern_of_string_list outputs in
 
413
             <:binding< $output_pattern$ = $firmware_application$ >>
 
414
            in
 
415
 
 
416
            let set_actions = Ast.exSem_of_list (List.map set_alone_application outputs)
 
417
            in
 
418
 
 
419
            [ <:class_str_item<
 
420
             method emit $lid:arg$ =
 
421
                 let actions () =
 
422
                   let $binding:output_bindings$ in
 
423
                   $set_actions$ ;
 
424
                   self#system#stabilize
 
425
                 in self#system#mutex_methods#with_mutex actions
 
426
            >>]
 
427
 
 
428
          in
 
429
 
 
430
          (* set method section *)
 
431
          let set =
 
432
           let input_pattern = pattern_of_string_list inputs in
 
433
           let set_alone_actions = Ast.exSem_of_list (List.map set_alone_application inputs)
 
434
            in
 
435
            [ <:class_str_item<
 
436
             method set $input_pattern$ =
 
437
              $set_alone_actions$ ;
 
438
              self#system#stabilize
 
439
            >> ]
 
440
 
 
441
          in
 
442
 
 
443
          (* get method section (outputs) *)
 
444
          let get =
 
445
           let mill a =
 
446
            let str = <:expr< $str:class_name^"#get (reading "^a^")"$ >> in
 
447
            <:expr< (extract ~caller:$str$ $lid:a$)#get_alone >> in
 
448
           let output_expression = expression_of_expr_list (List.map mill outputs)
 
449
           in [ <:class_str_item< method get = $output_expression$ >> ]
 
450
 
 
451
          in
 
452
 
 
453
          (* get_? methods for inputs *)
 
454
          let get_i =
 
455
            let mill a =
 
456
             let str = <:expr< $str:class_name^"#get_"^a$ >> in
 
457
             <:class_str_item< method $lid:"get_"^a$ = (fst_of_triple (extract ~caller:$str$ $lid:a$))#get_alone >> in
 
458
            List.map mill inputs
 
459
          in
 
460
 
 
461
          (* get_? methods for outputs *)
 
462
          let get_o =
 
463
            let mill a =
 
464
             let str = <:expr< $str:class_name^"#get_"^a$ >> in
 
465
             <:class_str_item< method $lid:"get_"^a$ = (extract ~caller:$str$ $lid:a$)#get_alone >> in
 
466
            List.map mill outputs
 
467
          in
 
468
 
 
469
          (* Merging sections *)
 
470
          let cst = Ast.crSem_of_list
 
471
           (List.concat
 
472
            [ inherit_section   ;
 
473
              firmware          ;
 
474
              in_port_fields    ;
 
475
              out_port_fields   ;
 
476
              port_names_fields ;
 
477
              connect_i         ;
 
478
              connect_o         ;
 
479
              connect           ;
 
480
              disconnect_x      ;
 
481
              disconnect        ;
 
482
              get_wire_i        ;
 
483
              get_wire_o        ;
 
484
              get_wire_connections;
 
485
              set_in_port_i     ;
 
486
(*              set_alone_i       ;*)
 
487
              set_alone_o       ;
 
488
(*              get               ;*)
 
489
              get_i             ;
 
490
(*              get_o             ;*)
 
491
              if is_source then emit else stabilize ;
 
492
(*              if is_source then [] else set       ;*)
 
493
              user_complement_section ;
 
494
            ])
 
495
           in
 
496
 
 
497
          (* Class expression *)
 
498
 
 
499
          let ce =
 
500
            <:class_expr<
 
501
             fun ?(system : system = (Chip.get_or_initialize_current_system ())) () -> object (self) $cst$ end >> in
 
502
 
 
503
          (* Class expression with optional parameters *)
 
504
          let cop_list = List.map (fun i -> Ast.PaOlb (_loc, i, <:patt< >>)) port_names in
 
505
          let cewop = List.fold_right (fun op ce -> <:class_expr< fun $op$ -> $ce$ >>) cop_list ce in
 
506
          let cewop = <:class_expr< fun ?name ?(equality=(Pervasives.(=))) -> $cewop$ >> in
 
507
          let cewop_with_user_parameters = lambda_class_expr _loc user_parameters cewop in
 
508
          let internal_module_name = ("Chip_class_definition_"^class_name) in
 
509
          let class_def = match is_virtual with
 
510
          | false -> <:str_item< class         [ $ctv$ ] $lid:class_name$ = $cewop_with_user_parameters$ >>
 
511
          | true  -> <:str_item< class virtual [ $ctv$ ] $lid:class_name$ = $cewop_with_user_parameters$ >>
 
512
          in
 
513
          <:str_item<
 
514
 
 
515
            module $uid:internal_module_name$ = struct
 
516
             open Chip
 
517
             $class_def$
 
518
            end
 
519
            include $uid:internal_module_name$
 
520
          >>
 
521
 
 
522
         ] ]
 
523
    ;
 
524
 
 
525
  END
 
526
 
 
527
end
 
528
 
 
529
let module M = Register.OCamlSyntaxExtension (Id) (Make) in ()