URL
https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk
#!/usr/bin/perl -w
#this file contains NoC topology related sub-functions
use constant::boolean;
use strict;
use warnings;
use FindBin;
use lib $FindBin::Bin;
sub get_topology_info {
my ($self) =@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my $T3=$self->object_get_attribute('noc_param','T3');
my $V = $self->object_get_attribute('noc_param','V');
my $Fpay = $self->object_get_attribute('noc_param','Fpay');
return get_topology_info_sub($topology, $T1, $T2, $T3,$V, $Fpay);
}
sub get_topology_info_from_parameters {
my ($ref) =@_;
my %noc_info;
my %param= %$ref if(defined $ref );
my $topology=$param{'TOPOLOGY'};
my $T1 =$param{'T1'};
my $T2 =$param{'T2'};
my $T3 =$param{'T3'};
my $V =$param{'V'};
my $Fpay=$param{'Fpay'};
return get_topology_info_sub($topology, $T1, $T2, $T3,$V, $Fpay);
}
sub get_topology_info_sub {
my ($topology, $T1, $T2, $T3,$V, $Fpay)=@_;
my $NE; # number of end points
my $NR; # number of routers
my $RAw; # routers address width
my $EAw; # Endpoints address width
my $Fw = 2+$V+$Fpay;
if($topology eq '"TREE"') {
my $K = $T1;
my $L = $T2;
$NE = powi( $K,$L );
$NR = sum_powi ( $K,$L );
my $Kw=log2($K);
my $LKw=$L*$Kw;
my $Lw=log2($L);
$RAw=$LKw + $Lw;
$EAw = $LKw;
}elsif($topology eq '"FATTREE"') {
my $K = $T1;
my $L = $T2;
$NE = powi( $K,$L );
$NR = $L * powi( $K , $L - 1 );
my $Kw=log2($K);
my $LKw=$L*$Kw;
my $Lw=log2($L);
$RAw=$LKw + $Lw;
$EAw = $LKw;
}elsif ($topology eq '"RING"' || $topology eq '"LINE"'){
my $NX=$T1;
my $NY=1;
my $NL=$T3;
$NE = $NX*$NY*$NL;
$NR = $NX*$NY;
my $Xw=log2($NX);
my $Yw=log2($NY);
my $Lw=log2($NL);
$RAw = $Xw;
$EAw = ($NL==1) ? $RAw : $RAw + $Lw;
}elsif ($topology eq '"MESH"' || $topology eq '"TORUS"' ) {
my $NX=$T1;
my $NY=$T2;
my $NL=$T3;
$NE = $NX*$NY*$NL;
$NR = $NX*$NY;
my $Xw=log2($NX);
my $Yw=log2($NY);
my $Lw=log2($NL);
$RAw = $Xw + $Yw;
$EAw = ($NL==1) ? $RAw : $RAw + $Lw;
}elsif ($topology eq '"FMESH"'){
my $NX=$T1;
my $NY=$T2;
my $NL=$T3;
$NE = $NX*$NY*$NL + 2*($NX + $NY);
$NR = $NX*$NY;
my $Xw=log2($NX);
my $Yw=log2($NY);
my $Lw=log2($NL);
$RAw = $Xw + $Yw;
$EAw = $RAw + log2(4+$NL);
}elsif ($topology eq '"STAR"' ) {
$NE= $T1;
$NR= 1;
$RAw=log2($NR);
$EAw=log2($NE);
}else{ #custom
$NE= $T1;
$NR= $T2;
$RAw=log2($NR);
$EAw=log2($NE);
}
return ($NE, $NR, $RAw, $EAw, $Fw);
}
sub fattree_addrencode {
my ( $pos, $k, $l)=@_;
my $pow; my $ tmp;
my $addrencode=0;
my $kw=log2($k);
$pow=1;
for (my $i = 0; $i <$l; $i=$i+1 ) {
$tmp=int($pos/$pow);
$tmp=$tmp % $k;
$tmp=$tmp << ($i)*$kw;
$addrencode=$addrencode | $tmp;
$pow=$pow * $k;
}
return $addrencode;
}
sub fattree_addrdecode{
my ($addrencode, $k, $l)=@_;
my $kw=0;
my $mask=0;
my $pow; my $tmp;
my $pos=0;
while((0x1 << $kw) < $k){
$kw++;
$mask<<=1;
$mask|=0x1;
}
$pow=1;
for (my $i = 0; $i <$l; $i=$i+1 ) {
$tmp = $addrencode & $mask;
#printf("tmp1=%u\n",tmp);
$tmp=($tmp*$pow);
$pos= $pos + $tmp;
$pow=$pow * $k;
$addrencode>>=$kw;
}
return $pos;
}
sub get_connected_router_id_to_endp{
my ($self,$endp_id)=@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my $T3=$self->object_get_attribute('noc_param','T3');
if($topology eq '"FATTREE"' || $topology eq '"TREE"') {
return int($endp_id/$T1);
}elsif ($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH"' || $topology eq '"TORUS"'){
return int($endp_id/$T3);
}elsif ($topology eq '"STAR"' ) {
return 0;#there is only one routerin star topology
}elsif ($topology eq '"FMESH"'){
my $tmp = $T1*$T2*$T3;
return int($endp_id/$T3) if($endp_id<$tmp);
return $endp_id-$tmp if($endp_id<$tmp+$T1);
return ($endp_id-$tmp-$T1)+ $T1*($T2-1) if($endp_id<$tmp+2*$T1);
return ($endp_id-$tmp-2*$T1)*$T1 if($endp_id<$tmp+2*$T1+$T2);
return ($endp_id-$tmp-2*$T1-$T2+1)*$T1-1;
}else{#custom
my @er_addr = $self->object_get_attribute('noc_connection','er_addr');
return $er_addr[$endp_id];
}
}
sub fmesh_addrencode{
my($id,$T1,$T2,$T3)=@_;
my ($y, $x, $l,$p, $diff,$mul);
$mul = $T1*$T2*$T3;
my $LOCAL = 0;
my $EAST = 1;
my $NORTH = 2;
my $WEST = 3;
my $SOUTH = 4;
if($id < $mul) {
$y = (($id/$T3) / $T1 );
$x = (($id/$T3) % $T1 );
$l = ( $id %$T3);
$p = ($l==0)? $LOCAL : 4+$l;
}else{
$diff = $id - $mul ;
if( $diff < $T1){ #top mesh edge
$y = 0;
$x = $diff;
$p = $NORTH;
}
elsif ( $diff < 2* $T1) { #bottom mesh edge
$y = $T2-1;
$x = $diff-$T1;
$p = $SOUTH;
}
elsif ( $diff < (2* $T1)+$T2 ) { #left mesh edge
$y = $diff - (2* $T1);
$x = 0;
$p = $WEST;
}
else { #right mesh edge
$y = $diff - (2* $T1) -$T2;
$x = $T1-1;
$p = $EAST;
}
}
my $NXw=log2($T1);
my $NYw=log2($T2);
my $addrencode=0;
$addrencode = ($p << ($NXw+$NYw)| ($y << $NXw) | $x);
return $addrencode;
}
sub fmesh_endp_addr_decoder {
my ($code, $T1, $T2, $T3)=@_;
my ($x, $y, $p) =mesh_tori_addr_sep ($code, $T1, $T2, $T3);
my $LOCAL = 0;
my $EAST = 1;
my $NORTH = 2;
my $WEST = 3;
my $SOUTH = 4;
return (($y*$T1)+$x)*$T3 if($p== $LOCAL);
return (($y*$T1)+$x)*$T3+($p-$SOUTH) if($p > $SOUTH);
return (($T1*$T2*$T3) + $x) if($p== $NORTH);
return (($T1*$T2*$T3) + $T1 + $x) if($p== $SOUTH);
return (($T1*$T2*$T3) + 2*$T1 + $y) if($p== $WEST );
return (($T1*$T2*$T3) + 2*$T1 + $T2 + $y) if($p== $EAST );
return 0; #should not reach here
}
sub get_router_num {
my ($self,$x, $y)=@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
if($topology eq '"FATTREE"') {
return fattree_addrdecode($x, $T1, $T2);
}elsif ($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"FMESH"' || $topology eq '"MESH"' || $topology eq '"TORUS"'){
return ($y*$T1)+$x;
}else{#custom
#It is not used for custom & STAR topology
}
}
sub router_addr_encoder{
my ($self, $id)=@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my $T3=$self->object_get_attribute('noc_param','T3');
if($topology eq '"FATTREE"' || $topology eq '"TREE"') {
return fattree_addrencode($id, $T1, $T2);
}elsif ($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH"' || $topology eq '"FESH"' || $topology eq '"TORUS"'){
return mesh_tori_addrencode($id,$T1, $T2,1);
}else { #custom & STAR
return $id;
}
}
sub endp_addr_encoder{
my ($self, $id)=@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my $T3=$self->object_get_attribute('noc_param','T3');
if($topology eq '"FATTREE"' || $topology eq '"TREE"') {
return fattree_addrencode($id, $T1, $T2);
}elsif ($topology eq '"MESH"' || $topology eq '"TORUS"'){
return mesh_tori_addrencode($id,$T1, $T2,$T3);
}elsif ($topology eq '"RING"' || $topology eq '"LINE"'){
return ring_line_addrencode($id,$T1, $T3);
}elsif ($topology eq '"FMESH"' ){
return fmesh_addrencode($id,$T1, $T2,$T3);
}else{#CUSTOM & STAR
return $id;
}
}
sub endp_addr_decoder {
my ($self,$code)=@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my $T3=$self->object_get_attribute('noc_param','T3');
if($topology eq '"FATTREE"' || $topology eq '"TREE"') {
return fattree_addrdecode($code, $T1, $T2);
}
elsif ($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH"' || $topology eq '"TORUS"'){
my ($x, $y, $l) = mesh_tori_addr_sep($code,$T1, $T2,$T3);
#print "my ($x, $y, $l) = mesh_tori_addr_sep($code,$T1, $T2,$T3);\n";
return (($y*$T1)+$x)*$T3+$l;
}elsif ($topology eq '"FMESH"' ){
return fmesh_endp_addr_decoder($code,$T1, $T2,$T3);
}else{#custom & STAR
return $code;
}
}
sub mask_gen{
my $k=shift;
my $kw=0;
my $mask=0;
while((0x1 << $kw) < $k){
$kw++;
$mask<<=1;
$mask|=0x1;
}
return $mask;
}
sub mesh_tori_addr_sep {
my ($code,$NX, $NY,$NL)=@_;
my ($x, $y, $l);
my $NXw=log2($NX);
my $NYw=log2($NY);
$x = $code & mask_gen($NX);
$code>>=$NXw;
$y = $code & mask_gen($NY);
$code>>=$NYw;
$l = $code;
return ($x, $y, $l);
}
sub mesh_tori_addrencode{
my ($id,$T1, $T2,$T3)=@_;
my ($x,$y,$l)=mesh_tori_addrencod_sep($id,$T1,$T2,$T3);
return mesh_tori_addr_join($x,$y,$l,$T1, $T2,$T3);
}
sub ring_line_addrencode {
my ($id,$T1, $T3)=@_;
my ($x,$y,$l)=mesh_tori_addrencod_sep($id,$T1,0,$T3);
return ring_line_addr_join($x,$y,$l,$T1, $T3);
}
sub mesh_tori_addrencod_sep{
my ($id,$T1,$T2,$T3)=@_;
my ($x,$y,$l);
$l=$id % $T3; # id%NL
my $R= int($id / $T3);
$x= $R % $T1;# (id/NL)%NX
$y=int($R / $T1);# (id/NL)/NX
return ($x,$y,$l);
}
sub mesh_tori_addr_join {
my ($x, $y, $l,$T1, $T2,$T3)=@_;
my $NXw=log2($T1);
my $NYw=log2($T2);
my $addrencode=0;
$addrencode =($T3==1)? ($y << $NXw | $x) : ($l << ($NXw+$NYw)| ($y << $NXw) | $x);
return $addrencode;
}
sub ring_line_addr_join {
my ($x, $y, $l,$T1, $T3)=@_;
my $NXw=log2($T1);
my $addrencode=0;
$addrencode =($T3==1)? $x : ($l << $NXw) | $x;
return $addrencode;
}
sub mcast_partial_width {
my ($p,$NE)=@_;
my $m=0;
$p=remove_not_hex($p);
my @arr=split (//, $p);
foreach my $i (@arr) {
my $n=hex($i);
$m++ if($n & 0x1);
$m++ if($n & 0x2);
$m++ if($n & 0x4);
$m++ if($n & 0x8);
}
return $m;
}
sub get_noc_verilator_top_modules_info {
my ($self) =@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my $T3=$self->object_get_attribute('noc_param','T3');
my $cast = $self->object_get_attribute('noc_param','MCAST_ENDP_LIST');
my $CAST_TYPE= $self->object_get_attribute('noc_param','CAST_TYPE');
my $DAw_OFFSETw = ($topology eq '"MESH"' || $topology eq '"TORUS"' || $topology eq '"FMESH"')? $T1 : 0;
my %tops;
my %nr_p; # number of routers have $p port num
my $router_p; #number of routers with different port number in topology
my ($ne, $nr, $RAw, $EAw)=get_topology_info($self);
my $MCAST_PRTLw= mcast_partial_width($cast,$ne);
my $MCASTw =
($CAST_TYPE eq '"MULTICAST_FULL"') ? $ne :
($CAST_TYPE eq '"MULTICAST_PARTIAL"' && $EAw >= $MCAST_PRTLw) ? $EAw +1 :
($CAST_TYPE eq '"MULTICAST_PARTIAL"' && $EAw < $MCAST_PRTLw) ? $MCAST_PRTLw +1 :
$EAw +1; #broadcast
my $DAw = ($CAST_TYPE eq '"UNICAST"') ? $EAw: $MCASTw + $DAw_OFFSETw;
my $custom_include="";
if($topology eq '"FATTREE"') {
my $K = $T1;
my $L = $T2;
my $p2 = 2*$K;
$router_p=2;
my $NRL= $ne/$K; #number of router in each layer
$nr_p{1}=$NRL;
$nr_p{2}=$nr-$NRL;
$nr_p{p1}=$K;
$nr_p{p2}=2*$K;
%tops = (
#"Vrouter1" => "router_top_v_p${K}.v",
#"Vrouter2" => "router_top_v_p${p2}.v",
"Vrouter1" => "--top-module router_top_v -GP=${K} ",
"Vrouter2" => "--top-module router_top_v -GP=${p2} ",
# "Vnoc" => " --top-module noc_connection ",
);
}elsif ($topology eq '"TREE"'){
my $K = $T1;
my $L = $T2;
my $p2 = $K+1;
$router_p=2;# number of router with different port number
$nr_p{1}=1;
$nr_p{2}=$nr-1;
$nr_p{p1}=$K;
$nr_p{p2}=$K+1;
%tops = (
#"Vrouter1" => "router_top_v_p${K}.v",
#"Vrouter2" => "router_top_v_p${p2}.v",
"Vrouter1" => "--top-module router_top_v -GP=${K} ",
"Vrouter2" => "--top-module router_top_v -GP=${p2} ",
# "Vnoc" => " --top-module noc_connection ",
);
}elsif ($topology eq '"RING"' || $topology eq '"LINE"'){
$router_p=1;
$nr_p{1}=$nr;
my $ports= 3+$T3-1;
$nr_p{p1}=$ports;
%tops = (
#"Vrouter1" => "router_top_v_p${ports}.v",
"Vrouter1" => "--top-module router_top_v -GP=${ports} ",
# "Vnoc" => " --top-module noc_connection ",
);
}elsif ($topology eq '"MESH"' || $topology eq '"TORUS"' || $topology eq '"FMESH"') {
$router_p=1;
$nr_p{1}=$nr;
my $ports= 5+$T3-1;
$nr_p{p1}=$ports;
%tops = (
#"Vrouter1" => "router_top_v_p${ports}.v",
"Vrouter1" => "--top-module router_top_v -GP=${ports} ",
# "Vnoc" => " --top-module noc_connection",
);
}elsif ($topology eq '"STAR"') {
$router_p=1;# number of router with different port number
my $ports= $T1;
$nr_p{p1}=$ports;
$nr_p{1}=1;
%tops = (
#"Vrouter1" => "router_top_v_p${ports}.v",
"Vrouter1" => "--top-module router_top_v -GP=${ports} ",
# "Vnoc" => " --top-module noc_connection",
);
}else {#custom
my $dir =get_project_dir()."/mpsoc/rtl/src_topolgy";
my $file="$dir/param.obj";
my %param;
if(-f $file){
my ($pp,$r,$err) = regen_object($file );
if ($r){
print "**Error: cannot open $file file: $err\n";
return;
}
%param=%{$pp};
}else {
print "**Error: cannot find $file \n";
return;
}
my $topology_name=$self->object_get_attribute('noc_param','CUSTOM_TOPOLOGY_NAME');
my $ref=$param{$topology_name}{'ROUTER_Ps'};
print $ref;
my %router_ps= %{$ref};
my $i=1;
#%tops = ("Vnoc" => " --top-module noc_connection");
#should sort neumeric. The router with smaller port number should comes first
foreach my $p (sort { $a <=> $b } keys %router_ps){
$nr_p{$i}=$router_ps{$p};
$nr_p{"p$i"}=$p;
#$tops{"Vrouter$i"}= "router_top_v_p${p}.v",
$tops{"Vrouter$i"}= "--top-module router_top_v -GP=${p} ",
$i++;
}
$router_p=$i-1;
${topology_name} =~ s/\"+//g;
$custom_include="#define IS_${topology_name}_noc\n";
}#else
my $includ_h="\n";
for (my $p=1; $p<=$router_p ; $p++){
$includ_h=$includ_h."#include \"Vrouter$p.h\" \n";
}
my $rns_num = $router_p+1;
$includ_h.="int router_NRs[$rns_num];\n";
my $max_p=0;
for (my $p=1; $p<=$router_p ; $p++){
my $pnum= $nr_p{"p$p"};
$includ_h=$includ_h."#define NR${p} $nr_p{$p}\n";
$includ_h=$includ_h."#define NR${p}_PNUM $pnum\n";
$includ_h=$includ_h."Vrouter${p} *router${p}[ $nr_p{$p} ]; // Instantiation of router with $pnum port number\n";
$max_p = $pnum if($max_p < $pnum);
}
$includ_h.="#define MAX_P $max_p //The maximum number of ports available in a router in this topology\n";
$includ_h.="#define DAw $DAw //The traffic generator's destination address width\n";
my $st1='';
my $st2='';
my $st3='';
my $st4='';
my $st5='';
my $st6='';
my $st7='';
my $st8='';
my $i=1;
my $j=0;
my $accum=0;
for (my $p=1; $p<=$router_p ; $p++){
$includ_h=$includ_h."
";
#if ROUTER_P_NUM >$j
#endif
$st2=$st2."
router_NRs[$p] =$nr_p{$p};
for(i=0;i
reset= reset;
router${i}[i]->clk= clk ;
}
";
$st4=$st4."
for(i=0;ieval();
";
$st5=$st5."
for(i=0;ifinal();
";
$st6=$st6."
if (ieval(); return;}
i-= NR${i};
";
$st7.="
if (icurrent_r_id,
router${i}[i]->router_event,
sizeof(router${i}[i]->router_event[0])
);
return;
}
i-= NR${i};
";
$st8=$st8."
if (ireset= reset;
router${i}[i]->clk= clk ;
return;
}
i-= NR${i};
";
$i++;
$j++;
$accum=$accum+$nr_p{$p};
}
$includ_h=$includ_h."
void Vrouter_new(){
int i=0;
$st2
}
$custom_include
void inline connect_routers_reset_clk(){
int i;
$st3
}
void inline routers_eval(){
int i=0;
$st4
}
void inline routers_final(){
int i;
$st5
}
void inline single_router_eval(int i){
$st6
}
#define SMART_NUM ((SMART_MAX==0)? 1 : SMART_MAX)
extern void update_router_st (
unsigned int,
unsigned int,
void * ,
size_t
);
void single_router_st_update(int i){
$st7
}
void inline single_router_reset_clk(int i){
$st8
}
";
#$includ_h.=" void connect_all_nodes(){\n";
#my $dot_file=get_dot_file_text($self,'topology');
#print "$dot_file\n";
#my @lines =split ("\n",$dot_file);
#foreach my $l (@lines) {
# if ( $l =~ m{#*\"\s*R(\d+)\"\s*:\s*\"[pP](\d+)\"\s*->\s*\"R(\d+)\"\s*:\s*\"[pP](\d+)\"} ) {
# my ($R1, $P1, $R2,$P2) = ($1, $2,$3,$4);
# $includ_h.=connect_sim_nodes ($self,$topology,$R1, $P1, $R2, $P2);
#
#
# }
# if ( $l =~ m{#*\"\s*R(\d+)\"\s*:\s*\"[pP](\d+)\"\s*->\s*\"[Tt](\d+)\"} ) {
# my ($R1, $P1, $T) = ($1, $2,$3);
# $includ_h.=connect_sim_nodes($self,$topology,$R1, $P1, $T);
#
#
# }
# if ( $l =~ m{#*\s*\"[Tt](\d+)\"\s*->\s*\"R(\d+)\"\s*:\s*\"[pP](\d+)\"} ) {
# my ($T, $R1, $P1) = ($1, $2,$3);
# $includ_h.=connect_sim_nodes($self,$topology,$R1, $P1, $T);
# }
#}
#$includ_h.="\n}\n";
return ($nr,$ne,$router_p,\%tops,$includ_h);
}
sub connect_sim_nodes{
my ($self,$topology,$R1, $P1, $R2, $P2)=@_;
if(defined $P2){ #R2R
if($topology eq '"FATTREE"' || $topology eq '"TREE"'){
}else{
return connect_r2r(1,$R1, $P1,1, $R2, $P2);
}
}else {
my $T=$R2;
if($topology eq '"FATTREE"' || $topology eq '"TREE"'){
}else{
return connect_r2t(1,$R1, $P1, $T);
}
}
}
sub connect_r2r{
my ($vrouter1_num,$r1,$p1,$vrouter2_num,$r2,$p2)=@_;
return "
memcpy(&router${vrouter1_num}[$r1]->chan_in[$p1], router${vrouter2_num}[$r2]->chan_out[$p2] , sizeof( router${vrouter1_num}[$r1]->chan_in[$p1] ) );
memcpy(&router${vrouter2_num}[$r2]->chan_in[$p2], router${vrouter1_num}[$r1]->chan_out[$p1] , sizeof( router${vrouter1_num}[$r1]->chan_in[$p1] ) );
";
}
sub connect_r2t{
my ($vrouter1_num,$r1, $p1, $T)=@_;
return "
memcpy(&router${vrouter1_num}[$r1]->chan_in[$p1], traffic[$T]->chan_out , sizeof( traffic[$T]->chan_in ) );
memcpy(&traffic[$T]->chan_in, router${vrouter1_num}[$r1]->chan_out[$p1] , sizeof( traffic[$T]->chan_in ) );
";
}
sub gen_tiles_physical_addrsses_header_file{
my ($self,$file)=@_;
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
my $txt = "#ifndef PHY_ADDR_H
#define PHY_ADDR_H\n\n";
#add phy addresses
my ($NE, $NR, $RAw, $EAw,$Fw)=get_topology_info($self);
for (my $id=0; $id<$NE; $id++){
my $phy= endp_addr_encoder($self,$id);
my $hex = sprintf("0x%x", $phy);
$txt=$txt."\t#define PHY_ADDR_ENDP_$id $hex\n";
}
$txt=$txt."#endif\n";
save_file($file,$txt);
}
sub get_endpoints_mah_distance {
my ($self,$endp1,$endp2)=@_;
my $router1=get_connected_router_id_to_endp($self,$endp1);
my $router2=get_connected_router_id_to_endp($self,$endp2);
my $topology=$self->object_get_attribute('noc_param','TOPOLOGY');
if($topology eq '"FATTREE"' || $topology eq '"TREE"') {
return fattree_mah_distance($self, $router1,$router2);
}elsif ($topology eq '"RING"' || $topology eq '"LINE"' || $topology eq '"MESH"' || $topology eq '"TORUS"' || $topology eq '"FMESH"' ){
return mesh_tori_mah_distance($self, $router1,$router2);
}elsif ($topology eq '"STAR"'){
return 1;
}else { #custom
return undef;
}
}
sub mesh_tori_mah_distance {
my ($self, $router1,$router2)=@_;
my $T1=$self->object_get_attribute('noc_param','T1');
my $T2=$self->object_get_attribute('noc_param','T2');
my ($x1,$y1,$l1) = mesh_tori_addrencod_sep ($router1,$T1,$T2,1);
my ($x2,$y2,$l2) = mesh_tori_addrencod_sep ($router2,$T1,$T2,1);
my $x_diff = ($x1 > $x2) ? ($x1 - $x2) : ($x2 - $x1);
my $y_diff = ($y1 > $y2) ? ($y1 - $y2) : ($y2 - $y1);
my $mah_distance = $x_diff + $y_diff;
return $mah_distance;
}
sub fattree_mah_distance {
my ($self, $router1,$router2)=@_;
my $k =$self->object_get_attribute('noc_param','T1');
my $l =$self->object_get_attribute('noc_param','T2');
my $pow;
my $tmp1;
my $tmp2;
my $distance=0;
$pow=1;
for (my $i = 0; $i <$l; $i=$i+1 ) {
$tmp1=int($router1/$pow);
$tmp2=int($router2/$pow);
$tmp1=$tmp1 % $k;
$tmp2=$tmp2 % $k;
$pow=$pow * $k;
$distance= ($i+1)*2-1 if($tmp1!=$tmp2); # distance obtained based on the highest level index which differ
}
return $distance;
}
1