------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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: 2019-08-27 15:21:33+02:00 -- $Author: nam $ ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ with Tasks; use Tasks; with Caches; use Caches; with CFGs; use CFGs; with Core_Units; use Core_Units; with Task_Set; use Task_Set; with CFG_Set; use CFG_Set; with Cache_Set; use Cache_Set; with Cache_Block_Set; use Cache_Block_Set; with Cache_Access_Profile_Set; use Cache_Access_Profile_Set; with Caches; use Caches.Cache_Blocks_Table_Package; with Basic_Block_Analysis; use Basic_Block_Analysis; with Systems; use Systems; with Debug; use Debug; with unbounded_strings; use unbounded_strings; with Xml_Tag; use Xml_Tag; with GNAT.Current_Exception; use GNAT.Current_Exception; with Framework_Config; use Framework_Config; with Translate; use Translate; with CFG_Nodes; use CFG_Nodes; with Basic_Blocks; use Basic_Blocks; with CFG_Nodes; use CFG_Nodes.CFG_Nodes_Table_Package; with CFG_Nodes.Extended; use CFG_Nodes.Extended; with CFG_Node_Set; use CFG_Node_Set; with CFG_Node_Set.Basic_Block_Set; use CFG_Node_Set.Basic_Block_Set; with CFG_Edge_Set; use CFG_Edge_Set; with CFG_Edges; use CFG_Edges.CFG_Edges_Table_Package; with CFGs; use CFGs; with CFG_Set; use CFG_Set; with Xml_Generic_Parsers; use XML_Generic_Parsers; with Sets; with Ada.Exceptions; use Ada; package body Call_Cache_Framework is procedure Import_CFG (Sys : in out System; A_Processor : in Generic_Processor_Ptr; Result : in out Unbounded_String; Output : in Output_Format := String_Output) is A_Task : Generic_Task_Ptr; My_Iterator : Tasks_Iterator; Sys_CFG : System; Project_File_List : unbounded_string_list; Project_File_Dir_List : unbounded_string_list; a_cfg : CFG_Ptr; begin Result := To_Unbounded_String (""); if Output = Xml_Output then Set_Tag; else Set_Empty; end if; reset_iterator (Sys.Tasks, My_Iterator); loop current_element (Sys.Tasks, A_Task, My_Iterator); Result := Result & Lb_Minus & Lb_Task (Current_Language) & " " & A_Task.name & ": " & unbounded_lf; if (A_Task.cfg_name /= empty_string) then begin Systems.Read_From_Xml_File (Sys_CFG, Project_File_Dir_List, A_Task.cfg_name); Result := Result & ASCII.HT & Lb_Minus & Lb_CFG_Imported (Current_Language) & a_task.cfg_name & unbounded_lf; --If a cfg is imported previously, remove all nodes and edges --This is done after we know that an external CFG file exist -- begin a_cfg := Search_CFG(Sys.CFGs, a_task.cfg_name); for i in 0..a_cfg.nodes.Nb_Entries-1 loop Delete(Sys.CFG_Nodes,a_cfg.nodes.Entries(i)); end loop; for i in 0..a_cfg.edges.Nb_Entries-1 loop Delete(Sys.CFG_Edges,a_cfg.edges.Entries(i)); end loop; Result := Result & ASCII.HT & Lb_Minus & "Removing the existing CFG and import one from a file with file_name=" & a_task.cfg_name & unbounded_lf; exception when CFG_Not_Found => Result := Result & ASCII.HT & Lb_Minus & "No CFG specified, import one from a file with file_name=" & a_task.cfg_name & unbounded_lf; end; a_cfg := Search_CFG(Sys_CFG.CFGs, a_task.cfg_name); Add(Sys.CFGs,a_cfg); for i in 0..a_cfg.nodes.Nb_Entries-1 loop Add(Sys.CFG_Nodes,a_cfg.nodes.Entries(i)); end loop; for i in 0..a_cfg.edges.Nb_Entries-1 loop Add(Sys.CFG_Edges,a_cfg.edges.Entries(i)); end loop; exception when ex : others => Result := Result & ASCII.HT & Lb_Minus & "ERROR: CFG is not imported" & " (" & Exceptions.Exception_Name(ex) & ") " & unbounded_lf; end; else Result := Result & ASCII.HT & Lb_Minus & "WARNING: No CFG specified for this task" & unbounded_lf; end if; exit when is_last_element (Sys.Tasks, My_Iterator); next_element (Sys.Tasks, My_Iterator); end loop; exception when Basic_Block_Analysis.Invalid_Input_Data => Result := Result & Exception_Message & unbounded_lf; end Import_CFG; procedure Compute_Tasks_Cache_Access_Profile (Sys : in out System; A_Processor : in Generic_Processor_Ptr; Result : in out Unbounded_String; Output : in Output_Format := String_Output) is A_Cache_Access_Profile : Cache_Access_Profile_Ptr; A_CAP_Search : Cache_Access_Profile_Ptr; A_Task : Generic_Task_Ptr; My_Iterator : Tasks_Iterator; Sys_CFG : System; Project_File_List : unbounded_string_list; Project_File_Dir_List : unbounded_string_list; begin Put_Debug("Call Compute_Task_Cache_Access_Profile"); Result := To_Unbounded_String (""); if Output = Xml_Output then Set_Tag; else Set_Empty; end if; Result := Result & Lb_Minus & Lb_Compute_Cache_Access_Profile(Current_Language) & To_Unbounded_String (" ") & Lb_Compute_Cache_Access_Profile_Method(Current_Language) & To_Unbounded_String (" (") & To_Unbounded_String ("[20]") & To_Unbounded_String (")") & To_Unbounded_String (" : ") & unbounded_lf; -- Task Loop -- reset_iterator (Sys.Tasks, My_Iterator); loop A_Cache_Access_Profile := new Cache_Access_Profile; current_element (Sys.Tasks, A_Task, My_Iterator); if(A_Task.cpu_name = A_Processor.name) then begin Result := Result & ASCII.HT & A_Task.name & unbounded_lf; if (A_Task.cfg_name /= empty_string) then -- If a task has a CFG, always compute a new Cache Access Profile (CAP) -- The old Cache Access Profile is removed -- begin A_CAP_Search := Search_Cache_Access_Profile(my_cache_access_profiles => Sys.Cache_Access_Profiles, name => A_Task.cache_access_profile_name); Delete(Sys.Cache_Access_Profiles, A_CAP_Search); Put_Debug("Delete cache access profile with name " & A_Task.cache_access_profile_name & " of task: " & A_Task.name); exception when Cache_Access_Profile_Not_Found => Put_Debug("No cache access profile with name " & A_Task.cache_access_profile_name & " found for: " & A_Task.name); end; Compute_Cache_Access_Profile(Sys => Sys, Task_Name => A_Task.name, A_Cache_Access_Profile => A_Cache_Access_Profile); Result := Result & ASCII.HT & ASCII.HT & "UCB: " & ASCII.HT ; for i in 0..a_cache_access_profile.UCBs.Nb_Entries-1 loop Result := Result & a_cache_access_profile.UCBs.Entries(i).cache_block_number'Img & " "; end loop; Result := Result & unbounded_lf; Result := Result & ASCII.HT & ASCII.HT & "ECB: " & ASCII.HT ; for i in 0..a_cache_access_profile.ECBs.Nb_Entries-1 loop Result := Result & a_cache_access_profile.ECBs.Entries(i).cache_block_number'Img & " "; end loop; elsif (A_Task.cfg_name = empty_string) AND (A_Task.cache_access_profile_name /= empty_string) then -- If a task has no CFG but has an existing CAP. -- Reuse the existing CAP -- Result := Result & ASCII.HT & ASCII.HT & "WARNING: No CFG specified for this task" & unbounded_lf; begin A_CAP_Search := Search_Cache_Access_Profile(my_cache_access_profiles => Sys.Cache_Access_Profiles, name => A_Task.cache_access_profile_name); Result := Result & ASCII.HT & ASCII.HT & "WARNING: Found and reused an existing cache access profile" & unbounded_lf; Result := Result & ASCII.HT & ASCII.HT & "UCB: " & ASCII.HT ; for i in 0..A_CAP_Search.UCBs.Nb_Entries-1 loop Result := Result & A_CAP_Search.UCBs.Entries(i).cache_block_number'Img & " "; end loop; Result := Result & unbounded_lf; Result := Result & ASCII.HT & ASCII.HT & "ECB: " & ASCII.HT ; for i in 0..A_CAP_Search.ECBs.Nb_Entries-1 loop Result := Result & A_CAP_Search.ECBs.Entries(i).cache_block_number'Img & " "; end loop; exception when Cache_Access_Profile_Not_Found => Put_Debug("No cache access profile found for: " & A_Task.name); end; else -- No CFG, no CAP -- Result := Result & ASCII.HT & ASCII.HT & "WARNING: No CFG and cache access profile specified for this task" & unbounded_lf; end if; Result := Result & unbounded_lf; exception -- Task has a CFG but it is not found -- when ex : CFG_Not_Found => Result := Result & ASCII.HT & ASCII.HT & "ERROR: CFG Not Found (cfg_name=" & A_Task.cfg_name & ")" & unbounded_lf; end; end if; exit when is_last_element (Sys.Tasks, My_Iterator); next_element (Sys.Tasks, My_Iterator); end loop; exception when Basic_Block_Analysis.Invalid_Input_Data => Result := Result & Exception_Message & unbounded_lf; end Compute_Tasks_Cache_Access_Profile; end Call_Cache_Framework;