taste-concurrency_view.adb 27.3 KB
Newer Older
1
--  *************************** kazoo ***********************  --
Maxime Perrotin's avatar
Maxime Perrotin committed
2
--  (c) 2019 European Space Agency - maxime.perrotin@esa.int
3
4
--  LGPL license, see LICENSE file

Maxime Perrotin's avatar
Maxime Perrotin committed
5
6
with Ada.Directories,
     Ada.IO_Exceptions,
Maxime Perrotin's avatar
Maxime Perrotin committed
7
8
     Ada.Exceptions,
     Ada.Characters.Latin_1;
Maxime Perrotin's avatar
Maxime Perrotin committed
9
10
11

use Ada.Directories;

12
13
package body TASTE.Concurrency_View is

Maxime Perrotin's avatar
Maxime Perrotin committed
14
15
   Newline : Character renames Ada.Characters.Latin_1.LF;

16
   procedure Debug_Dump (CV : Taste_Concurrency_View; Output : File_Type) is
Maxime Perrotin's avatar
Maxime Perrotin committed
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
      procedure Dump_Partition (Partition : CV_Partition) is
      begin
         for Block of Partition.Blocks loop
            Put_Line (Output, "Protected Block : " & To_String (Block.Name));
            for Provided of Block.Provided loop
               Put_Line (Output, " |_ PI : " & To_String (Provided.Name));
            end loop;
            for Required of Block.Required loop
               Put_Line (Output, " |_ RI : " & To_String (Required.Name));
            end loop;
            for Thread of Block.Calling_Threads loop
               Put_Line (Output, " |_ Calling_Thread : " & Thread);
            end loop;
            if Block.Node.Has_Value then
               Put_Line (Output, " |_ Node : "
                         & To_String (Block.Node.Unsafe_Just.Name));
               declare
                  P : constant Taste_Partition :=
                    Block.Node.Unsafe_Just.Find_Partition
                      (To_String (Block.Name)).Unsafe_Just;
               begin
                  Put_Line (Output, " |_ Partition : " & To_String (P.Name));
                  Put_Line (Output, "   |_ Coverage       : "
                            & P.Coverage'Img);
                  Put_Line (Output, "   |_ Package        : "
                            & To_String (P.Package_Name));
                  Put_Line (Output, "   |_ CPU Name       : "
                            & To_String (P.CPU_Name));
                  Put_Line (Output, "   |_ CPU Platform   : "
                            & P.CPU_Platform'Img);
                  Put_Line (Output, "   |_ CPU Classifier : "
                            & To_String (P.CPU_Classifier));
               end;
            end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
51
         end loop;
52

Maxime Perrotin's avatar
Maxime Perrotin committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
         for Thread of Partition.Threads loop
            Put_Line (Output, "Thread : " & To_String (Thread.Name));
            Put_Line (Output, " |_ Port : "
                      & To_String (Thread.Entry_Port_Name));
            Put_Line (Output, " |_ Protected Block : "
                      & To_String (Thread.Protected_Block_Name));
            Put_Line (Output, " |_ Node : "
                      & To_String (Thread.Node.Value_Or
                        (Taste_Node'(Name   => US ("(none)"),
                                     others => <>)).Name));
            for Out_Port of Thread.Output_Ports loop
               Put_Line (Output, " |_ Output port remote thread : "
                         & To_String (Out_Port.Remote_Thread));
               Put_Line (Output, " |_ Output port remote PI : "
                         & To_String (Out_Port.Remote_PI));
            end loop;
         end loop;
      end Dump_Partition;
   begin
      for Node of CV.Nodes loop
         for Partition of Node.Partitions loop
            Dump_Partition (Partition);
Maxime Perrotin's avatar
Maxime Perrotin committed
75
         end loop;
76
77
78
      end loop;
   end Debug_Dump;

79
   --  This function translates a protected block into a template
80
   function Prepare_Template (B : Protected_Block) return Block_As_Template is
81
      Calling_Threads : Tag;
82
      Result          : Block_As_Template;
83
84
85
86
87
   begin
      for Thread of B.Calling_Threads loop
         Calling_Threads := Calling_Threads & Thread;
      end loop;

88
89
90
91
      for PI of B.Provided loop
         declare
            Basic : constant Translate_Set := PI.PI.To_Template
              & Assoc ("Protected_Block_Name", To_String (PI.Name))
92
93
              & Assoc ("Caller_Is_Local", PI.Local_Caller)
              & Assoc ("Calling_Threads", Calling_Threads);
94
         begin
Maxime Perrotin's avatar
Maxime Perrotin committed
95
96
97
98
99
            if PI.PI.RCM = Protected_Operation then
               Result.Protected_Provided.Append (Basic);
            else
               Result.Unprotected_Provided.Append (Basic);
            end if;
100
101
102
103
         end;
      end loop;

      for RI of B.Required loop
104
105
         Result.Required.Append (RI.To_Template
                                 & Assoc ("Calling_Threads", Calling_Threads));
106
107
108
      end loop;

      Result.Header := +Assoc  ("Name",            To_String (B.Name))
109
                       & Assoc ("Language",        B.Language)
110
111
112
113
                       & Assoc ("Calling_Threads", Calling_Threads)
                       & Assoc ("Node_Name",       To_String (B.Node.Value_Or
                         (Taste_Node'(Name => US (""), others => <>)).Name));
      return Result;
114
   end Prepare_Template;
115
116

   --  This function translates a thread definition into a template
Maxime Perrotin's avatar
Maxime Perrotin committed
117
   function To_Template (T : AADL_Thread) return Translate_Set is
118
      Remote_Thread    : Vector_Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
119
      RI_Port_Name     : Vector_Tag;  --  Name of the local RI (= port name)
120
121
122
      Remote_PI        : Vector_Tag;  --  Name of the remote PI
      Remote_PI_Sort   : Vector_Tag;  --  ASN.1 type of the parameter
      Remote_PI_Module : Vector_Tag;  --  ASN.1 module containing the type
123
124
   begin
      for Out_Port of T.Output_Ports loop
Maxime Perrotin's avatar
Maxime Perrotin committed
125
         RI_Port_Name  := RI_Port_Name & Out_Port.Name;
126
127
         Remote_Thread := Remote_Thread & To_String (Out_Port.Remote_Thread);
         Remote_PI     := Remote_PI     & To_String (Out_Port.Remote_PI);
128
129
130
131
132
133
134
135
136
137
         --  Set the Asn.1 module and type of the optional RI parameter
         if Out_Port.RI.Params.Length > 0 then
            Remote_PI_Sort := Remote_PI_Sort
              & Out_Port.RI.Params.First_Element.Sort;
            Remote_PI_Module := Remote_PI_Module
              & Out_Port.RI.Params.First_Element.ASN1_Module;
         else
            Remote_PI_Sort   := Remote_PI_Sort   & "";
            Remote_PI_Module := Remote_PI_Module & "";
         end if;
138
139
140
      end loop;

      return Result : constant Translate_Set :=
141
142
143
144
        T.PI.To_Template   --  Template of the PI used to create the thread
        & Assoc ("Thread_Name",       To_String (T.Name))
        & Assoc ("Entry_Port_Name",   To_String (T.Entry_Port_Name))
        & Assoc ("RCM",               To_String (T.RCM))
Maxime Perrotin's avatar
Maxime Perrotin committed
145
        & Assoc ("Need_Mutex",        T.Need_Mutex)
146
147
148
149
        & Assoc ("Pro_Block_Name",    To_String (T.Protected_Block_Name))
        & Assoc ("Node_Name",         To_String (T.Node.Value_Or
          (Taste_Node'(Name => US (""), others => <>)).Name))
        & Assoc ("Remote_Threads",    Remote_Thread)
Maxime Perrotin's avatar
Maxime Perrotin committed
150
        & Assoc ("RI_Port_Names",     RI_Port_Name)
151
152
153
        & Assoc ("Remote_PIs",        Remote_PI)
        & Assoc ("Remote_PI_Sorts",   Remote_PI_Sort)
        & Assoc ("Remote_PI_Modules", Remote_PI_Module);
Maxime Perrotin's avatar
Maxime Perrotin committed
154
   end To_Template;
155

Maxime Perrotin's avatar
Maxime Perrotin committed
156
   --  Generate the code by iterating over template folders
157
   procedure Generate_Code (CV : Taste_Concurrency_View)
158
   is
Maxime Perrotin's avatar
Maxime Perrotin committed
159
      Prefix   : constant String := CV.Base_Template_Path.Element
Maxime Perrotin's avatar
Maxime Perrotin committed
160
161
162
163
164
165
        & "templates/concurrency_view";
      --  To iterate over template folders
      ST       : Search_Type;
      Current  : Directory_Entry_Type;
      Filter   : constant Filter_Type := (Directory => True,
                                          others    => False);
166
167
      Output_File      : File_Type;

168
      CV_Out_Dir  : constant String  :=
Maxime Perrotin's avatar
Maxime Perrotin committed
169
        CV.Base_Output_Path.Element & "/build/";
170
171
172
173
174
175

      --  Tags that are built over the whole system
      --  and cleant up between each template folder:
      Threads          : Unbounded_String;
      All_Thread_Names : Tag;  --  Complete list of threads
      All_Target_Names : Tag;  --  List of all targets used (AADL packages)
176
   begin
Maxime Perrotin's avatar
Maxime Perrotin committed
177
178
179
180
181
182
183
184
185
186
187
188
189
      Start_Search (Search    => ST,
                    Pattern   => "",
                    Directory => Prefix,
                    Filter    => Filter);

      if not More_Entries (ST) then
         --  On Unix, this will never happen because "." and ".." are part
         --  of the search result. We'll only get an IO Error if the
         --  concurrency_view folder itself does not exist
         raise Concurrency_View_Error with
           "No folders with templates for concurrency view";
      end if;

190
      --  Iterate over the folders containing template files
Maxime Perrotin's avatar
Maxime Perrotin committed
191
      while More_Entries (ST) loop
192
193
194
195
196
         --  Clean-up system-wise tags before the next template folder:
         Threads := US ("");
         Clear (All_Thread_Names);
         Clear (All_Target_Names);

Maxime Perrotin's avatar
Maxime Perrotin committed
197
198
199
200
201
202
203
         Get_Next_Entry (ST, Current);

         --  Ignore Unix special directories
         if Simple_Name (Current) = "." or Simple_Name (Current) = ".." then
            goto continue;
         end if;

Maxime Perrotin's avatar
Maxime Perrotin committed
204
         declare
Maxime Perrotin's avatar
Maxime Perrotin committed
205
206
            Path  : constant String  := Full_Name (Current);

207
208
            function Generate_Partition (Node_Name      : String;
                                         Partition_Name : String)
Maxime Perrotin's avatar
Maxime Perrotin committed
209
                                         return String
Maxime Perrotin's avatar
Maxime Perrotin committed
210
            is
Maxime Perrotin's avatar
Maxime Perrotin committed
211
212
               Partition       : constant CV_Partition :=
                 CV.Nodes (Node_Name).Partitions (Partition_Name);
213
               Thread_Names    : Tag;
214
215
               Block_Names     : Vector_Tag;
               Block_Languages : Vector_Tag;
Maxime Perrotin's avatar
Maxime Perrotin committed
216
               Blocks          : Unbounded_String;
Maxime Perrotin's avatar
Maxime Perrotin committed
217
               Partition_Assoc : Translate_Set;
218
219
220
221
222
               --  Connections between threads:
               Thread_Src_Name : Vector_Tag;
               Thread_Src_Port : Vector_Tag;
               Thread_Dst_Name : Vector_Tag;
               Thread_Dst_Port : Vector_Tag;
223
224
225
226
227
228
229
230
231
232
               --  Optionally generate partition code in separate files
               --  (if filepart.tmplt is present and contains a filename)
               File_Id         : constant String := Path & "/filepart.tmplt";
               Part_Check      : constant Boolean := Exists (File_Id);
               Part_Tag        : constant Translate_Set :=
                 +Assoc ("Partition_Name", Partition_Name);
               Part_File_Name  : constant String :=
                 (if Part_Check then Strip_String (Parse (File_Id, Part_Tag))
                  else "");
               Part_Content    : Unbounded_String;
Maxime Perrotin's avatar
Maxime Perrotin committed
233
            begin
234
235
               for T of Partition.Threads loop
                  declare
236
237
238
239
240
241
242
243
244
                     --  There is no "&" operator for Translate sets...
                     function Join_Sets (S1, S2 : Translate_Set)
                                         return Translate_Set is
                        Result : Translate_Set := S1;
                     begin
                        Insert (Result, S2);
                        return Result;
                     end Join_Sets;

245
                     --  Render each thread
246
                     Name         : constant String := To_String (T.Name);
247
248
                     Thread_Assoc : constant Translate_Set :=
                       Join_Sets (T.To_Template, CV.Configuration.To_Template);
249
                     Result       : constant String :=
250
                       (Parse (Path & "/thread.tmplt", Thread_Assoc));
251
252
253
254
255
256
257
258
259
260
261
262
263

                     --  Optionally generate thread code in separate files
                     --  (if filethread.tmplt present and contains a filename)
                     Thread_File_Id   : constant String :=
                       Path & "/filethread.tmplt";
                     Thread_Check     : constant Boolean :=
                       Exists (Thread_File_Id);
                     Thread_Tag       : constant Translate_Set :=
                       +Assoc ("Thread_Name", Name);
                     Thread_File_Name : constant String :=
                       (if Thread_Check
                        then Strip_String (Parse (Thread_File_Id, Thread_Tag))
                        else "");
264
                  begin
265
266
                     Threads      := Threads & Newline & Result;
                     Thread_Names := Thread_Names & Name;
267
                     All_Thread_Names := All_Thread_Names & Name;
268
269
270
271
272
273
274
275
276
                     for P of T.Output_Ports loop
                        Thread_Src_Name := Thread_Src_Name & Name;
                        Thread_Src_Port := Thread_Src_Port
                          & To_String (P.Name);
                        Thread_Dst_Name := Thread_Dst_Name
                          & To_String (P.Remote_Thread);
                        Thread_Dst_Port := Thread_Dst_Port
                          & To_String (P.Remote_PI);
                     end loop;
277
278
279
280
281
282
283
284
285
286
287
288
                     --  Save the content of the thread in a file
                     --  (if required at template folder level)
                     if Thread_File_Name /= "" then
                        Create_Path (CV_Out_Dir & Node_Name);
                        Create (File => Output_File,
                                Mode => Out_File,
                                Name =>
                                  CV_Out_Dir & Node_Name
                                & "/" & Thread_File_Name);
                        Put_Line (Output_File, Result);
                        Close (Output_File);
                     end if;
289
                  end;
Maxime Perrotin's avatar
Maxime Perrotin committed
290
               end loop;
291

292
293
               for B of Partition.Blocks loop
                  declare
Maxime Perrotin's avatar
Maxime Perrotin committed
294
295
                     Block_Name   : constant String := To_String (B.Name);
                     Tmpl         : constant Block_As_Template :=
296
                       B.Prepare_Template;
Maxime Perrotin's avatar
Maxime Perrotin committed
297
298
299
300
301
                     Block_Assoc  : Translate_Set := Tmpl.Header;
                     Pro_PI_Tag   : Unbounded_String;
                     Unpro_PI_Tag : Unbounded_String;
                     RI_Tag       : Unbounded_String;
                     Result       : Unbounded_String;
302
303
304
305
306
307
308
309
310
311
312
313
314

                     --  Optionally generate block code in separate files
                     --  (if fileblock.tmplt present and contains a filename)
                     Block_File_Id   : constant String :=
                       Path & "/fileblock.tmplt";
                     Block_Check     : constant Boolean :=
                       Exists (Block_File_Id);
                     Block_Tag       : constant Translate_Set :=
                       +Assoc ("Block_Name", B.Name);
                     Block_File_Name : constant String :=
                       (if Block_Check
                        then Strip_String (Parse (Block_File_Id, Block_Tag))
                        else "");
315
                  begin
316
317
318
                     Block_Names     := Block_Names & Block_Name;
                     Block_Languages := Block_Languages & B.Language;

Maxime Perrotin's avatar
Maxime Perrotin committed
319
320
                     for PI_Assoc of Tmpl.Protected_Provided loop
                        Pro_PI_Tag := Pro_PI_Tag & Newline
321
322
323
                          & String'(Parse (Path & "/pi.tmplt",
                                    PI_Assoc & Assoc
                                      ("Partition_Name", Partition_Name)));
Maxime Perrotin's avatar
Maxime Perrotin committed
324
325
326
                     end loop;
                     for PI_Assoc of Tmpl.Unprotected_Provided loop
                        Unpro_PI_Tag := Unpro_PI_Tag & Newline
327
328
329
                          & String'(Parse (Path & "/pi.tmplt",
                                    PI_Assoc & Assoc
                                      ("Partition_Name", Partition_Name)));
330
331
                     end loop;
                     for RI_Assoc of Tmpl.Required loop
Maxime Perrotin's avatar
Maxime Perrotin committed
332
                        RI_Tag := RI_Tag & Newline
333
334
335
                          & String'(Parse (Path & "/ri.tmplt",
                                    RI_Assoc & Assoc
                                      ("Partition_Name", Partition_Name)));
336
337
                     end loop;
                     Block_Assoc := Block_Assoc
Maxime Perrotin's avatar
Maxime Perrotin committed
338
339
340
                       & Assoc ("Protected_PIs",   Pro_PI_Tag)
                       & Assoc ("Unprotected_PIs", Unpro_PI_Tag)
                       & Assoc ("Required",        RI_Tag);
341

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
                     Result := Parse (Path & "/block.tmplt", Block_Assoc);

                     Blocks := Blocks & Newline & To_String (Result);

                     --  Save the content of the block in a file
                     --  (if required at template folder level)
                     if Block_File_Name /= "" then
                        Create_Path (CV_Out_Dir & Node_Name);
                        Create (File => Output_File,
                                Mode => Out_File,
                                Name => CV_Out_Dir & Node_Name
                                        & "/" & Block_File_Name);
                        Put_Line (Output_File, To_String (Result));
                        Close (Output_File);
                     end if;
357
                  end;
Maxime Perrotin's avatar
Maxime Perrotin committed
358
               end loop;
359
360
361
               --  Association includes Name, Coverage, CPU Info, etc.
               --  (see taste-deployment_view.ads for the complete list)
               Partition_Assoc := Partition.Deployment_Partition.To_Template
362
363
364
365
                 & Assoc ("Threads",         Threads)
                 & Assoc ("Thread_Names",    Thread_Names)
                 & Assoc ("Node_Name",       Node_Name)
                 & Assoc ("Blocks",          Blocks)
366
                 & Assoc ("Block_Names",     Block_Names)
367
                 & Assoc ("Block_Languages", Block_Languages)
368
369
370
371
                 & Assoc ("Thread_Src_Name", Thread_Src_Name)
                 & Assoc ("Thread_Src_Port", Thread_Src_Port)
                 & Assoc ("Thread_Dst_Name", Thread_Dst_Name)
                 & Assoc ("Thread_Dst_Port", Thread_Dst_Port);
372

373
374
375
               All_Target_Names := All_Target_Names
                 & String'(Get (Get (Partition_Assoc, "Package_Name")));

376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
               Part_Content :=
                 Parse (Path & "/partition.tmplt", Partition_Assoc);

               --  Save the content of the partition in a file
               --  (if required at template folder level)
               if Part_File_Name /= "" then
                  Create_Path (CV_Out_Dir & Node_Name);
                  Create (File => Output_File,
                          Mode => Out_File,
                          Name =>
                            CV_Out_Dir & Node_Name & "/" & Part_File_Name);
                  Put_Line (Output_File, To_String (Part_Content));
                  Close (Output_File);
               end if;

               return To_String (Part_Content);
Maxime Perrotin's avatar
Maxime Perrotin committed
392
            end Generate_Partition;
Maxime Perrotin's avatar
Maxime Perrotin committed
393

394
395
            --  Generate the code for one node
            function Generate_Node (Node_Name : String) return String is
396
397
398
               Partitions      : Unbounded_String;
               Partition_Names : Tag;
               Node_Assoc      : Translate_Set;
Maxime Perrotin's avatar
Maxime Perrotin committed
399
400
401
402
403
               --  Nodes may contain a list of virtual processors for TSP:
               VP_Names,
               VP_Package_Names,
               VP_Platforms,
               VP_Classifiers  : Vector_Tag;
404
            begin
Maxime Perrotin's avatar
Maxime Perrotin committed
405
               for Partition in CV.Nodes (Node_Name).Partitions.Iterate loop
406
407
                  Partition_Names := Partition_Names
                    & CV_Partitions.Key (Partition);
408
409
410
411
                  Partitions := Partitions & Newline
                    & Generate_Partition
                    (Partition_Name => CV_Partitions.Key (Partition),
                     Node_Name      => Node_Name);
Maxime Perrotin's avatar
Maxime Perrotin committed
412
               end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
413
414
415
416
417
418
419
               for VP of CV.Nodes (Node_Name).Deployment_Node.Virtual_CPUs loop
                  VP_Names         := VP_Names & VP.Name;
                  VP_Package_Names := VP_Package_Names & VP.Package_Name;
                  VP_Platforms     := VP_Platforms & VP.Platform;
                  VP_Classifiers   := VP_Classifiers & VP.Classifier;
               end loop;

Maxime Perrotin's avatar
Maxime Perrotin committed
420
               Node_Assoc := +Assoc ("Partitions", Partitions)
421
                 & Assoc ("Partition_Names", Partition_Names)
Maxime Perrotin's avatar
Maxime Perrotin committed
422
423
                 & Assoc ("Has_Memory", Boolean'
                      (CV.Nodes (Node_Name).Deployment_Node.Memory.Name /= ""))
Maxime Perrotin's avatar
Maxime Perrotin committed
424
425
426
427
                 & Assoc ("VP_Names", VP_Names)
                 & Assoc ("VP_Package_Names", VP_Package_Names)
                 & Assoc ("VP_Platforms", VP_Platforms)
                 & Assoc ("VP_Classifiers", VP_Classifiers)
428
429
                 & Assoc ("Node_Name", Node_Name)
                 & Assoc ("CPU_Name",
Maxime Perrotin's avatar
Maxime Perrotin committed
430
                          CV.Nodes (Node_Name).Deployment_Node.CPU_Name)
431
432
433
434
                 & Assoc ("CPU_Family",
                          CV.Nodes (Node_Name).Deployment_Node.CPU_Family)
                 & Assoc ("CPU_Instance",
                          CV.Nodes (Node_Name).Deployment_Node.CPU_Instance)
435
436
437
                 & Assoc ("CPU_Platform",
                         CV.Nodes (Node_Name).Deployment_Node.CPU_Platform'Img)
                 & Assoc ("CPU_Classifier",
Maxime Perrotin's avatar
Maxime Perrotin committed
438
439
440
                          CV.Nodes (Node_Name).Deployment_Node.CPU_Classifier)
                 & Assoc ("Package_Name",
                          CV.Nodes (Node_Name).Deployment_Node.Package_Name)
441
442
                 & Assoc ("Ada_Runtime",
                         CV.Nodes (Node_Name).Deployment_Node.Ada_Runtime);
443
444
               return Parse (Path & "/node.tmplt", Node_Assoc);
            end Generate_Node;
Maxime Perrotin's avatar
Maxime Perrotin committed
445

446
447
448
449
450
            Nodes           : Unbounded_String;
            Tmpl_File       : constant String  := Path & "/filesys.tmplt";
            Tmpl_Sys        : constant String  := Path & "/system.tmplt";
            Valid_Dir       : constant Boolean := Exists (Tmpl_File);
            File_Sys        : constant String  :=
Maxime Perrotin's avatar
Maxime Perrotin committed
451
              (if Valid_Dir then Strip_String (Parse (Tmpl_File)) else "");
452
453
            Trig_Sys        : constant Boolean := Exists (Tmpl_Sys);
            Set_Sys         : Translate_Set;
Maxime Perrotin's avatar
Maxime Perrotin committed
454
455
456
457
458
459
460
461
            Node_Names,                    --  List of nodes
            Node_CPU,                      --  Corresponding CPU name
            Node_CPU_Cls,                  --  Corresponding CPU classifier
            Node_Has_Memory : Vector_Tag;  --  Corresponding memory flag
            Partition_Names,               --  List of partitions
            Partition_Node,                --  Corresponding node name
            Partition_CPU,                 --  Corresponding CPU name
            Partition_VP    : Vector_Tag;  --  for TSP: VP binding
462
463
464
465
         begin
            for Node in CV.Nodes.Iterate loop
               declare
                  Node_Name    : constant String := CV_Nodes.Key (Node);
Maxime Perrotin's avatar
Maxime Perrotin committed
466
                  Output_Dir   : constant String := CV_Out_Dir & Node_Name;
467
468
469
470
471
472
473
474
475
476
477
478
                  Do_It        : constant Boolean :=
                    Exists (Path & "/filenode.tmplt");
                  Filename_Set : constant Translate_Set :=
                    +Assoc ("Node_Name", Node_Name);
                  --  Get output file name from template
                  File_Name    : constant String :=
                    (if Do_It then
                        Strip_String
                       (Parse (Path & "/filenode.tmplt", Filename_Set))
                     else "");
                  --  Check if file already exists
                  Present      : constant Boolean :=
479
480
                    (File_Name /= ""
                     and then Exists (Output_Dir & "/" & File_Name));
481

482
                  Trig_Tmpl    : constant Translate_Set :=
483
484
485
                    CV.Configuration.To_Template
                    & Assoc ("Filename_Is_Present", Present);

486
487
488
489
490
491
492
493
494
                  Trigger      : constant Boolean :=
                    (Node_Name /= "interfaceview"
                     and then Exists (Path & "/trigger.tmplt") and then
                     Strip_String
                       (Parse (Path & "/trigger.tmplt", Trig_Tmpl)) = "TRUE");
                  Node_Content : constant String :=
                    (if Trigger then Generate_Node (Node_Name)
                     else "");
               begin
Maxime Perrotin's avatar
Maxime Perrotin committed
495
496
497
498
499
500
501
502
                  if Node_Name /= "interfaceview" then
                     Put_Debug (Path & " :" & Trigger'Img
                               & " (" & Node_Name & ")");
                     Put_Debug (Strip_String
                               (Parse (Path & "/trigger.tmplt",
                                  Trig_Tmpl)));
                  end if;

503
                  if Trigger then
504
505

                     --  Associate node name, CPU name and CPU classifier
Maxime Perrotin's avatar
Maxime Perrotin committed
506
                     --  Also set flag if a memory region is defined
507
                     --  (this is needed for AADL backends)
Maxime Perrotin's avatar
Maxime Perrotin committed
508
                     Node_Names := Node_Names & Node_Name;
509
510
511
512
                     Node_CPU := Node_CPU
                       & CV.Nodes (Node_Name).Deployment_Node.CPU_Name;
                     Node_CPU_Cls := Node_CPU_Cls
                       & CV.Nodes (Node_Name).Deployment_Node.CPU_Classifier;
Maxime Perrotin's avatar
Maxime Perrotin committed
513
514
515
                     Node_Has_Memory := Node_Has_Memory
                       & (CV.Nodes (Node_Name)
                          .Deployment_Node.Memory.Name /= "");
516
517
518
519
520
521
522
523
524
525

                     --  Associate partition name, corresponding node and CPU
                     --  for AADL backends
                     for Partition in CV.Nodes (Node_Name).Partitions.Iterate
                     loop
                        Partition_Names := Partition_Names
                          & CV_Partitions.Key (Partition);
                        Partition_CPU := Partition_CPU
                          & CV_Partitions.Element (Partition)
                          .Deployment_Partition.CPU_Name;
Maxime Perrotin's avatar
Maxime Perrotin committed
526
527
528
                        Partition_VP := Partition_VP
                          & CV_Partitions.Element (Partition)
                          .Deployment_Partition.VP_Name;
529
530
531
532
                        Partition_Node := Partition_Node & Node_Name;
                     end loop;

                     Nodes := Nodes & Newline & Node_Content;
533
534
535
536
537
538
539
540
541
542
543
                     if File_Name /= "" then
                        Create_Path (Output_Dir);
                        Create (File => Output_File,
                                Mode => Out_File,
                                Name => Output_Dir & "/" & File_Name);
                        Put_Line (Output_File, Node_Content);
                        Close (Output_File);
                     end if;
                  end if;
               end;
            end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
544
            if Trig_Sys and File_Sys /= "" and Nodes /= "" then
Maxime Perrotin's avatar
Maxime Perrotin committed
545
546
               Set_Sys := CV.Configuration.To_Template
                 & Assoc ("Nodes",       Nodes)
547
548
549
                 & Assoc ("Node_Names",          Node_Names)
                 & Assoc ("Node_CPU",            Node_CPU)
                 & Assoc ("Node_CPU_Classifier", Node_CPU_Cls)
Maxime Perrotin's avatar
Maxime Perrotin committed
550
                 & Assoc ("Node_Has_Memory",     Node_Has_Memory)
551
552
553
                 & Assoc ("Partition_Names",     Partition_Names)
                 & Assoc ("Partition_Node",      Partition_Node)
                 & Assoc ("Partition_CPU",       Partition_CPU)
Maxime Perrotin's avatar
Maxime Perrotin committed
554
                 & Assoc ("Partition_VP",        Partition_VP)
555
556
557
                 & Assoc ("Threads",             Threads)
                 & Assoc ("Thread_Names",        All_Thread_Names)
                 & Assoc ("Target_Packages",     All_Target_Names);
Maxime Perrotin's avatar
Maxime Perrotin committed
558
559
560
561
562
563
564
               Create_Path (CV_Out_Dir);
               Create (File => Output_File,
                       Mode => Out_File,
                       Name => CV_Out_Dir & File_Sys);
               Put_Line (Output_File, Parse (Tmpl_Sys, Set_Sys));
               Close (Output_File);
            end if;
Maxime Perrotin's avatar
Maxime Perrotin committed
565
         end;
Maxime Perrotin's avatar
Maxime Perrotin committed
566
567
         <<continue>>
      end loop;
Maxime Perrotin's avatar
Maxime Perrotin committed
568
      End_Search (ST);
569
   end Generate_Code;
Maxime Perrotin's avatar
Maxime Perrotin committed
570
571
572

   procedure Generate_CV (CV : Taste_Concurrency_View) is
   begin
573
574
575
576
      --  In this first iteration Nodes are generated in standalone files,
      --  and they include their processes. It would be useful to be able
      --  to decide if processes could also have their own files, since
      --  in the future they may be more than one process per node (for TSP).
577
      CV.Generate_Code;
Maxime Perrotin's avatar
Maxime Perrotin committed
578
579
580
581
582
583
   exception
      when Error : Concurrency_View_Error | Ada.IO_Exceptions.Name_Error =>
         Put_Error ("Concurrency View : "
                    & Ada.Exceptions.Exception_Message (Error));
         raise Quit_Taste;
   end Generate_CV;
Maxime Perrotin's avatar
Maxime Perrotin committed
584

585
end TASTE.Concurrency_View;