----------------------------------------------------------- --------------------- ------------------------------------------------------------------------------ -- 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 Tasks; use Tasks; with Task_Set; use Task_Set; use Task_Set.Generic_Task_Set; with Processor_Set; use Processor_Set; use Processor_Set.Generic_Processor_Set; with Buffer_Set; use Buffer_Set; use Buffer_Set.Generic_Buffer_Set; with Processors; use Processors; with Random_Tools; use Random_Tools; with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random; with Ada.Numerics.Aux; use Ada.Numerics.Aux; with Text_IO; use Text_IO; with Buffers; use Buffers; use Buffers.Buffer_Roles_Package; with fixed_strings; use fixed_strings; with natural_util; use natural_util; with double_util; use double_util; with Ada.Sequential_IO; package body Random_Scheduling is -- display an array of respone time table procedure Put (Res_Time_Set : in Response_Table_Set; Nb_Res_Time_Set : in Natural) is begin for J in 1 .. Nb_Res_Time_Set loop for I in 0 .. Res_Time_Set (J).nb_entries - 1 loop Put_Line ("Task " & To_String (Res_Time_Set (J).entries (I).item.name) & ", r = " & Res_Time_Set (J).entries (I).data'Img); end loop; end loop; end Put; procedure Random_Buff_Size_Plot (Nb_Rand_Scheduling : Natural; Nb_Base_Period : Natural; Save_Response : Boolean; Save_Buff_Response : Natural; Save_File_Name : Unbounded_String; Sys : System) is type Save_Descriptor is record Task_Name : fixed_string; Eol1 : Character := ASCII.LF; Resp_Time : fixed_string; Deadline : fixed_string; Buff_Size : fixed_string; end record; package Save_File is new Ada.Sequential_IO (Save_Descriptor); use Save_File; -- types type Natural_Tab is array (Tasks_Range range <>) of Natural; type Natural_Tab_Ptr is access Natural_Tab; -- variables A_Buffer : Buffer_Ptr; A_Task : Generic_Task_Ptr; A_Processor : Generic_Processor_Ptr; My_Iterator_Task : Tasks_Iterator; My_Iterator_Buf : Buffers_Iterator; My_Iterator_Proc : Processors_Iterator; Res_Time : Response_Time_Table; -- array of random response time Buff_Size : Natural; -- size of the buffer Seed : Generator; I_Min_Resp_Time : Response_Time_Range; Cnt_Final : Natural_Tab_Ptr; -- array of the maximum number of response time generation Continu : Boolean; Max_Buff_Size : Natural; Buff_Bound : constant Natural := 0; -- maximum size of the buffer Lcm : Natural; -- study period Min_Resp : Natural; Max_Resp : Natural; Nb_Max_Activation : Natural; Nb_Tasks : Tasks_Range; L : Tasks_Range; K : Response_Time_Range; F_Desc : Save_File.File_Type; Desc : Save_Descriptor; File_Name : Unbounded_String; Cnt_File : Natural; -- return the index of the minimum response time function Min_Res_Time (Min : in Response_Time_Table) return Response_Time_Range is Minimum : Response_Time_Range; begin Minimum := 0; for I in 1 .. (Min.nb_entries - 1) loop if (Min.entries (I).data < Min.entries (Minimum).data) then Minimum := I; end if; end loop; return Minimum; end Min_Res_Time; begin -- !!! INIT !!! -- control : one processor, one buffer and only producer and consumer reset_iterator (Sys.Processors, My_Iterator_Proc); current_element (Sys.Processors, A_Processor, My_Iterator_Proc); reset_iterator (Sys.Buffers, My_Iterator_Buf); current_element (Sys.Buffers, A_Buffer, My_Iterator_Buf); Lcm := Scheduling_Period (Sys. -- only one processor Tasks, A_Processor.name); K := 0; L := 0; Res_Time.nb_entries := 0; Nb_Tasks := Get_Number_Of_Task_From_Processor (Sys.Tasks, A_Processor.name); Cnt_Final := new Natural_Tab (0 .. Nb_Tasks); reset_iterator (Sys.Tasks, My_Iterator_Task); loop -- take a task current_element (Sys.Tasks, A_Task, My_Iterator_Task); -- number of response time generation for each task Cnt_Final (L) := Lcm / Periodic_Task_Ptr (A_Task).period * Nb_Base_Period * Nb_Rand_Scheduling; -- intialization of the response time table Res_Time.entries (K).data := Double'Last; Res_Time.entries (K).item := A_Task; Res_Time.nb_entries := Res_Time.nb_entries + 1; -- display the information Put_Line ("#" & To_String (A_Task.name) & " P = " & Periodic_Task_Ptr (A_Task).period'Img & ", D = " & A_Task.deadline'Img); -- next task L := L + 1; K := K + 1; exit when is_last_element (Sys.Tasks, My_Iterator_Task); next_element (Sys.Tasks, My_Iterator_Task); end loop; Reset (Seed); Cnt_File := 0; Put_Line ("# Buffer bound = " & Buff_Bound'Img); -- plot the buffer size for T in 0 .. (Nb_Rand_Scheduling - 1) loop -- init Buff_Size := 0; Max_Buff_Size := 0; if (Save_Response) then File_Name := Save_File_Name & To_Unbounded_String ("_") & format (Cnt_File) & To_Unbounded_String (".sav"); -- Put_Line(File_name); Create (F_Desc, Mode => Out_File, Name => To_String (File_Name)); end if; -- start random response time generation Continu := True; while (Continu) loop Continu := False; -- if the buffer size doesn't change, stop the program K := 0; L := 0; reset_iterator (Sys.Tasks, My_Iterator_Task); loop -- take a task current_element (Sys.Tasks, A_Task, My_Iterator_Task); -- number maximum of activation during base period Nb_Max_Activation := Lcm / Periodic_Task_Ptr (A_Task).period * Nb_Base_Period; -- generate a response time if needed if (Res_Time.entries (K).data = Double'Last and Cnt_Final (L) > (Nb_Rand_Scheduling - T - 1) * Nb_Max_Activation) then Min_Resp := (Nb_Max_Activation * (Nb_Rand_Scheduling - T) - Cnt_Final (L)) * Periodic_Task_Ptr (A_Task).period; Max_Resp := Min_Resp + A_Task.deadline - 1; Res_Time.entries (K).data := Double (Get_Rand_Parameter (Min_Resp, Max_Resp, Seed)); Cnt_Final (L) := Cnt_Final (L) - 1; -- save data if (Save_Response) then Desc.Task_Name := To_Bounded_String (To_String (A_Task.name)); Desc.Resp_Time := To_Bounded_String (To_String (format (Res_Time.entries (K).data))); Desc.Deadline := To_Bounded_String (To_String (To_Unbounded_String (Max_Resp'Img))); Desc.Buff_Size := To_Bounded_String (To_String (To_Unbounded_String (Buff_Size'Img))); -- save the tasks response time in a file for further --studies Write (F_Desc, Desc); end if; end if; -- next task L := L + 1; K := K + 1; exit when is_last_element (Sys.Tasks, My_Iterator_Task); next_element (Sys.Tasks, My_Iterator_Task); end loop; -- find the minimum response time I_Min_Resp_Time := Min_Res_Time (Res_Time); -- the task A_Task := Res_Time.entries (I_Min_Resp_Time).item; -- Put_Line("min " & A_Task.Name & ", r=" & --Res_Time.Entries(I_Min_Resp_Time).Data'img); -- search for the type of the task which has the minimum response --time -- (if equalitie, worst case if consumption before production) for J in 0 .. Buffer_Roles_Range (Nb_Tasks - 1) loop if (Res_Time.entries (I_Min_Resp_Time).data < Double'Last) then if (A_Buffer.roles.entries (J).item = A_Task.name) then if (A_Buffer.roles.entries (J).data.the_role = Queuing_Consumer) then if (Buff_Size > 0) then Buff_Size := Buff_Size - 1; end if; Continu := True; -- new response time generation Res_Time.entries (I_Min_Resp_Time).data := Double'Last; -- Put_Line(To_Unbounded_String("Buffer size = ") & --Buff_Size'img); else if (A_Buffer.roles.entries (J).data.the_role = Queuing_Producer) then Buff_Size := Buff_Size + 1; if (Buff_Size > Max_Buff_Size) then Max_Buff_Size := Buff_Size; end if; Continu := True; -- new response time generation Res_Time.entries (I_Min_Resp_Time).data := Double'Last; -- Put_Line(To_Unbounded_String("Buffer size = ") & --Buff_Size'img); end if; end if; end if; end if; end loop; -- end for -- Put_Line(To_Unbounded_String("Buffer size = ") & Buff_Size'img); end loop; -- end while -- Put_Line("Maximum buffer size = " & Max_Buff_Size'img); if (Max_Buff_Size >= Save_Buff_Response) then Cnt_File := Cnt_File + 1; end if; if (Max_Buff_Size > Buff_Bound) then Put_Line ("# WARNING !!! max occupation = " & Max_Buff_Size'Img & "Bound = " & Buff_Bound'Img); end if; if (Save_Response) then Close (F_Desc); -- close the old file end if; -- use with gnuplot Put_Line (T'Img & " " & Max_Buff_Size'Img); end loop; -- end for nb tasks set generation end Random_Buff_Size_Plot; end Random_Scheduling;