--------------------------------------- ----------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- G A I A . P R O C E S S O R . E N T I T I E S . F E A T U R E 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 Locations; with Ocarina.Nodes; with Ocarina.AADL_Values; with Ocarina.Nutils; with Ocarina.Entities; with Ocarina.Entities.Components; with Gaia.Processor.Nodes; with Gaia.Processor.Nodes.Utils; package body Gaia.Processor.Entities.Features is package ON renames Ocarina.Nodes; package GN renames Gaia.Processor.Nodes; package GNU renames Gaia.Processor.Nodes.Utils; package OAV renames Ocarina.AADL_Values; function Find_Destination_Entities (Feature_Instance : Node_Id; Search_Outside_Parent_Component : Boolean := True) return List_Id; --------------------- -- Process_Feature -- --------------------- function Process_Feature (Instance : Node_Id; Procedure_Node : Node_Id) return Boolean is use Ocarina.Entities; use ON; use GN; use GNU; pragma Assert (ON.Kind (Instance) = ON.K_Subcomponent_Access_Instance or else ON.Kind (Instance) = ON.K_Port_Spec_Instance or else ON.Kind (Instance) = ON.K_Port_Group_Spec_Instance or else ON.Kind (Instance) = ON.K_Subprogram_Spec_Instance or else ON.Kind (Instance) = ON.K_Parameter_Instance); pragma Assert (Present (Procedure_Node)); List_Node : Node_Id; Success : Boolean := True; Feature : Node_Id; Identifier : Node_Id; begin case ON.Kind (Instance) is when K_Parameter_Instance => pragma Assert (Kind (Procedure_Node) = K_Subprogram); Feature := GNU.New_Node (GN.K_Parameter); Identifier := GNU.Make_Identifier (Normalize_Name (Get_Name_Of_Entity (Instance))); Bind_Identifier_To_Entity (Identifier, Feature); GN.Set_Scoped_Name (Feature, Map_Scoped_Name (Feature, Instance)); GN.Set_Is_In (Feature, ON.Is_In (Instance)); GN.Set_Is_Out (Feature, ON.Is_Out (Instance)); Try_Perform_Link (GN.Set_Type_Spec'Access, Feature, Corresponding_Instance (Instance), True); GNU.Append_Node_To_List (Feature, GN.Parameters (Procedure_Node)); when K_Port_Spec_Instance => pragma Assert (Kind (Procedure_Node) = K_Thread or else Kind (Procedure_Node) = K_Process); Feature := GNU.New_Node (GN.K_Port); Identifier := GNU.Make_Identifier (Normalize_Name (Get_Name_Of_Entity (Instance))); Bind_Identifier_To_Entity (Identifier, Feature); GN.Set_Scoped_Name (Feature, Map_Scoped_Name (Feature, Instance)); GN.Set_Is_In (Feature, ON.Is_In (Instance)); GN.Set_Is_Out (Feature, ON.Is_Out (Instance)); if ON.Is_Event (Instance) and then ON.Is_In (Instance) then GN.Set_Fifo_Size (Feature, OAV.V_One); -- XXX To be changed. We must use the corresponding -- AADL property GN.Set_Trigger (Feature, True); -- XXX To be changed. All event ports are not supposed -- to dispatch their thread. else GN.Set_Fifo_Size (Feature, OAV.V_Zero); GN.Set_Trigger (Feature, False); end if; if ON.Is_Out (Instance) then declare Feature_Destinations : constant List_Id := Find_Destination_Entities (Instance); Destination_Feature, Corresponding_Thread, Corresponding_Process : Node_Id; Identifier : Node_Id; begin if Feature_Destinations /= No_List then List_Node := ON.First_Node (Feature_Destinations); GN.Set_Destinations (Feature, New_List (K_List_Id)); while List_Node /= No_Node loop Destination_Feature := GNU.New_Node (K_Destination_Port); Identifier := Make_Identifier (Get_Name_Of_Entity (ON.Item (List_Node))); Bind_Identifier_To_Entity (Identifier, Destination_Feature); GN.Set_Frontend_Node (Destination_Feature, ON.Item (List_Node)); Corresponding_Thread := ON.Parent_Component (ON.Item (List_Node)); Corresponding_Process := ON.Parent_Component (ON.Parent_Subcomponent (Corresponding_Thread)); GN.Set_Thread_Name (Destination_Feature, Normalize_Name (Get_Name_Of_Entity (ON.Parent_Subcomponent (Corresponding_Thread)))); GN.Set_Process_Name (Destination_Feature, Normalize_Name (Get_Name_Of_Entity (ON.Parent_Subcomponent (Corresponding_Process)))); GN.Set_Thread_Location (Destination_Feature, Get_Process_Location (Corresponding_Process)); GN.Set_Port_Number (Destination_Feature, Get_Process_Port_Number (Corresponding_Process)); Append_Node_To_List (Destination_Feature, GN.Destinations (Feature)); List_Node := ON.Next_Node (List_Node); end loop; end if; end; end if; Try_Perform_Link (GN.Set_Type_Spec'Access, Feature, Corresponding_Instance (Instance), True); -- We set the annotation so that we can find the Gaia -- port node when dealing with Ocarina port node. Used -- in Process_Connection. ON.Set_Annotation (Instance, Feature); GNU.Append_Node_To_List (Feature, GN.Ports (Procedure_Node)); when K_Port_Group_Spec_Instance => -- We develop the features of the port group if ON.Features (Instance) /= No_List then List_Node := ON.First_Node (ON.Features (Instance)); while List_Node /= No_Node loop Success := Process_Feature (List_Node, Procedure_Node) and then Success; List_Node := ON.Next_Node (List_Node); end loop; end if; when K_Subcomponent_Access_Instance => -- Handle only provides/requires data accesses for now if ON.Is_Data (Instance) then pragma Assert (Kind (Procedure_Node) = K_Thread or else Kind (Procedure_Node) = K_Process or else Kind (Procedure_Node) = K_Subprogram); Feature := GNU.New_Node (GN.K_Variable_Definition); Bind_Identifier_To_Entity (GNU.Make_Identifier (Normalize_Name (Get_Name_Of_Entity (Instance))), Feature); GN.Set_Scoped_Name (Feature, Map_Scoped_Name (Feature, Instance)); Try_Perform_Link (GN.Set_Type_Spec'Access, Feature, Corresponding_Instance (Instance), True); -- If the component is a 'requires access' we set its -- container as its provider. This will close the -- access chain. if not ON.Is_Provided (Instance) then Set_Access_Provided_By (Feature, Procedure_Node); end if; ON.Set_Annotation (Instance, Feature); GNU.Append_Node_To_List (Feature, Variables (Procedure_Node)); Success := True; else raise Program_Error with "Subprogram Access not" & " handled by Gaia"; end if; when others => raise Program_Error with "Not supported feature " & ON.Node_Kind'Image (ON.Kind (Instance)); end case; return Success; end Process_Feature; ------------------------------- -- Find_Destination_Entities -- ------------------------------- function Find_Destination_Entities (Feature_Instance : Node_Id; Search_Outside_Parent_Component : Boolean := True) return List_Id is use Locations; use Ocarina.Entities; use Ocarina.Entities.Components; use Ocarina.Nutils; use ON; pragma Assert (Feature_Instance /= No_Node and then Kind (Feature_Instance) = K_Port_Spec_Instance); Component_Instance, Parent_Component_Instance, Parent_Subcomponent_Instance : Node_Id; List_Node, Container_Node, Source_Entity, Destination_Entity : Node_Id; Destination_Entities : List_Id := No_List; Search_Outside_Destination_Component : Boolean; begin -- The connections to follow may be inside the parent component -- or outside. Basically, following a connection through a -- feature implies going from the inside into the outside, or -- the contrary. if Search_Outside_Parent_Component then Parent_Subcomponent_Instance := Parent_Subcomponent (Parent_Component (Feature_Instance)); if Parent_Subcomponent_Instance /= No_Node then Parent_Component_Instance := Parent_Component (Parent_Subcomponent_Instance); -- Parent_Component_Instance is the component that contains -- the component which the feature belongs to. Hence -- Parent_Component_Instance contains the connections that -- are related to the feature instance. Component_Instance := Parent_Component_Instance; else Component_Instance := No_Node; end if; else Component_Instance := Parent_Component (Feature_Instance); end if; if Component_Instance /= No_Node and then Connections (Component_Instance) /= No_List then List_Node := First_Node (Connections (Component_Instance)); Destination_Entities := New_List (K_List_Id, No_Location); while List_Node /= No_Node loop Source_Entity := Item (Last_Node (Path (Source (List_Node)))); Destination_Entity := Item (Last_Node (Path (Destination (List_Node)))); if Source_Entity = Feature_Instance then -- If the connection is related to our feature -- instance if Kind (Destination_Entity) = K_Port_Spec_Instance and then Parent_Component (Destination_Entity) /= No_Node then if Get_Category_Of_Component (Parent_Component (Destination_Entity)) = CC_Thread then -- We reached the destination of the connection Container_Node := New_Node (K_Node_Container, Loc (Destination_Entity)); Set_Item (Container_Node, Destination_Entity); Append_Node_To_List (Container_Node, Destination_Entities); else -- We must go further. We have to follow -- connections, either inside the component we -- found, or outside, depending on where we come -- from (inside or outside) -- If the destination feature belongs to the -- same component as the connexion, then we are -- inside. Search_Outside_Destination_Component := Parent_Component (Destination_Entity) = Parent_Component (List_Node); Append_List_To_List (Find_Destination_Entities (Destination_Entity, Search_Outside_Destination_Component), Destination_Entities); end if; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; return Destination_Entities; end Find_Destination_Entities; end Gaia.Processor.Entities.Features;