1. -- 
  2. --  Uwe R. Zimmer, Australia, September 2011 
  3. -- 
  4.  
  5. with Ada.Float_Text_IO;                    use Ada.Float_Text_IO; 
  6. with Ada.Integer_Text_IO;                  use Ada.Integer_Text_IO; 
  7. with Ada.Text_IO;                          use Ada.Text_IO; 
  8. with Generic_Message_Structures; 
  9. with Generic_Router; 
  10. with Generic_Routers; 
  11. with Generic_Routers_Configuration; 
  12. with GNAT.Command_Line;                    use GNAT.Command_Line; 
  13. with Routers_Configuration_Structures;      use Routers_Configuration_Structures; 
  14. with Topologies;                           use Topologies; 
  15.  
  16. procedure Test_Routers is 
  17.  
  18.    Command_Line_Parameters : Command_Line_Defaults; 
  19.    Options_Ok              : Boolean               := True; 
  20.  
  21.    procedure Print_Options is 
  22.  
  23.    begin 
  24.       New_Line; Put ("accepted options:"); 
  25.       New_Line; Put ("   [-t {Topology            : String   }] -> "); Put (Preconfigured_Topologies'Image (Command_Line_Parameters.Selected_Topology)); 
  26.       New_Line; Put ("      by Size            : Line, Ring, Star, Fully_Connected"); 
  27.       New_Line; Put ("      by Degree, Depths  : Tree"); 
  28.       New_Line; Put ("      by Dimension, Size : Mesh, Torus"); 
  29.       New_Line; Put ("      by Dimension       : Hypercube, Cube_Connected_Cycles,"); 
  30.       New_Line; Put ("                           Butterfly, Wrap_Around_Butterfly"); 
  31.       New_Line; Put ("   [-s {Size                : Positive }] -> "); Put (Command_Line_Parameters.Size, 3); 
  32.       New_Line; Put ("   [-g {Degree              : Positive }] -> "); Put (Command_Line_Parameters.Degree, 3); 
  33.       New_Line; Put ("   [-p {Depths              : Positive }] -> "); Put (Command_Line_Parameters.Depths, 3); 
  34.       New_Line; Put ("   [-d {Dimension           : Positive }] -> "); Put (Command_Line_Parameters.Dimension, 3); 
  35.       New_Line; Put ("   [-c {Print connections   : Boolean  }] -> "); Put (Boolean'Image (Command_Line_Parameters.Print_Connections)); 
  36.       New_Line; Put ("   [-i {Print distances     : Boolean  }] -> "); Put (Boolean'Image (Command_Line_Parameters.Print_Distances)); 
  37.       New_Line; Put ("   [-w {Routers settle time : Seconds  }] -> "); Put (Float (Command_Line_Parameters.Routers_Settle_Time), 2, 2, 0); 
  38.       New_Line; Put ("   [-o {Comms timeout       : Seconds  }] -> "); Put (Float (Command_Line_Parameters.Comms_Timeout), 2, 2, 0); 
  39.       New_Line; Put ("   [-m {Test mode           : String   }] -> "); Put (Test_Modes'Image (Command_Line_Parameters.Test_Mode)); 
  40.       New_Line; Put ("      Available modes: One_to_All, All_to_One"); 
  41.       New_Line; 
  42.       New_Line; 
  43.    end Print_Options; 
  44.  
  45. begin 
  46.    Initialize_Option_Scan; 
  47.    loop 
  48.       declare 
  49.          Option : constant Character := Getopt ("t: s: g: p: d: c: i: w: o: m:"); 
  50.       begin 
  51.          case Option is 
  52.             when ASCII.NUL => exit; 
  53.             when 't' => Command_Line_Parameters.Selected_Topology   := Preconfigured_Topologies'Value (Parameter); 
  54.             when 's' => Command_Line_Parameters.Size                := Positive'Value (Parameter); 
  55.             when 'g' => Command_Line_Parameters.Degree              := Positive'Value (Parameter); 
  56.             when 'p' => Command_Line_Parameters.Depths              := Positive'Value (Parameter); 
  57.             when 'd' => Command_Line_Parameters.Dimension           := Positive'Value (Parameter); 
  58.             when 'c' => Command_Line_Parameters.Print_Connections   := Boolean'Value (Parameter); 
  59.             when 'i' => Command_Line_Parameters.Print_Distances     := Boolean'Value (Parameter); 
  60.             when 'w' => Command_Line_Parameters.Routers_Settle_Time := Duration'Value (Parameter); 
  61.             when 'o' => Command_Line_Parameters.Comms_Timeout       := Duration'Value (Parameter); 
  62.             when 'm' => Command_Line_Parameters.Test_Mode           := Test_Modes'Value (Parameter); 
  63.             when others => raise Program_Error; 
  64.          end case; 
  65.       exception 
  66.          when others => 
  67.             New_Line; Put ("---> Error in option -"); Put (Option); New_Line; 
  68.             Options_Ok := False; 
  69.       end; 
  70.    end loop; 
  71.  
  72.    Print_Options; 
  73.  
  74.    if Options_Ok then 
  75.  
  76.       New_Line; 
  77.       Put_Line ("----------------------- Instantiating router tasks -----------------------------"); 
  78.  
  79.       declare 
  80.  
  81.          package Routers_Configuration is new Generic_Routers_Configuration (Command_Line_Parameters); 
  82.          package Message_Structures   is new Generic_Message_Structures   (Routers_Configuration); 
  83.          package Router               is new Generic_Router               (Message_Structures); 
  84.          package Routers              is new Generic_Routers              (Router); 
  85.  
  86.          use Routers_Configuration; 
  87.          use Message_Structures; 
  88.          use Routers; 
  89.  
  90.          use Message_Strings; 
  91.  
  92.          type Distances_Map is array (Router_Range, Router_Range) of Natural; 
  93.  
  94.          procedure Print_Connections is 
  95.  
  96.          begin 
  97.             New_Line; 
  98.             Put ("    "); 
  99.             for i in Router_Range loop 
  100.                Put (Integer (i), 3); 
  101.             end loop; 
  102.             New_Line; 
  103.             Put ("    +"); 
  104.             for i in Router_Range loop 
  105.                Put ("---"); 
  106.             end loop; 
  107.             Put ('+'); 
  108.             New_Line; 
  109.             for i in Router_Range loop 
  110.                Put (Integer (i), 3); 
  111.                Put (" |"); 
  112.                for j in Router_Range loop 
  113.                   if i = j then 
  114.                      Put (" . "); 
  115.                   elsif Nodes_Connected (Connection_Topology, Positive (i), Positive (j)) then 
  116.                      if Nodes_Connected (Connection_Topology, Positive (j), Positive (i)) then 
  117.                         Put ("<->"); 
  118.                      else 
  119.                         Put (" ->"); 
  120.                      end if; 
  121.                   else 
  122.                      Put ("   "); 
  123.                   end if; 
  124.                end loop; 
  125.                Put ('|'); 
  126.                New_Line; 
  127.             end loop; 
  128.             Put ("    +"); 
  129.             for i in Router_Range loop 
  130.                Put ("---"); 
  131.             end loop; 
  132.             Put ('+'); 
  133.             New_Line; 
  134.          end Print_Connections; 
  135.  
  136.          procedure Print_Distance_Map (Map : Distances_Map) is 
  137.  
  138.          begin 
  139.             New_Line; 
  140.             Put ("     "); 
  141.             for i in Router_Range loop 
  142.                Put (Integer (i), 3); 
  143.             end loop; 
  144.             New_Line; 
  145.             Put ("    +"); 
  146.             for i in Router_Range loop 
  147.                Put ("---"); 
  148.             end loop; 
  149.             Put ('+'); 
  150.             New_Line; 
  151.             for i in Router_Range loop 
  152.                Put (Integer (i), 3); 
  153.                Put (" |"); 
  154.                for j in Router_Range loop 
  155.                   if i = j then 
  156.                      Put ("  ."); 
  157.                   elsif Map (i, j) = 1 then 
  158.                      Put ("   "); 
  159.                   else 
  160.                      Put (Map (i, j), 3); 
  161.                   end if; 
  162.                end loop; 
  163.                Put ('|'); 
  164.                New_Line; 
  165.             end loop; 
  166.             Put ("    +"); 
  167.             for i in Router_Range loop 
  168.                Put ("---"); 
  169.             end loop; 
  170.             Put ('+'); 
  171.             New_Line; 
  172.          end Print_Distance_Map; 
  173.  
  174.       begin 
  175.          if Routers_Configured then 
  176.  
  177.             Put_Line ("  => Routers up and running "); 
  178.             Put_Line ("-------------------------------- Waiting ---------------------------------------"); 
  179.             Put ("  Time for routers to establish their strategies : "); Put (Float (Command_Line_Parameters.Routers_Settle_Time), 2, 2, 0); Put (" second(s)"); New_Line; 
  180.  
  181.             delay Command_Line_Parameters.Routers_Settle_Time; -- let the routers establish their strategies first 
  182.  
  183.             Put_Line ("------------------------------ Measurements ------------------------------------"); 
  184.  
  185.             declare 
  186.                Sum_Hops                : Natural       := 0; 
  187.                Min_Hops                : Natural       := Natural'Last; 
  188.                Max_Hops                : Natural       := Natural'First; 
  189.                Distance_Map            : Distances_Map := (others => (others => Natural'Last)); 
  190.                Measurements_Successful : Boolean       := True; 
  191.  
  192.                function Send_Probe (Sender, Receiver : Router_Range) return Boolean is 
  193.  
  194.                begin 
  195.                   select 
  196.                      Router_Tasks (Sender).Send_Message ((Destination => Receiver, 
  197.                                                           The_Message => To_Bounded_String (" - The quick brown fox jumps over the lazy dog - "))); 
  198.                      return True; 
  199.                   or 
  200.                      delay Command_Line_Parameters.Comms_Timeout; 
  201.                      Put_Line ("Error: Unresponsive router found : " & Router_Range'Image (Sender) & " (does not respond to Send_Message)"); 
  202.                      Put_Line ("   -> Measurements aborted"); 
  203.                      return False; 
  204.                   end select; 
  205.                end Send_Probe; 
  206.  
  207.                function Receive_Probe (Sender, Receiver : Router_Range) return Boolean is 
  208.  
  209.                   Mailbox_Message : Messages_Mailbox; 
  210.  
  211.                begin 
  212.                   select 
  213.                      Router_Tasks (Receiver).Receive_Message (Mailbox_Message); 
  214.                      Distance_Map (Mailbox_Message.Sender, Receiver) := Mailbox_Message.Hop_Counter; 
  215.                      Sum_Hops := Sum_Hops + Mailbox_Message.Hop_Counter; 
  216.                      Min_Hops := Natural'Min (Min_Hops, Mailbox_Message.Hop_Counter); 
  217.                      Max_Hops := Natural'Max (Max_Hops, Mailbox_Message.Hop_Counter); 
  218.                      return True; 
  219.                   or 
  220.                      delay Command_Line_Parameters.Comms_Timeout; 
  221.                      Put_Line ("Error: Message not received in time : from router" & Router_Range'Image (Sender) & " to router" & Router_Range'Image (Receiver)); 
  222.                      Put_Line ("   -> Measurements aborted"); 
  223.                      return False; 
  224.                   end select; 
  225.                end Receive_Probe; 
  226.  
  227.             begin 
  228.                Main_Measurement : for i in Router_Range loop 
  229.                   for j in Router_Range loop 
  230.                      if i /= j then 
  231.                         case Command_Line_Parameters.Test_Mode is 
  232.                            when One_To_All => Measurements_Successful := Send_Probe (i, j); 
  233.                            when All_to_One => Measurements_Successful := Send_Probe (j, i); 
  234.                         end case; 
  235.                         if not Measurements_Successful then 
  236.                            exit Main_Measurement; 
  237.                         end if; 
  238.                      end if; 
  239.                   end loop; 
  240.                   for j in Router_Range loop 
  241.                      if i /= j then 
  242.                         case Command_Line_Parameters.Test_Mode is 
  243.                            when One_To_All => Measurements_Successful := Receive_Probe (i, j); 
  244.                            when All_to_One => Measurements_Successful := Receive_Probe (j, i); 
  245.                         end case; 
  246.                         if not Measurements_Successful then 
  247.                            exit Main_Measurement; 
  248.                         end if; 
  249.                      end if; 
  250.                   end loop; 
  251.                end loop Main_Measurement; 
  252.  
  253.                if Measurements_Successful then 
  254.                   declare 
  255.                      Avg_Hops : constant Float := Float (Sum_Hops) / Float (((Router_Range'Last ** 2) - Router_Range'Last)); 
  256.                   begin 
  257.                      Put ("Minimal hops : "); Put (Min_Hops, 3); New_Line; 
  258.                      Put ("Maximal hops : "); Put (Max_Hops, 3); New_Line; 
  259.                      Put      ("Average hops : "); Put (Avg_Hops, 3, 2, 0); New_Line; 
  260.                      for i in Router_Range loop 
  261.                         for j in Router_Range'First .. i loop 
  262.                            if Distance_Map (i, j) /= Distance_Map (j, i) then 
  263.                               Put_Line ("Warning: unsymmetrical distances " & "(" & Router_Range'Image (i) & "->" & Router_Range'Image (j) & "):" & Natural'Image (Distance_Map (i, j)) 
  264.                                         & " while " & "(" & Router_Range'Image (j) & "->" & Router_Range'Image (i) & "):" & Natural'Image (Distance_Map (j, i))); 
  265.                            end if; 
  266.                         end loop; 
  267.                      end loop; 
  268.  
  269.                      if Command_Line_Parameters.Print_Distances then 
  270.                         Print_Distance_Map (Distance_Map); 
  271.                      end if; 
  272.                   end; 
  273.                end if; 
  274.             end; 
  275.             New_Line; 
  276.  
  277.          else 
  278.             Put_Line ("  => Routers did not respond to configuration call -> no measurements performed"); 
  279.          end if; 
  280.  
  281.          Put_Line ("--------------- Information about the selected network topology ----------------"); 
  282.          Put_Line ("  Topology                    : " & Preconfigured_Topologies'Image (Command_Line_Parameters.Selected_Topology)); 
  283.          case Command_Line_Parameters.Selected_Topology is 
  284.             when Line                  => Put ("  Size                        : "); Put (Command_Line_Parameters.Size,      4); New_Line; 
  285.             when Ring                  => Put ("  Size                        : "); Put (Command_Line_Parameters.Size,      4); New_Line; 
  286.             when Star                  => Put ("  Size                        : "); Put (Command_Line_Parameters.Size,      4); New_Line; 
  287.             when Fully_Connected       => Put ("  Size                        : "); Put (Command_Line_Parameters.Size,      4); New_Line; 
  288.             when Tree                  => Put ("  Degree                      : "); Put (Command_Line_Parameters.Degree,    4); New_Line; 
  289.                Put ("  Depths                      : "); Put (Command_Line_Parameters.Depths,    4); New_Line; 
  290.             when Mesh                  => Put ("  Dimension                   : "); Put (Command_Line_Parameters.Dimension, 4); New_Line; 
  291.                Put ("  Size                        : "); Put (Command_Line_Parameters.Size,      4); New_Line; 
  292.             when Torus                 => Put ("  Dimension                   : "); Put (Command_Line_Parameters.Dimension, 4); New_Line; 
  293.                Put ("  Size                        : "); Put (Command_Line_Parameters.Size,      4); New_Line; 
  294.             when Hypercube             => Put ("  Dimension                   : "); Put (Command_Line_Parameters.Dimension, 4); New_Line; 
  295.             when Cube_Connected_Cycles => Put ("  Dimension                   : "); Put (Command_Line_Parameters.Dimension, 4); New_Line; 
  296.             when Butterfly              => Put ("  Dimension                   : "); Put (Command_Line_Parameters.Dimension, 4); New_Line; 
  297.             when Wrap_Around_Butterfly  => Put ("  Dimension                   : "); Put (Command_Line_Parameters.Dimension, 4); New_Line; 
  298.          end case; 
  299.          Put    ("  Number of nodes in topology : "); Put (Nodes_in_Topology (Connection_Topology), 4); New_Line; 
  300.          if Min_Degree (Connection_Topology) = Max_Degree (Connection_Topology) then 
  301.             Put ("  Constant connection degree  : ");  Put (Min_Degree (Connection_Topology), 4); New_Line; 
  302.          else 
  303.             Put ("  Minimal connection degree   : "); Put (Min_Degree (Connection_Topology), 4); New_Line; 
  304.             Put ("  Maximal connection degree   : "); Put (Max_Degree (Connection_Topology), 4); New_Line; 
  305.          end if; 
  306.          if Command_Line_Parameters.Print_Connections then 
  307.             Print_Connections; 
  308.          end if; 
  309.          New_Line; 
  310.  
  311.          Global_Shutdown; 
  312.  
  313.       end; 
  314.    end if; 
  315.  
  316. end Test_Routers;