------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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-2016, Frank Singhoff, Alain Plantec, Jerome Legrand -- -- The Cheddar project was started in 2002 by -- Frank Singhoff, Lab-STICC UMR 6285 laboratory, 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: 1249 $ -- $Date: 2014-08-28 07:02:15 +0200 (Fri, 28 Aug 2014) $ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Random_Tools; use Random_Tools; with Ada.Float_Text_IO; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Unbounded_Strings; use Unbounded_Strings; with convert_unbounded_strings; use unbounded_strings.unbounded_string_list_package; use unbounded_strings.strings_table_package; with Ada.Strings; use Ada.Strings; with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO; with architecture_factory; use architecture_factory; with Ada.text_IO; use Ada.text_IO; with Ada.Integer_text_IO; use Ada.Integer_text_IO; with Ada.Float_Text_IO; use Ada.Float_Text_IO; with Task_Set; use Task_Set; with Tasks; use Tasks; with Systems; use Systems; with Processors; use Processors; with Processor_Set; use Processor_Set; with processor_interface; use processor_interface; with Core_Units; use Core_Units; use Core_Units.Core_Units_Table_Package; with Scheduler_Interface; use Scheduler_Interface; with Address_Spaces; use Address_Spaces; with Address_Space_Set; use Address_Space_Set; with Call_Framework; use Call_Framework; with Call_Framework_Interface; use Call_Framework_Interface; use Call_Framework_Interface.Framework_Response_Package; use Call_Framework_Interface.Framework_Request_Package; with Call_Scheduling_Framework; use Call_Scheduling_Framework; with natural_util; use natural_util; with feasibility_test.feasibility_interval; use feasibility_test.feasibility_interval; with Pipe_Commands; use Pipe_Commands; with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO; with unbounded_strings; use unbounded_strings; with convert_unbounded_strings; with Ada.Directories; use Ada.Directories; with Debug; use Debug; with integer_util; use integer_util; with Resources; use Resources; use Resources.Resource_Accesses; with float_util; use float_util; package body Objective_Functions_and_Feasibility_Checks is Procedure initialize_FitnessFunctions is begin -- Initialize the list of all possible fitness functions -- for i in 1 .. MAX_FITNESS loop FitnessFunctions(i).Is_selected := 0; end loop; FitnessFunctions(1).Name := To_Unbounded_String("f1 = preemptions"); -- To Min FitnessFunctions(2).Name := To_Unbounded_String("f2 = contextSwitches"); -- To Min FitnessFunctions(3).Name := To_Unbounded_String("f3 = tasks"); -- To Min FitnessFunctions(4).Name := To_Unbounded_String("f4 = sum(Li) = sum(Di-Ri)");-- To Max -- FitnessFunctions(5).Name := To_Unbounded_String("f5 = sum(Ri/Di)"); -- To Min FitnessFunctions(6).Name := To_Unbounded_String("f6 = min(Li)"); -- To Max -- FitnessFunctions(7).Name := To_Unbounded_String("f7 = sum(Ri)"); -- To Min FitnessFunctions(8).Name := To_Unbounded_String("f8 = max(Ri)"); -- To Min FitnessFunctions(9).Name := To_Unbounded_String("f9 = sum(Bi)"); -- To Min FitnessFunctions(10).Name := To_Unbounded_String("f10 = max(Bi)"); -- To Min FitnessFunctions(11).Name := To_Unbounded_String("f11 = sharedResources"); -- To Min end initialize_FitnessFunctions; ------------------------------------- -- Check_Feasibility_of_A_Solution -- ------------------------------------- function Check_Feasibility_of_A_Solution (s : in solution; eidx : in Natural) return boolean is Is_feasible : boolean; min_periods : Integer; nb_tasks : Integer; gcd_periods : Integer; i : Integer; nb_functions_in_task_i : Integer; periods_array : array (1 .. genes) of Integer; Initial_Taskset : Tasks_Set := Initial_system.Tasks; capacity_i, deadline_i, period_i : integer; Total_Processor_Utilization : float; A_system : System; FileStream : stream; command : unbounded_String; F : Ada.Text_IO.File_Type; line : unbounded_String; Buffer : unbounded_String; begin Is_feasible := true; if slaves > 0 then if eidx /= 0 then Create_system (A_System); Transform_Chromosome_To_CheddarADL_Model (A_System, s); else A_System := Initial_system; end if; else Create_system (A_System); Transform_Chromosome_To_CheddarADL_Model (A_System, s); end if; nb_tasks := Integer (Get_Number_Of_Task_From_Processor (A_system.Tasks, To_Unbounded_String("processor1")) ); -- 1) Check for each task of the candidate solution that Ci <= Di -- 2) Check that the total processor Utilization <= 1 i := 1; Total_Processor_Utilization := 0.0; while (i<= nb_tasks) and Is_feasible loop capacity_i := Get(My_Tasks => A_system.Tasks, Task_Name => Suppress_Space (To_Unbounded_String ("Task" & i'Img)), Param_Name => Capacity); deadline_i := Get(My_Tasks => A_system.Tasks, Task_Name => Suppress_Space (To_Unbounded_String ("Task" & i'Img)), Param_Name => Deadline); period_i := Get(My_Tasks => A_system.Tasks, Task_Name => Suppress_Space (To_Unbounded_String ("Task" & i'Img)), Param_Name => Period); if capacity_i > deadline_i then Is_feasible := false; end if; Total_Processor_Utilization := Total_Processor_Utilization + Float(capacity_i) / Float(period_i); i := i + 1; end loop; if Is_feasible then if (Total_Processor_Utilization > 1.0) then Is_feasible := false; end if; end if; -- 3) check if there are two non-harmonic functions which are -- grouped alone in the same task. -- -- this constraint is checked only on candidate solutions -- generated by mutation -- i.e. if the solution to be checked is the initial design -- then we don't verify this constraint and we pass directly -- to the scheduling simulation if (eidx /= 0) and Is_feasible then i := 1; while (i<= nb_tasks) and Is_feasible loop nb_functions_in_task_i := 0; for j in 1 .. genes loop if (s.chrom(j) = i) then nb_functions_in_task_i := nb_functions_in_task_i + 1; periods_array (nb_functions_in_task_i) := Get(My_Tasks => Initial_Taskset, Task_Name => Suppress_Space (To_Unbounded_String ("Task" & j'Img)), Param_Name => Period); end if; end loop; if (nb_functions_in_task_i = 2) then if ( periods_array(1) < periods_array(2) ) then min_periods := periods_array(1); else min_periods := periods_array(2); end if; gcd_periods := integer_util.gcd (periods_array(1) , periods_array(2)); if (min_periods /= gcd_periods) then Is_feasible := false; end if; elsif (nb_functions_in_task_i > 2) then min_periods := periods_array(1); gcd_periods := integer_util.gcd (periods_array(1) , periods_array(2)); for j in 2 .. nb_functions_in_task_i loop if (periods_array(j) < min_periods) then min_periods := periods_array(j); end if; if (j < nb_functions_in_task_i) then gcd_periods := integer_util.gcd (gcd_periods, periods_array(j+1)); end if; end loop; if (min_periods /= gcd_periods) then Is_feasible := false; end if; else Is_feasible := true; end if; i := i + 1; end loop; end if; -- 4) Check the schedulability through scheduling simulation if Is_feasible then Write_To_Xml_File(A_System => A_System, File_Name => "candidate_solution" & eidx'Img & ".xmlv3"); command := To_Unbounded_String ("~/call_cheddar " & Hyperperiod_of_Initial_Taskset'img & " candidate_solution\" & eidx'Img & ".xmlv3"); FileStream := execute(To_String(command), read_file); loop begin Buffer := read_next(FileStream); exception when Pipe_Commands.End_of_file => exit; end; end loop; close(FileStream); Open(F, Ada.Text_IO.In_File,"Output" & eidx'Img & ".txt"); line := To_Unbounded_String(get_line(F)); if line = "schedulability : true" then Is_feasible := true; else Is_feasible := false; end if; Close(F); end if; return Is_feasible; end Check_Feasibility_of_A_Solution; ------------------ -- evaluate_F2T -- ------------------ procedure evaluate_F2T (s : in out solution; eidx : in Natural) is F : Ada.Text_IO.File_Type; line : unbounded_String; Buffer : unbounded_String; j : integer; My_System : System; hyperperiod_candidate_solution : integer; begin j := 0; for i in 1 .. MAX_FITNESS loop if FitnessFunctions(i).Is_selected = 1 then j := j + 1; -- open the file output_eidx.txt -- then read the line corresponding to the selected FitnessFunction Open (File => F, Mode => Ada.Text_IO.In_File, Name => "Output" & eidx'img & ".txt"); Ada.Text_IO.Set_Line (File => F, To => Ada.Text_IO.Count(i+1)); line := To_unbounded_string(Get_Line (File => F)); -- We distinguish the fitness to maximize i.e. (f4 and f6) -- in order to make all abjectives for minimization -- So, we transforme f4 and f6 as follow : -- f4 = Hyperperiod_of_Initial_Taskset - f4 -- f6 = Hyperperiod_of_Initial_Taskset - f6 If (i = 4) or (i = 6) then s.obj(j) := float(Hyperperiod_of_Initial_Taskset) - Float'Value(To_String(Unbounded_Slice(line, length(FitnessFunctions(i).Name & " = "), length(line)))); else s.obj(j) := Float'Value(To_String(Unbounded_Slice(line, length(FitnessFunctions(i).Name & " = "), length(line)))); end if; close(File => F); end if; end loop; -- Deleting the file "Output eidx.txt" Open (File => F, Mode => Ada.Text_IO.In_File, Name => "Output" & eidx'img & ".txt"); Ada.text_IO.Delete(File => F); -- Update the Max_hyperperiod taking into account the hyperperiod -- of the evaluated candidate solution "s" -- create_system (My_system); Transform_Chromosome_To_CheddarADL_Model(My_System, s); hyperperiod_candidate_solution := Scheduling_Period (My_system.Tasks, to_unbounded_string("processor1")); if Max_hyperperiod < hyperperiod_candidate_solution then Max_hyperperiod := hyperperiod_candidate_solution; end if; end evaluate_F2T; end Objective_Functions_and_Feasibility_Checks;