------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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 Gtk; use Gtk; with Gtk.Main; use Gtk.Main; with Gtk.Menu_Item; use Gtk.Menu_Item; with Gtk.Widget; use Gtk.Widget; with Gtk.Handlers; use Gtk.Handlers; with Gtk.Dialog; use Gtk.Dialog; with Gtk.About_Dialog; use Gtk.About_Dialog; with Gtk.Check_Button; use Gtk.Check_Button; with Gtk.Text_Buffer; use Gtk.Text_Buffer; with Gtk.Label; use Gtk.Label; with Gtk.Text_Iter; use Gtk.Text_Iter; with Glib; use Glib; with Glib.Error; use Glib.Error; with Glib.Object; use Glib.Object; with Gdk.Drawable; use Gdk.Drawable; with Gdk.Font; use Gdk.Font; with Gdk.Color; use Gdk.Color; with Gdk.GC; use Gdk.GC; with Gdk.Event; use Gdk.Event; with Gdk.Window; use Gdk.Window; with Pango.Font; use Pango.Font; with graphical_editor.generic_package_widget; use graphical_editor.generic_package_widget; with Ada.Text_IO; use Ada.Text_IO; with framework; use framework; with call_framework; use call_framework; with call_framework_interface; use call_framework_interface; use call_framework_interface.framework_request_package; use call_framework_interface.framework_response_package; with editor_config; use editor_config; with time_unit_events.extended; use time_unit_events.extended; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with parameters; use parameters; with parameters.extended; use parameters.extended; use parameters.framework_parameters_table_package; 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 framework_config; use framework_config; with editor_config; use editor_config; with strings; use strings; with unbounded_strings; use unbounded_strings; with translate; use translate; with processors; use processors; with processor_set; use processor_set; use processor_set.generic_processor_set; with task_set; use task_set; use task_set.generic_task_set; with resource_set; use resource_set; use resource_set.generic_resource_set; with message_set; use message_set; use message_set.generic_message_set; with buffer_set; use buffer_set; use buffer_set.generic_buffer_set; with time_unit_events; use time_unit_events; with time_unit_events.extended; use time_unit_events.extended; with graphical_editor.scheduling_simulation_callbacks; use graphical_editor.scheduling_simulation_callbacks; with graphical_editor.user_message; use graphical_editor.user_message; with graphical_editor.select_time_line; use graphical_editor.select_time_line; with graphical_editor.draw_scheduling; use graphical_editor.draw_scheduling; with graphical_editor.message_text; use graphical_editor.message_text; package body graphical_editor.scheduling_simulation_draw_callbacks is draw_from, draw_upto, schedule_to : Unbounded_String; last_period : constant Natural := framework_config.max_scheduling_period - 1; max_period : Integer := 0; start_draw : Integer := 0; stop_draw : Integer := 0; max_draw : Natural := 1500; ok : Boolean; line_number : Integer := 0; procedure read_scheduling_duration_and_draw_scheduling (object : access gtkada_builder_record'class) is object_number : Natural := 0; begin draw_from := suppress_space (get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer2")))); draw_upto := suppress_space (get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer3")))); schedule_to := suppress_space (get_value_buffer_string (gtk_text_buffer (Get_Object (object, "textbuffer1")))); graphical_editor.scheduling_simulation_draw_callbacks.close_widget (object); to_integer (draw_upto, stop_draw, ok); if not ok then show_message_box (lb_double_quote & lb_draw_to (current_language) & lb_double_quote & lb_must_be_numeric (current_language)); return; end if; to_integer (draw_from, start_draw, ok); if not ok then show_message_box (lb_double_quote & lb_draw_from (current_language) & lb_double_quote & lb_must_be_numeric (current_language)); return; end if; to_integer (schedule_to, max_period, ok); if not ok then show_message_box (lb_double_quote & lb_schedule_to (current_language) & lb_double_quote & lb_must_be_numeric (current_language)); return; end if; if (max_period > Integer (last_period)) then show_message_box (lb_double_quote & lb_schedule_to (current_language) & lb_double_quote & lb_must_be (current_language) & lb_less_or_equal_than (current_language) & last_period'img); return; end if; if (max_period <= 0) then show_message_box (lb_double_quote & lb_schedule_to (current_language) & lb_double_quote & lb_must_be (current_language) & lb_greater_than (current_language) & To_Unbounded_String (" 0")); return; end if; if (start_draw < 0) then show_message_box (lb_double_quote & lb_draw_from (current_language) & lb_double_quote & lb_must_be (current_language) & lb_greater_or_equal_than (current_language) & To_Unbounded_String (" 0")); return; end if; if (stop_draw < 0) then show_message_box (lb_double_quote & lb_draw_to (current_language) & lb_double_quote & lb_must_be (current_language) & lb_greater_or_equal_than (current_language) & To_Unbounded_String (" 0")); return; end if; if (start_draw > max_period) then show_message_box (lb_double_quote & lb_draw_from (current_language) & lb_double_quote & lb_must_be (current_language) & lb_less_or_equal_than (current_language) & lb_double_quote & lb_schedule_to (current_language) & lb_double_quote); return; end if; if (stop_draw - start_draw > max_draw) then show_message_box (lb_draw_time_line_too_large (current_language)); return; end if; -- Check if we need to select which tasks/messages/buffers -- to display with time lines -- object_number := Natural (get_number_of_elements (sys.tasks)) + Natural (get_number_of_elements (sys.messages)) + Natural (get_number_of_elements (sys.buffers)); if schedule_with_resources then object_number := object_number + Natural (get_number_of_elements (sys.resources)); end if; if customized_simulation then if object_number > editor_config.max_time_line_to_display then graphical_editor.select_time_line.gtk_new (graphical_editor.select_time_line.select_time_line, sys, call_customized_simulation'access); Show_All (graphical_editor.select_time_line.select_time_line); else call_customized_simulation; end if; else if object_number > editor_config.max_time_line_to_display then graphical_editor.select_time_line.gtk_new (graphical_editor.select_time_line.select_time_line, sys, call_uncustomized_simulation'access); Show_All (graphical_editor.select_time_line.select_time_line); else call_uncustomized_simulation; end if; end if; customized_simulation := False; end read_scheduling_duration_and_draw_scheduling; function expose (w : access Gtk.Drawing_Area.gtk_drawing_area_record'class) return Boolean is begin draw_time_line (stop_draw, start_draw, framework.sched); return False; end expose; procedure call_processor_analysis (name : Unbounded_String) is response_list : framework_response_table; request_list : framework_request_table; a_request : framework_request; a_param : parameter_ptr; begin if preemption_from_simulation then initialize (response_list); initialize (request_list); initialize (a_request); initialize (a_request.param); a_request.target := name; a_request.statement := scheduling_simulation_preemption_number; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; if context_switch_from_simulation then initialize (response_list); initialize (request_list); initialize (a_request); initialize (a_request.param); a_request.target := name; a_request.statement := scheduling_simulation_context_switch_number; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; if (response_time_from_simulation (worst_case) or response_time_from_simulation (best_case) or response_time_from_simulation (average_case) or response_time_from_simulation (plot_case)) then initialize (a_request); initialize (a_request.param); initialize (response_list); initialize (request_list); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("worst_case"); if response_time_from_simulation (worst_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("best_case"); if response_time_from_simulation (best_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("average_case"); if response_time_from_simulation (average_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_request.target := name; a_request.statement := scheduling_simulation_response_time; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; if (blocking_time_from_simulation (worst_case) or blocking_time_from_simulation (best_case) or blocking_time_from_simulation (average_case) or blocking_time_from_simulation (plot_case)) then initialize (a_request); initialize (a_request.param); initialize (response_list); initialize (request_list); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("worst_case"); if blocking_time_from_simulation (worst_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("best_case"); if blocking_time_from_simulation (best_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("average_case"); if blocking_time_from_simulation (average_case) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); a_request.target := name; a_request.statement := scheduling_simulation_blocking_time; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title (response_list); write_text (response_list); end if; end call_processor_analysis; procedure call_uncustomized_simulation is response_list : framework_response_table; request_list : framework_request_table; a_request : framework_request; a_param : parameter_ptr; begin initialize (a_request); initialize (a_request.param); a_request.statement := scheduling_simulation_time_line; a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("period"); a_param.integer_value := max_period; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_offsets"); a_param.boolean_value := schedule_with_offsets; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_precedencies"); a_param.boolean_value := schedule_with_precedencies; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("minimize_preemption"); a_param.boolean_value := minimize_preemption; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_jitters"); a_param.boolean_value := schedule_with_jitters; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_resources"); a_param.boolean_value := schedule_with_resources; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_crpd"); a_param.boolean_value := schedule_with_crpd; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("anomaly_detection"); a_param.boolean_value := anomaly_detection; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("dvfs"); a_param.boolean_value := dvfs; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("predictable"); a_param.boolean_value := is_global_predictable_seed; add (a_request.param, a_param); if has_global_seed then a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("seed_value"); a_param.integer_value := global_seed_value; add (a_request.param, a_param); end if; for i in time_unit_event_type'range loop a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String (to_lower (i'img)); if generate_events (i) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); end loop; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title_and_text (response_list); initialize (a_request); initialize (a_request.param); initialize (response_list); initialize (request_list); a_request.target := empty_string; a_request.statement := scheduling_simulation_basics; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title_and_text (response_list); cb.Connect (gtk_drawing_area (drawing_area_cheddar), "expose_event", cb.To_Marshaller (expose'access)); draw_time_line (stop_draw, start_draw, framework.sched); end call_uncustomized_simulation; procedure call_customized_simulation is a_processor : generic_processor_ptr; my_processor_iterator : processors_iterator; response_list : framework_response_table; request_list : framework_request_table; a_request : framework_request; a_param : parameter_ptr; begin initialize (a_request); initialize (a_request.param); a_request.statement := scheduling_simulation_time_line; a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("period"); a_param.integer_value := max_period; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_offsets"); a_param.boolean_value := schedule_with_offsets; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("minimize_preemption"); a_param.boolean_value := minimize_preemption; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_jitters"); a_param.boolean_value := schedule_with_jitters; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_precedencies"); a_param.boolean_value := schedule_with_precedencies; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_resources"); a_param.boolean_value := schedule_with_resources; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("schedule_with_crpd"); a_param.boolean_value := schedule_with_crpd; add (a_request.param, a_param); a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String ("predictable"); a_param.boolean_value := is_global_predictable_seed; add (a_request.param, a_param); if has_global_seed then a_param := new parameter (integer_parameter); a_param.parameter_name := To_Unbounded_String ("seed_value"); a_param.integer_value := global_seed_value; add (a_request.param, a_param); end if; for i in time_unit_event_type'range loop a_param := new parameter (boolean_parameter); a_param.parameter_name := To_Unbounded_String (to_lower (i'img)); if generate_events (i) then a_param.boolean_value := True; else a_param.boolean_value := False; end if; add (a_request.param, a_param); end loop; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); -- Put to the screen the resulting event table -- if schedule_and_display_event_table then display_scheduling (framework.sched); end if; write_title_and_text (response_list); cb.Connect (gtk_drawing_area (drawing_area_cheddar), "expose_event", cb.To_Marshaller (expose'access)); draw_time_line (stop_draw, start_draw, framework.sched); -- export event table in the targeted XML file -- if schedule_and_export_event_table then write_to_xml_file (framework.sched, sys, xml_event_table_file_name); end if; if schedule_all_processors = False then call_processor_analysis (last_selected_processor); else reset_iterator (sys.processors, my_processor_iterator); loop current_element (sys.processors, a_processor, my_processor_iterator); call_processor_analysis (a_processor.name); exit when is_last_element (sys.processors, my_processor_iterator); next_element (sys.processors, my_processor_iterator); end loop; end if; -- Now run, event analyzers, -- if run_event_analyzer_from_simulation then initialize (response_list); initialize (request_list); initialize (a_request); a_request.statement := scheduling_simulation_run_event_handler; add (request_list, a_request); sequential_framework_request (sys, request_list, response_list); write_title_and_text (response_list); end if; end call_customized_simulation; procedure close_widget (object : access gtkada_builder_record'class) is my_widget : gobject; begin my_widget := Get_Object (object, "window1"); Destroy_Cb (gtk_widget (my_widget)); Gtk.Main.Main_Quit; end close_widget; end graphical_editor.scheduling_simulation_draw_callbacks;