------------------------------------- ------------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- O C A R I N A . G E N E R A T O R S . P O _ H I _ C . M A I N -- -- -- -- B o d y -- -- -- -- Copyright (C) 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 Ocarina.Nodes; with Ocarina.Nutils; with Ocarina.Entities.Components; with Ocarina.Generators.Properties; with Ocarina.Generators.Utils; with Ocarina.Generators.Messages; with Ocarina.Generators.C_Tree.Nutils; with Ocarina.Generators.C_Tree.Nodes; with Ocarina.Generators.C_Values; with Ocarina.Generators.PO_HI_C.Runtime; with Ocarina.Generators.PO_HI_C.Mapping; package body Ocarina.Generators.PO_HI_C.Main is use Ocarina.Nodes; use Ocarina.Entities.Components; use Ocarina.Generators.Properties; use Ocarina.Generators.Messages; use Ocarina.Generators.C_Tree.Nutils; use Ocarina.Generators.C_Values; use Ocarina.Generators.PO_HI_C.Runtime; use Ocarina.Generators.PO_HI_C.Mapping; package AAU renames Ocarina.Nutils; package CTN renames Ocarina.Generators.C_Tree.Nodes; package CTU renames Ocarina.Generators.C_Tree.Nutils; --------------------- -- Subprogram_Body -- --------------------- package body Source_File is Main_Function : Node_Id; 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 Setup_Periodic_Thread (E : Node_Id); -- Create a periodic task according to all its properties -- (like period, priority, ...). The task creation -- is made in the main function, calling the function -- __po_hi_create_periodic_task(). procedure Setup_Sporadic_Thread (E : Node_Id); -- Create a sporadic task according to all its properties. -- The called function to create it is -- __po_hi_create_sporadic_task. --------------------------- -- Setup_Periodic_Thread -- --------------------------- procedure Setup_Periodic_Thread (E : Node_Id) is N : Node_Id; Parameters : List_Id; Priority : Unsigned_Long_Long; S : constant Node_Id := Parent_Subcomponent (E); begin -- This procedure makes a call to __po_hi_create_periodic_task -- with all task properties as parameters. Parameters := New_List (CTN.K_Parameter_List); -- Add the task name to the parameters list N := Make_Defining_Identifier (Map_C_Enumerator_Name (S)); Append_Node_To_List (N, Parameters); -- Add the period of the task to the parameters list N := Map_Time (Get_Thread_Period (E)); Append_Node_To_List (N, Parameters); -- Add the priority of the task in the parameters list. -- If the task do not have any priority, we use the -- maccro DEFAULT_PRIORITY. Priority := Get_Thread_Priority (E); if Priority = 0 then N := RE (RE_Default_Priority); else N := Make_Literal (New_Int_Value (Priority, 1, 10)); end if; Append_Node_To_List (N, Parameters); -- Add the name of function executed by the task in the -- parameters list. N := Copy_Node (CTN.Defining_Identifier (CTN.Job_Node (Backend_Node (Identifier (S))))); Append_Node_To_List (N, Parameters); Append_Node_To_List (CTU.Make_Call_Profile (RE (RE_Create_Periodic_Task), Parameters), CTN.Statements (Main_Function)); end Setup_Periodic_Thread; --------------------------- -- Setup_Sporadic_Thread -- --------------------------- procedure Setup_Sporadic_Thread (E : Node_Id) is N : Node_Id; Parameters : List_Id; Priority : Unsigned_Long_Long; S : constant Node_Id := Parent_Subcomponent (E); begin -- This procedure makes a call to the __po_hi_create_sporadic_task. -- Then, this call profile is added in the main function. Parameters := New_List (CTN.K_Parameter_List); -- Add the name of the task to the parameters list N := Make_Defining_Identifier (Map_C_Enumerator_Name (S)); Append_Node_To_List (N, Parameters); -- Add the period of the task to the parameters list N := Map_Time (Get_Thread_Period (E)); Append_Node_To_List (N, Parameters); -- Add the priority of the task to the parameters list Priority := Get_Thread_Priority (E); if Priority = 0 then N := RE (RE_Default_Priority); else N := Make_Literal (New_Int_Value (Priority, 1, 10)); end if; Append_Node_To_List (N, Parameters); -- Add the job name of the task to the parameters list N := Copy_Node (CTN.Defining_Identifier (CTN.Job_Node (Backend_Node (Identifier (S))))); Append_Node_To_List (N, Parameters); Append_Node_To_List (CTU.Make_Call_Profile (RE (RE_Create_Sporadic_Task), Parameters), CTN.Statements (Main_Function)); end Setup_Sporadic_Thread; ----------- -- 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 := CTN.Distributed_Application_Unit (CTN.Naming_Node (Backend_Node (Identifier (E)))); P : constant Node_Id := CTN.Entity (U); N : Node_Id; S : Node_Id; Spec : Node_Id; Declarations : constant List_Id := New_List (CTN.K_Declaration_List); Statements : constant List_Id := New_List (CTN.K_Statement_List); begin Push_Entity (P); Push_Entity (U); Set_Main_Source; Add_Include (E => RH (RH_Activity)); -- Make the main function specification and add it in the current -- file (main.c). Spec := Make_Function_Specification (Defining_Identifier => RE (RE_Main_Name), Parameters => No_List, Return_Type => RE (RE_Main_Type)); Main_Function := Make_Function_Implementation (Spec, Declarations, Statements); Append_Node_To_List (Main_Function, CTN.Declarations (Current_File)); N := CTU.Make_Call_Profile (RE (RE_Initialize)); Append_Node_To_List (N, CTN.Statements (Main_Function)); if not AAU.Is_Empty (Subcomponents (E)) then S := First_Node (Subcomponents (E)); while Present (S) loop -- Handle protected data, the following lines initialize -- the protected_id attribute for each protected data -- The generated code will look like : -- data_variable.protected_id = value. if Utils.Is_Data (Corresponding_Instance (S)) then -- Automatically use the types.h header if we use -- protected data. Add_Include (RH (RH_Types)); N := Make_Expression (Left_Expr => Make_Member_Designator (Defining_Identifier => Make_Defining_Identifier (MN (M_Protected_Id)), Aggregate_Name => Map_C_Defining_Identifier (S)), Operator => Op_Equal, Right_Expr => CTN.Default_Value_Node (Backend_Node (Identifier (S)))); Append_Node_To_List (N, CTN.Statements (Main_Function)); else -- Visit the component instance corresponding to the -- subcomponent S. Visit (Corresponding_Instance (S)); end if; S := Next_Node (S); end loop; end if; -- Call __po_hi_wait_initialization(). With this function, -- the main function will wait all other tasks initialization. N := CTU.Make_Call_Profile (RE (RE_Wait_Initialization), No_List); Append_Node_To_List (N, Statements); -- Make the call to __po_hi_wait_for_tasks(). This function will wait -- all other task. In fact, no task will terminate, so this function -- will only switch the main task to the sleep state all the time. N := CTU.Make_Call_Profile (RE (RE_Wait_For_Tasks)); Append_Node_To_List (N, CTN.Statements (Main_Function)); N := CTU.Make_Return_Statement (RE (RE_Main_Return)); Append_Node_To_List (N, CTN.Statements (Main_Function)); 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 begin case Get_Thread_Dispatch_Protocol (E) is when Thread_Periodic => Setup_Periodic_Thread (E); when Thread_Sporadic => Setup_Sporadic_Thread (E); when others => Display_Located_Error (Loc (E), "Thread is not periodic nor sporadic", Fatal => True); end case; end Visit_Thread_Instance; end Source_File; end Ocarina.Generators.PO_HI_C.Main;