-------------------------------------- ------------------------------------------ -- -- -- OCARINA COMPONENTS -- -- -- -- OCARINA.GENERATORS.PO_HI_ADA.DEPLOYMENT -- -- -- -- B o d y -- -- -- -- Copyright (C) 2006-2007, GET-Telecom Paris. -- -- -- -- Ocarina is free software; you can redistribute it and/or modify -- -- it under terms of the GNU General Public License as published by the -- -- Free Software Foundation; either version 2, or (at your option) any -- -- later version. 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. See the GNU General -- -- Public License for more details. You should have received a copy of the -- -- GNU General Public License distributed with Ocarina; see file COPYING. -- -- If not, write to the Free Software Foundation, 51 Franklin Street, Fifth -- -- Floor, Boston, MA 02111-1301, USA. -- -- -- -- As a special exception, if other files instantiate generics from this -- -- unit, or you link this unit with other files to produce an executable, -- -- this unit does not by itself cause the resulting executable to be -- -- covered by the GNU General Public License. This exception does not -- -- however invalidate any other reasons why the executable file might be -- -- covered by the GNU Public License. -- -- -- -- Ocarina is maintained by the Ocarina team -- -- (ocarina-users@listes.enst.fr) -- -- -- ------------------------------------------------------------------------------ with Namet; with Ocarina.Nodes; with Ocarina.Nutils; with Ocarina.Entities.Components; with Ocarina.Generators.Utils; with Ocarina.Generators.Ada_Values; with Ocarina.Generators.Ada_Tree.Nutils; with Ocarina.Generators.Ada_Tree.Nodes; with Ocarina.Generators.PO_HI_Ada.Mapping; package body Ocarina.Generators.PO_HI_Ada.Deployment is use Namet; use Ocarina.Nodes; use Ocarina.Entities.Components; use Ocarina.Generators.Utils; use Ocarina.Generators.Ada_Values; use Ocarina.Generators.Ada_Tree.Nutils; use Ocarina.Generators.PO_HI_Ada.Mapping; package AAU renames Ocarina.Nutils; package ADN renames Ocarina.Generators.Ada_Tree.Nodes; ------------------ -- Package_Spec -- ------------------ package body Package_Spec 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); Last_Node_Enum_Pos : nat := 1; Last_Thread_Enum_Pos : nat := 1; Last_Port_Enum_Pos : nat := 1; -- Global variables for the representation clauses of the -- generated enumerator types. They point to the next free -- position in the corresponding enumeration type. We start by -- 1 because 0 is the value to indicate that no position has -- been assigned to the enumerator yet. function Get_Node_Enum_Pos (Name : name_id) return nat; function Get_Thread_Enum_Pos (Name : name_id) return nat; function Get_Port_Enum_Pos (Name : name_id) return nat; -- Return the position corresponding to the enumerator. If no -- position has been computed for the given enumerator, compute -- a new one. function Added_Internal_Name (P : node_id; E : node_id) return name_id; function Is_Added (P : node_id; E : node_id) return Boolean; procedure Set_Added (P : node_id; E : node_id); -- Used to ensure that the enumerator for Process P and all the -- enumerator corresponding to its threads are added only once -- to the deployment package of node E. type get_enum_pos_access is access function (Name : name_id) return nat; procedure Insert_Node_In_List (N : node_id; L : list_id; Get_Enum_Pos : get_enum_pos_access); -- Insert the node N into list L. N is assumed to be an -- enumerator or an element association relative to an -- enumerator. The insertion is done so that the positions of -- all the enumerators in the list are ordered -- incresingly. This is necessary in Ada since the enumerator -- position order must respect their declaration order. ------------------ -- Global Lists -- ------------------ -- The lists below are global and initialized at the beginning -- of visit of each process instance. This does not cause a -- consistency nor a concurrency proble since the visits of -- processes are done sequentially and the visit of one process -- is performed entirely before beginning the visit of another -- one. Node_Enumerator_List : list_id; -- Global list for all the distributed application nodes -- enumeration type. Node_Enumerator_Pos_List : list_id; -- Global list to store the representation clause of the node -- enumeration type. Thread_Enumerator_List : list_id; -- Global list for all the distributed application threads -- enumeration types. Thread_Enumerator_Pos_List : list_id; -- Global list to store the representation clause of the thread -- enumeration type. Entity_Table_List : list_id; -- Global list that associates each thread of the distributed -- application to its containing process. Concretly, this is a -- list of associations that contain for each enumerator of the -- Entity_Type type the corresponding enumerator of the -- Node_Type type. Port_Enumerator_List : list_id; -- Global list for all the distributed application thread port -- enumeration types. Port_Enumerator_Pos_List : list_id; -- Global list to store the representation clause of the thread -- port enumeration type. Port_Table_List : list_id; -- Global list that associates each port of the distributed -- application to its containing thread. Concretly, this is a -- list of associations that contain for each enumerator of the -- Port_Type type the corresponding enumerator of the -- Entity_Type type. ----------------------- -- Get_Node_Enum_Pos -- ----------------------- function Get_Node_Enum_Pos (Name : name_id) return nat is I_Name : name_id; Position : nat; begin Set_Str_To_Name_Buffer ("%node_enum_pos%"); Get_Name_String (Name); I_Name := Name_Find; -- Check whether a value has been computed for the current -- enumerator. Otherwise, compute a new one. Position := Get_Name_Table_Info (I_Name); if Position = 0 then -- Get the next free position Position := Last_Node_Enum_Pos; -- Link it to the enumerator for future use Set_Name_Table_Info (I_Name, Position); -- Increment the next free position Last_Node_Enum_Pos := Last_Node_Enum_Pos + 1; end if; return Position; end Get_Node_Enum_Pos; ------------------------- -- Get_Thread_Enum_Pos -- ------------------------- function Get_Thread_Enum_Pos (Name : name_id) return nat is I_Name : name_id; Position : nat; begin Set_Str_To_Name_Buffer ("%thread_enum_pos%"); Get_Name_String (Name); I_Name := Name_Find; -- Check whether a value has been computed for the current -- enumerator. Otherwise, compute a new one. Position := Get_Name_Table_Info (I_Name); if Position = 0 then -- Get the next free position Position := Last_Thread_Enum_Pos; -- Link it to the enumerator for future use Set_Name_Table_Info (I_Name, Position); -- Increment the next free position Last_Thread_Enum_Pos := Last_Thread_Enum_Pos + 1; end if; return Position; end Get_Thread_Enum_Pos; ----------------------- -- Get_Port_Enum_Pos -- ----------------------- function Get_Port_Enum_Pos (Name : name_id) return nat is I_Name : name_id; Position : nat; begin Set_Str_To_Name_Buffer ("%port_enum_pos%"); Get_Name_String (Name); I_Name := Name_Find; -- Check whether a value has been computed for the current -- enumerator. Otherwise, compute a new one. Position := Get_Name_Table_Info (I_Name); if Position = 0 then -- Get the next free position Position := Last_Port_Enum_Pos; -- Link it to the enumerator for future use Set_Name_Table_Info (I_Name, Position); -- Increment the next free position Last_Port_Enum_Pos := Last_Port_Enum_Pos + 1; end if; return Position; end Get_Port_Enum_Pos; ------------------------- -- 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; -------------- -- 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; --------------- -- 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; ------------------------- -- Insert_Node_In_List -- ------------------------- procedure Insert_Node_In_List (N : node_id; L : list_id; Get_Enum_Pos : get_enum_pos_access) is use ADN; M : node_id; Position_N : nat; Position_M : nat; begin pragma assert (Kind (N) = k_defining_identifier or else Kind (N) = k_element_association); case ADN.Kind (N) is when ADN.k_defining_identifier => Position_N := Get_Enum_Pos (ADN.Name (N)); when ADN.k_element_association => Position_N := Get_Enum_Pos (ADN.Name (Index (N))); when others => raise Program_Error with "Inconsistency in Insert_Node_In_List"; end case; if Is_Empty (L) then Append_Node_To_List (N, L); else M := ADN.First_Node (L); while Present (M) loop case ADN.Kind (M) is when ADN.k_defining_identifier => Position_M := Get_Enum_Pos (ADN.Name (M)); when ADN.k_element_association => Position_M := Get_Enum_Pos (ADN.Name (Index (M))); when others => raise Program_Error with "Inconsistency in Insert_Node_In_List"; end case; if Position_N < Position_M then Insert_Before_Node (N, M, L); return; -- IMPORTANT end if; M := ADN.Next_Node (M); end loop; Append_Node_To_List (N, L); end if; end Insert_Node_In_List; ----------- -- 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 Cathegory : constant component_category := Get_Category_Of_Component (E); begin case Cathegory is when cc_system => Visit_System_Instance (E); when cc_process => Visit_Process_Instance (E); when cc_thread => Visit_Thread_Instance (E); when others => null; end case; end Visit_Component_Instance; ---------------------------- -- Visit_Process_Instance -- ---------------------------- procedure Visit_Process_Instance (E : node_id) is U : constant node_id := ADN.Distributed_Application_Unit (ADN.Naming_Node (Backend_Node (Identifier (E)))); P : constant node_id := ADN.Entity (U); S : constant node_id := Parent_Subcomponent (E); N : node_id; C : node_id; F : node_id; Src : node_id; Dst : node_id; Parent : node_id; S_Parent : node_id; begin Push_Entity (P); Push_Entity (U); Set_Deployment_Spec; -- Create the lists Node_Enumerator_List := New_List (ADN.k_enumeration_literals); Node_Enumerator_Pos_List := New_List (ADN.k_element_list); Thread_Enumerator_List := New_List (ADN.k_enumeration_literals); Thread_Enumerator_Pos_List := New_List (ADN.k_element_list); Entity_Table_List := New_List (ADN.k_element_list); Port_Enumerator_List := New_List (ADN.k_enumeration_literals); Port_Enumerator_Pos_List := New_List (ADN.k_element_list); Port_Table_List := New_List (ADN.k_element_list); -- The Deployment package must be preelaborated N := Make_Pragma_Statement (pragma_preelaborate, No_List); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Build the enumerator corresponding to the distributed -- application node. The enumerator name is mapped from the -- process *sub*component instance. N := Make_Defining_Identifier (Map_Ada_Enumerator_Name (S)); Append_Node_To_List (N, Node_Enumerator_List); Bind_AADL_To_Enumerator (Identifier (S), N); -- Build the representation clause of the enumerator N := Make_Element_Association (Make_Defining_Identifier (Map_Ada_Enumerator_Name (S)), Make_Literal (New_Integer_Value (unsigned_long_long (Get_Node_Enum_Pos (Map_Ada_Enumerator_Name (S))), 1, 10))); Insert_Node_In_List (N, Node_Enumerator_Pos_List, Get_Node_Enum_Pos'access); -- Visit all the subcomponents of the process if not AAU.Is_Empty (Subcomponents (E)) then C := First_Node (Subcomponents (E)); while Present (C) loop Visit (Corresponding_Instance (C)); 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)); if Is_Process (Parent) and then Parent /= E and then not Is_Added (Parent, E) then -- Add the process to the deployment -- enumerators of E. S_Parent := Parent_Subcomponent (Parent); N := Make_Defining_Identifier (Map_Ada_Enumerator_Name (S_Parent)); Insert_Node_In_List (N, Node_Enumerator_List, Get_Node_Enum_Pos'access); -- Add a representation clause for the -- enumerator corresponding to Parent. N := Make_Element_Association (Make_Defining_Identifier (Map_Ada_Enumerator_Name (S_Parent)), Make_Literal (New_Integer_Value (unsigned_long_long (Get_Node_Enum_Pos (Map_Ada_Enumerator_Name (S_Parent))), 1, 10))); Insert_Node_In_List (N, Node_Enumerator_Pos_List, Get_Node_Enum_Pos'access); -- 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; -- Mark P as being Added Set_Added (Parent, E); 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)); if Is_Process (Parent) and then Parent /= E and then not Is_Added (Parent, E) then -- Add the process to the deployment -- enumerators of E. S_Parent := Parent_Subcomponent (Parent); N := Make_Defining_Identifier (Map_Ada_Enumerator_Name (S_Parent)); Insert_Node_In_List (N, Node_Enumerator_List, Get_Node_Enum_Pos'access); -- Add a representation clause for the -- enumerator corresponding to P. N := Make_Element_Association (Make_Defining_Identifier (Map_Ada_Enumerator_Name (S_Parent)), Make_Literal (New_Integer_Value (unsigned_long_long (Get_Node_Enum_Pos (Map_Ada_Enumerator_Name (S_Parent))), 1, 10))); Insert_Node_In_List (N, Node_Enumerator_Pos_List, Get_Node_Enum_Pos'access); -- Traverse all the subcomponensts of P 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; -- Mark P as being Added Set_Added (Parent, E); end if; Dst := Next_Node (Dst); end loop; end if; F := Next_Node (F); end loop; end if; -- 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. N := Message_Comment ("For each node in the distributed" & " application add an enumerator"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Full_Type_Declaration (Defining_Identifier => Make_Defining_Identifier (TN (t_node_type)), Type_Definition => Make_Enumeration_Type_Definition (Node_Enumerator_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Create the enumeration representation clause so that all -- the enumerators in all the generated deployment packages -- have coherent position. N := Message_Comment ("Representation clause to have consistent" & " positions for enumarators"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Enumeration_Representation_Clause (Defining_Identifier => Make_Defining_Identifier (TN (t_node_type)), Array_Aggregate => Make_Array_Aggregate (Node_Enumerator_Pos_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Fix the size of type Node_Type to 8 bit because the -- message stream allocates one byte for it for now. This -- implies a maximum value of 256 nodes per application. N := Message_Comment ("Size of Node_Type fixed to 8 bits"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Attribute_Definition_Clause (Defining_Identifier => Make_Defining_Identifier (TN (t_node_type)), Attribute_Designator => a_size, Expression => Make_Literal (New_Integer_Value (8, 1, 10))); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Declare the constant that represent the current node N := Make_Object_Declaration (Defining_Identifier => Make_Defining_Identifier (PN (p_my_node)), Constant_Present => True, Object_Definition => Make_Designator (TN (t_node_type)), Expression => Make_Defining_Identifier (Map_Ada_Enumerator_Name (S))); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Create the thread enumeration type declaration. Note that -- the type creation is possible even the enumeration list -- is incomplete. if not Is_Empty (Thread_Enumerator_List) then N := Message_Comment ("For each thread in the distributed" & " application nodes, add an" & " enumerator"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Full_Type_Declaration (Defining_Identifier => Make_Defining_Identifier (TN (t_entity_type)), Type_Definition => Make_Enumeration_Type_Definition (Thread_Enumerator_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Create the enumeration representation clause so that -- all the enumerators in all the generated deployment -- packages have coherent position. N := Message_Comment ("Representation clause to have consistent" & " positions for enumarators"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Enumeration_Representation_Clause (Defining_Identifier => Make_Defining_Identifier (TN (t_entity_type)), Array_Aggregate => Make_Array_Aggregate (Thread_Enumerator_Pos_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Fix the size of type Entity_Type to 8 bit because the -- message stream allocates one byte for it for now. This -- implies a maximum value of 256 nodes per application. N := Message_Comment ("Size of Entity_Type fixed to 8 bits"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Attribute_Definition_Clause (Defining_Identifier => Make_Defining_Identifier (TN (t_entity_type)), Attribute_Designator => a_size, Expression => Make_Literal (New_Integer_Value (8, 1, 10))); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); end if; -- Declare the Entity Table when necessary if not Is_Empty (Entity_Table_List) then N := Message_Comment ("Entity Table"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Array_Type_Definition (Range_Constraints => Make_List_Id (Make_Range_Constraint (No_Node, No_Node, Make_Attribute_Designator (Make_Designator (TN (t_entity_type)), a_range))), Component_Definition => Make_Defining_Identifier (TN (t_node_type))); N := Make_Object_Declaration (Defining_Identifier => Make_Defining_Identifier (PN (p_entity_table)), Constant_Present => True, Object_Definition => N, Expression => Make_Array_Aggregate (Entity_Table_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); end if; -- Create the port enumeration type declaration. Note that -- the type creation is possible even the enumeration list -- is incomplete. if not Is_Empty (Port_Enumerator_List) then N := Message_Comment ("For each thread port in the distributed" & " application nodes, add an" & " enumerator"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Full_Type_Declaration (Defining_Identifier => Make_Defining_Identifier (TN (t_port_type)), Type_Definition => Make_Enumeration_Type_Definition (Port_Enumerator_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Create the enumeration representation clause so that -- all the enumerators in all the generated deployment -- packages have coherent position. N := Message_Comment ("Representation clause to have consistent" & " positions for enumarators"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Enumeration_Representation_Clause (Defining_Identifier => Make_Defining_Identifier (TN (t_port_type)), Array_Aggregate => Make_Array_Aggregate (Port_Enumerator_Pos_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); -- Fix the size of type Port_Type to 16 bits to be able -- to instanciate a Marshallers_G for it. N := Message_Comment ("Size of Port_Type fixed to 16 bits"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Attribute_Definition_Clause (Defining_Identifier => Make_Defining_Identifier (TN (t_port_type)), Attribute_Designator => a_size, Expression => Make_Literal (New_Integer_Value (16, 1, 10))); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); end if; -- Declare the Port Table when necessary if not Is_Empty (Port_Table_List) then N := Message_Comment ("Port Table"); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); N := Make_Array_Type_Definition (Range_Constraints => Make_List_Id (Make_Range_Constraint (No_Node, No_Node, Make_Attribute_Designator (Make_Designator (TN (t_port_type)), a_range))), Component_Definition => Make_Defining_Identifier (TN (t_entity_type))); N := Make_Object_Declaration (Defining_Identifier => Make_Defining_Identifier (PN (p_port_table)), Constant_Present => True, Object_Definition => N, Expression => Make_Array_Aggregate (Port_Table_List)); Append_Node_To_List (N, ADN.Visible_Part (Current_Package)); end if; Pop_Entity; -- U Pop_Entity; -- P end Visit_Process_Instance; --------------------------- -- Visit_System_Instance -- --------------------------- procedure Visit_System_Instance (E : node_id) is S : node_id; begin Push_Entity (HI_Distributed_Application_Root); -- Visit all the subcomponents of the system if not AAU.Is_Empty (Subcomponents (E)) then S := First_Node (Subcomponents (E)); while Present (S) loop -- Visit the component instance corresponding to the -- subcomponent S. Visit (Corresponding_Instance (S)); S := Next_Node (S); end loop; end if; Pop_Entity; -- HI_Distributed_Application_Root end Visit_System_Instance; --------------------------- -- Visit_Thread_Instance -- --------------------------- procedure Visit_Thread_Instance (E : node_id) is N : node_id; P : node_id; F : node_id; S : constant node_id := Parent_Subcomponent (E); begin -- Build the enumerator corresponding to the thread. The -- enumerator name is mapped from the the thread name and -- its containing process name. N := Make_Defining_Identifier (Map_Ada_Enumerator_Name (S)); Insert_Node_In_List (N, Thread_Enumerator_List, Get_Thread_Enum_Pos'access); Bind_AADL_To_Enumerator (Identifier (S), N); -- Build the representation clause for the enumerator N := Make_Element_Association (Make_Defining_Identifier (Map_Ada_Enumerator_Name (S)), Make_Literal (New_Integer_Value (unsigned_long_long (Get_Thread_Enum_Pos (Map_Ada_Enumerator_Name (S))), 1, 10))); Insert_Node_In_List (N, Thread_Enumerator_Pos_List, Get_Thread_Enum_Pos'access); -- For each thread, build the corresponding element -- association and append it to the entity list. -- Get the Process parent of the thread P := Parent_Component (S); pragma assert (Is_Process (P)); N := Make_Element_Association (Make_Defining_Identifier (Map_Ada_Enumerator_Name (S)), Make_Defining_Identifier (Map_Ada_Enumerator_Name (Parent_Subcomponent (P)))); Insert_Node_In_List (N, Entity_Table_List, Get_Thread_Enum_Pos'access); -- For each one of the thread ports, create its -- correspodning enumerator, representation clause and -- association. if not AAU.Is_Empty (Features (E)) then F := First_Node (Features (E)); while Present (F) loop if Kind (F) = k_port_spec_instance then declare Enum_Name : constant name_id := Map_Ada_Full_Feature_Name (F, 'K'); begin -- Create the enumerator corresponding to the -- port. N := Make_Defining_Identifier (Enum_Name); Insert_Node_In_List (N, Port_Enumerator_List, Get_Port_Enum_Pos'access); -- Build the representation clause for the -- enumerator. N := Make_Element_Association (Make_Defining_Identifier (Enum_Name), Make_Literal (New_Integer_Value (unsigned_long_long (Get_Port_Enum_Pos (Enum_Name)), 1, 10))); Insert_Node_In_List (N, Port_Enumerator_Pos_List, Get_Port_Enum_Pos'access); -- For each port, build the corresponding -- element association and append it to the -- association list. N := Make_Element_Association (Make_Defining_Identifier (Enum_Name), Make_Defining_Identifier (Map_Ada_Enumerator_Name (S))); Insert_Node_In_List (N, Port_Table_List, Get_Port_Enum_Pos'access); end; end if; F := Next_Node (F); end loop; end if; end Visit_Thread_Instance; end Package_Spec; end Ocarina.Generators.PO_HI_Ada.Deployment;