------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Cheddar is a GNU GPL real time scheduling analysis tool. -- This program provides services to automatically check performances -- of real time architectures. -- -- Copyright (C) 2002-2010, by Frank Singhoff, Alain Plantec, Jerome Legrand -- -- The Cheddar project was started in 2002 by -- the LISyC Team, University of Western Britanny. -- -- Since 2008, Ellidiss technologies also contributes to the development of -- Cheddar and provides industrial support. -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program 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 -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- -- -- Contact : cheddar@listes.univ-brest.fr -- ----------------------------------------------------------------------------- -- Last update : -- $Rev: 523 $ -- $Date: 2012-09-26 15:09:39 +0200 (Wed, 26 Sep 2012) $ -- $Author: fotsing $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Translate; use Translate; with Xml_Tag; use Xml_Tag; with Buffers.Extended; use Buffers.Extended; with Buffer_Set; use Buffer_Set; use Buffer_Set.Generic_Buffer_Set; with unbounded_strings; use unbounded_strings; with Framework; use Framework; with Call_Scheduling_Framework; use Call_Scheduling_Framework; with Multiprocessor_Services_Interface; use Multiprocessor_Services_Interface; use Multiprocessor_Services_Interface.Scheduling_Result_Per_Processor_Package; with Tasks; use Tasks; with Queueing_Systems; use Queueing_Systems; with Queueing_System; use Queueing_System; with Queueing_System.theoretical; use Queueing_System.theoretical; with Queueing_System.theoretical.Mp1; use Queueing_System.theoretical.Mp1; with Queueing_System.theoretical.Pp1; use Queueing_System.theoretical.Pp1; with Queueing_System.theoretical.Mm1; use Queueing_System.theoretical.Mm1; with Queueing_System.theoretical.Md1; use Queueing_System.theoretical.Md1; with Queueing_System.theoretical.Mg1; use Queueing_System.theoretical.Mg1; with double_util; use double_util; with Ada.Numerics.Aux; use Ada.Numerics.Aux; with Debug; use Debug; with Dependency_Services; use Dependency_Services; package body Call_Memory_Framework is procedure Compute_Buffer_Scheduling_Simulation (Sys : in System; Result : in out Unbounded_String; A_Processor : in Generic_Processor_Ptr; Output : in Output_Format := String_Output) is A_Buffer : Buffer_Ptr; My_Iterator : Buffers_Iterator; Index : Scheduling_Table_Range := 0; A_Buffer_Result : Buffer_Size_Table_Ptr; A_Task : Generic_Task_Ptr; Maximum_Size : Natural; Maximum_Waiting_Time : Natural; Average_Size : Double; Average_Waiting_Time : Double; Average_Consumer_Period : Double := 0.0; Sum_Period : Double := 0.0; Nb_Consumer : Double := 0.0; begin Put_Debug ("Call Compute_Buffer_Scheduling_Simulation"); -- find the processor on which we want to compute buffer utilization -- for I in 0 .. Sched.nb_entries - 1 loop if Sched.entries (I).item.name = A_Processor.name then if Sched.entries (I).data.error_msg = empty_string then Index := I; exit; end if; end if; end loop; -- Compute buffer utilization on all buffer of the -- selected processor -- A_Buffer_Result := new Buffer_Size_Table; loop current_element (Sys.Buffers, A_Buffer, My_Iterator); if A_Processor.name = A_Buffer.cpu_name then initialize (A_Buffer_Result.all); Compute_Buffer_Size_From_Simulation (Sched.entries (Index).data.result, A_Buffer, A_Buffer_Result); add (Buff, A_Buffer, A_Buffer_Result.all); -- Compute average consumer period -- Average_Consumer_Period := 0.0; Sum_Period := 0.0; Nb_Consumer := 0.0; for J in 0 .. A_Buffer.roles.nb_entries - 1 loop if (A_Buffer.roles.entries (J).data.the_role = queuing_Consumer) then A_Task := Search_Task (Sys.Tasks, A_Buffer.roles.entries (J).item); if (A_Task.task_type = Periodic_Type) then Sum_Period := +Double (Periodic_Task_Ptr (A_Task).period); Nb_Consumer := Nb_Consumer + 1.0; end if; end if; end loop; Average_Consumer_Period := Sum_Period / Nb_Consumer; -- Compute results -- Maximum_Size := Compute_Maximum_Buffer_Size_From_Simulation (A_Buffer_Result); Average_Size := Compute_Average_Buffer_Size_From_Simulation (A_Buffer_Result); Maximum_Waiting_Time := Compute_Maximum_Waiting_Time_From_Simulation (A_Buffer_Result, Average_Consumer_Period); Average_Waiting_Time := Compute_Average_Waiting_Time_From_Simulation (A_Buffer_Result, Average_Consumer_Period); -- Display results -- Result := Result & unbounded_lf & unbounded_lf & Start_Task & Lb_Buffer (Current_Language) & " " & A_Buffer.name & To_Unbounded_String (" => ") & unbounded_lf; Result := Result & To_Unbounded_String (" ") & Lb_Maximum_Buffer_Size (Current_Language) & Maximum_Size'Img & unbounded_lf & To_Unbounded_String (" ") & Lb_Maximum_Waiting_Time (Current_Language) & Maximum_Waiting_Time'Img & unbounded_lf; Result := Result & To_Unbounded_String (" ") & Lb_Average_Buffer_Size (Current_Language) & format (Average_Size, 8) & unbounded_lf & To_Unbounded_String (" ") & Lb_Average_Waiting_Time (Current_Language) & format (Average_Waiting_Time, 8) & unbounded_lf; end if; exit when is_last_element (Sys.Buffers, My_Iterator); next_element (Sys.Buffers, My_Iterator); end loop; free (A_Buffer_Result); end Compute_Buffer_Scheduling_Simulation; procedure Compute_Buffer_Feasibility_Tests (Sys : in System; Result : in out Unbounded_String; A_Processor : in Generic_Processor_Ptr; Output : in Output_Format := String_Output) is A_Buffer : Buffer_Ptr; Waiting_Time : Double := 0.0; Occupation : Double := 0.0; Reference, Ref1, Ref2 : Unbounded_String; My_Iterator : iterator; Nb_Arrival : Double := 0.0; Nb_Server : Double := 0.0; My_Consumer_Task : Generic_Task_Ptr; Service_Rate : Double := 0.0; Arrival_Rate : Double := 0.0; A_Mm1_Queueing_System : Mm1_Queueing_System_theoretical; A_Md1_Queueing_System : Md1_Queueing_System_theoretical; A_Mg1_Queueing_System : Mg1_Queueing_System_theoretical; A_Mp1_Queueing_System : Mp1_Queueing_System_theoretical; A_Pp1_Queueing_System : Pp1_Queueing_System_theoretical; No_Performance_Criteria : Boolean := False; begin Put_Debug ("Call Compute_Buffer_Feasibility_Tests"); if Output = Xml_Output then Set_Tag; else Set_Empty; end if; Result := unbounded_lf & Start_Line & unbounded_lf; reset_iterator (Sys.Buffers, My_Iterator); loop current_element (Sys.Buffers, A_Buffer, My_Iterator); if (A_Buffer.cpu_name = A_Processor.name) then if (Natural (A_Buffer.roles.nb_entries) >= 1) then begin Result := Result & unbounded_lf & unbounded_lf & Start_Task & Lb_Buffer (Current_Language) & " " & A_Buffer.name & To_Unbounded_String (" => (") & Qs_To_Display_String (A_Buffer.queueing_system_type) & To_Unbounded_String (")") & unbounded_lf; Ref1 := empty_string; Ref2 := empty_string; Reference := empty_string; Nb_Arrival := 0.0; Nb_Server := 0.0; No_Performance_Criteria := False; -- Number of producer (arrival) and consumer (server) -- for J in 0 .. A_Buffer.roles.nb_entries - 1 loop if (A_Buffer.roles.entries (J).data.the_role = queuing_Producer) then Nb_Arrival := Nb_Arrival + 1.0; end if; if (A_Buffer.roles.entries (J).data.the_role = queuing_Consumer) then My_Consumer_Task := Search_Task (Sys.Tasks, A_Buffer.roles.entries (J).item); Nb_Server := Nb_Server + 1.0; end if; end loop; -- Control before buffer computation -- Periodic_Buffer_Control (Sys.Tasks, A_Buffer); Buffer_Flow_Control (A_Buffer, Sys.Tasks, Service_Rate, Arrival_Rate); case A_Buffer.queueing_system_type is when Qs_Mm1 => -- initalization -- Reset (A_Mm1_Queueing_System); Set_Qs_Arrival_Rate (A_Mm1_Queueing_System, Arrival_Rate); Set_Qs_Service_Rate (A_Mm1_Queueing_System, Service_Rate); Set_Qs_Nb_Arrival (A_Mm1_Queueing_System, Nb_Arrival); Set_Qs_Nb_Server (A_Mm1_Queueing_System, Nb_Server); Set_Qs_Harmonic (A_Mm1_Queueing_System, Is_Cons_Prod_Harmonic (A_Buffer, Sys.Tasks)); -- consumer response time -- Set_Constant_Consumer_Response_Time (A_Mm1_Queueing_System, Double (My_Consumer_Task.deadline)); if (Nb_Server <= 1.0) then -- occupation computation -- Queueing_System.theoretical.Mm1. Qs_Average_Number_Customer (A_Mm1_Queueing_System, Occupation); -- waiting time computation -- Queueing_System.theoretical.Mm1. Qs_Average_Waiting_Time (A_Mm1_Queueing_System, Waiting_Time); -- Update message to be displayed -- Ref1 := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[12], page 96, ") & Lb_Theorem (Current_Language) & To_Unbounded_String ("3.24). "); Ref2 := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[12], page 98, ") & Lb_Theorem (Current_Language) & To_Unbounded_String ("3.26). "); Reference := To_Unbounded_String (" ") & Lb_Average_Buffer_Size (Current_Language) & format (Occupation, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref1 & End_Ref & unbounded_lf & To_Unbounded_String (" ") & Lb_Average_Waiting_Time (Current_Language) & format (Waiting_Time, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref2 & End_Ref & End_Task & unbounded_lf & End_Line & End_Buf_Bound & unbounded_lf; else No_Performance_Criteria := True; end if; when Qs_Md1 => -- initalization -- Reset (A_Md1_Queueing_System); Set_Qs_Arrival_Rate (A_Md1_Queueing_System, Arrival_Rate); Set_Qs_Service_Rate (A_Md1_Queueing_System, Service_Rate); Set_Qs_Nb_Arrival (A_Md1_Queueing_System, Nb_Arrival); Set_Qs_Nb_Server (A_Md1_Queueing_System, Nb_Server); Set_Qs_Harmonic (A_Md1_Queueing_System, Is_Cons_Prod_Harmonic (A_Buffer, Sys.Tasks)); -- consumer response time -- Set_Constant_Consumer_Response_Time (A_Md1_Queueing_System, Double (My_Consumer_Task.deadline)); if (Nb_Server <= 1.0) then -- occupation computation -- Queueing_System.theoretical.Md1. Qs_Average_Number_Customer (A_Md1_Queueing_System, Occupation); -- waiting time computation -- Queueing_System.theoretical.Md1. Qs_Average_Waiting_Time (A_Md1_Queueing_System, Waiting_Time); -- Update message to be displayed -- Ref1 := To_Unbounded_String ("to be filled"); Ref2 := To_Unbounded_String ("to be filled"); Reference := To_Unbounded_String (" ") & Lb_Average_Buffer_Size (Current_Language) & format (Occupation, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref1 & End_Ref & unbounded_lf & To_Unbounded_String (" ") & Lb_Average_Waiting_Time (Current_Language) & format (Waiting_Time, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref2 & End_Ref & End_Task & unbounded_lf & End_Line & End_Buf_Bound & unbounded_lf; else No_Performance_Criteria := True; end if; when Qs_Mg1 => -- initalization -- Reset (A_Mg1_Queueing_System); Set_Qs_Arrival_Rate (A_Mg1_Queueing_System, Arrival_Rate); Set_Qs_Service_Rate (A_Mg1_Queueing_System, Service_Rate); Set_Qs_Nb_Arrival (A_Mg1_Queueing_System, Nb_Arrival); Set_Qs_Nb_Server (A_Mg1_Queueing_System, Nb_Server); Set_Qs_Harmonic (A_Mg1_Queueing_System, Is_Cons_Prod_Harmonic (A_Buffer, Sys.Tasks)); -- consumer response time -- Set_Constant_Consumer_Response_Time (A_Mg1_Queueing_System, Double (My_Consumer_Task.deadline)); if (Nb_Server <= 1.0) then -- occupation computation -- Queueing_System.theoretical.Mg1. Qs_Average_Number_Customer (A_Mg1_Queueing_System, Occupation); -- waiting time computation -- Queueing_System.theoretical.Mg1. Qs_Average_Waiting_Time (A_Mg1_Queueing_System, Waiting_Time); -- Update message to be displayed -- Ref1 := To_Unbounded_String ("to be filled"); Ref2 := To_Unbounded_String ("to be filled"); Reference := To_Unbounded_String (" ") & Lb_Average_Buffer_Size (Current_Language) & format (Occupation, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref1 & End_Ref & unbounded_lf & To_Unbounded_String (" ") & Lb_Average_Waiting_Time (Current_Language) & format (Waiting_Time, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref2 & End_Ref & End_Task & unbounded_lf & End_Line & End_Buf_Bound & unbounded_lf; else No_Performance_Criteria := True; end if; when Qs_Mp1 => -- initalization -- Reset (A_Mp1_Queueing_System); Set_Qs_Arrival_Rate (A_Mp1_Queueing_System, Arrival_Rate); Set_Qs_Service_Rate (A_Mp1_Queueing_System, Service_Rate); Set_Qs_Nb_Arrival (A_Mp1_Queueing_System, Nb_Arrival); Set_Qs_Nb_Server (A_Mp1_Queueing_System, Nb_Server); Set_Qs_Harmonic (A_Mp1_Queueing_System, Is_Cons_Prod_Harmonic (A_Buffer, Sys.Tasks)); -- consumer response time -- Set_Constant_Consumer_Response_Time (A_Mp1_Queueing_System, Double (My_Consumer_Task.deadline)); if (Nb_Server <= 1.0) then -- occupation computation -- Queueing_System.theoretical.Mp1. Qs_Average_Number_Customer (A_Mp1_Queueing_System, Occupation); -- waiting time computation -- Queueing_System.theoretical.Mp1. Qs_Average_Waiting_Time (A_Mp1_Queueing_System, Waiting_Time); -- Update message to be displayed -- Ref1 := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[10], ") & Lb_Theorem (Current_Language) & To_Unbounded_String ("6). "); Ref2 := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[10], ") & Lb_Theorem (Current_Language) & To_Unbounded_String ("6). "); Reference := To_Unbounded_String (" ") & Lb_Average_Buffer_Size (Current_Language) & format (Occupation, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref1 & End_Ref & unbounded_lf & To_Unbounded_String (" ") & Lb_Average_Waiting_Time (Current_Language) & format (Waiting_Time, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref2 & End_Ref & End_Task & unbounded_lf & End_Line & End_Buf_Bound & unbounded_lf; else No_Performance_Criteria := True; end if; when Qs_Pp1 => -- initalization -- Reset (A_Pp1_Queueing_System); Set_Qs_Arrival_Rate (A_Pp1_Queueing_System, Arrival_Rate); Set_Qs_Service_Rate (A_Pp1_Queueing_System, Service_Rate); Set_Qs_Nb_Arrival (A_Pp1_Queueing_System, Nb_Arrival); Set_Qs_Nb_Server (A_Pp1_Queueing_System, Nb_Server); Set_Qs_Harmonic (A_Pp1_Queueing_System, Is_Cons_Prod_Harmonic (A_Buffer, Sys.Tasks)); -- consumer response time -- Set_Constant_Consumer_Response_Time (A_Mp1_Queueing_System, Double (My_Consumer_Task.deadline)); if (Nb_Server <= 1.0) then -- occupation computation -- Queueing_System.theoretical.Pp1. Qs_Maximum_Number_Customer (A_Pp1_Queueing_System, Occupation); -- waiting time computation -- Queueing_System.theoretical.Pp1. Qs_Maximum_Waiting_Time (A_Pp1_Queueing_System, Waiting_Time); -- Update message to be displayed -- Ref1 := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[4,10], ") & Lb_Theorem (Current_Language) & To_Unbounded_String ("1 or 8). "); Ref2 := To_Unbounded_String (" (") & Lb_See (Current_Language) & To_Unbounded_String ("[10], ") & Lb_Theorem (Current_Language) & To_Unbounded_String ("8). "); Reference := To_Unbounded_String (" ") & Lb_Maximum_Buffer_Size (Current_Language) & format (Occupation, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref1 & End_Ref & unbounded_lf & To_Unbounded_String (" ") & Lb_Maximum_Waiting_Time (Current_Language) & format (Waiting_Time, 8) & unbounded_lf & To_Unbounded_String (" ") & Start_Ref & Ref2 & End_Ref & End_Task & unbounded_lf & End_Line & End_Buf_Bound & unbounded_lf; else No_Performance_Criteria := True; end if; when others => No_Performance_Criteria := True; end case; if No_Performance_Criteria then Result := Result & To_Unbounded_String (" ") & Lb_Compute_Buffer_Error_4 (Current_Language) & unbounded_lf; else Result := Result & Reference; end if; exception when Not_Implemented => Result := Result & To_Unbounded_String (" ") & Lb_Compute_Buffer_Error_4 (Current_Language) & unbounded_lf; when Task_Set.Task_Model_Error => Result := Result & To_Unbounded_String (" ") & Lb_Compute_Buffer_Error_3 (Current_Language) & unbounded_lf; when Dependency_Services.Task_Must_Be_Periodic => Result := Result & To_Unbounded_String (" ") & Lb_Compute_Buffer_Error_2 (Current_Language) & unbounded_lf; when Flow_Constraint_Not_Respected => Result := Result & To_Unbounded_String (" ") & Lb_Compute_Buffer_Error_1 (Current_Language) & unbounded_lf; end; else Result := Result & To_Unbounded_String (" ") & A_Buffer.name & To_Unbounded_String (" => NA"); end if; end if; exit when is_last_element (Sys.Buffers, My_Iterator); next_element (Sys.Buffers, My_Iterator); end loop; end Compute_Buffer_Feasibility_Tests; procedure Compute_Memory_Requirement_Analysis (Sys : in System; Result : in out Unbounded_String; Update_Address_Spaces_Set : in Boolean; Output : in Output_Format := String_Output) is begin Put_Debug ("Call Compute_Memory_Requirement_Analysis"); Result := To_Unbounded_String ("to be written"); end Compute_Memory_Requirement_Analysis; end Call_Memory_Framework;