--------------------------------------- ----------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- G A I A . P R O C E S S O R . E N T I T I E S . C O N N E C T I O N S -- -- -- -- B o d y -- -- -- -- Copyright (C) 2005-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; use Namet; with Locations; with Ocarina.Nodes; with Ocarina.Nutils; with Ocarina.Entities; with Ocarina.Entities.Components; with Gaia.Processor.Nodes; with Gaia.Processor.Nodes.Utils; with Gaia.Messages; package body Gaia.Processor.Entities.Connections is package ON renames Ocarina.Nodes; package ONU renames Ocarina.Nutils; package GN renames Gaia.Processor.Nodes; package GNU renames Gaia.Processor.Nodes.Utils; function Compute_Unique_Name_Of_Connection_Extremity (Connection_Extremity : node_id) return name_id; -- Computes a system-unique name of a connection source or destination pragma unreferenced (Compute_Unique_Name_Of_Connection_Extremity); function Compute_Simple_Name_Of_Connection_Extremity (Connection_Extremity : node_id) return name_id; -- Computes a simple but not necessarily system-unique name of a -- connection source or destination Connection_Index : nat := 0; function Compute_New_Connection_Name return name_id; -- Computes a system unique connection name in order to attribute it -- to unnamed connections function Find_Node_Before_Last (List : list_id) return node_id; -- Return the element before the last ------------------------- -- Process_Connections -- ------------------------- function Process_Connections (Instance, Sp : node_id) return Boolean is use ON; use GN; use GNU; use Ocarina.Entities; use Ocarina.Entities.Components; use Gaia.Messages; pragma assert (Get_Category_Of_Component (Instance) = cc_subprogram or else Get_Category_Of_Component (Instance) = cc_thread or else Get_Category_Of_Component (Instance) = cc_process); pragma assert (GN.Kind (Sp) = GN.k_subprogram or else GN.Kind (Sp) = GN.k_thread or else GN.Kind (Sp) = GN.k_process); Success : constant Boolean := True; List_Node : node_id; Connection_Node : node_id; Identifier : node_id; I : node_id; C : node_id; Provide_Access : node_id := No_Node; Provide_Ref : node_id := No_Node; Require_Access : node_id := No_Node; Require_Ref : node_id := No_Node; begin if not ONU.Is_Empty (ON.Connections (Instance)) then List_Node := ON.First_Node (ON.Connections (Instance)); while Present (List_Node) loop Connection_Node := GNU.New_Node (GN.k_parameter_connection); -- If the connection is unnamed, display a warning and -- compute a new name if Get_Name_Of_Entity (List_Node) = No_Name then Display_Error ("Connection in " & Locations.Image (ON.Loc (List_Node)) & " does not have a name. Computing a new name...", Fatal => False, Warning => True); Identifier := GNU.Make_Identifier (Compute_New_Connection_Name); Bind_Identifier_To_Entity (Identifier, Connection_Node); GN.Set_Scoped_Name (Connection_Node, GNU.Append_Scoped_Name (GNU.Map_Scoped_Name (Connection_Node, Instance), Connection_Node, GN.Name (GN.Identifier (Connection_Node)))); else Identifier := GNU.Make_Identifier (Get_Name_Of_Entity (List_Node)); Bind_Identifier_To_Entity (Identifier, Connection_Node); GN.Set_Scoped_Name (Connection_Node, GNU.Map_Scoped_Name (Connection_Node, List_Node)); end if; -- Handling the connection source if Present (ON.Source (List_Node)) then I := ON.Item (ON.Last_Node (ON.Path (ON.Source (List_Node)))); Try_Perform_Link (GN.Set_Source'access, Connection_Node, I, False); GN.Set_Simple_Source (Connection_Node, Compute_Simple_Name_Of_Connection_Extremity (ON.Source (List_Node))); if Kind (I) = ON.k_parameter_instance then -- The source of the connection is a parameter of a -- subprogram call. -- Two cases: -- The source of the connection is a local parameter -- In this case we do nothing. -- The source of the connection is a parameter of a -- subprogram call. In this case we link the -- connecto the subprogram call. if ONU.Length (ON.Path (ON.Source (List_Node))) > 1 then -- Retrieve the subprogram call C := ON.Item (Find_Node_Before_Last (ON.Path (ON.Source (List_Node)))); -- Link the connection to subprogram call Try_Perform_Link (GN.Set_Source_Subprogram_Call'access, Connection_Node, C, False); end if; elsif Kind (I) = ON.k_subcomponent_access_instance then -- Prepare the handling of accesses Provide_Access := I; -- Two cases: -- The source of the connection is a local access -- feature (either provides or requires). In this -- case we do nothing. -- The source of the connection is a feature of a -- subprogram call or of a subcomponent. In this -- case we link the connecto the subprogram call. if ONU.Length (ON.Path (ON.Source (List_Node))) > 1 then -- Retrieve the parent C := ON.Item (Find_Node_Before_Last (ON.Path (ON.Source (List_Node)))); if ON.Kind (C) = k_call_instance then Provide_Ref := C; -- Link the connection to subprogram call Try_Perform_Link (GN.Set_Source_Subprogram_Call'access, Connection_Node, C, False); elsif ON.Kind (C) = k_subcomponent_instance then Provide_Ref := ON.Corresponding_Instance (C); else raise Program_Error; end if; end if; end if; else GN.Set_Simple_Source (Connection_Node, No_Name); end if; -- Handling the connection destination if Present (ON.Destination (List_Node)) then I := ON.Item (ON.Last_Node (ON.Path (ON.Destination (List_Node)))); Try_Perform_Link (GN.Set_Destination'access, Connection_Node, I, False); GN.Set_Simple_Destination (Connection_Node, Compute_Simple_Name_Of_Connection_Extremity (ON.Destination (List_Node))); if Kind (I) = ON.k_parameter_instance then -- The destination of the connection is a parameter -- of a subprogram call. -- Two cases: -- The destination of the connection is a local -- parameter In this case we do nothing. -- The destination of the connection is a parameter -- of a subprogram call. In this case we link the -- connecto the subprogram call. if ONU.Length (ON.Path (ON.Destination (List_Node))) > 1 then -- Retrieve the subprogram call C := ON.Item (Find_Node_Before_Last (ON.Path (ON.Destination (List_Node)))); -- Link the connection to subprogram call Try_Perform_Link (GN.Set_Destination_Subprogram_Call'access, Connection_Node, C, False); end if; elsif Kind (I) = ON.k_subcomponent_access_instance then -- Prepare the handling of accesses Require_Access := I; -- Two cases: -- The destination of the connection is a local -- access feature (either provide or requires). In -- this case we do nothing. -- The destination of the connection is a feature -- of a subprogram call or of a subcomponent. In -- this case we link the connecto the subprogram -- call. if ONU.Length (ON.Path (ON.Destination (List_Node))) > 1 then -- Retrieve the subprogram call C := ON.Item (Find_Node_Before_Last (ON.Path (ON.Destination (List_Node)))); if ON.Kind (C) = k_call_instance then Require_Ref := C; -- Link the connection to subprogram call Try_Perform_Link (GN.Set_Destination_Subprogram_Call'access, Connection_Node, C, False); elsif ON.Kind (C) = k_subcomponent_instance then Require_Ref := ON.Corresponding_Instance (C); else raise Program_Error; end if; end if; end if; else GN.Set_Simple_Destination (Connection_Node, No_Name); end if; -- Handle the possible access path if Present (Require_Access) or else Present (Require_Ref) then -- Complete eventual missing informations if No (Provide_Access) then Provide_Access := ON.Item (ON.Last_Node (ON.Path (ON.Source (List_Node)))); end if; -- Link the nodes -- FIXME: We support only ONE access -- (provides/require) per component. -- IMPORTANT: The order of the conditions is important -- to build correctly the "access chain". if Present (Require_Ref) and then Present (Provide_Ref) then Try_Perform_Link_From_Scratch (GN.Set_Access_Provided_By'access, Require_Ref, Provide_Ref); elsif Present (Require_Ref) then Try_Perform_Link_From_Scratch (GN.Set_Access_Provided_By'access, Require_Ref, Provide_Access); elsif Present (Provide_Ref) then Try_Perform_Link_From_Scratch (GN.Set_Access_Provided_By'access, Require_Access, Provide_Ref); else Try_Perform_Link_From_Scratch (GN.Set_Access_Provided_By'access, Require_Access, Provide_Access); end if; end if; GNU.Append_Node_To_List (Connection_Node, GN.Connections (Sp)); List_Node := ON.Next_Node (List_Node); end loop; end if; return Success; end Process_Connections; --------------------------- -- Find_Node_Before_Last -- --------------------------- function Find_Node_Before_Last (List : list_id) return node_id is Current : node_id; Next : node_id; begin Current := ON.First_Node (List); Next := ON.Next_Node (Current); if Next = No_Node then return No_Node; end if; while ON.Next_Node (Next) /= No_Node loop Current := Next; Next := ON.Next_Node (Next); end loop; return Current; end Find_Node_Before_Last; ------------------------------------------------- -- Compute_Unique_Name_Of_Connection_Extremity -- ------------------------------------------------- function Compute_Unique_Name_Of_Connection_Extremity (Connection_Extremity : node_id) return name_id is use Ocarina.Entities; use ONU; The_Path : constant list_id := ON.Path (Connection_Extremity); Path_Element : node_id; begin Get_Name_String (Compute_Full_Name_Of_Instance (ON.Item (ON.First_Node (The_Path)))); Path_Element := ON.Next_Node (ON.First_Node (The_Path)); while Present (Path_Element) loop Add_Str_To_Name_Buffer ("_"); Get_Name_String_And_Append (Get_Name_Of_Entity (ON.Item (Path_Element), False)); Path_Element := ON.Next_Node (Path_Element); end loop; return Name_Find; end Compute_Unique_Name_Of_Connection_Extremity; ------------------------------------------------- -- Compute_Simple_Name_Of_Connection_Extremity -- ------------------------------------------------- function Compute_Simple_Name_Of_Connection_Extremity (Connection_Extremity : node_id) return name_id is use Ocarina.Entities; The_Path : constant list_id := ON.Path (Connection_Extremity); Path_Element : node_id; begin Get_Name_String (Get_Name_Of_Entity (ON.Item (ON.First_Node (The_Path)))); Path_Element := ON.Next_Node (ON.First_Node (The_Path)); while Present (Path_Element) loop Add_Str_To_Name_Buffer ("_"); Get_Name_String_And_Append (Get_Name_Of_Entity (ON.Item (Path_Element), False)); Path_Element := ON.Next_Node (Path_Element); end loop; return Name_Find; end Compute_Simple_Name_Of_Connection_Extremity; --------------------------------- -- Compute_New_Connection_Name -- --------------------------------- function Compute_New_Connection_Name return name_id is begin Set_Str_To_Name_Buffer ("Cnx_"); Connection_Index := Connection_Index + 1; Add_Nat_To_Name_Buffer (Connection_Index); return Name_Find; end Compute_New_Connection_Name; end Gaia.Processor.Entities.Connections;