#!/usr/bin/perl
use strict;
use warnings;
use Switch;
sub dec2bin {
my $str = unpack("B32", pack("N", shift));
$str =~ s/^0+(?=\d)//; # otherwise we get leading zeros
switch($str)
{
case("0") {$str = '00'.$str;}
case("1") {$str = '00'.$str;}
case("10") {$str = '0'.$str;}
case("11") {$str = '0'.$str;}
}
return $str;
}
my @matrix_banyan;
my $out_port;
# Step 1 -
# Pre Routing Matrix - To be used after Batcher sorted is implemented
$matrix_banyan[9][0] = '0';
$matrix_banyan[9][1] = '2';
$matrix_banyan[9][2] = '4';
$matrix_banyan[9][3] = '6';
$matrix_banyan[9][4] = '1';
$matrix_banyan[9][5] = '3';
$matrix_banyan[9][6] = '5';
$matrix_banyan[9][7] = '7';
$matrix_banyan[0][0] = '0';
$matrix_banyan[0][1] = '4';
$matrix_banyan[0][2] = '2';
$matrix_banyan[0][3] = '6';
$matrix_banyan[0][4] = '1';
$matrix_banyan[0][5] = '5';
$matrix_banyan[0][6] = '3';
$matrix_banyan[0][7] = '7';
$matrix_banyan[1][0] = '0';
$matrix_banyan[1][1] = '2';
$matrix_banyan[1][2] = '1';
$matrix_banyan[1][3] = '3';
$matrix_banyan[1][4] = '4';
$matrix_banyan[1][5] = '6';
$matrix_banyan[1][6] = '5';
$matrix_banyan[1][7] = '7';
$matrix_banyan[2][0] = '0';
$matrix_banyan[2][1] = '1';
$matrix_banyan[2][2] = '2';
$matrix_banyan[2][3] = '3';
$matrix_banyan[2][4] = '4';
$matrix_banyan[2][5] = '5';
$matrix_banyan[2][6] = '6';
$matrix_banyan[2][7] = '7';
my @random_set;
my %seen;
# S1 *
# Generate Random Numbers
for (1..8) {
my $candidate
= int rand(8); # rand returns random numbers redo if $seen{$candidate}++;
if( $candidate eq 0 or $candidate eq 2 or $candidate eq 1) {
next;
}
push @random_set, $candidate;
}
print "\n => STEP 1 : Generate random output port options : ";
print "\n\n \t => Output Ports are :\t";
my @output_port_list = @random_set;
print join(', ', @output_port_list), "\n";
# S2 *
print "\n\n\n => STEP 2 : Apply Batcher Sorter to the Output Ports...";
print "\n\n \t => Sorted Output Port Order :\t";
# Use Merge Sort to sort the output ports in ascending order
my @sorted_output_ports = sort @output_port_list; # Sort output ports
print join(', ', @sorted_output_ports), "\n";
my @input; # Contains sorted output ports for each input port after batcher sorter
my @final_input_ports= ();
# Pre Banyan Switch Routing
# Sorted Output Ports are routed to input ports before the banyan switch
# Now, Make routing decision based on matrix_banyan[9][$i]
# Now each input port has a packet with an output port address attached to it
# Feed this array into Main Banyan Switcher
# S 3 * Pre-banyan - Trap Network( re route packets for input into banyan)
# Trap network is for shuffling
for ( my $i = 0,my $j = 0; $i < 8; $i++,$j++)
{
# Assign output ports to input ports
$input[$i] = $sorted_output_ports[$j]; # ip[0] = op
}
print "\n\n\n => STEP 3 : Mapping Output Ports after Batcher Sorter & Trap Network:\n";
# Assign NEW input ports to output ports based on [9][]
# Each input port attaches output port number as header
for(my $i = 0 ; $i < scalar(@sorted_output_ports); $i++)
{
# Packet at [9][6] input port should be assigned to [0][5] input port
$final_input_ports[$i] = $matrix_banyan[9][$i];
print "\n\t => Packet for Output Port $input[$i] will be routed through Input Port $final_input_ports[$i]\n\n\n";
}
# Move packets from input to output
print "\n\nSTEP 4 : Routing using Banyan : ";
# S 5 .. *
for ( my $s = 0, my $p = 1; $s < @sorted_output_ports ; $s++,$p++)
{
# Process input ports one by one
my $input_port = $final_input_ports[$s];
# Get the output port for the current input port
my $output_port = $input[$s];
# Convert output port to binary for bit processing
my $bin_output_port = dec2bin($output_port);
# Extract each bit of output port
my @digits = split('',$bin_output_port);
my $current_port = $input_port;
if ($current_port eq '')
{next;}
print "\n\n\tInput Port $s => $bin_output_port\n";
# Main Banyan Switch
for( my $i = 0, my $step = 1; $i<scalar(@digits);$i++, $step++)
{
my $ip = $current_port;
switch($digits[$i])
{
case 0 {
# If current bit is 0 and current_port is a 1 in the 2*2 microswitch.
# The packet has to go through 0 in the microswitch. Hence, the currentport value
# is decremented.
if ($current_port eq 1 or $current_port eq 3 or $current_port eq 5 or $current_port eq 7 )
{
$current_port = $current_port - 1;
}
$out_port = $matrix_banyan[$i][$current_port]; # Go Straight ahead through 0
$current_port = $out_port; # Assign the output port as current port
}
case 1 {
# If current bit is 1 and current_port is a 0 in the 2*2 microswitch.
# The packet has to go through 1 in the microswitch. Hence, the currentport value
# is incremented.
if ($current_port eq 0 or $current_port eq 2 or $current_port eq 4 or $current_port eq 6 )
{
$current_port = $current_port + 1;
}
$out_port = $matrix_banyan[$i][$current_port]; # Go through 1
$current_port = $out_port; # Assign the output port as current port
}
}
print "\t\t\t\tStage $step :\n \t\t\t\tCurrent Port : $ip \n \t\t\t\tBit Being Processed : $digits[$i]\n \t\t\t\tOutput Port : $out_port \n\n";
}
}