Commit 36cb0ba1 authored by bouazizrahma's avatar bouazizrahma Committed by Jerome Hugues
Browse files

code generation for many BA transitions of a thread

parent 0cbbf704
......@@ -82,11 +82,73 @@ package body Ocarina.Backends.C_Common.BA is
-- function Get_Instances_Of_Component_Type
-- (Root : Node_Id; E : Node_Id) return Node_Id;
function Get_Behavior_Specification
(S : Node_Id) return Node_Id;
function Map_Used_Type (N : Node_Id) return Node_Id;
procedure Map_C_Many_Transitions_Of_A_Thread
(S : Node_Id;
Declarations : List_Id;
Statements : List_Id);
procedure Map_BA_States_To_C_Types
(S : Node_Id);
function Is_State_Kind_Type_Declaration_Exist
return Boolean;
procedure Make_States_Initialization_Function
(S : Node_Id);
function Search_State_Kind
(BA : Node_Id;
State_Idt : Node_Id) return Ocarina.Types.Byte;
function Find_Index_In_States_Array
(BA : Node_Id;
State_Idt : Node_Id) return Unsigned_Long_Long;
procedure Update_Current_State
(E : Node_Id;
BA : Node_Id;
Transition_Node : Node_Id;
Stats : List_Id);
function Map_C_Transition_Node
(Node : Node_Id;
S : Node_Id;
Declarations : List_Id;
Statements : List_Id;
Else_St : List_Id) return List_Id;
procedure Map_C_A_List_Of_Transitions
(S : Node_Id;
BA : Node_Id;
Otherwise_Transition_Node : Node_Id;
Sub_Transition_List : List_Id;
WDeclarations : List_Id;
WStatements : List_Id);
procedure Examine_Current_State_Until_Reaching_Complete_State
(S : Node_Id;
BA : Node_Id;
WDeclarations : List_Id;
WStatements : List_Id);
procedure Make_BA_Initialization_Function
(S : Node_Id);
procedure Map_C_Implementation_of_BA_Body_Function
(S : Node_Id;
Declarations : List_Id;
Statements : List_Id);
procedure Make_BA_Body_Function
(S : Node_Id;
Declarations : List_Id;
Statements : List_Id);
function Map_C_State_Kind_Name
(State_Kind : Ocarina.Types.Byte) return Node_Id;
procedure Map_C_Behavior_Action_Block
(Node : Node_Id;
S : Node_Id;
......@@ -318,6 +380,30 @@ package body Ocarina.Backends.C_Common.BA is
--
-- end Get_Instances_Of_Component_Type;
------------------------------
-- Is_To_Make_Init_Sequence --
------------------------------
function Is_To_Make_Init_Sequence (S : Node_Id) return Boolean
is
BA : Node_Id;
State : Node_Id;
Result : Boolean := False;
begin
BA := Get_Behavior_Specification (S);
State := BATN.First_Node (BATN.States (BA));
while Present (State) loop
Result := Behavior_State_Kind'Val (BATN.State_Kind (State))
= BSK_Initial;
exit when Result;
State := BATN.Next_Node (State);
end loop;
return Result;
end Is_To_Make_Init_Sequence;
--------------------------------
-- Get_Behavior_Specification --
--------------------------------
......@@ -449,13 +535,13 @@ package body Ocarina.Backends.C_Common.BA is
end Map_C_Behavior_Variables;
----------------------------
-- Map_C_Behavior_Actions --
----------------------------
--------------------------------
-- Map_C_Behavior_Transitions --
--------------------------------
procedure Map_C_Behavior_Actions (S : Node_Id;
Declarations : List_Id;
Statements : List_Id)
procedure Map_C_Behavior_Transitions (S : Node_Id;
Declarations : List_Id;
Statements : List_Id)
is
BA : Node_Id;
behav_transition : Node_Id;
......@@ -464,40 +550,1429 @@ package body Ocarina.Backends.C_Common.BA is
BA := Get_Behavior_Specification (S);
-- For an AADL subprogram with BA, we have: a single state
-- as initial final state; a single transition without
-- condition with a Behavior_Action_Block.
-- Thus, we need to map the Behavior_Action_Block
-- To C-statements in the generated C-subprogram
--
if not BANu.Is_Empty (BATN.Transitions (BA)) then
behav_transition := BATN.First_Node (BATN.Transitions (BA));
Transition_Node := BATN.Transition (behav_transition);
if Present (behav_transition) and then
Present (BATN.Behavior_Action_Block (Transition_Node))
if BANu.Length (BATN.Transitions (BA)) = 1 then
if AINU.Is_Thread (S) then
Map_C_Behavior_Variables (S, Declarations);
end if;
if Present (BATN.Behavior_Action_Block (Transition_Node)) then
if BATN.Kind (Transition_Node) =
BATN.K_Execution_Behavior_Transition
then
-- For an AADL subprogram or thread with BA that includes
-- a unique transition, the Behavior_Action_Block
-- of this transition is mapped into C-statements.
Map_C_Behavior_Action_Block
(BATN.Behavior_Action_Block (Transition_Node),
S, Declarations, Statements);
if AINU.Is_Thread (S) then
Map_C_Implementation_of_BA_Body_Function
(S, Declarations, Statements);
end if;
else
-- i.e. Kind (Transition_Node) = K_Mode_Transition
-- We do not support Mode transition in a subprogram
--
Display_Error
("Mode Transition is not supported",
Fatal => True);
end if;
end if;
else
-- For an AADL subprogram with BA, many transitions
-- are not supported.
if AINU.Is_Subprogram (S) then
Display_Error
("Many transitions in the BA of a"
& "subprogram are not supported",
Fatal => True);
elsif AINU.Is_Thread (S) then
if Get_Thread_Dispatch_Protocol (S) = Thread_Periodic then
Map_C_Many_Transitions_Of_A_Thread
(S, Declarations, Statements);
else
Display_Error
("The mapping of many transitions in the BA of a non-periodic"
& "thread is not supported",
Fatal => True);
end if;
end if;
end if;
end if;
end Map_C_Behavior_Transitions;
------------------------------------------
-- Is_State_Kind_Type_Declaration_Exist --
------------------------------------------
function Is_State_Kind_Type_Declaration_Exist
return Boolean
is
Result : Boolean := False;
decl : Node_Id;
begin
decl := CTN.First_Node (CTN.Declarations (Current_File));
while Present (decl) loop
if Kind (decl) = CTN.K_Enumeration_Literals
and then
Standard.Utils.To_Lower
(CTN.Name (CTN.Defining_Identifier
(decl)))
= Standard.Utils.To_Lower
(Get_String_Name ("__po_hi_state_kind_t"))
then
if BATN.Kind (Transition_Node) =
BATN.K_Execution_Behavior_Transition
Result := True;
end if;
exit when Result;
decl := CTN.Next_Node (decl);
end loop;
return Result;
end Is_State_Kind_Type_Declaration_Exist;
------------------------------
-- Map_BA_States_To_C_Types --
------------------------------
procedure Map_BA_States_To_C_Types
(S : Node_Id)
is
BA : Node_Id;
State, List_Node : Node_Id;
N : Node_Id;
State_Enumerator_List : List_Id;
State_Kind_Enumerator_List : List_Id;
State_Struct : List_Id;
State_Identifier : Unsigned_Long_Long;
Nb_States : Unsigned_Long_Long;
Q : Name_Id;
Thread_Instance_Name : Name_Id;
E : constant Node_Id :=
AIN.Parent_Subcomponent (S);
begin
BA := Get_Behavior_Specification (S);
-- 1) Create an enumeration type declaration
-- called __po_hi_<<thread_instance_name>>_state_name_t
-- that enumerates all states in the BA of the thread
-- typedef enum
-- {
-- s0, s1, s2, s3
-- } __po_hi_producer_state_name_t;
State_Enumerator_List := New_List (CTN.K_Enumeration_Literals);
State := BATN.First_Node (BATN.States (BA));
State_Identifier := 0;
Nb_States := 0;
while Present (State) loop
if not BANu.Is_Empty (BATN.Identifiers (State)) then
List_Node := BATN.First_Node (BATN.Identifiers (State));
while Present (List_Node) loop
N := CTU.Make_Defining_Identifier
(BATN.Display_Name (List_Node));
-- N := Make_Expression
-- (CTU.Make_Defining_Identifier
-- (BATN.Display_Name (List_Node)),
-- Op_Equal,
-- Make_Literal
-- (CV.New_Int_Value (State_Identifier, 0, 10)));
Append_Node_To_List (N, State_Enumerator_List);
State_Identifier := State_Identifier + 1;
Nb_States := Nb_States + 1;
List_Node := BATN.Next_Node (List_Node);
end loop;
end if;
State := BATN.Next_Node (State);
end loop;
Thread_Instance_Name := Map_Thread_Port_Variable_Name (S);
N :=
Message_Comment
("For each state in the BA of the thread instance << " &
Get_Name_String (Thread_Instance_Name) &
" >> add an enumerator");
Append_Node_To_List (N, CTN.Declarations (Current_File));
N :=
Make_Full_Type_Declaration
(Defining_Identifier => Make_Defining_Identifier
(Map_C_Variable_Name (E, State_Name_T => True)),
Type_Definition => Make_Enum_Aggregate (State_Enumerator_List));
Append_Node_To_List (N, CTN.Declarations (Current_File));
-- 2) Create an enumeration type declaration
-- called state_kind
-- that enumerates all possible kinds of state
--
-- typedef enum
-- {
-- __po_hi_initial,
-- __po_hi_initial_complete,
-- __po_hi_initial_complete_final,
-- __po_hi_initial_final,
-- __po_hi_complete,
-- __po_hi_complete_final,
-- __po_hi_final,
-- __po_hi_execution
-- } __po_hi_state_kind_t;
--
if not Is_State_Kind_Type_Declaration_Exist then
State_Kind_Enumerator_List := New_List (CTN.K_Enumeration_Literals);
Append_Node_To_List (RE (RE_Initial), State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Initial_Complete),
State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Initial_Complete_Final),
State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Initial_Final),
State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Complete), State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Complete_Final),
State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Final), State_Kind_Enumerator_List);
Append_Node_To_List (RE (RE_Execution), State_Kind_Enumerator_List);
N :=
Make_Full_Type_Declaration
(Defining_Identifier => RE (RE_State_Kind_T),
Type_Definition => Make_Enum_Aggregate
(State_Kind_Enumerator_List));
Append_Node_To_List (N, CTN.Declarations (Current_File));
end if;
-- 3)
-- typedef struct
-- {
-- __po_hi_<<thread_instance_name>>_state_name_t name;
-- __po_hi_state_kind_t kind;
-- } __po_hi_<<thread_instance_name>>_state_t;
State_Struct := New_List (CTN.K_Enumeration_Literals);
Set_Str_To_Name_Buffer ("name");
Q := Name_Find;
N :=
Make_Member_Declaration
(Defining_Identifier => Make_Defining_Identifier (Q),
Used_Type => Make_Defining_Identifier
(Map_C_Variable_Name (E, State_Name_T => True)));
Append_Node_To_List (N, State_Struct);
Set_Str_To_Name_Buffer ("kind");
Q := Name_Find;
N :=
Make_Member_Declaration
(Defining_Identifier => Make_Defining_Identifier (Q),
Used_Type => RE (RE_State_Kind_T));
Append_Node_To_List (N, State_Struct);
N :=
Make_Full_Type_Declaration
(Defining_Identifier => Make_Defining_Identifier
(Map_C_Variable_Name (E, State_T => True)),
Type_Definition =>
Make_Struct_Aggregate (Members => State_Struct));
Append_Node_To_List (N, CTN.Declarations (Current_File));
-- 4)
-- #define __po_hi_<<thread_instance_name>>_nb_states <<Nb_States>>
N :=
Make_Define_Statement
(Defining_Identifier => Make_Defining_Identifier
(Map_C_Define_Name (E, Nb_States => True)),
Value =>
Make_Literal
(CV.New_Int_Value (Nb_States, 1, 10)));
Append_Node_To_List (N, CTN.Declarations (Current_File));
-- 5)
-- __po_hi_<<thread_instance_name>>_state_t
-- __po_hi_<<thread_instance_name>>_states_array
-- [__po_hi_<<thread_instance_name>>_nb_states];
N :=
Make_Variable_Declaration
(Defining_Identifier =>
Make_Array_Declaration
(Defining_Identifier =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, States_Array => True)),
Array_Size =>
Make_Defining_Identifier
(Map_C_Define_Name (E, Nb_States => True))),
Used_Type =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, State_T => True)));
Append_Node_To_List (N, CTN.Declarations (Current_File));
-- 6)
-- __po_hi_<<thread_instance_name>>_state_t
-- __po_hi_<<thread_instance_name>>_current_state
N :=
Make_Variable_Declaration
(Defining_Identifier =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, Current_State => True)),
Used_Type =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, State_T => True)));
Append_Node_To_List (N, CTN.Declarations (Current_File));
end Map_BA_States_To_C_Types;
---------------------------
-- Map_C_State_Kind_Name --
---------------------------
function Map_C_State_Kind_Name
(State_Kind : Ocarina.Types.Byte) return Node_Id
is
Result : Node_Id;
begin
case Behavior_State_Kind'Val (State_Kind) is
when BSK_Initial => Result := RE (RE_Initial);
when BSK_Initial_Complete =>
Result := RE (RE_Initial_Complete);
when BSK_Initial_Complete_Final =>
Result := RE (RE_Initial_Complete_Final);
when BSK_Initial_Final =>
Result := RE (RE_Initial_Final);
when BSK_Complete => Result := RE (RE_Complete);
when BSK_Complete_Final =>
Result := RE (RE_Complete_Final);
when BSK_Final => Result := RE (RE_Final);
when BSK_No_Kind => Result := RE (RE_Execution);
when others => raise Program_Error;
end case;
return Result;
end Map_C_State_Kind_Name;
-----------------------------------------
-- Make_States_Initialization_Function --
-----------------------------------------
procedure Make_States_Initialization_Function
(S : Node_Id)
is
BA : Node_Id;
State, List_Node : Node_Id;
N, N1 : Node_Id;
State_Identifier : Unsigned_Long_Long;
Q : Name_Id;
E : constant Node_Id :=
AIN.Parent_Subcomponent (S);
WStatements : constant List_Id := New_List (CTN.K_Statement_List);
begin
BA := Get_Behavior_Specification (S);
-- 7)
-- void <<thread_name>>_states_initialization (void)
-- {
-- /* fill the __po_hi_producer_states_array with corresponding
-- states */
-- __po_hi_producer_states_array[0].name = s0;
-- __po_hi_producer_states_array[0].kind = __po_hi_initial;
--
-- __po_hi_producer_states_array[1].name = s1;
-- __po_hi_producer_states_array[1].kind = __po_hi_execution;
--
-- __po_hi_producer_states_array[2].name = s2;
-- __po_hi_producer_states_array[2].kind = __po_hi_execution;
--
-- __po_hi_producer_states_array[3].name = s3;
-- __po_hi_producer_states_array[3].kind = __po_hi_complete_final;
-- /* initialize the __po_hi_producer_current_state with */
-- /* the initial state */
-- __po_hi_producer_current_state = __po_hi_producer_states_array[0];
-- }
N1 := Make_Function_Specification
(Defining_Identifier => Make_Defining_Identifier
(Map_C_BA_Related_Function_Name
(E, States_Initialization => True)),
Parameters => No_List,
Return_Type => New_Node (CTN.K_Void));
N := Message_Comment ("fill the array "
& Get_Name_String
(Map_C_Variable_Name (E, States_Array => True))
& " with corresponding states");
CTU.Append_Node_To_List (N, WStatements);
State := BATN.First_Node (BATN.States (BA));
State_Identifier := 0;
while Present (State) loop
if not BANu.Is_Empty (BATN.Identifiers (State)) then
List_Node := BATN.First_Node (BATN.Identifiers (State));
while Present (List_Node) loop
Set_Str_To_Name_Buffer ("name");
Q := Name_Find;
CTU.Append_Node_To_List
(Make_Assignment_Statement
(Variable_Identifier => Make_Member_Designator
(Defining_Identifier => Make_Defining_Identifier (Q),
Aggregate_Name => Make_Array_Declaration
(Defining_Identifier =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, States_Array => True)),
Array_Size => Make_Literal
(CV.New_Int_Value (State_Identifier, 0, 10)))),
Expression => CTU.Make_Defining_Identifier
(BATN.Display_Name (List_Node))),
WStatements);
Set_Str_To_Name_Buffer ("kind");
Q := Name_Find;
CTU.Append_Node_To_List
(Make_Assignment_Statement
(Variable_Identifier => Make_Member_Designator
(Defining_Identifier => Make_Defining_Identifier (Q),
Aggregate_Name => Make_Array_Declaration
(Defining_Identifier =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, States_Array => True)),
Array_Size => Make_Literal
(CV.New_Int_Value (State_Identifier, 0, 10)))),
Expression => Map_C_State_Kind_Name
(State_Kind (State))),
WStatements);
State_Identifier := State_Identifier + 1;
List_Node := BATN.Next_Node (List_Node);
end loop;
end if;
State := BATN.Next_Node (State);
end loop;
N := Message_Comment ("Initialize the current state of the thread "
& Get_Name_String
(Map_C_Variable_Name (E, Current_State => True))
& " with the initial state");
CTU.Append_Node_To_List (N, WStatements);
CTU.Append_Node_To_List
(Make_Assignment_Statement
(Variable_Identifier => Make_Defining_Identifier
(Map_C_Variable_Name (E, Current_State => True)),
Expression => Make_Array_Declaration
(Defining_Identifier =>
Make_Defining_Identifier
(Map_C_Variable_Name (E, States_Array => True)),
Array_Size => Make_Literal
(CV.New_Int_Value (0, 0, 10)))),
WStatements);
N := Make_Function_Implementation
(Specification => N1,
Declarations => No_List,
Statements => WStatements);
Append_Node_To_List (N, CTN.Declarations (Current_File));
end Make_States_Initialization_Function;
----------------------
-- Search_State_Kind --
-----------------------
function Search_State_Kind