------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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 Framework_Config; use Framework_Config; with Translate; use Translate; with Ada.Exceptions; use Ada.Exceptions; with Tasks; use Tasks; with Task_Set; use Task_Set; use Task_Set.Generic_Task_Set; with Address_Spaces; use Address_Spaces; with Address_Space_Set; use Address_Space_Set; use Address_Space_Set.Generic_Address_Space_Set; with Scheduler_Interface; use Scheduler_Interface; with Time_Unit_Events; use Time_Unit_Events; use Time_Unit_Events.Time_Unit_Package; with ARINC_653_Schema; use ARINC_653_Schema; use ARINC_653_Schema.PartitionType_List_Package; use ARINC_653_Schema.ProcessType_List_Package; use ARINC_653_Schema.Partition_Schedule_Element_List_Package; use ARINC_653_Schema.Window_Schedule_Element_List_Package; with Ada.Numerics.Aux; use Ada.Numerics.Aux; with framework; use framework; with Scheduling_Analysis; use Scheduling_Analysis; package body arinc_653_Services is procedure Check_Arinc_653 (Sys : in System) is Ad_Iterator : Address_Spaces_Iterator; Ta_Iterator : Tasks_Iterator; current_scheduler : Schedulers_Type; A_Address_space : Address_Space_Ptr; begin if (get_number_of_elements (Sys.Address_Spaces) > 0) then reset_iterator (Sys.Address_Spaces, Ad_Iterator); current_element (Sys.Address_Spaces, A_Address_space, Ad_Iterator); current_scheduler := A_Address_space.scheduling.scheduler_type; if (current_scheduler /= Hierarchical_Cyclic_Protocol) and (current_scheduler /= Hierarchical_Round_Robin_Protocol) then Raise_Exception (Invalid_Scheduler'Identity, To_String (Lb_Invalid_Scheduler (Current_Language))); end if; reset_iterator (Sys.Address_Spaces, Ad_Iterator); loop current_element (Sys.Address_Spaces, A_Address_space, Ad_Iterator); if (current_scheduler /= A_Address_space.scheduling.scheduler_type) then Raise_Exception (Invalid_Scheduler'Identity, To_String (Lb_require_same_Scheduler_on_all_address_space ( Current_Language))); end if; exit when is_last_element (Sys.Address_Spaces, Ad_Iterator); next_element (Sys.Address_Spaces, Ad_Iterator); end loop; end if; end Check_Arinc_653; function Build_ARINC653_Module (Sched : in Scheduling_Table_Ptr; Sys : in System; majorTimeFrame : in Natural) return ARINC_653_Module_Ptr is a_sched : Scheduling_Sequence_Ptr; a_mod : ARINC_653_Module_Ptr; a_partition : PartitionType_Ptr; a_process : ProcessType_Ptr; a_Partition_Schedule_element : Partition_Schedule_Element_Ptr; a_window_schedule_element : Window_Schedule_Element_Ptr; Ad_Iterator : Address_Spaces_Iterator; Ta_Iterator : Tasks_Iterator; par_Iterator : Partition_Schedule_Element_Iterator; A_task : Generic_Task_Ptr; A_Address_space : Address_Space_Ptr; begin -- Create the module -- a_mod := new ARINC_653_Module; a_mod.ModuleName := To_Unbounded_String ("cheddar"); -- Add processes and partitions -- if (get_number_of_elements (Sys.Address_Spaces) > 0) then reset_iterator (Sys.Address_Spaces, Ad_Iterator); loop current_element (Sys.Address_Spaces, A_Address_space, Ad_Iterator); a_partition := new PartitionType; a_partition.PartitionName := A_Address_space.name; add (a_mod.Partition, a_partition); if (get_number_of_elements (Sys.Tasks) > 0) then reset_iterator (Sys.Tasks, Ta_Iterator); loop current_element (Sys.Tasks, A_task, Ta_Iterator); a_process := new ProcessType; a_process.Name := A_task.name; add (a_partition.Process, a_process); exit when is_last_element (Sys.Tasks, Ta_Iterator); next_element (Sys.Tasks, Ta_Iterator); end loop; end if; exit when is_last_element (Sys.Address_Spaces, Ad_Iterator); next_element (Sys.Address_Spaces, Ad_Iterator); end loop; end if; -- Export partition scheduling -- a_mod.Module_Schedule := new Module_Schedule_Type; a_mod.Module_Schedule.MajorFrameSeconds := Double (majorTimeFrame); -- Create a Partition_Schedule_Element for each partition -- if (get_number_of_elements (Sys.Address_Spaces) > 0) then reset_iterator (Sys.Address_Spaces, Ad_Iterator); loop current_element (Sys.Address_Spaces, A_Address_space, Ad_Iterator); a_Partition_Schedule_element := new Partition_Schedule_Element; a_Partition_Schedule_element.PartitionName := A_Address_space.name; a_Partition_Schedule_element.PeriodSeconds := Double (A_Address_space.scheduling.period); a_Partition_Schedule_element.PeriodDurationSeconds := Double (A_Address_space.scheduling.capacity); add (a_mod.Module_Schedule.Partition_Schedule, a_Partition_Schedule_element); exit when is_last_element (Sys.Address_Spaces, Ad_Iterator); next_element (Sys.Address_Spaces, Ad_Iterator); end loop; end if; -- Fill each Partition_Schedule_Element with schedule table computed -- by cheddar -- for k in 0 .. Sched.nb_entries - 1 loop a_sched := Sched.entries (k).data.result; for I in 0 .. a_sched.nb_entries - 1 loop if (a_sched.entries (I).data.type_of_event = Address_Space_Activation) then -- Look for the corresponding partition -- reset_head_iterator (a_mod.Module_Schedule.Partition_Schedule, par_Iterator); loop current_element (a_mod.Module_Schedule.Partition_Schedule, a_Partition_Schedule_element, par_Iterator); -- Store the event in the PST table -- if (a_Partition_Schedule_element.PartitionName = a_sched.entries (I).data.activation_address_space) then a_window_schedule_element := new Window_Schedule_Element; a_window_schedule_element.WindowStartSeconds := Double (a_sched.entries (I).item); a_window_schedule_element.WindowDurationSeconds := Double (a_sched.entries (I).data.duration); a_window_schedule_element.PartitionPeriodStart := False; if (Natural (a_Partition_Schedule_element.PeriodSeconds) /= 0) then if (a_sched.entries (I).item mod Natural ( a_Partition_Schedule_element.PeriodSeconds) = 0) then a_window_schedule_element.PartitionPeriodStart := True; end if; end if; add (a_Partition_Schedule_element.Window_Schedule, a_window_schedule_element); end if; exit when is_tail_element (a_mod.Module_Schedule.Partition_Schedule, par_Iterator); next_element (a_mod.Module_Schedule.Partition_Schedule, par_Iterator); end loop; end if; end loop; end loop; return a_mod; end Build_ARINC653_Module; end arinc_653_Services;