------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- Cheddar is a GNU GPL real-time scheduling analysis tool. -- This program provides services to automatically check schedulability and -- other performance criteria of real-time architecture models. -- -- Copyright (C) 2002-2020, Frank Singhoff, Alain Plantec, Jerome Legrand, -- Hai Nam Tran, Stephane Rubini -- -- The Cheddar project was started in 2002 by -- Frank Singhoff, Lab-STICC UMR 6285, Université de Bretagne Occidentale -- -- Cheddar has been published in the "Agence de Protection des Programmes/France" in 2008. -- Since 2008, Ellidiss technologies also contributes to the development of -- Cheddar and provides industrial support. -- -- The full list of contributors and sponsors can be found in AUTHORS.txt and SPONSORS.txt -- -- 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$ -- $Date$ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with ada.text_IO; use Ada.Text_IO; with Ada.Numerics.Generic_Elementary_Functions; package body Random_Tools is function Get_Rand_Parameter (Min : in Natural; Max : in Natural; Seed : in Generator) return Natural is Aux : Double; Res : Natural; begin Aux := Double (Random (Seed)) * (Double (Max) - Double (Min)) + Double (Min); Res := Natural (Aux); if (Res < Min) or (Res > Max) then raise Constraint_Error; end if; return Res; end Get_Rand_Parameter; function Get_Rand_Parameter (Min : in Double; Max : in Double; Seed : in Generator) return Double is Res : Double := 0.0; begin Res := Double (Random (Seed)) * (Max - Min) + Min; if (Res < Min) or (Res > Max) then raise Constraint_Error; end if; return Res; end Get_Rand_Parameter; -- generate poisson inter arrival time (different from 0) -- function Get_Exponential_Time (Arrival_Rate : in Double; Seed : in Generator) return Double is Result : Double; begin Result := -1.0 / Arrival_Rate * Log (Double (Random (Seed))); return (Result); end Get_Exponential_Time; pragma Warnings (Off); -- generate a uniform distribution of task utilizations -- function Gen_UUniFast (n : in Integer; -- Number of task U : in Float) -- Processor utilization return Float_Array -- Float array of task utilizations is type Value_Type is new Float; package Value_Functions is new Ada.Numerics.Generic_Elementary_Functions (Value_Type); use Value_Functions; utilizations_array : Float_Array(0..n-1); G : Generator; sumU : Float; nextSumU : Value_Type; begin Reset(G); sumU := U; for i in 1..n-1 loop nextSumU := Value_Type(sumU) * Value_Type(Random(G))**Value_Type(1.0/(n-i)); utilizations_array(i-1) := sumU - Float(nextSumU); sumU:= Float(nextSumU); end loop; utilizations_array(n-1) := sumU; return utilizations_array; end Gen_UUniFast; -- generate a uniform distribution of task utilizations -- function Gen_UUniFast (n : in Integer; -- Number of task U : in Integer) -- Processor utilization return Integer_Array -- Integer array of task utilizations is type Value_Type is new Float; package Value_Functions is new Ada.Numerics.Generic_Elementary_Functions (Value_Type); use Value_Functions; utilizations_array : Integer_Array(0..n-1); G : Generator; sumU : Float; nextSumU : Value_Type; begin Reset(G); sumU := Float(U); for i in 1..n-1 loop nextSumU := Value_Type(sumU) * Value_Type(Random(G))**Value_Type(1.0/(n-i)); utilizations_array(i-1) := Integer(float'Floor(sumU - Float(nextSumU))); sumU:= Float(nextSumU); end loop; utilizations_array(n-1) := Integer(U); for i in 0..n-2 loop utilizations_array(n-1) := utilizations_array(n-1) - utilizations_array(i); end loop; return utilizations_array; end Gen_UUniFast; pragma Warnings (On); function Generate_Distinct_Periods (n : in integer) return Integer_Array is M : constant array (1 .. 5, 1 .. 7) of integer := ((1, 2, 2, 4, 4, 4, 8), (1, 3, 3, 3, 3, 9, 9), (1, 5, 5, 5, 5, 0, 0), (1, 1, 7, 7, 7, 0, 0), (1, 1, 1, 1, 11, 0, 0)); function Random_Limited_Period return integer is use Ada.Numerics.Float_Random ; Random_column : integer := 0; A_period : integer := 1; G : Ada.Numerics.Float_Random.Generator; x : integer := 0; begin reset (G); for i in 1 .. 5 loop -- for each line i of the matrix M loop Random_column := 0; x := 0; while (Random_column < 1) or (Random_column > 7) or (x = 0) loop Random_column := Integer (Float'Rounding (7.0 * random(G))); if (Random_column >= 1) and (Random_column <= 7) then x := M(i,Random_column); end if; end loop; A_period := A_period * M(i,Random_column); end loop; return A_period; end Random_Limited_Period; function found_element_in_array (x: integer ; Seq : Integer_Array) return boolean is b : boolean := false; i : integer := 1; begin while not b and i <= Seq'length loop if seq(i) = x then b := true; end if; i := i + 1; end loop; return b; end found_element_in_array; x : integer; Different_Periods : Integer_Array (1 .. n); begin for i in 1 .. n loop Different_Periods(i) := 0; end loop; for i in 1 .. n loop loop x := Random_Limited_Period; exit when not found_element_in_array (x,Different_Periods); end loop; Different_Periods (i) := x; end loop; return Different_Periods; end Generate_Distinct_Periods; function Generate_Period_set_with_Limited_HyperPeriod (N_Tasks : in Integer; N_Different_Periods : in Integer) return Integer_Array is procedure Shuffle_An_Array (To_Shuffle : in out Integer_Array) is use Ada.Numerics.Float_Random ; N : integer; G : Ada.Numerics.Float_Random.Generator; A_random_position : integer := 0; A_value : integer; begin N := To_Shuffle'Length; reset (G); while N > 1 loop A_random_position := 0; while (A_random_position < 1) or (A_random_position > N) loop A_random_position := Integer (Random(G) * Float(N)); end loop; N := N - 1; A_value := To_Shuffle (A_random_position); To_Shuffle (A_random_position) := To_Shuffle (N); To_Shuffle (N) := A_value; end loop; end Shuffle_An_Array; x,k : integer; occurences : Integer_Array (0 .. N_Different_Periods-1); Different_Periods : Integer_Array (1 .. N_Different_Periods); Set_of_periods : Integer_Array (1 .. N_Tasks); Has_A_Zero_value : boolean := true; begin -- Generate a set of different periods Different_Periods := Generate_Distinct_Periods (N_Different_Periods); if N_Different_Periods = N_Tasks then return Different_Periods; else -- Generate randomly occurence of each period in the set of tasks while Has_A_Zero_value loop occurences := Gen_UUniFast (N_Different_Periods , N_Tasks); k := 0; loop x := occurences (K); K := K + 1; exit when ((K = N_Different_Periods) or (x = 0)); end loop; if k = N_Different_Periods then Has_A_Zero_value := false; end if; end loop; -- Generate the set of periods from distincts_periods and occurences k := 1; for j in 0 .. N_Different_Periods-1 loop for i in 1 .. occurences(j) loop Set_of_periods (k) := Different_Periods (j+1); k := k + 1; end loop; end loop; -- Rearrange randomly the set of periods Shuffle_An_Array (Set_of_periods); return Set_of_periods; end if; end Generate_Period_set_with_Limited_HyperPeriod; end Random_Tools;