------------------------------------- ------------------------------------------- -- -- -- 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;