ocarina-backends-po_hi_c-deployment.adb 106 KB
Newer Older
1
2
3
4
5
6
7
8
------------------------------------------------------------------------------
--                                                                          --
--                           OCARINA COMPONENTS                             --
--                                                                          --
--  O C A R I N A . B A C K E N D S . P O _ H I _ C . D E P L O Y M E N T   --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
yoogx's avatar
yoogx committed
9
10
--               Copyright (C) 2008-2009 Telecom ParisTech,                 --
--                 2010-2019 ESA & ISAE, 2019-2020 OpenAADL                 --
11
--                                                                          --
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- Ocarina  is free software; you can redistribute it and/or modify under   --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion. Ocarina is distributed in the hope that it will be useful, but     --
-- WITHOUT ANY WARRANTY; without even the implied warranty of               --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
27
--                                                                          --
yoogx's avatar
yoogx committed
28
29
--                    Ocarina is maintained by OpenAADL team                --
--                              (info@openaadl.org)                         --
30
31
32
--                                                                          --
------------------------------------------------------------------------------

33
with Ocarina.Namet;
34
with Utils; use Utils;
35
36
37
38
39
40
41
42
43
44
45
46
47
with Ocarina.ME_AADL;
with Ocarina.ME_AADL.AADL_Instances.Nodes;
with Ocarina.ME_AADL.AADL_Instances.Nutils;
with Ocarina.ME_AADL.AADL_Instances.Entities;

with Ocarina.Backends.Utils;
with Ocarina.Backends.C_Values;
with Ocarina.Backends.C_Tree.Nutils;
with Ocarina.Backends.C_Tree.Nodes;
with Ocarina.Backends.C_Common.Mapping;
with Ocarina.Backends.PO_HI_C.Runtime;
with Ocarina.Backends.Properties;
with Ocarina.Backends.Messages;
48
49
50
with Ocarina.Backends.C_Common.BA;
with Ocarina.ME_AADL_BA.BA_Tree.Nutils;
with Ocarina.ME_AADL_BA.BA_Tree.Nodes;
51

52
53
with Ocarina.Instances.Queries;

54
55
with Locations;

56
57
package body Ocarina.Backends.PO_HI_C.Deployment is

58
   use Ocarina.Namet;
59
60
61
62
63
64
65
66
67
68
   use Ocarina.ME_AADL;
   use Ocarina.ME_AADL.AADL_Instances.Nodes;
   use Ocarina.ME_AADL.AADL_Instances.Entities;
   use Ocarina.Backends.Utils;
   use Ocarina.Backends.C_Values;
   use Ocarina.Backends.C_Tree.Nutils;
   use Ocarina.Backends.C_Common.Mapping;
   use Ocarina.Backends.PO_HI_C.Runtime;
   use Ocarina.Backends.Properties;
   use Ocarina.Backends.Messages;
69
   use Ocarina.Instances.Queries;
70
   use Ocarina.Backends.C_Common.BA;
71

72
73
   use Locations;

74
   package AAN renames Ocarina.ME_AADL.AADL_Instances.Nodes;
75
76
77
   package AAU renames Ocarina.ME_AADL.AADL_Instances.Nutils;
   package CV renames Ocarina.Backends.C_Values;
   package CTN renames Ocarina.Backends.C_Tree.Nodes;
78
   package CTU renames Ocarina.Backends.C_Tree.Nutils;
79
80
   package BATN renames Ocarina.ME_AADL_BA.BA_Tree.Nodes;
   package BANu renames Ocarina.ME_AADL_BA.BA_Tree.Nutils;
81

82
83
84
85
86
87
88
89
90
91
92
93
   Entity_Array           : Node_Id;
   Devices_Array          : Node_Id;
   Devices_Nb_Buses_Array : Node_Id;
   Devices_Confvars       : Node_Id;
   Protocols_Conf         : Node_Id;
   Devices_Buses_Array    : Node_Id;
   Port_To_Devices        : Node_Id;
   Devices_To_Nodes       : Node_Id;
   Global_Port_Kind       : Node_Id;
   Global_Port_Queue_Size : Node_Id;
   Global_Port_Data_Size  : Node_Id;
   Global_Ports           : List_Id;
94
   Protocol_Identifier    : Unsigned_Long_Long := 0;
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
   function Is_Added (P : Node_Id; E : Node_Id) return Boolean;
   function Added_Internal_Name (P : Node_Id; E : Node_Id) return Name_Id;

   --------------
   -- Is_Added --
   --------------

   function Is_Added (P : Node_Id; E : Node_Id) return Boolean is
      I_Name : constant Name_Id := Added_Internal_Name (P, E);
   begin
      return Get_Name_Table_Byte (I_Name) = 1;
   end Is_Added;

   -------------------------
   -- Added_Internal_Name --
   -------------------------

   function Added_Internal_Name (P : Node_Id; E : Node_Id) return Name_Id is
   begin
      Set_Str_To_Name_Buffer ("%add%enumerator%");
      Add_Nat_To_Name_Buffer (Nat (P));
      Add_Char_To_Name_Buffer ('%');
      Add_Nat_To_Name_Buffer (Nat (E));

      return Name_Find;
   end Added_Internal_Name;

123
124
125
126
127
128
129
130
131
132
133
134
   -----------------
   -- Header_File --
   -----------------

   package body Header_File is

      procedure Visit_Architecture_Instance (E : Node_Id);
      procedure Visit_Component_Instance (E : Node_Id);
      procedure Visit_System_Instance (E : Node_Id);
      procedure Visit_Process_Instance (E : Node_Id);
      procedure Visit_Thread_Instance (E : Node_Id);
      procedure Visit_Subprogram_Instance (E : Node_Id);
135
      procedure Visit_Device_Instance (E : Node_Id);
136
      procedure Visit_Bus_Instance (E : Node_Id);
137
      procedure Visit_Virtual_Bus_Instance (E : Node_Id);
138
139
140
141

      procedure Set_Added (P : Node_Id; E : Node_Id);

      procedure Append_Existing
142
143
144
145
        (S         :        Node_Id;
         L         :        List_Id;
         Id        : in out Unsigned_Long_Long;
         Is_Entity :        Boolean := False);
146
147
148
149
150
151
152
153

      --  Append a node in a List. If the node was node already processed,
      --  it assigns a value (using the Id) argument to the node and bind
      --  it to the Backend Node of S. Is a value was already assigned, it
      --  simply uses it and append the it in the list.
      --  This function is used to warrant that all entities will have
      --  the same values on each node.

154
      Nb_Ports_List           : List_Id;
155
156
157
158
159
160
161
162
163
164
      Node_Enumerator_List    : List_Id;
      Tasks_Enumerator_List   : List_Id;
      Devices_Enumerator_List : List_Id;
      Buses_Enumerator_List   : List_Id;
      Entity_Enumerator_List  : List_Id;
      Global_Port_List        : List_Id;
      Protocol_List           : List_Id;
      Global_Port_Names       : Node_Id;
      Global_Port_Model_Names : Node_Id;
      Local_Port_List         : List_Id;
165

166
      Nb_Nodes : Unsigned_Long_Long;
167

168
      Current_Process_Instance : Node_Id := No_Node;
169

170
171
172
      Global_Port_To_Entity : Node_Id;
      Global_Port_To_Local  : Node_Id;
      Local_Port_Values     : Node_Id;
173
174

      Invalid_Local_Port_Added  : Boolean := False;
175
      Invalid_Protocol_Added    : Boolean := False;
176
177
178
      Invalid_Global_Port_Added : Boolean := False;
      Invalid_Entity_Added      : Boolean := False;

179
180
181
      Current_Device : Node_Id := No_Node;
      --  Current_Process : Node_Id := No_Node;

182
183
184
185
186
      --  Point to the process currently visited. When we visit a process
      --  we look at all its ports and visit the called subprograms. So,
      --  we need to know if these subprograms are linked with the currrent
      --  process.

187
188
189
190
191
      Node_Identifier        : Unsigned_Long_Long := 0;
      Global_Port_Identifier : Unsigned_Long_Long := 0;
      Local_Port_Identifier  : Unsigned_Long_Long := 0;
      Entity_Identifier      : Unsigned_Long_Long := 0;
      Task_Identifier        : Unsigned_Long_Long := 0;
192
      Tasks_Stack            : Unsigned_Long_Long := 0;
193
194
195
196
197
198
199
200
201
202
      Nb_Protected           : Unsigned_Long_Long := 0;
      Device_Id              : Unsigned_Long_Long := 0;
      Bus_Id                 : Unsigned_Long_Long := 0;
      Nb_Ports_In_Process    : Unsigned_Long_Long := 0;
      Nb_Ports_Total         : Unsigned_Long_Long := 0;
      Total_Ports_Node       : Node_Id            := No_Node;
      Nb_Entities_Node       : Node_Id            := No_Node;
      Nb_Devices_Node        : Node_Id            := No_Node;
      Nb_Buses_Node          : Node_Id            := No_Node;
      Nb_Protocols_Node      : Node_Id            := No_Node;
203
204
205
206
207
208
209
210
211
212
213
214

      --  The information from Simulink can come
      --  from both data and subprograms. So, to avoid
      --  conflict, we add relevant informations from
      --  the first component that have them. And for other
      --  components, we add nothing.

      ---------------------
      -- Append_Existing --
      ---------------------

      procedure Append_Existing
215
216
        (S         :        Node_Id;
         L         :        List_Id;
217
         Id        : in out Unsigned_Long_Long;
218
219
220
         Is_Entity :        Boolean := False)
      is
         N : Node_Id;
221
      begin
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
         if No (Backend_Node (Identifier (S)))
           or else
           (Present (Backend_Node (Identifier (S)))
            and then No (CTN.Enumerator_Node (Backend_Node (Identifier (S)))))
         then

            N :=
              Make_Expression
                (Make_Defining_Identifier
                   (Map_C_Enumerator_Name
                      (S,
                       Custom_Parent => Current_Device,
                       Entity        => Is_Entity)),
                 Op_Equal,
                 Make_Literal (CV.New_Int_Value (Id, 0, 10)));
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
            Bind_AADL_To_Enumerator (Identifier (S), N);
            Append_Node_To_List (N, L);
            Id := Id + 1;
         end if;
      end Append_Existing;

      ---------------
      -- Set_Added --
      ---------------

      procedure Set_Added (P : Node_Id; E : Node_Id) is
         I_Name : constant Name_Id := Added_Internal_Name (P, E);
      begin
         Set_Name_Table_Byte (I_Name, 1);
      end Set_Added;

      -----------
      -- Visit --
      -----------

      procedure Visit (E : Node_Id) is
      begin
         case Kind (E) is
            when K_Architecture_Instance =>
               Visit_Architecture_Instance (E);

            when K_Component_Instance =>
               Visit_Component_Instance (E);

            when others =>
               null;
         end case;
      end Visit;

      ---------------------------------
      -- Visit_Architecture_Instance --
      ---------------------------------

      procedure Visit_Architecture_Instance (E : Node_Id) is
      begin
         Visit (Root_System (E));
      end Visit_Architecture_Instance;

      ------------------------------
      -- Visit_Component_Instance --
      ------------------------------

      procedure Visit_Component_Instance (E : Node_Id) is
285
286
         Category : constant Component_Category :=
           Get_Category_Of_Component (E);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
      begin
         case Category is
            when CC_System =>
               Visit_System_Instance (E);

            when CC_Process =>
               Visit_Process_Instance (E);

            when CC_Thread =>
               Visit_Thread_Instance (E);

            when CC_Subprogram =>
               Visit_Subprogram_Instance (E);

301
302
303
            when CC_Device =>
               Visit_Device_Instance (E);

304
305
306
            when CC_Bus =>
               Visit_Bus_Instance (E);

307
308
309
            when CC_Virtual_Bus =>
               Visit_Virtual_Bus_Instance (E);

310
311
312
313
314
            when others =>
               null;
         end case;
      end Visit_Component_Instance;

315
316
317
318
319
      ------------------------
      -- Visit_Bus_Instance --
      ------------------------

      procedure Visit_Bus_Instance (E : Node_Id) is
320
         N : Node_Id;
321
      begin
322
323
324
325
326
327
328
         N :=
           Make_Expression
             (Make_Defining_Identifier
                (Map_C_Enumerator_Name (E, Entity => False)),
              Op_Equal,
              (Make_Literal (CV.New_Int_Value (Bus_Id, 0, 10))));
         Append_Node_To_List (N, Buses_Enumerator_List);
329

330
331
332
         Bus_Id := Bus_Id + 1;

         CTN.Set_Value (Nb_Buses_Node, New_Int_Value (Bus_Id, 1, 10));
333
334
335

      end Visit_Bus_Instance;

336
337
338
339
340
      --------------------------------
      -- Visit_Virtual_Bus_Instance --
      --------------------------------

      procedure Visit_Virtual_Bus_Instance (E : Node_Id) is
341
342
343
344
345
         N        : Node_Id;
         C        : Node_Id;
         S        : Node_Id;
         Impl     : Node_Id;
         Found    : Boolean;
346
         PName    : Name_Id;
347
         Bus_Conf : constant Node_Id := Make_Array_Values;
348
      begin
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
         --  A virtual bus describe a user-defined protocol.
         --  We are expecting that such a component defines some
         --  sub-components that model how it works.
         --  We are expecting at least one subprogram
         --  for marshalling (called marshaller in the subcomponent)
         --  and one for unmarshalling.

         --  Here, we retrieve the implementation of the protocol, as
         --  an abstract component. Then, we look for the marshaller
         --  and unmarshaller components that model protocol internals.

         Impl := Get_Implementation (E);

         --  If there is no abstract component associated with the virtual
         --  bus, this is useless to continue.

         if Impl = No_Node then
            return;
         end if;

         --  Make sure we include the header of subprograms
         --  in order to avoid any compilation issue (warning/errors).
         Set_Deployment_Source;
         Add_Include (RH (RH_Subprograms));
         Set_Deployment_Header;

375
376
377
378
379
380
381
382
383
384
         --  Add a maccro __PO_HI_USE_PROTOCOL_<NAME> so that we can
         --  make conditional compilation depending on the protocol
         --  that are used within the distributed system.
         Set_Str_To_Name_Buffer ("__PO_HI_USE_PROTOCOL_");
         Get_Name_String_And_Append (Name (Identifier (E)));

         PName := Name_Find;
         PName := To_Upper (To_C_Name (PName));

         Add_Define_Deployment
385
           (Make_Defining_Identifier (PName, C_Conversion => False));
386

387
388
389
390
         --  If there is a backend node and a naming node associated
         --  with it, it means that we already processed this protocol
         --  and correctly mapped it in the generated code.

391
392
393
         if Backend_Node (Identifier (E)) /= No_Node
           and then CTN.Naming_Node (Backend_Node (Identifier (E))) /= No_Node
         then
394
395
396
            return;
         end if;

397
398
399
400
401
402
403
404
405
         --  First, we are looking for the marshaller subcomponent.
         --  If not found, we raise an error.

         Found := False;

         if not AAU.Is_Empty (Subcomponents (Impl)) then
            S := First_Node (Subcomponents (Impl));
            while Present (S) loop
               C := Corresponding_Instance (S);
406
407
408
409
410
               if AAU.Is_Subprogram (C)
                 and then
                   Get_Name_String (Name (Identifier (S))) =
                   "marshaller"
               then
411
412
                  Append_Node_To_List
                    (Map_C_Defining_Identifier (C),
413
                     CTN.Values (Bus_Conf));
414
415
416
417
418
419
420
421
422
                  Found := True;
               end if;

               S := Next_Node (S);
            end loop;
         end if;

         if not Found then
            Display_Error
423
424
              ("User-defined protocol does define a marshaller",
               Fatal => True);
425
426
427
428
429
430
431
432
433
434
435
         end if;

         --  First, we are looking for the unmarshaller subcomponent.
         --  If not found, we display an error.

         Found := False;

         if not AAU.Is_Empty (Subcomponents (Impl)) then
            S := First_Node (Subcomponents (Impl));
            while Present (S) loop
               C := Corresponding_Instance (S);
436
437
438
439
440
               if AAU.Is_Subprogram (C)
                 and then
                   Get_Name_String (Name (Identifier (S))) =
                   "unmarshaller"
               then
441
442
443

                  Append_Node_To_List
                    (Map_C_Defining_Identifier (C),
444
                     CTN.Values (Bus_Conf));
445
446
447
448
449
450
451
452
453
                  Found := True;
               end if;

               S := Next_Node (S);
            end loop;
         end if;

         if not Found then
            Display_Error
454
455
              ("User-defined protocol does define a unmarshaller",
               Fatal => True);
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
         end if;

--         Found := False;
--
--         if not AAU.Is_Empty (Subcomponents (Impl)) then
--            S := First_Node (Subcomponents (Impl));
--            while Present (S) loop
--               C := Corresponding_Instance (S);
--               if AAU.Is_Data (C) and then
--                  Append_Node_To_List
--                     (Map_C_Defining_Identifier (C),
--                     CTN.Values (Bus_Conf));
--               end if;
--               S := Next_Node (S);
--            end loop;
--         end if;
--
--         if not Found then
--            Display_Error
--               ("User-defined protocol does define an associated type",
--                Fatal => True);
--         end if;

         --  Here, we add the array we just built and that describe
         --  the protocol configuration into the global array
         --  that contain all protocols configuration.

         Append_Node_To_List (Bus_Conf, CTN.Values (Protocols_Conf));

         --  Finally, we assigned a unique protocol identifier to the
         --  virtual bus, that will be mapped in the protocol_t enumeration
         --  in deployment.h.

489
490
491
492
493
494
         N :=
           Make_Expression
             (Make_Defining_Identifier (Map_C_Enumerator_Name (E)),
              Op_Equal,
              (Make_Literal (CV.New_Int_Value (Protocol_Identifier, 1, 10))));
         Append_Node_To_List (N, Protocol_List);
495
496
497
         Protocol_Identifier := Protocol_Identifier + 1;

         CTN.Set_Value
498
499
           (Nb_Protocols_Node,
            New_Int_Value (Protocol_Identifier, 1, 10));
500
501

         Bind_AADL_To_Naming
502
503
           (Identifier (E),
            Make_Defining_Identifier (Map_C_Enumerator_Name (E)));
504
505
      end Visit_Virtual_Bus_Instance;

506
507
508
509
510
      ---------------------------
      -- Visit_Device_Instance --
      ---------------------------

      procedure Visit_Device_Instance (E : Node_Id) is
511
512
513
514
515
516
517
518
519
520
         N                     : Node_Id;
         U                     : Node_Id;
         P                     : Node_Id;
         Q                     : Node_Id;
         F                     : Node_Id;
         Conf_Str              : Name_Id          := No_Name;
         Tmp_Name              : Name_Id;
         Nb_Connected_Buses    : Unsigned_Long_Long;
         Accessed_Buses        : constant Node_Id := Make_Array_Values;
         Accessed_Bus          : Node_Id;
521
         Device_Implementation : Node_Id;
522
523
524
525
         Configuration_Data    : Node_Id;
         The_System            : constant Node_Id :=
           Parent_Component (Parent_Subcomponent (E));
         Associated_Process : Node_Id := No_Node;
526
527
528
      begin
         Current_Device := E;

529
530
531
532
533
         if Current_Process_Instance /= No_Node
           and then
             Get_Bound_Processor (E) =
             Get_Bound_Processor (Current_Process_Instance)
         then
534

535
536
537
538
539
            if Backend_Node (Identifier (E)) /= No_Node
              and then
                CTN.Enumerator_Node (Backend_Node (Identifier (E))) /=
                No_Node
            then
540
541
542
               return;
            end if;

543
            Bind_AADL_To_Enumerator
544
545
546
              (Identifier (E),
               Make_Defining_Identifier
                 (Map_C_Enumerator_Name (E, Entity => False)));
547

548
549
550
551
            --  Try to find the process bounded with the device.
            Q := First_Node (Subcomponents (The_System));

            while Present (Q) loop
552
553
554
555
556
               if AAU.Is_Process (Corresponding_Instance (Q))
                 and then
                   Get_Bound_Processor (Corresponding_Instance (Q)) =
                   Get_Bound_Processor (E)
               then
557
558
559
560
561
                  Associated_Process := Q;
               end if;
               Q := Next_Node (Q);
            end loop;

562
563
564
565
566
567
568
            N :=
              Make_Expression
                (Make_Defining_Identifier
                   (Map_C_Enumerator_Name (E, Entity => False)),
                 Op_Equal,
                 (Make_Literal (CV.New_Int_Value (Device_Id, 0, 10))));
            Append_Node_To_List (N, Devices_Enumerator_List);
569

570
571
            if Associated_Process /= No_Node then
               Append_Node_To_List
572
573
574
                 (Make_Defining_Identifier
                    (Map_C_Enumerator_Name (Associated_Process)),
                  CTN.Values (Devices_To_Nodes));
575
576
            else
               Append_Node_To_List
577
578
                 (RE (RE_Unused_Node),
                  CTN.Values (Devices_To_Nodes));
579
580
            end if;

581
            Device_Id := Device_Id + 1;
582

583
            CTN.Set_Value (Nb_Devices_Node, New_Int_Value (Device_Id, 1, 10));
584
585
586

            if Get_Location (E) /= No_Name then
               Get_Name_String (Get_Location (E));
julien.delange's avatar
julien.delange committed
587
588
589
590
               Conf_Str := Name_Find;
               if Get_Port_Number (E) /= Properties.No_Value then
                  Set_Str_To_Name_Buffer (":");
                  Add_Str_To_Name_Buffer
591
                    (Value_Id'Image (Get_Port_Number (E)));
julien.delange's avatar
julien.delange committed
592
593
594
595
                  Tmp_Name := Name_Find;
               end if;
               Get_Name_String (Conf_Str);
               Get_Name_String_And_Append (Tmp_Name);
596
597
598
               Conf_Str := Name_Find;
            elsif Is_Defined_Property (E, "deployment::channel_address") then
               Set_Str_To_Name_Buffer
599
600
                 (Unsigned_Long_Long'Image
                    (Get_Integer_Property (E, "deployment::channel_address")));
601
602
603
               Conf_Str := Name_Find;
               if Is_Defined_Property (E, "deployment::process_id") then
                  Set_Str_To_Name_Buffer
604
605
                    (Unsigned_Long_Long'Image
                       (Get_Integer_Property (E, "deployment::process_id")));
606
607
608
609
610
611
                  Tmp_Name := Name_Find;
                  Get_Name_String (Conf_Str);
                  Add_Str_To_Name_Buffer (":");
                  Get_Name_String_And_Append (Tmp_Name);
                  Conf_Str := Name_Find;
               end if;
612
613
614
615
616
            elsif Is_Defined_Property (E, "deployment::configuration")
              and then
                Get_String_Property (E, "deployment::configuration") /=
                No_Name
            then
617
               Get_Name_String
618
                 (Get_String_Property (E, "deployment::configuration"));
619
               Conf_Str := Name_Find;
620
621
            end if;

622
623
624
625
626
627
628
629
630
631
632
633
            --  Now, we look at the amount of buses connected to
            --  the device and which bus is connected to which
            --  device. As a result, the arrays
            --  __po_hi_devices_nb_accessed_bus and
            --  __po_hi_devices_accessed_bus will be created.

            Nb_Connected_Buses := 0;

            if not AAU.Is_Empty (Features (E)) then
               F := First_Node (Features (E));

               while Present (F) loop
634
635
636
637
                  if Kind (F) = K_Subcomponent_Access_Instance
                    and then AAU.Is_Bus (Corresponding_Instance (F))
                    and then First_Node (Sources (F)) /= No_Node
                  then
638
639
640
641

                     Accessed_Bus := Item (First_Node (Sources (F)));

                     Append_Node_To_List
642
643
644
645
                       (Make_Defining_Identifier
                          (Map_C_Enumerator_Name
                             (Corresponding_Instance (Accessed_Bus))),
                        CTN.Values (Accessed_Buses));
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668

                     Nb_Connected_Buses := Nb_Connected_Buses + 1;
                  end if;
                  F := Next_Node (F);
               end loop;
            end if;

            --  If the device accesses at least one bus, we declare
            --  an array in ALL processed that detail the buses
            --  it accesses. Then, this array is contained
            --  in the global array __po_hi_devices_accessed_buses.
            --  For this reason, we are forced to process again
            --  all processes to add the new array to all processes.

            if not Is_Empty (CTN.Values (Accessed_Buses)) then
               Set_Deployment_Source;

               --  Here, we browse all the process components
               --  of the root system.
               Q := First_Node (Subcomponents (The_System));

               while Present (Q) loop
                  if AAU.Is_Process (Corresponding_Instance (Q)) then
669
670
671
672
673
                     U :=
                       CTN.Distributed_Application_Unit
                         (CTN.Naming_Node
                            (Backend_Node
                               (Identifier (Corresponding_Instance (Q)))));
674
675
676
677
678
679
680
681
682
683
684
                     P := CTN.Entity (U);

                     Push_Entity (P);
                     Push_Entity (U);

                     Set_Deployment_Source;

                     --  Here, we build the array that details the buses
                     --  accessed by the device and add it to each
                     --  deployment.c file of ALL processes.

685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
                     N :=
                       Make_Expression
                         (Left_Expr =>
                            Make_Variable_Declaration
                              (Defining_Identifier =>
                                 Make_Array_Declaration
                                   (Defining_Identifier =>
                                      Make_Defining_Identifier
                                        (Map_Devices_Buses_Array_Name (E)),
                                    Array_Size =>
                                      Make_Literal
                                        (CV.New_Int_Value
                                           (Nb_Connected_Buses,
                                            1,
                                            10))),
                               Used_Type => RE (RE_Bus_Id)),
                          Operator   => Op_Equal,
                          Right_Expr => Accessed_Buses);

                     Append_Node_To_List (N, CTN.Declarations (Current_File));
705
706
707
708
709
710
711
712
713
714
715
716
717
718
                     Pop_Entity;
                     Pop_Entity;
                     Set_Deployment_Header;
                  end if;
                  Q := Next_Node (Q);
               end loop;

               Set_Deployment_Header;

               --  Finally, here, we reference the array name that
               --  contains connected buses to the main array
               --  __po_hi_devices_accessed_buses.

               Append_Node_To_List
719
                 (Make_Defining_Identifier (Map_Devices_Buses_Array_Name (E)),
720
721
722
723
724
725
                  CTN.Values (Devices_Buses_Array));
            else
               --  If no bus is connected, we just specify
               --  a null pointer, meaning that no bus is
               --  connected to this device.
               Append_Node_To_List
726
727
728
                 (Make_Defining_Identifier
                    (CONST (C_Null),
                     C_Conversion => False),
729
730
                  CTN.Values (Devices_Buses_Array));
            end if;
731

732
            Append_Node_To_List
733
              (Make_Literal (CV.New_Int_Value (Nb_Connected_Buses, 1, 10)),
734
               CTN.Values (Devices_Nb_Buses_Array));
735
736
737

            if Is_Defined_Property (E, "source_text") then
               Append_Node_To_List
738
739
                 (Make_Type_Conversion
                    (Make_Pointer_Type (RE (RE_Uint32_T)),
740
                     Make_Variable_Address
741
742
                       (Make_Defining_Identifier
                          (Map_Device_Confvar_Name (E)))),
743
744
745
746
747
                  CTN.Values (Devices_Confvars));
               Set_Deployment_Source;

               Device_Implementation := Get_Implementation (Current_Device);

748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
               if Is_Defined_Property
                   (Device_Implementation,
                    "deployment::configuration_type")
               then
                  Configuration_Data :=
                    Get_Classifier_Property
                      (Device_Implementation,
                       "deployment::configuration_type");
                  if Configuration_Data /= No_Node
                    and then Is_Defined_Property
                      (Configuration_Data,
                       "type_source_name")
                  then
                     --  Here, we browse all the process components
                     --  of the root system to declare external
                     --  variable that contain the configuration
                     --  of the device.

                     Q := First_Node (Subcomponents (The_System));

                     while Present (Q) loop
                        if AAU.Is_Process (Corresponding_Instance (Q)) then
                           U :=
                             CTN.Distributed_Application_Unit
                               (CTN.Naming_Node
                                  (Backend_Node
                                     (Identifier
                                        (Corresponding_Instance (Q)))));
                           P := CTN.Entity (U);

                           Push_Entity (P);
                           Push_Entity (U);

                           Set_Deployment_Source;

                           N :=
                             Make_Extern_Entity_Declaration
                               (Make_Variable_Declaration
                                  (Defining_Identifier =>
                                     Make_Defining_Identifier
                                       (Map_Device_Confvar_Name (E)),
                                   Used_Type =>
                                     Make_Pointer_Type
                                       (Make_Defining_Identifier
                                          (Map_ASN_Type
793
794
                                             (Get_String_Property
                                                (Configuration_Data,
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
                                                 "type_source_name"))))));
                           Append_Node_To_List
                             (N,
                              CTN.Declarations (Current_File));
                           declare
                              ST : constant Name_Array :=
                                Get_Source_Text (Configuration_Data);
                              Include_Name : Name_Id;
                           begin
                              Set_Deployment_Header;

                              if ST'Length = 0 then
                                 Display_Error
                                   ("Source_Text property of " &
                                    "configuration data" &
                                    " must have at least one element " &
                                    "(the header file).",
                                    Fatal => True);
                              end if;

                              Include_Name := No_Name;

                              for Index in ST'Range loop
                                 Get_Name_String (ST (Index));
                                 if Name_Buffer (Name_Len - 1 .. Name_Len) =
                                   ".h"
                                 then
                                    Include_Name :=
                                      Get_String_Name
                                        (Name_Buffer (1 .. Name_Len - 2));
825
                                 end if;
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
                              end loop;

                              if Include_Name = No_Name then
                                 Display_Error
                                   ("Cannot find header file " &
                                    "that implements the data type",
                                    Fatal => True);
                              end if;

                              Add_Include
                                (Make_Include_Clause
                                   (Make_Defining_Identifier (Include_Name)));
                           end;
                           Pop_Entity;
                           Pop_Entity;
                        end if;
                        Q := Next_Node (Q);
                     end loop;
844
845
                  end if;
               end if;
846
               Append_Node_To_List
847
848
849
                 (Make_Literal
                    (CV.New_Pointed_Char_Value (Get_String_Name ("noaddr"))),
                  CTN.Values (Devices_Array));
850
851
852
853

               Set_Deployment_Header;
            else
               Append_Node_To_List
854
                 (Make_Literal (CV.New_Int_Value (0, 0, 10)),
855
                  CTN.Values (Devices_Confvars));
856
857
858

               if Conf_Str /= No_Name then
                  Append_Node_To_List
859
860
                    (Make_Literal (CV.New_Pointed_Char_Value (Conf_Str)),
                     CTN.Values (Devices_Array));
861
862
               else
                  Append_Node_To_List
863
864
865
866
                    (Make_Literal
                       (CV.New_Pointed_Char_Value
                          (Get_String_Name ("noaddr"))),
                     CTN.Values (Devices_Array));
867
               end if;
868
            end if;
869
         end if;
870
871
872
         Current_Device := No_Node;
      end Visit_Device_Instance;

873
874
875
876
877
      ----------------------------
      -- Visit_Process_Instance --
      ----------------------------

      procedure Visit_Process_Instance (E : Node_Id) is
878
879
880
881
882
883
884
         U : constant Node_Id :=
           CTN.Distributed_Application_Unit
             (CTN.Naming_Node (Backend_Node (Identifier (E))));
         P        : constant Node_Id := CTN.Entity (U);
         S        : constant Node_Id := Parent_Subcomponent (E);
         Root_Sys : constant Node_Id :=
           Parent_Component (Parent_Subcomponent (E));
885
886
887
888
889
890
891
892
893
         Driver_Name : Name_Id;
         Q           : Node_Id;
         N           : Node_Id;
         C           : Node_Id;
         F           : Node_Id;
         Data        : Node_Id;
         Src         : Node_Id;
         Dst         : Node_Id;
         Parent      : Node_Id;
894
895
         The_System  : constant Node_Id :=
           Parent_Component (Parent_Subcomponent (E));
896
         Device_Implementation : Node_Id;
897
         Node_Name   : Name_Id;
898

899
900
901
      begin
         pragma Assert (AAU.Is_System (Root_Sys));

902
903
         Nb_Nodes := 0;

904
905
906
907
         Set_Added (E, E);

         Current_Process_Instance := E;

908
909
         Tasks_Enumerator_List := New_List (CTN.K_Enumeration_Literals);
         Node_Enumerator_List  := New_List (CTN.K_Enumeration_Literals);
910

911
912
         Nb_Ports_List := New_List (CTN.K_List_Id);

913
914
915
916
         Push_Entity (P);
         Push_Entity (U);
         Set_Deployment_Header;

917
918
         Node_Identifier     := 0;
         Task_Identifier     := 0;
919
         Tasks_Stack         := 0;
920
921
         Nb_Protected        := 0;
         Nb_Ports_In_Process := 0;
922

923
924
         --  Define the name of the current node

925
926
927
928
929
930
931
         N :=
           Make_Define_Statement
             (Defining_Identifier => (RE (RE_My_Node)),
              Value               =>
                Make_Defining_Identifier
                  (Map_C_Enumerator_Name (Parent_Subcomponent (E))));
         Append_Node_To_List (N, CTN.Declarations (Current_File));
932

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
         Node_Name :=
           Map_C_Enumerator_Name (Parent_Subcomponent (E));
         Set_Str_To_Name_Buffer ("");
         Get_Name_String (Token_Image (Tok_Quote));
         Get_Name_String_And_Append (Node_Name);
         Get_Name_String_And_Append (Token_Image (Tok_Quote));

         Node_Name := Name_Find;

         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_My_Node_Name),
              Value               =>
                Make_Defining_Identifier (Node_Name));
         Append_Node_To_List (N, CTN.Declarations (Current_File));

949
950
951
952
953
954
955
         --  Visit all devices attached to the parent system that
         --  share the same processor as process E.

         if not AAU.Is_Empty (Subcomponents (The_System)) then
            C := First_Node (Subcomponents (The_System));
            while Present (C) loop
               if AAU.Is_Device (Corresponding_Instance (C))
956
957
958
                 and then
                   Get_Bound_Processor (Corresponding_Instance (C)) =
                   Get_Bound_Processor (E)
959
960
961
962
963
               then
                  --  Build the enumerator corresponding to the device
                  --  Note: we reuse the process name XXX

                  Visit_Device_Instance (Corresponding_Instance (C));
964
965
966

                  Current_Device := Corresponding_Instance (C);

967
                  Device_Implementation := Get_Implementation (Current_Device);
968
969
970

                  if Device_Implementation /= No_Node then
                     if not AAU.Is_Empty
971
972
973
974
                         (AAN.Subcomponents (Device_Implementation))
                     then
                        N :=
                          First_Node (Subcomponents (Device_Implementation));
975
976
                        while Present (N) loop
                           Visit_Component_Instance
977
                             (Corresponding_Instance (N));
978
979
980
981
982
983
984
                           N := Next_Node (N);
                        end loop;
                     end if;
                  end if;

                  Current_Device := No_Node;

985
986
987
988
               end if;
               C := Next_Node (C);
            end loop;
         end if;
989
990
991
992
993
994
995
996

         --  Visit all the subcomponents of the process

         if not AAU.Is_Empty (Subcomponents (E)) then
            C := First_Node (Subcomponents (E));

            while Present (C) loop
               if AAU.Is_Data (Corresponding_Instance (C)) then
997
998
                  N := Make_Literal (New_Int_Value (Nb_Protected, 1, 10));
                  Bind_AADL_To_Default_Value (Identifier (C), N);
999

1000
                  Nb_Protected := Nb_Protected + 1;
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
               else
                  --  Visit the component instance corresponding to the
                  --  subcomponent S.
                  Visit (Corresponding_Instance (C));
               end if;

               C := Next_Node (C);
            end loop;
         end if;

         --  For each of the processes P connected to E, (1) we add an
         --  enumerator corresponding to P and (2) for each one of the
         --  threads of P, we add an enumerator.

         if not AAU.Is_Empty (Features (E)) then
            F := First_Node (Features (E));

            while Present (F) loop
               --  The sources of F

               if not AAU.Is_Empty (Sources (F)) then
                  Src := First_Node (Sources (F));

                  while Present (Src) loop

                     Parent := Parent_Component (Item (Src));

1028
1029
1030
1031
                     if AAU.Is_Process (Parent) and then Parent /= E then
                        if Get_Provided_Virtual_Bus_Class (Extra_Item (Src)) /=
                          No_Node
                        then
1032
                           Visit
1033
1034
                             (Get_Provided_Virtual_Bus_Class
                                (Extra_Item (Src)));
1035
1036
                        end if;

1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
                        Set_Added (Parent, E);
                        --  Traverse all the subcomponents of Parent

                        if not AAU.Is_Empty (Subcomponents (Parent)) then
                           C := First_Node (Subcomponents (Parent));

                           while Present (C) loop
                              Visit (Corresponding_Instance (C));

                              C := Next_Node (C);
                           end loop;
                        end if;

1050
1051
                     --  Mark P as being Added
                     elsif AAU.Is_Device (Parent) and then Parent /= E then
1052
1053
1054
1055
1056
1057
1058
1059
1060
                        Driver_Name := Get_Driver_Name (Parent);

                        if Driver_Name /= No_Name then
                           Set_Str_To_Name_Buffer ("__PO_HI_NEED_DRIVER_");
                           Get_Name_String_And_Append (Driver_Name);

                           Driver_Name := Name_Find;
                           Driver_Name := To_Upper (Driver_Name);

1061
                           Add_Define_Deployment
1062
1063
1064
                             (Make_Defining_Identifier
                                (Driver_Name,
                                 C_Conversion => False));
1065
                        end if;
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
                     end if;

                     Src := Next_Node (Src);
                  end loop;
               end if;

               --  The destinations of F

               if not AAU.Is_Empty (Destinations (F)) then
                  Dst := First_Node (Destinations (F));

                  while Present (Dst) loop
                     Parent := Parent_Component (Item (Dst));

1080
1081
1082
1083
                     if AAU.Is_Process (Parent) and then Parent /= E then
                        if Get_Provided_Virtual_Bus_Class (Extra_Item (Dst)) /=
                          No_Node
                        then
1084
                           Visit
1085
1086
                             (Get_Provided_Virtual_Bus_Class
                                (Extra_Item (Dst)));
1087
1088
                        end if;

1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
                        Set_Added (Parent, E);

                        if not AAU.Is_Empty (Subcomponents (Parent)) then
                           C := First_Node (Subcomponents (Parent));

                           while Present (C) loop
                              Visit (Corresponding_Instance (C));

                              C := Next_Node (C);
                           end loop;
                        end if;
1100
                     elsif AAU.Is_Device (Parent) and then Parent /= E then
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
                        Driver_Name := Get_Driver_Name (Parent);

                        if Driver_Name /= No_Name then
                           Set_Str_To_Name_Buffer ("__PO_HI_NEED_DRIVER_");
                           Get_Name_String_And_Append (Driver_Name);

                           Driver_Name := Name_Find;
                           Driver_Name := To_Upper (Driver_Name);

                           Append_Node_To_List
1111
1112
1113
1114
                             (Make_Define_Statement
                                (Defining_Identifier =>
                                   (Make_Defining_Identifier
                                      (Driver_Name,
1115
1116
                                       C_Conversion => False)),
                                 Value =>
1117
1118
                                   (Make_Literal
                                      (CV.New_Int_Value (1, 1, 10)))),
1119
1120
                              CTN.Declarations (Current_File));
                        end if;
1121
1122
1123
1124
1125
1126
1127
                     end if;

                     Dst := Next_Node (Dst);
                  end loop;
               end if;

               if Is_Data (F) then
1128
1129
1130
                  if Get_Source_Language (Corresponding_Instance (F)) =
                    Language_Simulink
                  then
1131
1132
1133
                     Data := Corresponding_Instance (F);

                     if Get_Source_Name (Data) /= No_Name then
1134
1135
1136
1137
1138
1139
                        N :=
                          Make_Define_Statement
                            (Defining_Identifier => (RE (RE_Simulink_Node)),
                             Value               =>
                               Make_Defining_Identifier
                                 (Get_Source_Name (Data)));
1140
                        Append_Node_To_List
1141
1142
1143
1144
1145
1146
1147
1148
                          (N,
                           CTN.Declarations (Current_File));

                        N :=
                          Make_Define_Statement
                            (Defining_Identifier =>
                               (RE (RE_Simulink_Init_Func)),
                             Value => Map_Simulink_Init_Func (Data));
1149
                        Append_Node_To_List
1150
1151
1152
1153
1154
1155
1156
1157
                          (N,
                           CTN.Declarations (Current_File));

                        N :=
                          Make_Define_Statement
                            (Defining_Identifier =>
                               (RE (RE_Simulink_Model_Type)),
                             Value => Map_Simulink_Model_Type (Data));
1158
                        Append_Node_To_List
1159
1160
                          (N,
                           CTN.Declarations (Current_File));
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
                     end if;
                  end if;

               end if;

               F := Next_Node (F);
            end loop;
         end if;

         Q := First_Node (Subcomponents (Root_Sys));

         while Present (Q) loop
            if AAU.Is_Process (Corresponding_Instance (Q)) then
               if Is_Added (Corresponding_Instance (Q), E) then
1175
1176
1177
1178
1179
1180
1181
                  N :=
                    Make_Expression
                      (Make_Defining_Identifier (Map_C_Enumerator_Name (Q)),
                       Op_Equal,
                       Make_Literal
                         (CV.New_Int_Value (Node_Identifier, 0, 10)));
                  Append_Node_To_List (N, Node_Enumerator_List);
1182
                  Node_Identifier := Node_Identifier + 1;
1183
                  Nb_Nodes        := Nb_Nodes + 1;
1184
               else
1185
1186
1187
1188
1189
1190
                  N :=
                    Make_Expression
                      (Make_Defining_Identifier (Map_C_Enumerator_Name (Q)),
                       Op_Equal,
                       RE (RE_Unused_Node));
                  Append_Node_To_List (N, Node_Enumerator_List);
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
               end if;
            end if;

            Q := Next_Node (Q);
         end loop;

         --  Create the node enumeration type declaration. Note that
         --  the type creation is possible even the enumeration list
         --  is incomplete. We can do this in the first traversal
         --  since we are sure that the enumerator list is not empty.

1202
1203
1204
1205
         N :=
           Message_Comment
             ("For each node in the distributed" &
              " application add an enumerator");
1206
1207
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1208
1209
1210
1211
         N :=
           Make_Full_Type_Declaration
             (Defining_Identifier => RE (RE_Node_T),
              Type_Definition => Make_Enum_Aggregate (Node_Enumerator_List));
1212
1213
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1214
1215
1216
1217
1218
         --  Make sure the __po_hi_protocol_t enum type is defined
         --  with at least the invalid_protocol value.

         if not Invalid_Protocol_Added then
            Set_Str_To_Name_Buffer ("invalid_protocol");
1219
1220
1221
1222
1223
1224
            N :=
              Make_Expression
                (Make_Defining_Identifier (Name_Find),
                 Op_Equal,
                 (Make_Literal (CV.New_Int_Value (1, -1, 10))));
            Append_Node_To_List (N, Protocol_List);
1225
1226
1227
1228

            Invalid_Protocol_Added := True;
         end if;

1229
1230
1231
1232
         N :=
           Make_Full_Type_Declaration
             (Defining_Identifier => RE (RE_Protocol_T),
              Type_Definition     => Make_Enum_Aggregate (Protocol_List));
1233
1234
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1235
1236
1237
1238
1239
1240
         --  Create the thread enumeration type declaration. Note that
         --  the type creation is possible even the enumeration list
         --  is incomplete. This type may not be generated in case the
         --  application is local.

         if not Is_Empty (Entity_Enumerator_List) then
1241
1242
1243
1244
1245
            N :=
              Message_Comment
                ("For each thread in the distributed" &
                 " application nodes, add an" &
                 " enumerator");
1246
1247
1248
1249
            Append_Node_To_List (N, CTN.Declarations (Current_File));

            if not Invalid_Entity_Added then
               Set_Str_To_Name_Buffer ("invalid_entity");
1250
1251
1252
1253
1254
1255
               N :=
                 Make_Expression
                   (Make_Defining_Identifier (Name_Find),
                    Op_Equal,
                    (Make_Literal (CV.New_Int_Value (1, -1, 10))));
               Append_Node_To_List (N, Entity_Enumerator_List);
1256
1257
1258
               Invalid_Entity_Added := True;
            end if;

1259
1260
1261
1262
1263
            N :=
              Make_Full_Type_Declaration
                (Defining_Identifier => RE (RE_Entity_T),
                 Type_Definition     =>
                   Make_Enum_Aggregate (Entity_Enumerator_List));
1264
1265
1266
1267
            Append_Node_To_List (N, CTN.Declarations (Current_File));
         end if;

         Set_Str_To_Name_Buffer ("invalid_task_id");
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
         N :=
           Make_Expression
             (Make_Defining_Identifier (Name_Find),
              Op_Equal,
              (Make_Literal (CV.New_Int_Value (1, -1, 10))));
         Append_Node_To_List (N, Tasks_Enumerator_List);

         N :=
           Make_Full_Type_Declaration
             (Defining_Identifier => RE (RE_Task_Id),
              Type_Definition => Make_Enum_Aggregate (Tasks_Enumerator_List));
1279
1280
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1281
1282
1283
1284
1285
         N :=
           Make_Full_Type_Declaration
             (Defining_Identifier => RE (RE_Device_Id),
              Type_Definition     =>
                Make_Enum_Aggregate (Devices_Enumerator_List));
1286
1287
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1288
1289
1290
1291
         N :=
           Make_Full_Type_Declaration
             (Defining_Identifier => RE (RE_Bus_Id),
              Type_Definition => Make_Enum_Aggregate (Buses_Enumerator_List));
1292
1293
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1294
1295
1296
1297
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Tasks),
              Value => Make_Literal (New_Int_Value (Task_Identifier, 1, 10)));
1298
1299
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1300
1301
1302
1303
1304
1305
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Tasks_Stack),
              Value => Make_Literal (New_Int_Value (Tasks_Stack, 1, 10)));
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1306
1307
1308
         --  Add an enumerator corresponding to an INVALID server
         --  entity to the entity list.

1309
1310
1311
1312
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Protected),
              Value => Make_Literal (New_Int_Value (Nb_Protected, 1, 10)));
1313
1314
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1315
1316
1317
1318
1319
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Nodes),
              Value => Make_Literal (New_Int_Value (Nb_Nodes, 1, 10)));
         Append_Node_To_List (N, CTN.Declarations (Current_File));
1320

1321
1322
1323
1324
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Entities),
              Value               => Nb_Entities_Node);
1325
1326
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
         --  If there are ports in the local process, we generate a
         --  macro indicating the total number of ports in the
         --  application, otherwise we generate a value of 0 to avoid
         --  dragging the whole transport logic. This may happen in
         --  corner cases when using external API for communication.

         if Nb_Ports_In_Process > 0 then
            N :=
              Make_Define_Statement
              (Defining_Identifier => RE (RE_Nb_Ports),
               Value               => Total_Ports_Node);
            Append_Node_To_List (N, CTN.Declarations (Current_File));
         else
            N :=
              Make_Define_Statement
              (Defining_Identifier => RE (RE_Nb_Ports),
               Value               => Make_Literal (New_Int_Value (0, 1, 10)));
            Append_Node_To_List (N, CTN.Declarations (Current_File));
         end if;
1346
1347
1348
1349

         if not Is_Empty (Global_Port_List) then
            if not Invalid_Global_Port_Added then
               Set_Str_To_Name_Buffer ("invalid_port_t");
1350
1351
1352
1353
1354
1355
               N :=
                 Make_Expression
                   (Make_Defining_Identifier (Name_Find),
                    Op_Equal,
                    (Make_Literal (CV.New_Int_Value (1, -1, 10))));
               Append_Node_To_List (N, Global_Port_List);
1356
1357
1358
1359

               Invalid_Global_Port_Added := True;
            end if;

1360
1361
1362
1363
            N :=
              Make_Full_Type_Declaration
                (Defining_Identifier => RE (RE_Port_T),
                 Type_Definition => Make_Enum_Aggregate (Global_Port_List));
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
            Append_Node_To_List (N, CTN.Declarations (Current_File));
         end if;

         if not Is_Empty (CTN.Values (Global_Port_To_Local)) then
            Bind_AADL_To_Local_Port (Identifier (S), Global_Port_To_Local);
         end if;

         if not Is_Empty (CTN.Values (Global_Port_To_Entity)) then
            Bind_AADL_To_Global_Port (Identifier (S), Global_Port_To_Entity);
         end if;

1375
1376
1377
1378
1379
1380
         if not Is_Empty (CTN.Values (Global_Port_Names)) then
            Bind_AADL_To_Global_Names (Identifier (S), Global_Port_Names);
         end if;

         if not Is_Empty (CTN.Values (Global_Port_Model_Names)) then
            Bind_AADL_To_Global_Model_Names
1381
1382
              (Identifier (S),
               Global_Port_Model_Names);
1383
1384
         end if;

1385
1386
         if not Invalid_Local_Port_Added then
            Set_Str_To_Name_Buffer ("invalid_local_port_t");
1387
            N :=
1388
1389
1390
1391
1392
1393
1394
              Make_Expression
              (Make_Defining_Identifier (Name_Find),
               Op_Equal,
               (Make_Literal (CV.New_Int_Value (1, -1, 10))));
            Append_Node_To_List (N, Local_Port_List);

            Invalid_Local_Port_Added := True;
1395
1396
         end if;

1397
1398
1399
1400
1401
1402
         N :=
           Make_Full_Type_Declaration
           (Defining_Identifier => RE (RE_Local_Port_T),
            Type_Definition     => Make_Enum_Aggregate (Local_Port_List));
         Append_Node_To_List (N, CTN.Declarations (Current_File));

1403
1404
1405
1406
1407
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Devices),
              Value               => Nb_Devices_Node);
         Append_Node_To_List (N, CTN.Declarations (Current_File));
1408

1409
1410
1411
1412
1413
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Buses),
              Value               => Nb_Buses_Node);
         Append_Node_To_List (N, CTN.Declarations (Current_File));
1414

1415
1416
1417
1418
1419
         N :=
           Make_Define_Statement
             (Defining_Identifier => RE (RE_Nb_Protocols),
              Value               => Nb_Protocols_Node);
         Append_Node_To_List (N, CTN.Declarations (Current_File));
1420

1421
1422
1423
         --  Define the PORT_TYPE_CONTENT macro for the monitoring of entities

         declare
yoogx's avatar
yoogx committed
1424
            K                  : Node_Id;
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
            Nb_Ports_List_Name : Name_Id := No_Name;
         begin
            K := CTN.First_Node (Nb_Ports_List);

            if Present (K) then
               Get_Name_String (CTN.Name (K));
               K := CTN.Next_Node (K);
               while Present (K) loop
                  Add_Str_To_Name_Buffer
                    (", " & Get_Name_String (CTN.Name (K)));
                  K := CTN.Next_Node (K);
               end loop;
            end if;
            Nb_Ports_List_Name := Name_Find;

            N :=
              Make_Define_Statement
yoogx's avatar
yoogx committed
1442
1443
                (Defining_Identifier => RE (RE_Port_Type_Content),
                 Value => Make_Defining_Identifier (Nb_Ports_List_Name));
1444
1445
1446
            Append_Node_To_List (N, CTN.Declarations (Current_File));
         end;

1447
1448
         Current_Process_Instance := No_Node;

1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
         Pop_Entity; -- U
         Pop_Entity; -- P
      end Visit_Process_Instance;

      ---------------------------
      -- Visit_System_Instance --
      ---------------------------

      procedure Visit_System_Instance (E : Node_Id) is
         S : Node_Id;
         N : Node_Id;
      begin
         Push_Entity (C_Root);

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
         Global_Ports           := AAU.New_List (K_List_Id, No_Location);
         Devices_Array          := Make_Array_Values;
         Devices_Nb_Buses_Array := Make_Array_Values;
         Devices_Confvars       := Make_Array_Values;
         Protocols_Conf         := Make_Array_Values;
         Devices_Buses_Array    := Make_Array_Values;
         Port_To_Devices        := Make_Array_Values;
         Devices_To_Nodes       := Make_Array_Values;

         Devices_Enumerator_List := New_List (CTN.K_Enumeration_Literals);
         Buses_Enumerator_List   := New_List (CTN.K_Enumeration_Literals);
         Global_Port_List        := New_List (CTN.K_Enumeration_Literals);
         Protocol_List           := New_List (CTN.K_Enumeration_Literals);
         Global_Port_Names       := Make_Array_Values;
         Global_Port_Model_Names := Make_Array_Values;
         Global_Port_Kind        := Make_Array_Values;
         Global_Port_Queue_Size  := Make_Array_Values;
         Global_Port_Data_Size   := Make_Array_Values;
         Global_Port_To_Entity   := Make_Array_Values;
         Global_Port_To_Local    := Make_Array_Values;
         Entity_Enumerator_List  := New_List (CTN.K_Enumeration_Literals);
         Local_Port_Values       := Make_Array_Values;
         Local_Port_List         := New_List (CTN.K_Enumeration_Literals);
         Total_Ports_Node        := Make_Literal (New_Int_Value (0, 1, 10));
         Nb_Entities_Node        := Make_Literal (New_Int_Value (0, 1, 10));
         Nb_Devices_Node         := Make_Literal (New_Int_Value (0, 1, 10));
         Nb_Buses_Node           := Make_Literal (New_Int_Value (0, 1, 10));
         Nb_Protocols_Node       := Make_Literal (New_Int_Value (0, 1, 10));
         Entity_Array            := Make_Array_Values;
         Device_Id               := 0;
1493