------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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: 97 $ -- $Date: 2007-07-20 15:17:15 +0200 (Fri, 20 Jul 2007) $ -- $Author: singhoff $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Ada.Numerics.Aux; use Ada.Numerics.Aux; with Text_IO; use Text_IO; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO.Unbounded_IO; with Framework_Config; use Framework_Config; with Processor_Set; use Processor_Set; use Processor_Set.Generic_Processor_Set; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with unbounded_strings; use unbounded_strings; use unbounded_strings.strings_table_package; use unbounded_strings.unbounded_string_list_package; with Parameters; use Parameters; with Parameters.extended; use Parameters.extended; use Parameters.Framework_Parameters_Table_Package; with Scheduling_Analysis; use Scheduling_Analysis.Double_Tasks_Parameters_Package; with Scheduler_Interface; use Scheduler_Interface; with Processor_Set; use Processor_Set; use Processor_Set.Generic_Processor_Set; with Processors; use Processors; with processor_interface; use processor_interface; with Caches; use Caches; use Caches.Caches_Table_Package; use Processors.Core_Units_Table_Package; with Address_Space_Set; use Address_Space_Set; use Address_Space_Set.Generic_Address_Space_Set; with Task_Set; use Task_Set; use Task_Set.Generic_Task_Set; with Offsets; use Offsets; with Systems; use Systems; 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 framework; use framework; with Call_Scheduling_Framework; use Call_Scheduling_Framework; with Multiprocessor_Services; use Multiprocessor_Services; with Multiprocessor_Services_Interface; use Multiprocessor_Services_Interface; use Multiprocessor_Services_Interface.Scheduling_Result_Per_Processor_Package; with Feasibility_Test.Wort_Case_Response_Time; use Feasibility_Test.Wort_Case_Response_Time; with Scheduling_Analysis; use Scheduling_Analysis; with GNAT.Command_Line; with GNAT.OS_Lib; use GNAT.OS_Lib; with Version; use Version; with Ada.Exceptions; use Ada.Exceptions; with GNAT.Traceback.Symbolic; with Task_Groups; use Task_Groups; with Task_Group_Set; use Task_Group_Set; with Tasks; use Tasks; with Task_Dependencies; use Task_Dependencies; with Dependencies; use Dependencies; with Architecture_Factory; use Architecture_Factory; with Task_Group_Transformation; use Task_Group_Transformation; with Comprehensive_Call; with Initialize_Framework; use initialize_framework; procedure WCDOPS_Plus_NIMP_Sim is use Double_Tasks_Parameters_Package; function Search_Task_In_Response_Times_Table (Response_Times : Response_Time_Table; Name : Unbounded_String) return Integer is Task_Not_Found : exception; begin for i in 0 .. Response_Times.nb_entries - 1 loop if Response_Times.entries(i).item.name = Name then return Integer(i); end if; end loop; raise Task_Not_Found; end Search_Task_In_Response_Times_Table; function Pred (My_System : System; tau_ij : Generic_Task_Ptr) return Generic_Task_Ptr is use Task_Dependencies.Half_Dep_Set; pred_ij : Generic_Task_Ptr; A_Task_Dependencies_Iterator : Tasks_Dependencies_Iterator; A_Half_Dep : Dependency_Ptr; begin if not is_empty(My_System.Dependencies.Depends) then reset_iterator(My_System.Dependencies.Depends, A_Task_Dependencies_Iterator); loop current_element(My_System.Dependencies.Depends, A_Half_Dep, A_Task_Dependencies_Iterator); if A_Half_Dep.type_of_dependency = Precedence_Dependency then if A_Half_Dep.precedence_sink.name = tau_ij.name then pred_ij := A_Half_Dep.precedence_source; return pred_ij; end if; end if; exit when is_last_element(My_system.Dependencies.Depends, A_Task_Dependencies_Iterator); next_element(My_System.Dependencies.Depends, A_Task_Dependencies_Iterator); end loop; end if; return null; end Pred; Sys_Transaction : System; Response_Times_NIMP : Response_Time_Table; Response_Times_WCDOPS_P : Response_Time_Table; Ghost : constant String := "wcdops"; Output_File_Name : Unbounded_String := To_Unbounded_String("default.csv"); n_tasks : Integer := 5; n_groups : Integer := 10; Nim_Prob : Double := 0.4; Cpu_Utilization : Double := 0.2; Prio_Prob : Double := 0.2; Verbose : Boolean := False; No_Error : Boolean := True; F : Ada.Text_IO.File_Type; Total : Double; N : Integer; Average : Double; J : Integer; pred_ij : Generic_Task_Ptr; begin loop case GNAT.Command_Line.Getopt("v o: n: c: p: t: g:") is when ASCII.NUL => No_Error := true; exit; when 'o' => Output_File_Name := To_Unbounded_String(GNAT.Command_Line.Parameter); when 'n' => To_Double(To_Unbounded_String(GNAT.Command_Line.Parameter), Nim_Prob, No_Error); if not No_Error then exit; end if; when 'c' => To_Double(To_Unbounded_String(GNAT.Command_Line.Parameter), Cpu_Utilization, No_Error); if not No_Error then exit; end if; when 'p' => To_Double(To_Unbounded_String(GNAT.Command_Line.Parameter), Prio_Prob, No_Error); if not No_Error then exit; end if; when 't' => To_Integer(To_Unbounded_String(GNAT.Command_Line.Parameter), n_tasks, No_Error); if not No_Error then exit; end if; when 'g' => To_Integer(To_Unbounded_String(GNAT.Command_Line.Parameter), n_groups, No_Error); if not No_Error then exit; end if; when 'v' => Verbose := True; when others => OS_Exit(0); end case; end loop; if not No_Error then Put_Line("Error in given options, please verify their values."); OS_Exit(1); end if; if Verbose then Put_Line ("WCDOPS+_NIM simulation will be launched with the following parameters:"); Put_Line (" - N_Tasks:" & n_tasks'Img); Put_Line (" - N_Groups:" & n_groups'Img); Put_Line (" - Prio_Prob:" & Prio_Prob'Img); Put_Line (" - NIM_Prob:" & Nim_Prob'Img); Put_Line (" - Cpu_Utilization:" & Cpu_Utilization'Img); end if; Set_Initialize; Create_Tree_Transaction_System(S => Sys_Transaction, number_groups => n_groups, number_tasks_per_group => n_tasks, number_resources => 0, number_resource_usages => 0, number_core_units_per_processor => 1, number_processors => 4, number_address_spaces => 0, sched => Posix_1003_Highest_Priority_First_Protocol, cpu_utilization => Cpu_Utilization, min_period => 0, max_period => 100000, -- Note: the less cpu you have, the higher this should be to give more freedom to approach the desired cpu_utiilzation value for each cpu nim_delta => 1000, priority_variation_prob => Prio_Prob, processor_variation_prob => 0.25, non_immediateness_prob => Nim_Prob); --Write_To_Xml_File(Sys_Transaction, To_Unbounded_String("randomly_generated_tree_system.xml")); WCDOPS_Plus_NIMP(Sys_Transaction, Response_Times_NIMP, True); -- for i in 0 .. Response_Times_NIMP.nb_entries - 1 loop -- put_line(to_string(Response_Times_NIMP.entries(i).item.name) & " (" & Periodic_Task_Ptr(Response_Times_NIMP.entries(i).item).jitter'Img & ") = " & Integer(Response_Times_NIMP.entries(i).data)'Img); -- put_line("============="); -- end loop; if Verbose then put_line("*************** NIMP done ***************"); end if; Add_Delta_Tasks(Sys_Transaction); if Verbose then put_line("done adding delta tasks"); end if; WCDOPS_Plus_NIMP(Sys_Transaction, Response_Times_WCDOPS_P, True); -- for i in 0 .. Response_Times_WCDOPS_P.nb_entries - 1 loop -- put_line(to_string(Response_Times_WCDOPS_P.entries(i).item.name) & " (" & Periodic_Task_Ptr(Response_Times_WCDOPS_P.entries(i).item).jitter'Img & ") = " & Integer(Response_Times_WCDOPS_P.entries(i).data)'Img); -- put_line("============="); -- end loop; if Verbose then put_line("*************** WCDOPS+ done ***************"); end if; -- exception -- when STORAGE_ERROR => -- Delete_Delta_Tasks(Sys_Transaction); -- put_line("*** ERROR ***"); -- OS_Exit(0); -- when CONSTRAINT_ERROR => -- Delete_Delta_Tasks(Sys_Transaction); -- put_line("*** ERROR ***"); -- OS_Exit(0); -- when others => -- Delete_Delta_Tasks(Sys_Transaction); -- put_line("*** OTHER ERROR ***"); -- OS_Exit(0); J := 0; N := 0; Total := 0.0; for i in 0 .. Response_Times_WCDOPS_P.nb_entries - 1 loop if not (to_string(Response_Times_WCDOPS_P.entries(i).item.name)'Length >= Ghost'Length and then to_string(Response_Times_WCDOPS_P.entries(i).item.name) (to_string(Response_Times_WCDOPS_P.entries(i).item.name)'First .. to_string(Response_Times_WCDOPS_P.entries(i).item.name)'First + Ghost'Length - 1) = Ghost) then pred_ij := pred(Sys_Transaction, Response_Times_WCDOPS_P.entries(i).item); -- If predecessor is a delta task, then the task is non-immediate. -- We then compute its response times ratio: WCDOPS+ / NIMP if pred_ij /= null and then (to_string(pred_ij.name)'Length >= Ghost'Length and then to_string(pred_ij.name) (to_string(pred_ij.name)'First .. to_string(pred_ij.name)'First + Ghost'Length - 1) = Ghost) then J := Search_Task_In_Response_Times_Table(Response_Times_NIMP, Response_Times_WCDOPS_P.entries(i).item.name); Total := Total + Response_Times_WCDOPS_P.entries(i).data / Response_Times_NIMP.entries(Double_Tasks_Parameters_Package.Indexed_Table_Range(j)).data; N := N + 1; end if; end if; end loop; Delete_Delta_Tasks(Sys_Transaction); if Verbose then put_line("done deleting delta tasks"); end if; Average := 0.0; if N > 0 then Average := Total / Double(N); end if; Open(F, Ada.Text_IO.Append_File, To_String(Output_File_Name)); Unbounded_IO.Put_Line(F, suppress_space(Prio_Prob'Img & ";" & Nim_Prob'Img & ";" & Cpu_Utilization'Img & ";" & Average'Img)); Close(F); exception when E : others => put_line(Ada.Exceptions.Exception_Information(E)); put_line(GNAT.Traceback.Symbolic.Symbolic_Traceback(E)); OS_Exit(0); end WCDOPS_Plus_NIMP_Sim;