------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- 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 Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with Text_IO; use Text_IO; with Ada.Exceptions; use Ada.Exceptions; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with translate; use translate; with text_io; use text_io; with unbounded_strings; use unbounded_strings; with Dependencies ; use Dependencies; with Task_Dependencies; use Task_Dependencies; with Task_Dependencies; use Task_Dependencies.Half_Dep_Set; with Tasks; use Tasks; with Task_Set; use Task_Set; with Message_Set ; use Message_Set ; with Messages; use Messages ; with Systems; use Systems; with Version; use Version; with Parameters; use Parameters; use Parameters.User_Defined_Parameters_Table_Package; with Parameters.extended; use Parameters.extended; with mesh_analysis; use mesh_analysis; with mesh_analysis.delays ; use mesh_analysis.delays ; with memories; use memories; use memories.Memories_Table_Package; with Processors; use Processors; with Processor_Set; use Processor_Set; use Processor_Set.Generic_Processor_Set; with debug; use debug; package body spacewire_flow_transformation is procedure Compute_Spacewire_transformation (Sys : in System; a_network : in spacewire_network_ptr; Result : out System) is Destination_tasks : Tasks_set ; Source_tasks : Tasks_set ; A_link_mat : links_mat ; SourceTask_position_Table : tab_Position ; DestinationTask_position_Table : tab_Position ; SourceTask_rank_table : processor_ranks ; DestinationTask_rank_table : processor_ranks ; begin ----------------------------------------------- -- Compute the flow Model and used links ----------------------------------------------- ----------------------------------------------- -- generate two tables : Destination_tasks and Source_tasks from sys. -- task Source_task(i) send a message to task Destination_task. ----------------------------------------------- compute_source_destination_task(My_tasks => sys.Tasks, My_Messages => sys.messages, My_dep => sys.dependencies, Destination_tasks => Destination_tasks, Source_tasks => Source_tasks); ----------------------------------------------- -- generate two tables : Destination_tasks_position_table and Source_tasks_position_table. -- task Source_task(i) will be executed on SourceTask_position_Table(i). -- task Destination_task(i) will be executed on Destination_Task_position_Table(i). ----------------------------------------------- compute_spw_source_destination_task_position(SourceTask_position_Table=> SourceTask_position_Table, DestinationTask_position_Table=> DestinationTask_position_Table, SourceTask_rank_table=> SourceTask_rank_table, DestinationTask_rank_table=> DestinationTask_rank_table, Source_tasks=> Source_tasks, Destination_tasks=> Destination_tasks, My_messages=> sys.messages, a_Network => a_network); ------------------------------------- --- generate used links for each --- message : the function F of the flow model ------------------------------------- generate_links_spw(A_link_mat => A_link_mat, My_messages => sys.messages, SourceTask_position_Table => SourceTask_position_Table, DestinationTask_position_Table => DestinationTask_position_Table, SourceTask_rank_table => SourceTask_rank_table, a_Network => a_network); ------------------------------------------------- --- Create the DAG model from the design model ------------------------------------------------- flow_to_task_spw ( My_processors => sys.Processors, My_tasks => sys.Tasks, My_messages => sys.messages, My_Dependencies => sys.dependencies, A_link_mat => A_link_mat, Destination_tasks => Destination_tasks, Source_tasks => Source_tasks, a_Network => a_network, result => result ); end Compute_Spacewire_transformation; ------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------ ----- flow_to_task_Spacewire converts the flow model generated by ------ ----- the Spw network to a task model ------ ----- For SpW Router: ------ ----- 1 tram/link ==> 1 task ------ ----- 1 link ==> 1 processor ------ ------------------------------------------------------------------------------------ ----- PS: 1. Delete (Spw architecture network / dependencies / messages) ------ ----- 2. add new messages with new dependencies. ------ ------------------------------------------------------------------------------------ procedure flow_to_task_spw ( My_processors : in Processors_set; My_tasks : in Tasks_set ; My_messages : in Messages_Set ; My_Dependencies : in Tasks_Dependencies_Ptr ; A_link_mat : in links_mat; Destination_tasks : in Tasks_set; Source_tasks : in Tasks_set; a_network : in spacewire_network_ptr; Result : in out system ) is a_core : Core_Unit_Ptr; a_cpu_name : Unbounded_String ; a_address_Space : Unbounded_String ; A_capacity : natural := 0; A_period : natural := 0; a_task : Generic_Task_Ptr; Mem : Memories_Table; My_Iterator1 : Tasks_Iterator; My_Iterator2: Messages_iterator; A_Message : Generic_Message_Ptr; i, var1, var2, var3 , var4, var5, Packet_size : integer ; A_link : mesh_Links ; A_link_table : Links_tab ; A_TaskNS : Generic_Task_Ptr; A_TaskND : Generic_Task_Ptr; A_message1, A_message2: Generic_Message_Ptr; A_task1 : Generic_Task_Ptr; A_task2 : Generic_Task_Ptr; My_Address_Spaces : Address_Spaces_set ; My_core_units: core_units_Set ; begin Result.Tasks := My_tasks ; Result.Processors := My_processors ; Result.Address_Spaces := My_Address_Spaces ; Result.Core_units := My_core_units ; Result.messages := My_messages ; Result.dependencies := My_Dependencies ; -- Create processing units of the DAG -- Add_core_unit(My_core_units => Result.Core_units, A_core_unit => a_core, Name => Suppress_Space (To_Unbounded_String ("Core_Link")), Is_Preemptive => preemptive, Quantum => 0, speed => 1, capacity => 1, period => 1, priority => 1, File_Name => empty_string, A_Scheduler => DAG_highest_level_first_estimated_times_protocol, automaton_name => empty_string, start_time => 0 , Mem => Mem ); --les liens horizontales-- -------------------------- for j in 0 .. (a_network.Ydimension) loop var1 := (a_network.Ydimension+1) * j ; for i in 0 .. (a_network.Xdimension-1) loop var2 := var1 ; var1 := var1 + 1 ; Add_Processor(My_processors => Result.Processors, Name => Suppress_Space (To_Unbounded_String("proc_link "& var2'Img & "To " & var1'Img )), a_Core => a_core ); Add_Processor(My_processors => Result.Processors, Name => Suppress_Space (To_Unbounded_String("proc_link "& var1'Img & "To " & var2'Img )), a_Core => a_core ); Add_Address_Space(My_Address_Spaces => Result.Address_Spaces, Name => Suppress_Space (To_Unbounded_String ("Address_Space_" & var2'Img & "To" & var1'Img )), Cpu_Name => Suppress_Space (To_Unbounded_String ("proc_link"& var2'Img & "To" & var1'Img )), Text_Memory_Size => 1024, Stack_Memory_Size => 1024, Data_Memory_Size => 1024, Heap_Memory_Size => 1024); Add_Address_Space(My_Address_Spaces => Result.Address_Spaces, Name => Suppress_Space (To_Unbounded_String ("Address_Space_" & var1'Img & "To" & var2'Img )), Cpu_Name => Suppress_Space (To_Unbounded_String ("proc_link"& var1'Img & "To" & var2'Img )), Text_Memory_Size => 1024, Stack_Memory_Size => 1024, Data_Memory_Size => 1024, Heap_Memory_Size => 1024); end loop ; end loop ; -------------------------- --les liens verticales-- -------------------------- for j in 0 .. (a_network.Ydimension) loop var1 := j ; for i in 0 .. (a_network.Xdimension-1) loop var2 := var1 ; var1 := var1 + (a_network.Xdimension+1) ; Add_Processor(My_processors => Result.Processors, Name => Suppress_Space (To_Unbounded_String("proc_link "& var2'Img & "To " & var1'Img )), a_Core => a_core ); Add_Processor(My_processors => Result.Processors, Name => Suppress_Space (To_Unbounded_String("proc_link "& var1'Img & "To " & var2'Img )), a_Core => a_core ); Add_Address_Space ( My_Address_Spaces => Result.Address_Spaces, Name => Suppress_Space (To_Unbounded_String ("Address_Space_" & var2'Img & "To" & var1'Img )), Cpu_Name => Suppress_Space (To_Unbounded_String ("proc_link"& var2'Img & "To" & var1'Img )), Text_Memory_Size => 1024, Stack_Memory_Size => 1024, Data_Memory_Size => 1024, Heap_Memory_Size => 1024 ); Add_Address_Space ( My_Address_Spaces => Result.Address_Spaces, Name => Suppress_Space (To_Unbounded_String ("Address_Space_" & var1'Img & "To" & var2'Img )), Cpu_Name => Suppress_Space (To_Unbounded_String ("proc_link"& var1'Img & "To" & var2'Img )), Text_Memory_Size => 1024, Stack_Memory_Size => 1024, Data_Memory_Size => 1024, Heap_Memory_Size => 1024); end loop ; end loop ; i := 1 ; reset_iterator (My_messages, My_Iterator2); reset_iterator (Destination_tasks, My_Iterator1); loop current_element (My_messages , A_Message, My_Iterator2) ; current_element (Destination_tasks , A_TaskND, My_Iterator1) ; current_element (Source_tasks , A_TaskNS, My_Iterator1) ; A_link_table := A_link_mat(i) ; For j in 1 .. Integer(link_table_size(i)) loop A_link := A_link_table(j) ; Packet_size := A_Message.size ; --------------------------------------- ------converts flows to tasks---------- --------------------------------------- for flit in 1 .. Packet_size loop Add_Task (My_tasks => Result.Tasks, A_Task => a_task, Name => Suppress_Space (To_Unbounded_String ("Task_flow"&i'Img&j'Img&":"&flit'Img)), Cpu_Name => Suppress_Space (To_Unbounded_String("proc_link"& A_link.source'Img & "To" & A_link.destination'Img )), Address_Space_Name => Suppress_Space (To_Unbounded_String("Address_Space_"& A_link.source'Img & "To" & A_link.destination'Img )), core_name => empty_string, Task_Type => Periodic_Type, Start_Time => 0, Capacity => a_network.link_delay, --- le temps de transmission (Path delay) d'un seul flit/lien Period => A_TaskNS.Deadline, --- Periode de tâche source Deadline => A_TaskND.Deadline, --- deadline de tâche destination Jitter => 0, Blocking_Time => 0, Priority => 1, --- Priorité de la tâche source Criticality => 0, Policy => Sched_Fifo); put_debug ("Added task name : "& To_String(A_task.name) ) ; --------------------------------------- ------Produce Messages between--------- --------task_flow---------------------- --------------------------------------- var3 := j; if var3 >1 then Add_Message(My_Messages => Result.messages, Name => Suppress_Space (To_Unbounded_String("Message_of_flow_H " & i'Img & ":" & var3'Img & ":" & flit'Img )), Size => 0, Period => 0, Deadline => 0, Jitter => 0, Param => No_User_Defined_Parameter, Response_Time => 0, Communication_Time => 0); end if ; --------------------------------------- ------Produce dependency between------- ------ task_flow ------- --------------------------------------- var3 := j ; if var3 >1 then var4 := var3 - 1 ; A_task1 := Search_Task (Result.Tasks, Suppress_Space (To_Unbounded_String ("Task_flow"&i'Img&var4'Img&":"&flit'Img))) ; A_task2 := Search_Task (Result.Tasks, Suppress_Space (To_Unbounded_String ("Task_flow"&i'Img&var3'Img&":"&flit'Img))); A_message2 := Search_Message (Result.Messages, Suppress_Space (To_Unbounded_String("Message_of_flow_H " & i'Img & ":" & var3'Img & ":" & flit'Img))); Add_One_Task_Dependency_asynchronous_communication (My_Dependencies => result.Dependencies, A_Task => A_task1, A_Dep => A_message2, A_Type => FROM_TASK_TO_OBJECT, protocol_property => All_Messages); Add_One_Task_Dependency_asynchronous_communication (My_Dependencies => result.Dependencies, A_Task => A_task2, A_Dep => A_message2, A_Type => FROM_OBJECT_TO_TASK, protocol_property => All_Messages); put_debug ("from : "& To_String(A_task1.name) & " to " & To_String(A_task2.name) & " over " & To_String(A_message2.name) ) ; end if ; end loop ; end loop ; --------------------------------------- ------Produce Messages between ------ ------ Source task and ------ ------ the first task_flow ------ --------------------------------------- for flit in 1 .. Packet_size loop Add_Message(My_Messages => Result.messages, Name => Suppress_Space (To_Unbounded_String("Message_of_flow" & i'Img & ":" & flit'Img & "from_source")), Size => 0, Period => 0, Deadline => 0, Jitter => 0, Param => No_User_Defined_Parameter, Response_Time => 0, Communication_Time => 0); --------------------------------------- ------Produce dependency between ------ ------ Source task and ------ ------ the first task_flow ------ --------------------------------------- A_message1 := Search_Message (Result.messages, Suppress_Space (To_Unbounded_String ("Message_of_flow" & i'Img & ":" & flit'Img & "from_source"))) ; A_task1 := Search_Task (Result.Tasks, Suppress_Space (To_Unbounded_String ("Task_flow"&i'Img&"1"&":"&flit'Img))) ; Add_One_Task_Dependency_asynchronous_communication (My_Dependencies => result.Dependencies, A_Task => A_TaskNS, A_Dep => A_message1, A_Type => FROM_TASK_TO_OBJECT, protocol_property => All_Messages); Add_One_Task_Dependency_asynchronous_communication (My_Dependencies => result.Dependencies, A_Task => A_task1, A_Dep => A_message1, A_Type => FROM_OBJECT_TO_TASK, protocol_property => All_Messages); put_debug ("from : "& To_String(A_TaskNS.name) & " to " & To_String(A_task1.name) & " over " & To_String(A_message1.name) ) ; --------------------------------------- ------Produce Messages between ------ ------ the last task_flow ------ ------ and the Destination task ------ --------------------------------------- Add_Message(My_Messages => Result.messages, Name => Suppress_Space (To_Unbounded_String("Message_of_flow" & i'Img & ":" & flit'Img & "To_Destination")), Size => 0, Period => 0, Deadline => 0, Jitter => 0, Param => No_User_Defined_Parameter, Response_Time => 0, Communication_Time => 0); --------------------------------------- ------Produce dependency between ------ ------ the last task_flow ------ ------ and the Destination task ------ --------------------------------------- A_message1 := Search_Message (Result.messages, Suppress_Space (To_Unbounded_String ("Message_of_flow" & i'Img & ":" & flit'Img & "To_Destination"))) ; var5 := Integer(link_table_size(i)) ; A_task2 := Search_Task (Result.Tasks, Suppress_Space (To_Unbounded_String ("Task_flow"&i'Img&var5'Img & ":" & flit'Img))); Add_One_Task_Dependency_asynchronous_communication (My_Dependencies => result.Dependencies, A_Task => A_Task2, A_Dep => A_message1, A_Type => FROM_TASK_TO_OBJECT, protocol_property => All_Messages); Add_One_Task_Dependency_asynchronous_communication (My_Dependencies => result.Dependencies, A_Task => A_taskND, A_Dep => A_message1, A_Type => FROM_OBJECT_TO_TASK, protocol_property => All_Messages); put_debug ("from : "& To_String(A_task2.name) & " to " & To_String(A_taskND.name) & " over " & To_String(A_message1.name) ) ; end loop ; i := i +1 ; exit when is_last_element (My_messages, My_Iterator2 ); next_element (My_messages , My_Iterator2) ; next_element (Destination_tasks, My_Iterator1) ; end loop; end flow_to_task_spw ; end spacewire_flow_transformation;